PostgreSQL Source Code  git master
partitionfuncs.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "catalog/partition.h"
#include "catalog/pg_class.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "utils/fmgrprotos.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
Include dependency graph for partitionfuncs.c:

Go to the source code of this file.

Macros

#define PG_PARTITION_TREE_COLS   4
 

Functions

static bool check_rel_can_be_partition (Oid relid)
 
Datum pg_partition_tree (PG_FUNCTION_ARGS)
 
Datum pg_partition_root (PG_FUNCTION_ARGS)
 
Datum pg_partition_ancestors (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ PG_PARTITION_TREE_COLS

#define PG_PARTITION_TREE_COLS   4

Referenced by pg_partition_tree().

Function Documentation

◆ check_rel_can_be_partition()

static bool check_rel_can_be_partition ( Oid  relid)
static

Definition at line 35 of file partitionfuncs.c.

References get_rel_relispartition(), get_rel_relkind(), ObjectIdGetDatum, relispartition, relkind, RELOID, and SearchSysCacheExists1.

Referenced by pg_partition_ancestors(), pg_partition_root(), and pg_partition_tree().

36 {
37  char relkind;
38  bool relispartition;
39 
40  /* Check if relation exists */
42  return false;
43 
44  relkind = get_rel_relkind(relid);
45  relispartition = get_rel_relispartition(relid);
46 
47  /* Only allow relation types that can appear in partition trees. */
48  if (!relispartition &&
49  relkind != RELKIND_PARTITIONED_TABLE &&
50  relkind != RELKIND_PARTITIONED_INDEX)
51  return false;
52 
53  return true;
54 }
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1805
char relkind
Definition: pg_class.h:81
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:183
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
bool relispartition
Definition: pg_class.h:117
bool get_rel_relispartition(Oid relid)
Definition: lsyscache.c:1829

◆ pg_partition_ancestors()

Datum pg_partition_ancestors ( PG_FUNCTION_ARGS  )

Definition at line 215 of file partitionfuncs.c.

References FuncCallContext::call_cntr, check_rel_can_be_partition(), get_partition_ancestors(), lcons_oid(), list_length(), list_nth_oid(), MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, ObjectIdGetDatum, PG_GETARG_OID, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, and FuncCallContext::user_fctx.

216 {
217  Oid relid = PG_GETARG_OID(0);
218  FuncCallContext *funcctx;
219  List *ancestors;
220 
221  if (SRF_IS_FIRSTCALL())
222  {
223  MemoryContext oldcxt;
224 
225  funcctx = SRF_FIRSTCALL_INIT();
226 
227  if (!check_rel_can_be_partition(relid))
228  SRF_RETURN_DONE(funcctx);
229 
230  oldcxt = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
231 
232  ancestors = get_partition_ancestors(relid);
233  ancestors = lcons_oid(relid, ancestors);
234 
235  /* The only state we need is the ancestors list */
236  funcctx->user_fctx = (void *) ancestors;
237 
238  MemoryContextSwitchTo(oldcxt);
239  }
240 
241  funcctx = SRF_PERCALL_SETUP();
242  ancestors = (List *) funcctx->user_fctx;
243 
244  if (funcctx->call_cntr < list_length(ancestors))
245  {
246  Oid relid = list_nth_oid(ancestors, funcctx->call_cntr);
247 
248  SRF_RETURN_NEXT(funcctx, ObjectIdGetDatum(relid));
249  }
250 
251  SRF_RETURN_DONE(funcctx);
252 }
uint64 call_cntr
Definition: funcapi.h:66
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:283
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
List * lcons_oid(Oid datum, List *list)
Definition: list.c:490
unsigned int Oid
Definition: postgres_ext.h:31
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:287
static Oid list_nth_oid(const List *list, int n)
Definition: pg_list.h:299
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:289
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define PG_GETARG_OID(n)
Definition: fmgr.h:270
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:102
static int list_length(const List *l)
Definition: pg_list.h:169
static bool check_rel_can_be_partition(Oid relid)
void * user_fctx
Definition: funcapi.h:83
Definition: pg_list.h:50
List * get_partition_ancestors(Oid relid)
Definition: partition.c:116
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:307
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:285

◆ pg_partition_root()

Datum pg_partition_root ( PG_FUNCTION_ARGS  )

Definition at line 178 of file partitionfuncs.c.

References Assert, check_rel_can_be_partition(), get_partition_ancestors(), list_free(), llast_oid, NIL, OidIsValid, PG_GETARG_OID, PG_RETURN_NULL, and PG_RETURN_OID.

179 {
180  Oid relid = PG_GETARG_OID(0);
181  Oid rootrelid;
182  List *ancestors;
183 
184  if (!check_rel_can_be_partition(relid))
185  PG_RETURN_NULL();
186 
187  /* fetch the list of ancestors */
188  ancestors = get_partition_ancestors(relid);
189 
190  /*
191  * If the input relation is already the top-most parent, just return
192  * itself.
193  */
194  if (ancestors == NIL)
195  PG_RETURN_OID(relid);
196 
197  rootrelid = llast_oid(ancestors);
198  list_free(ancestors);
199 
200  /*
201  * "rootrelid" must contain a valid OID, given that the input relation is
202  * a valid partition tree member as checked above.
203  */
204  Assert(OidIsValid(rootrelid));
205  PG_RETURN_OID(rootrelid);
206 }
#define NIL
Definition: pg_list.h:65
#define llast_oid(l)
Definition: pg_list.h:217
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
#define PG_GETARG_OID(n)
Definition: fmgr.h:270
#define Assert(condition)
Definition: c.h:732
static bool check_rel_can_be_partition(Oid relid)
void list_free(List *list)
Definition: list.c:1377
Definition: pg_list.h:50
#define PG_RETURN_OID(x)
Definition: fmgr.h:350
List * get_partition_ancestors(Oid relid)
Definition: partition.c:116
#define PG_RETURN_NULL()
Definition: fmgr.h:335

◆ pg_partition_tree()

Datum pg_partition_tree ( PG_FUNCTION_ARGS  )

Definition at line 65 of file partitionfuncs.c.

References AccessShareLock, BlessTupleDesc(), BoolGetDatum, FuncCallContext::call_cntr, check_rel_can_be_partition(), CreateTemplateTupleDesc(), find_all_inheritors(), get_partition_ancestors(), get_rel_relkind(), heap_form_tuple(), HeapTupleGetDatum, Int32GetDatum, InvalidOid, lfirst_oid, linitial_oid, list_length(), list_nth_oid(), MemoryContextSwitchTo(), MemSet, FuncCallContext::multi_call_memory_ctx, NIL, ObjectIdGetDatum, OidIsValid, partitions, PG_GETARG_OID, PG_PARTITION_TREE_COLS, relkind, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, FuncCallContext::tuple_desc, TupleDescInitEntry(), FuncCallContext::user_fctx, and values.

66 {
67 #define PG_PARTITION_TREE_COLS 4
68  Oid rootrelid = PG_GETARG_OID(0);
69  FuncCallContext *funcctx;
71 
72  /* stuff done only on the first call of the function */
73  if (SRF_IS_FIRSTCALL())
74  {
75  MemoryContext oldcxt;
76  TupleDesc tupdesc;
77 
78  /* create a function context for cross-call persistence */
79  funcctx = SRF_FIRSTCALL_INIT();
80 
81  if (!check_rel_can_be_partition(rootrelid))
82  SRF_RETURN_DONE(funcctx);
83 
84  /* switch to memory context appropriate for multiple function calls */
86 
87  /*
88  * Find all members of inheritance set. We only need AccessShareLock
89  * on the children for the partition information lookup.
90  */
91  partitions = find_all_inheritors(rootrelid, AccessShareLock, NULL);
92 
94  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "relid",
95  REGCLASSOID, -1, 0);
96  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "parentid",
97  REGCLASSOID, -1, 0);
98  TupleDescInitEntry(tupdesc, (AttrNumber) 3, "isleaf",
99  BOOLOID, -1, 0);
100  TupleDescInitEntry(tupdesc, (AttrNumber) 4, "level",
101  INT4OID, -1, 0);
102 
103  funcctx->tuple_desc = BlessTupleDesc(tupdesc);
104 
105  /* The only state we need is the partition list */
106  funcctx->user_fctx = (void *) partitions;
107 
108  MemoryContextSwitchTo(oldcxt);
109  }
110 
111  /* stuff done on every call of the function */
112  funcctx = SRF_PERCALL_SETUP();
113  partitions = (List *) funcctx->user_fctx;
114 
115  if (funcctx->call_cntr < list_length(partitions))
116  {
117  Datum result;
119  bool nulls[PG_PARTITION_TREE_COLS];
120  HeapTuple tuple;
121  Oid parentid = InvalidOid;
122  Oid relid = list_nth_oid(partitions, funcctx->call_cntr);
123  char relkind = get_rel_relkind(relid);
124  int level = 0;
125  List *ancestors = get_partition_ancestors(relid);
126  ListCell *lc;
127 
128  /*
129  * Form tuple with appropriate data.
130  */
131  MemSet(nulls, 0, sizeof(nulls));
132  MemSet(values, 0, sizeof(values));
133 
134  /* relid */
135  values[0] = ObjectIdGetDatum(relid);
136 
137  /* parentid */
138  if (ancestors != NIL)
139  parentid = linitial_oid(ancestors);
140  if (OidIsValid(parentid))
141  values[1] = ObjectIdGetDatum(parentid);
142  else
143  nulls[1] = true;
144 
145  /* isleaf */
146  values[2] = BoolGetDatum(relkind != RELKIND_PARTITIONED_TABLE &&
147  relkind != RELKIND_PARTITIONED_INDEX);
148 
149  /* level */
150  if (relid != rootrelid)
151  {
152  foreach(lc, ancestors)
153  {
154  level++;
155  if (lfirst_oid(lc) == rootrelid)
156  break;
157  }
158  }
159  values[3] = Int32GetDatum(level);
160 
161  tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
162  result = HeapTupleGetDatum(tuple);
163  SRF_RETURN_NEXT(funcctx, result);
164  }
165 
166  /* done when there are no more elements left */
167  SRF_RETURN_DONE(funcctx);
168 }
uint64 call_cntr
Definition: funcapi.h:66
#define NIL
Definition: pg_list.h:65
static int partitions
Definition: pgbench.c:193
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:283
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1805
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
#define MemSet(start, val, len)
Definition: c.h:955
#define PG_PARTITION_TREE_COLS
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:287
char relkind
Definition: pg_class.h:81
TupleDesc tuple_desc
Definition: funcapi.h:113
static Oid list_nth_oid(const List *list, int n)
Definition: pg_list.h:299
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:289
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2048
#define PG_GETARG_OID(n)
Definition: fmgr.h:270
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:603
uintptr_t Datum
Definition: postgres.h:367
#define BoolGetDatum(X)
Definition: postgres.h:402
#define InvalidOid
Definition: postgres_ext.h:36
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:102
#define linitial_oid(l)
Definition: pg_list.h:197
static int list_length(const List *l)
Definition: pg_list.h:169
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:221
static bool check_rel_can_be_partition(Oid relid)
static Datum values[MAXATTR]
Definition: bootstrap.c:167
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
Definition: pg_inherits.c:165
#define Int32GetDatum(X)
Definition: postgres.h:479
void * user_fctx
Definition: funcapi.h:83
Definition: pg_list.h:50
List * get_partition_ancestors(Oid relid)
Definition: partition.c:116
int16 AttrNumber
Definition: attnum.h:21
#define lfirst_oid(lc)
Definition: pg_list.h:192
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:307
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:285