private void lowerCanonicalExpandedPath()

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());
        });
    }