fix-EPQ-handling-for-direct-modifications.patch

application/octet-stream

Filename: fix-EPQ-handling-for-direct-modifications.patch
Type: application/octet-stream
Part: 0
Message: Re: BUG #17355: Server crashes on ExecReScanForeignScan in postgres_fdw when accessing foreign partition

Patch

Format: unified
File+
src/backend/executor/nodeForeignscan.c 23 3
diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c
index c22d0e7651..a3ad1e4f3c 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 there can be ForeignScan nodes doing direct
+		 * modifications in the EvalPlanQual subtree, however, so we ignore
+		 * those ForeignScan nodes when doing an EvalPlanQual recheck.  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);
 
 	/*