diff options
Diffstat (limited to 'src/backend/commands/tablecmds.c')
-rw-r--r-- | src/backend/commands/tablecmds.c | 58 |
1 files changed, 51 insertions, 7 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index a7722052faa..fafd85db348 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8207,6 +8207,9 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, SysScanDesc scan; HeapTuple depTup; ObjectAddress address; + ListCell *lc; + ListCell *prev; + ListCell *next; attrelation = heap_open(AttributeRelationId, RowExclusiveLock); @@ -8320,14 +8323,20 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, if (relKind == RELKIND_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); - if (!list_member_oid(tab->changedIndexOids, foundObject.objectId)) - { - tab->changedIndexOids = lappend_oid(tab->changedIndexOids, - foundObject.objectId); - tab->changedIndexDefs = lappend(tab->changedIndexDefs, - pg_get_indexdef_string(foundObject.objectId)); - } + tab->changedIndexOids = + list_append_unique_oid(tab->changedIndexOids, + foundObject.objectId); } else if (relKind == RELKIND_SEQUENCE) { @@ -8482,6 +8491,41 @@ 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. |