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); /*