I suspect the following is a bug: create table foo (a int) with oids; CREATE TABLE create table bar (a int); CREATE TABLE alter table bar inherit foo; ERROR: table "bar" without OIDs cannot inherit from table "foo" with OIDs
alter table bar set with oids; ALTER TABLE alter table bar inherit foo; ALTER TABLE alter table foo set without oids; ERROR: relation 16551 has non-inherited attribute "oid" Because: select attinhcount from pg_attribute where attrelid = 'bar'::regclass and attname = 'oid'; attinhcount ------------- 0 (1 row) Which also means "oid" can be safely dropped from bar breaking the invariant that if the parent table has oid column, its child tables must too: alter table bar drop oid; -- or, alter table bar set without oids; ALTER TABLE Attached patches modifies MergeAttributesIntoExisting() such that we increment attinhcount not only for user attributes, but also for the oid system column if one exists. Thoughts? Thanks, Amit
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index a7ac85e7ab..225a1fe9a1 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -10901,6 +10901,30 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel) } } + /* + * Must update the child's pg_attribute entry for the "oid" column, + * if any. + */ + if (tupleDesc->tdhasoid) + { + Form_pg_attribute childatt; + + tuple = SearchSysCacheCopyAttName(RelationGetRelid(child_rel), "oid"); + Assert(HeapTupleIsValid(tuple)); + childatt = (Form_pg_attribute) GETSTRUCT(tuple); + childatt->attinhcount++; + /* See the comment above. */ + if (child_is_partition) + { + Assert(childatt->attinhcount == 1); + childatt->attislocal = false; + } + + simple_heap_update(attrrel, &tuple->t_self, tuple); + CatalogUpdateIndexes(attrrel, tuple); + heap_freetuple(tuple); + } + heap_close(attrrel, RowExclusiveLock); } diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out index 38ea8e86f3..d1d20167c6 100644 --- a/src/test/regress/expected/inherit.out +++ b/src/test/regress/expected/inherit.out @@ -1814,3 +1814,28 @@ drop cascades to table part_40_inf drop cascades to table part_40_inf_ab drop cascades to table part_40_inf_cd drop cascades to table part_40_inf_null +-- check that oid column is handled properly during alter table inherit +create table _parent (a int) with oids; +create table _child (a int) with oids; +alter table _child inherit _parent; +-- fail +alter table _child set without oids; +ERROR: cannot drop inherited column "oid" +-- should return 1 +select attinhcount from pg_attribute where attrelid = '_child'::regclass and attname = 'oid'; + attinhcount +------------- + 1 +(1 row) + +alter table _parent set without oids; +-- should return 0 +select attinhcount from pg_attribute where attrelid = '_child'::regclass and attname = 'oid'; + attinhcount +------------- + 0 +(1 row) + +-- cleanup +drop table _parent cascade; +NOTICE: drop cascades to table _child diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql index e22a14ebda..01e04169e8 100644 --- a/src/test/regress/sql/inherit.sql +++ b/src/test/regress/sql/inherit.sql @@ -588,3 +588,18 @@ explain (costs off) select * from range_list_parted where a >= 30; drop table list_parted cascade; drop table range_list_parted cascade; + +-- check that oid column is handled properly during alter table inherit +create table _parent (a int) with oids; +create table _child (a int) with oids; +alter table _child inherit _parent; +-- fail +alter table _child set without oids; +-- should return 1 +select attinhcount from pg_attribute where attrelid = '_child'::regclass and attname = 'oid'; +alter table _parent set without oids; +-- should return 0 +select attinhcount from pg_attribute where attrelid = '_child'::regclass and attname = 'oid'; + +-- cleanup +drop table _parent cascade;
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers