code-diff-since-before-e76de8861.patch
text/x-diff
Filename: code-diff-since-before-e76de8861.patch
Type: text/x-diff
Part: 1
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/commands/tablecmds.c | 31 | 5 |
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 98519ef..83dc6df 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -10600,11 +10600,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 = table_open(DependRelationId, RowExclusiveLock);
@@ -10646,6 +10641,14 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
if (relKind == RELKIND_INDEX ||
relKind == RELKIND_PARTITIONED_INDEX)
{
+ /*
+ * This de-duplication check is critical for two
+ * independent reasons: we mustn't try to create 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.
+ */
Assert(foundObject.objectSubId == 0);
if (!list_member_oid(tab->changedIndexOids, foundObject.objectId))
{
@@ -10688,6 +10691,12 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
}
case OCLASS_CONSTRAINT:
+
+ /*
+ * As with indexes, de-duplication is critical, and it's
+ * needed because the same constraint could depend on multiple
+ * target columns.
+ */
Assert(foundObject.objectSubId == 0);
if (!list_member_oid(tab->changedConstraintOids,
foundObject.objectId))
@@ -11198,8 +11207,25 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
def_item, tab->changedIndexDefs)
{
Oid oldId = lfirst_oid(oid_item);
+ Oid conoid;
Oid relid;
+ /*
+ * We must check each index to see if it belongs to a constraint that
+ * we already processed above. Typically this check does not fire
+ * because constraint indexes normally have only dependencies on their
+ * constraint, and thus would not have been found by the dependency
+ * scan in ATExecAlterColumnType. But it's possible for such an index
+ * to also have direct dependencies on the table, for example with a
+ * partial exclusion constraint. In that case we'd have list entries
+ * for both the index and the constraint, and we must disregard the
+ * one for the index.
+ */
+ conoid = get_index_constraint(oldId);
+ if (OidIsValid(conoid) &&
+ list_member_oid(tab->changedConstraintOids, conoid))
+ continue;
+
relid = IndexGetRelation(oldId, false);
ATPostAlterTypeParse(oldId, relid, InvalidOid,
(char *) lfirst(def_item),