Skip to content

fix(gfql): polars chain re-executes steps on the graph's original edge columns (#2039) - #2046

Merged
lmeyerov merged 5 commits into
masterfrom
fix/gfql-2039-polars-alias-collision
Sep 5, 2026
Merged

fix(gfql): polars chain re-executes steps on the graph's original edge columns (#2039)#2046
lmeyerov merged 5 commits into
masterfrom
fix/gfql-2039-polars-alias-collision

Conversation

@lmeyerov

@lmeyerov lmeyerov commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

[n({"id": 30}, name="m"), e_forward({"type": "HAS_CREATOR"}, name="type"), n(name="p")] raised GFQLSchemaError [incompatible-column-type] on polars while pandas served it: the forward step stamps the alias marker type onto its edge frame, and the backward pass (g_step_full) and the pruned re-execution (g_sub) fed that stamped frame back into the hop, whose edge_match then compared the boolean marker to 'HAS_CREATOR'. Both sites now take the step's edge rows joined back to the graph's original edge columns (semi-join on the chain's edge id), so re-execution sees the user values; the combine's marker placement is unchanged.

Pins: test_polars_alias_column_collision_2039.py (edge-alias collision, node+edge collision, node-only collision: same rows on pandas and polars under policy off and use; a 2-hop with the colliding alias is served), and the #1911 alias-scoping suite unchanged except test_rows_route_edge_alias_colliding_with_its_own_type_filter, which keeps pinning polars' rows-route decline on that shape (now a typed GFQLValidationError from the rows route rather than the chain) — that residual stays open on #2039. Local: polars chain/hop/narrow-combine/conformance/alias-scoping suites 2031 passed. Real-GPU (polars-gpu) run to follow on dgx.

Fixes the native op-list half of #2039.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QztW7jYsDd66e8rb8pJNQA

@lmeyerov

lmeyerov commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Real-GPU receipt (dgx-spark, RAPIDS 26.02 image, cudf 26.02.01 / polars 1.35.2): test_polars_alias_column_collision_2039.py + test_engine_polars_gpu.py + polars chain/hop + alias-scoping suites at 662e557 = 1508 passed, 0 failed, 0 skipped.

@lmeyerov

lmeyerov commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

READY (662e557): 77/77; polars re-executes steps on the graph's original edge columns (#2039); real-GPU 1508 passed / 0 skipped; the rows-route residual stays pinned and open on #2039.

@lmeyerov

lmeyerov commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Review follow-up (owner: "other specializations of the same bug" + mirror-path tests), head 0de93ce.

Probe. 22 alias/column collision shapes × pandas/cuDF/polars × index policy off/use against the pandas full path (edge alias = filtered / unfiltered / src / dst / edge-id column; node alias = filtered column on the seed or the destination, node-id binding, an edge column name; hops=2; to_fixed_point; unseeded; step 2 of 2; all three colliding). Three more specializations surfaced:

  1. polars node side — fixed here. A destination alias that names its own filtered column (n({"type": "p"}, name="type")) raised the same incompatible-column-type, and the final alias tagging joined the marker in as type_right with nulls where pandas replaces the column. The node step now filters the graph's own values for that column and the marker replaces a colliding column (marker-authoritative, as pandas' combine).
  2. multi-hop edge alias (every engine) — gfql: an edge alias that collides with the column its own filter uses breaks multi-hop steps (pandas/cuDF raise, polars mis-names) #2049. hops=2 / to_fixed_point with an edge alias = the filtered column: pandas and cuDF raise, polars emits type_right. Separate PR.
  3. alias = source / destination / edge-id binding column — gfql: an alias named like the source, destination or edge-id binding column is not rejected (silent clobber on pandas/cuDF, raw polars SchemaError) #2050. pandas/cuDF silently clobber the binding (the seed's edges vanish, or the edge id becomes True); polars raises a raw SchemaError. Only the node-id binding is validated today. Separate PR (validator).

Pins. Tests moved to the mirror path graphistry/tests/compute/gfql/lazy/engine/polars/test_chain_alias_column_collision_2039.py; new cross-engine matrix graphistry/tests/compute/test_chain_alias_column_collision.py (12 served shapes × 3 engines × scan/indexed = every single-hop collision matches the pandas full path; strict xfails for #2049 and #2050 that flip when they land; node-binding rejection pinned as the positive control). Local: 696 passed / 15 xfailed across the polars suites, cuDF 25.10 included; mypy unchanged; ruff clean. Still stacked on #2045; CI running.

Base automatically changed from fix/gfql-2020-alias-prefilter-alignment to master September 5, 2026 20:39
lmeyerov and others added 4 commits September 5, 2026 13:41
…e columns (#2039)

An edge alias that shares its name with the column its own step filters on
was stamped as a boolean marker on the forward step's edges, and the backward
pass and pruned re-execution then filtered that marker as the column and
raised. Both now take the step's edge rows with the graph's original columns.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QztW7jYsDd66e8rb8pJNQA
…e served and marker-authoritative

The same marker-before-filter defect as the edge side (#2039): a node step whose alias
names its own filtered column re-filtered the marker of an earlier pass, and the final
alias tagging joined the marker in as a `_right` column with nulls instead of replacing
the column the way pandas' combine does. The step now filters the graph's own values for
that column and the marker replaces a colliding column.

Tests move to the mirror path (graphistry/tests/compute/gfql/lazy/engine/polars/) and a
cross-engine collision matrix (graphistry/tests/compute/test_chain_alias_column_collision.py)
pins every single-hop collision shape on pandas, cuDF and polars against the pandas full
path, with strict expected failures for the multi-hop (#2049) and binding-column (#2050)
forms.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QztW7jYsDd66e8rb8pJNQA
…enting it

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QztW7jYsDd66e8rb8pJNQA
… polars lane list

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QztW7jYsDd66e8rb8pJNQA
lmeyerov added a commit that referenced this pull request Sep 5, 2026
… single-hop shape (#2051)

Sibling-specialization sweep after #2046: polars' hop() collapses duplicate node rows
(#1993) but the unnamed, untyped single-hop chain shape still keeps the duplicate. The
collapsing shapes (named, typed, hops=2, undirected, hop()) are pinned green against
pandas; the two leaking shapes are strict expected failures that flip with the fix.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QztW7jYsDd66e8rb8pJNQA
@lmeyerov

lmeyerov commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

READY (04ff8ed) — rebased onto master after #2045 landed; CI 77/77 check-runs success (the earlier red was the pre-move #2020 pin path the union rebase re-added to the polars lane list; dropped). Content unchanged since the review follow-up: polars node-side collision fix + cross-engine collision matrix + mirror-path tests.

@lmeyerov

lmeyerov commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

note: #2049 goes into the eager case, and we'll separately handle alt specializations across recent fixes

@lmeyerov
lmeyerov merged commit b8f3e99 into master Sep 5, 2026
78 checks passed
@lmeyerov
lmeyerov deleted the fix/gfql-2039-polars-alias-collision branch September 5, 2026 21:43
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.

1 participant