]> granicus.if.org Git - postgresql/commitdiff
Propagate ALTER TYPE operations to typed tables
authorPeter Eisentraut <peter_e@gmx.net>
Tue, 23 Nov 2010 20:50:17 +0000 (22:50 +0200)
committerPeter Eisentraut <peter_e@gmx.net>
Tue, 23 Nov 2010 20:50:17 +0000 (22:50 +0200)
This adds RESTRICT/CASCADE flags to ALTER TYPE ... ADD/DROP/ALTER/
RENAME ATTRIBUTE to control whether to alter typed tables as well.

doc/src/sgml/ref/alter_type.sgml
src/backend/commands/alter.c
src/backend/commands/tablecmds.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/parser/gram.y
src/include/commands/tablecmds.h
src/include/nodes/parsenodes.h
src/test/regress/expected/alter_table.out
src/test/regress/sql/alter_table.sql

index 33413450c37e42fa8c9b9bc37cda29f52066f321..09db0cc8b2d7aa380460e4f7e16f54928a2f8970 100644 (file)
@@ -26,15 +26,15 @@ PostgreSQL documentation
 ALTER TYPE <replaceable class="PARAMETER">name</replaceable> <replaceable class="PARAMETER">action</replaceable> [, ... ]
 ALTER TYPE <replaceable class="PARAMETER">name</replaceable> OWNER TO <replaceable class="PARAMETER">new_owner</replaceable>
 ALTER TYPE <replaceable class="PARAMETER">name</replaceable> RENAME ATTRIBUTE <replaceable class="PARAMETER">attribute_name</replaceable> TO <replaceable class="PARAMETER">new_attribute_name</replaceable>
-ALTER TYPE <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable class="PARAMETER">new_name</replaceable>
+ALTER TYPE <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable class="PARAMETER">new_name</replaceable> [ CASCADE | RESTRICT ]
 ALTER TYPE <replaceable class="PARAMETER">name</replaceable> SET SCHEMA <replaceable class="PARAMETER">new_schema</replaceable>
 ALTER TYPE <replaceable class="PARAMETER">name</replaceable> ADD VALUE <replaceable class="PARAMETER">new_enum_value</replaceable> [ { BEFORE | AFTER } <replaceable class="PARAMETER">existing_enum_value</replaceable> ]
 
 <phrase>where <replaceable class="PARAMETER">action</replaceable> is one of:</phrase>
 
-    ADD ATTRIBUTE <replaceable class="PARAMETER">attribute_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable>
-    DROP ATTRIBUTE [ IF EXISTS ] <replaceable class="PARAMETER">attribute_name</replaceable>
-    ALTER ATTRIBUTE <replaceable class="PARAMETER">attribute_name</replaceable> [ SET DATA ] TYPE <replaceable class="PARAMETER">data_type</replaceable>
+    ADD ATTRIBUTE <replaceable class="PARAMETER">attribute_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [ CASCADE | RESTRICT ]
+    DROP ATTRIBUTE [ IF EXISTS ] <replaceable class="PARAMETER">attribute_name</replaceable> [ CASCADE | RESTRICT ]
+    ALTER ATTRIBUTE <replaceable class="PARAMETER">attribute_name</replaceable> [ SET DATA ] TYPE <replaceable class="PARAMETER">data_type</replaceable> [ CASCADE | RESTRICT ]
 </synopsis>
  </refsynopsisdiv>
 
@@ -116,6 +116,26 @@ ALTER TYPE <replaceable class="PARAMETER">name</replaceable> ADD VALUE <replacea
      </para>
     </listitem>
    </varlistentry>
+
+   <varlistentry>
+    <term><literal>CASCADE</literal></term>
+    <listitem>
+     <para>
+      Automatically propagate the operation to typed tables of the
+      type being altered.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><literal>RESTRICT</literal></term>
+    <listitem>
+     <para>
+      Refuse the operation if the type being altered is the type of a
+      typed table.  This is the default.
+     </para>
+    </listitem>
+   </varlistentry>
   </variablelist>
   </para>
 
