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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers