PostgreSQL Source Code  git master
nodeModifyTable.h File Reference
#include "nodes/execnodes.h"
Include dependency graph for nodeModifyTable.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

ModifyTableStateExecInitModifyTable (ModifyTable *node, EState *estate, int eflags)
 
void ExecEndModifyTable (ModifyTableState *node)
 
void ExecReScanModifyTable (ModifyTableState *node)
 

Function Documentation

◆ ExecEndModifyTable()

void ExecEndModifyTable ( ModifyTableState node)

Definition at line 2653 of file nodeModifyTable.c.

References FdwRoutine::EndForeignModify, EvalPlanQualEnd(), ExecCleanupTupleRouting(), ExecClearTuple(), ExecEndNode(), ExecFreeExprContext(), i, ModifyTableState::mt_epqstate, ModifyTableState::mt_nplans, ModifyTableState::mt_partition_tuple_routing, ModifyTableState::mt_plans, ModifyTableState::ps, PlanState::ps_ResultTupleSlot, ModifyTableState::resultRelInfo, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_usesFdwDirectModify, and PlanState::state.

Referenced by ExecEndNode().

2654 {
2655  int i;
2656 
2657  /*
2658  * Allow any FDWs to shut down
2659  */
2660  for (i = 0; i < node->mt_nplans; i++)
2661  {
2662  ResultRelInfo *resultRelInfo = node->resultRelInfo + i;
2663 
2664  if (!resultRelInfo->ri_usesFdwDirectModify &&
2665  resultRelInfo->ri_FdwRoutine != NULL &&
2666  resultRelInfo->ri_FdwRoutine->EndForeignModify != NULL)
2667  resultRelInfo->ri_FdwRoutine->EndForeignModify(node->ps.state,
2668  resultRelInfo);
2669  }
2670 
2671  /* Close all the partitioned tables, leaf partitions, and their indices */
2672  if (node->mt_partition_tuple_routing)
2674 
2675  /*
2676  * Free the exprcontext
2677  */
2678  ExecFreeExprContext(&node->ps);
2679 
2680  /*
2681  * clean out the tuple table
2682  */
2684 
2685  /*
2686  * Terminate EPQ execution if active
2687  */
2688  EvalPlanQualEnd(&node->mt_epqstate);
2689 
2690  /*
2691  * shut down subplans
2692  */
2693  for (i = 0; i < node->mt_nplans; i++)
2694  ExecEndNode(node->mt_plans[i]);
2695 }
struct PartitionTupleRouting * mt_partition_tuple_routing
Definition: execnodes.h:1053
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:539
ResultRelInfo * resultRelInfo
Definition: execnodes.h:1042
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:475
EState * state
Definition: execnodes.h:913
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:566
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:3251
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:945
PlanState ps
Definition: execnodes.h:1035
void ExecCleanupTupleRouting(ModifyTableState *mtstate, PartitionTupleRouting *proute)
bool ri_usesFdwDirectModify
Definition: execnodes.h:427
EPQState mt_epqstate
Definition: execnodes.h:1046
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:421
EndForeignModify_function EndForeignModify
Definition: fdwapi.h:213
PlanState ** mt_plans
Definition: execnodes.h:1039
int i

◆ ExecInitModifyTable()

ModifyTableState* ExecInitModifyTable ( ModifyTable node,
EState estate,
int  eflags 
)

Definition at line 2179 of file nodeModifyTable.c.

