diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/executor/nodeValuesscan.c | 21 | ||||
-rw-r--r-- | src/test/regress/expected/subselect.out | 30 | ||||
-rw-r--r-- | src/test/regress/sql/subselect.sql | 10 |
3 files changed, 56 insertions, 5 deletions
diff --git a/src/backend/executor/nodeValuesscan.c b/src/backend/executor/nodeValuesscan.c index d49a4733865..def7926ecb8 100644 --- a/src/backend/executor/nodeValuesscan.c +++ b/src/backend/executor/nodeValuesscan.c @@ -91,6 +91,7 @@ ValuesNext(ValuesScanState *node) if (exprlist) { MemoryContext oldContext; + List *oldsubplans; List *exprstatelist; Datum *values; bool *isnull; @@ -113,12 +114,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 = (List *) ExecInitExpr((Expr *) exprlist, NULL); + oldsubplans = node->ss.ps.subPlan; + node->ss.ps.subPlan = NIL; + + exprstatelist = (List *) ExecInitExpr((Expr *) 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 01c91308f33..7532c272a52 100644 --- a/src/test/regress/expected/subselect.out +++ b/src/test/regress/expected/subselect.out @@ -711,6 +711,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 56707e26bbf..81cf79928b3 100644 --- a/src/test/regress/sql/subselect.sql +++ b/src/test/regress/sql/subselect.sql @@ -413,6 +413,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) |