diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 886b792..90c74cd 100644 *** a/src/backend/commands/tablecmds.c --- /bsrc/backend/commands/tablecmds.c *************** static void createForeignKeyTriggers(Rel *** 197,202 **** --- 197,206 ---- static void ATController(Relation rel, List *cmds, bool recurse); static void ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, bool recurse, bool recursing); + static void ATPrepAlterColumn(List **wqueue, + AlteredTableInfo *tab, Relation rel, + bool recurse, bool recursing, + AlterTableCmd *cmd); static void ATRewriteCatalogs(List **wqueue); static void ATExecCmd(AlteredTableInfo *tab, Relation rel, AlterTableCmd *cmd); static void ATRewriteTables(List **wqueue); *************** static void ATExecAddInherit(Relation re *** 261,267 **** static void ATExecDropInherit(Relation rel, RangeVar *parent); static void copy_relation_data(Relation rel, SMgrRelation dst); - /* ---------------------------------------------------------------- * DefineRelation * Creates a new relation. --- 265,270 ---- *************** ATPrepCmd(List **wqueue, Relation rel, A *** 1911,1923 **** break; case AT_DropNotNull: /* ALTER COLUMN DROP NOT NULL */ ATSimplePermissions(rel, false); ! ATSimpleRecursion(wqueue, rel, cmd, recurse); ! /* No command-specific prep needed */ pass = AT_PASS_DROP; break; case AT_SetNotNull: /* ALTER COLUMN SET NOT NULL */ ATSimplePermissions(rel, false); ! ATSimpleRecursion(wqueue, rel, cmd, recurse); /* No command-specific prep needed */ pass = AT_PASS_ADD_CONSTR; break; --- 1914,1925 ---- break; case AT_DropNotNull: /* ALTER COLUMN DROP NOT NULL */ ATSimplePermissions(rel, false); ! ATPrepAlterColumn(wqueue, tab, rel, recurse, recursing, cmd); pass = AT_PASS_DROP; break; case AT_SetNotNull: /* ALTER COLUMN SET NOT NULL */ ATSimplePermissions(rel, false); ! ATPrepAlterColumn(wqueue, tab, rel, recurse, recursing, cmd); /* No command-specific prep needed */ pass = AT_PASS_ADD_CONSTR; break; *************** add_column_datatype_dependency(Oid relid *** 3262,3267 **** --- 3264,3318 ---- } /* + * Handles the generic ALTER TABLE ALTER COLUMN case + */ + static void + ATPrepAlterColumn(List **wqueue, + AlteredTableInfo *tab, Relation rel, + bool recurse, bool recursing, + AlterTableCmd *cmd) + { + AlterTableCmd *childCmd; + HeapTuple tuple; + Form_pg_attribute targetatt; + + /* + * get tuple, and targetatt so we can check inherits + */ + tuple = SearchSysCacheAttName(RelationGetRelid(rel), cmd->name); + if (!HeapTupleIsValid(tuple)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("column \"%s\" of relation \"%s\" does not exist", + cmd->name, RelationGetRelationName(rel)))); + targetatt = (Form_pg_attribute) GETSTRUCT(tuple); + + if (targetatt->attinhcount > 0 && !recursing) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("cannot alter inherited column \"%s\" %s", cmd->name, RelationGetRelationName(rel)))); + + ReleaseSysCache(tuple); + + childCmd = copyObject(cmd); + + /* + * The recursion case is handled by ATSimpleRecursion. However, if we are + * told not to recurse, there had better not be any child tables; else the + * alter would put them out of step. + */ + if (recurse) + ATSimpleRecursion(wqueue, rel, cmd, recurse); + else if (!recursing && + find_inheritance_children(RelationGetRelid(rel)) != NIL) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("inherited column \"%s\" must be changed in child tables too", + cmd->name))); + } + + + /* * ALTER TABLE ALTER COLUMN DROP NOT NULL */ static void diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index cba489d..06f5365 100644 *** a/src/test/regress/expected/alter_table.out --- /bsrc/test/regress/expected/alter_table.out *************** alter table parent alter a drop not null *** 594,611 **** insert into parent values (NULL); insert into child (a, b) values (NULL, 'foo'); alter table only parent alter a set not null; ! ERROR: column "a" contains null values alter table child alter a set not null; ERROR: column "a" contains null values delete from parent; ! alter table only parent alter a set not null; insert into parent values (NULL); ERROR: null value in column "a" violates not-null constraint - alter table child alter a set not null; - insert into child (a, b) values (NULL, 'foo'); - ERROR: null value in column "a" violates not-null constraint - delete from child; - alter table child alter a set not null; insert into child (a, b) values (NULL, 'foo'); ERROR: null value in column "a" violates not-null constraint drop table child; --- 594,608 ---- insert into parent values (NULL); insert into child (a, b) values (NULL, 'foo'); alter table only parent alter a set not null; ! ERROR: inherited column "a" must be changed in child tables too alter table child alter a set not null; + ERROR: cannot alter inherited column "a" child + alter table parent alter a set not null; ERROR: column "a" contains null values delete from parent; ! alter table parent alter a set not null; insert into parent values (NULL); ERROR: null value in column "a" violates not-null constraint insert into child (a, b) values (NULL, 'foo'); ERROR: null value in column "a" violates not-null constraint drop table child; diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out index f81776f..dc6e730 100644 *** a/src/test/regress/expected/inherit.out --- /bsrc/test/regress/expected/inherit.out *************** *** 1,7 **** -- -- Test inheritance features -- ! CREATE TABLE a (aa TEXT); CREATE TABLE b (bb TEXT) INHERITS (a); CREATE TABLE c (cc TEXT) INHERITS (a); CREATE TABLE d (dd TEXT) INHERITS (b,c,a); --- 1,7 ---- -- -- Test inheritance features -- ! CREATE TABLE a (aa TEXT NOT NULL); CREATE TABLE b (bb TEXT) INHERITS (a); CREATE TABLE c (cc TEXT) INHERITS (a); CREATE TABLE d (dd TEXT) INHERITS (b,c,a); diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql index d52d6c8..865b88d 100644 *** a/src/test/regress/sql/alter_table.sql --- /bsrc/test/regress/sql/alter_table.sql *************** insert into parent values (NULL); *** 582,594 **** insert into child (a, b) values (NULL, 'foo'); alter table only parent alter a set not null; alter table child alter a set not null; delete from parent; ! alter table only parent alter a set not null; insert into parent values (NULL); - alter table child alter a set not null; - insert into child (a, b) values (NULL, 'foo'); - delete from child; - alter table child alter a set not null; insert into child (a, b) values (NULL, 'foo'); drop table child; drop table parent; --- 582,591 ---- insert into child (a, b) values (NULL, 'foo'); alter table only parent alter a set not null; alter table child alter a set not null; + alter table parent alter a set not null; delete from parent; ! alter table parent alter a set not null; insert into parent values (NULL); insert into child (a, b) values (NULL, 'foo'); drop table child; drop table parent; diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql index b0499a6..592246c 100644 *** a/src/test/regress/sql/inherit.sql --- /bsrc/test/regress/sql/inherit.sql *************** *** 1,7 **** -- -- Test inheritance features -- ! CREATE TABLE a (aa TEXT); CREATE TABLE b (bb TEXT) INHERITS (a); CREATE TABLE c (cc TEXT) INHERITS (a); CREATE TABLE d (dd TEXT) INHERITS (b,c,a); --- 1,7 ---- -- -- Test inheritance features -- ! CREATE TABLE a (aa TEXT NOT NULL); CREATE TABLE b (bb TEXT) INHERITS (a); CREATE TABLE c (cc TEXT) INHERITS (a); CREATE TABLE d (dd TEXT) INHERITS (b,c,a);