summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2017-01-04 18:00:12 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2017-01-04 18:00:12 -0500
commit5f89a9885e118ab22689f9641237f7941d9ba8fd (patch)
tree166eacccc2679aabc3cac8435618a0b6a353450d
parente7c586e7b222b80c42de473468ce5e7e14bbca60 (diff)
Handle OID column inheritance correctly in ALTER TABLE ... INHERIT.
Inheritance operations must treat the OID column, if any, much like regular user columns. But MergeAttributesIntoExisting() neglected to do that, leading to weird results after a table with OIDs is associated to a parent with OIDs via ALTER TABLE ... INHERIT. Report and patch by Amit Langote, reviewed by Ashutosh Bapat, some adjustments by me. It's been broken all along, so back-patch to all supported branches. Discussion: https://postgr.es/m/cb13cfe7-a48c-5720-c383-bb843ab28298@lab.ntt.co.jp
-rw-r--r--src/backend/commands/tablecmds.c33
-rw-r--r--src/test/regress/expected/inherit.out49
-rw-r--r--src/test/regress/sql/inherit.sql26
3 files changed, 108 insertions, 0 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 327ef08b17c..5098358d5c1 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -9356,6 +9356,39 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel)
}
}
+ /*
+ * If the parent has an OID column, so must the child, and we'd better
+ * update the child's attinhcount and attislocal the same as for normal
+ * columns. We needn't check data type or not-nullness though.
+ */
+ if (tupleDesc->tdhasoid)
+ {
+ /*
+ * Here we match by column number not name; the match *must* be the
+ * system column, not some random column named "oid".
+ */
+ tuple = SearchSysCacheCopy2(ATTNUM,
+ ObjectIdGetDatum(RelationGetRelid(child_rel)),
+ Int16GetDatum(ObjectIdAttributeNumber));
+ if (HeapTupleIsValid(tuple))
+ {
+ Form_pg_attribute childatt = (Form_pg_attribute) GETSTRUCT(tuple);
+
+ /* See comments above; these changes should be the same */
+ childatt->attinhcount++;
+ simple_heap_update(attrrel, &tuple->t_self, tuple);
+ CatalogUpdateIndexes(attrrel, tuple);
+ heap_freetuple(tuple);
+ }
+ else
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("child table is missing column \"%s\"",
+ "oid")));
+ }
+ }
+
heap_close(attrrel, RowExclusiveLock);
}
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
index 6a6b840217f..0782242a62a 100644
--- a/src/test/regress/expected/inherit.out
+++ b/src/test/regress/expected/inherit.out
@@ -612,6 +612,55 @@ select * from d;
32 | one | two | three
(1 row)
+-- check that oid column is handled properly during alter table inherit
+create table oid_parent (a int) with oids;
+create table oid_child () inherits (oid_parent);
+select attinhcount, attislocal from pg_attribute
+ where attrelid = 'oid_child'::regclass and attname = 'oid';
+ attinhcount | attislocal
+-------------+------------
+ 1 | f
+(1 row)
+
+drop table oid_child;
+create table oid_child (a int) without oids;
+alter table oid_child inherit oid_parent; -- fail
+ERROR: table "oid_child" without OIDs cannot inherit from table "oid_parent" with OIDs
+alter table oid_child set with oids;
+select attinhcount, attislocal from pg_attribute
+ where attrelid = 'oid_child'::regclass and attname = 'oid';
+ attinhcount | attislocal
+-------------+------------
+ 0 | t
+(1 row)
+
+alter table oid_child inherit oid_parent;
+select attinhcount, attislocal from pg_attribute
+ where attrelid = 'oid_child'::regclass and attname = 'oid';
+ attinhcount | attislocal
+-------------+------------
+ 1 | t
+(1 row)
+
+alter table oid_child set without oids; -- fail
+ERROR: cannot drop inherited column "oid"
+alter table oid_parent set without oids;
+select attinhcount, attislocal from pg_attribute
+ where attrelid = 'oid_child'::regclass and attname = 'oid';
+ attinhcount | attislocal
+-------------+------------
+ 0 | t
+(1 row)
+
+alter table oid_child set without oids;
+select attinhcount, attislocal from pg_attribute
+ where attrelid = 'oid_child'::regclass and attname = 'oid';
+ attinhcount | attislocal
+-------------+------------
+(0 rows)
+
+drop table oid_parent cascade;
+NOTICE: drop cascades to table oid_child
-- Test non-inheritable parent constraints
create table p1(ff1 int);
alter table p1 add constraint p1chk check (ff1 > 0) no inherit;
diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql
index d65839899c1..0e390cda3e4 100644
--- a/src/test/regress/sql/inherit.sql
+++ b/src/test/regress/sql/inherit.sql
@@ -145,6 +145,32 @@ insert into d values('test','one','two','three');
alter table a alter column aa type integer using bit_length(aa);
select * from d;
+-- check that oid column is handled properly during alter table inherit
+create table oid_parent (a int) with oids;
+
+create table oid_child () inherits (oid_parent);
+select attinhcount, attislocal from pg_attribute
+ where attrelid = 'oid_child'::regclass and attname = 'oid';
+drop table oid_child;
+
+create table oid_child (a int) without oids;
+alter table oid_child inherit oid_parent; -- fail
+alter table oid_child set with oids;
+select attinhcount, attislocal from pg_attribute
+ where attrelid = 'oid_child'::regclass and attname = 'oid';
+alter table oid_child inherit oid_parent;
+select attinhcount, attislocal from pg_attribute
+ where attrelid = 'oid_child'::regclass and attname = 'oid';
+alter table oid_child set without oids; -- fail
+alter table oid_parent set without oids;
+select attinhcount, attislocal from pg_attribute
+ where attrelid = 'oid_child'::regclass and attname = 'oid';
+alter table oid_child set without oids;
+select attinhcount, attislocal from pg_attribute
+ where attrelid = 'oid_child'::regclass and attname = 'oid';
+
+drop table oid_parent cascade;
+
-- Test non-inheritable parent constraints
create table p1(ff1 int);
alter table p1 add constraint p1chk check (ff1 > 0) no inherit;