diff options
author | Noah Misch <noah@leadboat.com> | 2024-06-27 19:21:05 -0700 |
---|---|---|
committer | Noah Misch <noah@leadboat.com> | 2024-06-27 19:21:09 -0700 |
commit | f8135d8b54ff68f0788779d86edd796efc330ff4 (patch) | |
tree | 2f97647f9311233fe42a03e6819565da20ea2c99 /src/backend/executor/nodeModifyTable.c | |
parent | dd8008e8ec956845a3a25060e596994192489f0a (diff) | |
download | postgresql-f8135d8b54ff68f0788779d86edd796efc330ff4.tar.gz postgresql-f8135d8b54ff68f0788779d86edd796efc330ff4.zip |
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
Diffstat (limited to 'src/backend/executor/nodeModifyTable.c')
-rw-r--r-- | src/backend/executor/nodeModifyTable.c | 55 |
1 files changed, 32 insertions, 23 deletions
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 3a1f2ba5eba..27b55334ed4 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -24,6 +24,14 @@ * values plus row-locating info for UPDATE and MERGE cases, or just the * row-locating info for DELETE cases. * + * The relation to modify can be an ordinary table, a view having an + * INSTEAD OF trigger, or a foreign table. Earlier processing already + * pointed ModifyTable to the underlying relations of any automatically + * updatable view not using an INSTEAD OF trigger, so code here can + * assume it won't have one as a modification target. This node does + * process ri_WithCheckOptions, which may have expressions from those + * automatically updatable views. + * * MERGE runs a join between the source relation and the target * table; if any WHEN NOT MATCHED clauses are present, then the * join is an outer join. In this case, any unmatched tuples will @@ -1401,18 +1409,18 @@ ExecDeleteEpilogue(ModifyTableContext *context, ResultRelInfo *resultRelInfo, * DELETE is like UPDATE, except that we delete the tuple and no * index modifications are needed. * - * When deleting from a table, tupleid identifies the tuple to - * delete and oldtuple is NULL. When deleting from a view, - * oldtuple is passed to the INSTEAD OF triggers and identifies - * what to delete, and tupleid is invalid. When deleting from a - * foreign table, tupleid is invalid; the FDW has to figure out - * which row to delete using data from the planSlot. oldtuple is - * passed to foreign table triggers; it is NULL when the foreign - * table has no relevant triggers. We use tupleDeleted to indicate - * whether the tuple is actually deleted, callers can use it to - * decide whether to continue the operation. When this DELETE is a - * part of an UPDATE of partition-key, then the slot returned by - * EvalPlanQual() is passed back using output parameter epqreturnslot. + * When deleting from a table, tupleid identifies the tuple to delete and + * oldtuple is NULL. When deleting through a view INSTEAD OF trigger, + * oldtuple is passed to the triggers and identifies what to delete, and + * tupleid is invalid. When deleting from a foreign table, tupleid is + * invalid; the FDW has to figure out which row to delete using data from + * the planSlot. oldtuple is passed to foreign table triggers; it is + * NULL when the foreign table has no relevant triggers. We use + * tupleDeleted to indicate whether the tuple is actually deleted, + * callers can use it to decide whether to continue the operation. When + * this DELETE is a part of an UPDATE of partition-key, then the slot + * returned by EvalPlanQual() is passed back using output parameter + * epqreturnslot. * * Returns RETURNING result if any, otherwise NULL. * ---------------------------------------------------------------- @@ -2244,21 +2252,22 @@ ExecCrossPartitionUpdateForeignKey(ModifyTableContext *context, * is, we don't want to get stuck in an infinite loop * which corrupts your database.. * - * When updating a table, tupleid identifies the tuple to - * update and oldtuple is NULL. When updating a view, oldtuple - * is passed to the INSTEAD OF triggers and identifies what to - * update, and tupleid is invalid. When updating a foreign table, - * tupleid is invalid; the FDW has to figure out which row to - * update using data from the planSlot. oldtuple is passed to - * foreign table triggers; it is NULL when the foreign table has - * no relevant triggers. + * When updating a table, tupleid identifies the tuple to update and + * oldtuple is NULL. When updating through a view INSTEAD OF trigger, + * oldtuple is passed to the triggers and identifies what to update, and + * tupleid is invalid. When updating a foreign table, tupleid is + * invalid; the FDW has to figure out which row to update using data from + * the planSlot. oldtuple is passed to foreign table triggers; it is + * NULL when the foreign table has no relevant triggers. * * slot contains the new tuple value to be stored. * planSlot is the output of the ModifyTable's subplan; we use it * to access values from other input tables (for RETURNING), * row-ID junk columns, etc. * - * Returns RETURNING result if any, otherwise NULL. + * Returns RETURNING result if any, otherwise NULL. On exit, if tupleid + * had identified the tuple to update, it will identify the tuple + * actually updated after EvalPlanQual. * ---------------------------------------------------------------- */ static TupleTableSlot * @@ -3800,8 +3809,8 @@ ExecModifyTable(PlanState *pstate) * know enough here to set t_tableOid. Quite separately from * this, the FDW may fetch its own junk attrs to identify the row. * - * Other relevant relkinds, currently limited to views, always - * have a wholerow attribute. + * Other relevant relkinds, currently limited to views having + * INSTEAD OF triggers, always have a wholerow attribute. */ else if (AttributeNumberIsValid(resultRelInfo->ri_RowIdAttNo)) { |