]> granicus.if.org Git - postgresql/commitdiff
Avoid a few more SET DATA TYPE table rewrites.
authorRobert Haas <rhaas@postgresql.org>
Tue, 15 Feb 2011 04:17:35 +0000 (23:17 -0500)
committerRobert Haas <rhaas@postgresql.org>
Tue, 15 Feb 2011 04:40:05 +0000 (23:40 -0500)
When the new type is an unconstrained domain over the old type, we don't
need to rewrite the table.

Noah Misch and Robert Haas

doc/src/sgml/ref/alter_table.sgml
src/backend/commands/tablecmds.c

index 7e6e72f008e0d58b3bf54230daae07c6029060ad..b8c4c507a2c5ec68ded8f102e2267cbeea450bbf 100644 (file)
@@ -766,13 +766,14 @@ ALTER TABLE <replaceable class="PARAMETER">name</replaceable>
    <para>
     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 <literal>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 <literal>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 <literal>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 <literal>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.
    </para>
 
    <para>
index f901ecfd27f76608a71d693c380795ab40766bf1..5789a39ba3d6fbaa98fed8113e7a40a78090b7fa 100644 (file)
@@ -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;
        }