mirror of
https://github.com/postgres/postgres.git
synced 2025-11-19 13:42:17 +03:00
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
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user