summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/executor/nodeSubplan.c26
-rw-r--r--src/test/regress/expected/subselect.out17
-rw-r--r--src/test/regress/sql/subselect.sql16
3 files changed, 57 insertions, 2 deletions
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index 5d02d9420b1..225b323f55e 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -63,6 +63,9 @@ ExecSubPlan(SubPlanState *node,
ExprDoneCond *isDone)
{
SubPlan *subplan = (SubPlan *) node->xprstate.expr;
+ EState *estate = node->planstate->state;
+ ScanDirection dir = estate->es_direction;
+ Datum retval;
/* Set default values for result flags: non-null, not a set result */
*isNull = false;
@@ -75,11 +78,19 @@ ExecSubPlan(SubPlanState *node,
if (subplan->setParam != NIL)
elog(ERROR, "cannot set parent params from subquery");
+ /* Force forward-scan mode for evaluation */
+ estate->es_direction = ForwardScanDirection;
+
/* Select appropriate evaluation strategy */
if (subplan->useHashTable)
- return ExecHashSubPlan(node, econtext, isNull);
+ retval = ExecHashSubPlan(node, econtext, isNull);
else
- return ExecScanSubPlan(node, econtext, isNull);
+ retval = ExecScanSubPlan(node, econtext, isNull);
+
+ /* restore scan direction */
+ estate->es_direction = dir;
+
+ return retval;
}
/*
@@ -906,6 +917,8 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
SubPlan *subplan = (SubPlan *) node->xprstate.expr;
PlanState *planstate = node->planstate;
SubLinkType subLinkType = subplan->subLinkType;
+ EState *estate = planstate->state;
+ ScanDirection dir = estate->es_direction;
MemoryContext oldcontext;
TupleTableSlot *slot;
ListCell *l;
@@ -919,6 +932,12 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
elog(ERROR, "CTE subplans should not be executed via ExecSetParamPlan");
/*
+ * Enforce forward scan direction regardless of caller. It's hard but not
+ * impossible to get here in backward scan, so make it work anyway.
+ */
+ estate->es_direction = ForwardScanDirection;
+
+ /*
* Must switch to per-query memory context.
*/
oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
@@ -1048,6 +1067,9 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
}
MemoryContextSwitchTo(oldcontext);
+
+ /* restore scan direction */
+ estate->es_direction = dir;
}
/*
diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out
index 7532c272a52..5bad96366b6 100644
--- a/src/test/regress/expected/subselect.out
+++ b/src/test/regress/expected/subselect.out
@@ -851,3 +851,20 @@ select nextval('ts1');
11
(1 row)
+--
+-- Ensure that backward scan direction isn't propagated into
+-- expression subqueries (bug #15336)
+--
+begin;
+declare c1 scroll cursor for
+ select * from generate_series(1,4) i
+ where i <> all (values (2),(3));
+move forward all in c1;
+fetch backward all in c1;
+ i
+---
+ 4
+ 1
+(2 rows)
+
+commit;
diff --git a/src/test/regress/sql/subselect.sql b/src/test/regress/sql/subselect.sql
index 81cf79928b3..decfffd3e4b 100644
--- a/src/test/regress/sql/subselect.sql
+++ b/src/test/regress/sql/subselect.sql
@@ -464,3 +464,19 @@ select * from
order by 1;
select nextval('ts1');
+
+--
+-- Ensure that backward scan direction isn't propagated into
+-- expression subqueries (bug #15336)
+--
+
+begin;
+
+declare c1 scroll cursor for
+ select * from generate_series(1,4) i
+ where i <> all (values (2),(3));
+
+move forward all in c1;
+fetch backward all in c1;
+
+commit;