Skip to content

Commit 6ff3e8f

Browse files
Support WHERE in pattern elements (albertoventurini#64) (albertoventurini#66)
See https://neo4j.com/docs/cypher-manual/current/clauses/where/#pattern-element-predicates for more information on this usage of the WHERE clause.
1 parent fdc3602 commit 6ff3e8f

File tree

4 files changed

+254
-2
lines changed

4 files changed

+254
-2
lines changed

language/cypher/src/main/java/com/albertoventurini/graphdbplugin/language/cypher/lexer/Cypher.bnf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,11 +305,11 @@ PatternElementChain ::= RelationshipPattern NodePattern {pin=1}
305305

306306
RelationshipPattern ::= LeftArrowHead? Dash RelationshipDetail? Dash RightArrowHead? {pin=2}
307307

308-
RelationshipDetail ::= "[" Variable? "?"? RelationshipTypes? MaybeVariableLength? Properties? "]" {pin=1}
308+
RelationshipDetail ::= "[" Variable? "?"? RelationshipTypes? MaybeVariableLength? Properties? Where? "]" {pin=1}
309309
RelationshipTypes ::= ":" RelTypeName ("|" ":"? RelTypeName)* {pin=1}
310310
MaybeVariableLength ::= ("*" RangeLiteral?)
311311

312-
NodePattern ::= "(" Variable? NodeLabels? Properties? ")" {pin=1}
312+
NodePattern ::= "(" Variable? NodeLabels? Properties? Where? ")" {pin=1}
313313

314314
RelationshipsPattern ::= NodePattern PatternElementChain+ {
315315
implements="com.albertoventurini.graphdbplugin.language.cypher.references.types.CypherPathYielding"

testing/integration-neo4j/src/test/java/com/albertoventurini/graphdbplugin/test/integration/neo4j/tests/cypher/parsing/PatternsParsingTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,8 @@ public void testPatterns() {
1818
doTest(true);
1919
}
2020

21+
public void testWhereInsidePatterns() {
22+
doTest(true);
23+
}
24+
2125
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
WITH 30 AS minAge
2+
MATCH (a:Person WHERE a.name = 'Andy')-[:KNOWS]->(b:Person {city: "Somewhere"} WHERE b.age > minAge)
3+
RETURN b.name;
4+
MATCH (a:Person)-[r:KNOWS WHERE r.since < 2023]->(b:Person)
5+
RETURN r.since;
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
Cypher file: FILE(0,209)
2+
CypherStatementItemImpl(STATEMENT_ITEM)(0,133)
3+
CypherStatementImpl(STATEMENT)(0,132)
4+
CypherQueryOptionsImpl(QUERY_OPTIONS)(0,0)
5+
<empty list>
6+
CypherQueryImpl(QUERY)(0,132)
7+
CypherRegularQueryImpl(REGULAR_QUERY)(0,132)
8+
CypherSingleQueryImpl(SINGLE_QUERY)(0,132)
9+
CypherMultiPartQueryImpl(MULTI_PART_QUERY)(0,132)
10+
CypherWithImpl(WITH)(0,17)
11+
PsiElement(WITH)('WITH')(0,4)
12+
CypherReturnBodyImpl(RETURN_BODY)(5,17)
13+
CypherReturnItemsImpl(RETURN_ITEMS)(5,17)
14+
CypherReturnItemImpl(RETURN_ITEM)(5,17)
15+
CypherExpressionImpl(EXPRESSION)(5,7)
16+
CypherNumberLiteralImpl(NUMBER_LITERAL)(5,7)
17+
CypherIntegerLiteralImpl(INTEGER_LITERAL)(5,7)
18+
CypherUnsignedIntegerImpl(UNSIGNED_INTEGER)(5,7)
19+
PsiElement(integer)('30')(5,7)
20+
PsiElement(AS)('AS')(8,10)
21+
CypherVariableImpl(VARIABLE)(11,17)
22+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(11,17)
23+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(11,17)
24+
PsiElement(identifier)('minAge')(11,17)
25+
CypherSinglePartQueryImpl(SINGLE_PART_QUERY)(18,132)
26+
CypherReadingWithReturnImpl(READING_WITH_RETURN)(18,132)
27+
CypherReadingClauseImpl(READING_CLAUSE)(18,118)
28+
CypherMatchImpl(MATCH)(18,118)
29+
PsiElement(MATCH)('MATCH')(18,23)
30+
CypherPatternWithWhereClauseImpl(PATTERN_WITH_WHERE_CLAUSE)(24,118)
31+
CypherPatternImpl(PATTERN)(24,118)
32+
CypherPatternPartImpl(PATTERN_PART)(24,118)
33+
CypherAnonymousPatternPartImpl(ANONYMOUS_PATTERN_PART)(24,118)
34+
CypherPatternElementImpl(PATTERN_ELEMENT)(24,118)
35+
CypherNodePatternImpl(NODE_PATTERN)(24,56)
36+
PsiElement(()('(')(24,25)
37+
CypherVariableImpl(VARIABLE)(25,26)
38+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(25,26)
39+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(25,26)
40+
PsiElement(identifier)('a')(25,26)
41+
CypherNodeLabelsImpl(NODE_LABELS)(26,33)
42+
CypherNodeLabelImpl(NODE_LABEL)(26,33)
43+
PsiElement(:)(':')(26,27)
44+
CypherLabelNameImpl(LABEL_NAME)(27,33)
45+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(27,33)
46+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(27,33)
47+
PsiElement(identifier)('Person')(27,33)
48+
CypherWhereImpl(WHERE)(34,55)
49+
PsiElement(WHERE)('WHERE')(34,39)
50+
CypherExpressionImpl(EXPRESSION)(40,55)
51+
CypherVariableImpl(VARIABLE)(40,41)
52+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(40,41)
53+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(40,41)
54+
PsiElement(identifier)('a')(40,41)
55+
CypherPropertyLookupImpl(PROPERTY_LOOKUP)(41,46)
56+
PsiElement(.)('.')(41,42)
57+
CypherPropertyKeyNameImpl(PROPERTY_KEY_NAME)(42,46)
58+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(42,46)
59+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(42,46)
60+
PsiElement(identifier)('name')(42,46)
61+
PsiElement(=)('=')(47,48)
62+
CypherStringLiteralImpl(STRING_LITERAL)(49,55)
63+
PsiElement(string)(''Andy'')(49,55)
64+
PsiElement())(')')(55,56)
65+
CypherPatternElementChainImpl(PATTERN_ELEMENT_CHAIN)(56,118)
66+
CypherRelationshipPatternImpl(RELATIONSHIP_PATTERN)(56,67)
67+
CypherDashImpl(DASH)(56,57)
68+
PsiElement(-)('-')(56,57)
69+
CypherRelationshipDetailImpl(RELATIONSHIP_DETAIL)(57,65)
70+
PsiElement([)('[')(57,58)
71+
CypherRelationshipTypesImpl(RELATIONSHIP_TYPES)(58,64)
72+
PsiElement(:)(':')(58,59)
73+
CypherRelTypeNameImpl(REL_TYPE_NAME)(59,64)
74+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(59,64)
75+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(59,64)
76+
PsiElement(identifier)('KNOWS')(59,64)
77+
PsiElement(])(']')(64,65)
78+
CypherDashImpl(DASH)(65,66)
79+
PsiElement(-)('-')(65,66)
80+
CypherRightArrowHeadImpl(RIGHT_ARROW_HEAD)(66,67)
81+
PsiElement(>)('>')(66,67)
82+
CypherNodePatternImpl(NODE_PATTERN)(67,118)
83+
PsiElement(()('(')(67,68)
84+
CypherVariableImpl(VARIABLE)(68,69)
85+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(68,69)
86+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(68,69)
87+
PsiElement(identifier)('b')(68,69)
88+
CypherNodeLabelsImpl(NODE_LABELS)(69,76)
89+
CypherNodeLabelImpl(NODE_LABEL)(69,76)
90+
PsiElement(:)(':')(69,70)
91+
CypherLabelNameImpl(LABEL_NAME)(70,76)
92+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(70,76)
93+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(70,76)
94+
PsiElement(identifier)('Person')(70,76)
95+
CypherPropertiesImpl(PROPERTIES)(77,96)
96+
CypherMapLiteralImpl(MAP_LITERAL)(77,96)
97+
PsiElement({)('{')(77,78)
98+
CypherPropertyKeyNameImpl(PROPERTY_KEY_NAME)(78,82)
99+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(78,82)
100+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(78,82)
101+
PsiElement(identifier)('city')(78,82)
102+
PsiElement(:)(':')(82,83)
103+
CypherExpressionImpl(EXPRESSION)(84,95)
104+
CypherStringLiteralImpl(STRING_LITERAL)(84,95)
105+
PsiElement(string)('"Somewhere"')(84,95)
106+
PsiElement(})('}')(95,96)
107+
CypherWhereImpl(WHERE)(97,117)
108+
PsiElement(WHERE)('WHERE')(97,102)
109+
CypherExpressionImpl(EXPRESSION)(103,117)
110+
CypherVariableImpl(VARIABLE)(103,104)
111+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(103,104)
112+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(103,104)
113+
PsiElement(identifier)('b')(103,104)
114+
CypherPropertyLookupImpl(PROPERTY_LOOKUP)(104,108)
115+
PsiElement(.)('.')(104,105)
116+
CypherPropertyKeyNameImpl(PROPERTY_KEY_NAME)(105,108)
117+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(105,108)
118+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(105,108)
119+
PsiElement(identifier)('age')(105,108)
120+
PsiElement(>)('>')(109,110)
121+
CypherVariableImpl(VARIABLE)(111,117)
122+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(111,117)
123+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(111,117)
124+
PsiElement(identifier)('minAge')(111,117)
125+
PsiElement())(')')(117,118)
126+
CypherReturnImpl(RETURN)(119,132)
127+
PsiElement(RETURN)('RETURN')(119,125)
128+
CypherReturnBodyImpl(RETURN_BODY)(126,132)
129+
CypherReturnItemsImpl(RETURN_ITEMS)(126,132)
130+
CypherReturnItemImpl(RETURN_ITEM)(126,132)
131+
CypherExpressionImpl(EXPRESSION)(126,132)
132+
CypherVariableImpl(VARIABLE)(126,127)
133+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(126,127)
134+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(126,127)
135+
PsiElement(identifier)('b')(126,127)
136+
CypherPropertyLookupImpl(PROPERTY_LOOKUP)(127,132)
137+
PsiElement(.)('.')(127,128)
138+
CypherPropertyKeyNameImpl(PROPERTY_KEY_NAME)(128,132)
139+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(128,132)
140+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(128,132)
141+
PsiElement(identifier)('name')(128,132)
142+
PsiElement(;)(';')(132,133)
143+
CypherStatementItemImpl(STATEMENT_ITEM)(134,209)
144+
CypherStatementImpl(STATEMENT)(134,208)
145+
CypherQueryOptionsImpl(QUERY_OPTIONS)(134,134)
146+
<empty list>
147+
CypherQueryImpl(QUERY)(134,208)
148+
CypherRegularQueryImpl(REGULAR_QUERY)(134,208)
149+
CypherSingleQueryImpl(SINGLE_QUERY)(134,208)
150+
CypherSinglePartQueryImpl(SINGLE_PART_QUERY)(134,208)
151+
CypherReadingWithReturnImpl(READING_WITH_RETURN)(134,208)
152+
CypherReadingClauseImpl(READING_CLAUSE)(134,193)
153+
CypherMatchImpl(MATCH)(134,193)
154+
PsiElement(MATCH)('MATCH')(134,139)
155+
CypherPatternWithWhereClauseImpl(PATTERN_WITH_WHERE_CLAUSE)(140,193)
156+
CypherPatternImpl(PATTERN)(140,193)
157+
CypherPatternPartImpl(PATTERN_PART)(140,193)
158+
CypherAnonymousPatternPartImpl(ANONYMOUS_PATTERN_PART)(140,193)
159+
CypherPatternElementImpl(PATTERN_ELEMENT)(140,193)
160+
CypherNodePatternImpl(NODE_PATTERN)(140,150)
161+
PsiElement(()('(')(140,141)
162+
CypherVariableImpl(VARIABLE)(141,142)
163+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(141,142)
164+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(141,142)
165+
PsiElement(identifier)('a')(141,142)
166+
CypherNodeLabelsImpl(NODE_LABELS)(142,149)
167+
CypherNodeLabelImpl(NODE_LABEL)(142,149)
168+
PsiElement(:)(':')(142,143)
169+
CypherLabelNameImpl(LABEL_NAME)(143,149)
170+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(143,149)
171+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(143,149)
172+
PsiElement(identifier)('Person')(143,149)
173+
PsiElement())(')')(149,150)
174+
CypherPatternElementChainImpl(PATTERN_ELEMENT_CHAIN)(150,193)
175+
CypherRelationshipPatternImpl(RELATIONSHIP_PATTERN)(150,183)
176+
CypherDashImpl(DASH)(150,151)
177+
PsiElement(-)('-')(150,151)
178+
CypherRelationshipDetailImpl(RELATIONSHIP_DETAIL)(151,181)
179+
PsiElement([)('[')(151,152)
180+
CypherVariableImpl(VARIABLE)(152,153)
181+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(152,153)
182+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(152,153)
183+
PsiElement(identifier)('r')(152,153)
184+
CypherRelationshipTypesImpl(RELATIONSHIP_TYPES)(153,159)
185+
PsiElement(:)(':')(153,154)
186+
CypherRelTypeNameImpl(REL_TYPE_NAME)(154,159)
187+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(154,159)
188+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(154,159)
189+
PsiElement(identifier)('KNOWS')(154,159)
190+
CypherWhereImpl(WHERE)(160,180)
191+
PsiElement(WHERE)('WHERE')(160,165)
192+
CypherExpressionImpl(EXPRESSION)(166,180)
193+
CypherVariableImpl(VARIABLE)(166,167)
194+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(166,167)
195+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(166,167)
196+
PsiElement(identifier)('r')(166,167)
197+
CypherPropertyLookupImpl(PROPERTY_LOOKUP)(167,173)
198+
PsiElement(.)('.')(167,168)
199+
CypherPropertyKeyNameImpl(PROPERTY_KEY_NAME)(168,173)
200+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(168,173)
201+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(168,173)
202+
PsiElement(identifier)('since')(168,173)
203+
PsiElement(<)('<')(174,175)
204+
CypherNumberLiteralImpl(NUMBER_LITERAL)(176,180)
205+
CypherIntegerLiteralImpl(INTEGER_LITERAL)(176,180)
206+
CypherUnsignedIntegerImpl(UNSIGNED_INTEGER)(176,180)
207+
PsiElement(integer)('2023')(176,180)
208+
PsiElement(])(']')(180,181)
209+
CypherDashImpl(DASH)(181,182)
210+
PsiElement(-)('-')(181,182)
211+
CypherRightArrowHeadImpl(RIGHT_ARROW_HEAD)(182,183)
212+
PsiElement(>)('>')(182,183)
213+
CypherNodePatternImpl(NODE_PATTERN)(183,193)
214+
PsiElement(()('(')(183,184)
215+
CypherVariableImpl(VARIABLE)(184,185)
216+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(184,185)
217+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(184,185)
218+
PsiElement(identifier)('b')(184,185)
219+
CypherNodeLabelsImpl(NODE_LABELS)(185,192)
220+
CypherNodeLabelImpl(NODE_LABEL)(185,192)
221+
PsiElement(:)(':')(185,186)
222+
CypherLabelNameImpl(LABEL_NAME)(186,192)
223+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(186,192)
224+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(186,192)
225+
PsiElement(identifier)('Person')(186,192)
226+
PsiElement())(')')(192,193)
227+
CypherReturnImpl(RETURN)(194,208)
228+
PsiElement(RETURN)('RETURN')(194,200)
229+
CypherReturnBodyImpl(RETURN_BODY)(201,208)
230+
CypherReturnItemsImpl(RETURN_ITEMS)(201,208)
231+
CypherReturnItemImpl(RETURN_ITEM)(201,208)
232+
CypherExpressionImpl(EXPRESSION)(201,208)
233+
CypherVariableImpl(VARIABLE)(201,202)
234+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(201,202)
235+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(201,202)
236+
PsiElement(identifier)('r')(201,202)
237+
CypherPropertyLookupImpl(PROPERTY_LOOKUP)(202,208)
238+
PsiElement(.)('.')(202,203)
239+
CypherPropertyKeyNameImpl(PROPERTY_KEY_NAME)(203,208)
240+
CypherSymbolicNameStringImpl(SYMBOLIC_NAME_STRING)(203,208)
241+
CypherUnescapedSymbolicNameStringImpl(UNESCAPED_SYMBOLIC_NAME_STRING)(203,208)
242+
PsiElement(identifier)('since')(203,208)
243+
PsiElement(;)(';')(208,209)

0 commit comments

Comments
 (0)