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 2357 of file nodeModifyTable.c.

References FdwRoutine::EndForeignModify, EvalPlanQualEnd(), ExecClearTuple(), ExecCloseIndices(), ExecDropSingleTupleTableSlot(), ExecEndNode(), ExecFreeExprContext(), heap_close, i, ModifyTableState::mt_epqstate, ModifyTableState::mt_nplans, ModifyTableState::mt_num_dispatch, ModifyTableState::mt_num_partitions, ModifyTableState::mt_partition_dispatch_info, ModifyTableState::mt_partition_tuple_slot, ModifyTableState::mt_partitions, ModifyTableState::mt_plans, NoLock, ModifyTableState::ps, PlanState::ps_ResultTupleSlot, PartitionDispatchData::reldesc, ModifyTableState::resultRelInfo, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_usesFdwDirectModify, PlanState::state, and PartitionDispatchData::tupslot.

Referenced by ExecEndNode().

2358 {
2359  int i;
2360 
2361  /*
2362  * Allow any FDWs to shut down
2363  */
2364  for (i = 0; i < node->mt_nplans; i++)
2365  {
2366  ResultRelInfo *resultRelInfo = node->resultRelInfo + i;
2367 
2368  if (!resultRelInfo->ri_usesFdwDirectModify &&
2369  resultRelInfo->ri_FdwRoutine != NULL &&
2370  resultRelInfo->ri_FdwRoutine->EndForeignModify != NULL)
2371  resultRelInfo->ri_FdwRoutine->EndForeignModify(node->ps.state,
2372  resultRelInfo);
2373  }
2374 
2375  /*
2376  * Close all the partitioned tables, leaf partitions, and their indices
2377  *
2378  * Remember node->mt_partition_dispatch_info[0] corresponds to the root
2379  * partitioned table, which we must not try to close, because it is the
2380  * main target table of the query that will be closed by ExecEndPlan().
2381  * Also, tupslot is NULL for the root partitioned table.
2382  */
2383  for (i = 1; i < node->mt_num_dispatch; i++)
2384  {
2386 
2387  heap_close(pd->reldesc, NoLock);
2389  }
2390  for (i = 0; i < node->mt_num_partitions; i++)
2391  {
2392  ResultRelInfo *resultRelInfo = node->mt_partitions[i];
2393 
2394  ExecCloseIndices(resultRelInfo);
2395  heap_close(resultRelInfo->ri_RelationDesc, NoLock);
2396  }
2397 
2398  /* Release the standalone partition tuple descriptor, if any */
2399  if (node->mt_partition_tuple_slot)
2401 
2402  /*
2403  * Free the exprcontext
2404  */
2405  ExecFreeExprContext(&node->ps);
2406 
2407  /*
2408  * clean out the tuple table
2409  */
2411 
2412  /*
2413  * Terminate EPQ execution if active
2414  */
2415  EvalPlanQualEnd(&node->mt_epqstate);
2416 
2417  /*
2418  * shut down subplans
2419  */
2420  for (i = 0; i < node->mt_nplans; i++)
2421  ExecEndNode(node->mt_plans[i]);
2422 }
Relation ri_RelationDesc
Definition: execnodes.h:354
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:523
ResultRelInfo * resultRelInfo
Definition: execnodes.h:967
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
#define heap_close(r, l)
Definition: heapam.h:97
EState * state
Definition: execnodes.h:851
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:523
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:3208
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:882
PlanState ps
Definition: execnodes.h:960
bool ri_usesFdwDirectModify
Definition: execnodes.h:384
#define NoLock
Definition: lockdefs.h:34
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:216
EPQState mt_epqstate
Definition: execnodes.h:971
ResultRelInfo ** mt_partitions
Definition: execnodes.h:984
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:378
EndForeignModify_function EndForeignModify
Definition: fdwapi.h:206
PlanState ** mt_plans
Definition: execnodes.h:964
TupleTableSlot * tupslot
Definition: execPartition.h:45
TupleTableSlot * mt_partition_tuple_slot
Definition: execnodes.h:987
int i
struct PartitionDispatchData ** mt_partition_dispatch_info
Definition: execnodes.h:979
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Definition: execIndexing.c:224

◆ ExecInitModifyTable()

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

Definition at line 1823 of file nodeModifyTable.c.

