0001-Further-fix-for-EvalPlanQual-with-mix-of-local-and-f.patch
application/octet-stream
Filename: 0001-Further-fix-for-EvalPlanQual-with-mix-of-local-and-f.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Series: patch 0001
Subject: Further fix for EvalPlanQual with mix of local and foreign partitions.
| File | + | − |
|---|---|---|
| src/backend/executor/nodeForeignscan.c | 23 | 3 |
From 8e6fa6f36ba2a2ffd1189d3c30ca10fb37333557 Mon Sep 17 00:00:00 2001
From: Etsuro Fujita <etsuro.fujita@gmail.com>
Date: Tue, 1 Feb 2022 17:45:15 +0900
Subject: [PATCH] Further fix for EvalPlanQual with mix of local and foreign
partitions.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
We assume that direct-modify ForeignScan nodes cannot be re-evaluated
during EvalPlanQual processing, but the rework for inherited
UPDATE/DELETE in commit 86dc90056 changed things, without considering
this, so that there can be such ForeignScan nodes in the EvalPlanQual
subtree if the inheritance set contains foreign targets. Commit
c3928b467 modified nodeForeignScan.c to avoid re-evaluating such
ForeignScan nodes during EvalPlanQual processing, but the assumption
made there that ExecForeignScan() should never be called for such
ForeignScan nodes during EvalPlanQual processing was wrong in the case
of an UPDATE/DELETE on a partitioned table with a foreign partition as
the first child of it, leading to a segmentation fault or an “cannot
re-evaluate a Foreign Update or Delete during EvalPlanQual” error.
Fix by modifying nodeForeignScan.c further to avoid re-evaluating such
ForeignScan nodes even in ExecForeignScan()/ExecReScanForeignScan()
during EvalPlanQual processing.
Per bug #17355 from Alexander Lakhin. Back-patch to v14 where both
commits came in.
Patch by me, tested by Alexander Lakhin.
Discussion: https://postgr.es/m/17355-de8e362eb7001a96@postgresql.org
---
src/backend/executor/nodeForeignscan.c | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c
index c22d0e7651..cc5c180fb0 100644
--- a/src/backend/executor/nodeForeignscan.c
+++ b/src/backend/executor/nodeForeignscan.c
@@ -121,6 +121,15 @@ static TupleTableSlot *
ExecForeignScan(PlanState *pstate)
{
ForeignScanState *node = castNode(ForeignScanState, pstate);
+ ForeignScan *plan = (ForeignScan *) node->ss.ps.plan;
+ EState *estate = node->ss.ps.state;
+
+ /*
+ * Ignore direct modifications when EvalPlanQual is active --- they are
+ * irrelevant for EvalPlanQual rechecking
+ */
+ if (estate->es_epq_active != NULL && plan->operation != CMD_SELECT)
+ return NULL;
return ExecScan(&node->ss,
(ExecScanAccessMtd) ForeignNext,
@@ -265,9 +274,11 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
{
/*
* Direct modifications cannot be re-evaluated by EvalPlanQual, so
- * don't bother preparing the FDW. There can be ForeignScan nodes in
- * the EvalPlanQual subtree, but ExecForeignScan should never be
- * called on them when EvalPlanQual is active.
+ * don't bother preparing the FDW. In case of an inherited
+ * UPDATE/DELETE with foreign targets there can be direct-modify
+ * ForeignScan nodes in the EvalPlanQual subtree, however, so we need
+ * to ignore such ForeignScan nodes during EvalPlanQual processing.
+ * See ExecForeignScan/ExecReScanForeignScan.
*/
if (estate->es_epq_active == NULL)
fdwroutine->BeginDirectModify(scanstate, eflags);
@@ -321,8 +332,17 @@ ExecEndForeignScan(ForeignScanState *node)
void
ExecReScanForeignScan(ForeignScanState *node)
{
+ ForeignScan *plan = (ForeignScan *) node->ss.ps.plan;
+ EState *estate = node->ss.ps.state;
PlanState *outerPlan = outerPlanState(node);
+ /*
+ * Ignore direct modifications when EvalPlanQual is active --- they are
+ * irrelevant for EvalPlanQual rechecking
+ */
+ if (estate->es_epq_active != NULL && plan->operation != CMD_SELECT)
+ return;
+
node->fdwroutine->ReScanForeignScan(node);
/*
--
2.14.3 (Apple Git-98)