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
This commit is contained in:
parent
506b565831
commit
ee252f074b
@ -283,6 +283,14 @@ struct DropRelationCallbackState
|
|||||||
#define ATT_COMPOSITE_TYPE 0x0010
|
#define ATT_COMPOSITE_TYPE 0x0010
|
||||||
#define ATT_FOREIGN_TABLE 0x0020
|
#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 void truncate_check_rel(Relation rel);
|
||||||
static List *MergeAttributes(List *schema, List *supers, char relpersistence,
|
static List *MergeAttributes(List *schema, List *supers, char relpersistence,
|
||||||
bool is_partition, List **supOids, List **supconstr,
|
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 void ATPrepAddInherit(Relation child_rel);
|
||||||
static ObjectAddress ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode);
|
static ObjectAddress ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode);
|
||||||
static ObjectAddress ATExecDropInherit(Relation 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 ObjectAddress ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode);
|
||||||
static void ATExecDropOf(Relation rel, LOCKMODE lockmode);
|
static void ATExecDropOf(Relation rel, LOCKMODE lockmode);
|
||||||
static void ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode);
|
static void ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode);
|
||||||
@ -2367,14 +2376,8 @@ StoreCatalogInheritance1(Oid relationId, Oid parentOid,
|
|||||||
childobject.objectId = relationId;
|
childobject.objectId = relationId;
|
||||||
childobject.objectSubId = 0;
|
childobject.objectSubId = 0;
|
||||||
|
|
||||||
/*
|
recordDependencyOn(&childobject, &parentobject,
|
||||||
* Partition tables are expected to be dropped when the parent partitioned
|
child_dependency_type(child_is_partition));
|
||||||
* table gets dropped.
|
|
||||||
*/
|
|
||||||
if (child_is_partition)
|
|
||||||
recordDependencyOn(&childobject, &parentobject, DEPENDENCY_AUTO);
|
|
||||||
else
|
|
||||||
recordDependencyOn(&childobject, &parentobject, DEPENDENCY_NORMAL);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Post creation hook of this inheritance. Since object_access_hook
|
* 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),
|
drop_parent_dependency(RelationGetRelid(child_rel),
|
||||||
RelationRelationId,
|
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
|
* 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.
|
* through pg_depend.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid)
|
drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid,
|
||||||
|
DependencyType deptype)
|
||||||
{
|
{
|
||||||
Relation catalogRelation;
|
Relation catalogRelation;
|
||||||
SysScanDesc scan;
|
SysScanDesc scan;
|
||||||
@ -11718,7 +11723,7 @@ drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid)
|
|||||||
if (dep->refclassid == refclassid &&
|
if (dep->refclassid == refclassid &&
|
||||||
dep->refobjid == refobjid &&
|
dep->refobjid == refobjid &&
|
||||||
dep->refobjsubid == 0 &&
|
dep->refobjsubid == 0 &&
|
||||||
dep->deptype == DEPENDENCY_NORMAL)
|
dep->deptype == deptype)
|
||||||
CatalogTupleDelete(catalogRelation, &depTuple->t_self);
|
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 the table was already typed, drop the existing dependency. */
|
||||||
if (rel->rd_rel->reloftype)
|
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. */
|
/* Record a dependency on the new type. */
|
||||||
tableobj.classId = RelationRelationId;
|
tableobj.classId = RelationRelationId;
|
||||||
@ -11892,7 +11898,8 @@ ATExecDropOf(Relation rel, LOCKMODE lockmode)
|
|||||||
* table is presumed enough rights. No lock required on the type, either.
|
* 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 */
|
/* Clear pg_class.reloftype */
|
||||||
relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
|
relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
|
||||||
|
@ -3385,6 +3385,19 @@ SELECT coninhcount, conislocal FROM pg_constraint WHERE conrelid = 'part_3_4'::r
|
|||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
DROP TABLE part_3_4;
|
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
|
-- Check ALTER TABLE commands for partitioned tables and partitions
|
||||||
-- cannot add/drop column to/from *only* the parent
|
-- cannot add/drop column to/from *only* the parent
|
||||||
ALTER TABLE ONLY list_parted2 ADD COLUMN c int;
|
ALTER TABLE ONLY list_parted2 ADD COLUMN c int;
|
||||||
|
@ -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';
|
SELECT coninhcount, conislocal FROM pg_constraint WHERE conrelid = 'part_3_4'::regclass AND conname = 'check_a';
|
||||||
DROP TABLE part_3_4;
|
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
|
-- Check ALTER TABLE commands for partitioned tables and partitions
|
||||||
|
|
||||||
-- cannot add/drop column to/from *only* the parent
|
-- cannot add/drop column to/from *only* the parent
|
||||||
|
Loading…
x
Reference in New Issue
Block a user