下面列出了org.apache.commons.lang3.mutable.Mutable#setValue ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void push(Mutable<ILogicalOperator> opRefGby, Mutable<ILogicalOperator> opRefJoin, int branch,
List<Pair<LogicalVariable, Mutable<ILogicalExpression>>> decorToPush,
List<Pair<LogicalVariable, Mutable<ILogicalExpression>>> decorNotToPush, IOptimizationContext context)
throws AlgebricksException {
GroupByOperator gby = (GroupByOperator) opRefGby.getValue();
AbstractBinaryJoinOperator join = (AbstractBinaryJoinOperator) opRefJoin.getValue();
gby.getDecorList().clear();
gby.getDecorList().addAll(decorToPush);
for (Pair<LogicalVariable, Mutable<ILogicalExpression>> p : decorNotToPush) {
LogicalVariable v1 = p.first;
if (v1 != null) {
VariableReferenceExpression varRef = (VariableReferenceExpression) p.second.getValue();
LogicalVariable v2 = varRef.getVariableReference();
OperatorManipulationUtil.substituteVarRec(join, v2, v1, true, context);
}
}
Mutable<ILogicalOperator> branchRef = join.getInputs().get(branch);
ILogicalOperator opBranch = branchRef.getValue();
opRefJoin.setValue(opBranch);
branchRef.setValue(gby);
opRefGby.setValue(join);
}
public boolean convertFunctionToAlgebricksExpression(Mutable<ILogicalExpression> searchM,
AbstractFunctionCallExpression functionCall, IOptimizationContext context,
Map<FunctionIdentifier, FunctionIdentifier> map) {
if (map.containsKey(functionCall.getFunctionIdentifier())) {
IExpressionAnnotation annotate = new ExpressionAnnotationNoCopyImpl();
annotate.setObject(functionCall.getFunctionIdentifier());
FunctionIdentifier algebricksFid = map.get(functionCall.getFunctionIdentifier());
IFunctionInfo algebricksFunction = context.getMetadataProvider().lookupFunction(algebricksFid);
functionCall.setFunctionInfo(algebricksFunction);
functionCall.getAnnotations().put(ALGEBRICKS_CONVERSION_ANNOTATION, annotate);
searchM.setValue(functionCall);
return true;
}
return false;
}
/**
* Creates tracked node entries for the specified nodes and creates the
* corresponding selectors.
*
* @param refSelectors the reference where to store the selectors
* @param nodes the nodes to be tracked
* @param current the current {@code TreeData} object
* @param resolver the {@code NodeKeyResolver}
* @return the updated {@code TreeData} object
*/
private static TreeData createSelectorsForTrackedNodes(
final Mutable<Collection<NodeSelector>> refSelectors,
final List<ImmutableNode> nodes, final TreeData current,
final NodeKeyResolver<ImmutableNode> resolver)
{
final List<NodeSelector> selectors =
new ArrayList<>(nodes.size());
final Map<ImmutableNode, String> cache = new HashMap<>();
for (final ImmutableNode node : nodes)
{
selectors.add(new NodeSelector(resolver.nodeKey(node, cache,
current)));
}
refSelectors.setValue(selectors);
final NodeTracker newTracker =
current.getNodeTracker().trackNodes(selectors, nodes);
return current.updateNodeTracker(newTracker);
}
private <N extends Number> void deserializeNumber(Mutable<Number> number, String path, Class<N> numberClass) {
try {
if (settingsConfig.has(path)) {
number.setValue(getNumber(settingsConfig.get(path), numberClass));
}
} catch (Exception ex) {
SkyblockAddons.getInstance().getLogger().error("Failed to deserialize path: "+ path);
ex.printStackTrace();
}
}
@SuppressWarnings("unchecked")
private boolean convertAlgebricksExpression(Mutable<ILogicalExpression> searchM, IFunctionInfo funcInfo,
boolean isBoolean) {
AbstractFunctionCallExpression searchFunction = (AbstractFunctionCallExpression) searchM.getValue();
searchFunction.setFunctionInfo(funcInfo);
if (isBoolean) {
ScalarFunctionCallExpression functionCallExp = new ScalarFunctionCallExpression(
BuiltinFunctions.FN_BOOLEAN_1, new MutableObject<ILogicalExpression>(searchM.getValue()));
searchM.setValue(functionCallExp);
}
return true;
}
protected boolean setDataSourceScan(IDataSource<String> ids, Mutable<ILogicalOperator> opRef) {
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
UnnestOperator unnest = (UnnestOperator) op;
Mutable<ILogicalOperator> opRef2 = unnest.getInputs().get(0);
AbstractLogicalOperator op2 = (AbstractLogicalOperator) opRef2.getValue();
AssignOperator assign = (AssignOperator) op2;
DataSourceScanOperator opNew = new DataSourceScanOperator(assign.getVariables(), ids);
opNew.getInputs().addAll(assign.getInputs());
opRef2.setValue(opNew);
return true;
}
private boolean processTypeExpression(Mutable<ILogicalOperator> opRef, Mutable<ILogicalExpression> search) {
boolean modified = false;
SequenceType inputSequenceType;
SequenceType sTypeArg;
functionList.clear();
ExpressionToolbox.findAllFunctionExpressions(search, getSearchFunction(), functionList);
for (Mutable<ILogicalExpression> searchM : functionList) {
// Get input function
AbstractFunctionCallExpression searchFunction = (AbstractFunctionCallExpression) searchM.getValue();
Mutable<ILogicalExpression> argFirstM = searchFunction.getArguments().get(ARG_DATA);
// Find the input return type.
inputSequenceType = ExpressionToolbox.getOutputSequenceType(opRef, argFirstM, dCtx);
// Find the argument type.
if (inputSequenceType == null && !isNestedPlanOperator(opRef).isEmpty()) {
for (Mutable<ILogicalOperator> agg : isNestedPlanOperator(opRef)) {
inputSequenceType = ExpressionToolbox.getOutputSequenceType(agg, argFirstM, dCtx);
}
}
sTypeArg = null;
if (hasTypeArgument()) {
sTypeArg = ExpressionToolbox.getTypeExpressionTypeArgument(searchM, dCtx);
}
// remove
if (matchesAllInstancesOf(sTypeArg, inputSequenceType)) {
searchM.setValue(argFirstM.getValue());
modified = true;
}
}
return modified;
}
/**
* Tracks all nodes which are children of the node selected by the passed in
* key. If the key selects exactly one node, for all children of this node
* {@code NodeSelector} objects are created, and they become tracked nodes.
* The returned collection of {@code NodeSelector} objects can be used for
* interacting with the selected nodes.
*
* @param key the key for selecting the parent node whose children are to be
* tracked
* @param resolver the {@code NodeKeyResolver}
* @return a collection with the {@code NodeSelector} objects for the new
* tracked nodes
*/
public Collection<NodeSelector> trackChildNodes(final String key,
final NodeKeyResolver<ImmutableNode> resolver)
{
final Mutable<Collection<NodeSelector>> refSelectors =
new MutableObject<>();
boolean done;
do
{
refSelectors.setValue(Collections.<NodeSelector> emptyList());
final TreeData current = structure.get();
final List<ImmutableNode> nodes =
resolver.resolveNodeKey(current.getRootNode(), key, current);
if (nodes.size() == 1)
{
final ImmutableNode node = nodes.get(0);
done =
node.getChildren().isEmpty()
|| structure.compareAndSet(
current,
createSelectorsForTrackedNodes(
refSelectors,
node.getChildren(), current,
resolver));
}
else
{
done = true;
}
} while (!done);
return refSelectors.getValue();
}
protected boolean processOperator(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
throws AlgebricksException {
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
if (op.getOperatorTag() != LogicalOperatorTag.UNNEST) {
return false;
}
UnnestOperator unnest = (UnnestOperator) op;
// Check to see if the expression is a function and iterate.
ILogicalExpression logicalExpressionUnnest1 = (ILogicalExpression) unnest.getExpressionRef().getValue();
if (logicalExpressionUnnest1.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
AbstractFunctionCallExpression functionCallUnnest1 = (AbstractFunctionCallExpression) logicalExpressionUnnest1;
if (!functionCallUnnest1.getFunctionIdentifier().equals(BuiltinOperators.ITERATE.getFunctionIdentifier())) {
return false;
}
// Check to see if the expression is a variable.
Mutable<ILogicalExpression> logicalExpressionUnnestRef2 = functionCallUnnest1.getArguments().get(0);
ILogicalExpression logicalExpressionUnnest2 = (ILogicalExpression) logicalExpressionUnnestRef2.getValue();
if (logicalExpressionUnnest2.getExpressionTag() != LogicalExpressionTag.VARIABLE) {
return false;
}
VariableReferenceExpression vre2 = (VariableReferenceExpression) logicalExpressionUnnest2;
LogicalVariable unnestInput = vre2.getVariableReference();
// Check if the input is an DATASCAN or UNNEST operator..
Mutable<ILogicalOperator> opRef2 = unnest.getInputs().get(0);
AbstractLogicalOperator op2 = (AbstractLogicalOperator) opRef2.getValue();
if (op2.getOperatorTag() == LogicalOperatorTag.UNNEST
|| op2.getOperatorTag() == LogicalOperatorTag.DATASOURCESCAN) {
AbstractScanOperator aso = (AbstractScanOperator) op2;
if (aso.getVariables().size() == 1 && aso.getVariables().contains(unnestInput)) {
// Add in a noop.
AssignOperator assign = new AssignOperator(unnest.getVariable(), logicalExpressionUnnestRef2);
assign.getInputs().addAll(unnest.getInputs());
opRef.setValue(assign);
return true;
}
}
return false;
}
/**
* Find where an assign for a aggregate function is used before aggregate operator for a sequence.
* Search pattern 1: assign [function-call: count(function-call: treat($$))]
* Search pattern 2: $$ for aggregate [function-call: sequence()]
*/
@Override
public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
IFunctionInfo aggregateInfo;
AbstractFunctionCallExpression finalFunctionCall;
Mutable<ILogicalOperator> nextOperatorRef;
// Check if assign is for aggregate function.
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
if (op.getOperatorTag() != LogicalOperatorTag.ASSIGN) {
return false;
}
AssignOperator assign = (AssignOperator) op;
Mutable<ILogicalExpression> mutableLogicalExpression = assign.getExpressions().get(0);
ILogicalExpression logicalExpression = mutableLogicalExpression.getValue();
if (logicalExpression.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
AbstractFunctionCallExpression functionCall = (AbstractFunctionCallExpression) logicalExpression;
// TODO get the function through the function definition
aggregateInfo = getAggregateFunction(functionCall);
if (aggregateInfo == null) {
return false;
}
Mutable<ILogicalExpression> mutableVariableExpresion = ExpressionToolbox.findVariableExpression(mutableLogicalExpression);
if (mutableVariableExpresion == null) {
return false;
}
Mutable<ILogicalExpression> finalFunctionCallM = ExpressionToolbox
.findLastFunctionExpression(mutableLogicalExpression);
finalFunctionCall = (AbstractFunctionCallExpression) finalFunctionCallM.getValue();
// Build a subplan for replacing the sort distinct function with operators.
// Nested tuple source.
Mutable<ILogicalOperator> inputOperator = getInputOperator(assign.getInputs().get(0));
NestedTupleSourceOperator ntsOperator = new NestedTupleSourceOperator(inputOperator);
nextOperatorRef = new MutableObject<ILogicalOperator>(ntsOperator);
// Get variable that is being used for sort and distinct operators.
VariableReferenceExpression inputVariableRef = (VariableReferenceExpression) mutableVariableExpresion.getValue();
LogicalVariable inputVariable = inputVariableRef.getVariableReference();
// Unnest.
LogicalVariable unnestVariable = context.newVar();
UnnestOperator unnestOperator = getUnnestOperator(inputVariable, unnestVariable);
unnestOperator.getInputs().add(nextOperatorRef);
nextOperatorRef = new MutableObject<ILogicalOperator>(unnestOperator);
// Aggregate.
VariableReferenceExpression inputArg = new VariableReferenceExpression(unnestVariable);
finalFunctionCall.getArguments().get(0).setValue(inputArg);
Mutable<ILogicalExpression> aggregateArgs = functionCall.getArguments().get(0);
LogicalVariable aggregateVariable = assign.getVariables().get(0);
AggregateOperator aggregateOperator = getAggregateOperator(aggregateInfo, aggregateArgs, aggregateVariable);
aggregateOperator.getInputs().add(nextOperatorRef);
nextOperatorRef = new MutableObject<ILogicalOperator>(aggregateOperator);
// Subplan.
SubplanOperator subplanOperator = new SubplanOperator();
subplanOperator.getInputs().add(assign.getInputs().get(0));
subplanOperator.setRootOp(nextOperatorRef);
assign.getInputs().clear();
opRef.setValue(subplanOperator);
return true;
}
private boolean assignFunctionExpressions(AbstractLogicalOperator joinOp, ILogicalExpression expr,
IOptimizationContext context) throws AlgebricksException {
if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
AbstractFunctionCallExpression fexp = (AbstractFunctionCallExpression) expr;
FunctionIdentifier fi = fexp.getFunctionIdentifier();
boolean modified = false;
if (fi.equals(AlgebricksBuiltinFunctions.AND) || fi.equals(AlgebricksBuiltinFunctions.OR)) {
for (Mutable<ILogicalExpression> a : fexp.getArguments()) {
if (assignFunctionExpressions(joinOp, a.getValue(), context)) {
modified = true;
}
}
return modified;
} else if (AlgebricksBuiltinFunctions.isComparisonFunction(fi)) {
for (Mutable<ILogicalExpression> exprRef : fexp.getArguments()) {
if (exprRef.getValue().getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
LogicalVariable newVar = context.newVar();
AssignOperator newAssign = new AssignOperator(newVar, new MutableObject<ILogicalExpression>(exprRef
.getValue().cloneExpression()));
newAssign.setExecutionMode(joinOp.getExecutionMode());
// Place assign below joinOp.
List<LogicalVariable> used = new ArrayList<LogicalVariable>();
VariableUtilities.getUsedVariables(newAssign, used);
Mutable<ILogicalOperator> leftBranchRef = joinOp.getInputs().get(0);
ILogicalOperator leftBranch = leftBranchRef.getValue();
List<LogicalVariable> leftBranchVariables = new ArrayList<LogicalVariable>();
VariableUtilities.getLiveVariables(leftBranch, leftBranchVariables);
if (leftBranchVariables.containsAll(used)) {
// place assign on left branch
newAssign.getInputs().add(new MutableObject<ILogicalOperator>(leftBranch));
leftBranchRef.setValue(newAssign);
modified = true;
} else {
Mutable<ILogicalOperator> rightBranchRef = joinOp.getInputs().get(1);
ILogicalOperator rightBranch = rightBranchRef.getValue();
List<LogicalVariable> rightBranchVariables = new ArrayList<LogicalVariable>();
VariableUtilities.getLiveVariables(rightBranch, rightBranchVariables);
if (rightBranchVariables.containsAll(used)) {
// place assign on right branch
newAssign.getInputs().add(new MutableObject<ILogicalOperator>(rightBranch));
rightBranchRef.setValue(newAssign);
modified = true;
}
}
if (modified) {
// Replace original expr with variable reference.
exprRef.setValue(new VariableReferenceExpression(newVar));
context.computeAndSetTypeEnvironmentForOperator(newAssign);
context.computeAndSetTypeEnvironmentForOperator(joinOp);
}
}
}
return modified;
} else {
return false;
}
}
/**
* @param expr
* @param aggVars
* @param gbyWithAgg
* @param context
* @return a pair whose first member is a boolean which is true iff
* something was changed in the expression tree rooted at expr. The
* second member is the result of transforming expr.
* @throws AlgebricksException
*/
private Pair<Boolean, ILogicalExpression> extractAggFunctionsFromExpression(Mutable<ILogicalExpression> exprRef,
Map<LogicalVariable, GroupByOperator> gbyWithAgg,
Map<ILogicalExpression, ILogicalExpression> aggregateExprToVarExpr, IOptimizationContext context)
throws AlgebricksException {
ILogicalExpression expr = exprRef.getValue();
switch (expr.getExpressionTag()) {
case FUNCTION_CALL: {
AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) expr;
Function functionInfo = (Function) fce.getFunctionInfo();
FunctionIdentifier fi = null;
if (functionInfo.hasAggregateEvaluatorFactory()) {
fi = functionInfo.getFunctionIdentifier();
} //FunctionIdentifier fi = functionInfo.getFunctionIdentifier();
if (fi != null) {
ILogicalExpression a1 = fce.getArguments().get(0).getValue();
if (a1.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
LogicalVariable argVar = ((VariableReferenceExpression) a1).getVariableReference();
GroupByOperator gbyOp = gbyWithAgg.get(argVar);
if (gbyOp != null) {
if (!aggregateExprToVarExpr.containsKey(expr)) {
LogicalVariable newVar = context.newVar();
AggregateFunctionCallExpression aggFun = new AggregateFunctionCallExpression(
functionInfo, false, fce.getArguments());
rewriteGroupByAggregate(argVar, gbyOp, aggFun, newVar, context);
ILogicalExpression newVarExpr = new VariableReferenceExpression(newVar);
aggregateExprToVarExpr.put(expr, newVarExpr);
return new Pair<Boolean, ILogicalExpression>(Boolean.TRUE, newVarExpr);
} else {
ILogicalExpression varExpr = aggregateExprToVarExpr.get(expr);
return new Pair<Boolean, ILogicalExpression>(Boolean.TRUE, varExpr);
}
}
}
}
boolean change = false;
for (Mutable<ILogicalExpression> a : fce.getArguments()) {
Pair<Boolean, ILogicalExpression> aggArg = extractAggFunctionsFromExpression(a, gbyWithAgg,
aggregateExprToVarExpr, context);
if (aggArg.first.booleanValue()) {
a.setValue(aggArg.second);
change = true;
}
}
return new Pair<Boolean, ILogicalExpression>(change, fce);
}
case VARIABLE:
case CONSTANT: {
return new Pair<Boolean, ILogicalExpression>(Boolean.FALSE, expr);
}
default: {
throw new IllegalArgumentException();
}
}
}
protected boolean processOperator(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
throws AlgebricksException {
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
if (op.getOperatorTag() != LogicalOperatorTag.UNNEST) {
return false;
}
UnnestOperator unnest1 = (UnnestOperator) op;
AbstractLogicalOperator op2 = (AbstractLogicalOperator) unnest1.getInputs().get(0).getValue();
if (op2.getOperatorTag() != LogicalOperatorTag.UNNEST) {
return false;
}
UnnestOperator unnest2 = (UnnestOperator) op2;
if (usedVariables.contains(unnest2.getVariable())) {
return false;
}
// Check to see if the unnest2 expression has a scalar implementation.
ILogicalExpression logicalExpression2 = (ILogicalExpression) unnest2.getExpressionRef().getValue();
if (logicalExpression2.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
AbstractFunctionCallExpression functionCall2 = (AbstractFunctionCallExpression) logicalExpression2;
Function functionInfo2 = (Function) functionCall2.getFunctionInfo();
if (!functionInfo2.hasScalarEvaluatorFactory()) {
return false;
}
// Exception for specific path expressions.
if (functionCall2.getFunctionIdentifier().equals(BuiltinOperators.DESCENDANT.getFunctionIdentifier())
|| functionCall2.getFunctionIdentifier().equals(
BuiltinOperators.DESCENDANT_OR_SELF.getFunctionIdentifier())) {
return false;
}
// Find unnest2 variable in unnest1
Mutable<ILogicalExpression> unnest1Arg = ExpressionToolbox.findVariableExpression(unnest1.getExpressionRef(),
unnest2.getVariable());
if (unnest1Arg == null) {
return false;
}
// Replace unnest2 expression in unnest1
ScalarFunctionCallExpression child = new ScalarFunctionCallExpression(functionInfo2,
functionCall2.getArguments());
unnest1Arg.setValue(child);
// Move input for unnest2 into unnest1
unnest1.getInputs().clear();
unnest1.getInputs().addAll(unnest2.getInputs());
return true;
}
/**
* Find where a sort distinct nodes is being used and not required based on input parameters.
* Search pattern: assign [function-call: sort-distinct-nodes-asc-or-atomics]
*/
@SuppressWarnings("unused")
@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) {
Mutable<ILogicalOperator> nextOperatorRef;
// Check if assign is for sort-distinct-nodes-asc-or-atomics.
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
if (op.getOperatorTag() != LogicalOperatorTag.ASSIGN) {
return false;
}
AssignOperator assign = (AssignOperator) op;
// Check to see if the expression is a function and
// sort-distinct-nodes-asc-or-atomics.
ILogicalExpression logicalExpression = (ILogicalExpression) assign.getExpressions().get(0).getValue();
if (logicalExpression.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
AbstractFunctionCallExpression functionCall = (AbstractFunctionCallExpression) logicalExpression;
if (!functionCall.getFunctionIdentifier().equals(
BuiltinOperators.SORT_DISTINCT_NODES_ASC_OR_ATOMICS.getFunctionIdentifier())
&& !functionCall.getFunctionIdentifier().equals(
BuiltinOperators.DISTINCT_NODES_OR_ATOMICS.getFunctionIdentifier())
&& !functionCall.getFunctionIdentifier().equals(
BuiltinOperators.SORT_NODES_ASC_OR_ATOMICS.getFunctionIdentifier())) {
return false;
}
// Build a subplan for replacing the sort distinct function with operators.
// Nested tuple source.
Mutable<ILogicalOperator> inputOperator = getInputOperator(assign.getInputs().get(0));
NestedTupleSourceOperator ntsOperator = new NestedTupleSourceOperator(inputOperator);
nextOperatorRef = new MutableObject<ILogicalOperator>(ntsOperator);
// Get variable that is being used for sort and distinct operators.
VariableReferenceExpression inputVariableRef = (VariableReferenceExpression) functionCall.getArguments().get(0)
.getValue();
LogicalVariable inputVariable = inputVariableRef.getVariableReference();
// Unnest.
LogicalVariable unnestVariable = context.newVar();
UnnestOperator unnestOperator = getUnnestOperator(inputVariable, unnestVariable);
unnestOperator.getInputs().add(nextOperatorRef);
nextOperatorRef = new MutableObject<ILogicalOperator>(unnestOperator);
// Assign Node ID key.
LogicalVariable nodeIdKeyVariable = context.newVar();
AssignOperator nodeIdAssignOp = getAssignOperator(unnestVariable, nodeIdKeyVariable,
BuiltinOperators.ID_FROM_NODE);
nodeIdAssignOp.getInputs().add(nextOperatorRef);
nextOperatorRef = new MutableObject<ILogicalOperator>(nodeIdAssignOp);
// Prepare for Order and Distinct.
Mutable<ILogicalExpression> nodeIdKeyVariableRef = new MutableObject<ILogicalExpression>(
new VariableReferenceExpression(nodeIdKeyVariable));
// Distinct.
if (functionCall.getFunctionIdentifier().equals(
BuiltinOperators.SORT_DISTINCT_NODES_ASC_OR_ATOMICS.getFunctionIdentifier())
|| functionCall.getFunctionIdentifier().equals(
BuiltinOperators.DISTINCT_NODES_OR_ATOMICS.getFunctionIdentifier())) {
LogicalVariable groupByVariable = context.newVar();
ILogicalExpression nodeIdKeyVre = new VariableReferenceExpression(nodeIdKeyVariable);
GroupByOperator groupByOperator = getGroupByOperator(groupByVariable, nodeIdKeyVre);
groupByOperator.getInputs().add(nextOperatorRef);
nextOperatorRef = new MutableObject<ILogicalOperator>(groupByOperator);
}
// // Order.
// if (functionCall.getFunctionIdentifier().equals(
// BuiltinOperators.SORT_DISTINCT_NODES_ASC_OR_ATOMICS.getFunctionIdentifier())
// || functionCall.getFunctionIdentifier().equals(
// BuiltinOperators.SORT_NODES_ASC_OR_ATOMICS.getFunctionIdentifier())) {
// OrderOperator orderOperator = getOrderOperator(nodeIdKeyVariableRef);
// orderOperator.getInputs().add(nextOperatorRef);
// nextOperatorRef = new MutableObject<ILogicalOperator>(orderOperator);
// }
//
// Aggregate.
LogicalVariable aggregateVariable = assign.getVariables().get(0);
AggregateOperator aggregateOperator = getAggregateOperator(unnestVariable, aggregateVariable);
aggregateOperator.getInputs().add(nextOperatorRef);
nextOperatorRef = new MutableObject<ILogicalOperator>(aggregateOperator);
// Subplan.
SubplanOperator subplanOperator = new SubplanOperator();
subplanOperator.getInputs().add(assign.getInputs().get(0));
subplanOperator.setRootOp(nextOperatorRef);
opRef.setValue(subplanOperator);
return true;
}
@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
throws AlgebricksException {
// TODO Fix EliminateSubplanForSinglePathsRule to check for variables used after the subplan.
// TODO Add back to the rewrite rule list once fixed.
// Do not process empty or nested tuple source.
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
if (op.getOperatorTag() == LogicalOperatorTag.EMPTYTUPLESOURCE
|| op.getOperatorTag() == LogicalOperatorTag.NESTEDTUPLESOURCE) {
return false;
}
// Set cardinality in the context. Must update each time the rule is run.
VXQueryOptimizationContext vxqueryContext = (VXQueryOptimizationContext) context;
Cardinality cardinalityVariable = CardinalityRuleToolbox.getProducerCardinality(opRef.getValue(), vxqueryContext);
// Track variables created
// Track variables used
if (op.getOperatorTag() == LogicalOperatorTag.SUBPLAN && cardinalityVariable == Cardinality.ONE) {
SubplanOperator subplan = (SubplanOperator) op;
AbstractLogicalOperator subplanOp = (AbstractLogicalOperator) subplan.getNestedPlans().get(0).getRoots()
.get(0).getValue();
if (subplanOp.getOperatorTag() != LogicalOperatorTag.AGGREGATE) {
return false;
}
// Change plan to remove the subplan.
opRef.setValue(subplanOp);
// Make inline the arguments for the subplan.
AbstractLogicalOperator subplanEnd = findLastSubplanOperator(subplanOp);
subplanEnd.getInputs().get(0).setValue(subplan.getInputs().get(0).getValue());
}
// Now with the new operator, update the variable mappings.
cardinalityVariable = CardinalityRuleToolbox.updateCardinalityVariable(op, cardinalityVariable, vxqueryContext);
// Save propagated value.
vxqueryContext.putCardinalityOperatorMap(opRef.getValue(), cardinalityVariable);
return false;
}
@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
throws AlgebricksException {
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
if (op.getOperatorTag() != LogicalOperatorTag.INNERJOIN) {
return false;
}
AbstractBinaryJoinOperator join = (AbstractBinaryJoinOperator) op;
ILogicalExpression expr = join.getCondition().getValue();
if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
AbstractFunctionCallExpression fexp = (AbstractFunctionCallExpression) expr;
FunctionIdentifier fi = fexp.getFunctionIdentifier();
if (!(fi.equals(AlgebricksBuiltinFunctions.AND) || fi.equals(AlgebricksBuiltinFunctions.EQ))) {
return false;
}
boolean modified = false;
List<Mutable<ILogicalExpression>> functionList = new ArrayList<Mutable<ILogicalExpression>>();
List<Mutable<ILogicalExpression>> variableList = new ArrayList<Mutable<ILogicalExpression>>();
functionList.clear();
ExpressionToolbox.findAllFunctionExpressions(join.getCondition(), AlgebricksBuiltinFunctions.EQ, functionList);
Collection<LogicalVariable> producedVariables = new ArrayList<LogicalVariable>();
for (Mutable<ILogicalExpression> searchM : functionList) {
ILogicalExpression search = searchM.getValue();
if (search.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
continue;
}
AbstractFunctionCallExpression searchExp = (AbstractFunctionCallExpression) search;
// Go through all argument for EQ.
for (Mutable<ILogicalExpression> expressionM : searchExp.getArguments()) {
// Push on to branch when possible.
for (Mutable<ILogicalOperator> branch : join.getInputs()) {
producedVariables.clear();
getProducedVariablesInDescendantsAndSelf(branch.getValue(), producedVariables);
variableList.clear();
ExpressionToolbox.findVariableExpressions(expressionM, variableList);
boolean found = true;
for (Mutable<ILogicalExpression> searchVariableM : variableList) {
VariableReferenceExpression vre = (VariableReferenceExpression) searchVariableM.getValue();
if (!producedVariables.contains(vre.getVariableReference())) {
found = false;
}
}
if (found) {
// push down
LogicalVariable assignVariable = context.newVar();
AssignOperator aOp = new AssignOperator(assignVariable, new MutableObject<ILogicalExpression>(expressionM.getValue()));
aOp.getInputs().add(new MutableObject<ILogicalOperator>(branch.getValue()));
branch.setValue(aOp);
aOp.recomputeSchema();
expressionM.setValue(new VariableReferenceExpression(assignVariable));
modified = true;
}
}
}
}
return modified;
}