index 794d355944d3bec337deef3f4fa59336587c2fd3..0d0227d04ad96f0389e7caa2be797f220970562b 100644 (file)
@@ -125,11 +125,7 @@ ExecRenameStmt(RenameStmt *stmt)
                                                }
                                        case OBJECT_COLUMN:
                                        case OBJECT_ATTRIBUTE:
-                                               renameatt(relid,
-                                                                 stmt->subname,                /* old att name */
-                                                                 stmt->newname,                /* new att name */
-                                                                 interpretInhOption(stmt->relation->inhOpt),   /* recursive? */
-                                                                 0);   /* expected inhcount */
+                                               renameatt(relid, stmt);
                                                break;
                                        case OBJECT_TRIGGER:
                                                renametrig(relid,
index 11171eaa9901c322511d5508d2f64961a43c4af2..e8808e28c68ce397d0e87ce73122d94efe924570 100644 (file)
@@ -269,8 +269,11 @@ static void ATSimpleRecursion(List **wqueue, Relation rel,
                                  AlterTableCmd *cmd, bool recurse, LOCKMODE lockmode);
 static void ATOneLevelRecursion(List **wqueue, Relation rel,
                                        AlterTableCmd *cmd, LOCKMODE lockmode);
-static void find_typed_table_dependencies(Oid typeOid, const char *typeName);
-static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse,
+static void ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
+                                                                 LOCKMODE lockmode);
+static List *find_typed_table_dependencies(Oid typeOid, const char *typeName,
+                                                                                  DropBehavior behavior);
+static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
                                AlterTableCmd *cmd, LOCKMODE lockmode);
 static void ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
                                ColumnDef *colDef, bool isOid, LOCKMODE lockmode);
@@ -290,7 +293,8 @@ static void ATExecSetOptions(Relation rel, const char *colName,
                                 Node *options, bool isReset, LOCKMODE lockmode);
 static void ATExecSetStorage(Relation rel, const char *colName,
                                 Node *newValue, LOCKMODE lockmode);
-static void ATPrepDropColumn(Relation rel, bool recurse, AlterTableCmd *cmd);
+static void ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
+                                                        AlterTableCmd *cmd, LOCKMODE lockmode);
 static void ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
                                 DropBehavior behavior,
                                 bool recurse, bool recursing,
@@ -1942,14 +1946,16 @@ setRelhassubclassInRelation(Oid relationId, bool relhassubclass)
 
 
 /*
- *             renameatt               - changes the name of a attribute in a relation
+ *             renameatt_internal              - workhorse for renameatt
  */
-void
-renameatt(Oid myrelid,
-                 const char *oldattname,
-                 const char *newattname,
-                 bool recurse,
-                 int expected_parents)
+static void
+renameatt_internal(Oid myrelid,
+                                  const char *oldattname,
+                                  const char *newattname,
+                                  bool recurse,
+                                  bool recursing,
+                                  int expected_parents,
+                                  DropBehavior behavior)
 {
        Relation        targetrelation;
        Relation        attrelation;
@@ -1964,15 +1970,11 @@ renameatt(Oid myrelid,
         */
        targetrelation = relation_open(myrelid, AccessExclusiveLock);
 
-       if (targetrelation->rd_rel->reloftype)
+       if (targetrelation->rd_rel->reloftype && !recursing)
                ereport(ERROR,
                                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                                 errmsg("cannot rename column of typed table")));
 
-       if (targetrelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
-               find_typed_table_dependencies(targetrelation->rd_rel->reltype,
-                                                                         RelationGetRelationName(targetrelation));
-
        /*
         * Renaming the columns of sequences or toast tables doesn't actually
         * break anything from the system's point of view, since internal
@@ -2038,7 +2040,7 @@ renameatt(Oid myrelid,
                        if (childrelid == myrelid)
                                continue;
                        /* note we need not recurse again */
-                       renameatt(childrelid, oldattname, newattname, false, numparents);
+                       renameatt_internal(childrelid, oldattname, newattname, false, true, numparents, behavior);
                }
        }
        else
