Skip to content

fix(pgwire): keep the planner's output keys on the extended protocol - #345

Closed
EnRaiha wants to merge 1 commit into
mainfrom
fix/issue337-duplicate-columns
Closed

EnRaiha wants to merge 1 commit into
mainfrom
fix/issue337-duplicate-columns

Conversation

@EnRaiha

@EnRaiha EnRaiha commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Why

Over Parse/Bind/Execute (extended protocol), two output columns sharing a name render the same cell: SELECT w.id, b.id … returns (w1, w1) and SELECT nextval('s'), nextval('s') returns (1, 1).

The Describe phase built its OutputSchema with lookup_key = display_name = field name (prepared/execute.rs:136-149), and the execute path replaced the planner's columns with it (routing/execute.rs:153-160). Rows are written under the unique keys cell_keys derives (id, id_1), so the second column's cell was never read. Simple query has been correct since the derived-key work.

Fixes #337.

What

  • Merge instead of replace: lookup_key comes from the planner's build_output_schema — the single derivation that runs cell_keys; the announced schema supplies display_name, ty, and is_star; cp_computed stays the planner's.
  • An announced arity that disagrees with the plan keeps the announced columns but derives their keys with cell_keys, so the reader still agrees with the row writer.
  • effective_output_schema is private, unit-tested in place; no signature or public-API change.

Validation

  • Wire (extended protocol) on the harness: SELECT 1 AS id, 2 AS id → (1, 2); SELECT w.id, b.id FROM w JOIN b … → (w1, b1). Both cases fail on the current main (red: left: 1, right: 2; the join case reports error retrieving column 0) and pass with the fix (green).
  • cargo check -p nodedb --all-targets — clean.
  • cargo test -p nodedb --lib routing::execute — pass (merge keeps the planner keys; arity mismatch derives announced keys).
  • rustfmt clean; the repository preflight passes (test attributes +2).

Notes

  • Presentation-only: no authorization, redaction, or audit change; display names, types, and result formats are unchanged.

The Describe phase built its OutputSchema with lookup_key equal to the field
name, and the execute path replaced the planner's columns with it. Two output
columns sharing a name then read the same cell: rows are written under the
unique keys cell_keys derives (id, id_1), so the second column never saw its
own value on Parse/Bind/Execute while simple query stayed correct.

Merge instead of replace: lookup keys come from the planner, the one
derivation that runs cell_keys; the announced schema supplies the
client-facing display names and catalog types. An announced arity that
disagrees with the plan keeps the announced columns but derives their keys
with cell_keys so reader and writer still agree.

Tests: unit coverage for the merge (duplicate names keep id/id_1; arity
mismatch falls back to derived keys) and two wire cases — SELECT 1 AS id,
2 AS id and a w/b join of bare ids — each asserting its own cell on the
prepared path.
Copilot AI lite review requested due to automatic review settings September 19, 2026 04:41

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@farhan-syah

Copy link
Copy Markdown
Member

Closing: right behaviour, wrong place.

The producer is prepared/execute.rs — the Describe phase builds lookup_key: f.name() instead of deriving keys with cell_keys(names). Fix that one site and the existing replace-at-execute stays correct. The 40-line downstream merge is not needed; its arity-mismatch branch already is the producer fix. Resubmit as the producer fix plus the wire test.

@farhan-syah
farhan-syah deleted the fix/issue337-duplicate-columns branch September 23, 2026 01:41
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.

pgwire extended protocol collapses duplicate output column names to one cell

3 participants