private void propagateFDsAndEquivClassesForUsedVars( ILogicalOperator op, IOptimizationContext ctx, List<LogicalVariable> usedVariables) throws AlgebricksException { ILogicalOperator op2 = op.getInputs().get(0).getOperator(); Map<LogicalVariable, EquivalenceClass> eqClasses = new HashMap<LogicalVariable, EquivalenceClass>(); ctx.putEquivalenceClassMap(op, eqClasses); List<FunctionalDependency> fds = new ArrayList<FunctionalDependency>(); ctx.putFDList(op, fds); Map<LogicalVariable, EquivalenceClass> chldClasses = getOrComputeEqClasses(op2, ctx); for (LogicalVariable v : usedVariables) { EquivalenceClass ec = eqClasses.get(v); if (ec == null) { EquivalenceClass oc = chldClasses.get(v); if (oc == null) { continue; } List<LogicalVariable> m = new LinkedList<LogicalVariable>(); for (LogicalVariable v2 : oc.getMembers()) { if (usedVariables.contains(v2)) { m.add(v2); } } EquivalenceClass nc; if (oc.representativeIsConst()) { nc = new EquivalenceClass(m, oc.getConstRepresentative()); } else if (m.contains(oc.getVariableRepresentative())) { nc = new EquivalenceClass(m, oc.getVariableRepresentative()); } else { nc = new EquivalenceClass(m, v); } for (LogicalVariable v3 : m) { eqClasses.put(v3, nc); } } } List<FunctionalDependency> chldFds = getOrComputeFDs(op2, ctx); for (FunctionalDependency fd : chldFds) { if (!usedVariables.containsAll(fd.getHead())) { continue; } List<LogicalVariable> tl = new LinkedList<LogicalVariable>(); for (LogicalVariable v : fd.getTail()) { if (usedVariables.contains(v)) { tl.add(v); } } if (!tl.isEmpty()) { FunctionalDependency newFd = new FunctionalDependency(fd.getHead(), tl); fds.add(newFd); } } }
@Override public Void visitAssignOperator(AssignOperator op, IOptimizationContext ctx) throws AlgebricksException { ILogicalOperator inp1 = op.getInputs().get(0).getOperator(); Map<LogicalVariable, EquivalenceClass> eqClasses = getOrComputeEqClasses(inp1, ctx); ctx.putEquivalenceClassMap(op, eqClasses); 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; }
@Override public Void visitGroupByOperator(GroupByOperator 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); List<FunctionalDependency> inheritedFDs = new ArrayList<FunctionalDependency>(); for (ILogicalPlan p : op.getNestedPlans()) { for (LogicalOperatorReference r : p.getRoots()) { ILogicalOperator op2 = r.getOperator(); equivalenceClasses.putAll(getOrComputeEqClasses(op2, ctx)); inheritedFDs.addAll(getOrComputeFDs(op2, ctx)); } } ILogicalOperator op0 = op.getInputs().get(0).getOperator(); inheritedFDs.addAll(getOrComputeFDs(op0, ctx)); Map<LogicalVariable, EquivalenceClass> inheritedEcs = getOrComputeEqClasses(op0, ctx); for (FunctionalDependency inherited : inheritedFDs) { boolean isCoveredByGbyOrDecorVars = true; List<LogicalVariable> newHead = new ArrayList<LogicalVariable>(inherited.getHead().size()); for (LogicalVariable v : inherited.getHead()) { LogicalVariable vnew = getNewGbyVar(op, v); if (vnew == null) { vnew = getNewDecorVar(op, v); if (vnew == null) { isCoveredByGbyOrDecorVars = false; } break; } newHead.add(vnew); } if (isCoveredByGbyOrDecorVars) { List<LogicalVariable> newTail = new ArrayList<LogicalVariable>(); for (LogicalVariable v2 : inherited.getTail()) { LogicalVariable v3 = getNewGbyVar(op, v2); if (v3 != null) { newTail.add(v3); } } if (!newTail.isEmpty()) { FunctionalDependency newFd = new FunctionalDependency(newHead, newTail); functionalDependencies.add(newFd); } } } List<LogicalVariable> premiseGby = new LinkedList<LogicalVariable>(); List<Pair<LogicalVariable, LogicalExpressionReference>> gByList = op.getGroupByList(); for (Pair<LogicalVariable, LogicalExpressionReference> p : gByList) { premiseGby.add(p.first); } List<Pair<LogicalVariable, LogicalExpressionReference>> decorList = op.getDecorList(); LinkedList<LogicalVariable> conclDecor = new LinkedList<LogicalVariable>(); for (Pair<LogicalVariable, LogicalExpressionReference> p : decorList) { conclDecor.add(GroupByOperator.getDecorVariable(p)); } if (!conclDecor.isEmpty()) { functionalDependencies.add(new FunctionalDependency(premiseGby, conclDecor)); } Set<LogicalVariable> gbySet = new HashSet<LogicalVariable>(); for (Pair<LogicalVariable, LogicalExpressionReference> p : gByList) { ILogicalExpression expr = p.second.getExpression(); if (expr.getExpressionTag() == LogicalExpressionTag.VARIABLE) { VariableReferenceExpression v = (VariableReferenceExpression) expr; gbySet.add(v.getVariableReference()); } } LocalGroupingProperty lgp = new LocalGroupingProperty(gbySet); lgp.normalizeGroupingColumns(inheritedEcs, inheritedFDs); Set<LogicalVariable> normSet = lgp.getColumnSet(); List<Pair<LogicalVariable, LogicalExpressionReference>> newGbyList = new ArrayList<Pair<LogicalVariable, LogicalExpressionReference>>(); boolean changed = false; for (Pair<LogicalVariable, LogicalExpressionReference> p : gByList) { ILogicalExpression expr = p.second.getExpression(); if (expr.getExpressionTag() == LogicalExpressionTag.VARIABLE) { VariableReferenceExpression varRef = (VariableReferenceExpression) expr; LogicalVariable v2 = varRef.getVariableReference(); EquivalenceClass ec2 = inheritedEcs.get(v2); LogicalVariable v3; if (ec2 != null && !ec2.representativeIsConst()) { v3 = ec2.getVariableRepresentative(); } else { v3 = v2; } if (normSet.contains(v3)) { newGbyList.add(p); } else { changed = true; decorList.add(p); } } else { newGbyList.add(p); } } if (changed) { AlgebricksConfig.ALGEBRICKS_LOGGER.fine( ">>>> Group-by list changed from " + GroupByOperator.veListToString(gByList) + " to " + GroupByOperator.veListToString(newGbyList) + ".\n"); } gByList.clear(); gByList.addAll(newGbyList); return null; }
@Override public Void visitDistinctOperator(DistinctOperator op, IOptimizationContext ctx) throws AlgebricksException { ILogicalOperator op0 = op.getInputs().get(0).getOperator(); List<FunctionalDependency> functionalDependencies = new ArrayList<FunctionalDependency>(); ctx.putFDList(op, functionalDependencies); for (FunctionalDependency inherited : getOrComputeFDs(op0, ctx)) { boolean isCoveredByDistinctByVars = true; for (LogicalVariable v : inherited.getHead()) { if (!op.isDistinctByVar(v)) { isCoveredByDistinctByVars = false; } } if (isCoveredByDistinctByVars) { List<LogicalVariable> newTail = new ArrayList<LogicalVariable>(); for (LogicalVariable v2 : inherited.getTail()) { if (op.isDistinctByVar(v2)) { newTail.add(v2); } } if (!newTail.isEmpty()) { List<LogicalVariable> newHead = new ArrayList<LogicalVariable>(inherited.getHead()); FunctionalDependency newFd = new FunctionalDependency(newHead, newTail); functionalDependencies.add(newFd); } } } Set<LogicalVariable> gbySet = new HashSet<LogicalVariable>(); List<LogicalExpressionReference> expressions = op.getExpressions(); for (LogicalExpressionReference pRef : expressions) { ILogicalExpression p = pRef.getExpression(); if (p.getExpressionTag() == LogicalExpressionTag.VARIABLE) { VariableReferenceExpression v = (VariableReferenceExpression) p; gbySet.add(v.getVariableReference()); } } LocalGroupingProperty lgp = new LocalGroupingProperty(gbySet); Map<LogicalVariable, EquivalenceClass> equivalenceClasses = getOrComputeEqClasses(op0, ctx); ctx.putEquivalenceClassMap(op, equivalenceClasses); lgp.normalizeGroupingColumns(equivalenceClasses, functionalDependencies); Set<LogicalVariable> normSet = lgp.getColumnSet(); List<LogicalExpressionReference> newDistinctByList = new ArrayList<LogicalExpressionReference>(); for (LogicalExpressionReference p2Ref : expressions) { ILogicalExpression p2 = p2Ref.getExpression(); if (p2.getExpressionTag() == LogicalExpressionTag.VARIABLE) { VariableReferenceExpression var2 = (VariableReferenceExpression) p2; LogicalVariable v2 = var2.getVariableReference(); if (normSet.contains(v2)) { newDistinctByList.add(p2Ref); } } else { newDistinctByList.add(p2Ref); } } expressions.clear(); expressions.addAll(newDistinctByList); return null; }