Skip to content

Cypher WITH ORDER BY / LIMIT not preserved across MATCH re-entry for multi-row results #1342

Description

@lmeyerov

Summary

WITH ... ORDER BY ... LIMIT k followed by another MATCH is rejected when the prefix produces multi-row results — ordering / limit are not preserved across the MATCH re-entry. This blocks the LDBC SNB IC1 ordered-top-k friend tail.

Repro (minimal, fails on master 41d865ac9)

MATCH (p:Person {id: $pid})-[:KNOWS]-(friend)
WITH friend
ORDER BY friend.firstName ASC
LIMIT 5
MATCH (friend)-[:STUDY_AT]->(uni:University)
RETURN friend.id AS friendId, uni.name AS uniName

Expected vs observed

  • Expected: top-5 friends by firstName survive the LIMIT; the trailing MATCH expands STUDY_AT for that subset.
  • Observed: GFQLValidationError: [unsupported-cypher-query] Cypher MATCH after WITH does not yet preserve prefix WITH row ordering across MATCH re-entry for multi-row result shapes | field: with.order_by | value: ['friend.firstName']

Source

  • Guard: graphistry/compute/gfql/cypher/reentry/runtime.py:340
  • Helper: _bounded_reentry_prefix_order_is_safe (same file)
  • Asserting tests: graphistry/tests/compute/gfql/cypher/test_lowering.py:9218, :9226

Benchmark evidence

  • pyg-bench artifact: results/runs/dgx-spark-ic1-conformance-2026-04-05/probe-results.json
  • LDBC SNB lane: interactive-complex-1 / named-shortest-friends
  • Official IC1 query has WITH min(length(path)) AS distance, friend ORDER BY distance ASC, friend.lastName ASC, toInteger(friend.id) ASC LIMIT 20 immediately followed by another MATCH (friend)-[:IS_LOCATED_IN]->(friendCity:City).

Acceptance criteria

  • The minimal repro above succeeds with the trailing MATCH applied to exactly the top-5 friends ordered by firstName.
  • ReentryPlan (or the bounded-reentry runtime) preserves prefix.order_by and prefix.limit through the trailing MATCH for multi-row prefixes.
  • Regression tests cover: ORDER BY single column + LIMIT, ORDER BY multi-column + LIMIT, ORDER BY DESC + LIMIT, all followed by re-MATCH that traverses out from the carried alias.

Subsystem / scope

  • graphistry/compute/gfql/cypher/reentry/runtime.py (_bounded_reentry_prefix_order_is_safe, the surrounding admit logic)
  • graphistry/compute/gfql/cypher/reentry_plan.py (carry-set + ordering metadata)
  • Out of scope: ordering across more than one re-entry hop — that is a follow-up.

Related

Activity

  1. added 2 commits that reference this issue on May 8, 2026
    7d41625
    60f1bb9
  2. added a commit that references this issue on May 8, 2026
    0526f20
  3. lmeyerov commented on May 8, 2026

    @lmeyerov
    ContributorAuthor

    Merged via #1350 (commit 60f1bb9 on master).\n\nMeta trackers updated:\n- #1259: marked #1342 complete\n- #992: moved #1342 into recently landed progress\n

  4. lmeyerov commented on May 9, 2026

    @lmeyerov
    ContributorAuthor

    Merged via #1346 on 2026-05-09 (UTC) at commit e35d289.\n\nReceipt:\n- PR: https://github.com/graphistry/pygraphistry/pull/1346\n- CI: green at merge (including tck-gfql + docs/readthedocs).\n\nScope landed:\n- admit bounded WITH ORDER BY ... LIMIT literal across MATCH re-entry\n- preserve conservative failfast for unsupported ordering-preservation shapes (e.g., SKIP/param LIMIT)\n- add amplified lowering + cuDF parity regression coverage\n

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions