aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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 9eb4d63e1ac..cecd8d9f469 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -73,6 +73,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;
@@ -85,11 +88,19 @@ ExecSubPlan(SubPlanState *node,
if (subplan->setParam != NIL && subplan->subLinkType != MULTIEXPR_SUBLINK)
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;
}
/*
@@ -948,6 +959,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 *pvar;
@@ -961,6 +974,12 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
if (subLinkType == CTE_SUBLINK)
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;
+
/* Initialize ArrayBuildStateAny in caller's context, if needed */
if (subLinkType == ARRAY_SUBLINK)
astate = initArrayResultAny(subplan->firstColType,
@@ -1114,6 +1133,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 4cc40913d2d..7002049eb0d 100644
--- a/src/test/regress/expected/subselect.out
+++ b/src/test/regress/expected/subselect.out
@@ -913,3 +913,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 a1e726debc9..c12b3ecb6b3 100644
--- a/src/test/regress/sql/subselect.sql
+++ b/src/test/regress/sql/subselect.sql
@@ -491,3 +491,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;