PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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)
 
TupleTableSlotExecModifyTable (ModifyTableState *node)
 
void ExecEndModifyTable (ModifyTableState *node)
 
void ExecReScanModifyTable (ModifyTableState *node)
 

Function Documentation

void ExecEndModifyTable ( ModifyTableState node)

Definition at line 2154 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, NULL, 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().

2155 {
2156  int i;
2157 
2158  /*
2159  * Allow any FDWs to shut down
2160  */
2161  for (i = 0; i < node->mt_nplans; i++)
2162  {
2163  ResultRelInfo *resultRelInfo = node->resultRelInfo + i;
2164 
2165  if (!resultRelInfo->ri_usesFdwDirectModify &&
2166  resultRelInfo->ri_FdwRoutine != NULL &&
2167  resultRelInfo->ri_FdwRoutine->EndForeignModify != NULL)
2168  resultRelInfo->ri_FdwRoutine->EndForeignModify(node->ps.state,
2169  resultRelInfo);
2170  }
2171 
2172  /*
2173  * Close all the partitioned tables, leaf partitions, and their indices
2174  *
2175  * Remember node->mt_partition_dispatch_info[0] corresponds to the root
2176  * partitioned table, which we must not try to close, because it is the
2177  * main target table of the query that will be closed by ExecEndPlan().
2178  * Also, tupslot is NULL for the root partitioned table.
2179  */
2180  for (i = 1; i < node->mt_num_dispatch; i++)
2181  {
2183 
2184  heap_close(pd->reldesc, NoLock);
2186  }
2187  for (i = 0; i < node->mt_num_partitions; i++)
2188  {
2189  ResultRelInfo *resultRelInfo = node->mt_partitions + i;
2190 
2191  ExecCloseIndices(resultRelInfo);
2192  heap_close(resultRelInfo->ri_RelationDesc, NoLock);
2193  }
2194 
2195  /* Release the standalone partition tuple descriptor, if any */
2196  if (node->mt_partition_tuple_slot)
2198 
2199  /*
2200  * Free the exprcontext
2201  */
2202  ExecFreeExprContext(&node->ps);
2203 
2204  /*
2205  * clean out the tuple table
2206  */
2208 
2209  /*
2210  * Terminate EPQ execution if active
2211  */
2212  EvalPlanQualEnd(&node->mt_epqstate);
2213 
2214  /*
2215  * shut down subplans
2216  */
2217  for (i = 0; i < node->mt_nplans; i++)
2218  ExecEndNode(node->mt_plans[i]);
2219 }
Relation ri_RelationDesc
Definition: execnodes.h:374
ResultRelInfo * mt_partitions
Definition: execnodes.h:945
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:654
ResultRelInfo * resultRelInfo
Definition: execnodes.h:926
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
#define heap_close(r, l)
Definition: heapam.h:97
EState * state
Definition: execnodes.h:815
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:516
void EvalPlanQualEnd(EPQState *epqstate)
Definition: execMain.c:3162
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:842
PlanState ps
Definition: execnodes.h:919
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:930
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:382
EndForeignModify_function EndForeignModify
Definition: fdwapi.h:200
PlanState ** mt_plans
Definition: execnodes.h:923
TupleTableSlot * tupslot
Definition: partition.h:66
TupleTableSlot * mt_partition_tuple_slot
Definition: execnodes.h:948
#define NULL
Definition: c.h:229
int i
struct PartitionDispatchData ** mt_partition_dispatch_info
Definition: execnodes.h:940
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Definition: execIndexing.c:224
ModifyTableState* ExecInitModifyTable ( ModifyTable node,
EState estate,
int  eflags 
)

Definition at line 1646 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_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_MARK, ExecAssignExprContext(), ExecAssignResultType(), ExecBuildAuxRowMark(), ExecBuildProjectionInfo(), ExecCheckPlanOutput(), ExecFindJunkAttribute(), ExecFindRowMark(), ExecInitExtraTupleSlot(), ExecInitJunkFilter(), ExecInitNode(), ExecInitQual(), ExecInitResultTupleSlot(), ExecOpenIndices(), ExecSetSlotDescriptor(), ExecSetupPartitionTupleRouting(), 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, NULL, 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().

