feat(cypher): admit multi-prefix-row free-form intermediate MATCH (#1285)#1289
Merged
feat(cypher): admit multi-prefix-row free-form intermediate MATCH (#1285)#1289
Conversation
deab210 to
d49767c
Compare
) Replaces the single-row-only failfast in the free-form runtime path with a per-row union loop, mirroring the scalar-only multi-row pattern at ``_compiled_query_scalar_reentry_state`` (#1047). For each prefix row, the new ``_freeform_broadcast_row_to_nodes`` helper builds a dispatch graph with that row's hidden carry columns broadcast onto every base node; the suffix runs as a global MATCH (``start_nodes=None``) and per-row results are unioned via the existing engine-polymorphic ``_union_scalar_reentry_results``. Cartesian semantics fall out naturally: every prefix row × every trailing- MATCH row. Out of scope (preserved as failfasts): - ``optional_reentry`` + multi-row free-form: same null-fill gap as the scalar-only multi-row path; mirrors that lane's existing failfast. - Carried-property bridge in trailing scope (#1275). Refs #1285, #1263, #999, #989 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
#1285) Three test changes for the multi-prefix-row free-form admit: * ``..._failfast_rejects_simple_freeform_intermediate_reentry_match_on_multi_row_prefix`` → ``..._executes_freeform_intermediate_reentry_match_on_multi_row_prefix`` (retargeted to positive; pins per-row union behavior — 2 prefix rows × 1 trailing pair = 2 result rows). * ``..._executes_freeform_intermediate_reentry_match_on_multi_row_prefix_cartesian`` (new) — 2 prefix rows × 2 trailing pairs = 4 result rows; locks the Cartesian product semantics. * ``..._executes_freeform_intermediate_reentry_match_on_multi_row_prefix_on_cudf_when_available`` (new) — cuDF parity for the multi-row admit. Pre-existing simple (single-row) free-form tests stay untouched. Refs #1285 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wave 2 review surfaced an uncovered code path: the runtime guard at ``_execute_compiled_query_with_reentry`` rejects ``optional_reentry + multi-row free-form`` (mirror of the scalar-only multi-row guard from #1047) but no test asserted the failfast wording. Adds ``test_string_cypher_failfast_rejects_freeform_multi_row_prefix_with_optional_reentry``, following the sibling pattern from ``test_issue_1047_multi_row_scalar_prefix_with_optional_reentry_raises``. Refs #1285 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
d49767c to
2b5739b
Compare
This was referenced May 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #1285 (LDBC SNB IC3 follow-up). Replaces the single-row-only failfast in the free-form intermediate MATCH runtime path (#1279) with a per-row union loop, admitting multi-prefix-row free-form shapes. Cartesian semantics: every prefix row × every trailing-MATCH row.
What changed
graphistry/compute/gfql_unified.py:_freeform_broadcast_row_to_nodeshelper from_compiled_query_freeform_reentry_stateso single-row and multi-row paths share the broadcast logic._execute_compiled_query_with_reentry, mirroring the scalar-only multi-row pattern from Cypher/GFQL: multi-alias WITH prefix projection for bounded reentry #1047. Reuses_union_scalar_reentry_results(engine-polymorphic viadf_concat(engine)) for the union step.optional_reentry + multi-row free-formfailfast (same null-fill gap as the scalar lane's existing guard).Tests
..._failfast_rejects_simple_freeform_intermediate_reentry_match_on_multi_row_prefix→..._executes_freeform_intermediate_reentry_match_on_multi_row_prefix(positive: 2 prefix × 1 trailing = 2 rows)...._cartesian(2 prefix × 2 trailing = 4 rows; each (cid,did) pair appears twice; locks Cartesian semantics)...._on_cudf_when_available(cuDF parity)...._failfast_rejects_freeform_multi_row_prefix_with_optional_reentry(Wave 2 amplification — locks the scoped OPTIONAL MATCH failfast).Existing simple (single-row) free-form admits from #1279 stay green untouched.
Receipts
./bin/ruff.sh+./bin/mypy.shclean on touched files.Multi-wave review per
agents/skills/review/SKILL.mdWave artifacts:
plans/1285-freeform-multi-prefix-row/waves/wave-{1,2}/.Out of scope (#1263 follow-ups still open)
optional_reentry + multi-rownull-fill — same null-fill gap as Cypher/GFQL: multi-alias WITH prefix projection for bounded reentry #1047's existing scalar-only guard; both lanes raise.Test plan
pytest -q graphistry/tests/compute/gfql/cypher/test_lowering.pypytest -q graphistry/tests/compute/gfql/cypher/./bin/ruff.sh+./bin/mypy.shon touched filesRefs