Fix core dump in transformValuesClause when there are no columns.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 9 May 2022 18:15:37 +0000 (14:15 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 9 May 2022 18:15:37 +0000 (14:15 -0400)
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

src/backend/parser/analyze.c
src/test/regress/expected/select.out
src/test/regress/sql/select.sql

index 0144284aa35aadd25c561008c8d9f4f73de6c61f..6b54e8e46df4f448b93d8b437aba49d6d881e479 100644 (file)
@@ -1424,7 +1424,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;
@@ -1508,6 +1508,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);
        }
 
        /*
@@ -1551,17 +1554,7 @@ 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)
                {
@@ -1569,6 +1562,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
                        List       *sublist = lfirst(lc2);
 
                        sublist = lappend(sublist, col);
+                       lfirst(lc2) = sublist;
                }
                list_free(colexprs[i]);
        }
index d7888e44ebafa3ae65476cecb5a71dd2bc7040dc..33a6dceb0e32b95d4a4867a75f5be3156b234cea 100644 (file)
@@ -514,6 +514,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
 --
index aa3d0352046c2fec15b18b771c99990965ab5794..019f1e767398d96ee3208d6b458d91eadd99fe5c 100644 (file)
@@ -143,6 +143,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
 --