private LogicalVariable getNewDecorVar(GroupByOperator g, LogicalVariable v) { for (Pair<LogicalVariable, LogicalExpressionReference> p : g.getDecorList()) { ILogicalExpression e = p.second.getExpression(); if (e.getExpressionTag() == LogicalExpressionTag.VARIABLE) { LogicalVariable v2 = ((VariableReferenceExpression) e).getVariableReference(); if (v2 == v) { return (p.first != null) ? p.first : v2; } } } return null; }
@Override public Void visitNestedTupleSourceOperator(NestedTupleSourceOperator op, IOptimizationContext ctx) throws AlgebricksException { AbstractLogicalOperator op1 = (AbstractLogicalOperator) op.getDataSourceReference().getOperator(); ILogicalOperator inp1 = op1.getInputs().get(0).getOperator(); 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 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; }