Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * rel.h
4 : * POSTGRES relation descriptor (a/k/a relcache entry) definitions.
5 : *
6 : *
7 : * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
8 : * Portions Copyright (c) 1994, Regents of the University of California
9 : *
10 : * src/include/utils/rel.h
11 : *
12 : *-------------------------------------------------------------------------
13 : */
14 : #ifndef REL_H
15 : #define REL_H
16 :
17 : #include "access/tupdesc.h"
18 : #include "access/xlog.h"
19 : #include "catalog/pg_class.h"
20 : #include "catalog/pg_index.h"
21 : #include "catalog/pg_publication.h"
22 : #include "fmgr.h"
23 : #include "nodes/bitmapset.h"
24 : #include "rewrite/prs2lock.h"
25 : #include "storage/block.h"
26 : #include "storage/relfilenode.h"
27 : #include "utils/relcache.h"
28 : #include "utils/reltrigger.h"
29 :
30 :
31 : /*
32 : * LockRelId and LockInfo really belong to lmgr.h, but it's more convenient
33 : * to declare them here so we can have a LockInfoData field in a Relation.
34 : */
35 :
36 : typedef struct LockRelId
37 : {
38 : Oid relId; /* a relation identifier */
39 : Oid dbId; /* a database identifier */
40 : } LockRelId;
41 :
42 : typedef struct LockInfoData
43 : {
44 : LockRelId lockRelId;
45 : } LockInfoData;
46 :
47 : typedef LockInfoData *LockInfo;
48 :
49 : /*
50 : * Information about the partition key of a relation
51 : */
52 : typedef struct PartitionKeyData
53 : {
54 : char strategy; /* partitioning strategy */
55 : int16 partnatts; /* number of columns in the partition key */
56 : AttrNumber *partattrs; /* attribute numbers of columns in the
57 : * partition key */
58 : List *partexprs; /* list of expressions in the partitioning
59 : * key, or NIL */
60 :
61 : Oid *partopfamily; /* OIDs of operator families */
62 : Oid *partopcintype; /* OIDs of opclass declared input data types */
63 : FmgrInfo *partsupfunc; /* lookup info for support funcs */
64 :
65 : /* Partitioning collation per attribute */
66 : Oid *partcollation;
67 :
68 : /* Type information per attribute */
69 : Oid *parttypid;
70 : int32 *parttypmod;
71 : int16 *parttyplen;
72 : bool *parttypbyval;
73 : char *parttypalign;
74 : Oid *parttypcoll;
75 : } PartitionKeyData;
76 :
77 : typedef struct PartitionKeyData *PartitionKey;
78 :
79 : /*
80 : * Here are the contents of a relation cache entry.
81 : */
82 :
83 : typedef struct RelationData
84 : {
85 : RelFileNode rd_node; /* relation physical identifier */
86 : /* use "struct" here to avoid needing to include smgr.h: */
87 : struct SMgrRelationData *rd_smgr; /* cached file handle, or NULL */
88 : int rd_refcnt; /* reference count */
89 : BackendId rd_backend; /* owning backend id, if temporary relation */
90 : bool rd_islocaltemp; /* rel is a temp rel of this session */
91 : bool rd_isnailed; /* rel is nailed in cache */
92 : bool rd_isvalid; /* relcache entry is valid */
93 : char rd_indexvalid; /* state of rd_indexlist: 0 = not valid, 1 =
94 : * valid, 2 = temporarily forced */
95 : bool rd_statvalid; /* is rd_statlist valid? */
96 :
97 : /*
98 : * rd_createSubid is the ID of the highest subtransaction the rel has
99 : * survived into; or zero if the rel was not created in the current top
100 : * transaction. This can be now be relied on, whereas previously it could
101 : * be "forgotten" in earlier releases. Likewise, rd_newRelfilenodeSubid is
102 : * the ID of the highest subtransaction the relfilenode change has
103 : * survived into, or zero if not changed in the current transaction (or we
104 : * have forgotten changing it). rd_newRelfilenodeSubid can be forgotten
105 : * when a relation has multiple new relfilenodes within a single
106 : * transaction, with one of them occurring in a subsequently aborted
107 : * subtransaction, e.g. BEGIN; TRUNCATE t; SAVEPOINT save; TRUNCATE t;
108 : * ROLLBACK TO save; -- rd_newRelfilenode is now forgotten
109 : */
110 : SubTransactionId rd_createSubid; /* rel was created in current xact */
111 : SubTransactionId rd_newRelfilenodeSubid; /* new relfilenode assigned in
112 : * current xact */
113 :
114 : Form_pg_class rd_rel; /* RELATION tuple */
115 : TupleDesc rd_att; /* tuple descriptor */
116 : Oid rd_id; /* relation's object id */
117 : LockInfoData rd_lockInfo; /* lock mgr's info for locking relation */
118 : RuleLock *rd_rules; /* rewrite rules */
119 : MemoryContext rd_rulescxt; /* private memory cxt for rd_rules, if any */
120 : TriggerDesc *trigdesc; /* Trigger info, or NULL if rel has none */
121 : /* use "struct" here to avoid needing to include rowsecurity.h: */
122 : struct RowSecurityDesc *rd_rsdesc; /* row security policies, or NULL */
123 :
124 : /* data managed by RelationGetFKeyList: */
125 : List *rd_fkeylist; /* list of ForeignKeyCacheInfo (see below) */
126 : bool rd_fkeyvalid; /* true if list has been computed */
127 :
128 : MemoryContext rd_partkeycxt; /* private memory cxt for the below */
129 : struct PartitionKeyData *rd_partkey; /* partition key, or NULL */
130 : MemoryContext rd_pdcxt; /* private context for partdesc */
131 : struct PartitionDescData *rd_partdesc; /* partitions, or NULL */
132 : List *rd_partcheck; /* partition CHECK quals */
133 :
134 : /* data managed by RelationGetIndexList: */
135 : List *rd_indexlist; /* list of OIDs of indexes on relation */
136 : Oid rd_oidindex; /* OID of unique index on OID, if any */
137 : Oid rd_pkindex; /* OID of primary key, if any */
138 : Oid rd_replidindex; /* OID of replica identity index, if any */
139 :
140 : /* data managed by RelationGetStatExtList: */
141 : List *rd_statlist; /* list of OIDs of extended stats */
142 :
143 : /* data managed by RelationGetIndexAttrBitmap: */
144 : Bitmapset *rd_indexattr; /* identifies columns used in indexes */
145 : Bitmapset *rd_keyattr; /* cols that can be ref'd by foreign keys */
146 : Bitmapset *rd_pkattr; /* cols included in primary key */
147 : Bitmapset *rd_idattr; /* included in replica identity index */
148 :
149 : PublicationActions *rd_pubactions; /* publication actions */
150 :
151 : /*
152 : * rd_options is set whenever rd_rel is loaded into the relcache entry.
153 : * Note that you can NOT look into rd_rel for this data. NULL means "use
154 : * defaults".
155 : */
156 : bytea *rd_options; /* parsed pg_class.reloptions */
157 :
158 : /* These are non-NULL only for an index relation: */
159 : Form_pg_index rd_index; /* pg_index tuple describing this index */
160 : /* use "struct" here to avoid needing to include htup.h: */
161 : struct HeapTupleData *rd_indextuple; /* all of pg_index tuple */
162 :
163 : /*
164 : * index access support info (used only for an index relation)
165 : *
166 : * Note: only default support procs for each opclass are cached, namely
167 : * those with lefttype and righttype equal to the opclass's opcintype. The
168 : * arrays are indexed by support function number, which is a sufficient
169 : * identifier given that restriction.
170 : *
171 : * Note: rd_amcache is available for index AMs to cache private data about
172 : * an index. This must be just a cache since it may get reset at any time
173 : * (in particular, it will get reset by a relcache inval message for the
174 : * index). If used, it must point to a single memory chunk palloc'd in
175 : * rd_indexcxt. A relcache reset will include freeing that chunk and
176 : * setting rd_amcache = NULL.
177 : */
178 : Oid rd_amhandler; /* OID of index AM's handler function */
179 : MemoryContext rd_indexcxt; /* private memory cxt for this stuff */
180 : /* use "struct" here to avoid needing to include amapi.h: */
181 : struct IndexAmRoutine *rd_amroutine; /* index AM's API struct */
182 : Oid *rd_opfamily; /* OIDs of op families for each index col */
183 : Oid *rd_opcintype; /* OIDs of opclass declared input data types */
184 : RegProcedure *rd_support; /* OIDs of support procedures */
185 : FmgrInfo *rd_supportinfo; /* lookup info for support procedures */
186 : int16 *rd_indoption; /* per-column AM-specific flags */
187 : List *rd_indexprs; /* index expression trees, if any */
188 : List *rd_indpred; /* index predicate tree, if any */
189 : Oid *rd_exclops; /* OIDs of exclusion operators, if any */
190 : Oid *rd_exclprocs; /* OIDs of exclusion ops' procs, if any */
191 : uint16 *rd_exclstrats; /* exclusion ops' strategy numbers, if any */
192 : void *rd_amcache; /* available for use by index AM */
193 : Oid *rd_indcollation; /* OIDs of index collations */
194 :
195 : /*
196 : * foreign-table support
197 : *
198 : * rd_fdwroutine must point to a single memory chunk palloc'd in
199 : * CacheMemoryContext. It will be freed and reset to NULL on a relcache
200 : * reset.
201 : */
202 :
203 : /* use "struct" here to avoid needing to include fdwapi.h: */
204 : struct FdwRoutine *rd_fdwroutine; /* cached function pointers, or NULL */
205 :
206 : /*
207 : * Hack for CLUSTER, rewriting ALTER TABLE, etc: when writing a new
208 : * version of a table, we need to make any toast pointers inserted into it
209 : * have the existing toast table's OID, not the OID of the transient toast
210 : * table. If rd_toastoid isn't InvalidOid, it is the OID to place in
211 : * toast pointers inserted into this rel. (Note it's set on the new
212 : * version of the main heap, not the toast table itself.) This also
213 : * causes toast_save_datum() to try to preserve toast value OIDs.
214 : */
215 : Oid rd_toastoid; /* Real TOAST table's OID, or InvalidOid */
216 :
217 : /* use "struct" here to avoid needing to include pgstat.h: */
218 : struct PgStat_TableStatus *pgstat_info; /* statistics collection area */
219 : } RelationData;
220 :
221 :
222 : /*
223 : * ForeignKeyCacheInfo
224 : * Information the relcache can cache about foreign key constraints
225 : *
226 : * This is basically just an image of relevant columns from pg_constraint.
227 : * We make it a subclass of Node so that copyObject() can be used on a list
228 : * of these, but we also ensure it is a "flat" object without substructure,
229 : * so that list_free_deep() is sufficient to free such a list.
230 : * The per-FK-column arrays can be fixed-size because we allow at most
231 : * INDEX_MAX_KEYS columns in a foreign key constraint.
232 : *
233 : * Currently, we only cache fields of interest to the planner, but the
234 : * set of fields could be expanded in future.
235 : */
236 : typedef struct ForeignKeyCacheInfo
237 : {
238 : NodeTag type;
239 : Oid conrelid; /* relation constrained by the foreign key */
240 : Oid confrelid; /* relation referenced by the foreign key */
241 : int nkeys; /* number of columns in the foreign key */
242 : /* these arrays each have nkeys valid entries: */
243 : AttrNumber conkey[INDEX_MAX_KEYS]; /* cols in referencing table */
244 : AttrNumber confkey[INDEX_MAX_KEYS]; /* cols in referenced table */
245 : Oid conpfeqop[INDEX_MAX_KEYS]; /* PK = FK operator OIDs */
246 : } ForeignKeyCacheInfo;
247 :
248 :
249 : /*
250 : * StdRdOptions
251 : * Standard contents of rd_options for heaps and generic indexes.
252 : *
253 : * RelationGetFillFactor() and RelationGetTargetPageFreeSpace() can only
254 : * be applied to relations that use this format or a superset for
255 : * private options data.
256 : */
257 : /* autovacuum-related reloptions. */
258 : typedef struct AutoVacOpts
259 : {
260 : bool enabled;
261 : int vacuum_threshold;
262 : int analyze_threshold;
263 : int vacuum_cost_delay;
264 : int vacuum_cost_limit;
265 : int freeze_min_age;
266 : int freeze_max_age;
267 : int freeze_table_age;
268 : int multixact_freeze_min_age;
269 : int multixact_freeze_max_age;
270 : int multixact_freeze_table_age;
271 : int log_min_duration;
272 : float8 vacuum_scale_factor;
273 : float8 analyze_scale_factor;
274 : } AutoVacOpts;
275 :
276 : typedef struct StdRdOptions
277 : {
278 : int32 vl_len_; /* varlena header (do not touch directly!) */
279 : int fillfactor; /* page fill factor in percent (0..100) */
280 : AutoVacOpts autovacuum; /* autovacuum-related options */
281 : bool user_catalog_table; /* use as an additional catalog relation */
282 : int parallel_workers; /* max number of parallel workers */
283 : } StdRdOptions;
284 :
285 : #define HEAP_MIN_FILLFACTOR 10
286 : #define HEAP_DEFAULT_FILLFACTOR 100
287 :
288 : /*
289 : * RelationGetFillFactor
290 : * Returns the relation's fillfactor. Note multiple eval of argument!
291 : */
292 : #define RelationGetFillFactor(relation, defaultff) \
293 : ((relation)->rd_options ? \
294 : ((StdRdOptions *) (relation)->rd_options)->fillfactor : (defaultff))
295 :
296 : /*
297 : * RelationGetTargetPageUsage
298 : * Returns the relation's desired space usage per page in bytes.
299 : */
300 : #define RelationGetTargetPageUsage(relation, defaultff) \
301 : (BLCKSZ * RelationGetFillFactor(relation, defaultff) / 100)
302 :
303 : /*
304 : * RelationGetTargetPageFreeSpace
305 : * Returns the relation's desired freespace per page in bytes.
306 : */
307 : #define RelationGetTargetPageFreeSpace(relation, defaultff) \
308 : (BLCKSZ * (100 - RelationGetFillFactor(relation, defaultff)) / 100)
309 :
310 : /*
311 : * RelationIsUsedAsCatalogTable
312 : * Returns whether the relation should be treated as a catalog table
313 : * from the pov of logical decoding. Note multiple eval of argument!
314 : */
315 : #define RelationIsUsedAsCatalogTable(relation) \
316 : ((relation)->rd_options && \
317 : ((relation)->rd_rel->relkind == RELKIND_RELATION || \
318 : (relation)->rd_rel->relkind == RELKIND_MATVIEW) ? \
319 : ((StdRdOptions *) (relation)->rd_options)->user_catalog_table : false)
320 :
321 : /*
322 : * RelationGetParallelWorkers
323 : * Returns the relation's parallel_workers reloption setting.
324 : * Note multiple eval of argument!
325 : */
326 : #define RelationGetParallelWorkers(relation, defaultpw) \
327 : ((relation)->rd_options ? \
328 : ((StdRdOptions *) (relation)->rd_options)->parallel_workers : (defaultpw))
329 :
330 :
331 : /*
332 : * ViewOptions
333 : * Contents of rd_options for views
334 : */
335 : typedef struct ViewOptions
336 : {
337 : int32 vl_len_; /* varlena header (do not touch directly!) */
338 : bool security_barrier;
339 : int check_option_offset;
340 : } ViewOptions;
341 :
342 : /*
343 : * RelationIsSecurityView
344 : * Returns whether the relation is security view, or not. Note multiple
345 : * eval of argument!
346 : */
347 : #define RelationIsSecurityView(relation) \
348 : ((relation)->rd_options ? \
349 : ((ViewOptions *) (relation)->rd_options)->security_barrier : false)
350 :
351 : /*
352 : * RelationHasCheckOption
353 : * Returns true if the relation is a view defined with either the local
354 : * or the cascaded check option. Note multiple eval of argument!
355 : */
356 : #define RelationHasCheckOption(relation) \
357 : ((relation)->rd_options && \
358 : ((ViewOptions *) (relation)->rd_options)->check_option_offset != 0)
359 :
360 : /*
361 : * RelationHasLocalCheckOption
362 : * Returns true if the relation is a view defined with the local check
363 : * option. Note multiple eval of argument!
364 : */
365 : #define RelationHasLocalCheckOption(relation) \
366 : ((relation)->rd_options && \
367 : ((ViewOptions *) (relation)->rd_options)->check_option_offset != 0 ? \
368 : strcmp((char *) (relation)->rd_options + \
369 : ((ViewOptions *) (relation)->rd_options)->check_option_offset, \
370 : "local") == 0 : false)
371 :
372 : /*
373 : * RelationHasCascadedCheckOption
374 : * Returns true if the relation is a view defined with the cascaded check
375 : * option. Note multiple eval of argument!
376 : */
377 : #define RelationHasCascadedCheckOption(relation) \
378 : ((relation)->rd_options && \
379 : ((ViewOptions *) (relation)->rd_options)->check_option_offset != 0 ? \
380 : strcmp((char *) (relation)->rd_options + \
381 : ((ViewOptions *) (relation)->rd_options)->check_option_offset, \
382 : "cascaded") == 0 : false)
383 :
384 :
385 : /*
386 : * RelationIsValid
387 : * True iff relation descriptor is valid.
388 : */
389 : #define RelationIsValid(relation) PointerIsValid(relation)
390 :
391 : #define InvalidRelation ((Relation) NULL)
392 :
393 : /*
394 : * RelationHasReferenceCountZero
395 : * True iff relation reference count is zero.
396 : *
397 : * Note:
398 : * Assumes relation descriptor is valid.
399 : */
400 : #define RelationHasReferenceCountZero(relation) \
401 : ((bool)((relation)->rd_refcnt == 0))
402 :
403 : /*
404 : * RelationGetForm
405 : * Returns pg_class tuple for a relation.
406 : *
407 : * Note:
408 : * Assumes relation descriptor is valid.
409 : */
410 : #define RelationGetForm(relation) ((relation)->rd_rel)
411 :
412 : /*
413 : * RelationGetRelid
414 : * Returns the OID of the relation
415 : */
416 : #define RelationGetRelid(relation) ((relation)->rd_id)
417 :
418 : /*
419 : * RelationGetNumberOfAttributes
420 : * Returns the number of attributes in a relation.
421 : */
422 : #define RelationGetNumberOfAttributes(relation) ((relation)->rd_rel->relnatts)
423 :
424 : /*
425 : * RelationGetDescr
426 : * Returns tuple descriptor for a relation.
427 : */
428 : #define RelationGetDescr(relation) ((relation)->rd_att)
429 :
430 : /*
431 : * RelationGetRelationName
432 : * Returns the rel's name.
433 : *
434 : * Note that the name is only unique within the containing namespace.
435 : */
436 : #define RelationGetRelationName(relation) \
437 : (NameStr((relation)->rd_rel->relname))
438 :
439 : /*
440 : * RelationGetNamespace
441 : * Returns the rel's namespace OID.
442 : */
443 : #define RelationGetNamespace(relation) \
444 : ((relation)->rd_rel->relnamespace)
445 :
446 : /*
447 : * RelationIsMapped
448 : * True if the relation uses the relfilenode map.
449 : *
450 : * NB: this is only meaningful for relkinds that have storage, else it
451 : * will misleadingly say "true".
452 : */
453 : #define RelationIsMapped(relation) \
454 : ((relation)->rd_rel->relfilenode == InvalidOid)
455 :
456 : /*
457 : * RelationOpenSmgr
458 : * Open the relation at the smgr level, if not already done.
459 : */
460 : #define RelationOpenSmgr(relation) \
461 : do { \
462 : if ((relation)->rd_smgr == NULL) \
463 : smgrsetowner(&((relation)->rd_smgr), smgropen((relation)->rd_node, (relation)->rd_backend)); \
464 : } while (0)
465 :
466 : /*
467 : * RelationCloseSmgr
468 : * Close the relation at the smgr level, if not already done.
469 : *
470 : * Note: smgrclose should unhook from owner pointer, hence the Assert.
471 : */
472 : #define RelationCloseSmgr(relation) \
473 : do { \
474 : if ((relation)->rd_smgr != NULL) \
475 : { \
476 : smgrclose((relation)->rd_smgr); \
477 : Assert((relation)->rd_smgr == NULL); \
478 : } \
479 : } while (0)
480 :
481 : /*
482 : * RelationGetTargetBlock
483 : * Fetch relation's current insertion target block.
484 : *
485 : * Returns InvalidBlockNumber if there is no current target block. Note
486 : * that the target block status is discarded on any smgr-level invalidation.
487 : */
488 : #define RelationGetTargetBlock(relation) \
489 : ( (relation)->rd_smgr != NULL ? (relation)->rd_smgr->smgr_targblock : InvalidBlockNumber )
490 :
491 : /*
492 : * RelationSetTargetBlock
493 : * Set relation's current insertion target block.
494 : */
495 : #define RelationSetTargetBlock(relation, targblock) \
496 : do { \
497 : RelationOpenSmgr(relation); \
498 : (relation)->rd_smgr->smgr_targblock = (targblock); \
499 : } while (0)
500 :
501 : /*
502 : * RelationNeedsWAL
503 : * True if relation needs WAL.
504 : */
505 : #define RelationNeedsWAL(relation) \
506 : ((relation)->rd_rel->relpersistence == RELPERSISTENCE_PERMANENT)
507 :
508 : /*
509 : * RelationUsesLocalBuffers
510 : * True if relation's pages are stored in local buffers.
511 : */
512 : #define RelationUsesLocalBuffers(relation) \
513 : ((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
514 :
515 : /*
516 : * RELATION_IS_LOCAL
517 : * If a rel is either temp or newly created in the current transaction,
518 : * it can be assumed to be accessible only to the current backend.
519 : * This is typically used to decide that we can skip acquiring locks.
520 : *
521 : * Beware of multiple eval of argument
522 : */
523 : #define RELATION_IS_LOCAL(relation) \
524 : ((relation)->rd_islocaltemp || \
525 : (relation)->rd_createSubid != InvalidSubTransactionId)
526 :
527 : /*
528 : * RELATION_IS_OTHER_TEMP
529 : * Test for a temporary relation that belongs to some other session.
530 : *
531 : * Beware of multiple eval of argument
532 : */
533 : #define RELATION_IS_OTHER_TEMP(relation) \
534 : ((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP && \
535 : !(relation)->rd_islocaltemp)
536 :
537 :
538 : /*
539 : * RelationIsScannable
540 : * Currently can only be false for a materialized view which has not been
541 : * populated by its query. This is likely to get more complicated later,
542 : * so use a macro which looks like a function.
543 : */
544 : #define RelationIsScannable(relation) ((relation)->rd_rel->relispopulated)
545 :
546 : /*
547 : * RelationIsPopulated
548 : * Currently, we don't physically distinguish the "populated" and
549 : * "scannable" properties of matviews, but that may change later.
550 : * Hence, use the appropriate one of these macros in code tests.
551 : */
552 : #define RelationIsPopulated(relation) ((relation)->rd_rel->relispopulated)
553 :
554 : /*
555 : * RelationIsAccessibleInLogicalDecoding
556 : * True if we need to log enough information to have access via
557 : * decoding snapshot.
558 : */
559 : #define RelationIsAccessibleInLogicalDecoding(relation) \
560 : (XLogLogicalInfoActive() && \
561 : RelationNeedsWAL(relation) && \
562 : (IsCatalogRelation(relation) || RelationIsUsedAsCatalogTable(relation)))
563 :
564 : /*
565 : * RelationIsLogicallyLogged
566 : * True if we need to log enough information to extract the data from the
567 : * WAL stream.
568 : *
569 : * We don't log information for unlogged tables (since they don't WAL log
570 : * anyway) and for system tables (their content is hard to make sense of, and
571 : * it would complicate decoding slightly for little gain). Note that we *do*
572 : * log information for user defined catalog tables since they presumably are
573 : * interesting to the user...
574 : */
575 : #define RelationIsLogicallyLogged(relation) \
576 : (XLogLogicalInfoActive() && \
577 : RelationNeedsWAL(relation) && \
578 : !IsCatalogRelation(relation))
579 :
580 : /*
581 : * RelationGetPartitionKey
582 : * Returns the PartitionKey of a relation
583 : */
584 : #define RelationGetPartitionKey(relation) ((relation)->rd_partkey)
585 :
586 : /*
587 : * PartitionKey inquiry functions
588 : */
589 : static inline int
590 191 : get_partition_strategy(PartitionKey key)
591 : {
592 191 : return key->strategy;
593 : }
594 :
595 : static inline int
596 212 : get_partition_natts(PartitionKey key)
597 : {
598 212 : return key->partnatts;
599 : }
600 :
601 : static inline List *
602 201 : get_partition_exprs(PartitionKey key)
603 : {
604 201 : return key->partexprs;
605 : }
606 :
607 : /*
608 : * PartitionKey inquiry functions - one column
609 : */
610 : static inline int16
611 15 : get_partition_col_attnum(PartitionKey key, int col)
612 : {
613 15 : return key->partattrs[col];
614 : }
615 :
616 : static inline Oid
617 264 : get_partition_col_typid(PartitionKey key, int col)
618 : {
619 264 : return key->parttypid[col];
620 : }
621 :
622 : static inline int32
623 252 : get_partition_col_typmod(PartitionKey key, int col)
624 : {
625 252 : return key->parttypmod[col];
626 : }
627 :
628 : /*
629 : * RelationGetPartitionDesc
630 : * Returns partition descriptor for a relation.
631 : */
632 : #define RelationGetPartitionDesc(relation) ((relation)->rd_partdesc)
633 :
634 : /* routines in utils/cache/relcache.c */
635 : extern void RelationIncrementReferenceCount(Relation rel);
636 : extern void RelationDecrementReferenceCount(Relation rel);
637 : extern bool RelationHasUnloggedIndex(Relation rel);
638 : extern List *RelationGetRepsetList(Relation rel);
639 :
640 : #endif /* REL_H */
|