/*------------------------------------------------------------------------- * * pg_version_compat.h * Compatibility macros for writing code agnostic to PostgreSQL versions * * Copyright (c) Citus Data, Inc. * *------------------------------------------------------------------------- */ #ifndef PG_VERSION_COMPAT_H #define PG_VERSION_COMPAT_H #include "pg_version_constants.h" #if PG_VERSION_NUM >= PG_VERSION_17 #include "catalog/pg_am.h" #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" #include "catalog/pg_attrdef.h" #include "catalog/pg_auth_members.h" #include "catalog/pg_authid.h" #include "catalog/pg_cast.h" #include "catalog/pg_class.h" #include "catalog/pg_collation.h" #include "catalog/pg_constraint.h" #include "catalog/pg_conversion.h" #include "catalog/pg_database.h" #include "catalog/pg_default_acl.h" #include "catalog/pg_depend.h" #include "catalog/pg_event_trigger.h" #include "catalog/pg_extension.h" #include "catalog/pg_foreign_data_wrapper.h" #include "catalog/pg_foreign_server.h" #include "catalog/pg_init_privs.h" #include "catalog/pg_language.h" #include "catalog/pg_largeobject.h" #include "catalog/pg_namespace.h" #include "catalog/pg_opclass.h" #include "catalog/pg_operator.h" #include "catalog/pg_opfamily.h" #include "catalog/pg_parameter_acl.h" #include "catalog/pg_policy.h" #include "catalog/pg_proc.h" #include "catalog/pg_publication.h" #include "catalog/pg_publication_namespace.h" #include "catalog/pg_publication_rel.h" #include "catalog/pg_rewrite.h" #include "catalog/pg_statistic_ext.h" #include "catalog/pg_subscription.h" #include "catalog/pg_tablespace.h" #include "catalog/pg_transform.h" #include "catalog/pg_trigger.h" #include "catalog/pg_ts_config.h" #include "catalog/pg_ts_dict.h" #include "catalog/pg_ts_parser.h" #include "catalog/pg_ts_template.h" #include "catalog/pg_type.h" #include "catalog/pg_user_mapping.h" /* * This enum covers all system catalogs whose OIDs can appear in * pg_depend.classId or pg_shdepend.classId. */ typedef enum ObjectClass { OCLASS_CLASS, /* pg_class */ OCLASS_PROC, /* pg_proc */ OCLASS_TYPE, /* pg_type */ OCLASS_CAST, /* pg_cast */ OCLASS_COLLATION, /* pg_collation */ OCLASS_CONSTRAINT, /* pg_constraint */ OCLASS_CONVERSION, /* pg_conversion */ OCLASS_DEFAULT, /* pg_attrdef */ OCLASS_LANGUAGE, /* pg_language */ OCLASS_LARGEOBJECT, /* pg_largeobject */ OCLASS_OPERATOR, /* pg_operator */ OCLASS_OPCLASS, /* pg_opclass */ OCLASS_OPFAMILY, /* pg_opfamily */ OCLASS_AM, /* pg_am */ OCLASS_AMOP, /* pg_amop */ OCLASS_AMPROC, /* pg_amproc */ OCLASS_REWRITE, /* pg_rewrite */ OCLASS_TRIGGER, /* pg_trigger */ OCLASS_SCHEMA, /* pg_namespace */ OCLASS_STATISTIC_EXT, /* pg_statistic_ext */ OCLASS_TSPARSER, /* pg_ts_parser */ OCLASS_TSDICT, /* pg_ts_dict */ OCLASS_TSTEMPLATE, /* pg_ts_template */ OCLASS_TSCONFIG, /* pg_ts_config */ OCLASS_ROLE, /* pg_authid */ OCLASS_ROLE_MEMBERSHIP, /* pg_auth_members */ OCLASS_DATABASE, /* pg_database */ OCLASS_TBLSPACE, /* pg_tablespace */ OCLASS_FDW, /* pg_foreign_data_wrapper */ OCLASS_FOREIGN_SERVER, /* pg_foreign_server */ OCLASS_USER_MAPPING, /* pg_user_mapping */ OCLASS_DEFACL, /* pg_default_acl */ OCLASS_EXTENSION, /* pg_extension */ OCLASS_EVENT_TRIGGER, /* pg_event_trigger */ OCLASS_PARAMETER_ACL, /* pg_parameter_acl */ OCLASS_POLICY, /* pg_policy */ OCLASS_PUBLICATION, /* pg_publication */ OCLASS_PUBLICATION_NAMESPACE, /* pg_publication_namespace */ OCLASS_PUBLICATION_REL, /* pg_publication_rel */ OCLASS_SUBSCRIPTION, /* pg_subscription */ OCLASS_TRANSFORM, /* pg_transform */ } ObjectClass; #define LAST_OCLASS OCLASS_TRANSFORM /* * Determine the class of a given object identified by objectAddress. * * We implement it as a function instead of an array because the OIDs aren't * consecutive. */ static inline ObjectClass getObjectClass(const ObjectAddress *object) { /* only pg_class entries can have nonzero objectSubId */ if (object->classId != RelationRelationId && object->objectSubId != 0) { elog(ERROR, "invalid non-zero objectSubId for object class %u", object->classId); } switch (object->classId) { case RelationRelationId: { /* caller must check objectSubId */ return OCLASS_CLASS; } case ProcedureRelationId: { return OCLASS_PROC; } case TypeRelationId: { return OCLASS_TYPE; } case CastRelationId: { return OCLASS_CAST; } case CollationRelationId: { return OCLASS_COLLATION; } case ConstraintRelationId: { return OCLASS_CONSTRAINT; } case ConversionRelationId: { return OCLASS_CONVERSION; } case AttrDefaultRelationId: { return OCLASS_DEFAULT; } case LanguageRelationId: { return OCLASS_LANGUAGE; } case LargeObjectRelationId: { return OCLASS_LARGEOBJECT; } case OperatorRelationId: { return OCLASS_OPERATOR; } case OperatorClassRelationId: { return OCLASS_OPCLASS; } case OperatorFamilyRelationId: { return OCLASS_OPFAMILY; } case AccessMethodRelationId: { return OCLASS_AM; } case AccessMethodOperatorRelationId: { return OCLASS_AMOP; } case AccessMethodProcedureRelationId: { return OCLASS_AMPROC; } case RewriteRelationId: { return OCLASS_REWRITE; } case TriggerRelationId: { return OCLASS_TRIGGER; } case NamespaceRelationId: { return OCLASS_SCHEMA; } case StatisticExtRelationId: { return OCLASS_STATISTIC_EXT; } case TSParserRelationId: { return OCLASS_TSPARSER; } case TSDictionaryRelationId: { return OCLASS_TSDICT; } case TSTemplateRelationId: { return OCLASS_TSTEMPLATE; } case TSConfigRelationId: { return OCLASS_TSCONFIG; } case AuthIdRelationId: { return OCLASS_ROLE; } case AuthMemRelationId: { return OCLASS_ROLE_MEMBERSHIP; } case DatabaseRelationId: { return OCLASS_DATABASE; } case TableSpaceRelationId: { return OCLASS_TBLSPACE; } case ForeignDataWrapperRelationId: { return OCLASS_FDW; } case ForeignServerRelationId: { return OCLASS_FOREIGN_SERVER; } case UserMappingRelationId: { return OCLASS_USER_MAPPING; } case DefaultAclRelationId: { return OCLASS_DEFACL; } case ExtensionRelationId: { return OCLASS_EXTENSION; } case EventTriggerRelationId: { return OCLASS_EVENT_TRIGGER; } case ParameterAclRelationId: { return OCLASS_PARAMETER_ACL; } case PolicyRelationId: { return OCLASS_POLICY; } case PublicationNamespaceRelationId: { return OCLASS_PUBLICATION_NAMESPACE; } case PublicationRelationId: { return OCLASS_PUBLICATION; } case PublicationRelRelationId: { return OCLASS_PUBLICATION_REL; } case SubscriptionRelationId: { return OCLASS_SUBSCRIPTION; } case TransformRelationId: return OCLASS_TRANSFORM; } /* shouldn't get here */ elog(ERROR, "unrecognized object class: %u", object->classId); return OCLASS_CLASS; /* keep compiler quiet */ } #include "commands/tablecmds.h" static inline void RangeVarCallbackOwnsTable(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg) { return RangeVarCallbackMaintainsTable(relation, relId, oldRelId, arg); } #include "catalog/pg_attribute.h" #include "utils/syscache.h" static inline int getAttstattarget_compat(HeapTuple attTuple) { bool isnull; Datum dat = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attstattarget, &isnull); return (isnull ? -1 : DatumGetInt16(dat)); } #include "catalog/pg_statistic_ext.h" static inline int getStxstattarget_compat(HeapTuple tup) { bool isnull; Datum dat = SysCacheGetAttr(STATEXTOID, tup, Anum_pg_statistic_ext_stxstattarget, &isnull); return (isnull ? -1 : DatumGetInt16(dat)); } #define getAlterStatsStxstattarget_compat(a) ((Node *) makeInteger(a)) #define getIntStxstattarget_compat(a) (intVal(a)) #define WaitEventSetTracker_compat CurrentResourceOwner #define identitySequenceRelation_compat(a) (a) #define matched_compat(a) (a->matchKind == MERGE_WHEN_MATCHED) #define create_foreignscan_path_compat(a, b, c, d, e, f, g, h, i, j, \ k) create_foreignscan_path(a, b, c, d, e, f, g, h, \ i, j, k) #define getProcNo_compat(a) (a->vxid.procNumber) #define getLxid_compat(a) (a->vxid.lxid) #else #define Anum_pg_collation_colllocale Anum_pg_collation_colliculocale #define Anum_pg_database_datlocale Anum_pg_database_daticulocale #include "access/htup_details.h" static inline int getAttstattarget_compat(HeapTuple attTuple) { return ((Form_pg_attribute) GETSTRUCT(attTuple))->attstattarget; } #include "catalog/pg_statistic_ext.h" static inline int getStxstattarget_compat(HeapTuple tup) { return ((Form_pg_statistic_ext) GETSTRUCT(tup))->stxstattarget; } #define getAlterStatsStxstattarget_compat(a) (a) #define getIntStxstattarget_compat(a) (a) #define WaitEventSetTracker_compat CurrentMemoryContext #define identitySequenceRelation_compat(a) (RelationGetRelid(a)) #define matched_compat(a) (a->matched) #define create_foreignscan_path_compat(a, b, c, d, e, f, g, h, i, j, \ k) create_foreignscan_path(a, b, c, d, e, f, g, h, \ i, k) #define getProcNo_compat(a) (a->pgprocno) #define getLxid_compat(a) (a->lxid) #define COLLPROVIDER_BUILTIN 'b' #endif #if PG_VERSION_NUM >= PG_VERSION_16 #include "utils/guc_tables.h" #define pg_clean_ascii_compat(a, b) pg_clean_ascii(a, b) #define RelationPhysicalIdentifier_compat(a) ((a)->rd_locator) #define RelationTablespace_compat(a) (a.spcOid) #define RelationPhysicalIdentifierNumber_compat(a) (a.relNumber) #define RelationPhysicalIdentifierNumberPtr_compat(a) (a->relNumber) #define RelationPhysicalIdentifierBackend_compat(a) (a->smgr_rlocator.locator) #define float_abs(a) fabs(a) #define tuplesort_getdatum_compat(a, b, c, d, e, f) tuplesort_getdatum(a, b, c, d, e, f) static inline struct config_generic ** get_guc_variables_compat(int *gucCount) { return get_guc_variables(gucCount); } #define PG_FUNCNAME_MACRO __func__ #define stringToQualifiedNameList_compat(a) stringToQualifiedNameList(a, NULL) #define typeStringToTypeName_compat(a, b) typeStringToTypeName(a, b) #define get_relids_in_jointree_compat(a, b, c) get_relids_in_jointree(a, b, c) #define object_ownercheck(a, b, c) object_ownercheck(a, b, c) #define object_aclcheck(a, b, c, d) object_aclcheck(a, b, c, d) #define pgstat_fetch_stat_local_beentry(a) pgstat_get_local_beentry_by_index(a) #define have_createdb_privilege() have_createdb_privilege() #else #include "miscadmin.h" #include "catalog/pg_authid.h" #include "catalog/pg_class_d.h" #include "catalog/pg_database_d.h" #include "catalog/pg_namespace.h" #include "catalog/pg_proc_d.h" #include "storage/relfilenode.h" #include "utils/guc.h" #include "utils/guc_tables.h" #include "utils/syscache.h" #define pg_clean_ascii_compat(a, b) pg_clean_ascii(a) #define RelationPhysicalIdentifier_compat(a) ((a)->rd_node) #define RelationTablespace_compat(a) (a.spcNode) #define RelationPhysicalIdentifierNumber_compat(a) (a.relNode) #define RelationPhysicalIdentifierNumberPtr_compat(a) (a->relNode) #define RelationPhysicalIdentifierBackend_compat(a) (a->smgr_rnode.node) typedef RelFileNode RelFileLocator; typedef Oid RelFileNumber; #define RelidByRelfilenumber(a, b) RelidByRelfilenode(a, b) #define float_abs(a) Abs(a) #define tuplesort_getdatum_compat(a, b, c, d, e, f) tuplesort_getdatum(a, b, d, e, f) static inline struct config_generic ** get_guc_variables_compat(int *gucCount) { *gucCount = GetNumConfigOptions(); return get_guc_variables(); } #define stringToQualifiedNameList_compat(a) stringToQualifiedNameList(a) #define typeStringToTypeName_compat(a, b) typeStringToTypeName(a) #define get_relids_in_jointree_compat(a, b, c) get_relids_in_jointree(a, b) static inline bool object_ownercheck(Oid classid, Oid objectid, Oid roleid) { switch (classid) { case RelationRelationId: { return pg_class_ownercheck(objectid, roleid); } case NamespaceRelationId: { return pg_namespace_ownercheck(objectid, roleid); } case ProcedureRelationId: { return pg_proc_ownercheck(objectid, roleid); } case DatabaseRelationId: { return pg_database_ownercheck(objectid, roleid); } default: { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Missing classid:%d", classid))); } } } static inline AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode) { switch (classid) { case NamespaceRelationId: { return pg_namespace_aclcheck(objectid, roleid, mode); } case ProcedureRelationId: { return pg_proc_aclcheck(objectid, roleid, mode); } default: { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Missing classid:%d", classid))); } } } static inline bool have_createdb_privilege(void) { bool result = false; HeapTuple utup; /* Superusers can always do everything */ if (superuser()) { return true; } utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(GetUserId())); if (HeapTupleIsValid(utup)) { result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreatedb; ReleaseSysCache(utup); } return result; } typedef bool TU_UpdateIndexes; /* * we define RTEPermissionInfo for PG16 compatibility * There are some functions that need to include RTEPermissionInfo in their signature * for PG14/PG15 we pass a NULL argument in these functions */ typedef RangeTblEntry RTEPermissionInfo; #endif #define SetListCellPtr(a, b) ((a)->ptr_value = (b)) #define RangeTableEntryFromNSItem(a) ((a)->p_rte) #define fcGetArgValue(fc, n) ((fc)->args[n].value) #define fcGetArgNull(fc, n) ((fc)->args[n].isnull) #define fcSetArgExt(fc, n, val, is_null) \ (((fc)->args[n].isnull = (is_null)), ((fc)->args[n].value = (val))) #define fcSetArg(fc, n, value) fcSetArgExt(fc, n, value, false) #define fcSetArgNull(fc, n) fcSetArgExt(fc, n, (Datum) 0, true) #define CREATE_SEQUENCE_COMMAND \ "CREATE %sSEQUENCE IF NOT EXISTS %s AS %s INCREMENT BY " INT64_FORMAT \ " MINVALUE " INT64_FORMAT " MAXVALUE " INT64_FORMAT \ " START WITH " INT64_FORMAT " CACHE " INT64_FORMAT " %sCYCLE" #endif /* PG_VERSION_COMPAT_H */