From: Robert Haas Date: Tue, 13 Jun 2017 15:51:42 +0000 (-0400) Subject: Fix failure to remove dependencies when a partition is detached. X-Git-Tag: REL_10_BETA2~163 X-Git-Url: http://git.postgresql.org/gitweb/?a=commitdiff_plain;h=ee252f074b88e34ff7ac2b45a73d3cee12b1c671;p=postgresql.git Fix failure to remove dependencies when a partition is detached. Otherwise, dropping the partitioned table will automatically drop any previously-detached children, which would be unfortunate. Ashutosh Bapat and Rahila Syed, reviewed by Amit Langote and by me. Discussion: http://postgr.es/m/CAFjFpRdOwHuGj45i25iLQ4QituA0uH6RuLX1h5deD4KBZJ25yg@mail.gmail.com --- diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index b61fda9909d..9aef67be448 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -283,6 +283,14 @@ struct DropRelationCallbackState #define ATT_COMPOSITE_TYPE 0x0010 #define ATT_FOREIGN_TABLE 0x0020 +/* + * Partition tables are expected to be dropped when the parent partitioned + * table gets dropped. Hence for partitioning we use AUTO dependency. + * Otherwise, for regular inheritance use NORMAL dependency. + */ +#define child_dependency_type(child_is_partition) \ + ((child_is_partition) ? DEPENDENCY_AUTO : DEPENDENCY_NORMAL) + static void truncate_check_rel(Relation rel); static List *MergeAttributes(List *schema, List *supers, char relpersistence, bool is_partition, List **supOids, List **supconstr, @@ -439,7 +447,8 @@ static void ATExecEnableDisableRule(Relation rel, char *rulename, static void ATPrepAddInherit(Relation child_rel); static ObjectAddress ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode); static ObjectAddress ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode); -static void drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid); +static void drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid, + DependencyType deptype); static ObjectAddress ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode); static void ATExecDropOf(Relation rel, LOCKMODE lockmode); static void ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode); @@ -2367,14 +2376,8 @@ StoreCatalogInheritance1(Oid relationId, Oid parentOid, childobject.objectId = relationId; childobject.objectSubId = 0; - /* - * Partition tables are expected to be dropped when the parent partitioned - * table gets dropped. - */ - if (child_is_partition) - recordDependencyOn(&childobject, &parentobject, DEPENDENCY_AUTO); - else - recordDependencyOn(&childobject, &parentobject, DEPENDENCY_NORMAL); + recordDependencyOn(&childobject, &parentobject, + child_dependency_type(child_is_partition)); /* * Post creation hook of this inheritance. Since object_access_hook @@ -11666,7 +11669,8 @@ RemoveInheritance(Relation child_rel, Relation parent_rel) drop_parent_dependency(RelationGetRelid(child_rel), RelationRelationId, - RelationGetRelid(parent_rel)); + RelationGetRelid(parent_rel), + child_dependency_type(child_is_partition)); /* * Post alter hook of this inherits. Since object_access_hook doesn't take @@ -11686,7 +11690,8 @@ RemoveInheritance(Relation child_rel, Relation parent_rel) * through pg_depend. */ static void -drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid) +drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid, + DependencyType deptype) { Relation catalogRelation; SysScanDesc scan; @@ -11718,7 +11723,7 @@ drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid) if (dep->refclassid == refclassid && dep->refobjid == refobjid && dep->refobjsubid == 0 && - dep->deptype == DEPENDENCY_NORMAL) + dep->deptype == deptype) CatalogTupleDelete(catalogRelation, &depTuple->t_self); } @@ -11839,7 +11844,8 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode) /* If the table was already typed, drop the existing dependency. */ if (rel->rd_rel->reloftype) - drop_parent_dependency(relid, TypeRelationId, rel->rd_rel->reloftype); + drop_parent_dependency(relid, TypeRelationId, rel->rd_rel->reloftype, + DEPENDENCY_NORMAL); /* Record a dependency on the new type. */ tableobj.classId = RelationRelationId; @@ -11892,7 +11898,8 @@ ATExecDropOf(Relation rel, LOCKMODE lockmode) * table is presumed enough rights. No lock required on the type, either. */ - drop_parent_dependency(relid, TypeRelationId, rel->rd_rel->reloftype); + drop_parent_dependency(relid, TypeRelationId, rel->rd_rel->reloftype, + DEPENDENCY_NORMAL); /* Clear pg_class.reloftype */ relationRelation = heap_open(RelationRelationId, RowExclusiveLock); diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index 8aadbb88a34..d4dbe650a32 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -3385,6 +3385,19 @@ SELECT coninhcount, conislocal FROM pg_constraint WHERE conrelid = 'part_3_4'::r (1 row) DROP TABLE part_3_4; +-- check that a detached partition is not dropped on dropping a partitioned table +CREATE TABLE range_parted2 ( + a int +) PARTITION BY RANGE(a); +CREATE TABLE part_rp PARTITION OF range_parted2 FOR VALUES FROM (0) to (100); +ALTER TABLE range_parted2 DETACH PARTITION part_rp; +DROP TABLE range_parted2; +SELECT * from part_rp; + a +--- +(0 rows) + +DROP TABLE part_rp; -- Check ALTER TABLE commands for partitioned tables and partitions -- cannot add/drop column to/from *only* the parent ALTER TABLE ONLY list_parted2 ADD COLUMN c int; diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql index c41b48785b5..001717d91ce 100644 --- a/src/test/regress/sql/alter_table.sql +++ b/src/test/regress/sql/alter_table.sql @@ -2204,6 +2204,16 @@ SELECT attinhcount, attislocal FROM pg_attribute WHERE attrelid = 'part_3_4'::re SELECT coninhcount, conislocal FROM pg_constraint WHERE conrelid = 'part_3_4'::regclass AND conname = 'check_a'; DROP TABLE part_3_4; +-- check that a detached partition is not dropped on dropping a partitioned table +CREATE TABLE range_parted2 ( + a int +) PARTITION BY RANGE(a); +CREATE TABLE part_rp PARTITION OF range_parted2 FOR VALUES FROM (0) to (100); +ALTER TABLE range_parted2 DETACH PARTITION part_rp; +DROP TABLE range_parted2; +SELECT * from part_rp; +DROP TABLE part_rp; + -- Check ALTER TABLE commands for partitioned tables and partitions -- cannot add/drop column to/from *only* the parent