References ModifyTable::arbiterIndexes, Assert, AttributeNumberIsValid, FdwRoutine::BeginForeignModify, bms_is_member(), ModifyTable::canSetTag, ModifyTableState::canSetTag, castNode, CheckValidResultRel(), CMD_DELETE, CMD_INSERT, CMD_UPDATE, elog, ModifyTable::epqParam, ERROR, EState::es_auxmodifytables, EState::es_range_table, 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(), ExecAssignResultType(), ExecBuildAuxRowMark(), ExecBuildProjectionInfo(), ExecCheckPlanOutput(), ExecFindJunkAttribute(), ExecFindRowMark(), ExecInitExtraTupleSlot(), ExecInitJunkFilter(), ExecInitNode(), ExecInitQual(), ExecInitResultTupleSlot(), ExecModifyTable(), ExecOpenIndices(), PlanState::ExecProcNode, ExecSetSlotDescriptor(), ExecSetupPartitionTupleRouting(), ExecSetupTransitionCaptureState(), ExecTypeFromTL(), ModifyTable::fdwDirectModifyPlans, ModifyTable::fdwPrivLists, ModifyTableState::fireBSTriggers, getrelid, heap_close, heap_open(), i, PlanRowMark::isParent, JunkFilter::jf_junkAttNo, lappend(), lcons(), lfirst, lfirst_node, linitial, linitial_int, list_length(), list_nth(), makeNode, map_partition_varattnos(), ModifyTableState::mt_arbiterindexes, ModifyTableState::mt_arowmarks, ModifyTableState::mt_conflproj, ModifyTableState::mt_done, ModifyTableState::mt_epqstate, ModifyTableState::mt_excludedtlist, ModifyTableState::mt_existing, ModifyTableState::mt_nplans, ModifyTableState::mt_num_dispatch, ModifyTableState::mt_num_partitions, ModifyTableState::mt_onconflict, ModifyTableState::mt_partition_dispatch_info, ModifyTableState::mt_partition_tupconv_maps, ModifyTableState::mt_partition_tuple_slot, ModifyTableState::mt_partitions, ModifyTableState::mt_plans, ModifyTableState::mt_whichplan, NIL, NoLock, ModifyTable::nominalRelation, ONCONFLICT_NONE, ONCONFLICT_UPDATE, ModifyTable::onConflictAction, ModifyTable::onConflictSet, ModifyTable::onConflictWhere, ModifyTable::operation, ModifyTableState::operation, palloc0(), ModifyTable::partitioned_rels, PlanState::plan, ModifyTable::plans, ModifyTableState::ps, PlanState::ps_ExprContext, PlanState::ps_ResultTupleSlot, WithCheckOption::qual, RelationData::rd_att, RelationData::rd_rel, RELKIND_FOREIGN_TABLE, RELKIND_MATVIEW, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, TargetEntry::resjunk, ModifyTable::resultRelIndex, ModifyTableState::resultRelInfo, ModifyTable::returningLists, ResultRelInfo::ri_FdwRoutine, ResultRelInfo::ri_IndexRelationDescs, ResultRelInfo::ri_junkFilter, ResultRelInfo::ri_onConflictSetProj, ResultRelInfo::ri_onConflictSetWhere, ResultRelInfo::ri_projectReturning, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_usesFdwDirectModify, ResultRelInfo::ri_WithCheckOptionExprs, ResultRelInfo::ri_WithCheckOptions, ModifyTable::rootResultRelIndex, ModifyTableState::rootResultRelInfo, ModifyTable::rowMarks, PlanRowMark::rti, PlanState::state, Plan::targetlist, tupleDesc::tdhasoid, and ModifyTable::withCheckOptionLists.

Referenced by ExecInitNode().

