From 0156840e4e4647bef6c6278265b748c8a799e317 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Fri, 23 Jul 2010 20:04:18 +0000 Subject: [PATCH] Add more checks against altering typed tables - 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 | 61 ++++++++++++++++------- src/test/regress/expected/typed_table.out | 7 +++ src/test/regress/sql/typed_table.sql | 6 +++ 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 5f6e6fb005..c5981d4e5b 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -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); /* @@ -4325,6 +4330,19 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue) * static pre-pass because it won't handle multiple inheritance situations * 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, @@ -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)) @@ -7115,6 +7133,15 @@ ATExecEnableDisableRule(Relation rel, char *trigname, * check constraints of the parent appear in the child and that they have the * 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) { diff --git a/src/test/regress/expected/typed_table.out b/src/test/regress/expected/typed_table.out index e92cdf65e1..9b933fdadc 100644 --- a/src/test/regress/expected/typed_table.out +++ b/src/test/regress/expected/typed_table.out @@ -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; diff --git a/src/test/regress/sql/typed_table.sql b/src/test/regress/sql/typed_table.sql index 4e81f1dd6a..60cb6d6857 100644 --- a/src/test/regress/sql/typed_table.sql +++ b/src/test/regress/sql/typed_table.sql @@ -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;