in asterix-graphix/src/main/java/org/apache/asterix/graphix/lang/rewrite/visitor/GraphixLoweringVisitor.java [367:483]
private void lowerCanonicalExpandedPath(EdgePatternExpr edgePatternExpr, LoweringEnvironment environment)
throws CompilationException {
// Determine the starting vertex of our path.
VariableExpr leftVertexVariable = edgePatternExpr.getLeftVertex().getVariableExpr();
VariableExpr rightVertexVariable = edgePatternExpr.getRightVertex().getVariableExpr();
boolean isLeftVertexIntroduced = aliasLookupTable.getIterationAlias(leftVertexVariable) != null;
boolean isRightVertexIntroduced = aliasLookupTable.getIterationAlias(rightVertexVariable) != null;
boolean isJoiningLeftToRight = isLeftVertexIntroduced || !isRightVertexIntroduced;
VertexPatternExpr inputVertex, outputVertex;
if (isJoiningLeftToRight) {
inputVertex = edgePatternExpr.getLeftVertex();
outputVertex = edgePatternExpr.getRightVertex();
} else {
inputVertex = edgePatternExpr.getRightVertex();
outputVertex = edgePatternExpr.getLeftVertex();
}
VariableExpr inputVertexVariable = inputVertex.getVariableExpr();
VariableExpr outputVertexVariable = outputVertex.getVariableExpr();
// If we need to, introduce our left vertex (only occurs if nothing has been introduced).
if (!isLeftVertexIntroduced && !isRightVertexIntroduced) {
environment.acceptAction(actionFactory.buildDanglingVertexAction(edgePatternExpr.getLeftVertex()));
}
// Our input vertex must be introduced eagerly to be given to our graph clause as input.
VariableExpr inputClauseVariable = graphixRewritingContext.getGraphixVariableCopy(inputVertexVariable);
environment.acceptTransformer(lowerList -> {
// Find the representative vertex associated with our input.
Expression representativeVertexExpr = null;
for (LetClause vertexBinding : lowerList.getRepresentativeVertexBindings()) {
if (vertexBinding.getVarExpr().equals(inputVertex.getVariableExpr())) {
representativeVertexExpr = vertexBinding.getBindingExpr();
break;
}
}
if (representativeVertexExpr == null) {
throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, "Input vertex not found!");
}
// Once all variables of our representative LET-CLAUSE have been introduced, introduce our input binding.
Set<VariableExpr> usedVariables = SqlppVariableUtil.getFreeVariables(representativeVertexExpr);
ListIterator<AbstractClause> nonRepresentativeClauseIterator =
lowerList.getNonRepresentativeClauses().listIterator();
while (nonRepresentativeClauseIterator.hasNext()) {
AbstractClause workingClause = nonRepresentativeClauseIterator.next();
List<VariableExpr> bindingVariables = SqlppVariableUtil.getBindingVariables(workingClause);
bindingVariables.forEach(usedVariables::remove);
if (usedVariables.isEmpty()) {
VariableExpr inputClauseVariableCopy = graphixDeepCopyVisitor.visit(inputClauseVariable, null);
LetClause clauseInputBinding = new LetClause(inputClauseVariableCopy, representativeVertexExpr);
nonRepresentativeClauseIterator.add(clauseInputBinding);
lowerList.addEagerVertexBinding(inputVertex.getVariableExpr(), clauseInputBinding);
break;
}
}
});
// Lower each of our branches.
environment.beginBranches();
Map<ElementLabel, VariableExpr> labelInputVariableMap = new HashMap<>();
Map<ElementLabel, VariableExpr> labelOutputVariableMap = new HashMap<>();
for (EdgePatternExpr branch : branchLookupTable.getBranches(edgePatternExpr)) {
VertexPatternExpr inputBranchVertex, outputBranchVertex;
if (isJoiningLeftToRight) {
inputBranchVertex = branch.getLeftVertex();
outputBranchVertex = branch.getRightVertex();
} else {
inputBranchVertex = branch.getRightVertex();
outputBranchVertex = branch.getLeftVertex();
}
// Introduce the alias-- but do not lower our source vertex.
environment.beginTempLowerList();
environment.acceptAction(actionFactory.buildDanglingVertexAction(inputBranchVertex));
environment.endTempLowerList();
synchronizeVariables(environment, inputBranchVertex, labelInputVariableMap);
inputBranchVertex.addHint(LoweringExemptAnnotation.INSTANCE);
// Lower our branch, having introduced our source vertex.
lowerCanonicalExpandedEdge(branch, environment);
synchronizeVariables(environment, outputBranchVertex, labelOutputVariableMap);
environment.flushBranch(branch, isJoiningLeftToRight);
}
// Our output vertex will be aliased by the following:
VariableExpr outputVertexIterationAlias = graphixRewritingContext.getGraphixVariableCopy(outputVertexVariable);
VariableExpr outputVertexJoinAlias = graphixRewritingContext.getGraphixVariableCopy(outputVertexVariable);
aliasLookupTable.addIterationAlias(outputVertexVariable, outputVertexIterationAlias);
aliasLookupTable.addJoinAlias(outputVertexVariable, outputVertexJoinAlias);
// Introduce a SWITCH node, finalizing our path lowering.
VariableExpr pathVariable = edgePatternExpr.getEdgeDescriptor().getVariableExpr();
VariableExpr outputClauseVariable = graphixRewritingContext.getGraphixVariableCopy(outputVertexVariable);
ClauseOutputEnvironment outputEnvironment = new ClauseOutputEnvironment(outputClauseVariable,
aliasLookupTable.getIterationAlias(outputVertexVariable),
aliasLookupTable.getJoinAlias(outputVertexVariable), pathVariable,
outputVertex.getLabels().iterator().next());
ClauseInputEnvironment inputEnvironment = new ClauseInputEnvironment(
graphixDeepCopyVisitor.visit(inputClauseVariable, null), inputVertex.getLabels().iterator().next());
environment.endBranches(outputEnvironment, inputEnvironment, labelInputVariableMap, labelOutputVariableMap,
aliasLookupTable, edgePatternExpr.getSourceLocation());
// Expose our output vertex and path to the remainder of our query.
environment.acceptTransformer(lowerList -> {
VariableExpr iterationVariableCopy1 = graphixDeepCopyVisitor.visit(outputVertexIterationAlias, null);
VariableExpr iterationVariableCopy2 = graphixDeepCopyVisitor.visit(outputVertexIterationAlias, null);
VariableExpr joinVariableCopy = graphixDeepCopyVisitor.visit(outputVertexJoinAlias, null);
Expression iterationVariableAccess = outputEnvironment.buildIterationVariableAccess();
Expression joinVariableAccess = outputEnvironment.buildJoinVariableAccess();
lowerList.addNonRepresentativeClause(new LetClause(iterationVariableCopy1, iterationVariableAccess));
lowerList.addNonRepresentativeClause(new LetClause(joinVariableCopy, joinVariableAccess));
lowerList.addVertexBinding(outputVertexVariable, iterationVariableCopy2);
lowerList.addPathBinding(pathVariable, outputEnvironment.buildPathVariableAccess());
});
}