public IEnvironmentAction buildFoldedEdgeAction()

in asterix-graphix/src/main/java/org/apache/asterix/graphix/lang/rewrite/lower/EnvironmentActionFactory.java [268:341]


    public IEnvironmentAction buildFoldedEdgeAction(VertexPatternExpr vertexPatternExpr,
            EdgePatternExpr edgePatternExpr) throws CompilationException {
        VariableExpr vertexVar = vertexPatternExpr.getVariableExpr();
        VariableExpr edgeVar = edgePatternExpr.getEdgeDescriptor().getVariableExpr();
        VariableExpr intermediateVar = graphixRewritingContext.getGraphixVariableCopy(edgeVar);

        // We should only be working with one identifier (given that we only have one label).
        List<EdgeIdentifier> edgeElementIDs = edgePatternExpr.generateIdentifiers(graphIdentifier);
        if (edgeElementIDs.size() != 1) {
            throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, "Found non-canonical edge pattern!");
        }
        EdgeIdentifier edgeIdentifier = edgeElementIDs.get(0);
        ElementBodyAnalysisContext edgeAnalysisContext = analysisContextMap.get(edgeIdentifier);
        if (edgeAnalysisContext.isSelectClauseInline()) {
            return new AbstractInlineAction(graphixRewritingContext, edgeAnalysisContext, null) {
                @Override
                public void apply(LoweringEnvironment loweringEnvironment) throws CompilationException {
                    // We want to bind directly to the iteration variable of our vertex, not the join variable.
                    elementVariable = aliasLookupTable.getIterationAlias(vertexVar);

                    // Inline our edge body.
                    super.apply(loweringEnvironment);

                    // If we have a filter expression, add it as a WHERE clause here.
                    final Expression filterExpr = edgePatternExpr.getEdgeDescriptor().getFilterExpr();
                    if (filterExpr != null) {
                        loweringEnvironment.acceptAction(buildFilterExprAction(filterExpr, edgeVar, elementVariable));
                    }

                    // Build a binding for our edge variable.
                    loweringEnvironment.acceptTransformer(lowerList -> {
                        VariableExpr elementVarCopy1 = graphixDeepCopyVisitor.visit(elementVariable, null);
                        VariableExpr elementVarCopy2 = graphixDeepCopyVisitor.visit(elementVariable, null);
                        VariableExpr intermediateVarCopy = graphixDeepCopyVisitor.visit(intermediateVar, null);
                        LetClause nonRepresentativeBinding = new LetClause(intermediateVarCopy, elementVarCopy1);
                        lowerList.addNonRepresentativeClause(nonRepresentativeBinding);
                        lowerList.addEdgeBinding(edgeVar, elementVarCopy2);
                    });
                    aliasLookupTable.addIterationAlias(edgeVar, elementVariable);
                    aliasLookupTable.addJoinAlias(edgeVar, intermediateVar);
                }
            };

        } else {
            return new AbstractInlineAction(graphixRewritingContext, edgeAnalysisContext, null) {
                @Override
                public void apply(LoweringEnvironment loweringEnvironment) throws CompilationException {
                    // We want to bind directly to the iteration variable of our vertex, not the join variable.
                    elementVariable = aliasLookupTable.getIterationAlias(vertexVar);

                    // Inline our edge body.
                    super.apply(loweringEnvironment);

                    // If we have a filter expression, add it as a WHERE clause here.
                    final Expression filterExpr = edgePatternExpr.getEdgeDescriptor().getFilterExpr();
                    if (filterExpr != null) {
                        loweringEnvironment.acceptAction(buildFilterExprAction(filterExpr, edgeVar, elementVariable));
                    }

                    // Build a record constructor from our context to bind to our edge and intermediate (join) var.
                    loweringEnvironment.acceptTransformer(lowerList -> {
                        VariableExpr intermediateVarCopy = graphixDeepCopyVisitor.visit(intermediateVar, null);
                        RecordConstructor recordConstructor1 = buildRecordConstructor();
                        RecordConstructor recordConstructor2 = buildRecordConstructor();
                        LetClause nonRepresentativeBinding = new LetClause(intermediateVarCopy, recordConstructor1);
                        lowerList.addNonRepresentativeClause(nonRepresentativeBinding);
                        lowerList.addEdgeBinding(edgeVar, recordConstructor2);
                    });
                    aliasLookupTable.addIterationAlias(edgeVar, elementVariable);
                    aliasLookupTable.addJoinAlias(edgeVar, intermediateVar);
                }
            };
        }
    }