@@ -2057,6 +2059,20 @@ renameatt(Oid myrelid,
                                                        oldattname)));
        }
 
+       /* rename attributes in typed tables of composite type */
+       if (targetrelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
+       {
+               List       *child_oids;
+               ListCell   *lo;
+
+               child_oids = find_typed_table_dependencies(targetrelation->rd_rel->reltype,
+                                                                                                  RelationGetRelationName(targetrelation),
+                                                                                                  behavior);
+
+               foreach(lo, child_oids)
+                       renameatt_internal(lfirst_oid(lo), oldattname, newattname, true, true, 0, behavior);
+       }
+
        attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
 
        atttup = SearchSysCacheCopyAttName(myrelid, oldattname);
@@ -2116,6 +2132,22 @@ renameatt(Oid myrelid,
 }
 
 
+/*
+ *             renameatt               - changes the name of a attribute in a relation
+ */
+void
+renameatt(Oid myrelid, RenameStmt *stmt)
+{
+       renameatt_internal(myrelid,
+                                          stmt->subname,               /* old att name */
+                                          stmt->newname,               /* new att name */
+                                          interpretInhOption(stmt->relation->inhOpt),  /* recursive? */
+                                          false,  /* recursing? */
+                                          0,   /* expected inhcount */
+                                          stmt->behavior);
+}
+
+
 /*
  * Execute ALTER TABLE/INDEX/SEQUENCE/VIEW RENAME
  *
@@ -2649,14 +2681,14 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
                case AT_AddColumn:              /* ADD COLUMN */
                        ATSimplePermissions(rel, false, true);
                        /* Performs own recursion */
-                       ATPrepAddColumn(wqueue, rel, recurse, cmd, lockmode);
+                       ATPrepAddColumn(wqueue, rel, recurse, recursing, cmd, lockmode);
                        pass = AT_PASS_ADD_COL;
                        break;
                case AT_AddColumnToView:                /* add column via CREATE OR REPLACE
                                                                                 * VIEW */
                        ATSimplePermissions(rel, true, false);
                        /* Performs own recursion */
-                       ATPrepAddColumn(wqueue, rel, recurse, cmd, lockmode);
+                       ATPrepAddColumn(wqueue, rel, recurse, recursing, cmd, lockmode);
                        pass = AT_PASS_ADD_COL;
                        break;
                case AT_ColumnDefault:  /* ALTER COLUMN DEFAULT */
@@ -2704,7 +2736,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
                        break;
                case AT_DropColumn:             /* DROP COLUMN */
                        ATSimplePermissions(rel, false, true);
-                       ATPrepDropColumn(rel, recurse, cmd);
+                       ATPrepDropColumn(wqueue, rel, recurse, recursing, cmd, lockmode);
                        /* Recursion occurs during execution phase */
                        pass = AT_PASS_DROP;
                        break;
@@ -3671,6 +3703,37 @@ ATOneLevelRecursion(List **wqueue, Relation rel,
        }
 }
 
+/*
+ * ATTypedTableRecursion
+ *
+ * Propagate ALTER TYPE operations to the typed tables of that type.
+ * Also check the RESTRICT/CASCADE behavior.
+ */
+static void
+ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
+                                         LOCKMODE lockmode)
+{
+       ListCell   *child;
+       List       *children;
+
+       Assert(rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE);
+
+       children = find_typed_table_dependencies(rel->rd_rel->reltype,
+                                                                                        RelationGetRelationName(rel),
+                                                                                        cmd->behavior);
+
+       foreach(child, children)
+       {
+               Oid                     childrelid = lfirst_oid(child);
+               Relation        childrel;
+
+               childrel = relation_open(childrelid, lockmode);
+               CheckTableNotInUse(childrel, "ALTER TABLE");
+               ATPrepCmd(wqueue, childrel, cmd, false, true, lockmode);
+               relation_close(childrel, NoLock);
+       }
+}
+
 
 /*
  * find_composite_type_dependencies
@@ -3778,17 +3841,17 @@ find_composite_type_dependencies(Oid typeOid,
  * find_typed_table_dependencies
  *
  * Check to see if a composite type is being used as the type of a
- * typed table.  Eventually, we'd like to propagate the alter
- * operation into such tables, but for now, just error out if we find
- * any.
+ * typed table.  Abort if any are found and behavior is RESTRICT.
+ * Else return the list of tables.
  */
