diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 851432ab25..f7c5907994 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -9878,11 +9878,13 @@ ATPrepAlterColumnType(List **wqueue, RelationGetRelationName(rel)))); if (tab->relkind == RELKIND_COMPOSITE_TYPE || - tab->relkind == RELKIND_FOREIGN_TABLE) + tab->relkind == RELKIND_FOREIGN_TABLE || + tab->relkind == RELKIND_PARTITIONED_TABLE || + tab->relkind == RELKIND_PARTITIONED_INDEX) { /* - * For composite types, do this check now. Tables will check it later - * when the table is being rewritten. + * For relations without storage, do this check now. Regular tables + * will check it later when the table is being rewritten. */ find_composite_type_dependencies(rel->rd_rel->reltype, rel, NULL); } diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index 298d9c81ee..ba2e80a3b9 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -2093,11 +2093,24 @@ select * from another; (3 rows) drop table another; --- table's row type -create table tab1 (a int, b text); -create table tab2 (x int, y tab1); -alter table tab1 alter column b type varchar; -- fails -ERROR: cannot alter table "tab1" because column "tab2.y" uses its row type +-- We disallow changing table's row type if it's used for storage +create table at_tab1 (a int, b text); +create table at_tab2 (x int, y at_tab1); +alter table at_tab1 alter column b type varchar; -- fails +ERROR: cannot alter table "at_tab1" because column "at_tab2.y" uses its row type +drop table at_tab2; +-- Use of row type in an expression is defended differently +create table at_tab2 (x int, y text, check((x,y)::at_tab1 = (1,'42')::at_tab1)); +alter table at_tab1 alter column b type varchar; -- allowed, but ... +insert into at_tab2 values(1,'42'); -- ... this will fail +ERROR: ROW() column has type text instead of type character varying +drop table at_tab1, at_tab2; +-- Check it for a partitioned table, too +create table at_tab1 (a int, b text) partition by list(a); +create table at_tab2 (x int, y at_tab1); +alter table at_tab1 alter column b type varchar; -- fails +ERROR: cannot alter table "at_tab1" because column "at_tab2.y" uses its row type +drop table at_tab1, at_tab2; -- Alter column type that's part of a partitioned index create table at_partitioned (a int, b text) partition by range (a); create table at_part_1 partition of at_partitioned for values from (0) to (1000); diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql index 20713bd0c6..6b3f7d88ba 100644 --- a/src/test/regress/sql/alter_table.sql +++ b/src/test/regress/sql/alter_table.sql @@ -1420,10 +1420,21 @@ select * from another; drop table another; --- table's row type -create table tab1 (a int, b text); -create table tab2 (x int, y tab1); -alter table tab1 alter column b type varchar; -- fails +-- We disallow changing table's row type if it's used for storage +create table at_tab1 (a int, b text); +create table at_tab2 (x int, y at_tab1); +alter table at_tab1 alter column b type varchar; -- fails +drop table at_tab2; +-- Use of row type in an expression is defended differently +create table at_tab2 (x int, y text, check((x,y)::at_tab1 = (1,'42')::at_tab1)); +alter table at_tab1 alter column b type varchar; -- allowed, but ... +insert into at_tab2 values(1,'42'); -- ... this will fail +drop table at_tab1, at_tab2; +-- Check it for a partitioned table, too +create table at_tab1 (a int, b text) partition by list(a); +create table at_tab2 (x int, y at_tab1); +alter table at_tab1 alter column b type varchar; -- fails +drop table at_tab1, at_tab2; -- Alter column type that's part of a partitioned index create table at_partitioned (a int, b text) partition by range (a);