aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execMain.c97
-rw-r--r--src/backend/executor/execPartition.c36
-rw-r--r--src/backend/executor/execUtils.c64
-rw-r--r--src/backend/executor/nodeModifyTable.c7
4 files changed, 134 insertions, 70 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 8daf0fe9330..f852ac4faa9 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -102,17 +102,6 @@ static char *ExecBuildSlotValueDescription(Oid reloid,
static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate,
Plan *planTree);
-/*
- * Note that GetUpdatedColumns() also exists in commands/trigger.c. There does
- * not appear to be any good header to put it into, given the structures that
- * it uses, so we let them be duplicated. Be sure to update both if one needs
- * to be changed, however.
- */
-#define GetInsertedColumns(relinfo, estate) \
- (rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->insertedCols)
-#define GetUpdatedColumns(relinfo, estate) \
- (rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->updatedCols)
-
/* end of local decls */
@@ -1302,7 +1291,7 @@ void
InitResultRelInfo(ResultRelInfo *resultRelInfo,
Relation resultRelationDesc,
Index resultRelationIndex,
- Relation partition_root,
+ ResultRelInfo *partition_root_rri,
int instrument_options)
{
List *partition_check = NIL;
@@ -1363,7 +1352,7 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
partition_check = RelationGetPartitionQual(resultRelationDesc);
resultRelInfo->ri_PartitionCheck = partition_check;
- resultRelInfo->ri_PartitionRoot = partition_root;
+ resultRelInfo->ri_RootResultRelInfo = partition_root_rri;
resultRelInfo->ri_PartitionReadyForRouting = false;
}
@@ -1906,26 +1895,28 @@ ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo,
TupleTableSlot *slot,
EState *estate)
{
+ Oid root_relid;
Relation rel = resultRelInfo->ri_RelationDesc;
Relation orig_rel = rel;
TupleDesc tupdesc = RelationGetDescr(rel);
char *val_desc;
Bitmapset *modifiedCols;
- Bitmapset *insertedCols;
- Bitmapset *updatedCols;
/*
* Need to first convert the tuple to the root partitioned table's row
* type. For details, check similar comments in ExecConstraints().
*/
- if (resultRelInfo->ri_PartitionRoot)
+ if (resultRelInfo->ri_RootResultRelInfo)
{
HeapTuple tuple = ExecFetchSlotTuple(slot);
- TupleDesc old_tupdesc = RelationGetDescr(rel);
+ ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
+ TupleDesc old_tupdesc;
TupleConversionMap *map;
- rel = resultRelInfo->ri_PartitionRoot;
- tupdesc = RelationGetDescr(rel);
+ root_relid = RelationGetRelid(rootrel->ri_RelationDesc);
+ tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
+
+ old_tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
/* a reverse map */
map = convert_tuples_by_name(old_tupdesc, tupdesc,
gettext_noop("could not convert row type"));
@@ -1936,12 +1927,18 @@ ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo,
slot = MakeTupleTableSlot(tupdesc);
ExecStoreTuple(tuple, slot, InvalidBuffer, false);
}
+ modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
+ ExecGetUpdatedCols(rootrel, estate));
+ }
+ else
+ {
+ root_relid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
+ tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc);
+ modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
+ ExecGetUpdatedCols(resultRelInfo, estate));
}
- insertedCols = GetInsertedColumns(resultRelInfo, estate);
- updatedCols = GetUpdatedColumns(resultRelInfo, estate);
- modifiedCols = bms_union(insertedCols, updatedCols);
- val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
+ val_desc = ExecBuildSlotValueDescription(root_relid,
slot,
tupdesc,
modifiedCols,
@@ -1972,8 +1969,6 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
TupleDesc tupdesc = RelationGetDescr(rel);
TupleConstr *constr = tupdesc->constr;
Bitmapset *modifiedCols;
- Bitmapset *insertedCols;
- Bitmapset *updatedCols;
Assert(constr || resultRelInfo->ri_PartitionCheck);
@@ -1999,13 +1994,13 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
* rowtype so that val_desc shown error message matches the
* input tuple.
*/
- if (resultRelInfo->ri_PartitionRoot)
+ if (resultRelInfo->ri_RootResultRelInfo)
{
HeapTuple tuple = ExecFetchSlotTuple(slot);
+ ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
TupleConversionMap *map;
- rel = resultRelInfo->ri_PartitionRoot;
- tupdesc = RelationGetDescr(rel);
+ tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
/* a reverse map */
map = convert_tuples_by_name(orig_tupdesc, tupdesc,
gettext_noop("could not convert row type"));
@@ -2016,11 +2011,13 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
slot = MakeTupleTableSlot(tupdesc);
ExecStoreTuple(tuple, slot, InvalidBuffer, false);
}
+ modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
+ ExecGetUpdatedCols(rootrel, estate));
+ rel = rootrel->ri_RelationDesc;
}
-
- insertedCols = GetInsertedColumns(resultRelInfo, estate);
- updatedCols = GetUpdatedColumns(resultRelInfo, estate);
- modifiedCols = bms_union(insertedCols, updatedCols);
+ else
+ modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
+ ExecGetUpdatedCols(resultRelInfo, estate));
val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
slot,
tupdesc,
@@ -2047,14 +2044,14 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
Relation orig_rel = rel;
/* See the comment above. */
- if (resultRelInfo->ri_PartitionRoot)
+ if (resultRelInfo->ri_RootResultRelInfo)
{
HeapTuple tuple = ExecFetchSlotTuple(slot);
+ ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
TupleDesc old_tupdesc = RelationGetDescr(rel);
TupleConversionMap *map;
- rel = resultRelInfo->ri_PartitionRoot;
- tupdesc = RelationGetDescr(rel);
+ tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
/* a reverse map */
map = convert_tuples_by_name(old_tupdesc, tupdesc,
gettext_noop("could not convert row type"));
@@ -2065,11 +2062,13 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
slot = MakeTupleTableSlot(tupdesc);
ExecStoreTuple(tuple, slot, InvalidBuffer, false);
}
+ modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
+ ExecGetUpdatedCols(rootrel, estate));
+ rel = rootrel->ri_RelationDesc;
}
-
- insertedCols = GetInsertedColumns(resultRelInfo, estate);
- updatedCols = GetUpdatedColumns(resultRelInfo, estate);
- modifiedCols = bms_union(insertedCols, updatedCols);
+ else
+ modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
+ ExecGetUpdatedCols(resultRelInfo, estate));
val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
slot,
tupdesc,
@@ -2138,8 +2137,6 @@ ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo,
{
char *val_desc;
Bitmapset *modifiedCols;
- Bitmapset *insertedCols;
- Bitmapset *updatedCols;
switch (wco->kind)
{
@@ -2154,14 +2151,14 @@ ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo,
*/
case WCO_VIEW_CHECK:
/* See the comment in ExecConstraints(). */
- if (resultRelInfo->ri_PartitionRoot)
+ if (resultRelInfo->ri_RootResultRelInfo)
{
HeapTuple tuple = ExecFetchSlotTuple(slot);
+ ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo;
TupleDesc old_tupdesc = RelationGetDescr(rel);
TupleConversionMap *map;
- rel = resultRelInfo->ri_PartitionRoot;
- tupdesc = RelationGetDescr(rel);
+ tupdesc = RelationGetDescr(rootrel->ri_RelationDesc);
/* a reverse map */
map = convert_tuples_by_name(old_tupdesc, tupdesc,
gettext_noop("could not convert row type"));
@@ -2172,11 +2169,13 @@ ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo,
slot = MakeTupleTableSlot(tupdesc);
ExecStoreTuple(tuple, slot, InvalidBuffer, false);
}
+ modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate),
+ ExecGetUpdatedCols(rootrel, estate));
+ rel = rootrel->ri_RelationDesc;
}
-
- insertedCols = GetInsertedColumns(resultRelInfo, estate);
- updatedCols = GetUpdatedColumns(resultRelInfo, estate);
- modifiedCols = bms_union(insertedCols, updatedCols);
+ else
+ modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate),
+ ExecGetUpdatedCols(resultRelInfo, estate));
val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
slot,
tupdesc,
@@ -2390,7 +2389,7 @@ ExecUpdateLockMode(EState *estate, ResultRelInfo *relinfo)
* been modified, then we can use a weaker lock, allowing for better
* concurrency.
*/
- updatedCols = GetUpdatedColumns(relinfo, estate);
+ updatedCols = ExecGetUpdatedCols(relinfo, estate);
keyCols = RelationGetIndexAttrBitmap(relinfo->ri_RelationDesc,
INDEX_ATTR_BITMAP_KEY);
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index dc58fd0a82c..40b5d3717fd 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -107,7 +107,7 @@ static void find_matching_subplans_recurse(PartitionPruningData *prunedata,
* the partitions to route tuples to. See ExecPrepareTupleRouting.
*/
PartitionTupleRouting *
-ExecSetupPartitionTupleRouting(ModifyTableState *mtstate, Relation rel)
+ExecSetupPartitionTupleRouting(ModifyTableState *mtstate, ResultRelInfo *rootResultRelInfo)
{
List *leaf_parts;
ListCell *cell;
@@ -123,10 +123,12 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate, Relation rel)
* Get the information about the partition tree after locking all the
* partitions.
*/
- (void) find_all_inheritors(RelationGetRelid(rel), RowExclusiveLock, NULL);
+ (void) find_all_inheritors(RelationGetRelid(rootResultRelInfo->ri_RelationDesc),
+ RowExclusiveLock, NULL);
proute = (PartitionTupleRouting *) palloc0(sizeof(PartitionTupleRouting));
proute->partition_dispatch_info =
- RelationGetPartitionDispatchInfo(rel, &proute->num_dispatch,
+ RelationGetPartitionDispatchInfo(rootResultRelInfo->ri_RelationDesc,
+ &proute->num_dispatch,
&leaf_parts);
proute->num_partitions = nparts = list_length(leaf_parts);
proute->partitions =
@@ -186,7 +188,7 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate, Relation rel)
* descriptor. When generating the per-subplan result rels, this
* was not set.
*/
- leaf_part_rri->ri_PartitionRoot = rel;
+ leaf_part_rri->ri_RootResultRelInfo = rootResultRelInfo;
/* Remember the subplan offset for this ResultRelInfo */
proute->subplan_partition_offsets[update_rri_index] = i;
@@ -366,13 +368,13 @@ ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
*/
ResultRelInfo *
ExecInitPartitionInfo(ModifyTableState *mtstate,
- ResultRelInfo *resultRelInfo,
+ ResultRelInfo *rootResultRelInfo,
PartitionTupleRouting *proute,
EState *estate, int partidx)
{
ModifyTable *node = (ModifyTable *) mtstate->ps.plan;
- Relation rootrel = resultRelInfo->ri_RelationDesc,
- partrel;
+ Relation partrel;
+ int firstVarno = mtstate->resultRelInfo[0].ri_RangeTableIndex;
Relation firstResultRel = mtstate->resultRelInfo[0].ri_RelationDesc;
ResultRelInfo *leaf_part_rri;
MemoryContext oldContext;
@@ -394,8 +396,8 @@ ExecInitPartitionInfo(ModifyTableState *mtstate,
leaf_part_rri = makeNode(ResultRelInfo);
InitResultRelInfo(leaf_part_rri,
partrel,
- node ? node->nominalRelation : 1,
- rootrel,
+ 0,
+ rootResultRelInfo,
estate->es_instrument);
/*
@@ -441,7 +443,6 @@ ExecInitPartitionInfo(ModifyTableState *mtstate,
List *wcoList;
List *wcoExprs = NIL;
ListCell *ll;
- int firstVarno = mtstate->resultRelInfo[0].ri_RangeTableIndex;
/*
* In the case of INSERT on a partitioned table, there is only one
@@ -507,7 +508,6 @@ ExecInitPartitionInfo(ModifyTableState *mtstate,
TupleTableSlot *slot;
ExprContext *econtext;
List *returningList;
- int firstVarno = mtstate->resultRelInfo[0].ri_RangeTableIndex;
/* See the comment above for WCO lists. */
Assert((node->operation == CMD_INSERT &&
@@ -568,7 +568,6 @@ ExecInitPartitionInfo(ModifyTableState *mtstate,
if (node && node->onConflictAction != ONCONFLICT_NONE)
{
TupleConversionMap *map = proute->parent_child_tupconv_maps[partidx];
- int firstVarno = mtstate->resultRelInfo[0].ri_RangeTableIndex;
TupleDesc partrelDesc = RelationGetDescr(partrel);
ExprContext *econtext = mtstate->ps.ps_ExprContext;
ListCell *lc;
@@ -580,7 +579,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate,
* list and searching for ancestry relationships to each index in the
* ancestor table.
*/
- if (list_length(resultRelInfo->ri_onConflictArbiterIndexes) > 0)
+ if (list_length(rootResultRelInfo->ri_onConflictArbiterIndexes) > 0)
{
List *childIdxs;
@@ -593,7 +592,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate,
ListCell *lc2;
ancestors = get_partition_ancestors(childIdx);
- foreach(lc2, resultRelInfo->ri_onConflictArbiterIndexes)
+ foreach(lc2, rootResultRelInfo->ri_onConflictArbiterIndexes)
{
if (list_member_oid(ancestors, lfirst_oid(lc2)))
arbiterIndexes = lappend_oid(arbiterIndexes, childIdx);
@@ -607,7 +606,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate,
* (This shouldn't happen, since arbiter index selection should not
* pick up an invalid index.)
*/
- if (list_length(resultRelInfo->ri_onConflictArbiterIndexes) !=
+ if (list_length(rootResultRelInfo->ri_onConflictArbiterIndexes) !=
list_length(arbiterIndexes))
elog(ERROR, "invalid arbiter index list");
leaf_part_rri->ri_onConflictArbiterIndexes = arbiterIndexes;
@@ -618,7 +617,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate,
if (node->onConflictAction == ONCONFLICT_UPDATE)
{
Assert(node->onConflictSet != NIL);
- Assert(resultRelInfo->ri_onConflict != NULL);
+ Assert(rootResultRelInfo->ri_onConflict != NULL);
/*
* If the partition's tuple descriptor matches exactly the root
@@ -627,7 +626,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate,
* need to create state specific to this partition.
*/
if (map == NULL)
- leaf_part_rri->ri_onConflict = resultRelInfo->ri_onConflict;
+ leaf_part_rri->ri_onConflict = rootResultRelInfo->ri_onConflict;
else
{
List *onconflset;
@@ -737,6 +736,7 @@ ExecInitRoutingInfo(ModifyTableState *mtstate,
ResultRelInfo *partRelInfo,
int partidx)
{
+ ResultRelInfo *rootRelInfo = partRelInfo->ri_RootResultRelInfo;
MemoryContext oldContext;
/*
@@ -749,7 +749,7 @@ ExecInitRoutingInfo(ModifyTableState *mtstate,
* partition from the parent's type to the partition's.
*/
proute->parent_child_tupconv_maps[partidx] =
- convert_tuples_by_name(RelationGetDescr(partRelInfo->ri_PartitionRoot),
+ convert_tuples_by_name(RelationGetDescr(rootRelInfo->ri_RelationDesc),
RelationGetDescr(partRelInfo->ri_RelationDesc),
gettext_noop("could not convert row type"));
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 5b3eaec80bc..e91a6ebddd5 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -45,6 +45,7 @@
#include "access/relscan.h"
#include "access/transam.h"
#include "executor/executor.h"
+#include "executor/execPartition.h"
#include "jit/jit.h"
#include "mb/pg_wchar.h"
#include "nodes/nodeFuncs.h"
@@ -1068,3 +1069,66 @@ ExecCleanTargetListLength(List *targetlist)
}
return len;
}
+
+/* Return a bitmap representing columns being inserted */
+Bitmapset *
+ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate)
+{
+ /*
+ * The columns are stored in the range table entry. If this ResultRelInfo
+ * doesn't have an entry in the range table (i.e. if it represents a
+ * partition routing target), fetch the parent's RTE and map the columns
+ * to the order they are in the partition.
+ */
+ if (relinfo->ri_RangeTableIndex != 0)
+ {
+ RangeTblEntry *rte = rt_fetch(relinfo->ri_RangeTableIndex,
+ estate->es_range_table);
+
+ return rte->insertedCols;
+ }
+ else
+ {
+ ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo;
+ RangeTblEntry *rte = rt_fetch(rootRelInfo->ri_RangeTableIndex,
+ estate->es_range_table);
+ TupleConversionMap *map;
+
+ map = convert_tuples_by_name(RelationGetDescr(rootRelInfo->ri_RelationDesc),
+ RelationGetDescr(relinfo->ri_RelationDesc),
+ gettext_noop("could not convert row type"));
+ if (map != NULL)
+ return execute_attr_map_cols(rte->insertedCols, map);
+ else
+ return rte->insertedCols;
+ }
+}
+
+/* Return a bitmap representing columns being updated */
+Bitmapset *
+ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)
+{
+ /* see ExecGetInsertedCols() */
+ if (relinfo->ri_RangeTableIndex != 0)
+ {
+ RangeTblEntry *rte = rt_fetch(relinfo->ri_RangeTableIndex,
+ estate->es_range_table);
+
+ return rte->updatedCols;
+ }
+ else
+ {
+ ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo;
+ RangeTblEntry *rte = rt_fetch(rootRelInfo->ri_RangeTableIndex,
+ estate->es_range_table);
+ TupleConversionMap *map;
+
+ map = convert_tuples_by_name(RelationGetDescr(rootRelInfo->ri_RelationDesc),
+ RelationGetDescr(relinfo->ri_RelationDesc),
+ gettext_noop("could not convert row type"));
+ if (map != NULL)
+ return execute_attr_map_cols(rte->updatedCols, map);
+ else
+ return rte->updatedCols;
+ }
+}
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index c84171973c9..a0fd6c15d29 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -403,7 +403,7 @@ ExecInsert(ModifyTableState *mtstate,
* if there's no BR trigger defined on the partition.
*/
if (resultRelInfo->ri_PartitionCheck &&
- (resultRelInfo->ri_PartitionRoot == NULL ||
+ (resultRelInfo->ri_RootResultRelInfo == NULL ||
(resultRelInfo->ri_TrigDesc &&
resultRelInfo->ri_TrigDesc->trig_insert_before_row)))
ExecPartitionCheck(resultRelInfo, slot, estate, true);
@@ -2324,7 +2324,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
estate->es_result_relation_info = saved_resultRelInfo;
/* Get the target relation */
- rel = (getTargetResultRelInfo(mtstate))->ri_RelationDesc;
+ resultRelInfo = getTargetResultRelInfo(mtstate);
+ rel = resultRelInfo->ri_RelationDesc;
/*
* If it's not a partitioned table after all, UPDATE tuple routing should
@@ -2340,7 +2341,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
(operation == CMD_INSERT || update_tuple_routing_needed))
mtstate->mt_partition_tuple_routing =
- ExecSetupPartitionTupleRouting(mtstate, rel);
+ ExecSetupPartitionTupleRouting(mtstate, resultRelInfo);
/*
* Build state for collecting transition tuples. This requires having a