]> granicus.if.org Git - postgresql/commitdiff
Fix failure to remove dependencies when a partition is detached.
authorRobert Haas <rhaas@postgresql.org>
Tue, 13 Jun 2017 15:51:42 +0000 (11:51 -0400)
committerRobert Haas <rhaas@postgresql.org>
Tue, 13 Jun 2017 15:51:42 +0000 (11:51 -0400)
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

src/backend/commands/tablecmds.c
src/test/regress/expected/alter_table.out
src/test/regress/sql/alter_table.sql

index b61fda9909d5d6dae53d4cce114f2c8c0b6a0171..9aef67be44871f798f8bab7bfdc1d5599421d9fd 100644 (file)
@@ -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);
index 8aadbb88a348571dd2fe6e22d1e2a2f72380d35b..d4dbe650a323538fc8092fecd384d70aa401b555 100644 (file)
@@ -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;
index c41b48785b5cdf2f4ad76ea8ec414059b6de1824..001717d91ce0011d7c49afdc136eb79167e1e73b 100644 (file)
@@ -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