1647 {
1648  ModifyTableState *mtstate;
1649  CmdType operation = node->operation;
1650  int nplans = list_length(node->plans);
1651  ResultRelInfo *saved_resultRelInfo;
1652  ResultRelInfo *resultRelInfo;
1653  TupleDesc tupDesc;
1654  Plan *subplan;
1655  ListCell *l;
1656  int i;
1657  Relation rel;
1658 
1659  /* check for unsupported flags */
1660  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
1661 
1662  /*
1663  * create state structure
1664  */
1665  mtstate = makeNode(ModifyTableState);
1666  mtstate->ps.plan = (Plan *) node;
1667  mtstate->ps.state = estate;
1668 
1669  mtstate->operation = operation;
1670  mtstate->canSetTag = node->canSetTag;
1671  mtstate->mt_done = false;
1672 
1673  mtstate->mt_plans = (PlanState **) palloc0(sizeof(PlanState *) * nplans);
1674  mtstate->resultRelInfo = estate->es_result_relations + node->resultRelIndex;
1675 
1676  /* If modifying a partitioned table, initialize the root table info */
1677  if (node->rootResultRelIndex >= 0)
1678  mtstate->rootResultRelInfo = estate->es_root_result_relations +
1679  node->rootResultRelIndex;
1680 
1681  mtstate->mt_arowmarks = (List **) palloc0(sizeof(List *) * nplans);
1682  mtstate->mt_nplans = nplans;
1683  mtstate->mt_onconflict = node->onConflictAction;
1684  mtstate->mt_arbiterindexes = node->arbiterIndexes;
1685 
1686  /* set up epqstate with dummy subplan data for the moment */
1687  EvalPlanQualInit(&mtstate->mt_epqstate, estate, NULL, NIL, node->epqParam);
1688  mtstate->fireBSTriggers = true;
1689 
1690  /*
1691  * call ExecInitNode on each of the plans to be executed and save the
1692  * results into the array "mt_plans". This is also a convenient place to
1693  * verify that the proposed target relations are valid and open their
1694  * indexes for insertion of new index entries. Note we *must* set
1695  * estate->es_result_relation_info correctly while we initialize each
1696  * sub-plan; ExecContextForcesOids depends on that!
1697  */
1698  saved_resultRelInfo = estate->es_result_relation_info;
1699 
1700  resultRelInfo = mtstate->resultRelInfo;
1701  i = 0;
1702  foreach(l, node->plans)
1703  {
1704  subplan = (Plan *) lfirst(l);
1705 
1706  /* Initialize the usesFdwDirectModify flag */
1707  resultRelInfo->ri_usesFdwDirectModify = bms_is_member(i,
1708  node->fdwDirectModifyPlans);
1709 
1710  /*
1711  * Verify result relation is a valid target for the current operation
1712  */
1713  CheckValidResultRel(resultRelInfo->ri_RelationDesc, operation);
1714 
1715  /*
1716  * If there are indices on the result relation, open them and save
1717  * descriptors in the result relation info, so that we can add new
1718  * index entries for the tuples we add/update. We need not do this
1719  * for a DELETE, however, since deletion doesn't affect indexes. Also,
1720  * inside an EvalPlanQual operation, the indexes might be open
1721  * already, since we share the resultrel state with the original
1722  * query.
1723  */
1724  if (resultRelInfo->ri_RelationDesc->rd_rel->relhasindex &&
1725  operation != CMD_DELETE &&
1726  resultRelInfo->ri_IndexRelationDescs == NULL)
1727  ExecOpenIndices(resultRelInfo, mtstate->mt_onconflict != ONCONFLICT_NONE);
1728 
1729  /* Now init the plan for this result rel */
1730  estate->es_result_relation_info = resultRelInfo;
1731  mtstate->mt_plans[i] = ExecInitNode(subplan, estate, eflags);
1732 
1733  /* Also let FDWs init themselves for foreign-table result rels */
1734  if (!resultRelInfo->ri_usesFdwDirectModify &&
1735  resultRelInfo->ri_FdwRoutine != NULL &&
1736  resultRelInfo->ri_FdwRoutine->BeginForeignModify != NULL)
1737  {
1738  List *fdw_private = (List *) list_nth(node->fdwPrivLists, i);
1739 
1740  resultRelInfo->ri_FdwRoutine->BeginForeignModify(mtstate,
1741  resultRelInfo,
1742  fdw_private,
1743  i,
1744  eflags);
1745  }
1746 
1747  resultRelInfo++;
1748  i++;
1749  }
1750 
1751  estate->es_result_relation_info = saved_resultRelInfo;
1752 
1753  /* The root table RT index is at the head of the partitioned_rels list */
1754  if (node->partitioned_rels)
1755  {
1756  Index root_rti;
1757  Oid root_oid;
1758 
1759  root_rti = linitial_int(node->partitioned_rels);
1760  root_oid = getrelid(root_rti, estate->es_range_table);
1761  rel = heap_open(root_oid, NoLock); /* locked by InitPlan */
1762  }
1763  else
1764  rel = mtstate->resultRelInfo->ri_RelationDesc;
1765 
1766  /* Build state for INSERT tuple routing */
1767  if (operation == CMD_INSERT &&
1768  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1769  {
1770  PartitionDispatch *partition_dispatch_info;
1771  ResultRelInfo *partitions;
1772  TupleConversionMap **partition_tupconv_maps;
1773  TupleTableSlot *partition_tuple_slot;
1774  int num_parted,
1775  num_partitions;
1776 
1778  &partition_dispatch_info,
1779  &partitions,
1780  &partition_tupconv_maps,
1781  &partition_tuple_slot,
1782  &num_parted, &num_partitions);
1783  mtstate->mt_partition_dispatch_info = partition_dispatch_info;
1784  mtstate->mt_num_dispatch = num_parted;
1785  mtstate->mt_partitions = partitions;
1786  mtstate->mt_num_partitions = num_partitions;
1787  mtstate->mt_partition_tupconv_maps = partition_tupconv_maps;
1788  mtstate->mt_partition_tuple_slot = partition_tuple_slot;
1789  }
1790 
1791  /*
1792  * Initialize any WITH CHECK OPTION constraints if needed.
1793  */
1794  resultRelInfo = mtstate->resultRelInfo;
1795  i = 0;
1796  foreach(l, node->withCheckOptionLists)
1797  {
1798  List *wcoList = (List *) lfirst(l);
1799  List *wcoExprs = NIL;
1800  ListCell *ll;
1801 
1802  foreach(ll, wcoList)
1803  {
1804  WithCheckOption *wco = (WithCheckOption *) lfirst(ll);
1805  ExprState *wcoExpr = ExecInitQual((List *) wco->qual,
1806  mtstate->mt_plans[i]);
1807 
1808  wcoExprs = lappend(wcoExprs, wcoExpr);
1809  }
1810 
1811  resultRelInfo->ri_WithCheckOptions = wcoList;
1812  resultRelInfo->ri_WithCheckOptionExprs = wcoExprs;
1813  resultRelInfo++;
1814  i++;
1815  }
1816 
1817  /*
1818  * Build WITH CHECK OPTION constraints for each leaf partition rel. Note
1819  * that we didn't build the withCheckOptionList for each partition within
1820  * the planner, but simple translation of the varattnos for each partition
1821  * will suffice. This only occurs for the INSERT case; UPDATE/DELETE
1822  * cases are handled above.
1823  */
1824  if (node->withCheckOptionLists != NIL && mtstate->mt_num_partitions > 0)
1825  {
1826  List *wcoList;
1827 
1828  Assert(operation == CMD_INSERT);
1829  resultRelInfo = mtstate->mt_partitions;
1830  wcoList = linitial(node->withCheckOptionLists);
1831  for (i = 0; i < mtstate->mt_num_partitions; i++)
1832  {
1833  Relation partrel = resultRelInfo->ri_RelationDesc;
1834  List *mapped_wcoList;
1835  List *wcoExprs = NIL;
1836  ListCell *ll;
1837 
1838  /* varno = node->nominalRelation */
1839  mapped_wcoList = map_partition_varattnos(wcoList,
1840  node->nominalRelation,
1841  partrel, rel);
1842  foreach(ll, mapped_wcoList)
1843  {
1844  WithCheckOption *wco = (WithCheckOption *) lfirst(ll);
1845  ExprState *wcoExpr = ExecInitQual((List *) wco->qual,
1846  mtstate->mt_plans[i]);
1847 
1848  wcoExprs = lappend(wcoExprs, wcoExpr);
1849  }
1850 
1851  resultRelInfo->ri_WithCheckOptions = mapped_wcoList;
1852  resultRelInfo->ri_WithCheckOptionExprs = wcoExprs;
1853  resultRelInfo++;
1854  }
1855  }
1856 
1857  /*
1858  * Initialize RETURNING projections if needed.
1859  */
1860  if (node->returningLists)
1861  {
1862  TupleTableSlot *slot;
1863  ExprContext *econtext;
1864  List *returningList;
1865 
1866  /*
1867  * Initialize result tuple slot and assign its rowtype using the first
1868  * RETURNING list. We assume the rest will look the same.
1869  */
1870  tupDesc = ExecTypeFromTL((List *) linitial(node->returningLists),
1871  false);
1872 
1873  /* Set up a slot for the output of the RETURNING projection(s) */
1874  ExecInitResultTupleSlot(estate, &mtstate->ps);
1875  ExecAssignResultType(&mtstate->ps, tupDesc);
1876  slot = mtstate->ps.ps_ResultTupleSlot;
1877 
1878  /* Need an econtext too */
1879  if (mtstate->ps.ps_ExprContext == NULL)
1880  ExecAssignExprContext(estate, &mtstate->ps);
1881  econtext = mtstate->ps.ps_ExprContext;
1882 
1883  /*
1884  * Build a projection for each result rel.
1885  */
1886  resultRelInfo = mtstate->resultRelInfo;
1887  foreach(l, node->returningLists)
1888  {
1889  List *rlist = (List *) lfirst(l);
1890 
1891  resultRelInfo->ri_projectReturning =
1892  ExecBuildProjectionInfo(rlist, econtext, slot, &mtstate->ps,
1893  resultRelInfo->ri_RelationDesc->rd_att);
1894  resultRelInfo++;
1895  }
1896 
1897  /*
1898  * Build a projection for each leaf partition rel. Note that we
1899  * didn't build the returningList for each partition within the
1900  * planner, but simple translation of the varattnos for each partition
1901  * will suffice. This only occurs for the INSERT case; UPDATE/DELETE
1902  * are handled above.
1903  */
1904  resultRelInfo = mtstate->mt_partitions;
1905  returningList = linitial(node->returningLists);
1906  for (i = 0; i < mtstate->mt_num_partitions; i++)
1907  {
1908  Relation partrel = resultRelInfo->ri_RelationDesc;
1909  List *rlist;
1910 
1911  /* varno = node->nominalRelation */
1912  rlist = map_partition_varattnos(returningList,
1913  node->nominalRelation,
1914  partrel, rel);
1915  resultRelInfo->ri_projectReturning =
1916  ExecBuildProjectionInfo(rlist, econtext, slot, &mtstate->ps,
1917  resultRelInfo->ri_RelationDesc->rd_att);
1918  resultRelInfo++;
1919  }
1920  }
1921  else
1922  {
1923  /*
1924  * We still must construct a dummy result tuple type, because InitPlan
1925  * expects one (maybe should change that?).
1926  */
1927  tupDesc = ExecTypeFromTL(NIL, false);
1928  ExecInitResultTupleSlot(estate, &mtstate->ps);
1929  ExecAssignResultType(&mtstate->ps, tupDesc);
1930 
1931  mtstate->ps.ps_ExprContext = NULL;
1932  }
1933 
1934  /* Close the root partitioned rel if we opened it above. */
1935  if (rel != mtstate->resultRelInfo->ri_RelationDesc)
1936  heap_close(rel, NoLock);
1937 
1938  /*
1939  * If needed, Initialize target list, projection and qual for ON CONFLICT
1940  * DO UPDATE.
1941  */
1942  resultRelInfo = mtstate->resultRelInfo;
1943  if (node->onConflictAction == ONCONFLICT_UPDATE)
1944  {
1945  ExprContext *econtext;
1946  TupleDesc tupDesc;
1947 
1948  /* insert may only have one plan, inheritance is not expanded */
1949  Assert(nplans == 1);
1950 
1951  /* already exists if created by RETURNING processing above */
1952  if (mtstate->ps.ps_ExprContext == NULL)
1953  ExecAssignExprContext(estate, &mtstate->ps);
1954 
1955  econtext = mtstate->ps.ps_ExprContext;
1956 
1957  /* initialize slot for the existing tuple */
1958  mtstate->mt_existing = ExecInitExtraTupleSlot(mtstate->ps.state);
1960  resultRelInfo->ri_RelationDesc->rd_att);
1961 
1962  /* carried forward solely for the benefit of explain */
1963  mtstate->mt_excludedtlist = node->exclRelTlist;
1964 
1965  /* create target slot for UPDATE SET projection */
1966  tupDesc = ExecTypeFromTL((List *) node->onConflictSet,
1967  resultRelInfo->ri_RelationDesc->rd_rel->relhasoids);
1968  mtstate->mt_conflproj = ExecInitExtraTupleSlot(mtstate->ps.state);
1969  ExecSetSlotDescriptor(mtstate->mt_conflproj, tupDesc);
1970 
1971  /* build UPDATE SET projection state */
1972  resultRelInfo->ri_onConflictSetProj =
1973  ExecBuildProjectionInfo(node->onConflictSet, econtext,
1974  mtstate->mt_conflproj, &mtstate->ps,
1975  resultRelInfo->ri_RelationDesc->rd_att);
1976 
1977  /* build DO UPDATE WHERE clause expression */
1978  if (node->onConflictWhere)
1979  {
1980  ExprState *qualexpr;
1981 
1982  qualexpr = ExecInitQual((List *) node->onConflictWhere,
1983  &mtstate->ps);
1984 
1985  resultRelInfo->ri_onConflictSetWhere = qualexpr;
1986  }
1987  }
1988 
1989  /*
1990  * If we have any secondary relations in an UPDATE or DELETE, they need to
1991  * be treated like non-locked relations in SELECT FOR UPDATE, ie, the
1992  * EvalPlanQual mechanism needs to be told about them. Locate the
1993  * relevant ExecRowMarks.
1994  */
1995  foreach(l, node->rowMarks)
1996  {
1998  ExecRowMark *erm;
1999 
2000  /* ignore "parent" rowmarks; they are irrelevant at runtime */
2001  if (rc->isParent)
2002  continue;
2003 
2004  /* find ExecRowMark (same for all subplans) */
2005  erm = ExecFindRowMark(estate, rc->rti, false);
2006 
2007  /* build ExecAuxRowMark for each subplan */
2008  for (i = 0; i < nplans; i++)
2009  {
2010  ExecAuxRowMark *aerm;
2011 
2012  subplan = mtstate->mt_plans[i]->plan;
2013  aerm = ExecBuildAuxRowMark(erm, subplan->targetlist);
2014  mtstate->mt_arowmarks[i] = lappend(mtstate->mt_arowmarks[i], aerm);
2015  }
2016  }
2017 
2018  /* select first subplan */
2019  mtstate->mt_whichplan = 0;
2020  subplan = (Plan *) linitial(node->plans);
2021  EvalPlanQualSetPlan(&mtstate->mt_epqstate, subplan,
2022  mtstate->mt_arowmarks[0]);
2023 
2024  /*
2025  * Initialize the junk filter(s) if needed. INSERT queries need a filter
2026  * if there are any junk attrs in the tlist. UPDATE and DELETE always
2027  * need a filter, since there's always a junk 'ctid' or 'wholerow'
2028  * attribute present --- no need to look first.
2029  *
2030  * If there are multiple result relations, each one needs its own junk
2031  * filter. Note multiple rels are only possible for UPDATE/DELETE, so we
2032  * can't be fooled by some needing a filter and some not.
2033  *
2034  * This section of code is also a convenient place to verify that the
2035  * output of an INSERT or UPDATE matches the target table(s).
2036  */
2037  {
2038  bool junk_filter_needed = false;
2039 
2040  switch (operation)
2041  {
2042  case CMD_INSERT:
2043  foreach(l, subplan->targetlist)
2044  {
2045  TargetEntry *tle = (TargetEntry *) lfirst(l);
2046 
2047  if (tle->resjunk)
2048  {
2049  junk_filter_needed = true;
2050  break;
2051  }
2052  }
2053  break;
2054  case CMD_UPDATE:
2055  case CMD_DELETE:
2056  junk_filter_needed = true;
2057  break;
2058  default:
2059  elog(ERROR, "unknown operation");
2060  break;
2061  }
2062 
2063  if (junk_filter_needed)
2064  {
2065  resultRelInfo = mtstate->resultRelInfo;
2066  for (i = 0; i < nplans; i++)
2067  {
2068  JunkFilter *j;
2069 
2070  subplan = mtstate->mt_plans[i]->plan;
2071  if (operation == CMD_INSERT || operation == CMD_UPDATE)
2072  ExecCheckPlanOutput(resultRelInfo->ri_RelationDesc,
2073  subplan->targetlist);
2074 
2075  j = ExecInitJunkFilter(subplan->targetlist,
2076  resultRelInfo->ri_RelationDesc->rd_att->tdhasoid,
2077  ExecInitExtraTupleSlot(estate));
2078 
2079  if (operation == CMD_UPDATE || operation == CMD_DELETE)
2080  {
2081  /* For UPDATE/DELETE, find the appropriate junk attr now */
2082  char relkind;
2083 
2084  relkind = resultRelInfo->ri_RelationDesc->rd_rel->relkind;
2085  if (relkind == RELKIND_RELATION ||
2086  relkind == RELKIND_MATVIEW ||
2087  relkind == RELKIND_PARTITIONED_TABLE)
2088  {
2089  j->jf_junkAttNo = ExecFindJunkAttribute(j, "ctid");
2091  elog(ERROR, "could not find junk ctid column");
2092  }
2093  else if (relkind == RELKIND_FOREIGN_TABLE)
2094  {
2095  /*
2096  * When there is an AFTER trigger, there should be a
2097  * wholerow attribute.
2098  */
2099  j->jf_junkAttNo = ExecFindJunkAttribute(j, "wholerow");
2100  }
2101  else
2102  {
2103  j->jf_junkAttNo = ExecFindJunkAttribute(j, "wholerow");
2105  elog(ERROR, "could not find junk wholerow column");
2106  }
2107  }
2108 
2109  resultRelInfo->ri_junkFilter = j;
2110  resultRelInfo++;
2111  }
2112  }
2113  else
2114  {
2115  if (operation == CMD_INSERT)
2117  subplan->targetlist);
2118  }
2119  }
2120 
2121  /*
2122  * Set up a tuple table slot for use for trigger output tuples. In a plan
2123  * containing multiple ModifyTable nodes, all can share one such slot, so
2124  * we keep it in the estate.
2125  */
2126  if (estate->es_trig_tuple_slot == NULL)
2127  estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate);
2128 
2129  /*
2130  * Lastly, if this is not the primary (canSetTag) ModifyTable node, add it
2131  * to estate->es_auxmodifytables so that it will be run to completion by
2132  * ExecPostprocessPlan. (It'd actually work fine to add the primary
2133  * ModifyTable node too, but there's no need.) Note the use of lcons not
2134  * lappend: we need later-initialized ModifyTable nodes to be shut down
2135  * before earlier ones. This ensures that we don't throw away RETURNING
2136  * rows that need to be seen by a later CTE subplan.
2137  */
2138  if (!mtstate->canSetTag)
2139  estate->es_auxmodifytables = lcons(mtstate,
2140  estate->es_auxmodifytables);
2141 
2142  return mtstate;
2143 }
AttrNumber jf_junkAttNo
Definition: execnodes.h:336
#define NIL
Definition: pg_list.h:69
JunkFilter * ri_junkFilter
Definition: execnodes.h:388
List * arbiterIndexes
Definition: plannodes.h:233
Relation ri_RelationDesc
Definition: execnodes.h:374
Bitmapset * fdwDirectModifyPlans
Definition: plannodes.h:229
ExprState * ri_onConflictSetWhere
Definition: execnodes.h:391
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate)
Definition: execTuples.c:852
Index nominalRelation
Definition: plannodes.h:219
bool tdhasoid
Definition: tupdesc.h:79
ProjectionInfo * ri_onConflictSetProj
Definition: execnodes.h:390
ResultRelInfo * mt_partitions
Definition: execnodes.h:945
List * withCheckOptionLists
Definition: plannodes.h:226
int resultRelIndex
Definition: plannodes.h:223
ResultRelInfo * resultRelInfo
Definition: execnodes.h:926
AttrNumber ExecFindJunkAttribute(JunkFilter *junkfilter, const char *attrName)
Definition: execJunk.c:209
ExprContext * ps_ExprContext
Definition: execnodes.h:843
TupleTableSlot * mt_conflproj
Definition: execnodes.h:938
#define RELKIND_MATVIEW
Definition: pg_class.h:165
bool canSetTag
Definition: plannodes.h:218
CmdType operation
Definition: execnodes.h:920
ResultRelInfo * rootResultRelInfo
Definition: execnodes.h:927
void EvalPlanQualSetPlan(EPQState *epqstate, Plan *subplan, List *auxrowmarks)
Definition: execMain.c:2770
#define heap_close(r, l)
Definition: heapam.h:97
EState * state
Definition: execnodes.h:815
List * es_range_table
Definition: execnodes.h:411
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:428
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:160
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:935
List * ri_WithCheckOptionExprs
Definition: execnodes.h:386
#define linitial_int(l)
Definition: pg_list.h:112
OnConflictAction mt_onconflict
Definition: execnodes.h:932
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:842
List * rowMarks
Definition: plannodes.h:230
void ExecSetupPartitionTupleRouting(Relation rel, PartitionDispatch **pd, ResultRelInfo **partitions, TupleConversionMap ***tup_conv_maps, TupleTableSlot **partition_tuple_slot, int *num_parted, int *num_partitions)
Definition: execMain.c:3224
bool resjunk
Definition: primnodes.h:1374
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
PlanState ps
Definition: execnodes.h:919
void ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
Definition: execTuples.c:832
bool ri_usesFdwDirectModify
Definition: execnodes.h:384
#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:421
JunkFilter * ExecInitJunkFilter(List *targetList, bool hasoid, TupleTableSlot *slot)
Definition: execJunk.c:61
List * fdwPrivLists
Definition: plannodes.h:228
EPQState mt_epqstate
Definition: execnodes.h:930
ProjectionInfo * ri_projectReturning
Definition: execnodes.h:389
void CheckValidResultRel(Relation resultRel, CmdType operation)
Definition: execMain.c:1097
struct FdwRoutine * ri_FdwRoutine
Definition: execnodes.h:382
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
List * partitioned_rels
Definition: plannodes.h:221
TupleTableSlot * es_trig_tuple_slot
Definition: execnodes.h:437
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:923
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
void * palloc0(Size size)
Definition: mcxt.c:878
List * es_auxmodifytables
Definition: execnodes.h:465
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:247
List * ri_WithCheckOptions
Definition: execnodes.h:385
TupleTableSlot * mt_partition_tuple_slot
Definition: execnodes.h:948
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
unsigned int Index
Definition: c.h:365
TupleDesc rd_att
Definition: rel.h:115
void EvalPlanQualInit(EPQState *epqstate, EState *estate, Plan *subplan, List *auxrowmarks, int epqParam)
Definition: execMain.c:2751
Plan * plan
Definition: execnodes.h:813
List * lcons(void *datum, List *list)
Definition: list.c:259
#define makeNode(_type_)
Definition: nodes.h:557
static void ExecCheckPlanOutput(Relation resultRel, List *targetList)
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#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:418
static int list_length(const List *l)
Definition: pg_list.h:89
List * targetlist
Definition: plannodes.h:144
List * mt_arbiterindexes
Definition: execnodes.h:933
List * mt_excludedtlist
Definition: execnodes.h:936
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:432
int i
struct PartitionDispatchData ** mt_partition_dispatch_info
Definition: execnodes.h:940
List * returningLists
Definition: plannodes.h:227
bool isParent
Definition: plannodes.h:1013
TupleConversionMap ** mt_partition_tupconv_maps
Definition: execnodes.h:946
#define elog
Definition: elog.h:219
BeginForeignModify_function BeginForeignModify
Definition: fdwapi.h:196
#define RELKIND_RELATION
Definition: pg_class.h:160
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:140
Definition: pg_list.h:45
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:420
CmdType
Definition: nodes.h:648
RelationPtr ri_IndexRelationDescs
Definition: execnodes.h:376
ExecAuxRowMark * ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist)
Definition: execMain.c:2364
List * exclRelTlist
Definition: plannodes.h:237
List ** mt_arowmarks
Definition: execnodes.h:929
int epqParam
Definition: plannodes.h:231
List * map_partition_varattnos(List *expr, int target_varno, Relation partrel, Relation parent)
Definition: partition.c:932
Node * onConflictWhere
Definition: plannodes.h:235
ExecRowMark * ExecFindRowMark(EState *estate, Index rti, bool missing_ok)
Definition: execMain.c:2340
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:423
TupleTableSlot* ExecModifyTable ( ModifyTableState node)