-static void
-find_typed_table_dependencies(Oid typeOid, const char *typeName)
+static List *
+find_typed_table_dependencies(Oid typeOid, const char *typeName, DropBehavior behavior)
 {
        Relation        classRel;
        ScanKeyData key[1];
        HeapScanDesc scan;
        HeapTuple       tuple;
+       List       *result = NIL;
 
        classRel = heap_open(RelationRelationId, AccessShareLock);
 
@@ -3801,14 +3864,20 @@ find_typed_table_dependencies(Oid typeOid, const char *typeName)
 
        if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
        {
-               ereport(ERROR,
-                               (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                errmsg("cannot alter type \"%s\" because it is the type of a typed table",
-                                               typeName)));
+               if (behavior == DROP_RESTRICT)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+                                        errmsg("cannot alter type \"%s\" because it is the type of a typed table",
+                                                       typeName),
+                                        errhint("Use ALTER ... CASCADE to alter the typed tables too.")));
+               else
+                       result = lappend_oid(result, HeapTupleGetOid(tuple));
        }
 
        heap_endscan(scan);
        heap_close(classRel, AccessShareLock);
+
+       return result;
 }
 
 
@@ -3821,10 +3890,10 @@ find_typed_table_dependencies(Oid typeOid, const char *typeName)
  * AlterTableCmd's.
  */
 static void
-ATPrepAddColumn(List **wqueue, Relation rel, bool recurse,
+ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
                                AlterTableCmd *cmd, LOCKMODE lockmode)
 {
-       if (rel->rd_rel->reloftype)
+       if (rel->rd_rel->reloftype && !recursing)
                ereport(ERROR,
                                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                                 errmsg("cannot add column to typed table")));
@@ -3860,8 +3929,7 @@ ATPrepAddColumn(List **wqueue, Relation rel, bool recurse,
        }
 
        if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
-               find_typed_table_dependencies(rel->rd_rel->reltype,
-                                                                         RelationGetRelationName(rel));
+               ATTypedTableRecursion(wqueue, rel, cmd, lockmode);
 }
 
 static void
@@ -4162,7 +4230,7 @@ ATPrepAddOids(List **wqueue, Relation rel, bool recurse, AlterTableCmd *cmd, LOC
                cdef->storage = 0;
                cmd->def = (Node *) cdef;
        }
-       ATPrepAddColumn(wqueue, rel, recurse, cmd, lockmode);
+       ATPrepAddColumn(wqueue, rel, recurse, false, cmd, lockmode);
 }
 
 /*
@@ -4586,18 +4654,17 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc
  * correctly.)
  */
 static void
-ATPrepDropColumn(Relation rel, bool recurse, AlterTableCmd *cmd)
+ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
+                                AlterTableCmd *cmd, LOCKMODE lockmode)
 {
-       if (rel->rd_rel->reloftype)
+       if (rel->rd_rel->reloftype && !recursing)
                ereport(ERROR,
                                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                                 errmsg("cannot drop column from typed table")));
 
        if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
-               find_typed_table_dependencies(rel->rd_rel->reltype,
-                                                                         RelationGetRelationName(rel));
+               ATTypedTableRecursion(wqueue, rel, cmd, lockmode);
 
-       /* No command-specific prep needed except saving recurse flag */
        if (recurse)
                cmd->subtype = AT_DropColumnRecurse;
 }
@@ -6060,7 +6127,7 @@ ATPrepAlterColumnType(List **wqueue,
        NewColumnValue *newval;
        ParseState *pstate = make_parsestate(NULL);
 
-       if (rel->rd_rel->reloftype)
+       if (rel->rd_rel->reloftype && !recursing)
                ereport(ERROR,
                                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                                 errmsg("cannot alter column type of typed table")));
