diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2019-08-19 18:00:57 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2019-08-19 18:01:09 -0400 |
commit | e136a0d8ca31d1c94b3f2868ae0e735b8d9ff12f (patch) | |
tree | bae78325c357333fe05a63a8f1d3fb8d96e0e4b7 /src/test | |
parent | 4c01a1110388661d8752fee35e9c5614aa4a2d32 (diff) |
Restore json{b}_populate_record{set}'s ability to take type info from AS.
If the record argument is NULL and has no declared type more concrete
than RECORD, we can't extract useful information about the desired
rowtype from it. In this case, see if we're in FROM with an AS clause,
and if so extract the needed rowtype info from AS.
It worked like this before v11, but commit 37a795a60 removed the
behavior, reasoning that it was undocumented, inefficient, and utterly
not self-consistent. If you want to take type info from an AS clause,
you should be using the json_to_record() family of functions not the
json_populate_record() family. Also, it was already the case that
the "populate" functions would fail for a null-valued RECORD input
(with an unfriendly "record type has not been registered" error)
when there wasn't an AS clause at hand, and it wasn't obvious that
that behavior wasn't OK when there was one. However, it emerges
that some people were depending on this to work, and indeed the
rather off-point error message you got if you left off AS encouraged
slapping on AS without switching to the json_to_record() family.
Hence, put back the fallback behavior of looking for AS. While at it,
improve the run-time error you get when there's no place to obtain type
info; we can do a lot better than "record type has not been registered".
(We can't, unfortunately, easily improve the parse-time error message
that leads people down this path in the first place.)
While at it, I refactored the code a bit to avoid duplicating the
same logic in several different places.
Per bug #15940 from Jaroslav Sivy. Back-patch to v11 where the
current coding came in. (The pre-v11 deficiencies in this area
aren't regressions, so we'll leave those branches alone.)
Patch by me, based on preliminary analysis by Dmitry Dolgov.
Discussion: https://postgr.es/m/15940-2ab76dc58ffb85b6@postgresql.org
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/regress/expected/json.out | 29 | ||||
-rw-r--r-- | src/test/regress/expected/jsonb.out | 29 | ||||
-rw-r--r-- | src/test/regress/sql/json.sql | 6 | ||||
-rw-r--r-- | src/test/regress/sql/jsonb.sql | 6 |
4 files changed, 64 insertions, 6 deletions
diff --git a/src/test/regress/expected/json.out b/src/test/regress/expected/json.out index 5b8e67784f5..69b0a6ee6d6 100644 --- a/src/test/regress/expected/json.out +++ b/src/test/regress/expected/json.out @@ -1744,13 +1744,21 @@ SELECT rec FROM json_populate_record( -- anonymous record type SELECT json_populate_record(null::record, '{"x": 0, "y": 1}'); -ERROR: record type has not been registered +ERROR: could not determine row type for result of json_populate_record +HINT: Provide a non-null record argument, or call the function in the FROM clause using a column definition list. SELECT json_populate_record(row(1,2), '{"f1": 0, "f2": 1}'); json_populate_record ---------------------- (0,1) (1 row) +SELECT * FROM + json_populate_record(null::record, '{"x": 776}') AS (x int, y int); + x | y +-----+--- + 776 | +(1 row) + -- composite domain SELECT json_populate_record(null::j_ordered_pair, '{"x": 0, "y": 1}'); json_populate_record @@ -1834,7 +1842,8 @@ select * from json_populate_recordset(row('def',99,null)::jpop,'[{"a":[100,200,3 -- anonymous record type SELECT json_populate_recordset(null::record, '[{"x": 0, "y": 1}]'); -ERROR: record type has not been registered +ERROR: could not determine row type for result of json_populate_recordset +HINT: Provide a non-null record argument, or call the function in the FROM clause using a column definition list. SELECT json_populate_recordset(row(1,2), '[{"f1": 0, "f2": 1}]'); json_populate_recordset ------------------------- @@ -1851,9 +1860,17 @@ FROM (VALUES (1),(2)) v(i); 2 | (2,43) (4 rows) +SELECT * FROM + json_populate_recordset(null::record, '[{"x": 776}]') AS (x int, y int); + x | y +-----+--- + 776 | +(1 row) + -- empty array is a corner case SELECT json_populate_recordset(null::record, '[]'); -ERROR: record type has not been registered +ERROR: could not determine row type for result of json_populate_recordset +HINT: Provide a non-null record argument, or call the function in the FROM clause using a column definition list. SELECT json_populate_recordset(row(1,2), '[]'); json_populate_recordset ------------------------- @@ -1864,6 +1881,12 @@ SELECT * FROM json_populate_recordset(NULL::jpop,'[]') q; ---+---+--- (0 rows) +SELECT * FROM + json_populate_recordset(null::record, '[]') AS (x int, y int); + x | y +---+--- +(0 rows) + -- composite domain SELECT json_populate_recordset(null::j_ordered_pair, '[{"x": 0, "y": 1}]'); json_populate_recordset diff --git a/src/test/regress/expected/jsonb.out b/src/test/regress/expected/jsonb.out index 469079c5d8f..0f917557942 100644 --- a/src/test/regress/expected/jsonb.out +++ b/src/test/regress/expected/jsonb.out @@ -2433,13 +2433,21 @@ SELECT rec FROM jsonb_populate_record( -- anonymous record type SELECT jsonb_populate_record(null::record, '{"x": 0, "y": 1}'); -ERROR: record type has not been registered +ERROR: could not determine row type for result of jsonb_populate_record +HINT: Provide a non-null record argument, or call the function in the FROM clause using a column definition list. SELECT jsonb_populate_record(row(1,2), '{"f1": 0, "f2": 1}'); jsonb_populate_record ----------------------- (0,1) (1 row) +SELECT * FROM + jsonb_populate_record(null::record, '{"x": 776}') AS (x int, y int); + x | y +-----+--- + 776 | +(1 row) + -- composite domain SELECT jsonb_populate_record(null::jb_ordered_pair, '{"x": 0, "y": 1}'); jsonb_populate_record @@ -2516,7 +2524,8 @@ SELECT * FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"a":[100,200 -- anonymous record type SELECT jsonb_populate_recordset(null::record, '[{"x": 0, "y": 1}]'); -ERROR: record type has not been registered +ERROR: could not determine row type for result of jsonb_populate_recordset +HINT: Provide a non-null record argument, or call the function in the FROM clause using a column definition list. SELECT jsonb_populate_recordset(row(1,2), '[{"f1": 0, "f2": 1}]'); jsonb_populate_recordset -------------------------- @@ -2533,9 +2542,17 @@ FROM (VALUES (1),(2)) v(i); 2 | (2,43) (4 rows) +SELECT * FROM + jsonb_populate_recordset(null::record, '[{"x": 776}]') AS (x int, y int); + x | y +-----+--- + 776 | +(1 row) + -- empty array is a corner case SELECT jsonb_populate_recordset(null::record, '[]'); -ERROR: record type has not been registered +ERROR: could not determine row type for result of jsonb_populate_recordset +HINT: Provide a non-null record argument, or call the function in the FROM clause using a column definition list. SELECT jsonb_populate_recordset(row(1,2), '[]'); jsonb_populate_recordset -------------------------- @@ -2546,6 +2563,12 @@ SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[]') q; ---+---+--- (0 rows) +SELECT * FROM + jsonb_populate_recordset(null::record, '[]') AS (x int, y int); + x | y +---+--- +(0 rows) + -- composite domain SELECT jsonb_populate_recordset(null::jb_ordered_pair, '[{"x": 0, "y": 1}]'); jsonb_populate_recordset diff --git a/src/test/regress/sql/json.sql b/src/test/regress/sql/json.sql index a52beaa27a1..e0216645923 100644 --- a/src/test/regress/sql/json.sql +++ b/src/test/regress/sql/json.sql @@ -522,6 +522,8 @@ SELECT rec FROM json_populate_record( -- anonymous record type SELECT json_populate_record(null::record, '{"x": 0, "y": 1}'); SELECT json_populate_record(row(1,2), '{"f1": 0, "f2": 1}'); +SELECT * FROM + json_populate_record(null::record, '{"x": 776}') AS (x int, y int); -- composite domain SELECT json_populate_record(null::j_ordered_pair, '{"x": 0, "y": 1}'); @@ -549,11 +551,15 @@ SELECT json_populate_recordset(null::record, '[{"x": 0, "y": 1}]'); SELECT json_populate_recordset(row(1,2), '[{"f1": 0, "f2": 1}]'); SELECT i, json_populate_recordset(row(i,50), '[{"f1":"42"},{"f2":"43"}]') FROM (VALUES (1),(2)) v(i); +SELECT * FROM + json_populate_recordset(null::record, '[{"x": 776}]') AS (x int, y int); -- empty array is a corner case SELECT json_populate_recordset(null::record, '[]'); SELECT json_populate_recordset(row(1,2), '[]'); SELECT * FROM json_populate_recordset(NULL::jpop,'[]') q; +SELECT * FROM + json_populate_recordset(null::record, '[]') AS (x int, y int); -- composite domain SELECT json_populate_recordset(null::j_ordered_pair, '[{"x": 0, "y": 1}]'); diff --git a/src/test/regress/sql/jsonb.sql b/src/test/regress/sql/jsonb.sql index ba870872e80..58703a90b70 100644 --- a/src/test/regress/sql/jsonb.sql +++ b/src/test/regress/sql/jsonb.sql @@ -642,6 +642,8 @@ SELECT rec FROM jsonb_populate_record( -- anonymous record type SELECT jsonb_populate_record(null::record, '{"x": 0, "y": 1}'); SELECT jsonb_populate_record(row(1,2), '{"f1": 0, "f2": 1}'); +SELECT * FROM + jsonb_populate_record(null::record, '{"x": 776}') AS (x int, y int); -- composite domain SELECT jsonb_populate_record(null::jb_ordered_pair, '{"x": 0, "y": 1}'); @@ -665,11 +667,15 @@ SELECT jsonb_populate_recordset(null::record, '[{"x": 0, "y": 1}]'); SELECT jsonb_populate_recordset(row(1,2), '[{"f1": 0, "f2": 1}]'); SELECT i, jsonb_populate_recordset(row(i,50), '[{"f1":"42"},{"f2":"43"}]') FROM (VALUES (1),(2)) v(i); +SELECT * FROM + jsonb_populate_recordset(null::record, '[{"x": 776}]') AS (x int, y int); -- empty array is a corner case SELECT jsonb_populate_recordset(null::record, '[]'); SELECT jsonb_populate_recordset(row(1,2), '[]'); SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[]') q; +SELECT * FROM + jsonb_populate_recordset(null::record, '[]') AS (x int, y int); -- composite domain SELECT jsonb_populate_recordset(null::jb_ordered_pair, '[{"x": 0, "y": 1}]'); |