1824 {
1825  ModifyTableState *mtstate;
1826  CmdType operation = node->operation;
1827  int nplans = list_length(node->plans);
1828  ResultRelInfo *saved_resultRelInfo;
1829  ResultRelInfo *resultRelInfo;
1830  TupleDesc tupDesc;
1831  Plan *subplan;
1832  ListCell *l;
1833  int i;
1834  Relation rel;
1835 
1836  /* check for unsupported flags */
1837  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
1838 
1839  /*
1840  * create state structure
1841  */
1842  mtstate = makeNode(ModifyTableState);
1843  mtstate->ps.plan = (Plan *) node;
1844  mtstate->ps.state = estate;
1845  mtstate->ps.ExecProcNode = ExecModifyTable;
1846 
1847  mtstate->operation = operation;
1848  mtstate->canSetTag = node->canSetTag;
1849  mtstate->mt_done = false;
1850 
1851  mtstate->mt_plans = (PlanState **) palloc0(sizeof(PlanState *) * nplans);
1852  mtstate->resultRelInfo = estate->es_result_relations + node->resultRelIndex;
1853 
1854  /* If modifying a partitioned table, initialize the root table info */
1855  if (node->rootResultRelIndex >= 0)
1856  mtstate->rootResultRelInfo = estate->es_root_result_relations +
1857  node->rootResultRelIndex;
1858 
1859  mtstate->mt_arowmarks = (List **) palloc0(sizeof(List *) * nplans);
1860  mtstate->mt_nplans = nplans;
1861  mtstate->mt_onconflict = node->onConflictAction;
1862  mtstate->mt_arbiterindexes = node->arbiterIndexes;
1863 
1864  /* set up epqstate with dummy subplan data for the moment */
1865  EvalPlanQualInit(&mtstate->mt_epqstate, estate, NULL, NIL, node->epqParam);
1866  mtstate->fireBSTriggers = true;
1867 
1868  /*
1869  * call ExecInitNode on each of the plans to be executed and save the
1870  * results into the array "mt_plans". This is also a convenient place to
1871  * verify that the proposed target relations are valid and open their
1872  * indexes for insertion of new index entries. Note we *must* set
1873  * estate->es_result_relation_info correctly while we initialize each
1874  * sub-plan; ExecContextForcesOids depends on that!
1875  */
1876  saved_resultRelInfo = estate->es_result_relation_info;
1877 
1878  resultRelInfo = mtstate->resultRelInfo;
1879  i = 0;
1880  foreach(l, node->plans)
1881  {
1882  subplan = (Plan *) lfirst(l);
1883 
1884  /* Initialize the usesFdwDirectModify flag */
1885  resultRelInfo->ri_usesFdwDirectModify = bms_is_member(i,
1886  node->fdwDirectModifyPlans);
1887 
1888  /*
1889  * Verify result relation is a valid target for the current operation
1890  */
1891  CheckValidResultRel(resultRelInfo, operation);
1892 
1893  /*
1894  * If there are indices on the result relation, open them and save
1895  * descriptors in the result relation info, so that we can add new
1896  * index entries for the tuples we add/update. We need not do this
1897  * for a DELETE, however, since deletion doesn't affect indexes. Also,
1898  * inside an EvalPlanQual operation, the indexes might be open
1899  * already, since we share the resultrel state with the original
1900  * query.
1901  */
1902  if (resultRelInfo->ri_RelationDesc->rd_rel->relhasindex &&
1903  operation != CMD_DELETE &&
1904  resultRelInfo->ri_IndexRelationDescs == NULL)
1905  ExecOpenIndices(resultRelInfo, mtstate->mt_onconflict != ONCONFLICT_NONE);
1906 
1907  /* Now init the plan for this result rel */
1908  estate->es_result_relation_info = resultRelInfo;
1909  mtstate->mt_plans[i] = ExecInitNode(subplan, estate, eflags);
1910 
1911  /* Also let FDWs init themselves for foreign-table result rels */
1912  if (!resultRelInfo->ri_usesFdwDirectModify &&
1913  resultRelInfo->ri_FdwRoutine != NULL &&
1914  resultRelInfo->ri_FdwRoutine->BeginForeignModify != NULL)
1915  {
1916  List *fdw_private = (List *) list_nth(node->fdwPrivLists, i);
1917 
1918  resultRelInfo->ri_FdwRoutine->BeginForeignModify(mtstate,
1919  resultRelInfo,
1920  fdw_private,
1921  i,
1922  eflags);
1923  }
1924 
1925  resultRelInfo++;
1926  i++;
1927  }
1928 
1929  estate->es_result_relation_info = saved_resultRelInfo;
1930 
1931  /* The root table RT index is at the head of the partitioned_rels list */
1932  if (node->partitioned_rels)
1933  {
1934  Index root_rti;
1935  Oid root_oid;
1936 
1937  root_rti = linitial_int(node->partitioned_rels);
1938  root_oid = getrelid(root_rti, estate->es_range_table);
1939  rel = heap_open(root_oid, NoLock); /* locked by InitPlan */
1940  }
1941  else
1942  rel = mtstate->resultRelInfo->ri_RelationDesc;
1943 
1944  /* Build state for INSERT tuple routing */
1945  if (operation == CMD_INSERT &&
1946  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1947  {
1948  PartitionDispatch *partition_dispatch_info;
1949  ResultRelInfo **partitions;
1950  TupleConversionMap **partition_tupconv_maps;
1951  TupleTableSlot *partition_tuple_slot;
1952  int num_parted,
1953  num_partitions;
1954 
1956  node->nominalRelation,
1957  estate,
1958  &partition_dispatch_info,
1959  &partitions,
1960  &partition_tupconv_maps,
1961  &partition_tuple_slot,
1962  &num_parted, &num_partitions);
1963  mtstate->mt_partition_dispatch_info = partition_dispatch_info;
1964  mtstate->mt_num_dispatch = num_parted;
1965  mtstate->mt_partitions = partitions;
1966  mtstate->mt_num_partitions = num_partitions;
1967  mtstate->mt_partition_tupconv_maps = partition_tupconv_maps;
1968  mtstate->mt_partition_tuple_slot = partition_tuple_slot;
1969  }
1970 
1971  /*
1972  * Build state for collecting transition tuples. This requires having a
1973  * valid trigger query context, so skip it in explain-only mode.
1974  */
1975  if (!(eflags & EXEC_FLAG_EXPLAIN_ONLY))
1976  ExecSetupTransitionCaptureState(mtstate, estate);
1977 
1978  /*
1979  * Initialize any WITH CHECK OPTION constraints if needed.
1980  */
1981  resultRelInfo = mtstate->resultRelInfo;
1982  i = 0;
1983  foreach(l, node->withCheckOptionLists)
1984  {
1985  List *wcoList = (List *) lfirst(l);
1986  List *wcoExprs = NIL;
1987  ListCell *ll;
1988 
1989  foreach(ll, wcoList)
1990  {
1991  WithCheckOption *wco = (WithCheckOption *) lfirst(ll);
1992  ExprState *wcoExpr = ExecInitQual((List *) wco->qual,
1993  mtstate->mt_plans[i]);
1994 
1995  wcoExprs = lappend(wcoExprs, wcoExpr);
1996  }
1997 
1998  resultRelInfo->ri_WithCheckOptions = wcoList;
1999  resultRelInfo->ri_WithCheckOptionExprs = wcoExprs;
2000  resultRelInfo++;
2001  i++;
2002  }
2003 
2004  /*
2005  * Build WITH CHECK OPTION constraints for each leaf partition rel. Note
2006  * that we didn't build the withCheckOptionList for each partition within
2007  * the planner, but simple translation of the varattnos for each partition
2008  * will suffice. This only occurs for the INSERT case; UPDATE/DELETE
2009  * cases are handled above.
2010  */
2011  if (node->withCheckOptionLists != NIL && mtstate->mt_num_partitions > 0)
2012  {
2013  List *wcoList;
2014  PlanState *plan;
2015 
2016  /*
2017  * In case of INSERT on partitioned tables, there is only one plan.
2018  * Likewise, there is only one WITH CHECK OPTIONS list, not one per
2019  * partition. We make a copy of the WCO qual for each partition; note
2020  * that, if there are SubPlans in there, they all end up attached to
2021  * the one parent Plan node.
2022  */
2023  Assert(operation == CMD_INSERT &&
2024  list_length(node->withCheckOptionLists) == 1 &&
2025  mtstate->mt_nplans == 1);
2026  wcoList = linitial(node->withCheckOptionLists);
2027  plan = mtstate->mt_plans[0];
2028  for (i = 0; i < mtstate->mt_num_partitions; i++)
2029  {
2030  Relation partrel;
2031  List *mapped_wcoList;
2032  List *wcoExprs = NIL;
2033  ListCell *ll;
2034 
2035  resultRelInfo = mtstate->mt_partitions[i];
2036  partrel = resultRelInfo->ri_RelationDesc;
2037 
2038  /* varno = node->nominalRelation */
2039  mapped_wcoList = map_partition_varattnos(wcoList,
2040  node->nominalRelation,
2041  partrel, rel, NULL);
2042  foreach(ll, mapped_wcoList)
2043  {
2045  ExprState *wcoExpr = ExecInitQual(castNode(List, wco->qual),
2046  plan);
2047 
2048  wcoExprs = lappend(wcoExprs, wcoExpr);
2049  }
2050 
2051  resultRelInfo->ri_WithCheckOptions = mapped_wcoList;
2052  resultRelInfo->ri_WithCheckOptionExprs = wcoExprs;
2053  }
2054  }
2055 
2056  /*
2057  * Initialize RETURNING projections if needed.
2058  */
2059  if (node->returningLists)
2060  {
2061  TupleTableSlot *slot;
2062  ExprContext *econtext;
2063  List *returningList;
2064 
2065  /*
2066  * Initialize result tuple slot and assign its rowtype using the first
2067  * RETURNING list. We assume the rest will look the same.
2068  */
2069  tupDesc = ExecTypeFromTL((List *) linitial(node->returningLists),
2070  false);
2071 
2072  /* Set up a slot for the output of the RETURNING projection(s) */
2073  ExecInitResultTupleSlot(estate, &mtstate->ps);
2074  ExecAssignResultType(&mtstate->ps, tupDesc);
2075  slot = mtstate->ps.ps_ResultTupleSlot;
2076 
2077  /* Need an econtext too */
2078  if (mtstate->ps.ps_ExprContext == NULL)
2079  ExecAssignExprContext(estate, &mtstate->ps);
2080  econtext = mtstate->ps.ps_ExprContext;
2081 
2082  /*
2083  * Build a projection for each result rel.
2084  */
2085  resultRelInfo = mtstate->resultRelInfo;
2086  foreach(l, node->returningLists)
2087  {
2088  List *rlist = (List *) lfirst(l);
2089 
2090  resultRelInfo->ri_projectReturning =
2091  ExecBuildProjectionInfo(rlist, econtext, slot, &mtstate->ps,
2092  resultRelInfo->ri_RelationDesc->rd_att);
2093  resultRelInfo++;
2094  }
2095 
2096  /*
2097  * Build a projection for each leaf partition rel. Note that we
2098  * didn't build the returningList for each partition within the
2099  * planner, but simple translation of the varattnos for each partition
2100  * will suffice. This only occurs for the INSERT case; UPDATE/DELETE
2101  * are handled above.
2102  */
2103  returningList = linitial(node->returningLists);
2104  for (i = 0; i < mtstate->mt_num_partitions; i++)
2105  {
2106  Relation partrel;
2107  List *rlist;
2108 
2109  resultRelInfo = mtstate->mt_partitions[i];
2110  partrel = resultRelInfo->ri_RelationDesc;
2111 
2112  /* varno = node->nominalRelation */
2113  rlist = map_partition_varattnos(returningList,
2114  node->nominalRelation,
2115  partrel, rel, NULL);
2116  resultRelInfo->ri_projectReturning =
2117  ExecBuildProjectionInfo(rlist, econtext, slot, &mtstate->ps,
2118  resultRelInfo->ri_RelationDesc->rd_att);
2119  }
2120  }
2121  else
2122  {
2123  /*
2124  * We still must construct a dummy result tuple type, because InitPlan
2125  * expects one (maybe should change that?).
2126  */
2127  tupDesc = ExecTypeFromTL(NIL, false);
2128  ExecInitResultTupleSlot(estate, &mtstate->ps);
2129  ExecAssignResultType(&mtstate->ps, tupDesc);
2130 
2131  mtstate->ps.ps_ExprContext = NULL;
2132  }
2133 
2134  /* Close the root partitioned rel if we opened it above. */
2135  if (rel != mtstate->resultRelInfo->ri_RelationDesc)
2136  heap_close(rel, NoLock);
2137 
2138  /*
2139  * If needed, Initialize target list, projection and qual for ON CONFLICT
2140  * DO UPDATE.
2141  */
2142  resultRelInfo = mtstate->resultRelInfo;
2143  if (node->onConflictAction == ONCONFLICT_UPDATE)
2144  {
2145  ExprContext *econtext;
2146  TupleDesc tupDesc;
2147 
2148  /* insert may only have one plan, inheritance is not expanded */
2149  Assert(nplans == 1);
2150 
2151  /* already exists if created by RETURNING processing above */
2152  if (mtstate->ps.ps_ExprContext == NULL)
2153  ExecAssignExprContext(estate, &mtstate->ps);
2154 
2155  econtext = mtstate->ps.ps_ExprContext;
2156 
2157  /* initialize slot for the existing tuple */
2158  mtstate->mt_existing = ExecInitExtraTupleSlot(mtstate->ps.state);
2160  resultRelInfo->ri_RelationDesc->rd_att);
2161 
2162  /* carried forward solely for the benefit of explain */
2163  mtstate->mt_excludedtlist = node->exclRelTlist;
2164 
2165  /* create target slot for UPDATE SET projection */
2166  tupDesc = ExecTypeFromTL((List *) node->onConflictSet,
2167  resultRelInfo->ri_RelationDesc->rd_rel->relhasoids);
2168  mtstate->mt_conflproj = ExecInitExtraTupleSlot(mtstate->ps.state);
2169  ExecSetSlotDescriptor(mtstate->mt_conflproj, tupDesc);
2170 
2171  /* build UPDATE SET projection state */
2172  resultRelInfo->ri_onConflictSetProj =
2173  ExecBuildProjectionInfo(node->onConflictSet, econtext,
2174  mtstate->mt_conflproj, &mtstate->ps,
2175  resultRelInfo->ri_RelationDesc->rd_att);
2176 
2177  /* build DO UPDATE WHERE clause expression */
2178  if (node->onConflictWhere)
2179  {
2180  ExprState *qualexpr;
2181 
2182  qualexpr = ExecInitQual((List *) node->onConflictWhere,
2183  &mtstate->ps);
2184 
2185  resultRelInfo->ri_onConflictSetWhere = qualexpr;
2186  }
2187  }
2188 
2189  /*
2190  * If we have any secondary relations in an UPDATE or DELETE, they need to
2191  * be treated like non-locked relations in SELECT FOR UPDATE, ie, the
2192  * EvalPlanQual mechanism needs to be told about them. Locate the
2193  * relevant ExecRowMarks.
2194  */
2195  foreach(l, node->rowMarks)
2196  {
2198  ExecRowMark *erm;
2199 
2200  /* ignore "parent" rowmarks; they are irrelevant at runtime */
2201  if (rc->isParent)
2202  continue;
2203 
2204  /* find ExecRowMark (same for all subplans) */
2205  erm = ExecFindRowMark(estate, rc->rti, false);
2206 
2207  /* build ExecAuxRowMark for each subplan */
2208  for (i = 0; i < nplans; i++)
2209  {
2210  ExecAuxRowMark *aerm;
2211 
2212  subplan = mtstate->mt_plans[i]->plan;
2213  aerm = ExecBuildAuxRowMark(erm, subplan->targetlist);
2214  mtstate->mt_arowmarks[i] = lappend(mtstate->mt_arowmarks[i], aerm);
2215  }
2216  }
2217 
2218  /* select first subplan */
2219  mtstate->mt_whichplan = 0;
2220  subplan = (Plan *) linitial(node->plans);
2221  EvalPlanQualSetPlan(&mtstate->mt_epqstate, subplan,
2222  mtstate->mt_arowmarks[0]);
2223 
2224  /*
2225  * Initialize the junk filter(s) if needed. INSERT queries need a filter
2226  * if there are any junk attrs in the tlist. UPDATE and DELETE always
2227  * need a filter, since there's always at least one junk attribute present
2228  * --- no need to look first. Typically, this will be a 'ctid' or
2229  * 'wholerow' attribute, but in the case of a foreign data wrapper it
2230  * might be a set of junk attributes sufficient to identify the remote
2231  * row.
2232  *
2233  * If there are multiple result relations, each one needs its own junk
2234  * filter. Note multiple rels are only possible for UPDATE/DELETE, so we
2235  * can't be fooled by some needing a filter and some not.
2236  *
2237  * This section of code is also a convenient place to verify that the
2238  * output of an INSERT or UPDATE matches the target table(s).
2239  */
2240  {
2241  bool junk_filter_needed = false;
2242 
2243  switch (operation)
2244  {
2245  case CMD_INSERT:
2246  foreach(l, subplan->targetlist)
2247  {
2248  TargetEntry *tle = (TargetEntry *) lfirst(l);
2249 
2250  if (tle->resjunk)
2251  {
2252  junk_filter_needed = true;
2253  break;
2254  }
2255  }
2256  break;
2257  case CMD_UPDATE:
2258  case CMD_DELETE:
2259  junk_filter_needed = true;
2260  break;
2261  default:
2262  elog(ERROR, "unknown operation");
2263  break;
2264  }
2265 
2266  if (junk_filter_needed)
2267  {
2268  resultRelInfo = mtstate->resultRelInfo;
2269  for (i = 0; i < nplans; i++)
2270  {
2271  JunkFilter *j;
2272 
2273  subplan = mtstate->mt_plans[i]->plan;
2274  if (operation == CMD_INSERT || operation == CMD_UPDATE)
2275  ExecCheckPlanOutput(resultRelInfo->ri_RelationDesc,
2276  subplan->targetlist);
2277 
2278  j = ExecInitJunkFilter(subplan->targetlist,
2279  resultRelInfo->ri_RelationDesc->rd_att->tdhasoid,
2280  ExecInitExtraTupleSlot(estate));
2281 
2282  if (operation == CMD_UPDATE || operation == CMD_DELETE)
2283  {
2284  /* For UPDATE/DELETE, find the appropriate junk attr now */
2285  char relkind;
2286 
2287  relkind = resultRelInfo->ri_RelationDesc->rd_rel->relkind;
2288  if (relkind == RELKIND_RELATION ||
2289  relkind == RELKIND_MATVIEW ||
2290  relkind == RELKIND_PARTITIONED_TABLE)
2291  {
2292  j->jf_junkAttNo = ExecFindJunkAttribute(j, "ctid");
2294  elog(ERROR, "could not find junk ctid column");
2295  }
2296  else if (relkind == RELKIND_FOREIGN_TABLE)
2297  {
2298  /*
2299  * When there is a row-level trigger, there should be
2300  * a wholerow attribute.
2301  */
2302  j->jf_junkAttNo = ExecFindJunkAttribute(j, "wholerow");
2303  }
2304  else
2305  {
2306  j->jf_junkAttNo = ExecFindJunkAttribute(j, "wholerow");
2308  elog(ERROR, "could not find junk wholerow column");
2309  }
2310  }
2311 
2312  resultRelInfo->ri_junkFilter = j;
2313  resultRelInfo++;
2314  }
2315  }
2316  else
2317  {
2318  if (operation == CMD_INSERT)
2320  subplan->targetlist);
2321  }
2322  }
2323 
2324  /*
2325  * Set up a tuple table slot for use for trigger output tuples. In a plan
2326  * containing multiple ModifyTable nodes, all can share one such slot, so
2327  * we keep it in the estate.
2328  */
2329  if (estate->es_trig_tuple_slot == NULL)
2330  estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate);
2331 
2332  /*
2333  * Lastly, if this is not the primary (canSetTag) ModifyTable node, add it
2334  * to estate->es_auxmodifytables so that it will be run to completion by
2335  * ExecPostprocessPlan. (It'd actually work fine to add the primary
2336  * ModifyTable node too, but there's no need.) Note the use of lcons not
2337  * lappend: we need later-initialized ModifyTable nodes to be shut down
2338  * before earlier ones. This ensures that we don't throw away RETURNING
2339  * rows that need to be seen by a later CTE subplan.
2340  */
2341  if (!mtstate->canSetTag)
2342  estate->es_auxmodifytables = lcons(mtstate,
2343  estate->es_auxmodifytables);
2344 
2345  return mtstate;
2346 }
AttrNumber jf_junkAttNo
Definition: execnodes.h:336
#define NIL
Definition: pg_list.h:69
JunkFilter * ri_junkFilter
Definition: execnodes.h:396
List * arbiterIndexes
Definition: plannodes.h:233
Relation ri_RelationDesc
Definition: execnodes.h:354
Bitmapset * fdwDirectModifyPlans
Definition: plannodes.h:229
ExprState * ri_onConflictSetWhere
Definition: execnodes.h:405
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate)
Definition: execTuples.c:852
Index nominalRelation
Definition: plannodes.h:219
bool tdhasoid
Definition: tupdesc.h:82
ProjectionInfo * ri_onConflictSetProj
Definition: execnodes.h:402
List * withCheckOptionLists
Definition: plannodes.h:226
#define castNode(_type_, nodeptr)
Definition: nodes.h:579
int resultRelIndex
Definition: plannodes.h:223
ResultRelInfo * resultRelInfo
Definition: execnodes.h:967
AttrNumber ExecFindJunkAttribute(JunkFilter *junkfilter, const char *attrName)
Definition: execJunk.c:209
ExprContext * ps_ExprContext
Definition: execnodes.h:883
TupleTableSlot * mt_conflproj
Definition: execnodes.h:978
#define RELKIND_MATVIEW
Definition: pg_class.h:165
bool canSetTag
Definition: plannodes.h:218
CmdType operation
Definition: execnodes.h:961
ResultRelInfo * rootResultRelInfo
Definition: execnodes.h:968
void EvalPlanQualSetPlan(EPQState *epqstate, Plan *subplan, List *auxrowmarks)
Definition: execMain.c:2813
#define heap_close(r, l)
Definition: heapam.h:97
EState * state
Definition: execnodes.h:851
List * es_range_table
Definition: execnodes.h:431
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
List * plans
Definition: plannodes.h:225
void ExecAssignResultType(PlanState *planstate, TupleDesc tupDesc)
Definition: execUtils.c:435
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:160
List * map_partition_varattnos(List *expr, int target_varno, Relation partrel, Relation parent, bool *found_whole_row)
Definition: partition.c:1457
List * onConflictSet
Definition: plannodes.h:234
int rootResultRelIndex
Definition: plannodes.h:224
void ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative)
Definition: execIndexing.c:149
TupleTableSlot * mt_existing
Definition: execnodes.h:976
List * ri_WithCheckOptionExprs
Definition: execnodes.h:390
#define linitial_int(l)
Definition: pg_list.h:112
OnConflictAction mt_onconflict
Definition: execnodes.h:973
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:882
List * rowMarks
Definition: plannodes.h:230
bool resjunk
Definition: primnodes.h:1382
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
PlanState ps
Definition: execnodes.h:960
void ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
Definition: execTuples.c:832
bool ri_usesFdwDirectModify
Definition: execnodes.h:384
static void ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate)
void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation)
Definition: execMain.c:1098
#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
#define NoLock
Definition: lockdefs.h:34
ResultRelInfo * es_result_relations
Definition: execnodes.h:441
JunkFilter * ExecInitJunkFilter(List *targetList, bool hasoid, TupleTableSlot *slot)
Definition: execJunk.c:61
List * fdwPrivLists
Definition: plannodes.h:228
EPQState mt_epqstate
Definition: execnodes.h:971
ResultRelInfo ** mt_partitions
Definition: execnodes.h:984
ProjectionInfo * ri_projectReturning
Definition: execnodes.h:399
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:378
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
List * partitioned_rels
Definition: plannodes.h:221
TupleTableSlot * es_trig_tuple_slot
Definition: execnodes.h:460
TupleDesc ExecTypeFromTL(List *targetList, bool hasoid)
Definition: execTuples.c:888
List * lappend(List *list, void *datum)
Definition: list.c:128
PlanState ** mt_plans
Definition: execnodes.h:964
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
static TupleTableSlot * ExecModifyTable(PlanState *pstate)
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
void * palloc0(Size size)
Definition: mcxt.c:877
List * es_auxmodifytables
Definition: execnodes.h:488
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:855
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:247
List * ri_WithCheckOptions
Definition: execnodes.h:387
TupleTableSlot * mt_partition_tuple_slot
Definition: execnodes.h:987
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
unsigned int Index
Definition: c.h:413
TupleDesc rd_att
Definition: rel.h:115
void EvalPlanQualInit(EPQState *epqstate, EState *estate, Plan *subplan, List *auxrowmarks, int epqParam)
Definition: execMain.c:2794
Plan * plan
Definition: execnodes.h:849
List * lcons(void *datum, List *list)
Definition: list.c:259
#define makeNode(_type_)
Definition: nodes.h:558
static void ExecCheckPlanOutput(Relation resultRel, List *targetList)
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
#define EXEC_FLAG_MARK
Definition: executor.h:61
OnConflictAction onConflictAction
Definition: plannodes.h:232
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:425
static int list_length(const List *l)
Definition: pg_list.h:89
void ExecSetupPartitionTupleRouting(Relation rel, Index resultRTindex, EState *estate, PartitionDispatch **pd, ResultRelInfo ***partitions, TupleConversionMap ***tup_conv_maps, TupleTableSlot **partition_tuple_slot, int *num_parted, int *num_partitions)
Definition: execPartition.c:66
List * targetlist
Definition: plannodes.h:144
List * mt_arbiterindexes
Definition: execnodes.h:974
List * mt_excludedtlist
Definition: execnodes.h:977
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition: execExpr.c:301
#define getrelid(rangeindex, rangetable)
Definition: parsetree.h:41
CmdType operation
Definition: plannodes.h:217
ResultRelInfo * es_root_result_relations
Definition: execnodes.h:452
int i
struct PartitionDispatchData ** mt_partition_dispatch_info
Definition: execnodes.h:979
List * returningLists
Definition: plannodes.h:227
bool isParent
Definition: plannodes.h:1024
TupleConversionMap ** mt_partition_tupconv_maps
Definition: execnodes.h:985
#define elog
Definition: elog.h:219
BeginForeignModify_function BeginForeignModify
Definition: fdwapi.h:202
#define RELKIND_RELATION
Definition: pg_class.h:160
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:420
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:58
CmdType
Definition: nodes.h:650
RelationPtr ri_IndexRelationDescs
Definition: execnodes.h:360
ExecAuxRowMark * ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist)
Definition: execMain.c:2407
List * exclRelTlist
Definition: plannodes.h:237
List ** mt_arowmarks
Definition: execnodes.h:970
int epqParam
Definition: plannodes.h:231
Node * onConflictWhere
Definition: plannodes.h:235
ExecRowMark * ExecFindRowMark(EState *estate, Index rti, bool missing_ok)
Definition: execMain.c:2383
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:443

◆ ExecReScanModifyTable()

void ExecReScanModifyTable ( ModifyTableState node)

Definition at line 2425 of file nodeModifyTable.c.

References elog, and ERROR.

Referenced by ExecReScan().

2426 {
2427  /*
2428  * Currently, we don't need to support rescan on ModifyTable nodes. The
2429  * semantics of that would be a bit debatable anyway.
2430  */
2431  elog(ERROR, "ExecReScanModifyTable is not implemented");
2432 }
#define ERROR
Definition: elog.h:43
#define elog
Definition: elog.h:219