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