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  * GENERATED expressions might reference the tableoid column, so
663  * (re-)initialize tts_tableOid before evaluating them.
664  */
665  slot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
666 
667  /*
668  * Compute stored generated columns
669  */
670  if (resultRelationDesc->rd_att->constr &&
671  resultRelationDesc->rd_att->constr->has_generated_stored)
672  ExecComputeStoredGenerated(resultRelInfo, estate, slot,
673  CMD_INSERT);
674 
675  /*
676  * If the FDW supports batching, and batching is requested, accumulate
677  * rows and insert them in batches. Otherwise use the per-row inserts.
678  */
679  if (resultRelInfo->ri_BatchSize > 1)
680  {
681  /*
682  * If a certain number of tuples have already been accumulated, or
683  * a tuple has come for a different relation than that for the
684  * accumulated tuples, perform the batch insert
685  */
686  if (resultRelInfo->ri_NumSlots == resultRelInfo->ri_BatchSize)
687  {
688  ExecBatchInsert(mtstate, resultRelInfo,
689  resultRelInfo->ri_Slots,
690  resultRelInfo->ri_PlanSlots,
691  resultRelInfo->ri_NumSlots,
692  estate, canSetTag);
693  resultRelInfo->ri_NumSlots = 0;
694  }
695 
696  oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
697 
698  if (resultRelInfo->ri_Slots == NULL)
699  {
700  resultRelInfo->ri_Slots = palloc(sizeof(TupleTableSlot *) *
701  resultRelInfo->ri_BatchSize);
702  resultRelInfo->ri_PlanSlots = palloc(sizeof(TupleTableSlot *) *
703  resultRelInfo->ri_BatchSize);
704  }
705 
706  /*
707  * Initialize the batch slots. We don't know how many slots will
708  * be needed, so we initialize them as the batch grows, and we
709  * keep them across batches. To mitigate an inefficiency in how
710  * resource owner handles objects with many references (as with
711  * many slots all referencing the same tuple descriptor) we copy
712  * the tuple descriptor for each slot.
713  */
714  if (resultRelInfo->ri_NumSlots >= resultRelInfo->ri_NumSlotsInitialized)
715  {
717 
718  resultRelInfo->ri_Slots[resultRelInfo->ri_NumSlots] =
719  MakeSingleTupleTableSlot(tdesc, slot->tts_ops);
720 
721  resultRelInfo->ri_PlanSlots[resultRelInfo->ri_NumSlots] =
722  MakeSingleTupleTableSlot(tdesc, planSlot->tts_ops);
723 
724  /* remember how many batch slots we initialized */
725  resultRelInfo->ri_NumSlotsInitialized++;
726  }
727 
728  ExecCopySlot(resultRelInfo->ri_Slots[resultRelInfo->ri_NumSlots],
729  slot);
730 
731  ExecCopySlot(resultRelInfo->ri_PlanSlots[resultRelInfo->ri_NumSlots],
732  planSlot);
733 
734  resultRelInfo->ri_NumSlots++;
735 
736  MemoryContextSwitchTo(oldContext);
737 
738  return NULL;
739  }
740 
741  /*
742  * insert into foreign table: let the FDW do it
743  */
744  slot = resultRelInfo->ri_FdwRoutine->ExecForeignInsert(estate,
745  resultRelInfo,
746  slot,
747  planSlot);
748 
749  if (slot == NULL) /* "do nothing" */
750  return NULL;
751 
752  /*
753  * AFTER ROW Triggers or RETURNING expressions might reference the
754  * tableoid column, so (re-)initialize tts_tableOid before evaluating
755  * them. (This covers the case where the FDW replaced the slot.)
756  */
757  slot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
758  }
759  else
760  {
761  WCOKind wco_kind;
762 
763  /*
764  * Constraints and GENERATED expressions might reference the tableoid
765  * column, so (re-)initialize tts_tableOid before evaluating them.
766  */
767  slot->tts_tableOid = RelationGetRelid(resultRelationDesc);
768 
769  /*
770  * Compute stored generated columns
771  */
772  if (resultRelationDesc->rd_att->constr &&
773  resultRelationDesc->rd_att->constr->has_generated_stored)
774  ExecComputeStoredGenerated(resultRelInfo, estate, slot,
775  CMD_INSERT);
776 
777  /*
778  * Check any RLS WITH CHECK policies.
779  *
780  * Normally we should check INSERT policies. But if the insert is the
781  * result of a partition key update that moved the tuple to a new
782  * partition, we should instead check UPDATE policies, because we are
783  * executing policies defined on the target table, and not those
784  * defined on the child partitions.
785  */
786  wco_kind = (mtstate->operation == CMD_UPDATE) ?
788 
789  /*
790  * ExecWithCheckOptions() will skip any WCOs which are not of the kind
791  * we are looking for at this point.
792  */
793  if (resultRelInfo->ri_WithCheckOptions != NIL)
794  ExecWithCheckOptions(wco_kind, resultRelInfo, slot, estate);
795 
796  /*
797  * Check the constraints of the tuple.
798  */
799  if (resultRelationDesc->rd_att->constr)
800  ExecConstraints(resultRelInfo, slot, estate);
801 
802  /*
803  * Also check the tuple against the partition constraint, if there is
804  * one; except that if we got here via tuple-routing, we don't need to
805  * if there's no BR trigger defined on the partition.
806  */
807  if (resultRelationDesc->rd_rel->relispartition &&
808  (resultRelInfo->ri_RootResultRelInfo == NULL ||
809  (resultRelInfo->ri_TrigDesc &&
810  resultRelInfo->ri_TrigDesc->trig_insert_before_row)))
811  ExecPartitionCheck(resultRelInfo, slot, estate, true);
812 
813  if (onconflict != ONCONFLICT_NONE && resultRelInfo->ri_NumIndices > 0)
814  {
815  /* Perform a speculative insertion. */
816  uint32 specToken;
817  ItemPointerData conflictTid;
818  bool specConflict;
819  List *arbiterIndexes;
820 
821  arbiterIndexes = resultRelInfo->ri_onConflictArbiterIndexes;
822 
823  /*
824  * Do a non-conclusive check for conflicts first.
825  *
826  * We're not holding any locks yet, so this doesn't guarantee that
827  * the later insert won't conflict. But it avoids leaving behind
828  * a lot of canceled speculative insertions, if you run a lot of
829  * INSERT ON CONFLICT statements that do conflict.
830  *
831  * We loop back here if we find a conflict below, either during
832  * the pre-check, or when we re-check after inserting the tuple
833  * speculatively.
834  */
835  vlock:
836  specConflict = false;
837  if (!ExecCheckIndexConstraints(resultRelInfo, slot, estate,
838  &conflictTid, arbiterIndexes))
839  {
840  /* committed conflict tuple found */
841  if (onconflict == ONCONFLICT_UPDATE)
842  {
843  /*
844  * In case of ON CONFLICT DO UPDATE, execute the UPDATE
845  * part. Be prepared to retry if the UPDATE fails because
846  * of another concurrent UPDATE/DELETE to the conflict
847  * tuple.
848  */
849  TupleTableSlot *returning = NULL;
850 
851  if (ExecOnConflictUpdate(mtstate, resultRelInfo,
852  &conflictTid, planSlot, slot,
853  estate, canSetTag, &returning))
854  {
855  InstrCountTuples2(&mtstate->ps, 1);
856  return returning;
857  }
858  else
859  goto vlock;
860  }
861  else
862  {
863  /*
864  * In case of ON CONFLICT DO NOTHING, do nothing. However,
865  * verify that the tuple is visible to the executor's MVCC
866  * snapshot at higher isolation levels.
867  *
868  * Using ExecGetReturningSlot() to store the tuple for the
869  * recheck isn't that pretty, but we can't trivially use
870  * the input slot, because it might not be of a compatible
871  * type. As there's no conflicting usage of
872  * ExecGetReturningSlot() in the DO NOTHING case...
873  */
874  Assert(onconflict == ONCONFLICT_NOTHING);
875  ExecCheckTIDVisible(estate, resultRelInfo, &conflictTid,
876  ExecGetReturningSlot(estate, resultRelInfo));
877  InstrCountTuples2(&mtstate->ps, 1);
878  return NULL;
879  }
880  }
881 
882  /*
883  * Before we start insertion proper, acquire our "speculative
884  * insertion lock". Others can use that to wait for us to decide
885  * if we're going to go ahead with the insertion, instead of
886  * waiting for the whole transaction to complete.
887  */
889 
890  /* insert the tuple, with the speculative token */
891  table_tuple_insert_speculative(resultRelationDesc, slot,
892  estate->es_output_cid,
893  0,
894  NULL,
895  specToken);
896 
897  /* insert index entries for tuple */
898  recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
899  slot, estate, false, true,
900  &specConflict,
901  arbiterIndexes);
902 
903  /* adjust the tuple's state accordingly */
904  table_tuple_complete_speculative(resultRelationDesc, slot,
905  specToken, !specConflict);
906 
907  /*
908  * Wake up anyone waiting for our decision. They will re-check
909  * the tuple, see that it's no longer speculative, and wait on our
910  * XID as if this was a regularly inserted tuple all along. Or if
911  * we killed the tuple, they will see it's dead, and proceed as if
912  * the tuple never existed.
913  */
915 
916  /*
917  * If there was a conflict, start from the beginning. We'll do
918  * the pre-check again, which will now find the conflicting tuple
919  * (unless it aborts before we get there).
920  */
921  if (specConflict)
922  {
923  list_free(recheckIndexes);
924  goto vlock;
925  }
926 
927  /* Since there was no insertion conflict, we're done */
928  }
929  else
930  {
931  /* insert the tuple normally */
932  table_tuple_insert(resultRelationDesc, slot,
933  estate->es_output_cid,
934  0, NULL);
935 
936  /* insert index entries for tuple */
937  if (resultRelInfo->ri_NumIndices > 0)
938  recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
939  slot, estate, false,
940  false, NULL, NIL);
941  }
942  }
943 
944  if (canSetTag)
945  (estate->es_processed)++;
946 
947  /*
948  * If this insert is the result of a partition key update that moved the
949  * tuple to a new partition, put this row into the transition NEW TABLE,
950  * if there is one. We need to do this separately for DELETE and INSERT
951  * because they happen on different tables.
952  */
953  ar_insert_trig_tcs = mtstate->mt_transition_capture;
954  if (mtstate->operation == CMD_UPDATE && mtstate->mt_transition_capture
956  {
957  ExecARUpdateTriggers(estate, resultRelInfo, NULL,
958  NULL,
959  slot,
960  NULL,
961  mtstate->mt_transition_capture);
962 
963  /*
964  * We've already captured the NEW TABLE row, so make sure any AR
965  * INSERT trigger fired below doesn't capture it again.
966  */
967  ar_insert_trig_tcs = NULL;
968  }
969 
970  /* AFTER ROW INSERT Triggers */
971  ExecARInsertTriggers(estate, resultRelInfo, slot, recheckIndexes,
972  ar_insert_trig_tcs);
973 
974  list_free(recheckIndexes);
975 
976  /*
977  * Check any WITH CHECK OPTION constraints from parent views. We are
978  * required to do this after testing all constraints and uniqueness
979  * violations per the SQL spec, so we do it after actually inserting the
980  * record into the heap and all indexes.
981  *
982  * ExecWithCheckOptions will elog(ERROR) if a violation is found, so the
983  * tuple will never be seen, if it violates the WITH CHECK OPTION.
984  *
985  * ExecWithCheckOptions() will skip any WCOs which are not of the kind we
986  * are looking for at this point.
987  */
988  if (resultRelInfo->ri_WithCheckOptions != NIL)
989  ExecWithCheckOptions(WCO_VIEW_CHECK, resultRelInfo, slot, estate);
990 
991  /* Process RETURNING if present */
992  if (resultRelInfo->ri_projectReturning)
993  result = ExecProcessReturning(resultRelInfo, slot, planSlot);
994 
995  return result;
996 }
997 
998 /* ----------------------------------------------------------------
999  * ExecBatchInsert
1000  *
1001  * Insert multiple tuples in an efficient way.
1002  * Currently, this handles inserting into a foreign table without
1003  * RETURNING clause.
1004  * ----------------------------------------------------------------
1005  */
1006 static void
1008  ResultRelInfo *resultRelInfo,
1009  TupleTableSlot **slots,
1010  TupleTableSlot **planSlots,
1011  int numSlots,
1012  EState *estate,
1013  bool canSetTag)
1014 {
1015  int i;
1016  int numInserted = numSlots;
1017  TupleTableSlot *slot = NULL;
1018  TupleTableSlot **rslots;
1019 
1020  /*
1021  * insert into foreign table: let the FDW do it
1022  */
1023  rslots = resultRelInfo->ri_FdwRoutine->ExecForeignBatchInsert(estate,
1024  resultRelInfo,
1025  slots,
1026  planSlots,
1027  &numInserted);
1028 
1029  for (i = 0; i < numInserted; i++)
1030  {
1031  slot = rslots[i];
1032 
1033  /*
1034  * AFTER ROW Triggers or RETURNING expressions might reference the
1035  * tableoid column, so (re-)initialize tts_tableOid before evaluating
1036  * them.
1037  */
1038  slot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
1039 
1040  /* AFTER ROW INSERT Triggers */
1041  ExecARInsertTriggers(estate, resultRelInfo, slot, NIL,
1042  mtstate->mt_transition_capture);
1043 
1044  /*
1045  * Check any WITH CHECK OPTION constraints from parent views. See the
1046  * comment in ExecInsert.
1047  */
1048  if (resultRelInfo->ri_WithCheckOptions != NIL)
1049  ExecWithCheckOptions(WCO_VIEW_CHECK, resultRelInfo, slot, estate);
1050  }
1051 
1052  if (canSetTag && numInserted > 0)
1053  estate->es_processed += numInserted;
1054 }
1055 
1056 /* ----------------------------------------------------------------
1057  * ExecDelete
1058  *
1059  * DELETE is like UPDATE, except that we delete the tuple and no
1060  * index modifications are needed.
1061  *
1062  * When deleting from a table, tupleid identifies the tuple to
1063  * delete and oldtuple is NULL. When deleting from a view,
1064  * oldtuple is passed to the INSTEAD OF triggers and identifies
1065  * what to delete, and tupleid is invalid. When deleting from a
1066  * foreign table, tupleid is invalid; the FDW has to figure out
1067  * which row to delete using data from the planSlot. oldtuple is
1068  * passed to foreign table triggers; it is NULL when the foreign
1069  * table has no relevant triggers. We use tupleDeleted to indicate
1070  * whether the tuple is actually deleted, callers can use it to
1071  * decide whether to continue the operation. When this DELETE is a
1072  * part of an UPDATE of partition-key, then the slot returned by
1073  * EvalPlanQual() is passed back using output parameter epqslot.
1074  *
1075  * Returns RETURNING result if any, otherwise NULL.
1076  * ----------------------------------------------------------------
1077  */
1078 static TupleTableSlot *
1080  ResultRelInfo *resultRelInfo,
1081  ItemPointer tupleid,
1082  HeapTuple oldtuple,
1083  TupleTableSlot *planSlot,
1084  EPQState *epqstate,
1085  EState *estate,
1086  bool processReturning,
1087  bool canSetTag,
1088  bool changingPart,
1089  bool *tupleDeleted,
1090  TupleTableSlot **epqreturnslot)
1091 {
1092  Relation resultRelationDesc = resultRelInfo->ri_RelationDesc;
1093  TM_Result result;
1094  TM_FailureData tmfd;
1095  TupleTableSlot *slot = NULL;
1096  TransitionCaptureState *ar_delete_trig_tcs;
1097 
1098  if (tupleDeleted)
1099  *tupleDeleted = false;
1100 
1101  /* BEFORE ROW DELETE Triggers */
1102  if (resultRelInfo->ri_TrigDesc &&
1103  resultRelInfo->ri_TrigDesc->trig_delete_before_row)
1104  {
1105  bool dodelete;
1106 
1107  dodelete = ExecBRDeleteTriggers(estate, epqstate, resultRelInfo,
1108  tupleid, oldtuple, epqreturnslot);
1109 
1110  if (!dodelete) /* "do nothing" */
1111  return NULL;
1112  }
1113 
1114  /* INSTEAD OF ROW DELETE Triggers */
1115  if (resultRelInfo->ri_TrigDesc &&
1116  resultRelInfo->ri_TrigDesc->trig_delete_instead_row)
1117  {
1118  bool dodelete;
1119 
1120  Assert(oldtuple != NULL);
1121  dodelete = ExecIRDeleteTriggers(estate, resultRelInfo, oldtuple);
1122 
1123  if (!dodelete) /* "do nothing" */
1124  return NULL;
1125  }
1126  else if (resultRelInfo->ri_FdwRoutine)
1127  {
1128  /*
1129  * delete from foreign table: let the FDW do it
1130  *
1131  * We offer the returning slot as a place to store RETURNING data,
1132  * although the FDW can return some other slot if it wants.
1133  */
1134  slot = ExecGetReturningSlot(estate, resultRelInfo);
1135  slot = resultRelInfo->ri_FdwRoutine->ExecForeignDelete(estate,
1136  resultRelInfo,
1137  slot,
1138  planSlot);
1139 
1140  if (slot == NULL) /* "do nothing" */
1141  return NULL;
1142 
1143  /*
1144  * RETURNING expressions might reference the tableoid column, so
1145  * (re)initialize tts_tableOid before evaluating them.
1146  */
1147  if (TTS_EMPTY(slot))
1148  ExecStoreAllNullTuple(slot);
1149 
1150  slot->tts_tableOid = RelationGetRelid(resultRelationDesc);
1151  }
1152  else
1153  {
1154  /*
1155  * delete the tuple
1156  *
1157  * Note: if es_crosscheck_snapshot isn't InvalidSnapshot, we check
1158  * that the row to be deleted is visible to that snapshot, and throw a
1159  * can't-serialize error if not. This is a special-case behavior
1160  * needed for referential integrity updates in transaction-snapshot
1161  * mode transactions.
1162  */
1163 ldelete:;
1164  result = table_tuple_delete(resultRelationDesc, tupleid,
1165  estate->es_output_cid,
1166  estate->es_snapshot,
1167  estate->es_crosscheck_snapshot,
1168  true /* wait for commit */ ,
1169  &tmfd,
1170  changingPart);
1171 
1172  switch (result)
1173  {
1174  case TM_SelfModified:
1175 
1176  /*
1177  * The target tuple was already updated or deleted by the
1178  * current command, or by a later command in the current
1179  * transaction. The former case is possible in a join DELETE
1180  * where multiple tuples join to the same target tuple. This
1181  * is somewhat questionable, but Postgres has always allowed
1182  * it: we just ignore additional deletion attempts.
1183  *
1184  * The latter case arises if the tuple is modified by a
1185  * command in a BEFORE trigger, or perhaps by a command in a
1186  * volatile function used in the query. In such situations we
1187  * should not ignore the deletion, but it is equally unsafe to
1188  * proceed. We don't want to discard the original DELETE
1189  * while keeping the triggered actions based on its deletion;
1190  * and it would be no better to allow the original DELETE
1191  * while discarding updates that it triggered. The row update
1192  * carries some information that might be important according
1193  * to business rules; so throwing an error is the only safe
1194  * course.
1195  *
1196  * If a trigger actually intends this type of interaction, it
1197  * can re-execute the DELETE and then return NULL to cancel
1198  * the outer delete.
1199  */
1200  if (tmfd.cmax != estate->es_output_cid)
1201  ereport(ERROR,
1202  (errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
1203  errmsg("tuple to be deleted was already modified by an operation triggered by the current command"),
1204  errhint("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
1205 
1206  /* Else, already deleted by self; nothing to do */
1207  return NULL;
1208 
1209  case TM_Ok:
1210  break;
1211 
1212  case TM_Updated:
1213  {
1214  TupleTableSlot *inputslot;
1215  TupleTableSlot *epqslot;
1216 
1218  ereport(ERROR,
1219  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
1220  errmsg("could not serialize access due to concurrent update")));
1221 
1222  /*
1223  * Already know that we're going to need to do EPQ, so
1224  * fetch tuple directly into the right slot.
1225  */
1226  EvalPlanQualBegin(epqstate);
1227  inputslot = EvalPlanQualSlot(epqstate, resultRelationDesc,
1228  resultRelInfo->ri_RangeTableIndex);
1229 
1230  result = table_tuple_lock(resultRelationDesc, tupleid,
1231  estate->es_snapshot,
1232  inputslot, estate->es_output_cid,
1235  &tmfd);
1236 
1237  switch (result)
1238  {
1239  case TM_Ok:
1240  Assert(tmfd.traversed);
1241  epqslot = EvalPlanQual(epqstate,
1242  resultRelationDesc,
1243  resultRelInfo->ri_RangeTableIndex,
1244  inputslot);
1245  if (TupIsNull(epqslot))
1246  /* Tuple not passing quals anymore, exiting... */
1247  return NULL;
1248 
1249  /*
1250  * If requested, skip delete and pass back the
1251  * updated row.
1252  */
1253  if (epqreturnslot)
1254  {
1255  *epqreturnslot = epqslot;
1256  return NULL;
1257  }
1258  else
1259  goto ldelete;
1260 
1261  case TM_SelfModified:
1262 
1263  /*
1264  * This can be reached when following an update
1265  * chain from a tuple updated by another session,
1266  * reaching a tuple that was already updated in
1267  * this transaction. If previously updated by this
1268  * command, ignore the delete, otherwise error
1269  * out.
1270  *
1271  * See also TM_SelfModified response to
1272  * table_tuple_delete() above.
1273  */
1274  if (tmfd.cmax != estate->es_output_cid)
1275  ereport(ERROR,
1276  (errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
1277  errmsg("tuple to be deleted was already modified by an operation triggered by the current command"),
1278  errhint("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
1279  return NULL;
1280 
1281  case TM_Deleted:
1282  /* tuple already deleted; nothing to do */
1283  return NULL;
1284 
1285  default:
1286 
1287  /*
1288  * TM_Invisible should be impossible because we're
1289  * waiting for updated row versions, and would
1290  * already have errored out if the first version
1291  * is invisible.
1292  *
1293  * TM_Updated should be impossible, because we're
1294  * locking the latest version via
1295  * TUPLE_LOCK_FLAG_FIND_LAST_VERSION.
1296  */
1297  elog(ERROR, "unexpected table_tuple_lock status: %u",
1298  result);
1299  return NULL;
1300  }
1301 
1302  Assert(false);
1303  break;
1304  }
1305 
1306  case TM_Deleted:
1308  ereport(ERROR,
1309  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
1310  errmsg("could not serialize access due to concurrent delete")));
1311  /* tuple already deleted; nothing to do */
1312  return NULL;
1313 
1314  default:
1315  elog(ERROR, "unrecognized table_tuple_delete status: %u",
1316  result);
1317  return NULL;
1318  }
1319 
1320  /*
1321  * Note: Normally one would think that we have to delete index tuples
1322  * associated with the heap tuple now...
1323  *
1324  * ... but in POSTGRES, we have no need to do this because VACUUM will
1325  * take care of it later. We can't delete index tuples immediately
1326  * anyway, since the tuple is still visible to other transactions.
1327  */
1328  }
1329 
1330  if (canSetTag)
1331  (estate->es_processed)++;
1332 
1333  /* Tell caller that the delete actually happened. */
1334  if (tupleDeleted)
1335  *tupleDeleted = true;
1336 
1337  /*
1338  * If this delete is the result of a partition key update that moved the
1339  * tuple to a new partition, put this row into the transition OLD TABLE,
1340  * if there is one. We need to do this separately for DELETE and INSERT
1341  * because they happen on different tables.
1342  */
1343  ar_delete_trig_tcs = mtstate->mt_transition_capture;
1344  if (mtstate->operation == CMD_UPDATE && mtstate->mt_transition_capture
1346  {
1347  ExecARUpdateTriggers(estate, resultRelInfo,
1348  tupleid,
1349  oldtuple,
1350  NULL,
1351  NULL,
1352  mtstate->mt_transition_capture);
1353 
1354  /*
1355  * We've already captured the NEW TABLE row, so make sure any AR
1356  * DELETE trigger fired below doesn't capture it again.
1357  */
1358  ar_delete_trig_tcs = NULL;
1359  }
1360 
1361  /* AFTER ROW DELETE Triggers */
1362  ExecARDeleteTriggers(estate, resultRelInfo, tupleid, oldtuple,
1363  ar_delete_trig_tcs);
1364 
1365  /* Process RETURNING if present and if requested */
1366  if (processReturning && resultRelInfo->ri_projectReturning)
1367  {
1368  /*
1369  * We have to put the target tuple into a slot, which means first we
1370  * gotta fetch it. We can use the trigger tuple slot.
1371  */
1372  TupleTableSlot *rslot;
1373 
1374  if (resultRelInfo->ri_FdwRoutine)
1375  {
1376  /* FDW must have provided a slot containing the deleted row */
1377  Assert(!TupIsNull(slot));
1378  }
1379  else
1380  {
1381  slot = ExecGetReturningSlot(estate, resultRelInfo);
1382  if (oldtuple != NULL)
1383  {
1384  ExecForceStoreHeapTuple(oldtuple, slot, false);
1385  }
1386  else
1387  {
1388  if (!table_tuple_fetch_row_version(resultRelationDesc, tupleid,
1389  SnapshotAny, slot))
1390  elog(ERROR, "failed to fetch deleted tuple for DELETE RETURNING");
1391  }
1392  }
1393 
1394  rslot = ExecProcessReturning(resultRelInfo, slot, planSlot);
1395 
1396  /*
1397  * Before releasing the target tuple again, make sure rslot has a
1398  * local copy of any pass-by-reference values.
1399  */
1400  ExecMaterializeSlot(rslot);
1401 
1402  ExecClearTuple(slot);
1403 
1404  return rslot;
1405  }
1406 
1407  return NULL;
1408 }
1409 
1410 /*
1411  * ExecCrossPartitionUpdate --- Move an updated tuple to another partition.
1412  *
1413  * This works by first deleting the old tuple from the current partition,
1414  * followed by inserting the new tuple into the root parent table, that is,
1415  * mtstate->rootResultRelInfo. It will be re-routed from there to the
1416  * correct partition.
1417  *
1418  * Returns true if the tuple has been successfully moved, or if it's found
1419  * that the tuple was concurrently deleted so there's nothing more to do
1420  * for the caller.
1421  *
1422  * False is returned if the tuple we're trying to move is found to have been
1423  * concurrently updated. In that case, the caller must to check if the
1424  * updated tuple that's returned in *retry_slot still needs to be re-routed,
1425  * and call this function again or perform a regular update accordingly.
1426  */
1427 static bool
1429  ResultRelInfo *resultRelInfo,
1430  ItemPointer tupleid, HeapTuple oldtuple,
1431  TupleTableSlot *slot, TupleTableSlot *planSlot,
1432  EPQState *epqstate, bool canSetTag,
1433  TupleTableSlot **retry_slot,
1434  TupleTableSlot **inserted_tuple)
1435 {
1436  EState *estate = mtstate->ps.state;
1437  TupleConversionMap *tupconv_map;
1438  bool tuple_deleted;
1439  TupleTableSlot *epqslot = NULL;
1440 
1441  *inserted_tuple = NULL;
1442  *retry_slot = NULL;
1443 
1444  /*
1445  * Disallow an INSERT ON CONFLICT DO UPDATE that causes the original row
1446  * to migrate to a different partition. Maybe this can be implemented
1447  * some day, but it seems a fringe feature with little redeeming value.
1448  */
1449  if (((ModifyTable *) mtstate->ps.plan)->onConflictAction == ONCONFLICT_UPDATE)
1450  ereport(ERROR,
1451  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1452  errmsg("invalid ON UPDATE specification"),
1453  errdetail("The result tuple would appear in a different partition than the original tuple.")));
1454 
1455  /*
1456  * When an UPDATE is run directly on a leaf partition, simply fail with a
1457  * partition constraint violation error.
1458  */
1459  if (resultRelInfo == mtstate->rootResultRelInfo)
1460  ExecPartitionCheckEmitError(resultRelInfo, slot, estate);
1461 
1462  /* Initialize tuple routing info if not already done. */
1463  if (mtstate->mt_partition_tuple_routing == NULL)
1464  {
1465  Relation rootRel = mtstate->rootResultRelInfo->ri_RelationDesc;
1466  MemoryContext oldcxt;
1467 
1468  /* Things built here have to last for the query duration. */
1469  oldcxt = MemoryContextSwitchTo(estate->es_query_cxt);
1470 
1471  mtstate->mt_partition_tuple_routing =
1472  ExecSetupPartitionTupleRouting(estate, rootRel);
1473 
1474  /*
1475  * Before a partition's tuple can be re-routed, it must first be
1476  * converted to the root's format, so we'll need a slot for storing
1477  * such tuples.
1478  */
1479  Assert(mtstate->mt_root_tuple_slot == NULL);
1480  mtstate->mt_root_tuple_slot = table_slot_create(rootRel, NULL);
1481 
1482  MemoryContextSwitchTo(oldcxt);
1483  }
1484 
1485  /*
1486  * Row movement, part 1. Delete the tuple, but skip RETURNING processing.
1487  * We want to return rows from INSERT.
1488  */
1489  ExecDelete(mtstate, resultRelInfo, tupleid, oldtuple, planSlot,
1490  epqstate, estate,
1491  false, /* processReturning */
1492  false, /* canSetTag */
1493  true, /* changingPart */
1494  &tuple_deleted, &epqslot);
1495 
1496  /*
1497  * For some reason if DELETE didn't happen (e.g. trigger prevented it, or
1498  * it was already deleted by self, or it was concurrently deleted by
1499  * another transaction), then we should skip the insert as well;
1500  * otherwise, an UPDATE could cause an increase in the total number of
1501  * rows across all partitions, which is clearly wrong.
1502  *
1503  * For a normal UPDATE, the case where the tuple has been the subject of a
1504  * concurrent UPDATE or DELETE would be handled by the EvalPlanQual
1505  * machinery, but for an UPDATE that we've translated into a DELETE from
1506  * this partition and an INSERT into some other partition, that's not
1507  * available, because CTID chains can't span relation boundaries. We
1508  * mimic the semantics to a limited extent by skipping the INSERT if the
1509  * DELETE fails to find a tuple. This ensures that two concurrent
1510  * attempts to UPDATE the same tuple at the same time can't turn one tuple
1511  * into two, and that an UPDATE of a just-deleted tuple can't resurrect
1512  * it.
1513  */
1514  if (!tuple_deleted)
1515  {
1516  /*
1517  * epqslot will be typically NULL. But when ExecDelete() finds that
1518  * another transaction has concurrently updated the same row, it
1519  * re-fetches the row, skips the delete, and epqslot is set to the
1520  * re-fetched tuple slot. In that case, we need to do all the checks
1521  * again.
1522  */
1523  if (TupIsNull(epqslot))
1524  return true;
1525  else
1526  {
1527  /* Fetch the most recent version of old tuple. */
1528  TupleTableSlot *oldSlot;
1529 
1530  /* ... but first, make sure ri_oldTupleSlot is initialized. */
1531  if (unlikely(!resultRelInfo->ri_projectNewInfoValid))
1532  ExecInitUpdateProjection(mtstate, resultRelInfo);
1533  oldSlot = resultRelInfo->ri_oldTupleSlot;
1534  if (!table_tuple_fetch_row_version(resultRelInfo->ri_RelationDesc,
1535  tupleid,
1536  SnapshotAny,
1537  oldSlot))
1538  elog(ERROR, "failed to fetch tuple being updated");
1539  *retry_slot = ExecGetUpdateNewTuple(resultRelInfo, epqslot,
1540  oldSlot);
1541  return false;
1542  }
1543  }
1544 
1545  /*
1546  * resultRelInfo is one of the per-relation resultRelInfos. So we should
1547  * convert the tuple into root's tuple descriptor if needed, since
1548  * ExecInsert() starts the search from root.
1549  */
1550  tupconv_map = ExecGetChildToRootMap(resultRelInfo);
1551  if (tupconv_map != NULL)
1552  slot = execute_attr_map_slot(tupconv_map->attrMap,
1553  slot,
1554  mtstate->mt_root_tuple_slot);
1555 
1556  /* Tuple routing starts from the root table. */
1557  *inserted_tuple = ExecInsert(mtstate, mtstate->rootResultRelInfo, slot,
1558  planSlot, estate, canSetTag);
1559 
1560  /*
1561  * Reset the transition state that may possibly have been written by
1562  * INSERT.
1563  */
1564  if (mtstate->mt_transition_capture)
1566 
1567  /* We're done moving. */
1568  return true;
1569 }
1570 
1571 /* ----------------------------------------------------------------
1572  * ExecUpdate
1573  *
1574  * note: we can't run UPDATE queries with transactions
1575  * off because UPDATEs are actually INSERTs and our
1576  * scan will mistakenly loop forever, updating the tuple
1577  * it just inserted.. This should be fixed but until it
1578  * is, we don't want to get stuck in an infinite loop
1579  * which corrupts your database..
1580  *
1581  * When updating a table, tupleid identifies the tuple to
1582  * update and oldtuple is NULL. When updating a view, oldtuple
1583  * is passed to the INSTEAD OF triggers and identifies what to
1584  * update, and tupleid is invalid. When updating a foreign table,
1585  * tupleid is invalid; the FDW has to figure out which row to
1586  * update using data from the planSlot. oldtuple is passed to
1587  * foreign table triggers; it is NULL when the foreign table has
1588  * no relevant triggers.
1589  *
1590  * slot contains the new tuple value to be stored.
1591  * planSlot is the output of the ModifyTable's subplan; we use it
1592  * to access values from other input tables (for RETURNING),
1593  * row-ID junk columns, etc.
1594  *
1595  * Returns RETURNING result if any, otherwise NULL.
1596  * ----------------------------------------------------------------
1597  */
1598 static TupleTableSlot *
1600  ResultRelInfo *resultRelInfo,
1601  ItemPointer tupleid,
1602  HeapTuple oldtuple,
1603  TupleTableSlot *slot,
1604  TupleTableSlot *planSlot,
1605  EPQState *epqstate,
1606  EState *estate,
1607  bool canSetTag)
1608 {
1609  Relation resultRelationDesc = resultRelInfo->ri_RelationDesc;
1610  TM_Result result;
1611  TM_FailureData tmfd;
1612  List *recheckIndexes = NIL;
1613 
1614  /*
1615  * abort the operation if not running transactions
1616  */
1618  elog(ERROR, "cannot UPDATE during bootstrap");
1619 
1620  ExecMaterializeSlot(slot);
1621 
1622  /*
1623  * Open the table's indexes, if we have not done so already, so that we
1624  * can add new index entries for the updated tuple.
1625  */
1626  if (resultRelationDesc->rd_rel->relhasindex &&
1627  resultRelInfo->ri_IndexRelationDescs == NULL)
1628  ExecOpenIndices(resultRelInfo, false);
1629 
1630  /* BEFORE ROW UPDATE Triggers */
1631  if (resultRelInfo->ri_TrigDesc &&
1632  resultRelInfo->ri_TrigDesc->trig_update_before_row)
1633  {
1634  if (!ExecBRUpdateTriggers(estate, epqstate, resultRelInfo,
1635  tupleid, oldtuple, slot))
1636  return NULL; /* "do nothing" */
1637  }
1638 
1639  /* INSTEAD OF ROW UPDATE Triggers */
1640  if (resultRelInfo->ri_TrigDesc &&
1641  resultRelInfo->ri_TrigDesc->trig_update_instead_row)
1642  {
1643  if (!ExecIRUpdateTriggers(estate, resultRelInfo,
1644  oldtuple, slot))
1645  return NULL; /* "do nothing" */
1646  }
1647  else if (resultRelInfo->ri_FdwRoutine)
1648  {
1649  /*
1650  * GENERATED expressions might reference the tableoid column, so
1651  * (re-)initialize tts_tableOid before evaluating them.
1652  */
1653  slot->tts_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
1654 
1655  /*
1656  * Compute stored generated columns
1657  */
1658  if (resultRelationDesc->rd_att->constr &&
1659  resultRelationDesc->rd_att->constr->has_generated_stored)
1660  ExecComputeStoredGenerated(resultRelInfo, estate, slot,
1661  CMD_UPDATE);
1662 
1663  /*
1664  * update in foreign table: let the FDW do it
1665  */
1666  slot = resultRelInfo->ri_FdwRoutine->ExecForeignUpdate(estate,
1667  resultRelInfo,
1668  slot,
1669  planSlot);
1670 
1671  if (slot == NULL) /* "do nothing" */
1672  return NULL;
1673 
1674  /*
1675  * AFTER ROW Triggers or RETURNING expressions might reference the
1676  * tableoid column, so (re-)initialize tts_tableOid before evaluating
1677  * them. (This covers the case where the FDW replaced the slot.)
1678  */
1679  slot->tts_tableOid = RelationGetRelid(resultRelationDesc);
1680  }
1681  else
1682  {
1683  LockTupleMode lockmode;
1684  bool partition_constraint_failed;
1685  bool update_indexes;
1686 
1687  /*
1688  * Constraints and GENERATED expressions might reference the tableoid
1689  * column, so (re-)initialize tts_tableOid before evaluating them.
1690  */
1691  slot->tts_tableOid = RelationGetRelid(resultRelationDesc);
1692 
1693  /*
1694  * Compute stored generated columns
1695  */
1696  if (resultRelationDesc->rd_att->constr &&
1697  resultRelationDesc->rd_att->constr->has_generated_stored)
1698  ExecComputeStoredGenerated(resultRelInfo, estate, slot,
1699  CMD_UPDATE);
1700 
1701  /*
1702  * Check any RLS UPDATE WITH CHECK policies
1703  *
1704  * If we generate a new candidate tuple after EvalPlanQual testing, we
1705  * must loop back here and recheck any RLS policies and constraints.
1706  * (We don't need to redo triggers, however. If there are any BEFORE
1707  * triggers then trigger.c will have done table_tuple_lock to lock the
1708  * correct tuple, so there's no need to do them again.)
1709  */
1710 lreplace:;
1711 
1712  /* ensure slot is independent, consider e.g. EPQ */
1713  ExecMaterializeSlot(slot);
1714 
1715  /*
1716  * If partition constraint fails, this row might get moved to another
1717  * partition, in which case we should check the RLS CHECK policy just
1718  * before inserting into the new partition, rather than doing it here.
1719  * This is because a trigger on that partition might again change the
1720  * row. So skip the WCO checks if the partition constraint fails.
1721  */
1722  partition_constraint_failed =
1723  resultRelationDesc->rd_rel->relispartition &&
1724  !ExecPartitionCheck(resultRelInfo, slot, estate, false);
1725 
1726  if (!partition_constraint_failed &&
1727  resultRelInfo->ri_WithCheckOptions != NIL)
1728  {
1729  /*
1730  * ExecWithCheckOptions() will skip any WCOs which are not of the
1731  * kind we are looking for at this point.
1732  */
1734  resultRelInfo, slot, estate);
1735  }
1736 
1737  /*
1738  * If a partition check failed, try to move the row into the right
1739  * partition.
1740  */
1741  if (partition_constraint_failed)
1742  {
1743  TupleTableSlot *inserted_tuple,
1744  *retry_slot;
1745  bool retry;
1746 
1747  /*
1748  * ExecCrossPartitionUpdate will first DELETE the row from the
1749  * partition it's currently in and then insert it back into the
1750  * root table, which will re-route it to the correct partition.
1751  * The first part may have to be repeated if it is detected that
1752  * the tuple we're trying to move has been concurrently updated.
1753  */
1754  retry = !ExecCrossPartitionUpdate(mtstate, resultRelInfo, tupleid,
1755  oldtuple, slot, planSlot,
1756  epqstate, canSetTag,
1757  &retry_slot, &inserted_tuple);
1758  if (retry)
1759  {
1760  slot = retry_slot;
1761  goto lreplace;
1762  }
1763 
1764  return inserted_tuple;
1765  }
1766 
1767  /*
1768  * Check the constraints of the tuple. We've already checked the
1769  * partition constraint above; however, we must still ensure the tuple
1770  * passes all other constraints, so we will call ExecConstraints() and
1771  * have it validate all remaining checks.
1772  */
1773  if (resultRelationDesc->rd_att->constr)
1774  ExecConstraints(resultRelInfo, slot, estate);
1775 
1776  /*
1777  * replace the heap tuple
1778  *
1779  * Note: if es_crosscheck_snapshot isn't InvalidSnapshot, we check
1780  * that the row to be updated is visible to that snapshot, and throw a
1781  * can't-serialize error if not. This is a special-case behavior
1782  * needed for referential integrity updates in transaction-snapshot
1783  * mode transactions.
1784  */
1785  result = table_tuple_update(resultRelationDesc, tupleid, slot,
1786  estate->es_output_cid,
1787  estate->es_snapshot,
1788  estate->es_crosscheck_snapshot,
1789  true /* wait for commit */ ,
1790  &tmfd, &lockmode, &update_indexes);
1791 
1792  switch (result)
1793  {
1794  case TM_SelfModified:
1795 
1796  /*
1797  * The target tuple was already updated or deleted by the
1798  * current command, or by a later command in the current
1799  * transaction. The former case is possible in a join UPDATE
1800  * where multiple tuples join to the same target tuple. This
1801  * is pretty questionable, but Postgres has always allowed it:
1802  * we just execute the first update action and ignore
1803  * additional update attempts.
1804  *
1805  * The latter case arises if the tuple is modified by a
1806  * command in a BEFORE trigger, or perhaps by a command in a
1807  * volatile function used in the query. In such situations we
1808  * should not ignore the update, but it is equally unsafe to
1809  * proceed. We don't want to discard the original UPDATE
1810  * while keeping the triggered actions based on it; and we
1811  * have no principled way to merge this update with the
1812  * previous ones. So throwing an error is the only safe
1813  * course.
1814  *
1815  * If a trigger actually intends this type of interaction, it
1816  * can re-execute the UPDATE (assuming it can figure out how)
1817  * and then return NULL to cancel the outer update.
1818  */
1819  if (tmfd.cmax != estate->es_output_cid)
1820  ereport(ERROR,
1821  (errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
1822  errmsg("tuple to be updated was already modified by an operation triggered by the current command"),
1823  errhint("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
1824 
1825  /* Else, already updated by self; nothing to do */
1826  return NULL;
1827 
1828  case TM_Ok:
1829  break;
1830 
1831  case TM_Updated:
1832  {
1833  TupleTableSlot *inputslot;
1834  TupleTableSlot *epqslot;
1835  TupleTableSlot *oldSlot;
1836 
1838  ereport(ERROR,
1839  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
1840  errmsg("could not serialize access due to concurrent update")));
1841 
1842  /*
1843  * Already know that we're going to need to do EPQ, so
1844  * fetch tuple directly into the right slot.
1845  */
1846  inputslot = EvalPlanQualSlot(epqstate, resultRelationDesc,
1847  resultRelInfo->ri_RangeTableIndex);
1848 
1849  result = table_tuple_lock(resultRelationDesc, tupleid,
1850  estate->es_snapshot,
1851  inputslot, estate->es_output_cid,
1852  lockmode, LockWaitBlock,
1854  &tmfd);
1855 
1856  switch (result)
1857  {
1858  case TM_Ok:
1859  Assert(tmfd.traversed);
1860 
1861  epqslot = EvalPlanQual(epqstate,
1862  resultRelationDesc,
1863  resultRelInfo->ri_RangeTableIndex,
1864  inputslot);
1865  if (TupIsNull(epqslot))
1866  /* Tuple not passing quals anymore, exiting... */
1867  return NULL;
1868 
1869  /* Make sure ri_oldTupleSlot is initialized. */
1870  if (unlikely(!resultRelInfo->ri_projectNewInfoValid))
1871  ExecInitUpdateProjection(mtstate, resultRelInfo);
1872 
1873  /* Fetch the most recent version of old tuple. */
1874  oldSlot = resultRelInfo->ri_oldTupleSlot;
1875  if (!table_tuple_fetch_row_version(resultRelationDesc,
1876  tupleid,
1877  SnapshotAny,
1878  oldSlot))
1879  elog(ERROR, "failed to fetch tuple being updated");
1880  slot = ExecGetUpdateNewTuple(resultRelInfo,
1881  epqslot, oldSlot);
1882  goto lreplace;
1883 
1884  case TM_Deleted:
1885  /* tuple already deleted; nothing to do */
1886  return NULL;
1887 
1888  case TM_SelfModified:
1889 
1890  /*
1891  * This can be reached when following an update
1892  * chain from a tuple updated by another session,
1893  * reaching a tuple that was already updated in
1894  * this transaction. If previously modified by
1895  * this command, ignore the redundant update,
1896  * otherwise error out.
1897  *
1898  * See also TM_SelfModified response to
1899  * table_tuple_update() above.
1900  */
1901  if (tmfd.cmax != estate->es_output_cid)
1902  ereport(ERROR,
1903  (errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
1904  errmsg("tuple to be updated was already modified by an operation triggered by the current command"),
1905  errhint("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
1906  return NULL;
1907 
1908  default:
1909  /* see table_tuple_lock call in ExecDelete() */
1910  elog(ERROR, "unexpected table_tuple_lock status: %u",
1911  result);
1912  return NULL;
1913  }
1914  }
1915 
1916  break;
1917 
1918  case TM_Deleted:
1920  ereport(ERROR,
1921  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
1922  errmsg("could not serialize access due to concurrent delete")));
1923  /* tuple already deleted; nothing to do */
1924  return NULL;
1925 
1926  default:
1927  elog(ERROR, "unrecognized table_tuple_update status: %u",
1928  result);
1929  return NULL;
1930  }
1931 
1932  /* insert index entries for tuple if necessary */
1933  if (resultRelInfo->ri_NumIndices > 0 && update_indexes)
1934  recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
1935  slot, estate, true, false,
1936  NULL, NIL);
1937  }
1938 
1939  if (canSetTag)
1940  (estate->es_processed)++;
1941 
1942  /* AFTER ROW UPDATE Triggers */
1943  ExecARUpdateTriggers(estate, resultRelInfo, tupleid, oldtuple, slot,
1944  recheckIndexes,
1945  mtstate->operation == CMD_INSERT ?
1946  mtstate->mt_oc_transition_capture :
1947  mtstate->mt_transition_capture);
1948 
1949  list_free(recheckIndexes);
1950 
1951  /*
1952  * Check any WITH CHECK OPTION constraints from parent views. We are
1953  * required to do this after testing all constraints and uniqueness
1954  * violations per the SQL spec, so we do it after actually updating the
1955  * record in the heap and all indexes.
1956  *
1957  * ExecWithCheckOptions() will skip any WCOs which are not of the kind we
1958  * are looking for at this point.
1959  */
1960  if (resultRelInfo->ri_WithCheckOptions != NIL)
1961  ExecWithCheckOptions(WCO_VIEW_CHECK, resultRelInfo, slot, estate);
1962 
1963  /* Process RETURNING if present */
1964  if (resultRelInfo->ri_projectReturning)
1965  return ExecProcessReturning(resultRelInfo, slot, planSlot);
1966 
1967  return NULL;
1968 }
1969 
1970 /*
1971  * ExecOnConflictUpdate --- execute UPDATE of INSERT ON CONFLICT DO UPDATE
1972  *
1973  * Try to lock tuple for update as part of speculative insertion. If
1974  * a qual originating from ON CONFLICT DO UPDATE is satisfied, update
1975  * (but still lock row, even though it may not satisfy estate's
1976  * snapshot).
1977  *
1978  * Returns true if we're done (with or without an update), or false if
1979  * the caller must retry the INSERT from scratch.
1980  */
1981 static bool
1983  ResultRelInfo *resultRelInfo,
1984  ItemPointer conflictTid,
1985  TupleTableSlot *planSlot,
1986  TupleTableSlot *excludedSlot,
1987  EState *estate,
1988  bool canSetTag,
1989  TupleTableSlot **returning)
1990 {
1991  ExprContext *econtext = mtstate->ps.ps_ExprContext;
1992  Relation relation = resultRelInfo->ri_RelationDesc;
1993  ExprState *onConflictSetWhere = resultRelInfo->ri_onConflict->oc_WhereClause;
1994  TupleTableSlot *existing = resultRelInfo->ri_onConflict->oc_Existing;
1995  TM_FailureData tmfd;
1996  LockTupleMode lockmode;
1997  TM_Result test;
1998  Datum xminDatum;
1999  TransactionId xmin;
2000  bool isnull;
2001 
2002  /* Determine lock mode to use */
2003  lockmode = ExecUpdateLockMode(estate, resultRelInfo);
2004 
2005  /*
2006  * Lock tuple for update. Don't follow updates when tuple cannot be
2007  * locked without doing so. A row locking conflict here means our
2008  * previous conclusion that the tuple is conclusively committed is not
2009  * true anymore.
2010  */
2011  test = table_tuple_lock(relation, conflictTid,
2012  estate->es_snapshot,
2013  existing, estate->es_output_cid,
2014  lockmode, LockWaitBlock, 0,
2015  &tmfd);
2016  switch (test)
2017  {
2018  case TM_Ok:
2019  /* success! */
2020  break;
2021 
2022  case TM_Invisible:
2023 
2024  /*
2025  * This can occur when a just inserted tuple is updated again in
2026  * the same command. E.g. because multiple rows with the same
2027  * conflicting key values are inserted.
2028  *
2029  * This is somewhat similar to the ExecUpdate() TM_SelfModified
2030  * case. We do not want to proceed because it would lead to the
2031  * same row being updated a second time in some unspecified order,
2032  * and in contrast to plain UPDATEs there's no historical behavior
2033  * to break.
2034  *
2035  * It is the user's responsibility to prevent this situation from
2036  * occurring. These problems are why SQL-2003 similarly specifies
2037  * that for SQL MERGE, an exception must be raised in the event of
2038  * an attempt to update the same row twice.
2039  */
2040  xminDatum = slot_getsysattr(existing,
2042  &isnull);
2043  Assert(!isnull);
2044  xmin = DatumGetTransactionId(xminDatum);
2045 
2047  ereport(ERROR,
2048  (errcode(ERRCODE_CARDINALITY_VIOLATION),
2049  errmsg("ON CONFLICT DO UPDATE command cannot affect row a second time"),
2050  errhint("Ensure that no rows proposed for insertion within the same command have duplicate constrained values.")));
2051 
2052  /* This shouldn't happen */
2053  elog(ERROR, "attempted to lock invisible tuple");
2054  break;
2055 
2056  case TM_SelfModified:
2057 
2058  /*
2059  * This state should never be reached. As a dirty snapshot is used
2060  * to find conflicting tuples, speculative insertion wouldn't have
2061  * seen this row to conflict with.
2062  */
2063  elog(ERROR, "unexpected self-updated tuple");
2064  break;
2065 
2066  case TM_Updated:
2068  ereport(ERROR,
2069  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
2070  errmsg("could not serialize access due to concurrent update")));
2071 
2072  /*
2073  * As long as we don't support an UPDATE of INSERT ON CONFLICT for
2074  * a partitioned table we shouldn't reach to a case where tuple to
2075  * be lock is moved to another partition due to concurrent update
2076  * of the partition key.
2077  */
2079 
2080  /*
2081  * Tell caller to try again from the very start.
2082  *
2083  * It does not make sense to use the usual EvalPlanQual() style
2084  * loop here, as the new version of the row might not conflict
2085  * anymore, or the conflicting tuple has actually been deleted.
2086  */
2087  ExecClearTuple(existing);
2088  return false;
2089 
2090  case TM_Deleted:
2092  ereport(ERROR,
2093  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
2094  errmsg("could not serialize access due to concurrent delete")));
2095 
2096  /* see TM_Updated case */
2098  ExecClearTuple(existing);
2099  return false;
2100 
2101  default:
2102  elog(ERROR, "unrecognized table_tuple_lock status: %u", test);
2103  }
2104 
2105  /* Success, the tuple is locked. */
2106 
2107  /*
2108  * Verify that the tuple is visible to our MVCC snapshot if the current
2109  * isolation level mandates that.
2110  *
2111  * It's not sufficient to rely on the check within ExecUpdate() as e.g.
2112  * CONFLICT ... WHERE clause may prevent us from reaching that.
2113  *
2114  * This means we only ever continue when a new command in the current
2115  * transaction could see the row, even though in READ COMMITTED mode the
2116  * tuple will not be visible according to the current statement's
2117  * snapshot. This is in line with the way UPDATE deals with newer tuple
2118  * versions.
2119  */
2120  ExecCheckTupleVisible(estate, relation, existing);
2121 
2122  /*
2123  * Make tuple and any needed join variables available to ExecQual and
2124  * ExecProject. The EXCLUDED tuple is installed in ecxt_innertuple, while
2125  * the target's existing tuple is installed in the scantuple. EXCLUDED
2126  * has been made to reference INNER_VAR in setrefs.c, but there is no
2127  * other redirection.
2128  */
2129  econtext->ecxt_scantuple = existing;
2130  econtext->ecxt_innertuple = excludedSlot;
2131  econtext->ecxt_outertuple = NULL;
2132 
2133  if (!ExecQual(onConflictSetWhere, econtext))
2134  {
2135  ExecClearTuple(existing); /* see return below */
2136  InstrCountFiltered1(&mtstate->ps, 1);
2137  return true; /* done with the tuple */
2138  }
2139 
2140  if (resultRelInfo->ri_WithCheckOptions != NIL)
2141  {
2142  /*
2143  * Check target's existing tuple against UPDATE-applicable USING
2144  * security barrier quals (if any), enforced here as RLS checks/WCOs.
2145  *
2146  * The rewriter creates UPDATE RLS checks/WCOs for UPDATE security
2147  * quals, and stores them as WCOs of "kind" WCO_RLS_CONFLICT_CHECK,
2148  * but that's almost the extent of its special handling for ON
2149  * CONFLICT DO UPDATE.
2150  *
2151  * The rewriter will also have associated UPDATE applicable straight
2152  * RLS checks/WCOs for the benefit of the ExecUpdate() call that
2153  * follows. INSERTs and UPDATEs naturally have mutually exclusive WCO
2154  * kinds, so there is no danger of spurious over-enforcement in the
2155  * INSERT or UPDATE path.
2156  */
2158  existing,
2159  mtstate->ps.state);
2160  }
2161 
2162  /* Project the new tuple version */
2163  ExecProject(resultRelInfo->ri_onConflict->oc_ProjInfo);
2164 
2165  /*
2166  * Note that it is possible that the target tuple has been modified in
2167  * this session, after the above table_tuple_lock. We choose to not error
2168  * out in that case, in line with ExecUpdate's treatment of similar cases.
2169  * This can happen if an UPDATE is triggered from within ExecQual(),
2170  * ExecWithCheckOptions() or ExecProject() above, e.g. by selecting from a
2171  * wCTE in the ON CONFLICT's SET.
2172  */
2173 
2174  /* Execute UPDATE with projection */
2175  *returning = ExecUpdate(mtstate, resultRelInfo, conflictTid, NULL,
2176  resultRelInfo->ri_onConflict->oc_ProjSlot,
2177  planSlot,
2178  &mtstate->mt_epqstate, mtstate->ps.state,
2179  canSetTag);
2180 
2181  /*
2182  * Clear out existing tuple, as there might not be another conflict among
2183  * the next input rows. Don't want to hold resources till the end of the
2184  * query.
2185  */
2186  ExecClearTuple(existing);
2187  return true;
2188 }
2189 
2190 
2191 /*
2192  * Process BEFORE EACH STATEMENT triggers
2193  */
2194 static void
2196 {
2197  ModifyTable *plan = (ModifyTable *) node->ps.plan;
2198  ResultRelInfo *resultRelInfo = node->rootResultRelInfo;
2199 
2200  switch (node->operation)
2201  {
2202  case CMD_INSERT:
2203  ExecBSInsertTriggers(node->ps.state, resultRelInfo);
2204  if (plan->onConflictAction == ONCONFLICT_UPDATE)
2206  resultRelInfo);
2207  break;
2208  case CMD_UPDATE:
2209  ExecBSUpdateTriggers(node->ps.state, resultRelInfo);
2210  break;
2211  case CMD_DELETE:
2212  ExecBSDeleteTriggers(node->ps.state, resultRelInfo);
2213  break;
2214  default:
2215  elog(ERROR, "unknown operation");
2216  break;
2217  }
2218 }
2219 
2220 /*
2221  * Process AFTER EACH STATEMENT triggers
2222  */
2223 static void
2225 {
2226  ModifyTable *plan = (ModifyTable *) node->ps.plan;
2227  ResultRelInfo *resultRelInfo = node->rootResultRelInfo;
2228 
2229  switch (node->operation)
2230  {
2231  case CMD_INSERT:
2232  if (plan->onConflictAction == ONCONFLICT_UPDATE)
2234  resultRelInfo,
2235  node->mt_oc_transition_capture);
2236  ExecASInsertTriggers(node->ps.state, resultRelInfo,
2237  node->mt_transition_capture);
2238  break;
2239  case CMD_UPDATE:
2240  ExecASUpdateTriggers(node->ps.state, resultRelInfo,
2241  node->mt_transition_capture);
2242  break;
2243  case CMD_DELETE:
2244  ExecASDeleteTriggers(node->ps.state, resultRelInfo,
2245  node->mt_transition_capture);
2246  break;
2247  default:
2248  elog(ERROR, "unknown operation");
2249  break;
2250  }
2251 }
2252 
2253 /*
2254  * Set up the state needed for collecting transition tuples for AFTER
2255  * triggers.
2256  */
2257 static void
2259 {
2260  ModifyTable *plan = (ModifyTable *) mtstate->ps.plan;
2261  ResultRelInfo *targetRelInfo = mtstate->rootResultRelInfo;
2262 
2263  /* Check for transition tables on the directly targeted relation. */
2264  mtstate->mt_transition_capture =
2265  MakeTransitionCaptureState(targetRelInfo->ri_TrigDesc,
2266  RelationGetRelid(targetRelInfo->ri_RelationDesc),
2267  mtstate->operation);
2268  if (plan->operation == CMD_INSERT &&
2270  mtstate->mt_oc_transition_capture =
2271  MakeTransitionCaptureState(targetRelInfo->ri_TrigDesc,
2272  RelationGetRelid(targetRelInfo->ri_RelationDesc),
2273  CMD_UPDATE);
2274 }
2275 
2276 /*
2277  * ExecPrepareTupleRouting --- prepare for routing one tuple
2278  *
2279  * Determine the partition in which the tuple in slot is to be inserted,
2280  * and return its ResultRelInfo in *partRelInfo. The return value is
2281  * a slot holding the tuple of the partition rowtype.
2282  *
2283  * This also sets the transition table information in mtstate based on the
2284  * selected partition.
2285  */
2286 static TupleTableSlot *
2288  EState *estate,
2289  PartitionTupleRouting *proute,
2290  ResultRelInfo *targetRelInfo,
2291  TupleTableSlot *slot,
2292  ResultRelInfo **partRelInfo)
2293 {
2294  ResultRelInfo *partrel;
2295  TupleConversionMap *map;
2296 
2297  /*
2298  * Lookup the target partition's ResultRelInfo. If ExecFindPartition does
2299  * not find a valid partition for the tuple in 'slot' then an error is
2300  * raised. An error may also be raised if the found partition is not a
2301  * valid target for INSERTs. This is required since a partitioned table
2302  * UPDATE to another partition becomes a DELETE+INSERT.
2303  */
2304  partrel = ExecFindPartition(mtstate, targetRelInfo, proute, slot, estate);
2305 
2306  /*
2307  * If we're capturing transition tuples, we might need to convert from the
2308  * partition rowtype to root partitioned table's rowtype. But if there
2309  * are no BEFORE triggers on the partition that could change the tuple, we
2310  * can just remember the original unconverted tuple to avoid a needless
2311  * round trip conversion.
2312  */
2313  if (mtstate->mt_transition_capture != NULL)
2314  {
2315  bool has_before_insert_row_trig;
2316 
2317  has_before_insert_row_trig = (partrel->ri_TrigDesc &&
2319 
2321  !has_before_insert_row_trig ? slot : NULL;
2322  }
2323 
2324  /*
2325  * Convert the tuple, if necessary.
2326  */
2327  map = partrel->ri_RootToPartitionMap;
2328  if (map != NULL)
2329  {
2330  TupleTableSlot *new_slot = partrel->ri_PartitionTupleSlot;
2331 
2332  slot = execute_attr_map_slot(map->attrMap, slot, new_slot);
2333  }
2334 
2335  *partRelInfo = partrel;
2336  return slot;
2337 }
2338 
2339 /* ----------------------------------------------------------------
2340  * ExecModifyTable
2341  *
2342  * Perform table modifications as required, and return RETURNING results
2343  * if needed.
2344  * ----------------------------------------------------------------
2345  */
2346 static TupleTableSlot *
2348 {
2349  ModifyTableState *node = castNode(ModifyTableState, pstate);
2350  EState *estate = node->ps.state;
2351  CmdType operation = node->operation;
2352  ResultRelInfo *resultRelInfo;
2353  PlanState *subplanstate;
2354  TupleTableSlot *slot;
2355  TupleTableSlot *planSlot;
2356  TupleTableSlot *oldSlot;
2357  ItemPointer tupleid;
2358  ItemPointerData tuple_ctid;
2359  HeapTupleData oldtupdata;
2360  HeapTuple oldtuple;
2362  List *relinfos = NIL;
2363  ListCell *lc;
2364 
2366 
2367  /*
2368  * This should NOT get called during EvalPlanQual; we should have passed a
2369  * subplan tree to EvalPlanQual, instead. Use a runtime test not just
2370  * Assert because this condition is easy to miss in testing. (Note:
2371  * although ModifyTable should not get executed within an EvalPlanQual
2372  * operation, we do have to allow it to be initialized and shut down in
2373  * case it is within a CTE subplan. Hence this test must be here, not in
2374  * ExecInitModifyTable.)
2375  */
2376  if (estate->es_epq_active != NULL)
2377  elog(ERROR, "ModifyTable should not be called during EvalPlanQual");
2378 
2379  /*
2380  * If we've already completed processing, don't try to do more. We need
2381  * this test because ExecPostprocessPlan might call us an extra time, and
2382  * our subplan's nodes aren't necessarily robust against being called
2383  * extra times.
2384  */
2385  if (node->mt_done)
2386  return NULL;
2387 
2388  /*
2389  * On first call, fire BEFORE STATEMENT triggers before proceeding.
2390  */
2391  if (node->fireBSTriggers)
2392  {
2393  fireBSTriggers(node);
2394  node->fireBSTriggers = false;
2395  }
2396 
2397  /* Preload local variables */
2398  resultRelInfo = node->resultRelInfo + node->mt_lastResultIndex;
2399  subplanstate = outerPlanState(node);
2400 
2401  /*
2402  * Fetch rows from subplan, and execute the required table modification
2403  * for each row.
2404  */
2405  for (;;)
2406  {
2407  /*
2408  * Reset the per-output-tuple exprcontext. This is needed because
2409  * triggers expect to use that context as workspace. It's a bit ugly
2410  * to do this below the top level of the plan, however. We might need
2411  * to rethink this later.
2412  */
2413  ResetPerTupleExprContext(estate);
2414 
2415  /*
2416  * Reset per-tuple memory context used for processing on conflict and
2417  * returning clauses, to free any expression evaluation storage
2418  * allocated in the previous cycle.
2419  */
2420  if (pstate->ps_ExprContext)
2422 
2423  planSlot = ExecProcNode(subplanstate);
2424 
2425  /* No more tuples to process? */
2426  if (TupIsNull(planSlot))
2427  break;
2428 
2429  /*
2430  * When there are multiple result relations, each tuple contains a
2431  * junk column that gives the OID of the rel from which it came.
2432  * Extract it and select the correct result relation.
2433  */
2435  {
2436  Datum datum;
2437  bool isNull;
2438  Oid resultoid;
2439 
2440  datum = ExecGetJunkAttribute(planSlot, node->mt_resultOidAttno,
2441  &isNull);
2442  if (isNull)
2443  elog(ERROR, "tableoid is NULL");
2444  resultoid = DatumGetObjectId(datum);
2445 
2446  /* If it's not the same as last time, we need to locate the rel */
2447  if (resultoid != node->mt_lastResultOid)
2448  resultRelInfo = ExecLookupResultRelByOid(node, resultoid,
2449  false, true);
2450  }
2451 
2452  /*
2453  * If resultRelInfo->ri_usesFdwDirectModify is true, all we need to do
2454  * here is compute the RETURNING expressions.
2455  */
2456  if (resultRelInfo->ri_usesFdwDirectModify)
2457  {
2458  Assert(resultRelInfo->ri_projectReturning);
2459 
2460  /*
2461  * A scan slot containing the data that was actually inserted,
2462  * updated or deleted has already been made available to
2463  * ExecProcessReturning by IterateDirectModify, so no need to
2464  * provide it here.
2465  */
2466  slot = ExecProcessReturning(resultRelInfo, NULL, planSlot);
2467 
2468  return slot;
2469  }
2470 
2471  EvalPlanQualSetSlot(&node->mt_epqstate, planSlot);
2472  slot = planSlot;
2473 
2474  tupleid = NULL;
2475  oldtuple = NULL;
2476 
2477  /*
2478  * For UPDATE/DELETE, fetch the row identity info for the tuple to be
2479  * updated/deleted. For a heap relation, that's a TID; otherwise we
2480  * may have a wholerow junk attr that carries the old tuple in toto.
2481  * Keep this in step with the part of ExecInitModifyTable that sets up
2482  * ri_RowIdAttNo.
2483  */
2484  if (operation == CMD_UPDATE || operation == CMD_DELETE)
2485  {
2486  char relkind;
2487  Datum datum;
2488  bool isNull;
2489 
2490  relkind = resultRelInfo->ri_RelationDesc->rd_rel->relkind;
2491  if (relkind == RELKIND_RELATION ||
2492  relkind == RELKIND_MATVIEW ||
2493  relkind == RELKIND_PARTITIONED_TABLE)
2494  {
2495  /* ri_RowIdAttNo refers to a ctid attribute */
2496  Assert(AttributeNumberIsValid(resultRelInfo->ri_RowIdAttNo));
2497  datum = ExecGetJunkAttribute(slot,
2498  resultRelInfo->ri_RowIdAttNo,
2499  &isNull);
2500  /* shouldn't ever get a null result... */
2501  if (isNull)
2502  elog(ERROR, "ctid is NULL");
2503 
2504  tupleid = (ItemPointer) DatumGetPointer(datum);
2505  tuple_ctid = *tupleid; /* be sure we don't free ctid!! */
2506  tupleid = &tuple_ctid;
2507  }
2508 
2509  /*
2510  * Use the wholerow attribute, when available, to reconstruct the
2511  * old relation tuple. The old tuple serves one or both of two
2512  * purposes: 1) it serves as the OLD tuple for row triggers, 2) it
2513  * provides values for any unchanged columns for the NEW tuple of
2514  * an UPDATE, because the subplan does not produce all the columns
2515  * of the target table.
2516  *
2517  * Note that the wholerow attribute does not carry system columns,
2518  * so foreign table triggers miss seeing those, except that we
2519  * know enough here to set t_tableOid. Quite separately from
2520  * this, the FDW may fetch its own junk attrs to identify the row.
2521  *
2522  * Other relevant relkinds, currently limited to views, always
2523  * have a wholerow attribute.
2524  */
2525  else if (AttributeNumberIsValid(resultRelInfo->ri_RowIdAttNo))
2526  {
2527  datum = ExecGetJunkAttribute(slot,
2528  resultRelInfo->ri_RowIdAttNo,
2529  &isNull);
2530  /* shouldn't ever get a null result... */
2531  if (isNull)
2532  elog(ERROR, "wholerow is NULL");
2533 
2534  oldtupdata.t_data = DatumGetHeapTupleHeader(datum);
2535  oldtupdata.t_len =
2537  ItemPointerSetInvalid(&(oldtupdata.t_self));
2538  /* Historically, view triggers see invalid t_tableOid. */
2539  oldtupdata.t_tableOid =
2540  (relkind == RELKIND_VIEW) ? InvalidOid :
2541  RelationGetRelid(resultRelInfo->ri_RelationDesc);
2542 
2543  oldtuple = &oldtupdata;
2544  }
2545  else
2546  {
2547  /* Only foreign tables are allowed to omit a row-ID attr */
2548  Assert(relkind == RELKIND_FOREIGN_TABLE);
2549  }
2550  }
2551 
2552  switch (operation)
2553  {
2554  case CMD_INSERT:
2555  /* Initialize projection info if first time for this table */
2556  if (unlikely(!resultRelInfo->ri_projectNewInfoValid))
2557  ExecInitInsertProjection(node, resultRelInfo);
2558  slot = ExecGetInsertNewTuple(resultRelInfo, planSlot);
2559  slot = ExecInsert(node, resultRelInfo, slot, planSlot,
2560  estate, node->canSetTag);
2561  break;
2562  case CMD_UPDATE:
2563  /* Initialize projection info if first time for this table */
2564  if (unlikely(!resultRelInfo->ri_projectNewInfoValid))
2565  ExecInitUpdateProjection(node, resultRelInfo);
2566 
2567  /*
2568  * Make the new tuple by combining plan's output tuple with
2569  * the old tuple being updated.
2570  */
2571  oldSlot = resultRelInfo->ri_oldTupleSlot;
2572  if (oldtuple != NULL)
2573  {
2574  /* Use the wholerow junk attr as the old tuple. */
2575  ExecForceStoreHeapTuple(oldtuple, oldSlot, false);
2576  }
2577  else
2578  {
2579  /* Fetch the most recent version of old tuple. */
2580  Relation relation = resultRelInfo->ri_RelationDesc;
2581 
2582  Assert(tupleid != NULL);
2583  if (!table_tuple_fetch_row_version(relation, tupleid,
2584  SnapshotAny,
2585  oldSlot))
2586  elog(ERROR, "failed to fetch tuple being updated");
2587  }
2588  slot = ExecGetUpdateNewTuple(resultRelInfo, planSlot,
2589  oldSlot);
2590 
2591  /* Now apply the update. */
2592  slot = ExecUpdate(node, resultRelInfo, tupleid, oldtuple, slot,
2593  planSlot, &node->mt_epqstate, estate,
2594  node->canSetTag);
2595  break;
2596  case CMD_DELETE:
2597  slot = ExecDelete(node, resultRelInfo, tupleid, oldtuple,
2598  planSlot, &node->mt_epqstate, estate,
2599  true, /* processReturning */
2600  node->canSetTag,
2601  false, /* changingPart */
2602  NULL, NULL);
2603  break;
2604  default:
2605  elog(ERROR, "unknown operation");
2606  break;
2607  }
2608 
2609  /*
2610  * If we got a RETURNING result, return it to caller. We'll continue
2611  * the work on next call.
2612  */
2613  if (slot)
2614  return slot;
2615  }
2616 
2617  /*
2618  * Insert remaining tuples for batch insert.
2619  */
2620  if (proute)
2621  relinfos = estate->es_tuple_routing_result_relations;
2622  else
2623  relinfos = estate->es_opened_result_relations;
2624 
2625  foreach(lc, relinfos)
2626  {
2627  resultRelInfo = lfirst(lc);
2628  if (resultRelInfo->ri_NumSlots > 0)
2629  ExecBatchInsert(node, resultRelInfo,
2630  resultRelInfo->ri_Slots,
2631  resultRelInfo->ri_PlanSlots,
2632  resultRelInfo->ri_NumSlots,
2633  estate, node->canSetTag);
2634  }
2635 
2636  /*
2637  * We're done, but fire AFTER STATEMENT triggers before exiting.
2638  */
2639  fireASTriggers(node);
2640 
2641  node->mt_done = true;
2642 
2643  return NULL;
2644 }
2645 
2646 /*
2647  * ExecLookupResultRelByOid
2648  * If the table with given OID is among the result relations to be
2649  * updated by the given ModifyTable node, return its ResultRelInfo.
2650  *
2651  * If not found, return NULL if missing_ok, else raise error.
2652  *
2653  * If update_cache is true, then upon successful lookup, update the node's
2654  * one-element cache. ONLY ExecModifyTable may pass true for this.
2655  */
2656 ResultRelInfo *
2658  bool missing_ok, bool update_cache)
2659 {
2660  if (node->mt_resultOidHash)
2661  {
2662  /* Use the pre-built hash table to locate the rel */
2663  MTTargetRelLookup *mtlookup;
2664 
2665  mtlookup = (MTTargetRelLookup *)
2666  hash_search(node->mt_resultOidHash, &resultoid, HASH_FIND, NULL);
2667  if (mtlookup)
2668  {
2669  if (update_cache)
2670  {
2671  node->mt_lastResultOid = resultoid;
2672  node->mt_lastResultIndex = mtlookup->relationIndex;
2673  }
2674  return node->resultRelInfo + mtlookup->relationIndex;
2675  }
2676  }
2677  else
2678  {
2679  /* With few target rels, just search the ResultRelInfo array */
2680  for (int ndx = 0; ndx < node->mt_nrels; ndx++)
2681  {
2682  ResultRelInfo *rInfo = node->resultRelInfo + ndx;
2683 
2684  if (RelationGetRelid(rInfo->ri_RelationDesc) == resultoid)
2685  {
2686  if (update_cache)
2687  {
2688  node->mt_lastResultOid = resultoid;
2689  node->mt_lastResultIndex = ndx;
2690  }
2691  return rInfo;
2692  }
2693  }
2694  }
2695 
2696  if (!missing_ok)
2697  elog(ERROR, "incorrect result relation OID %u", resultoid);
2698  return NULL;
2699 }
2700 
2701 /* ----------------------------------------------------------------
2702  * ExecInitModifyTable
2703  * ----------------------------------------------------------------
2704  */
2706 ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
2707 {
2708  ModifyTableState *mtstate;
2709  Plan *subplan = outerPlan(node);
2710  CmdType operation = node->operation;
2711  int nrels = list_length(node->resultRelations);
2712  ResultRelInfo *resultRelInfo;
2713  List *arowmarks;
2714  ListCell *l;
2715  int i;
2716  Relation rel;
2717 
2718  /* check for unsupported flags */
2719  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
2720 
2721  /*
2722  * create state structure
2723  */
2724  mtstate = makeNode(ModifyTableState);
2725  mtstate->ps.plan = (Plan *) node;
2726  mtstate->ps.state = estate;
2727  mtstate->ps.ExecProcNode = ExecModifyTable;
2728 
2729  mtstate->operation = operation;
2730  mtstate->canSetTag = node->canSetTag;
2731  mtstate->mt_done = false;
2732 
2733  mtstate->mt_nrels = nrels;
2734  mtstate->resultRelInfo = (ResultRelInfo *)
2735  palloc(nrels * sizeof(ResultRelInfo));
2736 
2737  /*----------
2738  * Resolve the target relation. This is the same as:
2739  *
2740  * - the relation for which we will fire FOR STATEMENT triggers,
2741  * - the relation into whose tuple format all captured transition tuples
2742  * must be converted, and
2743  * - the root partitioned table used for tuple routing.
2744  *
2745  * If it's a partitioned table, the root partition doesn't appear
2746  * elsewhere in the plan and its RT index is given explicitly in
2747  * node->rootRelation. Otherwise (i.e. table inheritance) the target
2748  * relation is the first relation in the node->resultRelations list.
2749  *----------
2750  */
2751  if (node->rootRelation > 0)
2752  {
2754  ExecInitResultRelation(estate, mtstate->rootResultRelInfo,
2755  node->rootRelation);
2756  }
2757  else
2758  {
2759  mtstate->rootResultRelInfo = mtstate->resultRelInfo;
2760  ExecInitResultRelation(estate, mtstate->resultRelInfo,
2761  linitial_int(node->resultRelations));
2762  }
2763 
2764  /* set up epqstate with dummy subplan data for the moment */
2765  EvalPlanQualInit(&mtstate->mt_epqstate, estate, NULL, NIL, node->epqParam);
2766  mtstate->fireBSTriggers = true;
2767 
2768  /*
2769  * Build state for collecting transition tuples. This requires having a
2770  * valid trigger query context, so skip it in explain-only mode.
2771  */
2772  if (!(eflags & EXEC_FLAG_EXPLAIN_ONLY))
2773  ExecSetupTransitionCaptureState(mtstate, estate);
2774 
2775  /*
2776  * Open all the result relations and initialize the ResultRelInfo structs.
2777  * (But root relation was initialized above, if it's part of the array.)
2778  * We must do this before initializing the subplan, because direct-modify
2779  * FDWs expect their ResultRelInfos to be available.
2780  */
2781  resultRelInfo = mtstate->resultRelInfo;
2782  i = 0;
2783  foreach(l, node->resultRelations)
2784  {
2785  Index resultRelation = lfirst_int(l);
2786 
2787  if (resultRelInfo != mtstate->rootResultRelInfo)
2788  {
2789  ExecInitResultRelation(estate, resultRelInfo, resultRelation);
2790 
2791  /*
2792  * For child result relations, store the root result relation
2793  * pointer. We do so for the convenience of places that want to
2794  * look at the query's original target relation but don't have the
2795  * mtstate handy.
2796  */
2797  resultRelInfo->ri_RootResultRelInfo = mtstate->rootResultRelInfo;
2798  }
2799 
2800  /* Initialize the usesFdwDirectModify flag */
2801  resultRelInfo->ri_usesFdwDirectModify = bms_is_member(i,
2802  node->fdwDirectModifyPlans);
2803 
2804  /*
2805  * Verify result relation is a valid target for the current operation
2806  */
2807  CheckValidResultRel(resultRelInfo, operation);
2808 
2809  resultRelInfo++;
2810  i++;
2811  }
2812 
2813  /*
2814  * Now we may initialize the subplan.
2815  */
2816  outerPlanState(mtstate) = ExecInitNode(subplan, estate, eflags);
2817 
2818  /*
2819  * Do additional per-result-relation initialization.
2820  */
2821  for (i = 0; i < nrels; i++)
2822  {
2823  resultRelInfo = &mtstate->resultRelInfo[i];
2824 
2825  /* Let FDWs init themselves for foreign-table result rels */
2826  if (!resultRelInfo->ri_usesFdwDirectModify &&
2827  resultRelInfo->ri_FdwRoutine != NULL &&
2828  resultRelInfo->ri_FdwRoutine->BeginForeignModify != NULL)
2829  {
2830  List *fdw_private = (List *) list_nth(node->fdwPrivLists, i);
2831 
2832  resultRelInfo->ri_FdwRoutine->BeginForeignModify(mtstate,
2833  resultRelInfo,
2834  fdw_private,
2835  i,
2836  eflags);
2837  }
2838 
2839  /*
2840  * For UPDATE/DELETE, find the appropriate junk attr now, either a
2841  * 'ctid' or 'wholerow' attribute depending on relkind. For foreign
2842  * tables, the FDW might have created additional junk attr(s), but
2843  * those are no concern of ours.
2844  */
2845  if (operation == CMD_UPDATE || operation == CMD_DELETE)
2846  {
2847  char relkind;
2848 
2849  relkind = resultRelInfo->ri_RelationDesc->rd_rel->relkind;
2850  if (relkind == RELKIND_RELATION ||
2851  relkind == RELKIND_MATVIEW ||
2852  relkind == RELKIND_PARTITIONED_TABLE)
2853  {
2854  resultRelInfo->ri_RowIdAttNo =
2855  ExecFindJunkAttributeInTlist(subplan->targetlist, "ctid");
2856  if (!AttributeNumberIsValid(resultRelInfo->ri_RowIdAttNo))
2857  elog(ERROR, "could not find junk ctid column");
2858  }
2859  else if (relkind == RELKIND_FOREIGN_TABLE)
2860  {
2861  /*
2862  * When there is a row-level trigger, there should be a
2863  * wholerow attribute. We also require it to be present in
2864  * UPDATE, so we can get the values of unchanged columns.
2865  */
2866  resultRelInfo->ri_RowIdAttNo =
2868  "wholerow");
2869  if (mtstate->operation == CMD_UPDATE &&
2870  !AttributeNumberIsValid(resultRelInfo->ri_RowIdAttNo))
2871  elog(ERROR, "could not find junk wholerow column");
2872  }
2873  else
2874  {
2875  /* Other valid target relkinds must provide wholerow */
2876  resultRelInfo->ri_RowIdAttNo =
2878  "wholerow");
2879  if (!AttributeNumberIsValid(resultRelInfo->ri_RowIdAttNo))
2880  elog(ERROR, "could not find junk wholerow column");
2881  }
2882  }
2883  }
2884 
2885  /*
2886  * If this is an inherited update/delete, there will be a junk attribute
2887  * named "tableoid" present in the subplan's targetlist. It will be used
2888  * to identify the result relation for a given tuple to be
2889  * updated/deleted.
2890  */
2891  mtstate->mt_resultOidAttno =
2892  ExecFindJunkAttributeInTlist(subplan->targetlist, "tableoid");
2893  Assert(AttributeNumberIsValid(mtstate->mt_resultOidAttno) || nrels == 1);
2894  mtstate->mt_lastResultOid = InvalidOid; /* force lookup at first tuple */
2895  mtstate->mt_lastResultIndex = 0; /* must be zero if no such attr */
2896 
2897  /* Get the root target relation */
2898  rel = mtstate->rootResultRelInfo->ri_RelationDesc;
2899 
2900  /*
2901  * Build state for tuple routing if it's a partitioned INSERT. An UPDATE
2902  * might need this too, but only if it actually moves tuples between
2903  * partitions; in that case setup is done by ExecCrossPartitionUpdate.
2904  */
2905  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
2906  operation == CMD_INSERT)
2907  mtstate->mt_partition_tuple_routing =
2908  ExecSetupPartitionTupleRouting(estate, rel);
2909 
2910  /*
2911  * Initialize any WITH CHECK OPTION constraints if needed.
2912  */
2913  resultRelInfo = mtstate->resultRelInfo;
2914  foreach(l, node->withCheckOptionLists)
2915  {
2916  List *wcoList = (List *) lfirst(l);
2917  List *wcoExprs = NIL;
2918  ListCell *ll;
2919 
2920  foreach(ll, wcoList)
2921  {
2922  WithCheckOption *wco = (WithCheckOption *) lfirst(ll);
2923  ExprState *wcoExpr = ExecInitQual((List *) wco->qual,
2924  &mtstate->ps);
2925 
2926  wcoExprs = lappend(wcoExprs, wcoExpr);
2927  }
2928 
2929  resultRelInfo->ri_WithCheckOptions = wcoList;
2930  resultRelInfo->ri_WithCheckOptionExprs = wcoExprs;
2931  resultRelInfo++;
2932  }
2933 
2934  /*
2935  * Initialize RETURNING projections if needed.
2936  */
2937  if (node->returningLists)
2938  {
2939  TupleTableSlot *slot;
2940  ExprContext *econtext;
2941 
2942  /*
2943  * Initialize result tuple slot and assign its rowtype using the first
2944  * RETURNING list. We assume the rest will look the same.
2945  */
2946  mtstate->ps.plan->targetlist = (List *) linitial(node->returningLists);
2947 
2948  /* Set up a slot for the output of the RETURNING projection(s) */
2950  slot = mtstate->ps.ps_ResultTupleSlot;
2951 
2952  /* Need an econtext too */
2953  if (mtstate->ps.ps_ExprContext == NULL)
2954  ExecAssignExprContext(estate, &mtstate->ps);
2955  econtext = mtstate->ps.ps_ExprContext;
2956 
2957  /*
2958  * Build a projection for each result rel.
2959  */
2960  resultRelInfo = mtstate->resultRelInfo;
2961  foreach(l, node->returningLists)
2962  {
2963  List *rlist = (List *) lfirst(l);
2964 
2965  resultRelInfo->ri_returningList = rlist;
2966  resultRelInfo->ri_projectReturning =
2967  ExecBuildProjectionInfo(rlist, econtext, slot, &mtstate->ps,
2968  resultRelInfo->ri_RelationDesc->rd_att);
2969  resultRelInfo++;
2970  }
2971  }
2972  else
2973  {
2974  /*
2975  * We still must construct a dummy result tuple type, because InitPlan
2976  * expects one (maybe should change that?).
2977  */
2978  mtstate->ps.plan->targetlist = NIL;
2979  ExecInitResultTypeTL(&mtstate->ps);
2980 
2981  mtstate->ps.ps_ExprContext = NULL;
2982  }
2983 
2984  /* Set the list of arbiter indexes if needed for ON CONFLICT */
2985  resultRelInfo = mtstate->resultRelInfo;
2986  if (node->onConflictAction != ONCONFLICT_NONE)
2987  {
2988  /* insert may only have one relation, inheritance is not expanded */
2989  Assert(nrels == 1);
2990  resultRelInfo->ri_onConflictArbiterIndexes = node->arbiterIndexes;
2991  }
2992 
2993  /*
2994  * If needed, Initialize target list, projection and qual for ON CONFLICT
2995  * DO UPDATE.
2996  */
2997  if (node->onConflictAction == ONCONFLICT_UPDATE)
2998  {
3000  ExprContext *econtext;
3001  TupleDesc relationDesc;
3002 
3003  /* already exists if created by RETURNING processing above */
3004  if (mtstate->ps.ps_ExprContext == NULL)
3005  ExecAssignExprContext(estate, &mtstate->ps);
3006 
3007  econtext = mtstate->ps.ps_ExprContext;
3008  relationDesc = resultRelInfo->ri_RelationDesc->rd_att;
3009 
3010  /* create state for DO UPDATE SET operation */
3011  resultRelInfo->ri_onConflict = onconfl;
3012 
3013  /* initialize slot for the existing tuple */
3014  onconfl->oc_Existing =
3015  table_slot_create(resultRelInfo->ri_RelationDesc,
3016  &mtstate->ps.state->es_tupleTable);
3017 
3018  /*
3019  * Create the tuple slot for the UPDATE SET projection. We want a slot
3020  * of the table's type here, because the slot will be used to insert
3021  * into the table, and for RETURNING processing - which may access
3022  * system attributes.
3023  */
3024  onconfl->oc_ProjSlot =
3025  table_slot_create(resultRelInfo->ri_RelationDesc,
3026  &mtstate->ps.state->es_tupleTable);
3027 
3028  /* build UPDATE SET projection state */
3029  onconfl->oc_ProjInfo =
3031  true,
3032  node->onConflictCols,
3033  relationDesc,
3034  econtext,
3035  onconfl->oc_ProjSlot,
3036  &mtstate->ps);
3037 
3038  /* initialize state to evaluate the WHERE clause, if any */
3039  if (node->onConflictWhere)
3040  {
3041  ExprState *qualexpr;
3042 
3043  qualexpr = ExecInitQual((List *) node->onConflictWhere,
3044  &mtstate->ps);
3045  onconfl->oc_WhereClause = qualexpr;
3046  }
3047  }
3048 
3049  /*
3050  * If we have any secondary relations in an UPDATE or DELETE, they need to
3051  * be treated like non-locked relations in SELECT FOR UPDATE, ie, the
3052  * EvalPlanQual mechanism needs to be told about them. Locate the
3053  * relevant ExecRowMarks.
3054  */
3055  arowmarks = NIL;
3056  foreach(l, node->rowMarks)
3057  {
3059  ExecRowMark *erm;
3060  ExecAuxRowMark *aerm;
3061 
3062  /* ignore "parent" rowmarks; they are irrelevant at runtime */
3063  if (rc->isParent)
3064  continue;
3065 
3066  /* Find ExecRowMark and build ExecAuxRowMark */
3067  erm = ExecFindRowMark(estate, rc->rti, false);
3068  aerm = ExecBuildAuxRowMark(erm, subplan->targetlist);
3069  arowmarks = lappend(arowmarks, aerm);
3070  }
3071 
3072  EvalPlanQualSetPlan(&mtstate->mt_epqstate, subplan, arowmarks);
3073 
3074  /*
3075  * If there are a lot of result relations, use a hash table to speed the
3076  * lookups. If there are not a lot, a simple linear search is faster.
3077  *
3078  * It's not clear where the threshold is, but try 64 for starters. In a
3079  * debugging build, use a small threshold so that we get some test
3080  * coverage of both code paths.
3081  */
3082 #ifdef USE_ASSERT_CHECKING
3083 #define MT_NRELS_HASH 4
3084 #else
3085 #define MT_NRELS_HASH 64
3086 #endif
3087  if (nrels >= MT_NRELS_HASH)
3088  {
3089  HASHCTL hash_ctl;
3090 
3091  hash_ctl.keysize = sizeof(Oid);
3092  hash_ctl.entrysize = sizeof(MTTargetRelLookup);
3093  hash_ctl.hcxt = CurrentMemoryContext;
3094  mtstate->mt_resultOidHash =
3095  hash_create("ModifyTable target hash",
3096  nrels, &hash_ctl,
3098  for (i = 0; i < nrels; i++)
3099  {
3100  Oid hashkey;
3101  MTTargetRelLookup *mtlookup;
3102  bool found;
3103 
3104  resultRelInfo = &mtstate->resultRelInfo[i];
3105  hashkey = RelationGetRelid(resultRelInfo->ri_RelationDesc);
3106  mtlookup = (MTTargetRelLookup *)
3107  hash_search(mtstate->mt_resultOidHash, &hashkey,
3108  HASH_ENTER, &found);
3109  Assert(!found);
3110  mtlookup->relationIndex = i;
3111  }
3112  }
3113  else
3114  mtstate->mt_resultOidHash = NULL;
3115 
3116  /*
3117  * Determine if the FDW supports batch insert and determine the batch size
3118  * (a FDW may support batching, but it may be disabled for the
3119  * server/table).
3120  *
3121  * We only do this for INSERT, so that for UPDATE/DELETE the batch size
3122  * remains set to 0.
3123  */
3124  if (operation == CMD_INSERT)
3125  {
3126  /* insert may only have one relation, inheritance is not expanded */
3127  Assert(nrels == 1);
3128  resultRelInfo = mtstate->resultRelInfo;
3129  if (!resultRelInfo->ri_usesFdwDirectModify &&
3130  resultRelInfo->ri_FdwRoutine != NULL &&
3131  resultRelInfo->ri_FdwRoutine->GetForeignModifyBatchSize &&
3132  resultRelInfo->ri_FdwRoutine->ExecForeignBatchInsert)
3133  {
3134  resultRelInfo->ri_BatchSize =
3135  resultRelInfo->ri_FdwRoutine->GetForeignModifyBatchSize(resultRelInfo);
3136  Assert(resultRelInfo->ri_BatchSize >= 1);
3137  }
3138  else
3139  resultRelInfo->ri_BatchSize = 1;
3140  }
3141 
3142  /*
3143  * Lastly, if this is not the primary (canSetTag) ModifyTable node, add it
3144  * to estate->es_auxmodifytables so that it will be run to completion by
3145  * ExecPostprocessPlan. (It'd actually work fine to add the primary
3146  * ModifyTable node too, but there's no need.) Note the use of lcons not
3147  * lappend: we need later-initialized ModifyTable nodes to be shut down
3148  * before earlier ones. This ensures that we don't throw away RETURNING
3149  * rows that need to be seen by a later CTE subplan.
3150  */
3151  if (!mtstate->canSetTag)
3152  estate->es_auxmodifytables = lcons(mtstate,
3153  estate->es_auxmodifytables);
3154 
3155  return mtstate;
3156 }
3157 
3158 /* ----------------------------------------------------------------
3159  * ExecEndModifyTable
3160  *
3161  * Shuts down the plan.
3162  *
3163  * Returns nothing of interest.
3164  * ----------------------------------------------------------------
3165  */
3166 void
3168 {
3169  int i;
3170 
3171  /*
3172  * Allow any FDWs to shut down
3173  */
3174  for (i = 0; i < node->mt_nrels; i++)
3175  {
3176  int j;
3177  ResultRelInfo *resultRelInfo = node->resultRelInfo + i;
3178 
3179  if (!resultRelInfo->ri_usesFdwDirectModify &&
3180  resultRelInfo->ri_FdwRoutine != NULL &&
3181  resultRelInfo->ri_FdwRoutine->EndForeignModify != NULL)
3182  resultRelInfo->ri_FdwRoutine->EndForeignModify(node->ps.state,
3183  resultRelInfo);
3184 
3185  /*
3186  * Cleanup the initialized batch slots. This only matters for FDWs
3187  * with batching, but the other cases will have ri_NumSlotsInitialized
3188  * == 0.
3189  */
3190  for (j = 0; j < resultRelInfo->ri_NumSlotsInitialized; j++)
3191  {
3192  ExecDropSingleTupleTableSlot(resultRelInfo->ri_Slots[j]);
3193  ExecDropSingleTupleTableSlot(resultRelInfo->ri_PlanSlots[j]);
3194  }
3195  }
3196 
3197  /*
3198  * Close all the partitioned tables, leaf partitions, and their indices
3199  * and release the slot used for tuple routing, if set.
3200  */
3201  if (node->mt_partition_tuple_routing)
3202  {
3204 
3205  if (node->mt_root_tuple_slot)
3207  }
3208 
3209  /*
3210  * Free the exprcontext
3211  */
3212  ExecFreeExprContext(&node->ps);
3213 
3214  /*
3215  * clean out the tuple table
3216  */
3217  if (node->ps.ps_ResultTupleSlot)
3219 
3220  /*
3221  * Terminate EPQ execution if active
3222  */
3223  EvalPlanQualEnd(&node->mt_epqstate);
3224 
3225  /*
3226  * shut down subplan
3227  */
3228  ExecEndNode(outerPlanState(node));
3229 }
3230 
3231 void
3233 {
3234  /*
3235  * Currently, we don't need to support rescan on ModifyTable nodes. The
3236  * semantics of that would be a bit debatable anyway.
3237  */
3238  elog(ERROR, "ExecReScanModifyTable is not implemented");
3239 }
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
int ri_NumSlotsInitialized
Definition: execnodes.h:465
List * arbiterIndexes
Definition: plannodes.h:234
struct TransitionCaptureState * mt_oc_transition_capture
Definition: execnodes.h:1229
Relation ri_RelationDesc
Definition: execnodes.h:411
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
LockTupleMode
Definition: lockoptions.h:49
bool ExecIRDeleteTriggers(EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple)
Definition: trigger.c:2722
#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:2461
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:2537
TupleTableSlot * ExecGetReturningSlot(EState *estate, ResultRelInfo *relInfo)
Definition: execUtils.c:1210
CommandId es_output_cid
Definition: execnodes.h:572
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:468
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:1223
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:503
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:1192
#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:1005
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:559
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:1188
Snapshot es_snapshot
Definition: execnodes.h:558
ResultRelInfo * rootResultRelInfo
Definition: execnodes.h:1200
Datum * tts_values
Definition: tuptable.h:126
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
TupleTableSlot ** ri_Slots
Definition: execnodes.h:467
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:968
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:629
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:2588
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:474
#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:2606
void ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TransitionCaptureState *transition_capture)
Definition: trigger.c:2691
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:1004
List * rowMarks
Definition: plannodes.h:231
MemoryContext es_query_cxt
Definition: execnodes.h:600
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:1461
#define linitial(l)
Definition: pg_list.h:174
#define ERROR
Definition: elog.h:46
PlanState ps
Definition: execnodes.h:1187
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:2385
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:514
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:512
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:1062
TransactionId GetCurrentTransactionId(void)
Definition: xact.c:438
uint32 t_len
Definition: htup.h:64
void ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2323
struct TransitionCaptureState * mt_transition_capture
Definition: execnodes.h:1226
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:578
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:1202
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:480
bool trig_update_before_row
Definition: reltrigger.h:61
#define RelationGetRelationName(relation)
Definition: rel.h:511
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:489
#define TupIsNull(slot)
Definition: tuptable.h:292
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
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:1065
ExprState * oc_WhereClause
Definition: execnodes.h:383
EndForeignModify_function EndForeignModify
Definition: fdwapi.h:237
#define InstrCountFiltered1(node, delta)
Definition: execnodes.h:1070
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:483
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:2975
void EvalPlanQualInit(EPQState *epqstate, EState *parentestate, Plan *subplan, List *auxrowmarks, int epqParam)
Definition: execMain.c:2413
OnConflictSetState * ri_onConflict
Definition: execnodes.h:495
#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:2827
List * es_tupleTable
Definition: execnodes.h:602
List * es_auxmodifytables
Definition: execnodes.h:614
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:972
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:2374
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:471
TransitionCaptureState * MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType)
Definition: trigger.c:4548
#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:966
#define InvalidOid
Definition: postgres_ext.h:36
List * es_tuple_routing_result_relations
Definition: execnodes.h:588
#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:466
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:2476
Definition: tableam.h:77
OnConflictAction onConflictAction
Definition: plannodes.h:233
Expr * expr
Definition: primnodes.h:1454
uint64 es_processed
Definition: execnodes.h:604
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:1220
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:2769
#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:513
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:3018
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:2843
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:1124
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:477
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:492
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:486
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:1214
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:451
TupleTableSlot * tcs_original_insert_tuple
Definition: trigger.h:75
PartitionTupleRouting * ExecSetupPartitionTupleRouting(EState *estate, Relation rel)