@Override public Void visitSelectOperator(SelectOperator op, IOptimizationContext ctx) throws AlgebricksException { ILogicalOperator childOp = op.getInputs().get(0).getValue(); Map<LogicalVariable, EquivalenceClass> equivalenceClasses = getOrComputeEqClasses(childOp, ctx); ctx.putEquivalenceClassMap(op, equivalenceClasses); List<FunctionalDependency> functionalDependencies = new ArrayList<FunctionalDependency>(); ctx.putFDList(op, functionalDependencies); functionalDependencies.addAll(getOrComputeFDs(childOp, ctx)); equivalenceClasses.putAll(getOrComputeEqClasses(childOp, ctx)); ILogicalExpression expr = op.getCondition().getValue(); expr.getConstraintsAndEquivClasses(functionalDependencies, equivalenceClasses); return null; }
@Override public Void visitInnerJoinOperator(InnerJoinOperator op, IOptimizationContext ctx) throws AlgebricksException { Map<LogicalVariable, EquivalenceClass> equivalenceClasses = new HashMap<LogicalVariable, EquivalenceClass>(); List<FunctionalDependency> functionalDependencies = new ArrayList<FunctionalDependency>(); ctx.putEquivalenceClassMap(op, equivalenceClasses); ctx.putFDList(op, functionalDependencies); ILogicalOperator op0 = op.getInputs().get(0).getValue(); ILogicalOperator op1 = op.getInputs().get(1).getValue(); functionalDependencies.addAll(getOrComputeFDs(op0, ctx)); functionalDependencies.addAll(getOrComputeFDs(op1, ctx)); equivalenceClasses.putAll(getOrComputeEqClasses(op0, ctx)); equivalenceClasses.putAll(getOrComputeEqClasses(op1, ctx)); ILogicalExpression expr = op.getCondition().getValue(); expr.getConstraintsAndEquivClasses(functionalDependencies, equivalenceClasses); return null; }
@Override public Void visitLeftOuterUnnestMapOperator(LeftOuterUnnestMapOperator op, IOptimizationContext ctx) throws AlgebricksException { // Unlike the unnest-map operator, we propagate all inputs since // propagateInuput is always true. Map<LogicalVariable, EquivalenceClass> equivalenceClasses = new HashMap<LogicalVariable, EquivalenceClass>(); List<FunctionalDependency> functionalDependencies = new ArrayList<FunctionalDependency>(); ctx.putEquivalenceClassMap(op, equivalenceClasses); ctx.putFDList(op, functionalDependencies); ILogicalOperator childOp = op.getInputs().get(0).getValue(); functionalDependencies.addAll(getOrComputeFDs(childOp, ctx)); equivalenceClasses.putAll(getOrComputeEqClasses(childOp, ctx)); // Like Left-Outer join case, we add functional dependencies. List<LogicalVariable> leftSideVars = new ArrayList<LogicalVariable>(); List<LogicalVariable> producedVars = new ArrayList<LogicalVariable>(); VariableUtilities.getUsedVariables(op, leftSideVars); VariableUtilities.getProducedVariables(op, leftSideVars); functionalDependencies.add(new FunctionalDependency(leftSideVars, producedVars)); return null; }
@Override public Void visitSubplanOperator(SubplanOperator op, IOptimizationContext ctx) throws AlgebricksException { Map<LogicalVariable, EquivalenceClass> equivalenceClasses = new HashMap<LogicalVariable, EquivalenceClass>(); List<FunctionalDependency> functionalDependencies = new ArrayList<FunctionalDependency>(); ctx.putEquivalenceClassMap(op, equivalenceClasses); ctx.putFDList(op, functionalDependencies); for (ILogicalPlan p : op.getNestedPlans()) { for (Mutable<ILogicalOperator> r : p.getRoots()) { ILogicalOperator op2 = r.getValue(); equivalenceClasses.putAll(getOrComputeEqClasses(op2, ctx)); functionalDependencies.addAll(getOrComputeFDs(op2, ctx)); } } return null; }
private void propagateFDsAndEquivClasses(ILogicalOperator op, IOptimizationContext ctx) throws AlgebricksException { ILogicalOperator inp1 = op.getInputs().get(0).getValue(); Map<LogicalVariable, EquivalenceClass> eqClasses = getOrComputeEqClasses(inp1, ctx); ctx.putEquivalenceClassMap(op, eqClasses); List<FunctionalDependency> fds = getOrComputeFDs(inp1, ctx); ctx.putFDList(op, fds); }
@Override public Void visitLeftOuterJoinOperator(LeftOuterJoinOperator op, IOptimizationContext ctx) throws AlgebricksException { Map<LogicalVariable, EquivalenceClass> equivalenceClasses = new HashMap<LogicalVariable, EquivalenceClass>(); List<FunctionalDependency> functionalDependencies = new ArrayList<FunctionalDependency>(); ctx.putEquivalenceClassMap(op, equivalenceClasses); ctx.putFDList(op, functionalDependencies); ILogicalOperator opLeft = op.getInputs().get(0).getValue(); ILogicalOperator opRight = op.getInputs().get(1).getValue(); functionalDependencies.addAll(getOrComputeFDs(opLeft, ctx)); functionalDependencies.addAll(getOrComputeFDs(opRight, ctx)); equivalenceClasses.putAll(getOrComputeEqClasses(opLeft, ctx)); equivalenceClasses.putAll(getOrComputeEqClasses(opRight, ctx)); Collection<LogicalVariable> leftSideVars; if (opLeft.getSchema() == null) { leftSideVars = new LinkedList<LogicalVariable>(); VariableUtilities.getLiveVariables(opLeft, leftSideVars); // actually, not all produced vars. are visible (due to projection) // so using cached schema is better and faster } else { leftSideVars = opLeft.getSchema(); } ILogicalExpression expr = op.getCondition().getValue(); expr.getConstraintsForOuterJoin(functionalDependencies, leftSideVars); return null; }
@Override public Void visitNestedTupleSourceOperator(NestedTupleSourceOperator op, IOptimizationContext ctx) throws AlgebricksException { AbstractLogicalOperator op1 = (AbstractLogicalOperator) op.getDataSourceReference().getValue(); ILogicalOperator inp1 = op1.getInputs().get(0).getValue(); Map<LogicalVariable, EquivalenceClass> eqClasses = getOrComputeEqClasses(inp1, ctx); ctx.putEquivalenceClassMap(op, eqClasses); List<FunctionalDependency> fds = new ArrayList<FunctionalDependency>(getOrComputeFDs(inp1, ctx)); if (op1.getOperatorTag() == LogicalOperatorTag.GROUP) { GroupByOperator gby = (GroupByOperator) op1; LinkedList<LogicalVariable> tail = new LinkedList<LogicalVariable>(); for (LogicalVariable v : gby.getGbyVarList()) { tail.add(v); // all values for gby vars. are the same } FunctionalDependency gbyfd = new FunctionalDependency(new LinkedList<LogicalVariable>(), tail); fds.add(gbyfd); } ctx.putFDList(op, fds); return null; }
@Override public Void visitDataScanOperator(DataSourceScanOperator op, IOptimizationContext ctx) throws AlgebricksException { ILogicalOperator inp1 = op.getInputs().get(0).getValue(); Map<LogicalVariable, EquivalenceClass> eqClasses = getOrCreateEqClasses(op, ctx); Map<LogicalVariable, EquivalenceClass> propagatedEqClasses = getOrComputeEqClasses(inp1, ctx); eqClasses.putAll(propagatedEqClasses); ctx.putEquivalenceClassMap(op, eqClasses); List<FunctionalDependency> fds = new ArrayList<FunctionalDependency>(getOrComputeFDs(inp1, ctx)); ctx.putFDList(op, fds); op.getDataSource().computeFDs(op.getVariables(), fds); return null; }
@Override public Void visitAssignOperator(AssignOperator op, IOptimizationContext ctx) throws AlgebricksException { ILogicalOperator inp1 = op.getInputs().get(0).getValue(); Map<LogicalVariable, EquivalenceClass> eqClasses = getOrComputeEqClasses(inp1, ctx); ctx.putEquivalenceClassMap(op, eqClasses); // Propagates equivalence classes that from expressions. // Note that an equivalence class can also contain expression members. propagateEquivalenceFromExpressionsToVariables(eqClasses, op.getExpressions(), op.getVariables()); // Generates FDs. List<LogicalVariable> used = new ArrayList<LogicalVariable>(); VariableUtilities.getUsedVariables(op, used); List<FunctionalDependency> fds1 = getOrComputeFDs(inp1, ctx); List<FunctionalDependency> eFds = new ArrayList<FunctionalDependency>(fds1.size()); for (FunctionalDependency fd : fds1) { if (fd.getTail().containsAll(used)) { List<LogicalVariable> hd = new ArrayList<LogicalVariable>(fd.getHead()); List<LogicalVariable> tl = new ArrayList<LogicalVariable>(fd.getTail()); tl.addAll(op.getVariables()); FunctionalDependency fd2 = new FunctionalDependency(hd, tl); eFds.add(fd2); } else { eFds.add(fd); } } ctx.putFDList(op, eFds); return null; }
ctx.putFDList(op, fds); Map<LogicalVariable, EquivalenceClass> chldClasses = getOrComputeEqClasses(op2, ctx);
private void fdsEqClassesForAbstractUnnestOperator(AbstractUnnestOperator op, IOptimizationContext ctx) throws AlgebricksException { ILogicalOperator inp1 = op.getInputs().get(0).getValue(); Map<LogicalVariable, EquivalenceClass> eqClasses = getOrCreateEqClasses(op, ctx); Map<LogicalVariable, EquivalenceClass> propagatedEqClasses = getOrComputeEqClasses(inp1, ctx); /** * The original eq classes of unnest-map are only for produced * variables, therefore eqClasses and propagatedEqClasses do not have * overlaps. */ eqClasses.putAll(propagatedEqClasses); ctx.putEquivalenceClassMap(op, eqClasses); List<FunctionalDependency> fds = getOrComputeFDs(inp1, ctx); ctx.putFDList(op, fds); ILogicalExpression expr = op.getExpressionRef().getValue(); if (expr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) { AbstractFunctionCallExpression afe = (AbstractFunctionCallExpression) expr; if (afe.getKind() == FunctionKind.UNNEST && ((UnnestingFunctionCallExpression) afe).returnsUniqueValues()) { List<LogicalVariable> vars = new ArrayList<LogicalVariable>(); VariableUtilities.getLiveVariables(op, vars); ArrayList<LogicalVariable> h = new ArrayList<LogicalVariable>(); h.addAll(op.getVariables()); FunctionalDependency fd = new FunctionalDependency(h, vars); fds.add(fd); } } }
Map<LogicalVariable, EquivalenceClass> equivalenceClasses = getOrComputeEqClasses(op0, ctx); ctx.putEquivalenceClassMap(op, equivalenceClasses);
for (Mutable<ILogicalOperator> r : p.getRoots()) { ILogicalOperator op2 = r.getValue(); equivalenceClasses.putAll(getOrComputeEqClasses(op2, ctx)); inheritedFDs.addAll(getOrComputeFDs(op2, ctx)); Map<LogicalVariable, EquivalenceClass> inheritedEcs = getOrComputeEqClasses(op0, ctx); for (FunctionalDependency inherited : inheritedFDs) { boolean isCoveredByGbyOrDecorVars = true;