diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml index 7e6e72f008e..b8c4c507a2c 100644 --- a/doc/src/sgml/ref/alter_table.sgml +++ b/doc/src/sgml/ref/alter_table.sgml @@ -766,13 +766,14 @@ ALTER TABLE name Adding a column with a non-null default or changing the type of an existing column will require the entire table and indexes to be rewritten. - As an exception, if the old type type is binary coercible to the new - type and the USING clause does not change the column contents, - a table rewrite is not needed, but any indexes on the affected columns - must still be rebuilt. Adding or removing a system oid column - also requires rewriting the entire table. Table and/or index rebuilds may - take a significant amount of time for a large table; and will temporarily - require as much as double the disk space. + As an exception, if the USING clause does not change the column + contents and the old type is either binary coercible to the new type or + an unconstrained domain over the new type, a table rewrite is not needed, + but any indexes on the affected columns must still be rebuilt. Adding or + removing a system oid column also requires rewriting the entire + table. Table and/or index rebuilds may take a significant amount of time + for a large table; and will temporarily require as much as double the disk + space. diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index f901ecfd27f..5789a39ba3d 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -6632,10 +6632,14 @@ ATPrepAlterColumnType(List **wqueue, } /* - * When the data type of a column is changed, a rewrite might not be require - * if the data type is being changed to its current type, or more interestingly - * to a type to which it is binary coercible. But we must check carefully that - * the USING clause isn't trying to insert some other value. + * When the data type of a column is changed, a rewrite might not be required + * if the new type is sufficiently identical to the old one, and the USING + * clause isn't trying to insert some other value. It's safe to skip the + * rewrite if the old type is binary coercible to the new type, or if the + * new type is an unconstrained domain over the old type. In the case of a + * constrained domain, we could get by with scanning the table and checking + * the constraint rather than actually rewriting it, but we don't currently + * try to do that. */ static bool ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno) @@ -6649,6 +6653,14 @@ ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno) return false; else if (IsA(expr, RelabelType)) expr = (Node *) ((RelabelType *) expr)->arg; + else if (IsA(expr, CoerceToDomain)) + { + CoerceToDomain *d = (CoerceToDomain *) expr; + + if (GetDomainConstraints(d->resulttype) != NIL) + return true; + expr = (Node *) d->arg; + } else return true; }