Definition at line 1406 of file nodeModifyTable.c.

References Assert, AttributeNumberIsValid, ModifyTableState::canSetTag, CMD_DELETE, CMD_INSERT, CMD_UPDATE, DatumGetHeapTupleHeader, DatumGetPointer, elog, ERROR, EState::es_epqTuple, EState::es_result_relation_info, EvalPlanQualSetPlan(), EvalPlanQualSetSlot, ExecDelete(), ExecFilterJunk(), ExecGetJunkAttribute(), ExecInsert(), ExecProcessReturning(), ExecProcNode(), ExecUpdate(), fireASTriggers(), ModifyTableState::fireBSTriggers, fireBSTriggers(), HeapTupleHeaderGetDatumLength, InvalidOid, ItemPointerSetInvalid, JunkFilter::jf_junkAttNo, ModifyTableState::mt_arbiterindexes, ModifyTableState::mt_arowmarks, ModifyTableState::mt_done, ModifyTableState::mt_epqstate, ModifyTableState::mt_nplans, ModifyTableState::mt_onconflict, ModifyTableState::mt_plans, ModifyTableState::mt_whichplan, NULL, ModifyTableState::operation, PlanState::plan, ModifyTableState::ps, RelationData::rd_rel, RelationGetRelid, RELKIND_FOREIGN_TABLE, RELKIND_MATVIEW, RELKIND_RELATION, RELKIND_VIEW, ResetPerTupleExprContext, ModifyTableState::resultRelInfo, ResultRelInfo::ri_junkFilter, ResultRelInfo::ri_projectReturning, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_usesFdwDirectModify, PlanState::state, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, and TupIsNull.

