]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeModifyTable.c
Make some small planner API cleanups.
[postgresql] / src / backend / executor / nodeModifyTable.c
1 /*-------------------------------------------------------------------------
2  *
3  * nodeModifyTable.c
4  *        routines to handle ModifyTable nodes.
5  *
6  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        src/backend/executor/nodeModifyTable.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 /* INTERFACE ROUTINES
16  *              ExecInitModifyTable - initialize the ModifyTable node
17  *              ExecModifyTable         - retrieve the next tuple from the node
18  *              ExecEndModifyTable      - shut down the ModifyTable node
19  *              ExecReScanModifyTable - rescan the ModifyTable node
20  *
21  *       NOTES
22  *              Each ModifyTable node contains a list of one or more subplans,
23  *              much like an Append node.  There is one subplan per result relation.
24  *              The key reason for this is that in an inherited UPDATE command, each
25  *              result relation could have a different schema (more or different
26  *              columns) requiring a different plan tree to produce it.  In an
27  *              inherited DELETE, all the subplans should produce the same output
28  *              rowtype, but we might still find that different plans are appropriate
29  *              for different child relations.
30  *
31  *              If the query specifies RETURNING, then the ModifyTable returns a
32  *              RETURNING tuple after completing each row insert, update, or delete.
33  *              It must be called again to continue the operation.  Without RETURNING,
34  *              we just loop within the node until all the work is done, then
35  *              return NULL.  This avoids useless call/return overhead.
36  */
37
38 #include "postgres.h"
39
40 #include "access/heapam.h"
41 #include "access/htup_details.h"
42 #include "access/xact.h"
43 #include "catalog/catalog.h"
44 #include "commands/trigger.h"
45 #include "executor/execPartition.h"
46 #include "executor/executor.h"
47 #include "executor/nodeModifyTable.h"
48 #include "foreign/fdwapi.h"
49 #include "miscadmin.h"
50 #include "nodes/nodeFuncs.h"
51 #include "storage/bufmgr.h"
52 #include "storage/lmgr.h"
53 #include "utils/builtins.h"
54 #include "utils/memutils.h"
55 #include "utils/rel.h"
56
57
58 static bool ExecOnConflictUpdate(ModifyTableState *mtstate,
59                                          ResultRelInfo *resultRelInfo,
60                                          ItemPointer conflictTid,
61                                          TupleTableSlot *planSlot,
62                                          TupleTableSlot *excludedSlot,
63                                          EState *estate,
64                                          bool canSetTag,
65                                          TupleTableSlot **returning);
66 static TupleTableSlot *ExecPrepareTupleRouting(ModifyTableState *mtstate,
67                                                 EState *estate,
68                                                 PartitionTupleRouting *proute,
69                                                 ResultRelInfo *targetRelInfo,
70                                                 TupleTableSlot *slot);
71 static ResultRelInfo *getTargetResultRelInfo(ModifyTableState *node);
72 static void ExecSetupChildParentMapForSubplan(ModifyTableState *mtstate);
73 static TupleConversionMap *tupconv_map_for_subplan(ModifyTableState *node,
74                                                 int whichplan);
75
76 /*
77  * Verify that the tuples to be produced by INSERT or UPDATE match the
78  * target relation's rowtype
79  *
80  * We do this to guard against stale plans.  If plan invalidation is
81  * functioning properly then we should never get a failure here, but better
82  * safe than sorry.  Note that this is called after we have obtained lock
83  * on the target rel, so the rowtype can't change underneath us.
84  *
85  * The plan output is represented by its targetlist, because that makes
86  * handling the dropped-column case easier.
87  */
88 static void
89 ExecCheckPlanOutput(Relation resultRel, List *targetList)
90 {
91         TupleDesc       resultDesc = RelationGetDescr(resultRel);
92         int                     attno = 0;
93         ListCell   *lc;
94
95         foreach(lc, targetList)
96         {
97                 TargetEntry *tle = (TargetEntry *) lfirst(lc);
98                 Form_pg_attribute attr;
99
100                 if (tle->resjunk)
101                         continue;                       /* ignore junk tlist items */
102
103                 if (attno >= resultDesc->natts)
104                         ereport(ERROR,
105                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
106                                          errmsg("table row type and query-specified row type do not match"),
107                                          errdetail("Query has too many columns.")));
108                 attr = TupleDescAttr(resultDesc, attno);
109                 attno++;
110
111                 if (!attr->attisdropped)
112                 {
113                         /* Normal case: demand type match */
114                         if (exprType((Node *) tle->expr) != attr->atttypid)
115                                 ereport(ERROR,
116                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
117                                                  errmsg("table row type and query-specified row type do not match"),
118                                                  errdetail("Table has type %s at ordinal position %d, but query expects %s.",
119                                                                    format_type_be(attr->atttypid),
120                                                                    attno,
121                                                                    format_type_be(exprType((Node *) tle->expr)))));
122                 }
123                 else
124                 {
125                         /*
126                          * For a dropped column, we can't check atttypid (it's likely 0).
127                          * In any case the planner has most likely inserted an INT4 null.
128                          * What we insist on is just *some* NULL constant.
129                          */
130                         if (!IsA(tle->expr, Const) ||
131                                 !((Const *) tle->expr)->constisnull)
132                                 ereport(ERROR,
133                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
134                                                  errmsg("table row type and query-specified row type do not match"),
135                                                  errdetail("Query provides a value for a dropped column at ordinal position %d.",
136                                                                    attno)));
137                 }
138         }
139         if (attno != resultDesc->natts)
140                 ereport(ERROR,
141                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
142                                  errmsg("table row type and query-specified row type do not match"),
143                                  errdetail("Query has too few columns.")));
144 }
145
146 /*
147  * ExecProcessReturning --- evaluate a RETURNING list
148  *
149  * resultRelInfo: current result rel
150  * tupleSlot: slot holding tuple actually inserted/updated/deleted
151  * planSlot: slot holding tuple returned by top subplan node
152  *
153  * Note: If tupleSlot is NULL, the FDW should have already provided econtext's
154  * scan tuple.
155  *
156  * Returns a slot holding the result tuple
157  */
158 static TupleTableSlot *
159 ExecProcessReturning(ResultRelInfo *resultRelInfo,
160                                          TupleTableSlot *tupleSlot,
161                                          TupleTableSlot *planSlot)
162 {
163         ProjectionInfo *projectReturning = resultRelInfo->ri_projectReturning;
164         ExprContext *econtext = projectReturning->pi_exprContext;
165
166         /* Make tuple and any needed join variables available to ExecProject */
167         if (tupleSlot)
168                 econtext->ecxt_scantuple = tupleSlot;
169         else
170         {
171                 HeapTuple       tuple;
172
173                 /*
174                  * RETURNING expressions might reference the tableoid column, so
175                  * initialize t_tableOid before evaluating them.
176                  */
177                 Assert(!TupIsNull(econtext->ecxt_scantuple));
178                 tuple = ExecFetchSlotHeapTuple(econtext->ecxt_scantuple, true, NULL);
179                 tuple->t_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
180         }
181         econtext->ecxt_outertuple = planSlot;
182
183         /* Compute the RETURNING expressions */
184         return ExecProject(projectReturning);
185 }
186
187 /*
188  * ExecCheckHeapTupleVisible -- verify heap tuple is visible
189  *
190  * It would not be consistent with guarantees of the higher isolation levels to
191  * proceed with avoiding insertion (taking speculative insertion's alternative
192  * path) on the basis of another tuple that is not visible to MVCC snapshot.
193  * Check for the need to raise a serialization failure, and do so as necessary.
194  */
195 static void
196 ExecCheckHeapTupleVisible(EState *estate,
197                                                   HeapTuple tuple,
198                                                   Buffer buffer)
199 {
200         if (!IsolationUsesXactSnapshot())
201                 return;
202
203         /*
204          * We need buffer pin and lock to call HeapTupleSatisfiesVisibility.
205          * Caller should be holding pin, but not lock.
206          */
207         LockBuffer(buffer, BUFFER_LOCK_SHARE);
208         if (!HeapTupleSatisfiesVisibility(tuple, estate->es_snapshot, buffer))
209         {
210                 /*
211                  * We should not raise a serialization failure if the conflict is
212                  * against a tuple inserted by our own transaction, even if it's not
213                  * visible to our snapshot.  (This would happen, for example, if
214                  * conflicting keys are proposed for insertion in a single command.)
215                  */
216                 if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple->t_data)))
217                         ereport(ERROR,
218                                         (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
219                                          errmsg("could not serialize access due to concurrent update")));
220         }
221         LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
222 }
223
224 /*
225  * ExecCheckTIDVisible -- convenience variant of ExecCheckHeapTupleVisible()
226  */
227 static void
228 ExecCheckTIDVisible(EState *estate,
229                                         ResultRelInfo *relinfo,
230                                         ItemPointer tid)
231 {
232         Relation        rel = relinfo->ri_RelationDesc;
233         Buffer          buffer;
234         HeapTupleData tuple;
235
236         /* Redundantly check isolation level */
237         if (!IsolationUsesXactSnapshot())
238                 return;
239
240         tuple.t_self = *tid;
241         if (!heap_fetch(rel, SnapshotAny, &tuple, &buffer, false, NULL))
242                 elog(ERROR, "failed to fetch conflicting tuple for ON CONFLICT");
243         ExecCheckHeapTupleVisible(estate, &tuple, buffer);
244         ReleaseBuffer(buffer);
245 }
246
247 /* ----------------------------------------------------------------
248  *              ExecInsert
249  *
250  *              For INSERT, we have to insert the tuple into the target relation
251  *              and insert appropriate tuples into the index relations.
252  *
253  *              Returns RETURNING result if any, otherwise NULL.
254  * ----------------------------------------------------------------
255  */
256 static TupleTableSlot *
257 ExecInsert(ModifyTableState *mtstate,
258                    TupleTableSlot *slot,
259                    TupleTableSlot *planSlot,
260                    EState *estate,
261                    bool canSetTag)
262 {
263         HeapTuple       tuple;
264         ResultRelInfo *resultRelInfo;
265         Relation        resultRelationDesc;
266         List       *recheckIndexes = NIL;
267         TupleTableSlot *result = NULL;
268         TransitionCaptureState *ar_insert_trig_tcs;
269         ModifyTable *node = (ModifyTable *) mtstate->ps.plan;
270         OnConflictAction onconflict = node->onConflictAction;
271
272         /*
273          * get the heap tuple out of the tuple table slot, making sure we have a
274          * writable copy
275          */
276         tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
277
278         /*
279          * get information on the (current) result relation
280          */
281         resultRelInfo = estate->es_result_relation_info;
282         resultRelationDesc = resultRelInfo->ri_RelationDesc;
283
284         /*
285          * BEFORE ROW INSERT Triggers.
286          *
287          * Note: We fire BEFORE ROW TRIGGERS for every attempted insertion in an
288          * INSERT ... ON CONFLICT statement.  We cannot check for constraint
289          * violations before firing these triggers, because they can change the
290          * values to insert.  Also, they can run arbitrary user-defined code with
291          * side-effects that we can't cancel by just not inserting the tuple.
292          */
293         if (resultRelInfo->ri_TrigDesc &&
294                 resultRelInfo->ri_TrigDesc->trig_insert_before_row)
295         {
296                 slot = ExecBRInsertTriggers(estate, resultRelInfo, slot);
297
298                 if (slot == NULL)               /* "do nothing" */
299                         return NULL;
300
301                 /* trigger might have changed tuple */
302                 tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
303         }
304
305         /* INSTEAD OF ROW INSERT Triggers */
306         if (resultRelInfo->ri_TrigDesc &&
307                 resultRelInfo->ri_TrigDesc->trig_insert_instead_row)
308         {
309                 slot = ExecIRInsertTriggers(estate, resultRelInfo, slot);
310
311                 if (slot == NULL)               /* "do nothing" */
312                         return NULL;
313
314                 /* trigger might have changed tuple */
315                 tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
316         }
317         else if (resultRelInfo->ri_FdwRoutine)
318         {
319                 /*
320                  * insert into foreign table: let the FDW do it
321                  */
322                 slot = resultRelInfo->ri_FdwRoutine->ExecForeignInsert(estate,
323                                                                                                                            resultRelInfo,
324                                                                                                                            slot,
325                                                                                                                            planSlot);
326
327                 if (slot == NULL)               /* "do nothing" */
328                         return NULL;
329
330                 /* FDW might have changed tuple */
331                 tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
332
333                 /*
334                  * AFTER ROW Triggers or RETURNING expressions might reference the
335                  * tableoid column, so initialize t_tableOid before evaluating them.
336                  */
337                 tuple->t_tableOid = RelationGetRelid(resultRelationDesc);
338         }
339         else
340         {
341                 WCOKind         wco_kind;
342
343                 /*
344                  * Constraints might reference the tableoid column, so initialize
345                  * t_tableOid before evaluating them.
346                  */
347                 tuple->t_tableOid = RelationGetRelid(resultRelationDesc);
348
349                 /*
350                  * Check any RLS WITH CHECK policies.
351                  *
352                  * Normally we should check INSERT policies. But if the insert is the
353                  * result of a partition key update that moved the tuple to a new
354                  * partition, we should instead check UPDATE policies, because we are
355                  * executing policies defined on the target table, and not those
356                  * defined on the child partitions.
357                  */
358                 wco_kind = (mtstate->operation == CMD_UPDATE) ?
359                         WCO_RLS_UPDATE_CHECK : WCO_RLS_INSERT_CHECK;
360
361                 /*
362                  * ExecWithCheckOptions() will skip any WCOs which are not of the kind
363                  * we are looking for at this point.
364                  */
365                 if (resultRelInfo->ri_WithCheckOptions != NIL)
366                         ExecWithCheckOptions(wco_kind, resultRelInfo, slot, estate);
367
368                 /*
369                  * Check the constraints of the tuple.
370                  */
371                 if (resultRelationDesc->rd_att->constr)
372                         ExecConstraints(resultRelInfo, slot, estate);
373
374                 /*
375                  * Also check the tuple against the partition constraint, if there is
376                  * one; except that if we got here via tuple-routing, we don't need to
377                  * if there's no BR trigger defined on the partition.
378                  */
379                 if (resultRelInfo->ri_PartitionCheck &&
380                         (resultRelInfo->ri_PartitionRoot == NULL ||
381                          (resultRelInfo->ri_TrigDesc &&
382                           resultRelInfo->ri_TrigDesc->trig_insert_before_row)))
383                         ExecPartitionCheck(resultRelInfo, slot, estate, true);
384
385                 if (onconflict != ONCONFLICT_NONE && resultRelInfo->ri_NumIndices > 0)
386                 {
387                         /* Perform a speculative insertion. */
388                         uint32          specToken;
389                         ItemPointerData conflictTid;
390                         bool            specConflict;
391                         List       *arbiterIndexes;
392
393                         arbiterIndexes = resultRelInfo->ri_onConflictArbiterIndexes;
394
395                         /*
396                          * Do a non-conclusive check for conflicts first.
397                          *
398                          * We're not holding any locks yet, so this doesn't guarantee that
399                          * the later insert won't conflict.  But it avoids leaving behind
400                          * a lot of canceled speculative insertions, if you run a lot of
401                          * INSERT ON CONFLICT statements that do conflict.
402                          *
403                          * We loop back here if we find a conflict below, either during
404                          * the pre-check, or when we re-check after inserting the tuple
405                          * speculatively.
406                          */
407         vlock:
408                         specConflict = false;
409                         if (!ExecCheckIndexConstraints(slot, estate, &conflictTid,
410                                                                                    arbiterIndexes))
411                         {
412                                 /* committed conflict tuple found */
413                                 if (onconflict == ONCONFLICT_UPDATE)
414                                 {
415                                         /*
416                                          * In case of ON CONFLICT DO UPDATE, execute the UPDATE
417                                          * part.  Be prepared to retry if the UPDATE fails because
418                                          * of another concurrent UPDATE/DELETE to the conflict
419                                          * tuple.
420                                          */
421                                         TupleTableSlot *returning = NULL;
422
423                                         if (ExecOnConflictUpdate(mtstate, resultRelInfo,
424                                                                                          &conflictTid, planSlot, slot,
425                                                                                          estate, canSetTag, &returning))
426                                         {
427                                                 InstrCountTuples2(&mtstate->ps, 1);
428                                                 return returning;
429                                         }
430                                         else
431                                                 goto vlock;
432                                 }
433                                 else
434                                 {
435                                         /*
436                                          * In case of ON CONFLICT DO NOTHING, do nothing. However,
437                                          * verify that the tuple is visible to the executor's MVCC
438                                          * snapshot at higher isolation levels.
439                                          */
440                                         Assert(onconflict == ONCONFLICT_NOTHING);
441                                         ExecCheckTIDVisible(estate, resultRelInfo, &conflictTid);
442                                         InstrCountTuples2(&mtstate->ps, 1);
443                                         return NULL;
444                                 }
445                         }
446
447                         /*
448                          * Before we start insertion proper, acquire our "speculative
449                          * insertion lock".  Others can use that to wait for us to decide
450                          * if we're going to go ahead with the insertion, instead of
451                          * waiting for the whole transaction to complete.
452                          */
453                         specToken = SpeculativeInsertionLockAcquire(GetCurrentTransactionId());
454                         HeapTupleHeaderSetSpeculativeToken(tuple->t_data, specToken);
455
456                         /* insert the tuple, with the speculative token */
457                         heap_insert(resultRelationDesc, tuple,
458                                                 estate->es_output_cid,
459                                                 HEAP_INSERT_SPECULATIVE,
460                                                 NULL);
461
462                         /* insert index entries for tuple */
463                         recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self),
464                                                                                                    estate, true, &specConflict,
465                                                                                                    arbiterIndexes);
466
467                         /* adjust the tuple's state accordingly */
468                         if (!specConflict)
469                                 heap_finish_speculative(resultRelationDesc, tuple);
470                         else
471                                 heap_abort_speculative(resultRelationDesc, tuple);
472
473                         /*
474                          * Wake up anyone waiting for our decision.  They will re-check
475                          * the tuple, see that it's no longer speculative, and wait on our
476                          * XID as if this was a regularly inserted tuple all along.  Or if
477                          * we killed the tuple, they will see it's dead, and proceed as if
478                          * the tuple never existed.
479                          */
480                         SpeculativeInsertionLockRelease(GetCurrentTransactionId());
481
482                         /*
483                          * If there was a conflict, start from the beginning.  We'll do
484                          * the pre-check again, which will now find the conflicting tuple
485                          * (unless it aborts before we get there).
486                          */
487                         if (specConflict)
488                         {
489                                 list_free(recheckIndexes);
490                                 goto vlock;
491                         }
492
493                         /* Since there was no insertion conflict, we're done */
494                 }
495                 else
496                 {
497                         /*
498                          * insert the tuple normally.
499                          *
500                          * Note: heap_insert returns the tid (location) of the new tuple
501                          * in the t_self field.
502                          */
503                         heap_insert(resultRelationDesc, tuple,
504                                                 estate->es_output_cid,
505                                                 0, NULL);
506
507                         /* insert index entries for tuple */
508                         if (resultRelInfo->ri_NumIndices > 0)
509                                 recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self),
510                                                                                                            estate, false, NULL,
511                                                                                                            NIL);
512                 }
513         }
514
515         if (canSetTag)
516         {
517                 (estate->es_processed)++;
518                 setLastTid(&(tuple->t_self));
519         }
520
521         /*
522          * If this insert is the result of a partition key update that moved the
523          * tuple to a new partition, put this row into the transition NEW TABLE,
524          * if there is one. We need to do this separately for DELETE and INSERT
525          * because they happen on different tables.
526          */
527         ar_insert_trig_tcs = mtstate->mt_transition_capture;
528         if (mtstate->operation == CMD_UPDATE && mtstate->mt_transition_capture
529                 && mtstate->mt_transition_capture->tcs_update_new_table)
530         {
531                 ExecARUpdateTriggers(estate, resultRelInfo, NULL,
532                                                          NULL,
533                                                          tuple,
534                                                          NULL,
535                                                          mtstate->mt_transition_capture);
536
537                 /*
538                  * We've already captured the NEW TABLE row, so make sure any AR
539                  * INSERT trigger fired below doesn't capture it again.
540                  */
541                 ar_insert_trig_tcs = NULL;
542         }
543
544         /* AFTER ROW INSERT Triggers */
545         ExecARInsertTriggers(estate, resultRelInfo, tuple, recheckIndexes,
546                                                  ar_insert_trig_tcs);
547
548         list_free(recheckIndexes);
549
550         /*
551          * Check any WITH CHECK OPTION constraints from parent views.  We are
552          * required to do this after testing all constraints and uniqueness
553          * violations per the SQL spec, so we do it after actually inserting the
554          * record into the heap and all indexes.
555          *
556          * ExecWithCheckOptions will elog(ERROR) if a violation is found, so the
557          * tuple will never be seen, if it violates the WITH CHECK OPTION.
558          *
559          * ExecWithCheckOptions() will skip any WCOs which are not of the kind we
560          * are looking for at this point.
561          */
562         if (resultRelInfo->ri_WithCheckOptions != NIL)
563                 ExecWithCheckOptions(WCO_VIEW_CHECK, resultRelInfo, slot, estate);
564
565         /* Process RETURNING if present */
566         if (resultRelInfo->ri_projectReturning)
567                 result = ExecProcessReturning(resultRelInfo, slot, planSlot);
568
569         return result;
570 }
571
572 /* ----------------------------------------------------------------
573  *              ExecDelete
574  *
575  *              DELETE is like UPDATE, except that we delete the tuple and no
576  *              index modifications are needed.
577  *
578  *              When deleting from a table, tupleid identifies the tuple to
579  *              delete and oldtuple is NULL.  When deleting from a view,
580  *              oldtuple is passed to the INSTEAD OF triggers and identifies
581  *              what to delete, and tupleid is invalid.  When deleting from a
582  *              foreign table, tupleid is invalid; the FDW has to figure out
583  *              which row to delete using data from the planSlot.  oldtuple is
584  *              passed to foreign table triggers; it is NULL when the foreign
585  *              table has no relevant triggers.  We use tupleDeleted to indicate
586  *              whether the tuple is actually deleted, callers can use it to
587  *              decide whether to continue the operation.  When this DELETE is a
588  *              part of an UPDATE of partition-key, then the slot returned by
589  *              EvalPlanQual() is passed back using output parameter epqslot.
590  *
591  *              Returns RETURNING result if any, otherwise NULL.
592  * ----------------------------------------------------------------
593  */
594 static TupleTableSlot *
595 ExecDelete(ModifyTableState *mtstate,
596                    ItemPointer tupleid,
597                    HeapTuple oldtuple,
598                    TupleTableSlot *planSlot,
599                    EPQState *epqstate,
600                    EState *estate,
601                    bool processReturning,
602                    bool canSetTag,
603                    bool changingPart,
604                    bool *tupleDeleted,
605                    TupleTableSlot **epqslot)
606 {
607         ResultRelInfo *resultRelInfo;
608         Relation        resultRelationDesc;
609         HTSU_Result result;
610         HeapUpdateFailureData hufd;
611         TupleTableSlot *slot = NULL;
612         TransitionCaptureState *ar_delete_trig_tcs;
613
614         if (tupleDeleted)
615                 *tupleDeleted = false;
616
617         /*
618          * get information on the (current) result relation
619          */
620         resultRelInfo = estate->es_result_relation_info;
621         resultRelationDesc = resultRelInfo->ri_RelationDesc;
622
623         /* BEFORE ROW DELETE Triggers */
624         if (resultRelInfo->ri_TrigDesc &&
625                 resultRelInfo->ri_TrigDesc->trig_delete_before_row)
626         {
627                 bool            dodelete;
628
629                 dodelete = ExecBRDeleteTriggers(estate, epqstate, resultRelInfo,
630                                                                                 tupleid, oldtuple, epqslot);
631
632                 if (!dodelete)                  /* "do nothing" */
633                         return NULL;
634         }
635
636         /* INSTEAD OF ROW DELETE Triggers */
637         if (resultRelInfo->ri_TrigDesc &&
638                 resultRelInfo->ri_TrigDesc->trig_delete_instead_row)
639         {
640                 bool            dodelete;
641
642                 Assert(oldtuple != NULL);
643                 dodelete = ExecIRDeleteTriggers(estate, resultRelInfo, oldtuple);
644
645                 if (!dodelete)                  /* "do nothing" */
646                         return NULL;
647         }
648         else if (resultRelInfo->ri_FdwRoutine)
649         {
650                 HeapTuple       tuple;
651
652                 /*
653                  * delete from foreign table: let the FDW do it
654                  *
655                  * We offer the trigger tuple slot as a place to store RETURNING data,
656                  * although the FDW can return some other slot if it wants.  Set up
657                  * the slot's tupdesc so the FDW doesn't need to do that for itself.
658                  */
659                 slot = estate->es_trig_tuple_slot;
660                 if (slot->tts_tupleDescriptor != RelationGetDescr(resultRelationDesc))
661                         ExecSetSlotDescriptor(slot, RelationGetDescr(resultRelationDesc));
662
663                 slot = resultRelInfo->ri_FdwRoutine->ExecForeignDelete(estate,
664                                                                                                                            resultRelInfo,
665                                                                                                                            slot,
666                                                                                                                            planSlot);
667
668                 if (slot == NULL)               /* "do nothing" */
669                         return NULL;
670
671                 /*
672                  * RETURNING expressions might reference the tableoid column, so
673                  * initialize t_tableOid before evaluating them.
674                  */
675                 if (TTS_EMPTY(slot))
676                         ExecStoreAllNullTuple(slot);
677                 tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
678                 tuple->t_tableOid = RelationGetRelid(resultRelationDesc);
679         }
680         else
681         {
682                 /*
683                  * delete the tuple
684                  *
685                  * Note: if es_crosscheck_snapshot isn't InvalidSnapshot, we check
686                  * that the row to be deleted is visible to that snapshot, and throw a
687                  * can't-serialize error if not. This is a special-case behavior
688                  * needed for referential integrity updates in transaction-snapshot
689                  * mode transactions.
690                  */
691 ldelete:;
692                 result = heap_delete(resultRelationDesc, tupleid,
693                                                          estate->es_output_cid,
694                                                          estate->es_crosscheck_snapshot,
695                                                          true /* wait for commit */ ,
696                                                          &hufd,
697                                                          changingPart);
698                 switch (result)
699                 {
700                         case HeapTupleSelfUpdated:
701
702                                 /*
703                                  * The target tuple was already updated or deleted by the
704                                  * current command, or by a later command in the current
705                                  * transaction.  The former case is possible in a join DELETE
706                                  * where multiple tuples join to the same target tuple. This
707                                  * is somewhat questionable, but Postgres has always allowed
708                                  * it: we just ignore additional deletion attempts.
709                                  *
710                                  * The latter case arises if the tuple is modified by a
711                                  * command in a BEFORE trigger, or perhaps by a command in a
712                                  * volatile function used in the query.  In such situations we
713                                  * should not ignore the deletion, but it is equally unsafe to
714                                  * proceed.  We don't want to discard the original DELETE
715                                  * while keeping the triggered actions based on its deletion;
716                                  * and it would be no better to allow the original DELETE
717                                  * while discarding updates that it triggered.  The row update
718                                  * carries some information that might be important according
719                                  * to business rules; so throwing an error is the only safe
720                                  * course.
721                                  *
722                                  * If a trigger actually intends this type of interaction, it
723                                  * can re-execute the DELETE and then return NULL to cancel
724                                  * the outer delete.
725                                  */
726                                 if (hufd.cmax != estate->es_output_cid)
727                                         ereport(ERROR,
728                                                         (errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
729                                                          errmsg("tuple to be updated was already modified by an operation triggered by the current command"),
730                                                          errhint("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
731
732                                 /* Else, already deleted by self; nothing to do */
733                                 return NULL;
734
735                         case HeapTupleMayBeUpdated:
736                                 break;
737
738                         case HeapTupleUpdated:
739                                 if (IsolationUsesXactSnapshot())
740                                         ereport(ERROR,
741                                                         (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
742                                                          errmsg("could not serialize access due to concurrent update")));
743                                 if (ItemPointerIndicatesMovedPartitions(&hufd.ctid))
744                                         ereport(ERROR,
745                                                         (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
746                                                          errmsg("tuple to be deleted was already moved to another partition due to concurrent update")));
747
748                                 if (!ItemPointerEquals(tupleid, &hufd.ctid))
749                                 {
750                                         TupleTableSlot *my_epqslot;
751
752                                         my_epqslot = EvalPlanQual(estate,
753                                                                                           epqstate,
754                                                                                           resultRelationDesc,
755                                                                                           resultRelInfo->ri_RangeTableIndex,
756                                                                                           LockTupleExclusive,
757                                                                                           &hufd.ctid,
758                                                                                           hufd.xmax);
759                                         if (!TupIsNull(my_epqslot))
760                                         {
761                                                 *tupleid = hufd.ctid;
762
763                                                 /*
764                                                  * If requested, skip delete and pass back the updated
765                                                  * row.
766                                                  */
767                                                 if (epqslot)
768                                                 {
769                                                         *epqslot = my_epqslot;
770                                                         return NULL;
771                                                 }
772                                                 else
773                                                         goto ldelete;
774                                         }
775                                 }
776                                 /* tuple already deleted; nothing to do */
777                                 return NULL;
778
779                         default:
780                                 elog(ERROR, "unrecognized heap_delete status: %u", result);
781                                 return NULL;
782                 }
783
784                 /*
785                  * Note: Normally one would think that we have to delete index tuples
786                  * associated with the heap tuple now...
787                  *
788                  * ... but in POSTGRES, we have no need to do this because VACUUM will
789                  * take care of it later.  We can't delete index tuples immediately
790                  * anyway, since the tuple is still visible to other transactions.
791                  */
792         }
793
794         if (canSetTag)
795                 (estate->es_processed)++;
796
797         /* Tell caller that the delete actually happened. */
798         if (tupleDeleted)
799                 *tupleDeleted = true;
800
801         /*
802          * If this delete is the result of a partition key update that moved the
803          * tuple to a new partition, put this row into the transition OLD TABLE,
804          * if there is one. We need to do this separately for DELETE and INSERT
805          * because they happen on different tables.
806          */
807         ar_delete_trig_tcs = mtstate->mt_transition_capture;
808         if (mtstate->operation == CMD_UPDATE && mtstate->mt_transition_capture
809                 && mtstate->mt_transition_capture->tcs_update_old_table)
810         {
811                 ExecARUpdateTriggers(estate, resultRelInfo,
812                                                          tupleid,
813                                                          oldtuple,
814                                                          NULL,
815                                                          NULL,
816                                                          mtstate->mt_transition_capture);
817
818                 /*
819                  * We've already captured the NEW TABLE row, so make sure any AR
820                  * DELETE trigger fired below doesn't capture it again.
821                  */
822                 ar_delete_trig_tcs = NULL;
823         }
824
825         /* AFTER ROW DELETE Triggers */
826         ExecARDeleteTriggers(estate, resultRelInfo, tupleid, oldtuple,
827                                                  ar_delete_trig_tcs);
828
829         /* Process RETURNING if present and if requested */
830         if (processReturning && resultRelInfo->ri_projectReturning)
831         {
832                 /*
833                  * We have to put the target tuple into a slot, which means first we
834                  * gotta fetch it.  We can use the trigger tuple slot.
835                  */
836                 TupleTableSlot *rslot;
837                 HeapTupleData deltuple;
838                 Buffer          delbuffer;
839
840                 if (resultRelInfo->ri_FdwRoutine)
841                 {
842                         /* FDW must have provided a slot containing the deleted row */
843                         Assert(!TupIsNull(slot));
844                         delbuffer = InvalidBuffer;
845                 }
846                 else
847                 {
848                         slot = estate->es_trig_tuple_slot;
849                         if (oldtuple != NULL)
850                         {
851                                 deltuple = *oldtuple;
852                                 delbuffer = InvalidBuffer;
853                         }
854                         else
855                         {
856                                 deltuple.t_self = *tupleid;
857                                 if (!heap_fetch(resultRelationDesc, SnapshotAny,
858                                                                 &deltuple, &delbuffer, false, NULL))
859                                         elog(ERROR, "failed to fetch deleted tuple for DELETE RETURNING");
860                         }
861
862                         if (slot->tts_tupleDescriptor != RelationGetDescr(resultRelationDesc))
863                                 ExecSetSlotDescriptor(slot, RelationGetDescr(resultRelationDesc));
864                         ExecStoreHeapTuple(&deltuple, slot, false);
865                 }
866
867                 rslot = ExecProcessReturning(resultRelInfo, slot, planSlot);
868
869                 /*
870                  * Before releasing the target tuple again, make sure rslot has a
871                  * local copy of any pass-by-reference values.
872                  */
873                 ExecMaterializeSlot(rslot);
874
875                 ExecClearTuple(slot);
876                 if (BufferIsValid(delbuffer))
877                         ReleaseBuffer(delbuffer);
878
879                 return rslot;
880         }
881
882         return NULL;
883 }
884
885 /* ----------------------------------------------------------------
886  *              ExecUpdate
887  *
888  *              note: we can't run UPDATE queries with transactions
889  *              off because UPDATEs are actually INSERTs and our
890  *              scan will mistakenly loop forever, updating the tuple
891  *              it just inserted..  This should be fixed but until it
892  *              is, we don't want to get stuck in an infinite loop
893  *              which corrupts your database..
894  *
895  *              When updating a table, tupleid identifies the tuple to
896  *              update and oldtuple is NULL.  When updating a view, oldtuple
897  *              is passed to the INSTEAD OF triggers and identifies what to
898  *              update, and tupleid is invalid.  When updating a foreign table,
899  *              tupleid is invalid; the FDW has to figure out which row to
900  *              update using data from the planSlot.  oldtuple is passed to
901  *              foreign table triggers; it is NULL when the foreign table has
902  *              no relevant triggers.
903  *
904  *              Returns RETURNING result if any, otherwise NULL.
905  * ----------------------------------------------------------------
906  */
907 static TupleTableSlot *
908 ExecUpdate(ModifyTableState *mtstate,
909                    ItemPointer tupleid,
910                    HeapTuple oldtuple,
911                    TupleTableSlot *slot,
912                    TupleTableSlot *planSlot,
913                    EPQState *epqstate,
914                    EState *estate,
915                    bool canSetTag)
916 {
917         HeapTuple       tuple;
918         ResultRelInfo *resultRelInfo;
919         Relation        resultRelationDesc;
920         HTSU_Result result;
921         HeapUpdateFailureData hufd;
922         List       *recheckIndexes = NIL;
923         TupleConversionMap *saved_tcs_map = NULL;
924
925         /*
926          * abort the operation if not running transactions
927          */
928         if (IsBootstrapProcessingMode())
929                 elog(ERROR, "cannot UPDATE during bootstrap");
930
931         /*
932          * get the heap tuple out of the tuple table slot, making sure we have a
933          * writable copy
934          */
935         tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
936
937         /*
938          * get information on the (current) result relation
939          */
940         resultRelInfo = estate->es_result_relation_info;
941         resultRelationDesc = resultRelInfo->ri_RelationDesc;
942
943         /* BEFORE ROW UPDATE Triggers */
944         if (resultRelInfo->ri_TrigDesc &&
945                 resultRelInfo->ri_TrigDesc->trig_update_before_row)
946         {
947                 slot = ExecBRUpdateTriggers(estate, epqstate, resultRelInfo,
948                                                                         tupleid, oldtuple, slot);
949
950                 if (slot == NULL)               /* "do nothing" */
951                         return NULL;
952
953                 /* trigger might have changed tuple */
954                 tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
955         }
956
957         /* INSTEAD OF ROW UPDATE Triggers */
958         if (resultRelInfo->ri_TrigDesc &&
959                 resultRelInfo->ri_TrigDesc->trig_update_instead_row)
960         {
961                 slot = ExecIRUpdateTriggers(estate, resultRelInfo,
962                                                                         oldtuple, slot);
963
964                 if (slot == NULL)               /* "do nothing" */
965                         return NULL;
966
967                 /* trigger might have changed tuple */
968                 tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
969         }
970         else if (resultRelInfo->ri_FdwRoutine)
971         {
972                 /*
973                  * update in foreign table: let the FDW do it
974                  */
975                 slot = resultRelInfo->ri_FdwRoutine->ExecForeignUpdate(estate,
976                                                                                                                            resultRelInfo,
977                                                                                                                            slot,
978                                                                                                                            planSlot);
979
980                 if (slot == NULL)               /* "do nothing" */
981                         return NULL;
982
983                 /* FDW might have changed tuple */
984                 tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
985
986                 /*
987                  * AFTER ROW Triggers or RETURNING expressions might reference the
988                  * tableoid column, so initialize t_tableOid before evaluating them.
989                  */
990                 tuple->t_tableOid = RelationGetRelid(resultRelationDesc);
991         }
992         else
993         {
994                 LockTupleMode lockmode;
995                 bool            partition_constraint_failed;
996
997                 /*
998                  * Constraints might reference the tableoid column, so initialize
999                  * t_tableOid before evaluating them.
1000                  */
1001                 tuple->t_tableOid = RelationGetRelid(resultRelationDesc);
1002
1003                 /*
1004                  * Check any RLS UPDATE WITH CHECK policies
1005                  *
1006                  * If we generate a new candidate tuple after EvalPlanQual testing, we
1007                  * must loop back here and recheck any RLS policies and constraints.
1008                  * (We don't need to redo triggers, however.  If there are any BEFORE
1009                  * triggers then trigger.c will have done heap_lock_tuple to lock the
1010                  * correct tuple, so there's no need to do them again.)
1011                  */
1012 lreplace:;
1013
1014                 /*
1015                  * If partition constraint fails, this row might get moved to another
1016                  * partition, in which case we should check the RLS CHECK policy just
1017                  * before inserting into the new partition, rather than doing it here.
1018                  * This is because a trigger on that partition might again change the
1019                  * row.  So skip the WCO checks if the partition constraint fails.
1020                  */
1021                 partition_constraint_failed =
1022                         resultRelInfo->ri_PartitionCheck &&
1023                         !ExecPartitionCheck(resultRelInfo, slot, estate, false);
1024
1025                 if (!partition_constraint_failed &&
1026                         resultRelInfo->ri_WithCheckOptions != NIL)
1027                 {
1028                         /*
1029                          * ExecWithCheckOptions() will skip any WCOs which are not of the
1030                          * kind we are looking for at this point.
1031                          */
1032                         ExecWithCheckOptions(WCO_RLS_UPDATE_CHECK,
1033                                                                  resultRelInfo, slot, estate);
1034                 }
1035
1036                 /*
1037                  * If a partition check failed, try to move the row into the right
1038                  * partition.
1039                  */
1040                 if (partition_constraint_failed)
1041                 {
1042                         bool            tuple_deleted;
1043                         TupleTableSlot *ret_slot;
1044                         TupleTableSlot *epqslot = NULL;
1045                         PartitionTupleRouting *proute = mtstate->mt_partition_tuple_routing;
1046                         int                     map_index;
1047                         TupleConversionMap *tupconv_map;
1048
1049                         /*
1050                          * Disallow an INSERT ON CONFLICT DO UPDATE that causes the
1051                          * original row to migrate to a different partition.  Maybe this
1052                          * can be implemented some day, but it seems a fringe feature with
1053                          * little redeeming value.
1054                          */
1055                         if (((ModifyTable *) mtstate->ps.plan)->onConflictAction == ONCONFLICT_UPDATE)
1056                                 ereport(ERROR,
1057                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1058                                                  errmsg("invalid ON UPDATE specification"),
1059                                                  errdetail("The result tuple would appear in a different partition than the original tuple.")));
1060
1061                         /*
1062                          * When an UPDATE is run on a leaf partition, we will not have
1063                          * partition tuple routing set up. In that case, fail with
1064                          * partition constraint violation error.
1065                          */
1066                         if (proute == NULL)
1067                                 ExecPartitionCheckEmitError(resultRelInfo, slot, estate);
1068
1069                         /*
1070                          * Row movement, part 1.  Delete the tuple, but skip RETURNING
1071                          * processing. We want to return rows from INSERT.
1072                          */
1073                         ExecDelete(mtstate, tupleid, oldtuple, planSlot, epqstate,
1074                                            estate, false, false /* canSetTag */ ,
1075                                            true /* changingPart */ , &tuple_deleted, &epqslot);
1076
1077                         /*
1078                          * For some reason if DELETE didn't happen (e.g. trigger prevented
1079                          * it, or it was already deleted by self, or it was concurrently
1080                          * deleted by another transaction), then we should skip the insert
1081                          * as well; otherwise, an UPDATE could cause an increase in the
1082                          * total number of rows across all partitions, which is clearly
1083                          * wrong.
1084                          *
1085                          * For a normal UPDATE, the case where the tuple has been the
1086                          * subject of a concurrent UPDATE or DELETE would be handled by
1087                          * the EvalPlanQual machinery, but for an UPDATE that we've
1088                          * translated into a DELETE from this partition and an INSERT into
1089                          * some other partition, that's not available, because CTID chains
1090                          * can't span relation boundaries.  We mimic the semantics to a
1091                          * limited extent by skipping the INSERT if the DELETE fails to
1092                          * find a tuple. This ensures that two concurrent attempts to
1093                          * UPDATE the same tuple at the same time can't turn one tuple
1094                          * into two, and that an UPDATE of a just-deleted tuple can't
1095                          * resurrect it.
1096                          */
1097                         if (!tuple_deleted)
1098                         {
1099                                 /*
1100                                  * epqslot will be typically NULL.  But when ExecDelete()
1101                                  * finds that another transaction has concurrently updated the
1102                                  * same row, it re-fetches the row, skips the delete, and
1103                                  * epqslot is set to the re-fetched tuple slot. In that case,
1104                                  * we need to do all the checks again.
1105                                  */
1106                                 if (TupIsNull(epqslot))
1107                                         return NULL;
1108                                 else
1109                                 {
1110                                         slot = ExecFilterJunk(resultRelInfo->ri_junkFilter, epqslot);
1111                                         tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
1112                                         goto lreplace;
1113                                 }
1114                         }
1115
1116                         /*
1117                          * Updates set the transition capture map only when a new subplan
1118                          * is chosen.  But for inserts, it is set for each row. So after
1119                          * INSERT, we need to revert back to the map created for UPDATE;
1120                          * otherwise the next UPDATE will incorrectly use the one created
1121                          * for INSERT.  So first save the one created for UPDATE.
1122                          */
1123                         if (mtstate->mt_transition_capture)
1124                                 saved_tcs_map = mtstate->mt_transition_capture->tcs_map;
1125
1126                         /*
1127                          * resultRelInfo is one of the per-subplan resultRelInfos.  So we
1128                          * should convert the tuple into root's tuple descriptor, since
1129                          * ExecInsert() starts the search from root.  The tuple conversion
1130                          * map list is in the order of mtstate->resultRelInfo[], so to
1131                          * retrieve the one for this resultRel, we need to know the
1132                          * position of the resultRel in mtstate->resultRelInfo[].
1133                          */
1134                         map_index = resultRelInfo - mtstate->resultRelInfo;
1135                         Assert(map_index >= 0 && map_index < mtstate->mt_nplans);
1136                         tupconv_map = tupconv_map_for_subplan(mtstate, map_index);
1137                         if (tupconv_map != NULL)
1138                                 slot = execute_attr_map_slot(tupconv_map->attrMap,
1139                                                                                          slot,
1140                                                                                          mtstate->mt_root_tuple_slot);
1141
1142                         /*
1143                          * Prepare for tuple routing, making it look like we're inserting
1144                          * into the root.
1145                          */
1146                         Assert(mtstate->rootResultRelInfo != NULL);
1147                         slot = ExecPrepareTupleRouting(mtstate, estate, proute,
1148                                                                                    mtstate->rootResultRelInfo, slot);
1149
1150                         ret_slot = ExecInsert(mtstate, slot, planSlot,
1151                                                                   estate, canSetTag);
1152
1153                         /* Revert ExecPrepareTupleRouting's node change. */
1154                         estate->es_result_relation_info = resultRelInfo;
1155                         if (mtstate->mt_transition_capture)
1156                         {
1157                                 mtstate->mt_transition_capture->tcs_original_insert_tuple = NULL;
1158                                 mtstate->mt_transition_capture->tcs_map = saved_tcs_map;
1159                         }
1160
1161                         return ret_slot;
1162                 }
1163
1164                 /*
1165                  * Check the constraints of the tuple.  We've already checked the
1166                  * partition constraint above; however, we must still ensure the tuple
1167                  * passes all other constraints, so we will call ExecConstraints() and
1168                  * have it validate all remaining checks.
1169                  */
1170                 if (resultRelationDesc->rd_att->constr)
1171                         ExecConstraints(resultRelInfo, slot, estate);
1172
1173                 /*
1174                  * replace the heap tuple
1175                  *
1176                  * Note: if es_crosscheck_snapshot isn't InvalidSnapshot, we check
1177                  * that the row to be updated is visible to that snapshot, and throw a
1178                  * can't-serialize error if not. This is a special-case behavior
1179                  * needed for referential integrity updates in transaction-snapshot
1180                  * mode transactions.
1181                  */
1182                 result = heap_update(resultRelationDesc, tupleid, tuple,
1183                                                          estate->es_output_cid,
1184                                                          estate->es_crosscheck_snapshot,
1185                                                          true /* wait for commit */ ,
1186                                                          &hufd, &lockmode);
1187                 switch (result)
1188                 {
1189                         case HeapTupleSelfUpdated:
1190
1191                                 /*
1192                                  * The target tuple was already updated or deleted by the
1193                                  * current command, or by a later command in the current
1194                                  * transaction.  The former case is possible in a join UPDATE
1195                                  * where multiple tuples join to the same target tuple. This
1196                                  * is pretty questionable, but Postgres has always allowed it:
1197                                  * we just execute the first update action and ignore
1198                                  * additional update attempts.
1199                                  *
1200                                  * The latter case arises if the tuple is modified by a
1201                                  * command in a BEFORE trigger, or perhaps by a command in a
1202                                  * volatile function used in the query.  In such situations we
1203                                  * should not ignore the update, but it is equally unsafe to
1204                                  * proceed.  We don't want to discard the original UPDATE
1205                                  * while keeping the triggered actions based on it; and we
1206                                  * have no principled way to merge this update with the
1207                                  * previous ones.  So throwing an error is the only safe
1208                                  * course.
1209                                  *
1210                                  * If a trigger actually intends this type of interaction, it
1211                                  * can re-execute the UPDATE (assuming it can figure out how)
1212                                  * and then return NULL to cancel the outer update.
1213                                  */
1214                                 if (hufd.cmax != estate->es_output_cid)
1215                                         ereport(ERROR,
1216                                                         (errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
1217                                                          errmsg("tuple to be updated was already modified by an operation triggered by the current command"),
1218                                                          errhint("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
1219
1220                                 /* Else, already updated by self; nothing to do */
1221                                 return NULL;
1222
1223                         case HeapTupleMayBeUpdated:
1224                                 break;
1225
1226                         case HeapTupleUpdated:
1227                                 if (IsolationUsesXactSnapshot())
1228                                         ereport(ERROR,
1229                                                         (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
1230                                                          errmsg("could not serialize access due to concurrent update")));
1231                                 if (ItemPointerIndicatesMovedPartitions(&hufd.ctid))
1232                                         ereport(ERROR,
1233                                                         (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
1234                                                          errmsg("tuple to be updated was already moved to another partition due to concurrent update")));
1235
1236                                 if (!ItemPointerEquals(tupleid, &hufd.ctid))
1237                                 {
1238                                         TupleTableSlot *epqslot;
1239
1240                                         epqslot = EvalPlanQual(estate,
1241                                                                                    epqstate,
1242                                                                                    resultRelationDesc,
1243                                                                                    resultRelInfo->ri_RangeTableIndex,
1244                                                                                    lockmode,
1245                                                                                    &hufd.ctid,
1246                                                                                    hufd.xmax);
1247                                         if (!TupIsNull(epqslot))
1248                                         {
1249                                                 *tupleid = hufd.ctid;
1250                                                 slot = ExecFilterJunk(resultRelInfo->ri_junkFilter, epqslot);
1251                                                 tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
1252                                                 goto lreplace;
1253                                         }
1254                                 }
1255                                 /* tuple already deleted; nothing to do */
1256                                 return NULL;
1257
1258                         default:
1259                                 elog(ERROR, "unrecognized heap_update status: %u", result);
1260                                 return NULL;
1261                 }
1262
1263                 /*
1264                  * Note: instead of having to update the old index tuples associated
1265                  * with the heap tuple, all we do is form and insert new index tuples.
1266                  * This is because UPDATEs are actually DELETEs and INSERTs, and index
1267                  * tuple deletion is done later by VACUUM (see notes in ExecDelete).
1268                  * All we do here is insert new index tuples.  -cim 9/27/89
1269                  */
1270
1271                 /*
1272                  * insert index entries for tuple
1273                  *
1274                  * Note: heap_update returns the tid (location) of the new tuple in
1275                  * the t_self field.
1276                  *
1277                  * If it's a HOT update, we mustn't insert new index entries.
1278                  */
1279                 if (resultRelInfo->ri_NumIndices > 0 && !HeapTupleIsHeapOnly(tuple))
1280                         recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self),
1281                                                                                                    estate, false, NULL, NIL);
1282         }
1283
1284         if (canSetTag)
1285                 (estate->es_processed)++;
1286
1287         /* AFTER ROW UPDATE Triggers */
1288         ExecARUpdateTriggers(estate, resultRelInfo, tupleid, oldtuple, tuple,
1289                                                  recheckIndexes,
1290                                                  mtstate->operation == CMD_INSERT ?
1291                                                  mtstate->mt_oc_transition_capture :
1292                                                  mtstate->mt_transition_capture);
1293
1294         list_free(recheckIndexes);
1295
1296         /*
1297          * Check any WITH CHECK OPTION constraints from parent views.  We are
1298          * required to do this after testing all constraints and uniqueness
1299          * violations per the SQL spec, so we do it after actually updating the
1300          * record in the heap and all indexes.
1301          *
1302          * ExecWithCheckOptions() will skip any WCOs which are not of the kind we
1303          * are looking for at this point.
1304          */
1305         if (resultRelInfo->ri_WithCheckOptions != NIL)
1306                 ExecWithCheckOptions(WCO_VIEW_CHECK, resultRelInfo, slot, estate);
1307
1308         /* Process RETURNING if present */
1309         if (resultRelInfo->ri_projectReturning)
1310                 return ExecProcessReturning(resultRelInfo, slot, planSlot);
1311
1312         return NULL;
1313 }
1314
1315 /*
1316  * ExecOnConflictUpdate --- execute UPDATE of INSERT ON CONFLICT DO UPDATE
1317  *
1318  * Try to lock tuple for update as part of speculative insertion.  If
1319  * a qual originating from ON CONFLICT DO UPDATE is satisfied, update
1320  * (but still lock row, even though it may not satisfy estate's
1321  * snapshot).
1322  *
1323  * Returns true if we're done (with or without an update), or false if
1324  * the caller must retry the INSERT from scratch.
1325  */
1326 static bool
1327 ExecOnConflictUpdate(ModifyTableState *mtstate,
1328                                          ResultRelInfo *resultRelInfo,
1329                                          ItemPointer conflictTid,
1330                                          TupleTableSlot *planSlot,
1331                                          TupleTableSlot *excludedSlot,
1332                                          EState *estate,
1333                                          bool canSetTag,
1334                                          TupleTableSlot **returning)
1335 {
1336         ExprContext *econtext = mtstate->ps.ps_ExprContext;
1337         Relation        relation = resultRelInfo->ri_RelationDesc;
1338         ExprState  *onConflictSetWhere = resultRelInfo->ri_onConflict->oc_WhereClause;
1339         HeapTupleData tuple;
1340         HeapUpdateFailureData hufd;
1341         LockTupleMode lockmode;
1342         HTSU_Result test;
1343         Buffer          buffer;
1344
1345         /* Determine lock mode to use */
1346         lockmode = ExecUpdateLockMode(estate, resultRelInfo);
1347
1348         /*
1349          * Lock tuple for update.  Don't follow updates when tuple cannot be
1350          * locked without doing so.  A row locking conflict here means our
1351          * previous conclusion that the tuple is conclusively committed is not
1352          * true anymore.
1353          */
1354         tuple.t_self = *conflictTid;
1355         test = heap_lock_tuple(relation, &tuple, estate->es_output_cid,
1356                                                    lockmode, LockWaitBlock, false, &buffer,
1357                                                    &hufd);
1358         switch (test)
1359         {
1360                 case HeapTupleMayBeUpdated:
1361                         /* success! */
1362                         break;
1363
1364                 case HeapTupleInvisible:
1365
1366                         /*
1367                          * This can occur when a just inserted tuple is updated again in
1368                          * the same command. E.g. because multiple rows with the same
1369                          * conflicting key values are inserted.
1370                          *
1371                          * This is somewhat similar to the ExecUpdate()
1372                          * HeapTupleSelfUpdated case.  We do not want to proceed because
1373                          * it would lead to the same row being updated a second time in
1374                          * some unspecified order, and in contrast to plain UPDATEs
1375                          * there's no historical behavior to break.
1376                          *
1377                          * It is the user's responsibility to prevent this situation from
1378                          * occurring.  These problems are why SQL-2003 similarly specifies
1379                          * that for SQL MERGE, an exception must be raised in the event of
1380                          * an attempt to update the same row twice.
1381                          */
1382                         if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple.t_data)))
1383                                 ereport(ERROR,
1384                                                 (errcode(ERRCODE_CARDINALITY_VIOLATION),
1385                                                  errmsg("ON CONFLICT DO UPDATE command cannot affect row a second time"),
1386                                                  errhint("Ensure that no rows proposed for insertion within the same command have duplicate constrained values.")));
1387
1388                         /* This shouldn't happen */
1389                         elog(ERROR, "attempted to lock invisible tuple");
1390                         break;
1391
1392                 case HeapTupleSelfUpdated:
1393
1394                         /*
1395                          * This state should never be reached. As a dirty snapshot is used
1396                          * to find conflicting tuples, speculative insertion wouldn't have
1397                          * seen this row to conflict with.
1398                          */
1399                         elog(ERROR, "unexpected self-updated tuple");
1400                         break;
1401
1402                 case HeapTupleUpdated:
1403                         if (IsolationUsesXactSnapshot())
1404                                 ereport(ERROR,
1405                                                 (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
1406                                                  errmsg("could not serialize access due to concurrent update")));
1407
1408                         /*
1409                          * As long as we don't support an UPDATE of INSERT ON CONFLICT for
1410                          * a partitioned table we shouldn't reach to a case where tuple to
1411                          * be lock is moved to another partition due to concurrent update
1412                          * of the partition key.
1413                          */
1414                         Assert(!ItemPointerIndicatesMovedPartitions(&hufd.ctid));
1415
1416                         /*
1417                          * Tell caller to try again from the very start.
1418                          *
1419                          * It does not make sense to use the usual EvalPlanQual() style
1420                          * loop here, as the new version of the row might not conflict
1421                          * anymore, or the conflicting tuple has actually been deleted.
1422                          */
1423                         ReleaseBuffer(buffer);
1424                         return false;
1425
1426                 default:
1427                         elog(ERROR, "unrecognized heap_lock_tuple status: %u", test);
1428         }
1429
1430         /* Success, the tuple is locked. */
1431
1432         /*
1433          * Verify that the tuple is visible to our MVCC snapshot if the current
1434          * isolation level mandates that.
1435          *
1436          * It's not sufficient to rely on the check within ExecUpdate() as e.g.
1437          * CONFLICT ... WHERE clause may prevent us from reaching that.
1438          *
1439          * This means we only ever continue when a new command in the current
1440          * transaction could see the row, even though in READ COMMITTED mode the
1441          * tuple will not be visible according to the current statement's
1442          * snapshot.  This is in line with the way UPDATE deals with newer tuple
1443          * versions.
1444          */
1445         ExecCheckHeapTupleVisible(estate, &tuple, buffer);
1446
1447         /* Store target's existing tuple in the state's dedicated slot */
1448         ExecStoreBufferHeapTuple(&tuple, mtstate->mt_existing, buffer);
1449
1450         /*
1451          * Make tuple and any needed join variables available to ExecQual and
1452          * ExecProject.  The EXCLUDED tuple is installed in ecxt_innertuple, while
1453          * the target's existing tuple is installed in the scantuple.  EXCLUDED
1454          * has been made to reference INNER_VAR in setrefs.c, but there is no
1455          * other redirection.
1456          */
1457         econtext->ecxt_scantuple = mtstate->mt_existing;
1458         econtext->ecxt_innertuple = excludedSlot;
1459         econtext->ecxt_outertuple = NULL;
1460
1461         if (!ExecQual(onConflictSetWhere, econtext))
1462         {
1463                 ReleaseBuffer(buffer);
1464                 InstrCountFiltered1(&mtstate->ps, 1);
1465                 return true;                    /* done with the tuple */
1466         }
1467
1468         if (resultRelInfo->ri_WithCheckOptions != NIL)
1469         {
1470                 /*
1471                  * Check target's existing tuple against UPDATE-applicable USING
1472                  * security barrier quals (if any), enforced here as RLS checks/WCOs.
1473                  *
1474                  * The rewriter creates UPDATE RLS checks/WCOs for UPDATE security
1475                  * quals, and stores them as WCOs of "kind" WCO_RLS_CONFLICT_CHECK,
1476                  * but that's almost the extent of its special handling for ON
1477                  * CONFLICT DO UPDATE.
1478                  *
1479                  * The rewriter will also have associated UPDATE applicable straight
1480                  * RLS checks/WCOs for the benefit of the ExecUpdate() call that
1481                  * follows.  INSERTs and UPDATEs naturally have mutually exclusive WCO
1482                  * kinds, so there is no danger of spurious over-enforcement in the
1483                  * INSERT or UPDATE path.
1484                  */
1485                 ExecWithCheckOptions(WCO_RLS_CONFLICT_CHECK, resultRelInfo,
1486                                                          mtstate->mt_existing,
1487                                                          mtstate->ps.state);
1488         }
1489
1490         /* Project the new tuple version */
1491         ExecProject(resultRelInfo->ri_onConflict->oc_ProjInfo);
1492
1493         /*
1494          * Note that it is possible that the target tuple has been modified in
1495          * this session, after the above heap_lock_tuple. We choose to not error
1496          * out in that case, in line with ExecUpdate's treatment of similar cases.
1497          * This can happen if an UPDATE is triggered from within ExecQual(),
1498          * ExecWithCheckOptions() or ExecProject() above, e.g. by selecting from a
1499          * wCTE in the ON CONFLICT's SET.
1500          */
1501
1502         /* Execute UPDATE with projection */
1503         *returning = ExecUpdate(mtstate, &tuple.t_self, NULL,
1504                                                         mtstate->mt_conflproj, planSlot,
1505                                                         &mtstate->mt_epqstate, mtstate->ps.state,
1506                                                         canSetTag);
1507
1508         ReleaseBuffer(buffer);
1509         return true;
1510 }
1511
1512
1513 /*
1514  * Process BEFORE EACH STATEMENT triggers
1515  */
1516 static void
1517 fireBSTriggers(ModifyTableState *node)
1518 {
1519         ModifyTable *plan = (ModifyTable *) node->ps.plan;
1520         ResultRelInfo *resultRelInfo = node->resultRelInfo;
1521
1522         /*
1523          * If the node modifies a partitioned table, we must fire its triggers.
1524          * Note that in that case, node->resultRelInfo points to the first leaf
1525          * partition, not the root table.
1526          */
1527         if (node->rootResultRelInfo != NULL)
1528                 resultRelInfo = node->rootResultRelInfo;
1529
1530         switch (node->operation)
1531         {
1532                 case CMD_INSERT:
1533                         ExecBSInsertTriggers(node->ps.state, resultRelInfo);
1534                         if (plan->onConflictAction == ONCONFLICT_UPDATE)
1535                                 ExecBSUpdateTriggers(node->ps.state,
1536                                                                          resultRelInfo);
1537                         break;
1538                 case CMD_UPDATE:
1539                         ExecBSUpdateTriggers(node->ps.state, resultRelInfo);
1540                         break;
1541                 case CMD_DELETE:
1542                         ExecBSDeleteTriggers(node->ps.state, resultRelInfo);
1543                         break;
1544                 default:
1545                         elog(ERROR, "unknown operation");
1546                         break;
1547         }
1548 }
1549
1550 /*
1551  * Return the target rel ResultRelInfo.
1552  *
1553  * This relation is the same as :
1554  * - the relation for which we will fire AFTER STATEMENT triggers.
1555  * - the relation into whose tuple format all captured transition tuples must
1556  *   be converted.
1557  * - the root partitioned table.
1558  */
1559 static ResultRelInfo *
1560 getTargetResultRelInfo(ModifyTableState *node)
1561 {
1562         /*
1563          * Note that if the node modifies a partitioned table, node->resultRelInfo
1564          * points to the first leaf partition, not the root table.
1565          */
1566         if (node->rootResultRelInfo != NULL)
1567                 return node->rootResultRelInfo;
1568         else
1569                 return node->resultRelInfo;
1570 }
1571
1572 /*
1573  * Process AFTER EACH STATEMENT triggers
1574  */
1575 static void
1576 fireASTriggers(ModifyTableState *node)
1577 {
1578         ModifyTable *plan = (ModifyTable *) node->ps.plan;
1579         ResultRelInfo *resultRelInfo = getTargetResultRelInfo(node);
1580
1581         switch (node->operation)
1582         {
1583                 case CMD_INSERT:
1584                         if (plan->onConflictAction == ONCONFLICT_UPDATE)
1585                                 ExecASUpdateTriggers(node->ps.state,
1586                                                                          resultRelInfo,
1587                                                                          node->mt_oc_transition_capture);
1588                         ExecASInsertTriggers(node->ps.state, resultRelInfo,
1589                                                                  node->mt_transition_capture);
1590                         break;
1591                 case CMD_UPDATE:
1592                         ExecASUpdateTriggers(node->ps.state, resultRelInfo,
1593                                                                  node->mt_transition_capture);
1594                         break;
1595                 case CMD_DELETE:
1596                         ExecASDeleteTriggers(node->ps.state, resultRelInfo,
1597                                                                  node->mt_transition_capture);
1598                         break;
1599                 default:
1600                         elog(ERROR, "unknown operation");
1601                         break;
1602         }
1603 }
1604
1605 /*
1606  * Set up the state needed for collecting transition tuples for AFTER
1607  * triggers.
1608  */
1609 static void
1610 ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate)
1611 {
1612         ModifyTable *plan = (ModifyTable *) mtstate->ps.plan;
1613         ResultRelInfo *targetRelInfo = getTargetResultRelInfo(mtstate);
1614
1615         /* Check for transition tables on the directly targeted relation. */
1616         mtstate->mt_transition_capture =
1617                 MakeTransitionCaptureState(targetRelInfo->ri_TrigDesc,
1618                                                                    RelationGetRelid(targetRelInfo->ri_RelationDesc),
1619                                                                    mtstate->operation);
1620         if (plan->operation == CMD_INSERT &&
1621                 plan->onConflictAction == ONCONFLICT_UPDATE)
1622                 mtstate->mt_oc_transition_capture =
1623                         MakeTransitionCaptureState(targetRelInfo->ri_TrigDesc,
1624                                                                            RelationGetRelid(targetRelInfo->ri_RelationDesc),
1625                                                                            CMD_UPDATE);
1626
1627         /*
1628          * If we found that we need to collect transition tuples then we may also
1629          * need tuple conversion maps for any children that have TupleDescs that
1630          * aren't compatible with the tuplestores.  (We can share these maps
1631          * between the regular and ON CONFLICT cases.)
1632          */
1633         if (mtstate->mt_transition_capture != NULL ||
1634                 mtstate->mt_oc_transition_capture != NULL)
1635         {
1636                 ExecSetupChildParentMapForSubplan(mtstate);
1637
1638                 /*
1639                  * Install the conversion map for the first plan for UPDATE and DELETE
1640                  * operations.  It will be advanced each time we switch to the next
1641                  * plan.  (INSERT operations set it every time, so we need not update
1642                  * mtstate->mt_oc_transition_capture here.)
1643                  */
1644                 if (mtstate->mt_transition_capture && mtstate->operation != CMD_INSERT)
1645                         mtstate->mt_transition_capture->tcs_map =
1646                                 tupconv_map_for_subplan(mtstate, 0);
1647         }
1648 }
1649
1650 /*
1651  * ExecPrepareTupleRouting --- prepare for routing one tuple
1652  *
1653  * Determine the partition in which the tuple in slot is to be inserted,
1654  * and modify mtstate and estate to prepare for it.
1655  *
1656  * Caller must revert the estate changes after executing the insertion!
1657  * In mtstate, transition capture changes may also need to be reverted.
1658  *
1659  * Returns a slot holding the tuple of the partition rowtype.
1660  */
1661 static TupleTableSlot *
1662 ExecPrepareTupleRouting(ModifyTableState *mtstate,
1663                                                 EState *estate,
1664                                                 PartitionTupleRouting *proute,
1665                                                 ResultRelInfo *targetRelInfo,
1666                                                 TupleTableSlot *slot)
1667 {
1668         ModifyTable *node;
1669         ResultRelInfo *partrel;
1670         PartitionRoutingInfo *partrouteinfo;
1671         HeapTuple       tuple;
1672         TupleConversionMap *map;
1673
1674         /*
1675          * Lookup the target partition's ResultRelInfo.  If ExecFindPartition does
1676          * not find a valid partition for the tuple in 'slot' then an error is
1677          * raised.  An error may also be raised if the found partition is not a
1678          * valid target for INSERTs.  This is required since a partitioned table
1679          * UPDATE to another partition becomes a DELETE+INSERT.
1680          */
1681         partrel = ExecFindPartition(mtstate, targetRelInfo, proute, slot, estate);
1682         partrouteinfo = partrel->ri_PartitionInfo;
1683         Assert(partrouteinfo != NULL);
1684
1685         /*
1686          * Make it look like we are inserting into the partition.
1687          */
1688         estate->es_result_relation_info = partrel;
1689
1690         /* Get the heap tuple out of the given slot. */
1691         tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
1692
1693         /*
1694          * If we're capturing transition tuples, we might need to convert from the
1695          * partition rowtype to root partitioned table's rowtype.
1696          */
1697         if (mtstate->mt_transition_capture != NULL)
1698         {
1699                 if (partrel->ri_TrigDesc &&
1700                         partrel->ri_TrigDesc->trig_insert_before_row)
1701                 {
1702                         /*
1703                          * If there are any BEFORE triggers on the partition, we'll have
1704                          * to be ready to convert their result back to tuplestore format.
1705                          */
1706                         mtstate->mt_transition_capture->tcs_original_insert_tuple = NULL;
1707                         mtstate->mt_transition_capture->tcs_map =
1708                                 partrouteinfo->pi_PartitionToRootMap;
1709                 }
1710                 else
1711                 {
1712                         /*
1713                          * Otherwise, just remember the original unconverted tuple, to
1714                          * avoid a needless round trip conversion.
1715                          */
1716                         mtstate->mt_transition_capture->tcs_original_insert_tuple = tuple;
1717                         mtstate->mt_transition_capture->tcs_map = NULL;
1718                 }
1719         }
1720         if (mtstate->mt_oc_transition_capture != NULL)
1721         {
1722                 mtstate->mt_oc_transition_capture->tcs_map =
1723                         partrouteinfo->pi_PartitionToRootMap;
1724         }
1725
1726         /*
1727          * Convert the tuple, if necessary.
1728          */
1729         map = partrouteinfo->pi_RootToPartitionMap;
1730         if (map != NULL)
1731         {
1732                 TupleTableSlot *new_slot = partrouteinfo->pi_PartitionTupleSlot;
1733
1734                 slot = execute_attr_map_slot(map->attrMap, slot, new_slot);
1735         }
1736
1737         /* Initialize information needed to handle ON CONFLICT DO UPDATE. */
1738         Assert(mtstate != NULL);
1739         node = (ModifyTable *) mtstate->ps.plan;
1740         if (node->onConflictAction == ONCONFLICT_UPDATE)
1741         {
1742                 Assert(mtstate->mt_existing != NULL);
1743                 ExecSetSlotDescriptor(mtstate->mt_existing,
1744                                                           RelationGetDescr(partrel->ri_RelationDesc));
1745                 Assert(mtstate->mt_conflproj != NULL);
1746                 ExecSetSlotDescriptor(mtstate->mt_conflproj,
1747                                                           partrel->ri_onConflict->oc_ProjTupdesc);
1748         }
1749
1750         return slot;
1751 }
1752
1753 /*
1754  * Initialize the child-to-root tuple conversion map array for UPDATE subplans.
1755  *
1756  * This map array is required to convert the tuple from the subplan result rel
1757  * to the target table descriptor. This requirement arises for two independent
1758  * scenarios:
1759  * 1. For update-tuple-routing.
1760  * 2. For capturing tuples in transition tables.
1761  */
1762 static void
1763 ExecSetupChildParentMapForSubplan(ModifyTableState *mtstate)
1764 {
1765         ResultRelInfo *targetRelInfo = getTargetResultRelInfo(mtstate);
1766         ResultRelInfo *resultRelInfos = mtstate->resultRelInfo;
1767         TupleDesc       outdesc;
1768         int                     numResultRelInfos = mtstate->mt_nplans;
1769         int                     i;
1770
1771         /*
1772          * Build array of conversion maps from each child's TupleDesc to the one
1773          * used in the target relation.  The map pointers may be NULL when no
1774          * conversion is necessary, which is hopefully a common case.
1775          */
1776
1777         /* Get tuple descriptor of the target rel. */
1778         outdesc = RelationGetDescr(targetRelInfo->ri_RelationDesc);
1779
1780         mtstate->mt_per_subplan_tupconv_maps = (TupleConversionMap **)
1781                 palloc(sizeof(TupleConversionMap *) * numResultRelInfos);
1782
1783         for (i = 0; i < numResultRelInfos; ++i)
1784         {
1785                 mtstate->mt_per_subplan_tupconv_maps[i] =
1786                         convert_tuples_by_name(RelationGetDescr(resultRelInfos[i].ri_RelationDesc),
1787                                                                    outdesc,
1788                                                                    gettext_noop("could not convert row type"));
1789         }
1790 }
1791
1792 /*
1793  * For a given subplan index, get the tuple conversion map.
1794  */
1795 static TupleConversionMap *
1796 tupconv_map_for_subplan(ModifyTableState *mtstate, int whichplan)
1797 {
1798         /* If nobody else set the per-subplan array of maps, do so ourselves. */
1799         if (mtstate->mt_per_subplan_tupconv_maps == NULL)
1800                 ExecSetupChildParentMapForSubplan(mtstate);
1801
1802         Assert(whichplan >= 0 && whichplan < mtstate->mt_nplans);
1803         return mtstate->mt_per_subplan_tupconv_maps[whichplan];
1804 }
1805
1806 /* ----------------------------------------------------------------
1807  *         ExecModifyTable
1808  *
1809  *              Perform table modifications as required, and return RETURNING results
1810  *              if needed.
1811  * ----------------------------------------------------------------
1812  */
1813 static TupleTableSlot *
1814 ExecModifyTable(PlanState *pstate)
1815 {
1816         ModifyTableState *node = castNode(ModifyTableState, pstate);
1817         PartitionTupleRouting *proute = node->mt_partition_tuple_routing;
1818         EState     *estate = node->ps.state;
1819         CmdType         operation = node->operation;
1820         ResultRelInfo *saved_resultRelInfo;
1821         ResultRelInfo *resultRelInfo;
1822         PlanState  *subplanstate;
1823         JunkFilter *junkfilter;
1824         TupleTableSlot *slot;
1825         TupleTableSlot *planSlot;
1826         ItemPointer tupleid;
1827         ItemPointerData tuple_ctid;
1828         HeapTupleData oldtupdata;
1829         HeapTuple       oldtuple;
1830
1831         CHECK_FOR_INTERRUPTS();
1832
1833         /*
1834          * This should NOT get called during EvalPlanQual; we should have passed a
1835          * subplan tree to EvalPlanQual, instead.  Use a runtime test not just
1836          * Assert because this condition is easy to miss in testing.  (Note:
1837          * although ModifyTable should not get executed within an EvalPlanQual
1838          * operation, we do have to allow it to be initialized and shut down in
1839          * case it is within a CTE subplan.  Hence this test must be here, not in
1840          * ExecInitModifyTable.)
1841          */
1842         if (estate->es_epqTuple != NULL)
1843                 elog(ERROR, "ModifyTable should not be called during EvalPlanQual");
1844
1845         /*
1846          * If we've already completed processing, don't try to do more.  We need
1847          * this test because ExecPostprocessPlan might call us an extra time, and
1848          * our subplan's nodes aren't necessarily robust against being called
1849          * extra times.
1850          */
1851         if (node->mt_done)
1852                 return NULL;
1853
1854         /*
1855          * On first call, fire BEFORE STATEMENT triggers before proceeding.
1856          */
1857         if (node->fireBSTriggers)
1858         {
1859                 fireBSTriggers(node);
1860                 node->fireBSTriggers = false;
1861         }
1862
1863         /* Preload local variables */
1864         resultRelInfo = node->resultRelInfo + node->mt_whichplan;
1865         subplanstate = node->mt_plans[node->mt_whichplan];
1866         junkfilter = resultRelInfo->ri_junkFilter;
1867
1868         /*
1869          * es_result_relation_info must point to the currently active result
1870          * relation while we are within this ModifyTable node.  Even though
1871          * ModifyTable nodes can't be nested statically, they can be nested
1872          * dynamically (since our subplan could include a reference to a modifying
1873          * CTE).  So we have to save and restore the caller's value.
1874          */
1875         saved_resultRelInfo = estate->es_result_relation_info;
1876
1877         estate->es_result_relation_info = resultRelInfo;
1878
1879         /*
1880          * Fetch rows from subplan(s), and execute the required table modification
1881          * for each row.
1882          */
1883         for (;;)
1884         {
1885                 /*
1886                  * Reset the per-output-tuple exprcontext.  This is needed because
1887                  * triggers expect to use that context as workspace.  It's a bit ugly
1888                  * to do this below the top level of the plan, however.  We might need
1889                  * to rethink this later.
1890                  */
1891                 ResetPerTupleExprContext(estate);
1892
1893                 /*
1894                  * Reset per-tuple memory context used for processing on conflict and
1895                  * returning clauses, to free any expression evaluation storage
1896                  * allocated in the previous cycle.
1897                  */
1898                 if (pstate->ps_ExprContext)
1899                         ResetExprContext(pstate->ps_ExprContext);
1900
1901                 planSlot = ExecProcNode(subplanstate);
1902
1903                 if (TupIsNull(planSlot))
1904                 {
1905                         /* advance to next subplan if any */
1906                         node->mt_whichplan++;
1907                         if (node->mt_whichplan < node->mt_nplans)
1908                         {
1909                                 resultRelInfo++;
1910                                 subplanstate = node->mt_plans[node->mt_whichplan];
1911                                 junkfilter = resultRelInfo->ri_junkFilter;
1912                                 estate->es_result_relation_info = resultRelInfo;
1913                                 EvalPlanQualSetPlan(&node->mt_epqstate, subplanstate->plan,
1914                                                                         node->mt_arowmarks[node->mt_whichplan]);
1915                                 /* Prepare to convert transition tuples from this child. */
1916                                 if (node->mt_transition_capture != NULL)
1917                                 {
1918                                         node->mt_transition_capture->tcs_map =
1919                                                 tupconv_map_for_subplan(node, node->mt_whichplan);
1920                                 }
1921                                 if (node->mt_oc_transition_capture != NULL)
1922                                 {
1923                                         node->mt_oc_transition_capture->tcs_map =
1924                                                 tupconv_map_for_subplan(node, node->mt_whichplan);
1925                                 }
1926                                 continue;
1927                         }
1928                         else
1929                                 break;
1930                 }
1931
1932                 /*
1933                  * Ensure input tuple is the right format for the target relation.
1934                  */
1935                 if (node->mt_scans[node->mt_whichplan]->tts_ops != planSlot->tts_ops)
1936                 {
1937                         ExecCopySlot(node->mt_scans[node->mt_whichplan], planSlot);
1938                         planSlot = node->mt_scans[node->mt_whichplan];
1939                 }
1940
1941                 /*
1942                  * If resultRelInfo->ri_usesFdwDirectModify is true, all we need to do
1943                  * here is compute the RETURNING expressions.
1944                  */
1945                 if (resultRelInfo->ri_usesFdwDirectModify)
1946                 {
1947                         Assert(resultRelInfo->ri_projectReturning);
1948
1949                         /*
1950                          * A scan slot containing the data that was actually inserted,
1951                          * updated or deleted has already been made available to
1952                          * ExecProcessReturning by IterateDirectModify, so no need to
1953                          * provide it here.
1954                          */
1955                         slot = ExecProcessReturning(resultRelInfo, NULL, planSlot);
1956
1957                         estate->es_result_relation_info = saved_resultRelInfo;
1958                         return slot;
1959                 }
1960
1961                 EvalPlanQualSetSlot(&node->mt_epqstate, planSlot);
1962                 slot = planSlot;
1963
1964                 tupleid = NULL;
1965                 oldtuple = NULL;
1966                 if (junkfilter != NULL)
1967                 {
1968                         /*
1969                          * extract the 'ctid' or 'wholerow' junk attribute.
1970                          */
1971                         if (operation == CMD_UPDATE || operation == CMD_DELETE)
1972                         {
1973                                 char            relkind;
1974                                 Datum           datum;
1975                                 bool            isNull;
1976
1977                                 relkind = resultRelInfo->ri_RelationDesc->rd_rel->relkind;
1978                                 if (relkind == RELKIND_RELATION || relkind == RELKIND_MATVIEW)
1979                                 {
1980                                         datum = ExecGetJunkAttribute(slot,
1981                                                                                                  junkfilter->jf_junkAttNo,
1982                                                                                                  &isNull);
1983                                         /* shouldn't ever get a null result... */
1984                                         if (isNull)
1985                                                 elog(ERROR, "ctid is NULL");
1986
1987                                         tupleid = (ItemPointer) DatumGetPointer(datum);
1988                                         tuple_ctid = *tupleid;  /* be sure we don't free ctid!! */
1989                                         tupleid = &tuple_ctid;
1990                                 }
1991
1992                                 /*
1993                                  * Use the wholerow attribute, when available, to reconstruct
1994                                  * the old relation tuple.
1995                                  *
1996                                  * Foreign table updates have a wholerow attribute when the
1997                                  * relation has a row-level trigger.  Note that the wholerow
1998                                  * attribute does not carry system columns.  Foreign table
1999                                  * triggers miss seeing those, except that we know enough here
2000                                  * to set t_tableOid.  Quite separately from this, the FDW may
2001                                  * fetch its own junk attrs to identify the row.
2002                                  *
2003                                  * Other relevant relkinds, currently limited to views, always
2004                                  * have a wholerow attribute.
2005                                  */
2006                                 else if (AttributeNumberIsValid(junkfilter->jf_junkAttNo))
2007                                 {
2008                                         datum = ExecGetJunkAttribute(slot,
2009                                                                                                  junkfilter->jf_junkAttNo,
2010                                                                                                  &isNull);
2011                                         /* shouldn't ever get a null result... */
2012                                         if (isNull)
2013                                                 elog(ERROR, "wholerow is NULL");
2014
2015                                         oldtupdata.t_data = DatumGetHeapTupleHeader(datum);
2016                                         oldtupdata.t_len =
2017                                                 HeapTupleHeaderGetDatumLength(oldtupdata.t_data);
2018                                         ItemPointerSetInvalid(&(oldtupdata.t_self));
2019                                         /* Historically, view triggers see invalid t_tableOid. */
2020                                         oldtupdata.t_tableOid =
2021                                                 (relkind == RELKIND_VIEW) ? InvalidOid :
2022                                                 RelationGetRelid(resultRelInfo->ri_RelationDesc);
2023
2024                                         oldtuple = &oldtupdata;
2025                                 }
2026                                 else
2027                                         Assert(relkind == RELKIND_FOREIGN_TABLE);
2028                         }
2029
2030                         /*
2031                          * apply the junkfilter if needed.
2032                          */
2033                         if (operation != CMD_DELETE)
2034                                 slot = ExecFilterJunk(junkfilter, slot);
2035                 }
2036
2037                 switch (operation)
2038                 {
2039                         case CMD_INSERT:
2040                                 /* Prepare for tuple routing if needed. */
2041                                 if (proute)
2042                                         slot = ExecPrepareTupleRouting(node, estate, proute,
2043                                                                                                    resultRelInfo, slot);
2044                                 slot = ExecInsert(node, slot, planSlot,
2045                                                                   estate, node->canSetTag);
2046                                 /* Revert ExecPrepareTupleRouting's state change. */
2047                                 if (proute)
2048                                         estate->es_result_relation_info = resultRelInfo;
2049                                 break;
2050                         case CMD_UPDATE:
2051                                 slot = ExecUpdate(node, tupleid, oldtuple, slot, planSlot,
2052                                                                   &node->mt_epqstate, estate, node->canSetTag);
2053                                 break;
2054                         case CMD_DELETE:
2055                                 slot = ExecDelete(node, tupleid, oldtuple, planSlot,
2056                                                                   &node->mt_epqstate, estate,
2057                                                                   true, node->canSetTag,
2058                                                                   false /* changingPart */ , NULL, NULL);
2059                                 break;
2060                         default:
2061                                 elog(ERROR, "unknown operation");
2062                                 break;
2063                 }
2064
2065                 /*
2066                  * If we got a RETURNING result, return it to caller.  We'll continue
2067                  * the work on next call.
2068                  */
2069                 if (slot)
2070                 {
2071                         estate->es_result_relation_info = saved_resultRelInfo;
2072                         return slot;
2073                 }
2074         }
2075
2076         /* Restore es_result_relation_info before exiting */
2077         estate->es_result_relation_info = saved_resultRelInfo;
2078
2079         /*
2080          * We're done, but fire AFTER STATEMENT triggers before exiting.
2081          */
2082         fireASTriggers(node);
2083
2084         node->mt_done = true;
2085
2086         return NULL;
2087 }
2088
2089 /* ----------------------------------------------------------------
2090  *              ExecInitModifyTable
2091  * ----------------------------------------------------------------
2092  */
2093 ModifyTableState *
2094 ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
2095 {
2096         ModifyTableState *mtstate;
2097         CmdType         operation = node->operation;
2098         int                     nplans = list_length(node->plans);
2099         ResultRelInfo *saved_resultRelInfo;
2100         ResultRelInfo *resultRelInfo;
2101         Plan       *subplan;
2102         ListCell   *l;
2103         int                     i;
2104         Relation        rel;
2105         bool            update_tuple_routing_needed = node->partColsUpdated;
2106
2107         /* check for unsupported flags */
2108         Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
2109
2110         /*
2111          * create state structure
2112          */
2113         mtstate = makeNode(ModifyTableState);
2114         mtstate->ps.plan = (Plan *) node;
2115         mtstate->ps.state = estate;
2116         mtstate->ps.ExecProcNode = ExecModifyTable;
2117
2118         mtstate->operation = operation;
2119         mtstate->canSetTag = node->canSetTag;
2120         mtstate->mt_done = false;
2121
2122         mtstate->mt_plans = (PlanState **) palloc0(sizeof(PlanState *) * nplans);
2123         mtstate->resultRelInfo = estate->es_result_relations + node->resultRelIndex;
2124         mtstate->mt_scans = (TupleTableSlot **) palloc0(sizeof(TupleTableSlot *) * nplans);
2125
2126         /* If modifying a partitioned table, initialize the root table info */
2127         if (node->rootResultRelIndex >= 0)
2128                 mtstate->rootResultRelInfo = estate->es_root_result_relations +
2129                         node->rootResultRelIndex;
2130
2131         mtstate->mt_arowmarks = (List **) palloc0(sizeof(List *) * nplans);
2132         mtstate->mt_nplans = nplans;
2133
2134         /* set up epqstate with dummy subplan data for the moment */
2135         EvalPlanQualInit(&mtstate->mt_epqstate, estate, NULL, NIL, node->epqParam);
2136         mtstate->fireBSTriggers = true;
2137
2138         /*
2139          * call ExecInitNode on each of the plans to be executed and save the
2140          * results into the array "mt_plans".  This is also a convenient place to
2141          * verify that the proposed target relations are valid and open their
2142          * indexes for insertion of new index entries.  Note we *must* set
2143          * estate->es_result_relation_info correctly while we initialize each
2144          * sub-plan; ExecContextForcesOids depends on that!
2145          */
2146         saved_resultRelInfo = estate->es_result_relation_info;
2147
2148         resultRelInfo = mtstate->resultRelInfo;
2149         i = 0;
2150         foreach(l, node->plans)
2151         {
2152                 subplan = (Plan *) lfirst(l);
2153
2154                 /* Initialize the usesFdwDirectModify flag */
2155                 resultRelInfo->ri_usesFdwDirectModify = bms_is_member(i,
2156                                                                                                                           node->fdwDirectModifyPlans);
2157
2158                 /*
2159                  * Verify result relation is a valid target for the current operation
2160                  */
2161                 CheckValidResultRel(resultRelInfo, operation);
2162
2163                 /*
2164                  * If there are indices on the result relation, open them and save
2165                  * descriptors in the result relation info, so that we can add new
2166                  * index entries for the tuples we add/update.  We need not do this
2167                  * for a DELETE, however, since deletion doesn't affect indexes. Also,
2168                  * inside an EvalPlanQual operation, the indexes might be open
2169                  * already, since we share the resultrel state with the original
2170                  * query.
2171                  */
2172                 if (resultRelInfo->ri_RelationDesc->rd_rel->relhasindex &&
2173                         operation != CMD_DELETE &&
2174                         resultRelInfo->ri_IndexRelationDescs == NULL)
2175                         ExecOpenIndices(resultRelInfo,
2176                                                         node->onConflictAction != ONCONFLICT_NONE);
2177
2178                 /*
2179                  * If this is an UPDATE and a BEFORE UPDATE trigger is present, the
2180                  * trigger itself might modify the partition-key values. So arrange
2181                  * for tuple routing.
2182                  */
2183                 if (resultRelInfo->ri_TrigDesc &&
2184                         resultRelInfo->ri_TrigDesc->trig_update_before_row &&
2185                         operation == CMD_UPDATE)
2186                         update_tuple_routing_needed = true;
2187
2188                 /* Now init the plan for this result rel */
2189                 estate->es_result_relation_info = resultRelInfo;
2190                 mtstate->mt_plans[i] = ExecInitNode(subplan, estate, eflags);
2191                 mtstate->mt_scans[i] =
2192                         ExecInitExtraTupleSlot(mtstate->ps.state, ExecGetResultType(mtstate->mt_plans[i]),
2193                                                                    &TTSOpsHeapTuple);
2194
2195                 /* Also let FDWs init themselves for foreign-table result rels */
2196                 if (!resultRelInfo->ri_usesFdwDirectModify &&
2197                         resultRelInfo->ri_FdwRoutine != NULL &&
2198                         resultRelInfo->ri_FdwRoutine->BeginForeignModify != NULL)
2199                 {
2200                         List       *fdw_private = (List *) list_nth(node->fdwPrivLists, i);
2201
2202                         resultRelInfo->ri_FdwRoutine->BeginForeignModify(mtstate,
2203                                                                                                                          resultRelInfo,
2204                                                                                                                          fdw_private,
2205                                                                                                                          i,
2206                                                                                                                          eflags);
2207                 }
2208
2209                 resultRelInfo++;
2210                 i++;
2211         }
2212
2213         estate->es_result_relation_info = saved_resultRelInfo;
2214
2215         /* Get the target relation */
2216         rel = (getTargetResultRelInfo(mtstate))->ri_RelationDesc;
2217
2218         /*
2219          * If it's not a partitioned table after all, UPDATE tuple routing should
2220          * not be attempted.
2221          */
2222         if (rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
2223                 update_tuple_routing_needed = false;
2224
2225         /*
2226          * Build state for tuple routing if it's an INSERT or if it's an UPDATE of
2227          * partition key.
2228          */
2229         if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
2230                 (operation == CMD_INSERT || update_tuple_routing_needed))
2231                 mtstate->mt_partition_tuple_routing =
2232                         ExecSetupPartitionTupleRouting(mtstate, rel);
2233
2234         /*
2235          * Build state for collecting transition tuples.  This requires having a
2236          * valid trigger query context, so skip it in explain-only mode.
2237          */
2238         if (!(eflags & EXEC_FLAG_EXPLAIN_ONLY))
2239                 ExecSetupTransitionCaptureState(mtstate, estate);
2240
2241         /*
2242          * Construct mapping from each of the per-subplan partition attnos to the
2243          * root attno.  This is required when during update row movement the tuple
2244          * descriptor of a source partition does not match the root partitioned
2245          * table descriptor.  In such a case we need to convert tuples to the root
2246          * tuple descriptor, because the search for destination partition starts
2247          * from the root.  We'll also need a slot to store these converted tuples.
2248          * We can skip this setup if it's not a partition key update.
2249          */
2250         if (update_tuple_routing_needed)
2251         {
2252                 ExecSetupChildParentMapForSubplan(mtstate);
2253                 mtstate->mt_root_tuple_slot = MakeTupleTableSlot(RelationGetDescr(rel),
2254                                                                                                                  &TTSOpsHeapTuple);
2255         }
2256
2257         /*
2258          * Initialize any WITH CHECK OPTION constraints if needed.
2259          */
2260         resultRelInfo = mtstate->resultRelInfo;
2261         i = 0;
2262         foreach(l, node->withCheckOptionLists)
2263         {
2264                 List       *wcoList = (List *) lfirst(l);
2265                 List       *wcoExprs = NIL;
2266                 ListCell   *ll;
2267
2268                 foreach(ll, wcoList)
2269                 {
2270                         WithCheckOption *wco = (WithCheckOption *) lfirst(ll);
2271                         ExprState  *wcoExpr = ExecInitQual((List *) wco->qual,
2272                                                                                            &mtstate->ps);
2273
2274                         wcoExprs = lappend(wcoExprs, wcoExpr);
2275                 }
2276
2277                 resultRelInfo->ri_WithCheckOptions = wcoList;
2278                 resultRelInfo->ri_WithCheckOptionExprs = wcoExprs;
2279                 resultRelInfo++;
2280                 i++;
2281         }
2282
2283         /*
2284          * Initialize RETURNING projections if needed.
2285          */
2286         if (node->returningLists)
2287         {
2288                 TupleTableSlot *slot;
2289                 ExprContext *econtext;
2290
2291                 /*
2292                  * Initialize result tuple slot and assign its rowtype using the first
2293                  * RETURNING list.  We assume the rest will look the same.
2294                  */
2295                 mtstate->ps.plan->targetlist = (List *) linitial(node->returningLists);
2296
2297                 /* Set up a slot for the output of the RETURNING projection(s) */
2298                 ExecInitResultTupleSlotTL(&mtstate->ps, &TTSOpsVirtual);
2299                 slot = mtstate->ps.ps_ResultTupleSlot;
2300
2301                 /* Need an econtext too */
2302                 if (mtstate->ps.ps_ExprContext == NULL)
2303                         ExecAssignExprContext(estate, &mtstate->ps);
2304                 econtext = mtstate->ps.ps_ExprContext;
2305
2306                 /*
2307                  * Build a projection for each result rel.
2308                  */
2309                 resultRelInfo = mtstate->resultRelInfo;
2310                 foreach(l, node->returningLists)
2311                 {
2312                         List       *rlist = (List *) lfirst(l);
2313
2314                         resultRelInfo->ri_returningList = rlist;
2315                         resultRelInfo->ri_projectReturning =
2316                                 ExecBuildProjectionInfo(rlist, econtext, slot, &mtstate->ps,
2317                                                                                 resultRelInfo->ri_RelationDesc->rd_att);
2318                         resultRelInfo++;
2319                 }
2320         }
2321         else
2322         {
2323                 /*
2324                  * We still must construct a dummy result tuple type, because InitPlan
2325                  * expects one (maybe should change that?).
2326                  */
2327                 mtstate->ps.plan->targetlist = NIL;
2328                 ExecInitResultTypeTL(&mtstate->ps);
2329
2330                 mtstate->ps.ps_ExprContext = NULL;
2331         }
2332
2333         /* Set the list of arbiter indexes if needed for ON CONFLICT */
2334         resultRelInfo = mtstate->resultRelInfo;
2335         if (node->onConflictAction != ONCONFLICT_NONE)
2336                 resultRelInfo->ri_onConflictArbiterIndexes = node->arbiterIndexes;
2337
2338         /*
2339          * If needed, Initialize target list, projection and qual for ON CONFLICT
2340          * DO UPDATE.
2341          */
2342         if (node->onConflictAction == ONCONFLICT_UPDATE)
2343         {
2344                 ExprContext *econtext;
2345                 TupleDesc       relationDesc;
2346                 TupleDesc       tupDesc;
2347
2348                 /* insert may only have one plan, inheritance is not expanded */
2349                 Assert(nplans == 1);
2350
2351                 /* already exists if created by RETURNING processing above */
2352                 if (mtstate->ps.ps_ExprContext == NULL)
2353                         ExecAssignExprContext(estate, &mtstate->ps);
2354
2355                 econtext = mtstate->ps.ps_ExprContext;
2356                 relationDesc = resultRelInfo->ri_RelationDesc->rd_att;
2357
2358                 /*
2359                  * Initialize slot for the existing tuple.  If we'll be performing
2360                  * tuple routing, the tuple descriptor to use for this will be
2361                  * determined based on which relation the update is actually applied
2362                  * to, so we don't set its tuple descriptor here.
2363                  */
2364                 mtstate->mt_existing =
2365                         ExecInitExtraTupleSlot(mtstate->ps.state,
2366                                                                    mtstate->mt_partition_tuple_routing ?
2367                                                                    NULL : relationDesc, &TTSOpsBufferHeapTuple);
2368
2369                 /* carried forward solely for the benefit of explain */
2370                 mtstate->mt_excludedtlist = node->exclRelTlist;
2371
2372                 /* create state for DO UPDATE SET operation */
2373                 resultRelInfo->ri_onConflict = makeNode(OnConflictSetState);
2374
2375                 /*
2376                  * Create the tuple slot for the UPDATE SET projection.
2377                  *
2378                  * Just like mt_existing above, we leave it without a tuple descriptor
2379                  * in the case of partitioning tuple routing, so that it can be
2380                  * changed by ExecPrepareTupleRouting.  In that case, we still save
2381                  * the tupdesc in the parent's state: it can be reused by partitions
2382                  * with an identical descriptor to the parent.
2383                  */
2384                 tupDesc = ExecTypeFromTL((List *) node->onConflictSet);
2385                 mtstate->mt_conflproj =
2386                         ExecInitExtraTupleSlot(mtstate->ps.state,
2387                                                                    mtstate->mt_partition_tuple_routing ?
2388                                                                    NULL : tupDesc, &TTSOpsHeapTuple);
2389                 resultRelInfo->ri_onConflict->oc_ProjTupdesc = tupDesc;
2390
2391                 /* build UPDATE SET projection state */
2392                 resultRelInfo->ri_onConflict->oc_ProjInfo =
2393                         ExecBuildProjectionInfo(node->onConflictSet, econtext,
2394                                                                         mtstate->mt_conflproj, &mtstate->ps,
2395                                                                         relationDesc);
2396
2397                 /* initialize state to evaluate the WHERE clause, if any */
2398                 if (node->onConflictWhere)
2399                 {
2400                         ExprState  *qualexpr;
2401
2402                         qualexpr = ExecInitQual((List *) node->onConflictWhere,
2403                                                                         &mtstate->ps);
2404                         resultRelInfo->ri_onConflict->oc_WhereClause = qualexpr;
2405                 }
2406         }
2407
2408         /*
2409          * If we have any secondary relations in an UPDATE or DELETE, they need to
2410          * be treated like non-locked relations in SELECT FOR UPDATE, ie, the
2411          * EvalPlanQual mechanism needs to be told about them.  Locate the
2412          * relevant ExecRowMarks.
2413          */
2414         foreach(l, node->rowMarks)
2415         {
2416                 PlanRowMark *rc = lfirst_node(PlanRowMark, l);
2417                 ExecRowMark *erm;
2418
2419                 /* ignore "parent" rowmarks; they are irrelevant at runtime */
2420                 if (rc->isParent)
2421                         continue;
2422
2423                 /* find ExecRowMark (same for all subplans) */
2424                 erm = ExecFindRowMark(estate, rc->rti, false);
2425
2426                 /* build ExecAuxRowMark for each subplan */
2427                 for (i = 0; i < nplans; i++)
2428                 {
2429                         ExecAuxRowMark *aerm;
2430
2431                         subplan = mtstate->mt_plans[i]->plan;
2432                         aerm = ExecBuildAuxRowMark(erm, subplan->targetlist);
2433                         mtstate->mt_arowmarks[i] = lappend(mtstate->mt_arowmarks[i], aerm);
2434                 }
2435         }
2436
2437         /* select first subplan */
2438         mtstate->mt_whichplan = 0;
2439         subplan = (Plan *) linitial(node->plans);
2440         EvalPlanQualSetPlan(&mtstate->mt_epqstate, subplan,
2441                                                 mtstate->mt_arowmarks[0]);
2442
2443         /*
2444          * Initialize the junk filter(s) if needed.  INSERT queries need a filter
2445          * if there are any junk attrs in the tlist.  UPDATE and DELETE always
2446          * need a filter, since there's always at least one junk attribute present
2447          * --- no need to look first.  Typically, this will be a 'ctid' or
2448          * 'wholerow' attribute, but in the case of a foreign data wrapper it
2449          * might be a set of junk attributes sufficient to identify the remote
2450          * row.
2451          *
2452          * If there are multiple result relations, each one needs its own junk
2453          * filter.  Note multiple rels are only possible for UPDATE/DELETE, so we
2454          * can't be fooled by some needing a filter and some not.
2455          *
2456          * This section of code is also a convenient place to verify that the
2457          * output of an INSERT or UPDATE matches the target table(s).
2458          */
2459         {
2460                 bool            junk_filter_needed = false;
2461
2462                 switch (operation)
2463                 {
2464                         case CMD_INSERT:
2465                                 foreach(l, subplan->targetlist)
2466                                 {
2467                                         TargetEntry *tle = (TargetEntry *) lfirst(l);
2468
2469                                         if (tle->resjunk)
2470                                         {
2471                                                 junk_filter_needed = true;
2472                                                 break;
2473                                         }
2474                                 }
2475                                 break;
2476                         case CMD_UPDATE:
2477                         case CMD_DELETE:
2478                                 junk_filter_needed = true;
2479                                 break;
2480                         default:
2481                                 elog(ERROR, "unknown operation");
2482                                 break;
2483                 }
2484
2485                 if (junk_filter_needed)
2486                 {
2487                         resultRelInfo = mtstate->resultRelInfo;
2488                         for (i = 0; i < nplans; i++)
2489                         {
2490                                 JunkFilter *j;
2491
2492                                 subplan = mtstate->mt_plans[i]->plan;
2493                                 if (operation == CMD_INSERT || operation == CMD_UPDATE)
2494                                         ExecCheckPlanOutput(resultRelInfo->ri_RelationDesc,
2495                                                                                 subplan->targetlist);
2496
2497                                 j = ExecInitJunkFilter(subplan->targetlist,
2498                                                                            ExecInitExtraTupleSlot(estate, NULL,
2499                                                                                                                           &TTSOpsHeapTuple));
2500
2501                                 if (operation == CMD_UPDATE || operation == CMD_DELETE)
2502                                 {
2503                                         /* For UPDATE/DELETE, find the appropriate junk attr now */
2504                                         char            relkind;
2505
2506                                         relkind = resultRelInfo->ri_RelationDesc->rd_rel->relkind;
2507                                         if (relkind == RELKIND_RELATION ||
2508                                                 relkind == RELKIND_MATVIEW ||
2509                                                 relkind == RELKIND_PARTITIONED_TABLE)
2510                                         {
2511                                                 j->jf_junkAttNo = ExecFindJunkAttribute(j, "ctid");
2512                                                 if (!AttributeNumberIsValid(j->jf_junkAttNo))
2513                                                         elog(ERROR, "could not find junk ctid column");
2514                                         }
2515                                         else if (relkind == RELKIND_FOREIGN_TABLE)
2516                                         {
2517                                                 /*
2518                                                  * When there is a row-level trigger, there should be
2519                                                  * a wholerow attribute.
2520                                                  */
2521                                                 j->jf_junkAttNo = ExecFindJunkAttribute(j, "wholerow");
2522                                         }
2523                                         else
2524                                         {
2525                                                 j->jf_junkAttNo = ExecFindJunkAttribute(j, "wholerow");
2526                                                 if (!AttributeNumberIsValid(j->jf_junkAttNo))
2527                                                         elog(ERROR, "could not find junk wholerow column");
2528                                         }
2529                                 }
2530
2531                                 resultRelInfo->ri_junkFilter = j;
2532                                 resultRelInfo++;
2533                         }
2534                 }
2535                 else
2536                 {
2537                         if (operation == CMD_INSERT)
2538                                 ExecCheckPlanOutput(mtstate->resultRelInfo->ri_RelationDesc,
2539                                                                         subplan->targetlist);
2540                 }
2541         }
2542
2543         /*
2544          * Set up a tuple table slot for use for trigger output tuples. In a plan
2545          * containing multiple ModifyTable nodes, all can share one such slot, so
2546          * we keep it in the estate. The tuple being inserted doesn't come from a
2547          * buffer.
2548          */
2549         if (estate->es_trig_tuple_slot == NULL)
2550                 estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL,
2551                                                                                                                         &TTSOpsHeapTuple);
2552
2553         /*
2554          * Lastly, if this is not the primary (canSetTag) ModifyTable node, add it
2555          * to estate->es_auxmodifytables so that it will be run to completion by
2556          * ExecPostprocessPlan.  (It'd actually work fine to add the primary
2557          * ModifyTable node too, but there's no need.)  Note the use of lcons not
2558          * lappend: we need later-initialized ModifyTable nodes to be shut down
2559          * before earlier ones.  This ensures that we don't throw away RETURNING
2560          * rows that need to be seen by a later CTE subplan.
2561          */
2562         if (!mtstate->canSetTag)
2563                 estate->es_auxmodifytables = lcons(mtstate,
2564                                                                                    estate->es_auxmodifytables);
2565
2566         return mtstate;
2567 }
2568
2569 /* ----------------------------------------------------------------
2570  *              ExecEndModifyTable
2571  *
2572  *              Shuts down the plan.
2573  *
2574  *              Returns nothing of interest.
2575  * ----------------------------------------------------------------
2576  */
2577 void
2578 ExecEndModifyTable(ModifyTableState *node)
2579 {
2580         int                     i;
2581
2582         /*
2583          * Allow any FDWs to shut down
2584          */
2585         for (i = 0; i < node->mt_nplans; i++)
2586         {
2587                 ResultRelInfo *resultRelInfo = node->resultRelInfo + i;
2588
2589                 if (!resultRelInfo->ri_usesFdwDirectModify &&
2590                         resultRelInfo->ri_FdwRoutine != NULL &&
2591                         resultRelInfo->ri_FdwRoutine->EndForeignModify != NULL)
2592                         resultRelInfo->ri_FdwRoutine->EndForeignModify(node->ps.state,
2593                                                                                                                    resultRelInfo);
2594         }
2595
2596         /*
2597          * Close all the partitioned tables, leaf partitions, and their indices
2598          * and release the slot used for tuple routing, if set.
2599          */
2600         if (node->mt_partition_tuple_routing)
2601         {
2602                 ExecCleanupTupleRouting(node, node->mt_partition_tuple_routing);
2603
2604                 if (node->mt_root_tuple_slot)
2605                         ExecDropSingleTupleTableSlot(node->mt_root_tuple_slot);
2606         }
2607
2608         /*
2609          * Free the exprcontext
2610          */
2611         ExecFreeExprContext(&node->ps);
2612
2613         /*
2614          * clean out the tuple table
2615          */
2616         if (node->ps.ps_ResultTupleSlot)
2617                 ExecClearTuple(node->ps.ps_ResultTupleSlot);
2618
2619         /*
2620          * Terminate EPQ execution if active
2621          */
2622         EvalPlanQualEnd(&node->mt_epqstate);
2623
2624         /*
2625          * shut down subplans
2626          */
2627         for (i = 0; i < node->mt_nplans; i++)
2628                 ExecEndNode(node->mt_plans[i]);
2629 }
2630
2631 void
2632 ExecReScanModifyTable(ModifyTableState *node)
2633 {
2634         /*
2635          * Currently, we don't need to support rescan on ModifyTable nodes. The
2636          * semantics of that would be a bit debatable anyway.
2637          */
2638         elog(ERROR, "ExecReScanModifyTable is not implemented");
2639 }