References ModifyTable::arbiterIndexes, Assert, AttributeNumberIsValid, FdwRoutine::BeginForeignModify, bms_is_member(), ModifyTable::canSetTag, ModifyTableState::canSetTag, CheckValidResultRel(), CMD_DELETE, CMD_INSERT, CMD_UPDATE, elog, ModifyTable::epqParam, ERROR, EState::es_auxmodifytables, EState::es_result_relation_info, EState::es_result_relations, EState::es_root_result_relations, EState::es_trig_tuple_slot, EvalPlanQualInit(), EvalPlanQualSetPlan(), ModifyTable::exclRelTlist, EXEC_FLAG_BACKWARD, EXEC_FLAG_EXPLAIN_ONLY, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecBuildAuxRowMark(), ExecBuildProjectionInfo(), ExecCheckPlanOutput(), ExecFindJunkAttribute(), ExecFindRowMark(), ExecInitExtraTupleSlot(), ExecInitJunkFilter(), ExecInitNode(), ExecInitQual(), ExecInitResultTupleSlotTL(), ExecModifyTable(), ExecOpenIndices(), PlanState::ExecProcNode, ExecSetupChildParentMapForSubplan(), ExecSetupPartitionTupleRouting(), ExecSetupTransitionCaptureState(), ExecTypeFromTL(), ModifyTable::fdwDirectModifyPlans, ModifyTable::fdwPrivLists, ModifyTableState::fireBSTriggers, getTargetResultRelInfo(), i, PlanRowMark::isParent, JunkFilter::jf_junkAttNo, lappend(), lcons(), lfirst, lfirst_node, linitial, list_length(), list_nth(), makeNode, ModifyTableState::mt_arowmarks, ModifyTableState::mt_conflproj, ModifyTableState::mt_done, ModifyTableState::mt_epqstate, ModifyTableState::mt_excludedtlist, ModifyTableState::mt_existing, ModifyTableState::mt_nplans, ModifyTableState::mt_partition_tuple_routing, ModifyTableState::mt_plans, ModifyTableState::mt_whichplan, NIL, OnConflictSetState::oc_ProjInfo, OnConflictSetState::oc_ProjTupdesc, OnConflictSetState::oc_WhereClause, ONCONFLICT_NONE, ONCONFLICT_UPDATE, ModifyTable::onConflictAction, ModifyTable::onConflictSet, ModifyTable::onConflictWhere, ModifyTable::operation, ModifyTableState::operation, palloc0(), ModifyTable::partColsUpdated, PlanState::plan, ModifyTable::plans, ModifyTableState::ps, PlanState::ps_ExprContext, PlanState::ps_ResultTupleSlot, WithCheckOption::qual, RelationData::rd_att, RelationData::rd_rel, relkind, TargetEntry::resjunk, ModifyTable::resultRelIndex, ModifyTableState::resultRelInfo, ModifyTable::returningLists, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_junkFilter, ResultRelInfo::ri_onConflict, ResultRelInfo::ri_onConflictArbiterIndexes, ResultRelInfo::ri_projectReturning, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_returningList, ResultRelInfo::ri_TrigDesc, ResultRelInfo::ri_usesFdwDirectModify, ResultRelInfo::ri_WithCheckOptionExprs, ResultRelInfo::ri_WithCheckOptions, ModifyTable::rootResultRelIndex, ModifyTableState::rootResultRelInfo, ModifyTable::rowMarks, PlanRowMark::rti, PlanState::state, Plan::targetlist, tupleDesc::tdhasoid, TriggerDesc::trig_update_before_row, and ModifyTable::withCheckOptionLists.

Referenced by ExecInitNode().

