diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index ca14cdabdd0..bfd3ebc601e 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -880,21 +880,25 @@ InitPlan(QueryDesc *queryDesc, int eflags) foreach(l, plannedstmt->rowMarks) { PlanRowMark *rc = (PlanRowMark *) lfirst(l); + RangeTblEntry *rte = exec_rt_fetch(rc->rti, estate); Oid relid; Relation relation; ExecRowMark *erm; + /* ignore "parent" rowmarks; they are irrelevant at runtime */ + if (rc->isParent) + continue; + /* - * Ignore "parent" rowmarks, because they are irrelevant at - * runtime. Also ignore the rowmarks belonging to child tables - * that have been pruned in ExecDoInitialPruning(). + * Also ignore rowmarks belonging to child tables that have been + * pruned in ExecDoInitialPruning(). */ - if (rc->isParent || + if (rte->rtekind == RTE_RELATION && !bms_is_member(rc->rti, estate->es_unpruned_relids)) continue; /* get relation's OID (will produce InvalidOid if subquery) */ - relid = exec_rt_fetch(rc->rti, estate)->relid; + relid = rte->relid; /* open relation, if we need to access it for this mark type */ switch (rc->markType) diff --git a/src/backend/executor/nodeLockRows.c b/src/backend/executor/nodeLockRows.c index 67bee922a3c..8d865470780 100644 --- a/src/backend/executor/nodeLockRows.c +++ b/src/backend/executor/nodeLockRows.c @@ -344,15 +344,19 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags) foreach(lc, node->rowMarks) { PlanRowMark *rc = lfirst_node(PlanRowMark, lc); + RangeTblEntry *rte = exec_rt_fetch(rc->rti, estate); ExecRowMark *erm; ExecAuxRowMark *aerm; + /* ignore "parent" rowmarks; they are irrelevant at runtime */ + if (rc->isParent) + continue; + /* - * Ignore "parent" rowmarks, because they are irrelevant at runtime. - * Also ignore the rowmarks belonging to child tables that have been + * Also ignore rowmarks belonging to child tables that have been * pruned in ExecDoInitialPruning(). */ - if (rc->isParent || + if (rte->rtekind == RTE_RELATION && !bms_is_member(rc->rti, estate->es_unpruned_relids)) continue; diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 46ff6da8289..7d7411a7056 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -5092,15 +5092,19 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) foreach(l, node->rowMarks) { PlanRowMark *rc = lfirst_node(PlanRowMark, l); + RangeTblEntry *rte = exec_rt_fetch(rc->rti, estate); ExecRowMark *erm; ExecAuxRowMark *aerm; + /* ignore "parent" rowmarks; they are irrelevant at runtime */ + if (rc->isParent) + continue; + /* - * Ignore "parent" rowmarks, because they are irrelevant at runtime. - * Also ignore the rowmarks belonging to child tables that have been + * Also ignore rowmarks belonging to child tables that have been * pruned in ExecDoInitialPruning(). */ - if (rc->isParent || + if (rte->rtekind == RTE_RELATION && !bms_is_member(rc->rti, estate->es_unpruned_relids)) continue; diff --git a/src/test/isolation/expected/eval-plan-qual.out b/src/test/isolation/expected/eval-plan-qual.out index 05fffe0d570..a122047fd2a 100644 --- a/src/test/isolation/expected/eval-plan-qual.out +++ b/src/test/isolation/expected/eval-plan-qual.out @@ -1473,3 +1473,23 @@ step s2pp4: DELETE FROM another_parttbl WHERE a = (SELECT 1); step c1: COMMIT; step s2pp4: <... completed> step c2: COMMIT; + +starting permutation: updateformergevalues mergevalues c1 c2 read +step updateformergevalues: UPDATE accounts SET balance = balance + 100; +step mergevalues: + MERGE INTO accounts + USING (VALUES ('checking', 610), ('savings', 620)) v(accountid, balance) + ON v.accountid = accounts.accountid + WHEN MATCHED THEN UPDATE SET balance = v.balance + WHEN NOT MATCHED THEN INSERT VALUES ('unmatched', -1); + +step c1: COMMIT; +step mergevalues: <... completed> +step c2: COMMIT; +step read: SELECT * FROM accounts ORDER BY accountid; +accountid|balance|balance2 +---------+-------+-------- +checking | 610| 1220 +savings | 620| 1240 +(2 rows) + diff --git a/src/test/isolation/specs/eval-plan-qual.spec b/src/test/isolation/specs/eval-plan-qual.spec index 80e1e6bb307..fb57fb237dd 100644 --- a/src/test/isolation/specs/eval-plan-qual.spec +++ b/src/test/isolation/specs/eval-plan-qual.spec @@ -206,6 +206,8 @@ step sys1 { step s1pp1 { UPDATE another_parttbl SET b = b + 1 WHERE a = 1; } +step updateformergevalues { UPDATE accounts SET balance = balance + 100; } + session s2 setup { BEGIN ISOLATION LEVEL READ COMMITTED; } step wx2 { UPDATE accounts SET balance = balance + 450 WHERE accountid = 'checking' RETURNING balance; } @@ -318,6 +320,14 @@ step s2pp2 { PREPARE epd AS DELETE FROM another_parttbl WHERE a = $1; } step s2pp3 { EXECUTE epd(1); } step s2pp4 { DELETE FROM another_parttbl WHERE a = (SELECT 1); } +step mergevalues { + MERGE INTO accounts + USING (VALUES ('checking', 610), ('savings', 620)) v(accountid, balance) + ON v.accountid = accounts.accountid + WHEN MATCHED THEN UPDATE SET balance = v.balance + WHEN NOT MATCHED THEN INSERT VALUES ('unmatched', -1); +} + session s3 setup { BEGIN ISOLATION LEVEL READ COMMITTED; } step read { SELECT * FROM accounts ORDER BY accountid; } @@ -425,3 +435,6 @@ permutation sys1 sysmerge2 c1 c2 # Exercise run-time partition pruning code in an EPQ recheck permutation s1pp1 s2pp1 s2pp2 s2pp3 c1 c2 permutation s1pp1 s2pp4 c1 c2 + +# test EPQ recheck in MERGE from VALUES_RTE, cf bug #19355 +permutation updateformergevalues mergevalues c1 c2 read