Skip to content

Commit 1956737

Browse files
committed
test: harden cypher reentry regressions
1 parent 1499ac6 commit 1956737

2 files changed

Lines changed: 180 additions & 117 deletions

File tree

graphistry/tests/compute/gfql/cypher/test_lowering.py

Lines changed: 50 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import pandas as pd
44
import pytest
5-
from typing import Any, Dict, List, Tuple, cast
5+
from typing import Any, Dict, List, Optional, Tuple, cast
66

77
from graphistry.compute.ast import ASTCall, ASTNode, ASTEdgeForward, ASTEdgeReverse, ASTEdgeUndirected
88
from graphistry.compute.exceptions import ErrorCode, GFQLSyntaxError, GFQLTypeError, GFQLValidationError
@@ -116,6 +116,23 @@ def _compiled_reentry_projection_outputs(compiled: CompiledCypherQuery) -> Tuple
116116
return whole_row_columns[0], carried_columns
117117

118118

119+
def _reentry_query(
120+
with_clause: str,
121+
*,
122+
return_clause: str,
123+
match_alias: str = "a",
124+
order_by: Optional[str] = None,
125+
where_clause: Optional[str] = None,
126+
) -> str:
127+
parts = ["MATCH (a:A) ", f"WITH {with_clause} ", f"MATCH ({match_alias})-->(b) "]
128+
if where_clause is not None:
129+
parts.append(f"WHERE {where_clause} ")
130+
parts.append(f"RETURN {return_clause}")
131+
if order_by is not None:
132+
parts.append(f" ORDER BY {order_by}")
133+
return "".join(parts)
134+
135+
119136
def _assert_query_rows(
120137
query: str,
121138
expected_rows: list[dict[str, object]],
@@ -5049,29 +5066,26 @@ def test_string_cypher_executes_with_match_reentry_multihop_shape() -> None:
50495066
("query", "expected_whole_row_output", "expected_columns"),
50505067
[
50515068
(
5052-
"MATCH (a:A) "
5053-
"WITH a, a.num AS property "
5054-
"MATCH (a)-->(b) "
5055-
"RETURN property "
5056-
"ORDER BY property DESC",
5069+
_reentry_query("a, a.num AS property", return_clause="property", order_by="property DESC"),
50575070
"a",
50585071
("property",),
50595072
),
50605073
(
5061-
"MATCH (a:A) "
5062-
"WITH a, a.num AS property, a.num + 10 AS property2 "
5063-
"MATCH (a)-->(b) "
5064-
"RETURN property, property2 "
5065-
"ORDER BY property DESC",
5074+
_reentry_query(
5075+
"a, a.num AS property, a.num + 10 AS property2",
5076+
return_clause="property, property2",
5077+
order_by="property DESC",
5078+
),
50665079
"a",
50675080
("property", "property2"),
50685081
),
50695082
(
5070-
"MATCH (a:A) "
5071-
"WITH a AS x, a.num AS property "
5072-
"MATCH (x)-->(b) "
5073-
"RETURN property "
5074-
"ORDER BY property DESC",
5083+
_reentry_query(
5084+
"a AS x, a.num AS property",
5085+
match_alias="x",
5086+
return_clause="property",
5087+
order_by="property DESC",
5088+
),
50755089
"x",
50765090
("property",),
50775091
),
@@ -5093,43 +5107,32 @@ def test_compile_cypher_tracks_reentry_carried_scalar_columns(
50935107
("query", "expected"),
50945108
[
50955109
(
5096-
"MATCH (a:A) "
5097-
"WITH a AS x "
5098-
"MATCH (x)-->(b) "
5099-
"RETURN b.id AS bid "
5100-
"ORDER BY bid",
5110+
_reentry_query("a AS x", match_alias="x", return_clause="b.id AS bid", order_by="bid"),
51015111
[{"bid": "b1"}, {"bid": "b2"}],
51025112
),
51035113
(
5104-
"MATCH (a:A) "
5105-
"WITH a, a.num AS property "
5106-
"MATCH (a)-->(b) "
5107-
"RETURN property "
5108-
"ORDER BY property DESC",
5114+
_reentry_query("a, a.num AS property", return_clause="property", order_by="property DESC"),
51095115
[{"property": 2}, {"property": 1}],
51105116
),
51115117
(
5112-
"MATCH (a:A) "
5113-
"WITH a, a.num AS property "
5114-
"MATCH (a)-->(b) "
5115-
"RETURN a "
5116-
"ORDER BY property DESC",
5118+
_reentry_query("a, a.num AS property", return_clause="a", order_by="property DESC"),
51175119
[{"a": "(:A {num: 2})"}, {"a": "(:A {num: 1})"}],
51185120
),
51195121
(
5120-
"MATCH (a:A) "
5121-
"WITH a, a.num AS property, a.num + 10 AS property2 "
5122-
"MATCH (a)-->(b) "
5123-
"RETURN property, property2 "
5124-
"ORDER BY property DESC",
5122+
_reentry_query(
5123+
"a, a.num AS property, a.num + 10 AS property2",
5124+
return_clause="property, property2",
5125+
order_by="property DESC",
5126+
),
51255127
[{"property": 2, "property2": 12}, {"property": 1, "property2": 11}],
51265128
),
51275129
(
5128-
"MATCH (a:A) "
5129-
"WITH a AS x, a.num AS property "
5130-
"MATCH (x)-->(b) "
5131-
"RETURN x, property "
5132-
"ORDER BY property DESC",
5130+
_reentry_query(
5131+
"a AS x, a.num AS property",
5132+
match_alias="x",
5133+
return_clause="x, property",
5134+
order_by="property DESC",
5135+
),
51335136
[{"x": "(:A {num: 2})", "property": 2}, {"x": "(:A {num: 1})", "property": 1}],
51345137
),
51355138
],
@@ -5143,13 +5146,7 @@ def test_string_cypher_reentry_carried_scalars_ignore_internal_hidden_column_col
51435146
g = _mk_reentry_carried_scalar_graph()
51445147
g._nodes = g._nodes.assign(__cypher_reentry_property__=["orig1", "orig2", None, None])
51455148

5146-
result = g.gfql(
5147-
"MATCH (a:A) "
5148-
"WITH a, a.num AS property "
5149-
"MATCH (a)-->(b) "
5150-
"RETURN property "
5151-
"ORDER BY property DESC"
5152-
)
5149+
result = g.gfql(_reentry_query("a, a.num AS property", return_clause="property", order_by="property DESC"))
51535150

51545151
assert result._nodes.to_dict(orient="records") == [{"property": 2}, {"property": 1}]
51555152

@@ -5158,11 +5155,11 @@ def test_string_cypher_reentry_carried_scalars_ignore_internal_hidden_column_col
51585155
("query", "match"),
51595156
[
51605157
(
5161-
"MATCH (a:A) "
5162-
"WITH a, a.num AS property "
5163-
"MATCH (a)-->(b) "
5164-
"WHERE property = b.num "
5165-
"RETURN b.id AS id",
5158+
_reentry_query(
5159+
"a, a.num AS property",
5160+
return_clause="b.id AS id",
5161+
where_clause="property = b.num",
5162+
),
51665163
"one MATCH source alias at a time",
51675164
),
51685165
(

0 commit comments

Comments
 (0)