@@ -6178,9 +6245,6 @@ ATPrepAlterColumnType(List **wqueue,
                find_composite_type_dependencies(rel->rd_rel->reltype,
                                                                                 NULL,
                                                                                 RelationGetRelationName(rel));
-
-               find_typed_table_dependencies(rel->rd_rel->reltype,
-                                                                         RelationGetRelationName(rel));
        }
 
        ReleaseSysCache(tuple);
@@ -6198,6 +6262,9 @@ ATPrepAlterColumnType(List **wqueue,
                                (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                                 errmsg("type of inherited column \"%s\" must be changed in child tables too",
                                                colName)));
+
+       if (tab->relkind == RELKIND_COMPOSITE_TYPE)
+               ATTypedTableRecursion(wqueue, rel, cmd, lockmode);
 }
 
 static void
index e91044bc4adb314b570b5c6d94f1e8fad4489b70..bbfbab2e39bd75e16f9b0f07147f3e60c325c0b4 100644 (file)
@@ -2803,6 +2803,7 @@ _copyRenameStmt(RenameStmt *from)
        COPY_NODE_FIELD(objarg);
        COPY_STRING_FIELD(subname);
        COPY_STRING_FIELD(newname);
+       COPY_SCALAR_FIELD(behavior);
 
        return newnode;
 }
index 73b28f96c0e8f47d35d6ca6a4051fa2f10d3d71c..be4b835585c4260d14ddf4d4771c0b50d0182912 100644 (file)
@@ -1306,6 +1306,7 @@ _equalRenameStmt(RenameStmt *a, RenameStmt *b)
        COMPARE_NODE_FIELD(objarg);
        COMPARE_STRING_FIELD(subname);
        COMPARE_STRING_FIELD(newname);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
index d9b20746fa1d2469b42d9f3061f20ae1f2ceca32..f0c2cd06ea6358b598a02bb579ac288c562b2cdf 100644 (file)
@@ -2003,41 +2003,43 @@ alter_type_cmds:
                ;
 
 alter_type_cmd:
-                       /* ALTER TYPE <name> ADD ATTRIBUTE <coldef> */
-                       ADD_P ATTRIBUTE TableFuncElement
+                       /* ALTER TYPE <name> ADD ATTRIBUTE <coldef> [RESTRICT|CASCADE] */
+                       ADD_P ATTRIBUTE TableFuncElement opt_drop_behavior
                                {
                                        AlterTableCmd *n = makeNode(AlterTableCmd);
                                        n->subtype = AT_AddColumn;
                                        n->def = $3;
+                                       n->behavior = $4;
                                        $$ = (Node *)n;
                                }
-                       /* ALTER TYPE <name> DROP ATTRIBUTE IF EXISTS <attname> */
-                       | DROP ATTRIBUTE IF_P EXISTS ColId
+                       /* ALTER TYPE <name> DROP ATTRIBUTE IF EXISTS <attname> [RESTRICT|CASCADE] */
+                       | DROP ATTRIBUTE IF_P EXISTS ColId opt_drop_behavior
                                {
                                        AlterTableCmd *n = makeNode(AlterTableCmd);
                                        n->subtype = AT_DropColumn;
                                        n->name = $5;
-                                       n->behavior = DROP_RESTRICT; /* currently no effect */
+                                       n->behavior = $6;
                                        n->missing_ok = TRUE;
                                        $$ = (Node *)n;
                                }
-                       /* ALTER TYPE <name> DROP ATTRIBUTE <attname> */
+                       /* ALTER TYPE <name> DROP ATTRIBUTE <attname> [RESTRICT|CASCADE] */
                        | DROP ATTRIBUTE ColId opt_drop_behavior
                                {
                                        AlterTableCmd *n = makeNode(AlterTableCmd);
                                        n->subtype = AT_DropColumn;
                                        n->name = $3;
-                                       n->behavior = DROP_RESTRICT; /* currently no effect */
+                                       n->behavior = $4;
                                        n->missing_ok = FALSE;
                                        $$ = (Node *)n;
                                }
