diff options
Diffstat (limited to 'src/backend/executor/execPartition.c')
-rw-r--r-- | src/backend/executor/execPartition.c | 123 |
1 files changed, 46 insertions, 77 deletions
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index 8afddca73a0..8e2feafd28c 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -181,7 +181,7 @@ static char *ExecBuildSlotPartitionKeyDescription(Relation rel, Datum *values, bool *isnull, int maxfieldlen); -static List *adjust_partition_tlist(List *tlist, TupleConversionMap *map); +static List *adjust_partition_colnos(List *colnos, ResultRelInfo *leaf_part_rri); static void ExecInitPruningContext(PartitionPruneContext *context, List *pruning_steps, PartitionDesc partdesc, @@ -714,6 +714,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, */ if (node->onConflictAction == ONCONFLICT_UPDATE) { + OnConflictSetState *onconfl = makeNode(OnConflictSetState); TupleConversionMap *map; map = leaf_part_rri->ri_RootToPartitionMap; @@ -721,14 +722,14 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, Assert(node->onConflictSet != NIL); Assert(rootResultRelInfo->ri_onConflict != NULL); - leaf_part_rri->ri_onConflict = makeNode(OnConflictSetState); + leaf_part_rri->ri_onConflict = onconfl; /* * Need a separate existing slot for each partition, as the * partition could be of a different AM, even if the tuple * descriptors match. */ - leaf_part_rri->ri_onConflict->oc_Existing = + onconfl->oc_Existing = table_slot_create(leaf_part_rri->ri_RelationDesc, &mtstate->ps.state->es_tupleTable); @@ -748,17 +749,17 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, * Projections and where clauses themselves don't store state * / are independent of the underlying storage. */ - leaf_part_rri->ri_onConflict->oc_ProjSlot = + onconfl->oc_ProjSlot = rootResultRelInfo->ri_onConflict->oc_ProjSlot; - leaf_part_rri->ri_onConflict->oc_ProjInfo = + onconfl->oc_ProjInfo = rootResultRelInfo->ri_onConflict->oc_ProjInfo; - leaf_part_rri->ri_onConflict->oc_WhereClause = + onconfl->oc_WhereClause = rootResultRelInfo->ri_onConflict->oc_WhereClause; } else { List *onconflset; - TupleDesc tupDesc; + List *onconflcols; bool found_whole_row; /* @@ -768,7 +769,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, * pseudo-relation (INNER_VAR), and second to handle the main * target relation (firstVarno). */ - onconflset = (List *) copyObject((Node *) node->onConflictSet); + onconflset = copyObject(node->onConflictSet); if (part_attmap == NULL) part_attmap = build_attrmap_by_name(RelationGetDescr(partrel), @@ -788,20 +789,24 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, &found_whole_row); /* We ignore the value of found_whole_row. */ - /* Finally, adjust this tlist to match the partition. */ - onconflset = adjust_partition_tlist(onconflset, map); + /* Finally, adjust the target colnos to match the partition. */ + onconflcols = adjust_partition_colnos(node->onConflictCols, + leaf_part_rri); /* create the tuple slot for the UPDATE SET projection */ - tupDesc = ExecTypeFromTL(onconflset); - leaf_part_rri->ri_onConflict->oc_ProjSlot = - ExecInitExtraTupleSlot(mtstate->ps.state, tupDesc, - &TTSOpsVirtual); + onconfl->oc_ProjSlot = + table_slot_create(partrel, + &mtstate->ps.state->es_tupleTable); /* build UPDATE SET projection state */ - leaf_part_rri->ri_onConflict->oc_ProjInfo = - ExecBuildProjectionInfo(onconflset, econtext, - leaf_part_rri->ri_onConflict->oc_ProjSlot, - &mtstate->ps, partrelDesc); + onconfl->oc_ProjInfo = + ExecBuildUpdateProjection(onconflset, + true, + onconflcols, + partrelDesc, + econtext, + onconfl->oc_ProjSlot, + &mtstate->ps); /* * If there is a WHERE clause, initialize state where it will @@ -828,7 +833,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, EState *estate, RelationGetForm(partrel)->reltype, &found_whole_row); /* We ignore the value of found_whole_row. */ - leaf_part_rri->ri_onConflict->oc_WhereClause = + onconfl->oc_WhereClause = ExecInitQual((List *) clause, &mtstate->ps); } } @@ -1421,71 +1426,35 @@ ExecBuildSlotPartitionKeyDescription(Relation rel, } /* - * adjust_partition_tlist - * Adjust the targetlist entries for a given partition to account for - * attribute differences between parent and the partition - * - * The expressions have already been fixed, but here we fix the list to make - * target resnos match the partition's attribute numbers. This results in a - * copy of the original target list in which the entries appear in resno - * order, including both the existing entries (that may have their resno - * changed in-place) and the newly added entries for columns that don't exist - * in the parent. - * - * Scribbles on the input tlist, so callers must make sure to make a copy - * before passing it to us. + * adjust_partition_colnos + * Adjust the list of UPDATE target column numbers to account for + * attribute differences between the parent and the partition. */ static List * -adjust_partition_tlist(List *tlist, TupleConversionMap *map) +adjust_partition_colnos(List *colnos, ResultRelInfo *leaf_part_rri) { - List *new_tlist = NIL; - TupleDesc tupdesc = map->outdesc; - AttrMap *attrMap = map->attrMap; - AttrNumber attrno; - - Assert(tupdesc->natts == attrMap->maplen); - for (attrno = 1; attrno <= tupdesc->natts; attrno++) - { - Form_pg_attribute att_tup = TupleDescAttr(tupdesc, attrno - 1); - TargetEntry *tle; - - if (attrMap->attnums[attrno - 1] != InvalidAttrNumber) - { - Assert(!att_tup->attisdropped); - - /* - * Use the corresponding entry from the parent's tlist, adjusting - * the resno the match the partition's attno. - */ - tle = (TargetEntry *) list_nth(tlist, attrMap->attnums[attrno - 1] - 1); - tle->resno = attrno; - } - else - { - Const *expr; + List *new_colnos = NIL; + TupleConversionMap *map = ExecGetChildToRootMap(leaf_part_rri); + AttrMap *attrMap; + ListCell *lc; - /* - * For a dropped attribute in the partition, generate a dummy - * entry with resno matching the partition's attno. - */ - Assert(att_tup->attisdropped); - expr = makeConst(INT4OID, - -1, - InvalidOid, - sizeof(int32), - (Datum) 0, - true, /* isnull */ - true /* byval */ ); - tle = makeTargetEntry((Expr *) expr, - attrno, - pstrdup(NameStr(att_tup->attname)), - false); - } + Assert(map != NULL); /* else we shouldn't be here */ + attrMap = map->attrMap; - new_tlist = lappend(new_tlist, tle); + foreach(lc, colnos) + { + AttrNumber parentattrno = lfirst_int(lc); + + if (parentattrno <= 0 || + parentattrno > attrMap->maplen || + attrMap->attnums[parentattrno - 1] == 0) + elog(ERROR, "unexpected attno %d in target column list", + parentattrno); + new_colnos = lappend_int(new_colnos, + attrMap->attnums[parentattrno - 1]); } - return new_tlist; + return new_colnos; } /*------------------------------------------------------------------------- |