mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
Ensure that whole-row Vars produce nonempty column names.
At one time it wasn't terribly important what column names were associated with the fields of a composite Datum, but since the introduction of operations like row_to_json(), it's important that looking up the rowtype ID embedded in the Datum returns the column names that users would expect. However, that doesn't work terribly well: you could get the column names of the underlying table, or column aliases from any level of the query, depending on minor details of the plan tree. You could even get totally empty field names, which is disastrous for cases like row_to_json(). It seems unwise to change this behavior too much in stable branches, however, since users might not have noticed that they weren't getting the least-unintuitive choice of field names. Therefore, in the back branches, only change the results when the child plan has returned an actually-empty field name. (We assume that can't happen with a named rowtype, so this also dodges the issue of possibly producing RECORD-typed output from a Var with a named composite result type.) As in the sister patch for HEAD, we can get a better name to use from the Var's corresponding RTE. There is no need to touch the RowExpr code since it was already using a copy of the RTE's alias list for RECORD cases. Back-patch as far as 9.2. Before that we did not have row_to_json() so there were no core functions potentially affected by bogus field names. While 9.1 and earlier do have contrib's hstore(record) which is also affected, those versions don't seem to produce empty field names (at least not in the known problem cases), so we'll leave them alone.
This commit is contained in:
@@ -474,3 +474,163 @@ select (row('Jim', 'Beam')).text; -- error
|
||||
ERROR: could not identify column "text" in record data type
|
||||
LINE 1: select (row('Jim', 'Beam')).text;
|
||||
^
|
||||
--
|
||||
-- Test that composite values are seen to have the correct column names
|
||||
-- (bug #11210 and other reports)
|
||||
--
|
||||
select row_to_json(i) from int8_tbl i;
|
||||
row_to_json
|
||||
------------------------------------------------
|
||||
{"q1":123,"q2":456}
|
||||
{"q1":123,"q2":4567890123456789}
|
||||
{"q1":4567890123456789,"q2":123}
|
||||
{"q1":4567890123456789,"q2":4567890123456789}
|
||||
{"q1":4567890123456789,"q2":-4567890123456789}
|
||||
(5 rows)
|
||||
|
||||
select row_to_json(i) from int8_tbl i(x,y);
|
||||
row_to_json
|
||||
------------------------------------------------
|
||||
{"q1":123,"q2":456}
|
||||
{"q1":123,"q2":4567890123456789}
|
||||
{"q1":4567890123456789,"q2":123}
|
||||
{"q1":4567890123456789,"q2":4567890123456789}
|
||||
{"q1":4567890123456789,"q2":-4567890123456789}
|
||||
(5 rows)
|
||||
|
||||
create temp view vv1 as select * from int8_tbl;
|
||||
select row_to_json(i) from vv1 i;
|
||||
row_to_json
|
||||
------------------------------------------------
|
||||
{"q1":123,"q2":456}
|
||||
{"q1":123,"q2":4567890123456789}
|
||||
{"q1":4567890123456789,"q2":123}
|
||||
{"q1":4567890123456789,"q2":4567890123456789}
|
||||
{"q1":4567890123456789,"q2":-4567890123456789}
|
||||
(5 rows)
|
||||
|
||||
select row_to_json(i) from vv1 i(x,y);
|
||||
row_to_json
|
||||
------------------------------------------------
|
||||
{"q1":123,"q2":456}
|
||||
{"q1":123,"q2":4567890123456789}
|
||||
{"q1":4567890123456789,"q2":123}
|
||||
{"q1":4567890123456789,"q2":4567890123456789}
|
||||
{"q1":4567890123456789,"q2":-4567890123456789}
|
||||
(5 rows)
|
||||
|
||||
select row_to_json(ss) from
|
||||
(select q1, q2 from int8_tbl) as ss;
|
||||
row_to_json
|
||||
------------------------------------------------
|
||||
{"q1":123,"q2":456}
|
||||
{"q1":123,"q2":4567890123456789}
|
||||
{"q1":4567890123456789,"q2":123}
|
||||
{"q1":4567890123456789,"q2":4567890123456789}
|
||||
{"q1":4567890123456789,"q2":-4567890123456789}
|
||||
(5 rows)
|
||||
|
||||
select row_to_json(ss) from
|
||||
(select q1, q2 from int8_tbl offset 0) as ss;
|
||||
row_to_json
|
||||
------------------------------------------------
|
||||
{"q1":123,"q2":456}
|
||||
{"q1":123,"q2":4567890123456789}
|
||||
{"q1":4567890123456789,"q2":123}
|
||||
{"q1":4567890123456789,"q2":4567890123456789}
|
||||
{"q1":4567890123456789,"q2":-4567890123456789}
|
||||
(5 rows)
|
||||
|
||||
select row_to_json(ss) from
|
||||
(select q1 as a, q2 as b from int8_tbl) as ss;
|
||||
row_to_json
|
||||
----------------------------------------------
|
||||
{"a":123,"b":456}
|
||||
{"a":123,"b":4567890123456789}
|
||||
{"a":4567890123456789,"b":123}
|
||||
{"a":4567890123456789,"b":4567890123456789}
|
||||
{"a":4567890123456789,"b":-4567890123456789}
|
||||
(5 rows)
|
||||
|
||||
select row_to_json(ss) from
|
||||
(select q1 as a, q2 as b from int8_tbl offset 0) as ss;
|
||||
row_to_json
|
||||
------------------------------------------------
|
||||
{"q1":123,"q2":456}
|
||||
{"q1":123,"q2":4567890123456789}
|
||||
{"q1":4567890123456789,"q2":123}
|
||||
{"q1":4567890123456789,"q2":4567890123456789}
|
||||
{"q1":4567890123456789,"q2":-4567890123456789}
|
||||
(5 rows)
|
||||
|
||||
select row_to_json(ss) from
|
||||
(select q1 as a, q2 as b from int8_tbl) as ss(x,y);
|
||||
row_to_json
|
||||
----------------------------------------------
|
||||
{"x":123,"y":456}
|
||||
{"x":123,"y":4567890123456789}
|
||||
{"x":4567890123456789,"y":123}
|
||||
{"x":4567890123456789,"y":4567890123456789}
|
||||
{"x":4567890123456789,"y":-4567890123456789}
|
||||
(5 rows)
|
||||
|
||||
select row_to_json(ss) from
|
||||
(select q1 as a, q2 as b from int8_tbl offset 0) as ss(x,y);
|
||||
row_to_json
|
||||
------------------------------------------------
|
||||
{"q1":123,"q2":456}
|
||||
{"q1":123,"q2":4567890123456789}
|
||||
{"q1":4567890123456789,"q2":123}
|
||||
{"q1":4567890123456789,"q2":4567890123456789}
|
||||
{"q1":4567890123456789,"q2":-4567890123456789}
|
||||
(5 rows)
|
||||
|
||||
explain (costs off)
|
||||
select row_to_json(q) from
|
||||
(select thousand, tenthous from tenk1
|
||||
where thousand = 42 and tenthous < 2000 offset 0) q;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------
|
||||
Subquery Scan on q
|
||||
-> Index Only Scan using tenk1_thous_tenthous on tenk1
|
||||
Index Cond: ((thousand = 42) AND (tenthous < 2000))
|
||||
(3 rows)
|
||||
|
||||
select row_to_json(q) from
|
||||
(select thousand, tenthous from tenk1
|
||||
where thousand = 42 and tenthous < 2000 offset 0) q;
|
||||
row_to_json
|
||||
---------------------------------
|
||||
{"thousand":42,"tenthous":42}
|
||||
{"thousand":42,"tenthous":1042}
|
||||
(2 rows)
|
||||
|
||||
select row_to_json(q) from
|
||||
(select thousand as x, tenthous as y from tenk1
|
||||
where thousand = 42 and tenthous < 2000 offset 0) q;
|
||||
row_to_json
|
||||
-------------------
|
||||
{"x":42,"y":42}
|
||||
{"x":42,"y":1042}
|
||||
(2 rows)
|
||||
|
||||
select row_to_json(q) from
|
||||
(select thousand as x, tenthous as y from tenk1
|
||||
where thousand = 42 and tenthous < 2000 offset 0) q(a,b);
|
||||
row_to_json
|
||||
-------------------
|
||||
{"a":42,"b":42}
|
||||
{"a":42,"b":1042}
|
||||
(2 rows)
|
||||
|
||||
create temp table tt1 as select * from int8_tbl limit 2;
|
||||
create temp table tt2 () inherits(tt1);
|
||||
insert into tt2 values(0,0);
|
||||
select row_to_json(r) from (select q2,q1 from tt1 offset 0) r;
|
||||
row_to_json
|
||||
----------------------------------
|
||||
{"q2":456,"q1":123}
|
||||
{"q2":4567890123456789,"q1":123}
|
||||
{"q2":0,"q1":0}
|
||||
(3 rows)
|
||||
|
||||
|
@@ -227,3 +227,47 @@ select cast (row('Jim', 'Beam') as text);
|
||||
select (row('Jim', 'Beam'))::text;
|
||||
select text(row('Jim', 'Beam')); -- error
|
||||
select (row('Jim', 'Beam')).text; -- error
|
||||
|
||||
--
|
||||
-- Test that composite values are seen to have the correct column names
|
||||
-- (bug #11210 and other reports)
|
||||
--
|
||||
|
||||
select row_to_json(i) from int8_tbl i;
|
||||
select row_to_json(i) from int8_tbl i(x,y);
|
||||
|
||||
create temp view vv1 as select * from int8_tbl;
|
||||
select row_to_json(i) from vv1 i;
|
||||
select row_to_json(i) from vv1 i(x,y);
|
||||
|
||||
select row_to_json(ss) from
|
||||
(select q1, q2 from int8_tbl) as ss;
|
||||
select row_to_json(ss) from
|
||||
(select q1, q2 from int8_tbl offset 0) as ss;
|
||||
select row_to_json(ss) from
|
||||
(select q1 as a, q2 as b from int8_tbl) as ss;
|
||||
select row_to_json(ss) from
|
||||
(select q1 as a, q2 as b from int8_tbl offset 0) as ss;
|
||||
select row_to_json(ss) from
|
||||
(select q1 as a, q2 as b from int8_tbl) as ss(x,y);
|
||||
select row_to_json(ss) from
|
||||
(select q1 as a, q2 as b from int8_tbl offset 0) as ss(x,y);
|
||||
|
||||
explain (costs off)
|
||||
select row_to_json(q) from
|
||||
(select thousand, tenthous from tenk1
|
||||
where thousand = 42 and tenthous < 2000 offset 0) q;
|
||||
select row_to_json(q) from
|
||||
(select thousand, tenthous from tenk1
|
||||
where thousand = 42 and tenthous < 2000 offset 0) q;
|
||||
select row_to_json(q) from
|
||||
(select thousand as x, tenthous as y from tenk1
|
||||
where thousand = 42 and tenthous < 2000 offset 0) q;
|
||||
select row_to_json(q) from
|
||||
(select thousand as x, tenthous as y from tenk1
|
||||
where thousand = 42 and tenthous < 2000 offset 0) q(a,b);
|
||||
|
||||
create temp table tt1 as select * from int8_tbl limit 2;
|
||||
create temp table tt2 () inherits(tt1);
|
||||
insert into tt2 values(0,0);
|
||||
select row_to_json(r) from (select q2,q1 from tt1 offset 0) r;
|
||||
|
Reference in New Issue
Block a user