* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
*
* openGauss is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* ---------------------------------------------------------------------------------------
*
* rel_gs.h
* openGauss relation descriptor (a/k/a relcache entry) definitions.
*
*
* IDENTIFICATION
* src/include/utils/rel_gs.h
*
* ---------------------------------------------------------------------------------------
*/
#ifndef REL_GS_H
#define REL_GS_H
* Relation Compression Type
* REL_CMPRS_NOT_SUPPORT:
* relation doesn't support compression. That means these relations have constant
* commpression attr. 'ALTER TABLE ... SET COMPRESS/UNCOMPRESS' mustn't applies
* to these relations. For examples, system relations, index, etc.
* REL_CMPRS_PAGE_PLAIN:
* relation support compression with 'CREATE/ALTER TABLE ... [SET] COMPRESS/UNCOMPRESS' clause.
* Under this condition, all the data in this relation are stored in plain format.
* REL_CMPRS_PAGE_DICT:
* relation support compression with 'CREATE/ALTER TABLE ... [SET] COMPRESS/UNCOMPRESS' clause.
* Under this condition, many tuples of one page in this relation are stored after compressing.
* REL_CMPRS_MAX_TYPE:
* The other types must be defined above this value.
*/
typedef enum {
REL_CMPRS_NOT_SUPPORT = 0,
REL_CMPRS_PAGE_PLAIN,
REL_CMPRS_FIELDS_EXTRACT,
REL_CMPRS_MAX_TYPE
} RelCompressType;
#ifndef FRONTEND_PARSER
#include "catalog/pg_partition.h"
#include "catalog/pg_hashbucket.h"
#include "catalog/catalog.h"
#include "catalog/pg_namespace.h"
#include "utils/partitionmap_gs.h"
#include "rel.h"
#define CHECK_CMPRS_VALID(compress) ((compress) > REL_CMPRS_NOT_SUPPORT && (compress) < REL_CMPRS_MAX_TYPE)
#define CHECK_CMPRS_NOT_SUPPORT(compress) (REL_CMPRS_NOT_SUPPORT == (compress))
typedef struct PartitionData {
RelFileNode pd_node;
struct SMgrRelationData* pd_smgr;
int pd_refcnt;
bool pd_isvalid;
char pd_indexvalid;
* valid, 2 = temporarily forced */
* rd_createSubid is the ID of the highest subtransaction the rel has
* survived into; or zero if the rel was not created in the current top
* transaction. This should be relied on only for optimization purposes;
* it is possible for new-ness to be "forgotten" (eg, after CLUSTER).
* Likewise, rd_newRelfilenodeSubid is the ID of the highest
* subtransaction the relfilenode change has survived into, or zero if not
* changed in the current transaction (or we have forgotten changing it).
*/
SubTransactionId pd_createSubid;
SubTransactionId pd_newRelfilenodeSubid;
* current xact */
Relation partrel;
Form_pg_partition pd_part;
Oid pd_id;
List* pd_indexlist;
Bitmapset* pd_indexattr;
Oid pd_oidindex;
LockInfoData pd_lockInfo;
* Hack for CLUSTER, rewriting ALTER TABLE, etc: when writing a new
* version of a table, we need to make any toast pointers inserted into it
* have the existing toast table's OID, not the OID of the transient toast
* table. If rd_toastoid isn't InvalidOid, it is the OID to place in
* toast pointers inserted into this rel. (Note it's set on the new
* version of the main heap, not the toast table itself.) This also
* causes toast_save_datum() to try to preserve toast value OIDs.
*/
Oid pd_toastoid;
bytea* rd_options;
struct PgStat_TableStatus* pd_pgstat_info;
Partition parent;
bool newcbi;
PartitionMap* partMap;
struct LocalPartitionEntry *entry;
CommitSeqNo xmin_csn;
} PartitionData;
typedef struct AttrMetaData {
NodeTag type;
char* attname;
Oid atttypid;
int2 attlen;
int2 attnum;
int4 atttypmod;
bool attbyval;
char attstorage;
char attalign;
bool attnotnull;
bool atthasdef;
bool attisdropped;
bool attislocal;
int1 attkvtype;
int1 attcmprmode;
int4 attinhcount;
Oid attcollation;
} AttrMetaData;
typedef struct RelationMetaData {
NodeTag type;
Oid rd_id;
Oid spcNode;
Oid dbNode;
Oid relNode;
int4 bucketNode;
char* relname;
char relkind;
char parttype;
int natts;
List* attrs;
} RelationMetaData;
#define ORIENTATION_ROW "row"
#define ORIENTATION_COLUMN "column"
#define ORIENTATION_ORC "orc"
#define ORIENTATION_TIMESERIES "timeseries"
#define TIME_ONE_HOUR "1 HOUR"
#define INDEXSPLIT_OPT_DEFAULT "default"
#define INDEXSPLIT_OPT_INSERTPT "insertpt"
#define TIME_ONE_DAY "1 DAY"
#define TIME_ONE_WEEK "1 WEEK"
#define TIME_ONE_MONTH "1 MONTH"
#define TIME_ONE_YEAR "1 YEAR"
#define TIME_UNDEFINED "UNDEFINED"
#define COLUMN_UNDEFINED "UNDEFINED"
#define ORC_VERSION_011 "0.11"
#define ORC_VERSION_012 "0.12"
#define COMPRESSION_NO "no"
#define COMPRESSION_YES "yes"
#define COMPRESSION_LOW "low"
#define COMPRESSION_MIDDLE "middle"
#define COMPRESSION_HIGH "high"
#define COMPRESSION_ZLIB "zlib"
#define COMPRESSION_SNAPPY "snappy"
#define COMPRESSION_LZ4 "lz4"
#define UBTREE_INDEX_TYPE_PCR "pcr"
#define UBTREE_INDEX_TYPE_RCR "rcr"
* values for different table access method types.
*/
#define TABLE_ACCESS_METHOD_ASTORE "ASTORE"
#define TABLE_ACCESS_METHOD_USTORE "USTORE"
#define TABLE_ACCESS_METHOD_USTORE_LOWER "ustore"
#define FILESYSTEM_GENERAL "general"
#define FILESYSTEM_HDFS "hdfs"
#define OptIgnoreEnableHadoopEnv "ignore_enable_hadoop_env"
#define TS_PSEUDO_DIST_COLUMN "ts_pseudo_distcol"
#define OptEnabledWaitCleanGpi "y"
#define OptDisabledWaitCleanGpi "n"
#define OptEnabledWaitCleanCbi "y"
#define OptDisabledWaitCleanCbi "n"
#define INTERNAL_MASK_DISABLE 0x0
#define INTERNAL_MASK_ENABLE 0x8000
#define INTERNAL_MASK_DINSERT 0x01
#define INTERNAL_MASK_DDELETE 0x02
#define INTERNAL_MASK_DALTER 0x04
#define INTERNAL_MASK_DSELECT 0x08
#define INTERNAL_MASK_DUPDATE 0x0100
#define StdRdOptionsHasStringData(_basePtr, _memberName) \
((_basePtr) && (((StdRdOptions*)(_basePtr))->_memberName))
#define StdRdOptionsGetStringData(_basePtr, _memberName, _defaultVal) \
(((_basePtr) && (((StdRdOptions*)(_basePtr))->_memberName)) \
? (((char*)(_basePtr) + *(int*)&(((StdRdOptions*)(_basePtr))->_memberName))) \
: (_defaultVal))
* ReltionGetTableAccessMethoType
* Returns the relations TableAmType
*/
#define RelationGetTableAccessMethodType(_reloptions) \
StdRdOptionsGetStringData(_reloptions, storage_type, TABLE_ACCESS_METHOD_ASTORE)
#define RelationIsTableAccessMethodHeapType(_reloptions) \
pg_strcasecmp(RelationGetTableAccessMethodType(_reloptions), TABLE_ACCESS_METHOD_ASTORE) == 0
#define RelationIsTableAccessMethodUStoreType(_reloptions) \
pg_strcasecmp(RelationGetTableAccessMethodType(_reloptions), TABLE_ACCESS_METHOD_USTORE) == 0
* @Description: get TableAmType type from Relation's reloptions data.
* @IN reloptions: Table's reloptions.
* @Return: return TableAmType type for this relation.
*/
static inline TableAmType get_tableam_from_reloptions(bytea* reloptions, char relkind, Oid amoid)
{
if (relkind == RELKIND_RELATION || relkind == RELKIND_TOASTVALUE || amoid == BTREE_AM_OID) {
if (reloptions!= NULL) {
if (RelationIsTableAccessMethodHeapType(reloptions)) {
return TAM_HEAP;
} else if (RelationIsTableAccessMethodUStoreType(reloptions)) {
return TAM_USTORE;
}
return TAM_HEAP;
} else {
return TAM_HEAP;
}
} else if (relkind == RELKIND_INDEX ||
RELKIND_IS_SEQUENCE(relkind) ||
relkind == RELKIND_COMPOSITE_TYPE ||
relkind == RELKIND_VIEW ||
relkind == RELKIND_FOREIGN_TABLE) {
return TAM_HEAP;
}
return TAM_HEAP;
}
* ReltionGetTableAccessMethoType
* Returns the relations TableAmType
*/
#define RelationGetIndexsplitMethod(_reloptions) \
StdRdOptionsGetStringData(_reloptions, indexsplit, INDEXSPLIT_OPT_INSERTPT)
#define RelationIsIndexsplitMethodDefault(_reloptions) \
pg_strcasecmp(RelationGetIndexsplitMethod(_reloptions), INDEXSPLIT_OPT_DEFAULT) == 0
#define RelationIsIndexsplitMethodInsertpt(_reloptions) \
pg_strcasecmp(RelationGetIndexsplitMethod(_reloptions), INDEXSPLIT_OPT_INSERTPT) == 0
#define RelationGetIndexType(_reloptions) \
StdRdOptionsGetStringData(_reloptions, index_type, UBTREE_INDEX_TYPE_RCR)
#define RelationIndexIsPCR(_reloptions) \
pg_strcasecmp(RelationGetIndexType(_reloptions), UBTREE_INDEX_TYPE_PCR) == 0
* @Description: get indexsplit type from Relation's reloptions data.
* @IN reloptions: Table's reloptions.
* @Return: return indexsplit type for this relation.
*/
static inline int8 get_indexsplit_from_reloptions(bytea *reloptions, Oid amoid)
{
if (reloptions != NULL && (amoid == BTREE_AM_OID || amoid == UBTREE_AM_OID)) {
return (RelationIsIndexsplitMethodInsertpt(reloptions) ? INDEXSPLIT_NO_INSERTPT : INDEXSPLIT_NO_DEFAULT);
}
return (amoid == UBTREE_AM_OID ? INDEXSPLIT_NO_INSERTPT : INDEXSPLIT_NO_DEFAULT);
}
* Return the relations' orientation
*/
#define RelationGetOrientation(relation) StdRdOptionsGetStringData((relation)->rd_options, orientation, ORIENTATION_ROW)
#define RaletionGetStoreVersion(relation) StdRdOptionsGetStringData((relation)->rd_options, version, ORC_VERSION_012)
#define RelationGetFileSystem(relation) \
StdRdOptionsGetStringData((relation)->rd_options, filesystem, FILESYSTEM_GENERAL)
#define RelationIsCUFormat(relation) \
((RELKIND_RELATION == relation->rd_rel->relkind) && \
pg_strcasecmp(RelationGetOrientation(relation), ORIENTATION_COLUMN) == 0)
#define RelationIsRowFormat(relation) \
((RELKIND_RELATION == relation->rd_rel->relkind) && \
pg_strcasecmp(RelationGetOrientation(relation), ORIENTATION_ROW) == 0)
#define RelationIsColumnFormat(relation) \
((RELKIND_RELATION == relation->rd_rel->relkind) && (RelationIsCUFormat(relation) || RelationIsPAXFormat(relation)))
#define RelationIsUstoreFormat(relation) \
((RELKIND_RELATION == relation->rd_rel->relkind || \
RELKIND_TOASTVALUE == relation->rd_rel->relkind) && \
relation->rd_tam_ops == TableAmUstore)
#define RelationIsAstoreFormat(relation) \
((RELKIND_RELATION == relation->rd_rel->relkind || \
RELKIND_TOASTVALUE == relation->rd_rel->relkind) && \
relation->rd_tam_ops == TableAmHeap)
#define RelationIsUBTree(relation) (relation->rd_rel->relam == UBTREE_AM_OID)
#define RelationIsUstoreIndex(relation) (RelationIsUBTree(relation))
#define RelationGetCUDescRelId(r) ((r)->rd_rel->relcudescrelid)
#define RelationGetDeltaRelId(r) ((r)->rd_rel->reldeltarelid)
#define IS_BTREE(r) ((r)->rd_rel->relam == BTREE_AM_OID || \
(r)->rd_rel->relam == CBTREE_AM_OID || \
(r)->rd_rel->relam == UBTREE_AM_OID)
* @Description: get columnar relation's compress level.
* @IN rel: columnar heap relation
* @Return: return user explictly defined compresslevel,
* or return compresslevel zero.
* @See also:
*/
static inline int relation_get_compresslevel(Relation rel)
{
Assert(rel != NULL);
if ((RELKIND_RELATION == rel->rd_rel->relkind) && rel->rd_options) {
return ((StdRdOptions*)rel->rd_options)->compresslevel;
}
return 0;
}
static inline int RelationGetInternalMask(Relation rel)
{
if ((RELKIND_RELATION == rel->rd_rel->relkind) && rel->rd_options) {
return ((StdRdOptions*)rel->rd_options)->internalMask;
} else {
return INTERNAL_MASK_DISABLE;
}
}
static inline int RelationGetInitTd(Relation rel)
{
if ((RELKIND_RELATION == rel->rd_rel->relkind) && rel->rd_options) {
return ((StdRdOptions*)rel->rd_options)->initTd;
} else if (RELKIND_TOASTVALUE == rel->rd_rel->relkind) {
return UHEAP_DEFAULT_TOAST_TD_COUNT;
}
return UHEAP_DEFAULT_TD;
}
#define RelationIsInternal(relation) (RelationGetInternalMask(relation) != INTERNAL_MASK_DISABLE)
#define RelationIsRelation(relation) (RELKIND_RELATION == (relation)->rd_rel->relkind)
#define RelationIsMatview(relation) (RELKIND_MATVIEW == (relation)->rd_rel->relkind)
* Mgr for Redistribute
*/
static inline RedisHtlAction RelationGetAppendMode(Relation rel)
{
Assert(rel != NULL);
if (RelationIsRelation(rel) && rel->rd_options) {
return ((StdRdOptions*)rel->rd_options)->append_mode_internal;
}
return REDIS_REL_NORMAL;
}
* RelationIsPAXFormat
* Return the relations' orientation. Pax format includes ORC format.
*/
#ifdef ENABLE_MULTIPLE_NONDES
#define RelationIsPAXFormat(relation) \
((RELKIND_RELATION == relation->rd_rel->relkind) && \
pg_strcasecmp(RelationGetOrientation(relation), ORIENTATION_ORC) == 0)
#else
#define RelationIsPAXFormat(relation) (false)
#endif
* Return relation whether is column store, which includes CU format and PAX format.
*/
#define RelationIsColStore(relation) \
((RELKIND_RELATION == relation->rd_rel->relkind) && (RelationIsCUFormat(relation) || RelationIsPAXFormat(relation)))
#ifdef ENABLE_MULTIPLE_NODES
#define RelationIsTsStore(relation) \
((RELKIND_RELATION == relation->rd_rel->relkind) && \
pg_strcasecmp(RelationGetOrientation(relation), ORIENTATION_TIMESERIES) == 0)
#else
#define RelationIsTsStore(relation) (false)
#endif
#define TsRelWithImplDistColumn(attribute, pos) \
(((attribute)[pos].attkvtype == ATT_KV_HIDE) && \
namestrcmp(&((attribute)[pos].attname), TS_PSEUDO_DIST_COLUMN) == 0)
#define StdRelOptGetOrientation(__stdRelOpt) StdRdOptionsGetStringData((__stdRelOpt), orientation, ORIENTATION_ROW)
#define StdRelOptIsColStore(__stdRelOpt) (0 == pg_strcasecmp(ORIENTATION_COLUMN, StdRelOptGetOrientation(__stdRelOpt)))
#define StdRelOptIsRowStore(__stdRelOpt) (0 == pg_strcasecmp(ORIENTATION_ROW, StdRelOptGetOrientation(__stdRelOpt)))
#define StdRelOptIsTsStore(__stdRelOpt) (0 == pg_strcasecmp(ORIENTATION_TIMESERIES, \
StdRelOptGetOrientation(__stdRelOpt)))
#define StdRelOptGetInternalMask(__stdRelOpt) StdRdOptionsGetStringData((__stdRelOpt), internalMask, 0)
#define RelationGetCompression(relation) StdRdOptionsGetStringData((relation)->rd_options, compression, COMPRESSION_LOW)
#define RelMaxFullCuSize (60 * BatchMaxSize)
#define RelDefaultFullCuSize RelMaxFullCuSize
#define RelDefaultPartialClusterRows (70 * RelDefaultFullCuSize)
#define RelDefaultDletaRows 100
#define REL_MIN_COMPRESSLEVEL (0)
#define REL_MAX_COMPRESSLEVEL (3)
#define RelRoundIntOption(_v1, _v2) (AssertMacro((_v1) >= (_v2)), ((_v2) * ((_v1) / (_v2))))
#define RelationGetMaxBatchRows(relation) \
((relation)->rd_options ? RelRoundIntOption(((StdRdOptions*)(relation)->rd_options)->max_batch_rows, BatchMaxSize) \
: RelDefaultFullCuSize)
#define RelationGetDeltaRowsThreshold(relation) \
((relation)->rd_options ? ((StdRdOptions*)(relation)->rd_options)->delta_rows_threshold : RelDefaultDletaRows)
#define RelationGetPartialClusterRows(relation) \
((relation)->rd_options \
? ((((StdRdOptions*)(relation)->rd_options)->partial_cluster_rows < 0) \
? RelRoundIntOption(0x7fffffff, RelationGetMaxBatchRows(relation)) \
: RelRoundIntOption(((StdRdOptions*)(relation)->rd_options)->partial_cluster_rows, \
RelationGetMaxBatchRows(relation))) \
: RelDefaultPartialClusterRows)
static inline bool RelationCreateInCurrXact(Relation rel)
{
return rel->rd_createSubid != InvalidTransactionId;
}
* return the pg_class OID of this relation.
* if this is a PARTITION, return its parent oid;
* if this is a SUBPARTITION, return its grandparent oid;
* otherwise the same to macro RelationGetRelid().
*/
#define RelationGetPgClassOid(relation, isPartition) \
((isPartition) ? (RelationIsSubPartitionOfSubPartitionTable(relation) ? ((relation)->grandparentId) \
: ((relation)->parentId)) \
: RelationGetRelid(relation))
* PartitionOpenSmgr
* Open the partition at the smgr level, if not already done.
*/
#define PartitionOpenSmgr(partition) \
do { \
if ((partition)->pd_smgr == NULL) \
smgrsetowner(&((partition)->pd_smgr), smgropen((partition)->pd_node, InvalidBackendId)); \
else { \
TryFreshSmgrCache((partition)->pd_smgr); \
} \
} while (0)
* PartionCloseSmgr
* Close the partition at the smgr level, if not already done.
*
* Note: smgrclose should unhook from owner pointer, hence the Assert.
*/
#define PartitionCloseSmgr(partition) \
do { \
if ((partition)->pd_smgr != NULL) { \
smgrclose((partition)->pd_smgr); \
Assert(PartitionIsBucket(partition) || (partition)->pd_smgr == NULL); \
} \
} while (0)
* PartitionGetTargetBlock
* Fetch partition's current insertion target block.
*
* Returns InvalidBlockNumber if there is no current target block. Note
* that the target block status is discarded on any smgr-level invalidation.
*/
#define PartitionGetTargetBlock(partition) \
((partition)->pd_smgr != NULL ? (partition)->pd_smgr->smgr_targblock : InvalidBlockNumber)
* PartitionSetTargetBlock
* Set relation's current insertion target block.
*/
* PartitionGetPartitionName
* Returns the part's name.
*
* Note that the name is only unique within the containing namespace.
*/
#define PartitionGetPartitionName(partition) (NameStr((partition)->pd_part->relname))
* PartitionGetPartid
* Returns the OID of the partition
*/
#define PartitionGetPartid(partition) ((partition)->pd_id)
#define PartitionGetRelid(partition) ((partition)->pd_part->parentid)
* PartitionIsValid
* True iff partition descriptor is valid.
*/
#define PartitionIsValid(partition) PointerIsValid(partition)
* true if the relation is construct from a partition
*/
#define RelationIsPartition(relation) \
(OidIsValid((relation)->parentId) && (PARTTYPE_NON_PARTITIONED_RELATION == (relation)->rd_rel->parttype) && \
((RELKIND_RELATION == (relation)->rd_rel->relkind) || (RELKIND_INDEX == (relation)->rd_rel->relkind)))
#define RelationIsPartitionOfSubPartitionTable(relation) \
((relation)->subpartitiontype == PART_OBJ_TYPE_TABLE_PARTITION)
#define RelationIsSubPartitionOfSubPartitionTable(relation) \
((relation)->subpartitiontype == PART_OBJ_TYPE_TABLE_SUB_PARTITION)
#define InvalidPartition ((Partition)NULL)
#define InvalidBktId (-1)
#define RelationIsBucket(relation) \
((relation)->rd_node.bucketNode > InvalidBktId && (relation)->rd_node.bucketNode < SegmentBktId)
* PartitionHasReferenceCountZero
* True iff partition reference count is zero.
*
* Note:
* Assumes partition descriptor is valid.
*/
#define PartitionHasReferenceCountZero(partition) ((bool)((partition)->pd_refcnt == 0))
extern void PartitionIncrementReferenceCount(Partition part);
extern void PartitionDecrementReferenceCount(Partition part);
#define PartitionIsMapped(part) ((part)->pd_part->relfilenode == InvalidOid)
#define PartitionHasSubpartition(part) ((part)->pd_part->relfilenode == InvalidOid)
#define CStoreRelationOpenSmgr(relation, col) \
do { \
if ((relation)->rd_smgr == NULL) \
smgrsetowner(&((relation)->rd_smgr), smgropen((relation)->rd_node, (relation)->rd_backend, (col))); \
else { \
SMgrRelation tmp; \
tmp = smgropen((relation)->rd_node, (relation)->rd_backend, (col)); \
Assert((relation)->rd_smgr == tmp); \
TryFreshSmgrCache((relation)->rd_smgr); \
} \
} while (0)
#define RelationIsLocalTemp(relation) \
((relation)->rd_rel->relnamespace == u_sess->catalog_cxt.myTempNamespace || \
(relation)->rd_rel->relnamespace == u_sess->catalog_cxt.myTempToastNamespace)
#define RelationIsUnlogged(relation) ((relation)->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
#define RelationIsGlobalIndex(relation) (RELKIND_GLOBAL_INDEX == (relation)->rd_rel->relkind)
#define RelationIsIndex(relation) (RELKIND_INDEX == (relation)->rd_rel->relkind || RelationIsGlobalIndex(relation))
#define RelationAmIsBtree(relation) ((relation)->rd_rel->relam == BTREE_AM_OID)
#define RelationIsCrossBucketIndex(relation) \
(RelationAmIsBtree(relation) && RELATION_HAS_BUCKET(relation) && RELOPTIONS_CROSSBUCKET((relation)->rd_options))
#define RelationIsSequnce(relation) (RELKIND_SEQUENCE == (relation)->rd_rel->relkind || \
RELKIND_LARGE_SEQUENCE == (relation)->rd_rel->relkind)
#define RelationIsToast(relation) (RELKIND_TOASTVALUE == (relation)->rd_rel->relkind)
#define RelationIsView(relation) (RELKIND_VIEW == (relation)->rd_rel->relkind)
#define RelationIsContquery(relation) (RELKIND_CONTQUERY == (relation)->rd_rel->relkind)
#define RelationIsForeignTable(relation) (RELKIND_FOREIGN_TABLE == (relation)->rd_rel->relkind)
#define RelationIsStream(relation) (RELKIND_STREAM == (relation)->rd_rel->relkind)
#define RelationIsUnCataloged(relation) (RELKIND_UNCATALOGED == (relation)->rd_rel->relkind)
#define RelationIsPartitioned(relation) \
(PARTTYPE_PARTITIONED_RELATION == (relation)->rd_rel->parttype || \
PARTTYPE_SUBPARTITIONED_RELATION == (relation)->rd_rel->parttype)
#define RelationIsCommonPartitioned(relation) (PARTTYPE_PARTITIONED_RELATION == (relation)->rd_rel->parttype)
#define RelationIsSubPartitioned(relation) (PARTTYPE_SUBPARTITIONED_RELATION == (relation)->rd_rel->parttype)
#define RelationIsValuePartitioned(relation) (PARTTYPE_VALUE_PARTITIONED_RELATION == (relation)->rd_rel->parttype)
#define RelationGetValuePartitionList(relation) \
(RelationIsValuePartitioned(relation) ? ((ValuePartitionMap*)relation->partMap)->partList : NIL)
#define RelationIsNonpartitioned(relation) (PARTTYPE_NON_PARTITIONED_RELATION == (relation)->rd_rel->parttype)
#define RelationIsSegmentTable(relation) ((relation)->rd_node.bucketNode > InvalidBktId)
#define RelationIsPartitionedHashBucketTable(relation) \
(RelationIsPartitioned(relation) && RELATION_OWN_BUCKET(relation))
#define IsCreatingCrossBucketIndex(relation) ((relation)->newcbi)
#define RELOPTIONS_CROSSBUCKET(options) ((options) ? ((StdRdOptions *)(options))->crossbucket : false)
* RELATION_IS_OTHER_TEMP
* Test for a temporary relation that belongs to some other session.
*
* Beware of multiple eval of argument
*/
#define RELATION_IS_OTHER_TEMP(relation) \
(STMT_RETRY_ENABLED ? ((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP && \
u_sess->catalog_cxt.myTempNamespace != (relation)->rd_rel->relnamespace && \
u_sess->catalog_cxt.myTempToastNamespace != (relation)->rd_rel->relnamespace && \
CSTORE_NAMESPACE != (relation)->rd_rel->relnamespace && \
PG_TOAST_NAMESPACE != (relation)->rd_rel->relnamespace) \
: ((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP && \
u_sess->catalog_cxt.myTempNamespace != (relation)->rd_rel->relnamespace && \
u_sess->catalog_cxt.myTempToastNamespace != (relation)->rd_rel->relnamespace))
#define RELATION_IS_PARTITIONED(relation) \
((PARTTYPE_PARTITIONED_RELATION == (relation)->rd_rel->parttype || \
PARTTYPE_SUBPARTITIONED_RELATION == (relation)->rd_rel->parttype) && \
(RELKIND_RELATION == (relation)->rd_rel->relkind))
#define RELATION_IS_INTERVAL_PARTITIONED(relation) \
(RELATION_IS_PARTITIONED(relation) && PartitionMapIsInterval((relation)->partMap))
#define RELATION_IS_VALUE_PARTITIONED(relation) \
((PARTTYPE_VALUE_PARTITIONED_RELATION == (relation)->rd_rel->parttype) && \
(RELKIND_RELATION == (relation)->rd_rel->relkind))
#define HEAP_IS_PARTITIONED(relation) \
((PARTTYPE_PARTITIONED_RELATION == (relation)->rd_rel->parttype || \
PARTTYPE_VALUE_PARTITIONED_RELATION == (relation)->rd_rel->parttype) && \
(RELKIND_RELATION == (relation)->rd_rel->relkind || RELKIND_INDEX == (relation)->rd_rel->relkind))
#define RELATION_SUPPORT_AUTONOMOUS_EXTEND_PARTITION \
g_instance.attr.attr_storage.max_concurrent_autonomous_transactions > 0
* type bucketOid bucketKey meaning
* N INV INV relation has no bucket
* B 1 KEY relation has bucket but without bucket storage
* S OID INV relation has bucket storage without bucket key
* K OID KEY relation has bucket key
*/
#define REALTION_BUCKETKEY_INITED(relation) \
((relation)->rd_bucketkey != (RelationBucketKey *)&((relation)->rd_bucketkey))
#define REALTION_BUCKETKEY_VALID(relation) \
(REALTION_BUCKETKEY_INITED(relation) && PointerIsValid((relation)->rd_bucketkey))
#define RELATION_HAS_BUCKET(relation) (OidIsValid((relation)->rd_bucketoid))
#define RELATION_OWN_BUCKET(relation) (RELATION_HAS_BUCKET(relation) && (VirtualBktOid != (relation)->rd_bucketoid))
#define RELATION_OWN_BUCKETKEY(relation) \
(RELATION_OWN_BUCKET(relation) && \
RelationIsPartitioned(relation) && \
!RelationIsCrossBucketIndex(relation) && \
!IsCreatingCrossBucketIndex(relation))
#ifdef ENABLE_MULTIPLE_NODES
#define RELATION_CREATE_BUCKET(relation) \
(RelationIsNonpartitioned(relation) && \
RELATION_OWN_BUCKET(relation) && \
!RelationIsCrossBucketIndex(relation) && \
!IsCreatingCrossBucketIndex(relation))
#else
#define RELATION_CREATE_BUCKET(relation) false
#endif
#define RELATION_OWN_BUCKETKEY_COMMON(relation) (RELATION_OWN_BUCKET(relation) && RelationIsPartitioned(relation))
#define RELATION_CREATE_BUCKET_COMMON(relation) (RelationIsNonpartitioned(relation) && RELATION_OWN_BUCKET(relation))
#define RELATION_HAS_UIDS(relation) \
((((relation)->rd_rel->relkind == RELKIND_RELATION) && ((relation)->rd_options)) ? \
((StdRdOptions*)(relation)->rd_options)->hasuids : false)
#define StdRdOptionsHasUids(options, relkind) \
((((relkind) == RELKIND_RELATION) && options) ? ((StdRdOptions*)options)->hasuids : false)
#define RELATION_IS_DELTA(relation) \
(IsCStoreNamespace(RelationGetNamespace(relation)) && \
pg_strncasecmp(RelationGetRelationName(relation), "pg_delta", strlen("pg_delta")) == 0)
#define RELATION_GET_CMPRS_ATTR(relation) ((relation)->rd_rel->relcmprs)
#define RELATION_SET_CMPRS_ATTR(relation, cmprs) ((relation)->rd_rel->relcmprs = cmprs)
static inline bool IsCompressedByCmprsInPgclass(const RelCompressType cmprInPgclass)
{
return (cmprInPgclass > REL_CMPRS_PAGE_PLAIN && cmprInPgclass < REL_CMPRS_MAX_TYPE);
}
#define RowRelationIsCompressed(relation) \
(pg_strcasecmp(COMPRESSION_YES, StdRdOptionsGetStringData(relation->rd_options, compression, COMPRESSION_NO)) == 0 || \
IsCompressedByCmprsInPgclass((RelCompressType)relation->rd_rel->relcmprs))
#define RelIsSpecifiedFTbl(rte, SepcifiedType) \
((rte->relkind == RELKIND_FOREIGN_TABLE || rte->relkind == RELKIND_STREAM) \
&& isSpecifiedSrvTypeFromRelId(rte->relid, SepcifiedType))
#define RelationGetStartCtidInternal(relation) \
StdRdOptionsGetStringData((relation)->rd_options, start_ctid_internal, NULL)
#define RelationGetEndCtidInternal(relation) StdRdOptionsGetStringData((relation)->rd_options, end_ctid_internal, NULL)
#ifdef ENABLE_MULTIPLE_NODES
#define RelationInRedistribute(relation) (REDIS_REL_NORMAL < (RelationGetAppendMode(relation)) ? true : false)
#define RelationInRedistributeReadOnly(relation) \
(REDIS_REL_READ_ONLY == (RelationGetAppendMode(relation)) ? true : false)
#define RelationInRedistributeEndCatchup(relation) \
(REDIS_REL_END_CATCHUP == (RelationGetAppendMode(relation)) ? true : false)
#define RelationIsRedistributeDest(relation) \
(REDIS_REL_DESTINATION == (RelationGetAppendMode(relation)) ? true : false)
#else
#define RelationInRedistribute(relation) (false)
#define RelationInRedistributeReadOnly(relation) (false)
#define RelationInRedistributeEndCatchup(relation) (false)
#define RelationIsRedistributeDest(relation) (false)
#endif
#define RelationGetRelCnOid(relation) \
((relation)->rd_options ? ((StdRdOptions*)(relation)->rd_options)->rel_cn_oid : InvalidOid)
#define RelationGetRelMergeList(relation) \
StdRdOptionsGetStringData((relation)->rd_options, merge_list, NULL)
#define ParitionGetWaitCleanGpi(partition) StdRdOptionsGetStringData((partition)->rd_options, wait_clean_gpi, OptDisabledWaitCleanGpi)
#define RelationGetWaitCleanGpi(relation) StdRdOptionsGetStringData((relation)->rd_options, wait_clean_gpi, OptDisabledWaitCleanGpi)
#define IndexGetWaitCleanCbi(relation) \
StdRdOptionsGetStringData((relation)->rd_options, wait_clean_cbi, OptDisabledWaitCleanCbi)
static inline bool PartitionEnableWaitCleanGpi(Partition partition)
{
if (PointerIsValid(partition) && partition->rd_options != NULL &&
pg_strcasecmp(OptEnabledWaitCleanGpi, ParitionGetWaitCleanGpi(partition)) == 0) {
return true;
}
return false;
}
static inline bool IndexEnableWaitCleanCbi(Relation relation)
{
if (PointerIsValid(relation) && relation->rd_options != NULL && RelationIsCrossBucketIndex(relation) &&
pg_strcasecmp(OptEnabledWaitCleanCbi, IndexGetWaitCleanCbi(relation)) == 0) {
return true;
}
return false;
}
static inline bool RelationEnableWaitCleanGpi(Relation relation)
{
if (PointerIsValid(relation) && relation->rd_options != NULL &&
pg_strcasecmp(OptEnabledWaitCleanGpi, RelationGetWaitCleanGpi(relation)) == 0) {
return true;
}
return false;
}
extern bool RelationIsPaxFormatByOid(Oid relid);
#ifdef ENABLE_MOT
extern bool RelationIsMOTTableByOid(Oid relid);
#endif
extern bool RelationIsCUFormatByOid(Oid relid);
extern bool RelationIsUStoreFormatByOid(Oid relid);
#define IS_FOREIGNTABLE(rel) ((rel)->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
#define IS_STREAM_TABLE(rel) ((rel)->rd_rel->relkind == RELKIND_STREAM)
extern bool have_useft_privilege(void);
extern RelationMetaData* make_relmeta(Relation rel);
extern Relation get_rel_from_meta(RelationMetaData* frel);
extern bool CheckRelOrientationByPgClassTuple(HeapTuple tuple, TupleDesc tupdesc, const char* orientation);
#endif
#endif