diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2022-05-09 14:15:37 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2022-05-09 14:15:37 -0400 |
commit | 91a3a74c65f4094420b28c393ac1d38af8ae4c4a (patch) | |
tree | ad9de71a94f9301ba56f36a18d2d750d7b2a47cb | |
parent | 7f0754bc4c0a0abadcbe02e886e31305c37a7053 (diff) | |
download | postgresql-91a3a74c65f4094420b28c393ac1d38af8ae4c4a.tar.gz postgresql-91a3a74c65f4094420b28c393ac1d38af8ae4c4a.zip |
Fix core dump in transformValuesClause when there are no columns.
The parser code that transformed VALUES from row-oriented to
column-oriented lists failed if there were zero columns.
You can't write that straightforwardly (though probably you
should be able to), but the case can be reached by expanding
a "tab.*" reference to a zero-column table.
Per bug #17477 from Wang Ke. Back-patch to all supported branches.
Discussion: https://postgr.es/m/17477-0af3c6ac6b0a6ae0@postgresql.org
-rw-r--r-- | src/backend/parser/analyze.c | 21 | ||||
-rw-r--r-- | src/test/regress/expected/select.out | 7 | ||||
-rw-r--r-- | src/test/regress/sql/select.sql | 5 |
3 files changed, 19 insertions, 14 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 8a47b854d40..a309dc36665 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -1331,7 +1331,7 @@ static Query * transformValuesClause(ParseState *pstate, SelectStmt *stmt) { Query *qry = makeNode(Query); - List *exprsLists; + List *exprsLists = NIL; List *coltypes = NIL; List *coltypmods = NIL; List *colcollations = NIL; @@ -1415,6 +1415,9 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) /* Release sub-list's cells to save memory */ list_free(sublist); + + /* Prepare an exprsLists element for this row */ + exprsLists = lappend(exprsLists, NIL); } /* @@ -1469,25 +1472,15 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) /* * Finally, rearrange the coerced expressions into row-organized lists. */ - exprsLists = NIL; - foreach(lc, colexprs[0]) - { - Node *col = (Node *) lfirst(lc); - List *sublist; - - sublist = list_make1(col); - exprsLists = lappend(exprsLists, sublist); - } - list_free(colexprs[0]); - for (i = 1; i < sublist_length; i++) + for (i = 0; i < sublist_length; i++) { forboth(lc, colexprs[i], lc2, exprsLists) { Node *col = (Node *) lfirst(lc); List *sublist = lfirst(lc2); - /* sublist pointer in exprsLists won't need adjustment */ - (void) lappend(sublist, col); + sublist = lappend(sublist, col); + lfirst(lc2) = sublist; } list_free(colexprs[i]); } diff --git a/src/test/regress/expected/select.out b/src/test/regress/expected/select.out index c441049f413..6dcd4fa8f32 100644 --- a/src/test/regress/expected/select.out +++ b/src/test/regress/expected/select.out @@ -517,6 +517,13 @@ TABLE int8_tbl; 4567890123456789 | -4567890123456789 (9 rows) +-- corner case: VALUES with no columns +CREATE TEMP TABLE nocols(); +INSERT INTO nocols DEFAULT VALUES; +SELECT * FROM nocols n, LATERAL (VALUES(n.*)) v; +-- +(1 row) + -- -- Test ORDER BY options -- diff --git a/src/test/regress/sql/select.sql b/src/test/regress/sql/select.sql index b5929b2eca6..d6f42aa0d41 100644 --- a/src/test/regress/sql/select.sql +++ b/src/test/regress/sql/select.sql @@ -148,6 +148,11 @@ SELECT 2+2, 57 UNION ALL TABLE int8_tbl; +-- corner case: VALUES with no columns +CREATE TEMP TABLE nocols(); +INSERT INTO nocols DEFAULT VALUES; +SELECT * FROM nocols n, LATERAL (VALUES(n.*)) v; + -- -- Test ORDER BY options -- |