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