in algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/visitors/FDsAndEquivClassesVisitor.java [617:699]
private void propagateFDsAndEquivClassesForUsedVars(ILogicalOperator op, IOptimizationContext ctx,
List<LogicalVariable> usedVariables) throws AlgebricksException {
ILogicalOperator op2 = op.getInputs().get(0).getValue();
Map<LogicalVariable, EquivalenceClass> eqClasses = getOrCreateEqClasses(op, ctx);
List<FunctionalDependency> fds = new ArrayList<FunctionalDependency>();
ctx.putFDList(op, fds);
Map<LogicalVariable, EquivalenceClass> chldClasses = getOrComputeEqClasses(op2, ctx);
// Propagate equivalent classes that contain the used variables.
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);
}
}
}
// Propagates equivalent classes that contain expressions that use the
// used variables.
// Note that for the case variable $v is not in the used variables but
// it is
// equivalent to field-access($t, i) and $t is a used variable, the
// equivalent
// class should still be propagated (kept).
Set<LogicalVariable> usedVarSet = new HashSet<LogicalVariable>(usedVariables);
for (Entry<LogicalVariable, EquivalenceClass> entry : chldClasses.entrySet()) {
EquivalenceClass ec = entry.getValue();
for (ILogicalExpression expr : ec.getExpressionMembers()) {
Set<LogicalVariable> exprUsedVars = new HashSet<LogicalVariable>();
expr.getUsedVariables(exprUsedVars);
exprUsedVars.retainAll(usedVarSet);
// Check if the expression member uses a used variable.
if (!exprUsedVars.isEmpty()) {
for (LogicalVariable v : ec.getMembers()) {
eqClasses.put(v, ec);
// If variable members contain a used variable, the
// representative
// variable should be a used variable.
if (usedVarSet.contains(v)) {
ec.setVariableRepresentative(v);
}
}
}
}
}
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);
}
}
}