feat(gfql): native polars multi-source (node-cartesian) MATCH lowering (#1273)#1749
Merged
Merged
Conversation
lmeyerov
added a commit
that referenced
this pull request
Jul 20, 2026
ops: Sequence[Any] -> Sequence[ASTObject] (call site passes List[ASTObject]; ASTObject added to the TYPE_CHECKING import). DRY vs pandas assessed: the docstring documents the mirror of _gfql_cartesian_node_bindings_row_table — cross-engine (pandas .merge vs polars .join) sharing would add indirection without removing real duplication; the value is parity via faithful column-contract mirroring. CHANGELOG [Development]/Fixed entry added. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y6dQEcjdazEnzuvuwf73ZL
#1273) Multi-source MATCH like `MATCH (a {..}), (b {..})` lowers to a `rows(binding_ops=[Node, Node, ...])` op whose node_cartesian mode was previously deferred (returned None -> NotImplementedError) on the polars engine. Implement it natively, mirroring the pandas `_gfql_cartesian_node_bindings_row_table` oracle exactly: - per-alias frame = filter_by_dict + project into the `_gfql_node_alias_lookup_frame` schema (bare `alias` id, `alias.id`, `alias.<prop>`, and the leaked named-op flag `alias.alias = True` that shadows a same-named real property), then a left-major cross join so the row order matches pandas' constant-key merge (no ORDER BY needed). - Decline (honest NIE, no pandas bridge) outside pandas' reliable zone: anonymous node ops (pandas raises a spurious schema error on empty results) and >3 named aliases (pandas' bare-id merge residue collides on the 4th frame). Both engines then error, never diverge. Verified by a differential fuzz (random small graphs x multi-source query shapes incl. WHERE / ORDER BY / property-name-vs-alias collisions) against the pandas oracle: 0 disagreements over ~10k lowered cases across seeds. Adds parametrized parity + explicit pin tests. No new ruff/mypy findings. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y6dQEcjdazEnzuvuwf73ZL
…rage gate) Add an alias==node_id decline test (the one reachable defensive branch), and pragma: no cover the genuinely-unreachable guards (post-materialize nodes present, node_id is the bound column, non-str alias already filtered, defensive filter/collect excepts, non-empty per_alias) with rationale — mirrors this repo's accepted approach for structurally-uncoverable branches. 41 tests still pass, ruff clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y6dQEcjdazEnzuvuwf73ZL
ops: Sequence[Any] -> Sequence[ASTObject] (call site passes List[ASTObject]; ASTObject added to the TYPE_CHECKING import). DRY vs pandas assessed: the docstring documents the mirror of _gfql_cartesian_node_bindings_row_table — cross-engine (pandas .merge vs polars .join) sharing would add indirection without removing real duplication; the value is parity via faithful column-contract mirroring. CHANGELOG [Development]/Fixed entry added. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y6dQEcjdazEnzuvuwf73ZL
lmeyerov
force-pushed
the
feat/gfql-1273-multi-source-cartesian-polars
branch
from
July 20, 2026 18:25
11a9d06 to
772a655
Compare
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.
What
Implements native polars lowering for multi-source MATCH — comma-separated disconnected aliases, e.g.
MATCH (a {..}), (b {..}) RETURN a.id, b.id. Previously the polarsrows(binding_ops)cartesian branch hard-declined (NotImplementedError); pandas handled it. New_cartesian_node_bindings_polarsinrow_pipeline.pyreproduces the pandas per-alias schema exactly (barealiasid,alias.id,alias.<prop>, and the pandasalias.alias=Trueflag quirk incl. property-shadowing) and left-major cross-joins for row-order parity.Two evidence-backed declines keep strict parity — both are shapes where pandas itself errors (proven on master), so both engines fail identically, never diverge:
MATCH (a),(b),()) — pandas raises on empty results.suffixes-duplicate-columns).Verification (independent A/B, done by the reviewing agent — not just the author's self-report)
End-to-end
g.gfql(...)vs the pandas oracle on the same graphs:RETURN a.id, b.id(2-source scalar)RETURN a.id AS ai, b.id AS bi(3-source aliased)RETURN count(*) AS cRETURN a, b(whole-entity)MATCH (a),(b),(c),(d)(≥4)test_engine_polars_binding_rows.py: 41 passed (independently re-run).ruff: clean.ceiling/roundconformance cases verified pre-existing on clean masterc355660a(polars version drift), 0 new regressions.mypy: master baseline, 0 new.Scope / follow-ups (not this PR)
RETURN a, bprojection remains NIE (different surface).ORDER BY a.id, b.idon raw cross-source refs trips a separate Cypher/GFQL: admit multi-MATCH-source row projection without hidden carries (IC5 sub-residual B) #1273 ORDER-BY residual that fails at compile for both engines (no divergence).rows(source=...)property-name-vs-alias bug on master is a candidate for a sharper follow-up issue.Independent fork off master (touches
row_pipeline.pyonly — no overlap with the #1741 chain stack or #1743). Refs #1273.🤖 Generated with Claude Code