aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/partitionfuncs.c
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2019-02-08 08:56:14 +0900
committerMichael Paquier <michael@paquier.xyz>2019-02-08 08:56:14 +0900
commit3677a0b26bb2f3f72d16dc7fa6f34c305badacce (patch)
treea46ee2b807265d8f0c899c53f1bad3bebec67b34 /src/backend/utils/adt/partitionfuncs.c
parent34ea1ab7fd305afe1124a6e73ada0ebae04b6ebb (diff)
downloadpostgresql-3677a0b26bb2f3f72d16dc7fa6f34c305badacce.tar.gz
postgresql-3677a0b26bb2f3f72d16dc7fa6f34c305badacce.zip
Add pg_partition_root to display top-most parent of a partition tree
This is useful when looking at partition trees with multiple layers, and combined with pg_partition_tree, it provides the possibility to show up an entire tree by just knowing one member at any level. Author: Michael Paquier Reviewed-by: Álvaro Herrera, Amit Langote Discussion: https://postgr.es/m/20181207014015.GP2407@paquier.xyz
Diffstat (limited to 'src/backend/utils/adt/partitionfuncs.c')
-rw-r--r--src/backend/utils/adt/partitionfuncs.c75
1 files changed, 65 insertions, 10 deletions
diff --git a/src/backend/utils/adt/partitionfuncs.c b/src/backend/utils/adt/partitionfuncs.c
index 5cdf4a4524e..ffd66b64394 100644
--- a/src/backend/utils/adt/partitionfuncs.c
+++ b/src/backend/utils/adt/partitionfuncs.c
@@ -25,6 +25,33 @@
#include "utils/lsyscache.h"
#include "utils/syscache.h"
+/*
+ * Checks if a given relation can be part of a partition tree. Returns
+ * false if the relation cannot be processed, in which case it is up to
+ * the caller to decide what to do, by either raising an error or doing
+ * something else.
+ */
+static bool
+check_rel_can_be_partition(Oid relid)
+{
+ char relkind;
+
+ /* Check if relation exists */
+ if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relid)))
+ return false;
+
+ relkind = get_rel_relkind(relid);
+
+ /* Only allow relation types that can appear in partition trees. */
+ if (relkind != RELKIND_RELATION &&
+ relkind != RELKIND_FOREIGN_TABLE &&
+ relkind != RELKIND_INDEX &&
+ relkind != RELKIND_PARTITIONED_TABLE &&
+ relkind != RELKIND_PARTITIONED_INDEX)
+ return false;
+
+ return true;
+}
/*
* pg_partition_tree
@@ -39,19 +66,10 @@ pg_partition_tree(PG_FUNCTION_ARGS)
{
#define PG_PARTITION_TREE_COLS 4
Oid rootrelid = PG_GETARG_OID(0);
- char relkind = get_rel_relkind(rootrelid);
FuncCallContext *funcctx;
ListCell **next;
- if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(rootrelid)))
- PG_RETURN_NULL();
-
- /* Return NULL for relation types that cannot appear in partition trees */
- if (relkind != RELKIND_RELATION &&
- relkind != RELKIND_FOREIGN_TABLE &&
- relkind != RELKIND_INDEX &&
- relkind != RELKIND_PARTITIONED_TABLE &&
- relkind != RELKIND_PARTITIONED_INDEX)
+ if (!check_rel_can_be_partition(rootrelid))
PG_RETURN_NULL();
/* stuff done only on the first call of the function */
@@ -153,3 +171,40 @@ pg_partition_tree(PG_FUNCTION_ARGS)
/* done when there are no more elements left */
SRF_RETURN_DONE(funcctx);
}
+
+/*
+ * pg_partition_root
+ *
+ * Returns the top-most parent of the partition tree to which a given
+ * relation belongs, or NULL if it's not (or cannot be) part of any
+ * partition tree.
+ */
+Datum
+pg_partition_root(PG_FUNCTION_ARGS)
+{
+ Oid relid = PG_GETARG_OID(0);
+ Oid rootrelid;
+ List *ancestors;
+
+ if (!check_rel_can_be_partition(relid))
+ PG_RETURN_NULL();
+
+ /*
+ * If the relation is not a partition (it may be the partition parent),
+ * return itself as a result.
+ */
+ if (!get_rel_relispartition(relid))
+ PG_RETURN_OID(relid);
+
+ /* Fetch the top-most parent */
+ ancestors = get_partition_ancestors(relid);
+ rootrelid = llast_oid(ancestors);
+ list_free(ancestors);
+
+ /*
+ * "rootrelid" must contain a valid OID, given that the input relation is
+ * a valid partition tree member as checked above.
+ */
+ Assert(OidIsValid(rootrelid));
+ PG_RETURN_OID(rootrelid);
+}