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