diff options
Diffstat (limited to 'src/backend/catalog/partition.c')
-rw-r--r-- | src/backend/catalog/partition.c | 38 |
1 files changed, 30 insertions, 8 deletions
diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c index af7754d6ab7..790f4ccb927 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -32,7 +32,8 @@ #include "utils/rel.h" #include "utils/syscache.h" -static Oid get_partition_parent_worker(Relation inhRel, Oid relid); +static Oid get_partition_parent_worker(Relation inhRel, Oid relid, + bool *detach_pending); static void get_partition_ancestors_worker(Relation inhRel, Oid relid, List **ancestors); @@ -42,23 +43,32 @@ static void get_partition_ancestors_worker(Relation inhRel, Oid relid, * * Returns inheritance parent of a partition by scanning pg_inherits * + * If the partition is in the process of being detached, an error is thrown, + * unless even_if_detached is passed as true. + * * Note: Because this function assumes that the relation whose OID is passed * as an argument will have precisely one parent, it should only be called * when it is known that the relation is a partition. */ Oid -get_partition_parent(Oid relid) +get_partition_parent(Oid relid, bool even_if_detached) { Relation catalogRelation; Oid result; + bool detach_pending; catalogRelation = table_open(InheritsRelationId, AccessShareLock); - result = get_partition_parent_worker(catalogRelation, relid); + result = get_partition_parent_worker(catalogRelation, relid, + &detach_pending); if (!OidIsValid(result)) elog(ERROR, "could not find tuple for parent of relation %u", relid); + if (detach_pending && !even_if_detached) + elog(ERROR, "relation %u has no parent because it's being detached", + relid); + table_close(catalogRelation, AccessShareLock); return result; @@ -68,15 +78,20 @@ get_partition_parent(Oid relid) * get_partition_parent_worker * Scan the pg_inherits relation to return the OID of the parent of the * given relation + * + * If the partition is being detached, *detach_pending is set true (but the + * original parent is still returned.) */ static Oid -get_partition_parent_worker(Relation inhRel, Oid relid) +get_partition_parent_worker(Relation inhRel, Oid relid, bool *detach_pending) { SysScanDesc scan; ScanKeyData key[2]; Oid result = InvalidOid; HeapTuple tuple; + *detach_pending = false; + ScanKeyInit(&key[0], Anum_pg_inherits_inhrelid, BTEqualStrategyNumber, F_OIDEQ, @@ -93,6 +108,9 @@ get_partition_parent_worker(Relation inhRel, Oid relid) { Form_pg_inherits form = (Form_pg_inherits) GETSTRUCT(tuple); + /* Let caller know of partition being detached */ + if (form->inhdetachpending) + *detach_pending = true; result = form->inhparent; } @@ -134,10 +152,14 @@ static void get_partition_ancestors_worker(Relation inhRel, Oid relid, List **ancestors) { Oid parentOid; + bool detach_pending; - /* Recursion ends at the topmost level, ie., when there's no parent */ - parentOid = get_partition_parent_worker(inhRel, relid); - if (parentOid == InvalidOid) + /* + * Recursion ends at the topmost level, ie., when there's no parent; also + * when the partition is being detached. + */ + parentOid = get_partition_parent_worker(inhRel, relid, &detach_pending); + if (parentOid == InvalidOid || detach_pending) return; *ancestors = lappend_oid(*ancestors, parentOid); @@ -170,7 +192,7 @@ index_get_partition(Relation partition, Oid indexId) ReleaseSysCache(tup); if (!ispartition) continue; - if (get_partition_parent(partIdx) == indexId) + if (get_partition_parent(partIdx, false) == indexId) { list_free(idxlist); return partIdx; |