Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f862d57

Browse files
author
Etsuro Fujita
committed
Further fix for EvalPlanQual with mix of local and foreign partitions.
We assume that direct-modify ForeignScan nodes cannot be re-evaluated during EvalPlanQual processing, but the rework for inherited UPDATE/DELETE in commit 86dc900 changed things, without considering that, so that such ForeignScan nodes get called as part of the EvalPlanQual subtree during EvalPlanQual processing in the case of an inherited UPDATE/DELETE where the inheritance set contains foreign target relations. To avoid re-evaluating such ForeignScan nodes during EvalPlanQual processing, commit c3928b4 modified nodeForeignscan.c, but the assumption made there that ExecForeignScan() should never be called for such ForeignScan nodes during EvalPlanQual processing turned out to be wrong in some cases, leading to a segmentation fault or a "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. Since this makes non-reachable the test-and-elog added to ForeignNext() by commit c3928b4 that produced the aforesaid error, convert the test-and-elog to an Assert. Per bug #17355 from Alexander Lakhin. Back-patch to v14 where both commits came in. Patch by me, reviewed and tested by Alexander Lakhin and Amit Langote. Discussion: https://postgr.es/m/17355-de8e362eb7001a96@postgresql.org
1 parent 4b0e37f commit f862d57

File tree

1 file changed

+25
-5
lines changed

1 file changed

+25
-5
lines changed

src/backend/executor/nodeForeignscan.c

+25-5
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ ForeignNext(ForeignScanState *node)
5555
* direct modifications cannot be re-evaluated, so shouldn't get here
5656
* during EvalPlanQual processing
5757
*/
58-
if (estate->es_epq_active != NULL)
59-
elog(ERROR, "cannot re-evaluate a Foreign Update or Delete during EvalPlanQual");
58+
Assert(estate->es_epq_active == NULL);
6059

6160
slot = node->fdwroutine->IterateDirectModify(node);
6261
}
@@ -121,6 +120,15 @@ static TupleTableSlot *
121120
ExecForeignScan(PlanState *pstate)
122121
{
123122
ForeignScanState *node = castNode(ForeignScanState, pstate);
123+
ForeignScan *plan = (ForeignScan *) node->ss.ps.plan;
124+
EState *estate = node->ss.ps.state;
125+
126+
/*
127+
* Ignore direct modifications when EvalPlanQual is active --- they are
128+
* irrelevant for EvalPlanQual rechecking
129+
*/
130+
if (estate->es_epq_active != NULL && plan->operation != CMD_SELECT)
131+
return NULL;
124132

125133
return ExecScan(&node->ss,
126134
(ExecScanAccessMtd) ForeignNext,
@@ -265,9 +273,12 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
265273
{
266274
/*
267275
* Direct modifications cannot be re-evaluated by EvalPlanQual, so
268-
* don't bother preparing the FDW. There can be ForeignScan nodes in
269-
* the EvalPlanQual subtree, but ExecForeignScan should never be
270-
* called on them when EvalPlanQual is active.
276+
* don't bother preparing the FDW.
277+
*
278+
* In case of an inherited UPDATE/DELETE with foreign targets there
279+
* can be direct-modify ForeignScan nodes in the EvalPlanQual subtree,
280+
* so we need to ignore such ForeignScan nodes during EvalPlanQual
281+
* processing. See also ExecForeignScan/ExecReScanForeignScan.
271282
*/
272283
if (estate->es_epq_active == NULL)
273284
fdwroutine->BeginDirectModify(scanstate, eflags);
@@ -321,8 +332,17 @@ ExecEndForeignScan(ForeignScanState *node)
321332
void
322333
ExecReScanForeignScan(ForeignScanState *node)
323334
{
335+
ForeignScan *plan = (ForeignScan *) node->ss.ps.plan;
336+
EState *estate = node->ss.ps.state;
324337
PlanState *outerPlan = outerPlanState(node);
325338

339+
/*
340+
* Ignore direct modifications when EvalPlanQual is active --- they are
341+
* irrelevant for EvalPlanQual rechecking
342+
*/
343+
if (estate->es_epq_active != NULL && plan->operation != CMD_SELECT)
344+
return;
345+
326346
node->fdwroutine->ReScanForeignScan(node);
327347

328348
/*

0 commit comments

Comments
 (0)