private void removeUnusedAssigns( Mutable<ILogicalOperator> opRef, Set<LogicalVariable> toRemove, IOptimizationContext context) throws AlgebricksException { AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue(); while (removeFromAssigns(op, toRemove, context) == 0) { if (op.getOperatorTag() == LogicalOperatorTag.AGGREGATE) { break; } op = (AbstractLogicalOperator) op.getInputs().get(0).getValue(); opRef.setValue(op); } Iterator<Mutable<ILogicalOperator>> childIter = op.getInputs().iterator(); while (childIter.hasNext()) { Mutable<ILogicalOperator> cRef = childIter.next(); removeUnusedAssigns(cRef, toRemove, context); } if (op.hasNestedPlans()) { AbstractOperatorWithNestedPlans opWithNest = (AbstractOperatorWithNestedPlans) op; Iterator<ILogicalPlan> planIter = opWithNest.getNestedPlans().iterator(); while (planIter.hasNext()) { ILogicalPlan p = planIter.next(); for (Mutable<ILogicalOperator> r : p.getRoots()) { removeUnusedAssigns(r, toRemove, context); } } // Removes redundant nested plans that produces nothing for (int i = opWithNest.getNestedPlans().size() - 1; i >= 0; i--) { ILogicalPlan nestedPlan = opWithNest.getNestedPlans().get(i); List<Mutable<ILogicalOperator>> rootsToBeRemoved = new ArrayList<Mutable<ILogicalOperator>>(); for (Mutable<ILogicalOperator> r : nestedPlan.getRoots()) { ILogicalOperator topOp = r.getValue(); Set<LogicalVariable> producedVars = new ListSet<LogicalVariable>(); VariableUtilities.getProducedVariablesInDescendantsAndSelf(topOp, producedVars); if (producedVars.size() == 0) { rootsToBeRemoved.add(r); } } // Makes sure the operator should have at least ONE nested plan even it is empty // (because a lot of places uses this assumption, TODO(yingyib): clean them up). if (nestedPlan.getRoots().size() == rootsToBeRemoved.size() && opWithNest.getNestedPlans().size() > 1) { nestedPlan.getRoots().removeAll(rootsToBeRemoved); opWithNest.getNestedPlans().remove(nestedPlan); } } } }
private void collectUnusedAssignedVars( AbstractLogicalOperator op, Set<LogicalVariable> toRemove, boolean first, IOptimizationContext context) throws AlgebricksException { if (!first) { context.addToDontApplySet(this, op); } for (Mutable<ILogicalOperator> c : op.getInputs()) { collectUnusedAssignedVars((AbstractLogicalOperator) c.getValue(), toRemove, false, context); } if (op.hasNestedPlans()) { AbstractOperatorWithNestedPlans opWithNested = (AbstractOperatorWithNestedPlans) op; for (ILogicalPlan plan : opWithNested.getNestedPlans()) { for (Mutable<ILogicalOperator> r : plan.getRoots()) { collectUnusedAssignedVars( (AbstractLogicalOperator) r.getValue(), toRemove, false, context); } } } boolean removeUsedVars = true; switch (op.getOperatorTag()) { case ASSIGN: { AssignOperator assign = (AssignOperator) op; toRemove.addAll(assign.getVariables()); break; } case AGGREGATE: { AggregateOperator agg = (AggregateOperator) op; toRemove.addAll(agg.getVariables()); break; } case UNNEST: { UnnestOperator uOp = (UnnestOperator) op; LogicalVariable pVar = uOp.getPositionalVariable(); if (pVar != null) { toRemove.add(pVar); } break; } case UNIONALL: { UnionAllOperator unionOp = (UnionAllOperator) op; for (Triple<LogicalVariable, LogicalVariable, LogicalVariable> varMapping : unionOp.getVariableMappings()) { toRemove.add(varMapping.third); } removeUsedVars = false; break; } } if (removeUsedVars) { List<LogicalVariable> used = new LinkedList<LogicalVariable>(); VariableUtilities.getUsedVariables(op, used); toRemove.removeAll(used); } }
@Override public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException { AbstractLogicalOperator unnest = (AbstractLogicalOperator) opRef.getValue(); if (unnest.getOperatorTag() != LogicalOperatorTag.UNNEST) { return false; } UnnestOperator unnestOpRef = (UnnestOperator) opRef.getValue(); Mutable<ILogicalOperator> unionOp = unnest.getInputs().get(0); AbstractLogicalOperator unionAbstractOp = (AbstractLogicalOperator) unionOp.getValue(); if (unionAbstractOp.getOperatorTag() != LogicalOperatorTag.UNIONALL) { return false; } LogicalVariable unnestVar1 = context.newVar(); UnnestOperator unnest1 = new UnnestOperator( unnestVar1, new MutableObject<ILogicalExpression>( unnestOpRef.getExpressionRef().getValue().cloneExpression())); LogicalVariable unnestVar2 = context.newVar(); UnnestOperator unnest2 = new UnnestOperator( unnestVar2, new MutableObject<ILogicalExpression>( unnestOpRef.getExpressionRef().getValue().cloneExpression())); // Getting the two topmost branched and adding them as an input to the unnests: Mutable<ILogicalOperator> branch1 = unionAbstractOp.getInputs().get(0); ILogicalOperator agg1 = branch1.getValue(); List<LogicalVariable> agg1_var = new ArrayList<LogicalVariable>(); VariableUtilities.getLiveVariables(agg1, agg1_var); Mutable<ILogicalOperator> branch2 = unionAbstractOp.getInputs().get(1); ILogicalOperator agg2 = branch2.getValue(); List<LogicalVariable> agg2_var = new ArrayList<LogicalVariable>(); VariableUtilities.getLiveVariables(agg2, agg2_var); // Modifying the unnest so it has the right variable List<LogicalVariable> var_unnest_1 = new ArrayList<LogicalVariable>(); unnest1.getExpressionRef().getValue().getUsedVariables(var_unnest_1); unnest1.getExpressionRef().getValue().substituteVar(var_unnest_1.get(0), agg1_var.get(0)); List<LogicalVariable> var_unnest2 = new ArrayList<LogicalVariable>(); unnest2.getExpressionRef().getValue().getUsedVariables(var_unnest2); unnest2.getExpressionRef().getValue().substituteVar(var_unnest2.get(0), agg2_var.get(0)); unnest1.getInputs().add(branch1); unnest2.getInputs().add(branch2); context.computeAndSetTypeEnvironmentForOperator(unnest1); context.computeAndSetTypeEnvironmentForOperator(unnest2); // creating a new union operator with the updated logical variables List<Triple<LogicalVariable, LogicalVariable, LogicalVariable>> varMap = new ArrayList<Triple<LogicalVariable, LogicalVariable, LogicalVariable>>(1); Triple<LogicalVariable, LogicalVariable, LogicalVariable> union_triple_vars = new Triple<LogicalVariable, LogicalVariable, LogicalVariable>( unnestVar1, unnestVar2, unnestOpRef.getVariables().get(0)); varMap.add(union_triple_vars); UnionAllOperator unionOpFinal = new UnionAllOperator(varMap); unionOpFinal.getInputs().add(new MutableObject<ILogicalOperator>(unnest1)); unionOpFinal.getInputs().add(new MutableObject<ILogicalOperator>(unnest2)); context.computeAndSetTypeEnvironmentForOperator(unionOpFinal); opRef.setValue(unionOpFinal); return true; }