| 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 | |