Skip to content

feat(query): NULL-aware after() position paging - #399

Merged
0x054 merged 1 commit into
feat/position-pagingfrom
feat/394-null-aware-after
Aug 30, 2026
Merged

feat(query): NULL-aware after() position paging#399
0x054 merged 1 commit into
feat/position-pagingfrom
feat/394-null-aware-after

Conversation

@0x054

@0x054 0x054 commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • after() now accepts None in every non-PK position slot (PK None is still a build-time error) and no longer consults ColumnSpec.nullable.
  • exclusive_stepwise_compare is still the one expander: each key's direction, nulls= placement, and whether the bound is NULL fold into one IS NULL / IS NOT NULL / inequality tree so a cursor can cross the NULL bucket in one query.
  • "native" resolves at render from Dialect (Postgres: NULL is larger; SQLite: NULL is smaller). QueryIR stays at v13; a new golden pins kind: "null" in after.

Closes #394

Test plan

  • uv run pytest tests/test_after_position.py — build-time contract + SQLite backend-matrix e2e (Pinch nulls="last" DESC, after((None, id)), non-NULL cursor into the NULL bucket)
  • cargo test --no-default-features --features testing query:: — expander combinatorics (ASC/DESC × first/last × bound-NULL/non-NULL, native on both dialects, two keys)
  • Wire/IR: tests/test_query_wire_vectors.py, tests/test_ir_vectors_contract.py, cargo test -p ferro-schema-ir query_after
  • uv run ty check src/ferro/query
  • Postgres backend-matrix — pytest-postgresql could not start locally (pg_ctl initdb failed). CI will run it.

Made with Cursor

after() accepts None in non-PK slots and expands the exclusive
stepwise compare across NULL buckets so a pinned-first list can
page from the last pinned row into unpinned rows in one query.

Co-authored-by: Cursor <cursoragent@cursor.com>
@0x054
0x054 merged commit 04723ec into feat/position-paging Aug 30, 2026
7 checks passed
@0x054 0x054 mentioned this pull request Aug 30, 2026
6 tasks
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