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