diff options
author | Michael Paquier <michael@paquier.xyz> | 2019-02-08 08:56:14 +0900 |
---|---|---|
committer | Michael Paquier <michael@paquier.xyz> | 2019-02-08 08:56:14 +0900 |
commit | 3677a0b26bb2f3f72d16dc7fa6f34c305badacce (patch) | |
tree | a46ee2b807265d8f0c899c53f1bad3bebec67b34 /src/backend/utils/adt/partitionfuncs.c | |
parent | 34ea1ab7fd305afe1124a6e73ada0ebae04b6ebb (diff) | |
download | postgresql-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.c | 75 |
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); +} |