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
This commit is contained in:
Tom Lane 2022-05-09 14:15:37 -04:00
parent c0406fa768
commit 539f8c563c
3 changed files with 19 additions and 14 deletions

View File

@ -1347,7 +1347,7 @@ static Query *
transformValuesClause(ParseState *pstate, SelectStmt *stmt) transformValuesClause(ParseState *pstate, SelectStmt *stmt)
{ {
Query *qry = makeNode(Query); Query *qry = makeNode(Query);
List *exprsLists; List *exprsLists = NIL;
List *coltypes = NIL; List *coltypes = NIL;
List *coltypmods = NIL; List *coltypmods = NIL;
List *colcollations = NIL; List *colcollations = NIL;
@ -1432,6 +1432,9 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
/* Release sub-list's cells to save memory */ /* Release sub-list's cells to save memory */
list_free(sublist); list_free(sublist);
/* Prepare an exprsLists element for this row */
exprsLists = lappend(exprsLists, NIL);
} }
/* /*
@ -1486,25 +1489,15 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
/* /*
* Finally, rearrange the coerced expressions into row-organized lists. * Finally, rearrange the coerced expressions into row-organized lists.
*/ */
exprsLists = NIL; for (i = 0; i < sublist_length; i++)
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++)
{ {
forboth(lc, colexprs[i], lc2, exprsLists) forboth(lc, colexprs[i], lc2, exprsLists)
{ {
Node *col = (Node *) lfirst(lc); Node *col = (Node *) lfirst(lc);
List *sublist = lfirst(lc2); List *sublist = lfirst(lc2);
/* sublist pointer in exprsLists won't need adjustment */ sublist = lappend(sublist, col);
(void) lappend(sublist, col); lfirst(lc2) = sublist;
} }
list_free(colexprs[i]); list_free(colexprs[i]);
} }

View File

@ -517,6 +517,13 @@ TABLE int8_tbl;
4567890123456789 | -4567890123456789 4567890123456789 | -4567890123456789
(9 rows) (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 -- Test ORDER BY options
-- --

View File

@ -148,6 +148,11 @@ SELECT 2+2, 57
UNION ALL UNION ALL
TABLE int8_tbl; 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 -- Test ORDER BY options
-- --