OSDN Git Service

Add more checks against altering typed tables
authorPeter Eisentraut <peter_e@gmx.net>
Fri, 23 Jul 2010 20:04:18 +0000 (20:04 +0000)
committerPeter Eisentraut <peter_e@gmx.net>
Fri, 23 Jul 2010 20:04:18 +0000 (20:04 +0000)
- Prohibit altering column type
- Prohibit changing inheritance
- Move checks from Exec to Prep phases in ALTER TABLE code

backpatched to 9.0

src/backend/commands/tablecmds.c
src/test/regress/expected/typed_table.out
src/test/regress/sql/typed_table.sql

index 5f6e6fb..c5981d4 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.332 2010/07/06 19:18:56 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.333 2010/07/23 20:04:18 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -288,6 +288,7 @@ static void ATExecSetOptions(Relation rel, const char *colName,
                                 Node *options, bool isReset);
 static void ATExecSetStorage(Relation rel, const char *colName,
                                 Node *newValue);
+static void ATPrepDropColumn(Relation rel, bool recurse, AlterTableCmd *cmd);
 static void ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
                                 DropBehavior behavior,
                                 bool recurse, bool recursing,
@@ -327,7 +328,8 @@ static void ATExecEnableDisableTrigger(Relation rel, char *trigname,
                                                   char fires_when, bool skip_system);
 static void ATExecEnableDisableRule(Relation rel, char *rulename,
                                                char fires_when);
-static void ATExecAddInherit(Relation rel, RangeVar *parent);
+static void ATPrepAddInherit(Relation child_rel);
+static void ATExecAddInherit(Relation child_rel, RangeVar *parent);
 static void ATExecDropInherit(Relation rel, RangeVar *parent);
 static void copy_relation_data(SMgrRelation rel, SMgrRelation dst,
                                   ForkNumber forkNum, bool istemp);
@@ -2499,10 +2501,8 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
                        break;
                case AT_DropColumn:             /* DROP COLUMN */
                        ATSimplePermissions(rel, false);
+                       ATPrepDropColumn(rel, recurse, cmd);
                        /* Recursion occurs during execution phase */
-                       /* No command-specific prep needed except saving recurse flag */
-                       if (recurse)
-                               cmd->subtype = AT_DropColumnRecurse;
                        pass = AT_PASS_DROP;
                        break;
                case AT_AddIndex:               /* ADD INDEX */
@@ -2579,6 +2579,12 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
                        /* No command-specific prep needed */
                        pass = AT_PASS_MISC;
                        break;
+               case AT_AddInherit:             /* INHERIT */
+                       ATSimplePermissions(rel, false);
+                       /* This command never recurses */
+                       ATPrepAddInherit(rel);
+                       pass = AT_PASS_MISC;
+                       break;
                case AT_EnableTrig:             /* ENABLE TRIGGER variants */
                case AT_EnableAlwaysTrig:
                case AT_EnableReplicaTrig:
@@ -2591,8 +2597,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
                case AT_EnableAlwaysRule:
                case AT_EnableReplicaRule:
                case AT_DisableRule:
-               case AT_AddInherit:             /* INHERIT / NO INHERIT */
-               case AT_DropInherit:
+               case AT_DropInherit:    /* NO INHERIT */
                        ATSimplePermissions(rel, false);
                        /* These commands never recurse */
                        /* No command-specific prep needed */
@@ -3568,6 +3573,11 @@ static void
 ATPrepAddColumn(List **wqueue, Relation rel, bool recurse,
                                AlterTableCmd *cmd)
 {
+       if (rel->rd_rel->reloftype)
+               ereport(ERROR,
+                               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                                errmsg("cannot add column to typed table")));
+
        /*
         * Recurse to add the column to child classes, if requested.
         *
@@ -3616,11 +3626,6 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
        Form_pg_type tform;
        Expr       *defval;
 
-       if (rel->rd_rel->reloftype)
-               ereport(ERROR,
-                               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
-                                errmsg("cannot add column to typed table")));
-
        attrdesc = heap_open(AttributeRelationId, RowExclusiveLock);
 
        /*
@@ -4326,6 +4331,19 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue)
  * correctly.)
  */
 static void
