fix(gfql): decline undirected varlen + node alias on polars chain (honest NIE, #1741)#1742
fix(gfql): decline undirected varlen + node alias on polars chain (honest NIE, #1741)#1742lmeyerov wants to merge 1 commit into
Conversation
…nest NIE) issue #1741: undirected multi-hop lacks pandas' backtrack avoidance — node/edge SETS agree, but the alias flag on nodes after the undirected varlen edge tags nodes whose only path bounces back over a single edge (the seed at *1..2), which pandas' trail semantics leaves untagged. Cypher RETURN projects those flags, so MATCH (a)-[:T*1..2]-(f) RETURN f silently returned wrong rows on engine='polars'. Decline the affected shape (undirected non-single-hop + any node alias) with a NotImplemented pointing at #1741; unnamed chains keep native parity (pinned by test). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y6dQEcjdazEnzuvuwf73ZL
Reviewer pushback accepted — my first diagnosis was wrong, and the real fix is smaller than I claimed@lmeyerov asked why we raise instead of implementing it. Re-investigated, and the framing in this PR's description ("missing backtrack avoidance") is incorrect. Direct A/B:
What pandas actually does ( Why it isn't a one-liner today: the gate needs per-node hop distances (
Proposed disposition: keep this open only as stop-the-bleeding (master currently returns silently wrong rows, which is worse than an error). If (1)+(2) land promptly, close this unmerged and ship the real fix instead. Happy to go straight to the real fix if you'd rather not carry the interim decline at all — say the word. Full diagnosis with the A/B evidence is recorded in |
|
Superseded by the real fix: #1746 (native Leaving this open only until #1747 merges, since master currently returns silently wrong rows for this shape and a decline is strictly better than that. Once #1747 lands I'll close this unmerged and flip its test from "raises" to "matches the pandas oracle". |
Superseded by #1747 — will close once that landsThis PR declines ( Keeping this open only as a safety net until #1747 merges; it will be closed at that point. No further work planned on it. |
|
Closing now (not waiting for #1747 to merge): this PR touches the same two files (chain.py + test_engine_polars_chain.py) and the same undirected-varlen-alias shape as #1747, with the opposite approach — declining (NIE) what #1747 correctly implements. Two open PRs conflicting on the same lines is confusing and offers no benefit: #1747 is reviewed, cross-engine-verified (0 regressions), and CI-green. Reopen if #1747 is ever rejected. Superseded by #1747 (refs #1741). |
…ong (#1748) Adapts the retired #1742 decline pattern to the one shape #1747's hop-gate can't yet cover: a node named after a forward/reverse variable-length edge with min_hops>1. Those labels come from pandas' layered backward walk (not ported), so the alias runs ungated and tags nodes outside the [min_hop, max_hop] window — silently wrong rows. Now an honest NotImplementedError pointing at #1748. The decline is precise (differential vs pandas, 15 graphs x fwd/rev x named/unnamed): 30/30 named shapes NIE, 30/30 unnamed shapes run and match pandas, 0 silent-wrong, 0 over-decline. With this the whole #1741 stack leaves ZERO silent-wrong shape on the polars chain. xfail pins flipped to positive assert-raises tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y6dQEcjdazEnzuvuwf73ZL
…ong (#1748) Adapts the retired #1742 decline pattern to the one shape #1747's hop-gate can't yet cover: a node named after a forward/reverse variable-length edge with min_hops>1. Those labels come from pandas' layered backward walk (not ported), so the alias runs ungated and tags nodes outside the [min_hop, max_hop] window — silently wrong rows. Now an honest NotImplementedError pointing at #1748. The decline is precise (differential vs pandas, 15 graphs x fwd/rev x named/unnamed): 30/30 named shapes NIE, 30/30 unnamed shapes run and match pandas, 0 silent-wrong, 0 over-decline. With this the whole #1741 stack leaves ZERO silent-wrong shape on the polars chain. xfail pins flipped to positive assert-raises tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y6dQEcjdazEnzuvuwf73ZL
Summary
Fixes the silent-wrong-results half of #1741: on
engine='polars'/'polars-gpu',MATCH (a {..})-[:T*1..2]-(f) RETURN f.idreturned rows pandas (the parity oracle) correctly excludes.*1..2. CypherRETURNprojects those flags → silent wrong rows.NotImplementedErrorreferencing GFQL polars chain: undirected bounded varlen (-[:T*1..k]-) silently diverges from pandas — missing backtrack avoidance includes the seed #1741, per the parity-or-honest-NIE contract. Unnamed undirected varlen chains keep native execution (their parity is pinned by a new test).Tests
TestUndirectedVarlenAliasNIE: NIE on the named shape; the exact GFQL polars chain: undirected bounded varlen (-[:T*1..k]-) silently diverges from pandas — missing backtrack avoidance includes the seed #1741 cypher repro now declines instead of returning a wrong row set (pandas oracle result pinned); unnamed undirected varlen keeps native parity.🤖 Generated with Claude Code
https://claude.ai/code/session_01Y6dQEcjdazEnzuvuwf73ZL