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