Fix core dump in transformValuesClause when there are no columns.
authorTom Lane
Mon, 9 May 2022 18:15:37 +0000 (14:15 -0400)
committerTom Lane
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 8a47b854d40308cf7d28c7f881ef4035cf236afe..a309dc36665b4cab5bf97c28f6c054ceccc05838 100644 (file)
@@ -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]);
    }
index c441049f4131c99cf9721021df867890a703eafd..6dcd4fa8f32fbc841065f367227000e57c69ddb9 100644 (file)
@@ -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
 --
index b5929b2eca68655bbc73339be54d5ed9a7b4aba6..d6f42aa0d414fd55c10dd4efb73b9f2d3319b892 100644 (file)
@@ -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
 --