@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; }