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

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.

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 && !RELKIND_HAS_PARTITIONS(relkind))
49  return false;
50 
51  return true;
52 }
bool get_rel_relispartition(Oid relid)
Definition: lsyscache.c:2009
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1985
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:600
@ RELOID
Definition: syscache.h:89
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:188

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

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

◆ pg_partition_ancestors()

Datum pg_partition_ancestors ( PG_FUNCTION_ARGS  )

Definition at line 210 of file partitionfuncs.c.

211 {
212  Oid relid = PG_GETARG_OID(0);
213  FuncCallContext *funcctx;
214  List *ancestors;
215 
216  if (SRF_IS_FIRSTCALL())
217  {
218  MemoryContext oldcxt;
219 
220  funcctx = SRF_FIRSTCALL_INIT();
221 
222  if (!check_rel_can_be_partition(relid))
223  SRF_RETURN_DONE(funcctx);
224 
225  oldcxt = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
226 
227  ancestors = get_partition_ancestors(relid);
228  ancestors = lcons_oid(relid, ancestors);
229 
230  /* The only state we need is the ancestors list */
231  funcctx->user_fctx = (void *) ancestors;
232 
233  MemoryContextSwitchTo(oldcxt);
234  }
235 
236  funcctx = SRF_PERCALL_SETUP();
237  ancestors = (List *) funcctx->user_fctx;
238 
239  if (funcctx->call_cntr < list_length(ancestors))
240  {
241  Oid resultrel = list_nth_oid(ancestors, funcctx->call_cntr);
242 
243  SRF_RETURN_NEXT(funcctx, ObjectIdGetDatum(resultrel));
244  }
245 
246  SRF_RETURN_DONE(funcctx);
247 }
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:303
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:307
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:309
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:305
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:327
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
List * lcons_oid(Oid datum, List *list)
Definition: list.c:530
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:135
List * get_partition_ancestors(Oid relid)
Definition: partition.c:133
static bool check_rel_can_be_partition(Oid relid)
static int list_length(const List *l)
Definition: pg_list.h:150
static Oid list_nth_oid(const List *list, int n)
Definition: pg_list.h:319
unsigned int Oid
Definition: postgres_ext.h:31
void * user_fctx
Definition: funcapi.h:82
uint64 call_cntr
Definition: funcapi.h:65
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
Definition: pg_list.h:52

References FuncCallContext::call_cntr, check_rel_can_be_partition(), get_partition_ancestors(), if(), 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.

◆ pg_partition_root()

Datum pg_partition_root ( PG_FUNCTION_ARGS  )

Definition at line 173 of file partitionfuncs.c.

174 {
175  Oid relid = PG_GETARG_OID(0);
176  Oid rootrelid;
177  List *ancestors;
178 
179  if (!check_rel_can_be_partition(relid))
180  PG_RETURN_NULL();
181 
182  /* fetch the list of ancestors */
183  ancestors = get_partition_ancestors(relid);
184 
185  /*
186  * If the input relation is already the top-most parent, just return
187  * itself.
188  */
189  if (ancestors == NIL)
190  PG_RETURN_OID(relid);
191 
192  rootrelid = llast_oid(ancestors);
193  list_free(ancestors);
194 
195  /*
196  * "rootrelid" must contain a valid OID, given that the input relation is
197  * a valid partition tree member as checked above.
198  */
199  Assert(OidIsValid(rootrelid));
200  PG_RETURN_OID(rootrelid);
201 }
#define OidIsValid(objectId)
Definition: c.h:711
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_RETURN_OID(x)
Definition: fmgr.h:360
Assert(fmt[strlen(fmt) - 1] !='\n')
void list_free(List *list)
Definition: list.c:1545
#define NIL
Definition: pg_list.h:66
#define llast_oid(l)
Definition: pg_list.h:198

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.

◆ pg_partition_tree()

Datum pg_partition_tree ( PG_FUNCTION_ARGS  )

Definition at line 63 of file partitionfuncs.c.