Referenced by ExecProcNode().

1407 {
1408  EState *estate = node->ps.state;
1409  CmdType operation = node->operation;
1410  ResultRelInfo *saved_resultRelInfo;
1411  ResultRelInfo *resultRelInfo;
1412  PlanState *subplanstate;
1413  JunkFilter *junkfilter;
1414  TupleTableSlot *slot;
1415  TupleTableSlot *planSlot;
1416  ItemPointer tupleid = NULL;
1417  ItemPointerData tuple_ctid;
1418  HeapTupleData oldtupdata;
1419  HeapTuple oldtuple;
1420 
1421  /*
1422  * This should NOT get called during EvalPlanQual; we should have passed a
1423  * subplan tree to EvalPlanQual, instead. Use a runtime test not just
1424  * Assert because this condition is easy to miss in testing. (Note:
1425  * although ModifyTable should not get executed within an EvalPlanQual
1426  * operation, we do have to allow it to be initialized and shut down in
1427  * case it is within a CTE subplan. Hence this test must be here, not in
1428  * ExecInitModifyTable.)
1429  */
1430  if (estate->es_epqTuple != NULL)
1431  elog(ERROR, "ModifyTable should not be called during EvalPlanQual");
1432 
1433  /*
1434  * If we've already completed processing, don't try to do more. We need
1435  * this test because ExecPostprocessPlan might call us an extra time, and
1436  * our subplan's nodes aren't necessarily robust against being called
1437  * extra times.
1438  */
1439  if (node->mt_done)
1440  return NULL;
1441 
1442  /*
1443  * On first call, fire BEFORE STATEMENT triggers before proceeding.
1444  */
1445  if (node->fireBSTriggers)
1446  {
1447  fireBSTriggers(node);
1448  node->fireBSTriggers = false;
1449  }
1450 
1451  /* Preload local variables */
1452  resultRelInfo = node->resultRelInfo + node->mt_whichplan;
1453  subplanstate = node->mt_plans[node->mt_whichplan];
1454  junkfilter = resultRelInfo->ri_junkFilter;
1455 
1456  /*
1457  * es_result_relation_info must point to the currently active result
1458  * relation while we are within this ModifyTable node. Even though
1459  * ModifyTable nodes can't be nested statically, they can be nested
1460  * dynamically (since our subplan could include a reference to a modifying
1461  * CTE). So we have to save and restore the caller's value.
1462  */
1463  saved_resultRelInfo = estate->es_result_relation_info;
1464 
1465  estate->es_result_relation_info = resultRelInfo;
1466 
1467  /*
1468  * Fetch rows from subplan(s), and execute the required table modification
1469  * for each row.
1470  */
1471  for (;;)
1472  {
1473  /*
1474  * Reset the per-output-tuple exprcontext. This is needed because
1475  * triggers expect to use that context as workspace. It's a bit ugly
1476  * to do this below the top level of the plan, however. We might need
1477  * to rethink this later.
1478  */
1479  ResetPerTupleExprContext(estate);
1480 
1481  planSlot = ExecProcNode(subplanstate);
1482 
1483  if (TupIsNull(planSlot))
1484  {
1485  /* advance to next subplan if any */
1486  node->mt_whichplan++;
1487  if (node->mt_whichplan < node->mt_nplans)
1488  {
1489  resultRelInfo++;
1490  subplanstate = node->mt_plans[node->mt_whichplan];
1491  junkfilter = resultRelInfo->ri_junkFilter;
1492  estate->es_result_relation_info = resultRelInfo;
1493  EvalPlanQualSetPlan(&node->mt_epqstate, subplanstate->plan,
1494  node->mt_arowmarks[node->mt_whichplan]);
1495  continue;
1496  }
1497  else
1498  break;
1499  }
1500 
1501  /*
1502  * If resultRelInfo->ri_usesFdwDirectModify is true, all we need to do
1503  * here is compute the RETURNING expressions.
1504  */
1505  if (resultRelInfo->ri_usesFdwDirectModify)
1506  {
1507  Assert(resultRelInfo->ri_projectReturning);
1508 
1509  /*
1510  * A scan slot containing the data that was actually inserted,
1511  * updated or deleted has already been made available to
1512  * ExecProcessReturning by IterateDirectModify, so no need to
1513  * provide it here.
1514  */
1515  slot = ExecProcessReturning(resultRelInfo, NULL, planSlot);
1516 
1517  estate->es_result_relation_info = saved_resultRelInfo;
1518  return slot;
1519  }
1520 
1521  EvalPlanQualSetSlot(&node->mt_epqstate, planSlot);
1522  slot = planSlot;
1523 
1524  oldtuple = NULL;
1525  if (junkfilter != NULL)
1526  {
1527  /*
1528  * extract the 'ctid' or 'wholerow' junk attribute.
1529  */
1530  if (operation == CMD_UPDATE || operation == CMD_DELETE)
1531  {
1532  char relkind;
1533  Datum datum;
1534  bool isNull;
1535 
1536  relkind = resultRelInfo->ri_RelationDesc->rd_rel->relkind;
1537  if (relkind == RELKIND_RELATION || relkind == RELKIND_MATVIEW)
1538  {
1539  datum = ExecGetJunkAttribute(slot,
1540  junkfilter->jf_junkAttNo,
1541  &isNull);
1542  /* shouldn't ever get a null result... */
1543  if (isNull)
1544  elog(ERROR, "ctid is NULL");
1545 
1546  tupleid = (ItemPointer) DatumGetPointer(datum);
1547  tuple_ctid = *tupleid; /* be sure we don't free
1548  * ctid!! */
1549  tupleid = &tuple_ctid;
1550  }
1551 
1552  /*
1553  * Use the wholerow attribute, when available, to reconstruct
1554  * the old relation tuple.
1555  *
1556  * Foreign table updates have a wholerow attribute when the
1557  * relation has an AFTER ROW trigger. Note that the wholerow
1558  * attribute does not carry system columns. Foreign table
1559  * triggers miss seeing those, except that we know enough here
1560  * to set t_tableOid. Quite separately from this, the FDW may
1561  * fetch its own junk attrs to identify the row.
1562  *
1563  * Other relevant relkinds, currently limited to views, always
1564  * have a wholerow attribute.
1565  */
1566  else if (AttributeNumberIsValid(junkfilter->jf_junkAttNo))
1567  {
1568  datum = ExecGetJunkAttribute(slot,
1569  junkfilter->jf_junkAttNo,
1570  &isNull);
1571  /* shouldn't ever get a null result... */
1572  if (isNull)
1573  elog(ERROR, "wholerow is NULL");
1574 
1575  oldtupdata.t_data = DatumGetHeapTupleHeader(datum);
1576  oldtupdata.t_len =
1578  ItemPointerSetInvalid(&(oldtupdata.t_self));
1579  /* Historically, view triggers see invalid t_tableOid. */
1580  oldtupdata.t_tableOid =
1581  (relkind == RELKIND_VIEW) ? InvalidOid :
1582  RelationGetRelid(resultRelInfo->ri_RelationDesc);
1583 
1584  oldtuple = &oldtupdata;
1585  }
1586  else
1587  Assert(relkind == RELKIND_FOREIGN_TABLE);
1588  }
1589 
1590  /*
1591  * apply the junkfilter if needed.
1592  */
1593  if (operation != CMD_DELETE)
1594  slot = ExecFilterJunk(junkfilter, slot);
1595  }
1596 
1597  switch (operation)
1598  {
1599  case CMD_INSERT:
1600  slot = ExecInsert(node, slot, planSlot,
1601  node->mt_arbiterindexes, node->mt_onconflict,
1602  estate, node->canSetTag);
1603  break;
1604  case CMD_UPDATE:
1605  slot = ExecUpdate(tupleid, oldtuple, slot, planSlot,
1606  &node->mt_epqstate, estate, node->canSetTag);
1607  break;
1608  case CMD_DELETE:
1609  slot = ExecDelete(tupleid, oldtuple, planSlot,
1610  &node->mt_epqstate, estate, node->canSetTag);
1611  break;
1612  default:
1613  elog(ERROR, "unknown operation");
1614  break;
1615  }
1616 
1617  /*
1618  * If we got a RETURNING result, return it to caller. We'll continue
1619  * the work on next call.
1620  */
1621  if (slot)
1622  {
1623  estate->es_result_relation_info = saved_resultRelInfo;
1624  return slot;
1625  }
1626  }
1627 
1628  /* Restore es_result_relation_info before exiting */
1629  estate->es_result_relation_info = saved_resultRelInfo;
1630 
1631  /*
1632  * We're done, but fire AFTER STATEMENT triggers before exiting.
1633  */
1634  fireASTriggers(node);
1635 
1636  node->mt_done = true;
1637 
1638  return NULL;
1639 }
AttrNumber jf_junkAttNo
Definition: execnodes.h:336
JunkFilter * ri_junkFilter
Definition: execnodes.h:388
HeapTuple * es_epqTuple
Definition: execnodes.h:483
Relation ri_RelationDesc
Definition: execnodes.h:374
TupleTableSlot * ExecProcNode(PlanState *node)
Definition: execProcnode.c:398
#define ResetPerTupleExprContext(estate)
Definition: executor.h:465
static TupleTableSlot * ExecUpdate(ItemPointer tupleid, HeapTuple oldtuple, TupleTableSlot *slot, TupleTableSlot *planSlot, EPQState *epqstate, EState *estate, bool canSetTag)
ResultRelInfo * resultRelInfo
Definition: execnodes.h:926
static void fireBSTriggers(ModifyTableState *node)
#define RELKIND_MATVIEW
Definition: pg_class.h:165
CmdType operation
Definition: execnodes.h:920
void EvalPlanQualSetPlan(EPQState *epqstate, Plan *subplan, List *auxrowmarks)
Definition: execMain.c:2770
EState * state
Definition: execnodes.h:815
Form_pg_class rd_rel
Definition: rel.h:114
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:259
ItemPointerData * ItemPointer
Definition: itemptr.h:48
HeapTupleHeader t_data
Definition: htup.h:67
static TupleTableSlot * ExecDelete(ItemPointer tupleid, HeapTuple oldtuple, TupleTableSlot *planSlot, EPQState *epqstate, EState *estate, bool canSetTag)
OnConflictAction mt_onconflict
Definition: execnodes.h:932
#define ERROR
Definition: elog.h:43
PlanState ps
Definition: execnodes.h:919
ItemPointerData t_self
Definition: htup.h:65
bool ri_usesFdwDirectModify
Definition: execnodes.h:384
uint32 t_len
Definition: htup.h:64
EPQState mt_epqstate
Definition: execnodes.h:930
ProjectionInfo * ri_projectReturning
Definition: execnodes.h:389
#define TupIsNull(slot)
Definition: tuptable.h:138
Oid t_tableOid
Definition: htup.h:66
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
static TupleTableSlot * ExecProcessReturning(ResultRelInfo *resultRelInfo, TupleTableSlot *tupleSlot, TupleTableSlot *planSlot)
PlanState ** mt_plans
Definition: execnodes.h:923
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
static void fireASTriggers(ModifyTableState *node)
uintptr_t Datum
Definition: postgres.h:372
TupleTableSlot * ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
Definition: execJunk.c:262
Plan * plan
Definition: execnodes.h:813
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
static TupleTableSlot * ExecInsert(ModifyTableState *mtstate, TupleTableSlot *slot, TupleTableSlot *planSlot, List *arbiterIndexes, OnConflictAction onconflict, EState *estate, bool canSetTag)
#define DatumGetPointer(X)
Definition: postgres.h:555
List * mt_arbiterindexes
Definition: execnodes.h:933
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:149
Datum ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno, bool *isNull)
Definition: execJunk.c:248
#define RELKIND_VIEW
Definition: pg_class.h:164
#define elog
Definition: elog.h:219
#define RELKIND_RELATION
Definition: pg_class.h:160
#define RelationGetRelid(relation)
Definition: rel.h:417
CmdType
Definition: nodes.h:648
List ** mt_arowmarks
Definition: execnodes.h:929
#define EvalPlanQualSetSlot(epqstate, slot)
Definition: executor.h:220
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:439
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:423
void ExecReScanModifyTable ( ModifyTableState node)

Definition at line 2222 of file nodeModifyTable.c.

References elog, and ERROR.

Referenced by ExecReScan().

2223 {
2224  /*
2225  * Currently, we don't need to support rescan on ModifyTable nodes. The
2226  * semantics of that would be a bit debatable anyway.
2227  */
2228  elog(ERROR, "ExecReScanModifyTable is not implemented");
2229 }
#define ERROR
Definition: elog.h:43
#define elog
Definition: elog.h:219