diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphBuilder.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphBuilder.java index 276dad1425f5..8ba5e7ccde8b 100644 --- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphBuilder.java +++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/common/ir/tools/GraphBuilder.java @@ -306,13 +306,12 @@ public GraphBuilder match(RelNode first, Iterable others) { RelNode input = size() > 0 ? peek() : null; RelNode match = GraphLogicalMultiMatch.create( - (GraphOptCluster) cluster, - null, - input, - first, - ImmutableList.copyOf(others)); - if (size() > 0) pop(); - push(match); + (GraphOptCluster) cluster, null, null, first, ImmutableList.copyOf(others)); + if (input == null) { + push(match); + } else { + push(match).join(getJoinRelType(GraphOpt.Match.INNER), getJoinCondition(input, match)); + } return this; } diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/GraphBuilderVisitor.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/GraphBuilderVisitor.java index 41a90e548d34..52d04619f33f 100644 --- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/GraphBuilderVisitor.java +++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/GraphBuilderVisitor.java @@ -23,6 +23,7 @@ import com.alibaba.graphscope.cypher.antlr4.visitor.type.ExprVisitorResult; import com.alibaba.graphscope.grammar.CypherGSBaseVisitor; import com.alibaba.graphscope.grammar.CypherGSParser; +import com.google.common.base.Preconditions; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rex.RexCall; @@ -63,6 +64,8 @@ public GraphBuilder visitOC_Match(CypherGSParser.OC_MatchContext ctx) { sentences.get(0), (ctx.OPTIONAL() != null) ? GraphOpt.Match.OPTIONAL : GraphOpt.Match.INNER); } else if (sentences.size() > 1) { + Preconditions.checkArgument( + ctx.OPTIONAL() == null, "multiple sentences in match should not be optional"); builder.match(sentences.get(0), sentences.subList(1, sentences.size())); } else { throw new IllegalArgumentException("sentences in match should not be empty"); diff --git a/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/cypher/antlr4/MatchTest.java b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/cypher/antlr4/MatchTest.java index 1d4a8e3fa496..5f1e1021aafa 100644 --- a/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/cypher/antlr4/MatchTest.java +++ b/interactive_engine/compiler/src/test/java/com/alibaba/graphscope/cypher/antlr4/MatchTest.java @@ -347,4 +347,39 @@ public void match_19_test() { + " _UTF-8'.*marko.*')]], opt=[VERTEX])", node.explain().trim()); } + + @Test + public void match_20_test() { + RelNode node = + Utils.eval( + "Match (a:person)-[]->(b:person) Match (a:person)-[]-(c:person)," + + " (c:person)-[]->(b:person) Return a, b") + .build(); + Assert.assertEquals( + "GraphLogicalProject(a=[a], b=[b], isAppend=[false])\n" + + " LogicalJoin(condition=[AND(=(a, a), =(b, b))], joinType=[inner])\n" + + " GraphLogicalSingleMatch(input=[null]," + + " sentence=[GraphLogicalGetV(tableConfig=[{isAll=false, tables=[person]}]," + + " alias=[b], opt=[END])\n" + + " GraphLogicalExpand(tableConfig=[{isAll=true, tables=[created, knows]}]," + + " alias=[DEFAULT], opt=[OUT])\n" + + " GraphLogicalSource(tableConfig=[{isAll=false, tables=[person]}]," + + " alias=[a], opt=[VERTEX])\n" + + "], matchOpt=[INNER])\n" + + " GraphLogicalMultiMatch(input=[null]," + + " sentences=[{s0=[GraphLogicalGetV(tableConfig=[{isAll=false," + + " tables=[person]}], alias=[c], opt=[OTHER])\n" + + " GraphLogicalExpand(tableConfig=[{isAll=true, tables=[created, knows]}]," + + " alias=[DEFAULT], opt=[BOTH])\n" + + " GraphLogicalSource(tableConfig=[{isAll=false, tables=[person]}]," + + " alias=[a], opt=[VERTEX])\n" + + "], s1=[GraphLogicalGetV(tableConfig=[{isAll=false, tables=[person]}]," + + " alias=[b], opt=[END])\n" + + " GraphLogicalExpand(tableConfig=[{isAll=true, tables=[created, knows]}]," + + " alias=[DEFAULT], opt=[OUT])\n" + + " GraphLogicalSource(tableConfig=[{isAll=false, tables=[person]}]," + + " alias=[c], opt=[VERTEX])\n" + + "]}])", + node.explain().trim()); + } }