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