-                       /* ALTER TYPE <name> ALTER ATTRIBUTE <attname> [SET DATA] TYPE <typename> */
-                       | ALTER ATTRIBUTE ColId opt_set_data TYPE_P Typename
+                       /* ALTER TYPE <name> ALTER ATTRIBUTE <attname> [SET DATA] TYPE <typename> [RESTRICT|CASCADE] */
+                       | ALTER ATTRIBUTE ColId opt_set_data TYPE_P Typename opt_drop_behavior
                                {
                                        AlterTableCmd *n = makeNode(AlterTableCmd);
                                        n->subtype = AT_AlterColumnType;
                                        n->name = $3;
                                        n->def = (Node *) $6;
+                                       n->behavior = $7;
                                        $$ = (Node *)n;
                                }
                ;
@@ -6005,13 +6007,14 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
                                        n->newname = $6;
                                        $$ = (Node *)n;
                                }
-                       | ALTER TYPE_P any_name RENAME ATTRIBUTE name TO name
+                       | ALTER TYPE_P any_name RENAME ATTRIBUTE name TO name opt_drop_behavior
                                {
                                        RenameStmt *n = makeNode(RenameStmt);
                                        n->renameType = OBJECT_ATTRIBUTE;
                                        n->relation = makeRangeVarFromAnyName($3, @3, yyscanner);
                                        n->subname = $6;
                                        n->newname = $8;
+                                       n->behavior = $9;
                                        $$ = (Node *)n;
                                }
                ;
index aed3960e497cac3f8d4771e5b51b1b62421f8dc5..ad932d397958f0d2ecca23d521e7432b59f65edb 100644 (file)
@@ -42,11 +42,7 @@ extern void CheckTableNotInUse(Relation rel, const char *stmt);
 
 extern void ExecuteTruncate(TruncateStmt *stmt);
 
