aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/executor/nodeValuesscan.c21
-rw-r--r--src/test/regress/expected/subselect.out30
-rw-r--r--src/test/regress/sql/subselect.sql10
3 files changed, 56 insertions, 5 deletions
diff --git a/src/backend/executor/nodeValuesscan.c b/src/backend/executor/nodeValuesscan.c
index 1a72bfe1600..47ba9faa78e 100644
--- a/src/backend/executor/nodeValuesscan.c
+++ b/src/backend/executor/nodeValuesscan.c
@@ -92,6 +92,7 @@ ValuesNext(ValuesScanState *node)
if (exprlist)
{
MemoryContext oldContext;
+ List *oldsubplans;
List *exprstatelist;
Datum *values;
bool *isnull;
@@ -114,12 +115,22 @@ ValuesNext(ValuesScanState *node)
oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
/*
- * Pass NULL, not my plan node, because we don't want anything in this
- * transient state linking into permanent state. The only possibility
- * is a SubPlan, and there shouldn't be any (any subselects in the
- * VALUES list should be InitPlans).
+ * The expressions might contain SubPlans (this is currently only
+ * possible if there's a sub-select containing a LATERAL reference,
+ * otherwise sub-selects in a VALUES list should be InitPlans). Those
+ * subplans will want to hook themselves into our subPlan list, which
+ * would result in a corrupted list after we delete the eval state. We
+ * can work around this by saving and restoring the subPlan list.
+ * (There's no need for the functionality that would be enabled by
+ * having the list entries, since the SubPlans aren't going to be
+ * re-executed anyway.)
*/
- exprstatelist = ExecInitExprList(exprlist, NULL);
+ oldsubplans = node->ss.ps.subPlan;
+ node->ss.ps.subPlan = NIL;
+
+ exprstatelist = ExecInitExprList(exprlist, &node->ss.ps);
+
+ node->ss.ps.subPlan = oldsubplans;
/* parser should have checked all sublists are the same length */
Assert(list_length(exprstatelist) == slot->tts_tupleDescriptor->natts);
diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out
index 992d29bb860..4b893856cfc 100644
--- a/src/test/regress/expected/subselect.out
+++ b/src/test/regress/expected/subselect.out
@@ -841,6 +841,36 @@ select exists(select * from nocolumns);
(1 row)
--
+-- Check behavior with a SubPlan in VALUES (bug #14924)
+--
+select val.x
+ from generate_series(1,10) as s(i),
+ lateral (
+ values ((select s.i + 1)), (s.i + 101)
+ ) as val(x)
+where s.i < 10 and (select val.x) < 110;
+ x
+-----
+ 2
+ 102
+ 3
+ 103
+ 4
+ 104
+ 5
+ 105
+ 6
+ 106
+ 7
+ 107
+ 8
+ 108
+ 9
+ 109
+ 10
+(17 rows)
+
+--
-- Check sane behavior with nested IN SubLinks
--
explain (verbose, costs off)
diff --git a/src/test/regress/sql/subselect.sql b/src/test/regress/sql/subselect.sql
index 0d2dd2f1d81..0100367b8d7 100644
--- a/src/test/regress/sql/subselect.sql
+++ b/src/test/regress/sql/subselect.sql
@@ -473,6 +473,16 @@ create temp table nocolumns();
select exists(select * from nocolumns);
--
+-- Check behavior with a SubPlan in VALUES (bug #14924)
+--
+select val.x
+ from generate_series(1,10) as s(i),
+ lateral (
+ values ((select s.i + 1)), (s.i + 101)
+ ) as val(x)
+where s.i < 10 and (select val.x) < 110;
+
+--
-- Check sane behavior with nested IN SubLinks
--
explain (verbose, costs off)