aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2022-05-09 14:15:37 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2022-05-09 14:15:37 -0400
commit539f8c563ce70cecb1d45f026015162ca52c7306 (patch)
treec2a8756715db3c7b69e380708d121de3618f601a
parentc0406fa768edd6b9e4bb543b04c871cd80f03934 (diff)
downloadpostgresql-539f8c563ce70cecb1d45f026015162ca52c7306.tar.gz
postgresql-539f8c563ce70cecb1d45f026015162ca52c7306.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.c21
-rw-r--r--src/test/regress/expected/select.out7
-rw-r--r--src/test/regress/sql/select.sql5
3 files changed, 19 insertions, 14 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 21d26cf7dbc..408d4c5b30d 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -1347,7 +1347,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;
@@ -1432,6 +1432,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);
}
/*
@@ -1486,25 +1489,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 7ad1f0bc773..53fda82f77d 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 fdab06d5bc1..0b040abba9e 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
--