2180 {
2181  ModifyTableState *mtstate;
2182  CmdType operation = node->operation;
2183  int nplans = list_length(node->plans);
2184  ResultRelInfo *saved_resultRelInfo;
2185  ResultRelInfo *resultRelInfo;
2186  Plan *subplan;
2187  ListCell *l;
2188  int i;
2189  Relation rel;
2190  bool update_tuple_routing_needed = node->partColsUpdated;
2191 
2192  /* check for unsupported flags */
2193  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
2194 
2195  /*
2196  * create state structure
2197  */
2198  mtstate = makeNode(ModifyTableState);
2199  mtstate->ps.plan = (Plan *) node;
2200  mtstate->ps.state = estate;
2201  mtstate->ps.ExecProcNode = ExecModifyTable;
2202 
2203  mtstate->operation = operation;
2204  mtstate->canSetTag = node->canSetTag;
2205  mtstate->mt_done = false;
2206 
2207  mtstate->mt_plans = (PlanState **) palloc0(sizeof(PlanState *) * nplans);
2208  mtstate->resultRelInfo = estate->es_result_relations + node->resultRelIndex;
2209 
2210  /* If modifying a partitioned table, initialize the root table info */
2211  if (node->rootResultRelIndex >= 0)
2212  mtstate->rootResultRelInfo = estate->es_root_result_relations +
2213  node->rootResultRelIndex;
2214 
2215  mtstate->mt_arowmarks = (List **) palloc0(sizeof(List *) * nplans);
2216  mtstate->mt_nplans = nplans;
2217 
2218  /* set up epqstate with dummy subplan data for the moment */
2219  EvalPlanQualInit(&mtstate->mt_epqstate, estate, NULL, NIL, node->epqParam);
2220  mtstate->fireBSTriggers = true;
2221 
2222  /*
2223  * call ExecInitNode on each of the plans to be executed and save the
2224  * results into the array "mt_plans". This is also a convenient place to
2225  * verify that the proposed target relations are valid and open their
2226  * indexes for insertion of new index entries. Note we *must* set
2227  * estate->es_result_relation_info correctly while we initialize each
2228  * sub-plan; ExecContextForcesOids depends on that!
2229  */
2230  saved_resultRelInfo = estate->es_result_relation_info;
2231 
2232  resultRelInfo = mtstate->resultRelInfo;
2233  i = 0;
2234  foreach(l, node->plans)
2235  {
2236  subplan = (Plan *) lfirst(l);
2237 
2238  /* Initialize the usesFdwDirectModify flag */
2239  resultRelInfo->ri_usesFdwDirectModify = bms_is_member(i,
2240  node->fdwDirectModifyPlans);
2241 
2242  /*
2243  * Verify result relation is a valid target for the current operation
2244  */
2245  CheckValidResultRel(resultRelInfo, operation);
2246 
2247  /*
2248  * If there are indices on the result relation, open them and save
2249  * descriptors in the result relation info, so that we can add new
2250  * index entries for the tuples we add/update. We need not do this
2251  * for a DELETE, however, since deletion doesn't affect indexes. Also,
2252  * inside an EvalPlanQual operation, the indexes might be open
2253  * already, since we share the resultrel state with the original
2254  * query.
2255  */
2256  if (resultRelInfo->ri_RelationDesc->rd_rel->relhasindex &&
2257  operation != CMD_DELETE &&
2258  resultRelInfo->ri_IndexRelationDescs == NULL)
2259  ExecOpenIndices(resultRelInfo,
2261 
2262  /*
2263  * If this is an UPDATE and a BEFORE UPDATE trigger is present, the
2264  * trigger itself might modify the partition-key values. So arrange
2265  * for tuple routing.
2266  */
2267  if (resultRelInfo->ri_TrigDesc &&
2268  resultRelInfo->ri_TrigDesc->trig_update_before_row &&
2269  operation == CMD_UPDATE)
2270  update_tuple_routing_needed = true;
2271 
2272  /* Now init the plan for this result rel */
2273  estate->es_result_relation_info = resultRelInfo;
2274  mtstate->mt_plans[i] = ExecInitNode(subplan, estate, eflags);
2275 
2276  /* Also let FDWs init themselves for foreign-table result rels */
2277  if (!resultRelInfo->ri_usesFdwDirectModify &&
2278  resultRelInfo->ri_FdwRoutine != NULL &&
2279  resultRelInfo->ri_FdwRoutine->BeginForeignModify != NULL)
2280  {
2281  List *fdw_private = (List *) list_nth(node->fdwPrivLists, i);
2282 
2283  resultRelInfo->ri_FdwRoutine->BeginForeignModify(mtstate,
2284  resultRelInfo,
2285  fdw_private,
2286  i,
2287  eflags);
2288  }
2289 
2290  resultRelInfo++;
2291  i++;
2292  }
2293 
2294  estate->es_result_relation_info = saved_resultRelInfo;
2295 
2296  /* Get the target relation */
2297  rel = (getTargetResultRelInfo(mtstate))->ri_RelationDesc;
2298 
2299  /*
2300  * If it's not a partitioned table after all, UPDATE tuple routing should
2301  * not be attempted.
2302  */
2303  if (rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
2304  update_tuple_routing_needed = false;
2305 
2306  /*
2307  * Build state for tuple routing if it's an INSERT or if it's an UPDATE of
2308  * partition key.
2309  */
2310  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
2311  (operation == CMD_INSERT || update_tuple_routing_needed))
2312  mtstate->mt_partition_tuple_routing =
2313  ExecSetupPartitionTupleRouting(mtstate, rel);
2314 
2315  /*
2316  * Build state for collecting transition tuples. This requires having a
2317  * valid trigger query context, so skip it in explain-only mode.
2318  */
2319  if (!(eflags & EXEC_FLAG_EXPLAIN_ONLY))
2320  ExecSetupTransitionCaptureState(mtstate, estate);
2321 
2322  /*
2323  * Construct mapping from each of the per-subplan partition attnos to the
2324  * root attno. This is required when during update row movement the tuple
2325  * descriptor of a source partition does not match the root partitioned
2326  * table descriptor. In such a case we need to convert tuples to the root
2327  * tuple descriptor, because the search for destination partition starts
2328  * from the root. Skip this setup if it's not a partition key update.
2329  */
2330  if (update_tuple_routing_needed)
2332 
2333  /*
2334  * Initialize any WITH CHECK OPTION constraints if needed.
2335  */
2336  resultRelInfo = mtstate->resultRelInfo;
2337  i = 0;
2338  foreach(l, node->withCheckOptionLists)
2339  {
2340  List *wcoList = (List *) lfirst(l);
2341  List *wcoExprs = NIL;
2342  ListCell *ll;
2343 
2344  foreach(ll, wcoList)
2345  {
2346  WithCheckOption *wco = (WithCheckOption *) lfirst(ll);
2347  ExprState *wcoExpr = ExecInitQual((List *) wco->qual,
2348  mtstate->mt_plans[i]);
2349 
2350  wcoExprs = lappend(wcoExprs, wcoExpr);
2351  }
2352 
2353  resultRelInfo->ri_WithCheckOptions = wcoList;
2354  resultRelInfo->ri_WithCheckOptionExprs = wcoExprs;
2355  resultRelInfo++;
2356  i++;
2357  }
2358 
2359  /*
2360  * Initialize RETURNING projections if needed.
2361  */
2362  if (node->returningLists)
2363  {
2364  TupleTableSlot *slot;
2365  ExprContext *econtext;
2366 
2367  /*
2368  * Initialize result tuple slot and assign its rowtype using the first
2369  * RETURNING list. We assume the rest will look the same.
2370  */
2371  mtstate->ps.plan->targetlist = (List *) linitial(node->returningLists);
2372 
2373  /* Set up a slot for the output of the RETURNING projection(s) */
2374  ExecInitResultTupleSlotTL(estate, &mtstate->ps);
2375  slot = mtstate->ps.ps_ResultTupleSlot;
2376 
2377  /* Need an econtext too */
2378  if (mtstate->ps.ps_ExprContext == NULL)
2379  ExecAssignExprContext(estate, &mtstate->ps);
2380  econtext = mtstate->ps.ps_ExprContext;
2381 
2382  /*
2383  * Build a projection for each result rel.
2384  */
2385  resultRelInfo = mtstate->resultRelInfo;
2386  foreach(l, node->returningLists)
2387  {
2388  List *rlist = (List *) lfirst(l);
2389 
2390  resultRelInfo->ri_returningList = rlist;
2391  resultRelInfo->ri_projectReturning =
2392  ExecBuildProjectionInfo(rlist, econtext, slot, &mtstate->ps,
2393  resultRelInfo->ri_RelationDesc->rd_att);
2394  resultRelInfo++;
2395  }
2396  }
2397  else
2398  {
2399  /*
2400  * We still must construct a dummy result tuple type, because InitPlan
2401  * expects one (maybe should change that?).
2402  */
2403  mtstate->ps.plan->targetlist = NIL;
2404  ExecInitResultTupleSlotTL(estate, &mtstate->ps);
2405 
2406  mtstate->ps.ps_ExprContext = NULL;
2407  }
2408 
2409  /* Set the list of arbiter indexes if needed for ON CONFLICT */
2410  resultRelInfo = mtstate->resultRelInfo;
2411  if (node->onConflictAction != ONCONFLICT_NONE)
2412  resultRelInfo->ri_onConflictArbiterIndexes = node->arbiterIndexes;
2413 
2414  /*
2415  * If needed, Initialize target list, projection and qual for ON CONFLICT
2416  * DO UPDATE.
2417  */
2418  if (node->onConflictAction == ONCONFLICT_UPDATE)
2419  {
2420  ExprContext *econtext;
2421  TupleDesc relationDesc;
2422  TupleDesc tupDesc;
2423 
2424  /* insert may only have one plan, inheritance is not expanded */
2425  Assert(nplans == 1);
2426 
2427  /* already exists if created by RETURNING processing above */
2428  if (mtstate->ps.ps_ExprContext == NULL)
2429  ExecAssignExprContext(estate, &mtstate->ps);
2430 
2431  econtext = mtstate->ps.ps_ExprContext;
2432  relationDesc = resultRelInfo->ri_RelationDesc->rd_att;
2433 
2434  /*
2435  * Initialize slot for the existing tuple. If we'll be performing
2436  * tuple routing, the tuple descriptor to use for this will be
2437  * determined based on which relation the update is actually applied
2438  * to, so we don't set its tuple descriptor here.
2439  */
2440  mtstate->mt_existing =
2441  ExecInitExtraTupleSlot(mtstate->ps.state,
2442  mtstate->mt_partition_tuple_routing ?
2443  NULL : relationDesc);
2444 
2445  /* carried forward solely for the benefit of explain */
2446  mtstate->mt_excludedtlist = node->exclRelTlist;
2447 
2448  /* create state for DO UPDATE SET operation */
2449  resultRelInfo->ri_onConflict = makeNode(OnConflictSetState);
2450 
2451  /*
2452  * Create the tuple slot for the UPDATE SET projection.
2453  *
2454  * Just like mt_existing above, we leave it without a tuple descriptor
2455  * in the case of partitioning tuple routing, so that it can be
2456  * changed by ExecPrepareTupleRouting. In that case, we still save
2457  * the tupdesc in the parent's state: it can be reused by partitions
2458  * with an identical descriptor to the parent.
2459  */
2460  tupDesc = ExecTypeFromTL((List *) node->onConflictSet,
2461  relationDesc->tdhasoid);
2462  mtstate->mt_conflproj =
2463  ExecInitExtraTupleSlot(mtstate->ps.state,
2464  mtstate->mt_partition_tuple_routing ?
2465  NULL : tupDesc);
2466  resultRelInfo->ri_onConflict->oc_ProjTupdesc = tupDesc;
2467 
2468  /* build UPDATE SET projection state */
2469  resultRelInfo->ri_onConflict->oc_ProjInfo =
2470  ExecBuildProjectionInfo(node->onConflictSet, econtext,
2471  mtstate->mt_conflproj, &mtstate->ps,
2472  relationDesc);
2473 
2474  /* initialize state to evaluate the WHERE clause, if any */
2475  if (node->onConflictWhere)
2476  {
2477  ExprState *qualexpr;
2478 
2479  qualexpr = ExecInitQual((List *) node->onConflictWhere,
2480  &mtstate->ps);
2481  resultRelInfo->ri_onConflict->oc_WhereClause = qualexpr;
2482  }
2483  }
2484 
2485  /*
2486  * If we have any secondary relations in an UPDATE or DELETE, they need to
2487  * be treated like non-locked relations in SELECT FOR UPDATE, ie, the
2488  * EvalPlanQual mechanism needs to be told about them. Locate the
2489  * relevant ExecRowMarks.
2490  */
2491  foreach(l, node->rowMarks)
2492  {
2494  ExecRowMark *erm;
2495 
2496  /* ignore "parent" rowmarks; they are irrelevant at runtime */
2497  if (rc->isParent)
2498  continue;
2499 
2500  /* find ExecRowMark (same for all subplans) */
2501  erm = ExecFindRowMark(estate, rc->rti, false);
2502 
2503  /* build ExecAuxRowMark for each subplan */
2504  for (i = 0; i < nplans; i++)
2505  {
2506  ExecAuxRowMark *aerm;
2507 
2508  subplan = mtstate->mt_plans[i]->plan;
2509  aerm = ExecBuildAuxRowMark(erm, subplan->targetlist);
2510  mtstate->mt_arowmarks[i] = lappend(mtstate->mt_arowmarks[i], aerm);
2511  }
2512  }
2513 
2514  /* select first subplan */
2515  mtstate->mt_whichplan = 0;
2516  subplan = (Plan *) linitial(node->plans);
2517  EvalPlanQualSetPlan(&mtstate->mt_epqstate, subplan,
2518  mtstate->mt_arowmarks[0]);
2519 
2520  /*
2521  * Initialize the junk filter(s) if needed. INSERT queries need a filter
2522  * if there are any junk attrs in the tlist. UPDATE and DELETE always
2523  * need a filter, since there's always at least one junk attribute present
2524  * --- no need to look first. Typically, this will be a 'ctid' or
2525  * 'wholerow' attribute, but in the case of a foreign data wrapper it
2526  * might be a set of junk attributes sufficient to identify the remote
2527  * row.
2528  *
2529  * If there are multiple result relations, each one needs its own junk
2530  * filter. Note multiple rels are only possible for UPDATE/DELETE, so we
2531  * can't be fooled by some needing a filter and some not.
2532  *
2533  * This section of code is also a convenient place to verify that the
2534  * output of an INSERT or UPDATE matches the target table(s).
2535  */
2536  {
2537  bool junk_filter_needed = false;
2538 
2539  switch (operation)
2540  {
2541  case CMD_INSERT:
2542  foreach(l, subplan->targetlist)
2543  {
2544  TargetEntry *tle = (TargetEntry *) lfirst(l);
2545 
2546  if (tle->resjunk)
2547  {
2548  junk_filter_needed = true;
2549  break;
2550  }
2551  }
2552  break;
2553  case CMD_UPDATE:
2554  case CMD_DELETE:
2555  junk_filter_needed = true;
2556  break;
2557  default:
2558  elog(ERROR, "unknown operation");
2559  break;
2560  }
2561 
2562  if (junk_filter_needed)
2563  {
2564  resultRelInfo = mtstate->resultRelInfo;
2565  for (i = 0; i < nplans; i++)
2566  {
2567  JunkFilter *j;
2568 
2569  subplan = mtstate->mt_plans[i]->plan;
2570  if (operation == CMD_INSERT || operation == CMD_UPDATE)
2571  ExecCheckPlanOutput(resultRelInfo->ri_RelationDesc,
2572  subplan->targetlist);
2573 
2574  j = ExecInitJunkFilter(subplan->targetlist,
2575  resultRelInfo->ri_RelationDesc->rd_att->tdhasoid,
2576  ExecInitExtraTupleSlot(estate, NULL));
2577 
2578  if (operation == CMD_UPDATE || operation == CMD_DELETE)
2579  {
2580  /* For UPDATE/DELETE, find the appropriate junk attr now */
2581  char relkind;
2582 
2583  relkind = resultRelInfo->ri_RelationDesc->rd_rel->relkind;
2584  if (relkind == RELKIND_RELATION ||
2585  relkind == RELKIND_MATVIEW ||
2586  relkind == RELKIND_PARTITIONED_TABLE)
2587  {
2588  j->jf_junkAttNo = ExecFindJunkAttribute(j, "ctid");
2590  elog(ERROR, "could not find junk ctid column");
2591  }
2592  else if (relkind == RELKIND_FOREIGN_TABLE)
2593  {
2594  /*
2595  * When there is a row-level trigger, there should be
2596  * a wholerow attribute.
2597  */
2598  j->jf_junkAttNo = ExecFindJunkAttribute(j, "wholerow");
2599  }
2600  else
2601  {
2602  j->jf_junkAttNo = ExecFindJunkAttribute(j, "wholerow");
2604  elog(ERROR, "could not find junk wholerow column");
2605  }
2606  }
2607 
2608  resultRelInfo->ri_junkFilter = j;
2609  resultRelInfo++;
2610  }
2611  }
2612  else
2613  {
2614  if (operation == CMD_INSERT)
2616  subplan->targetlist);
2617  }
2618  }
2619 
2620  /*
2621  * Set up a tuple table slot for use for trigger output tuples. In a plan
2622  * containing multiple ModifyTable nodes, all can share one such slot, so
2623  * we keep it in the estate.
2624  */
2625  if (estate->es_trig_tuple_slot == NULL)
2626  estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL);
2627 
2628  /*
2629  * Lastly, if this is not the primary (canSetTag) ModifyTable node, add it
2630  * to estate->es_auxmodifytables so that it will be run to completion by
2631  * ExecPostprocessPlan. (It'd actually work fine to add the primary
2632  * ModifyTable node too, but there's no need.) Note the use of lcons not
2633  * lappend: we need later-initialized ModifyTable nodes to be shut down
2634  * before earlier ones. This ensures that we don't throw away RETURNING
2635  * rows that need to be seen by a later CTE subplan.
2636  */
2637  if (!mtstate->canSetTag)
2638  estate->es_auxmodifytables = lcons(mtstate,
2639  estate->es_auxmodifytables);
2640 
2641  return mtstate;
2642 }
AttrNumber jf_junkAttNo
Definition: execnodes.h:365
#define NIL
Definition: pg_list.h:69
JunkFilter * ri_junkFilter
Definition: execnodes.h:439
List * arbiterIndexes
Definition: plannodes.h:236
Relation ri_RelationDesc
Definition: execnodes.h:397
Bitmapset * fdwDirectModifyPlans
Definition: plannodes.h:232
static ResultRelInfo * getTargetResultRelInfo(ModifyTableState *node)
bool tdhasoid
Definition: tupdesc.h:85
struct PartitionTupleRouting * mt_partition_tuple_routing
Definition: execnodes.h:1053
List * withCheckOptionLists
Definition: plannodes.h:229
int resultRelIndex
Definition: plannodes.h:226
ResultRelInfo * resultRelInfo
Definition: execnodes.h:1042
AttrNumber ExecFindJunkAttribute(JunkFilter *junkfilter, const char *attrName)
Definition: execJunk.c:209
ExprContext * ps_ExprContext
Definition: execnodes.h:946
TupleTableSlot * mt_conflproj
Definition: execnodes.h:1050
bool partColsUpdated
Definition: plannodes.h:224
bool canSetTag
Definition: plannodes.h:220
CmdType operation
Definition: execnodes.h:1036
ResultRelInfo * rootResultRelInfo
Definition: execnodes.h:1043
void EvalPlanQualSetPlan(EPQState *epqstate, Plan *subplan, List *auxrowmarks)
Definition: execMain.c:2847
EState * state
Definition: execnodes.h:913
Form_pg_class rd_rel
Definition: rel.h:84
List * plans
Definition: plannodes.h:228
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc)
Definition: execTuples.c:931
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:205
char relkind
Definition: pg_class.h:51
List * onConflictSet
Definition: plannodes.h:237
int rootResultRelIndex
Definition: plannodes.h:227
void ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative)
Definition: execIndexing.c:149
TupleTableSlot * mt_existing
Definition: execnodes.h:1048
PartitionTupleRouting * ExecSetupPartitionTupleRouting(ModifyTableState *mtstate, Relation rel)
Definition: execPartition.c:76
List * ri_WithCheckOptionExprs
Definition: execnodes.h:433
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:945
static void ExecSetupChildParentMapForSubplan(ModifyTableState *mtstate)
List * rowMarks
Definition: plannodes.h:233
bool resjunk
Definition: primnodes.h:1383
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
PlanState ps
Definition: execnodes.h:1035
ProjectionInfo * oc_ProjInfo
Definition: execnodes.h:377
bool ri_usesFdwDirectModify
Definition: execnodes.h:427
static void ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate)
void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation)
Definition: execMain.c:1104
#define EXEC_FLAG_BACKWARD
Definition: executor.h:60
#define lfirst_node(type, lc)
Definition: pg_list.h:109
void * list_nth(const List *list, int n)
Definition: list.c:410
ResultRelInfo * es_result_relations
Definition: execnodes.h:490
JunkFilter * ExecInitJunkFilter(List *targetList, bool hasoid, TupleTableSlot *slot)
Definition: execJunk.c:61
List * fdwPrivLists
Definition: plannodes.h:231
EPQState mt_epqstate
Definition: execnodes.h:1046
bool trig_update_before_row
Definition: reltrigger.h:60
ProjectionInfo * ri_projectReturning
Definition: execnodes.h:445
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:421
ExprState * oc_WhereClause
Definition: execnodes.h:379
TupleTableSlot * es_trig_tuple_slot
Definition: execnodes.h:512
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:409
TupleDesc ExecTypeFromTL(List *targetList, bool hasoid)
Definition: execTuples.c:965
List * lappend(List *list, void *datum)
Definition: list.c:128
PlanState ** mt_plans
Definition: execnodes.h:1039
OnConflictSetState * ri_onConflict
Definition: execnodes.h:451
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
static TupleTableSlot * ExecModifyTable(PlanState *pstate)
void * palloc0(Size size)
Definition: mcxt.c:955
List * es_auxmodifytables
Definition: execnodes.h:540
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:917
List * ri_WithCheckOptions
Definition: execnodes.h:430
void ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate)
Definition: execTuples.c:890
TupleDesc rd_att
Definition: rel.h:85
void EvalPlanQualInit(EPQState *epqstate, EState *estate, Plan *subplan, List *auxrowmarks, int epqParam)
Definition: execMain.c:2828
Plan * plan
Definition: execnodes.h:911
List * lcons(void *datum, List *list)
Definition: list.c:259
#define makeNode(_type_)
Definition: nodes.h:565
static void ExecCheckPlanOutput(Relation resultRel, List *targetList)
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
#define EXEC_FLAG_MARK
Definition: executor.h:61
OnConflictAction onConflictAction
Definition: plannodes.h:235
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:428
static int list_length(const List *l)
Definition: pg_list.h:89
List * targetlist
Definition: plannodes.h:146
List * mt_excludedtlist
Definition: execnodes.h:1049
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition: execExpr.c:349
CmdType operation
Definition: plannodes.h:219
ResultRelInfo * es_root_result_relations
Definition: execnodes.h:501
int i
List * returningLists
Definition: plannodes.h:230
bool isParent
Definition: plannodes.h:1045
#define elog
Definition: elog.h:219
BeginForeignModify_function BeginForeignModify
Definition: fdwapi.h:209
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:139
Definition: pg_list.h:45
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:486
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:58
TupleDesc oc_ProjTupdesc
Definition: execnodes.h:378
List * ri_onConflictArbiterIndexes
Definition: execnodes.h:448
CmdType
Definition: nodes.h:657
RelationPtr ri_IndexRelationDescs
Definition: execnodes.h:403
ExecAuxRowMark * ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist)
Definition: execMain.c:2429
List * exclRelTlist
Definition: plannodes.h:240
List * ri_returningList
Definition: execnodes.h:442
List ** mt_arowmarks
Definition: execnodes.h:1045
int epqParam
Definition: plannodes.h:234
Node * onConflictWhere
Definition: plannodes.h:238
ExecRowMark * ExecFindRowMark(EState *estate, Index rti, bool missing_ok)
Definition: execMain.c:2405
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:492

◆ ExecReScanModifyTable()

void ExecReScanModifyTable ( ModifyTableState node)

Definition at line 2698 of file nodeModifyTable.c.

References elog, and ERROR.

Referenced by ExecReScan().

2699 {
2700  /*
2701  * Currently, we don't need to support rescan on ModifyTable nodes. The
2702  * semantics of that would be a bit debatable anyway.
2703  */
2704  elog(ERROR, "ExecReScanModifyTable is not implemented");
2705 }
#define ERROR
Definition: elog.h:43
#define elog
Definition: elog.h:219