gooderp18绿色标准版
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

617 lines
21KB

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