64 {
65 #define PG_PARTITION_TREE_COLS 4
66  Oid rootrelid = PG_GETARG_OID(0);
67  FuncCallContext *funcctx;
69 
70  /* stuff done only on the first call of the function */
71  if (SRF_IS_FIRSTCALL())
72  {
73  MemoryContext oldcxt;
74  TupleDesc tupdesc;
75 
76  /* create a function context for cross-call persistence */
77  funcctx = SRF_FIRSTCALL_INIT();
78 
79  if (!check_rel_can_be_partition(rootrelid))
80  SRF_RETURN_DONE(funcctx);
81 
82  /* switch to memory context appropriate for multiple function calls */
84 
85  /*
86  * Find all members of inheritance set. We only need AccessShareLock
87  * on the children for the partition information lookup.
88  */
90 
92  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "relid",
93  REGCLASSOID, -1, 0);
94  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "parentid",
95  REGCLASSOID, -1, 0);
96  TupleDescInitEntry(tupdesc, (AttrNumber) 3, "isleaf",
97  BOOLOID, -1, 0);
98  TupleDescInitEntry(tupdesc, (AttrNumber) 4, "level",
99  INT4OID, -1, 0);
100 
101  funcctx->tuple_desc = BlessTupleDesc(tupdesc);
102 
103  /* The only state we need is the partition list */
104  funcctx->user_fctx = (void *) partitions;
105 
106  MemoryContextSwitchTo(oldcxt);
107  }
108 
109  /* stuff done on every call of the function */
110  funcctx = SRF_PERCALL_SETUP();
111  partitions = (List *) funcctx->user_fctx;
112 
113  if (funcctx->call_cntr < list_length(partitions))
114  {
115  Datum result;
117  bool nulls[PG_PARTITION_TREE_COLS] = {0};
118  HeapTuple tuple;
119  Oid parentid = InvalidOid;
120  Oid relid = list_nth_oid(partitions, funcctx->call_cntr);
121  char relkind = get_rel_relkind(relid);
122  int level = 0;
123  List *ancestors = get_partition_ancestors(relid);
124  ListCell *lc;
125 
126  /*
127  * Form tuple with appropriate data.
128  */
129 
130  /* relid */
131  values[0] = ObjectIdGetDatum(relid);
132 
133  /* parentid */
134  if (ancestors != NIL)
135  parentid = linitial_oid(ancestors);
136  if (OidIsValid(parentid))
137  values[1] = ObjectIdGetDatum(parentid);
138  else
139  nulls[1] = true;
140 
141  /* isleaf */
142  values[2] = BoolGetDatum(!RELKIND_HAS_PARTITIONS(relkind));
143 
144  /* level */
145  if (relid != rootrelid)
146  {
147  foreach(lc, ancestors)
148  {
149  level++;
150  if (lfirst_oid(lc) == rootrelid)
151  break;
152  }
153  }
154  values[3] = Int32GetDatum(level);
155 
156  tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
157  result = HeapTupleGetDatum(tuple);
158  SRF_RETURN_NEXT(funcctx, result);
159  }
160 
161  /* done when there are no more elements left */
162  SRF_RETURN_DONE(funcctx);
163 }
int16 AttrNumber
Definition: attnum.h:21
static Datum values[MAXATTR]
Definition: bootstrap.c:156
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2071
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition: funcapi.h:230
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#define AccessShareLock
Definition: lockdefs.h:36
#define PG_PARTITION_TREE_COLS
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
Definition: pg_inherits.c:256
#define linitial_oid(l)
Definition: pg_list.h:178
#define lfirst_oid(lc)
Definition: pg_list.h:172
static int partitions
Definition: pgbench.c:232
uintptr_t Datum
Definition: postgres.h:412
static Datum BoolGetDatum(bool X)
Definition: postgres.h:450
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:560
#define InvalidOid
Definition: postgres_ext.h:36
TupleDesc tuple_desc
Definition: funcapi.h:112
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:45
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:583

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(), if(), Int32GetDatum(), InvalidOid, lfirst_oid, linitial_oid, list_length(), list_nth_oid(), MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, NIL, ObjectIdGetDatum(), OidIsValid, partitions, PG_GETARG_OID, PG_PARTITION_TREE_COLS, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, FuncCallContext::tuple_desc, TupleDescInitEntry(), FuncCallContext::user_fctx, and values.