Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d5f788b

Browse filesBrowse files
committed
Expand comments and add an assertion in nodeModifyTable.c.
Most comments concern RELKIND_VIEW. One addresses the ExecUpdate() "tupleid" parameter. A later commit will rely on these facts, but they hold already. Back-patch to v12 (all supported versions), the plan for that commit. Reviewed (in an earlier version) by Robert Haas. Discussion: https://postgr.es/m/20240512232923.aa.nmisch@google.com
1 parent c35f419 commit d5f788b
Copy full SHA for d5f788b

File tree

1 file changed

+41
-29
lines changed
Filter options

1 file changed

+41
-29
lines changed

‎src/backend/executor/nodeModifyTable.c

Copy file name to clipboardExpand all lines: src/backend/executor/nodeModifyTable.c
+41-29Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@
2424
* values plus row-locating info for UPDATE and MERGE cases, or just the
2525
* row-locating info for DELETE cases.
2626
*
27+
* The relation to modify can be an ordinary table, a view having an
28+
* INSTEAD OF trigger, or a foreign table. Earlier processing already
29+
* pointed ModifyTable to the underlying relations of any automatically
30+
* updatable view not using an INSTEAD OF trigger, so code here can
31+
* assume it won't have one as a modification target. This node does
32+
* process ri_WithCheckOptions, which may have expressions from those
33+
* automatically updatable views.
34+
*
2735
* MERGE runs a join between the source relation and the target table.
2836
* If any WHEN NOT MATCHED [BY TARGET] clauses are present, then the join
2937
* is an outer join that might output tuples without a matching target
@@ -1398,18 +1406,18 @@ ExecDeleteEpilogue(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
13981406
* DELETE is like UPDATE, except that we delete the tuple and no
13991407
* index modifications are needed.
14001408
*
1401-
* When deleting from a table, tupleid identifies the tuple to
1402-
* delete and oldtuple is NULL. When deleting from a view,
1403-
* oldtuple is passed to the INSTEAD OF triggers and identifies
1404-
* what to delete, and tupleid is invalid. When deleting from a
1405-
* foreign table, tupleid is invalid; the FDW has to figure out
1406-
* which row to delete using data from the planSlot. oldtuple is
1407-
* passed to foreign table triggers; it is NULL when the foreign
1408-
* table has no relevant triggers. We use tupleDeleted to indicate
1409-
* whether the tuple is actually deleted, callers can use it to
1410-
* decide whether to continue the operation. When this DELETE is a
1411-
* part of an UPDATE of partition-key, then the slot returned by
1412-
* EvalPlanQual() is passed back using output parameter epqreturnslot.
1409+
* When deleting from a table, tupleid identifies the tuple to delete and
1410+
* oldtuple is NULL. When deleting through a view INSTEAD OF trigger,
1411+
* oldtuple is passed to the triggers and identifies what to delete, and
1412+
* tupleid is invalid. When deleting from a foreign table, tupleid is
1413+
* invalid; the FDW has to figure out which row to delete using data from
1414+
* the planSlot. oldtuple is passed to foreign table triggers; it is
1415+
* NULL when the foreign table has no relevant triggers. We use
1416+
* tupleDeleted to indicate whether the tuple is actually deleted,
1417+
* callers can use it to decide whether to continue the operation. When
1418+
* this DELETE is a part of an UPDATE of partition-key, then the slot
1419+
* returned by EvalPlanQual() is passed back using output parameter
1420+
* epqreturnslot.
14131421
*
14141422
* Returns RETURNING result if any, otherwise NULL.
14151423
* ----------------------------------------------------------------
@@ -2238,21 +2246,22 @@ ExecCrossPartitionUpdateForeignKey(ModifyTableContext *context,
22382246
* is, we don't want to get stuck in an infinite loop
22392247
* which corrupts your database..
22402248
*
2241-
* When updating a table, tupleid identifies the tuple to
2242-
* update and oldtuple is NULL. When updating a view, oldtuple
2243-
* is passed to the INSTEAD OF triggers and identifies what to
2244-
* update, and tupleid is invalid. When updating a foreign table,
2245-
* tupleid is invalid; the FDW has to figure out which row to
2246-
* update using data from the planSlot. oldtuple is passed to
2247-
* foreign table triggers; it is NULL when the foreign table has
2248-
* no relevant triggers.
2249+
* When updating a table, tupleid identifies the tuple to update and
2250+
* oldtuple is NULL. When updating through a view INSTEAD OF trigger,
2251+
* oldtuple is passed to the triggers and identifies what to update, and
2252+
* tupleid is invalid. When updating a foreign table, tupleid is
2253+
* invalid; the FDW has to figure out which row to update using data from
2254+
* the planSlot. oldtuple is passed to foreign table triggers; it is
2255+
* NULL when the foreign table has no relevant triggers.
22492256
*
22502257
* slot contains the new tuple value to be stored.
22512258
* planSlot is the output of the ModifyTable's subplan; we use it
22522259
* to access values from other input tables (for RETURNING),
22532260
* row-ID junk columns, etc.
22542261
*
2255-
* Returns RETURNING result if any, otherwise NULL.
2262+
* Returns RETURNING result if any, otherwise NULL. On exit, if tupleid
2263+
* had identified the tuple to update, it will identify the tuple
2264+
* actually updated after EvalPlanQual.
22562265
* ----------------------------------------------------------------
22572266
*/
22582267
static TupleTableSlot *
@@ -2717,10 +2726,10 @@ ExecMerge(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
27172726

27182727
/*-----
27192728
* If we are dealing with a WHEN MATCHED case, tupleid or oldtuple is
2720-
* valid, depending on whether the result relation is a table or a view.
2721-
* We execute the first action for which the additional WHEN MATCHED AND
2722-
* quals pass. If an action without quals is found, that action is
2723-
* executed.
2729+
* valid, depending on whether the result relation is a table or a view
2730+
* having an INSTEAD OF trigger. We execute the first action for which
2731+
* the additional WHEN MATCHED AND quals pass. If an action without quals
2732+
* is found, that action is executed.
27242733
*
27252734
* Similarly, in the WHEN NOT MATCHED BY SOURCE case, tupleid or oldtuple
27262735
* is valid, and we look at the given WHEN NOT MATCHED BY SOURCE actions
@@ -2811,8 +2820,8 @@ ExecMerge(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
28112820
* Check and execute the first qualifying MATCHED or NOT MATCHED BY SOURCE
28122821
* action, depending on whether the join quals are satisfied. If the target
28132822
* relation is a table, the current target tuple is identified by tupleid.
2814-
* Otherwise, if the target relation is a view, oldtuple is the current target
2815-
* tuple from the view.
2823+
* Otherwise, if the target relation is a view having an INSTEAD OF trigger,
2824+
* oldtuple is the current target tuple from the view.
28162825
*
28172826
* We start from the first WHEN MATCHED or WHEN NOT MATCHED BY SOURCE action
28182827
* and check if the WHEN quals pass, if any. If the WHEN quals for the first
@@ -2878,8 +2887,11 @@ ExecMergeMatched(ModifyTableContext *context, ResultRelInfo *resultRelInfo,
28782887
*/
28792888
Assert(tupleid != NULL || oldtuple != NULL);
28802889
if (oldtuple != NULL)
2890+
{
2891+
Assert(resultRelInfo->ri_TrigDesc);
28812892
ExecForceStoreHeapTuple(oldtuple, resultRelInfo->ri_oldTupleSlot,
28822893
false);
2894+
}
28832895
else if (!table_tuple_fetch_row_version(resultRelInfo->ri_RelationDesc,
28842896
tupleid,
28852897
SnapshotAny,
@@ -3992,8 +4004,8 @@ ExecModifyTable(PlanState *pstate)
39924004
* know enough here to set t_tableOid. Quite separately from
39934005
* this, the FDW may fetch its own junk attrs to identify the row.
39944006
*
3995-
* Other relevant relkinds, currently limited to views, always
3996-
* have a wholerow attribute.
4007+
* Other relevant relkinds, currently limited to views having
4008+
* INSTEAD OF triggers, always have a wholerow attribute.
39974009
*/
39984010
else if (AttributeNumberIsValid(resultRelInfo->ri_RowIdAttNo))
39994011
{

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.