Skip to content

Commit 1848681

Browse files
authored
Merge pull request #22 from microsoft/fix/parser-where-whitespace
Fix/parser where whitespace
2 parents 85a36dc + c13ae20 commit 1848681

40 files changed

+2197
-2544
lines changed

.husky/pre-commit

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ if git diff --cached --name-only | grep -q "^flowquery-py/.*\.py$"; then
1818
cd ..
1919
fi
2020

21-
# Strip outputs from notebook files in flowquery-py
22-
for notebook in $(git ls-files 'flowquery-py/**/*.ipynb'); do
21+
# Strip outputs from notebook files in flowquery-py (only changed ones)
22+
for notebook in $(git diff --cached --name-only -- 'flowquery-py/**/*.ipynb'); do
2323
if [ -f "$notebook" ]; then
2424
echo "Stripping outputs from: $notebook"
2525
python -m nbstripout "$notebook"
26+
git add "$notebook"
2627
fi
2728
done

flowquery-py/src/parsing/parser.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ def _parse_return(self) -> Optional[Return]:
199199
return Return(expressions)
200200

201201
def _parse_where(self) -> Optional[Where]:
202+
self._skip_whitespace_and_comments()
202203
if not self.token.is_where():
203204
return None
204205
self._expect_previous_token_to_be_whitespace_or_comment()

flowquery-py/tests/compute/test_runner.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,6 +1258,31 @@ async def test_statement_with_graph_pattern_in_where_clause(self):
12581258
assert results[1] == {"name1": "Person 2", "name2": "Person 3"}
12591259
assert results[2] == {"name1": "Person 3", "name2": "Person 4"}
12601260

1261+
# Test negative match
1262+
nomatch = Runner(
1263+
"""
1264+
MATCH (a:WherePerson), (b:WherePerson)
1265+
WHERE (a)-[:KNOWS]->(b) <> true
1266+
RETURN a.name AS name1, b.name AS name2
1267+
"""
1268+
)
1269+
await nomatch.run()
1270+
noresults = nomatch.results
1271+
assert len(noresults) == 13
1272+
assert noresults[0] == {"name1": "Person 1", "name2": "Person 1"}
1273+
assert noresults[1] == {"name1": "Person 1", "name2": "Person 3"}
1274+
assert noresults[2] == {"name1": "Person 1", "name2": "Person 4"}
1275+
assert noresults[3] == {"name1": "Person 2", "name2": "Person 1"}
1276+
assert noresults[4] == {"name1": "Person 2", "name2": "Person 2"}
1277+
assert noresults[5] == {"name1": "Person 2", "name2": "Person 4"}
1278+
assert noresults[6] == {"name1": "Person 3", "name2": "Person 1"}
1279+
assert noresults[7] == {"name1": "Person 3", "name2": "Person 2"}
1280+
assert noresults[8] == {"name1": "Person 3", "name2": "Person 3"}
1281+
assert noresults[9] == {"name1": "Person 4", "name2": "Person 1"}
1282+
assert noresults[10] == {"name1": "Person 4", "name2": "Person 2"}
1283+
assert noresults[11] == {"name1": "Person 4", "name2": "Person 3"}
1284+
assert noresults[12] == {"name1": "Person 4", "name2": "Person 4"}
1285+
12611286
@pytest.mark.asyncio
12621287
async def test_person_who_does_not_know_anyone(self):
12631288
"""Test person who does not know anyone."""
@@ -1516,6 +1541,7 @@ async def test_match_with_leftward_double_graph_pattern(self):
15161541
assert results[0] == {"name1": "Person 1", "name2": "Person 2", "name3": "Person 3"}
15171542
assert results[1] == {"name1": "Person 2", "name2": "Person 3", "name3": "Person 4"}
15181543