-extern void renameatt(Oid myrelid,
-                 const char *oldattname,
-                 const char *newattname,
-                 bool recurse,
-                 int expected_parents);
+extern void renameatt(Oid myrelid, RenameStmt *stmt);
 
 extern void RenameRelation(Oid myrelid,
                           const char *newrelname,
index a320be4d899c2d13b85a01676f7e2de4e915dcc1..d6cfafea711f4a25c99662257112794075a874e5 100644 (file)
@@ -2073,6 +2073,7 @@ typedef struct RenameStmt
        char       *subname;            /* name of contained object (column, rule,
                                                                 * trigger, etc) */
        char       *newname;            /* the new name */
+       DropBehavior behavior;          /* RESTRICT or CASCADE behavior */
 } RenameStmt;
 
 /* ----------------------
index d6c5827c68b8e1b9711ecf6451997bd8f18a9439..b68dfd4fc2641d2fbb0d3d79dc9af0b1483c711d 100644 (file)
@@ -1760,13 +1760,100 @@ ALTER TYPE test_type1 ALTER ATTRIBUTE b TYPE varchar; -- fails
 ERROR:  cannot alter type "test_type1" because column "test_tbl1"."y" uses it
 CREATE TYPE test_type2 AS (a int, b text);
 CREATE TABLE test_tbl2 OF test_type2;
+\d test_type2
+Composite type "public.test_type2"
+ Column |  Type   
+--------+---------
+ a      | integer
+ b      | text
+
+\d test_tbl2
+   Table "public.test_tbl2"
+ Column |  Type   | Modifiers 
+--------+---------+-----------
+ a      | integer | 
+ b      | text    | 
+Typed table of type: test_type2
+
 ALTER TYPE test_type2 ADD ATTRIBUTE c text; -- fails
 ERROR:  cannot alter type "test_type2" because it is the type of a typed table
+HINT:  Use ALTER ... CASCADE to alter the typed tables too.
+ALTER TYPE test_type2 ADD ATTRIBUTE c text CASCADE;
+\d test_type2
+Composite type "public.test_type2"
+ Column |  Type   
+--------+---------
+ a      | integer
+ b      | text
+ c      | text
+
+\d test_tbl2
+   Table "public.test_tbl2"
+ Column |  Type   | Modifiers 
+--------+---------+-----------
+ a      | integer | 
+ b      | text    | 
+ c      | text    | 
+Typed table of type: test_type2
+
 ALTER TYPE test_type2 ALTER ATTRIBUTE b TYPE varchar; -- fails
 ERROR:  cannot alter type "test_type2" because it is the type of a typed table
+HINT:  Use ALTER ... CASCADE to alter the typed tables too.
+ALTER TYPE test_type2 ALTER ATTRIBUTE b TYPE varchar CASCADE;
+\d test_type2
+Composite type "public.test_type2"
+ Column |       Type        
+--------+-------------------
+ a      | integer
+ b      | character varying
+ c      | text
+
+\d test_tbl2
+        Table "public.test_tbl2"
+ Column |       Type        | Modifiers 
+--------+-------------------+-----------
+ a      | integer           | 
+ b      | character varying | 
+ c      | text              | 
+Typed table of type: test_type2
+
 ALTER TYPE test_type2 DROP ATTRIBUTE b; -- fails
 ERROR:  cannot alter type "test_type2" because it is the type of a typed table
-ALTER TYPE test_type2 RENAME ATTRIBUTE b TO bb; -- fails
+HINT:  Use ALTER ... CASCADE to alter the typed tables too.
+ALTER TYPE test_type2 DROP ATTRIBUTE b CASCADE;
+\d test_type2
+Composite type "public.test_type2"
+ Column |  Type   
+--------+---------
+ a      | integer
+ c      | text
+
+\d test_tbl2
+   Table "public.test_tbl2"
+ Column |  Type   | Modifiers 
+--------+---------+-----------
+ a      | integer | 
+ c      | text    | 
+Typed table of type: test_type2
+
+ALTER TYPE test_type2 RENAME ATTRIBUTE a TO aa; -- fails
 ERROR:  cannot alter type "test_type2" because it is the type of a typed table
+HINT:  Use ALTER ... CASCADE to alter the typed tables too.
+ALTER TYPE test_type2 RENAME ATTRIBUTE a TO aa CASCADE;
+\d test_type2
+Composite type "public.test_type2"
+ Column |  Type   
+--------+---------
+ aa     | integer
+ c      | text
+
+\d test_tbl2
+   Table "public.test_tbl2"
+ Column |  Type   | Modifiers 
+--------+---------+-----------
+ aa     | integer | 
+ c      | text    | 
+Typed table of type: test_type2
+
 CREATE TYPE test_type_empty AS ();
 DROP TYPE test_type_empty;
index c6015cbb4016c21004fa34f213fd960c1e7448d2..98a68d587729cd49d375fe588b915ee04132c9c0 100644 (file)
@@ -1272,10 +1272,28 @@ ALTER TYPE test_type1 ALTER ATTRIBUTE b TYPE varchar; -- fails
 
 CREATE TYPE test_type2 AS (a int, b text);
 CREATE TABLE test_tbl2 OF test_type2;
+\d test_type2
+\d test_tbl2
+
 ALTER TYPE test_type2 ADD ATTRIBUTE c text; -- fails
+ALTER TYPE test_type2 ADD ATTRIBUTE c text CASCADE;
+\d test_type2
+\d test_tbl2
+
 ALTER TYPE test_type2 ALTER ATTRIBUTE b TYPE varchar; -- fails
+ALTER TYPE test_type2 ALTER ATTRIBUTE b TYPE varchar CASCADE;
+\d test_type2
+\d test_tbl2
+
 ALTER TYPE test_type2 DROP ATTRIBUTE b; -- fails
-ALTER TYPE test_type2 RENAME ATTRIBUTE b TO bb; -- fails
+ALTER TYPE test_type2 DROP ATTRIBUTE b CASCADE;
+\d test_type2
+\d test_tbl2
+
+ALTER TYPE test_type2 RENAME ATTRIBUTE a TO aa; -- fails
+ALTER TYPE test_type2 RENAME ATTRIBUTE a TO aa CASCADE;
+\d test_type2
+\d test_tbl2
 
 CREATE TYPE test_type_empty AS ();
 DROP TYPE test_type_empty;