From 40d43781c41359d2fc834827db55d8edd39710cf Mon Sep 17 00:00:00 2001 From: Tender Wang Date: Wed, 12 Jun 2024 13:29:10 +0800 Subject: [PATCH v1] Fix assert failure when detach partition. --- src/backend/catalog/pg_inherits.c | 26 ++++++++++++++++++++ src/backend/commands/tablecmds.c | 21 ++++++++++++++++ src/include/catalog/pg_inherits.h | 2 ++ src/test/regress/expected/partition_info.out | 13 ++++++++++ src/test/regress/sql/partition_info.sql | 15 +++++++++++ 5 files changed, 77 insertions(+) diff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c index 836b4bfd89..c386863699 100644 --- a/src/backend/catalog/pg_inherits.c +++ b/src/backend/catalog/pg_inherits.c @@ -393,6 +393,32 @@ has_superclass(Oid relationId) return result; } +/* + * get_superclass - returns this relation inherit tuple if it has + */ +HeapTuple +get_superclass(Oid relationId) +{ + Relation catalog; + SysScanDesc scan; + ScanKeyData skey; + HeapTuple inhTup, + retval = NULL; + + catalog = table_open(InheritsRelationId, AccessShareLock); + ScanKeyInit(&skey, Anum_pg_inherits_inhrelid, BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(relationId)); + scan = systable_beginscan(catalog, InheritsRelidSeqnoIndexId, true, + NULL, 1, &skey); + inhTup = systable_getnext(scan); + if (HeapTupleIsValid(inhTup)) + retval = heap_copytuple(inhTup); + + systable_endscan(scan); + table_close(catalog, AccessShareLock); + + return retval; +} /* * Given two type OIDs, determine whether the first is a complex type * (class type) that inherits from the second. diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 6adfd87614..a300676e14 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -19289,6 +19289,10 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent, Oid idxid = lfirst_oid(cell); Relation idx; Oid constrOid; + HeapTuple parentTuple; + Oid parentIdxid; + Oid parentConstrOid; + Form_pg_inherits inhForm; if (!has_superclass(idxid)) continue; @@ -19296,15 +19300,32 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent, Assert((IndexGetRelation(get_partition_parent(idxid, false), false) == RelationGetRelid(rel))); + /* Get inherit tuple */ + parentTuple = get_superclass(idxid); + Assert(HeapTupleIsValid(parentTuple)); + inhForm = (Form_pg_inherits) GETSTRUCT(parentTuple); + parentIdxid = inhForm->inhparent; + + parentConstrOid = get_relation_idx_constraint_oid(RelationGetRelid(rel), + parentIdxid); idx = index_open(idxid, AccessExclusiveLock); IndexSetParentIndex(idx, InvalidOid); + /* Skip if there's no a constraint associated with parent index */ + if (!OidIsValid(parentConstrOid)) + { + heap_freetuple(parentTuple); + index_close(idx, NoLock); + continue; + } + /* If there's a constraint associated with the index, detach it too */ constrOid = get_relation_idx_constraint_oid(RelationGetRelid(partRel), idxid); if (OidIsValid(constrOid)) ConstraintSetParentConstraint(constrOid, InvalidOid, InvalidOid); + heap_freetuple(parentTuple); index_close(idx, NoLock); } diff --git a/src/include/catalog/pg_inherits.h b/src/include/catalog/pg_inherits.h index b3da78c24b..d8855a1733 100644 --- a/src/include/catalog/pg_inherits.h +++ b/src/include/catalog/pg_inherits.h @@ -18,6 +18,7 @@ #ifndef PG_INHERITS_H #define PG_INHERITS_H +#include "access/htup.h" #include "catalog/genbki.h" #include "catalog/pg_inherits_d.h" @@ -56,6 +57,7 @@ extern List *find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents); extern bool has_subclass(Oid relationId); extern bool has_superclass(Oid relationId); +extern HeapTuple get_superclass(Oid relationId); extern bool typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId); extern void StoreSingleInheritance(Oid relationId, Oid parentOid, int32 seqNumber); diff --git a/src/test/regress/expected/partition_info.out b/src/test/regress/expected/partition_info.out index 42b6bc77ca..3f689989b9 100644 --- a/src/test/regress/expected/partition_info.out +++ b/src/test/regress/expected/partition_info.out @@ -275,6 +275,19 @@ SELECT pg_partition_root('ptif_normal_table'); (1 row) DROP TABLE ptif_normal_table; +-- If parent index doesn't have a constraint tuple +-- detach partition should not fail. +CREATE TABLE pt_ind_t (a int) PARTITION BY RANGE (a); +CREATE TABLE pt_ind_tp (a int PRIMARY KEY); +ALTER TABLE pt_ind_t ATTACH PARTITION pt_ind_tp FOR VALUES FROM (0) TO (1000); +CREATE UNIQUE INDEX pt_a_idx ON pt_ind_t (a); +ALTER INDEX pt_a_idx ATTACH PARTITION pt_ind_tp_pkey; +ALTER TABLE pt_ind_t DETACH PARTITION pt_ind_tp; +CREATE TABLE pt_indx_t (a int) PARTITION BY RANGE (a); +CREATE TABLE pt_indx_tp (a int PRIMARY KEY); +CREATE UNIQUE INDEX ptx_a_idx ON pt_indx_t (a); +ALTER TABLE pt_indx_t ATTACH PARTITION pt_indx_tp FOR VALUES FROM (0) TO (1000); +ALTER TABLE pt_indx_t DETACH PARTITION pt_indx_tp; -- Various partitioning-related functions return empty/NULL if passed relations -- of types that cannot be part of a partition tree; for example, views, -- materialized views, legacy inheritance children or parents, etc. diff --git a/src/test/regress/sql/partition_info.sql b/src/test/regress/sql/partition_info.sql index b5060bec7f..a36f8db562 100644 --- a/src/test/regress/sql/partition_info.sql +++ b/src/test/regress/sql/partition_info.sql @@ -105,6 +105,21 @@ SELECT * FROM pg_partition_ancestors('ptif_normal_table'); SELECT pg_partition_root('ptif_normal_table'); DROP TABLE ptif_normal_table; +-- If parent index doesn't have a constraint tuple +-- detach partition should not fail. +CREATE TABLE pt_ind_t (a int) PARTITION BY RANGE (a); +CREATE TABLE pt_ind_tp (a int PRIMARY KEY); +ALTER TABLE pt_ind_t ATTACH PARTITION pt_ind_tp FOR VALUES FROM (0) TO (1000); +CREATE UNIQUE INDEX pt_a_idx ON pt_ind_t (a); +ALTER INDEX pt_a_idx ATTACH PARTITION pt_ind_tp_pkey; +ALTER TABLE pt_ind_t DETACH PARTITION pt_ind_tp; + +CREATE TABLE pt_indx_t (a int) PARTITION BY RANGE (a); +CREATE TABLE pt_indx_tp (a int PRIMARY KEY); +CREATE UNIQUE INDEX ptx_a_idx ON pt_indx_t (a); +ALTER TABLE pt_indx_t ATTACH PARTITION pt_indx_tp FOR VALUES FROM (0) TO (1000); +ALTER TABLE pt_indx_t DETACH PARTITION pt_indx_tp; + -- Various partitioning-related functions return empty/NULL if passed relations -- of types that cannot be part of a partition tree; for example, views, -- materialized views, legacy inheritance children or parents, etc. -- 2.34.1