1544+
@pytest.mark.asyncio
15191545
async def test_match_with_constraints(self):
15201546
await Runner(
15211547
"""

flowquery-py/tests/parsing/test_parser.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from flowquery.parsing.functions.async_function import AsyncFunction
77
from flowquery.parsing.functions.function_metadata import FunctionDef
88
from flowquery.parsing.operations.match import Match
9+
from flowquery.parsing.operations.create_relationship import CreateRelationship
910
from flowquery.graph.node import Node
1011
from flowquery.graph.relationship import Relationship
1112

@@ -784,6 +785,23 @@ def test_node_with_properties(self):
784785
assert node.properties.get("value") is not None
785786
assert node.properties["value"].value() == "hello"
786787

788+
def test_where_in_create_virtual_sub_query(self):
789+
"""Test WHERE in CREATE VIRTUAL sub-query."""
790+
parser = Parser()
791+
ast = parser.parse(
792+
"CREATE VIRTUAL (:Email)-[:HAS_ATTACHMENT]-(:File) AS {"
793+
" LOAD JSON FROM '/data/emails.json' AS email"
794+
" WHERE email.hasAttachments = true"
795+
" UNWIND email.attachments AS fileId"
796+
" RETURN email.id AS left_id, fileId AS right_id"
797+
" }"
798+
)
799+
create = ast.first_child()
800+
assert isinstance(create, CreateRelationship)
801+
assert create.relationship is not None
802+
assert create.relationship.type == "HAS_ATTACHMENT"
803+
assert create.statement is not None
804+
787805
def test_relationship_with_properties(self):
788806
"""Test relationship with properties."""
789807
parser = Parser()

misc/apps/RAG/data/chats.json

Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
[
2+
{
3+
"id": "ch-001",
4+
"topic": "Project Aurora",
5+
"type": "channel",
6+
"teamName": "Product & Engineering",
7+
"members": ["u-002", "u-003", "u-005", "u-006", "u-007", "u-008", "u-009"],
8+
"messages": [
9+
{
10+
"id": "msg-001",
11+
"from": "u-008",
12+
"timestamp": "2026-01-10T09:15:00Z",
13+
"body": "Hey team! Mia just shared the Aurora mockups. They look amazing. Let's review before the design meeting Tuesday.",
14+
"reactions": [{ "type": "thumbsUp", "users": ["u-005", "u-009"] }],
15+
"mentions": ["u-009"],
16+
"relatedFiles": ["f-003"]
17+
},
18+
{
19+
"id": "msg-002",
20+
"from": "u-005",
21+
"timestamp": "2026-01-10T09:32:00Z",
22+
"body": "Just looked through them - the drag-and-drop widget approach is really clean. I think we can leverage the existing React DnD library for that. Should be straightforward.",
23+
"reactions": [{ "type": "thumbsUp", "users": ["u-009", "u-008"] }],
24+
"mentions": []
25+
},
26+
{
27+
"id": "msg-003",
28+
"from": "u-009",
29+
"timestamp": "2026-01-10T09:40:00Z",
30+
"body": "Thanks Emily! I designed the grid system with 12-column breakpoints so it maps well to a component-based layout. Happy to walk through the interaction specs.",
31+
"reactions": [],
32+
"mentions": ["u-005"]
33+
},
34+
{
35+
"id": "msg-004",
36+
"from": "u-002",
37+
"timestamp": "2026-01-10T10:05:00Z",
38+
"body": "Great collaboration you two. @Liam, can you make sure we have story points estimated for the frontend work before sprint planning Monday?",
39+
"reactions": [{ "type": "thumbsUp", "users": ["u-008"] }],
40+
"mentions": ["u-008"]
41+
},
42+
{
43+
"id": "msg-005",
44+
"from": "u-008",
45+
"timestamp": "2026-01-10T10:08:00Z",
46+
"body": "Will do. I'll break it into epics: widget framework, chart components, real-time data layer, and settings/preferences.",
47+
"reactions": [],
48+
"mentions": []
49+
}
50+
]
51+
},
52+
{
53+
"id": "ch-002",
54+
"topic": "DevOps & Infrastructure",
55+
"type": "channel",
56+
"teamName": "Engineering",
57+
"members": ["u-002", "u-005", "u-006", "u-007", "u-012"],
58+
"messages": [
59+
{
60+
"id": "msg-006",
61+
"from": "u-007",
62+
"timestamp": "2026-01-08T11:00:00Z",
63+
"body": "Migration plan for AKS is shared in the Engineering folder. @David, can you review the CosmosDB connection string migration section? Want to make sure the failover logic is right.",
64+
"reactions": [],
65+
"mentions": ["u-006"],
66+
"relatedFiles": ["f-004"]
67+
},
68+
{
69+
"id": "msg-007",
70+
"from": "u-006",
71+
"timestamp": "2026-01-08T11:25:00Z",
72+
"body": "Looking at it now. One thing - we should use managed identity instead of connection strings for the new cluster. I'll update the Terraform configs.",
73+
"reactions": [{ "type": "thumbsUp", "users": ["u-007", "u-012"] }],
74+
"mentions": []
75+
},
76+
{
77+
"id": "msg-008",
78+
"from": "u-012",
79+
"timestamp": "2026-01-08T11:45:00Z",
80+
"body": "Good call David. I've already set up the managed identity in Azure AD for the staging subscription. I'll send you the resource IDs.",
81+
"reactions": [{ "type": "heart", "users": ["u-006"] }],
82+
"mentions": ["u-006"]
83+
},
84+
{
85+
"id": "msg-009",
86+
"from": "u-007",
87+
"timestamp": "2026-01-08T12:00:00Z",
88+
"body": "Perfect teamwork 🎉 Updated the plan to reflect managed identity approach. The staging migration window is confirmed for Jan 20-24. I'll send a calendar invite.",
89+
"reactions": [{ "type": "thumbsUp", "users": ["u-002", "u-006", "u-012"] }],
90+
"mentions": [],
91+
"relatedEvents": ["ev-005"]
92+
}
93+
]
94+
},
95+
{
96+
"id": "ch-003",
97+
"topic": null,
98+
"type": "oneOnOne",
99+
"teamName": null,
100+
"members": ["u-004", "u-010"],
101+
"messages": [
102+
{
103+
"id": "msg-010",
104+
"from": "u-010",
105+
"timestamp": "2026-01-09T14:50:00Z",
106+
"body": "James, just got off the call with Contoso. They're in! 200 seats. 🎉",
107+
"reactions": [{ "type": "celebrate", "users": ["u-004"] }],
108+
"mentions": []
109+
},
110+
{
111+
"id": "msg-011",
112+
"from": "u-004",
113+
"timestamp": "2026-01-09T14:52:00Z",
114+
"body": "That's incredible Ryan!! Best news all week. Can you send me the details over email so I can loop in Sarah and Marcus?",
115+
"reactions": [],
116+
"mentions": []
117+
},
118+
{
119+
"id": "msg-012",
120+
"from": "u-010",
121+
"timestamp": "2026-01-09T14:55:00Z",
122+
"body": "Sending now. They need SSO scoping and a data residency conversation. I told them we'd get back to them by end of next week.",
123+
"reactions": [{ "type": "thumbsUp", "users": ["u-004"] }],
124+
"mentions": [],
125+
"relatedEmails": ["em-005"]
126+
}
127+
]
128+
},
129+
{
130+
"id": "ch-004",
131+
"topic": "Security & Compliance",
132+
"type": "channel",
133+
"teamName": "Engineering",
134+
"members": ["u-002", "u-005", "u-006", "u-007", "u-012"],
135+
"messages": [
136+
{
137+
"id": "msg-013",
138+
"from": "u-012",
139+
"timestamp": "2026-01-13T09:30:00Z",
140+
"body": "Heads up team - just sent the Q4 security audit findings via email. Three items need attention within 14 days. Most critical: npm CVEs in the frontend build.",
141+
"reactions": [],
142+
"mentions": [],
143+
"relatedEmails": ["em-009"],
144+
"relatedFiles": ["f-007"]
145+
},
146+
{
147+
"id": "msg-014",
148+
"from": "u-005",
149+
"timestamp": "2026-01-13T09:45:00Z",
150+
"body": "I saw the report. Two of the three CVEs are in transitive dependencies. I can bump the parent packages and run the test suite today.",
151+
"reactions": [{ "type": "thumbsUp", "users": ["u-012", "u-002"] }],
152+
"mentions": []
153+
},
154+
{
155+
"id": "msg-015",
156+
"from": "u-007",
157+
"timestamp": "2026-01-13T10:00:00Z",
158+
"body": "I'll handle the TLS 1.0 deprecation on the legacy gateway. Should be a config change + testing. @Noah, can you verify from the network side after I push?",
159+
"reactions": [],
160+
"mentions": ["u-012"]
161+
},
162+
{
163+
"id": "msg-016",
164+
"from": "u-012",
165+
"timestamp": "2026-01-13T10:05:00Z",
166+
"body": "Absolutely. I'll set up the TLS scanner to validate. For the service account permissions, I can tighten those in Azure AD this afternoon - just need Marcus to approve the scope changes.",
167+
"reactions": [{ "type": "thumbsUp", "users": ["u-002"] }],
168+
"mentions": ["u-002"]
169+
},
170+
{
171+
"id": "msg-017",
172+
"from": "u-002",
173+
"timestamp": "2026-01-13T10:12:00Z",
174+
"body": "Approved. Go ahead Noah. And let's add the security items to sprint 25 backlog. @Liam can you create the tickets?",
175+
"reactions": [{ "type": "thumbsUp", "users": ["u-012", "u-008"] }],
176+
"mentions": ["u-008"]
177+
}
178+
]
179+
},
180+
{
181+
"id": "ch-005",
182+
"topic": null,
183+
"type": "oneOnOne",
184+
"teamName": null,
185+
"members": ["u-003", "u-009"],
186+
"messages": [
187+
{
188+
"id": "msg-018",
189+
"from": "u-003",
190+
"timestamp": "2026-01-10T09:00:00Z",
191+
"body": "Mia, the mockups look fantastic! Quick question - did we consider the accessibility requirements for the color contrast in dark mode?",
192+
"reactions": [],
193+
"mentions": [],
194+
"relatedFiles": ["f-003"]
195+
},
196+
{
197+
"id": "msg-019",
198+
"from": "u-009",
199+
"timestamp": "2026-01-10T09:10:00Z",
200+
"body": "Yes! All color combinations meet WCAG 2.1 AA standards. I used the Figma contrast checker plugin. I'll add the accessibility notes to the design spec doc.",
201+
"reactions": [{ "type": "heart", "users": ["u-003"] }],
202+
"mentions": []
203+
},
204+
{
205+
"id": "msg-020",
206+
"from": "u-003",
207+
"timestamp": "2026-01-10T09:12:00Z",
208+
"body": "Perfect. Let's make sure Emily knows about the ARIA roles needed for the drag-and-drop. Great work!",
209+
"reactions": [{ "type": "thumbsUp", "users": ["u-009"] }],
210+
"mentions": ["u-005"]
211+
}
212+
]
213+
},
214+
{
215+
"id": "ch-006",
216+
"topic": "Sales & Marketing",
217+
"type": "channel",
218+
"teamName": "Sales & Marketing",
219+
"members": ["u-004", "u-010", "u-011"],
220+
"messages": [
221+
{
222+
"id": "msg-021",
223+
"from": "u-011",
224+
"timestamp": "2026-01-12T14:00:00Z",
225+
"body": "Blog post draft is out for review. @James and @Sarah have it. Targeting Jan 15th publish date.",
226+
"reactions": [],
227+
"mentions": ["u-004"],
228+
"relatedEmails": ["em-008"],
229+
"relatedFiles": ["f-006"]
230+
},
231+
{
232+
"id": "msg-022",
233+
"from": "u-004",
234+
"timestamp": "2026-01-12T14:15:00Z",
235+
"body": "Great timing Olivia. Also - Fabrikam wants to do a joint webinar Feb 12th. Can you start planning the logistics?",
236+
"reactions": [],
237+
"mentions": [],
238+
"relatedEmails": ["em-011"]
239+
},
240+
{
241+
"id": "msg-023",
242+
"from": "u-011",
243+
"timestamp": "2026-01-12T14:20:00Z",
244+
"body": "On it! I'll draft a landing page and promotional email sequence. We should aim for 200+ registrations. Ryan, can you share the Contoso win as a case study teaser?",
245+
"reactions": [{ "type": "thumbsUp", "users": ["u-004"] }],
246+
"mentions": ["u-010"]
247+
},
248+
{
249+
"id": "msg-024",
250+
"from": "u-010",
251+
"timestamp": "2026-01-12T14:30:00Z",
252+
"body": "Definitely! Once the deal is signed I'll get a quote from their CTO. Should make great social proof.",
253+
"reactions": [{ "type": "fire", "users": ["u-011", "u-004"] }],
254+
"mentions": []
255+
}
256+
]
257+
},
258+
{
259+
"id": "ch-007",
260+
"topic": null,
261+
"type": "groupChat",
262+
"teamName": null,
263+
"members": ["u-005", "u-006", "u-007"],
264+
"messages": [
265+
{
266+
"id": "msg-025",
267+
"from": "u-006",
268+
"timestamp": "2026-01-16T12:00:00Z",
269+
"body": "Hey, did either of you see the Python SDK beta results? 9 out of 12 rated DX as excellent or good!",
270+
"reactions": [{ "type": "celebrate", "users": ["u-005", "u-007"] }],
271+
"mentions": [],
272+
"relatedEmails": ["em-012"],
273+
"relatedFiles": ["f-008"]
274+
},
275+
{
276+
"id": "msg-026",
277+
"from": "u-005",
278+
"timestamp": "2026-01-16T12:05:00Z",
279+
"body": "That's awesome David! The auth token refresh bugs - are those in the same area I refactored last sprint?",
280+
"reactions": [],
281+
"mentions": ["u-006"]
282+
},
283+
{
284+
"id": "msg-027",
285+
"from": "u-006",
286+
"timestamp": "2026-01-16T12:10:00Z",
287+
"body": "Different code path actually. It's the background renewal timer in the async client. I have a fix ready, just need to add retry logic.",
288+
"reactions": [{ "type": "thumbsUp", "users": ["u-005"] }],
289+
"mentions": []
290+
},
291+
{
292+
"id": "msg-028",
293+
"from": "u-007",
294+
"timestamp": "2026-01-16T12:15:00Z",
295+
"body": "Nice work both of you! David, make sure the fix goes through the security scan pipeline before merging. Noah flagged some dependency issues yesterday.",
296+
"reactions": [{ "type": "thumbsUp", "users": ["u-006"] }],
297+
"mentions": ["u-006"],
298+
"relatedEmails": ["em-009"]
299+
}
300+
]
301+
}
302+
]

0 commit comments

Comments
 (0)