diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/ExpressionVisitor.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/ExpressionVisitor.java index 209e9c317b09..70bc21515fd6 100644 --- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/ExpressionVisitor.java +++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/ExpressionVisitor.java @@ -279,7 +279,7 @@ public ExprVisitorResult visitOC_ParenthesizedExpression( @Override public ExprVisitorResult visitOC_Variable(CypherGSParser.OC_VariableContext ctx) { - String aliasName = ctx.getText(); + String aliasName = Utils.getAliasName(ctx); return new ExprVisitorResult(builder.variable(aliasName)); } 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 cab36fdc1348..0fefef6a9717 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 @@ -100,7 +100,7 @@ public GraphBuilder visitOC_Cypher(CypherGSParser.OC_CypherContext ctx) { @Override public GraphBuilder visitOC_Unwind(CypherGSParser.OC_UnwindContext ctx) { RexNode expr = expressionVisitor.visitOC_Expression(ctx.oC_Expression()).getExpr(); - String alias = ctx.oC_Variable() == null ? null : ctx.oC_Variable().getText(); + String alias = Utils.getAliasName(ctx.oC_Variable()); return builder.unfold(expr, alias); } @@ -339,7 +339,8 @@ private boolean isGroupPattern( for (CypherGSParser.OC_ProjectionItemContext itemCtx : ctx.oC_ProjectionItems().oC_ProjectionItem()) { ExprVisitorResult item = expressionVisitor.visitOC_Expression(itemCtx.oC_Expression()); - String alias = (itemCtx.AS() == null) ? null : itemCtx.oC_Variable().getText(); + String alias = + (itemCtx.AS() == null) ? null : Utils.getAliasName(itemCtx.oC_Variable()); if (item.getAggCalls().isEmpty()) { keyExprs.add(item.getExpr()); keyAliases.add(alias); diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/LiteralVisitor.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/LiteralVisitor.java index 5ca354a23c68..346fa16e78ed 100644 --- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/LiteralVisitor.java +++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/LiteralVisitor.java @@ -100,6 +100,15 @@ public Object visitTerminal(TerminalNode node) { } } + @Override + public Object visitOC_SymbolicName(CypherGSParser.OC_SymbolicNameContext ctx) { + if (ctx.EscapedSymbolicName() != null) { + // escape the back-ticks + return ctx.getText().replace("`", ""); + } + return ctx.getText(); + } + /** * Remove single/double quotes around String literal * diff --git a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/Utils.java b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/Utils.java index ad5f668c8521..9f8ff8b0fbb9 100644 --- a/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/Utils.java +++ b/interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/Utils.java @@ -24,20 +24,21 @@ import org.apache.calcite.rex.RexCall; import org.apache.calcite.rex.RexNode; import org.apache.calcite.sql.SqlKind; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.ArrayList; import java.util.List; public abstract class Utils extends com.alibaba.graphscope.common.antlr4.Utils { public static SourceConfig sourceConfig(CypherGSParser.OC_NodePatternContext ctx) { - String alias = (ctx.oC_Variable() != null) ? ctx.oC_Variable().getText() : null; + String alias = getAliasName(ctx.oC_Variable()); LabelConfig config = labelConfig(ctx.oC_NodeLabels()); // source return new SourceConfig(GraphOpt.Source.VERTEX, config, alias); } public static GetVConfig getVConfig(CypherGSParser.OC_NodePatternContext ctx) { - String alias = (ctx.oC_Variable() != null) ? ctx.oC_Variable().getText() : null; + String alias = getAliasName(ctx.oC_Variable()); LabelConfig config = labelConfig(ctx.oC_NodeLabels()); // getV return new GetVConfig(getVOpt(ctx), config, alias); @@ -50,7 +51,7 @@ public static ExpandConfig expandConfig(CypherGSParser.OC_RelationshipPatternCon public static ExpandConfig expandConfig( CypherGSParser.OC_RelationshipDetailContext ctx, GraphOpt.Expand opt) { - String alias = (ctx.oC_Variable() != null) ? ctx.oC_Variable().getText() : null; + String alias = getAliasName(ctx.oC_Variable()); LabelConfig config = labelConfig(ctx.oC_RelationshipTypes()); return new ExpandConfig(opt, config, alias); } @@ -63,7 +64,7 @@ public static LabelConfig labelConfig(CypherGSParser.OC_NodeLabelsContext ctx) { config = new LabelConfig(false); for (CypherGSParser.OC_LabelNameContext ctx1 : ctx.oC_LabelName()) { if (ctx1 == null) continue; - config.addLabel(ctx1.getText()); + config.addLabel(getLabelName(ctx1)); } } return config; @@ -77,7 +78,7 @@ public static LabelConfig labelConfig(CypherGSParser.OC_RelationshipTypesContext config = new LabelConfig(false); for (CypherGSParser.OC_RelTypeNameContext ctx1 : ctx.oC_RelTypeName()) { if (ctx1 == null) continue; - config.addLabel(ctx1.getText()); + config.addLabel(getLabelName(ctx1)); } } return config; @@ -133,4 +134,16 @@ public static final List propertyFilters( } return filters; } + + public static @Nullable String getAliasName(CypherGSParser.OC_VariableContext ctx) { + return ctx == null ? null : (String) LiteralVisitor.INSTANCE.visit(ctx); + } + + public static String getLabelName(CypherGSParser.OC_LabelNameContext ctx) { + return (String) LiteralVisitor.INSTANCE.visit(ctx); + } + + public static String getLabelName(CypherGSParser.OC_RelTypeNameContext ctx) { + return (String) LiteralVisitor.INSTANCE.visit(ctx); + } } 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 68e3318dfe42..6d8f49b7be03 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 @@ -713,4 +713,22 @@ public void optional_shortest_path_test() { + " alias=[p1], opt=[VERTEX], uniqueKeyFilters=[=(_.id, ?0)])", after.explain().trim()); } + + @Test + public void special_label_name_test() { + GraphBuilder builder = + com.alibaba.graphscope.common.ir.Utils.mockGraphBuilder(optimizer, irMeta); + RelNode node = + Utils.eval("Match (n:`@person`)-[e:`contains`]->(n2) Return n", builder).build(); + RelNode after = optimizer.optimize(node, new GraphIOProcessor(builder, irMeta)); + Assert.assertEquals( + "GraphLogicalProject(n=[n], isAppend=[false])\n" + + " GraphLogicalGetV(tableConfig=[{isAll=false, tables=[@person]}]," + + " alias=[n2], opt=[END])\n" + + " GraphLogicalExpand(tableConfig=[{isAll=false, tables=[contains]}]," + + " alias=[e], startAlias=[n], opt=[OUT])\n" + + " GraphLogicalSource(tableConfig=[{isAll=false, tables=[@person]}]," + + " alias=[n], opt=[VERTEX])", + after.explain().trim()); + } } diff --git a/interactive_engine/compiler/src/test/resources/config/modern/graph.yaml b/interactive_engine/compiler/src/test/resources/config/modern/graph.yaml index 053d11184603..a740b08c2098 100644 --- a/interactive_engine/compiler/src/test/resources/config/modern/graph.yaml +++ b/interactive_engine/compiler/src/test/resources/config/modern/graph.yaml @@ -100,6 +100,26 @@ schema: date32: primary_keys: - id + - type_name: "@person" + type_id: 2 + x_csr_params: + max_vertex_num: 100 + properties: + - property_id: 0 + property_name: id + property_type: + primitive_type: DT_SIGNED_INT64 + - property_id: 1 + property_name: name + property_type: + string: + long_text: + - property_id: 2 + property_name: age + property_type: + primitive_type: DT_SIGNED_INT32 + primary_keys: + - id edge_types: - type_name: knows type_id: 0 @@ -123,3 +143,14 @@ schema: property_name: weight property_type: primitive_type: DT_DOUBLE + - type_name: contains + type_id: 2 + vertex_type_pair_relations: + - source_vertex: "@person" + destination_vertex: "@person" + relation: MANY_TO_MANY + properties: + - property_id: 0 + property_name: weight + property_type: + primitive_type: DT_DOUBLE diff --git a/interactive_engine/compiler/src/test/resources/statistics/modern_statistics.json b/interactive_engine/compiler/src/test/resources/statistics/modern_statistics.json index ac3a7a7959c7..dfaad011c331 100644 --- a/interactive_engine/compiler/src/test/resources/statistics/modern_statistics.json +++ b/interactive_engine/compiler/src/test/resources/statistics/modern_statistics.json @@ -11,6 +11,11 @@ "type_id": 1, "type_name": "software", "count": 3 + }, + { + "type_id": 2, + "type_name": "@person", + "count": 3 } ], "edge_type_statistics": [ @@ -35,6 +40,16 @@ "count": 4 } ] + },{ + "type_id": 2, + "type_name": "contains", + "vertex_type_pair_statistics": [ + { + "source_vertex": "@person", + "destination_vertex": "@person", + "count": 2 + } + ] } ] } \ No newline at end of file