aboutsummaryrefslogtreecommitdiff
path: root/src/backend/catalog/partition.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/catalog/partition.c')
-rw-r--r--src/backend/catalog/partition.c38
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;