Skip to content

Commit c38dd7d

Browse files
authored
fix(interactive): Fix Bugs of Special Characters as Label Name (#4366)
allow special characters and reserved words as the label names, use back-ticks to escape, i.e.: ``` Match (n:`@person`) Return n; # contains is a reserved word for operator `contains` Match (n1)-[m:`contains`]->(n2) Return m; ``` Fixes #4347 Fixes #4317
1 parent 936371c commit c38dd7d

File tree

7 files changed

+95
-8
lines changed

7 files changed

+95
-8
lines changed

interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/ExpressionVisitor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ public ExprVisitorResult visitOC_ParenthesizedExpression(
279279

280280
@Override
281281
public ExprVisitorResult visitOC_Variable(CypherGSParser.OC_VariableContext ctx) {
282-
String aliasName = ctx.getText();
282+
String aliasName = Utils.getAliasName(ctx);
283283
return new ExprVisitorResult(builder.variable(aliasName));
284284
}
285285

interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/GraphBuilderVisitor.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public GraphBuilder visitOC_Cypher(CypherGSParser.OC_CypherContext ctx) {
100100
@Override
101101
public GraphBuilder visitOC_Unwind(CypherGSParser.OC_UnwindContext ctx) {
102102
RexNode expr = expressionVisitor.visitOC_Expression(ctx.oC_Expression()).getExpr();
103-
String alias = ctx.oC_Variable() == null ? null : ctx.oC_Variable().getText();
103+
String alias = Utils.getAliasName(ctx.oC_Variable());
104104
return builder.unfold(expr, alias);
105105
}
106106

@@ -339,7 +339,8 @@ private boolean isGroupPattern(
339339
for (CypherGSParser.OC_ProjectionItemContext itemCtx :
340340
ctx.oC_ProjectionItems().oC_ProjectionItem()) {
341341
ExprVisitorResult item = expressionVisitor.visitOC_Expression(itemCtx.oC_Expression());
342-
String alias = (itemCtx.AS() == null) ? null : itemCtx.oC_Variable().getText();
342+
String alias =
343+
(itemCtx.AS() == null) ? null : Utils.getAliasName(itemCtx.oC_Variable());
343344
if (item.getAggCalls().isEmpty()) {
344345
keyExprs.add(item.getExpr());
345346
keyAliases.add(alias);

interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/LiteralVisitor.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,15 @@ public Object visitTerminal(TerminalNode node) {
100100
}
101101
}
102102

103+
@Override
104+
public Object visitOC_SymbolicName(CypherGSParser.OC_SymbolicNameContext ctx) {
105+
if (ctx.EscapedSymbolicName() != null) {
106+
// escape the back-ticks
107+
return ctx.getText().replace("`", "");
108+
}
109+
return ctx.getText();
110+
}
111+
103112
/**
104113
* Remove single/double quotes around String literal
105114
*

interactive_engine/compiler/src/main/java/com/alibaba/graphscope/cypher/antlr4/visitor/Utils.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,21 @@
2424
import org.apache.calcite.rex.RexCall;
2525
import org.apache.calcite.rex.RexNode;
2626
import org.apache.calcite.sql.SqlKind;
27+
import org.checkerframework.checker.nullness.qual.Nullable;
2728

2829
import java.util.ArrayList;
2930
import java.util.List;
3031

3132
public abstract class Utils extends com.alibaba.graphscope.common.antlr4.Utils {
3233
public static SourceConfig sourceConfig(CypherGSParser.OC_NodePatternContext ctx) {
33-
String alias = (ctx.oC_Variable() != null) ? ctx.oC_Variable().getText() : null;
34+
String alias = getAliasName(ctx.oC_Variable());
3435
LabelConfig config = labelConfig(ctx.oC_NodeLabels());
3536
// source
3637
return new SourceConfig(GraphOpt.Source.VERTEX, config, alias);
3738
}
3839

3940
public static GetVConfig getVConfig(CypherGSParser.OC_NodePatternContext ctx) {
40-
String alias = (ctx.oC_Variable() != null) ? ctx.oC_Variable().getText() : null;
41+
String alias = getAliasName(ctx.oC_Variable());
4142
LabelConfig config = labelConfig(ctx.oC_NodeLabels());
4243
// getV
4344
return new GetVConfig(getVOpt(ctx), config, alias);
@@ -50,7 +51,7 @@ public static ExpandConfig expandConfig(CypherGSParser.OC_RelationshipPatternCon
5051

5152
public static ExpandConfig expandConfig(
5253
CypherGSParser.OC_RelationshipDetailContext ctx, GraphOpt.Expand opt) {
53-
String alias = (ctx.oC_Variable() != null) ? ctx.oC_Variable().getText() : null;
54+
String alias = getAliasName(ctx.oC_Variable());
5455
LabelConfig config = labelConfig(ctx.oC_RelationshipTypes());
5556
return new ExpandConfig(opt, config, alias);
5657
}
@@ -63,7 +64,7 @@ public static LabelConfig labelConfig(CypherGSParser.OC_NodeLabelsContext ctx) {
6364
config = new LabelConfig(false);
6465
for (CypherGSParser.OC_LabelNameContext ctx1 : ctx.oC_LabelName()) {
6566
if (ctx1 == null) continue;
66-
config.addLabel(ctx1.getText());
67+
config.addLabel(getLabelName(ctx1));
6768
}
6869
}
6970
return config;
@@ -77,7 +78,7 @@ public static LabelConfig labelConfig(CypherGSParser.OC_RelationshipTypesContext
7778
config = new LabelConfig(false);
7879
for (CypherGSParser.OC_RelTypeNameContext ctx1 : ctx.oC_RelTypeName()) {
7980
if (ctx1 == null) continue;
80-
config.addLabel(ctx1.getText());
81+
config.addLabel(getLabelName(ctx1));
8182
}
8283
}
8384
return config;
@@ -133,4 +134,16 @@ public static final List<RexNode> propertyFilters(
133134
}
134135
return filters;
135136
}
137+
138+
public static @Nullable String getAliasName(CypherGSParser.OC_VariableContext ctx) {
139+
return ctx == null ? null : (String) LiteralVisitor.INSTANCE.visit(ctx);
140+
}
141+
142+
public static String getLabelName(CypherGSParser.OC_LabelNameContext ctx) {
143+
return (String) LiteralVisitor.INSTANCE.visit(ctx);
144+
}
145+
146+
public static String getLabelName(CypherGSParser.OC_RelTypeNameContext ctx) {
147+
return (String) LiteralVisitor.INSTANCE.visit(ctx);
148+
}
136149
}

interactive_engine/compiler/src/test/java/com/alibaba/graphscope/cypher/antlr4/MatchTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,4 +713,22 @@ public void optional_shortest_path_test() {
713713
+ " alias=[p1], opt=[VERTEX], uniqueKeyFilters=[=(_.id, ?0)])",
714714
after.explain().trim());
715715
}
716+
717+
@Test
718+
public void special_label_name_test() {
719+
GraphBuilder builder =
720+
com.alibaba.graphscope.common.ir.Utils.mockGraphBuilder(optimizer, irMeta);
721+
RelNode node =
722+
Utils.eval("Match (n:`@person`)-[e:`contains`]->(n2) Return n", builder).build();
723+
RelNode after = optimizer.optimize(node, new GraphIOProcessor(builder, irMeta));
724+
Assert.assertEquals(
725+
"GraphLogicalProject(n=[n], isAppend=[false])\n"
726+
+ " GraphLogicalGetV(tableConfig=[{isAll=false, tables=[@person]}],"
727+
+ " alias=[n2], opt=[END])\n"
728+
+ " GraphLogicalExpand(tableConfig=[{isAll=false, tables=[contains]}],"
729+
+ " alias=[e], startAlias=[n], opt=[OUT])\n"
730+
+ " GraphLogicalSource(tableConfig=[{isAll=false, tables=[@person]}],"
731+
+ " alias=[n], opt=[VERTEX])",
732+
after.explain().trim());
733+
}
716734
}

interactive_engine/compiler/src/test/resources/config/modern/graph.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,26 @@ schema:
100100
date32:
101101
primary_keys:
102102
- id
103+
- type_name: "@person"
104+
type_id: 2
105+
x_csr_params:
106+
max_vertex_num: 100
107+
properties:
108+
- property_id: 0
109+
property_name: id
110+
property_type:
111+
primitive_type: DT_SIGNED_INT64
112+
- property_id: 1
113+
property_name: name
114+
property_type:
115+
string:
116+
long_text:
117+
- property_id: 2
118+
property_name: age
119+
property_type:
120+
primitive_type: DT_SIGNED_INT32
121+
primary_keys:
122+
- id
103123
edge_types:
104124
- type_name: knows
105125
type_id: 0
@@ -123,3 +143,14 @@ schema:
123143
property_name: weight
124144
property_type:
125145
primitive_type: DT_DOUBLE
146+
- type_name: contains
147+
type_id: 2
148+
vertex_type_pair_relations:
149+
- source_vertex: "@person"
150+
destination_vertex: "@person"
151+
relation: MANY_TO_MANY
152+
properties:
153+
- property_id: 0
154+
property_name: weight
155+
property_type:
156+
primitive_type: DT_DOUBLE

interactive_engine/compiler/src/test/resources/statistics/modern_statistics.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
"type_id": 1,
1212
"type_name": "software",
1313
"count": 3
14+
},
15+
{
16+
"type_id": 2,
17+
"type_name": "@person",
18+
"count": 3
1419
}
1520
],
1621
"edge_type_statistics": [
@@ -35,6 +40,16 @@
3540
"count": 4
3641
}
3742
]
43+
},{
44+
"type_id": 2,
45+
"type_name": "contains",
46+
"vertex_type_pair_statistics": [
47+
{
48+
"source_vertex": "@person",
49+
"destination_vertex": "@person",
50+
"count": 2
51+
}
52+
]
3853
}
3954
]
4055
}

0 commit comments

Comments
 (0)