use of org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression in project asterixdb by apache.
the class RemoveUnusedAssignAndAggregateRule method collectUnusedAssignedVars.
private void collectUnusedAssignedVars(Mutable<ILogicalOperator> opRef, Set<LogicalVariable> accumulatedUsedVarFromRootSet, boolean first, IOptimizationContext context) throws AlgebricksException {
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
if (!first) {
context.addToDontApplySet(this, op);
}
Set<LogicalVariable> assignVarsSetInThisOp = new HashSet<>();
Set<LogicalVariable> usedVarsSetInThisOp = new HashSet<>();
// Add used variables in this operator to the accumulated used variables set?
boolean addUsedVarsInThisOp = true;
// ASSIGN, AGGREGATE, UNNEST, UNIONALL, or GROUP operator found?
boolean targetOpFound = false;
switch(op.getOperatorTag()) {
case ASSIGN:
AssignOperator assign = (AssignOperator) op;
assignVarsSetInThisOp.addAll(assign.getVariables());
targetOpFound = true;
break;
case AGGREGATE:
AggregateOperator agg = (AggregateOperator) op;
assignVarsSetInThisOp.addAll(agg.getVariables());
targetOpFound = true;
break;
case UNNEST:
UnnestOperator uOp = (UnnestOperator) op;
LogicalVariable pVar = uOp.getPositionalVariable();
if (pVar != null) {
assignVarsSetInThisOp.add(pVar);
targetOpFound = true;
}
break;
case UNIONALL:
UnionAllOperator unionOp = (UnionAllOperator) op;
for (Triple<LogicalVariable, LogicalVariable, LogicalVariable> varMapping : unionOp.getVariableMappings()) {
assignVarsSetInThisOp.add(varMapping.third);
}
targetOpFound = true;
// Don't add used variables in UNIONALL.
addUsedVarsInThisOp = false;
break;
case GROUP:
GroupByOperator groupByOp = (GroupByOperator) op;
for (Pair<LogicalVariable, Mutable<ILogicalExpression>> decorMapping : groupByOp.getDecorList()) {
LogicalVariable decorVar = decorMapping.first;
if (decorVar != null) {
assignVarsSetInThisOp.add(decorVar);
targetOpFound = true;
} else {
// A decor var mapping can have a variable reference expression without a new variable
// definition, which is for rebinding the referred variable.
VariableReferenceExpression varExpr = (VariableReferenceExpression) decorMapping.second.getValue();
LogicalVariable reboundDecorVar = varExpr.getVariableReference();
assignVarsSetInThisOp.add(reboundDecorVar);
}
}
break;
default:
break;
}
if (targetOpFound) {
assignedVarMap.put(opRef, assignVarsSetInThisOp);
assignedVarSet.addAll(assignVarsSetInThisOp);
}
if (addUsedVarsInThisOp) {
VariableUtilities.getUsedVariables(op, usedVarsSetInThisOp);
accumulatedUsedVarFromRootSet.addAll(usedVarsSetInThisOp);
// paths in the plan.
if (accumulatedUsedVarFromRootMap.containsKey(opRef)) {
accumulatedUsedVarFromRootMap.get(opRef).addAll(accumulatedUsedVarFromRootSet);
} else {
accumulatedUsedVarFromRootMap.put(opRef, new HashSet<LogicalVariable>(accumulatedUsedVarFromRootSet));
}
} else {
accumulatedUsedVarFromRootMap.put(opRef, new HashSet<LogicalVariable>(accumulatedUsedVarFromRootSet));
}
for (Mutable<ILogicalOperator> c : op.getInputs()) {
collectUnusedAssignedVars(c, new HashSet<LogicalVariable>(accumulatedUsedVarFromRootSet), false, context);
}
if (op.hasNestedPlans()) {
AbstractOperatorWithNestedPlans opWithNested = (AbstractOperatorWithNestedPlans) op;
for (ILogicalPlan plan : opWithNested.getNestedPlans()) {
for (Mutable<ILogicalOperator> r : plan.getRoots()) {
collectUnusedAssignedVars(r, new HashSet<LogicalVariable>(accumulatedUsedVarFromRootSet), false, context);
}
}
}
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression in project asterixdb by apache.
the class IntroduceGroupByForSubplanRule method buildVarExprList.
private Map<LogicalVariable, LogicalVariable> buildVarExprList(Collection<LogicalVariable> vars, IOptimizationContext context, GroupByOperator g, List<Pair<LogicalVariable, Mutable<ILogicalExpression>>> outVeList) throws AlgebricksException {
Map<LogicalVariable, LogicalVariable> m = new HashMap<LogicalVariable, LogicalVariable>();
for (LogicalVariable ov : vars) {
LogicalVariable newVar = context.newVar();
ILogicalExpression varExpr = new VariableReferenceExpression(newVar);
outVeList.add(new Pair<LogicalVariable, Mutable<ILogicalExpression>>(ov, new MutableObject<ILogicalExpression>(varExpr)));
for (ILogicalPlan p : g.getNestedPlans()) {
for (Mutable<ILogicalOperator> r : p.getRoots()) {
OperatorManipulationUtil.substituteVarRec((AbstractLogicalOperator) r.getValue(), ov, newVar, true, context);
}
}
AbstractLogicalOperator opUnder = (AbstractLogicalOperator) g.getInputs().get(0).getValue();
OperatorManipulationUtil.substituteVarRec(opUnder, ov, newVar, true, context);
m.put(ov, newVar);
}
return m;
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression in project asterixdb by apache.
the class RemoveRedundantGroupByDecorVarsRule method checkAndApplyTheRule.
/**
* Collect used variables in each operator in the plan until the optimizer sees a GroupBy operator.
* It first removes duplicated variables in the decor list.
* Then, it eliminates useless variables in the decor list that are not going to be used
* after the given groupBy operator.
*/
protected boolean checkAndApplyTheRule(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
Set<LogicalVariable> usedVarsFromThisOp = new HashSet<>();
Set<LogicalVariable> collectedUsedVarsBeforeThisOpFromRoot = new HashSet<>();
boolean redundantVarsRemoved = false;
boolean uselessVarsRemoved = false;
// Found Group-By operator?
if (op.getOperatorTag() == LogicalOperatorTag.GROUP) {
GroupByOperator groupByOp = (GroupByOperator) op;
Set<LogicalVariable> decorVars = new HashSet<>();
// First, get rid of duplicated variables from a group-by operator's decor list.
Iterator<Pair<LogicalVariable, Mutable<ILogicalExpression>>> iter = groupByOp.getDecorList().iterator();
while (iter.hasNext()) {
Pair<LogicalVariable, Mutable<ILogicalExpression>> decor = iter.next();
if (decor.first != null || decor.second.getValue().getExpressionTag() != LogicalExpressionTag.VARIABLE) {
continue;
}
VariableReferenceExpression varRefExpr = (VariableReferenceExpression) decor.second.getValue();
LogicalVariable var = varRefExpr.getVariableReference();
if (decorVars.contains(var)) {
iter.remove();
redundantVarsRemoved = true;
} else {
decorVars.add(var);
}
}
// Next, get rid of useless decor variables in the GROUP-BY operator.
List<Pair<LogicalVariable, Mutable<ILogicalExpression>>> newDecorList = new ArrayList<>();
for (Pair<LogicalVariable, Mutable<ILogicalExpression>> p : groupByOp.getDecorList()) {
LogicalVariable decorVar = GroupByOperator.getDecorVariable(p);
// If a variable in the decor list will not be used after this operator, then it needs to be removed.
if (!usedVars.contains(decorVar)) {
uselessVarsRemoved = true;
} else {
// Maintain the variable since it will be used.
newDecorList.add(p);
}
}
// then the decor list needs to be reset without those variables.
if (uselessVarsRemoved) {
groupByOp.getDecorList().clear();
groupByOp.getDecorList().addAll(newDecorList);
}
// since if there are more GROUP-BY operators, the next trigger on this plan will find them.
if (redundantVarsRemoved || uselessVarsRemoved) {
context.computeAndSetTypeEnvironmentForOperator(groupByOp);
context.addToDontApplySet(this, op);
return redundantVarsRemoved || uselessVarsRemoved;
}
}
// Either we have found a GroupBy operator but no removal is happened or
// there we haven't found a GroupBy operator yet. Thus, we add used variables for this operator
// and keep traversing the plan.
VariableUtilities.getUsedVariables(op, usedVarsFromThisOp);
collectedUsedVarsBeforeThisOpFromRoot.addAll(usedVars);
usedVars.addAll(usedVarsFromThisOp);
// Recursively check the plan and try to optimize it.
for (int i = 0; i < op.getInputs().size(); i++) {
boolean groupByChanged = checkAndApplyTheRule(op.getInputs().get(i), context);
if (groupByChanged) {
return true;
}
}
// This rule can't be applied to this operator or its descendants.
// Thus, remove the effects of this operator so that the depth-first-search can return to the parent.
usedVars.clear();
usedVars.addAll(collectedUsedVarsBeforeThisOpFromRoot);
return false;
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression in project asterixdb by apache.
the class ListifyUnnestingFunctionRule method listifyUnnestingFunction.
// Performs the actual logical transformation.
private boolean listifyUnnestingFunction(ILogicalOperator op, Mutable<ILogicalExpression> exprRef, AbstractFunctionCallExpression func, IOptimizationContext context) throws AlgebricksException {
IFunctionInfo functionInfo = func.getFunctionInfo();
// Checks if the function is an unnesting function.
if (!BuiltinFunctions.isBuiltinUnnestingFunction(functionInfo.getFunctionIdentifier())) {
return false;
}
// Generates the listified collection in a subplan.
SubplanOperator subplanOperator = new SubplanOperator();
// Creates a nested tuple source operator.
NestedTupleSourceOperator ntsOperator = new NestedTupleSourceOperator(new MutableObject<>(subplanOperator));
// Unnests the dataset.
LogicalVariable unnestVar = context.newVar();
ILogicalExpression unnestExpr = new UnnestingFunctionCallExpression(functionInfo, func.getArguments());
UnnestOperator unnestOperator = new UnnestOperator(unnestVar, new MutableObject<>(unnestExpr));
unnestOperator.getInputs().add(new MutableObject<>(ntsOperator));
// Listify the dataset into one collection.
LogicalVariable aggVar = context.newVar();
Mutable<ILogicalExpression> aggArgExprRef = new MutableObject<>(new VariableReferenceExpression(unnestVar));
ILogicalExpression aggExpr = new AggregateFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.LISTIFY), false, new ArrayList<>(Collections.singletonList(aggArgExprRef)));
AggregateOperator aggregateOperator = new AggregateOperator(new ArrayList<>(Collections.singletonList(aggVar)), new ArrayList<>(Collections.singletonList(new MutableObject<>(aggExpr))));
aggregateOperator.getInputs().add(new MutableObject<>(unnestOperator));
// Adds the aggregate operator as the root of the subplan.
subplanOperator.setRootOp(new MutableObject<>(aggregateOperator));
// Sticks a subplan operator into the query plan.
// Note: given the way we compile JOINs, the unnesting function expression cannot appear in
// any binary operators.
// Example test queries:
// asterixdb/asterix-app/src/test/resources/runtimets/results/list/query-ASTERIXDB-159-2
// asterixdb/asterix-app/src/test/resources/runtimets/results/list/query-ASTERIXDB-159-3
subplanOperator.getInputs().add(op.getInputs().get(0));
op.getInputs().set(0, new MutableObject<>(subplanOperator));
exprRef.setValue(new VariableReferenceExpression(aggVar));
// Computes type environments for new operators.
context.computeAndSetTypeEnvironmentForOperator(ntsOperator);
context.computeAndSetTypeEnvironmentForOperator(unnestOperator);
context.computeAndSetTypeEnvironmentForOperator(aggregateOperator);
context.computeAndSetTypeEnvironmentForOperator(subplanOperator);
return true;
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression in project asterixdb by apache.
the class IntroduceSecondaryIndexInsertDeleteRule method createFilterExpression.
private Mutable<ILogicalExpression> createFilterExpression(List<LogicalVariable> secondaryKeyVars, IVariableTypeEnvironment typeEnv, boolean forceFilter) throws AlgebricksException {
List<Mutable<ILogicalExpression>> filterExpressions = new ArrayList<>();
// condition.
for (LogicalVariable secondaryKeyVar : secondaryKeyVars) {
IAType secondaryKeyType = (IAType) typeEnv.getVarType(secondaryKeyVar);
if (!NonTaggedFormatUtil.isOptional(secondaryKeyType) && !forceFilter) {
continue;
}
ScalarFunctionCallExpression isUnknownFuncExpr = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.IS_UNKOWN), new MutableObject<ILogicalExpression>(new VariableReferenceExpression(secondaryKeyVar)));
ScalarFunctionCallExpression notFuncExpr = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.NOT), new MutableObject<ILogicalExpression>(isUnknownFuncExpr));
filterExpressions.add(new MutableObject<ILogicalExpression>(notFuncExpr));
}
// No nullable secondary keys.
if (filterExpressions.isEmpty()) {
return null;
}
Mutable<ILogicalExpression> filterExpression;
if (filterExpressions.size() > 1) {
// Create a conjunctive condition.
filterExpression = new MutableObject<>(new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.AND), filterExpressions));
} else {
filterExpression = filterExpressions.get(0);
}
return filterExpression;
}
Aggregations