+ATPrepDropColumn(Relation rel, bool recurse, AlterTableCmd *cmd)
+{
+       if (rel->rd_rel->reloftype)
+               ereport(ERROR,
+                               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                                errmsg("cannot drop column from typed table")));
+
+       /* No command-specific prep needed except saving recurse flag */
+       if (recurse)
+               cmd->subtype = AT_DropColumnRecurse;
+}
+
+static void
 ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
                                 DropBehavior behavior,
                                 bool recurse, bool recursing,
@@ -4337,11 +4355,6 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
        List       *children;
        ObjectAddress object;
 
-       if (rel->rd_rel->reloftype)
-               ereport(ERROR,
-                               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
-                                errmsg("cannot drop column from typed table")));
-
        /* At top level, permission check was done in ATPrepCmd, else do it */
        if (recursing)
                ATSimplePermissions(rel, false);
@@ -5788,6 +5801,11 @@ ATPrepAlterColumnType(List **wqueue,
        NewColumnValue *newval;
        ParseState *pstate = make_parsestate(NULL);
 
+       if (rel->rd_rel->reloftype)
+               ereport(ERROR,
+                               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                                errmsg("cannot alter column type of typed table")));
+
        /* lookup the attribute so we can check inheritance status */
        tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName);
        if (!HeapTupleIsValid(tuple))
@@ -7116,6 +7134,15 @@ ATExecEnableDisableRule(Relation rel, char *trigname,
  * same data types and expressions.
  */
 static void
+ATPrepAddInherit(Relation child_rel)
+{
+       if (child_rel->rd_rel->reloftype)
+               ereport(ERROR,
+                               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                                errmsg("cannot change inheritance of typed table")));
+}
+
+static void
 ATExecAddInherit(Relation child_rel, RangeVar *parent)
 {
        Relation        parent_rel,
index e92cdf6..9b933fd 100644 (file)
@@ -25,12 +25,18 @@ SELECT * FROM get_all_persons();
 ----+------
 (0 rows)
 
+-- certain ALTER TABLE operations on typed tables are not allowed
 ALTER TABLE persons ADD COLUMN comment text;
 ERROR:  cannot add column to typed table
 ALTER TABLE persons DROP COLUMN name;
 ERROR:  cannot drop column from typed table
 ALTER TABLE persons RENAME COLUMN id TO num;
 ERROR:  cannot rename column of typed table
+ALTER TABLE persons ALTER COLUMN name TYPE varchar;
+ERROR:  cannot alter column type of typed table
+CREATE TABLE stuff (id int);
+ALTER TABLE persons INHERIT stuff;
+ERROR:  cannot change inheritance of typed table
 CREATE TABLE personsx OF person_type (myname WITH OPTIONS NOT NULL); -- error
 ERROR:  column "myname" does not exist
 CREATE TABLE persons2 OF person_type (
@@ -83,3 +89,4 @@ DETAIL:  drop cascades to table persons
 drop cascades to function get_all_persons()
 drop cascades to table persons2
 drop cascades to table persons3
+DROP TABLE stuff;
index 4e81f1d..60cb6d6 100644 (file)
@@ -13,9 +13,13 @@ $$;
 
 SELECT * FROM get_all_persons();
 
+-- certain ALTER TABLE operations on typed tables are not allowed
 ALTER TABLE persons ADD COLUMN comment text;
 ALTER TABLE persons DROP COLUMN name;
 ALTER TABLE persons RENAME COLUMN id TO num;
+ALTER TABLE persons ALTER COLUMN name TYPE varchar;
+CREATE TABLE stuff (id int);
+ALTER TABLE persons INHERIT stuff;
 
 CREATE TABLE personsx OF person_type (myname WITH OPTIONS NOT NULL); -- error
 
@@ -40,3 +44,5 @@ CREATE TABLE persons4 OF person_type (
 
 DROP TYPE person_type RESTRICT;
 DROP TYPE person_type CASCADE;
+
+DROP TABLE stuff;