diff --git a/src/backend/distributed/planner/insert_select_planner.c b/src/backend/distributed/planner/insert_select_planner.c index 2df116a6f..56ad2d8de 100644 --- a/src/backend/distributed/planner/insert_select_planner.c +++ b/src/backend/distributed/planner/insert_select_planner.c @@ -1627,6 +1627,68 @@ RelabelTargetEntryList(List *selectTargetList, List *insertTargetList) } +/* + * AddInsertSelectCasts ensures that the columns in the given target lists + * have the same type as the corresponding columns of the target relation. + * It adds casts when necessary. + * + * Returns the updated selectTargetList. + */ +static List * +AddInsertSelectCasts(List *insertTargetList, List *selectTargetList, + Oid targetRelationId) +{ + List *projectedEntries = NIL; + List *nonProjectedEntries = NIL; + + /* + * ReorderInsertSelectTargetLists() ensures that the first few columns of the + * SELECT query match the insert targets. It might also include additional + * items (for GROUP BY, etc.), so the insertTargetList is shorter. + */ + Assert(list_length(insertTargetList) <= list_length(selectTargetList)); + + Relation distributedRelation = table_open(targetRelationId, RowExclusiveLock); + TupleDesc destTupleDescriptor = RelationGetDescr(distributedRelation); + + int targetEntryIndex = 0; + TargetEntry *insertEntry = NULL; + TargetEntry *selectEntry = NULL; + + forboth_ptr(insertEntry, insertTargetList, selectEntry, selectTargetList) + { + /* + * Retrieve the target attribute corresponding to the insert entry. + * The attribute is located at (resno - 1) in the tuple descriptor. + */ + Form_pg_attribute attr = TupleDescAttr(destTupleDescriptor, + insertEntry->resno - 1); + + process_entry_pair(insertEntry, selectEntry, attr, targetEntryIndex, + &projectedEntries, &nonProjectedEntries); + + targetEntryIndex++; + } + + /* Append any additional non-projected entries from selectTargetList */ + for (int entryIndex = list_length(insertTargetList); + entryIndex < list_length(selectTargetList); + entryIndex++) + { + nonProjectedEntries = lappend(nonProjectedEntries, list_nth(selectTargetList, + entryIndex)); + } + + /* Concatenate projected and non-projected entries and reset resno numbering */ + selectTargetList = list_concat(projectedEntries, nonProjectedEntries); + reset_target_entry_resno(selectTargetList); + + table_close(distributedRelation, NoLock); + + return selectTargetList; +} + + /* * Processes a single pair of insert and select target entries. * It compares the source and target types and appends either the @@ -1703,68 +1765,6 @@ reset_target_entry_resno(List *targetList) } -/* - * AddInsertSelectCasts ensures that the columns in the given target lists - * have the same type as the corresponding columns of the target relation. - * It adds casts when necessary. - * - * Returns the updated selectTargetList. - */ -static List * -AddInsertSelectCasts(List *insertTargetList, List *selectTargetList, - Oid targetRelationId) -{ - List *projectedEntries = NIL; - List *nonProjectedEntries = NIL; - - /* - * ReorderInsertSelectTargetLists() ensures that the first few columns of the - * SELECT query match the insert targets. It might also include additional - * items (for GROUP BY, etc.), so the insertTargetList is shorter. - */ - Assert(list_length(insertTargetList) <= list_length(selectTargetList)); - - Relation distributedRelation = table_open(targetRelationId, RowExclusiveLock); - TupleDesc destTupleDescriptor = RelationGetDescr(distributedRelation); - - int targetEntryIndex = 0; - TargetEntry *insertEntry = NULL; - TargetEntry *selectEntry = NULL; - - forboth_ptr(insertEntry, insertTargetList, selectEntry, selectTargetList) - { - /* - * Retrieve the target attribute corresponding to the insert entry. - * The attribute is located at (resno - 1) in the tuple descriptor. - */ - Form_pg_attribute attr = TupleDescAttr(destTupleDescriptor, - insertEntry->resno - 1); - - process_entry_pair(insertEntry, selectEntry, attr, targetEntryIndex, - &projectedEntries, &nonProjectedEntries); - - targetEntryIndex++; - } - - /* Append any additional non-projected entries from selectTargetList */ - for (int entryIndex = list_length(insertTargetList); - entryIndex < list_length(selectTargetList); - entryIndex++) - { - nonProjectedEntries = lappend(nonProjectedEntries, list_nth(selectTargetList, - entryIndex)); - } - - /* Concatenate projected and non-projected entries and reset resno numbering */ - selectTargetList = list_concat(projectedEntries, nonProjectedEntries); - reset_target_entry_resno(selectTargetList); - - table_close(distributedRelation, NoLock); - - return selectTargetList; -} - - /* * Looks up the nextval(regclass) function in pg_proc, returning its actual * rettype. In a standard build, that will be INT8OID, but this is more robust. @@ -1795,16 +1795,6 @@ GetNextvalReturnTypeCatalog(void) } -/* Helper function to set the target entry name using a formatted string */ -static void -set_target_entry_name(TargetEntry *tle, const char *format, int index) -{ - StringInfo resnameString = makeStringInfo(); - appendStringInfo(resnameString, format, index); - tle->resname = resnameString->data; -} - - /** * Modifies the given insert entry to match the target column's type and typmod, * then creates and appends a new target entry containing a casted expression @@ -1932,6 +1922,16 @@ CastExpr(Expr *expr, Oid sourceType, Oid targetType, Oid targetCollation, } +/* Helper function to set the target entry name using a formatted string */ +static void +set_target_entry_name(TargetEntry *tle, const char *format, int index) +{ + StringInfo resnameString = makeStringInfo(); + appendStringInfo(resnameString, format, index); + tle->resname = resnameString->data; +} + + /* PlanningInsertSelect returns true if we are planning an INSERT ...SELECT query */ bool PlanningInsertSelect(void)