On ons, 2010-07-21 at 15:48 -0400, Alvaro Herrera wrote:
> Excerpts from Peter Eisentraut's message of miƩ jul 21 15:18:58 -0400 2010:
> > After some investigation I figured that I need to add two more checks
> > into the ALTER TABLE code to prevent certain types of direct changes to
> > typed tables (see attached patch).
> > 
> > But it's not clear to me whether such checks should go into the "Prep"
> > or the "Exec" phases.  Prep seems more plausible to me, but some
> > commands such as DropColumn don't have a Prep handler.  A clarification
> > would be helpful.
> 
> I think if there's no Prep phase, you should add it.  I don't think it
> makes sense to have this kind of check in Exec.

OK, here is my patch for this.  (should go into 9.0 and 9.1)

Index: src/backend/commands/tablecmds.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v
retrieving revision 1.332
diff -u -3 -p -r1.332 tablecmds.c
--- src/backend/commands/tablecmds.c	6 Jul 2010 19:18:56 -0000	1.332
+++ src/backend/commands/tablecmds.c	22 Jul 2010 14:53:24 -0000
@@ -288,6 +288,7 @@ static void ATExecSetOptions(Relation re
 				 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(R
 						   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, A
 			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, A
 			/* 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, A
 		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, R
 	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 cha
  * 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
 	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, ch
  * 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: src/test/regress/expected/typed_table.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/typed_table.out,v
retrieving revision 1.1
diff -u -3 -p -r1.1 typed_table.out
--- src/test/regress/expected/typed_table.out	28 Jan 2010 23:21:13 -0000	1.1
+++ src/test/regress/expected/typed_table.out	22 Jul 2010 14:53:26 -0000
@@ -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: src/test/regress/sql/typed_table.sql
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/sql/typed_table.sql,v
retrieving revision 1.1
diff -u -3 -p -r1.1 typed_table.sql
--- src/test/regress/sql/typed_table.sql	28 Jan 2010 23:21:13 -0000	1.1
+++ src/test/regress/sql/typed_table.sql	22 Jul 2010 14:53:26 -0000
@@ -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;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to