Skip to content

fix(cypher): support multi-row scalar prefix in MATCH re-entry (#1047) - #1068

Merged
lmeyerov merged 2 commits into
masterfrom
feat/issue-1047-multi-row-scalar-prefix
Apr 6, 2026
Merged

lmeyerov merged 2 commits into
masterfrom
feat/issue-1047-multi-row-scalar-prefix

Conversation

@lmeyerov

@lmeyerov lmeyerov commented Apr 6, 2026

Copy link
Copy Markdown
Contributor

Summary

  • MATCH ... WITH scalar ... MATCH re-entry now works when the WITH prefix produces N rows (previously required exactly 1)
  • Implementation: fan out in _execute_compiled_query_with_reentry — run suffix once per prefix row, union results
  • Unblocks IC6 (tag-cooccurrence): UNWIND fanout produces 4+ prefix rows before re-entry MATCH

Closes #1047

Test plan

  • RED: 6 new execution tests fail before fix
  • GREEN: all 6 pass after fix; existing single-row tests unchanged
  • Full cypher suite: 811 passed, 57 skipped (no regressions)
  • dgx-spark GPU validation (TEST_CUDF=1)
  • IC6 conformance rebaseline on dgx-spark

🤖 Generated with Claude Code

MATCH ... WITH scalar1, scalar2 ... MATCH re-entry now works when the
WITH prefix produces N rows (previously required exactly 1).

Implementation: detect N>1 prefix rows in
_execute_compiled_query_with_reentry; fan out: run the suffix MATCH once
per prefix row (each row's scalars broadcast as hidden columns), then
union results via _union_scalar_reentry_results.

This unblocks IC6 (tag-cooccurrence): the UNWIND fanout before the
tag-cooccurrence MATCH produces 4+ prefix rows.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
@lmeyerov
lmeyerov merged commit 6de1f6d into master Apr 6, 2026
101 checks passed
lmeyerov added a commit that referenced this pull request May 3, 2026
…entry (#1071)

Pre-rewrite the prefix WITH stage in _compile_bounded_reentry_query so
secondary whole-row aliases are demoted to scalar property carries
(S.X AS __cypher_reentry_<S>_<X>__) and downstream S.X references compose
with the existing single-whole-row machinery (#1047/#1068). RETURN of a
secondary whole-row alias, and re-binding a secondary alias as a node
variable in the trailing MATCH, remain unsupported with precise errors.

Closes #1071.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
lmeyerov added a commit that referenced this pull request May 3, 2026
…entry (#1071)

Pre-rewrite the prefix WITH stage in _compile_bounded_reentry_query so
secondary whole-row aliases are demoted to scalar property carries
(S.X AS __cypher_reentry_<S>_<X>__) and downstream S.X references compose
with the existing single-whole-row machinery (#1047/#1068). RETURN of a
secondary whole-row alias, and re-binding a secondary alias as a node
variable in the trailing MATCH, remain unsupported with precise errors.

Closes #1071.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
pull Bot pushed a commit to admariner/pygraphistry that referenced this pull request May 3, 2026
…entry (graphistry#1071)

Pre-rewrite the prefix WITH stage in _compile_bounded_reentry_query so
secondary whole-row aliases are demoted to scalar property carries
(S.X AS __cypher_reentry_<S>_<X>__) and downstream S.X references compose
with the existing single-whole-row machinery (graphistry#1047/graphistry#1068). RETURN of a
secondary whole-row alias, and re-binding a secondary alias as a node
variable in the trailing MATCH, remain unsupported with precise errors.

Closes graphistry#1071.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
lmeyerov added a commit that referenced this pull request May 3, 2026
…entry (#1071)

Pre-rewrite the prefix WITH stage in _compile_bounded_reentry_query so
secondary whole-row aliases are demoted to scalar property carries
(S.X AS __cypher_reentry_<S>_<X>__) and downstream S.X references compose
with the existing single-whole-row machinery (#1047/#1068). RETURN of a
secondary whole-row alias, and re-binding a secondary alias as a node
variable in the trailing MATCH, remain unsupported with precise errors.

Closes #1071.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
lmeyerov added a commit that referenced this pull request May 3, 2026
) (#1249)

* fix(gfql/row): resolve bare relationship alias in row expressions (#1072)

Bare edge aliases in select / where_rows / order_by row expressions raised
"unsupported token in row expression" because _gfql_resolve_token only had a
node-id fallback for the bare-alias case. Add an edge fallback: prefer the
edge-id column, otherwise render the relationship as a Cypher-style
[:TYPE {props}] string, mirroring what cypher RETURN <relAlias> already
produces via result_postprocess. Direct GFQL chains and cypher-lowered chains
now see the same column shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

* feat(cypher): support multi-alias carry through WITH before MATCH re-entry (#1071)

Pre-rewrite the prefix WITH stage in _compile_bounded_reentry_query so
secondary whole-row aliases are demoted to scalar property carries
(S.X AS __cypher_reentry_<S>_<X>__) and downstream S.X references compose
with the existing single-whole-row machinery (#1047/#1068). RETURN of a
secondary whole-row alias, and re-binding a secondary alias as a node
variable in the trailing MATCH, remain unsupported with precise errors.

Closes #1071.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

* feat(gfql): unify relationship alias rendering and harden row resolution (#1072)

* fix(gfql/cypher): close wave-3 alias resolution and reentry where gaps (#1072)

* docs(changelog): add #1072 entry for relationship alias in row expressions

Records the user-facing fix and amplifications for #1072 under
## [Development] → ### Fixed: bare edge-alias resolution in row
expressions, shared vectorized renderer in row/entity_props.py,
edge-alias gating via _gfql_rows_edge_aliases, string-escape /
float / empty-type rendering normalization, and re-entry WHERE
secondary-alias predicate rewriting via synthesized text.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

* test(gfql/row): add cuDF smoke test for bare relationship alias rendering

Wave 4 finding T2 (IMPORTANT): TestRelationshipAliasInRowExpression
had 14 new tests in PR #1249 but zero cuDF coverage on the new
edge-alias rendering path, despite Wave 2 vectorization being
specifically motivated by cuDF support (Wave 1 finding #4).

Adds test_select_bare_relationship_alias_renders_on_cudf_when_available
following the sibling pattern at test_row_pipeline_vectorized_cudf_when_available
(pytest.importorskip("cudf")). Asserts: (a) result keeps cuDF backend,
(b) bare-alias rendering produces "[:WORKS_AT {workFrom: 2010}]",
(c) select/return cell-for-cell parity holds on cuDF.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

* refactor(gfql/row): collapse duplicate ValueError in _gfql_resolve_token

Wave 4 finding D1 (SUGGESTION): the conditional at pipeline.py:2310 and
the raise at pipeline.py:2312 produce identical errors. After the
node-id branch (lines 2306-2309) returns, the only remaining outcome
is "unsupported token", regardless of edge_aliases membership — both
branches raised the same f-string. Collapsed to a single raise.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cypher/GFQL: multi-alias WITH prefix projection for bounded reentry

1 participant