diff options
Diffstat (limited to 'src/backend/commands/tablecmds.c')
-rw-r--r-- | src/backend/commands/tablecmds.c | 141 |
1 files changed, 73 insertions, 68 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 5c278463c6d..b6f6bca26b8 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -425,6 +425,8 @@ static void ATPrepAlterColumnType(List **wqueue, static bool ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno); static ObjectAddress ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, AlterTableCmd *cmd, LOCKMODE lockmode); +static void RememberConstraintForRebuilding(Oid conoid, AlteredTableInfo *tab); +static void RememberIndexForRebuilding(Oid indoid, AlteredTableInfo *tab); static ObjectAddress ATExecAlterColumnGenericOptions(Relation rel, const char *colName, List *options, LOCKMODE lockmode); static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, @@ -9785,9 +9787,6 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, SysScanDesc scan; HeapTuple depTup; ObjectAddress address; - ListCell *lc; - ListCell *prev; - ListCell *next; /* * Clear all the missing values if we're rewriting the table, since this @@ -9872,11 +9871,6 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, * performed all the individual ALTER TYPE operations. We have to save * the info before executing ALTER TYPE, though, else the deparser will * get confused. - * - * There could be multiple entries for the same object, so we must check - * to ensure we process each one only once. Note: we assume that an index - * that implements a constraint will not show a direct dependency on the - * column. */ depRel = heap_open(DependRelationId, RowExclusiveLock); @@ -9918,20 +9912,8 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, if (relKind == RELKIND_INDEX || relKind == RELKIND_PARTITIONED_INDEX) { - /* - * Indexes that are directly dependent on the table - * might be regular indexes or constraint indexes. - * Constraint indexes typically have only indirect - * dependencies; but there are exceptions, notably - * partial exclusion constraints. Hence we must check - * whether the index depends on any constraint that's - * due to be rebuilt, which we'll do below after we've - * found all such constraints. - */ Assert(foundObject.objectSubId == 0); - tab->changedIndexOids = - list_append_unique_oid(tab->changedIndexOids, - foundObject.objectId); + RememberIndexForRebuilding(foundObject.objectId, tab); } else if (relKind == RELKIND_SEQUENCE) { @@ -9952,18 +9934,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, case OCLASS_CONSTRAINT: Assert(foundObject.objectSubId == 0); - if (!list_member_oid(tab->changedConstraintOids, - foundObject.objectId)) - { - char *defstring = pg_get_constraintdef_command(foundObject.objectId); - - tab->changedConstraintOids = - lappend_oid(tab->changedConstraintOids, - foundObject.objectId); - tab->changedConstraintDefs = - lappend(tab->changedConstraintDefs, - defstring); - } + RememberConstraintForRebuilding(foundObject.objectId, tab); break; case OCLASS_REWRITE: @@ -10083,41 +10054,6 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, systable_endscan(scan); /* - * Check the collected index OIDs to see which ones belong to the - * constraint(s) of the table, and drop those from the list of indexes - * that we need to process; rebuilding the constraints will handle them. - */ - prev = NULL; - for (lc = list_head(tab->changedIndexOids); lc; lc = next) - { - Oid indexoid = lfirst_oid(lc); - Oid conoid; - - next = lnext(lc); - - conoid = get_index_constraint(indexoid); - if (OidIsValid(conoid) && - list_member_oid(tab->changedConstraintOids, conoid)) - tab->changedIndexOids = list_delete_cell(tab->changedIndexOids, - lc, prev); - else - prev = lc; - } - - /* - * Now collect the definitions of the indexes that must be rebuilt. (We - * could merge this into the previous loop, but it'd be more complicated - * for little gain.) - */ - foreach(lc, tab->changedIndexOids) - { - Oid indexoid = lfirst_oid(lc); - - tab->changedIndexDefs = lappend(tab->changedIndexDefs, - pg_get_indexdef_string(indexoid)); - } - - /* * Now scan for dependencies of this column on other things. The only * thing we should find is the dependency on the column datatype, which we * want to remove, and possibly a collation dependency. @@ -10286,6 +10222,75 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, } /* + * Subroutine for ATExecAlterColumnType: remember that a constraint needs + * to be rebuilt (which we might already know). + */ +static void +RememberConstraintForRebuilding(Oid conoid, AlteredTableInfo *tab) +{ + /* + * This de-duplication check is critical for two independent reasons: we + * mustn't try to recreate the same constraint twice, and if a constraint + * depends on more than one column whose type is to be altered, we must + * capture its definition string before applying any of the column type + * changes. ruleutils.c will get confused if we ask again later. + */ + if (!list_member_oid(tab->changedConstraintOids, conoid)) + { + /* OK, capture the constraint's existing definition string */ + char *defstring = pg_get_constraintdef_command(conoid); + + tab->changedConstraintOids = lappend_oid(tab->changedConstraintOids, + conoid); + tab->changedConstraintDefs = lappend(tab->changedConstraintDefs, + defstring); + } +} + +/* + * Subroutine for ATExecAlterColumnType: remember that an index needs + * to be rebuilt (which we might already know). + */ +static void +RememberIndexForRebuilding(Oid indoid, AlteredTableInfo *tab) +{ + /* + * This de-duplication check is critical for two independent reasons: we + * mustn't try to recreate the same index twice, and if an index depends + * on more than one column whose type is to be altered, we must capture + * its definition string before applying any of the column type changes. + * ruleutils.c will get confused if we ask again later. + */ + if (!list_member_oid(tab->changedIndexOids, indoid)) + { + /* + * Before adding it as an index-to-rebuild, we'd better see if it + * belongs to a constraint, and if so rebuild the constraint instead. + * Typically this check fails, because constraint indexes normally + * have only dependencies on their constraint. But it's possible for + * such an index to also have direct dependencies on table columns, + * for example with a partial exclusion constraint. + */ + Oid conoid = get_index_constraint(indoid); + + if (OidIsValid(conoid)) + { + RememberConstraintForRebuilding(conoid, tab); + } + else + { + /* OK, capture the index's existing definition string */ + char *defstring = pg_get_indexdef_string(indoid); + + tab->changedIndexOids = lappend_oid(tab->changedIndexOids, + indoid); + tab->changedIndexDefs = lappend(tab->changedIndexDefs, + defstring); + } + } +} + +/* * Returns the address of the modified column */ static ObjectAddress |