Skip to content

fix(rust): render columns in projection order - #1171

Merged
thekevinscott merged 4 commits into
mainfrom
claude/1170-projection-order
Sep 24, 2026
Merged

thekevinscott merged 4 commits into
mainfrom
claude/1170-projection-order

Conversation

@thekevinbot

@thekevinbot thekevinbot commented Sep 23, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #1170

SELECT path, ctime FROM './' printed ctime, path: Db::query collected each
row into a HashMap and threw away stmt.column_names(), so every renderer
re-derived its columns from row keys and got alphabetical order. --format json
had the same defect through serde_json's BTreeMap-backed objects.

The column order now travels with the rows. Db::query_ordered /
DirSQL::query_ordered return a QueryResult { columns, rows }; the CLI's
shared query pipeline serializes each row against columns (with
serde_json's preserve_order), and the table renderer takes the columns in
the order the rows carry them rather than sorting them into a BTreeSet.
query keeps its Vec<Row> signature, so Row, differ.rs and the SDK
bindings are untouched.

Scope is the Rust core + CLI. Python/TS parity is drift, tracked in PARITY.md
and filed as #1173 and #1174.

Red/green

The two test commits went up alone first. CI (Rust CI / Integration tests, run
35888793774) went red on the new integration test for exactly the asserted
reason:

test serialized_rows_follow_the_projection_order ... FAILED
panicked at packages/rust/tests/column_order.rs:56:5:
expected `size` before `basename`, got: [{"basename":"a.md","size":6}]

cargo test aborts at the first failing test binary, so column_order_e2e.rs
was not reached in that run; its red was confirmed locally on the same commit:

test the_table_header_follows_the_select_list ... FAILED
  left: ["basename", "size"]
 right: ["size", "basename"]
test json_keys_follow_the_select_list ... FAILED
expected `size` before `basename`, got: [{"basename":"a.md","size":6}]

Manual run

Built cargo build -p dirsql --features cli and ran it over a two-file temp dir:

$ dirsql "SELECT path, ctime FROM './' LIMIT 5" --format table
path  ctime
----  ----------
a.md  1790181167
b.md  1790181167

2 rows

$ dirsql "SELECT path, ctime, size FROM './' LIMIT 2" --format json
[{"path":"a.md","ctime":1790181167,"size":6},{"path":"b.md","ctime":1790181167,"size":10}]

E2E Verification

  • Ran e2e suites locally for every affected SDK
  • Python SDK e2e: pass
  • TypeScript SDK e2e: pass
  • Rust core e2e (if applicable): pass
  • packages/python/e2e-attestations/<branch>.json receipt written if packages/python changed (just e2e-attest-python)
  • packages/ts/e2e-attestations/<branch>.json receipt written if packages/ts changed (just e2e-attest-ts)
  • Command(s) run: cargo test --manifest-path packages/rust/Cargo.toml --features cli --lib, ... --tests, just e2e-attest-python, just e2e-attest-ts, just preflight
  • Result summary: rust unit 894 passed; rust integration + e2e all binaries green; python e2e 38 passed; ts e2e 17 passed (5 files); preflight 0 failing pairs (rust mutation: 11 mutants, all caught).

Changelog / Migrations

  • Changelog fragment added under <root>/<pkg>/changelog.d/ for each changed package (packages/rust/changelog.d/2026-09-23-projection-column-order.md)
  • Migration fragment added under <root>/<pkg>/migrations.d/ (packages/rust/migrations.d/2026-09-23-projection-column-order.md — output key order changes for consumers who relied on the alphabetical order)

Parity

Introduces drift: query_ordered / QueryResult exist in Rust only.
PARITY.md updated; follow-ups filed as #1173 (Python) and #1174 (TypeScript).

Thread the statement's column order out of the query path and serialize
each row against it, instead of re-deriving the column set from the
unordered row maps.
@thekevinscott
thekevinscott merged commit ad02e1e into main Sep 24, 2026
82 checks passed
@thekevinscott
thekevinscott deleted the claude/1170-projection-order branch September 24, 2026 01:47
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.

Column order is alphabetical instead of projection order

2 participants