pgsql: COPY TO FORMAT JSON: use the query's column names as keys

From: Andrew Dunstan <andrew(at)dunslane(dot)net>
To: pgsql-committers(at)lists(dot)postgresql(dot)org
Subject: pgsql: COPY TO FORMAT JSON: use the query's column names as keys
Date: 2026-10-08 17:41:25
Message-ID: E1xEs7R-00000000qEL-1fLw@gemulon.postgresql.org
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-committers

COPY TO FORMAT JSON: use the query's column names as keys

CopyToJsonOneRow() stamped the row datum with the query's descriptor
only when the slot's descriptor was of type RECORD. A scan that does
not project returns the table's row type, so the keys came from the
table, not the query, losing column aliases and mislabelling rows
from UNION ALL branches with different column orders.

Fix by always using the query's descriptor. For non-virtual slots,
heap_copy_tuple_as_datum() can just be passed that descriptor, so
there is no extra cost. This is safe because a scan skips projection
only when tlist_matches_tupdesc() holds, so the layouts match.

Bug introduced in 7dadd38cda9.

Reported-by: Shihao Zhong <zhong950419(at)gmail(dot)com>
Reviewed-by: Shihao Zhong <zhong950419(at)gmail(dot)com>
Reviewed-by: João Marcelo Detomini <joao(dot)detomini(at)enterprisedb(dot)com>
Discussion: https://postgr.es/m/CAGRkXqQHjxgufHPz86+dxGaQZt37hikduUArYtfbn2_3mryZAw@mail.gmail.com
Backpatch-through: 19

Branch
------
master

Details
-------
https://git.postgresql.org/pg/commitdiff/c652cd3f94d57e69965f065c4ed45708a2b2a757

Modified Files
--------------
src/backend/commands/copyto.c | 40 ++++++++++++++++++++++++++------------
src/test/regress/expected/copy.out | 13 +++++++++++++
src/test/regress/sql/copy.sql | 10 ++++++++++
3 files changed, 51 insertions(+), 12 deletions(-)

Browse pgsql-committers by date

  From Date Subject
Next Message Jacob Champion 2026-10-08 18:02:22 pgsql: oauth_validator: Remove racing GUC check
Previous Message Masahiko Sawada 2026-10-08 17:33:51 pgsql: Stabilize recently added tests in 051_effective_wal_level.pl.