summaryrefslogtreecommitdiffstats
path: root/src/include/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/utils')
-rw-r--r--src/include/utils/.gitignore5
-rw-r--r--src/include/utils/acl.h278
-rw-r--r--src/include/utils/aclchk_internal.h45
-rw-r--r--src/include/utils/array.h482
-rw-r--r--src/include/utils/arrayaccess.h118
-rw-r--r--src/include/utils/ascii.h84
-rw-r--r--src/include/utils/attoptcache.h28
-rw-r--r--src/include/utils/backend_progress.h45
-rw-r--r--src/include/utils/backend_status.h342
-rw-r--r--src/include/utils/builtins.h136
-rw-r--r--src/include/utils/bytea.h28
-rw-r--r--src/include/utils/cash.h35
-rw-r--r--src/include/utils/catcache.h231
-rw-r--r--src/include/utils/combocid.h28
-rw-r--r--src/include/utils/conffiles.h27
-rw-r--r--src/include/utils/date.h118
-rw-r--r--src/include/utils/datetime.h364
-rw-r--r--src/include/utils/datum.h76
-rw-r--r--src/include/utils/dsa.h127
-rw-r--r--src/include/utils/dynahash.h20
-rw-r--r--src/include/utils/elog.h545
-rw-r--r--src/include/utils/evtcache.h37
-rw-r--r--src/include/utils/expandeddatum.h170
-rw-r--r--src/include/utils/expandedrecord.h241
-rw-r--r--src/include/utils/float.h357
-rw-r--r--src/include/utils/fmgrtab.h49
-rw-r--r--src/include/utils/formatting.h33
-rw-r--r--src/include/utils/freepage.h99
-rw-r--r--src/include/utils/geo_decls.h285
-rw-r--r--src/include/utils/guc.h442
-rw-r--r--src/include/utils/guc_hooks.h163
-rw-r--r--src/include/utils/guc_tables.h322
-rw-r--r--src/include/utils/help_config.h17
-rw-r--r--src/include/utils/hsearch.h153
-rw-r--r--src/include/utils/index_selfuncs.h74
-rw-r--r--src/include/utils/inet.h184
-rw-r--r--src/include/utils/inval.h68
-rw-r--r--src/include/utils/json.h31
-rw-r--r--src/include/utils/jsonb.h439
-rw-r--r--src/include/utils/jsonfuncs.h66
-rw-r--r--src/include/utils/jsonpath.h264
-rw-r--r--src/include/utils/logtape.h77
-rw-r--r--src/include/utils/lsyscache.h212
-rw-r--r--src/include/utils/memdebug.h82
-rw-r--r--src/include/utils/memutils.h185
-rw-r--r--src/include/utils/memutils_internal.h136
-rw-r--r--src/include/utils/memutils_memorychunk.h237
-rw-r--r--src/include/utils/meson.build60
-rw-r--r--src/include/utils/multirangetypes.h150
-rw-r--r--src/include/utils/numeric.h105
-rw-r--r--src/include/utils/old_snapshot.h75
-rw-r--r--src/include/utils/palloc.h165
-rw-r--r--src/include/utils/partcache.h103
-rw-r--r--src/include/utils/pg_crc.h107
-rw-r--r--src/include/utils/pg_locale.h135
-rw-r--r--src/include/utils/pg_lsn.h38
-rw-r--r--src/include/utils/pg_rusage.h32
-rw-r--r--src/include/utils/pgstat_internal.h814
-rw-r--r--src/include/utils/pidfile.h56
-rw-r--r--src/include/utils/plancache.h236
-rw-r--r--src/include/utils/portal.h252
-rw-r--r--src/include/utils/ps_status.h47
-rw-r--r--src/include/utils/queryenvironment.h74
-rw-r--r--src/include/utils/rangetypes.h168
-rw-r--r--src/include/utils/regproc.h39
-rw-r--r--src/include/utils/rel.h712
-rw-r--r--src/include/utils/relcache.h158
-rw-r--r--src/include/utils/relfilenumbermap.h21
-rw-r--r--src/include/utils/relmapper.h73
-rw-r--r--src/include/utils/relptr.h93
-rw-r--r--src/include/utils/reltrigger.h81
-rw-r--r--src/include/utils/resowner.h86
-rw-r--r--src/include/utils/resowner_private.h117
-rw-r--r--src/include/utils/rls.h50
-rw-r--r--src/include/utils/ruleutils.h52
-rw-r--r--src/include/utils/sampling.h64
-rw-r--r--src/include/utils/selfuncs.h241
-rw-r--r--src/include/utils/sharedtuplestore.h61
-rw-r--r--src/include/utils/snapmgr.h181
-rw-r--r--src/include/utils/snapshot.h219
-rw-r--r--src/include/utils/sortsupport.h391
-rw-r--r--src/include/utils/spccache.h21
-rw-r--r--src/include/utils/syscache.h227
-rw-r--r--src/include/utils/timeout.h95
-rw-r--r--src/include/utils/timestamp.h147
-rw-r--r--src/include/utils/tuplesort.h445
-rw-r--r--src/include/utils/tuplestore.h91
-rw-r--r--src/include/utils/typcache.h209
-rw-r--r--src/include/utils/tzparser.h39
-rw-r--r--src/include/utils/usercontext.h26
-rw-r--r--src/include/utils/uuid.h42
-rw-r--r--src/include/utils/varbit.h89
-rw-r--r--src/include/utils/varlena.h53
-rw-r--r--src/include/utils/wait_event.h295
-rw-r--r--src/include/utils/xid8.h32
-rw-r--r--src/include/utils/xml.h94
96 files changed, 14746 insertions, 0 deletions
diff --git a/src/include/utils/.gitignore b/src/include/utils/.gitignore
new file mode 100644
index 0000000..05cfa7a
--- /dev/null
+++ b/src/include/utils/.gitignore
@@ -0,0 +1,5 @@
+/fmgroids.h
+/fmgrprotos.h
+/probes.h
+/errcodes.h
+/header-stamp
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
new file mode 100644
index 0000000..aba1afa
--- /dev/null
+++ b/src/include/utils/acl.h
@@ -0,0 +1,278 @@
+/*-------------------------------------------------------------------------
+ *
+ * acl.h
+ * Definition of (and support for) access control list data structures.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/acl.h
+ *
+ * NOTES
+ * An ACL array is simply an array of AclItems, representing the union
+ * of the privileges represented by the individual items. A zero-length
+ * array represents "no privileges".
+ *
+ * The order of items in the array is important as client utilities (in
+ * particular, pg_dump, though possibly other clients) expect to be able
+ * to issue GRANTs in the ordering of the items in the array. The reason
+ * this matters is that GRANTs WITH GRANT OPTION must be before any GRANTs
+ * which depend on it. This happens naturally in the backend during
+ * operations as we update ACLs in-place, new items are appended, and
+ * existing entries are only removed if there's no dependency on them (no
+ * GRANT can been based on it, or, if there was, those GRANTs are also
+ * removed).
+ *
+ * For backward-compatibility purposes we have to allow null ACL entries
+ * in system catalogs. A null ACL will be treated as meaning "default
+ * protection" (i.e., whatever acldefault() returns).
+ *-------------------------------------------------------------------------
+ */
+#ifndef ACL_H
+#define ACL_H
+
+#include "access/htup.h"
+#include "nodes/parsenodes.h"
+#include "parser/parse_node.h"
+#include "utils/snapshot.h"
+
+
+/*
+ * typedef AclMode is declared in parsenodes.h, also the individual privilege
+ * bit meanings are defined there
+ */
+
+#define ACL_ID_PUBLIC 0 /* placeholder for id in a PUBLIC acl item */
+
+/*
+ * AclItem
+ *
+ * Note: must be same size on all platforms, because the size is hardcoded
+ * in the pg_type.h entry for aclitem.
+ */
+typedef struct AclItem
+{
+ Oid ai_grantee; /* ID that this item grants privs to */
+ Oid ai_grantor; /* grantor of privs */
+ AclMode ai_privs; /* privilege bits */
+} AclItem;
+
+/*
+ * The upper 32 bits of the ai_privs field of an AclItem are the grant option
+ * bits, and the lower 32 bits are the actual privileges. We use "rights"
+ * to mean the combined grant option and privilege bits fields.
+ */
+#define ACLITEM_GET_PRIVS(item) ((item).ai_privs & 0xFFFFFFFF)
+#define ACLITEM_GET_GOPTIONS(item) (((item).ai_privs >> 32) & 0xFFFFFFFF)
+#define ACLITEM_GET_RIGHTS(item) ((item).ai_privs)
+
+#define ACL_GRANT_OPTION_FOR(privs) (((AclMode) (privs) & 0xFFFFFFFF) << 32)
+#define ACL_OPTION_TO_PRIVS(privs) (((AclMode) (privs) >> 32) & 0xFFFFFFFF)
+
+#define ACLITEM_SET_PRIVS(item,privs) \
+ ((item).ai_privs = ((item).ai_privs & ~((AclMode) 0xFFFFFFFF)) | \
+ ((AclMode) (privs) & 0xFFFFFFFF))
+#define ACLITEM_SET_GOPTIONS(item,goptions) \
+ ((item).ai_privs = ((item).ai_privs & ~(((AclMode) 0xFFFFFFFF) << 32)) | \
+ (((AclMode) (goptions) & 0xFFFFFFFF) << 32))
+#define ACLITEM_SET_RIGHTS(item,rights) \
+ ((item).ai_privs = (AclMode) (rights))
+
+#define ACLITEM_SET_PRIVS_GOPTIONS(item,privs,goptions) \
+ ((item).ai_privs = ((AclMode) (privs) & 0xFFFFFFFF) | \
+ (((AclMode) (goptions) & 0xFFFFFFFF) << 32))
+
+
+#define ACLITEM_ALL_PRIV_BITS ((AclMode) 0xFFFFFFFF)
+#define ACLITEM_ALL_GOPTION_BITS ((AclMode) 0xFFFFFFFF << 32)
+
+/*
+ * Definitions for convenient access to Acl (array of AclItem).
+ * These are standard PostgreSQL arrays, but are restricted to have one
+ * dimension and no nulls. We also ignore the lower bound when reading,
+ * and set it to one when writing.
+ *
+ * CAUTION: as of PostgreSQL 7.1, these arrays are toastable (just like all
+ * other array types). Therefore, be careful to detoast them with the
+ * macros provided, unless you know for certain that a particular array
+ * can't have been toasted.
+ */
+
+
+/*
+ * Acl a one-dimensional array of AclItem
+ */
+typedef struct ArrayType Acl;
+
+#define ACL_NUM(ACL) (ARR_DIMS(ACL)[0])
+#define ACL_DAT(ACL) ((AclItem *) ARR_DATA_PTR(ACL))
+#define ACL_N_SIZE(N) (ARR_OVERHEAD_NONULLS(1) + ((N) * sizeof(AclItem)))
+#define ACL_SIZE(ACL) ARR_SIZE(ACL)
+
+/*
+ * fmgr macros for these types
+ */
+#define DatumGetAclItemP(X) ((AclItem *) DatumGetPointer(X))
+#define PG_GETARG_ACLITEM_P(n) DatumGetAclItemP(PG_GETARG_DATUM(n))
+#define PG_RETURN_ACLITEM_P(x) PG_RETURN_POINTER(x)
+
+#define DatumGetAclP(X) ((Acl *) PG_DETOAST_DATUM(X))
+#define DatumGetAclPCopy(X) ((Acl *) PG_DETOAST_DATUM_COPY(X))
+#define PG_GETARG_ACL_P(n) DatumGetAclP(PG_GETARG_DATUM(n))
+#define PG_GETARG_ACL_P_COPY(n) DatumGetAclPCopy(PG_GETARG_DATUM(n))
+#define PG_RETURN_ACL_P(x) PG_RETURN_POINTER(x)
+
+/*
+ * ACL modification opcodes for aclupdate
+ */
+#define ACL_MODECHG_ADD 1
+#define ACL_MODECHG_DEL 2
+#define ACL_MODECHG_EQL 3
+
+/*
+ * External representations of the privilege bits --- aclitemin/aclitemout
+ * represent each possible privilege bit with a distinct 1-character code
+ */
+#define ACL_INSERT_CHR 'a' /* formerly known as "append" */
+#define ACL_SELECT_CHR 'r' /* formerly known as "read" */
+#define ACL_UPDATE_CHR 'w' /* formerly known as "write" */
+#define ACL_DELETE_CHR 'd'
+#define ACL_TRUNCATE_CHR 'D' /* super-delete, as it were */
+#define ACL_REFERENCES_CHR 'x'
+#define ACL_TRIGGER_CHR 't'
+#define ACL_EXECUTE_CHR 'X'
+#define ACL_USAGE_CHR 'U'
+#define ACL_CREATE_CHR 'C'
+#define ACL_CREATE_TEMP_CHR 'T'
+#define ACL_CONNECT_CHR 'c'
+#define ACL_SET_CHR 's'
+#define ACL_ALTER_SYSTEM_CHR 'A'
+
+/* string holding all privilege code chars, in order by bitmask position */
+#define ACL_ALL_RIGHTS_STR "arwdDxtXUCTcsA"
+
+/*
+ * Bitmasks defining "all rights" for each supported object type
+ */
+#define ACL_ALL_RIGHTS_COLUMN (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_REFERENCES)
+#define ACL_ALL_RIGHTS_RELATION (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_TRUNCATE|ACL_REFERENCES|ACL_TRIGGER)
+#define ACL_ALL_RIGHTS_SEQUENCE (ACL_USAGE|ACL_SELECT|ACL_UPDATE)
+#define ACL_ALL_RIGHTS_DATABASE (ACL_CREATE|ACL_CREATE_TEMP|ACL_CONNECT)
+#define ACL_ALL_RIGHTS_FDW (ACL_USAGE)
+#define ACL_ALL_RIGHTS_FOREIGN_SERVER (ACL_USAGE)
+#define ACL_ALL_RIGHTS_FUNCTION (ACL_EXECUTE)
+#define ACL_ALL_RIGHTS_LANGUAGE (ACL_USAGE)
+#define ACL_ALL_RIGHTS_LARGEOBJECT (ACL_SELECT|ACL_UPDATE)
+#define ACL_ALL_RIGHTS_PARAMETER_ACL (ACL_SET|ACL_ALTER_SYSTEM)
+#define ACL_ALL_RIGHTS_SCHEMA (ACL_USAGE|ACL_CREATE)
+#define ACL_ALL_RIGHTS_TABLESPACE (ACL_CREATE)
+#define ACL_ALL_RIGHTS_TYPE (ACL_USAGE)
+
+/* operation codes for pg_*_aclmask */
+typedef enum
+{
+ ACLMASK_ALL, /* normal case: compute all bits */
+ ACLMASK_ANY /* return when result is known nonzero */
+} AclMaskHow;
+
+/* result codes for pg_*_aclcheck */
+typedef enum
+{
+ ACLCHECK_OK = 0,
+ ACLCHECK_NO_PRIV,
+ ACLCHECK_NOT_OWNER
+} AclResult;
+
+
+/*
+ * routines used internally
+ */
+extern Acl *acldefault(ObjectType objtype, Oid ownerId);
+extern Acl *get_user_default_acl(ObjectType objtype, Oid ownerId,
+ Oid nsp_oid);
+extern void recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId,
+ Oid ownerId, Acl *acl);
+
+extern Acl *aclupdate(const Acl *old_acl, const AclItem *mod_aip,
+ int modechg, Oid ownerId, DropBehavior behavior);
+extern Acl *aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId);
+extern Acl *make_empty_acl(void);
+extern Acl *aclcopy(const Acl *orig_acl);
+extern Acl *aclconcat(const Acl *left_acl, const Acl *right_acl);
+extern Acl *aclmerge(const Acl *left_acl, const Acl *right_acl, Oid ownerId);
+extern void aclitemsort(Acl *acl);
+extern bool aclequal(const Acl *left_acl, const Acl *right_acl);
+
+extern AclMode aclmask(const Acl *acl, Oid roleid, Oid ownerId,
+ AclMode mask, AclMaskHow how);
+extern int aclmembers(const Acl *acl, Oid **roleids);
+
+extern bool has_privs_of_role(Oid member, Oid role);
+extern bool member_can_set_role(Oid member, Oid role);
+extern void check_can_set_role(Oid member, Oid role);
+extern bool is_member_of_role(Oid member, Oid role);
+extern bool is_member_of_role_nosuper(Oid member, Oid role);
+extern bool is_admin_of_role(Oid member, Oid role);
+extern Oid select_best_admin(Oid member, Oid role);
+extern Oid get_role_oid(const char *rolname, bool missing_ok);
+extern Oid get_role_oid_or_public(const char *rolname);
+extern Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok);
+extern void check_rolespec_name(const RoleSpec *role, const char *detail_msg);
+extern HeapTuple get_rolespec_tuple(const RoleSpec *role);
+extern char *get_rolespec_name(const RoleSpec *role);
+
+extern void select_best_grantor(Oid roleId, AclMode privileges,
+ const Acl *acl, Oid ownerId,
+ Oid *grantorId, AclMode *grantOptions);
+
+extern void initialize_acl(void);
+
+/*
+ * prototypes for functions in aclchk.c
+ */
+extern void ExecuteGrantStmt(GrantStmt *stmt);
+extern void ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *stmt);
+
+extern void RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid);
+
+extern AclMode pg_class_aclmask(Oid table_oid, Oid roleid,
+ AclMode mask, AclMaskHow how);
+
+/* generic function */
+extern AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode);
+
+/* special cases */
+extern AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum,
+ Oid roleid, AclMode mode);
+extern AclResult pg_attribute_aclcheck_ext(Oid table_oid, AttrNumber attnum,
+ Oid roleid, AclMode mode,
+ bool *is_missing);
+extern AclResult pg_attribute_aclcheck_all(Oid table_oid, Oid roleid,
+ AclMode mode, AclMaskHow how);
+extern AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode);
+extern AclResult pg_class_aclcheck_ext(Oid table_oid, Oid roleid,
+ AclMode mode, bool *is_missing);
+extern AclResult pg_parameter_aclcheck(const char *name, Oid roleid,
+ AclMode mode);
+extern AclResult pg_largeobject_aclcheck_snapshot(Oid lobj_oid, Oid roleid,
+ AclMode mode, Snapshot snapshot);
+
+extern void aclcheck_error(AclResult aclerr, ObjectType objtype,
+ const char *objectname);
+
+extern void aclcheck_error_col(AclResult aclerr, ObjectType objtype,
+ const char *objectname, const char *colname);
+
+extern void aclcheck_error_type(AclResult aclerr, Oid typeOid);
+
+extern void recordExtObjInitPriv(Oid objoid, Oid classoid);
+extern void removeExtObjInitPriv(Oid objoid, Oid classoid);
+
+
+/* ownercheck routines just return true (owner) or false (not) */
+extern bool object_ownercheck(Oid classid, Oid objectid, Oid roleid);
+extern bool has_createrole_privilege(Oid roleid);
+extern bool has_bypassrls_privilege(Oid roleid);
+
+#endif /* ACL_H */
diff --git a/src/include/utils/aclchk_internal.h b/src/include/utils/aclchk_internal.h
new file mode 100644
index 0000000..55af624
--- /dev/null
+++ b/src/include/utils/aclchk_internal.h
@@ -0,0 +1,45 @@
+/*-------------------------------------------------------------------------
+ *
+ * aclchk_internal.h
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/aclchk_internal.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ACLCHK_INTERNAL_H
+#define ACLCHK_INTERNAL_H
+
+#include "nodes/parsenodes.h"
+#include "nodes/pg_list.h"
+
+/*
+ * The information about one Grant/Revoke statement, in internal format: object
+ * and grantees names have been turned into Oids, the privilege list is an
+ * AclMode bitmask. If 'privileges' is ACL_NO_RIGHTS (the 0 value) and
+ * all_privs is true, 'privileges' will be internally set to the right kind of
+ * ACL_ALL_RIGHTS_*, depending on the object type (NB - this will modify the
+ * InternalGrant struct!)
+ *
+ * Note: 'all_privs' and 'privileges' represent object-level privileges only.
+ * There might also be column-level privilege specifications, which are
+ * represented in col_privs (this is a list of untransformed AccessPriv nodes).
+ * Column privileges are only valid for objtype OBJECT_TABLE.
+ */
+typedef struct
+{
+ bool is_grant;
+ ObjectType objtype;
+ List *objects;
+ bool all_privs;
+ AclMode privileges;
+ List *col_privs;
+ List *grantees;
+ bool grant_option;
+ DropBehavior behavior;
+} InternalGrant;
+
+
+#endif /* ACLCHK_INTERNAL_H */
diff --git a/src/include/utils/array.h b/src/include/utils/array.h
new file mode 100644
index 0000000..e6c8d88
--- /dev/null
+++ b/src/include/utils/array.h
@@ -0,0 +1,482 @@
+/*-------------------------------------------------------------------------
+ *
+ * array.h
+ * Declarations for Postgres arrays.
+ *
+ * A standard varlena array has the following internal structure:
+ * <vl_len_> - standard varlena header word
+ * <ndim> - number of dimensions of the array
+ * <dataoffset> - offset to stored data, or 0 if no nulls bitmap
+ * <elemtype> - element type OID
+ * <dimensions> - length of each array axis (C array of int)
+ * <lower bnds> - lower boundary of each dimension (C array of int)
+ * <null bitmap> - bitmap showing locations of nulls (OPTIONAL)
+ * <actual data> - whatever is the stored data
+ *
+ * The <dimensions> and <lower bnds> arrays each have ndim elements.
+ *
+ * The <null bitmap> may be omitted if the array contains no NULL elements.
+ * If it is absent, the <dataoffset> field is zero and the offset to the
+ * stored data must be computed on-the-fly. If the bitmap is present,
+ * <dataoffset> is nonzero and is equal to the offset from the array start
+ * to the first data element (including any alignment padding). The bitmap
+ * follows the same conventions as tuple null bitmaps, ie, a 1 indicates
+ * a non-null entry and the LSB of each bitmap byte is used first.
+ *
+ * The actual data starts on a MAXALIGN boundary. Individual items in the
+ * array are aligned as specified by the array element type. They are
+ * stored in row-major order (last subscript varies most rapidly).
+ *
+ * NOTE: it is important that array elements of toastable datatypes NOT be
+ * toasted, since the tupletoaster won't know they are there. (We could
+ * support compressed toasted items; only out-of-line items are dangerous.
+ * However, it seems preferable to store such items uncompressed and allow
+ * the toaster to compress the whole array as one input.)
+ *
+ *
+ * The OIDVECTOR and INT2VECTOR datatypes are storage-compatible with
+ * generic arrays, but they support only one-dimensional arrays with no
+ * nulls (and no null bitmap). They don't support being toasted, either.
+ *
+ * There are also some "fixed-length array" datatypes, such as NAME and
+ * POINT. These are simply a sequence of a fixed number of items each
+ * of a fixed-length datatype, with no overhead; the item size must be
+ * a multiple of its alignment requirement, because we do no padding.
+ * We support subscripting on these types, but array_in() and array_out()
+ * only work with varlena arrays.
+ *
+ * In addition, arrays are a major user of the "expanded object" TOAST
+ * infrastructure. This allows a varlena array to be converted to a
+ * separate representation that may include "deconstructed" Datum/isnull
+ * arrays holding the elements.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/array.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ARRAY_H
+#define ARRAY_H
+
+#include "fmgr.h"
+#include "utils/expandeddatum.h"
+
+/* avoid including execnodes.h here */
+struct ExprState;
+struct ExprContext;
+
+
+/*
+ * Maximum number of array subscripts (arbitrary limit)
+ */
+#define MAXDIM 6
+
+/*
+ * Maximum number of elements in an array. We limit this to at most about a
+ * quarter billion elements, so that it's not necessary to check for overflow
+ * in quite so many places --- for instance when palloc'ing Datum arrays.
+ */
+#define MaxArraySize ((Size) (MaxAllocSize / sizeof(Datum)))
+
+/*
+ * Arrays are varlena objects, so must meet the varlena convention that
+ * the first int32 of the object contains the total object size in bytes.
+ * Be sure to use VARSIZE() and SET_VARSIZE() to access it, though!
+ *
+ * CAUTION: if you change the header for ordinary arrays you will also
+ * need to change the headers for oidvector and int2vector!
+ */
+typedef struct ArrayType
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ int ndim; /* # of dimensions */
+ int32 dataoffset; /* offset to data, or 0 if no bitmap */
+ Oid elemtype; /* element type OID */
+} ArrayType;
+
+/*
+ * An expanded array is contained within a private memory context (as
+ * all expanded objects must be) and has a control structure as below.
+ *
+ * The expanded array might contain a regular "flat" array if that was the
+ * original input and we've not modified it significantly. Otherwise, the
+ * contents are represented by Datum/isnull arrays plus dimensionality and
+ * type information. We could also have both forms, if we've deconstructed
+ * the original array for access purposes but not yet changed it. For pass-
+ * by-reference element types, the Datums would point into the flat array in
+ * this situation. Once we start modifying array elements, new pass-by-ref
+ * elements are separately palloc'd within the memory context.
+ */
+#define EA_MAGIC 689375833 /* ID for debugging crosschecks */
+
+typedef struct ExpandedArrayHeader
+{
+ /* Standard header for expanded objects */
+ ExpandedObjectHeader hdr;
+
+ /* Magic value identifying an expanded array (for debugging only) */
+ int ea_magic;
+
+ /* Dimensionality info (always valid) */
+ int ndims; /* # of dimensions */
+ int *dims; /* array dimensions */
+ int *lbound; /* index lower bounds for each dimension */
+
+ /* Element type info (always valid) */
+ Oid element_type; /* element type OID */
+ int16 typlen; /* needed info about element datatype */
+ bool typbyval;
+ char typalign;
+
+ /*
+ * If we have a Datum-array representation of the array, it's kept here;
+ * else dvalues/dnulls are NULL. The dvalues and dnulls arrays are always
+ * palloc'd within the object private context, but may change size from
+ * time to time. For pass-by-ref element types, dvalues entries might
+ * point either into the fstartptr..fendptr area, or to separately
+ * palloc'd chunks. Elements should always be fully detoasted, as they
+ * are in the standard flat representation.
+ *
+ * Even when dvalues is valid, dnulls can be NULL if there are no null
+ * elements.
+ */
+ Datum *dvalues; /* array of Datums */
+ bool *dnulls; /* array of is-null flags for Datums */
+ int dvalueslen; /* allocated length of above arrays */
+ int nelems; /* number of valid entries in above arrays */
+
+ /*
+ * flat_size is the current space requirement for the flat equivalent of
+ * the expanded array, if known; otherwise it's 0. We store this to make
+ * consecutive calls of get_flat_size cheap.
+ */
+ Size flat_size;
+
+ /*
+ * fvalue points to the flat representation if it is valid, else it is
+ * NULL. If we have or ever had a flat representation then
+ * fstartptr/fendptr point to the start and end+1 of its data area; this
+ * is so that we can tell which Datum pointers point into the flat
+ * representation rather than being pointers to separately palloc'd data.
+ */
+ ArrayType *fvalue; /* must be a fully detoasted array */
+ char *fstartptr; /* start of its data area */
+ char *fendptr; /* end+1 of its data area */
+} ExpandedArrayHeader;
+
+/*
+ * Functions that can handle either a "flat" varlena array or an expanded
+ * array use this union to work with their input. Don't refer to "flt";
+ * instead, cast to ArrayType. This struct nominally requires 8-byte
+ * alignment on 64-bit, but it's often used for an ArrayType having 4-byte
+ * alignment. UBSan complains about referencing "flt" in such cases.
+ */
+typedef union AnyArrayType
+{
+ ArrayType flt;
+ ExpandedArrayHeader xpn;
+} AnyArrayType;
+
+/*
+ * working state for accumArrayResult() and friends
+ * note that the input must be scalars (legal array elements)
+ */
+typedef struct ArrayBuildState
+{
+ MemoryContext mcontext; /* where all the temp stuff is kept */
+ Datum *dvalues; /* array of accumulated Datums */
+ bool *dnulls; /* array of is-null flags for Datums */
+ int alen; /* allocated length of above arrays */
+ int nelems; /* number of valid entries in above arrays */
+ Oid element_type; /* data type of the Datums */
+ int16 typlen; /* needed info about datatype */
+ bool typbyval;
+ char typalign;
+ bool private_cxt; /* use private memory context */
+} ArrayBuildState;
+
+/*
+ * working state for accumArrayResultArr() and friends
+ * note that the input must be arrays, and the same array type is returned
+ */
+typedef struct ArrayBuildStateArr
+{
+ MemoryContext mcontext; /* where all the temp stuff is kept */
+ char *data; /* accumulated data */
+ bits8 *nullbitmap; /* bitmap of is-null flags, or NULL if none */
+ int abytes; /* allocated length of "data" */
+ int nbytes; /* number of bytes used so far */
+ int aitems; /* allocated length of bitmap (in elements) */
+ int nitems; /* total number of elements in result */
+ int ndims; /* current dimensions of result */
+ int dims[MAXDIM];
+ int lbs[MAXDIM];
+ Oid array_type; /* data type of the arrays */
+ Oid element_type; /* data type of the array elements */
+ bool private_cxt; /* use private memory context */
+} ArrayBuildStateArr;
+
+/*
+ * working state for accumArrayResultAny() and friends
+ * these functions handle both cases
+ */
+typedef struct ArrayBuildStateAny
+{
+ /* Exactly one of these is not NULL: */
+ ArrayBuildState *scalarstate;
+ ArrayBuildStateArr *arraystate;
+} ArrayBuildStateAny;
+
+/*
+ * structure to cache type metadata needed for array manipulation
+ */
+typedef struct ArrayMetaState
+{
+ Oid element_type;
+ int16 typlen;
+ bool typbyval;
+ char typalign;
+ char typdelim;
+ Oid typioparam;
+ Oid typiofunc;
+ FmgrInfo proc;
+} ArrayMetaState;
+
+/*
+ * private state needed by array_map (here because caller must provide it)
+ */
+typedef struct ArrayMapState
+{
+ ArrayMetaState inp_extra;
+ ArrayMetaState ret_extra;
+} ArrayMapState;
+
+/* ArrayIteratorData is private in arrayfuncs.c */
+typedef struct ArrayIteratorData *ArrayIterator;
+
+/* fmgr macros for regular varlena array objects */
+#define DatumGetArrayTypeP(X) ((ArrayType *) PG_DETOAST_DATUM(X))
+#define DatumGetArrayTypePCopy(X) ((ArrayType *) PG_DETOAST_DATUM_COPY(X))
+#define PG_GETARG_ARRAYTYPE_P(n) DatumGetArrayTypeP(PG_GETARG_DATUM(n))
+#define PG_GETARG_ARRAYTYPE_P_COPY(n) DatumGetArrayTypePCopy(PG_GETARG_DATUM(n))
+#define PG_RETURN_ARRAYTYPE_P(x) PG_RETURN_POINTER(x)
+
+/* fmgr macros for expanded array objects */
+#define PG_GETARG_EXPANDED_ARRAY(n) DatumGetExpandedArray(PG_GETARG_DATUM(n))
+#define PG_GETARG_EXPANDED_ARRAYX(n, metacache) \
+ DatumGetExpandedArrayX(PG_GETARG_DATUM(n), metacache)
+#define PG_RETURN_EXPANDED_ARRAY(x) PG_RETURN_DATUM(EOHPGetRWDatum(&(x)->hdr))
+
+/* fmgr macros for AnyArrayType (ie, get either varlena or expanded form) */
+#define PG_GETARG_ANY_ARRAY_P(n) DatumGetAnyArrayP(PG_GETARG_DATUM(n))
+
+/*
+ * Access macros for varlena array header fields.
+ *
+ * ARR_DIMS returns a pointer to an array of array dimensions (number of
+ * elements along the various array axes).
+ *
+ * ARR_LBOUND returns a pointer to an array of array lower bounds.
+ *
+ * That is: if the third axis of an array has elements 5 through 8, then
+ * ARR_DIMS(a)[2] == 4 and ARR_LBOUND(a)[2] == 5.
+ *
+ * Unlike C, the default lower bound is 1.
+ */
+#define ARR_SIZE(a) VARSIZE(a)
+#define ARR_NDIM(a) ((a)->ndim)
+#define ARR_HASNULL(a) ((a)->dataoffset != 0)
+#define ARR_ELEMTYPE(a) ((a)->elemtype)
+
+#define ARR_DIMS(a) \
+ ((int *) (((char *) (a)) + sizeof(ArrayType)))
+#define ARR_LBOUND(a) \
+ ((int *) (((char *) (a)) + sizeof(ArrayType) + \
+ sizeof(int) * ARR_NDIM(a)))
+
+#define ARR_NULLBITMAP(a) \
+ (ARR_HASNULL(a) ? \
+ (bits8 *) (((char *) (a)) + sizeof(ArrayType) + \
+ 2 * sizeof(int) * ARR_NDIM(a)) \
+ : (bits8 *) NULL)
+
+/*
+ * The total array header size (in bytes) for an array with the specified
+ * number of dimensions and total number of items.
+ */
+#define ARR_OVERHEAD_NONULLS(ndims) \
+ MAXALIGN(sizeof(ArrayType) + 2 * sizeof(int) * (ndims))
+#define ARR_OVERHEAD_WITHNULLS(ndims, nitems) \
+ MAXALIGN(sizeof(ArrayType) + 2 * sizeof(int) * (ndims) + \
+ ((nitems) + 7) / 8)
+
+#define ARR_DATA_OFFSET(a) \
+ (ARR_HASNULL(a) ? (a)->dataoffset : ARR_OVERHEAD_NONULLS(ARR_NDIM(a)))
+
+/*
+ * Returns a pointer to the actual array data.
+ */
+#define ARR_DATA_PTR(a) \
+ (((char *) (a)) + ARR_DATA_OFFSET(a))
+
+/*
+ * Macros for working with AnyArrayType inputs. Beware multiple references!
+ */
+#define AARR_NDIM(a) \
+ (VARATT_IS_EXPANDED_HEADER(a) ? \
+ (a)->xpn.ndims : ARR_NDIM((ArrayType *) (a)))
+#define AARR_HASNULL(a) \
+ (VARATT_IS_EXPANDED_HEADER(a) ? \
+ ((a)->xpn.dvalues != NULL ? (a)->xpn.dnulls != NULL : ARR_HASNULL((a)->xpn.fvalue)) : \
+ ARR_HASNULL((ArrayType *) (a)))
+#define AARR_ELEMTYPE(a) \
+ (VARATT_IS_EXPANDED_HEADER(a) ? \
+ (a)->xpn.element_type : ARR_ELEMTYPE((ArrayType *) (a)))
+#define AARR_DIMS(a) \
+ (VARATT_IS_EXPANDED_HEADER(a) ? \
+ (a)->xpn.dims : ARR_DIMS((ArrayType *) (a)))
+#define AARR_LBOUND(a) \
+ (VARATT_IS_EXPANDED_HEADER(a) ? \
+ (a)->xpn.lbound : ARR_LBOUND((ArrayType *) (a)))
+
+
+/*
+ * GUC parameter
+ */
+extern PGDLLIMPORT bool Array_nulls;
+
+/*
+ * prototypes for functions defined in arrayfuncs.c
+ */
+extern void CopyArrayEls(ArrayType *array,
+ Datum *values,
+ bool *nulls,
+ int nitems,
+ int typlen,
+ bool typbyval,
+ char typalign,
+ bool freedata);
+
+extern Datum array_get_element(Datum arraydatum, int nSubscripts, int *indx,
+ int arraytyplen, int elmlen, bool elmbyval, char elmalign,
+ bool *isNull);
+extern Datum array_set_element(Datum arraydatum, int nSubscripts, int *indx,
+ Datum dataValue, bool isNull,
+ int arraytyplen, int elmlen, bool elmbyval, char elmalign);
+extern Datum array_get_slice(Datum arraydatum, int nSubscripts,
+ int *upperIndx, int *lowerIndx,
+ bool *upperProvided, bool *lowerProvided,
+ int arraytyplen, int elmlen, bool elmbyval, char elmalign);
+extern Datum array_set_slice(Datum arraydatum, int nSubscripts,
+ int *upperIndx, int *lowerIndx,
+ bool *upperProvided, bool *lowerProvided,
+ Datum srcArrayDatum, bool isNull,
+ int arraytyplen, int elmlen, bool elmbyval, char elmalign);
+
+extern Datum array_ref(ArrayType *array, int nSubscripts, int *indx,
+ int arraytyplen, int elmlen, bool elmbyval, char elmalign,
+ bool *isNull);
+extern ArrayType *array_set(ArrayType *array, int nSubscripts, int *indx,
+ Datum dataValue, bool isNull,
+ int arraytyplen, int elmlen, bool elmbyval, char elmalign);
+
+extern Datum array_map(Datum arrayd,
+ struct ExprState *exprstate, struct ExprContext *econtext,
+ Oid retType, ArrayMapState *amstate);
+
+extern void array_bitmap_copy(bits8 *destbitmap, int destoffset,
+ const bits8 *srcbitmap, int srcoffset,
+ int nitems);
+
+extern ArrayType *construct_array(Datum *elems, int nelems,
+ Oid elmtype,
+ int elmlen, bool elmbyval, char elmalign);
+extern ArrayType *construct_array_builtin(Datum *elems, int nelems, Oid elmtype);
+extern ArrayType *construct_md_array(Datum *elems,
+ bool *nulls,
+ int ndims,
+ int *dims,
+ int *lbs,
+ Oid elmtype, int elmlen, bool elmbyval, char elmalign);
+extern ArrayType *construct_empty_array(Oid elmtype);
+extern ExpandedArrayHeader *construct_empty_expanded_array(Oid element_type,
+ MemoryContext parentcontext,
+ ArrayMetaState *metacache);
+extern void deconstruct_array(ArrayType *array,
+ Oid elmtype,
+ int elmlen, bool elmbyval, char elmalign,
+ Datum **elemsp, bool **nullsp, int *nelemsp);
+extern void deconstruct_array_builtin(ArrayType *array,
+ Oid elmtype,
+ Datum **elemsp, bool **nullsp, int *nelemsp);
+extern bool array_contains_nulls(ArrayType *array);
+
+extern ArrayBuildState *initArrayResult(Oid element_type,
+ MemoryContext rcontext, bool subcontext);
+extern ArrayBuildState *initArrayResultWithSize(Oid element_type,
+ MemoryContext rcontext,
+ bool subcontext, int initsize);
+extern ArrayBuildState *accumArrayResult(ArrayBuildState *astate,
+ Datum dvalue, bool disnull,
+ Oid element_type,
+ MemoryContext rcontext);
+extern Datum makeArrayResult(ArrayBuildState *astate,
+ MemoryContext rcontext);
+extern Datum makeMdArrayResult(ArrayBuildState *astate, int ndims,
+ int *dims, int *lbs, MemoryContext rcontext, bool release);
+
+extern ArrayBuildStateArr *initArrayResultArr(Oid array_type, Oid element_type,
+ MemoryContext rcontext, bool subcontext);
+extern ArrayBuildStateArr *accumArrayResultArr(ArrayBuildStateArr *astate,
+ Datum dvalue, bool disnull,
+ Oid array_type,
+ MemoryContext rcontext);
+extern Datum makeArrayResultArr(ArrayBuildStateArr *astate,
+ MemoryContext rcontext, bool release);
+
+extern ArrayBuildStateAny *initArrayResultAny(Oid input_type,
+ MemoryContext rcontext, bool subcontext);
+extern ArrayBuildStateAny *accumArrayResultAny(ArrayBuildStateAny *astate,
+ Datum dvalue, bool disnull,
+ Oid input_type,
+ MemoryContext rcontext);
+extern Datum makeArrayResultAny(ArrayBuildStateAny *astate,
+ MemoryContext rcontext, bool release);
+
+extern ArrayIterator array_create_iterator(ArrayType *arr, int slice_ndim, ArrayMetaState *mstate);
+extern bool array_iterate(ArrayIterator iterator, Datum *value, bool *isnull);
+extern void array_free_iterator(ArrayIterator iterator);
+
+/*
+ * prototypes for functions defined in arrayutils.c
+ */
+
+extern int ArrayGetOffset(int n, const int *dim, const int *lb, const int *indx);
+extern int ArrayGetOffset0(int n, const int *tup, const int *scale);
+extern int ArrayGetNItems(int ndim, const int *dims);
+extern int ArrayGetNItemsSafe(int ndim, const int *dims,
+ struct Node *escontext);
+extern void ArrayCheckBounds(int ndim, const int *dims, const int *lb);
+extern bool ArrayCheckBoundsSafe(int ndim, const int *dims, const int *lb,
+ struct Node *escontext);
+extern void mda_get_range(int n, int *span, const int *st, const int *endp);
+extern void mda_get_prod(int n, const int *range, int *prod);
+extern void mda_get_offset_values(int n, int *dist, const int *prod, const int *span);
+extern int mda_next_tuple(int n, int *curr, const int *span);
+extern int32 *ArrayGetIntegerTypmods(ArrayType *arr, int *n);
+
+/*
+ * prototypes for functions defined in array_expanded.c
+ */
+extern Datum expand_array(Datum arraydatum, MemoryContext parentcontext,
+ ArrayMetaState *metacache);
+extern ExpandedArrayHeader *DatumGetExpandedArray(Datum d);
+extern ExpandedArrayHeader *DatumGetExpandedArrayX(Datum d,
+ ArrayMetaState *metacache);
+extern AnyArrayType *DatumGetAnyArrayP(Datum d);
+extern void deconstruct_expanded_array(ExpandedArrayHeader *eah);
+
+#endif /* ARRAY_H */
diff --git a/src/include/utils/arrayaccess.h b/src/include/utils/arrayaccess.h
new file mode 100644
index 0000000..fd267d5
--- /dev/null
+++ b/src/include/utils/arrayaccess.h
@@ -0,0 +1,118 @@
+/*-------------------------------------------------------------------------
+ *
+ * arrayaccess.h
+ * Declarations for element-by-element access to Postgres arrays.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/arrayaccess.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ARRAYACCESS_H
+#define ARRAYACCESS_H
+
+#include "access/tupmacs.h"
+#include "utils/array.h"
+
+
+/*
+ * Functions for iterating through elements of a flat or expanded array.
+ * These require a state struct "array_iter iter".
+ *
+ * Use "array_iter_setup(&iter, arrayptr);" to prepare to iterate, and
+ * "datumvar = array_iter_next(&iter, &isnullvar, index, ...);" to fetch
+ * the next element into datumvar/isnullvar.
+ * "index" must be the zero-origin element number; we make caller provide
+ * this since caller is generally counting the elements anyway. Despite
+ * that, these functions can only fetch elements sequentially.
+ */
+
+typedef struct array_iter
+{
+ /* datumptr being NULL or not tells if we have flat or expanded array */
+
+ /* Fields used when we have an expanded array */
+ Datum *datumptr; /* Pointer to Datum array */
+ bool *isnullptr; /* Pointer to isnull array */
+
+ /* Fields used when we have a flat array */
+ char *dataptr; /* Current spot in the data area */
+ bits8 *bitmapptr; /* Current byte of the nulls bitmap, or NULL */
+ int bitmask; /* mask for current bit in nulls bitmap */
+} array_iter;
+
+
+static inline void
+array_iter_setup(array_iter *it, AnyArrayType *a)
+{
+ if (VARATT_IS_EXPANDED_HEADER(a))
+ {
+ if (a->xpn.dvalues)
+ {
+ it->datumptr = a->xpn.dvalues;
+ it->isnullptr = a->xpn.dnulls;
+ /* we must fill all fields to prevent compiler warnings */
+ it->dataptr = NULL;
+ it->bitmapptr = NULL;
+ }
+ else
+ {
+ /* Work with flat array embedded in the expanded datum */
+ it->datumptr = NULL;
+ it->isnullptr = NULL;
+ it->dataptr = ARR_DATA_PTR(a->xpn.fvalue);
+ it->bitmapptr = ARR_NULLBITMAP(a->xpn.fvalue);
+ }
+ }
+ else
+ {
+ it->datumptr = NULL;
+ it->isnullptr = NULL;
+ it->dataptr = ARR_DATA_PTR((ArrayType *) a);
+ it->bitmapptr = ARR_NULLBITMAP((ArrayType *) a);
+ }
+ it->bitmask = 1;
+}
+
+static inline Datum
+array_iter_next(array_iter *it, bool *isnull, int i,
+ int elmlen, bool elmbyval, char elmalign)
+{
+ Datum ret;
+
+ if (it->datumptr)
+ {
+ ret = it->datumptr[i];
+ *isnull = it->isnullptr ? it->isnullptr[i] : false;
+ }
+ else
+ {
+ if (it->bitmapptr && (*(it->bitmapptr) & it->bitmask) == 0)
+ {
+ *isnull = true;
+ ret = (Datum) 0;
+ }
+ else
+ {
+ *isnull = false;
+ ret = fetch_att(it->dataptr, elmbyval, elmlen);
+ it->dataptr = att_addlength_pointer(it->dataptr, elmlen,
+ it->dataptr);
+ it->dataptr = (char *) att_align_nominal(it->dataptr, elmalign);
+ }
+ it->bitmask <<= 1;
+ if (it->bitmask == 0x100)
+ {
+ if (it->bitmapptr)
+ it->bitmapptr++;
+ it->bitmask = 1;
+ }
+ }
+
+ return ret;
+}
+
+#endif /* ARRAYACCESS_H */
diff --git a/src/include/utils/ascii.h b/src/include/utils/ascii.h
new file mode 100644
index 0000000..7df024d
--- /dev/null
+++ b/src/include/utils/ascii.h
@@ -0,0 +1,84 @@
+/*-----------------------------------------------------------------------
+ * ascii.h
+ *
+ * Portions Copyright (c) 1999-2023, PostgreSQL Global Development Group
+ *
+ * src/include/utils/ascii.h
+ *
+ *-----------------------------------------------------------------------
+ */
+
+#ifndef _ASCII_H_
+#define _ASCII_H_
+
+#include "port/simd.h"
+
+extern void ascii_safe_strlcpy(char *dest, const char *src, size_t destsiz);
+
+/*
+ * Verify a chunk of bytes for valid ASCII.
+ *
+ * Returns false if the input contains any zero bytes or bytes with the
+ * high-bit set. Input len must be a multiple of the chunk size (8 or 16).
+ */
+static inline bool
+is_valid_ascii(const unsigned char *s, int len)
+{
+ const unsigned char *const s_end = s + len;
+ Vector8 chunk;
+ Vector8 highbit_cum = vector8_broadcast(0);
+#ifdef USE_NO_SIMD
+ Vector8 zero_cum = vector8_broadcast(0x80);
+#endif
+
+ Assert(len % sizeof(chunk) == 0);
+
+ while (s < s_end)
+ {
+ vector8_load(&chunk, s);
+
+ /* Capture any zero bytes in this chunk. */
+#ifdef USE_NO_SIMD
+
+ /*
+ * First, add 0x7f to each byte. This sets the high bit in each byte,
+ * unless it was a zero. If any resulting high bits are zero, the
+ * corresponding high bits in the zero accumulator will be cleared.
+ *
+ * If none of the bytes in the chunk had the high bit set, the max
+ * value each byte can have after the addition is 0x7f + 0x7f = 0xfe,
+ * and we don't need to worry about carrying over to the next byte. If
+ * any input bytes did have the high bit set, it doesn't matter
+ * because we check for those separately.
+ */
+ zero_cum &= (chunk + vector8_broadcast(0x7F));
+#else
+
+ /*
+ * Set all bits in each lane of the highbit accumulator where input
+ * bytes are zero.
+ */
+ highbit_cum = vector8_or(highbit_cum,
+ vector8_eq(chunk, vector8_broadcast(0)));
+#endif
+
+ /* Capture all set bits in this chunk. */
+ highbit_cum = vector8_or(highbit_cum, chunk);
+
+ s += sizeof(chunk);
+ }
+
+ /* Check if any high bits in the high bit accumulator got set. */
+ if (vector8_is_highbit_set(highbit_cum))
+ return false;
+
+#ifdef USE_NO_SIMD
+ /* Check if any high bits in the zero accumulator got cleared. */
+ if (zero_cum != vector8_broadcast(0x80))
+ return false;
+#endif
+
+ return true;
+}
+
+#endif /* _ASCII_H_ */
diff --git a/src/include/utils/attoptcache.h b/src/include/utils/attoptcache.h
new file mode 100644
index 0000000..e4119b6
--- /dev/null
+++ b/src/include/utils/attoptcache.h
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+ *
+ * attoptcache.h
+ * Attribute options cache.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/attoptcache.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ATTOPTCACHE_H
+#define ATTOPTCACHE_H
+
+/*
+ * Attribute options.
+ */
+typedef struct AttributeOpts
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ float8 n_distinct;
+ float8 n_distinct_inherited;
+} AttributeOpts;
+
+extern AttributeOpts *get_attribute_options(Oid attrelid, int attnum);
+
+#endif /* ATTOPTCACHE_H */
diff --git a/src/include/utils/backend_progress.h b/src/include/utils/backend_progress.h
new file mode 100644
index 0000000..a84752a
--- /dev/null
+++ b/src/include/utils/backend_progress.h
@@ -0,0 +1,45 @@
+/* ----------
+ * backend_progress.h
+ * Command progress reporting definition.
+ *
+ * Note that this file provides the infrastructure for storing a single
+ * backend's command progress counters, without ascribing meaning to the
+ * individual fields. See commands/progress.h and system_views.sql for that.
+ *
+ * Copyright (c) 2001-2023, PostgreSQL Global Development Group
+ *
+ * src/include/utils/backend_progress.h
+ * ----------
+ */
+#ifndef BACKEND_PROGRESS_H
+#define BACKEND_PROGRESS_H
+
+
+/* ----------
+ * Command type for progress reporting purposes
+ * ----------
+ */
+typedef enum ProgressCommandType
+{
+ PROGRESS_COMMAND_INVALID,
+ PROGRESS_COMMAND_VACUUM,
+ PROGRESS_COMMAND_ANALYZE,
+ PROGRESS_COMMAND_CLUSTER,
+ PROGRESS_COMMAND_CREATE_INDEX,
+ PROGRESS_COMMAND_BASEBACKUP,
+ PROGRESS_COMMAND_COPY
+} ProgressCommandType;
+
+#define PGSTAT_NUM_PROGRESS_PARAM 20
+
+
+extern void pgstat_progress_start_command(ProgressCommandType cmdtype,
+ Oid relid);
+extern void pgstat_progress_update_param(int index, int64 val);
+extern void pgstat_progress_incr_param(int index, int64 incr);
+extern void pgstat_progress_update_multi_param(int nparam, const int *index,
+ const int64 *val);
+extern void pgstat_progress_end_command(void);
+
+
+#endif /* BACKEND_PROGRESS_H */
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
new file mode 100644
index 0000000..d51c840
--- /dev/null
+++ b/src/include/utils/backend_status.h
@@ -0,0 +1,342 @@
+/* ----------
+ * backend_status.h
+ * Definitions related to backend status reporting
+ *
+ * Copyright (c) 2001-2023, PostgreSQL Global Development Group
+ *
+ * src/include/utils/backend_status.h
+ * ----------
+ */
+#ifndef BACKEND_STATUS_H
+#define BACKEND_STATUS_H
+
+#include "datatype/timestamp.h"
+#include "libpq/pqcomm.h"
+#include "miscadmin.h" /* for BackendType */
+#include "storage/backendid.h"
+#include "utils/backend_progress.h"
+
+
+/* ----------
+ * Backend states
+ * ----------
+ */
+typedef enum BackendState
+{
+ STATE_UNDEFINED,
+ STATE_IDLE,
+ STATE_RUNNING,
+ STATE_IDLEINTRANSACTION,
+ STATE_FASTPATH,
+ STATE_IDLEINTRANSACTION_ABORTED,
+ STATE_DISABLED
+} BackendState;
+
+
+/* ----------
+ * Shared-memory data structures
+ * ----------
+ */
+
+/*
+ * PgBackendSSLStatus
+ *
+ * For each backend, we keep the SSL status in a separate struct, that
+ * is only filled in if SSL is enabled.
+ *
+ * All char arrays must be null-terminated.
+ */
+typedef struct PgBackendSSLStatus
+{
+ /* Information about SSL connection */
+ int ssl_bits;
+ char ssl_version[NAMEDATALEN];
+ char ssl_cipher[NAMEDATALEN];
+ char ssl_client_dn[NAMEDATALEN];
+
+ /*
+ * serial number is max "20 octets" per RFC 5280, so this size should be
+ * fine
+ */
+ char ssl_client_serial[NAMEDATALEN];
+
+ char ssl_issuer_dn[NAMEDATALEN];
+} PgBackendSSLStatus;
+
+/*
+ * PgBackendGSSStatus
+ *
+ * For each backend, we keep the GSS status in a separate struct, that
+ * is only filled in if GSS is enabled.
+ *
+ * All char arrays must be null-terminated.
+ */
+typedef struct PgBackendGSSStatus
+{
+ /* Information about GSSAPI connection */
+ char gss_princ[NAMEDATALEN]; /* GSSAPI Principal used to auth */
+ bool gss_auth; /* If GSSAPI authentication was used */
+ bool gss_enc; /* If encryption is being used */
+ bool gss_delegation; /* If credentials delegated */
+
+} PgBackendGSSStatus;
+
+
+/* ----------
+ * PgBackendStatus
+ *
+ * Each live backend maintains a PgBackendStatus struct in shared memory
+ * showing its current activity. (The structs are allocated according to
+ * BackendId, but that is not critical.) Note that this is unrelated to the
+ * cumulative stats system (i.e. pgstat.c et al).
+ *
+ * Each auxiliary process also maintains a PgBackendStatus struct in shared
+ * memory.
+ * ----------
+ */
+typedef struct PgBackendStatus
+{
+ /*
+ * To avoid locking overhead, we use the following protocol: a backend
+ * increments st_changecount before modifying its entry, and again after
+ * finishing a modification. A would-be reader should note the value of
+ * st_changecount, copy the entry into private memory, then check
+ * st_changecount again. If the value hasn't changed, and if it's even,
+ * the copy is valid; otherwise start over. This makes updates cheap
+ * while reads are potentially expensive, but that's the tradeoff we want.
+ *
+ * The above protocol needs memory barriers to ensure that the apparent
+ * order of execution is as it desires. Otherwise, for example, the CPU
+ * might rearrange the code so that st_changecount is incremented twice
+ * before the modification on a machine with weak memory ordering. Hence,
+ * use the macros defined below for manipulating st_changecount, rather
+ * than touching it directly.
+ */
+ int st_changecount;
+
+ /* The entry is valid iff st_procpid > 0, unused if st_procpid == 0 */
+ int st_procpid;
+
+ /* Type of backends */
+ BackendType st_backendType;
+
+ /* Times when current backend, transaction, and activity started */
+ TimestampTz st_proc_start_timestamp;
+ TimestampTz st_xact_start_timestamp;
+ TimestampTz st_activity_start_timestamp;
+ TimestampTz st_state_start_timestamp;
+
+ /* Database OID, owning user's OID, connection client address */
+ Oid st_databaseid;
+ Oid st_userid;
+ SockAddr st_clientaddr;
+ char *st_clienthostname; /* MUST be null-terminated */
+
+ /* Information about SSL connection */
+ bool st_ssl;
+ PgBackendSSLStatus *st_sslstatus;
+
+ /* Information about GSSAPI connection */
+ bool st_gss;
+ PgBackendGSSStatus *st_gssstatus;
+
+ /* current state */
+ BackendState st_state;
+
+ /* application name; MUST be null-terminated */
+ char *st_appname;
+
+ /*
+ * Current command string; MUST be null-terminated. Note that this string
+ * possibly is truncated in the middle of a multi-byte character. As
+ * activity strings are stored more frequently than read, that allows to
+ * move the cost of correct truncation to the display side. Use
+ * pgstat_clip_activity() to truncate correctly.
+ */
+ char *st_activity_raw;
+
+ /*
+ * Command progress reporting. Any command which wishes can advertise
+ * that it is running by setting st_progress_command,
+ * st_progress_command_target, and st_progress_param[].
+ * st_progress_command_target should be the OID of the relation which the
+ * command targets (we assume there's just one, as this is meant for
+ * utility commands), but the meaning of each element in the
+ * st_progress_param array is command-specific.
+ */
+ ProgressCommandType st_progress_command;
+ Oid st_progress_command_target;
+ int64 st_progress_param[PGSTAT_NUM_PROGRESS_PARAM];
+
+ /* query identifier, optionally computed using post_parse_analyze_hook */
+ uint64 st_query_id;
+} PgBackendStatus;
+
+
+/*
+ * Macros to load and store st_changecount with appropriate memory barriers.
+ *
+ * Use PGSTAT_BEGIN_WRITE_ACTIVITY() before, and PGSTAT_END_WRITE_ACTIVITY()
+ * after, modifying the current process's PgBackendStatus data. Note that,
+ * since there is no mechanism for cleaning up st_changecount after an error,
+ * THESE MACROS FORM A CRITICAL SECTION. Any error between them will be
+ * promoted to PANIC, causing a database restart to clean up shared memory!
+ * Hence, keep the critical section as short and straight-line as possible.
+ * Aside from being safer, that minimizes the window in which readers will
+ * have to loop.
+ *
+ * Reader logic should follow this sketch:
+ *
+ * for (;;)
+ * {
+ * int before_ct, after_ct;
+ *
+ * pgstat_begin_read_activity(beentry, before_ct);
+ * ... copy beentry data to local memory ...
+ * pgstat_end_read_activity(beentry, after_ct);
+ * if (pgstat_read_activity_complete(before_ct, after_ct))
+ * break;
+ * CHECK_FOR_INTERRUPTS();
+ * }
+ *
+ * For extra safety, we generally use volatile beentry pointers, although
+ * the memory barriers should theoretically be sufficient.
+ */
+#define PGSTAT_BEGIN_WRITE_ACTIVITY(beentry) \
+ do { \
+ START_CRIT_SECTION(); \
+ (beentry)->st_changecount++; \
+ pg_write_barrier(); \
+ } while (0)
+
+#define PGSTAT_END_WRITE_ACTIVITY(beentry) \
+ do { \
+ pg_write_barrier(); \
+ (beentry)->st_changecount++; \
+ Assert(((beentry)->st_changecount & 1) == 0); \
+ END_CRIT_SECTION(); \
+ } while (0)
+
+#define pgstat_begin_read_activity(beentry, before_changecount) \
+ do { \
+ (before_changecount) = (beentry)->st_changecount; \
+ pg_read_barrier(); \
+ } while (0)
+
+#define pgstat_end_read_activity(beentry, after_changecount) \
+ do { \
+ pg_read_barrier(); \
+ (after_changecount) = (beentry)->st_changecount; \
+ } while (0)
+
+#define pgstat_read_activity_complete(before_changecount, after_changecount) \
+ ((before_changecount) == (after_changecount) && \
+ ((before_changecount) & 1) == 0)
+
+
+/* ----------
+ * LocalPgBackendStatus
+ *
+ * When we build the backend status array, we use LocalPgBackendStatus to be
+ * able to add new values to the struct when needed without adding new fields
+ * to the shared memory. It contains the backend status as a first member.
+ * ----------
+ */
+typedef struct LocalPgBackendStatus
+{
+ /*
+ * Local version of the backend status entry.
+ */
+ PgBackendStatus backendStatus;
+
+ /*
+ * The backend ID. For auxiliary processes, this will be set to a value
+ * greater than MaxBackends (since auxiliary processes do not have proper
+ * backend IDs).
+ */
+ BackendId backend_id;
+
+ /*
+ * The xid of the current transaction if available, InvalidTransactionId
+ * if not.
+ */
+ TransactionId backend_xid;
+
+ /*
+ * The xmin of the current session if available, InvalidTransactionId if
+ * not.
+ */
+ TransactionId backend_xmin;
+
+ /*
+ * Number of cached subtransactions in the current session.
+ */
+ int backend_subxact_count;
+
+ /*
+ * The number of subtransactions in the current session which exceeded the
+ * cached subtransaction limit.
+ */
+ bool backend_subxact_overflowed;
+} LocalPgBackendStatus;
+
+
+/* ----------
+ * GUC parameters
+ * ----------
+ */
+extern PGDLLIMPORT bool pgstat_track_activities;
+extern PGDLLIMPORT int pgstat_track_activity_query_size;
+
+
+/* ----------
+ * Other global variables
+ * ----------
+ */
+extern PGDLLIMPORT PgBackendStatus *MyBEEntry;
+
+
+/* ----------
+ * Functions called from postmaster
+ * ----------
+ */
+extern Size BackendStatusShmemSize(void);
+extern void CreateSharedBackendStatus(void);
+
+
+/* ----------
+ * Functions called from backends
+ * ----------
+ */
+
+/* Initialization functions */
+extern void pgstat_beinit(void);
+extern void pgstat_bestart(void);
+
+extern void pgstat_clear_backend_activity_snapshot(void);
+
+/* Activity reporting functions */
+extern void pgstat_report_activity(BackendState state, const char *cmd_str);
+extern void pgstat_report_query_id(uint64 query_id, bool force);
+extern void pgstat_report_tempfile(size_t filesize);
+extern void pgstat_report_appname(const char *appname);
+extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
+extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
+extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
+ int buflen);
+extern uint64 pgstat_get_my_query_id(void);
+
+
+/* ----------
+ * Support functions for the SQL-callable functions to
+ * generate the pgstat* views.
+ * ----------
+ */
+extern int pgstat_fetch_stat_numbackends(void);
+extern PgBackendStatus *pgstat_get_beentry_by_backend_id(BackendId beid);
+extern LocalPgBackendStatus *pgstat_get_local_beentry_by_backend_id(BackendId beid);
+extern LocalPgBackendStatus *pgstat_get_local_beentry_by_index(int idx);
+extern char *pgstat_clip_activity(const char *raw_activity);
+
+
+#endif /* BACKEND_STATUS_H */
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
new file mode 100644
index 0000000..2f8b46d
--- /dev/null
+++ b/src/include/utils/builtins.h
@@ -0,0 +1,136 @@
+/*-------------------------------------------------------------------------
+ *
+ * builtins.h
+ * Declarations for operations on built-in types.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/builtins.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BUILTINS_H
+#define BUILTINS_H
+
+#include "fmgr.h"
+#include "nodes/nodes.h"
+#include "utils/fmgrprotos.h"
+
+/* Sign + the most decimal digits an 8-byte number could have */
+#define MAXINT8LEN 20
+
+/* bool.c */
+extern bool parse_bool(const char *value, bool *result);
+extern bool parse_bool_with_len(const char *value, size_t len, bool *result);
+
+/* domains.c */
+extern void domain_check(Datum value, bool isnull, Oid domainType,
+ void **extra, MemoryContext mcxt);
+extern int errdatatype(Oid datatypeOid);
+extern int errdomainconstraint(Oid datatypeOid, const char *conname);
+
+/* encode.c */
+extern uint64 hex_encode(const char *src, size_t len, char *dst);
+extern uint64 hex_decode(const char *src, size_t len, char *dst);
+extern uint64 hex_decode_safe(const char *src, size_t len, char *dst,
+ Node *escontext);
+
+/* int.c */
+extern int2vector *buildint2vector(const int16 *int2s, int n);
+
+/* name.c */
+extern void namestrcpy(Name name, const char *str);
+extern int namestrcmp(Name name, const char *str);
+
+/* numutils.c */
+extern int16 pg_strtoint16(const char *s);
+extern int16 pg_strtoint16_safe(const char *s, Node *escontext);
+extern int32 pg_strtoint32(const char *s);
+extern int32 pg_strtoint32_safe(const char *s, Node *escontext);
+extern int64 pg_strtoint64(const char *s);
+extern int64 pg_strtoint64_safe(const char *s, Node *escontext);
+extern uint32 uint32in_subr(const char *s, char **endloc,
+ const char *typname, Node *escontext);
+extern uint64 uint64in_subr(const char *s, char **endloc,
+ const char *typname, Node *escontext);
+extern int pg_itoa(int16 i, char *a);
+extern int pg_ultoa_n(uint32 value, char *a);
+extern int pg_ulltoa_n(uint64 value, char *a);
+extern int pg_ltoa(int32 value, char *a);
+extern int pg_lltoa(int64 value, char *a);
+extern char *pg_ultostr_zeropad(char *str, uint32 value, int32 minwidth);
+extern char *pg_ultostr(char *str, uint32 value);
+
+/* oid.c */
+extern oidvector *buildoidvector(const Oid *oids, int n);
+extern Oid oidparse(Node *node);
+extern int oid_cmp(const void *p1, const void *p2);
+
+/* regexp.c */
+extern char *regexp_fixed_prefix(text *text_re, bool case_insensitive,
+ Oid collation, bool *exact);
+
+/* ruleutils.c */
+extern PGDLLIMPORT bool quote_all_identifiers;
+extern const char *quote_identifier(const char *ident);
+extern char *quote_qualified_identifier(const char *qualifier,
+ const char *ident);
+extern void generate_operator_clause(fmStringInfo buf,
+ const char *leftop, Oid leftoptype,
+ Oid opoid,
+ const char *rightop, Oid rightoptype);
+
+/* varchar.c */
+extern int bpchartruelen(char *s, int len);
+
+/* popular functions from varlena.c */
+extern text *cstring_to_text(const char *s);
+extern text *cstring_to_text_with_len(const char *s, int len);
+extern char *text_to_cstring(const text *t);
+extern void text_to_cstring_buffer(const text *src, char *dst, size_t dst_len);
+
+#define CStringGetTextDatum(s) PointerGetDatum(cstring_to_text(s))
+#define TextDatumGetCString(d) text_to_cstring((text *) DatumGetPointer(d))
+
+/* xid.c */
+extern int xidComparator(const void *arg1, const void *arg2);
+extern int xidLogicalComparator(const void *arg1, const void *arg2);
+
+/* inet_cidr_ntop.c */
+extern char *pg_inet_cidr_ntop(int af, const void *src, int bits,
+ char *dst, size_t size);
+
+/* inet_net_pton.c */
+extern int pg_inet_net_pton(int af, const char *src,
+ void *dst, size_t size);
+
+/* network.c */
+extern double convert_network_to_scalar(Datum value, Oid typid, bool *failure);
+extern Datum network_scan_first(Datum in);
+extern Datum network_scan_last(Datum in);
+extern void clean_ipv6_addr(int addr_family, char *addr);
+
+/* numeric.c */
+extern Datum numeric_float8_no_overflow(PG_FUNCTION_ARGS);
+
+/* format_type.c */
+
+/* Control flags for format_type_extended */
+#define FORMAT_TYPE_TYPEMOD_GIVEN 0x01 /* typemod defined by caller */
+#define FORMAT_TYPE_ALLOW_INVALID 0x02 /* allow invalid types */
+#define FORMAT_TYPE_FORCE_QUALIFY 0x04 /* force qualification of type */
+#define FORMAT_TYPE_INVALID_AS_NULL 0x08 /* NULL if undefined */
+extern char *format_type_extended(Oid type_oid, int32 typemod, bits16 flags);
+
+extern char *format_type_be(Oid type_oid);
+extern char *format_type_be_qualified(Oid type_oid);
+extern char *format_type_with_typemod(Oid type_oid, int32 typemod);
+
+extern int32 type_maximum_size(Oid type_oid, int32 typemod);
+
+/* quote.c */
+extern char *quote_literal_cstr(const char *rawstr);
+
+#endif /* BUILTINS_H */
diff --git a/src/include/utils/bytea.h b/src/include/utils/bytea.h
new file mode 100644
index 0000000..166dd03
--- /dev/null
+++ b/src/include/utils/bytea.h
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+ *
+ * bytea.h
+ * Declarations for BYTEA data type support.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/bytea.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BYTEA_H
+#define BYTEA_H
+
+
+
+typedef enum
+{
+ BYTEA_OUTPUT_ESCAPE,
+ BYTEA_OUTPUT_HEX
+} ByteaOutputType;
+
+extern PGDLLIMPORT int bytea_output; /* ByteaOutputType, but int for GUC
+ * enum */
+
+#endif /* BYTEA_H */
diff --git a/src/include/utils/cash.h b/src/include/utils/cash.h
new file mode 100644
index 0000000..55d45fa
--- /dev/null
+++ b/src/include/utils/cash.h
@@ -0,0 +1,35 @@
+/*
+ * src/include/utils/cash.h
+ *
+ *
+ * cash.h
+ * Written by D'Arcy J.M. Cain
+ *
+ * Functions to allow input and output of money normally but store
+ * and handle it as 64 bit integer.
+ */
+
+#ifndef CASH_H
+#define CASH_H
+
+#include "fmgr.h"
+
+typedef int64 Cash;
+
+/* Cash is pass-by-reference if and only if int64 is */
+static inline Cash
+DatumGetCash(Datum X)
+{
+ return DatumGetInt64(X);
+}
+
+static inline Datum
+CashGetDatum(Cash X)
+{
+ return Int64GetDatum(X);
+}
+
+#define PG_GETARG_CASH(n) DatumGetCash(PG_GETARG_DATUM(n))
+#define PG_RETURN_CASH(x) return CashGetDatum(x)
+
+#endif /* CASH_H */
diff --git a/src/include/utils/catcache.h b/src/include/utils/catcache.h
new file mode 100644
index 0000000..af0b341
--- /dev/null
+++ b/src/include/utils/catcache.h
@@ -0,0 +1,231 @@
+/*-------------------------------------------------------------------------
+ *
+ * catcache.h
+ * Low-level catalog cache definitions.
+ *
+ * NOTE: every catalog cache must have a corresponding unique index on
+ * the system table that it caches --- ie, the index must match the keys
+ * used to do lookups in this cache. All cache fetches are done with
+ * indexscans (under normal conditions). The index should be unique to
+ * guarantee that there can only be one matching row for a key combination.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/catcache.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef CATCACHE_H
+#define CATCACHE_H
+
+#include "access/htup.h"
+#include "access/skey.h"
+#include "lib/ilist.h"
+#include "utils/relcache.h"
+
+/*
+ * struct catctup: individual tuple in the cache.
+ * struct catclist: list of tuples matching a partial key.
+ * struct catcache: information for managing a cache.
+ * struct catcacheheader: information for managing all the caches.
+ */
+
+#define CATCACHE_MAXKEYS 4
+
+
+/* function computing a datum's hash */
+typedef uint32 (*CCHashFN) (Datum datum);
+
+/* function computing equality of two datums */
+typedef bool (*CCFastEqualFN) (Datum a, Datum b);
+
+typedef struct catcache
+{
+ int id; /* cache identifier --- see syscache.h */
+ int cc_nbuckets; /* # of hash buckets in this cache */
+ TupleDesc cc_tupdesc; /* tuple descriptor (copied from reldesc) */
+ dlist_head *cc_bucket; /* hash buckets */
+ CCHashFN cc_hashfunc[CATCACHE_MAXKEYS]; /* hash function for each key */
+ CCFastEqualFN cc_fastequal[CATCACHE_MAXKEYS]; /* fast equal function for
+ * each key */
+ int cc_keyno[CATCACHE_MAXKEYS]; /* AttrNumber of each key */
+ dlist_head cc_lists; /* list of CatCList structs */
+ int cc_ntup; /* # of tuples currently in this cache */
+ int cc_nkeys; /* # of keys (1..CATCACHE_MAXKEYS) */
+ const char *cc_relname; /* name of relation the tuples come from */
+ Oid cc_reloid; /* OID of relation the tuples come from */
+ Oid cc_indexoid; /* OID of index matching cache keys */
+ bool cc_relisshared; /* is relation shared across databases? */
+ slist_node cc_next; /* list link */
+ ScanKeyData cc_skey[CATCACHE_MAXKEYS]; /* precomputed key info for heap
+ * scans */
+
+ /*
+ * Keep these at the end, so that compiling catcache.c with CATCACHE_STATS
+ * doesn't break ABI for other modules
+ */
+#ifdef CATCACHE_STATS
+ long cc_searches; /* total # searches against this cache */
+ long cc_hits; /* # of matches against existing entry */
+ long cc_neg_hits; /* # of matches against negative entry */
+ long cc_newloads; /* # of successful loads of new entry */
+
+ /*
+ * cc_searches - (cc_hits + cc_neg_hits + cc_newloads) is number of failed
+ * searches, each of which will result in loading a negative entry
+ */
+ long cc_invals; /* # of entries invalidated from cache */
+ long cc_lsearches; /* total # list-searches */
+ long cc_lhits; /* # of matches against existing lists */
+#endif
+} CatCache;
+
+
+typedef struct catctup
+{
+ int ct_magic; /* for identifying CatCTup entries */
+#define CT_MAGIC 0x57261502
+
+ uint32 hash_value; /* hash value for this tuple's keys */
+
+ /*
+ * Lookup keys for the entry. By-reference datums point into the tuple for
+ * positive cache entries, and are separately allocated for negative ones.
+ */
+ Datum keys[CATCACHE_MAXKEYS];
+
+ /*
+ * Each tuple in a cache is a member of a dlist that stores the elements
+ * of its hash bucket. We keep each dlist in LRU order to speed repeated
+ * lookups.
+ */
+ dlist_node cache_elem; /* list member of per-bucket list */
+
+ /*
+ * A tuple marked "dead" must not be returned by subsequent searches.
+ * However, it won't be physically deleted from the cache until its
+ * refcount goes to zero. (If it's a member of a CatCList, the list's
+ * refcount must go to zero, too; also, remember to mark the list dead at
+ * the same time the tuple is marked.)
+ *
+ * A negative cache entry is an assertion that there is no tuple matching
+ * a particular key. This is just as useful as a normal entry so far as
+ * avoiding catalog searches is concerned. Management of positive and
+ * negative entries is identical.
+ */
+ int refcount; /* number of active references */
+ bool dead; /* dead but not yet removed? */
+ bool negative; /* negative cache entry? */
+ HeapTupleData tuple; /* tuple management header */
+
+ /*
+ * The tuple may also be a member of at most one CatCList. (If a single
+ * catcache is list-searched with varying numbers of keys, we may have to
+ * make multiple entries for the same tuple because of this restriction.
+ * Currently, that's not expected to be common, so we accept the potential
+ * inefficiency.)
+ */
+ struct catclist *c_list; /* containing CatCList, or NULL if none */
+
+ CatCache *my_cache; /* link to owning catcache */
+ /* properly aligned tuple data follows, unless a negative entry */
+} CatCTup;
+
+
+/*
+ * A CatCList describes the result of a partial search, ie, a search using
+ * only the first K key columns of an N-key cache. We store the keys used
+ * into the keys attribute to represent the stored key set. The CatCList
+ * object contains links to cache entries for all the table rows satisfying
+ * the partial key. (Note: none of these will be negative cache entries.)
+ *
+ * A CatCList is only a member of a per-cache list; we do not currently
+ * divide them into hash buckets.
+ *
+ * A list marked "dead" must not be returned by subsequent searches.
+ * However, it won't be physically deleted from the cache until its
+ * refcount goes to zero. (A list should be marked dead if any of its
+ * member entries are dead.)
+ *
+ * If "ordered" is true then the member tuples appear in the order of the
+ * cache's underlying index. This will be true in normal operation, but
+ * might not be true during bootstrap or recovery operations. (namespace.c
+ * is able to save some cycles when it is true.)
+ */
+typedef struct catclist
+{
+ int cl_magic; /* for identifying CatCList entries */
+#define CL_MAGIC 0x52765103
+
+ uint32 hash_value; /* hash value for lookup keys */
+
+ dlist_node cache_elem; /* list member of per-catcache list */
+
+ /*
+ * Lookup keys for the entry, with the first nkeys elements being valid.
+ * All by-reference are separately allocated.
+ */
+ Datum keys[CATCACHE_MAXKEYS];
+
+ int refcount; /* number of active references */
+ bool dead; /* dead but not yet removed? */
+ bool ordered; /* members listed in index order? */
+ short nkeys; /* number of lookup keys specified */
+ int n_members; /* number of member tuples */
+ CatCache *my_cache; /* link to owning catcache */
+ CatCTup *members[FLEXIBLE_ARRAY_MEMBER]; /* members */
+} CatCList;
+
+
+typedef struct catcacheheader
+{
+ slist_head ch_caches; /* head of list of CatCache structs */
+ int ch_ntup; /* # of tuples in all caches */
+} CatCacheHeader;
+
+
+/* this extern duplicates utils/memutils.h... */
+extern PGDLLIMPORT MemoryContext CacheMemoryContext;
+
+extern void CreateCacheMemoryContext(void);
+
+extern CatCache *InitCatCache(int id, Oid reloid, Oid indexoid,
+ int nkeys, const int *key,
+ int nbuckets);
+extern void InitCatCachePhase2(CatCache *cache, bool touch_index);
+
+extern HeapTuple SearchCatCache(CatCache *cache,
+ Datum v1, Datum v2, Datum v3, Datum v4);
+extern HeapTuple SearchCatCache1(CatCache *cache,
+ Datum v1);
+extern HeapTuple SearchCatCache2(CatCache *cache,
+ Datum v1, Datum v2);
+extern HeapTuple SearchCatCache3(CatCache *cache,
+ Datum v1, Datum v2, Datum v3);
+extern HeapTuple SearchCatCache4(CatCache *cache,
+ Datum v1, Datum v2, Datum v3, Datum v4);
+extern void ReleaseCatCache(HeapTuple tuple);
+
+extern uint32 GetCatCacheHashValue(CatCache *cache,
+ Datum v1, Datum v2,
+ Datum v3, Datum v4);
+
+extern CatCList *SearchCatCacheList(CatCache *cache, int nkeys,
+ Datum v1, Datum v2,
+ Datum v3);
+extern void ReleaseCatCacheList(CatCList *list);
+
+extern void ResetCatalogCaches(void);
+extern void CatalogCacheFlushCatalog(Oid catId);
+extern void CatCacheInvalidate(CatCache *cache, uint32 hashValue);
+extern void PrepareToInvalidateCacheTuple(Relation relation,
+ HeapTuple tuple,
+ HeapTuple newtuple,
+ void (*function) (int, uint32, Oid));
+
+extern void PrintCatCacheLeakWarning(HeapTuple tuple);
+extern void PrintCatCacheListLeakWarning(CatCList *list);
+
+#endif /* CATCACHE_H */
diff --git a/src/include/utils/combocid.h b/src/include/utils/combocid.h
new file mode 100644
index 0000000..2b496ee
--- /dev/null
+++ b/src/include/utils/combocid.h
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+ *
+ * combocid.h
+ * Combo command ID support routines
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/combocid.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef COMBOCID_H
+#define COMBOCID_H
+
+/*
+ * HeapTupleHeaderGetCmin and HeapTupleHeaderGetCmax function prototypes
+ * are in access/htup.h, because that's where the macro definitions that
+ * those functions replaced used to be.
+ */
+
+extern void AtEOXact_ComboCid(void);
+extern void RestoreComboCIDState(char *comboCIDstate);
+extern void SerializeComboCIDState(Size maxsize, char *start_address);
+extern Size EstimateComboCIDStateSpace(void);
+
+#endif /* COMBOCID_H */
diff --git a/src/include/utils/conffiles.h b/src/include/utils/conffiles.h
new file mode 100644
index 0000000..e3868fb
--- /dev/null
+++ b/src/include/utils/conffiles.h
@@ -0,0 +1,27 @@
+/*--------------------------------------------------------------------
+ * conffiles.h
+ *
+ * Utilities related to configuration files.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/conffiles.h
+ *
+ *--------------------------------------------------------------------
+ */
+#ifndef CONFFILES_H
+#define CONFFILES_H
+
+/* recursion nesting depth for configuration files */
+#define CONF_FILE_START_DEPTH 0
+#define CONF_FILE_MAX_DEPTH 10
+
+extern char *AbsoluteConfigLocation(const char *location,
+ const char *calling_file);
+extern char **GetConfFilesInDir(const char *includedir,
+ const char *calling_file,
+ int elevel, int *num_filenames,
+ char **err_msg);
+
+#endif /* CONFFILES_H */
diff --git a/src/include/utils/date.h b/src/include/utils/date.h
new file mode 100644
index 0000000..97e1a02
--- /dev/null
+++ b/src/include/utils/date.h
@@ -0,0 +1,118 @@
+/*-------------------------------------------------------------------------
+ *
+ * date.h
+ * Definitions for the SQL "date" and "time" types.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/date.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DATE_H
+#define DATE_H
+
+#include <math.h>
+
+#include "datatype/timestamp.h"
+#include "fmgr.h"
+#include "pgtime.h"
+
+typedef int32 DateADT;
+
+typedef int64 TimeADT;
+
+typedef struct
+{
+ TimeADT time; /* all time units other than months and years */
+ int32 zone; /* numeric time zone, in seconds */
+} TimeTzADT;
+
+/*
+ * Infinity and minus infinity must be the max and min values of DateADT.
+ */
+#define DATEVAL_NOBEGIN ((DateADT) PG_INT32_MIN)
+#define DATEVAL_NOEND ((DateADT) PG_INT32_MAX)
+
+#define DATE_NOBEGIN(j) ((j) = DATEVAL_NOBEGIN)
+#define DATE_IS_NOBEGIN(j) ((j) == DATEVAL_NOBEGIN)
+#define DATE_NOEND(j) ((j) = DATEVAL_NOEND)
+#define DATE_IS_NOEND(j) ((j) == DATEVAL_NOEND)
+#define DATE_NOT_FINITE(j) (DATE_IS_NOBEGIN(j) || DATE_IS_NOEND(j))
+
+#define MAX_TIME_PRECISION 6
+
+/*
+ * Functions for fmgr-callable functions.
+ *
+ * For TimeADT, we make use of the same support routines as for int64.
+ * Therefore TimeADT is pass-by-reference if and only if int64 is!
+ */
+static inline DateADT
+DatumGetDateADT(Datum X)
+{
+ return (DateADT) DatumGetInt32(X);
+}
+
+static inline TimeADT
+DatumGetTimeADT(Datum X)
+{
+ return (TimeADT) DatumGetInt64(X);
+}
+
+static inline TimeTzADT *
+DatumGetTimeTzADTP(Datum X)
+{
+ return (TimeTzADT *) DatumGetPointer(X);
+}
+
+static inline Datum
+DateADTGetDatum(DateADT X)
+{
+ return Int32GetDatum(X);
+}
+
+static inline Datum
+TimeADTGetDatum(TimeADT X)
+{
+ return Int64GetDatum(X);
+}
+
+static inline Datum
+TimeTzADTPGetDatum(const TimeTzADT *X)
+{
+ return PointerGetDatum(X);
+}
+
+#define PG_GETARG_DATEADT(n) DatumGetDateADT(PG_GETARG_DATUM(n))
+#define PG_GETARG_TIMEADT(n) DatumGetTimeADT(PG_GETARG_DATUM(n))
+#define PG_GETARG_TIMETZADT_P(n) DatumGetTimeTzADTP(PG_GETARG_DATUM(n))
+
+#define PG_RETURN_DATEADT(x) return DateADTGetDatum(x)
+#define PG_RETURN_TIMEADT(x) return TimeADTGetDatum(x)
+#define PG_RETURN_TIMETZADT_P(x) return TimeTzADTPGetDatum(x)
+
+
+/* date.c */
+extern int32 anytime_typmod_check(bool istz, int32 typmod);
+extern double date2timestamp_no_overflow(DateADT dateVal);
+extern Timestamp date2timestamp_opt_overflow(DateADT dateVal, int *overflow);
+extern TimestampTz date2timestamptz_opt_overflow(DateADT dateVal, int *overflow);
+extern int32 date_cmp_timestamp_internal(DateADT dateVal, Timestamp dt2);
+extern int32 date_cmp_timestamptz_internal(DateADT dateVal, TimestampTz dt2);
+
+extern void EncodeSpecialDate(DateADT dt, char *str);
+extern DateADT GetSQLCurrentDate(void);
+extern TimeTzADT *GetSQLCurrentTime(int32 typmod);
+extern TimeADT GetSQLLocalTime(int32 typmod);
+extern int time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec);
+extern int timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp);
+extern int tm2time(struct pg_tm *tm, fsec_t fsec, TimeADT *result);
+extern int tm2timetz(struct pg_tm *tm, fsec_t fsec, int tz, TimeTzADT *result);
+extern bool time_overflows(int hour, int min, int sec, fsec_t fsec);
+extern bool float_time_overflows(int hour, int min, double sec);
+extern void AdjustTimeForTypmod(TimeADT *time, int32 typmod);
+
+#endif /* DATE_H */
diff --git a/src/include/utils/datetime.h b/src/include/utils/datetime.h
new file mode 100644
index 0000000..a871e32
--- /dev/null
+++ b/src/include/utils/datetime.h
@@ -0,0 +1,364 @@
+/*-------------------------------------------------------------------------
+ *
+ * datetime.h
+ * Definitions for date/time support code.
+ * The support code is shared with other date data types,
+ * including date, and time.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/datetime.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DATETIME_H
+#define DATETIME_H
+
+#include "utils/timestamp.h"
+
+/* this struct is declared in utils/tzparser.h: */
+struct tzEntry;
+
+
+/* ----------------------------------------------------------------
+ * time types + support macros
+ *
+ * String definitions for standard time quantities.
+ *
+ * These strings are the defaults used to form output time strings.
+ * Other alternative forms are hardcoded into token tables in datetime.c.
+ * ----------------------------------------------------------------
+ */
+
+#define DAGO "ago"
+#define DCURRENT "current"
+#define EPOCH "epoch"
+#define INVALID "invalid"
+#define EARLY "-infinity"
+#define LATE "infinity"
+#define NOW "now"
+#define TODAY "today"
+#define TOMORROW "tomorrow"
+#define YESTERDAY "yesterday"
+#define ZULU "zulu"
+
+#define DMICROSEC "usecond"
+#define DMILLISEC "msecond"
+#define DSECOND "second"
+#define DMINUTE "minute"
+#define DHOUR "hour"
+#define DDAY "day"
+#define DWEEK "week"
+#define DMONTH "month"
+#define DQUARTER "quarter"
+#define DYEAR "year"
+#define DDECADE "decade"
+#define DCENTURY "century"
+#define DMILLENNIUM "millennium"
+#define DA_D "ad"
+#define DB_C "bc"
+#define DTIMEZONE "timezone"
+
+/*
+ * Fundamental time field definitions for parsing.
+ *
+ * Meridian: am, pm, or 24-hour style.
+ * Millennium: ad, bc
+ */
+
+#define AM 0
+#define PM 1
+#define HR24 2
+
+#define AD 0
+#define BC 1
+
+/*
+ * Field types for time decoding.
+ *
+ * Can't have more of these than there are bits in an unsigned int
+ * since these are turned into bit masks during parsing and decoding.
+ *
+ * Furthermore, the values for YEAR, MONTH, DAY, HOUR, MINUTE, SECOND
+ * must be in the range 0..14 so that the associated bitmasks can fit
+ * into the left half of an INTERVAL's typmod value. Since those bits
+ * are stored in typmods, you can't change them without initdb!
+ */
+
+#define RESERV 0
+#define MONTH 1
+#define YEAR 2
+#define DAY 3
+#define JULIAN 4
+#define TZ 5 /* fixed-offset timezone abbreviation */
+#define DTZ 6 /* fixed-offset timezone abbrev, DST */
+#define DYNTZ 7 /* dynamic timezone abbreviation */
+#define IGNORE_DTF 8
+#define AMPM 9
+#define HOUR 10
+#define MINUTE 11
+#define SECOND 12
+#define MILLISECOND 13
+#define MICROSECOND 14
+#define DOY 15
+#define DOW 16
+#define UNITS 17
+#define ADBC 18
+/* these are only for relative dates */
+#define AGO 19
+#define ABS_BEFORE 20
+#define ABS_AFTER 21
+/* generic fields to help with parsing */
+#define ISODATE 22
+#define ISOTIME 23
+/* these are only for parsing intervals */
+#define WEEK 24
+#define DECADE 25
+#define CENTURY 26
+#define MILLENNIUM 27
+/* hack for parsing two-word timezone specs "MET DST" etc */
+#define DTZMOD 28 /* "DST" as a separate word */
+/* reserved for unrecognized string values */
+#define UNKNOWN_FIELD 31
+
+/*
+ * Token field definitions for time parsing and decoding.
+ *
+ * Some field type codes (see above) use these as the "value" in datetktbl[].
+ * These are also used for bit masks in DecodeDateTime and friends
+ * so actually restrict them to within [0,31] for now.
+ * - thomas 97/06/19
+ * Not all of these fields are used for masks in DecodeDateTime
+ * so allow some larger than 31. - thomas 1997-11-17
+ *
+ * Caution: there are undocumented assumptions in the code that most of these
+ * values are not equal to IGNORE_DTF nor RESERV. Be very careful when
+ * renumbering values in either of these apparently-independent lists :-(
+ */
+
+#define DTK_NUMBER 0
+#define DTK_STRING 1
+
+#define DTK_DATE 2
+#define DTK_TIME 3
+#define DTK_TZ 4
+#define DTK_AGO 5
+
+#define DTK_SPECIAL 6
+#define DTK_EARLY 9
+#define DTK_LATE 10
+#define DTK_EPOCH 11
+#define DTK_NOW 12
+#define DTK_YESTERDAY 13
+#define DTK_TODAY 14
+#define DTK_TOMORROW 15
+#define DTK_ZULU 16
+
+#define DTK_DELTA 17
+#define DTK_SECOND 18
+#define DTK_MINUTE 19
+#define DTK_HOUR 20
+#define DTK_DAY 21
+#define DTK_WEEK 22
+#define DTK_MONTH 23
+#define DTK_QUARTER 24
+#define DTK_YEAR 25
+#define DTK_DECADE 26
+#define DTK_CENTURY 27
+#define DTK_MILLENNIUM 28
+#define DTK_MILLISEC 29
+#define DTK_MICROSEC 30
+#define DTK_JULIAN 31
+
+#define DTK_DOW 32
+#define DTK_DOY 33
+#define DTK_TZ_HOUR 34
+#define DTK_TZ_MINUTE 35
+#define DTK_ISOYEAR 36
+#define DTK_ISODOW 37
+
+
+/*
+ * Bit mask definitions for time parsing.
+ */
+
+#define DTK_M(t) (0x01 << (t))
+
+/* Convenience: a second, plus any fractional component */
+#define DTK_ALL_SECS_M (DTK_M(SECOND) | DTK_M(MILLISECOND) | DTK_M(MICROSECOND))
+#define DTK_DATE_M (DTK_M(YEAR) | DTK_M(MONTH) | DTK_M(DAY))
+#define DTK_TIME_M (DTK_M(HOUR) | DTK_M(MINUTE) | DTK_ALL_SECS_M)
+
+/*
+ * Working buffer size for input and output of interval, timestamp, etc.
+ * Inputs that need more working space will be rejected early. Longer outputs
+ * will overrun buffers, so this must suffice for all possible output. As of
+ * this writing, interval_out() needs the most space at ~90 bytes.
+ */
+#define MAXDATELEN 128
+/* maximum possible number of fields in a date string */
+#define MAXDATEFIELDS 25
+/* only this many chars are stored in datetktbl */
+#define TOKMAXLEN 10
+
+/* keep this struct small; it gets used a lot */
+typedef struct
+{
+ char token[TOKMAXLEN + 1]; /* always NUL-terminated */
+ char type; /* see field type codes above */
+ int32 value; /* meaning depends on type */
+} datetkn;
+
+/* one of its uses is in tables of time zone abbreviations */
+typedef struct TimeZoneAbbrevTable
+{
+ Size tblsize; /* size in bytes of TimeZoneAbbrevTable */
+ int numabbrevs; /* number of entries in abbrevs[] array */
+ datetkn abbrevs[FLEXIBLE_ARRAY_MEMBER];
+ /* DynamicZoneAbbrev(s) may follow the abbrevs[] array */
+} TimeZoneAbbrevTable;
+
+/* auxiliary data for a dynamic time zone abbreviation (non-fixed-offset) */
+typedef struct DynamicZoneAbbrev
+{
+ pg_tz *tz; /* NULL if not yet looked up */
+ char zone[FLEXIBLE_ARRAY_MEMBER]; /* NUL-terminated zone name */
+} DynamicZoneAbbrev;
+
+
+/* FMODULO()
+ * Macro to replace modf(), which is broken on some platforms.
+ * t = input and remainder
+ * q = integer part
+ * u = divisor
+ */
+#define FMODULO(t,q,u) \
+do { \
+ (q) = (((t) < 0) ? ceil((t) / (u)) : floor((t) / (u))); \
+ if ((q) != 0) (t) -= rint((q) * (u)); \
+} while(0)
+
+/* TMODULO()
+ * Like FMODULO(), but work on the timestamp datatype (now always int64).
+ * We assume that int64 follows the C99 semantics for division (negative
+ * quotients truncate towards zero).
+ */
+#define TMODULO(t,q,u) \
+do { \
+ (q) = ((t) / (u)); \
+ if ((q) != 0) (t) -= ((q) * (u)); \
+} while(0)
+
+/*
+ * Date/time validation
+ * Include check for leap year.
+ */
+
+extern PGDLLIMPORT const char *const months[]; /* months (3-char
+ * abbreviations) */
+extern PGDLLIMPORT const char *const days[]; /* days (full names) */
+extern PGDLLIMPORT const int day_tab[2][13];
+
+/*
+ * These are the rules for the Gregorian calendar, which was adopted in 1582.
+ * However, we use this calculation for all prior years as well because the
+ * SQL standard specifies use of the Gregorian calendar. This prevents the
+ * date 1500-02-29 from being stored, even though it is valid in the Julian
+ * calendar.
+ */
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+
+
+/*
+ * Datetime input parsing routines (ParseDateTime, DecodeDateTime, etc)
+ * return zero or a positive value on success. On failure, they return
+ * one of these negative code values. DateTimeParseError may be used to
+ * produce a suitable error report. For some of these codes,
+ * DateTimeParseError requires additional information, which is carried
+ * in struct DateTimeErrorExtra.
+ */
+#define DTERR_BAD_FORMAT (-1)
+#define DTERR_FIELD_OVERFLOW (-2)
+#define DTERR_MD_FIELD_OVERFLOW (-3) /* triggers hint about DateStyle */
+#define DTERR_INTERVAL_OVERFLOW (-4)
+#define DTERR_TZDISP_OVERFLOW (-5)
+#define DTERR_BAD_TIMEZONE (-6)
+#define DTERR_BAD_ZONE_ABBREV (-7)
+
+typedef struct DateTimeErrorExtra
+{
+ /* Needed for DTERR_BAD_TIMEZONE and DTERR_BAD_ZONE_ABBREV: */
+ const char *dtee_timezone; /* incorrect time zone name */
+ /* Needed for DTERR_BAD_ZONE_ABBREV: */
+ const char *dtee_abbrev; /* relevant time zone abbreviation */
+} DateTimeErrorExtra;
+
+/* Result codes for DecodeTimezoneName() */
+#define TZNAME_FIXED_OFFSET 0
+#define TZNAME_DYNTZ 1
+#define TZNAME_ZONE 2
+
+
+extern void GetCurrentDateTime(struct pg_tm *tm);
+extern void GetCurrentTimeUsec(struct pg_tm *tm, fsec_t *fsec, int *tzp);
+extern void j2date(int jd, int *year, int *month, int *day);
+extern int date2j(int year, int month, int day);
+
+extern int ParseDateTime(const char *timestr, char *workbuf, size_t buflen,
+ char **field, int *ftype,
+ int maxfields, int *numfields);
+extern int DecodeDateTime(char **field, int *ftype, int nf,
+ int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp,
+ DateTimeErrorExtra *extra);
+extern int DecodeTimezone(const char *str, int *tzp);
+extern int DecodeTimeOnly(char **field, int *ftype, int nf,
+ int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp,
+ DateTimeErrorExtra *extra);
+extern int DecodeInterval(char **field, int *ftype, int nf, int range,
+ int *dtype, struct pg_itm_in *itm_in);
+extern int DecodeISO8601Interval(char *str,
+ int *dtype, struct pg_itm_in *itm_in);
+
+extern void DateTimeParseError(int dterr, DateTimeErrorExtra *extra,
+ const char *str, const char *datatype,
+ struct Node *escontext);
+
+extern int DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp);
+extern int DetermineTimeZoneAbbrevOffset(struct pg_tm *tm, const char *abbr, pg_tz *tzp);
+extern int DetermineTimeZoneAbbrevOffsetTS(TimestampTz ts, const char *abbr,
+ pg_tz *tzp, int *isdst);
+
+extern void EncodeDateOnly(struct pg_tm *tm, int style, char *str);
+extern void EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, int style, char *str);
+extern void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str);
+extern void EncodeInterval(struct pg_itm *itm, int style, char *str);
+extern void EncodeSpecialTimestamp(Timestamp dt, char *str);
+
+extern int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc,
+ struct pg_tm *tm);
+
+extern int DecodeTimezoneAbbrev(int field, const char *lowtoken,
+ int *ftype, int *offset, pg_tz **tz,
+ DateTimeErrorExtra *extra);
+extern int DecodeSpecial(int field, const char *lowtoken, int *val);
+extern int DecodeUnits(int field, const char *lowtoken, int *val);
+
+extern int DecodeTimezoneName(const char *tzname, int *offset, pg_tz **tz);
+extern pg_tz *DecodeTimezoneNameToTz(const char *tzname);
+
+extern int j2day(int date);
+
+extern struct Node *TemporalSimplify(int32 max_precis, struct Node *node);
+
+extern bool CheckDateTokenTables(void);
+
+extern TimeZoneAbbrevTable *ConvertTimeZoneAbbrevs(struct tzEntry *abbrevs,
+ int n);
+extern void InstallTimeZoneAbbrevs(TimeZoneAbbrevTable *tbl);
+
+extern bool AdjustTimestampForTypmod(Timestamp *time, int32 typmod,
+ struct Node *escontext);
+
+#endif /* DATETIME_H */
diff --git a/src/include/utils/datum.h b/src/include/utils/datum.h
new file mode 100644
index 0000000..70a47f3
--- /dev/null
+++ b/src/include/utils/datum.h
@@ -0,0 +1,76 @@
+/*-------------------------------------------------------------------------
+ *
+ * datum.h
+ * POSTGRES Datum (abstract data type) manipulation routines.
+ *
+ * These routines are driven by the 'typbyval' and 'typlen' information,
+ * which must previously have been obtained by the caller for the datatype
+ * of the Datum. (We do it this way because in most situations the caller
+ * can look up the info just once and use it for many per-datum operations.)
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/datum.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DATUM_H
+#define DATUM_H
+
+/*
+ * datumGetSize - find the "real" length of a datum
+ */
+extern Size datumGetSize(Datum value, bool typByVal, int typLen);
+
+/*
+ * datumCopy - make a copy of a non-NULL datum.
+ *
+ * If the datatype is pass-by-reference, memory is obtained with palloc().
+ */
+extern Datum datumCopy(Datum value, bool typByVal, int typLen);
+
+/*
+ * datumTransfer - transfer a non-NULL datum into the current memory context.
+ *
+ * Differs from datumCopy() in its handling of read-write expanded objects.
+ */
+extern Datum datumTransfer(Datum value, bool typByVal, int typLen);
+
+/*
+ * datumIsEqual
+ * return true if two datums of the same type are equal, false otherwise.
+ *
+ * XXX : See comments in the code for restrictions!
+ */
+extern bool datumIsEqual(Datum value1, Datum value2,
+ bool typByVal, int typLen);
+
+/*
+ * datum_image_eq
+ *
+ * Compares two datums for identical contents, based on byte images. Return
+ * true if the two datums are equal, false otherwise.
+ */
+extern bool datum_image_eq(Datum value1, Datum value2,
+ bool typByVal, int typLen);
+
+/*
+ * datum_image_hash
+ *
+ * Generates hash value for 'value' based on its bits rather than logical
+ * value.
+ */
+extern uint32 datum_image_hash(Datum value, bool typByVal, int typLen);
+
+/*
+ * Serialize and restore datums so that we can transfer them to parallel
+ * workers.
+ */
+extern Size datumEstimateSpace(Datum value, bool isnull, bool typByVal,
+ int typLen);
+extern void datumSerialize(Datum value, bool isnull, bool typByVal,
+ int typLen, char **start_address);
+extern Datum datumRestore(char **start_address, bool *isnull);
+
+#endif /* DATUM_H */
diff --git a/src/include/utils/dsa.h b/src/include/utils/dsa.h
new file mode 100644
index 0000000..3ce4ee3
--- /dev/null
+++ b/src/include/utils/dsa.h
@@ -0,0 +1,127 @@
+/*-------------------------------------------------------------------------
+ *
+ * dsa.h
+ * Dynamic shared memory areas.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/utils/dsa.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DSA_H
+#define DSA_H
+
+#include "port/atomics.h"
+#include "storage/dsm.h"
+
+/* The opaque type used for an area. */
+struct dsa_area;
+typedef struct dsa_area dsa_area;
+
+/*
+ * If this system only uses a 32-bit value for size_t, then use the 32-bit
+ * implementation of DSA. This limits the amount of DSA that can be created
+ * to something significantly less than the entire 4GB address space because
+ * the DSA pointer must encode both a segment identifier and an offset, but
+ * that shouldn't be a significant limitation in practice.
+ *
+ * If this system doesn't support atomic operations on 64-bit values, then
+ * we fall back to 32-bit dsa_pointer for lack of other options.
+ *
+ * For testing purposes, USE_SMALL_DSA_POINTER can be defined to force the use
+ * of 32-bit dsa_pointer even on systems capable of supporting a 64-bit
+ * dsa_pointer.
+ */
+#if SIZEOF_SIZE_T == 4 || !defined(PG_HAVE_ATOMIC_U64_SUPPORT) || \
+ defined(USE_SMALL_DSA_POINTER)
+#define SIZEOF_DSA_POINTER 4
+#else
+#define SIZEOF_DSA_POINTER 8
+#endif
+
+/*
+ * The type of 'relative pointers' to memory allocated by a dynamic shared
+ * area. dsa_pointer values can be shared with other processes, but must be
+ * converted to backend-local pointers before they can be dereferenced. See
+ * dsa_get_address. Also, an atomic version and appropriately sized atomic
+ * operations.
+ */
+#if SIZEOF_DSA_POINTER == 4
+typedef uint32 dsa_pointer;
+typedef pg_atomic_uint32 dsa_pointer_atomic;
+#define dsa_pointer_atomic_init pg_atomic_init_u32
+#define dsa_pointer_atomic_read pg_atomic_read_u32
+#define dsa_pointer_atomic_write pg_atomic_write_u32
+#define dsa_pointer_atomic_fetch_add pg_atomic_fetch_add_u32
+#define dsa_pointer_atomic_compare_exchange pg_atomic_compare_exchange_u32
+#define DSA_POINTER_FORMAT "%08x"
+#else
+typedef uint64 dsa_pointer;
+typedef pg_atomic_uint64 dsa_pointer_atomic;
+#define dsa_pointer_atomic_init pg_atomic_init_u64
+#define dsa_pointer_atomic_read pg_atomic_read_u64
+#define dsa_pointer_atomic_write pg_atomic_write_u64
+#define dsa_pointer_atomic_fetch_add pg_atomic_fetch_add_u64
+#define dsa_pointer_atomic_compare_exchange pg_atomic_compare_exchange_u64
+#define DSA_POINTER_FORMAT "%016" INT64_MODIFIER "x"
+#endif
+
+/* Flags for dsa_allocate_extended. */
+#define DSA_ALLOC_HUGE 0x01 /* allow huge allocation (> 1 GB) */
+#define DSA_ALLOC_NO_OOM 0x02 /* no failure if out-of-memory */
+#define DSA_ALLOC_ZERO 0x04 /* zero allocated memory */
+
+/* A sentinel value for dsa_pointer used to indicate failure to allocate. */
+#define InvalidDsaPointer ((dsa_pointer) 0)
+
+/* Check if a dsa_pointer value is valid. */
+#define DsaPointerIsValid(x) ((x) != InvalidDsaPointer)
+
+/* Allocate uninitialized memory with error on out-of-memory. */
+#define dsa_allocate(area, size) \
+ dsa_allocate_extended(area, size, 0)
+
+/* Allocate zero-initialized memory with error on out-of-memory. */
+#define dsa_allocate0(area, size) \
+ dsa_allocate_extended(area, size, DSA_ALLOC_ZERO)
+
+/*
+ * The type used for dsa_area handles. dsa_handle values can be shared with
+ * other processes, so that they can attach to them. This provides a way to
+ * share allocated storage with other processes.
+ *
+ * The handle for a dsa_area is currently implemented as the dsm_handle
+ * for the first DSM segment backing this dynamic storage area, but client
+ * code shouldn't assume that is true.
+ */
+typedef dsm_handle dsa_handle;
+
+/* Sentinel value to use for invalid dsa_handles. */
+#define DSA_HANDLE_INVALID ((dsa_handle) DSM_HANDLE_INVALID)
+
+
+extern dsa_area *dsa_create(int tranche_id);
+extern dsa_area *dsa_create_in_place(void *place, size_t size,
+ int tranche_id, dsm_segment *segment);
+extern dsa_area *dsa_attach(dsa_handle handle);
+extern dsa_area *dsa_attach_in_place(void *place, dsm_segment *segment);
+extern void dsa_release_in_place(void *place);
+extern void dsa_on_dsm_detach_release_in_place(dsm_segment *, Datum);
+extern void dsa_on_shmem_exit_release_in_place(int, Datum);
+extern void dsa_pin_mapping(dsa_area *area);
+extern void dsa_detach(dsa_area *area);
+extern void dsa_pin(dsa_area *area);
+extern void dsa_unpin(dsa_area *area);
+extern void dsa_set_size_limit(dsa_area *area, size_t limit);
+extern size_t dsa_minimum_size(void);
+extern dsa_handle dsa_get_handle(dsa_area *area);
+extern dsa_pointer dsa_allocate_extended(dsa_area *area, size_t size, int flags);
+extern void dsa_free(dsa_area *area, dsa_pointer dp);
+extern void *dsa_get_address(dsa_area *area, dsa_pointer dp);
+extern void dsa_trim(dsa_area *area);
+extern void dsa_dump(dsa_area *area);
+
+#endif /* DSA_H */
diff --git a/src/include/utils/dynahash.h b/src/include/utils/dynahash.h
new file mode 100644
index 0000000..866677a
--- /dev/null
+++ b/src/include/utils/dynahash.h
@@ -0,0 +1,20 @@
+/*-------------------------------------------------------------------------
+ *
+ * dynahash.h
+ * POSTGRES dynahash.h file definitions
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/utils/dynahash.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DYNAHASH_H
+#define DYNAHASH_H
+
+extern int my_log2(long num);
+
+#endif /* DYNAHASH_H */
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
new file mode 100644
index 0000000..0292e88
--- /dev/null
+++ b/src/include/utils/elog.h
@@ -0,0 +1,545 @@
+/*-------------------------------------------------------------------------
+ *
+ * elog.h
+ * POSTGRES error reporting/logging definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/elog.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ELOG_H
+#define ELOG_H
+
+#include <setjmp.h>
+
+#include "lib/stringinfo.h"
+
+/* We cannot include nodes.h yet, so forward-declare struct Node */
+struct Node;
+
+
+/* Error level codes */
+#define DEBUG5 10 /* Debugging messages, in categories of
+ * decreasing detail. */
+#define DEBUG4 11
+#define DEBUG3 12
+#define DEBUG2 13
+#define DEBUG1 14 /* used by GUC debug_* variables */
+#define LOG 15 /* Server operational messages; sent only to
+ * server log by default. */
+#define LOG_SERVER_ONLY 16 /* Same as LOG for server reporting, but never
+ * sent to client. */
+#define COMMERROR LOG_SERVER_ONLY /* Client communication problems; same as
+ * LOG for server reporting, but never
+ * sent to client. */
+#define INFO 17 /* Messages specifically requested by user (eg
+ * VACUUM VERBOSE output); always sent to
+ * client regardless of client_min_messages,
+ * but by default not sent to server log. */
+#define NOTICE 18 /* Helpful messages to users about query
+ * operation; sent to client and not to server
+ * log by default. */
+#define WARNING 19 /* Warnings. NOTICE is for expected messages
+ * like implicit sequence creation by SERIAL.
+ * WARNING is for unexpected messages. */
+#define PGWARNING 19 /* Must equal WARNING; see NOTE below. */
+#define WARNING_CLIENT_ONLY 20 /* Warnings to be sent to client as usual, but
+ * never to the server log. */
+#define ERROR 21 /* user error - abort transaction; return to
+ * known state */
+#define PGERROR 21 /* Must equal ERROR; see NOTE below. */
+#define FATAL 22 /* fatal error - abort process */
+#define PANIC 23 /* take down the other backends with me */
+
+/*
+ * NOTE: the alternate names PGWARNING and PGERROR are useful for dealing
+ * with third-party headers that make other definitions of WARNING and/or
+ * ERROR. One can, for example, re-define ERROR as PGERROR after including
+ * such a header.
+ */
+
+
+/* macros for representing SQLSTATE strings compactly */
+#define PGSIXBIT(ch) (((ch) - '0') & 0x3F)
+#define PGUNSIXBIT(val) (((val) & 0x3F) + '0')
+
+#define MAKE_SQLSTATE(ch1,ch2,ch3,ch4,ch5) \
+ (PGSIXBIT(ch1) + (PGSIXBIT(ch2) << 6) + (PGSIXBIT(ch3) << 12) + \
+ (PGSIXBIT(ch4) << 18) + (PGSIXBIT(ch5) << 24))
+
+/* These macros depend on the fact that '0' becomes a zero in PGSIXBIT */
+#define ERRCODE_TO_CATEGORY(ec) ((ec) & ((1 << 12) - 1))
+#define ERRCODE_IS_CATEGORY(ec) (((ec) & ~((1 << 12) - 1)) == 0)
+
+/* SQLSTATE codes for errors are defined in a separate file */
+#include "utils/errcodes.h"
+
+/*
+ * Provide a way to prevent "errno" from being accidentally used inside an
+ * elog() or ereport() invocation. Since we know that some operating systems
+ * define errno as something involving a function call, we'll put a local
+ * variable of the same name as that function in the local scope to force a
+ * compile error. On platforms that don't define errno in that way, nothing
+ * happens, so we get no warning ... but we can live with that as long as it
+ * happens on some popular platforms.
+ */
+#if defined(errno) && defined(__linux__)
+#define pg_prevent_errno_in_scope() int __errno_location pg_attribute_unused()
+#elif defined(errno) && (defined(__darwin__) || defined(__FreeBSD__))
+#define pg_prevent_errno_in_scope() int __error pg_attribute_unused()
+#else
+#define pg_prevent_errno_in_scope()
+#endif
+
+
+/*----------
+ * New-style error reporting API: to be used in this way:
+ * ereport(ERROR,
+ * errcode(ERRCODE_UNDEFINED_CURSOR),
+ * errmsg("portal \"%s\" not found", stmt->portalname),
+ * ... other errxxx() fields as needed ...);
+ *
+ * The error level is required, and so is a primary error message (errmsg
+ * or errmsg_internal). All else is optional. errcode() defaults to
+ * ERRCODE_INTERNAL_ERROR if elevel is ERROR or more, ERRCODE_WARNING
+ * if elevel is WARNING, or ERRCODE_SUCCESSFUL_COMPLETION if elevel is
+ * NOTICE or below.
+ *
+ * Before Postgres v12, extra parentheses were required around the
+ * list of auxiliary function calls; that's now optional.
+ *
+ * ereport_domain() allows a message domain to be specified, for modules that
+ * wish to use a different message catalog from the backend's. To avoid having
+ * one copy of the default text domain per .o file, we define it as NULL here
+ * and have errstart insert the default text domain. Modules can either use
+ * ereport_domain() directly, or preferably they can override the TEXTDOMAIN
+ * macro.
+ *
+ * When __builtin_constant_p is available and elevel >= ERROR we make a call
+ * to errstart_cold() instead of errstart(). This version of the function is
+ * marked with pg_attribute_cold which will coax supporting compilers into
+ * generating code which is more optimized towards non-ERROR cases. Because
+ * we use __builtin_constant_p() in the condition, when elevel is not a
+ * compile-time constant, or if it is, but it's < ERROR, the compiler has no
+ * need to generate any code for this branch. It can simply call errstart()
+ * unconditionally.
+ *
+ * If elevel >= ERROR, the call will not return; we try to inform the compiler
+ * of that via pg_unreachable(). However, no useful optimization effect is
+ * obtained unless the compiler sees elevel as a compile-time constant, else
+ * we're just adding code bloat. So, if __builtin_constant_p is available,
+ * use that to cause the second if() to vanish completely for non-constant
+ * cases. We avoid using a local variable because it's not necessary and
+ * prevents gcc from making the unreachability deduction at optlevel -O0.
+ *----------
+ */
+#ifdef HAVE__BUILTIN_CONSTANT_P
+#define ereport_domain(elevel, domain, ...) \
+ do { \
+ pg_prevent_errno_in_scope(); \
+ if (__builtin_constant_p(elevel) && (elevel) >= ERROR ? \
+ errstart_cold(elevel, domain) : \
+ errstart(elevel, domain)) \
+ __VA_ARGS__, errfinish(__FILE__, __LINE__, __func__); \
+ if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \
+ pg_unreachable(); \
+ } while(0)
+#else /* !HAVE__BUILTIN_CONSTANT_P */
+#define ereport_domain(elevel, domain, ...) \
+ do { \
+ const int elevel_ = (elevel); \
+ pg_prevent_errno_in_scope(); \
+ if (errstart(elevel_, domain)) \
+ __VA_ARGS__, errfinish(__FILE__, __LINE__, __func__); \
+ if (elevel_ >= ERROR) \
+ pg_unreachable(); \
+ } while(0)
+#endif /* HAVE__BUILTIN_CONSTANT_P */
+
+#define ereport(elevel, ...) \
+ ereport_domain(elevel, TEXTDOMAIN, __VA_ARGS__)
+
+#define TEXTDOMAIN NULL
+
+extern bool message_level_is_interesting(int elevel);
+
+extern bool errstart(int elevel, const char *domain);
+extern pg_attribute_cold bool errstart_cold(int elevel, const char *domain);
+extern void errfinish(const char *filename, int lineno, const char *funcname);
+
+extern int errcode(int sqlerrcode);
+
+extern int errcode_for_file_access(void);
+extern int errcode_for_socket_access(void);
+
+extern int errmsg(const char *fmt,...) pg_attribute_printf(1, 2);
+extern int errmsg_internal(const char *fmt,...) pg_attribute_printf(1, 2);
+
+extern int errmsg_plural(const char *fmt_singular, const char *fmt_plural,
+ unsigned long n,...) pg_attribute_printf(1, 4) pg_attribute_printf(2, 4);
+
+extern int errdetail(const char *fmt,...) pg_attribute_printf(1, 2);
+extern int errdetail_internal(const char *fmt,...) pg_attribute_printf(1, 2);
+
+extern int errdetail_log(const char *fmt,...) pg_attribute_printf(1, 2);
+
+extern int errdetail_log_plural(const char *fmt_singular,
+ const char *fmt_plural,
+ unsigned long n,...) pg_attribute_printf(1, 4) pg_attribute_printf(2, 4);
+
+extern int errdetail_plural(const char *fmt_singular, const char *fmt_plural,
+ unsigned long n,...) pg_attribute_printf(1, 4) pg_attribute_printf(2, 4);
+
+extern int errhint(const char *fmt,...) pg_attribute_printf(1, 2);
+
+extern int errhint_plural(const char *fmt_singular, const char *fmt_plural,
+ unsigned long n,...) pg_attribute_printf(1, 4) pg_attribute_printf(2, 4);
+
+/*
+ * errcontext() is typically called in error context callback functions, not
+ * within an ereport() invocation. The callback function can be in a different
+ * module than the ereport() call, so the message domain passed in errstart()
+ * is not usually the correct domain for translating the context message.
+ * set_errcontext_domain() first sets the domain to be used, and
+ * errcontext_msg() passes the actual message.
+ */
+#define errcontext set_errcontext_domain(TEXTDOMAIN), errcontext_msg
+
+extern int set_errcontext_domain(const char *domain);
+
+extern int errcontext_msg(const char *fmt,...) pg_attribute_printf(1, 2);
+
+extern int errhidestmt(bool hide_stmt);
+extern int errhidecontext(bool hide_ctx);
+
+extern int errbacktrace(void);
+
+extern int errposition(int cursorpos);
+
+extern int internalerrposition(int cursorpos);
+extern int internalerrquery(const char *query);
+
+extern int err_generic_string(int field, const char *str);
+
+extern int geterrcode(void);
+extern int geterrposition(void);
+extern int getinternalerrposition(void);
+
+
+/*----------
+ * Old-style error reporting API: to be used in this way:
+ * elog(ERROR, "portal \"%s\" not found", stmt->portalname);
+ *----------
+ */
+#define elog(elevel, ...) \
+ ereport(elevel, errmsg_internal(__VA_ARGS__))
+
+
+/*----------
+ * Support for reporting "soft" errors that don't require a full transaction
+ * abort to clean up. This is to be used in this way:
+ * errsave(context,
+ * errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ * errmsg("invalid input syntax for type %s: \"%s\"",
+ * "boolean", in_str),
+ * ... other errxxx() fields as needed ...);
+ *
+ * "context" is a node pointer or NULL, and the remaining auxiliary calls
+ * provide the same error details as in ereport(). If context is not a
+ * pointer to an ErrorSaveContext node, then errsave(context, ...)
+ * behaves identically to ereport(ERROR, ...). If context is a pointer
+ * to an ErrorSaveContext node, then the information provided by the
+ * auxiliary calls is stored in the context node and control returns
+ * normally. The caller of errsave() must then do any required cleanup
+ * and return control back to its caller. That caller must check the
+ * ErrorSaveContext node to see whether an error occurred before
+ * it can trust the function's result to be meaningful.
+ *
+ * errsave_domain() allows a message domain to be specified; it is
+ * precisely analogous to ereport_domain().
+ *----------
+ */
+#define errsave_domain(context, domain, ...) \
+ do { \
+ struct Node *context_ = (context); \
+ pg_prevent_errno_in_scope(); \
+ if (errsave_start(context_, domain)) \
+ __VA_ARGS__, errsave_finish(context_, __FILE__, __LINE__, __func__); \
+ } while(0)
+
+#define errsave(context, ...) \
+ errsave_domain(context, TEXTDOMAIN, __VA_ARGS__)
+
+/*
+ * "ereturn(context, dummy_value, ...);" is exactly the same as
+ * "errsave(context, ...); return dummy_value;". This saves a bit
+ * of typing in the common case where a function has no cleanup
+ * actions to take after reporting a soft error. "dummy_value"
+ * can be empty if the function returns void.
+ */
+#define ereturn_domain(context, dummy_value, domain, ...) \
+ do { \
+ errsave_domain(context, domain, __VA_ARGS__); \
+ return dummy_value; \
+ } while(0)
+
+#define ereturn(context, dummy_value, ...) \
+ ereturn_domain(context, dummy_value, TEXTDOMAIN, __VA_ARGS__)
+
+extern bool errsave_start(struct Node *context, const char *domain);
+extern void errsave_finish(struct Node *context,
+ const char *filename, int lineno,
+ const char *funcname);
+
+
+/* Support for constructing error strings separately from ereport() calls */
+
+extern void pre_format_elog_string(int errnumber, const char *domain);
+extern char *format_elog_string(const char *fmt,...) pg_attribute_printf(1, 2);
+
+
+/* Support for attaching context information to error reports */
+
+typedef struct ErrorContextCallback
+{
+ struct ErrorContextCallback *previous;
+ void (*callback) (void *arg);
+ void *arg;
+} ErrorContextCallback;
+
+extern PGDLLIMPORT ErrorContextCallback *error_context_stack;
+
+
+/*----------
+ * API for catching ereport(ERROR) exits. Use these macros like so:
+ *
+ * PG_TRY();
+ * {
+ * ... code that might throw ereport(ERROR) ...
+ * }
+ * PG_CATCH();
+ * {
+ * ... error recovery code ...
+ * }
+ * PG_END_TRY();
+ *
+ * (The braces are not actually necessary, but are recommended so that
+ * pgindent will indent the construct nicely.) The error recovery code
+ * can either do PG_RE_THROW to propagate the error outwards, or do a
+ * (sub)transaction abort. Failure to do so may leave the system in an
+ * inconsistent state for further processing.
+ *
+ * For the common case that the error recovery code and the cleanup in the
+ * normal code path are identical, the following can be used instead:
+ *
+ * PG_TRY();
+ * {
+ * ... code that might throw ereport(ERROR) ...
+ * }
+ * PG_FINALLY();
+ * {
+ * ... cleanup code ...
+ * }
+ * PG_END_TRY();
+ *
+ * The cleanup code will be run in either case, and any error will be rethrown
+ * afterwards.
+ *
+ * You cannot use both PG_CATCH() and PG_FINALLY() in the same
+ * PG_TRY()/PG_END_TRY() block.
+ *
+ * Note: while the system will correctly propagate any new ereport(ERROR)
+ * occurring in the recovery section, there is a small limit on the number
+ * of levels this will work for. It's best to keep the error recovery
+ * section simple enough that it can't generate any new errors, at least
+ * not before popping the error stack.
+ *
+ * Note: an ereport(FATAL) will not be caught by this construct; control will
+ * exit straight through proc_exit(). Therefore, do NOT put any cleanup
+ * of non-process-local resources into the error recovery section, at least
+ * not without taking thought for what will happen during ereport(FATAL).
+ * The PG_ENSURE_ERROR_CLEANUP macros provided by storage/ipc.h may be
+ * helpful in such cases.
+ *
+ * Note: if a local variable of the function containing PG_TRY is modified
+ * in the PG_TRY section and used in the PG_CATCH section, that variable
+ * must be declared "volatile" for POSIX compliance. This is not mere
+ * pedantry; we have seen bugs from compilers improperly optimizing code
+ * away when such a variable was not marked. Beware that gcc's -Wclobbered
+ * warnings are just about entirely useless for catching such oversights.
+ *
+ * Each of these macros accepts an optional argument which can be specified
+ * to apply a suffix to the variables declared within the macros. This suffix
+ * can be used to avoid the compiler emitting warnings about shadowed
+ * variables when compiling with -Wshadow in situations where nested PG_TRY()
+ * statements are required. The optional suffix may contain any character
+ * that's allowed in a variable name. The suffix, if specified, must be the
+ * same within each component macro of the given PG_TRY() statement.
+ *----------
+ */
+#define PG_TRY(...) \
+ do { \
+ sigjmp_buf *_save_exception_stack##__VA_ARGS__ = PG_exception_stack; \
+ ErrorContextCallback *_save_context_stack##__VA_ARGS__ = error_context_stack; \
+ sigjmp_buf _local_sigjmp_buf##__VA_ARGS__; \
+ bool _do_rethrow##__VA_ARGS__ = false; \
+ if (sigsetjmp(_local_sigjmp_buf##__VA_ARGS__, 0) == 0) \
+ { \
+ PG_exception_stack = &_local_sigjmp_buf##__VA_ARGS__
+
+#define PG_CATCH(...) \
+ } \
+ else \
+ { \
+ PG_exception_stack = _save_exception_stack##__VA_ARGS__; \
+ error_context_stack = _save_context_stack##__VA_ARGS__
+
+#define PG_FINALLY(...) \
+ } \
+ else \
+ _do_rethrow##__VA_ARGS__ = true; \
+ { \
+ PG_exception_stack = _save_exception_stack##__VA_ARGS__; \
+ error_context_stack = _save_context_stack##__VA_ARGS__
+
+#define PG_END_TRY(...) \
+ } \
+ if (_do_rethrow##__VA_ARGS__) \
+ PG_RE_THROW(); \
+ PG_exception_stack = _save_exception_stack##__VA_ARGS__; \
+ error_context_stack = _save_context_stack##__VA_ARGS__; \
+ } while (0)
+
+/*
+ * Some compilers understand pg_attribute_noreturn(); for other compilers,
+ * insert pg_unreachable() so that the compiler gets the point.
+ */
+#ifdef HAVE_PG_ATTRIBUTE_NORETURN
+#define PG_RE_THROW() \
+ pg_re_throw()
+#else
+#define PG_RE_THROW() \
+ (pg_re_throw(), pg_unreachable())
+#endif
+
+extern PGDLLIMPORT sigjmp_buf *PG_exception_stack;
+
+
+/* Stuff that error handlers might want to use */
+
+/*
+ * ErrorData holds the data accumulated during any one ereport() cycle.
+ * Any non-NULL pointers must point to palloc'd data.
+ * (The const pointers are an exception; we assume they point at non-freeable
+ * constant strings.)
+ */
+typedef struct ErrorData
+{
+ int elevel; /* error level */
+ bool output_to_server; /* will report to server log? */
+ bool output_to_client; /* will report to client? */
+ bool hide_stmt; /* true to prevent STATEMENT: inclusion */
+ bool hide_ctx; /* true to prevent CONTEXT: inclusion */
+ const char *filename; /* __FILE__ of ereport() call */
+ int lineno; /* __LINE__ of ereport() call */
+ const char *funcname; /* __func__ of ereport() call */
+ const char *domain; /* message domain */
+ const char *context_domain; /* message domain for context message */
+ int sqlerrcode; /* encoded ERRSTATE */
+ char *message; /* primary error message (translated) */
+ char *detail; /* detail error message */
+ char *detail_log; /* detail error message for server log only */
+ char *hint; /* hint message */
+ char *context; /* context message */
+ char *backtrace; /* backtrace */
+ const char *message_id; /* primary message's id (original string) */
+ char *schema_name; /* name of schema */
+ char *table_name; /* name of table */
+ char *column_name; /* name of column */
+ char *datatype_name; /* name of datatype */
+ char *constraint_name; /* name of constraint */
+ int cursorpos; /* cursor index into query string */
+ int internalpos; /* cursor index into internalquery */
+ char *internalquery; /* text of internally-generated query */
+ int saved_errno; /* errno at entry */
+
+ /* context containing associated non-constant strings */
+ struct MemoryContextData *assoc_context;
+} ErrorData;
+
+extern void EmitErrorReport(void);
+extern ErrorData *CopyErrorData(void);
+extern void FreeErrorData(ErrorData *edata);
+extern void FlushErrorState(void);
+extern void ReThrowError(ErrorData *edata) pg_attribute_noreturn();
+extern void ThrowErrorData(ErrorData *edata);
+extern void pg_re_throw(void) pg_attribute_noreturn();
+
+extern char *GetErrorContextStack(void);
+
+/* Hook for intercepting messages before they are sent to the server log */
+typedef void (*emit_log_hook_type) (ErrorData *edata);
+extern PGDLLIMPORT emit_log_hook_type emit_log_hook;
+
+
+/* GUC-configurable parameters */
+
+typedef enum
+{
+ PGERROR_TERSE, /* single-line error messages */
+ PGERROR_DEFAULT, /* recommended style */
+ PGERROR_VERBOSE /* all the facts, ma'am */
+} PGErrorVerbosity;
+
+extern PGDLLIMPORT int Log_error_verbosity;
+extern PGDLLIMPORT char *Log_line_prefix;
+extern PGDLLIMPORT int Log_destination;
+extern PGDLLIMPORT char *Log_destination_string;
+extern PGDLLIMPORT bool syslog_sequence_numbers;
+extern PGDLLIMPORT bool syslog_split_messages;
+
+/* Log destination bitmap */
+#define LOG_DESTINATION_STDERR 1
+#define LOG_DESTINATION_SYSLOG 2
+#define LOG_DESTINATION_EVENTLOG 4
+#define LOG_DESTINATION_CSVLOG 8
+#define LOG_DESTINATION_JSONLOG 16
+
+/* Other exported functions */
+extern void log_status_format(StringInfo buf, const char *format,
+ ErrorData *edata);
+extern void DebugFileOpen(void);
+extern char *unpack_sql_state(int sql_state);
+extern bool in_error_recursion_trouble(void);
+
+/* Common functions shared across destinations */
+extern void reset_formatted_start_time(void);
+extern char *get_formatted_start_time(void);
+extern char *get_formatted_log_time(void);
+extern const char *get_backend_type_for_log(void);
+extern bool check_log_of_query(ErrorData *edata);
+extern const char *error_severity(int elevel);
+extern void write_pipe_chunks(char *data, int len, int dest);
+
+/* Destination-specific functions */
+extern void write_csvlog(ErrorData *edata);
+extern void write_jsonlog(ErrorData *edata);
+
+/*
+ * Write errors to stderr (or by equal means when stderr is
+ * not available). Used before ereport/elog can be used
+ * safely (memory context, GUC load etc)
+ */
+extern void write_stderr(const char *fmt,...) pg_attribute_printf(1, 2);
+
+/*
+ * Write a message to STDERR using only async-signal-safe functions. This can
+ * be used to safely emit a message from a signal handler.
+ */
+extern void write_stderr_signal_safe(const char *fmt);
+
+#endif /* ELOG_H */
diff --git a/src/include/utils/evtcache.h b/src/include/utils/evtcache.h
new file mode 100644
index 0000000..d340026
--- /dev/null
+++ b/src/include/utils/evtcache.h
@@ -0,0 +1,37 @@
+/*-------------------------------------------------------------------------
+ *
+ * evtcache.h
+ * Special-purpose cache for event trigger data.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/utils/evtcache.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EVTCACHE_H
+#define EVTCACHE_H
+
+#include "nodes/bitmapset.h"
+#include "nodes/pg_list.h"
+
+typedef enum
+{
+ EVT_DDLCommandStart,
+ EVT_DDLCommandEnd,
+ EVT_SQLDrop,
+ EVT_TableRewrite
+} EventTriggerEvent;
+
+typedef struct
+{
+ Oid fnoid; /* function to be called */
+ char enabled; /* as SESSION_REPLICATION_ROLE_* */
+ Bitmapset *tagset; /* command tags, or NULL if empty */
+} EventTriggerCacheItem;
+
+extern List *EventCacheLookup(EventTriggerEvent event);
+
+#endif /* EVTCACHE_H */
diff --git a/src/include/utils/expandeddatum.h b/src/include/utils/expandeddatum.h
new file mode 100644
index 0000000..a77bb7e
--- /dev/null
+++ b/src/include/utils/expandeddatum.h
@@ -0,0 +1,170 @@
+/*-------------------------------------------------------------------------
+ *
+ * expandeddatum.h
+ * Declarations for access to "expanded" value representations.
+ *
+ * Complex data types, particularly container types such as arrays and
+ * records, usually have on-disk representations that are compact but not
+ * especially convenient to modify. What's more, when we do modify them,
+ * having to recopy all the rest of the value can be extremely inefficient.
+ * Therefore, we provide a notion of an "expanded" representation that is used
+ * only in memory and is optimized more for computation than storage.
+ * The format appearing on disk is called the data type's "flattened"
+ * representation, since it is required to be a contiguous blob of bytes --
+ * but the type can have an expanded representation that is not. Data types
+ * must provide means to translate an expanded representation back to
+ * flattened form.
+ *
+ * An expanded object is meant to survive across multiple operations, but
+ * not to be enormously long-lived; for example it might be a local variable
+ * in a PL/pgSQL procedure. So its extra bulk compared to the on-disk format
+ * is a worthwhile trade-off.
+ *
+ * References to expanded objects are a type of TOAST pointer.
+ * Because of longstanding conventions in Postgres, this means that the
+ * flattened form of such an object must always be a varlena object.
+ * Fortunately that's no restriction in practice.
+ *
+ * There are actually two kinds of TOAST pointers for expanded objects:
+ * read-only and read-write pointers. Possession of one of the latter
+ * authorizes a function to modify the value in-place rather than copying it
+ * as would normally be required. Functions should always return a read-write
+ * pointer to any new expanded object they create. Functions that modify an
+ * argument value in-place must take care that they do not corrupt the old
+ * value if they fail partway through.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/expandeddatum.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXPANDEDDATUM_H
+#define EXPANDEDDATUM_H
+
+#include "varatt.h"
+
+/* Size of an EXTERNAL datum that contains a pointer to an expanded object */
+#define EXPANDED_POINTER_SIZE (VARHDRSZ_EXTERNAL + sizeof(varatt_expanded))
+
+/*
+ * "Methods" that must be provided for any expanded object.
+ *
+ * get_flat_size: compute space needed for flattened representation (total,
+ * including header).
+ *
+ * flatten_into: construct flattened representation in the caller-allocated
+ * space at *result, of size allocated_size (which will always be the result
+ * of a preceding get_flat_size call; it's passed for cross-checking).
+ *
+ * The flattened representation must be a valid in-line, non-compressed,
+ * 4-byte-header varlena object.
+ *
+ * Note: construction of a heap tuple from an expanded datum calls
+ * get_flat_size twice, so it's worthwhile to make sure that that doesn't
+ * incur too much overhead.
+ */
+typedef Size (*EOM_get_flat_size_method) (ExpandedObjectHeader *eohptr);
+typedef void (*EOM_flatten_into_method) (ExpandedObjectHeader *eohptr,
+ void *result, Size allocated_size);
+
+/* Struct of function pointers for an expanded object's methods */
+typedef struct ExpandedObjectMethods
+{
+ EOM_get_flat_size_method get_flat_size;
+ EOM_flatten_into_method flatten_into;
+} ExpandedObjectMethods;
+
+/*
+ * Every expanded object must contain this header; typically the header
+ * is embedded in some larger struct that adds type-specific fields.
+ *
+ * It is presumed that the header object and all subsidiary data are stored
+ * in eoh_context, so that the object can be freed by deleting that context,
+ * or its storage lifespan can be altered by reparenting the context.
+ * (In principle the object could own additional resources, such as malloc'd
+ * storage, and use a memory context reset callback to free them upon reset or
+ * deletion of eoh_context.)
+ *
+ * We set up two TOAST pointers within the standard header, one read-write
+ * and one read-only. This allows functions to return either kind of pointer
+ * without making an additional allocation, and in particular without worrying
+ * whether a separately palloc'd object would have sufficient lifespan.
+ * But note that these pointers are just a convenience; a pointer object
+ * appearing somewhere else would still be legal.
+ *
+ * The typedef declaration for this appears in postgres.h.
+ */
+struct ExpandedObjectHeader
+{
+ /* Phony varlena header */
+ int32 vl_len_; /* always EOH_HEADER_MAGIC, see below */
+
+ /* Pointer to methods required for object type */
+ const ExpandedObjectMethods *eoh_methods;
+
+ /* Memory context containing this header and subsidiary data */
+ MemoryContext eoh_context;
+
+ /* Standard R/W TOAST pointer for this object is kept here */
+ char eoh_rw_ptr[EXPANDED_POINTER_SIZE];
+
+ /* Standard R/O TOAST pointer for this object is kept here */
+ char eoh_ro_ptr[EXPANDED_POINTER_SIZE];
+};
+
+/*
+ * Particularly for read-only functions, it is handy to be able to work with
+ * either regular "flat" varlena inputs or expanded inputs of the same data
+ * type. To allow determining which case an argument-fetching function has
+ * returned, the first int32 of an ExpandedObjectHeader always contains -1
+ * (EOH_HEADER_MAGIC to the code). This works since no 4-byte-header varlena
+ * could have that as its first 4 bytes. Caution: we could not reliably tell
+ * the difference between an ExpandedObjectHeader and a short-header object
+ * with this trick. However, it works fine if the argument fetching code
+ * always returns either a 4-byte-header flat object or an expanded object.
+ */
+#define EOH_HEADER_MAGIC (-1)
+#define VARATT_IS_EXPANDED_HEADER(PTR) \
+ (((varattrib_4b *) (PTR))->va_4byte.va_header == (uint32) EOH_HEADER_MAGIC)
+
+/*
+ * Generic support functions for expanded objects.
+ * (More of these might be worth inlining later.)
+ */
+
+static inline Datum
+EOHPGetRWDatum(const struct ExpandedObjectHeader *eohptr)
+{
+ return PointerGetDatum(eohptr->eoh_rw_ptr);
+}
+
+static inline Datum
+EOHPGetRODatum(const struct ExpandedObjectHeader *eohptr)
+{
+ return PointerGetDatum(eohptr->eoh_ro_ptr);
+}
+
+/* Does the Datum represent a writable expanded object? */
+#define DatumIsReadWriteExpandedObject(d, isnull, typlen) \
+ (((isnull) || (typlen) != -1) ? false : \
+ VARATT_IS_EXTERNAL_EXPANDED_RW(DatumGetPointer(d)))
+
+#define MakeExpandedObjectReadOnly(d, isnull, typlen) \
+ (((isnull) || (typlen) != -1) ? (d) : \
+ MakeExpandedObjectReadOnlyInternal(d))
+
+extern ExpandedObjectHeader *DatumGetEOHP(Datum d);
+extern void EOH_init_header(ExpandedObjectHeader *eohptr,
+ const ExpandedObjectMethods *methods,
+ MemoryContext obj_context);
+extern Size EOH_get_flat_size(ExpandedObjectHeader *eohptr);
+extern void EOH_flatten_into(ExpandedObjectHeader *eohptr,
+ void *result, Size allocated_size);
+extern Datum MakeExpandedObjectReadOnlyInternal(Datum d);
+extern Datum TransferExpandedObject(Datum d, MemoryContext new_parent);
+extern void DeleteExpandedObject(Datum d);
+
+#endif /* EXPANDEDDATUM_H */
diff --git a/src/include/utils/expandedrecord.h b/src/include/utils/expandedrecord.h
new file mode 100644
index 0000000..7e7c114
--- /dev/null
+++ b/src/include/utils/expandedrecord.h
@@ -0,0 +1,241 @@
+/*-------------------------------------------------------------------------
+ *
+ * expandedrecord.h
+ * Declarations for composite expanded objects.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/expandedrecord.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXPANDEDRECORD_H
+#define EXPANDEDRECORD_H
+
+#include "access/htup.h"
+#include "access/tupdesc.h"
+#include "fmgr.h"
+#include "utils/expandeddatum.h"
+
+
+/*
+ * An expanded record is contained within a private memory context (as
+ * all expanded objects must be) and has a control structure as below.
+ *
+ * The expanded record might contain a regular "flat" tuple if that was the
+ * original input and we've not modified it. Otherwise, the contents are
+ * represented by Datum/isnull arrays plus type information. We could also
+ * have both forms, if we've deconstructed the original tuple for access
+ * purposes but not yet changed it. For pass-by-reference field types, the
+ * Datums would point into the flat tuple in this situation. Once we start
+ * modifying tuple fields, new pass-by-ref fields are separately palloc'd
+ * within the memory context.
+ *
+ * It's possible to build an expanded record that references a "flat" tuple
+ * stored externally, if the caller can guarantee that that tuple will not
+ * change for the lifetime of the expanded record. (This frammish is mainly
+ * meant to avoid unnecessary data copying in trigger functions.)
+ */
+#define ER_MAGIC 1384727874 /* ID for debugging crosschecks */
+
+typedef struct ExpandedRecordHeader
+{
+ /* Standard header for expanded objects */
+ ExpandedObjectHeader hdr;
+
+ /* Magic value identifying an expanded record (for debugging only) */
+ int er_magic;
+
+ /* Assorted flag bits */
+ int flags;
+#define ER_FLAG_FVALUE_VALID 0x0001 /* fvalue is up to date? */
+#define ER_FLAG_FVALUE_ALLOCED 0x0002 /* fvalue is local storage? */
+#define ER_FLAG_DVALUES_VALID 0x0004 /* dvalues/dnulls are up to date? */
+#define ER_FLAG_DVALUES_ALLOCED 0x0008 /* any field values local storage? */
+#define ER_FLAG_HAVE_EXTERNAL 0x0010 /* any field values are external? */
+#define ER_FLAG_TUPDESC_ALLOCED 0x0020 /* tupdesc is local storage? */
+#define ER_FLAG_IS_DOMAIN 0x0040 /* er_decltypeid is domain? */
+#define ER_FLAG_IS_DUMMY 0x0080 /* this header is dummy (see below) */
+/* flag bits that are not to be cleared when replacing tuple data: */
+#define ER_FLAGS_NON_DATA \
+ (ER_FLAG_TUPDESC_ALLOCED | ER_FLAG_IS_DOMAIN | ER_FLAG_IS_DUMMY)
+
+ /* Declared type of the record variable (could be a domain type) */
+ Oid er_decltypeid;
+
+ /*
+ * Actual composite type/typmod; never a domain (if ER_FLAG_IS_DOMAIN,
+ * these identify the composite base type). These will match
+ * er_tupdesc->tdtypeid/tdtypmod, as well as the header fields of
+ * composite datums made from or stored in this expanded record.
+ */
+ Oid er_typeid; /* type OID of the composite type */
+ int32 er_typmod; /* typmod of the composite type */
+
+ /*
+ * Tuple descriptor, if we have one, else NULL. This may point to a
+ * reference-counted tupdesc originally belonging to the typcache, in
+ * which case we use a memory context reset callback to release the
+ * refcount. It can also be locally allocated in this object's private
+ * context (in which case ER_FLAG_TUPDESC_ALLOCED is set).
+ */
+ TupleDesc er_tupdesc;
+
+ /*
+ * Unique-within-process identifier for the tupdesc (see typcache.h). This
+ * field will never be equal to INVALID_TUPLEDESC_IDENTIFIER.
+ */
+ uint64 er_tupdesc_id;
+
+ /*
+ * If we have a Datum-array representation of the record, it's kept here;
+ * else ER_FLAG_DVALUES_VALID is not set, and dvalues/dnulls may be NULL
+ * if they've not yet been allocated. If allocated, the dvalues and
+ * dnulls arrays are palloc'd within the object private context, and are
+ * of length matching er_tupdesc->natts. For pass-by-ref field types,
+ * dvalues entries might point either into the fstartptr..fendptr area, or
+ * to separately palloc'd chunks.
+ */
+ Datum *dvalues; /* array of Datums */
+ bool *dnulls; /* array of is-null flags for Datums */
+ int nfields; /* length of above arrays */
+
+ /*
+ * flat_size is the current space requirement for the flat equivalent of
+ * the expanded record, if known; otherwise it's 0. We store this to make
+ * consecutive calls of get_flat_size cheap. If flat_size is not 0, the
+ * component values data_len, hoff, and hasnull must be valid too.
+ */
+ Size flat_size;
+
+ Size data_len; /* data len within flat_size */
+ int hoff; /* header offset */
+ bool hasnull; /* null bitmap needed? */
+
+ /*
+ * fvalue points to the flat representation if we have one, else it is
+ * NULL. If the flat representation is valid (up to date) then
+ * ER_FLAG_FVALUE_VALID is set. Even if we've outdated the flat
+ * representation due to changes of user fields, it can still be used to
+ * fetch system column values. If we have a flat representation then
+ * fstartptr/fendptr point to the start and end+1 of its data area; this
+ * is so that we can tell which Datum pointers point into the flat
+ * representation rather than being pointers to separately palloc'd data.
+ */
+ HeapTuple fvalue; /* might or might not be private storage */
+ char *fstartptr; /* start of its data area */
+ char *fendptr; /* end+1 of its data area */
+
+ /* Some operations on the expanded record need a short-lived context */
+ MemoryContext er_short_term_cxt; /* short-term memory context */
+
+ /* Working state for domain checking, used if ER_FLAG_IS_DOMAIN is set */
+ struct ExpandedRecordHeader *er_dummy_header; /* dummy record header */
+ void *er_domaininfo; /* cache space for domain_check() */
+
+ /* Callback info (it's active if er_mcb.arg is not NULL) */
+ MemoryContextCallback er_mcb;
+} ExpandedRecordHeader;
+
+/* fmgr functions and macros for expanded record objects */
+static inline Datum
+ExpandedRecordGetDatum(const ExpandedRecordHeader *erh)
+{
+ return EOHPGetRWDatum(&erh->hdr);
+}
+
+static inline Datum
+ExpandedRecordGetRODatum(const ExpandedRecordHeader *erh)
+{
+ return EOHPGetRODatum(&erh->hdr);
+}
+
+#define PG_GETARG_EXPANDED_RECORD(n) DatumGetExpandedRecord(PG_GETARG_DATUM(n))
+#define PG_RETURN_EXPANDED_RECORD(x) PG_RETURN_DATUM(ExpandedRecordGetDatum(x))
+
+/* assorted other macros */
+#define ExpandedRecordIsEmpty(erh) \
+ (((erh)->flags & (ER_FLAG_DVALUES_VALID | ER_FLAG_FVALUE_VALID)) == 0)
+#define ExpandedRecordIsDomain(erh) \
+ (((erh)->flags & ER_FLAG_IS_DOMAIN) != 0)
+
+/* this can substitute for TransferExpandedObject() when we already have erh */
+#define TransferExpandedRecord(erh, cxt) \
+ MemoryContextSetParent((erh)->hdr.eoh_context, cxt)
+
+/* information returned by expanded_record_lookup_field() */
+typedef struct ExpandedRecordFieldInfo
+{
+ int fnumber; /* field's attr number in record */
+ Oid ftypeid; /* field's type/typmod info */
+ int32 ftypmod;
+ Oid fcollation; /* field's collation if any */
+} ExpandedRecordFieldInfo;
+
+/*
+ * prototypes for functions defined in expandedrecord.c
+ */
+extern ExpandedRecordHeader *make_expanded_record_from_typeid(Oid type_id, int32 typmod,
+ MemoryContext parentcontext);
+extern ExpandedRecordHeader *make_expanded_record_from_tupdesc(TupleDesc tupdesc,
+ MemoryContext parentcontext);
+extern ExpandedRecordHeader *make_expanded_record_from_exprecord(ExpandedRecordHeader *olderh,
+ MemoryContext parentcontext);
+extern void expanded_record_set_tuple(ExpandedRecordHeader *erh,
+ HeapTuple tuple, bool copy, bool expand_external);
+extern Datum make_expanded_record_from_datum(Datum recorddatum,
+ MemoryContext parentcontext);
+extern TupleDesc expanded_record_fetch_tupdesc(ExpandedRecordHeader *erh);
+extern HeapTuple expanded_record_get_tuple(ExpandedRecordHeader *erh);
+extern ExpandedRecordHeader *DatumGetExpandedRecord(Datum d);
+extern void deconstruct_expanded_record(ExpandedRecordHeader *erh);
+extern bool expanded_record_lookup_field(ExpandedRecordHeader *erh,
+ const char *fieldname,
+ ExpandedRecordFieldInfo *finfo);
+extern Datum expanded_record_fetch_field(ExpandedRecordHeader *erh, int fnumber,
+ bool *isnull);
+extern void expanded_record_set_field_internal(ExpandedRecordHeader *erh,
+ int fnumber,
+ Datum newValue, bool isnull,
+ bool expand_external,
+ bool check_constraints);
+extern void expanded_record_set_fields(ExpandedRecordHeader *erh,
+ const Datum *newValues, const bool *isnulls,
+ bool expand_external);
+
+/* outside code should never call expanded_record_set_field_internal as such */
+#define expanded_record_set_field(erh, fnumber, newValue, isnull, expand_external) \
+ expanded_record_set_field_internal(erh, fnumber, newValue, isnull, expand_external, true)
+
+/*
+ * Inline-able fast cases. The expanded_record_fetch_xxx functions above
+ * handle the general cases.
+ */
+
+/* Get the tupdesc for the expanded record's actual type */
+static inline TupleDesc
+expanded_record_get_tupdesc(ExpandedRecordHeader *erh)
+{
+ if (likely(erh->er_tupdesc != NULL))
+ return erh->er_tupdesc;
+ else
+ return expanded_record_fetch_tupdesc(erh);
+}
+
+/* Get value of record field */
+static inline Datum
+expanded_record_get_field(ExpandedRecordHeader *erh, int fnumber,
+ bool *isnull)
+{
+ if ((erh->flags & ER_FLAG_DVALUES_VALID) &&
+ likely(fnumber > 0 && fnumber <= erh->nfields))
+ {
+ *isnull = erh->dnulls[fnumber - 1];
+ return erh->dvalues[fnumber - 1];
+ }
+ else
+ return expanded_record_fetch_field(erh, fnumber, isnull);
+}
+
+#endif /* EXPANDEDRECORD_H */
diff --git a/src/include/utils/float.h b/src/include/utils/float.h
new file mode 100644
index 0000000..7529899
--- /dev/null
+++ b/src/include/utils/float.h
@@ -0,0 +1,357 @@
+/*-------------------------------------------------------------------------
+ *
+ * float.h
+ * Definitions for the built-in floating-point types
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/include/utils/float.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FLOAT_H
+#define FLOAT_H
+
+#include <math.h>
+
+/* X/Open (XSI) requires <math.h> to provide M_PI, but core POSIX does not */
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+/* Radians per degree, a.k.a. PI / 180 */
+#define RADIANS_PER_DEGREE 0.0174532925199432957692
+
+/* Visual C++ etc lacks NAN, and won't accept 0.0/0.0. */
+#if defined(WIN32) && !defined(NAN)
+static const uint32 nan[2] = {0xffffffff, 0x7fffffff};
+
+#define NAN (*(const float8 *) nan)
+#endif
+
+extern PGDLLIMPORT int extra_float_digits;
+
+/*
+ * Utility functions in float.c
+ */
+extern void float_overflow_error(void) pg_attribute_noreturn();
+extern void float_underflow_error(void) pg_attribute_noreturn();
+extern void float_zero_divide_error(void) pg_attribute_noreturn();
+extern int is_infinite(float8 val);
+extern float8 float8in_internal(char *num, char **endptr_p,
+ const char *type_name, const char *orig_string,
+ struct Node *escontext);
+extern float4 float4in_internal(char *num, char **endptr_p,
+ const char *type_name, const char *orig_string,
+ struct Node *escontext);
+extern char *float8out_internal(float8 num);
+extern int float4_cmp_internal(float4 a, float4 b);
+extern int float8_cmp_internal(float8 a, float8 b);
+
+/*
+ * Routines to provide reasonably platform-independent handling of
+ * infinity and NaN
+ *
+ * We assume that isinf() and isnan() are available and work per spec.
+ * (On some platforms, we have to supply our own; see src/port.) However,
+ * generating an Infinity or NaN in the first place is less well standardized;
+ * pre-C99 systems tend not to have C99's INFINITY and NaN macros. We
+ * centralize our workarounds for this here.
+ */
+
+/*
+ * The funny placements of the two #pragmas is necessary because of a
+ * long lived bug in the Microsoft compilers.
+ * See http://support.microsoft.com/kb/120968/en-us for details
+ */
+#ifdef _MSC_VER
+#pragma warning(disable:4756)
+#endif
+static inline float4
+get_float4_infinity(void)
+{
+#ifdef INFINITY
+ /* C99 standard way */
+ return (float4) INFINITY;
+#else
+#ifdef _MSC_VER
+#pragma warning(default:4756)
+#endif
+
+ /*
+ * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
+ * largest normal float8. We assume forcing an overflow will get us a
+ * true infinity.
+ */
+ return (float4) (HUGE_VAL * HUGE_VAL);
+#endif
+}
+
+static inline float8
+get_float8_infinity(void)
+{
+#ifdef INFINITY
+ /* C99 standard way */
+ return (float8) INFINITY;
+#else
+
+ /*
+ * On some platforms, HUGE_VAL is an infinity, elsewhere it's just the
+ * largest normal float8. We assume forcing an overflow will get us a
+ * true infinity.
+ */
+ return (float8) (HUGE_VAL * HUGE_VAL);
+#endif
+}
+
+static inline float4
+get_float4_nan(void)
+{
+#ifdef NAN
+ /* C99 standard way */
+ return (float4) NAN;
+#else
+ /* Assume we can get a NAN via zero divide */
+ return (float4) (0.0 / 0.0);
+#endif
+}
+
+static inline float8
+get_float8_nan(void)
+{
+ /* (float8) NAN doesn't work on some NetBSD/MIPS releases */
+#if defined(NAN) && !(defined(__NetBSD__) && defined(__mips__))
+ /* C99 standard way */
+ return (float8) NAN;
+#else
+ /* Assume we can get a NaN via zero divide */
+ return (float8) (0.0 / 0.0);
+#endif
+}
+
+/*
+ * Floating-point arithmetic with overflow/underflow reported as errors
+ *
+ * There isn't any way to check for underflow of addition/subtraction
+ * because numbers near the underflow value have already been rounded to
+ * the point where we can't detect that the two values were originally
+ * different, e.g. on x86, '1e-45'::float4 == '2e-45'::float4 ==
+ * 1.4013e-45.
+ */
+
+static inline float4
+float4_pl(const float4 val1, const float4 val2)
+{
+ float4 result;
+
+ result = val1 + val2;
+ if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
+ float_overflow_error();
+
+ return result;
+}
+
+static inline float8
+float8_pl(const float8 val1, const float8 val2)
+{
+ float8 result;
+
+ result = val1 + val2;
+ if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
+ float_overflow_error();
+
+ return result;
+}
+
+static inline float4
+float4_mi(const float4 val1, const float4 val2)
+{
+ float4 result;
+
+ result = val1 - val2;
+ if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
+ float_overflow_error();
+
+ return result;
+}
+
+static inline float8
+float8_mi(const float8 val1, const float8 val2)
+{
+ float8 result;
+
+ result = val1 - val2;
+ if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
+ float_overflow_error();
+
+ return result;
+}
+
+static inline float4
+float4_mul(const float4 val1, const float4 val2)
+{
+ float4 result;
+
+ result = val1 * val2;
+ if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
+ float_overflow_error();
+ if (unlikely(result == 0.0f) && val1 != 0.0f && val2 != 0.0f)
+ float_underflow_error();
+
+ return result;
+}
+
+static inline float8
+float8_mul(const float8 val1, const float8 val2)
+{
+ float8 result;
+
+ result = val1 * val2;
+ if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
+ float_overflow_error();
+ if (unlikely(result == 0.0) && val1 != 0.0 && val2 != 0.0)
+ float_underflow_error();
+
+ return result;
+}
+
+static inline float4
+float4_div(const float4 val1, const float4 val2)
+{
+ float4 result;
+
+ if (unlikely(val2 == 0.0f) && !isnan(val1))
+ float_zero_divide_error();
+ result = val1 / val2;
+ if (unlikely(isinf(result)) && !isinf(val1))
+ float_overflow_error();
+ if (unlikely(result == 0.0f) && val1 != 0.0f && !isinf(val2))
+ float_underflow_error();
+
+ return result;
+}
+
+static inline float8
+float8_div(const float8 val1, const float8 val2)
+{
+ float8 result;
+
+ if (unlikely(val2 == 0.0) && !isnan(val1))
+ float_zero_divide_error();
+ result = val1 / val2;
+ if (unlikely(isinf(result)) && !isinf(val1))
+ float_overflow_error();
+ if (unlikely(result == 0.0) && val1 != 0.0 && !isinf(val2))
+ float_underflow_error();
+
+ return result;
+}
+
+/*
+ * Routines for NaN-aware comparisons
+ *
+ * We consider all NaNs to be equal and larger than any non-NaN. This is
+ * somewhat arbitrary; the important thing is to have a consistent sort
+ * order.
+ */
+
+static inline bool
+float4_eq(const float4 val1, const float4 val2)
+{
+ return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
+}
+
+static inline bool
+float8_eq(const float8 val1, const float8 val2)
+{
+ return isnan(val1) ? isnan(val2) : !isnan(val2) && val1 == val2;
+}
+
+static inline bool
+float4_ne(const float4 val1, const float4 val2)
+{
+ return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
+}
+
+static inline bool
+float8_ne(const float8 val1, const float8 val2)
+{
+ return isnan(val1) ? !isnan(val2) : isnan(val2) || val1 != val2;
+}
+
+static inline bool
+float4_lt(const float4 val1, const float4 val2)
+{
+ return !isnan(val1) && (isnan(val2) || val1 < val2);
+}
+
+static inline bool
+float8_lt(const float8 val1, const float8 val2)
+{
+ return !isnan(val1) && (isnan(val2) || val1 < val2);
+}
+
+static inline bool
+float4_le(const float4 val1, const float4 val2)
+{
+ return isnan(val2) || (!isnan(val1) && val1 <= val2);
+}
+
+static inline bool
+float8_le(const float8 val1, const float8 val2)
+{
+ return isnan(val2) || (!isnan(val1) && val1 <= val2);
+}
+
+static inline bool
+float4_gt(const float4 val1, const float4 val2)
+{
+ return !isnan(val2) && (isnan(val1) || val1 > val2);
+}
+
+static inline bool
+float8_gt(const float8 val1, const float8 val2)
+{
+ return !isnan(val2) && (isnan(val1) || val1 > val2);
+}
+
+static inline bool
+float4_ge(const float4 val1, const float4 val2)
+{
+ return isnan(val1) || (!isnan(val2) && val1 >= val2);
+}
+
+static inline bool
+float8_ge(const float8 val1, const float8 val2)
+{
+ return isnan(val1) || (!isnan(val2) && val1 >= val2);
+}
+
+static inline float4
+float4_min(const float4 val1, const float4 val2)
+{
+ return float4_lt(val1, val2) ? val1 : val2;
+}
+
+static inline float8
+float8_min(const float8 val1, const float8 val2)
+{
+ return float8_lt(val1, val2) ? val1 : val2;
+}
+
+static inline float4
+float4_max(const float4 val1, const float4 val2)
+{
+ return float4_gt(val1, val2) ? val1 : val2;
+}
+
+static inline float8
+float8_max(const float8 val1, const float8 val2)
+{
+ return float8_gt(val1, val2) ? val1 : val2;
+}
+
+#endif /* FLOAT_H */
diff --git a/src/include/utils/fmgrtab.h b/src/include/utils/fmgrtab.h
new file mode 100644
index 0000000..838ffe3
--- /dev/null
+++ b/src/include/utils/fmgrtab.h
@@ -0,0 +1,49 @@
+/*-------------------------------------------------------------------------
+ *
+ * fmgrtab.h
+ * The function manager's table of internal functions.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/fmgrtab.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FMGRTAB_H
+#define FMGRTAB_H
+
+#include "access/transam.h"
+#include "fmgr.h"
+
+
+/*
+ * This table stores info about all the built-in functions (ie, functions
+ * that are compiled into the Postgres executable).
+ */
+
+typedef struct
+{
+ Oid foid; /* OID of the function */
+ short nargs; /* 0..FUNC_MAX_ARGS, or -1 if variable count */
+ bool strict; /* T if function is "strict" */
+ bool retset; /* T if function returns a set */
+ const char *funcName; /* C name of the function */
+ PGFunction func; /* pointer to compiled function */
+} FmgrBuiltin;
+
+extern PGDLLIMPORT const FmgrBuiltin fmgr_builtins[];
+
+extern PGDLLIMPORT const int fmgr_nbuiltins; /* number of entries in table */
+
+extern PGDLLIMPORT const Oid fmgr_last_builtin_oid; /* highest function OID in
+ * table */
+
+/*
+ * Mapping from a builtin function's OID to its index in the fmgr_builtins
+ * array. This is indexed from 0 through fmgr_last_builtin_oid.
+ */
+#define InvalidOidBuiltinMapping PG_UINT16_MAX
+extern PGDLLIMPORT const uint16 fmgr_builtin_oid_index[];
+
+#endif /* FMGRTAB_H */
diff --git a/src/include/utils/formatting.h b/src/include/utils/formatting.h
new file mode 100644
index 0000000..0cad3a2
--- /dev/null
+++ b/src/include/utils/formatting.h
@@ -0,0 +1,33 @@
+/* -----------------------------------------------------------------------
+ * formatting.h
+ *
+ * src/include/utils/formatting.h
+ *
+ *
+ * Portions Copyright (c) 1999-2023, PostgreSQL Global Development Group
+ *
+ * The PostgreSQL routines for a DateTime/int/float/numeric formatting,
+ * inspired by the Oracle TO_CHAR() / TO_DATE() / TO_NUMBER() routines.
+ *
+ * Karel Zak
+ *
+ * -----------------------------------------------------------------------
+ */
+
+#ifndef _FORMATTING_H_
+#define _FORMATTING_H_
+
+
+extern char *str_tolower(const char *buff, size_t nbytes, Oid collid);
+extern char *str_toupper(const char *buff, size_t nbytes, Oid collid);
+extern char *str_initcap(const char *buff, size_t nbytes, Oid collid);
+
+extern char *asc_tolower(const char *buff, size_t nbytes);
+extern char *asc_toupper(const char *buff, size_t nbytes);
+extern char *asc_initcap(const char *buff, size_t nbytes);
+
+extern Datum parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
+ Oid *typid, int32 *typmod, int *tz,
+ struct Node *escontext);
+
+#endif
diff --git a/src/include/utils/freepage.h b/src/include/utils/freepage.h
new file mode 100644
index 0000000..8d1ebb4
--- /dev/null
+++ b/src/include/utils/freepage.h
@@ -0,0 +1,99 @@
+/*-------------------------------------------------------------------------
+ *
+ * freepage.h
+ * Management of page-organized free memory.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/freepage.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FREEPAGE_H
+#define FREEPAGE_H
+
+#include "storage/lwlock.h"
+#include "utils/relptr.h"
+
+/* Forward declarations. */
+typedef struct FreePageSpanLeader FreePageSpanLeader;
+typedef struct FreePageBtree FreePageBtree;
+typedef struct FreePageManager FreePageManager;
+
+/*
+ * PostgreSQL normally uses 8kB pages for most things, but many common
+ * architecture/operating system pairings use a 4kB page size for memory
+ * allocation, so we do that here also.
+ */
+#define FPM_PAGE_SIZE 4096
+
+/*
+ * Each freelist except for the last contains only spans of one particular
+ * size. Everything larger goes on the last one. In some sense this seems
+ * like a waste since most allocations are in a few common sizes, but it
+ * means that small allocations can simply pop the head of the relevant list
+ * without needing to worry about whether the object we find there is of
+ * precisely the correct size (because we know it must be).
+ */
+#define FPM_NUM_FREELISTS 129
+
+/* Define relative pointer types. */
+relptr_declare(FreePageBtree, RelptrFreePageBtree);
+relptr_declare(FreePageManager, RelptrFreePageManager);
+relptr_declare(FreePageSpanLeader, RelptrFreePageSpanLeader);
+
+/* Everything we need in order to manage free pages (see freepage.c) */
+struct FreePageManager
+{
+ RelptrFreePageManager self;
+ RelptrFreePageBtree btree_root;
+ RelptrFreePageSpanLeader btree_recycle;
+ unsigned btree_depth;
+ unsigned btree_recycle_count;
+ Size singleton_first_page;
+ Size singleton_npages;
+ Size contiguous_pages;
+ bool contiguous_pages_dirty;
+ RelptrFreePageSpanLeader freelist[FPM_NUM_FREELISTS];
+#ifdef FPM_EXTRA_ASSERTS
+ /* For debugging only, pages put minus pages gotten. */
+ Size free_pages;
+#endif
+};
+
+/* Macros to convert between page numbers (expressed as Size) and pointers. */
+#define fpm_page_to_pointer(base, page) \
+ (AssertVariableIsOfTypeMacro(page, Size), \
+ (base) + FPM_PAGE_SIZE * (page))
+#define fpm_pointer_to_page(base, ptr) \
+ (((Size) (((char *) (ptr)) - (base))) / FPM_PAGE_SIZE)
+
+/* Macro to convert an allocation size to a number of pages. */
+#define fpm_size_to_pages(sz) \
+ (((sz) + FPM_PAGE_SIZE - 1) / FPM_PAGE_SIZE)
+
+/* Macros to check alignment of absolute and relative pointers. */
+#define fpm_pointer_is_page_aligned(base, ptr) \
+ (((Size) (((char *) (ptr)) - (base))) % FPM_PAGE_SIZE == 0)
+#define fpm_relptr_is_page_aligned(base, relptr) \
+ (relptr_offset(relptr) % FPM_PAGE_SIZE == 0)
+
+/* Macro to find base address of the segment containing a FreePageManager. */
+#define fpm_segment_base(fpm) \
+ (((char *) fpm) - relptr_offset(fpm->self))
+
+/* Macro to access a FreePageManager's largest consecutive run of pages. */
+#define fpm_largest(fpm) \
+ (fpm->contiguous_pages)
+
+/* Functions to manipulate the free page map. */
+extern void FreePageManagerInitialize(FreePageManager *fpm, char *base);
+extern bool FreePageManagerGet(FreePageManager *fpm, Size npages,
+ Size *first_page);
+extern void FreePageManagerPut(FreePageManager *fpm, Size first_page,
+ Size npages);
+extern char *FreePageManagerDump(FreePageManager *fpm);
+
+#endif /* FREEPAGE_H */
diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h
new file mode 100644
index 0000000..d176f58
--- /dev/null
+++ b/src/include/utils/geo_decls.h
@@ -0,0 +1,285 @@
+/*-------------------------------------------------------------------------
+ *
+ * geo_decls.h - Declarations for various 2D constructs.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/geo_decls.h
+ *
+ * XXX These routines were not written by a numerical analyst.
+ *
+ * XXX I have made some attempt to flesh out the operators
+ * and data types. There are still some more to do. - tgl 97/04/19
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef GEO_DECLS_H
+#define GEO_DECLS_H
+
+#include <math.h>
+
+#include "fmgr.h"
+
+/*--------------------------------------------------------------------
+ * Useful floating point utilities and constants.
+ *--------------------------------------------------------------------
+ *
+ * "Fuzzy" floating-point comparisons: values within EPSILON of each other
+ * are considered equal. Beware of normal reasoning about the behavior of
+ * these comparisons, since for example FPeq does not behave transitively.
+ *
+ * Note that these functions are not NaN-aware and will give FALSE for
+ * any case involving NaN inputs.
+ *
+ * Also note that these will give sane answers for infinite inputs,
+ * where it's important to avoid computing Inf minus Inf; we do so
+ * by eliminating equality cases before subtracting.
+ */
+
+#define EPSILON 1.0E-06
+
+#ifdef EPSILON
+#define FPzero(A) (fabs(A) <= EPSILON)
+
+static inline bool
+FPeq(double A, double B)
+{
+ return A == B || fabs(A - B) <= EPSILON;
+}
+
+static inline bool
+FPne(double A, double B)
+{
+ return A != B && fabs(A - B) > EPSILON;
+}
+
+static inline bool
+FPlt(double A, double B)
+{
+ return A + EPSILON < B;
+}
+
+static inline bool
+FPle(double A, double B)
+{
+ return A <= B + EPSILON;
+}
+
+static inline bool
+FPgt(double A, double B)
+{
+ return A > B + EPSILON;
+}
+
+static inline bool
+FPge(double A, double B)
+{
+ return A + EPSILON >= B;
+}
+#else
+#define FPzero(A) ((A) == 0)
+#define FPeq(A,B) ((A) == (B))
+#define FPne(A,B) ((A) != (B))
+#define FPlt(A,B) ((A) < (B))
+#define FPle(A,B) ((A) <= (B))
+#define FPgt(A,B) ((A) > (B))
+#define FPge(A,B) ((A) >= (B))
+#endif
+
+#define HYPOT(A, B) pg_hypot(A, B)
+
+/*---------------------------------------------------------------------
+ * Point - (x,y)
+ *-------------------------------------------------------------------*/
+typedef struct
+{
+ float8 x,
+ y;
+} Point;
+
+
+/*---------------------------------------------------------------------
+ * LSEG - A straight line, specified by endpoints.
+ *-------------------------------------------------------------------*/
+typedef struct
+{
+ Point p[2];
+} LSEG;
+
+
+/*---------------------------------------------------------------------
+ * PATH - Specified by vertex points.
+ *-------------------------------------------------------------------*/
+typedef struct
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ int32 npts;
+ int32 closed; /* is this a closed polygon? */
+ int32 dummy; /* padding to make it double align */
+ Point p[FLEXIBLE_ARRAY_MEMBER];
+} PATH;
+
+
+/*---------------------------------------------------------------------
+ * LINE - Specified by its general equation (Ax+By+C=0).
+ *-------------------------------------------------------------------*/
+typedef struct
+{
+ float8 A,
+ B,
+ C;
+} LINE;
+
+
+/*---------------------------------------------------------------------
+ * BOX - Specified by two corner points, which are
+ * sorted to save calculation time later.
+ *-------------------------------------------------------------------*/
+typedef struct
+{
+ Point high,
+ low; /* corner POINTs */
+} BOX;
+
+/*---------------------------------------------------------------------
+ * POLYGON - Specified by an array of doubles defining the points,
+ * keeping the number of points and the bounding box for
+ * speed purposes.
+ *-------------------------------------------------------------------*/
+typedef struct
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ int32 npts;
+ BOX boundbox;
+ Point p[FLEXIBLE_ARRAY_MEMBER];
+} POLYGON;
+
+/*---------------------------------------------------------------------
+ * CIRCLE - Specified by a center point and radius.
+ *-------------------------------------------------------------------*/
+typedef struct
+{
+ Point center;
+ float8 radius;
+} CIRCLE;
+
+/*
+ * fmgr interface functions
+ *
+ * Path and Polygon are toastable varlena types, the others are just
+ * fixed-size pass-by-reference types.
+ */
+
+static inline Point *
+DatumGetPointP(Datum X)
+{
+ return (Point *) DatumGetPointer(X);
+}
+static inline Datum
+PointPGetDatum(const Point *X)
+{
+ return PointerGetDatum(X);
+}
+#define PG_GETARG_POINT_P(n) DatumGetPointP(PG_GETARG_DATUM(n))
+#define PG_RETURN_POINT_P(x) return PointPGetDatum(x)
+
+static inline LSEG *
+DatumGetLsegP(Datum X)
+{
+ return (LSEG *) DatumGetPointer(X);
+}
+static inline Datum
+LsegPGetDatum(const LSEG *X)
+{
+ return PointerGetDatum(X);
+}
+#define PG_GETARG_LSEG_P(n) DatumGetLsegP(PG_GETARG_DATUM(n))
+#define PG_RETURN_LSEG_P(x) return LsegPGetDatum(x)
+
+static inline PATH *
+DatumGetPathP(Datum X)
+{
+ return (PATH *) PG_DETOAST_DATUM(X);
+}
+static inline PATH *
+DatumGetPathPCopy(Datum X)
+{
+ return (PATH *) PG_DETOAST_DATUM_COPY(X);
+}
+static inline Datum
+PathPGetDatum(const PATH *X)
+{
+ return PointerGetDatum(X);
+}
+#define PG_GETARG_PATH_P(n) DatumGetPathP(PG_GETARG_DATUM(n))
+#define PG_GETARG_PATH_P_COPY(n) DatumGetPathPCopy(PG_GETARG_DATUM(n))
+#define PG_RETURN_PATH_P(x) return PathPGetDatum(x)
+
+static inline LINE *
+DatumGetLineP(Datum X)
+{
+ return (LINE *) DatumGetPointer(X);
+}
+static inline Datum
+LinePGetDatum(const LINE *X)
+{
+ return PointerGetDatum(X);
+}
+#define PG_GETARG_LINE_P(n) DatumGetLineP(PG_GETARG_DATUM(n))
+#define PG_RETURN_LINE_P(x) return LinePGetDatum(x)
+
+static inline BOX *
+DatumGetBoxP(Datum X)
+{
+ return (BOX *) DatumGetPointer(X);
+}
+static inline Datum
+BoxPGetDatum(const BOX *X)
+{
+ return PointerGetDatum(X);
+}
+#define PG_GETARG_BOX_P(n) DatumGetBoxP(PG_GETARG_DATUM(n))
+#define PG_RETURN_BOX_P(x) return BoxPGetDatum(x)
+
+static inline POLYGON *
+DatumGetPolygonP(Datum X)
+{
+ return (POLYGON *) PG_DETOAST_DATUM(X);
+}
+static inline POLYGON *
+DatumGetPolygonPCopy(Datum X)
+{
+ return (POLYGON *) PG_DETOAST_DATUM_COPY(X);
+}
+static inline Datum
+PolygonPGetDatum(const POLYGON *X)
+{
+ return PointerGetDatum(X);
+}
+#define PG_GETARG_POLYGON_P(n) DatumGetPolygonP(PG_GETARG_DATUM(n))
+#define PG_GETARG_POLYGON_P_COPY(n) DatumGetPolygonPCopy(PG_GETARG_DATUM(n))
+#define PG_RETURN_POLYGON_P(x) return PolygonPGetDatum(x)
+
+static inline CIRCLE *
+DatumGetCircleP(Datum X)
+{
+ return (CIRCLE *) DatumGetPointer(X);
+}
+static inline Datum
+CirclePGetDatum(const CIRCLE *X)
+{
+ return PointerGetDatum(X);
+}
+#define PG_GETARG_CIRCLE_P(n) DatumGetCircleP(PG_GETARG_DATUM(n))
+#define PG_RETURN_CIRCLE_P(x) return CirclePGetDatum(x)
+
+
+/*
+ * in geo_ops.c
+ */
+
+extern float8 pg_hypot(float8 x, float8 y);
+
+#endif /* GEO_DECLS_H */
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
new file mode 100644
index 0000000..d5253c7
--- /dev/null
+++ b/src/include/utils/guc.h
@@ -0,0 +1,442 @@
+/*--------------------------------------------------------------------
+ * guc.h
+ *
+ * External declarations pertaining to Grand Unified Configuration.
+ *
+ * Copyright (c) 2000-2023, PostgreSQL Global Development Group
+ * Written by Peter Eisentraut <peter_e@gmx.net>.
+ *
+ * src/include/utils/guc.h
+ *--------------------------------------------------------------------
+ */
+#ifndef GUC_H
+#define GUC_H
+
+#include "nodes/parsenodes.h"
+#include "tcop/dest.h"
+#include "utils/array.h"
+
+
+/* upper limit for GUC variables measured in kilobytes of memory */
+/* note that various places assume the byte size fits in a "long" variable */
+#if SIZEOF_SIZE_T > 4 && SIZEOF_LONG > 4
+#define MAX_KILOBYTES INT_MAX
+#else
+#define MAX_KILOBYTES (INT_MAX / 1024)
+#endif
+
+/*
+ * Automatic configuration file name for ALTER SYSTEM.
+ * This file will be used to store values of configuration parameters
+ * set by ALTER SYSTEM command.
+ */
+#define PG_AUTOCONF_FILENAME "postgresql.auto.conf"
+
+/*
+ * Certain options can only be set at certain times. The rules are
+ * like this:
+ *
+ * INTERNAL options cannot be set by the user at all, but only through
+ * internal processes ("server_version" is an example). These are GUC
+ * variables only so they can be shown by SHOW, etc.
+ *
+ * POSTMASTER options can only be set when the postmaster starts,
+ * either from the configuration file or the command line.
+ *
+ * SIGHUP options can only be set at postmaster startup or by changing
+ * the configuration file and sending the HUP signal to the postmaster
+ * or a backend process. (Notice that the signal receipt will not be
+ * evaluated immediately. The postmaster and the backend check it at a
+ * certain point in their main loop. It's safer to wait than to read a
+ * file asynchronously.)
+ *
+ * BACKEND and SU_BACKEND options can only be set at postmaster startup,
+ * from the configuration file, or by client request in the connection
+ * startup packet (e.g., from libpq's PGOPTIONS variable). SU_BACKEND
+ * options can be set from the startup packet only when the user is a
+ * superuser. Furthermore, an already-started backend will ignore changes
+ * to such an option in the configuration file. The idea is that these
+ * options are fixed for a given backend once it's started, but they can
+ * vary across backends.
+ *
+ * SUSET options can be set at postmaster startup, with the SIGHUP
+ * mechanism, or from the startup packet or SQL if you're a superuser.
+ *
+ * USERSET options can be set by anyone any time.
+ */
+typedef enum
+{
+ PGC_INTERNAL,
+ PGC_POSTMASTER,
+ PGC_SIGHUP,
+ PGC_SU_BACKEND,
+ PGC_BACKEND,
+ PGC_SUSET,
+ PGC_USERSET
+} GucContext;
+
+/*
+ * The following type records the source of the current setting. A
+ * new setting can only take effect if the previous setting had the
+ * same or lower level. (E.g, changing the config file doesn't
+ * override the postmaster command line.) Tracking the source allows us
+ * to process sources in any convenient order without affecting results.
+ * Sources <= PGC_S_OVERRIDE will set the default used by RESET, as well
+ * as the current value.
+ *
+ * PGC_S_INTERACTIVE isn't actually a source value, but is the
+ * dividing line between "interactive" and "non-interactive" sources for
+ * error reporting purposes.
+ *
+ * PGC_S_TEST is used when testing values to be used later. For example,
+ * ALTER DATABASE/ROLE tests proposed per-database or per-user defaults this
+ * way, and CREATE FUNCTION tests proposed function SET clauses this way.
+ * This is an interactive case, but it needs its own source value because
+ * some assign hooks need to make different validity checks in this case.
+ * In particular, references to nonexistent database objects generally
+ * shouldn't throw hard errors in this case, at most NOTICEs, since the
+ * objects might exist by the time the setting is used for real.
+ *
+ * When setting the value of a non-compile-time-constant PGC_INTERNAL option,
+ * source == PGC_S_DYNAMIC_DEFAULT should typically be used so that the value
+ * will show as "default" in pg_settings. If there is a specific reason not
+ * to want that, use source == PGC_S_OVERRIDE.
+ *
+ * NB: see GucSource_Names in guc.c if you change this.
+ */
+typedef enum
+{
+ PGC_S_DEFAULT, /* hard-wired default ("boot_val") */
+ PGC_S_DYNAMIC_DEFAULT, /* default computed during initialization */
+ PGC_S_ENV_VAR, /* postmaster environment variable */
+ PGC_S_FILE, /* postgresql.conf */
+ PGC_S_ARGV, /* postmaster command line */
+ PGC_S_GLOBAL, /* global in-database setting */
+ PGC_S_DATABASE, /* per-database setting */
+ PGC_S_USER, /* per-user setting */
+ PGC_S_DATABASE_USER, /* per-user-and-database setting */
+ PGC_S_CLIENT, /* from client connection request */
+ PGC_S_OVERRIDE, /* special case to forcibly set default */
+ PGC_S_INTERACTIVE, /* dividing line for error reporting */
+ PGC_S_TEST, /* test per-database or per-user setting */
+ PGC_S_SESSION /* SET command */
+} GucSource;
+
+/*
+ * Parsing the configuration file(s) will return a list of name-value pairs
+ * with source location info. We also abuse this data structure to carry
+ * error reports about the config files. An entry reporting an error will
+ * have errmsg != NULL, and might have NULLs for name, value, and/or filename.
+ *
+ * If "ignore" is true, don't attempt to apply the item (it might be an error
+ * report, or an item we determined to be duplicate). "applied" is set true
+ * if we successfully applied, or could have applied, the setting.
+ */
+typedef struct ConfigVariable
+{
+ char *name;
+ char *value;
+ char *errmsg;
+ char *filename;
+ int sourceline;
+ bool ignore;
+ bool applied;
+ struct ConfigVariable *next;
+} ConfigVariable;
+
+extern bool ParseConfigFile(const char *config_file, bool strict,
+ const char *calling_file, int calling_lineno,
+ int depth, int elevel,
+ ConfigVariable **head_p, ConfigVariable **tail_p);
+extern bool ParseConfigFp(FILE *fp, const char *config_file,
+ int depth, int elevel,
+ ConfigVariable **head_p, ConfigVariable **tail_p);
+extern bool ParseConfigDirectory(const char *includedir,
+ const char *calling_file, int calling_lineno,
+ int depth, int elevel,
+ ConfigVariable **head_p,
+ ConfigVariable **tail_p);
+extern void FreeConfigVariables(ConfigVariable *list);
+extern char *DeescapeQuotedString(const char *s);
+
+/*
+ * The possible values of an enum variable are specified by an array of
+ * name-value pairs. The "hidden" flag means the value is accepted but
+ * won't be displayed when guc.c is asked for a list of acceptable values.
+ */
+struct config_enum_entry
+{
+ const char *name;
+ int val;
+ bool hidden;
+};
+
+/*
+ * Signatures for per-variable check/assign/show hook functions
+ */
+typedef bool (*GucBoolCheckHook) (bool *newval, void **extra, GucSource source);
+typedef bool (*GucIntCheckHook) (int *newval, void **extra, GucSource source);
+typedef bool (*GucRealCheckHook) (double *newval, void **extra, GucSource source);
+typedef bool (*GucStringCheckHook) (char **newval, void **extra, GucSource source);
+typedef bool (*GucEnumCheckHook) (int *newval, void **extra, GucSource source);
+
+typedef void (*GucBoolAssignHook) (bool newval, void *extra);
+typedef void (*GucIntAssignHook) (int newval, void *extra);
+typedef void (*GucRealAssignHook) (double newval, void *extra);
+typedef void (*GucStringAssignHook) (const char *newval, void *extra);
+typedef void (*GucEnumAssignHook) (int newval, void *extra);
+
+typedef const char *(*GucShowHook) (void);
+
+/*
+ * Miscellaneous
+ */
+typedef enum
+{
+ /* Types of set_config_option actions */
+ GUC_ACTION_SET, /* regular SET command */
+ GUC_ACTION_LOCAL, /* SET LOCAL command */
+ GUC_ACTION_SAVE /* function SET option, or temp assignment */
+} GucAction;
+
+#define GUC_QUALIFIER_SEPARATOR '.'
+
+/*
+ * Bit values in "flags" of a GUC variable. Note that these don't appear
+ * on disk, so we can reassign their values freely.
+ */
+#define GUC_LIST_INPUT 0x000001 /* input can be list format */
+#define GUC_LIST_QUOTE 0x000002 /* double-quote list elements */
+#define GUC_NO_SHOW_ALL 0x000004 /* exclude from SHOW ALL */
+#define GUC_NO_RESET 0x000008 /* disallow RESET and SAVE */
+#define GUC_NO_RESET_ALL 0x000010 /* exclude from RESET ALL */
+#define GUC_EXPLAIN 0x000020 /* include in EXPLAIN */
+#define GUC_REPORT 0x000040 /* auto-report changes to client */
+#define GUC_NOT_IN_SAMPLE 0x000080 /* not in postgresql.conf.sample */
+#define GUC_DISALLOW_IN_FILE 0x000100 /* can't set in postgresql.conf */
+#define GUC_CUSTOM_PLACEHOLDER 0x000200 /* placeholder for custom variable */
+#define GUC_SUPERUSER_ONLY 0x000400 /* show only to superusers */
+#define GUC_IS_NAME 0x000800 /* limit string to NAMEDATALEN-1 */
+#define GUC_NOT_WHILE_SEC_REST 0x001000 /* can't set if security restricted */
+#define GUC_DISALLOW_IN_AUTO_FILE \
+ 0x002000 /* can't set in PG_AUTOCONF_FILENAME */
+#define GUC_RUNTIME_COMPUTED 0x004000 /* delay processing in 'postgres -C' */
+
+#define GUC_UNIT_KB 0x01000000 /* value is in kilobytes */
+#define GUC_UNIT_BLOCKS 0x02000000 /* value is in blocks */
+#define GUC_UNIT_XBLOCKS 0x03000000 /* value is in xlog blocks */
+#define GUC_UNIT_MB 0x04000000 /* value is in megabytes */
+#define GUC_UNIT_BYTE 0x05000000 /* value is in bytes */
+#define GUC_UNIT_MEMORY 0x0F000000 /* mask for size-related units */
+
+#define GUC_UNIT_MS 0x10000000 /* value is in milliseconds */
+#define GUC_UNIT_S 0x20000000 /* value is in seconds */
+#define GUC_UNIT_MIN 0x30000000 /* value is in minutes */
+#define GUC_UNIT_TIME 0x70000000 /* mask for time-related units */
+
+#define GUC_UNIT (GUC_UNIT_MEMORY | GUC_UNIT_TIME)
+
+
+/* GUC vars that are actually defined in guc_tables.c, rather than elsewhere */
+extern PGDLLIMPORT bool Debug_print_plan;
+extern PGDLLIMPORT bool Debug_print_parse;
+extern PGDLLIMPORT bool Debug_print_rewritten;
+extern PGDLLIMPORT bool Debug_pretty_print;
+
+extern PGDLLIMPORT bool log_parser_stats;
+extern PGDLLIMPORT bool log_planner_stats;
+extern PGDLLIMPORT bool log_executor_stats;
+extern PGDLLIMPORT bool log_statement_stats;
+extern PGDLLIMPORT bool log_btree_build_stats;
+
+extern PGDLLIMPORT bool check_function_bodies;
+extern PGDLLIMPORT bool session_auth_is_superuser;
+
+extern PGDLLIMPORT bool log_duration;
+extern PGDLLIMPORT int log_parameter_max_length;
+extern PGDLLIMPORT int log_parameter_max_length_on_error;
+extern PGDLLIMPORT int log_min_error_statement;
+extern PGDLLIMPORT int log_min_messages;
+extern PGDLLIMPORT int client_min_messages;
+extern PGDLLIMPORT int log_min_duration_sample;
+extern PGDLLIMPORT int log_min_duration_statement;
+extern PGDLLIMPORT int log_temp_files;
+extern PGDLLIMPORT double log_statement_sample_rate;
+extern PGDLLIMPORT double log_xact_sample_rate;
+extern PGDLLIMPORT char *backtrace_functions;
+
+extern PGDLLIMPORT int temp_file_limit;
+
+extern PGDLLIMPORT int num_temp_buffers;
+
+extern PGDLLIMPORT char *cluster_name;
+extern PGDLLIMPORT char *ConfigFileName;
+extern PGDLLIMPORT char *HbaFileName;
+extern PGDLLIMPORT char *IdentFileName;
+extern PGDLLIMPORT char *external_pid_file;
+
+extern PGDLLIMPORT char *application_name;
+
+extern PGDLLIMPORT int tcp_keepalives_idle;
+extern PGDLLIMPORT int tcp_keepalives_interval;
+extern PGDLLIMPORT int tcp_keepalives_count;
+extern PGDLLIMPORT int tcp_user_timeout;
+
+#ifdef TRACE_SORT
+extern PGDLLIMPORT bool trace_sort;
+#endif
+
+/*
+ * Functions exported by guc.c
+ */
+extern void SetConfigOption(const char *name, const char *value,
+ GucContext context, GucSource source);
+
+extern void DefineCustomBoolVariable(const char *name,
+ const char *short_desc,
+ const char *long_desc,
+ bool *valueAddr,
+ bool bootValue,
+ GucContext context,
+ int flags,
+ GucBoolCheckHook check_hook,
+ GucBoolAssignHook assign_hook,
+ GucShowHook show_hook) pg_attribute_nonnull(1, 4);
+
+extern void DefineCustomIntVariable(const char *name,
+ const char *short_desc,
+ const char *long_desc,
+ int *valueAddr,
+ int bootValue,
+ int minValue,
+ int maxValue,
+ GucContext context,
+ int flags,
+ GucIntCheckHook check_hook,
+ GucIntAssignHook assign_hook,
+ GucShowHook show_hook) pg_attribute_nonnull(1, 4);
+
+extern void DefineCustomRealVariable(const char *name,
+ const char *short_desc,
+ const char *long_desc,
+ double *valueAddr,
+ double bootValue,
+ double minValue,
+ double maxValue,
+ GucContext context,
+ int flags,
+ GucRealCheckHook check_hook,
+ GucRealAssignHook assign_hook,
+ GucShowHook show_hook) pg_attribute_nonnull(1, 4);
+
+extern void DefineCustomStringVariable(const char *name,
+ const char *short_desc,
+ const char *long_desc,
+ char **valueAddr,
+ const char *bootValue,
+ GucContext context,
+ int flags,
+ GucStringCheckHook check_hook,
+ GucStringAssignHook assign_hook,
+ GucShowHook show_hook) pg_attribute_nonnull(1, 4);
+
+extern void DefineCustomEnumVariable(const char *name,
+ const char *short_desc,
+ const char *long_desc,
+ int *valueAddr,
+ int bootValue,
+ const struct config_enum_entry *options,
+ GucContext context,
+ int flags,
+ GucEnumCheckHook check_hook,
+ GucEnumAssignHook assign_hook,
+ GucShowHook show_hook) pg_attribute_nonnull(1, 4);
+
+extern void MarkGUCPrefixReserved(const char *className);
+
+/* old name for MarkGUCPrefixReserved, for backwards compatibility: */
+#define EmitWarningsOnPlaceholders(className) MarkGUCPrefixReserved(className)
+
+extern const char *GetConfigOption(const char *name, bool missing_ok,
+ bool restrict_privileged);
+extern const char *GetConfigOptionResetString(const char *name);
+extern int GetConfigOptionFlags(const char *name, bool missing_ok);
+extern void ProcessConfigFile(GucContext context);
+extern char *convert_GUC_name_for_parameter_acl(const char *name);
+extern bool check_GUC_name_for_parameter_acl(const char *name);
+extern void InitializeGUCOptions(void);
+extern bool SelectConfigFiles(const char *userDoption, const char *progname);
+extern void ResetAllOptions(void);
+extern void AtStart_GUC(void);
+extern int NewGUCNestLevel(void);
+extern void AtEOXact_GUC(bool isCommit, int nestLevel);
+extern void BeginReportingGUCOptions(void);
+extern void ReportChangedGUCOptions(void);
+extern void ParseLongOption(const char *string, char **name, char **value);
+extern const char *get_config_unit_name(int flags);
+extern bool parse_int(const char *value, int *result, int flags,
+ const char **hintmsg);
+extern bool parse_real(const char *value, double *result, int flags,
+ const char **hintmsg);
+extern int set_config_option(const char *name, const char *value,
+ GucContext context, GucSource source,
+ GucAction action, bool changeVal, int elevel,
+ bool is_reload);
+extern int set_config_option_ext(const char *name, const char *value,
+ GucContext context, GucSource source,
+ Oid srole,
+ GucAction action, bool changeVal, int elevel,
+ bool is_reload);
+extern void AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt);
+extern char *GetConfigOptionByName(const char *name, const char **varname,
+ bool missing_ok);
+
+extern void ProcessGUCArray(ArrayType *array,
+ GucContext context, GucSource source, GucAction action);
+extern ArrayType *GUCArrayAdd(ArrayType *array, const char *name, const char *value);
+extern ArrayType *GUCArrayDelete(ArrayType *array, const char *name);
+extern ArrayType *GUCArrayReset(ArrayType *array);
+
+extern void *guc_malloc(int elevel, size_t size);
+extern pg_nodiscard void *guc_realloc(int elevel, void *old, size_t size);
+extern char *guc_strdup(int elevel, const char *src);
+extern void guc_free(void *ptr);
+
+#ifdef EXEC_BACKEND
+extern void write_nondefault_variables(GucContext context);
+extern void read_nondefault_variables(void);
+#endif
+
+/* GUC serialization */
+extern Size EstimateGUCStateSpace(void);
+extern void SerializeGUCState(Size maxsize, char *start_address);
+extern void RestoreGUCState(void *gucstate);
+
+/* Functions exported by guc_funcs.c */
+extern void ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel);
+extern char *ExtractSetVariableArgs(VariableSetStmt *stmt);
+extern void SetPGVariable(const char *name, List *args, bool is_local);
+extern void GetPGVariable(const char *name, DestReceiver *dest);
+extern TupleDesc GetPGVariableResultDesc(const char *name);
+
+/* Support for messages reported from GUC check hooks */
+
+extern PGDLLIMPORT char *GUC_check_errmsg_string;
+extern PGDLLIMPORT char *GUC_check_errdetail_string;
+extern PGDLLIMPORT char *GUC_check_errhint_string;
+
+extern void GUC_check_errcode(int sqlerrcode);
+
+#define GUC_check_errmsg \
+ pre_format_elog_string(errno, TEXTDOMAIN), \
+ GUC_check_errmsg_string = format_elog_string
+
+#define GUC_check_errdetail \
+ pre_format_elog_string(errno, TEXTDOMAIN), \
+ GUC_check_errdetail_string = format_elog_string
+
+#define GUC_check_errhint \
+ pre_format_elog_string(errno, TEXTDOMAIN), \
+ GUC_check_errhint_string = format_elog_string
+
+#endif /* GUC_H */
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
new file mode 100644
index 0000000..952293a
--- /dev/null
+++ b/src/include/utils/guc_hooks.h
@@ -0,0 +1,163 @@
+/*-------------------------------------------------------------------------
+ *
+ * guc_hooks.h
+ * Declarations of per-variable callback functions used by GUC.
+ *
+ * These functions are scattered throughout the system, but we
+ * declare them all here to avoid having to propagate guc.h into
+ * a lot of unrelated header files.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ *
+ * src/include/utils/guc_hooks.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef GUC_HOOKS_H
+#define GUC_HOOKS_H 1
+
+#include "utils/guc.h"
+
+/*
+ * See guc.h for the typedefs that these hook functions should match
+ * (GucBoolCheckHook and so on).
+ *
+ * Please keep the declarations in order by GUC variable name.
+ */
+
+extern bool check_application_name(char **newval, void **extra,
+ GucSource source);
+extern void assign_application_name(const char *newval, void *extra);
+extern const char *show_archive_command(void);
+extern bool check_autovacuum_max_workers(int *newval, void **extra,
+ GucSource source);
+extern bool check_autovacuum_work_mem(int *newval, void **extra,
+ GucSource source);
+extern bool check_vacuum_buffer_usage_limit(int *newval, void **extra,
+ GucSource source);
+extern bool check_backtrace_functions(char **newval, void **extra,
+ GucSource source);
+extern void assign_backtrace_functions(const char *newval, void *extra);
+extern bool check_bonjour(bool *newval, void **extra, GucSource source);
+extern bool check_canonical_path(char **newval, void **extra, GucSource source);
+extern void assign_checkpoint_completion_target(double newval, void *extra);
+extern bool check_client_connection_check_interval(int *newval, void **extra,
+ GucSource source);
+extern bool check_client_encoding(char **newval, void **extra, GucSource source);
+extern void assign_client_encoding(const char *newval, void *extra);
+extern bool check_cluster_name(char **newval, void **extra, GucSource source);
+extern const char *show_data_directory_mode(void);
+extern bool check_datestyle(char **newval, void **extra, GucSource source);
+extern void assign_datestyle(const char *newval, void *extra);
+extern bool check_debug_io_direct(char **newval, void **extra, GucSource source);
+extern void assign_debug_io_direct(const char *newval, void *extra);
+extern bool check_default_table_access_method(char **newval, void **extra,
+ GucSource source);
+extern bool check_default_tablespace(char **newval, void **extra,
+ GucSource source);
+extern bool check_default_text_search_config(char **newval, void **extra, GucSource source);
+extern void assign_default_text_search_config(const char *newval, void *extra);
+extern bool check_default_with_oids(bool *newval, void **extra,
+ GucSource source);
+extern bool check_effective_io_concurrency(int *newval, void **extra,
+ GucSource source);
+extern bool check_huge_page_size(int *newval, void **extra, GucSource source);
+extern const char *show_in_hot_standby(void);
+extern bool check_locale_messages(char **newval, void **extra, GucSource source);
+extern void assign_locale_messages(const char *newval, void *extra);
+extern bool check_locale_monetary(char **newval, void **extra, GucSource source);
+extern void assign_locale_monetary(const char *newval, void *extra);
+extern bool check_locale_numeric(char **newval, void **extra, GucSource source);
+extern void assign_locale_numeric(const char *newval, void *extra);
+extern bool check_locale_time(char **newval, void **extra, GucSource source);
+extern void assign_locale_time(const char *newval, void *extra);
+extern bool check_log_destination(char **newval, void **extra,
+ GucSource source);
+extern void assign_log_destination(const char *newval, void *extra);
+extern const char *show_log_file_mode(void);
+extern bool check_log_stats(bool *newval, void **extra, GucSource source);
+extern bool check_log_timezone(char **newval, void **extra, GucSource source);
+extern void assign_log_timezone(const char *newval, void *extra);
+extern const char *show_log_timezone(void);
+extern bool check_maintenance_io_concurrency(int *newval, void **extra,
+ GucSource source);
+extern void assign_maintenance_io_concurrency(int newval, void *extra);
+extern bool check_max_connections(int *newval, void **extra, GucSource source);
+extern bool check_max_wal_senders(int *newval, void **extra, GucSource source);
+extern void assign_max_wal_size(int newval, void *extra);
+extern bool check_max_worker_processes(int *newval, void **extra,
+ GucSource source);
+extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
+extern void assign_max_stack_depth(int newval, void *extra);
+extern bool check_primary_slot_name(char **newval, void **extra,
+ GucSource source);
+extern bool check_random_seed(double *newval, void **extra, GucSource source);
+extern void assign_random_seed(double newval, void *extra);
+extern const char *show_random_seed(void);
+extern bool check_recovery_prefetch(int *new_value, void **extra,
+ GucSource source);
+extern void assign_recovery_prefetch(int new_value, void *extra);
+extern bool check_recovery_target(char **newval, void **extra,
+ GucSource source);
+extern void assign_recovery_target(const char *newval, void *extra);
+extern bool check_recovery_target_lsn(char **newval, void **extra,
+ GucSource source);
+extern void assign_recovery_target_lsn(const char *newval, void *extra);
+extern bool check_recovery_target_name(char **newval, void **extra,
+ GucSource source);
+extern void assign_recovery_target_name(const char *newval, void *extra);
+extern bool check_recovery_target_time(char **newval, void **extra,
+ GucSource source);
+extern void assign_recovery_target_time(const char *newval, void *extra);
+extern bool check_recovery_target_timeline(char **newval, void **extra,
+ GucSource source);
+extern void assign_recovery_target_timeline(const char *newval, void *extra);
+extern bool check_recovery_target_xid(char **newval, void **extra,
+ GucSource source);
+extern void assign_recovery_target_xid(const char *newval, void *extra);
+extern bool check_role(char **newval, void **extra, GucSource source);
+extern void assign_role(const char *newval, void *extra);
+extern const char *show_role(void);
+extern bool check_search_path(char **newval, void **extra, GucSource source);
+extern void assign_search_path(const char *newval, void *extra);
+extern bool check_session_authorization(char **newval, void **extra, GucSource source);
+extern void assign_session_authorization(const char *newval, void *extra);
+extern void assign_session_replication_role(int newval, void *extra);
+extern void assign_stats_fetch_consistency(int newval, void *extra);
+extern bool check_ssl(bool *newval, void **extra, GucSource source);
+extern bool check_stage_log_stats(bool *newval, void **extra, GucSource source);
+extern bool check_synchronous_standby_names(char **newval, void **extra,
+ GucSource source);
+extern void assign_synchronous_standby_names(const char *newval, void *extra);
+extern void assign_synchronous_commit(int newval, void *extra);
+extern void assign_syslog_facility(int newval, void *extra);
+extern void assign_syslog_ident(const char *newval, void *extra);
+extern void assign_tcp_keepalives_count(int newval, void *extra);
+extern const char *show_tcp_keepalives_count(void);
+extern void assign_tcp_keepalives_idle(int newval, void *extra);
+extern const char *show_tcp_keepalives_idle(void);
+extern void assign_tcp_keepalives_interval(int newval, void *extra);
+extern const char *show_tcp_keepalives_interval(void);
+extern void assign_tcp_user_timeout(int newval, void *extra);
+extern const char *show_tcp_user_timeout(void);
+extern bool check_temp_buffers(int *newval, void **extra, GucSource source);
+extern bool check_temp_tablespaces(char **newval, void **extra,
+ GucSource source);
+extern void assign_temp_tablespaces(const char *newval, void *extra);
+extern bool check_timezone(char **newval, void **extra, GucSource source);
+extern void assign_timezone(const char *newval, void *extra);
+extern const char *show_timezone(void);
+extern bool check_timezone_abbreviations(char **newval, void **extra,
+ GucSource source);
+extern void assign_timezone_abbreviations(const char *newval, void *extra);
+extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
+extern bool check_transaction_isolation(int *newval, void **extra, GucSource source);
+extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
+extern const char *show_unix_socket_permissions(void);
+extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
+extern bool check_wal_consistency_checking(char **newval, void **extra,
+ GucSource source);
+extern void assign_wal_consistency_checking(const char *newval, void *extra);
+extern void assign_xlog_sync_method(int new_sync_method, void *extra);
+
+#endif /* GUC_HOOKS_H */
diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h
new file mode 100644
index 0000000..ab880ca
--- /dev/null
+++ b/src/include/utils/guc_tables.h
@@ -0,0 +1,322 @@
+/*-------------------------------------------------------------------------
+ *
+ * guc_tables.h
+ * Declarations of tables used by GUC.
+ *
+ * See src/backend/utils/misc/README for design notes.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ *
+ * src/include/utils/guc_tables.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef GUC_TABLES_H
+#define GUC_TABLES_H 1
+
+#include "lib/ilist.h"
+#include "utils/guc.h"
+
+/*
+ * GUC supports these types of variables:
+ */
+enum config_type
+{
+ PGC_BOOL,
+ PGC_INT,
+ PGC_REAL,
+ PGC_STRING,
+ PGC_ENUM
+};
+
+union config_var_val
+{
+ bool boolval;
+ int intval;
+ double realval;
+ char *stringval;
+ int enumval;
+};
+
+/*
+ * The actual value of a GUC variable can include a malloc'd opaque struct
+ * "extra", which is created by its check_hook and used by its assign_hook.
+ */
+typedef struct config_var_value
+{
+ union config_var_val val;
+ void *extra;
+} config_var_value;
+
+/*
+ * Groupings to help organize all the run-time options for display.
+ * Be sure this agrees with the way the options are categorized in config.sgml!
+ */
+enum config_group
+{
+ UNGROUPED, /* use for options not shown in pg_settings */
+ FILE_LOCATIONS,
+ CONN_AUTH_SETTINGS,
+ CONN_AUTH_TCP,
+ CONN_AUTH_AUTH,
+ CONN_AUTH_SSL,
+ RESOURCES_MEM,
+ RESOURCES_DISK,
+ RESOURCES_KERNEL,
+ RESOURCES_VACUUM_DELAY,
+ RESOURCES_BGWRITER,
+ RESOURCES_ASYNCHRONOUS,
+ WAL_SETTINGS,
+ WAL_CHECKPOINTS,
+ WAL_ARCHIVING,
+ WAL_RECOVERY,
+ WAL_ARCHIVE_RECOVERY,
+ WAL_RECOVERY_TARGET,
+ REPLICATION_SENDING,
+ REPLICATION_PRIMARY,
+ REPLICATION_STANDBY,
+ REPLICATION_SUBSCRIBERS,
+ QUERY_TUNING_METHOD,
+ QUERY_TUNING_COST,
+ QUERY_TUNING_GEQO,
+ QUERY_TUNING_OTHER,
+ LOGGING_WHERE,
+ LOGGING_WHEN,
+ LOGGING_WHAT,
+ PROCESS_TITLE,
+ STATS_MONITORING,
+ STATS_CUMULATIVE,
+ AUTOVACUUM,
+ CLIENT_CONN_STATEMENT,
+ CLIENT_CONN_LOCALE,
+ CLIENT_CONN_PRELOAD,
+ CLIENT_CONN_OTHER,
+ LOCK_MANAGEMENT,
+ COMPAT_OPTIONS_PREVIOUS,
+ COMPAT_OPTIONS_CLIENT,
+ ERROR_HANDLING_OPTIONS,
+ PRESET_OPTIONS,
+ CUSTOM_OPTIONS,
+ DEVELOPER_OPTIONS
+};
+
+/*
+ * Stack entry for saving the state a variable had prior to an uncommitted
+ * transactional change
+ */
+typedef enum
+{
+ /* This is almost GucAction, but we need a fourth state for SET+LOCAL */
+ GUC_SAVE, /* entry caused by function SET option */
+ GUC_SET, /* entry caused by plain SET command */
+ GUC_LOCAL, /* entry caused by SET LOCAL command */
+ GUC_SET_LOCAL /* entry caused by SET then SET LOCAL */
+} GucStackState;
+
+typedef struct guc_stack
+{
+ struct guc_stack *prev; /* previous stack item, if any */
+ int nest_level; /* nesting depth at which we made entry */
+ GucStackState state; /* see enum above */
+ GucSource source; /* source of the prior value */
+ /* masked value's source must be PGC_S_SESSION, so no need to store it */
+ GucContext scontext; /* context that set the prior value */
+ GucContext masked_scontext; /* context that set the masked value */
+ Oid srole; /* role that set the prior value */
+ Oid masked_srole; /* role that set the masked value */
+ config_var_value prior; /* previous value of variable */
+ config_var_value masked; /* SET value in a GUC_SET_LOCAL entry */
+} GucStack;
+
+/*
+ * Generic fields applicable to all types of variables
+ *
+ * The short description should be less than 80 chars in length. Some
+ * applications may use the long description as well, and will append
+ * it to the short description. (separated by a newline or '. ')
+ *
+ * srole is the role that set the current value, or BOOTSTRAP_SUPERUSERID
+ * if the value came from an internal source or the config file. Similarly
+ * for reset_srole (which is usually BOOTSTRAP_SUPERUSERID, but not always).
+ *
+ * Variables that are currently of active interest for maintenance
+ * operations are linked into various lists using the xxx_link fields.
+ * The link fields are unused/garbage in variables not currently having
+ * the specified properties.
+ *
+ * Note that sourcefile/sourceline are kept here, and not pushed into stacked
+ * values, although in principle they belong with some stacked value if the
+ * active value is session- or transaction-local. This is to avoid bloating
+ * stack entries. We know they are only relevant when source == PGC_S_FILE.
+ */
+struct config_generic
+{
+ /* constant fields, must be set correctly in initial value: */
+ const char *name; /* name of variable - MUST BE FIRST */
+ GucContext context; /* context required to set the variable */
+ enum config_group group; /* to help organize variables by function */
+ const char *short_desc; /* short desc. of this variable's purpose */
+ const char *long_desc; /* long desc. of this variable's purpose */
+ int flags; /* flag bits, see guc.h */
+ /* variable fields, initialized at runtime: */
+ enum config_type vartype; /* type of variable (set only at startup) */
+ int status; /* status bits, see below */
+ GucSource source; /* source of the current actual value */
+ GucSource reset_source; /* source of the reset_value */
+ GucContext scontext; /* context that set the current value */
+ GucContext reset_scontext; /* context that set the reset value */
+ Oid srole; /* role that set the current value */
+ Oid reset_srole; /* role that set the reset value */
+ GucStack *stack; /* stacked prior values */
+ void *extra; /* "extra" pointer for current actual value */
+ dlist_node nondef_link; /* list link for variables that have source
+ * different from PGC_S_DEFAULT */
+ slist_node stack_link; /* list link for variables that have non-NULL
+ * stack */
+ slist_node report_link; /* list link for variables that have the
+ * GUC_NEEDS_REPORT bit set in status */
+ char *last_reported; /* if variable is GUC_REPORT, value last sent
+ * to client (NULL if not yet sent) */
+ char *sourcefile; /* file current setting is from (NULL if not
+ * set in config file) */
+ int sourceline; /* line in source file */
+};
+
+/* bit values in status field */
+#define GUC_IS_IN_FILE 0x0001 /* found it in config file */
+/*
+ * Caution: the GUC_IS_IN_FILE bit is transient state for ProcessConfigFile.
+ * Do not assume that its value represents useful information elsewhere.
+ */
+#define GUC_PENDING_RESTART 0x0002 /* changed value cannot be applied yet */
+#define GUC_NEEDS_REPORT 0x0004 /* new value must be reported to client */
+
+
+/* GUC records for specific variable types */
+
+struct config_bool
+{
+ struct config_generic gen;
+ /* constant fields, must be set correctly in initial value: */
+ bool *variable;
+ bool boot_val;
+ GucBoolCheckHook check_hook;
+ GucBoolAssignHook assign_hook;
+ GucShowHook show_hook;
+ /* variable fields, initialized at runtime: */
+ bool reset_val;
+ void *reset_extra;
+};
+
+struct config_int
+{
+ struct config_generic gen;
+ /* constant fields, must be set correctly in initial value: */
+ int *variable;
+ int boot_val;
+ int min;
+ int max;
+ GucIntCheckHook check_hook;
+ GucIntAssignHook assign_hook;
+ GucShowHook show_hook;
+ /* variable fields, initialized at runtime: */
+ int reset_val;
+ void *reset_extra;
+};
+
+struct config_real
+{
+ struct config_generic gen;
+ /* constant fields, must be set correctly in initial value: */
+ double *variable;
+ double boot_val;
+ double min;
+ double max;
+ GucRealCheckHook check_hook;
+ GucRealAssignHook assign_hook;
+ GucShowHook show_hook;
+ /* variable fields, initialized at runtime: */
+ double reset_val;
+ void *reset_extra;
+};
+
+/*
+ * A note about string GUCs: the boot_val is allowed to be NULL, which leads
+ * to the reset_val and the actual variable value (*variable) also being NULL.
+ * However, there is no way to set a NULL value subsequently using
+ * set_config_option or any other GUC API. Also, GUC APIs such as SHOW will
+ * display a NULL value as an empty string. Callers that choose to use a NULL
+ * boot_val should overwrite the setting later in startup, or else be careful
+ * that NULL doesn't have semantics that are visibly different from an empty
+ * string.
+ */
+struct config_string
+{
+ struct config_generic gen;
+ /* constant fields, must be set correctly in initial value: */
+ char **variable;
+ const char *boot_val;
+ GucStringCheckHook check_hook;
+ GucStringAssignHook assign_hook;
+ GucShowHook show_hook;
+ /* variable fields, initialized at runtime: */
+ char *reset_val;
+ void *reset_extra;
+};
+
+struct config_enum
+{
+ struct config_generic gen;
+ /* constant fields, must be set correctly in initial value: */
+ int *variable;
+ int boot_val;
+ const struct config_enum_entry *options;
+ GucEnumCheckHook check_hook;
+ GucEnumAssignHook assign_hook;
+ GucShowHook show_hook;
+ /* variable fields, initialized at runtime: */
+ int reset_val;
+ void *reset_extra;
+};
+
+/* constant tables corresponding to enums above and in guc.h */
+extern PGDLLIMPORT const char *const config_group_names[];
+extern PGDLLIMPORT const char *const config_type_names[];
+extern PGDLLIMPORT const char *const GucContext_Names[];
+extern PGDLLIMPORT const char *const GucSource_Names[];
+
+/* data arrays defining all the built-in GUC variables */
+extern PGDLLIMPORT struct config_bool ConfigureNamesBool[];
+extern PGDLLIMPORT struct config_int ConfigureNamesInt[];
+extern PGDLLIMPORT struct config_real ConfigureNamesReal[];
+extern PGDLLIMPORT struct config_string ConfigureNamesString[];
+extern PGDLLIMPORT struct config_enum ConfigureNamesEnum[];
+
+/* lookup GUC variables, returning config_generic pointers */
+extern struct config_generic *find_option(const char *name,
+ bool create_placeholders,
+ bool skip_errors,
+ int elevel);
+extern struct config_generic **get_explain_guc_options(int *num);
+
+/* get string value of variable */
+extern char *ShowGUCOption(struct config_generic *record, bool use_units);
+
+/* get whether or not the GUC variable is visible to current user */
+extern bool ConfigOptionIsVisible(struct config_generic *conf);
+
+/* get the current set of variables */
+extern struct config_generic **get_guc_variables(int *num_vars);
+
+extern void build_guc_variables(void);
+
+/* search in enum options */
+extern const char *config_enum_lookup_by_value(struct config_enum *record, int val);
+extern bool config_enum_lookup_by_name(struct config_enum *record,
+ const char *value, int *retval);
+extern char *config_enum_get_options(struct config_enum *record,
+ const char *prefix,
+ const char *suffix,
+ const char *separator);
+
+#endif /* GUC_TABLES_H */
diff --git a/src/include/utils/help_config.h b/src/include/utils/help_config.h
new file mode 100644
index 0000000..e9bc417
--- /dev/null
+++ b/src/include/utils/help_config.h
@@ -0,0 +1,17 @@
+/*-------------------------------------------------------------------------
+ *
+ * help_config.h
+ * Interface to the --help-config option of main.c
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ *
+ * src/include/utils/help_config.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef HELP_CONFIG_H
+#define HELP_CONFIG_H 1
+
+extern void GucInfoMain(void) pg_attribute_noreturn();
+
+#endif
diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h
new file mode 100644
index 0000000..bc3d5ef
--- /dev/null
+++ b/src/include/utils/hsearch.h
@@ -0,0 +1,153 @@
+/*-------------------------------------------------------------------------
+ *
+ * hsearch.h
+ * exported definitions for utils/hash/dynahash.c; see notes therein
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/hsearch.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef HSEARCH_H
+#define HSEARCH_H
+
+
+/*
+ * Hash functions must have this signature.
+ */
+typedef uint32 (*HashValueFunc) (const void *key, Size keysize);
+
+/*
+ * Key comparison functions must have this signature. Comparison functions
+ * return zero for match, nonzero for no match. (The comparison function
+ * definition is designed to allow memcmp() and strncmp() to be used directly
+ * as key comparison functions.)
+ */
+typedef int (*HashCompareFunc) (const void *key1, const void *key2,
+ Size keysize);
+
+/*
+ * Key copying functions must have this signature. The return value is not
+ * used. (The definition is set up to allow memcpy() and strlcpy() to be
+ * used directly.)
+ */
+typedef void *(*HashCopyFunc) (void *dest, const void *src, Size keysize);
+
+/*
+ * Space allocation function for a hashtable --- designed to match malloc().
+ * Note: there is no free function API; can't destroy a hashtable unless you
+ * use the default allocator.
+ */
+typedef void *(*HashAllocFunc) (Size request);
+
+/*
+ * HASHELEMENT is the private part of a hashtable entry. The caller's data
+ * follows the HASHELEMENT structure (on a MAXALIGN'd boundary). The hash key
+ * is expected to be at the start of the caller's hash entry data structure.
+ */
+typedef struct HASHELEMENT
+{
+ struct HASHELEMENT *link; /* link to next entry in same bucket */
+ uint32 hashvalue; /* hash function result for this entry */
+} HASHELEMENT;
+
+/* Hash table header struct is an opaque type known only within dynahash.c */
+typedef struct HASHHDR HASHHDR;
+
+/* Hash table control struct is an opaque type known only within dynahash.c */
+typedef struct HTAB HTAB;
+
+/* Parameter data structure for hash_create */
+/* Only those fields indicated by hash_flags need be set */
+typedef struct HASHCTL
+{
+ /* Used if HASH_PARTITION flag is set: */
+ long num_partitions; /* # partitions (must be power of 2) */
+ /* Used if HASH_SEGMENT flag is set: */
+ long ssize; /* segment size */
+ /* Used if HASH_DIRSIZE flag is set: */
+ long dsize; /* (initial) directory size */
+ long max_dsize; /* limit to dsize if dir size is limited */
+ /* Used if HASH_ELEM flag is set (which is now required): */
+ Size keysize; /* hash key length in bytes */
+ Size entrysize; /* total user element size in bytes */
+ /* Used if HASH_FUNCTION flag is set: */
+ HashValueFunc hash; /* hash function */
+ /* Used if HASH_COMPARE flag is set: */
+ HashCompareFunc match; /* key comparison function */
+ /* Used if HASH_KEYCOPY flag is set: */
+ HashCopyFunc keycopy; /* key copying function */
+ /* Used if HASH_ALLOC flag is set: */
+ HashAllocFunc alloc; /* memory allocator */
+ /* Used if HASH_CONTEXT flag is set: */
+ MemoryContext hcxt; /* memory context to use for allocations */
+ /* Used if HASH_SHARED_MEM flag is set: */
+ HASHHDR *hctl; /* location of header in shared mem */
+} HASHCTL;
+
+/* Flag bits for hash_create; most indicate which parameters are supplied */
+#define HASH_PARTITION 0x0001 /* Hashtable is used w/partitioned locking */
+#define HASH_SEGMENT 0x0002 /* Set segment size */
+#define HASH_DIRSIZE 0x0004 /* Set directory size (initial and max) */
+#define HASH_ELEM 0x0008 /* Set keysize and entrysize (now required!) */
+#define HASH_STRINGS 0x0010 /* Select support functions for string keys */
+#define HASH_BLOBS 0x0020 /* Select support functions for binary keys */
+#define HASH_FUNCTION 0x0040 /* Set user defined hash function */
+#define HASH_COMPARE 0x0080 /* Set user defined comparison function */
+#define HASH_KEYCOPY 0x0100 /* Set user defined key-copying function */
+#define HASH_ALLOC 0x0200 /* Set memory allocator */
+#define HASH_CONTEXT 0x0400 /* Set memory allocation context */
+#define HASH_SHARED_MEM 0x0800 /* Hashtable is in shared memory */
+#define HASH_ATTACH 0x1000 /* Do not initialize hctl */
+#define HASH_FIXED_SIZE 0x2000 /* Initial size is a hard limit */
+
+/* max_dsize value to indicate expansible directory */
+#define NO_MAX_DSIZE (-1)
+
+/* hash_search operations */
+typedef enum
+{
+ HASH_FIND,
+ HASH_ENTER,
+ HASH_REMOVE,
+ HASH_ENTER_NULL
+} HASHACTION;
+
+/* hash_seq status (should be considered an opaque type by callers) */
+typedef struct
+{
+ HTAB *hashp;
+ uint32 curBucket; /* index of current bucket */
+ HASHELEMENT *curEntry; /* current entry in bucket */
+} HASH_SEQ_STATUS;
+
+/*
+ * prototypes for functions in dynahash.c
+ */
+extern HTAB *hash_create(const char *tabname, long nelem,
+ const HASHCTL *info, int flags);
+extern void hash_destroy(HTAB *hashp);
+extern void hash_stats(const char *where, HTAB *hashp);
+extern void *hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action,
+ bool *foundPtr);
+extern uint32 get_hash_value(HTAB *hashp, const void *keyPtr);
+extern void *hash_search_with_hash_value(HTAB *hashp, const void *keyPtr,
+ uint32 hashvalue, HASHACTION action,
+ bool *foundPtr);
+extern bool hash_update_hash_key(HTAB *hashp, void *existingEntry,
+ const void *newKeyPtr);
+extern long hash_get_num_entries(HTAB *hashp);
+extern void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp);
+extern void *hash_seq_search(HASH_SEQ_STATUS *status);
+extern void hash_seq_term(HASH_SEQ_STATUS *status);
+extern void hash_freeze(HTAB *hashp);
+extern Size hash_estimate_size(long num_entries, Size entrysize);
+extern long hash_select_dirsize(long num_entries);
+extern Size hash_get_shared_size(HASHCTL *info, int flags);
+extern void AtEOXact_HashTables(bool isCommit);
+extern void AtEOSubXact_HashTables(bool isCommit, int nestDepth);
+
+#endif /* HSEARCH_H */
diff --git a/src/include/utils/index_selfuncs.h b/src/include/utils/index_selfuncs.h
new file mode 100644
index 0000000..f081a1a
--- /dev/null
+++ b/src/include/utils/index_selfuncs.h
@@ -0,0 +1,74 @@
+/*-------------------------------------------------------------------------
+ *
+ * index_selfuncs.h
+ * Index cost estimation functions for standard index access methods.
+ *
+ *
+ * Note: this is split out of selfuncs.h mainly to avoid importing all of the
+ * planner's data structures into the non-planner parts of the index AMs.
+ * If you make it depend on anything besides access/amapi.h, that's likely
+ * a mistake.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/index_selfuncs.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef INDEX_SELFUNCS_H
+#define INDEX_SELFUNCS_H
+
+#include "access/amapi.h"
+
+/* Functions in selfuncs.c */
+extern void brincostestimate(struct PlannerInfo *root,
+ struct IndexPath *path,
+ double loop_count,
+ Cost *indexStartupCost,
+ Cost *indexTotalCost,
+ Selectivity *indexSelectivity,
+ double *indexCorrelation,
+ double *indexPages);
+extern void btcostestimate(struct PlannerInfo *root,
+ struct IndexPath *path,
+ double loop_count,
+ Cost *indexStartupCost,
+ Cost *indexTotalCost,
+ Selectivity *indexSelectivity,
+ double *indexCorrelation,
+ double *indexPages);
+extern void hashcostestimate(struct PlannerInfo *root,
+ struct IndexPath *path,
+ double loop_count,
+ Cost *indexStartupCost,
+ Cost *indexTotalCost,
+ Selectivity *indexSelectivity,
+ double *indexCorrelation,
+ double *indexPages);
+extern void gistcostestimate(struct PlannerInfo *root,
+ struct IndexPath *path,
+ double loop_count,
+ Cost *indexStartupCost,
+ Cost *indexTotalCost,
+ Selectivity *indexSelectivity,
+ double *indexCorrelation,
+ double *indexPages);
+extern void spgcostestimate(struct PlannerInfo *root,
+ struct IndexPath *path,
+ double loop_count,
+ Cost *indexStartupCost,
+ Cost *indexTotalCost,
+ Selectivity *indexSelectivity,
+ double *indexCorrelation,
+ double *indexPages);
+extern void gincostestimate(struct PlannerInfo *root,
+ struct IndexPath *path,
+ double loop_count,
+ Cost *indexStartupCost,
+ Cost *indexTotalCost,
+ Selectivity *indexSelectivity,
+ double *indexCorrelation,
+ double *indexPages);
+
+#endif /* INDEX_SELFUNCS_H */
diff --git a/src/include/utils/inet.h b/src/include/utils/inet.h
new file mode 100644
index 0000000..96d9f6a
--- /dev/null
+++ b/src/include/utils/inet.h
@@ -0,0 +1,184 @@
+/*-------------------------------------------------------------------------
+ *
+ * inet.h
+ * Declarations for operations on INET datatypes.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/inet.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef INET_H
+#define INET_H
+
+#include "fmgr.h"
+
+/*
+ * This is the internal storage format for IP addresses
+ * (both INET and CIDR datatypes):
+ */
+typedef struct
+{
+ unsigned char family; /* PGSQL_AF_INET or PGSQL_AF_INET6 */
+ unsigned char bits; /* number of bits in netmask */
+ unsigned char ipaddr[16]; /* up to 128 bits of address */
+} inet_struct;
+
+/*
+ * We use these values for the "family" field.
+ *
+ * Referencing all of the non-AF_INET types to AF_INET lets us work on
+ * machines which did not have the appropriate address family (like
+ * inet6 addresses when AF_INET6 wasn't present) but didn't cause a
+ * dump/reload requirement. Pre-7.4 databases used AF_INET for the family
+ * type on disk.
+ */
+#define PGSQL_AF_INET (AF_INET + 0)
+#define PGSQL_AF_INET6 (AF_INET + 1)
+
+/*
+ * Both INET and CIDR addresses are represented within Postgres as varlena
+ * objects, ie, there is a varlena header in front of the struct type
+ * depicted above. This struct depicts what we actually have in memory
+ * in "uncompressed" cases. Note that since the maximum data size is only
+ * 18 bytes, INET/CIDR will invariably be stored into tuples using the
+ * 1-byte-header varlena format. However, we have to be prepared to cope
+ * with the 4-byte-header format too, because various code may helpfully
+ * try to "decompress" 1-byte-header datums.
+ */
+typedef struct
+{
+ char vl_len_[4]; /* Do not touch this field directly! */
+ inet_struct inet_data;
+} inet;
+
+/*
+ * Access macros. We use VARDATA_ANY so that we can process short-header
+ * varlena values without detoasting them. This requires a trick:
+ * VARDATA_ANY assumes the varlena header is already filled in, which is
+ * not the case when constructing a new value (until SET_INET_VARSIZE is
+ * called, which we typically can't do till the end). Therefore, we
+ * always initialize the newly-allocated value to zeroes (using palloc0).
+ * A zero length word will look like the not-1-byte case to VARDATA_ANY,
+ * and so we correctly construct an uncompressed value.
+ *
+ * Note that ip_addrsize(), ip_maxbits(), and SET_INET_VARSIZE() require
+ * the family field to be set correctly.
+ */
+#define ip_family(inetptr) \
+ (((inet_struct *) VARDATA_ANY(inetptr))->family)
+
+#define ip_bits(inetptr) \
+ (((inet_struct *) VARDATA_ANY(inetptr))->bits)
+
+#define ip_addr(inetptr) \
+ (((inet_struct *) VARDATA_ANY(inetptr))->ipaddr)
+
+#define ip_addrsize(inetptr) \
+ (ip_family(inetptr) == PGSQL_AF_INET ? 4 : 16)
+
+#define ip_maxbits(inetptr) \
+ (ip_family(inetptr) == PGSQL_AF_INET ? 32 : 128)
+
+#define SET_INET_VARSIZE(dst) \
+ SET_VARSIZE(dst, VARHDRSZ + offsetof(inet_struct, ipaddr) + \
+ ip_addrsize(dst))
+
+
+/*
+ * This is the internal storage format for MAC addresses:
+ */
+typedef struct macaddr
+{
+ unsigned char a;
+ unsigned char b;
+ unsigned char c;
+ unsigned char d;
+ unsigned char e;
+ unsigned char f;
+} macaddr;
+
+/*
+ * This is the internal storage format for MAC8 addresses:
+ */
+typedef struct macaddr8
+{
+ unsigned char a;
+ unsigned char b;
+ unsigned char c;
+ unsigned char d;
+ unsigned char e;
+ unsigned char f;
+ unsigned char g;
+ unsigned char h;
+} macaddr8;
+
+/*
+ * fmgr interface macros
+ */
+static inline inet *
+DatumGetInetPP(Datum X)
+{
+ return (inet *) PG_DETOAST_DATUM_PACKED(X);
+}
+
+static inline Datum
+InetPGetDatum(const inet *X)
+{
+ return PointerGetDatum(X);
+}
+
+#define PG_GETARG_INET_PP(n) DatumGetInetPP(PG_GETARG_DATUM(n))
+#define PG_RETURN_INET_P(x) return InetPGetDatum(x)
+
+/* obsolescent variants */
+static inline inet *
+DatumGetInetP(Datum X)
+{
+ return (inet *) PG_DETOAST_DATUM(X);
+}
+#define PG_GETARG_INET_P(n) DatumGetInetP(PG_GETARG_DATUM(n))
+
+/* macaddr is a fixed-length pass-by-reference datatype */
+static inline macaddr *
+DatumGetMacaddrP(Datum X)
+{
+ return (macaddr *) DatumGetPointer(X);
+}
+
+static inline Datum
+MacaddrPGetDatum(const macaddr *X)
+{
+ return PointerGetDatum(X);
+}
+
+#define PG_GETARG_MACADDR_P(n) DatumGetMacaddrP(PG_GETARG_DATUM(n))
+#define PG_RETURN_MACADDR_P(x) return MacaddrPGetDatum(x)
+
+/* macaddr8 is a fixed-length pass-by-reference datatype */
+static inline macaddr8 *
+DatumGetMacaddr8P(Datum X)
+{
+ return (macaddr8 *) DatumGetPointer(X);
+}
+
+static inline Datum
+Macaddr8PGetDatum(const macaddr8 *X)
+{
+ return PointerGetDatum(X);
+}
+
+#define PG_GETARG_MACADDR8_P(n) DatumGetMacaddr8P(PG_GETARG_DATUM(n))
+#define PG_RETURN_MACADDR8_P(x) return Macaddr8PGetDatum(x)
+
+/*
+ * Support functions in network.c
+ */
+extern inet *cidr_set_masklen_internal(const inet *src, int bits);
+extern int bitncmp(const unsigned char *l, const unsigned char *r, int n);
+extern int bitncommon(const unsigned char *l, const unsigned char *r, int n);
+
+#endif /* INET_H */
diff --git a/src/include/utils/inval.h b/src/include/utils/inval.h
new file mode 100644
index 0000000..14b4eac
--- /dev/null
+++ b/src/include/utils/inval.h
@@ -0,0 +1,68 @@
+/*-------------------------------------------------------------------------
+ *
+ * inval.h
+ * POSTGRES cache invalidation dispatcher definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/inval.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef INVAL_H
+#define INVAL_H
+
+#include "access/htup.h"
+#include "storage/relfilelocator.h"
+#include "utils/relcache.h"
+
+extern PGDLLIMPORT int debug_discard_caches;
+
+typedef void (*SyscacheCallbackFunction) (Datum arg, int cacheid, uint32 hashvalue);
+typedef void (*RelcacheCallbackFunction) (Datum arg, Oid relid);
+
+
+extern void AcceptInvalidationMessages(void);
+
+extern void AtEOXact_Inval(bool isCommit);
+
+extern void AtEOSubXact_Inval(bool isCommit);
+
+extern void PostPrepare_Inval(void);
+
+extern void CommandEndInvalidationMessages(void);
+
+extern void CacheInvalidateHeapTuple(Relation relation,
+ HeapTuple tuple,
+ HeapTuple newtuple);
+
+extern void CacheInvalidateCatalog(Oid catalogId);
+
+extern void CacheInvalidateRelcache(Relation relation);
+
+extern void CacheInvalidateRelcacheAll(void);
+
+extern void CacheInvalidateRelcacheByTuple(HeapTuple classTuple);
+
+extern void CacheInvalidateRelcacheByRelid(Oid relid);
+
+extern void CacheInvalidateSmgr(RelFileLocatorBackend rlocator);
+
+extern void CacheInvalidateRelmap(Oid databaseId);
+
+extern void CacheRegisterSyscacheCallback(int cacheid,
+ SyscacheCallbackFunction func,
+ Datum arg);
+
+extern void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func,
+ Datum arg);
+
+extern void CallSyscacheCallbacks(int cacheid, uint32 hashvalue);
+
+extern void InvalidateSystemCaches(void);
+extern void InvalidateSystemCachesExtended(bool debug_discard);
+
+extern void LogLogicalInvalidations(void);
+#endif /* INVAL_H */
diff --git a/src/include/utils/json.h b/src/include/utils/json.h
new file mode 100644
index 0000000..35a9a55
--- /dev/null
+++ b/src/include/utils/json.h
@@ -0,0 +1,31 @@
+/*-------------------------------------------------------------------------
+ *
+ * json.h
+ * Declarations for JSON data type support.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/json.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef JSON_H
+#define JSON_H
+
+#include "lib/stringinfo.h"
+
+/* functions in json.c */
+extern void escape_json(StringInfo buf, const char *str);
+extern char *JsonEncodeDateTime(char *buf, Datum value, Oid typid,
+ const int *tzp);
+extern bool to_json_is_immutable(Oid typoid);
+extern Datum json_build_object_worker(int nargs, Datum *args, bool *nulls,
+ Oid *types, bool absent_on_null,
+ bool unique_keys);
+extern Datum json_build_array_worker(int nargs, Datum *args, bool *nulls,
+ Oid *types, bool absent_on_null);
+extern bool json_validate(text *json, bool check_unique_keys, bool throw_error);
+
+#endif /* JSON_H */
diff --git a/src/include/utils/jsonb.h b/src/include/utils/jsonb.h
new file mode 100644
index 0000000..649a164
--- /dev/null
+++ b/src/include/utils/jsonb.h
@@ -0,0 +1,439 @@
+/*-------------------------------------------------------------------------
+ *
+ * jsonb.h
+ * Declarations for jsonb data type support.
+ *
+ * Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ *
+ * src/include/utils/jsonb.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef __JSONB_H__
+#define __JSONB_H__
+
+#include "lib/stringinfo.h"
+#include "utils/array.h"
+#include "utils/numeric.h"
+
+/* Tokens used when sequentially processing a jsonb value */
+typedef enum
+{
+ WJB_DONE,
+ WJB_KEY,
+ WJB_VALUE,
+ WJB_ELEM,
+ WJB_BEGIN_ARRAY,
+ WJB_END_ARRAY,
+ WJB_BEGIN_OBJECT,
+ WJB_END_OBJECT
+} JsonbIteratorToken;
+
+/* Strategy numbers for GIN index opclasses */
+#define JsonbContainsStrategyNumber 7
+#define JsonbExistsStrategyNumber 9
+#define JsonbExistsAnyStrategyNumber 10
+#define JsonbExistsAllStrategyNumber 11
+#define JsonbJsonpathExistsStrategyNumber 15
+#define JsonbJsonpathPredicateStrategyNumber 16
+
+
+/*
+ * In the standard jsonb_ops GIN opclass for jsonb, we choose to index both
+ * keys and values. The storage format is text. The first byte of the text
+ * string distinguishes whether this is a key (always a string), null value,
+ * boolean value, numeric value, or string value. However, array elements
+ * that are strings are marked as though they were keys; this imprecision
+ * supports the definition of the "exists" operator, which treats array
+ * elements like keys. The remainder of the text string is empty for a null
+ * value, "t" or "f" for a boolean value, a normalized print representation of
+ * a numeric value, or the text of a string value. However, if the length of
+ * this text representation would exceed JGIN_MAXLENGTH bytes, we instead hash
+ * the text representation and store an 8-hex-digit representation of the
+ * uint32 hash value, marking the prefix byte with an additional bit to
+ * distinguish that this has happened. Hashing long strings saves space and
+ * ensures that we won't overrun the maximum entry length for a GIN index.
+ * (But JGIN_MAXLENGTH is quite a bit shorter than GIN's limit. It's chosen
+ * to ensure that the on-disk text datum will have a short varlena header.)
+ * Note that when any hashed item appears in a query, we must recheck index
+ * matches against the heap tuple; currently, this costs nothing because we
+ * must always recheck for other reasons.
+ */
+#define JGINFLAG_KEY 0x01 /* key (or string array element) */
+#define JGINFLAG_NULL 0x02 /* null value */
+#define JGINFLAG_BOOL 0x03 /* boolean value */
+#define JGINFLAG_NUM 0x04 /* numeric value */
+#define JGINFLAG_STR 0x05 /* string value (if not an array element) */
+#define JGINFLAG_HASHED 0x10 /* OR'd into flag if value was hashed */
+#define JGIN_MAXLENGTH 125 /* max length of text part before hashing */
+
+typedef struct JsonbPair JsonbPair;
+typedef struct JsonbValue JsonbValue;
+
+/*
+ * Jsonbs are varlena objects, so must meet the varlena convention that the
+ * first int32 of the object contains the total object size in bytes. Be sure
+ * to use VARSIZE() and SET_VARSIZE() to access it, though!
+ *
+ * Jsonb is the on-disk representation, in contrast to the in-memory JsonbValue
+ * representation. Often, JsonbValues are just shims through which a Jsonb
+ * buffer is accessed, but they can also be deep copied and passed around.
+ *
+ * Jsonb is a tree structure. Each node in the tree consists of a JEntry
+ * header and a variable-length content (possibly of zero size). The JEntry
+ * header indicates what kind of a node it is, e.g. a string or an array,
+ * and provides the length of its variable-length portion.
+ *
+ * The JEntry and the content of a node are not stored physically together.
+ * Instead, the container array or object has an array that holds the JEntrys
+ * of all the child nodes, followed by their variable-length portions.
+ *
+ * The root node is an exception; it has no parent array or object that could
+ * hold its JEntry. Hence, no JEntry header is stored for the root node. It
+ * is implicitly known that the root node must be an array or an object,
+ * so we can get away without the type indicator as long as we can distinguish
+ * the two. For that purpose, both an array and an object begin with a uint32
+ * header field, which contains an JB_FOBJECT or JB_FARRAY flag. When a naked
+ * scalar value needs to be stored as a Jsonb value, what we actually store is
+ * an array with one element, with the flags in the array's header field set
+ * to JB_FSCALAR | JB_FARRAY.
+ *
+ * Overall, the Jsonb struct requires 4-bytes alignment. Within the struct,
+ * the variable-length portion of some node types is aligned to a 4-byte
+ * boundary, while others are not. When alignment is needed, the padding is
+ * in the beginning of the node that requires it. For example, if a numeric
+ * node is stored after a string node, so that the numeric node begins at
+ * offset 3, the variable-length portion of the numeric node will begin with
+ * one padding byte so that the actual numeric data is 4-byte aligned.
+ */
+
+/*
+ * JEntry format.
+ *
+ * The least significant 28 bits store either the data length of the entry,
+ * or its end+1 offset from the start of the variable-length portion of the
+ * containing object. The next three bits store the type of the entry, and
+ * the high-order bit tells whether the least significant bits store a length
+ * or an offset.
+ *
+ * The reason for the offset-or-length complication is to compromise between
+ * access speed and data compressibility. In the initial design each JEntry
+ * always stored an offset, but this resulted in JEntry arrays with horrible
+ * compressibility properties, so that TOAST compression of a JSONB did not
+ * work well. Storing only lengths would greatly improve compressibility,
+ * but it makes random access into large arrays expensive (O(N) not O(1)).
+ * So what we do is store an offset in every JB_OFFSET_STRIDE'th JEntry and
+ * a length in the rest. This results in reasonably compressible data (as
+ * long as the stride isn't too small). We may have to examine as many as
+ * JB_OFFSET_STRIDE JEntrys in order to find out the offset or length of any
+ * given item, but that's still O(1) no matter how large the container is.
+ *
+ * We could avoid eating a flag bit for this purpose if we were to store
+ * the stride in the container header, or if we were willing to treat the
+ * stride as an unchangeable constant. Neither of those options is very
+ * attractive though.
+ */
+typedef uint32 JEntry;
+
+#define JENTRY_OFFLENMASK 0x0FFFFFFF
+#define JENTRY_TYPEMASK 0x70000000
+#define JENTRY_HAS_OFF 0x80000000
+
+/* values stored in the type bits */
+#define JENTRY_ISSTRING 0x00000000
+#define JENTRY_ISNUMERIC 0x10000000
+#define JENTRY_ISBOOL_FALSE 0x20000000
+#define JENTRY_ISBOOL_TRUE 0x30000000
+#define JENTRY_ISNULL 0x40000000
+#define JENTRY_ISCONTAINER 0x50000000 /* array or object */
+
+/* Access macros. Note possible multiple evaluations */
+#define JBE_OFFLENFLD(je_) ((je_) & JENTRY_OFFLENMASK)
+#define JBE_HAS_OFF(je_) (((je_) & JENTRY_HAS_OFF) != 0)
+#define JBE_ISSTRING(je_) (((je_) & JENTRY_TYPEMASK) == JENTRY_ISSTRING)
+#define JBE_ISNUMERIC(je_) (((je_) & JENTRY_TYPEMASK) == JENTRY_ISNUMERIC)
+#define JBE_ISCONTAINER(je_) (((je_) & JENTRY_TYPEMASK) == JENTRY_ISCONTAINER)
+#define JBE_ISNULL(je_) (((je_) & JENTRY_TYPEMASK) == JENTRY_ISNULL)
+#define JBE_ISBOOL_TRUE(je_) (((je_) & JENTRY_TYPEMASK) == JENTRY_ISBOOL_TRUE)
+#define JBE_ISBOOL_FALSE(je_) (((je_) & JENTRY_TYPEMASK) == JENTRY_ISBOOL_FALSE)
+#define JBE_ISBOOL(je_) (JBE_ISBOOL_TRUE(je_) || JBE_ISBOOL_FALSE(je_))
+
+/* Macro for advancing an offset variable to the next JEntry */
+#define JBE_ADVANCE_OFFSET(offset, je) \
+ do { \
+ JEntry je_ = (je); \
+ if (JBE_HAS_OFF(je_)) \
+ (offset) = JBE_OFFLENFLD(je_); \
+ else \
+ (offset) += JBE_OFFLENFLD(je_); \
+ } while(0)
+
+/*
+ * We store an offset, not a length, every JB_OFFSET_STRIDE children.
+ * Caution: this macro should only be referenced when creating a JSONB
+ * value. When examining an existing value, pay attention to the HAS_OFF
+ * bits instead. This allows changes in the offset-placement heuristic
+ * without breaking on-disk compatibility.
+ */
+#define JB_OFFSET_STRIDE 32
+
+/*
+ * A jsonb array or object node, within a Jsonb Datum.
+ *
+ * An array has one child for each element, stored in array order.
+ *
+ * An object has two children for each key/value pair. The keys all appear
+ * first, in key sort order; then the values appear, in an order matching the
+ * key order. This arrangement keeps the keys compact in memory, making a
+ * search for a particular key more cache-friendly.
+ */
+typedef struct JsonbContainer
+{
+ uint32 header; /* number of elements or key/value pairs, and
+ * flags */
+ JEntry children[FLEXIBLE_ARRAY_MEMBER];
+
+ /* the data for each child node follows. */
+} JsonbContainer;
+
+/* flags for the header-field in JsonbContainer */
+#define JB_CMASK 0x0FFFFFFF /* mask for count field */
+#define JB_FSCALAR 0x10000000 /* flag bits */
+#define JB_FOBJECT 0x20000000
+#define JB_FARRAY 0x40000000
+
+/* convenience macros for accessing a JsonbContainer struct */
+#define JsonContainerSize(jc) ((jc)->header & JB_CMASK)
+#define JsonContainerIsScalar(jc) (((jc)->header & JB_FSCALAR) != 0)
+#define JsonContainerIsObject(jc) (((jc)->header & JB_FOBJECT) != 0)
+#define JsonContainerIsArray(jc) (((jc)->header & JB_FARRAY) != 0)
+
+/* The top-level on-disk format for a jsonb datum. */
+typedef struct
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ JsonbContainer root;
+} Jsonb;
+
+/* convenience macros for accessing the root container in a Jsonb datum */
+#define JB_ROOT_COUNT(jbp_) (*(uint32 *) VARDATA(jbp_) & JB_CMASK)
+#define JB_ROOT_IS_SCALAR(jbp_) ((*(uint32 *) VARDATA(jbp_) & JB_FSCALAR) != 0)
+#define JB_ROOT_IS_OBJECT(jbp_) ((*(uint32 *) VARDATA(jbp_) & JB_FOBJECT) != 0)
+#define JB_ROOT_IS_ARRAY(jbp_) ((*(uint32 *) VARDATA(jbp_) & JB_FARRAY) != 0)
+
+
+enum jbvType
+{
+ /* Scalar types */
+ jbvNull = 0x0,
+ jbvString,
+ jbvNumeric,
+ jbvBool,
+ /* Composite types */
+ jbvArray = 0x10,
+ jbvObject,
+ /* Binary (i.e. struct Jsonb) jbvArray/jbvObject */
+ jbvBinary,
+
+ /*
+ * Virtual types.
+ *
+ * These types are used only for in-memory JSON processing and serialized
+ * into JSON strings when outputted to json/jsonb.
+ */
+ jbvDatetime = 0x20,
+};
+
+/*
+ * JsonbValue: In-memory representation of Jsonb. This is a convenient
+ * deserialized representation, that can easily support using the "val"
+ * union across underlying types during manipulation. The Jsonb on-disk
+ * representation has various alignment considerations.
+ */
+struct JsonbValue
+{
+ enum jbvType type; /* Influences sort order */
+
+ union
+ {
+ Numeric numeric;
+ bool boolean;
+ struct
+ {
+ int len;
+ char *val; /* Not necessarily null-terminated */
+ } string; /* String primitive type */
+
+ struct
+ {
+ int nElems;
+ JsonbValue *elems;
+ bool rawScalar; /* Top-level "raw scalar" array? */
+ } array; /* Array container type */
+
+ struct
+ {
+ int nPairs; /* 1 pair, 2 elements */
+ JsonbPair *pairs;
+ } object; /* Associative container type */
+
+ struct
+ {
+ int len;
+ JsonbContainer *data;
+ } binary; /* Array or object, in on-disk format */
+
+ struct
+ {
+ Datum value;
+ Oid typid;
+ int32 typmod;
+ int tz; /* Numeric time zone, in seconds, for
+ * TimestampTz data type */
+ } datetime;
+ } val;
+};
+
+#define IsAJsonbScalar(jsonbval) (((jsonbval)->type >= jbvNull && \
+ (jsonbval)->type <= jbvBool) || \
+ (jsonbval)->type == jbvDatetime)
+
+/*
+ * Key/value pair within an Object.
+ *
+ * This struct type is only used briefly while constructing a Jsonb; it is
+ * *not* the on-disk representation.
+ *
+ * Pairs with duplicate keys are de-duplicated. We store the originally
+ * observed pair ordering for the purpose of removing duplicates in a
+ * well-defined way (which is "last observed wins").
+ */
+struct JsonbPair
+{
+ JsonbValue key; /* Must be a jbvString */
+ JsonbValue value; /* May be of any type */
+ uint32 order; /* Pair's index in original sequence */
+};
+
+/* Conversion state used when parsing Jsonb from text, or for type coercion */
+typedef struct JsonbParseState
+{
+ JsonbValue contVal;
+ Size size;
+ struct JsonbParseState *next;
+ bool unique_keys; /* Check object key uniqueness */
+ bool skip_nulls; /* Skip null object fields */
+} JsonbParseState;
+
+/*
+ * JsonbIterator holds details of the type for each iteration. It also stores a
+ * Jsonb varlena buffer, which can be directly accessed in some contexts.
+ */
+typedef enum
+{
+ JBI_ARRAY_START,
+ JBI_ARRAY_ELEM,
+ JBI_OBJECT_START,
+ JBI_OBJECT_KEY,
+ JBI_OBJECT_VALUE
+} JsonbIterState;
+
+typedef struct JsonbIterator
+{
+ /* Container being iterated */
+ JsonbContainer *container;
+ uint32 nElems; /* Number of elements in children array (will
+ * be nPairs for objects) */
+ bool isScalar; /* Pseudo-array scalar value? */
+ JEntry *children; /* JEntrys for child nodes */
+ /* Data proper. This points to the beginning of the variable-length data */
+ char *dataProper;
+
+ /* Current item in buffer (up to nElems) */
+ int curIndex;
+
+ /* Data offset corresponding to current item */
+ uint32 curDataOffset;
+
+ /*
+ * If the container is an object, we want to return keys and values
+ * alternately; so curDataOffset points to the current key, and
+ * curValueOffset points to the current value.
+ */
+ uint32 curValueOffset;
+
+ /* Private state */
+ JsonbIterState state;
+
+ struct JsonbIterator *parent;
+} JsonbIterator;
+
+
+/* Convenience macros */
+static inline Jsonb *
+DatumGetJsonbP(Datum d)
+{
+ return (Jsonb *) PG_DETOAST_DATUM(d);
+}
+
+static inline Jsonb *
+DatumGetJsonbPCopy(Datum d)
+{
+ return (Jsonb *) PG_DETOAST_DATUM_COPY(d);
+}
+
+static inline Datum
+JsonbPGetDatum(const Jsonb *p)
+{
+ return PointerGetDatum(p);
+}
+
+#define PG_GETARG_JSONB_P(x) DatumGetJsonbP(PG_GETARG_DATUM(x))
+#define PG_GETARG_JSONB_P_COPY(x) DatumGetJsonbPCopy(PG_GETARG_DATUM(x))
+#define PG_RETURN_JSONB_P(x) PG_RETURN_POINTER(x)
+
+/* Support functions */
+extern uint32 getJsonbOffset(const JsonbContainer *jc, int index);
+extern uint32 getJsonbLength(const JsonbContainer *jc, int index);
+extern int compareJsonbContainers(JsonbContainer *a, JsonbContainer *b);
+extern JsonbValue *findJsonbValueFromContainer(JsonbContainer *container,
+ uint32 flags,
+ JsonbValue *key);
+extern JsonbValue *getKeyJsonValueFromContainer(JsonbContainer *container,
+ const char *keyVal, int keyLen,
+ JsonbValue *res);
+extern JsonbValue *getIthJsonbValueFromContainer(JsonbContainer *container,
+ uint32 i);
+extern JsonbValue *pushJsonbValue(JsonbParseState **pstate,
+ JsonbIteratorToken seq, JsonbValue *jbval);
+extern JsonbIterator *JsonbIteratorInit(JsonbContainer *container);
+extern JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val,
+ bool skipNested);
+extern void JsonbToJsonbValue(Jsonb *jsonb, JsonbValue *val);
+extern Jsonb *JsonbValueToJsonb(JsonbValue *val);
+extern bool JsonbDeepContains(JsonbIterator **val,
+ JsonbIterator **mContained);
+extern void JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash);
+extern void JsonbHashScalarValueExtended(const JsonbValue *scalarVal,
+ uint64 *hash, uint64 seed);
+
+/* jsonb.c support functions */
+extern char *JsonbToCString(StringInfo out, JsonbContainer *in,
+ int estimated_len);
+extern char *JsonbToCStringIndent(StringInfo out, JsonbContainer *in,
+ int estimated_len);
+extern bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res);
+extern const char *JsonbTypeName(JsonbValue *val);
+
+extern Datum jsonb_set_element(Jsonb *jb, Datum *path, int path_len,
+ JsonbValue *newval);
+extern Datum jsonb_get_element(Jsonb *jb, Datum *path, int npath,
+ bool *isnull, bool as_text);
+extern bool to_jsonb_is_immutable(Oid typoid);
+extern Datum jsonb_build_object_worker(int nargs, Datum *args, bool *nulls,
+ Oid *types, bool absent_on_null,
+ bool unique_keys);
+extern Datum jsonb_build_array_worker(int nargs, Datum *args, bool *nulls,
+ Oid *types, bool absent_on_null);
+
+#endif /* __JSONB_H__ */
diff --git a/src/include/utils/jsonfuncs.h b/src/include/utils/jsonfuncs.h
new file mode 100644
index 0000000..a85203d
--- /dev/null
+++ b/src/include/utils/jsonfuncs.h
@@ -0,0 +1,66 @@
+/*-------------------------------------------------------------------------
+ *
+ * jsonfuncs.h
+ * Functions to process JSON data types.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/jsonfuncs.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef JSONFUNCS_H
+#define JSONFUNCS_H
+
+#include "common/jsonapi.h"
+#include "utils/jsonb.h"
+
+/*
+ * Flag types for iterate_json(b)_values to specify what elements from a
+ * json(b) document we want to iterate.
+ */
+typedef enum JsonToIndex
+{
+ jtiKey = 0x01,
+ jtiString = 0x02,
+ jtiNumeric = 0x04,
+ jtiBool = 0x08,
+ jtiAll = jtiKey | jtiString | jtiNumeric | jtiBool
+} JsonToIndex;
+
+/* an action that will be applied to each value in iterate_json(b)_values functions */
+typedef void (*JsonIterateStringValuesAction) (void *state, char *elem_value, int elem_len);
+
+/* an action that will be applied to each value in transform_json(b)_values functions */
+typedef text *(*JsonTransformStringValuesAction) (void *state, char *elem_value, int elem_len);
+
+/* build a JsonLexContext from a text datum */
+extern JsonLexContext *makeJsonLexContext(text *json, bool need_escapes);
+
+/* try to parse json, and errsave(escontext) on failure */
+extern bool pg_parse_json_or_errsave(JsonLexContext *lex, JsonSemAction *sem,
+ struct Node *escontext);
+
+#define pg_parse_json_or_ereport(lex, sem) \
+ (void) pg_parse_json_or_errsave(lex, sem, NULL)
+
+/* save an error during json lexing or parsing */
+extern void json_errsave_error(JsonParseErrorType error, JsonLexContext *lex,
+ struct Node *escontext);
+
+/* get first JSON token */
+extern JsonTokenType json_get_first_token(text *json, bool throw_error);
+
+extern uint32 parse_jsonb_index_flags(Jsonb *jb);
+extern void iterate_jsonb_values(Jsonb *jb, uint32 flags, void *state,
+ JsonIterateStringValuesAction action);
+extern void iterate_json_values(text *json, uint32 flags, void *action_state,
+ JsonIterateStringValuesAction action);
+extern Jsonb *transform_jsonb_string_values(Jsonb *jsonb, void *action_state,
+ JsonTransformStringValuesAction transform_action);
+extern text *transform_json_string_values(text *json, void *action_state,
+ JsonTransformStringValuesAction transform_action);
+
+#endif
diff --git a/src/include/utils/jsonpath.h b/src/include/utils/jsonpath.h
new file mode 100644
index 0000000..f0181e0
--- /dev/null
+++ b/src/include/utils/jsonpath.h
@@ -0,0 +1,264 @@
+/*-------------------------------------------------------------------------
+ *
+ * jsonpath.h
+ * Definitions for jsonpath datatype
+ *
+ * Copyright (c) 2019-2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/utils/jsonpath.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef JSONPATH_H
+#define JSONPATH_H
+
+#include "fmgr.h"
+#include "nodes/pg_list.h"
+#include "utils/jsonb.h"
+
+typedef struct
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ uint32 header; /* version and flags (see below) */
+ char data[FLEXIBLE_ARRAY_MEMBER];
+} JsonPath;
+
+#define JSONPATH_VERSION (0x01)
+#define JSONPATH_LAX (0x80000000)
+#define JSONPATH_HDRSZ (offsetof(JsonPath, data))
+
+static inline JsonPath *
+DatumGetJsonPathP(Datum d)
+{
+ return (JsonPath *) PG_DETOAST_DATUM(d);
+}
+
+static inline JsonPath *
+DatumGetJsonPathPCopy(Datum d)
+{
+ return (JsonPath *) PG_DETOAST_DATUM_COPY(d);
+}
+
+#define PG_GETARG_JSONPATH_P(x) DatumGetJsonPathP(PG_GETARG_DATUM(x))
+#define PG_GETARG_JSONPATH_P_COPY(x) DatumGetJsonPathPCopy(PG_GETARG_DATUM(x))
+#define PG_RETURN_JSONPATH_P(p) PG_RETURN_POINTER(p)
+
+#define jspIsScalar(type) ((type) >= jpiNull && (type) <= jpiBool)
+
+/*
+ * All node's type of jsonpath expression
+ */
+typedef enum JsonPathItemType
+{
+ jpiNull = jbvNull, /* NULL literal */
+ jpiString = jbvString, /* string literal */
+ jpiNumeric = jbvNumeric, /* numeric literal */
+ jpiBool = jbvBool, /* boolean literal: TRUE or FALSE */
+ jpiAnd, /* predicate && predicate */
+ jpiOr, /* predicate || predicate */
+ jpiNot, /* ! predicate */
+ jpiIsUnknown, /* (predicate) IS UNKNOWN */
+ jpiEqual, /* expr == expr */
+ jpiNotEqual, /* expr != expr */
+ jpiLess, /* expr < expr */
+ jpiGreater, /* expr > expr */
+ jpiLessOrEqual, /* expr <= expr */
+ jpiGreaterOrEqual, /* expr >= expr */
+ jpiAdd, /* expr + expr */
+ jpiSub, /* expr - expr */
+ jpiMul, /* expr * expr */
+ jpiDiv, /* expr / expr */
+ jpiMod, /* expr % expr */
+ jpiPlus, /* + expr */
+ jpiMinus, /* - expr */
+ jpiAnyArray, /* [*] */
+ jpiAnyKey, /* .* */
+ jpiIndexArray, /* [subscript, ...] */
+ jpiAny, /* .** */
+ jpiKey, /* .key */
+ jpiCurrent, /* @ */
+ jpiRoot, /* $ */
+ jpiVariable, /* $variable */
+ jpiFilter, /* ? (predicate) */
+ jpiExists, /* EXISTS (expr) predicate */
+ jpiType, /* .type() item method */
+ jpiSize, /* .size() item method */
+ jpiAbs, /* .abs() item method */
+ jpiFloor, /* .floor() item method */
+ jpiCeiling, /* .ceiling() item method */
+ jpiDouble, /* .double() item method */
+ jpiDatetime, /* .datetime() item method */
+ jpiKeyValue, /* .keyvalue() item method */
+ jpiSubscript, /* array subscript: 'expr' or 'expr TO expr' */
+ jpiLast, /* LAST array subscript */
+ jpiStartsWith, /* STARTS WITH predicate */
+ jpiLikeRegex, /* LIKE_REGEX predicate */
+} JsonPathItemType;
+
+/* XQuery regex mode flags for LIKE_REGEX predicate */
+#define JSP_REGEX_ICASE 0x01 /* i flag, case insensitive */
+#define JSP_REGEX_DOTALL 0x02 /* s flag, dot matches newline */
+#define JSP_REGEX_MLINE 0x04 /* m flag, ^/$ match at newlines */
+#define JSP_REGEX_WSPACE 0x08 /* x flag, ignore whitespace in pattern */
+#define JSP_REGEX_QUOTE 0x10 /* q flag, no special characters */
+
+/*
+ * Support functions to parse/construct binary value.
+ * Unlike many other representation of expression the first/main
+ * node is not an operation but left operand of expression. That
+ * allows to implement cheap follow-path descending in jsonb
+ * structure and then execute operator with right operand
+ */
+
+typedef struct JsonPathItem
+{
+ JsonPathItemType type;
+
+ /* position form base to next node */
+ int32 nextPos;
+
+ /*
+ * pointer into JsonPath value to current node, all positions of current
+ * are relative to this base
+ */
+ char *base;
+
+ union
+ {
+ /* classic operator with two operands: and, or etc */
+ struct
+ {
+ int32 left;
+ int32 right;
+ } args;
+
+ /* any unary operation */
+ int32 arg;
+
+ /* storage for jpiIndexArray: indexes of array */
+ struct
+ {
+ int32 nelems;
+ struct
+ {
+ int32 from;
+ int32 to;
+ } *elems;
+ } array;
+
+ /* jpiAny: levels */
+ struct
+ {
+ uint32 first;
+ uint32 last;
+ } anybounds;
+
+ struct
+ {
+ char *data; /* for bool, numeric and string/key */
+ int32 datalen; /* filled only for string/key */
+ } value;
+
+ struct
+ {
+ int32 expr;
+ char *pattern;
+ int32 patternlen;
+ uint32 flags;
+ } like_regex;
+ } content;
+} JsonPathItem;
+
+#define jspHasNext(jsp) ((jsp)->nextPos > 0)
+
+extern void jspInit(JsonPathItem *v, JsonPath *js);
+extern void jspInitByBuffer(JsonPathItem *v, char *base, int32 pos);
+extern bool jspGetNext(JsonPathItem *v, JsonPathItem *a);
+extern void jspGetArg(JsonPathItem *v, JsonPathItem *a);
+extern void jspGetLeftArg(JsonPathItem *v, JsonPathItem *a);
+extern void jspGetRightArg(JsonPathItem *v, JsonPathItem *a);
+extern Numeric jspGetNumeric(JsonPathItem *v);
+extern bool jspGetBool(JsonPathItem *v);
+extern char *jspGetString(JsonPathItem *v, int32 *len);
+extern bool jspGetArraySubscript(JsonPathItem *v, JsonPathItem *from,
+ JsonPathItem *to, int i);
+
+extern const char *jspOperationName(JsonPathItemType type);
+
+/*
+ * Parsing support data structures.
+ */
+
+typedef struct JsonPathParseItem JsonPathParseItem;
+
+struct JsonPathParseItem
+{
+ JsonPathItemType type;
+ JsonPathParseItem *next; /* next in path */
+
+ union
+ {
+
+ /* classic operator with two operands: and, or etc */
+ struct
+ {
+ JsonPathParseItem *left;
+ JsonPathParseItem *right;
+ } args;
+
+ /* any unary operation */
+ JsonPathParseItem *arg;
+
+ /* storage for jpiIndexArray: indexes of array */
+ struct
+ {
+ int nelems;
+ struct
+ {
+ JsonPathParseItem *from;
+ JsonPathParseItem *to;
+ } *elems;
+ } array;
+
+ /* jpiAny: levels */
+ struct
+ {
+ uint32 first;
+ uint32 last;
+ } anybounds;
+
+ struct
+ {
+ JsonPathParseItem *expr;
+ char *pattern; /* could not be not null-terminated */
+ uint32 patternlen;
+ uint32 flags;
+ } like_regex;
+
+ /* scalars */
+ Numeric numeric;
+ bool boolean;
+ struct
+ {
+ uint32 len;
+ char *val; /* could not be not null-terminated */
+ } string;
+ } value;
+};
+
+typedef struct JsonPathParseResult
+{
+ JsonPathParseItem *expr;
+ bool lax;
+} JsonPathParseResult;
+
+extern JsonPathParseResult *parsejsonpath(const char *str, int len,
+ struct Node *escontext);
+
+extern bool jspConvertRegexFlags(uint32 xflags, int *result,
+ struct Node *escontext);
+
+
+#endif
diff --git a/src/include/utils/logtape.h b/src/include/utils/logtape.h
new file mode 100644
index 0000000..5420a24
--- /dev/null
+++ b/src/include/utils/logtape.h
@@ -0,0 +1,77 @@
+/*-------------------------------------------------------------------------
+ *
+ * logtape.h
+ * Management of "logical tapes" within temporary files.
+ *
+ * See logtape.c for explanations.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/logtape.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef LOGTAPE_H
+#define LOGTAPE_H
+
+#include "storage/sharedfileset.h"
+
+/*
+ * LogicalTapeSet and LogicalTape are opaque types whose details are not
+ * known outside logtape.c.
+ */
+typedef struct LogicalTapeSet LogicalTapeSet;
+typedef struct LogicalTape LogicalTape;
+
+
+/*
+ * The approach tuplesort.c takes to parallel external sorts is that workers,
+ * whose state is almost the same as independent serial sorts, are made to
+ * produce a final materialized tape of sorted output in all cases. This is
+ * frozen, just like any case requiring a final materialized tape. However,
+ * there is one difference, which is that freezing will also export an
+ * underlying shared fileset BufFile for sharing. Freezing produces TapeShare
+ * metadata for the worker when this happens, which is passed along through
+ * shared memory to leader.
+ *
+ * The leader process can then pass an array of TapeShare metadata (one per
+ * worker participant) to LogicalTapeSetCreate(), alongside a handle to a
+ * shared fileset, which is sufficient to construct a new logical tapeset that
+ * consists of each of the tapes materialized by workers.
+ *
+ * Note that while logtape.c does create an empty leader tape at the end of the
+ * tapeset in the leader case, it can never be written to due to a restriction
+ * in the shared buffile infrastructure.
+ */
+typedef struct TapeShare
+{
+ /*
+ * Currently, all the leader process needs is the location of the
+ * materialized tape's first block.
+ */
+ long firstblocknumber;
+} TapeShare;
+
+/*
+ * prototypes for functions in logtape.c
+ */
+
+extern LogicalTapeSet *LogicalTapeSetCreate(bool preallocate,
+ SharedFileSet *fileset, int worker);
+extern void LogicalTapeClose(LogicalTape *lt);
+extern void LogicalTapeSetClose(LogicalTapeSet *lts);
+extern LogicalTape *LogicalTapeCreate(LogicalTapeSet *lts);
+extern LogicalTape *LogicalTapeImport(LogicalTapeSet *lts, int worker, TapeShare *shared);
+extern void LogicalTapeSetForgetFreeSpace(LogicalTapeSet *lts);
+extern size_t LogicalTapeRead(LogicalTape *lt, void *ptr, size_t size);
+extern void LogicalTapeWrite(LogicalTape *lt, const void *ptr, size_t size);
+extern void LogicalTapeRewindForRead(LogicalTape *lt, size_t buffer_size);
+extern void LogicalTapeFreeze(LogicalTape *lt, TapeShare *share);
+extern size_t LogicalTapeBackspace(LogicalTape *lt, size_t size);
+extern void LogicalTapeSeek(LogicalTape *lt, long blocknum, int offset);
+extern void LogicalTapeTell(LogicalTape *lt, long *blocknum, int *offset);
+extern long LogicalTapeSetBlocks(LogicalTapeSet *lts);
+
+#endif /* LOGTAPE_H */
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
new file mode 100644
index 0000000..4f5418b
--- /dev/null
+++ b/src/include/utils/lsyscache.h
@@ -0,0 +1,212 @@
+/*-------------------------------------------------------------------------
+ *
+ * lsyscache.h
+ * Convenience routines for common queries in the system catalog cache.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/lsyscache.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LSYSCACHE_H
+#define LSYSCACHE_H
+
+#include "access/attnum.h"
+#include "access/htup.h"
+#include "nodes/pg_list.h"
+
+/* avoid including subscripting.h here */
+struct SubscriptRoutines;
+
+/* Result list element for get_op_btree_interpretation */
+typedef struct OpBtreeInterpretation
+{
+ Oid opfamily_id; /* btree opfamily containing operator */
+ int strategy; /* its strategy number */
+ Oid oplefttype; /* declared left input datatype */
+ Oid oprighttype; /* declared right input datatype */
+} OpBtreeInterpretation;
+
+/* I/O function selector for get_type_io_data */
+typedef enum IOFuncSelector
+{
+ IOFunc_input,
+ IOFunc_output,
+ IOFunc_receive,
+ IOFunc_send
+} IOFuncSelector;
+
+/* Flag bits for get_attstatsslot */
+#define ATTSTATSSLOT_VALUES 0x01
+#define ATTSTATSSLOT_NUMBERS 0x02
+
+/* Result struct for get_attstatsslot */
+typedef struct AttStatsSlot
+{
+ /* Always filled: */
+ Oid staop; /* Actual staop for the found slot */
+ Oid stacoll; /* Actual collation for the found slot */
+ /* Filled if ATTSTATSSLOT_VALUES is specified: */
+ Oid valuetype; /* Actual datatype of the values */
+ Datum *values; /* slot's "values" array, or NULL if none */
+ int nvalues; /* length of values[], or 0 */
+ /* Filled if ATTSTATSSLOT_NUMBERS is specified: */
+ float4 *numbers; /* slot's "numbers" array, or NULL if none */
+ int nnumbers; /* length of numbers[], or 0 */
+
+ /* Remaining fields are private to get_attstatsslot/free_attstatsslot */
+ void *values_arr; /* palloc'd values array, if any */
+ void *numbers_arr; /* palloc'd numbers array, if any */
+} AttStatsSlot;
+
+/* Hook for plugins to get control in get_attavgwidth() */
+typedef int32 (*get_attavgwidth_hook_type) (Oid relid, AttrNumber attnum);
+extern PGDLLIMPORT get_attavgwidth_hook_type get_attavgwidth_hook;
+
+extern bool op_in_opfamily(Oid opno, Oid opfamily);
+extern int get_op_opfamily_strategy(Oid opno, Oid opfamily);
+extern Oid get_op_opfamily_sortfamily(Oid opno, Oid opfamily);
+extern void get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op,
+ int *strategy,
+ Oid *lefttype,
+ Oid *righttype);
+extern Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
+ int16 strategy);
+extern bool get_ordering_op_properties(Oid opno,
+ Oid *opfamily, Oid *opcintype, int16 *strategy);
+extern Oid get_equality_op_for_ordering_op(Oid opno, bool *reverse);
+extern Oid get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type);
+extern List *get_mergejoin_opfamilies(Oid opno);
+extern bool get_compatible_hash_operators(Oid opno,
+ Oid *lhs_opno, Oid *rhs_opno);
+extern bool get_op_hash_functions(Oid opno,
+ RegProcedure *lhs_procno, RegProcedure *rhs_procno);
+extern List *get_op_btree_interpretation(Oid opno);
+extern bool equality_ops_are_compatible(Oid opno1, Oid opno2);
+extern bool comparison_ops_are_compatible(Oid opno1, Oid opno2);
+extern Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype,
+ int16 procnum);
+extern char *get_attname(Oid relid, AttrNumber attnum, bool missing_ok);
+extern AttrNumber get_attnum(Oid relid, const char *attname);
+extern int get_attstattarget(Oid relid, AttrNumber attnum);
+extern char get_attgenerated(Oid relid, AttrNumber attnum);
+extern Oid get_atttype(Oid relid, AttrNumber attnum);
+extern void get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
+ Oid *typid, int32 *typmod, Oid *collid);
+extern Datum get_attoptions(Oid relid, int16 attnum);
+extern Oid get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok);
+extern char *get_collation_name(Oid colloid);
+extern bool get_collation_isdeterministic(Oid colloid);
+extern char *get_constraint_name(Oid conoid);
+extern Oid get_constraint_index(Oid conoid);
+extern char *get_language_name(Oid langoid, bool missing_ok);
+extern Oid get_opclass_family(Oid opclass);
+extern Oid get_opclass_input_type(Oid opclass);
+extern bool get_opclass_opfamily_and_input_type(Oid opclass,
+ Oid *opfamily, Oid *opcintype);
+extern RegProcedure get_opcode(Oid opno);
+extern char *get_opname(Oid opno);
+extern Oid get_op_rettype(Oid opno);
+extern void op_input_types(Oid opno, Oid *lefttype, Oid *righttype);
+extern bool op_mergejoinable(Oid opno, Oid inputtype);
+extern bool op_hashjoinable(Oid opno, Oid inputtype);
+extern bool op_strict(Oid opno);
+extern char op_volatile(Oid opno);
+extern Oid get_commutator(Oid opno);
+extern Oid get_negator(Oid opno);
+extern RegProcedure get_oprrest(Oid opno);
+extern RegProcedure get_oprjoin(Oid opno);
+extern char *get_func_name(Oid funcid);
+extern Oid get_func_namespace(Oid funcid);
+extern Oid get_func_rettype(Oid funcid);
+extern int get_func_nargs(Oid funcid);
+extern Oid get_func_signature(Oid funcid, Oid **argtypes, int *nargs);
+extern Oid get_func_variadictype(Oid funcid);
+extern bool get_func_retset(Oid funcid);
+extern bool func_strict(Oid funcid);
+extern char func_volatile(Oid funcid);
+extern char func_parallel(Oid funcid);
+extern char get_func_prokind(Oid funcid);
+extern bool get_func_leakproof(Oid funcid);
+extern RegProcedure get_func_support(Oid funcid);
+extern Oid get_relname_relid(const char *relname, Oid relnamespace);
+extern char *get_rel_name(Oid relid);
+extern Oid get_rel_namespace(Oid relid);
+extern Oid get_rel_type_id(Oid relid);
+extern char get_rel_relkind(Oid relid);
+extern bool get_rel_relispartition(Oid relid);
+extern Oid get_rel_tablespace(Oid relid);
+extern char get_rel_persistence(Oid relid);
+extern Oid get_transform_fromsql(Oid typid, Oid langid, List *trftypes);
+extern Oid get_transform_tosql(Oid typid, Oid langid, List *trftypes);
+extern bool get_typisdefined(Oid typid);
+extern int16 get_typlen(Oid typid);
+extern bool get_typbyval(Oid typid);
+extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval);
+extern void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
+ char *typalign);
+extern Oid getTypeIOParam(HeapTuple typeTuple);
+extern void get_type_io_data(Oid typid,
+ IOFuncSelector which_func,
+ int16 *typlen,
+ bool *typbyval,
+ char *typalign,
+ char *typdelim,
+ Oid *typioparam,
+ Oid *func);
+extern char get_typstorage(Oid typid);
+extern Node *get_typdefault(Oid typid);
+extern char get_typtype(Oid typid);
+extern bool type_is_rowtype(Oid typid);
+extern bool type_is_enum(Oid typid);
+extern bool type_is_range(Oid typid);
+extern bool type_is_multirange(Oid typid);
+extern void get_type_category_preferred(Oid typid,
+ char *typcategory,
+ bool *typispreferred);
+extern Oid get_typ_typrelid(Oid typid);
+extern Oid get_element_type(Oid typid);
+extern Oid get_array_type(Oid typid);
+extern Oid get_promoted_array_type(Oid typid);
+extern Oid get_base_element_type(Oid typid);
+extern void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam);
+extern void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena);
+extern void getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam);
+extern void getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena);
+extern Oid get_typmodin(Oid typid);
+extern Oid get_typcollation(Oid typid);
+extern bool type_is_collatable(Oid typid);
+extern RegProcedure get_typsubscript(Oid typid, Oid *typelemp);
+extern const struct SubscriptRoutines *getSubscriptingRoutines(Oid typid,
+ Oid *typelemp);
+extern Oid getBaseType(Oid typid);
+extern Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod);
+extern int32 get_typavgwidth(Oid typid, int32 typmod);
+extern int32 get_attavgwidth(Oid relid, AttrNumber attnum);
+extern bool get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple,
+ int reqkind, Oid reqop, int flags);
+extern void free_attstatsslot(AttStatsSlot *sslot);
+extern char *get_namespace_name(Oid nspid);
+extern char *get_namespace_name_or_temp(Oid nspid);
+extern Oid get_range_subtype(Oid rangeOid);
+extern Oid get_range_collation(Oid rangeOid);
+extern Oid get_range_multirange(Oid rangeOid);
+extern Oid get_multirange_range(Oid multirangeOid);
+extern Oid get_index_column_opclass(Oid index_oid, int attno);
+extern bool get_index_isreplident(Oid index_oid);
+extern bool get_index_isvalid(Oid index_oid);
+extern bool get_index_isclustered(Oid index_oid);
+extern Oid get_publication_oid(const char *pubname, bool missing_ok);
+extern char *get_publication_name(Oid pubid, bool missing_ok);
+extern Oid get_subscription_oid(const char *subname, bool missing_ok);
+extern char *get_subscription_name(Oid subid, bool missing_ok);
+
+#define type_is_array(typid) (get_element_type(typid) != InvalidOid)
+/* type_is_array_domain accepts both plain arrays and domains over arrays */
+#define type_is_array_domain(typid) (get_base_element_type(typid) != InvalidOid)
+
+#define TypeIsToastable(typid) (get_typstorage(typid) != TYPSTORAGE_PLAIN)
+
+#endif /* LSYSCACHE_H */
diff --git a/src/include/utils/memdebug.h b/src/include/utils/memdebug.h
new file mode 100644
index 0000000..804ed1f
--- /dev/null
+++ b/src/include/utils/memdebug.h
@@ -0,0 +1,82 @@
+/*-------------------------------------------------------------------------
+ *
+ * memdebug.h
+ * Memory debugging support.
+ *
+ * Currently, this file either wraps <valgrind/memcheck.h> or substitutes
+ * empty definitions for Valgrind client request macros we use.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/memdebug.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef MEMDEBUG_H
+#define MEMDEBUG_H
+
+#ifdef USE_VALGRIND
+#include <valgrind/memcheck.h>
+#else
+#define VALGRIND_CHECK_MEM_IS_DEFINED(addr, size) do {} while (0)
+#define VALGRIND_CREATE_MEMPOOL(context, redzones, zeroed) do {} while (0)
+#define VALGRIND_DESTROY_MEMPOOL(context) do {} while (0)
+#define VALGRIND_MAKE_MEM_DEFINED(addr, size) do {} while (0)
+#define VALGRIND_MAKE_MEM_NOACCESS(addr, size) do {} while (0)
+#define VALGRIND_MAKE_MEM_UNDEFINED(addr, size) do {} while (0)
+#define VALGRIND_MEMPOOL_ALLOC(context, addr, size) do {} while (0)
+#define VALGRIND_MEMPOOL_FREE(context, addr) do {} while (0)
+#define VALGRIND_MEMPOOL_CHANGE(context, optr, nptr, size) do {} while (0)
+#endif
+
+
+#ifdef CLOBBER_FREED_MEMORY
+
+/* Wipe freed memory for debugging purposes */
+static inline void
+wipe_mem(void *ptr, size_t size)
+{
+ VALGRIND_MAKE_MEM_UNDEFINED(ptr, size);
+ memset(ptr, 0x7F, size);
+ VALGRIND_MAKE_MEM_NOACCESS(ptr, size);
+}
+
+#endif /* CLOBBER_FREED_MEMORY */
+
+#ifdef MEMORY_CONTEXT_CHECKING
+
+static inline void
+set_sentinel(void *base, Size offset)
+{
+ char *ptr = (char *) base + offset;
+
+ VALGRIND_MAKE_MEM_UNDEFINED(ptr, 1);
+ *ptr = 0x7E;
+ VALGRIND_MAKE_MEM_NOACCESS(ptr, 1);
+}
+
+static inline bool
+sentinel_ok(const void *base, Size offset)
+{
+ const char *ptr = (const char *) base + offset;
+ bool ret;
+
+ VALGRIND_MAKE_MEM_DEFINED(ptr, 1);
+ ret = *ptr == 0x7E;
+ VALGRIND_MAKE_MEM_NOACCESS(ptr, 1);
+
+ return ret;
+}
+
+#endif /* MEMORY_CONTEXT_CHECKING */
+
+#ifdef RANDOMIZE_ALLOCATED_MEMORY
+
+void randomize_mem(char *ptr, size_t size);
+
+#endif /* RANDOMIZE_ALLOCATED_MEMORY */
+
+
+#endif /* MEMDEBUG_H */
diff --git a/src/include/utils/memutils.h b/src/include/utils/memutils.h
new file mode 100644
index 0000000..21640d6
--- /dev/null
+++ b/src/include/utils/memutils.h
@@ -0,0 +1,185 @@
+/*-------------------------------------------------------------------------
+ *
+ * memutils.h
+ * This file contains declarations for memory allocation utility
+ * functions. These are functions that are not quite widely used
+ * enough to justify going in utils/palloc.h, but are still part
+ * of the API of the memory management subsystem.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/memutils.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef MEMUTILS_H
+#define MEMUTILS_H
+
+#include "nodes/memnodes.h"
+
+
+/*
+ * MaxAllocSize, MaxAllocHugeSize
+ * Quasi-arbitrary limits on size of allocations.
+ *
+ * Note:
+ * There is no guarantee that smaller allocations will succeed, but
+ * larger requests will be summarily denied.
+ *
+ * palloc() enforces MaxAllocSize, chosen to correspond to the limiting size
+ * of varlena objects under TOAST. See VARSIZE_4B() and related macros in
+ * postgres.h. Many datatypes assume that any allocatable size can be
+ * represented in a varlena header. This limit also permits a caller to use
+ * an "int" variable for an index into or length of an allocation. Callers
+ * careful to avoid these hazards can access the higher limit with
+ * MemoryContextAllocHuge(). Both limits permit code to assume that it may
+ * compute twice an allocation's size without overflow.
+ */
+#define MaxAllocSize ((Size) 0x3fffffff) /* 1 gigabyte - 1 */
+
+#define AllocSizeIsValid(size) ((Size) (size) <= MaxAllocSize)
+
+/* Must be less than SIZE_MAX */
+#define MaxAllocHugeSize (SIZE_MAX / 2)
+
+#define InvalidAllocSize SIZE_MAX
+
+#define AllocHugeSizeIsValid(size) ((Size) (size) <= MaxAllocHugeSize)
+
+
+/*
+ * Standard top-level memory contexts.
+ *
+ * Only TopMemoryContext and ErrorContext are initialized by
+ * MemoryContextInit() itself.
+ */
+extern PGDLLIMPORT MemoryContext TopMemoryContext;
+extern PGDLLIMPORT MemoryContext ErrorContext;
+extern PGDLLIMPORT MemoryContext PostmasterContext;
+extern PGDLLIMPORT MemoryContext CacheMemoryContext;
+extern PGDLLIMPORT MemoryContext MessageContext;
+extern PGDLLIMPORT MemoryContext TopTransactionContext;
+extern PGDLLIMPORT MemoryContext CurTransactionContext;
+
+/* This is a transient link to the active portal's memory context: */
+extern PGDLLIMPORT MemoryContext PortalContext;
+
+/* Backwards compatibility macro */
+#define MemoryContextResetAndDeleteChildren(ctx) MemoryContextReset(ctx)
+
+
+/*
+ * Memory-context-type-independent functions in mcxt.c
+ */
+extern void MemoryContextInit(void);
+extern void MemoryContextReset(MemoryContext context);
+extern void MemoryContextDelete(MemoryContext context);
+extern void MemoryContextResetOnly(MemoryContext context);
+extern void MemoryContextResetChildren(MemoryContext context);
+extern void MemoryContextDeleteChildren(MemoryContext context);
+extern void MemoryContextSetIdentifier(MemoryContext context, const char *id);
+extern void MemoryContextSetParent(MemoryContext context,
+ MemoryContext new_parent);
+extern MemoryContext GetMemoryChunkContext(void *pointer);
+extern Size GetMemoryChunkSpace(void *pointer);
+extern MemoryContext MemoryContextGetParent(MemoryContext context);
+extern bool MemoryContextIsEmpty(MemoryContext context);
+extern Size MemoryContextMemAllocated(MemoryContext context, bool recurse);
+extern void MemoryContextStats(MemoryContext context);
+extern void MemoryContextStatsDetail(MemoryContext context, int max_children,
+ bool print_to_stderr);
+extern void MemoryContextAllowInCriticalSection(MemoryContext context,
+ bool allow);
+
+#ifdef MEMORY_CONTEXT_CHECKING
+extern void MemoryContextCheck(MemoryContext context);
+#endif
+
+/* Handy macro for copying and assigning context ID ... but note double eval */
+#define MemoryContextCopyAndSetIdentifier(cxt, id) \
+ MemoryContextSetIdentifier(cxt, MemoryContextStrdup(cxt, id))
+
+extern void HandleLogMemoryContextInterrupt(void);
+extern void ProcessLogMemoryContextInterrupt(void);
+
+/*
+ * Memory-context-type-specific functions
+ */
+
+/* aset.c */
+extern MemoryContext AllocSetContextCreateInternal(MemoryContext parent,
+ const char *name,
+ Size minContextSize,
+ Size initBlockSize,
+ Size maxBlockSize);
+
+/*
+ * This wrapper macro exists to check for non-constant strings used as context
+ * names; that's no longer supported. (Use MemoryContextSetIdentifier if you
+ * want to provide a variable identifier.)
+ */
+#ifdef HAVE__BUILTIN_CONSTANT_P
+#define AllocSetContextCreate(parent, name, ...) \
+ (StaticAssertExpr(__builtin_constant_p(name), \
+ "memory context names must be constant strings"), \
+ AllocSetContextCreateInternal(parent, name, __VA_ARGS__))
+#else
+#define AllocSetContextCreate \
+ AllocSetContextCreateInternal
+#endif
+
+/* slab.c */
+extern MemoryContext SlabContextCreate(MemoryContext parent,
+ const char *name,
+ Size blockSize,
+ Size chunkSize);
+
+/* generation.c */
+extern MemoryContext GenerationContextCreate(MemoryContext parent,
+ const char *name,
+ Size minContextSize,
+ Size initBlockSize,
+ Size maxBlockSize);
+
+/*
+ * Recommended default alloc parameters, suitable for "ordinary" contexts
+ * that might hold quite a lot of data.
+ */
+#define ALLOCSET_DEFAULT_MINSIZE 0
+#define ALLOCSET_DEFAULT_INITSIZE (8 * 1024)
+#define ALLOCSET_DEFAULT_MAXSIZE (8 * 1024 * 1024)
+#define ALLOCSET_DEFAULT_SIZES \
+ ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE
+
+/*
+ * Recommended alloc parameters for "small" contexts that are never expected
+ * to contain much data (for example, a context to contain a query plan).
+ */
+#define ALLOCSET_SMALL_MINSIZE 0
+#define ALLOCSET_SMALL_INITSIZE (1 * 1024)
+#define ALLOCSET_SMALL_MAXSIZE (8 * 1024)
+#define ALLOCSET_SMALL_SIZES \
+ ALLOCSET_SMALL_MINSIZE, ALLOCSET_SMALL_INITSIZE, ALLOCSET_SMALL_MAXSIZE
+
+/*
+ * Recommended alloc parameters for contexts that should start out small,
+ * but might sometimes grow big.
+ */
+#define ALLOCSET_START_SMALL_SIZES \
+ ALLOCSET_SMALL_MINSIZE, ALLOCSET_SMALL_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE
+
+
+/*
+ * Threshold above which a request in an AllocSet context is certain to be
+ * allocated separately (and thereby have constant allocation overhead).
+ * Few callers should be interested in this, but tuplesort/tuplestore need
+ * to know it.
+ */
+#define ALLOCSET_SEPARATE_THRESHOLD 8192
+
+#define SLAB_DEFAULT_BLOCK_SIZE (8 * 1024)
+#define SLAB_LARGE_BLOCK_SIZE (8 * 1024 * 1024)
+
+#endif /* MEMUTILS_H */
diff --git a/src/include/utils/memutils_internal.h b/src/include/utils/memutils_internal.h
new file mode 100644
index 0000000..2d107bb
--- /dev/null
+++ b/src/include/utils/memutils_internal.h
@@ -0,0 +1,136 @@
+/*-------------------------------------------------------------------------
+ *
+ * memutils_internal.h
+ * This file contains declarations for memory allocation utility
+ * functions for internal use.
+ *
+ *
+ * Portions Copyright (c) 2022-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/memutils_internal.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef MEMUTILS_INTERNAL_H
+#define MEMUTILS_INTERNAL_H
+
+#include "utils/memutils.h"
+
+/* These functions implement the MemoryContext API for AllocSet context. */
+extern void *AllocSetAlloc(MemoryContext context, Size size);
+extern void AllocSetFree(void *pointer);
+extern void *AllocSetRealloc(void *pointer, Size size);
+extern void AllocSetReset(MemoryContext context);
+extern void AllocSetDelete(MemoryContext context);
+extern MemoryContext AllocSetGetChunkContext(void *pointer);
+extern Size AllocSetGetChunkSpace(void *pointer);
+extern bool AllocSetIsEmpty(MemoryContext context);
+extern void AllocSetStats(MemoryContext context,
+ MemoryStatsPrintFunc printfunc, void *passthru,
+ MemoryContextCounters *totals,
+ bool print_to_stderr);
+#ifdef MEMORY_CONTEXT_CHECKING
+extern void AllocSetCheck(MemoryContext context);
+#endif
+
+/* These functions implement the MemoryContext API for Generation context. */
+extern void *GenerationAlloc(MemoryContext context, Size size);
+extern void GenerationFree(void *pointer);
+extern void *GenerationRealloc(void *pointer, Size size);
+extern void GenerationReset(MemoryContext context);
+extern void GenerationDelete(MemoryContext context);
+extern MemoryContext GenerationGetChunkContext(void *pointer);
+extern Size GenerationGetChunkSpace(void *pointer);
+extern bool GenerationIsEmpty(MemoryContext context);
+extern void GenerationStats(MemoryContext context,
+ MemoryStatsPrintFunc printfunc, void *passthru,
+ MemoryContextCounters *totals,
+ bool print_to_stderr);
+#ifdef MEMORY_CONTEXT_CHECKING
+extern void GenerationCheck(MemoryContext context);
+#endif
+
+
+/* These functions implement the MemoryContext API for Slab context. */
+extern void *SlabAlloc(MemoryContext context, Size size);
+extern void SlabFree(void *pointer);
+extern void *SlabRealloc(void *pointer, Size size);
+extern void SlabReset(MemoryContext context);
+extern void SlabDelete(MemoryContext context);
+extern MemoryContext SlabGetChunkContext(void *pointer);
+extern Size SlabGetChunkSpace(void *pointer);
+extern bool SlabIsEmpty(MemoryContext context);
+extern void SlabStats(MemoryContext context,
+ MemoryStatsPrintFunc printfunc, void *passthru,
+ MemoryContextCounters *totals,
+ bool print_to_stderr);
+#ifdef MEMORY_CONTEXT_CHECKING
+extern void SlabCheck(MemoryContext context);
+#endif
+
+/*
+ * These functions support the implementation of palloc_aligned() and are not
+ * part of a fully-fledged MemoryContext type.
+ */
+extern void AlignedAllocFree(void *pointer);
+extern void *AlignedAllocRealloc(void *pointer, Size size);
+extern MemoryContext AlignedAllocGetChunkContext(void *pointer);
+extern Size AlignedAllocGetChunkSpace(void *pointer);
+
+/*
+ * How many extra bytes do we need to request in order to ensure that we can
+ * align a pointer to 'alignto'. Since palloc'd pointers are already aligned
+ * to MAXIMUM_ALIGNOF we can subtract that amount. We also need to make sure
+ * there is enough space for the redirection MemoryChunk.
+ */
+#define PallocAlignedExtraBytes(alignto) \
+ ((alignto) + (sizeof(MemoryChunk) - MAXIMUM_ALIGNOF))
+
+/*
+ * MemoryContextMethodID
+ * A unique identifier for each MemoryContext implementation which
+ * indicates the index into the mcxt_methods[] array. See mcxt.c.
+ *
+ * For robust error detection, ensure that MemoryContextMethodID has a value
+ * for each possible bit-pattern of MEMORY_CONTEXT_METHODID_MASK, and make
+ * dummy entries for unused IDs in the mcxt_methods[] array. We also try
+ * to avoid using bit-patterns as valid IDs if they are likely to occur in
+ * garbage data, or if they could falsely match on chunks that are really from
+ * malloc not palloc. (We can't tell that for most malloc implementations,
+ * but it happens that glibc stores flag bits in the same place where we put
+ * the MemoryContextMethodID, so the possible values are predictable for it.)
+ */
+typedef enum MemoryContextMethodID
+{
+ MCTX_UNUSED1_ID, /* 000 occurs in never-used memory */
+ MCTX_UNUSED2_ID, /* glibc malloc'd chunks usually match 001 */
+ MCTX_UNUSED3_ID, /* glibc malloc'd chunks > 128kB match 010 */
+ MCTX_ASET_ID,
+ MCTX_GENERATION_ID,
+ MCTX_SLAB_ID,
+ MCTX_ALIGNED_REDIRECT_ID,
+ MCTX_UNUSED4_ID /* 111 occurs in wipe_mem'd memory */
+} MemoryContextMethodID;
+
+/*
+ * The number of bits that 8-byte memory chunk headers can use to encode the
+ * MemoryContextMethodID.
+ */
+#define MEMORY_CONTEXT_METHODID_BITS 3
+#define MEMORY_CONTEXT_METHODID_MASK \
+ ((((uint64) 1) << MEMORY_CONTEXT_METHODID_BITS) - 1)
+
+/*
+ * This routine handles the context-type-independent part of memory
+ * context creation. It's intended to be called from context-type-
+ * specific creation routines, and noplace else.
+ */
+extern void MemoryContextCreate(MemoryContext node,
+ NodeTag tag,
+ MemoryContextMethodID method_id,
+ MemoryContext parent,
+ const char *name);
+
+#endif /* MEMUTILS_INTERNAL_H */
diff --git a/src/include/utils/memutils_memorychunk.h b/src/include/utils/memutils_memorychunk.h
new file mode 100644
index 0000000..ffa9113
--- /dev/null
+++ b/src/include/utils/memutils_memorychunk.h
@@ -0,0 +1,237 @@
+/*-------------------------------------------------------------------------
+ *
+ * memutils_memorychunk.h
+ * Here we define a struct named MemoryChunk which implementations of
+ * MemoryContexts may use as a header for chunks of memory they allocate.
+ *
+ * MemoryChunk provides a lightweight header that a MemoryContext can use to
+ * store a reference back to the block which the given chunk is allocated on
+ * and also an additional 30-bits to store another value such as the size of
+ * the allocated chunk.
+ *
+ * Although MemoryChunks are used by each of our MemoryContexts, future
+ * implementations may choose to implement their own method for storing chunk
+ * headers. The only requirement is that the header ends with an 8-byte value
+ * which the least significant 3-bits of are set to the MemoryContextMethodID
+ * of the given context.
+ *
+ * By default, a MemoryChunk is 8 bytes in size, however, when
+ * MEMORY_CONTEXT_CHECKING is defined the header becomes 16 bytes in size due
+ * to the additional requested_size field. The MemoryContext may use this
+ * field for whatever they wish, but it is intended to be used for additional
+ * checks which are only done in MEMORY_CONTEXT_CHECKING builds.
+ *
+ * The MemoryChunk contains a uint64 field named 'hdrmask'. This field is
+ * used to encode 4 separate pieces of information. Starting with the least
+ * significant bits of 'hdrmask', the bit space is reserved as follows:
+ *
+ * 1. 3-bits to indicate the MemoryContextMethodID as defined by
+ * MEMORY_CONTEXT_METHODID_MASK
+ * 2. 1-bit to denote an "external" chunk (see below)
+ * 3. 30-bits reserved for the MemoryContext to use for anything it
+ * requires. Most MemoryContext likely want to store the size of the
+ * chunk here.
+ * 4. 30-bits for the number of bytes that must be subtracted from the chunk
+ * to obtain the address of the block that the chunk is stored on.
+ *
+ * In some cases, for example when memory allocations become large, it's
+ * possible fields 3 and 4 above are not large enough to store the values
+ * required for the chunk. In this case, the MemoryContext can choose to mark
+ * the chunk as "external" by calling the MemoryChunkSetHdrMaskExternal()
+ * function. When this is done, fields 3 and 4 are unavailable for use by the
+ * MemoryContext and it's up to the MemoryContext itself to devise its own
+ * method for getting the reference to the block.
+ *
+ * Interface:
+ *
+ * MemoryChunkSetHdrMask:
+ * Used to set up a non-external MemoryChunk.
+ *
+ * MemoryChunkSetHdrMaskExternal:
+ * Used to set up an externally managed MemoryChunk.
+ *
+ * MemoryChunkIsExternal:
+ * Determine if the given MemoryChunk is externally managed, i.e.
+ * MemoryChunkSetHdrMaskExternal() was called on the chunk.
+ *
+ * MemoryChunkGetValue:
+ * For non-external chunks, return the stored 30-bit value as it was set
+ * in the call to MemoryChunkSetHdrMask().
+ *
+ * MemoryChunkGetBlock:
+ * For non-external chunks, return a pointer to the block as it was set
+ * in the call to MemoryChunkSetHdrMask().
+ *
+ * Also exports:
+ * MEMORYCHUNK_MAX_VALUE
+ * MEMORYCHUNK_MAX_BLOCKOFFSET
+ * PointerGetMemoryChunk
+ * MemoryChunkGetPointer
+ *
+ * Portions Copyright (c) 2022-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/memutils_memorychunk.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef MEMUTILS_MEMORYCHUNK_H
+#define MEMUTILS_MEMORYCHUNK_H
+
+#include "utils/memutils_internal.h"
+
+ /*
+ * The maximum allowed value that MemoryContexts can store in the value
+ * field. Must be 1 less than a power of 2.
+ */
+#define MEMORYCHUNK_MAX_VALUE UINT64CONST(0x3FFFFFFF)
+
+/*
+ * The maximum distance in bytes that a MemoryChunk can be offset from the
+ * block that is storing the chunk. Must be 1 less than a power of 2.
+ */
+#define MEMORYCHUNK_MAX_BLOCKOFFSET UINT64CONST(0x3FFFFFFF)
+
+/* define the least significant base-0 bit of each portion of the hdrmask */
+#define MEMORYCHUNK_EXTERNAL_BASEBIT MEMORY_CONTEXT_METHODID_BITS
+#define MEMORYCHUNK_VALUE_BASEBIT (MEMORYCHUNK_EXTERNAL_BASEBIT + 1)
+#define MEMORYCHUNK_BLOCKOFFSET_BASEBIT (MEMORYCHUNK_VALUE_BASEBIT + 30)
+
+/*
+ * A magic number for storing in the free bits of an external chunk. This
+ * must mask out the bits used for storing the MemoryContextMethodID and the
+ * external bit.
+ */
+#define MEMORYCHUNK_MAGIC (UINT64CONST(0xB1A8DB858EB6EFBA) >> \
+ MEMORYCHUNK_VALUE_BASEBIT << \
+ MEMORYCHUNK_VALUE_BASEBIT)
+
+typedef struct MemoryChunk
+{
+#ifdef MEMORY_CONTEXT_CHECKING
+ Size requested_size;
+#endif
+
+ /* bitfield for storing details about the chunk */
+ uint64 hdrmask; /* must be last */
+} MemoryChunk;
+
+/* Get the MemoryChunk from the pointer */
+#define PointerGetMemoryChunk(p) \
+ ((MemoryChunk *) ((char *) (p) - sizeof(MemoryChunk)))
+/* Get the pointer from the MemoryChunk */
+#define MemoryChunkGetPointer(c) \
+ ((void *) ((char *) (c) + sizeof(MemoryChunk)))
+
+/* private macros for making the inline functions below more simple */
+#define HdrMaskIsExternal(hdrmask) \
+ ((hdrmask) & (((uint64) 1) << MEMORYCHUNK_EXTERNAL_BASEBIT))
+#define HdrMaskGetValue(hdrmask) \
+ (((hdrmask) >> MEMORYCHUNK_VALUE_BASEBIT) & MEMORYCHUNK_MAX_VALUE)
+
+/*
+ * We should have used up all the bits here, so the compiler is likely to
+ * optimize out the & MEMORYCHUNK_MAX_BLOCKOFFSET.
+ */
+#define HdrMaskBlockOffset(hdrmask) \
+ (((hdrmask) >> MEMORYCHUNK_BLOCKOFFSET_BASEBIT) & MEMORYCHUNK_MAX_BLOCKOFFSET)
+
+/* For external chunks only, check the magic number matches */
+#define HdrMaskCheckMagic(hdrmask) \
+ (MEMORYCHUNK_MAGIC == \
+ ((hdrmask) >> MEMORYCHUNK_VALUE_BASEBIT << MEMORYCHUNK_VALUE_BASEBIT))
+/*
+ * MemoryChunkSetHdrMask
+ * Store the given 'block', 'chunk_size' and 'methodid' in the given
+ * MemoryChunk.
+ *
+ * The number of bytes between 'block' and 'chunk' must be <=
+ * MEMORYCHUNK_MAX_BLOCKOFFSET.
+ * 'value' must be <= MEMORYCHUNK_MAX_VALUE.
+ */
+static inline void
+MemoryChunkSetHdrMask(MemoryChunk *chunk, void *block,
+ Size value, MemoryContextMethodID methodid)
+{
+ Size blockoffset = (char *) chunk - (char *) block;
+
+ Assert((char *) chunk >= (char *) block);
+ Assert(blockoffset <= MEMORYCHUNK_MAX_BLOCKOFFSET);
+ Assert(value <= MEMORYCHUNK_MAX_VALUE);
+ Assert((int) methodid <= MEMORY_CONTEXT_METHODID_MASK);
+
+ chunk->hdrmask = (((uint64) blockoffset) << MEMORYCHUNK_BLOCKOFFSET_BASEBIT) |
+ (((uint64) value) << MEMORYCHUNK_VALUE_BASEBIT) |
+ methodid;
+}
+
+/*
+ * MemoryChunkSetHdrMaskExternal
+ * Set 'chunk' as an externally managed chunk. Here we only record the
+ * MemoryContextMethodID and set the external chunk bit.
+ */
+static inline void
+MemoryChunkSetHdrMaskExternal(MemoryChunk *chunk,
+ MemoryContextMethodID methodid)
+{
+ Assert((int) methodid <= MEMORY_CONTEXT_METHODID_MASK);
+
+ chunk->hdrmask = MEMORYCHUNK_MAGIC | (((uint64) 1) << MEMORYCHUNK_EXTERNAL_BASEBIT) |
+ methodid;
+}
+
+/*
+ * MemoryChunkIsExternal
+ * Return true if 'chunk' is marked as external.
+ */
+static inline bool
+MemoryChunkIsExternal(MemoryChunk *chunk)
+{
+ /*
+ * External chunks should always store MEMORYCHUNK_MAGIC in the upper
+ * portion of the hdrmask, check that nothing has stomped on that.
+ */
+ Assert(!HdrMaskIsExternal(chunk->hdrmask) ||
+ HdrMaskCheckMagic(chunk->hdrmask));
+
+ return HdrMaskIsExternal(chunk->hdrmask);
+}
+
+/*
+ * MemoryChunkGetValue
+ * For non-external chunks, returns the value field as it was set in
+ * MemoryChunkSetHdrMask.
+ */
+static inline Size
+MemoryChunkGetValue(MemoryChunk *chunk)
+{
+ Assert(!HdrMaskIsExternal(chunk->hdrmask));
+
+ return HdrMaskGetValue(chunk->hdrmask);
+}
+
+/*
+ * MemoryChunkGetBlock
+ * For non-external chunks, returns the pointer to the block as was set
+ * in MemoryChunkSetHdrMask.
+ */
+static inline void *
+MemoryChunkGetBlock(MemoryChunk *chunk)
+{
+ Assert(!HdrMaskIsExternal(chunk->hdrmask));
+
+ return (void *) ((char *) chunk - HdrMaskBlockOffset(chunk->hdrmask));
+}
+
+/* cleanup all internal definitions */
+#undef MEMORYCHUNK_EXTERNAL_BASEBIT
+#undef MEMORYCHUNK_VALUE_BASEBIT
+#undef MEMORYCHUNK_BLOCKOFFSET_BASEBIT
+#undef MEMORYCHUNK_MAGIC
+#undef HdrMaskIsExternal
+#undef HdrMaskGetValue
+#undef HdrMaskBlockOffset
+#undef HdrMaskCheckMagic
+
+#endif /* MEMUTILS_MEMORYCHUNK_H */
diff --git a/src/include/utils/meson.build b/src/include/utils/meson.build
new file mode 100644
index 0000000..c212c40
--- /dev/null
+++ b/src/include/utils/meson.build
@@ -0,0 +1,60 @@
+# Copyright (c) 2022-2023, PostgreSQL Global Development Group
+
+errcodes = custom_target('errcodes',
+ input: files('../../backend/utils/errcodes.txt'),
+ output: ['errcodes.h'],
+ command: [
+ perl, files('../../backend/utils/generate-errcodes.pl'),
+ '--outfile', '@OUTPUT@',
+ '@INPUT@',
+ ],
+ install: true,
+ install_dir: dir_include_server / 'utils',
+)
+generated_headers += errcodes
+
+if dtrace.found()
+ probes_tmp = custom_target('probes.h.tmp',
+ input: files('../../backend/utils/probes.d'),
+ output: 'probes.h.tmp',
+ command: [dtrace, '-C', '-h', '-s', '@INPUT@', '-o', '@OUTPUT@'],
+ )
+ probes = custom_target('probes.h',
+ input: probes_tmp,
+ output: 'probes.h',
+ capture: true,
+ command: [sed, '-f', files('../../backend/utils/postprocess_dtrace.sed'), '@INPUT@'],
+ install: true,
+ install_dir: dir_include_server / 'utils',
+ )
+else
+ probes = custom_target('probes.h',
+ input: files('../../backend/utils/probes.d'),
+ output: 'probes.h',
+ capture: true,
+ command: [sed, '-f', files('../../backend/utils/Gen_dummy_probes.sed'), '@INPUT@'],
+ install: true,
+ install_dir: dir_include_server / 'utils',
+ )
+endif
+
+generated_backend_headers += probes
+
+fmgrtab_output = ['fmgroids.h', 'fmgrprotos.h', 'fmgrtab.c']
+fmgrtab_target = custom_target('fmgrtab',
+ input: '../catalog/pg_proc.dat',
+ output : fmgrtab_output,
+ depend_files: catalog_pm,
+ command: [perl, '-I', '@SOURCE_ROOT@/src/backend/catalog/', files('../../backend/utils/Gen_fmgrtab.pl'), '--include-path=@SOURCE_ROOT@/src/include', '--output=@OUTDIR@', '@INPUT@'],
+ install: true,
+ install_dir: [dir_include_server / 'utils', dir_include_server / 'utils', false],
+)
+
+generated_backend_headers += fmgrtab_target[0]
+generated_backend_headers += fmgrtab_target[1]
+
+# autoconf generates the file there, ensure we get a conflict
+generated_sources_ac += {
+ 'src/backend/utils': fmgrtab_output + ['errcodes.h', 'probes.h', 'fmgr-stamp'],
+ 'src/include/utils': ['header-stamp'],
+}
diff --git a/src/include/utils/multirangetypes.h b/src/include/utils/multirangetypes.h
new file mode 100644
index 0000000..7663d35
--- /dev/null
+++ b/src/include/utils/multirangetypes.h
@@ -0,0 +1,150 @@
+/*-------------------------------------------------------------------------
+ *
+ * multirangetypes.h
+ * Declarations for Postgres multirange types.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/multirangetypes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef MULTIRANGETYPES_H
+#define MULTIRANGETYPES_H
+
+#include "utils/rangetypes.h"
+#include "utils/typcache.h"
+
+
+/*
+ * Multiranges are varlena objects, so must meet the varlena convention that
+ * the first int32 of the object contains the total object size in bytes.
+ * Be sure to use VARSIZE() and SET_VARSIZE() to access it, though!
+ */
+typedef struct
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ Oid multirangetypid; /* multirange type's own OID */
+ uint32 rangeCount; /* the number of ranges */
+
+ /*
+ * Following the count are the range objects themselves, as ShortRangeType
+ * structs. Note that ranges are varlena too, depending on whether they
+ * have lower/upper bounds and because even their base types can be
+ * varlena. So we can't really index into this list.
+ */
+} MultirangeType;
+
+/* Use these macros in preference to accessing these fields directly */
+#define MultirangeTypeGetOid(mr) ((mr)->multirangetypid)
+#define MultirangeIsEmpty(mr) ((mr)->rangeCount == 0)
+
+/*
+ * fmgr functions for multirange type objects
+ */
+static inline MultirangeType *
+DatumGetMultirangeTypeP(Datum X)
+{
+ return (MultirangeType *) PG_DETOAST_DATUM(X);
+}
+
+static inline MultirangeType *
+DatumGetMultirangeTypePCopy(Datum X)
+{
+ return (MultirangeType *) PG_DETOAST_DATUM_COPY(X);
+}
+
+static inline Datum
+MultirangeTypePGetDatum(const MultirangeType *X)
+{
+ return PointerGetDatum(X);
+}
+
+#define PG_GETARG_MULTIRANGE_P(n) DatumGetMultirangeTypeP(PG_GETARG_DATUM(n))
+#define PG_GETARG_MULTIRANGE_P_COPY(n) DatumGetMultirangeTypePCopy(PG_GETARG_DATUM(n))
+#define PG_RETURN_MULTIRANGE_P(x) return MultirangeTypePGetDatum(x)
+
+/*
+ * prototypes for functions defined in multirangetypes.c
+ */
+
+/* internal versions of the above */
+extern bool multirange_eq_internal(TypeCacheEntry *rangetyp,
+ const MultirangeType *mr1,
+ const MultirangeType *mr2);
+extern bool multirange_ne_internal(TypeCacheEntry *rangetyp,
+ const MultirangeType *mr1,
+ const MultirangeType *mr2);
+extern bool multirange_contains_elem_internal(TypeCacheEntry *rangetyp,
+ const MultirangeType *mr,
+ Datum val);
+extern bool multirange_contains_range_internal(TypeCacheEntry *rangetyp,
+ const MultirangeType *mr,
+ const RangeType *r);
+extern bool range_contains_multirange_internal(TypeCacheEntry *rangetyp,
+ const RangeType *r,
+ const MultirangeType *mr);
+extern bool multirange_contains_multirange_internal(TypeCacheEntry *rangetyp,
+ const MultirangeType *mr1,
+ const MultirangeType *mr2);
+extern bool range_overlaps_multirange_internal(TypeCacheEntry *rangetyp,
+ const RangeType *r,
+ const MultirangeType *mr);
+extern bool multirange_overlaps_multirange_internal(TypeCacheEntry *rangetyp,
+ const MultirangeType *mr1,
+ const MultirangeType *mr2);
+extern bool range_overleft_multirange_internal(TypeCacheEntry *rangetyp,
+ const RangeType *r,
+ const MultirangeType *mr);
+extern bool range_overright_multirange_internal(TypeCacheEntry *rangetyp,
+ const RangeType *r,
+ const MultirangeType *mr);
+extern bool range_before_multirange_internal(TypeCacheEntry *rangetyp,
+ const RangeType *r,
+ const MultirangeType *mr);
+extern bool range_after_multirange_internal(TypeCacheEntry *rangetyp,
+ const RangeType *r,
+ const MultirangeType *mr);
+extern bool range_adjacent_multirange_internal(TypeCacheEntry *rangetyp,
+ const RangeType *r,
+ const MultirangeType *mr);
+extern bool multirange_before_multirange_internal(TypeCacheEntry *rangetyp,
+ const MultirangeType *mr1,
+ const MultirangeType *mr2);
+extern MultirangeType *multirange_minus_internal(Oid mltrngtypoid,
+ TypeCacheEntry *rangetyp,
+ int32 range_count1,
+ RangeType **ranges1,
+ int32 range_count2,
+ RangeType **ranges2);
+extern MultirangeType *multirange_intersect_internal(Oid mltrngtypoid,
+ TypeCacheEntry *rangetyp,
+ int32 range_count1,
+ RangeType **ranges1,
+ int32 range_count2,
+ RangeType **ranges2);
+
+/* assorted support functions */
+extern TypeCacheEntry *multirange_get_typcache(FunctionCallInfo fcinfo,
+ Oid mltrngtypid);
+extern void multirange_deserialize(TypeCacheEntry *rangetyp,
+ const MultirangeType *multirange,
+ int32 *range_count,
+ RangeType ***ranges);
+extern MultirangeType *make_multirange(Oid mltrngtypoid,
+ TypeCacheEntry *rangetyp,
+ int32 range_count, RangeType **ranges);
+extern MultirangeType *make_empty_multirange(Oid mltrngtypoid,
+ TypeCacheEntry *rangetyp);
+extern void multirange_get_bounds(TypeCacheEntry *rangetyp,
+ const MultirangeType *multirange,
+ uint32 i,
+ RangeBound *lower, RangeBound *upper);
+extern RangeType *multirange_get_range(TypeCacheEntry *rangetyp,
+ const MultirangeType *multirange, int i);
+extern RangeType *multirange_get_union_range(TypeCacheEntry *rangetyp,
+ const MultirangeType *mr);
+
+#endif /* MULTIRANGETYPES_H */
diff --git a/src/include/utils/numeric.h b/src/include/utils/numeric.h
new file mode 100644
index 0000000..08e4f8c
--- /dev/null
+++ b/src/include/utils/numeric.h
@@ -0,0 +1,105 @@
+/*-------------------------------------------------------------------------
+ *
+ * numeric.h
+ * Definitions for the exact numeric data type of Postgres
+ *
+ * Original coding 1998, Jan Wieck. Heavily revised 2003, Tom Lane.
+ *
+ * Copyright (c) 1998-2023, PostgreSQL Global Development Group
+ *
+ * src/include/utils/numeric.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _PG_NUMERIC_H_
+#define _PG_NUMERIC_H_
+
+#include "fmgr.h"
+
+/*
+ * Limits on the precision and scale specifiable in a NUMERIC typmod. The
+ * precision is strictly positive, but the scale may be positive or negative.
+ * A negative scale implies rounding before the decimal point.
+ *
+ * Note that the minimum display scale defined below is zero --- we always
+ * display all digits before the decimal point, even when the scale is
+ * negative.
+ *
+ * Note that the implementation limits on the precision and display scale of a
+ * numeric value are much larger --- beware of what you use these for!
+ */
+#define NUMERIC_MAX_PRECISION 1000
+
+#define NUMERIC_MIN_SCALE (-1000)
+#define NUMERIC_MAX_SCALE 1000
+
+/*
+ * Internal limits on the scales chosen for calculation results
+ */
+#define NUMERIC_MAX_DISPLAY_SCALE NUMERIC_MAX_PRECISION
+#define NUMERIC_MIN_DISPLAY_SCALE 0
+
+#define NUMERIC_MAX_RESULT_SCALE (NUMERIC_MAX_PRECISION * 2)
+
+/*
+ * For inherently inexact calculations such as division and square root,
+ * we try to get at least this many significant digits; the idea is to
+ * deliver a result no worse than float8 would.
+ */
+#define NUMERIC_MIN_SIG_DIGITS 16
+
+/* The actual contents of Numeric are private to numeric.c */
+struct NumericData;
+typedef struct NumericData *Numeric;
+
+/*
+ * fmgr interface macros
+ */
+
+static inline Numeric
+DatumGetNumeric(Datum X)
+{
+ return (Numeric) PG_DETOAST_DATUM(X);
+}
+
+static inline Numeric
+DatumGetNumericCopy(Datum X)
+{
+ return (Numeric) PG_DETOAST_DATUM_COPY(X);
+}
+
+static inline Datum
+NumericGetDatum(Numeric X)
+{
+ return PointerGetDatum(X);
+}
+
+#define PG_GETARG_NUMERIC(n) DatumGetNumeric(PG_GETARG_DATUM(n))
+#define PG_GETARG_NUMERIC_COPY(n) DatumGetNumericCopy(PG_GETARG_DATUM(n))
+#define PG_RETURN_NUMERIC(x) return NumericGetDatum(x)
+
+/*
+ * Utility functions in numeric.c
+ */
+extern bool numeric_is_nan(Numeric num);
+extern bool numeric_is_inf(Numeric num);
+extern int32 numeric_maximum_size(int32 typmod);
+extern char *numeric_out_sci(Numeric num, int scale);
+extern char *numeric_normalize(Numeric num);
+
+extern Numeric int64_to_numeric(int64 val);
+extern Numeric int64_div_fast_to_numeric(int64 val1, int log10val2);
+
+extern Numeric numeric_add_opt_error(Numeric num1, Numeric num2,
+ bool *have_error);
+extern Numeric numeric_sub_opt_error(Numeric num1, Numeric num2,
+ bool *have_error);
+extern Numeric numeric_mul_opt_error(Numeric num1, Numeric num2,
+ bool *have_error);
+extern Numeric numeric_div_opt_error(Numeric num1, Numeric num2,
+ bool *have_error);
+extern Numeric numeric_mod_opt_error(Numeric num1, Numeric num2,
+ bool *have_error);
+extern int32 numeric_int4_opt_error(Numeric num, bool *have_error);
+
+#endif /* _PG_NUMERIC_H_ */
diff --git a/src/include/utils/old_snapshot.h b/src/include/utils/old_snapshot.h
new file mode 100644
index 0000000..f1978a2
--- /dev/null
+++ b/src/include/utils/old_snapshot.h
@@ -0,0 +1,75 @@
+/*-------------------------------------------------------------------------
+ *
+ * old_snapshot.h
+ * Data structures for 'snapshot too old'
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/utils/old_snapshot.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef OLD_SNAPSHOT_H
+#define OLD_SNAPSHOT_H
+
+#include "datatype/timestamp.h"
+#include "storage/s_lock.h"
+
+/*
+ * Structure for dealing with old_snapshot_threshold implementation.
+ */
+typedef struct OldSnapshotControlData
+{
+ /*
+ * Variables for old snapshot handling are shared among processes and are
+ * only allowed to move forward.
+ */
+ slock_t mutex_current; /* protect current_timestamp */
+ TimestampTz current_timestamp; /* latest snapshot timestamp */
+ slock_t mutex_latest_xmin; /* protect latest_xmin and next_map_update */
+ TransactionId latest_xmin; /* latest snapshot xmin */
+ TimestampTz next_map_update; /* latest snapshot valid up to */
+ slock_t mutex_threshold; /* protect threshold fields */
+ TimestampTz threshold_timestamp; /* earlier snapshot is old */
+ TransactionId threshold_xid; /* earlier xid may be gone */
+
+ /*
+ * Keep one xid per minute for old snapshot error handling.
+ *
+ * Use a circular buffer with a head offset, a count of entries currently
+ * used, and a timestamp corresponding to the xid at the head offset. A
+ * count_used value of zero means that there are no times stored; a
+ * count_used value of OLD_SNAPSHOT_TIME_MAP_ENTRIES means that the buffer
+ * is full and the head must be advanced to add new entries. Use
+ * timestamps aligned to minute boundaries, since that seems less
+ * surprising than aligning based on the first usage timestamp. The
+ * latest bucket is effectively stored within latest_xmin. The circular
+ * buffer is updated when we get a new xmin value that doesn't fall into
+ * the same interval.
+ *
+ * It is OK if the xid for a given time slot is from earlier than
+ * calculated by adding the number of minutes corresponding to the
+ * (possibly wrapped) distance from the head offset to the time of the
+ * head entry, since that just results in the vacuuming of old tuples
+ * being slightly less aggressive. It would not be OK for it to be off in
+ * the other direction, since it might result in vacuuming tuples that are
+ * still expected to be there.
+ *
+ * Use of an SLRU was considered but not chosen because it is more
+ * heavyweight than is needed for this, and would probably not be any less
+ * code to implement.
+ *
+ * Persistence is not needed.
+ */
+ int head_offset; /* subscript of oldest tracked time */
+ TimestampTz head_timestamp; /* time corresponding to head xid */
+ int count_used; /* how many slots are in use */
+ TransactionId xid_by_minute[FLEXIBLE_ARRAY_MEMBER];
+} OldSnapshotControlData;
+
+extern PGDLLIMPORT volatile OldSnapshotControlData *oldSnapshotControl;
+
+#endif
diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h
new file mode 100644
index 0000000..d1146c1
--- /dev/null
+++ b/src/include/utils/palloc.h
@@ -0,0 +1,165 @@
+/*-------------------------------------------------------------------------
+ *
+ * palloc.h
+ * POSTGRES memory allocator definitions.
+ *
+ * This file contains the basic memory allocation interface that is
+ * needed by almost every backend module. It is included directly by
+ * postgres.h, so the definitions here are automatically available
+ * everywhere. Keep it lean!
+ *
+ * Memory allocation occurs within "contexts". Every chunk obtained from
+ * palloc()/MemoryContextAlloc() is allocated within a specific context.
+ * The entire contents of a context can be freed easily and quickly by
+ * resetting or deleting the context --- this is both faster and less
+ * prone to memory-leakage bugs than releasing chunks individually.
+ * We organize contexts into context trees to allow fine-grain control
+ * over chunk lifetime while preserving the certainty that we will free
+ * everything that should be freed. See utils/mmgr/README for more info.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/palloc.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PALLOC_H
+#define PALLOC_H
+
+/*
+ * Type MemoryContextData is declared in nodes/memnodes.h. Most users
+ * of memory allocation should just treat it as an abstract type, so we
+ * do not provide the struct contents here.
+ */
+typedef struct MemoryContextData *MemoryContext;
+
+/*
+ * A memory context can have callback functions registered on it. Any such
+ * function will be called once just before the context is next reset or
+ * deleted. The MemoryContextCallback struct describing such a callback
+ * typically would be allocated within the context itself, thereby avoiding
+ * any need to manage it explicitly (the reset/delete action will free it).
+ */
+typedef void (*MemoryContextCallbackFunction) (void *arg);
+
+typedef struct MemoryContextCallback
+{
+ MemoryContextCallbackFunction func; /* function to call */
+ void *arg; /* argument to pass it */
+ struct MemoryContextCallback *next; /* next in list of callbacks */
+} MemoryContextCallback;
+
+/*
+ * CurrentMemoryContext is the default allocation context for palloc().
+ * Avoid accessing it directly! Instead, use MemoryContextSwitchTo()
+ * to change the setting.
+ */
+extern PGDLLIMPORT MemoryContext CurrentMemoryContext;
+
+/*
+ * Flags for MemoryContextAllocExtended.
+ */
+#define MCXT_ALLOC_HUGE 0x01 /* allow huge allocation (> 1 GB) */
+#define MCXT_ALLOC_NO_OOM 0x02 /* no failure if out-of-memory */
+#define MCXT_ALLOC_ZERO 0x04 /* zero allocated memory */
+
+/*
+ * Fundamental memory-allocation operations (more are in utils/memutils.h)
+ */
+extern void *MemoryContextAlloc(MemoryContext context, Size size);
+extern void *MemoryContextAllocZero(MemoryContext context, Size size);
+extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size);
+extern void *MemoryContextAllocExtended(MemoryContext context,
+ Size size, int flags);
+extern void *MemoryContextAllocAligned(MemoryContext context,
+ Size size, Size alignto, int flags);
+
+extern void *palloc(Size size);
+extern void *palloc0(Size size);
+extern void *palloc_extended(Size size, int flags);
+extern void *palloc_aligned(Size size, Size alignto, int flags);
+extern pg_nodiscard void *repalloc(void *pointer, Size size);
+extern pg_nodiscard void *repalloc_extended(void *pointer,
+ Size size, int flags);
+extern pg_nodiscard void *repalloc0(void *pointer, Size oldsize, Size size);
+extern void pfree(void *pointer);
+
+/*
+ * Variants with easier notation and more type safety
+ */
+
+/*
+ * Allocate space for one object of type "type"
+ */
+#define palloc_object(type) ((type *) palloc(sizeof(type)))
+#define palloc0_object(type) ((type *) palloc0(sizeof(type)))
+
+/*
+ * Allocate space for "count" objects of type "type"
+ */
+#define palloc_array(type, count) ((type *) palloc(sizeof(type) * (count)))
+#define palloc0_array(type, count) ((type *) palloc0(sizeof(type) * (count)))
+
+/*
+ * Change size of allocation pointed to by "pointer" to have space for "count"
+ * objects of type "type"
+ */
+#define repalloc_array(pointer, type, count) ((type *) repalloc(pointer, sizeof(type) * (count)))
+#define repalloc0_array(pointer, type, oldcount, count) ((type *) repalloc0(pointer, sizeof(type) * (oldcount), sizeof(type) * (count)))
+
+/*
+ * The result of palloc() is always word-aligned, so we can skip testing
+ * alignment of the pointer when deciding which MemSet variant to use.
+ * Note that this variant does not offer any advantage, and should not be
+ * used, unless its "sz" argument is a compile-time constant; therefore, the
+ * issue that it evaluates the argument multiple times isn't a problem in
+ * practice.
+ */
+#define palloc0fast(sz) \
+ ( MemSetTest(0, sz) ? \
+ MemoryContextAllocZeroAligned(CurrentMemoryContext, sz) : \
+ MemoryContextAllocZero(CurrentMemoryContext, sz) )
+
+/* Higher-limit allocators. */
+extern void *MemoryContextAllocHuge(MemoryContext context, Size size);
+extern pg_nodiscard void *repalloc_huge(void *pointer, Size size);
+
+/*
+ * Although this header file is nominally backend-only, certain frontend
+ * programs like pg_controldata include it via postgres.h. For some compilers
+ * it's necessary to hide the inline definition of MemoryContextSwitchTo in
+ * this scenario; hence the #ifndef FRONTEND.
+ */
+
+#ifndef FRONTEND
+static inline MemoryContext
+MemoryContextSwitchTo(MemoryContext context)
+{
+ MemoryContext old = CurrentMemoryContext;
+
+ CurrentMemoryContext = context;
+ return old;
+}
+#endif /* FRONTEND */
+
+/* Registration of memory context reset/delete callbacks */
+extern void MemoryContextRegisterResetCallback(MemoryContext context,
+ MemoryContextCallback *cb);
+
+/*
+ * These are like standard strdup() except the copied string is
+ * allocated in a context, not with malloc().
+ */
+extern char *MemoryContextStrdup(MemoryContext context, const char *string);
+extern char *pstrdup(const char *in);
+extern char *pnstrdup(const char *in, Size len);
+
+extern char *pchomp(const char *in);
+
+/* sprintf into a palloc'd buffer --- these are in psprintf.c */
+extern char *psprintf(const char *fmt,...) pg_attribute_printf(1, 2);
+extern size_t pvsnprintf(char *buf, size_t len, const char *fmt, va_list args) pg_attribute_printf(3, 0);
+
+#endif /* PALLOC_H */
diff --git a/src/include/utils/partcache.h b/src/include/utils/partcache.h
new file mode 100644
index 0000000..eb9bc4b
--- /dev/null
+++ b/src/include/utils/partcache.h
@@ -0,0 +1,103 @@
+/*-------------------------------------------------------------------------
+ *
+ * partcache.h
+ *
+ * Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ *
+ * src/include/utils/partcache.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARTCACHE_H
+#define PARTCACHE_H
+
+#include "access/attnum.h"
+#include "fmgr.h"
+#include "nodes/parsenodes.h"
+#include "nodes/pg_list.h"
+#include "nodes/primnodes.h"
+#include "partitioning/partdefs.h"
+#include "utils/relcache.h"
+
+/*
+ * Information about the partition key of a relation
+ */
+typedef struct PartitionKeyData
+{
+ PartitionStrategy strategy; /* partitioning strategy */
+ int16 partnatts; /* number of columns in the partition key */
+ AttrNumber *partattrs; /* attribute numbers of columns in the
+ * partition key or 0 if it's an expr */
+ List *partexprs; /* list of expressions in the partitioning
+ * key, one for each zero-valued partattrs */
+
+ Oid *partopfamily; /* OIDs of operator families */
+ Oid *partopcintype; /* OIDs of opclass declared input data types */
+ FmgrInfo *partsupfunc; /* lookup info for support funcs */
+
+ /* Partitioning collation per attribute */
+ Oid *partcollation;
+
+ /* Type information per attribute */
+ Oid *parttypid;
+ int32 *parttypmod;
+ int16 *parttyplen;
+ bool *parttypbyval;
+ char *parttypalign;
+ Oid *parttypcoll;
+} PartitionKeyData;
+
+
+extern PartitionKey RelationGetPartitionKey(Relation rel);
+extern List *RelationGetPartitionQual(Relation rel);
+extern Expr *get_partition_qual_relid(Oid relid);
+
+/*
+ * PartitionKey inquiry functions
+ */
+static inline int
+get_partition_strategy(PartitionKey key)
+{
+ return key->strategy;
+}
+
+static inline int
+get_partition_natts(PartitionKey key)
+{
+ return key->partnatts;
+}
+
+static inline List *
+get_partition_exprs(PartitionKey key)
+{
+ return key->partexprs;
+}
+
+/*
+ * PartitionKey inquiry functions - one column
+ */
+static inline int16
+get_partition_col_attnum(PartitionKey key, int col)
+{
+ return key->partattrs[col];
+}
+
+static inline Oid
+get_partition_col_typid(PartitionKey key, int col)
+{
+ return key->parttypid[col];
+}
+
+static inline int32
+get_partition_col_typmod(PartitionKey key, int col)
+{
+ return key->parttypmod[col];
+}
+
+static inline Oid
+get_partition_col_collation(PartitionKey key, int col)
+{
+ return key->partcollation[col];
+}
+
+#endif /* PARTCACHE_H */
diff --git a/src/include/utils/pg_crc.h b/src/include/utils/pg_crc.h
new file mode 100644
index 0000000..a0369c6
--- /dev/null
+++ b/src/include/utils/pg_crc.h
@@ -0,0 +1,107 @@
+/*
+ * pg_crc.h
+ *
+ * PostgreSQL CRC support
+ *
+ * See Ross Williams' excellent introduction
+ * A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS, available from
+ * http://ross.net/crc/ or several other net sites.
+ *
+ * We have three slightly different variants of a 32-bit CRC calculation:
+ * CRC-32C (Castagnoli polynomial), CRC-32 (Ethernet polynomial), and a legacy
+ * CRC-32 version that uses the lookup table in a funny way. They all consist
+ * of four macros:
+ *
+ * INIT_<variant>(crc)
+ * Initialize a CRC accumulator
+ *
+ * COMP_<variant>(crc, data, len)
+ * Accumulate some (more) bytes into a CRC
+ *
+ * FIN_<variant>(crc)
+ * Finish a CRC calculation
+ *
+ * EQ_<variant>(c1, c2)
+ * Check for equality of two CRCs.
+ *
+ * The CRC-32C variant is in port/pg_crc32c.h.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/pg_crc.h
+ */
+#ifndef PG_CRC_H
+#define PG_CRC_H
+
+typedef uint32 pg_crc32;
+
+/*
+ * CRC-32, the same used e.g. in Ethernet.
+ *
+ * This is currently only used in ltree and hstore contrib modules. It uses
+ * the same lookup table as the legacy algorithm below. New code should
+ * use the Castagnoli version instead.
+ */
+#define INIT_TRADITIONAL_CRC32(crc) ((crc) = 0xFFFFFFFF)
+#define FIN_TRADITIONAL_CRC32(crc) ((crc) ^= 0xFFFFFFFF)
+#define COMP_TRADITIONAL_CRC32(crc, data, len) \
+ COMP_CRC32_NORMAL_TABLE(crc, data, len, pg_crc32_table)
+#define EQ_TRADITIONAL_CRC32(c1, c2) ((c1) == (c2))
+
+/* Sarwate's algorithm, for use with a "normal" lookup table */
+#define COMP_CRC32_NORMAL_TABLE(crc, data, len, table) \
+do { \
+ const unsigned char *__data = (const unsigned char *) (data); \
+ uint32 __len = (len); \
+\
+ while (__len-- > 0) \
+ { \
+ int __tab_index = ((int) (crc) ^ *__data++) & 0xFF; \
+ (crc) = table[__tab_index] ^ ((crc) >> 8); \
+ } \
+} while (0)
+
+/*
+ * The CRC algorithm used for WAL et al in pre-9.5 versions.
+ *
+ * This closely resembles the normal CRC-32 algorithm, but is subtly
+ * different. Using Williams' terms, we use the "normal" table, but with
+ * "reflected" code. That's bogus, but it was like that for years before
+ * anyone noticed. It does not correspond to any polynomial in a normal CRC
+ * algorithm, so it's not clear what the error-detection properties of this
+ * algorithm actually are.
+ *
+ * We still need to carry this around because it is used in a few on-disk
+ * structures that need to be pg_upgradeable. It should not be used in new
+ * code.
+ */
+#define INIT_LEGACY_CRC32(crc) ((crc) = 0xFFFFFFFF)
+#define FIN_LEGACY_CRC32(crc) ((crc) ^= 0xFFFFFFFF)
+#define COMP_LEGACY_CRC32(crc, data, len) \
+ COMP_CRC32_REFLECTED_TABLE(crc, data, len, pg_crc32_table)
+#define EQ_LEGACY_CRC32(c1, c2) ((c1) == (c2))
+
+/*
+ * Sarwate's algorithm, for use with a "reflected" lookup table (but in the
+ * legacy algorithm, we actually use it on a "normal" table, see above)
+ */
+#define COMP_CRC32_REFLECTED_TABLE(crc, data, len, table) \
+do { \
+ const unsigned char *__data = (const unsigned char *) (data); \
+ uint32 __len = (len); \
+\
+ while (__len-- > 0) \
+ { \
+ int __tab_index = ((int) ((crc) >> 24) ^ *__data++) & 0xFF; \
+ (crc) = table[__tab_index] ^ ((crc) << 8); \
+ } \
+} while (0)
+
+/*
+ * Constant table for the CRC-32 polynomials. The same table is used by both
+ * the normal and traditional variants.
+ */
+extern PGDLLIMPORT const uint32 pg_crc32_table[256];
+
+#endif /* PG_CRC_H */
diff --git a/src/include/utils/pg_locale.h b/src/include/utils/pg_locale.h
new file mode 100644
index 0000000..e2a7243
--- /dev/null
+++ b/src/include/utils/pg_locale.h
@@ -0,0 +1,135 @@
+/*-----------------------------------------------------------------------
+ *
+ * PostgreSQL locale utilities
+ *
+ * src/include/utils/pg_locale.h
+ *
+ * Copyright (c) 2002-2023, PostgreSQL Global Development Group
+ *
+ *-----------------------------------------------------------------------
+ */
+
+#ifndef _PG_LOCALE_
+#define _PG_LOCALE_
+
+#if defined(LOCALE_T_IN_XLOCALE) || defined(WCSTOMBS_L_IN_XLOCALE)
+#include <xlocale.h>
+#endif
+#ifdef USE_ICU
+#include <unicode/ucol.h>
+#endif
+
+#ifdef USE_ICU
+/*
+ * ucol_strcollUTF8() was introduced in ICU 50, but it is buggy before ICU 53.
+ * (see
+ * <https://www.postgresql.org/message-id/flat/f1438ec6-22aa-4029-9a3b-26f79d330e72%40manitou-mail.org>)
+ */
+#if U_ICU_VERSION_MAJOR_NUM >= 53
+#define HAVE_UCOL_STRCOLLUTF8 1
+#else
+#undef HAVE_UCOL_STRCOLLUTF8
+#endif
+#endif
+
+/* use for libc locale names */
+#define LOCALE_NAME_BUFLEN 128
+
+/* GUC settings */
+extern PGDLLIMPORT char *locale_messages;
+extern PGDLLIMPORT char *locale_monetary;
+extern PGDLLIMPORT char *locale_numeric;
+extern PGDLLIMPORT char *locale_time;
+extern PGDLLIMPORT int icu_validation_level;
+
+/* lc_time localization cache */
+extern PGDLLIMPORT char *localized_abbrev_days[];
+extern PGDLLIMPORT char *localized_full_days[];
+extern PGDLLIMPORT char *localized_abbrev_months[];
+extern PGDLLIMPORT char *localized_full_months[];
+
+/* is the databases's LC_CTYPE the C locale? */
+extern PGDLLIMPORT bool database_ctype_is_c;
+
+extern bool check_locale(int category, const char *locale, char **canonname);
+extern char *pg_perm_setlocale(int category, const char *locale);
+
+extern bool lc_collate_is_c(Oid collation);
+extern bool lc_ctype_is_c(Oid collation);
+
+/*
+ * Return the POSIX lconv struct (contains number/money formatting
+ * information) with locale information for all categories.
+ */
+extern struct lconv *PGLC_localeconv(void);
+
+extern void cache_locale_time(void);
+
+
+/*
+ * We define our own wrapper around locale_t so we can keep the same
+ * function signatures for all builds, while not having to create a
+ * fake version of the standard type locale_t in the global namespace.
+ * pg_locale_t is occasionally checked for truth, so make it a pointer.
+ */
+struct pg_locale_struct
+{
+ char provider;
+ bool deterministic;
+ union
+ {
+#ifdef HAVE_LOCALE_T
+ locale_t lt;
+#endif
+#ifdef USE_ICU
+ struct
+ {
+ const char *locale;
+ UCollator *ucol;
+ } icu;
+#endif
+ int dummy; /* in case we have neither LOCALE_T nor ICU */
+ } info;
+};
+
+typedef struct pg_locale_struct *pg_locale_t;
+
+extern PGDLLIMPORT struct pg_locale_struct default_locale;
+
+extern void make_icu_collator(const char *iculocstr,
+ const char *icurules,
+ struct pg_locale_struct *resultp);
+
+extern bool pg_locale_deterministic(pg_locale_t locale);
+extern pg_locale_t pg_newlocale_from_collation(Oid collid);
+
+extern char *get_collation_actual_version(char collprovider, const char *collcollate);
+extern int pg_strcoll(const char *arg1, const char *arg2, pg_locale_t locale);
+extern int pg_strncoll(const char *arg1, size_t len1,
+ const char *arg2, size_t len2, pg_locale_t locale);
+extern bool pg_strxfrm_enabled(pg_locale_t locale);
+extern size_t pg_strxfrm(char *dest, const char *src, size_t destsize,
+ pg_locale_t locale);
+extern size_t pg_strnxfrm(char *dest, size_t destsize, const char *src,
+ size_t srclen, pg_locale_t locale);
+extern bool pg_strxfrm_prefix_enabled(pg_locale_t locale);
+extern size_t pg_strxfrm_prefix(char *dest, const char *src, size_t destsize,
+ pg_locale_t locale);
+extern size_t pg_strnxfrm_prefix(char *dest, size_t destsize, const char *src,
+ size_t srclen, pg_locale_t locale);
+
+extern void icu_validate_locale(const char *loc_str);
+extern char *icu_language_tag(const char *loc_str, int elevel);
+
+#ifdef USE_ICU
+extern int32_t icu_to_uchar(UChar **buff_uchar, const char *buff, size_t nbytes);
+extern int32_t icu_from_uchar(char **result, const UChar *buff_uchar, int32_t len_uchar);
+#endif
+
+/* These functions convert from/to libc's wchar_t, *not* pg_wchar_t */
+extern size_t wchar2char(char *to, const wchar_t *from, size_t tolen,
+ pg_locale_t locale);
+extern size_t char2wchar(wchar_t *to, size_t tolen,
+ const char *from, size_t fromlen, pg_locale_t locale);
+
+#endif /* _PG_LOCALE_ */
diff --git a/src/include/utils/pg_lsn.h b/src/include/utils/pg_lsn.h
new file mode 100644
index 0000000..7bda26b
--- /dev/null
+++ b/src/include/utils/pg_lsn.h
@@ -0,0 +1,38 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_lsn.h
+ * Declarations for operations on log sequence numbers (LSNs) of
+ * PostgreSQL.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/pg_lsn.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_LSN_H
+#define PG_LSN_H
+
+#include "access/xlogdefs.h"
+#include "fmgr.h"
+
+static inline XLogRecPtr
+DatumGetLSN(Datum X)
+{
+ return (XLogRecPtr) DatumGetInt64(X);
+}
+
+static inline Datum
+LSNGetDatum(XLogRecPtr X)
+{
+ return Int64GetDatum((int64) X);
+}
+
+#define PG_GETARG_LSN(n) DatumGetLSN(PG_GETARG_DATUM(n))
+#define PG_RETURN_LSN(x) return LSNGetDatum(x)
+
+extern XLogRecPtr pg_lsn_in_internal(const char *str, bool *have_error);
+
+#endif /* PG_LSN_H */
diff --git a/src/include/utils/pg_rusage.h b/src/include/utils/pg_rusage.h
new file mode 100644
index 0000000..219ee67
--- /dev/null
+++ b/src/include/utils/pg_rusage.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_rusage.h
+ * header file for resource usage measurement support routines
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/pg_rusage.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_RUSAGE_H
+#define PG_RUSAGE_H
+
+#include <sys/resource.h>
+#include <sys/time.h>
+
+
+/* State structure for pg_rusage_init/pg_rusage_show */
+typedef struct PGRUsage
+{
+ struct timeval tv;
+ struct rusage ru;
+} PGRUsage;
+
+
+extern void pg_rusage_init(PGRUsage *ru0);
+extern const char *pg_rusage_show(const PGRUsage *ru0);
+
+#endif /* PG_RUSAGE_H */
diff --git a/src/include/utils/pgstat_internal.h b/src/include/utils/pgstat_internal.h
new file mode 100644
index 0000000..60fbf93
--- /dev/null
+++ b/src/include/utils/pgstat_internal.h
@@ -0,0 +1,814 @@
+/* ----------
+ * pgstat_internal.h
+ *
+ * Definitions for the PostgreSQL cumulative statistics system that should
+ * only be needed by files implementing statistics support (rather than ones
+ * reporting / querying stats).
+ *
+ * Copyright (c) 2001-2023, PostgreSQL Global Development Group
+ *
+ * src/include/utils/pgstat_internal.h
+ * ----------
+ */
+#ifndef PGSTAT_INTERNAL_H
+#define PGSTAT_INTERNAL_H
+
+
+#include "common/hashfn.h"
+#include "lib/dshash.h"
+#include "lib/ilist.h"
+#include "pgstat.h"
+#include "storage/lwlock.h"
+#include "utils/dsa.h"
+
+
+/*
+ * Types related to shared memory storage of statistics.
+ *
+ * Per-object statistics are stored in the "shared stats" hashtable. That
+ * table's entries (PgStatShared_HashEntry) contain a pointer to the actual stats
+ * data for the object (the size of the stats data varies depending on the
+ * kind of stats). The table is keyed by PgStat_HashKey.
+ *
+ * Once a backend has a reference to a shared stats entry, it increments the
+ * entry's refcount. Even after stats data is dropped (e.g., due to a DROP
+ * TABLE), the entry itself can only be deleted once all references have been
+ * released.
+ *
+ * These refcounts, in combination with a backend local hashtable
+ * (pgStatEntryRefHash, with entries pointing to PgStat_EntryRef) in front of
+ * the shared hash table, mean that most stats work can happen without
+ * touching the shared hash table, reducing contention.
+ *
+ * Once there are pending stats updates for a table PgStat_EntryRef->pending
+ * is allocated to contain a working space for as-of-yet-unapplied stats
+ * updates. Once the stats are flushed, PgStat_EntryRef->pending is freed.
+ *
+ * Each stat kind in the shared hash table has a fixed member
+ * PgStatShared_Common as the first element.
+ */
+
+/* struct for shared statistics hash entry key. */
+typedef struct PgStat_HashKey
+{
+ PgStat_Kind kind; /* statistics entry kind */
+ Oid dboid; /* database ID. InvalidOid for shared objects. */
+ Oid objoid; /* object ID, either table or function. */
+} PgStat_HashKey;
+
+/*
+ * Shared statistics hash entry. Doesn't itself contain any stats, but points
+ * to them (with ->body). That allows the stats entries themselves to be of
+ * variable size.
+ */
+typedef struct PgStatShared_HashEntry
+{
+ PgStat_HashKey key; /* hash key */
+
+ /*
+ * If dropped is set, backends need to release their references so that
+ * the memory for the entry can be freed. No new references may be made
+ * once marked as dropped.
+ */
+ bool dropped;
+
+ /*
+ * Refcount managing lifetime of the entry itself (as opposed to the
+ * dshash entry pointing to it). The stats lifetime has to be separate
+ * from the hash table entry lifetime because we allow backends to point
+ * to a stats entry without holding a hash table lock (and some other
+ * reasons).
+ *
+ * As long as the entry is not dropped, 1 is added to the refcount
+ * representing that the entry should not be dropped. In addition each
+ * backend that has a reference to the entry needs to increment the
+ * refcount as long as it does.
+ *
+ * May only be incremented / decremented while holding at least a shared
+ * lock on the dshash partition containing the entry. It needs to be an
+ * atomic variable because multiple backends can increment the refcount
+ * with just a shared lock.
+ *
+ * When the refcount reaches 0 the entry needs to be freed.
+ */
+ pg_atomic_uint32 refcount;
+
+ /*
+ * Pointer to shared stats. The stats entry always starts with
+ * PgStatShared_Common, embedded in a larger struct containing the
+ * PgStat_Kind specific stats fields.
+ */
+ dsa_pointer body;
+} PgStatShared_HashEntry;
+
+/*
+ * Common header struct for PgStatShared_*.
+ */
+typedef struct PgStatShared_Common
+{
+ uint32 magic; /* just a validity cross-check */
+ /* lock protecting stats contents (i.e. data following the header) */
+ LWLock lock;
+} PgStatShared_Common;
+
+/*
+ * A backend local reference to a shared stats entry. As long as at least one
+ * such reference exists, the shared stats entry will not be released.
+ *
+ * If there are pending stats update to the shared stats, these are stored in
+ * ->pending.
+ */
+typedef struct PgStat_EntryRef
+{
+ /*
+ * Pointer to the PgStatShared_HashEntry entry in the shared stats
+ * hashtable.
+ */
+ PgStatShared_HashEntry *shared_entry;
+
+ /*
+ * Pointer to the stats data (i.e. PgStatShared_HashEntry->body), resolved
+ * as a local pointer, to avoid repeated dsa_get_address() calls.
+ */
+ PgStatShared_Common *shared_stats;
+
+ /*
+ * Pending statistics data that will need to be flushed to shared memory
+ * stats eventually. Each stats kind utilizing pending data defines what
+ * format its pending data has and needs to provide a
+ * PgStat_KindInfo->flush_pending_cb callback to merge pending into shared
+ * stats.
+ */
+ void *pending;
+ dlist_node pending_node; /* membership in pgStatPending list */
+} PgStat_EntryRef;
+
+
+/*
+ * Some stats changes are transactional. To maintain those, a stack of
+ * PgStat_SubXactStatus entries is maintained, which contain data pertaining
+ * to the current transaction and its active subtransactions.
+ */
+typedef struct PgStat_SubXactStatus
+{
+ int nest_level; /* subtransaction nest level */
+
+ struct PgStat_SubXactStatus *prev; /* higher-level subxact if any */
+
+ /*
+ * Statistics for transactionally dropped objects need to be
+ * transactionally dropped as well. Collect the stats dropped in the
+ * current (sub-)transaction and only execute the stats drop when we know
+ * if the transaction commits/aborts. To handle replicas and crashes,
+ * stats drops are included in commit / abort records.
+ */
+ dclist_head pending_drops;
+
+ /*
+ * Tuple insertion/deletion counts for an open transaction can't be
+ * propagated into PgStat_TableStatus counters until we know if it is
+ * going to commit or abort. Hence, we keep these counts in per-subxact
+ * structs that live in TopTransactionContext. This data structure is
+ * designed on the assumption that subxacts won't usually modify very many
+ * tables.
+ */
+ PgStat_TableXactStatus *first; /* head of list for this subxact */
+} PgStat_SubXactStatus;
+
+
+/*
+ * Metadata for a specific kind of statistics.
+ */
+typedef struct PgStat_KindInfo
+{
+ /*
+ * Do a fixed number of stats objects exist for this kind of stats (e.g.
+ * bgwriter stats) or not (e.g. tables).
+ */
+ bool fixed_amount:1;
+
+ /*
+ * Can stats of this kind be accessed from another database? Determines
+ * whether a stats object gets included in stats snapshots.
+ */
+ bool accessed_across_databases:1;
+
+ /*
+ * For variable-numbered stats: Identified on-disk using a name, rather
+ * than PgStat_HashKey. Probably only needed for replication slot stats.
+ */
+ bool named_on_disk:1;
+
+ /*
+ * The size of an entry in the shared stats hash table (pointed to by
+ * PgStatShared_HashEntry->body).
+ */
+ uint32 shared_size;
+
+ /*
+ * The offset/size of statistics inside the shared stats entry. Used when
+ * [de-]serializing statistics to / from disk respectively. Separate from
+ * shared_size because [de-]serialization may not include in-memory state
+ * like lwlocks.
+ */
+ uint32 shared_data_off;
+ uint32 shared_data_len;
+
+ /*
+ * The size of the pending data for this kind. E.g. how large
+ * PgStat_EntryRef->pending is. Used for allocations.
+ *
+ * 0 signals that an entry of this kind should never have a pending entry.
+ */
+ uint32 pending_size;
+
+ /*
+ * For variable-numbered stats: flush pending stats. Required if pending
+ * data is used.
+ */
+ bool (*flush_pending_cb) (PgStat_EntryRef *sr, bool nowait);
+
+ /*
+ * For variable-numbered stats: delete pending stats. Optional.
+ */
+ void (*delete_pending_cb) (PgStat_EntryRef *sr);
+
+ /*
+ * For variable-numbered stats: reset the reset timestamp. Optional.
+ */
+ void (*reset_timestamp_cb) (PgStatShared_Common *header, TimestampTz ts);
+
+ /*
+ * For variable-numbered stats with named_on_disk. Optional.
+ */
+ void (*to_serialized_name) (const PgStat_HashKey *key,
+ const PgStatShared_Common *header, NameData *name);
+ bool (*from_serialized_name) (const NameData *name, PgStat_HashKey *key);
+
+ /*
+ * For fixed-numbered statistics: Reset All.
+ */
+ void (*reset_all_cb) (TimestampTz ts);
+
+ /*
+ * For fixed-numbered statistics: Build snapshot for entry
+ */
+ void (*snapshot_cb) (void);
+
+ /* name of the kind of stats */
+ const char *const name;
+} PgStat_KindInfo;
+
+
+/*
+ * List of SLRU names that we keep stats for. There is no central registry of
+ * SLRUs, so we use this fixed list instead. The "other" entry is used for
+ * all SLRUs without an explicit entry (e.g. SLRUs in extensions).
+ *
+ * This is only defined here so that SLRU_NUM_ELEMENTS is known for later type
+ * definitions.
+ */
+static const char *const slru_names[] = {
+ "CommitTs",
+ "MultiXactMember",
+ "MultiXactOffset",
+ "Notify",
+ "Serial",
+ "Subtrans",
+ "Xact",
+ "other" /* has to be last */
+};
+
+#define SLRU_NUM_ELEMENTS lengthof(slru_names)
+
+
+/* ----------
+ * Types and definitions for different kinds of fixed-amount stats.
+ *
+ * Single-writer stats use the changecount mechanism to achieve low-overhead
+ * writes - they're obviously more performance critical than reads. Check the
+ * definition of struct PgBackendStatus for some explanation of the
+ * changecount mechanism.
+ *
+ * Because the obvious implementation of resetting single-writer stats isn't
+ * compatible with that (another backend needs to write), we don't scribble on
+ * shared stats while resetting. Instead, just record the current counter
+ * values in a copy of the stats data, which is protected by ->lock. See
+ * pgstat_fetch_stat_(archiver|bgwriter|checkpointer) for the reader side.
+ *
+ * The only exception to that is the stat_reset_timestamp in these structs,
+ * which is protected by ->lock, because it has to be written by another
+ * backend while resetting.
+ * ----------
+ */
+
+typedef struct PgStatShared_Archiver
+{
+ /* lock protects ->reset_offset as well as stats->stat_reset_timestamp */
+ LWLock lock;
+ uint32 changecount;
+ PgStat_ArchiverStats stats;
+ PgStat_ArchiverStats reset_offset;
+} PgStatShared_Archiver;
+
+typedef struct PgStatShared_BgWriter
+{
+ /* lock protects ->reset_offset as well as stats->stat_reset_timestamp */
+ LWLock lock;
+ uint32 changecount;
+ PgStat_BgWriterStats stats;
+ PgStat_BgWriterStats reset_offset;
+} PgStatShared_BgWriter;
+
+typedef struct PgStatShared_Checkpointer
+{
+ /* lock protects ->reset_offset as well as stats->stat_reset_timestamp */
+ LWLock lock;
+ uint32 changecount;
+ PgStat_CheckpointerStats stats;
+ PgStat_CheckpointerStats reset_offset;
+} PgStatShared_Checkpointer;
+
+/* Shared-memory ready PgStat_IO */
+typedef struct PgStatShared_IO
+{
+ /*
+ * locks[i] protects stats.stats[i]. locks[0] also protects
+ * stats.stat_reset_timestamp.
+ */
+ LWLock locks[BACKEND_NUM_TYPES];
+ PgStat_IO stats;
+} PgStatShared_IO;
+
+typedef struct PgStatShared_SLRU
+{
+ /* lock protects ->stats */
+ LWLock lock;
+ PgStat_SLRUStats stats[SLRU_NUM_ELEMENTS];
+} PgStatShared_SLRU;
+
+typedef struct PgStatShared_Wal
+{
+ /* lock protects ->stats */
+ LWLock lock;
+ PgStat_WalStats stats;
+} PgStatShared_Wal;
+
+
+
+/* ----------
+ * Types and definitions for different kinds of variable-amount stats.
+ *
+ * Each struct has to start with PgStatShared_Common, containing information
+ * common across the different types of stats. Kind-specific data follows.
+ * ----------
+ */
+
+typedef struct PgStatShared_Database
+{
+ PgStatShared_Common header;
+ PgStat_StatDBEntry stats;
+} PgStatShared_Database;
+
+typedef struct PgStatShared_Relation
+{
+ PgStatShared_Common header;
+ PgStat_StatTabEntry stats;
+} PgStatShared_Relation;
+
+typedef struct PgStatShared_Function
+{
+ PgStatShared_Common header;
+ PgStat_StatFuncEntry stats;
+} PgStatShared_Function;
+
+typedef struct PgStatShared_Subscription
+{
+ PgStatShared_Common header;
+ PgStat_StatSubEntry stats;
+} PgStatShared_Subscription;
+
+typedef struct PgStatShared_ReplSlot
+{
+ PgStatShared_Common header;
+ PgStat_StatReplSlotEntry stats;
+} PgStatShared_ReplSlot;
+
+
+/*
+ * Central shared memory entry for the cumulative stats system.
+ *
+ * Fixed amount stats, the dynamic shared memory hash table for
+ * non-fixed-amount stats, as well as remaining bits and pieces are all
+ * reached from here.
+ */
+typedef struct PgStat_ShmemControl
+{
+ void *raw_dsa_area;
+
+ /*
+ * Stats for variable-numbered objects are kept in this shared hash table.
+ * See comment above PgStat_Kind for details.
+ */
+ dshash_table_handle hash_handle; /* shared dbstat hash */
+
+ /* Has the stats system already been shut down? Just a debugging check. */
+ bool is_shutdown;
+
+ /*
+ * Whenever statistics for dropped objects could not be freed - because
+ * backends still have references - the dropping backend calls
+ * pgstat_request_entry_refs_gc() incrementing this counter. Eventually
+ * that causes backends to run pgstat_gc_entry_refs(), allowing memory to
+ * be reclaimed.
+ */
+ pg_atomic_uint64 gc_request_count;
+
+ /*
+ * Stats data for fixed-numbered objects.
+ */
+ PgStatShared_Archiver archiver;
+ PgStatShared_BgWriter bgwriter;
+ PgStatShared_Checkpointer checkpointer;
+ PgStatShared_IO io;
+ PgStatShared_SLRU slru;
+ PgStatShared_Wal wal;
+} PgStat_ShmemControl;
+
+
+/*
+ * Cached statistics snapshot
+ */
+typedef struct PgStat_Snapshot
+{
+ PgStat_FetchConsistency mode;
+
+ /* time at which snapshot was taken */
+ TimestampTz snapshot_timestamp;
+
+ bool fixed_valid[PGSTAT_NUM_KINDS];
+
+ PgStat_ArchiverStats archiver;
+
+ PgStat_BgWriterStats bgwriter;
+
+ PgStat_CheckpointerStats checkpointer;
+
+ PgStat_IO io;
+
+ PgStat_SLRUStats slru[SLRU_NUM_ELEMENTS];
+
+ PgStat_WalStats wal;
+
+ /* to free snapshot in bulk */
+ MemoryContext context;
+ struct pgstat_snapshot_hash *stats;
+} PgStat_Snapshot;
+
+
+/*
+ * Collection of backend-local stats state.
+ */
+typedef struct PgStat_LocalState
+{
+ PgStat_ShmemControl *shmem;
+ dsa_area *dsa;
+ dshash_table *shared_hash;
+
+ /* the current statistics snapshot */
+ PgStat_Snapshot snapshot;
+} PgStat_LocalState;
+
+
+/*
+ * Inline functions defined further below.
+ */
+
+static inline void pgstat_begin_changecount_write(uint32 *cc);
+static inline void pgstat_end_changecount_write(uint32 *cc);
+static inline uint32 pgstat_begin_changecount_read(uint32 *cc);
+static inline bool pgstat_end_changecount_read(uint32 *cc, uint32 cc_before);
+
+static inline void pgstat_copy_changecounted_stats(void *dst, void *src, size_t len,
+ uint32 *cc);
+
+static inline int pgstat_cmp_hash_key(const void *a, const void *b, size_t size, void *arg);
+static inline uint32 pgstat_hash_hash_key(const void *d, size_t size, void *arg);
+static inline size_t pgstat_get_entry_len(PgStat_Kind kind);
+static inline void *pgstat_get_entry_data(PgStat_Kind kind, PgStatShared_Common *entry);
+
+
+/*
+ * Functions in pgstat.c
+ */
+
+extern const PgStat_KindInfo *pgstat_get_kind_info(PgStat_Kind kind);
+
+#ifdef USE_ASSERT_CHECKING
+extern void pgstat_assert_is_up(void);
+#else
+#define pgstat_assert_is_up() ((void)true)
+#endif
+
+extern void pgstat_delete_pending_entry(PgStat_EntryRef *entry_ref);
+extern PgStat_EntryRef *pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid, bool *created_entry);
+extern PgStat_EntryRef *pgstat_fetch_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid);
+
+extern void *pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid);
+extern void pgstat_snapshot_fixed(PgStat_Kind kind);
+
+
+/*
+ * Functions in pgstat_archiver.c
+ */
+
+extern void pgstat_archiver_reset_all_cb(TimestampTz ts);
+extern void pgstat_archiver_snapshot_cb(void);
+
+
+/*
+ * Functions in pgstat_bgwriter.c
+ */
+
+extern void pgstat_bgwriter_reset_all_cb(TimestampTz ts);
+extern void pgstat_bgwriter_snapshot_cb(void);
+
+
+/*
+ * Functions in pgstat_checkpointer.c
+ */
+
+extern void pgstat_checkpointer_reset_all_cb(TimestampTz ts);
+extern void pgstat_checkpointer_snapshot_cb(void);
+
+
+/*
+ * Functions in pgstat_database.c
+ */
+
+extern void pgstat_report_disconnect(Oid dboid);
+extern void pgstat_update_dbstats(TimestampTz ts);
+extern void AtEOXact_PgStat_Database(bool isCommit, bool parallel);
+
+extern PgStat_StatDBEntry *pgstat_prep_database_pending(Oid dboid);
+extern void pgstat_reset_database_timestamp(Oid dboid, TimestampTz ts);
+extern bool pgstat_database_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
+extern void pgstat_database_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts);
+
+
+/*
+ * Functions in pgstat_function.c
+ */
+
+extern bool pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
+
+
+/*
+ * Functions in pgstat_io.c
+ */
+
+extern bool pgstat_flush_io(bool nowait);
+extern void pgstat_io_reset_all_cb(TimestampTz ts);
+extern void pgstat_io_snapshot_cb(void);
+
+
+/*
+ * Functions in pgstat_relation.c
+ */
+
+extern void AtEOXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit);
+extern void AtEOSubXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit, int nestDepth);
+extern void AtPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state);
+extern void PostPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state);
+
+extern bool pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
+extern void pgstat_relation_delete_pending_cb(PgStat_EntryRef *entry_ref);
+
+
+/*
+ * Functions in pgstat_replslot.c
+ */
+
+extern void pgstat_replslot_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts);
+extern void pgstat_replslot_to_serialized_name_cb(const PgStat_HashKey *key, const PgStatShared_Common *header, NameData *name);
+extern bool pgstat_replslot_from_serialized_name_cb(const NameData *name, PgStat_HashKey *key);
+
+
+/*
+ * Functions in pgstat_shmem.c
+ */
+
+extern void pgstat_attach_shmem(void);
+extern void pgstat_detach_shmem(void);
+
+extern PgStat_EntryRef *pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, Oid objoid,
+ bool create, bool *created_entry);
+extern bool pgstat_lock_entry(PgStat_EntryRef *entry_ref, bool nowait);
+extern bool pgstat_lock_entry_shared(PgStat_EntryRef *entry_ref, bool nowait);
+extern void pgstat_unlock_entry(PgStat_EntryRef *entry_ref);
+extern bool pgstat_drop_entry(PgStat_Kind kind, Oid dboid, Oid objoid);
+extern void pgstat_drop_all_entries(void);
+extern PgStat_EntryRef *pgstat_get_entry_ref_locked(PgStat_Kind kind, Oid dboid, Oid objoid,
+ bool nowait);
+extern void pgstat_reset_entry(PgStat_Kind kind, Oid dboid, Oid objoid, TimestampTz ts);
+extern void pgstat_reset_entries_of_kind(PgStat_Kind kind, TimestampTz ts);
+extern void pgstat_reset_matching_entries(bool (*do_reset) (PgStatShared_HashEntry *, Datum),
+ Datum match_data,
+ TimestampTz ts);
+
+extern void pgstat_request_entry_refs_gc(void);
+extern PgStatShared_Common *pgstat_init_entry(PgStat_Kind kind,
+ PgStatShared_HashEntry *shhashent);
+
+
+/*
+ * Functions in pgstat_slru.c
+ */
+
+extern bool pgstat_slru_flush(bool nowait);
+extern void pgstat_slru_reset_all_cb(TimestampTz ts);
+extern void pgstat_slru_snapshot_cb(void);
+
+
+/*
+ * Functions in pgstat_wal.c
+ */
+
+extern bool pgstat_flush_wal(bool nowait);
+extern void pgstat_init_wal(void);
+extern bool pgstat_have_pending_wal(void);
+
+extern void pgstat_wal_reset_all_cb(TimestampTz ts);
+extern void pgstat_wal_snapshot_cb(void);
+
+
+/*
+ * Functions in pgstat_subscription.c
+ */
+
+extern bool pgstat_subscription_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
+extern void pgstat_subscription_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts);
+
+
+/*
+ * Functions in pgstat_xact.c
+ */
+
+extern PgStat_SubXactStatus *pgstat_get_xact_stack_level(int nest_level);
+extern void pgstat_drop_transactional(PgStat_Kind kind, Oid dboid, Oid objoid);
+extern void pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid);
+
+
+/*
+ * Variables in pgstat.c
+ */
+
+extern PGDLLIMPORT PgStat_LocalState pgStatLocal;
+
+
+/*
+ * Variables in pgstat_io.c
+ */
+
+extern PGDLLIMPORT bool have_iostats;
+
+
+/*
+ * Variables in pgstat_slru.c
+ */
+
+extern PGDLLIMPORT bool have_slrustats;
+
+
+/*
+ * Implementation of inline functions declared above.
+ */
+
+/*
+ * Helpers for changecount manipulation. See comments around struct
+ * PgBackendStatus for details.
+ */
+
+static inline void
+pgstat_begin_changecount_write(uint32 *cc)
+{
+ Assert((*cc & 1) == 0);
+
+ START_CRIT_SECTION();
+ (*cc)++;
+ pg_write_barrier();
+}
+
+static inline void
+pgstat_end_changecount_write(uint32 *cc)
+{
+ Assert((*cc & 1) == 1);
+
+ pg_write_barrier();
+
+ (*cc)++;
+
+ END_CRIT_SECTION();
+}
+
+static inline uint32
+pgstat_begin_changecount_read(uint32 *cc)
+{
+ uint32 before_cc = *cc;
+
+ CHECK_FOR_INTERRUPTS();
+
+ pg_read_barrier();
+
+ return before_cc;
+}
+
+/*
+ * Returns true if the read succeeded, false if it needs to be repeated.
+ */
+static inline bool
+pgstat_end_changecount_read(uint32 *cc, uint32 before_cc)
+{
+ uint32 after_cc;
+
+ pg_read_barrier();
+
+ after_cc = *cc;
+
+ /* was a write in progress when we started? */
+ if (before_cc & 1)
+ return false;
+
+ /* did writes start and complete while we read? */
+ return before_cc == after_cc;
+}
+
+
+/*
+ * helper function for PgStat_KindInfo->snapshot_cb
+ * PgStat_KindInfo->reset_all_cb callbacks.
+ *
+ * Copies out the specified memory area following change-count protocol.
+ */
+static inline void
+pgstat_copy_changecounted_stats(void *dst, void *src, size_t len,
+ uint32 *cc)
+{
+ uint32 cc_before;
+
+ do
+ {
+ cc_before = pgstat_begin_changecount_read(cc);
+
+ memcpy(dst, src, len);
+ }
+ while (!pgstat_end_changecount_read(cc, cc_before));
+}
+
+/* helpers for dshash / simplehash hashtables */
+static inline int
+pgstat_cmp_hash_key(const void *a, const void *b, size_t size, void *arg)
+{
+ Assert(size == sizeof(PgStat_HashKey) && arg == NULL);
+ return memcmp(a, b, sizeof(PgStat_HashKey));
+}
+
+static inline uint32
+pgstat_hash_hash_key(const void *d, size_t size, void *arg)
+{
+ const PgStat_HashKey *key = (PgStat_HashKey *) d;
+ uint32 hash;
+
+ Assert(size == sizeof(PgStat_HashKey) && arg == NULL);
+
+ hash = murmurhash32(key->kind);
+ hash = hash_combine(hash, murmurhash32(key->dboid));
+ hash = hash_combine(hash, murmurhash32(key->objoid));
+
+ return hash;
+}
+
+/*
+ * The length of the data portion of a shared memory stats entry (i.e. without
+ * transient data such as refcounts, lwlocks, ...).
+ */
+static inline size_t
+pgstat_get_entry_len(PgStat_Kind kind)
+{
+ return pgstat_get_kind_info(kind)->shared_data_len;
+}
+
+/*
+ * Returns a pointer to the data portion of a shared memory stats entry.
+ */
+static inline void *
+pgstat_get_entry_data(PgStat_Kind kind, PgStatShared_Common *entry)
+{
+ size_t off = pgstat_get_kind_info(kind)->shared_data_off;
+
+ Assert(off != 0 && off < PG_UINT32_MAX);
+
+ return ((char *) (entry)) + off;
+}
+
+#endif /* PGSTAT_INTERNAL_H */
diff --git a/src/include/utils/pidfile.h b/src/include/utils/pidfile.h
new file mode 100644
index 0000000..1393a53
--- /dev/null
+++ b/src/include/utils/pidfile.h
@@ -0,0 +1,56 @@
+/*-------------------------------------------------------------------------
+ *
+ * pidfile.h
+ * Declarations describing the data directory lock file (postmaster.pid)
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/pidfile.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef UTILS_PIDFILE_H
+#define UTILS_PIDFILE_H
+
+/*
+ * As of Postgres 10, the contents of the data-directory lock file are:
+ *
+ * line #
+ * 1 postmaster PID (or negative of a standalone backend's PID)
+ * 2 data directory path
+ * 3 postmaster start timestamp (time_t representation)
+ * 4 port number
+ * 5 first Unix socket directory path (empty if none)
+ * 6 first listen_address (IP address or "*"; empty if no TCP port)
+ * 7 shared memory key (empty on Windows)
+ * 8 postmaster status (see values below)
+ *
+ * Lines 6 and up are added via AddToDataDirLockFile() after initial file
+ * creation; also, line 5 is initially empty and is changed after the first
+ * Unix socket is opened. Onlookers should not assume that lines 4 and up
+ * are filled in any particular order.
+ *
+ * Socket lock file(s), if used, have the same contents as lines 1-5, with
+ * line 5 being their own directory.
+ */
+#define LOCK_FILE_LINE_PID 1
+#define LOCK_FILE_LINE_DATA_DIR 2
+#define LOCK_FILE_LINE_START_TIME 3
+#define LOCK_FILE_LINE_PORT 4
+#define LOCK_FILE_LINE_SOCKET_DIR 5
+#define LOCK_FILE_LINE_LISTEN_ADDR 6
+#define LOCK_FILE_LINE_SHMEM_KEY 7
+#define LOCK_FILE_LINE_PM_STATUS 8
+
+/*
+ * The PM_STATUS line may contain one of these values. All these strings
+ * must be the same length, per comments for AddToDataDirLockFile().
+ * We pad with spaces as needed to make that true.
+ */
+#define PM_STATUS_STARTING "starting" /* still starting up */
+#define PM_STATUS_STOPPING "stopping" /* in shutdown sequence */
+#define PM_STATUS_READY "ready " /* ready for connections */
+#define PM_STATUS_STANDBY "standby " /* up, won't accept connections */
+
+#endif /* UTILS_PIDFILE_H */
diff --git a/src/include/utils/plancache.h b/src/include/utils/plancache.h
new file mode 100644
index 0000000..a443181
--- /dev/null
+++ b/src/include/utils/plancache.h
@@ -0,0 +1,236 @@
+/*-------------------------------------------------------------------------
+ *
+ * plancache.h
+ * Plan cache definitions.
+ *
+ * See plancache.c for comments.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/plancache.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PLANCACHE_H
+#define PLANCACHE_H
+
+#include "access/tupdesc.h"
+#include "lib/ilist.h"
+#include "nodes/params.h"
+#include "tcop/cmdtag.h"
+#include "utils/queryenvironment.h"
+#include "utils/resowner.h"
+
+
+/* Forward declaration, to avoid including parsenodes.h here */
+struct RawStmt;
+
+/* possible values for plan_cache_mode */
+typedef enum
+{
+ PLAN_CACHE_MODE_AUTO,
+ PLAN_CACHE_MODE_FORCE_GENERIC_PLAN,
+ PLAN_CACHE_MODE_FORCE_CUSTOM_PLAN
+} PlanCacheMode;
+
+/* GUC parameter */
+extern PGDLLIMPORT int plan_cache_mode;
+
+#define CACHEDPLANSOURCE_MAGIC 195726186
+#define CACHEDPLAN_MAGIC 953717834
+#define CACHEDEXPR_MAGIC 838275847
+
+/*
+ * CachedPlanSource (which might better have been called CachedQuery)
+ * represents a SQL query that we expect to use multiple times. It stores
+ * the query source text, the raw parse tree, and the analyzed-and-rewritten
+ * query tree, as well as adjunct data. Cache invalidation can happen as a
+ * result of DDL affecting objects used by the query. In that case we discard
+ * the analyzed-and-rewritten query tree, and rebuild it when next needed.
+ *
+ * An actual execution plan, represented by CachedPlan, is derived from the
+ * CachedPlanSource when we need to execute the query. The plan could be
+ * either generic (usable with any set of plan parameters) or custom (for a
+ * specific set of parameters). plancache.c contains the logic that decides
+ * which way to do it for any particular execution. If we are using a generic
+ * cached plan then it is meant to be re-used across multiple executions, so
+ * callers must always treat CachedPlans as read-only.
+ *
+ * Once successfully built and "saved", CachedPlanSources typically live
+ * for the life of the backend, although they can be dropped explicitly.
+ * CachedPlans are reference-counted and go away automatically when the last
+ * reference is dropped. A CachedPlan can outlive the CachedPlanSource it
+ * was created from.
+ *
+ * An "unsaved" CachedPlanSource can be used for generating plans, but it
+ * lives in transient storage and will not be updated in response to sinval
+ * events.
+ *
+ * CachedPlans made from saved CachedPlanSources are likewise in permanent
+ * storage, so to avoid memory leaks, the reference-counted references to them
+ * must be held in permanent data structures or ResourceOwners. CachedPlans
+ * made from unsaved CachedPlanSources are in children of the caller's
+ * memory context, so references to them should not be longer-lived than
+ * that context. (Reference counting is somewhat pro forma in that case,
+ * though it may be useful if the CachedPlan can be discarded early.)
+ *
+ * A CachedPlanSource has two associated memory contexts: one that holds the
+ * struct itself, the query source text and the raw parse tree, and another
+ * context that holds the rewritten query tree and associated data. This
+ * allows the query tree to be discarded easily when it is invalidated.
+ *
+ * Some callers wish to use the CachedPlan API even with one-shot queries
+ * that have no reason to be saved at all. We therefore support a "oneshot"
+ * variant that does no data copying or invalidation checking. In this case
+ * there are no separate memory contexts: the CachedPlanSource struct and
+ * all subsidiary data live in the caller's CurrentMemoryContext, and there
+ * is no way to free memory short of clearing that entire context. A oneshot
+ * plan is always treated as unsaved.
+ *
+ * Note: the string referenced by commandTag is not subsidiary storage;
+ * it is assumed to be a compile-time-constant string. As with portals,
+ * commandTag shall be NULL if and only if the original query string (before
+ * rewriting) was an empty string.
+ */
+typedef struct CachedPlanSource
+{
+ int magic; /* should equal CACHEDPLANSOURCE_MAGIC */
+ struct RawStmt *raw_parse_tree; /* output of raw_parser(), or NULL */
+ const char *query_string; /* source text of query */
+ CommandTag commandTag; /* 'nuff said */
+ Oid *param_types; /* array of parameter type OIDs, or NULL */
+ int num_params; /* length of param_types array */
+ ParserSetupHook parserSetup; /* alternative parameter spec method */
+ void *parserSetupArg;
+ int cursor_options; /* cursor options used for planning */
+ bool fixed_result; /* disallow change in result tupdesc? */
+ TupleDesc resultDesc; /* result type; NULL = doesn't return tuples */
+ MemoryContext context; /* memory context holding all above */
+ /* These fields describe the current analyzed-and-rewritten query tree: */
+ List *query_list; /* list of Query nodes, or NIL if not valid */
+ List *relationOids; /* OIDs of relations the queries depend on */
+ List *invalItems; /* other dependencies, as PlanInvalItems */
+ struct OverrideSearchPath *search_path; /* search_path used for parsing
+ * and planning */
+ MemoryContext query_context; /* context holding the above, or NULL */
+ Oid rewriteRoleId; /* Role ID we did rewriting for */
+ bool rewriteRowSecurity; /* row_security used during rewrite */
+ bool dependsOnRLS; /* is rewritten query specific to the above? */
+ /* If we have a generic plan, this is a reference-counted link to it: */
+ struct CachedPlan *gplan; /* generic plan, or NULL if not valid */
+ /* Some state flags: */
+ bool is_oneshot; /* is it a "oneshot" plan? */
+ bool is_complete; /* has CompleteCachedPlan been done? */
+ bool is_saved; /* has CachedPlanSource been "saved"? */
+ bool is_valid; /* is the query_list currently valid? */
+ int generation; /* increments each time we create a plan */
+ /* If CachedPlanSource has been saved, it is a member of a global list */
+ dlist_node node; /* list link, if is_saved */
+ /* State kept to help decide whether to use custom or generic plans: */
+ double generic_cost; /* cost of generic plan, or -1 if not known */
+ double total_custom_cost; /* total cost of custom plans so far */
+ int64 num_custom_plans; /* # of custom plans included in total */
+ int64 num_generic_plans; /* # of generic plans */
+} CachedPlanSource;
+
+/*
+ * CachedPlan represents an execution plan derived from a CachedPlanSource.
+ * The reference count includes both the link from the parent CachedPlanSource
+ * (if any), and any active plan executions, so the plan can be discarded
+ * exactly when refcount goes to zero. Both the struct itself and the
+ * subsidiary data live in the context denoted by the context field.
+ * This makes it easy to free a no-longer-needed cached plan. (However,
+ * if is_oneshot is true, the context does not belong solely to the CachedPlan
+ * so no freeing is possible.)
+ */
+typedef struct CachedPlan
+{
+ int magic; /* should equal CACHEDPLAN_MAGIC */
+ List *stmt_list; /* list of PlannedStmts */
+ bool is_oneshot; /* is it a "oneshot" plan? */
+ bool is_saved; /* is CachedPlan in a long-lived context? */
+ bool is_valid; /* is the stmt_list currently valid? */
+ Oid planRoleId; /* Role ID the plan was created for */
+ bool dependsOnRole; /* is plan specific to that role? */
+ TransactionId saved_xmin; /* if valid, replan when TransactionXmin
+ * changes from this value */
+ int generation; /* parent's generation number for this plan */
+ int refcount; /* count of live references to this struct */
+ MemoryContext context; /* context containing this CachedPlan */
+} CachedPlan;
+
+/*
+ * CachedExpression is a low-overhead mechanism for caching the planned form
+ * of standalone scalar expressions. While such expressions are not usually
+ * subject to cache invalidation events, that can happen, for example because
+ * of replacement of a SQL function that was inlined into the expression.
+ * The plancache takes care of storing the expression tree and marking it
+ * invalid if a cache invalidation occurs, but the caller must notice the
+ * !is_valid status and discard the obsolete expression without reusing it.
+ * We do not store the original parse tree, only the planned expression;
+ * this is an optimization based on the assumption that we usually will not
+ * need to replan for the life of the session.
+ */
+typedef struct CachedExpression
+{
+ int magic; /* should equal CACHEDEXPR_MAGIC */
+ Node *expr; /* planned form of expression */
+ bool is_valid; /* is the expression still valid? */
+ /* remaining fields should be treated as private to plancache.c: */
+ List *relationOids; /* OIDs of relations the expr depends on */
+ List *invalItems; /* other dependencies, as PlanInvalItems */
+ MemoryContext context; /* context containing this CachedExpression */
+ dlist_node node; /* link in global list of CachedExpressions */
+} CachedExpression;
+
+
+extern void InitPlanCache(void);
+extern void ResetPlanCache(void);
+
+extern CachedPlanSource *CreateCachedPlan(struct RawStmt *raw_parse_tree,
+ const char *query_string,
+ CommandTag commandTag);
+extern CachedPlanSource *CreateOneShotCachedPlan(struct RawStmt *raw_parse_tree,
+ const char *query_string,
+ CommandTag commandTag);
+extern void CompleteCachedPlan(CachedPlanSource *plansource,
+ List *querytree_list,
+ MemoryContext querytree_context,
+ Oid *param_types,
+ int num_params,
+ ParserSetupHook parserSetup,
+ void *parserSetupArg,
+ int cursor_options,
+ bool fixed_result);
+
+extern void SaveCachedPlan(CachedPlanSource *plansource);
+extern void DropCachedPlan(CachedPlanSource *plansource);
+
+extern void CachedPlanSetParentContext(CachedPlanSource *plansource,
+ MemoryContext newcontext);
+
+extern CachedPlanSource *CopyCachedPlan(CachedPlanSource *plansource);
+
+extern bool CachedPlanIsValid(CachedPlanSource *plansource);
+
+extern List *CachedPlanGetTargetList(CachedPlanSource *plansource,
+ QueryEnvironment *queryEnv);
+
+extern CachedPlan *GetCachedPlan(CachedPlanSource *plansource,
+ ParamListInfo boundParams,
+ ResourceOwner owner,
+ QueryEnvironment *queryEnv);
+extern void ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner);
+
+extern bool CachedPlanAllowsSimpleValidityCheck(CachedPlanSource *plansource,
+ CachedPlan *plan,
+ ResourceOwner owner);
+extern bool CachedPlanIsSimplyValid(CachedPlanSource *plansource,
+ CachedPlan *plan,
+ ResourceOwner owner);
+
+extern CachedExpression *GetCachedExpression(Node *expr);
+extern void FreeCachedExpression(CachedExpression *cexpr);
+
+#endif /* PLANCACHE_H */
diff --git a/src/include/utils/portal.h b/src/include/utils/portal.h
new file mode 100644
index 0000000..aa08b1e
--- /dev/null
+++ b/src/include/utils/portal.h
@@ -0,0 +1,252 @@
+/*-------------------------------------------------------------------------
+ *
+ * portal.h
+ * POSTGRES portal definitions.
+ *
+ * A portal is an abstraction which represents the execution state of
+ * a running or runnable query. Portals support both SQL-level CURSORs
+ * and protocol-level portals.
+ *
+ * Scrolling (nonsequential access) and suspension of execution are allowed
+ * only for portals that contain a single SELECT-type query. We do not want
+ * to let the client suspend an update-type query partway through! Because
+ * the query rewriter does not allow arbitrary ON SELECT rewrite rules,
+ * only queries that were originally update-type could produce multiple
+ * plan trees; so the restriction to a single query is not a problem
+ * in practice.
+ *
+ * For SQL cursors, we support three kinds of scroll behavior:
+ *
+ * (1) Neither NO SCROLL nor SCROLL was specified: to remain backward
+ * compatible, we allow backward fetches here, unless it would
+ * impose additional runtime overhead to do so.
+ *
+ * (2) NO SCROLL was specified: don't allow any backward fetches.
+ *
+ * (3) SCROLL was specified: allow all kinds of backward fetches, even
+ * if we need to take a performance hit to do so. (The planner sticks
+ * a Materialize node atop the query plan if needed.)
+ *
+ * Case #1 is converted to #2 or #3 by looking at the query itself and
+ * determining if scrollability can be supported without additional
+ * overhead.
+ *
+ * Protocol-level portals have no nonsequential-fetch API and so the
+ * distinction doesn't matter for them. They are always initialized
+ * to look like NO SCROLL cursors.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/portal.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PORTAL_H
+#define PORTAL_H
+
+#include "datatype/timestamp.h"
+#include "executor/execdesc.h"
+#include "tcop/cmdtag.h"
+#include "utils/plancache.h"
+#include "utils/resowner.h"
+
+/*
+ * We have several execution strategies for Portals, depending on what
+ * query or queries are to be executed. (Note: in all cases, a Portal
+ * executes just a single source-SQL query, and thus produces just a
+ * single result from the user's viewpoint. However, the rule rewriter
+ * may expand the single source query to zero or many actual queries.)
+ *
+ * PORTAL_ONE_SELECT: the portal contains one single SELECT query. We run
+ * the Executor incrementally as results are demanded. This strategy also
+ * supports holdable cursors (the Executor results can be dumped into a
+ * tuplestore for access after transaction completion).
+ *
+ * PORTAL_ONE_RETURNING: the portal contains a single INSERT/UPDATE/DELETE
+ * query with a RETURNING clause (plus possibly auxiliary queries added by
+ * rule rewriting). On first execution, we run the portal to completion
+ * and dump the primary query's results into the portal tuplestore; the
+ * results are then returned to the client as demanded. (We can't support
+ * suspension of the query partway through, because the AFTER TRIGGER code
+ * can't cope, and also because we don't want to risk failing to execute
+ * all the auxiliary queries.)
+ *
+ * PORTAL_ONE_MOD_WITH: the portal contains one single SELECT query, but
+ * it has data-modifying CTEs. This is currently treated the same as the
+ * PORTAL_ONE_RETURNING case because of the possibility of needing to fire
+ * triggers. It may act more like PORTAL_ONE_SELECT in future.
+ *
+ * PORTAL_UTIL_SELECT: the portal contains a utility statement that returns
+ * a SELECT-like result (for example, EXPLAIN or SHOW). On first execution,
+ * we run the statement and dump its results into the portal tuplestore;
+ * the results are then returned to the client as demanded.
+ *
+ * PORTAL_MULTI_QUERY: all other cases. Here, we do not support partial
+ * execution: the portal's queries will be run to completion on first call.
+ */
+typedef enum PortalStrategy
+{
+ PORTAL_ONE_SELECT,
+ PORTAL_ONE_RETURNING,
+ PORTAL_ONE_MOD_WITH,
+ PORTAL_UTIL_SELECT,
+ PORTAL_MULTI_QUERY
+} PortalStrategy;
+
+/*
+ * A portal is always in one of these states. It is possible to transit
+ * from ACTIVE back to READY if the query is not run to completion;
+ * otherwise we never back up in status.
+ */
+typedef enum PortalStatus
+{
+ PORTAL_NEW, /* freshly created */
+ PORTAL_DEFINED, /* PortalDefineQuery done */
+ PORTAL_READY, /* PortalStart complete, can run it */
+ PORTAL_ACTIVE, /* portal is running (can't delete it) */
+ PORTAL_DONE, /* portal is finished (don't re-run it) */
+ PORTAL_FAILED /* portal got error (can't re-run it) */
+} PortalStatus;
+
+typedef struct PortalData *Portal;
+
+typedef struct PortalData
+{
+ /* Bookkeeping data */
+ const char *name; /* portal's name */
+ const char *prepStmtName; /* source prepared statement (NULL if none) */
+ MemoryContext portalContext; /* subsidiary memory for portal */
+ ResourceOwner resowner; /* resources owned by portal */
+ void (*cleanup) (Portal portal); /* cleanup hook */
+
+ /*
+ * State data for remembering which subtransaction(s) the portal was
+ * created or used in. If the portal is held over from a previous
+ * transaction, both subxids are InvalidSubTransactionId. Otherwise,
+ * createSubid is the creating subxact and activeSubid is the last subxact
+ * in which we ran the portal.
+ */
+ SubTransactionId createSubid; /* the creating subxact */
+ SubTransactionId activeSubid; /* the last subxact with activity */
+ int createLevel; /* creating subxact's nesting level */
+
+ /* The query or queries the portal will execute */
+ const char *sourceText; /* text of query (as of 8.4, never NULL) */
+ CommandTag commandTag; /* command tag for original query */
+ QueryCompletion qc; /* command completion data for executed query */
+ List *stmts; /* list of PlannedStmts */
+ CachedPlan *cplan; /* CachedPlan, if stmts are from one */
+
+ ParamListInfo portalParams; /* params to pass to query */
+ QueryEnvironment *queryEnv; /* environment for query */
+
+ /* Features/options */
+ PortalStrategy strategy; /* see above */
+ int cursorOptions; /* DECLARE CURSOR option bits */
+ bool run_once; /* portal will only be run once */
+
+ /* Status data */
+ PortalStatus status; /* see above */
+ bool portalPinned; /* a pinned portal can't be dropped */
+ bool autoHeld; /* was automatically converted from pinned to
+ * held (see HoldPinnedPortals()) */
+
+ /* If not NULL, Executor is active; call ExecutorEnd eventually: */
+ QueryDesc *queryDesc; /* info needed for executor invocation */
+
+ /* If portal returns tuples, this is their tupdesc: */
+ TupleDesc tupDesc; /* descriptor for result tuples */
+ /* and these are the format codes to use for the columns: */
+ int16 *formats; /* a format code for each column */
+
+ /*
+ * Outermost ActiveSnapshot for execution of the portal's queries. For
+ * all but a few utility commands, we require such a snapshot to exist.
+ * This ensures that TOAST references in query results can be detoasted,
+ * and helps to reduce thrashing of the process's exposed xmin.
+ */
+ Snapshot portalSnapshot; /* active snapshot, or NULL if none */
+
+ /*
+ * Where we store tuples for a held cursor or a PORTAL_ONE_RETURNING or
+ * PORTAL_UTIL_SELECT query. (A cursor held past the end of its
+ * transaction no longer has any active executor state.)
+ */
+ Tuplestorestate *holdStore; /* store for holdable cursors */
+ MemoryContext holdContext; /* memory containing holdStore */
+
+ /*
+ * Snapshot under which tuples in the holdStore were read. We must keep a
+ * reference to this snapshot if there is any possibility that the tuples
+ * contain TOAST references, because releasing the snapshot could allow
+ * recently-dead rows to be vacuumed away, along with any toast data
+ * belonging to them. In the case of a held cursor, we avoid needing to
+ * keep such a snapshot by forcibly detoasting the data.
+ */
+ Snapshot holdSnapshot; /* registered snapshot, or NULL if none */
+
+ /*
+ * atStart, atEnd and portalPos indicate the current cursor position.
+ * portalPos is zero before the first row, N after fetching N'th row of
+ * query. After we run off the end, portalPos = # of rows in query, and
+ * atEnd is true. Note that atStart implies portalPos == 0, but not the
+ * reverse: we might have backed up only as far as the first row, not to
+ * the start. Also note that various code inspects atStart and atEnd, but
+ * only the portal movement routines should touch portalPos.
+ */
+ bool atStart;
+ bool atEnd;
+ uint64 portalPos;
+
+ /* Presentation data, primarily used by the pg_cursors system view */
+ TimestampTz creation_time; /* time at which this portal was defined */
+ bool visible; /* include this portal in pg_cursors? */
+} PortalData;
+
+/*
+ * PortalIsValid
+ * True iff portal is valid.
+ */
+#define PortalIsValid(p) PointerIsValid(p)
+
+
+/* Prototypes for functions in utils/mmgr/portalmem.c */
+extern void EnablePortalManager(void);
+extern bool PreCommit_Portals(bool isPrepare);
+extern void AtAbort_Portals(void);
+extern void AtCleanup_Portals(void);
+extern void PortalErrorCleanup(void);
+extern void AtSubCommit_Portals(SubTransactionId mySubid,
+ SubTransactionId parentSubid,
+ int parentLevel,
+ ResourceOwner parentXactOwner);
+extern void AtSubAbort_Portals(SubTransactionId mySubid,
+ SubTransactionId parentSubid,
+ ResourceOwner myXactOwner,
+ ResourceOwner parentXactOwner);
+extern void AtSubCleanup_Portals(SubTransactionId mySubid);
+extern Portal CreatePortal(const char *name, bool allowDup, bool dupSilent);
+extern Portal CreateNewPortal(void);
+extern void PinPortal(Portal portal);
+extern void UnpinPortal(Portal portal);
+extern void MarkPortalActive(Portal portal);
+extern void MarkPortalDone(Portal portal);
+extern void MarkPortalFailed(Portal portal);
+extern void PortalDrop(Portal portal, bool isTopCommit);
+extern Portal GetPortalByName(const char *name);
+extern void PortalDefineQuery(Portal portal,
+ const char *prepStmtName,
+ const char *sourceText,
+ CommandTag commandTag,
+ List *stmts,
+ CachedPlan *cplan);
+extern PlannedStmt *PortalGetPrimaryStmt(Portal portal);
+extern void PortalCreateHoldStore(Portal portal);
+extern void PortalHashTableDeleteAll(void);
+extern bool ThereAreNoReadyPortals(void);
+extern void HoldPinnedPortals(void);
+extern void ForgetPortalSnapshots(void);
+
+#endif /* PORTAL_H */
diff --git a/src/include/utils/ps_status.h b/src/include/utils/ps_status.h
new file mode 100644
index 0000000..ff5a2b2
--- /dev/null
+++ b/src/include/utils/ps_status.h
@@ -0,0 +1,47 @@
+/*-------------------------------------------------------------------------
+ *
+ * ps_status.h
+ *
+ * Declarations for backend/utils/misc/ps_status.c
+ *
+ * src/include/utils/ps_status.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef PS_STATUS_H
+#define PS_STATUS_H
+
+/* disabled on Windows as the performance overhead can be significant */
+#ifdef WIN32
+#define DEFAULT_UPDATE_PROCESS_TITLE false
+#else
+#define DEFAULT_UPDATE_PROCESS_TITLE true
+#endif
+
+extern PGDLLIMPORT bool update_process_title;
+
+extern char **save_ps_display_args(int argc, char **argv);
+
+extern void init_ps_display(const char *fixed_part);
+
+extern void set_ps_display_suffix(const char *suffix);
+
+extern void set_ps_display_remove_suffix(void);
+
+extern void set_ps_display_with_len(const char *activity, size_t len);
+
+/*
+ * set_ps_display
+ * inlined to allow strlen to be evaluated during compilation when
+ * passing string constants.
+ */
+static inline void
+set_ps_display(const char *activity)
+{
+ set_ps_display_with_len(activity, strlen(activity));
+}
+
+extern const char *get_ps_display(int *displen);
+
+#endif /* PS_STATUS_H */
diff --git a/src/include/utils/queryenvironment.h b/src/include/utils/queryenvironment.h
new file mode 100644
index 0000000..532219a
--- /dev/null
+++ b/src/include/utils/queryenvironment.h
@@ -0,0 +1,74 @@
+/*-------------------------------------------------------------------------
+ *
+ * queryenvironment.h
+ * Access to functions to mutate the query environment and retrieve the
+ * actual data related to entries (if any).
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/queryenvironment.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef QUERYENVIRONMENT_H
+#define QUERYENVIRONMENT_H
+
+#include "access/tupdesc.h"
+
+
+typedef enum EphemeralNameRelationType
+{
+ ENR_NAMED_TUPLESTORE /* named tuplestore relation; e.g., deltas */
+} EphemeralNameRelationType;
+
+/*
+ * Some ephemeral named relations must match some relation (e.g., trigger
+ * transition tables), so to properly handle cached plans and DDL, we should
+ * carry the OID of that relation. In other cases an ENR might be independent
+ * of any relation which is stored in the system catalogs, so we need to be
+ * able to directly store the TupleDesc. We never need both.
+ */
+typedef struct EphemeralNamedRelationMetadataData
+{
+ char *name; /* name used to identify the relation */
+
+ /* only one of the next two fields should be used */
+ Oid reliddesc; /* oid of relation to get tupdesc */
+ TupleDesc tupdesc; /* description of result rows */
+
+ EphemeralNameRelationType enrtype; /* to identify type of relation */
+ double enrtuples; /* estimated number of tuples */
+} EphemeralNamedRelationMetadataData;
+
+typedef EphemeralNamedRelationMetadataData *EphemeralNamedRelationMetadata;
+
+/*
+ * Ephemeral Named Relation data; used for parsing named relations not in the
+ * catalog, like transition tables in AFTER triggers.
+ */
+typedef struct EphemeralNamedRelationData
+{
+ EphemeralNamedRelationMetadataData md;
+ void *reldata; /* structure for execution-time access to data */
+} EphemeralNamedRelationData;
+
+typedef EphemeralNamedRelationData *EphemeralNamedRelation;
+
+/*
+ * This is an opaque structure outside of queryenvironment.c itself. The
+ * intention is to be able to change the implementation or add new context
+ * features without needing to change existing code for use of existing
+ * features.
+ */
+typedef struct QueryEnvironment QueryEnvironment;
+
+
+extern QueryEnvironment *create_queryEnv(void);
+extern EphemeralNamedRelationMetadata get_visible_ENR_metadata(QueryEnvironment *queryEnv, const char *refname);
+extern void register_ENR(QueryEnvironment *queryEnv, EphemeralNamedRelation enr);
+extern void unregister_ENR(QueryEnvironment *queryEnv, const char *name);
+extern EphemeralNamedRelation get_ENR(QueryEnvironment *queryEnv, const char *name);
+extern TupleDesc ENRMetadataGetTupDesc(EphemeralNamedRelationMetadata enrmd);
+
+#endif /* QUERYENVIRONMENT_H */
diff --git a/src/include/utils/rangetypes.h b/src/include/utils/rangetypes.h
new file mode 100644
index 0000000..6b420a8
--- /dev/null
+++ b/src/include/utils/rangetypes.h
@@ -0,0 +1,168 @@
+/*-------------------------------------------------------------------------
+ *
+ * rangetypes.h
+ * Declarations for Postgres range types.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/rangetypes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RANGETYPES_H
+#define RANGETYPES_H
+
+#include "utils/typcache.h"
+
+
+/*
+ * Ranges are varlena objects, so must meet the varlena convention that
+ * the first int32 of the object contains the total object size in bytes.
+ * Be sure to use VARSIZE() and SET_VARSIZE() to access it, though!
+ */
+typedef struct
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ Oid rangetypid; /* range type's own OID */
+ /* Following the OID are zero to two bound values, then a flags byte */
+} RangeType;
+
+#define RANGE_EMPTY_LITERAL "empty"
+
+/* Use this macro in preference to fetching rangetypid field directly */
+#define RangeTypeGetOid(r) ((r)->rangetypid)
+
+/* A range's flags byte contains these bits: */
+#define RANGE_EMPTY 0x01 /* range is empty */
+#define RANGE_LB_INC 0x02 /* lower bound is inclusive */
+#define RANGE_UB_INC 0x04 /* upper bound is inclusive */
+#define RANGE_LB_INF 0x08 /* lower bound is -infinity */
+#define RANGE_UB_INF 0x10 /* upper bound is +infinity */
+#define RANGE_LB_NULL 0x20 /* lower bound is null (NOT USED) */
+#define RANGE_UB_NULL 0x40 /* upper bound is null (NOT USED) */
+#define RANGE_CONTAIN_EMPTY 0x80 /* marks a GiST internal-page entry whose
+ * subtree contains some empty ranges */
+
+#define RANGE_HAS_LBOUND(flags) (!((flags) & (RANGE_EMPTY | \
+ RANGE_LB_NULL | \
+ RANGE_LB_INF)))
+
+#define RANGE_HAS_UBOUND(flags) (!((flags) & (RANGE_EMPTY | \
+ RANGE_UB_NULL | \
+ RANGE_UB_INF)))
+
+#define RangeIsEmpty(r) ((range_get_flags(r) & RANGE_EMPTY) != 0)
+#define RangeIsOrContainsEmpty(r) \
+ ((range_get_flags(r) & (RANGE_EMPTY | RANGE_CONTAIN_EMPTY)) != 0)
+
+
+/* Internal representation of either bound of a range (not what's on disk) */
+typedef struct
+{
+ Datum val; /* the bound value, if any */
+ bool infinite; /* bound is +/- infinity */
+ bool inclusive; /* bound is inclusive (vs exclusive) */
+ bool lower; /* this is the lower (vs upper) bound */
+} RangeBound;
+
+/*
+ * fmgr functions for range type objects
+ */
+static inline RangeType *
+DatumGetRangeTypeP(Datum X)
+{
+ return (RangeType *) PG_DETOAST_DATUM(X);
+}
+
+static inline RangeType *
+DatumGetRangeTypePCopy(Datum X)
+{
+ return (RangeType *) PG_DETOAST_DATUM_COPY(X);
+}
+
+static inline Datum
+RangeTypePGetDatum(const RangeType *X)
+{
+ return PointerGetDatum(X);
+}
+
+#define PG_GETARG_RANGE_P(n) DatumGetRangeTypeP(PG_GETARG_DATUM(n))
+#define PG_GETARG_RANGE_P_COPY(n) DatumGetRangeTypePCopy(PG_GETARG_DATUM(n))
+#define PG_RETURN_RANGE_P(x) return RangeTypePGetDatum(x)
+
+/* Operator strategy numbers used in the GiST and SP-GiST range opclasses */
+/* Numbers are chosen to match up operator names with existing usages */
+#define RANGESTRAT_BEFORE RTLeftStrategyNumber
+#define RANGESTRAT_OVERLEFT RTOverLeftStrategyNumber
+#define RANGESTRAT_OVERLAPS RTOverlapStrategyNumber
+#define RANGESTRAT_OVERRIGHT RTOverRightStrategyNumber
+#define RANGESTRAT_AFTER RTRightStrategyNumber
+#define RANGESTRAT_ADJACENT RTSameStrategyNumber
+#define RANGESTRAT_CONTAINS RTContainsStrategyNumber
+#define RANGESTRAT_CONTAINED_BY RTContainedByStrategyNumber
+#define RANGESTRAT_CONTAINS_ELEM RTContainsElemStrategyNumber
+#define RANGESTRAT_EQ RTEqualStrategyNumber
+
+/*
+ * prototypes for functions defined in rangetypes.c
+ */
+
+extern bool range_contains_elem_internal(TypeCacheEntry *typcache, const RangeType *r, Datum val);
+
+/* internal versions of the above */
+extern bool range_eq_internal(TypeCacheEntry *typcache, const RangeType *r1,
+ const RangeType *r2);
+extern bool range_ne_internal(TypeCacheEntry *typcache, const RangeType *r1,
+ const RangeType *r2);
+extern bool range_contains_internal(TypeCacheEntry *typcache, const RangeType *r1,
+ const RangeType *r2);
+extern bool range_contained_by_internal(TypeCacheEntry *typcache, const RangeType *r1,
+ const RangeType *r2);
+extern bool range_before_internal(TypeCacheEntry *typcache, const RangeType *r1,
+ const RangeType *r2);
+extern bool range_after_internal(TypeCacheEntry *typcache, const RangeType *r1,
+ const RangeType *r2);
+extern bool range_adjacent_internal(TypeCacheEntry *typcache, const RangeType *r1,
+ const RangeType *r2);
+extern bool range_overlaps_internal(TypeCacheEntry *typcache, const RangeType *r1,
+ const RangeType *r2);
+extern bool range_overleft_internal(TypeCacheEntry *typcache, const RangeType *r1,
+ const RangeType *r2);
+extern bool range_overright_internal(TypeCacheEntry *typcache, const RangeType *r1,
+ const RangeType *r2);
+extern RangeType *range_union_internal(TypeCacheEntry *typcache, RangeType *r1,
+ RangeType *r2, bool strict);
+extern RangeType *range_minus_internal(TypeCacheEntry *typcache, RangeType *r1,
+ RangeType *r2);
+extern RangeType *range_intersect_internal(TypeCacheEntry *typcache, const RangeType *r1,
+ const RangeType *r2);
+
+/* assorted support functions */
+extern TypeCacheEntry *range_get_typcache(FunctionCallInfo fcinfo,
+ Oid rngtypid);
+extern RangeType *range_serialize(TypeCacheEntry *typcache, RangeBound *lower,
+ RangeBound *upper, bool empty,
+ struct Node *escontext);
+extern void range_deserialize(TypeCacheEntry *typcache, const RangeType *range,
+ RangeBound *lower, RangeBound *upper,
+ bool *empty);
+extern char range_get_flags(const RangeType *range);
+extern void range_set_contain_empty(RangeType *range);
+extern RangeType *make_range(TypeCacheEntry *typcache, RangeBound *lower,
+ RangeBound *upper, bool empty,
+ struct Node *escontext);
+extern int range_cmp_bounds(TypeCacheEntry *typcache, const RangeBound *b1,
+ const RangeBound *b2);
+extern int range_cmp_bound_values(TypeCacheEntry *typcache, const RangeBound *b1,
+ const RangeBound *b2);
+extern int range_compare(const void *key1, const void *key2, void *arg);
+extern bool bounds_adjacent(TypeCacheEntry *typcache, RangeBound boundA,
+ RangeBound boundB);
+extern RangeType *make_empty_range(TypeCacheEntry *typcache);
+extern bool range_split_internal(TypeCacheEntry *typcache, const RangeType *r1,
+ const RangeType *r2, RangeType **output1,
+ RangeType **output2);
+
+#endif /* RANGETYPES_H */
diff --git a/src/include/utils/regproc.h b/src/include/utils/regproc.h
new file mode 100644
index 0000000..a1f7c6b
--- /dev/null
+++ b/src/include/utils/regproc.h
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * regproc.h
+ * Functions for the built-in types regproc, regclass, regtype, etc.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/regproc.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef REGPROC_H
+#define REGPROC_H
+
+#include "nodes/pg_list.h"
+
+/* Control flags for format_procedure_extended */
+#define FORMAT_PROC_INVALID_AS_NULL 0x01 /* NULL if undefined */
+#define FORMAT_PROC_FORCE_QUALIFY 0x02 /* force qualification */
+extern char *format_procedure_extended(Oid procedure_oid, bits16 flags);
+
+/* Control flags for format_operator_extended */
+#define FORMAT_OPERATOR_INVALID_AS_NULL 0x01 /* NULL if undefined */
+#define FORMAT_OPERATOR_FORCE_QUALIFY 0x02 /* force qualification */
+extern char *format_operator_extended(Oid operator_oid, bits16 flags);
+
+extern List *stringToQualifiedNameList(const char *string, Node *escontext);
+extern char *format_procedure(Oid procedure_oid);
+extern char *format_procedure_qualified(Oid procedure_oid);
+extern void format_procedure_parts(Oid procedure_oid, List **objnames,
+ List **objargs, bool missing_ok);
+
+extern char *format_operator(Oid operator_oid);
+extern char *format_operator_qualified(Oid operator_oid);
+extern void format_operator_parts(Oid operator_oid, List **objnames,
+ List **objargs, bool missing_ok);
+
+#endif
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
new file mode 100644
index 0000000..1426a35
--- /dev/null
+++ b/src/include/utils/rel.h
@@ -0,0 +1,712 @@
+/*-------------------------------------------------------------------------
+ *
+ * rel.h
+ * POSTGRES relation descriptor (a/k/a relcache entry) definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/rel.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef REL_H
+#define REL_H
+
+#include "access/tupdesc.h"
+#include "access/xlog.h"
+#include "catalog/catalog.h"
+#include "catalog/pg_class.h"
+#include "catalog/pg_index.h"
+#include "catalog/pg_publication.h"
+#include "nodes/bitmapset.h"
+#include "partitioning/partdefs.h"
+#include "rewrite/prs2lock.h"
+#include "storage/block.h"
+#include "storage/relfilelocator.h"
+#include "storage/smgr.h"
+#include "utils/relcache.h"
+#include "utils/reltrigger.h"
+
+
+/*
+ * LockRelId and LockInfo really belong to lmgr.h, but it's more convenient
+ * to declare them here so we can have a LockInfoData field in a Relation.
+ */
+
+typedef struct LockRelId
+{
+ Oid relId; /* a relation identifier */
+ Oid dbId; /* a database identifier */
+} LockRelId;
+
+typedef struct LockInfoData
+{
+ LockRelId lockRelId;
+} LockInfoData;
+
+typedef LockInfoData *LockInfo;
+
+/*
+ * Here are the contents of a relation cache entry.
+ */
+
+typedef struct RelationData
+{
+ RelFileLocator rd_locator; /* relation physical identifier */
+ SMgrRelation rd_smgr; /* cached file handle, or NULL */
+ int rd_refcnt; /* reference count */
+ BackendId rd_backend; /* owning backend id, if temporary relation */
+ bool rd_islocaltemp; /* rel is a temp rel of this session */
+ bool rd_isnailed; /* rel is nailed in cache */
+ bool rd_isvalid; /* relcache entry is valid */
+ bool rd_indexvalid; /* is rd_indexlist valid? (also rd_pkindex and
+ * rd_replidindex) */
+ bool rd_statvalid; /* is rd_statlist valid? */
+
+ /*----------
+ * rd_createSubid is the ID of the highest subtransaction the rel has
+ * survived into or zero if the rel or its storage was created before the
+ * current top transaction. (IndexStmt.oldNumber leads to the case of a new
+ * rel with an old rd_locator.) rd_firstRelfilelocatorSubid is the ID of the
+ * highest subtransaction an rd_locator change has survived into or zero if
+ * rd_locator matches the value it had at the start of the current top
+ * transaction. (Rolling back the subtransaction that
+ * rd_firstRelfilelocatorSubid denotes would restore rd_locator to the value it
+ * had at the start of the current top transaction. Rolling back any
+ * lower subtransaction would not.) Their accuracy is critical to
+ * RelationNeedsWAL().
+ *
+ * rd_newRelfilelocatorSubid is the ID of the highest subtransaction the
+ * most-recent relfilenumber change has survived into or zero if not changed
+ * in the current transaction (or we have forgotten changing it). This
+ * field is accurate when non-zero, but it can be zero when a relation has
+ * multiple new relfilenumbers within a single transaction, with one of them
+ * occurring in a subsequently aborted subtransaction, e.g.
+ * BEGIN;
+ * TRUNCATE t;
+ * SAVEPOINT save;
+ * TRUNCATE t;
+ * ROLLBACK TO save;
+ * -- rd_newRelfilelocatorSubid is now forgotten
+ *
+ * If every rd_*Subid field is zero, they are read-only outside
+ * relcache.c. Files that trigger rd_locator changes by updating
+ * pg_class.reltablespace and/or pg_class.relfilenode call
+ * RelationAssumeNewRelfilelocator() to update rd_*Subid.
+ *
+ * rd_droppedSubid is the ID of the highest subtransaction that a drop of
+ * the rel has survived into. In entries visible outside relcache.c, this
+ * is always zero.
+ */
+ SubTransactionId rd_createSubid; /* rel was created in current xact */
+ SubTransactionId rd_newRelfilelocatorSubid; /* highest subxact changing
+ * rd_locator to current value */
+ SubTransactionId rd_firstRelfilelocatorSubid; /* highest subxact
+ * changing rd_locator to
+ * any value */
+ SubTransactionId rd_droppedSubid; /* dropped with another Subid set */
+
+ Form_pg_class rd_rel; /* RELATION tuple */
+ TupleDesc rd_att; /* tuple descriptor */
+ Oid rd_id; /* relation's object id */
+ LockInfoData rd_lockInfo; /* lock mgr's info for locking relation */
+ RuleLock *rd_rules; /* rewrite rules */
+ MemoryContext rd_rulescxt; /* private memory cxt for rd_rules, if any */
+ TriggerDesc *trigdesc; /* Trigger info, or NULL if rel has none */
+ /* use "struct" here to avoid needing to include rowsecurity.h: */
+ struct RowSecurityDesc *rd_rsdesc; /* row security policies, or NULL */
+
+ /* data managed by RelationGetFKeyList: */
+ List *rd_fkeylist; /* list of ForeignKeyCacheInfo (see below) */
+ bool rd_fkeyvalid; /* true if list has been computed */
+
+ /* data managed by RelationGetPartitionKey: */
+ PartitionKey rd_partkey; /* partition key, or NULL */
+ MemoryContext rd_partkeycxt; /* private context for rd_partkey, if any */
+
+ /* data managed by RelationGetPartitionDesc: */
+ PartitionDesc rd_partdesc; /* partition descriptor, or NULL */
+ MemoryContext rd_pdcxt; /* private context for rd_partdesc, if any */
+
+ /* Same as above, for partdescs that omit detached partitions */
+ PartitionDesc rd_partdesc_nodetached; /* partdesc w/o detached parts */
+ MemoryContext rd_pddcxt; /* for rd_partdesc_nodetached, if any */
+
+ /*
+ * pg_inherits.xmin of the partition that was excluded in
+ * rd_partdesc_nodetached. This informs a future user of that partdesc:
+ * if this value is not in progress for the active snapshot, then the
+ * partdesc can be used, otherwise they have to build a new one. (This
+ * matches what find_inheritance_children_extended would do).
+ */
+ TransactionId rd_partdesc_nodetached_xmin;
+
+ /* data managed by RelationGetPartitionQual: */
+ List *rd_partcheck; /* partition CHECK quals */
+ bool rd_partcheckvalid; /* true if list has been computed */
+ MemoryContext rd_partcheckcxt; /* private cxt for rd_partcheck, if any */
+
+ /* data managed by RelationGetIndexList: */
+ List *rd_indexlist; /* list of OIDs of indexes on relation */
+ Oid rd_pkindex; /* OID of primary key, if any */
+ Oid rd_replidindex; /* OID of replica identity index, if any */
+
+ /* data managed by RelationGetStatExtList: */
+ List *rd_statlist; /* list of OIDs of extended stats */
+
+ /* data managed by RelationGetIndexAttrBitmap: */
+ bool rd_attrsvalid; /* are bitmaps of attrs valid? */
+ Bitmapset *rd_keyattr; /* cols that can be ref'd by foreign keys */
+ Bitmapset *rd_pkattr; /* cols included in primary key */
+ Bitmapset *rd_idattr; /* included in replica identity index */
+ Bitmapset *rd_hotblockingattr; /* cols blocking HOT update */
+ Bitmapset *rd_summarizedattr; /* cols indexed by summarizing indexes */
+
+ PublicationDesc *rd_pubdesc; /* publication descriptor, or NULL */
+
+ /*
+ * rd_options is set whenever rd_rel is loaded into the relcache entry.
+ * Note that you can NOT look into rd_rel for this data. NULL means "use
+ * defaults".
+ */
+ bytea *rd_options; /* parsed pg_class.reloptions */
+
+ /*
+ * Oid of the handler for this relation. For an index this is a function
+ * returning IndexAmRoutine, for table like relations a function returning
+ * TableAmRoutine. This is stored separately from rd_indam, rd_tableam as
+ * its lookup requires syscache access, but during relcache bootstrap we
+ * need to be able to initialize rd_tableam without syscache lookups.
+ */
+ Oid rd_amhandler; /* OID of index AM's handler function */
+
+ /*
+ * Table access method.
+ */
+ const struct TableAmRoutine *rd_tableam;
+
+ /* These are non-NULL only for an index relation: */
+ Form_pg_index rd_index; /* pg_index tuple describing this index */
+ /* use "struct" here to avoid needing to include htup.h: */
+ struct HeapTupleData *rd_indextuple; /* all of pg_index tuple */
+
+ /*
+ * index access support info (used only for an index relation)
+ *
+ * Note: only default support procs for each opclass are cached, namely
+ * those with lefttype and righttype equal to the opclass's opcintype. The
+ * arrays are indexed by support function number, which is a sufficient
+ * identifier given that restriction.
+ */
+ MemoryContext rd_indexcxt; /* private memory cxt for this stuff */
+ /* use "struct" here to avoid needing to include amapi.h: */
+ struct IndexAmRoutine *rd_indam; /* index AM's API struct */
+ Oid *rd_opfamily; /* OIDs of op families for each index col */
+ Oid *rd_opcintype; /* OIDs of opclass declared input data types */
+ RegProcedure *rd_support; /* OIDs of support procedures */
+ struct FmgrInfo *rd_supportinfo; /* lookup info for support procedures */
+ int16 *rd_indoption; /* per-column AM-specific flags */
+ List *rd_indexprs; /* index expression trees, if any */
+ List *rd_indpred; /* index predicate tree, if any */
+ Oid *rd_exclops; /* OIDs of exclusion operators, if any */
+ Oid *rd_exclprocs; /* OIDs of exclusion ops' procs, if any */
+ uint16 *rd_exclstrats; /* exclusion ops' strategy numbers, if any */
+ Oid *rd_indcollation; /* OIDs of index collations */
+ bytea **rd_opcoptions; /* parsed opclass-specific options */
+
+ /*
+ * rd_amcache is available for index and table AMs to cache private data
+ * about the relation. This must be just a cache since it may get reset
+ * at any time (in particular, it will get reset by a relcache inval
+ * message for the relation). If used, it must point to a single memory
+ * chunk palloc'd in CacheMemoryContext, or in rd_indexcxt for an index
+ * relation. A relcache reset will include freeing that chunk and setting
+ * rd_amcache = NULL.
+ */
+ void *rd_amcache; /* available for use by index/table AM */
+
+ /*
+ * foreign-table support
+ *
+ * rd_fdwroutine must point to a single memory chunk palloc'd in
+ * CacheMemoryContext. It will be freed and reset to NULL on a relcache
+ * reset.
+ */
+
+ /* use "struct" here to avoid needing to include fdwapi.h: */
+ struct FdwRoutine *rd_fdwroutine; /* cached function pointers, or NULL */
+
+ /*
+ * 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 rd_toastoid; /* Real TOAST table's OID, or InvalidOid */
+
+ bool pgstat_enabled; /* should relation stats be counted */
+ /* use "struct" here to avoid needing to include pgstat.h: */
+ struct PgStat_TableStatus *pgstat_info; /* statistics collection area */
+} RelationData;
+
+
+/*
+ * ForeignKeyCacheInfo
+ * Information the relcache can cache about foreign key constraints
+ *
+ * This is basically just an image of relevant columns from pg_constraint.
+ * We make it a subclass of Node so that copyObject() can be used on a list
+ * of these, but we also ensure it is a "flat" object without substructure,
+ * so that list_free_deep() is sufficient to free such a list.
+ * The per-FK-column arrays can be fixed-size because we allow at most
+ * INDEX_MAX_KEYS columns in a foreign key constraint.
+ *
+ * Currently, we mostly cache fields of interest to the planner, but the set
+ * of fields has already grown the constraint OID for other uses.
+ */
+typedef struct ForeignKeyCacheInfo
+{
+ pg_node_attr(no_equal, no_read, no_query_jumble)
+
+ NodeTag type;
+ /* oid of the constraint itself */
+ Oid conoid;
+ /* relation constrained by the foreign key */
+ Oid conrelid;
+ /* relation referenced by the foreign key */
+ Oid confrelid;
+ /* number of columns in the foreign key */
+ int nkeys;
+
+ /*
+ * these arrays each have nkeys valid entries:
+ */
+ /* cols in referencing table */
+ AttrNumber conkey[INDEX_MAX_KEYS] pg_node_attr(array_size(nkeys));
+ /* cols in referenced table */
+ AttrNumber confkey[INDEX_MAX_KEYS] pg_node_attr(array_size(nkeys));
+ /* PK = FK operator OIDs */
+ Oid conpfeqop[INDEX_MAX_KEYS] pg_node_attr(array_size(nkeys));
+} ForeignKeyCacheInfo;
+
+
+/*
+ * StdRdOptions
+ * Standard contents of rd_options for heaps.
+ *
+ * RelationGetFillFactor() and RelationGetTargetPageFreeSpace() can only
+ * be applied to relations that use this format or a superset for
+ * private options data.
+ */
+ /* autovacuum-related reloptions. */
+typedef struct AutoVacOpts
+{
+ bool enabled;
+ int vacuum_threshold;
+ int vacuum_ins_threshold;
+ int analyze_threshold;
+ int vacuum_cost_limit;
+ int freeze_min_age;
+ int freeze_max_age;
+ int freeze_table_age;
+ int multixact_freeze_min_age;
+ int multixact_freeze_max_age;
+ int multixact_freeze_table_age;
+ int log_min_duration;
+ float8 vacuum_cost_delay;
+ float8 vacuum_scale_factor;
+ float8 vacuum_ins_scale_factor;
+ float8 analyze_scale_factor;
+} AutoVacOpts;
+
+/* StdRdOptions->vacuum_index_cleanup values */
+typedef enum StdRdOptIndexCleanup
+{
+ STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO = 0,
+ STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF,
+ STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON
+} StdRdOptIndexCleanup;
+
+typedef struct StdRdOptions
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ int fillfactor; /* page fill factor in percent (0..100) */
+ int toast_tuple_target; /* target for tuple toasting */
+ AutoVacOpts autovacuum; /* autovacuum-related options */
+ bool user_catalog_table; /* use as an additional catalog relation */
+ int parallel_workers; /* max number of parallel workers */
+ StdRdOptIndexCleanup vacuum_index_cleanup; /* controls index vacuuming */
+ bool vacuum_truncate; /* enables vacuum to truncate a relation */
+} StdRdOptions;
+
+#define HEAP_MIN_FILLFACTOR 10
+#define HEAP_DEFAULT_FILLFACTOR 100
+
+/*
+ * RelationGetToastTupleTarget
+ * Returns the relation's toast_tuple_target. Note multiple eval of argument!
+ */
+#define RelationGetToastTupleTarget(relation, defaulttarg) \
+ ((relation)->rd_options ? \
+ ((StdRdOptions *) (relation)->rd_options)->toast_tuple_target : (defaulttarg))
+
+/*
+ * RelationGetFillFactor
+ * Returns the relation's fillfactor. Note multiple eval of argument!
+ */
+#define RelationGetFillFactor(relation, defaultff) \
+ ((relation)->rd_options ? \
+ ((StdRdOptions *) (relation)->rd_options)->fillfactor : (defaultff))
+
+/*
+ * RelationGetTargetPageUsage
+ * Returns the relation's desired space usage per page in bytes.
+ */
+#define RelationGetTargetPageUsage(relation, defaultff) \
+ (BLCKSZ * RelationGetFillFactor(relation, defaultff) / 100)
+
+/*
+ * RelationGetTargetPageFreeSpace
+ * Returns the relation's desired freespace per page in bytes.
+ */
+#define RelationGetTargetPageFreeSpace(relation, defaultff) \
+ (BLCKSZ * (100 - RelationGetFillFactor(relation, defaultff)) / 100)
+
+/*
+ * RelationIsUsedAsCatalogTable
+ * Returns whether the relation should be treated as a catalog table
+ * from the pov of logical decoding. Note multiple eval of argument!
+ */
+#define RelationIsUsedAsCatalogTable(relation) \
+ ((relation)->rd_options && \
+ ((relation)->rd_rel->relkind == RELKIND_RELATION || \
+ (relation)->rd_rel->relkind == RELKIND_MATVIEW) ? \
+ ((StdRdOptions *) (relation)->rd_options)->user_catalog_table : false)
+
+/*
+ * RelationGetParallelWorkers
+ * Returns the relation's parallel_workers reloption setting.
+ * Note multiple eval of argument!
+ */
+#define RelationGetParallelWorkers(relation, defaultpw) \
+ ((relation)->rd_options ? \
+ ((StdRdOptions *) (relation)->rd_options)->parallel_workers : (defaultpw))
+
+/* ViewOptions->check_option values */
+typedef enum ViewOptCheckOption
+{
+ VIEW_OPTION_CHECK_OPTION_NOT_SET,
+ VIEW_OPTION_CHECK_OPTION_LOCAL,
+ VIEW_OPTION_CHECK_OPTION_CASCADED
+} ViewOptCheckOption;
+
+/*
+ * ViewOptions
+ * Contents of rd_options for views
+ */
+typedef struct ViewOptions
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ bool security_barrier;
+ bool security_invoker;
+ ViewOptCheckOption check_option;
+} ViewOptions;
+
+/*
+ * RelationIsSecurityView
+ * Returns whether the relation is security view, or not. Note multiple
+ * eval of argument!
+ */
+#define RelationIsSecurityView(relation) \
+ (AssertMacro(relation->rd_rel->relkind == RELKIND_VIEW), \
+ (relation)->rd_options ? \
+ ((ViewOptions *) (relation)->rd_options)->security_barrier : false)
+
+/*
+ * RelationHasSecurityInvoker
+ * Returns true if the relation has the security_invoker property set.
+ * Note multiple eval of argument!
+ */
+#define RelationHasSecurityInvoker(relation) \
+ (AssertMacro(relation->rd_rel->relkind == RELKIND_VIEW), \
+ (relation)->rd_options ? \
+ ((ViewOptions *) (relation)->rd_options)->security_invoker : false)
+
+/*
+ * RelationHasCheckOption
+ * Returns true if the relation is a view defined with either the local
+ * or the cascaded check option. Note multiple eval of argument!
+ */
+#define RelationHasCheckOption(relation) \
+ (AssertMacro(relation->rd_rel->relkind == RELKIND_VIEW), \
+ (relation)->rd_options && \
+ ((ViewOptions *) (relation)->rd_options)->check_option != \
+ VIEW_OPTION_CHECK_OPTION_NOT_SET)
+
+/*
+ * RelationHasLocalCheckOption
+ * Returns true if the relation is a view defined with the local check
+ * option. Note multiple eval of argument!
+ */
+#define RelationHasLocalCheckOption(relation) \
+ (AssertMacro(relation->rd_rel->relkind == RELKIND_VIEW), \
+ (relation)->rd_options && \
+ ((ViewOptions *) (relation)->rd_options)->check_option == \
+ VIEW_OPTION_CHECK_OPTION_LOCAL)
+
+/*
+ * RelationHasCascadedCheckOption
+ * Returns true if the relation is a view defined with the cascaded check
+ * option. Note multiple eval of argument!
+ */
+#define RelationHasCascadedCheckOption(relation) \
+ (AssertMacro(relation->rd_rel->relkind == RELKIND_VIEW), \
+ (relation)->rd_options && \
+ ((ViewOptions *) (relation)->rd_options)->check_option == \
+ VIEW_OPTION_CHECK_OPTION_CASCADED)
+
+/*
+ * RelationIsValid
+ * True iff relation descriptor is valid.
+ */
+#define RelationIsValid(relation) PointerIsValid(relation)
+
+#define InvalidRelation ((Relation) NULL)
+
+/*
+ * RelationHasReferenceCountZero
+ * True iff relation reference count is zero.
+ *
+ * Note:
+ * Assumes relation descriptor is valid.
+ */
+#define RelationHasReferenceCountZero(relation) \
+ ((bool)((relation)->rd_refcnt == 0))
+
+/*
+ * RelationGetForm
+ * Returns pg_class tuple for a relation.
+ *
+ * Note:
+ * Assumes relation descriptor is valid.
+ */
+#define RelationGetForm(relation) ((relation)->rd_rel)
+
+/*
+ * RelationGetRelid
+ * Returns the OID of the relation
+ */
+#define RelationGetRelid(relation) ((relation)->rd_id)
+
+/*
+ * RelationGetNumberOfAttributes
+ * Returns the total number of attributes in a relation.
+ */
+#define RelationGetNumberOfAttributes(relation) ((relation)->rd_rel->relnatts)
+
+/*
+ * IndexRelationGetNumberOfAttributes
+ * Returns the number of attributes in an index.
+ */
+#define IndexRelationGetNumberOfAttributes(relation) \
+ ((relation)->rd_index->indnatts)
+
+/*
+ * IndexRelationGetNumberOfKeyAttributes
+ * Returns the number of key attributes in an index.
+ */
+#define IndexRelationGetNumberOfKeyAttributes(relation) \
+ ((relation)->rd_index->indnkeyatts)
+
+/*
+ * RelationGetDescr
+ * Returns tuple descriptor for a relation.
+ */
+#define RelationGetDescr(relation) ((relation)->rd_att)
+
+/*
+ * RelationGetRelationName
+ * Returns the rel's name.
+ *
+ * Note that the name is only unique within the containing namespace.
+ */
+#define RelationGetRelationName(relation) \
+ (NameStr((relation)->rd_rel->relname))
+
+/*
+ * RelationGetNamespace
+ * Returns the rel's namespace OID.
+ */
+#define RelationGetNamespace(relation) \
+ ((relation)->rd_rel->relnamespace)
+
+/*
+ * RelationIsMapped
+ * True if the relation uses the relfilenumber map. Note multiple eval
+ * of argument!
+ */
+#define RelationIsMapped(relation) \
+ (RELKIND_HAS_STORAGE((relation)->rd_rel->relkind) && \
+ ((relation)->rd_rel->relfilenode == InvalidRelFileNumber))
+
+#ifndef FRONTEND
+/*
+ * RelationGetSmgr
+ * Returns smgr file handle for a relation, opening it if needed.
+ *
+ * Very little code is authorized to touch rel->rd_smgr directly. Instead
+ * use this function to fetch its value.
+ *
+ * Note: since a relcache flush can cause the file handle to be closed again,
+ * it's unwise to hold onto the pointer returned by this function for any
+ * long period. Recommended practice is to just re-execute RelationGetSmgr
+ * each time you need to access the SMgrRelation. It's quite cheap in
+ * comparison to whatever an smgr function is going to do.
+ */
+static inline SMgrRelation
+RelationGetSmgr(Relation rel)
+{
+ if (unlikely(rel->rd_smgr == NULL))
+ smgrsetowner(&(rel->rd_smgr), smgropen(rel->rd_locator, rel->rd_backend));
+ return rel->rd_smgr;
+}
+
+/*
+ * RelationCloseSmgr
+ * Close the relation at the smgr level, if not already done.
+ */
+static inline void
+RelationCloseSmgr(Relation relation)
+{
+ if (relation->rd_smgr != NULL)
+ smgrclose(relation->rd_smgr);
+
+ /* smgrclose should unhook from owner pointer */
+ Assert(relation->rd_smgr == NULL);
+}
+#endif /* !FRONTEND */
+
+/*
+ * RelationGetTargetBlock
+ * Fetch relation'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,
+ * so there's no need to re-open the smgr handle if it's not currently open.
+ */
+#define RelationGetTargetBlock(relation) \
+ ( (relation)->rd_smgr != NULL ? (relation)->rd_smgr->smgr_targblock : InvalidBlockNumber )
+
+/*
+ * RelationSetTargetBlock
+ * Set relation's current insertion target block.
+ */
+#define RelationSetTargetBlock(relation, targblock) \
+ do { \
+ RelationGetSmgr(relation)->smgr_targblock = (targblock); \
+ } while (0)
+
+/*
+ * RelationIsPermanent
+ * True if relation is permanent.
+ */
+#define RelationIsPermanent(relation) \
+ ((relation)->rd_rel->relpersistence == RELPERSISTENCE_PERMANENT)
+
+/*
+ * RelationNeedsWAL
+ * True if relation needs WAL.
+ *
+ * Returns false if wal_level = minimal and this relation is created or
+ * truncated in the current transaction. See "Skipping WAL for New
+ * RelFileLocator" in src/backend/access/transam/README.
+ */
+#define RelationNeedsWAL(relation) \
+ (RelationIsPermanent(relation) && (XLogIsNeeded() || \
+ (relation->rd_createSubid == InvalidSubTransactionId && \
+ relation->rd_firstRelfilelocatorSubid == InvalidSubTransactionId)))
+
+/*
+ * RelationUsesLocalBuffers
+ * True if relation's pages are stored in local buffers.
+ */
+#define RelationUsesLocalBuffers(relation) \
+ ((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
+
+/*
+ * RELATION_IS_LOCAL
+ * If a rel is either temp or newly created in the current transaction,
+ * it can be assumed to be accessible only to the current backend.
+ * This is typically used to decide that we can skip acquiring locks.
+ *
+ * Beware of multiple eval of argument
+ */
+#define RELATION_IS_LOCAL(relation) \
+ ((relation)->rd_islocaltemp || \
+ (relation)->rd_createSubid != InvalidSubTransactionId)
+
+/*
+ * 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) \
+ ((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP && \
+ !(relation)->rd_islocaltemp)
+
+
+/*
+ * RelationIsScannable
+ * Currently can only be false for a materialized view which has not been
+ * populated by its query. This is likely to get more complicated later,
+ * so use a macro which looks like a function.
+ */
+#define RelationIsScannable(relation) ((relation)->rd_rel->relispopulated)
+
+/*
+ * RelationIsPopulated
+ * Currently, we don't physically distinguish the "populated" and
+ * "scannable" properties of matviews, but that may change later.
+ * Hence, use the appropriate one of these macros in code tests.
+ */
+#define RelationIsPopulated(relation) ((relation)->rd_rel->relispopulated)
+
+/*
+ * RelationIsAccessibleInLogicalDecoding
+ * True if we need to log enough information to have access via
+ * decoding snapshot.
+ */
+#define RelationIsAccessibleInLogicalDecoding(relation) \
+ (XLogLogicalInfoActive() && \
+ RelationNeedsWAL(relation) && \
+ (IsCatalogRelation(relation) || RelationIsUsedAsCatalogTable(relation)))
+
+/*
+ * RelationIsLogicallyLogged
+ * True if we need to log enough information to extract the data from the
+ * WAL stream.
+ *
+ * We don't log information for unlogged tables (since they don't WAL log
+ * anyway), for foreign tables (since they don't WAL log, either),
+ * and for system tables (their content is hard to make sense of, and
+ * it would complicate decoding slightly for little gain). Note that we *do*
+ * log information for user defined catalog tables since they presumably are
+ * interesting to the user...
+ */
+#define RelationIsLogicallyLogged(relation) \
+ (XLogLogicalInfoActive() && \
+ RelationNeedsWAL(relation) && \
+ (relation)->rd_rel->relkind != RELKIND_FOREIGN_TABLE && \
+ !IsCatalogRelation(relation))
+
+/* routines in utils/cache/relcache.c */
+extern void RelationIncrementReferenceCount(Relation rel);
+extern void RelationDecrementReferenceCount(Relation rel);
+
+#endif /* REL_H */
diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h
new file mode 100644
index 0000000..3852464
--- /dev/null
+++ b/src/include/utils/relcache.h
@@ -0,0 +1,158 @@
+/*-------------------------------------------------------------------------
+ *
+ * relcache.h
+ * Relation descriptor cache definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/relcache.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RELCACHE_H
+#define RELCACHE_H
+
+#include "access/tupdesc.h"
+#include "common/relpath.h"
+#include "nodes/bitmapset.h"
+
+
+/*
+ * Name of relcache init file(s), used to speed up backend startup
+ */
+#define RELCACHE_INIT_FILENAME "pg_internal.init"
+
+typedef struct RelationData *Relation;
+
+/* ----------------
+ * RelationPtr is used in the executor to support index scans
+ * where we have to keep track of several index relations in an
+ * array. -cim 9/10/89
+ * ----------------
+ */
+typedef Relation *RelationPtr;
+
+/*
+ * Routines to open (lookup) and close a relcache entry
+ */
+extern Relation RelationIdGetRelation(Oid relationId);
+extern void RelationClose(Relation relation);
+
+/*
+ * Routines to compute/retrieve additional cached information
+ */
+extern List *RelationGetFKeyList(Relation relation);
+extern List *RelationGetIndexList(Relation relation);
+extern List *RelationGetStatExtList(Relation relation);
+extern Oid RelationGetPrimaryKeyIndex(Relation relation);
+extern Oid RelationGetReplicaIndex(Relation relation);
+extern List *RelationGetIndexExpressions(Relation relation);
+extern List *RelationGetDummyIndexExpressions(Relation relation);
+extern List *RelationGetIndexPredicate(Relation relation);
+extern Datum *RelationGetIndexRawAttOptions(Relation indexrel);
+extern bytea **RelationGetIndexAttOptions(Relation relation, bool copy);
+
+/*
+ * Which set of columns to return by RelationGetIndexAttrBitmap.
+ */
+typedef enum IndexAttrBitmapKind
+{
+ INDEX_ATTR_BITMAP_KEY,
+ INDEX_ATTR_BITMAP_PRIMARY_KEY,
+ INDEX_ATTR_BITMAP_IDENTITY_KEY,
+ INDEX_ATTR_BITMAP_HOT_BLOCKING,
+ INDEX_ATTR_BITMAP_SUMMARIZED
+} IndexAttrBitmapKind;
+
+extern Bitmapset *RelationGetIndexAttrBitmap(Relation relation,
+ IndexAttrBitmapKind attrKind);
+
+extern Bitmapset *RelationGetIdentityKeyBitmap(Relation relation);
+
+extern void RelationGetExclusionInfo(Relation indexRelation,
+ Oid **operators,
+ Oid **procs,
+ uint16 **strategies);
+
+extern void RelationInitIndexAccessInfo(Relation relation);
+
+/* caller must include pg_publication.h */
+struct PublicationDesc;
+extern void RelationBuildPublicationDesc(Relation relation,
+ struct PublicationDesc *pubdesc);
+
+extern void RelationInitTableAccessMethod(Relation relation);
+
+/*
+ * Routines to support ereport() reports of relation-related errors
+ */
+extern int errtable(Relation rel);
+extern int errtablecol(Relation rel, int attnum);
+extern int errtablecolname(Relation rel, const char *colname);
+extern int errtableconstraint(Relation rel, const char *conname);
+
+/*
+ * Routines for backend startup
+ */
+extern void RelationCacheInitialize(void);
+extern void RelationCacheInitializePhase2(void);
+extern void RelationCacheInitializePhase3(void);
+
+/*
+ * Routine to create a relcache entry for an about-to-be-created relation
+ */
+extern Relation RelationBuildLocalRelation(const char *relname,
+ Oid relnamespace,
+ TupleDesc tupDesc,
+ Oid relid,
+ Oid accessmtd,
+ RelFileNumber relfilenumber,
+ Oid reltablespace,
+ bool shared_relation,
+ bool mapped_relation,
+ char relpersistence,
+ char relkind);
+
+/*
+ * Routines to manage assignment of new relfilenumber to a relation
+ */
+extern void RelationSetNewRelfilenumber(Relation relation, char persistence);
+extern void RelationAssumeNewRelfilelocator(Relation relation);
+
+/*
+ * Routines for flushing/rebuilding relcache entries in various scenarios
+ */
+extern void RelationForgetRelation(Oid rid);
+
+extern void RelationCacheInvalidateEntry(Oid relationId);
+
+extern void RelationCacheInvalidate(bool debug_discard);
+
+extern void RelationCloseSmgrByOid(Oid relationId);
+
+#ifdef USE_ASSERT_CHECKING
+extern void AssertPendingSyncs_RelationCache(void);
+#else
+#define AssertPendingSyncs_RelationCache() do {} while (0)
+#endif
+extern void AtEOXact_RelationCache(bool isCommit);
+extern void AtEOSubXact_RelationCache(bool isCommit, SubTransactionId mySubid,
+ SubTransactionId parentSubid);
+
+/*
+ * Routines to help manage rebuilding of relcache init files
+ */
+extern bool RelationIdIsInInitFile(Oid relationId);
+extern void RelationCacheInitFilePreInvalidate(void);
+extern void RelationCacheInitFilePostInvalidate(void);
+extern void RelationCacheInitFileRemove(void);
+
+/* should be used only by relcache.c and catcache.c */
+extern PGDLLIMPORT bool criticalRelcachesBuilt;
+
+/* should be used only by relcache.c and postinit.c */
+extern PGDLLIMPORT bool criticalSharedRelcachesBuilt;
+
+#endif /* RELCACHE_H */
diff --git a/src/include/utils/relfilenumbermap.h b/src/include/utils/relfilenumbermap.h
new file mode 100644
index 0000000..d9b280d
--- /dev/null
+++ b/src/include/utils/relfilenumbermap.h
@@ -0,0 +1,21 @@
+/*-------------------------------------------------------------------------
+ *
+ * relfilenumbermap.h
+ * relfilenumber to oid mapping cache.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/relfilenumbermap.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RELFILENUMBERMAP_H
+#define RELFILENUMBERMAP_H
+
+#include "common/relpath.h"
+
+extern Oid RelidByRelfilenumber(Oid reltablespace,
+ RelFileNumber relfilenumber);
+
+#endif /* RELFILENUMBERMAP_H */
diff --git a/src/include/utils/relmapper.h b/src/include/utils/relmapper.h
new file mode 100644
index 0000000..5c173bd
--- /dev/null
+++ b/src/include/utils/relmapper.h
@@ -0,0 +1,73 @@
+/*-------------------------------------------------------------------------
+ *
+ * relmapper.h
+ * Catalog-to-filenumber mapping
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/relmapper.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RELMAPPER_H
+#define RELMAPPER_H
+
+#include "access/xlogreader.h"
+#include "lib/stringinfo.h"
+
+/* ----------------
+ * relmap-related XLOG entries
+ * ----------------
+ */
+
+#define XLOG_RELMAP_UPDATE 0x00
+
+typedef struct xl_relmap_update
+{
+ Oid dbid; /* database ID, or 0 for shared map */
+ Oid tsid; /* database's tablespace, or pg_global */
+ int32 nbytes; /* size of relmap data */
+ char data[FLEXIBLE_ARRAY_MEMBER];
+} xl_relmap_update;
+
+#define MinSizeOfRelmapUpdate offsetof(xl_relmap_update, data)
+
+
+extern RelFileNumber RelationMapOidToFilenumber(Oid relationId, bool shared);
+
+extern Oid RelationMapFilenumberToOid(RelFileNumber filenumber, bool shared);
+extern RelFileNumber RelationMapOidToFilenumberForDatabase(char *dbpath,
+ Oid relationId);
+extern void RelationMapCopy(Oid dbid, Oid tsid, char *srcdbpath,
+ char *dstdbpath);
+extern void RelationMapUpdateMap(Oid relationId, RelFileNumber fileNumber,
+ bool shared, bool immediate);
+
+extern void RelationMapRemoveMapping(Oid relationId);
+
+extern void RelationMapInvalidate(bool shared);
+extern void RelationMapInvalidateAll(void);
+
+extern void AtCCI_RelationMap(void);
+extern void AtEOXact_RelationMap(bool isCommit, bool isParallelWorker);
+extern void AtPrepare_RelationMap(void);
+
+extern void CheckPointRelationMap(void);
+
+extern void RelationMapFinishBootstrap(void);
+
+extern void RelationMapInitialize(void);
+extern void RelationMapInitializePhase2(void);
+extern void RelationMapInitializePhase3(void);
+
+extern Size EstimateRelationMapSpace(void);
+extern void SerializeRelationMap(Size maxSize, char *startAddress);
+extern void RestoreRelationMap(char *startAddress);
+
+extern void relmap_redo(XLogReaderState *record);
+extern void relmap_desc(StringInfo buf, XLogReaderState *record);
+extern const char *relmap_identify(uint8 info);
+
+#endif /* RELMAPPER_H */
diff --git a/src/include/utils/relptr.h b/src/include/utils/relptr.h
new file mode 100644
index 0000000..365cea1
--- /dev/null
+++ b/src/include/utils/relptr.h
@@ -0,0 +1,93 @@
+/*-------------------------------------------------------------------------
+ *
+ * relptr.h
+ * This file contains basic declarations for relative pointers.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/relptr.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef RELPTR_H
+#define RELPTR_H
+
+/*
+ * Relative pointers are intended to be used when storing an address that may
+ * be relative either to the base of the process's address space or some
+ * dynamic shared memory segment mapped therein.
+ *
+ * The idea here is that you declare a relative pointer as relptr(type)
+ * and then use relptr_access to dereference it and relptr_store to change
+ * it. The use of a union here is a hack, because what's stored in the
+ * relptr is always a Size, never an actual pointer. But including a pointer
+ * in the union allows us to use stupid macro tricks to provide some measure
+ * of type-safety.
+ */
+#define relptr(type) union { type *relptr_type; Size relptr_off; }
+
+/*
+ * pgindent gets confused by declarations that use "relptr(type)" directly,
+ * so preferred style is to write
+ * typedef struct ... SomeStruct;
+ * relptr_declare(SomeStruct, RelptrSomeStruct);
+ * and then declare pointer variables as "RelptrSomeStruct someptr".
+ */
+#define relptr_declare(type, relptrtype) \
+ typedef relptr(type) relptrtype
+
+#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
+#define relptr_access(base, rp) \
+ (AssertVariableIsOfTypeMacro(base, char *), \
+ (__typeof__((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \
+ (base) + (rp).relptr_off - 1))
+#else
+/*
+ * If we don't have __builtin_types_compatible_p, assume we might not have
+ * __typeof__ either.
+ */
+#define relptr_access(base, rp) \
+ (AssertVariableIsOfTypeMacro(base, char *), \
+ (void *) ((rp).relptr_off == 0 ? NULL : (base) + (rp).relptr_off - 1))
+#endif
+
+#define relptr_is_null(rp) \
+ ((rp).relptr_off == 0)
+
+#define relptr_offset(rp) \
+ ((rp).relptr_off - 1)
+
+/* We use this inline to avoid double eval of "val" in relptr_store */
+static inline Size
+relptr_store_eval(char *base, char *val)
+{
+ if (val == NULL)
+ return 0;
+ else
+ {
+ Assert(val >= base);
+ return val - base + 1;
+ }
+}
+
+#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
+#define relptr_store(base, rp, val) \
+ (AssertVariableIsOfTypeMacro(base, char *), \
+ AssertVariableIsOfTypeMacro(val, __typeof__((rp).relptr_type)), \
+ (rp).relptr_off = relptr_store_eval((base), (char *) (val)))
+#else
+/*
+ * If we don't have __builtin_types_compatible_p, assume we might not have
+ * __typeof__ either.
+ */
+#define relptr_store(base, rp, val) \
+ (AssertVariableIsOfTypeMacro(base, char *), \
+ (rp).relptr_off = relptr_store_eval((base), (char *) (val)))
+#endif
+
+#define relptr_copy(rp1, rp2) \
+ ((rp1).relptr_off = (rp2).relptr_off)
+
+#endif /* RELPTR_H */
diff --git a/src/include/utils/reltrigger.h b/src/include/utils/reltrigger.h
new file mode 100644
index 0000000..df9a2fb
--- /dev/null
+++ b/src/include/utils/reltrigger.h
@@ -0,0 +1,81 @@
+/*-------------------------------------------------------------------------
+ *
+ * reltrigger.h
+ * POSTGRES relation trigger definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/reltrigger.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RELTRIGGER_H
+#define RELTRIGGER_H
+
+
+/*
+ * These struct really belongs to trigger.h, but we put it separately so that
+ * it can be cleanly included in rel.h and other places.
+ */
+
+typedef struct Trigger
+{
+ Oid tgoid; /* OID of trigger (pg_trigger row) */
+ /* Remaining fields are copied from pg_trigger, see pg_trigger.h */
+ char *tgname;
+ Oid tgfoid;
+ int16 tgtype;
+ char tgenabled;
+ bool tgisinternal;
+ bool tgisclone;
+ Oid tgconstrrelid;
+ Oid tgconstrindid;
+ Oid tgconstraint;
+ bool tgdeferrable;
+ bool tginitdeferred;
+ int16 tgnargs;
+ int16 tgnattr;
+ int16 *tgattr;
+ char **tgargs;
+ char *tgqual;
+ char *tgoldtable;
+ char *tgnewtable;
+} Trigger;
+
+typedef struct TriggerDesc
+{
+ Trigger *triggers; /* array of Trigger structs */
+ int numtriggers; /* number of array entries */
+
+ /*
+ * These flags indicate whether the array contains at least one of each
+ * type of trigger. We use these to skip searching the array if not.
+ */
+ bool trig_insert_before_row;
+ bool trig_insert_after_row;
+ bool trig_insert_instead_row;
+ bool trig_insert_before_statement;
+ bool trig_insert_after_statement;
+ bool trig_update_before_row;
+ bool trig_update_after_row;
+ bool trig_update_instead_row;
+ bool trig_update_before_statement;
+ bool trig_update_after_statement;
+ bool trig_delete_before_row;
+ bool trig_delete_after_row;
+ bool trig_delete_instead_row;
+ bool trig_delete_before_statement;
+ bool trig_delete_after_statement;
+ /* there are no row-level truncate triggers */
+ bool trig_truncate_before_statement;
+ bool trig_truncate_after_statement;
+ /* Is there at least one trigger specifying each transition relation? */
+ bool trig_insert_new_table;
+ bool trig_update_old_table;
+ bool trig_update_new_table;
+ bool trig_delete_old_table;
+} TriggerDesc;
+
+#endif /* RELTRIGGER_H */
diff --git a/src/include/utils/resowner.h b/src/include/utils/resowner.h
new file mode 100644
index 0000000..cd070b6
--- /dev/null
+++ b/src/include/utils/resowner.h
@@ -0,0 +1,86 @@
+/*-------------------------------------------------------------------------
+ *
+ * resowner.h
+ * POSTGRES resource owner definitions.
+ *
+ * Query-lifespan resources are tracked by associating them with
+ * ResourceOwner objects. This provides a simple mechanism for ensuring
+ * that such resources are freed at the right time.
+ * See utils/resowner/README for more info.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/resowner.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RESOWNER_H
+#define RESOWNER_H
+
+
+/*
+ * ResourceOwner objects are an opaque data structure known only within
+ * resowner.c.
+ */
+typedef struct ResourceOwnerData *ResourceOwner;
+
+
+/*
+ * Globally known ResourceOwners
+ */
+extern PGDLLIMPORT ResourceOwner CurrentResourceOwner;
+extern PGDLLIMPORT ResourceOwner CurTransactionResourceOwner;
+extern PGDLLIMPORT ResourceOwner TopTransactionResourceOwner;
+extern PGDLLIMPORT ResourceOwner AuxProcessResourceOwner;
+
+/*
+ * Resource releasing is done in three phases: pre-locks, locks, and
+ * post-locks. The pre-lock phase must release any resources that are
+ * visible to other backends (such as pinned buffers); this ensures that
+ * when we release a lock that another backend may be waiting on, it will
+ * see us as being fully out of our transaction. The post-lock phase
+ * should be used for backend-internal cleanup.
+ */
+typedef enum
+{
+ RESOURCE_RELEASE_BEFORE_LOCKS,
+ RESOURCE_RELEASE_LOCKS,
+ RESOURCE_RELEASE_AFTER_LOCKS
+} ResourceReleasePhase;
+
+/*
+ * Dynamically loaded modules can get control during ResourceOwnerRelease
+ * by providing a callback of this form.
+ */
+typedef void (*ResourceReleaseCallback) (ResourceReleasePhase phase,
+ bool isCommit,
+ bool isTopLevel,
+ void *arg);
+
+
+/*
+ * Functions in resowner.c
+ */
+
+/* generic routines */
+extern ResourceOwner ResourceOwnerCreate(ResourceOwner parent,
+ const char *name);
+extern void ResourceOwnerRelease(ResourceOwner owner,
+ ResourceReleasePhase phase,
+ bool isCommit,
+ bool isTopLevel);
+extern void ResourceOwnerReleaseAllPlanCacheRefs(ResourceOwner owner);
+extern void ResourceOwnerDelete(ResourceOwner owner);
+extern ResourceOwner ResourceOwnerGetParent(ResourceOwner owner);
+extern void ResourceOwnerNewParent(ResourceOwner owner,
+ ResourceOwner newparent);
+extern void RegisterResourceReleaseCallback(ResourceReleaseCallback callback,
+ void *arg);
+extern void UnregisterResourceReleaseCallback(ResourceReleaseCallback callback,
+ void *arg);
+extern void CreateAuxProcessResourceOwner(void);
+extern void ReleaseAuxProcessResources(bool isCommit);
+
+#endif /* RESOWNER_H */
diff --git a/src/include/utils/resowner_private.h b/src/include/utils/resowner_private.h
new file mode 100644
index 0000000..ae58438
--- /dev/null
+++ b/src/include/utils/resowner_private.h
@@ -0,0 +1,117 @@
+/*-------------------------------------------------------------------------
+ *
+ * resowner_private.h
+ * POSTGRES resource owner private definitions.
+ *
+ * See utils/resowner/README for more info.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/resowner_private.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RESOWNER_PRIVATE_H
+#define RESOWNER_PRIVATE_H
+
+#include "storage/dsm.h"
+#include "storage/fd.h"
+#include "storage/lock.h"
+#include "utils/catcache.h"
+#include "utils/plancache.h"
+#include "utils/resowner.h"
+#include "utils/snapshot.h"
+
+
+/* support for buffer refcount management */
+extern void ResourceOwnerEnlargeBuffers(ResourceOwner owner);
+extern void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer);
+extern void ResourceOwnerForgetBuffer(ResourceOwner owner, Buffer buffer);
+
+/* support for IO-in-progress management */
+extern void ResourceOwnerEnlargeBufferIOs(ResourceOwner owner);
+extern void ResourceOwnerRememberBufferIO(ResourceOwner owner, Buffer buffer);
+extern void ResourceOwnerForgetBufferIO(ResourceOwner owner, Buffer buffer);
+
+/* support for local lock management */
+extern void ResourceOwnerRememberLock(ResourceOwner owner, LOCALLOCK *locallock);
+extern void ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock);
+
+/* support for catcache refcount management */
+extern void ResourceOwnerEnlargeCatCacheRefs(ResourceOwner owner);
+extern void ResourceOwnerRememberCatCacheRef(ResourceOwner owner,
+ HeapTuple tuple);
+extern void ResourceOwnerForgetCatCacheRef(ResourceOwner owner,
+ HeapTuple tuple);
+extern void ResourceOwnerEnlargeCatCacheListRefs(ResourceOwner owner);
+extern void ResourceOwnerRememberCatCacheListRef(ResourceOwner owner,
+ CatCList *list);
+extern void ResourceOwnerForgetCatCacheListRef(ResourceOwner owner,
+ CatCList *list);
+
+/* support for relcache refcount management */
+extern void ResourceOwnerEnlargeRelationRefs(ResourceOwner owner);
+extern void ResourceOwnerRememberRelationRef(ResourceOwner owner,
+ Relation rel);
+extern void ResourceOwnerForgetRelationRef(ResourceOwner owner,
+ Relation rel);
+
+/* support for plancache refcount management */
+extern void ResourceOwnerEnlargePlanCacheRefs(ResourceOwner owner);
+extern void ResourceOwnerRememberPlanCacheRef(ResourceOwner owner,
+ CachedPlan *plan);
+extern void ResourceOwnerForgetPlanCacheRef(ResourceOwner owner,
+ CachedPlan *plan);
+
+/* support for tupledesc refcount management */
+extern void ResourceOwnerEnlargeTupleDescs(ResourceOwner owner);
+extern void ResourceOwnerRememberTupleDesc(ResourceOwner owner,
+ TupleDesc tupdesc);
+extern void ResourceOwnerForgetTupleDesc(ResourceOwner owner,
+ TupleDesc tupdesc);
+
+/* support for snapshot refcount management */
+extern void ResourceOwnerEnlargeSnapshots(ResourceOwner owner);
+extern void ResourceOwnerRememberSnapshot(ResourceOwner owner,
+ Snapshot snapshot);
+extern void ResourceOwnerForgetSnapshot(ResourceOwner owner,
+ Snapshot snapshot);
+
+/* support for temporary file management */
+extern void ResourceOwnerEnlargeFiles(ResourceOwner owner);
+extern void ResourceOwnerRememberFile(ResourceOwner owner,
+ File file);
+extern void ResourceOwnerForgetFile(ResourceOwner owner,
+ File file);
+
+/* support for dynamic shared memory management */
+extern void ResourceOwnerEnlargeDSMs(ResourceOwner owner);
+extern void ResourceOwnerRememberDSM(ResourceOwner owner,
+ dsm_segment *);
+extern void ResourceOwnerForgetDSM(ResourceOwner owner,
+ dsm_segment *);
+
+/* support for JITContext management */
+extern void ResourceOwnerEnlargeJIT(ResourceOwner owner);
+extern void ResourceOwnerRememberJIT(ResourceOwner owner,
+ Datum handle);
+extern void ResourceOwnerForgetJIT(ResourceOwner owner,
+ Datum handle);
+
+/* support for cryptohash context management */
+extern void ResourceOwnerEnlargeCryptoHash(ResourceOwner owner);
+extern void ResourceOwnerRememberCryptoHash(ResourceOwner owner,
+ Datum handle);
+extern void ResourceOwnerForgetCryptoHash(ResourceOwner owner,
+ Datum handle);
+
+/* support for HMAC context management */
+extern void ResourceOwnerEnlargeHMAC(ResourceOwner owner);
+extern void ResourceOwnerRememberHMAC(ResourceOwner owner,
+ Datum handle);
+extern void ResourceOwnerForgetHMAC(ResourceOwner owner,
+ Datum handle);
+
+#endif /* RESOWNER_PRIVATE_H */
diff --git a/src/include/utils/rls.h b/src/include/utils/rls.h
new file mode 100644
index 0000000..1e95f83
--- /dev/null
+++ b/src/include/utils/rls.h
@@ -0,0 +1,50 @@
+/*-------------------------------------------------------------------------
+ *
+ * rls.h
+ * Header file for Row Level Security (RLS) utility commands to be used
+ * with the rowsecurity feature.
+ *
+ * Copyright (c) 2007-2023, PostgreSQL Global Development Group
+ *
+ * src/include/utils/rls.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RLS_H
+#define RLS_H
+
+/* GUC variable */
+extern PGDLLIMPORT bool row_security;
+
+/*
+ * Used by callers of check_enable_rls.
+ *
+ * RLS could be completely disabled on the tables involved in the query,
+ * which is the simple case, or it may depend on the current environment
+ * (the role which is running the query or the value of the row_security
+ * GUC), or it might be simply enabled as usual.
+ *
+ * If RLS isn't on the table involved then RLS_NONE is returned to indicate
+ * that we don't need to worry about invalidating the query plan for RLS
+ * reasons. If RLS is on the table, but we are bypassing it for now, then
+ * we return RLS_NONE_ENV to indicate that, if the environment changes,
+ * we need to invalidate and replan. Finally, if RLS should be turned on
+ * for the query, then we return RLS_ENABLED, which means we also need to
+ * invalidate if the environment changes.
+ *
+ * Note that RLS_ENABLED will also be returned if noError is true
+ * (indicating that the caller simply want to know if RLS should be applied
+ * for this user but doesn't want an error thrown if it is; this is used
+ * by other error cases where we're just trying to decide if data from the
+ * table should be passed back to the user or not).
+ */
+enum CheckEnableRlsResult
+{
+ RLS_NONE,
+ RLS_NONE_ENV,
+ RLS_ENABLED
+};
+
+extern int check_enable_rls(Oid relid, Oid checkAsUser, bool noError);
+
+#endif /* RLS_H */
diff --git a/src/include/utils/ruleutils.h b/src/include/utils/ruleutils.h
new file mode 100644
index 0000000..b006d9d
--- /dev/null
+++ b/src/include/utils/ruleutils.h
@@ -0,0 +1,52 @@
+/*-------------------------------------------------------------------------
+ *
+ * ruleutils.h
+ * Declarations for ruleutils.c
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/ruleutils.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RULEUTILS_H
+#define RULEUTILS_H
+
+#include "nodes/nodes.h"
+#include "nodes/parsenodes.h"
+#include "nodes/pg_list.h"
+
+struct Plan; /* avoid including plannodes.h here */
+struct PlannedStmt;
+
+/* Flags for pg_get_indexdef_columns_extended() */
+#define RULE_INDEXDEF_PRETTY 0x01
+#define RULE_INDEXDEF_KEYS_ONLY 0x02 /* ignore included attributes */
+
+extern char *pg_get_indexdef_string(Oid indexrelid);
+extern char *pg_get_indexdef_columns(Oid indexrelid, bool pretty);
+extern char *pg_get_indexdef_columns_extended(Oid indexrelid,
+ bits16 flags);
+extern char *pg_get_querydef(Query *query, bool pretty);
+
+extern char *pg_get_partkeydef_columns(Oid relid, bool pretty);
+extern char *pg_get_partconstrdef_string(Oid partitionId, char *aliasname);
+
+extern char *pg_get_constraintdef_command(Oid constraintId);
+extern char *deparse_expression(Node *expr, List *dpcontext,
+ bool forceprefix, bool showimplicit);
+extern List *deparse_context_for(const char *aliasname, Oid relid);
+extern List *deparse_context_for_plan_tree(struct PlannedStmt *pstmt,
+ List *rtable_names);
+extern List *set_deparse_context_plan(List *dpcontext,
+ struct Plan *plan, List *ancestors);
+extern List *select_rtable_names_for_explain(List *rtable,
+ Bitmapset *rels_used);
+extern char *generate_collation_name(Oid collid);
+extern char *generate_opclass_name(Oid opclass);
+extern char *get_range_partbound_string(List *bound_datums);
+
+extern char *pg_get_statisticsobjdef_string(Oid statextid);
+
+#endif /* RULEUTILS_H */
diff --git a/src/include/utils/sampling.h b/src/include/utils/sampling.h
new file mode 100644
index 0000000..e269448
--- /dev/null
+++ b/src/include/utils/sampling.h
@@ -0,0 +1,64 @@
+/*-------------------------------------------------------------------------
+ *
+ * sampling.h
+ * definitions for sampling functions
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/sampling.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SAMPLING_H
+#define SAMPLING_H
+
+#include "common/pg_prng.h"
+#include "storage/block.h" /* for typedef BlockNumber */
+
+
+/* Random generator for sampling code */
+extern void sampler_random_init_state(uint32 seed,
+ pg_prng_state *randstate);
+extern double sampler_random_fract(pg_prng_state *randstate);
+
+/* Block sampling methods */
+
+/* Data structure for Algorithm S from Knuth 3.4.2 */
+typedef struct
+{
+ BlockNumber N; /* number of blocks, known in advance */
+ int n; /* desired sample size */
+ BlockNumber t; /* current block number */
+ int m; /* blocks selected so far */
+ pg_prng_state randstate; /* random generator state */
+} BlockSamplerData;
+
+typedef BlockSamplerData *BlockSampler;
+
+extern BlockNumber BlockSampler_Init(BlockSampler bs, BlockNumber nblocks,
+ int samplesize, uint32 randseed);
+extern bool BlockSampler_HasMore(BlockSampler bs);
+extern BlockNumber BlockSampler_Next(BlockSampler bs);
+
+/* Reservoir sampling methods */
+
+typedef struct
+{
+ double W;
+ pg_prng_state randstate; /* random generator state */
+} ReservoirStateData;
+
+typedef ReservoirStateData *ReservoirState;
+
+extern void reservoir_init_selection_state(ReservoirState rs, int n);
+extern double reservoir_get_next_S(ReservoirState rs, double t, int n);
+
+/* Old API, still in use by assorted FDWs */
+/* For backwards compatibility, these declarations are duplicated in vacuum.h */
+
+extern double anl_random_fract(void);
+extern double anl_init_selection_state(int n);
+extern double anl_get_next_S(double t, int n, double *stateptr);
+
+#endif /* SAMPLING_H */
diff --git a/src/include/utils/selfuncs.h b/src/include/utils/selfuncs.h
new file mode 100644
index 0000000..2f76c47
--- /dev/null
+++ b/src/include/utils/selfuncs.h
@@ -0,0 +1,241 @@
+/*-------------------------------------------------------------------------
+ *
+ * selfuncs.h
+ * Selectivity functions for standard operators, and assorted
+ * infrastructure for selectivity and cost estimation.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/selfuncs.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SELFUNCS_H
+#define SELFUNCS_H
+
+#include "access/htup.h"
+#include "fmgr.h"
+#include "nodes/pathnodes.h"
+
+
+/*
+ * Note: the default selectivity estimates are not chosen entirely at random.
+ * We want them to be small enough to ensure that indexscans will be used if
+ * available, for typical table densities of ~100 tuples/page. Thus, for
+ * example, 0.01 is not quite small enough, since that makes it appear that
+ * nearly all pages will be hit anyway. Also, since we sometimes estimate
+ * eqsel as 1/num_distinct, we probably want DEFAULT_NUM_DISTINCT to equal
+ * 1/DEFAULT_EQ_SEL.
+ */
+
+/* default selectivity estimate for equalities such as "A = b" */
+#define DEFAULT_EQ_SEL 0.005
+
+/* default selectivity estimate for inequalities such as "A < b" */
+#define DEFAULT_INEQ_SEL 0.3333333333333333
+
+/* default selectivity estimate for range inequalities "A > b AND A < c" */
+#define DEFAULT_RANGE_INEQ_SEL 0.005
+
+/* default selectivity estimate for multirange inequalities "A > b AND A < c" */
+#define DEFAULT_MULTIRANGE_INEQ_SEL 0.005
+
+/* default selectivity estimate for pattern-match operators such as LIKE */
+#define DEFAULT_MATCH_SEL 0.005
+
+/* default selectivity estimate for other matching operators */
+#define DEFAULT_MATCHING_SEL 0.010
+
+/* default number of distinct values in a table */
+#define DEFAULT_NUM_DISTINCT 200
+
+/* default selectivity estimate for boolean and null test nodes */
+#define DEFAULT_UNK_SEL 0.005
+#define DEFAULT_NOT_UNK_SEL (1.0 - DEFAULT_UNK_SEL)
+
+
+/*
+ * Clamp a computed probability estimate (which may suffer from roundoff or
+ * estimation errors) to valid range. Argument must be a float variable.
+ */
+#define CLAMP_PROBABILITY(p) \
+ do { \
+ if (p < 0.0) \
+ p = 0.0; \
+ else if (p > 1.0) \
+ p = 1.0; \
+ } while (0)
+
+/*
+ * A set of flags which some selectivity estimation functions can pass back to
+ * callers to provide further details about some assumptions which were made
+ * during the estimation.
+ */
+#define SELFLAG_USED_DEFAULT (1 << 0) /* Estimation fell back on one
+ * of the DEFAULTs as defined
+ * above. */
+
+typedef struct EstimationInfo
+{
+ uint32 flags; /* Flags, as defined above to mark special
+ * properties of the estimation. */
+} EstimationInfo;
+
+/* Return data from examine_variable and friends */
+typedef struct VariableStatData
+{
+ Node *var; /* the Var or expression tree */
+ RelOptInfo *rel; /* Relation, or NULL if not identifiable */
+ HeapTuple statsTuple; /* pg_statistic tuple, or NULL if none */
+ /* NB: if statsTuple!=NULL, it must be freed when caller is done */
+ void (*freefunc) (HeapTuple tuple); /* how to free statsTuple */
+ Oid vartype; /* exposed type of expression */
+ Oid atttype; /* actual type (after stripping relabel) */
+ int32 atttypmod; /* actual typmod (after stripping relabel) */
+ bool isunique; /* matches unique index or DISTINCT clause */
+ bool acl_ok; /* result of ACL check on table or column */
+} VariableStatData;
+
+#define ReleaseVariableStats(vardata) \
+ do { \
+ if (HeapTupleIsValid((vardata).statsTuple)) \
+ (vardata).freefunc((vardata).statsTuple); \
+ } while(0)
+
+
+/*
+ * genericcostestimate is a general-purpose estimator that can be used for
+ * most index types. In some cases we use genericcostestimate as the base
+ * code and then incorporate additional index-type-specific knowledge in
+ * the type-specific calling function. To avoid code duplication, we make
+ * genericcostestimate return a number of intermediate values as well as
+ * its preliminary estimates of the output cost values. The GenericCosts
+ * struct includes all these values.
+ *
+ * Callers should initialize all fields of GenericCosts to zero. In addition,
+ * they can set numIndexTuples to some positive value if they have a better
+ * than default way of estimating the number of leaf index tuples visited.
+ */
+typedef struct
+{
+ /* These are the values the cost estimator must return to the planner */
+ Cost indexStartupCost; /* index-related startup cost */
+ Cost indexTotalCost; /* total index-related scan cost */
+ Selectivity indexSelectivity; /* selectivity of index */
+ double indexCorrelation; /* order correlation of index */
+
+ /* Intermediate values we obtain along the way */
+ double numIndexPages; /* number of leaf pages visited */
+ double numIndexTuples; /* number of leaf tuples visited */
+ double spc_random_page_cost; /* relevant random_page_cost value */
+ double num_sa_scans; /* # indexscans from ScalarArrayOpExprs */
+} GenericCosts;
+
+/* Hooks for plugins to get control when we ask for stats */
+typedef bool (*get_relation_stats_hook_type) (PlannerInfo *root,
+ RangeTblEntry *rte,
+ AttrNumber attnum,
+ VariableStatData *vardata);
+extern PGDLLIMPORT get_relation_stats_hook_type get_relation_stats_hook;
+typedef bool (*get_index_stats_hook_type) (PlannerInfo *root,
+ Oid indexOid,
+ AttrNumber indexattnum,
+ VariableStatData *vardata);
+extern PGDLLIMPORT get_index_stats_hook_type get_index_stats_hook;
+
+/* Functions in selfuncs.c */
+
+extern void examine_variable(PlannerInfo *root, Node *node, int varRelid,
+ VariableStatData *vardata);
+extern bool statistic_proc_security_check(VariableStatData *vardata, Oid func_oid);
+extern bool get_restriction_variable(PlannerInfo *root, List *args,
+ int varRelid,
+ VariableStatData *vardata, Node **other,
+ bool *varonleft);
+extern void get_join_variables(PlannerInfo *root, List *args,
+ SpecialJoinInfo *sjinfo,
+ VariableStatData *vardata1,
+ VariableStatData *vardata2,
+ bool *join_is_reversed);
+extern double get_variable_numdistinct(VariableStatData *vardata,
+ bool *isdefault);
+extern double mcv_selectivity(VariableStatData *vardata,
+ FmgrInfo *opproc, Oid collation,
+ Datum constval, bool varonleft,
+ double *sumcommonp);
+extern double histogram_selectivity(VariableStatData *vardata,
+ FmgrInfo *opproc, Oid collation,
+ Datum constval, bool varonleft,
+ int min_hist_size, int n_skip,
+ int *hist_size);
+extern double generic_restriction_selectivity(PlannerInfo *root,
+ Oid oproid, Oid collation,
+ List *args, int varRelid,
+ double default_selectivity);
+extern double ineq_histogram_selectivity(PlannerInfo *root,
+ VariableStatData *vardata,
+ Oid opoid, FmgrInfo *opproc,
+ bool isgt, bool iseq,
+ Oid collation,
+ Datum constval, Oid consttype);
+extern double var_eq_const(VariableStatData *vardata,
+ Oid oproid, Oid collation,
+ Datum constval, bool constisnull,
+ bool varonleft, bool negate);
+extern double var_eq_non_const(VariableStatData *vardata,
+ Oid oproid, Oid collation,
+ Node *other,
+ bool varonleft, bool negate);
+
+extern Selectivity boolvarsel(PlannerInfo *root, Node *arg, int varRelid);
+extern Selectivity booltestsel(PlannerInfo *root, BoolTestType booltesttype,
+ Node *arg, int varRelid,
+ JoinType jointype, SpecialJoinInfo *sjinfo);
+extern Selectivity nulltestsel(PlannerInfo *root, NullTestType nulltesttype,
+ Node *arg, int varRelid,
+ JoinType jointype, SpecialJoinInfo *sjinfo);
+extern Selectivity scalararraysel(PlannerInfo *root,
+ ScalarArrayOpExpr *clause,
+ bool is_join_clause,
+ int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo);
+extern int estimate_array_length(Node *arrayexpr);
+extern Selectivity rowcomparesel(PlannerInfo *root,
+ RowCompareExpr *clause,
+ int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo);
+
+extern void mergejoinscansel(PlannerInfo *root, Node *clause,
+ Oid opfamily, int strategy, bool nulls_first,
+ Selectivity *leftstart, Selectivity *leftend,
+ Selectivity *rightstart, Selectivity *rightend);
+
+extern double estimate_num_groups(PlannerInfo *root, List *groupExprs,
+ double input_rows, List **pgset,
+ EstimationInfo *estinfo);
+
+extern void estimate_hash_bucket_stats(PlannerInfo *root,
+ Node *hashkey, double nbuckets,
+ Selectivity *mcv_freq,
+ Selectivity *bucketsize_frac);
+extern double estimate_hashagg_tablesize(PlannerInfo *root, Path *path,
+ const AggClauseCosts *agg_costs,
+ double dNumGroups);
+
+extern List *get_quals_from_indexclauses(List *indexclauses);
+extern Cost index_other_operands_eval_cost(PlannerInfo *root,
+ List *indexquals);
+extern List *add_predicate_to_index_quals(IndexOptInfo *index,
+ List *indexQuals);
+extern void genericcostestimate(PlannerInfo *root, IndexPath *path,
+ double loop_count,
+ GenericCosts *costs);
+
+/* Functions in array_selfuncs.c */
+
+extern Selectivity scalararraysel_containment(PlannerInfo *root,
+ Node *leftop, Node *rightop,
+ Oid elemtype, bool isEquality, bool useOr,
+ int varRelid);
+
+#endif /* SELFUNCS_H */
diff --git a/src/include/utils/sharedtuplestore.h b/src/include/utils/sharedtuplestore.h
new file mode 100644
index 0000000..c7075ad
--- /dev/null
+++ b/src/include/utils/sharedtuplestore.h
@@ -0,0 +1,61 @@
+/*-------------------------------------------------------------------------
+ *
+ * sharedtuplestore.h
+ * Simple mechanism for sharing tuples between backends.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/sharedtuplestore.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SHAREDTUPLESTORE_H
+#define SHAREDTUPLESTORE_H
+
+#include "access/htup.h"
+#include "storage/fd.h"
+#include "storage/sharedfileset.h"
+
+struct SharedTuplestore;
+typedef struct SharedTuplestore SharedTuplestore;
+
+struct SharedTuplestoreAccessor;
+typedef struct SharedTuplestoreAccessor SharedTuplestoreAccessor;
+
+/*
+ * A flag indicating that the tuplestore will only be scanned once, so backing
+ * files can be unlinked early.
+ */
+#define SHARED_TUPLESTORE_SINGLE_PASS 0x01
+
+extern size_t sts_estimate(int participants);
+
+extern SharedTuplestoreAccessor *sts_initialize(SharedTuplestore *sts,
+ int participants,
+ int my_participant_number,
+ size_t meta_data_size,
+ int flags,
+ SharedFileSet *fileset,
+ const char *name);
+
+extern SharedTuplestoreAccessor *sts_attach(SharedTuplestore *sts,
+ int my_participant_number,
+ SharedFileSet *fileset);
+
+extern void sts_end_write(SharedTuplestoreAccessor *accessor);
+
+extern void sts_reinitialize(SharedTuplestoreAccessor *accessor);
+
+extern void sts_begin_parallel_scan(SharedTuplestoreAccessor *accessor);
+
+extern void sts_end_parallel_scan(SharedTuplestoreAccessor *accessor);
+
+extern void sts_puttuple(SharedTuplestoreAccessor *accessor,
+ void *meta_data,
+ MinimalTuple tuple);
+
+extern MinimalTuple sts_parallel_scan_next(SharedTuplestoreAccessor *accessor,
+ void *meta_data);
+
+#endif /* SHAREDTUPLESTORE_H */
diff --git a/src/include/utils/snapmgr.h b/src/include/utils/snapmgr.h
new file mode 100644
index 0000000..980d37a
--- /dev/null
+++ b/src/include/utils/snapmgr.h
@@ -0,0 +1,181 @@
+/*-------------------------------------------------------------------------
+ *
+ * snapmgr.h
+ * POSTGRES snapshot manager
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/snapmgr.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SNAPMGR_H
+#define SNAPMGR_H
+
+#include "access/transam.h"
+#include "utils/relcache.h"
+#include "utils/resowner.h"
+#include "utils/snapshot.h"
+
+
+/*
+ * The structure used to map times to TransactionId values for the "snapshot
+ * too old" feature must have a few entries at the tail to hold old values;
+ * otherwise the lookup will often fail and the expected early pruning or
+ * vacuum will not usually occur. It is best if this padding is for a number
+ * of minutes greater than a thread would normally be stalled, but it's OK if
+ * early vacuum opportunities are occasionally missed, so there's no need to
+ * use an extreme value or get too fancy. 10 minutes seems plenty.
+ */
+#define OLD_SNAPSHOT_PADDING_ENTRIES 10
+#define OLD_SNAPSHOT_TIME_MAP_ENTRIES (old_snapshot_threshold + OLD_SNAPSHOT_PADDING_ENTRIES)
+
+/*
+ * Common definition of relation properties that allow early pruning/vacuuming
+ * when old_snapshot_threshold >= 0.
+ */
+#define RelationAllowsEarlyPruning(rel) \
+( \
+ RelationIsPermanent(rel) && !IsCatalogRelation(rel) \
+ && !RelationIsAccessibleInLogicalDecoding(rel) \
+)
+
+#define EarlyPruningEnabled(rel) (old_snapshot_threshold >= 0 && RelationAllowsEarlyPruning(rel))
+
+/* GUC variables */
+extern PGDLLIMPORT int old_snapshot_threshold;
+
+
+extern Size SnapMgrShmemSize(void);
+extern void SnapMgrInit(void);
+extern TimestampTz GetSnapshotCurrentTimestamp(void);
+extern TimestampTz GetOldSnapshotThresholdTimestamp(void);
+extern void SnapshotTooOldMagicForTest(void);
+
+extern PGDLLIMPORT bool FirstSnapshotSet;
+
+extern PGDLLIMPORT TransactionId TransactionXmin;
+extern PGDLLIMPORT TransactionId RecentXmin;
+
+/* Variables representing various special snapshot semantics */
+extern PGDLLIMPORT SnapshotData SnapshotSelfData;
+extern PGDLLIMPORT SnapshotData SnapshotAnyData;
+extern PGDLLIMPORT SnapshotData CatalogSnapshotData;
+
+#define SnapshotSelf (&SnapshotSelfData)
+#define SnapshotAny (&SnapshotAnyData)
+
+/*
+ * We don't provide a static SnapshotDirty variable because it would be
+ * non-reentrant. Instead, users of that snapshot type should declare a
+ * local variable of type SnapshotData, and initialize it with this macro.
+ */
+#define InitDirtySnapshot(snapshotdata) \
+ ((snapshotdata).snapshot_type = SNAPSHOT_DIRTY)
+
+/*
+ * Similarly, some initialization is required for a NonVacuumable snapshot.
+ * The caller must supply the visibility cutoff state to use (c.f.
+ * GlobalVisTestFor()).
+ */
+#define InitNonVacuumableSnapshot(snapshotdata, vistestp) \
+ ((snapshotdata).snapshot_type = SNAPSHOT_NON_VACUUMABLE, \
+ (snapshotdata).vistest = (vistestp))
+
+/*
+ * Similarly, some initialization is required for SnapshotToast. We need
+ * to set lsn and whenTaken correctly to support snapshot_too_old.
+ */
+#define InitToastSnapshot(snapshotdata, l, w) \
+ ((snapshotdata).snapshot_type = SNAPSHOT_TOAST, \
+ (snapshotdata).lsn = (l), \
+ (snapshotdata).whenTaken = (w))
+
+/* This macro encodes the knowledge of which snapshots are MVCC-safe */
+#define IsMVCCSnapshot(snapshot) \
+ ((snapshot)->snapshot_type == SNAPSHOT_MVCC || \
+ (snapshot)->snapshot_type == SNAPSHOT_HISTORIC_MVCC)
+
+#ifndef FRONTEND
+static inline bool
+OldSnapshotThresholdActive(void)
+{
+ return old_snapshot_threshold >= 0;
+}
+#endif
+
+extern Snapshot GetTransactionSnapshot(void);
+extern Snapshot GetLatestSnapshot(void);
+extern void SnapshotSetCommandId(CommandId curcid);
+extern Snapshot GetOldestSnapshot(void);
+
+extern Snapshot GetCatalogSnapshot(Oid relid);
+extern Snapshot GetNonHistoricCatalogSnapshot(Oid relid);
+extern void InvalidateCatalogSnapshot(void);
+extern void InvalidateCatalogSnapshotConditionally(void);
+
+extern void PushActiveSnapshot(Snapshot snapshot);
+extern void PushActiveSnapshotWithLevel(Snapshot snapshot, int snap_level);
+extern void PushCopiedSnapshot(Snapshot snapshot);
+extern void UpdateActiveSnapshotCommandId(void);
+extern void PopActiveSnapshot(void);
+extern Snapshot GetActiveSnapshot(void);
+extern bool ActiveSnapshotSet(void);
+
+extern Snapshot RegisterSnapshot(Snapshot snapshot);
+extern void UnregisterSnapshot(Snapshot snapshot);
+extern Snapshot RegisterSnapshotOnOwner(Snapshot snapshot, ResourceOwner owner);
+extern void UnregisterSnapshotFromOwner(Snapshot snapshot, ResourceOwner owner);
+
+extern void AtSubCommit_Snapshot(int level);
+extern void AtSubAbort_Snapshot(int level);
+extern void AtEOXact_Snapshot(bool isCommit, bool resetXmin);
+
+extern void ImportSnapshot(const char *idstr);
+extern bool XactHasExportedSnapshots(void);
+extern void DeleteAllExportedSnapshotFiles(void);
+extern void WaitForOlderSnapshots(TransactionId limitXmin, bool progress);
+extern bool ThereAreNoPriorRegisteredSnapshots(void);
+extern bool HaveRegisteredOrActiveSnapshot(void);
+extern bool TransactionIdLimitedForOldSnapshots(TransactionId recentXmin,
+ Relation relation,
+ TransactionId *limit_xid,
+ TimestampTz *limit_ts);
+extern void SetOldSnapshotThresholdTimestamp(TimestampTz ts, TransactionId xlimit);
+extern void MaintainOldSnapshotTimeMapping(TimestampTz whenTaken,
+ TransactionId xmin);
+
+extern char *ExportSnapshot(Snapshot snapshot);
+
+/*
+ * These live in procarray.c because they're intimately linked to the
+ * procarray contents, but thematically they better fit into snapmgr.h.
+ */
+typedef struct GlobalVisState GlobalVisState;
+extern GlobalVisState *GlobalVisTestFor(Relation rel);
+extern bool GlobalVisTestIsRemovableXid(GlobalVisState *state, TransactionId xid);
+extern bool GlobalVisTestIsRemovableFullXid(GlobalVisState *state, FullTransactionId fxid);
+extern FullTransactionId GlobalVisTestNonRemovableFullHorizon(GlobalVisState *state);
+extern TransactionId GlobalVisTestNonRemovableHorizon(GlobalVisState *state);
+extern bool GlobalVisCheckRemovableXid(Relation rel, TransactionId xid);
+extern bool GlobalVisCheckRemovableFullXid(Relation rel, FullTransactionId fxid);
+
+/*
+ * Utility functions for implementing visibility routines in table AMs.
+ */
+extern bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot);
+
+/* Support for catalog timetravel for logical decoding */
+struct HTAB;
+extern struct HTAB *HistoricSnapshotGetTupleCids(void);
+extern void SetupHistoricSnapshot(Snapshot historic_snapshot, struct HTAB *tuplecids);
+extern void TeardownHistoricSnapshot(bool is_error);
+extern bool HistoricSnapshotActive(void);
+
+extern Size EstimateSnapshotSpace(Snapshot snapshot);
+extern void SerializeSnapshot(Snapshot snapshot, char *start_address);
+extern Snapshot RestoreSnapshot(char *start_address);
+extern void RestoreTransactionSnapshot(Snapshot snapshot, void *source_pgproc);
+
+#endif /* SNAPMGR_H */
diff --git a/src/include/utils/snapshot.h b/src/include/utils/snapshot.h
new file mode 100644
index 0000000..583a667
--- /dev/null
+++ b/src/include/utils/snapshot.h
@@ -0,0 +1,219 @@
+/*-------------------------------------------------------------------------
+ *
+ * snapshot.h
+ * POSTGRES snapshot definition
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/snapshot.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SNAPSHOT_H
+#define SNAPSHOT_H
+
+#include "access/htup.h"
+#include "access/xlogdefs.h"
+#include "datatype/timestamp.h"
+#include "lib/pairingheap.h"
+#include "storage/buf.h"
+
+
+/*
+ * The different snapshot types. We use SnapshotData structures to represent
+ * both "regular" (MVCC) snapshots and "special" snapshots that have non-MVCC
+ * semantics. The specific semantics of a snapshot are encoded by its type.
+ *
+ * The behaviour of each type of snapshot should be documented alongside its
+ * enum value, best in terms that are not specific to an individual table AM.
+ *
+ * The reason the snapshot type rather than a callback as it used to be is
+ * that that allows to use the same snapshot for different table AMs without
+ * having one callback per AM.
+ */
+typedef enum SnapshotType
+{
+ /*-------------------------------------------------------------------------
+ * A tuple is visible iff the tuple is valid for the given MVCC snapshot.
+ *
+ * Here, we consider the effects of:
+ * - all transactions committed as of the time of the given snapshot
+ * - previous commands of this transaction
+ *
+ * Does _not_ include:
+ * - transactions shown as in-progress by the snapshot
+ * - transactions started after the snapshot was taken
+ * - changes made by the current command
+ * -------------------------------------------------------------------------
+ */
+ SNAPSHOT_MVCC = 0,
+
+ /*-------------------------------------------------------------------------
+ * A tuple is visible iff the tuple is valid "for itself".
+ *
+ * Here, we consider the effects of:
+ * - all committed transactions (as of the current instant)
+ * - previous commands of this transaction
+ * - changes made by the current command
+ *
+ * Does _not_ include:
+ * - in-progress transactions (as of the current instant)
+ * -------------------------------------------------------------------------
+ */
+ SNAPSHOT_SELF,
+
+ /*
+ * Any tuple is visible.
+ */
+ SNAPSHOT_ANY,
+
+ /*
+ * A tuple is visible iff the tuple is valid as a TOAST row.
+ */
+ SNAPSHOT_TOAST,
+
+ /*-------------------------------------------------------------------------
+ * A tuple is visible iff the tuple is valid including effects of open
+ * transactions.
+ *
+ * Here, we consider the effects of:
+ * - all committed and in-progress transactions (as of the current instant)
+ * - previous commands of this transaction
+ * - changes made by the current command
+ *
+ * This is essentially like SNAPSHOT_SELF as far as effects of the current
+ * transaction and committed/aborted xacts are concerned. However, it
+ * also includes the effects of other xacts still in progress.
+ *
+ * A special hack is that when a snapshot of this type is used to
+ * determine tuple visibility, the passed-in snapshot struct is used as an
+ * output argument to return the xids of concurrent xacts that affected
+ * the tuple. snapshot->xmin is set to the tuple's xmin if that is
+ * another transaction that's still in progress; or to
+ * InvalidTransactionId if the tuple's xmin is committed good, committed
+ * dead, or my own xact. Similarly for snapshot->xmax and the tuple's
+ * xmax. If the tuple was inserted speculatively, meaning that the
+ * inserter might still back down on the insertion without aborting the
+ * whole transaction, the associated token is also returned in
+ * snapshot->speculativeToken. See also InitDirtySnapshot().
+ * -------------------------------------------------------------------------
+ */
+ SNAPSHOT_DIRTY,
+
+ /*
+ * A tuple is visible iff it follows the rules of SNAPSHOT_MVCC, but
+ * supports being called in timetravel context (for decoding catalog
+ * contents in the context of logical decoding).
+ */
+ SNAPSHOT_HISTORIC_MVCC,
+
+ /*
+ * A tuple is visible iff the tuple might be visible to some transaction;
+ * false if it's surely dead to everyone, i.e., vacuumable.
+ *
+ * For visibility checks snapshot->min must have been set up with the xmin
+ * horizon to use.
+ */
+ SNAPSHOT_NON_VACUUMABLE
+} SnapshotType;
+
+typedef struct SnapshotData *Snapshot;
+
+#define InvalidSnapshot ((Snapshot) NULL)
+
+/*
+ * Struct representing all kind of possible snapshots.
+ *
+ * There are several different kinds of snapshots:
+ * * Normal MVCC snapshots
+ * * MVCC snapshots taken during recovery (in Hot-Standby mode)
+ * * Historic MVCC snapshots used during logical decoding
+ * * snapshots passed to HeapTupleSatisfiesDirty()
+ * * snapshots passed to HeapTupleSatisfiesNonVacuumable()
+ * * snapshots used for SatisfiesAny, Toast, Self where no members are
+ * accessed.
+ *
+ * TODO: It's probably a good idea to split this struct using a NodeTag
+ * similar to how parser and executor nodes are handled, with one type for
+ * each different kind of snapshot to avoid overloading the meaning of
+ * individual fields.
+ */
+typedef struct SnapshotData
+{
+ SnapshotType snapshot_type; /* type of snapshot */
+
+ /*
+ * The remaining fields are used only for MVCC snapshots, and are normally
+ * just zeroes in special snapshots. (But xmin and xmax are used
+ * specially by HeapTupleSatisfiesDirty, and xmin is used specially by
+ * HeapTupleSatisfiesNonVacuumable.)
+ *
+ * An MVCC snapshot can never see the effects of XIDs >= xmax. It can see
+ * the effects of all older XIDs except those listed in the snapshot. xmin
+ * is stored as an optimization to avoid needing to search the XID arrays
+ * for most tuples.
+ */
+ TransactionId xmin; /* all XID < xmin are visible to me */
+ TransactionId xmax; /* all XID >= xmax are invisible to me */
+
+ /*
+ * For normal MVCC snapshot this contains the all xact IDs that are in
+ * progress, unless the snapshot was taken during recovery in which case
+ * it's empty. For historic MVCC snapshots, the meaning is inverted, i.e.
+ * it contains *committed* transactions between xmin and xmax.
+ *
+ * note: all ids in xip[] satisfy xmin <= xip[i] < xmax
+ */
+ TransactionId *xip;
+ uint32 xcnt; /* # of xact ids in xip[] */
+
+ /*
+ * For non-historic MVCC snapshots, this contains subxact IDs that are in
+ * progress (and other transactions that are in progress if taken during
+ * recovery). For historic snapshot it contains *all* xids assigned to the
+ * replayed transaction, including the toplevel xid.
+ *
+ * note: all ids in subxip[] are >= xmin, but we don't bother filtering
+ * out any that are >= xmax
+ */
+ TransactionId *subxip;
+ int32 subxcnt; /* # of xact ids in subxip[] */
+ bool suboverflowed; /* has the subxip array overflowed? */
+
+ bool takenDuringRecovery; /* recovery-shaped snapshot? */
+ bool copied; /* false if it's a static snapshot */
+
+ CommandId curcid; /* in my xact, CID < curcid are visible */
+
+ /*
+ * An extra return value for HeapTupleSatisfiesDirty, not used in MVCC
+ * snapshots.
+ */
+ uint32 speculativeToken;
+
+ /*
+ * For SNAPSHOT_NON_VACUUMABLE (and hopefully more in the future) this is
+ * used to determine whether row could be vacuumed.
+ */
+ struct GlobalVisState *vistest;
+
+ /*
+ * Book-keeping information, used by the snapshot manager
+ */
+ uint32 active_count; /* refcount on ActiveSnapshot stack */
+ uint32 regd_count; /* refcount on RegisteredSnapshots */
+ pairingheap_node ph_node; /* link in the RegisteredSnapshots heap */
+
+ TimestampTz whenTaken; /* timestamp when snapshot was taken */
+ XLogRecPtr lsn; /* position in the WAL stream when taken */
+
+ /*
+ * The transaction completion count at the time GetSnapshotData() built
+ * this snapshot. Allows to avoid re-computing static snapshots when no
+ * transactions completed since the last GetSnapshotData().
+ */
+ uint64 snapXactCompletionCount;
+} SnapshotData;
+
+#endif /* SNAPSHOT_H */
diff --git a/src/include/utils/sortsupport.h b/src/include/utils/sortsupport.h
new file mode 100644
index 0000000..475ed1d
--- /dev/null
+++ b/src/include/utils/sortsupport.h
@@ -0,0 +1,391 @@
+/*-------------------------------------------------------------------------
+ *
+ * sortsupport.h
+ * Framework for accelerated sorting.
+ *
+ * Traditionally, PostgreSQL has implemented sorting by repeatedly invoking
+ * an SQL-callable comparison function "cmp(x, y) returns int" on pairs of
+ * values to be compared, where the comparison function is the BTORDER_PROC
+ * pg_amproc support function of the appropriate btree index opclass.
+ *
+ * This file defines alternative APIs that allow sorting to be performed with
+ * reduced overhead. To support lower-overhead sorting, a btree opclass may
+ * provide a BTSORTSUPPORT_PROC pg_amproc entry, which must take a single
+ * argument of type internal and return void. The argument is actually a
+ * pointer to a SortSupportData struct, which is defined below.
+ *
+ * If provided, the BTSORTSUPPORT function will be called during sort setup,
+ * and it must initialize the provided struct with pointers to function(s)
+ * that can be called to perform sorting. This API is defined to allow
+ * multiple acceleration mechanisms to be supported, but no opclass is
+ * required to provide all of them. The BTSORTSUPPORT function should
+ * simply not set any function pointers for mechanisms it doesn't support.
+ * Opclasses that provide BTSORTSUPPORT and don't provide a comparator
+ * function will have a shim set up by sort support automatically. However,
+ * opclasses that support the optional additional abbreviated key capability
+ * must always provide an authoritative comparator used to tie-break
+ * inconclusive abbreviated comparisons and also used when aborting
+ * abbreviation. Furthermore, a converter and abort/costing function must be
+ * provided.
+ *
+ * All sort support functions will be passed the address of the
+ * SortSupportData struct when called, so they can use it to store
+ * additional private data as needed. In particular, for collation-aware
+ * datatypes, the ssup_collation field is set before calling BTSORTSUPPORT
+ * and is available to all support functions. Additional opclass-dependent
+ * data can be stored using the ssup_extra field. Any such data
+ * should be allocated in the ssup_cxt memory context.
+ *
+ * Note: since pg_amproc functions are indexed by (lefttype, righttype)
+ * it is possible to associate a BTSORTSUPPORT function with a cross-type
+ * comparison. This could sensibly be used to provide a fast comparator
+ * function for such cases, but probably not any other acceleration method.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/sortsupport.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SORTSUPPORT_H
+#define SORTSUPPORT_H
+
+#include "access/attnum.h"
+#include "utils/relcache.h"
+
+typedef struct SortSupportData *SortSupport;
+
+typedef struct SortSupportData
+{
+ /*
+ * These fields are initialized before calling the BTSORTSUPPORT function
+ * and should not be changed later.
+ */
+ MemoryContext ssup_cxt; /* Context containing sort info */
+ Oid ssup_collation; /* Collation to use, or InvalidOid */
+
+ /*
+ * Additional sorting parameters; but unlike ssup_collation, these can be
+ * changed after BTSORTSUPPORT is called, so don't use them in selecting
+ * sort support functions.
+ */
+ bool ssup_reverse; /* descending-order sort? */
+ bool ssup_nulls_first; /* sort nulls first? */
+
+ /*
+ * These fields are workspace for callers, and should not be touched by
+ * opclass-specific functions.
+ */
+ AttrNumber ssup_attno; /* column number to sort */
+
+ /*
+ * ssup_extra is zeroed before calling the BTSORTSUPPORT function, and is
+ * not touched subsequently by callers.
+ */
+ void *ssup_extra; /* Workspace for opclass functions */
+
+ /*
+ * Function pointers are zeroed before calling the BTSORTSUPPORT function,
+ * and must be set by it for any acceleration methods it wants to supply.
+ * The comparator pointer must be set, others are optional.
+ */
+
+ /*
+ * Comparator function has the same API as the traditional btree
+ * comparison function, ie, return <0, 0, or >0 according as x is less
+ * than, equal to, or greater than y. Note that x and y are guaranteed
+ * not null, and there is no way to return null either.
+ *
+ * This may be either the authoritative comparator, or the abbreviated
+ * comparator. Core code may switch this over the initial preference of
+ * an opclass support function despite originally indicating abbreviation
+ * was applicable, by assigning the authoritative comparator back.
+ */
+ int (*comparator) (Datum x, Datum y, SortSupport ssup);
+
+ /*
+ * "Abbreviated key" infrastructure follows.
+ *
+ * All callbacks must be set by sortsupport opclasses that make use of
+ * this optional additional infrastructure (unless for whatever reasons
+ * the opclass doesn't proceed with abbreviation, in which case
+ * abbrev_converter must not be set).
+ *
+ * This allows opclass authors to supply a conversion routine, used to
+ * create an alternative representation of the underlying type (an
+ * "abbreviated key"). This representation must be pass-by-value and
+ * typically will use some ad-hoc format that only the opclass has
+ * knowledge of. An alternative comparator, used only with this
+ * alternative representation must also be provided (which is assigned to
+ * "comparator"). This representation is a simple approximation of the
+ * original Datum. It must be possible to compare datums of this
+ * representation with each other using the supplied alternative
+ * comparator, and have any non-zero return value be a reliable proxy for
+ * what a proper comparison would indicate. Returning zero from the
+ * alternative comparator does not indicate equality, as with a
+ * conventional support routine 1, though -- it indicates that it wasn't
+ * possible to determine how the two abbreviated values compared. A
+ * proper comparison, using "abbrev_full_comparator"/
+ * ApplySortAbbrevFullComparator() is therefore required. In many cases
+ * this results in most or all comparisons only using the cheap
+ * alternative comparison func, which is typically implemented as code
+ * that compiles to just a few CPU instructions. CPU cache miss penalties
+ * are expensive; to get good overall performance, sort infrastructure
+ * must heavily weigh cache performance.
+ *
+ * Opclass authors must consider the final cardinality of abbreviated keys
+ * when devising an encoding scheme. It's possible for a strategy to work
+ * better than an alternative strategy with one usage pattern, while the
+ * reverse might be true for another usage pattern. All of these factors
+ * must be considered.
+ */
+
+ /*
+ * "abbreviate" concerns whether or not the abbreviated key optimization
+ * is applicable in principle (that is, the sortsupport routine needs to
+ * know if its dealing with a key where an abbreviated representation can
+ * usefully be packed together. Conventionally, this is the leading
+ * attribute key). Note, however, that in order to determine that
+ * abbreviation is not in play, the core code always checks whether or not
+ * the opclass has set abbrev_converter. This is a one way, one time
+ * message to the opclass.
+ */
+ bool abbreviate;
+
+ /*
+ * Converter to abbreviated format, from original representation. Core
+ * code uses this callback to convert from a pass-by-reference "original"
+ * Datum to a pass-by-value abbreviated key Datum. Note that original is
+ * guaranteed NOT NULL, because it doesn't make sense to factor NULLness
+ * into ad-hoc cost model.
+ *
+ * abbrev_converter is tested to see if abbreviation is in play. Core
+ * code may set it to NULL to indicate abbreviation should not be used
+ * (which is something sortsupport routines need not concern themselves
+ * with). However, sortsupport routines must not set it when it is
+ * immediately established that abbreviation should not proceed (e.g., for
+ * !abbreviate calls, or due to platform-specific impediments to using
+ * abbreviation).
+ */
+ Datum (*abbrev_converter) (Datum original, SortSupport ssup);
+
+ /*
+ * abbrev_abort callback allows clients to verify that the current
+ * strategy is working out, using a sortsupport routine defined ad-hoc
+ * cost model. If there is a lot of duplicate abbreviated keys in
+ * practice, it's useful to be able to abandon the strategy before paying
+ * too high a cost in conversion (perhaps certain opclass-specific
+ * adaptations are useful too).
+ */
+ bool (*abbrev_abort) (int memtupcount, SortSupport ssup);
+
+ /*
+ * Full, authoritative comparator for key that an abbreviated
+ * representation was generated for, used when an abbreviated comparison
+ * was inconclusive (by calling ApplySortAbbrevFullComparator()), or used
+ * to replace "comparator" when core system ultimately decides against
+ * abbreviation.
+ */
+ int (*abbrev_full_comparator) (Datum x, Datum y, SortSupport ssup);
+} SortSupportData;
+
+
+/*
+ * Apply a sort comparator function and return a 3-way comparison result.
+ * This takes care of handling reverse-sort and NULLs-ordering properly.
+ */
+static inline int
+ApplySortComparator(Datum datum1, bool isNull1,
+ Datum datum2, bool isNull2,
+ SortSupport ssup)
+{
+ int compare;
+
+ if (isNull1)
+ {
+ if (isNull2)
+ compare = 0; /* NULL "=" NULL */
+ else if (ssup->ssup_nulls_first)
+ compare = -1; /* NULL "<" NOT_NULL */
+ else
+ compare = 1; /* NULL ">" NOT_NULL */
+ }
+ else if (isNull2)
+ {
+ if (ssup->ssup_nulls_first)
+ compare = 1; /* NOT_NULL ">" NULL */
+ else
+ compare = -1; /* NOT_NULL "<" NULL */
+ }
+ else
+ {
+ compare = ssup->comparator(datum1, datum2, ssup);
+ if (ssup->ssup_reverse)
+ INVERT_COMPARE_RESULT(compare);
+ }
+
+ return compare;
+}
+
+static inline int
+ApplyUnsignedSortComparator(Datum datum1, bool isNull1,
+ Datum datum2, bool isNull2,
+ SortSupport ssup)
+{
+ int compare;
+
+ if (isNull1)
+ {
+ if (isNull2)
+ compare = 0; /* NULL "=" NULL */
+ else if (ssup->ssup_nulls_first)
+ compare = -1; /* NULL "<" NOT_NULL */
+ else
+ compare = 1; /* NULL ">" NOT_NULL */
+ }
+ else if (isNull2)
+ {
+ if (ssup->ssup_nulls_first)
+ compare = 1; /* NOT_NULL ">" NULL */
+ else
+ compare = -1; /* NOT_NULL "<" NULL */
+ }
+ else
+ {
+ compare = datum1 < datum2 ? -1 : datum1 > datum2 ? 1 : 0;
+ if (ssup->ssup_reverse)
+ INVERT_COMPARE_RESULT(compare);
+ }
+
+ return compare;
+}
+
+#if SIZEOF_DATUM >= 8
+static inline int
+ApplySignedSortComparator(Datum datum1, bool isNull1,
+ Datum datum2, bool isNull2,
+ SortSupport ssup)
+{
+ int compare;
+
+ if (isNull1)
+ {
+ if (isNull2)
+ compare = 0; /* NULL "=" NULL */
+ else if (ssup->ssup_nulls_first)
+ compare = -1; /* NULL "<" NOT_NULL */
+ else
+ compare = 1; /* NULL ">" NOT_NULL */
+ }
+ else if (isNull2)
+ {
+ if (ssup->ssup_nulls_first)
+ compare = 1; /* NOT_NULL ">" NULL */
+ else
+ compare = -1; /* NOT_NULL "<" NULL */
+ }
+ else
+ {
+ compare = DatumGetInt64(datum1) < DatumGetInt64(datum2) ? -1 :
+ DatumGetInt64(datum1) > DatumGetInt64(datum2) ? 1 : 0;
+ if (ssup->ssup_reverse)
+ INVERT_COMPARE_RESULT(compare);
+ }
+
+ return compare;
+}
+#endif
+
+static inline int
+ApplyInt32SortComparator(Datum datum1, bool isNull1,
+ Datum datum2, bool isNull2,
+ SortSupport ssup)
+{
+ int compare;
+
+ if (isNull1)
+ {
+ if (isNull2)
+ compare = 0; /* NULL "=" NULL */
+ else if (ssup->ssup_nulls_first)
+ compare = -1; /* NULL "<" NOT_NULL */
+ else
+ compare = 1; /* NULL ">" NOT_NULL */
+ }
+ else if (isNull2)
+ {
+ if (ssup->ssup_nulls_first)
+ compare = 1; /* NOT_NULL ">" NULL */
+ else
+ compare = -1; /* NOT_NULL "<" NULL */
+ }
+ else
+ {
+ compare = DatumGetInt32(datum1) < DatumGetInt32(datum2) ? -1 :
+ DatumGetInt32(datum1) > DatumGetInt32(datum2) ? 1 : 0;
+ if (ssup->ssup_reverse)
+ INVERT_COMPARE_RESULT(compare);
+ }
+
+ return compare;
+}
+
+/*
+ * Apply a sort comparator function and return a 3-way comparison using full,
+ * authoritative comparator. This takes care of handling reverse-sort and
+ * NULLs-ordering properly.
+ */
+static inline int
+ApplySortAbbrevFullComparator(Datum datum1, bool isNull1,
+ Datum datum2, bool isNull2,
+ SortSupport ssup)
+{
+ int compare;
+
+ if (isNull1)
+ {
+ if (isNull2)
+ compare = 0; /* NULL "=" NULL */
+ else if (ssup->ssup_nulls_first)
+ compare = -1; /* NULL "<" NOT_NULL */
+ else
+ compare = 1; /* NULL ">" NOT_NULL */
+ }
+ else if (isNull2)
+ {
+ if (ssup->ssup_nulls_first)
+ compare = 1; /* NOT_NULL ">" NULL */
+ else
+ compare = -1; /* NOT_NULL "<" NULL */
+ }
+ else
+ {
+ compare = ssup->abbrev_full_comparator(datum1, datum2, ssup);
+ if (ssup->ssup_reverse)
+ INVERT_COMPARE_RESULT(compare);
+ }
+
+ return compare;
+}
+
+/*
+ * Datum comparison functions that we have specialized sort routines for.
+ * Datatypes that install these as their comparator or abbreviated comparator
+ * are eligible for faster sorting.
+ */
+extern int ssup_datum_unsigned_cmp(Datum x, Datum y, SortSupport ssup);
+#if SIZEOF_DATUM >= 8
+extern int ssup_datum_signed_cmp(Datum x, Datum y, SortSupport ssup);
+#endif
+extern int ssup_datum_int32_cmp(Datum x, Datum y, SortSupport ssup);
+
+/* Other functions in utils/sort/sortsupport.c */
+extern void PrepareSortSupportComparisonShim(Oid cmpFunc, SortSupport ssup);
+extern void PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup);
+extern void PrepareSortSupportFromIndexRel(Relation indexRel, int16 strategy,
+ SortSupport ssup);
+extern void PrepareSortSupportFromGistIndexRel(Relation indexRel, SortSupport ssup);
+
+#endif /* SORTSUPPORT_H */
diff --git a/src/include/utils/spccache.h b/src/include/utils/spccache.h
new file mode 100644
index 0000000..c6c754a
--- /dev/null
+++ b/src/include/utils/spccache.h
@@ -0,0 +1,21 @@
+/*-------------------------------------------------------------------------
+ *
+ * spccache.h
+ * Tablespace cache.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/spccache.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SPCCACHE_H
+#define SPCCACHE_H
+
+extern void get_tablespace_page_costs(Oid spcid, float8 *spc_random_page_cost,
+ float8 *spc_seq_page_cost);
+extern int get_tablespace_io_concurrency(Oid spcid);
+extern int get_tablespace_maintenance_io_concurrency(Oid spcid);
+
+#endif /* SPCCACHE_H */
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
new file mode 100644
index 0000000..67ea6e4
--- /dev/null
+++ b/src/include/utils/syscache.h
@@ -0,0 +1,227 @@
+/*-------------------------------------------------------------------------
+ *
+ * syscache.h
+ * System catalog cache definitions.
+ *
+ * See also lsyscache.h, which provides convenience routines for
+ * common cache-lookup operations.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/syscache.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SYSCACHE_H
+#define SYSCACHE_H
+
+#include "access/attnum.h"
+#include "access/htup.h"
+/* we intentionally do not include utils/catcache.h here */
+
+/*
+ * SysCache identifiers.
+ *
+ * The order of these identifiers must match the order
+ * of the entries in the array cacheinfo[] in syscache.c.
+ * Keep them in alphabetical order (renumbering only costs a
+ * backend rebuild).
+ */
+
+enum SysCacheIdentifier
+{
+ AGGFNOID = 0,
+ AMNAME,
+ AMOID,
+ AMOPOPID,
+ AMOPSTRATEGY,
+ AMPROCNUM,
+ ATTNAME,
+ ATTNUM,
+ AUTHMEMMEMROLE,
+ AUTHMEMROLEMEM,
+ AUTHNAME,
+ AUTHOID,
+ CASTSOURCETARGET,
+ CLAAMNAMENSP,
+ CLAOID,
+ COLLNAMEENCNSP,
+ COLLOID,
+ CONDEFAULT,
+ CONNAMENSP,
+ CONSTROID,
+ CONVOID,
+ DATABASEOID,
+ DEFACLROLENSPOBJ,
+ ENUMOID,
+ ENUMTYPOIDNAME,
+ EVENTTRIGGERNAME,
+ EVENTTRIGGEROID,
+ FOREIGNDATAWRAPPERNAME,
+ FOREIGNDATAWRAPPEROID,
+ FOREIGNSERVERNAME,
+ FOREIGNSERVEROID,
+ FOREIGNTABLEREL,
+ INDEXRELID,
+ LANGNAME,
+ LANGOID,
+ NAMESPACENAME,
+ NAMESPACEOID,
+ OPERNAMENSP,
+ OPEROID,
+ OPFAMILYAMNAMENSP,
+ OPFAMILYOID,
+ PARAMETERACLNAME,
+ PARAMETERACLOID,
+ PARTRELID,
+ PROCNAMEARGSNSP,
+ PROCOID,
+ PUBLICATIONNAME,
+ PUBLICATIONNAMESPACE,
+ PUBLICATIONNAMESPACEMAP,
+ PUBLICATIONOID,
+ PUBLICATIONREL,
+ PUBLICATIONRELMAP,
+ RANGEMULTIRANGE,
+ RANGETYPE,
+ RELNAMENSP,
+ RELOID,
+ REPLORIGIDENT,
+ REPLORIGNAME,
+ RULERELNAME,
+ SEQRELID,
+ STATEXTDATASTXOID,
+ STATEXTNAMENSP,
+ STATEXTOID,
+ STATRELATTINH,
+ SUBSCRIPTIONNAME,
+ SUBSCRIPTIONOID,
+ SUBSCRIPTIONRELMAP,
+ TABLESPACEOID,
+ TRFOID,
+ TRFTYPELANG,
+ TSCONFIGMAP,
+ TSCONFIGNAMENSP,
+ TSCONFIGOID,
+ TSDICTNAMENSP,
+ TSDICTOID,
+ TSPARSERNAMENSP,
+ TSPARSEROID,
+ TSTEMPLATENAMENSP,
+ TSTEMPLATEOID,
+ TYPENAMENSP,
+ TYPEOID,
+ USERMAPPINGOID,
+ USERMAPPINGUSERSERVER
+
+#define SysCacheSize (USERMAPPINGUSERSERVER + 1)
+};
+
+extern void InitCatalogCache(void);
+extern void InitCatalogCachePhase2(void);
+
+extern HeapTuple SearchSysCache(int cacheId,
+ Datum key1, Datum key2, Datum key3, Datum key4);
+
+/*
+ * The use of argument specific numbers is encouraged. They're faster, and
+ * insulates the caller from changes in the maximum number of keys.
+ */
+extern HeapTuple SearchSysCache1(int cacheId,
+ Datum key1);
+extern HeapTuple SearchSysCache2(int cacheId,
+ Datum key1, Datum key2);
+extern HeapTuple SearchSysCache3(int cacheId,
+ Datum key1, Datum key2, Datum key3);
+extern HeapTuple SearchSysCache4(int cacheId,
+ Datum key1, Datum key2, Datum key3, Datum key4);
+
+extern void ReleaseSysCache(HeapTuple tuple);
+
+/* convenience routines */
+extern HeapTuple SearchSysCacheCopy(int cacheId,
+ Datum key1, Datum key2, Datum key3, Datum key4);
+extern bool SearchSysCacheExists(int cacheId,
+ Datum key1, Datum key2, Datum key3, Datum key4);
+extern Oid GetSysCacheOid(int cacheId, AttrNumber oidcol,
+ Datum key1, Datum key2, Datum key3, Datum key4);
+
+extern HeapTuple SearchSysCacheAttName(Oid relid, const char *attname);
+extern HeapTuple SearchSysCacheCopyAttName(Oid relid, const char *attname);
+extern bool SearchSysCacheExistsAttName(Oid relid, const char *attname);
+
+extern HeapTuple SearchSysCacheAttNum(Oid relid, int16 attnum);
+extern HeapTuple SearchSysCacheCopyAttNum(Oid relid, int16 attnum);
+
+extern Datum SysCacheGetAttr(int cacheId, HeapTuple tup,
+ AttrNumber attributeNumber, bool *isNull);
+
+extern Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup,
+ AttrNumber attributeNumber);
+
+extern uint32 GetSysCacheHashValue(int cacheId,
+ Datum key1, Datum key2, Datum key3, Datum key4);
+
+/* list-search interface. Users of this must import catcache.h too */
+struct catclist;
+extern struct catclist *SearchSysCacheList(int cacheId, int nkeys,
+ Datum key1, Datum key2, Datum key3);
+
+extern void SysCacheInvalidate(int cacheId, uint32 hashValue);
+
+extern bool RelationInvalidatesSnapshotsOnly(Oid relid);
+extern bool RelationHasSysCache(Oid relid);
+extern bool RelationSupportsSysCache(Oid relid);
+
+/*
+ * The use of the macros below rather than direct calls to the corresponding
+ * functions is encouraged, as it insulates the caller from changes in the
+ * maximum number of keys.
+ */
+#define SearchSysCacheCopy1(cacheId, key1) \
+ SearchSysCacheCopy(cacheId, key1, 0, 0, 0)
+#define SearchSysCacheCopy2(cacheId, key1, key2) \
+ SearchSysCacheCopy(cacheId, key1, key2, 0, 0)
+#define SearchSysCacheCopy3(cacheId, key1, key2, key3) \
+ SearchSysCacheCopy(cacheId, key1, key2, key3, 0)
+#define SearchSysCacheCopy4(cacheId, key1, key2, key3, key4) \
+ SearchSysCacheCopy(cacheId, key1, key2, key3, key4)
+
+#define SearchSysCacheExists1(cacheId, key1) \
+ SearchSysCacheExists(cacheId, key1, 0, 0, 0)
+#define SearchSysCacheExists2(cacheId, key1, key2) \
+ SearchSysCacheExists(cacheId, key1, key2, 0, 0)
+#define SearchSysCacheExists3(cacheId, key1, key2, key3) \
+ SearchSysCacheExists(cacheId, key1, key2, key3, 0)
+#define SearchSysCacheExists4(cacheId, key1, key2, key3, key4) \
+ SearchSysCacheExists(cacheId, key1, key2, key3, key4)
+
+#define GetSysCacheOid1(cacheId, oidcol, key1) \
+ GetSysCacheOid(cacheId, oidcol, key1, 0, 0, 0)
+#define GetSysCacheOid2(cacheId, oidcol, key1, key2) \
+ GetSysCacheOid(cacheId, oidcol, key1, key2, 0, 0)
+#define GetSysCacheOid3(cacheId, oidcol, key1, key2, key3) \
+ GetSysCacheOid(cacheId, oidcol, key1, key2, key3, 0)
+#define GetSysCacheOid4(cacheId, oidcol, key1, key2, key3, key4) \
+ GetSysCacheOid(cacheId, oidcol, key1, key2, key3, key4)
+
+#define GetSysCacheHashValue1(cacheId, key1) \
+ GetSysCacheHashValue(cacheId, key1, 0, 0, 0)
+#define GetSysCacheHashValue2(cacheId, key1, key2) \
+ GetSysCacheHashValue(cacheId, key1, key2, 0, 0)
+#define GetSysCacheHashValue3(cacheId, key1, key2, key3) \
+ GetSysCacheHashValue(cacheId, key1, key2, key3, 0)
+#define GetSysCacheHashValue4(cacheId, key1, key2, key3, key4) \
+ GetSysCacheHashValue(cacheId, key1, key2, key3, key4)
+
+#define SearchSysCacheList1(cacheId, key1) \
+ SearchSysCacheList(cacheId, 1, key1, 0, 0)
+#define SearchSysCacheList2(cacheId, key1, key2) \
+ SearchSysCacheList(cacheId, 2, key1, key2, 0)
+#define SearchSysCacheList3(cacheId, key1, key2, key3) \
+ SearchSysCacheList(cacheId, 3, key1, key2, key3)
+
+#define ReleaseSysCacheList(x) ReleaseCatCacheList(x)
+
+#endif /* SYSCACHE_H */
diff --git a/src/include/utils/timeout.h b/src/include/utils/timeout.h
new file mode 100644
index 0000000..e561a1c
--- /dev/null
+++ b/src/include/utils/timeout.h
@@ -0,0 +1,95 @@
+/*-------------------------------------------------------------------------
+ *
+ * timeout.h
+ * Routines to multiplex SIGALRM interrupts for multiple timeout reasons.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/timeout.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TIMEOUT_H
+#define TIMEOUT_H
+
+#include "datatype/timestamp.h"
+
+/*
+ * Identifiers for timeout reasons. Note that in case multiple timeouts
+ * trigger at the same time, they are serviced in the order of this enum.
+ */
+typedef enum TimeoutId
+{
+ /* Predefined timeout reasons */
+ STARTUP_PACKET_TIMEOUT,
+ DEADLOCK_TIMEOUT,
+ LOCK_TIMEOUT,
+ STATEMENT_TIMEOUT,
+ STANDBY_DEADLOCK_TIMEOUT,
+ STANDBY_TIMEOUT,
+ STANDBY_LOCK_TIMEOUT,
+ IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
+ IDLE_SESSION_TIMEOUT,
+ IDLE_STATS_UPDATE_TIMEOUT,
+ CLIENT_CONNECTION_CHECK_TIMEOUT,
+ STARTUP_PROGRESS_TIMEOUT,
+ /* First user-definable timeout reason */
+ USER_TIMEOUT,
+ /* Maximum number of timeout reasons */
+ MAX_TIMEOUTS = USER_TIMEOUT + 10
+} TimeoutId;
+
+/* callback function signature */
+typedef void (*timeout_handler_proc) (void);
+
+/*
+ * Parameter structure for setting multiple timeouts at once
+ */
+typedef enum TimeoutType
+{
+ TMPARAM_AFTER,
+ TMPARAM_AT,
+ TMPARAM_EVERY
+} TimeoutType;
+
+typedef struct
+{
+ TimeoutId id; /* timeout to set */
+ TimeoutType type; /* TMPARAM_AFTER or TMPARAM_AT */
+ int delay_ms; /* only used for TMPARAM_AFTER/EVERY */
+ TimestampTz fin_time; /* only used for TMPARAM_AT */
+} EnableTimeoutParams;
+
+/*
+ * Parameter structure for clearing multiple timeouts at once
+ */
+typedef struct
+{
+ TimeoutId id; /* timeout to clear */
+ bool keep_indicator; /* keep the indicator flag? */
+} DisableTimeoutParams;
+
+/* timeout setup */
+extern void InitializeTimeouts(void);
+extern TimeoutId RegisterTimeout(TimeoutId id, timeout_handler_proc handler);
+extern void reschedule_timeouts(void);
+
+/* timeout operation */
+extern void enable_timeout_after(TimeoutId id, int delay_ms);
+extern void enable_timeout_every(TimeoutId id, TimestampTz fin_time,
+ int delay_ms);
+extern void enable_timeout_at(TimeoutId id, TimestampTz fin_time);
+extern void enable_timeouts(const EnableTimeoutParams *timeouts, int count);
+extern void disable_timeout(TimeoutId id, bool keep_indicator);
+extern void disable_timeouts(const DisableTimeoutParams *timeouts, int count);
+extern void disable_all_timeouts(bool keep_indicators);
+
+/* accessors */
+extern bool get_timeout_active(TimeoutId id);
+extern bool get_timeout_indicator(TimeoutId id, bool reset_indicator);
+extern TimestampTz get_timeout_start_time(TimeoutId id);
+extern TimestampTz get_timeout_finish_time(TimeoutId id);
+
+#endif /* TIMEOUT_H */
diff --git a/src/include/utils/timestamp.h b/src/include/utils/timestamp.h
new file mode 100644
index 0000000..c4dd96c
--- /dev/null
+++ b/src/include/utils/timestamp.h
@@ -0,0 +1,147 @@
+/*-------------------------------------------------------------------------
+ *
+ * timestamp.h
+ * Definitions for the SQL "timestamp" and "interval" types.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/timestamp.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TIMESTAMP_H
+#define TIMESTAMP_H
+
+#include "datatype/timestamp.h"
+#include "fmgr.h"
+#include "pgtime.h"
+
+
+/*
+ * Functions for fmgr-callable functions.
+ *
+ * For Timestamp, we make use of the same support routines as for int64.
+ * Therefore Timestamp is pass-by-reference if and only if int64 is!
+ */
+static inline Timestamp
+DatumGetTimestamp(Datum X)
+{
+ return (Timestamp) DatumGetInt64(X);
+}
+
+static inline TimestampTz
+DatumGetTimestampTz(Datum X)
+{
+ return (TimestampTz) DatumGetInt64(X);
+}
+
+static inline Interval *
+DatumGetIntervalP(Datum X)
+{
+ return (Interval *) DatumGetPointer(X);
+}
+
+static inline Datum
+TimestampGetDatum(Timestamp X)
+{
+ return Int64GetDatum(X);
+}
+
+static inline Datum
+TimestampTzGetDatum(TimestampTz X)
+{
+ return Int64GetDatum(X);
+}
+
+static inline Datum
+IntervalPGetDatum(const Interval *X)
+{
+ return PointerGetDatum(X);
+}
+
+#define PG_GETARG_TIMESTAMP(n) DatumGetTimestamp(PG_GETARG_DATUM(n))
+#define PG_GETARG_TIMESTAMPTZ(n) DatumGetTimestampTz(PG_GETARG_DATUM(n))
+#define PG_GETARG_INTERVAL_P(n) DatumGetIntervalP(PG_GETARG_DATUM(n))
+
+#define PG_RETURN_TIMESTAMP(x) return TimestampGetDatum(x)
+#define PG_RETURN_TIMESTAMPTZ(x) return TimestampTzGetDatum(x)
+#define PG_RETURN_INTERVAL_P(x) return IntervalPGetDatum(x)
+
+
+#define TIMESTAMP_MASK(b) (1 << (b))
+#define INTERVAL_MASK(b) (1 << (b))
+
+/* Macros to handle packing and unpacking the typmod field for intervals */
+#define INTERVAL_FULL_RANGE (0x7FFF)
+#define INTERVAL_RANGE_MASK (0x7FFF)
+#define INTERVAL_FULL_PRECISION (0xFFFF)
+#define INTERVAL_PRECISION_MASK (0xFFFF)
+#define INTERVAL_TYPMOD(p,r) ((((r) & INTERVAL_RANGE_MASK) << 16) | ((p) & INTERVAL_PRECISION_MASK))
+#define INTERVAL_PRECISION(t) ((t) & INTERVAL_PRECISION_MASK)
+#define INTERVAL_RANGE(t) (((t) >> 16) & INTERVAL_RANGE_MASK)
+
+/* Macros for doing timestamp arithmetic without assuming timestamp's units */
+#define TimestampTzPlusMilliseconds(tz,ms) ((tz) + ((ms) * (int64) 1000))
+#define TimestampTzPlusSeconds(tz,s) ((tz) + ((s) * (int64) 1000000))
+
+
+/* Set at postmaster start */
+extern PGDLLIMPORT TimestampTz PgStartTime;
+
+/* Set at configuration reload */
+extern PGDLLIMPORT TimestampTz PgReloadTime;
+
+
+/* Internal routines (not fmgr-callable) */
+
+extern int32 anytimestamp_typmod_check(bool istz, int32 typmod);
+
+extern TimestampTz GetCurrentTimestamp(void);
+extern TimestampTz GetSQLCurrentTimestamp(int32 typmod);
+extern Timestamp GetSQLLocalTimestamp(int32 typmod);
+extern void TimestampDifference(TimestampTz start_time, TimestampTz stop_time,
+ long *secs, int *microsecs);
+extern long TimestampDifferenceMilliseconds(TimestampTz start_time,
+ TimestampTz stop_time);
+extern bool TimestampDifferenceExceeds(TimestampTz start_time,
+ TimestampTz stop_time,
+ int msec);
+
+extern TimestampTz time_t_to_timestamptz(pg_time_t tm);
+extern pg_time_t timestamptz_to_time_t(TimestampTz t);
+
+extern const char *timestamptz_to_str(TimestampTz t);
+
+extern int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result);
+extern int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm,
+ fsec_t *fsec, const char **tzn, pg_tz *attimezone);
+extern void dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec);
+
+extern void interval2itm(Interval span, struct pg_itm *itm);
+extern int itm2interval(struct pg_itm *itm, Interval *span);
+extern int itmin2interval(struct pg_itm_in *itm_in, Interval *span);
+
+extern Timestamp SetEpochTimestamp(void);
+extern void GetEpochTime(struct pg_tm *tm);
+
+extern int timestamp_cmp_internal(Timestamp dt1, Timestamp dt2);
+
+/* timestamp comparison works for timestamptz also */
+#define timestamptz_cmp_internal(dt1,dt2) timestamp_cmp_internal(dt1, dt2)
+
+extern TimestampTz timestamp2timestamptz_opt_overflow(Timestamp timestamp,
+ int *overflow);
+extern int32 timestamp_cmp_timestamptz_internal(Timestamp timestampVal,
+ TimestampTz dt2);
+
+extern int isoweek2j(int year, int week);
+extern void isoweek2date(int woy, int *year, int *mon, int *mday);
+extern void isoweekdate2date(int isoweek, int wday, int *year, int *mon, int *mday);
+extern int date2isoweek(int year, int mon, int mday);
+extern int date2isoyear(int year, int mon, int mday);
+extern int date2isoyearday(int year, int mon, int mday);
+
+extern bool TimestampTimestampTzRequiresRewrite(void);
+
+#endif /* TIMESTAMP_H */
diff --git a/src/include/utils/tuplesort.h b/src/include/utils/tuplesort.h
new file mode 100644
index 0000000..af057b6
--- /dev/null
+++ b/src/include/utils/tuplesort.h
@@ -0,0 +1,445 @@
+/*-------------------------------------------------------------------------
+ *
+ * tuplesort.h
+ * Generalized tuple sorting routines.
+ *
+ * This module handles sorting of heap tuples, index tuples, or single
+ * Datums (and could easily support other kinds of sortable objects,
+ * if necessary). It works efficiently for both small and large amounts
+ * of data. Small amounts are sorted in-memory using qsort(). Large
+ * amounts are sorted using temporary files and a standard external sort
+ * algorithm. Parallel sorts use a variant of this external sort
+ * algorithm, and are typically only used for large amounts of data.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/tuplesort.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TUPLESORT_H
+#define TUPLESORT_H
+
+#include "access/itup.h"
+#include "executor/tuptable.h"
+#include "storage/dsm.h"
+#include "utils/logtape.h"
+#include "utils/relcache.h"
+#include "utils/sortsupport.h"
+
+
+/*
+ * Tuplesortstate and Sharedsort are opaque types whose details are not
+ * known outside tuplesort.c.
+ */
+typedef struct Tuplesortstate Tuplesortstate;
+typedef struct Sharedsort Sharedsort;
+
+/*
+ * Tuplesort parallel coordination state, allocated by each participant in
+ * local memory. Participant caller initializes everything. See usage notes
+ * below.
+ */
+typedef struct SortCoordinateData
+{
+ /* Worker process? If not, must be leader. */
+ bool isWorker;
+
+ /*
+ * Leader-process-passed number of participants known launched (workers
+ * set this to -1). Includes state within leader needed for it to
+ * participate as a worker, if any.
+ */
+ int nParticipants;
+
+ /* Private opaque state (points to shared memory) */
+ Sharedsort *sharedsort;
+} SortCoordinateData;
+
+typedef struct SortCoordinateData *SortCoordinate;
+
+/*
+ * Data structures for reporting sort statistics. Note that
+ * TuplesortInstrumentation can't contain any pointers because we
+ * sometimes put it in shared memory.
+ *
+ * The parallel-sort infrastructure relies on having a zero TuplesortMethod
+ * to indicate that a worker never did anything, so we assign zero to
+ * SORT_TYPE_STILL_IN_PROGRESS. The other values of this enum can be
+ * OR'ed together to represent a situation where different workers used
+ * different methods, so we need a separate bit for each one. Keep the
+ * NUM_TUPLESORTMETHODS constant in sync with the number of bits!
+ */
+typedef enum
+{
+ SORT_TYPE_STILL_IN_PROGRESS = 0,
+ SORT_TYPE_TOP_N_HEAPSORT = 1 << 0,
+ SORT_TYPE_QUICKSORT = 1 << 1,
+ SORT_TYPE_EXTERNAL_SORT = 1 << 2,
+ SORT_TYPE_EXTERNAL_MERGE = 1 << 3
+} TuplesortMethod;
+
+#define NUM_TUPLESORTMETHODS 4
+
+typedef enum
+{
+ SORT_SPACE_TYPE_DISK,
+ SORT_SPACE_TYPE_MEMORY
+} TuplesortSpaceType;
+
+/* Bitwise option flags for tuple sorts */
+#define TUPLESORT_NONE 0
+
+/* specifies whether non-sequential access to the sort result is required */
+#define TUPLESORT_RANDOMACCESS (1 << 0)
+
+/* specifies if the tuplesort is able to support bounded sorts */
+#define TUPLESORT_ALLOWBOUNDED (1 << 1)
+
+typedef struct TuplesortInstrumentation
+{
+ TuplesortMethod sortMethod; /* sort algorithm used */
+ TuplesortSpaceType spaceType; /* type of space spaceUsed represents */
+ int64 spaceUsed; /* space consumption, in kB */
+} TuplesortInstrumentation;
+
+/*
+ * The objects we actually sort are SortTuple structs. These contain
+ * a pointer to the tuple proper (might be a MinimalTuple or IndexTuple),
+ * which is a separate palloc chunk --- we assume it is just one chunk and
+ * can be freed by a simple pfree() (except during merge, when we use a
+ * simple slab allocator). SortTuples also contain the tuple's first key
+ * column in Datum/nullflag format, and a source/input tape number that
+ * tracks which tape each heap element/slot belongs to during merging.
+ *
+ * Storing the first key column lets us save heap_getattr or index_getattr
+ * calls during tuple comparisons. We could extract and save all the key
+ * columns not just the first, but this would increase code complexity and
+ * overhead, and wouldn't actually save any comparison cycles in the common
+ * case where the first key determines the comparison result. Note that
+ * for a pass-by-reference datatype, datum1 points into the "tuple" storage.
+ *
+ * There is one special case: when the sort support infrastructure provides an
+ * "abbreviated key" representation, where the key is (typically) a pass by
+ * value proxy for a pass by reference type. In this case, the abbreviated key
+ * is stored in datum1 in place of the actual first key column.
+ *
+ * When sorting single Datums, the data value is represented directly by
+ * datum1/isnull1 for pass by value types (or null values). If the datatype is
+ * pass-by-reference and isnull1 is false, then "tuple" points to a separately
+ * palloc'd data value, otherwise "tuple" is NULL. The value of datum1 is then
+ * either the same pointer as "tuple", or is an abbreviated key value as
+ * described above. Accordingly, "tuple" is always used in preference to
+ * datum1 as the authoritative value for pass-by-reference cases.
+ */
+typedef struct
+{
+ void *tuple; /* the tuple itself */
+ Datum datum1; /* value of first key column */
+ bool isnull1; /* is first key column NULL? */
+ int srctape; /* source tape number */
+} SortTuple;
+
+typedef int (*SortTupleComparator) (const SortTuple *a, const SortTuple *b,
+ Tuplesortstate *state);
+
+/*
+ * The public part of a Tuple sort operation state. This data structure
+ * contains the definition of sort-variant-specific interface methods and
+ * the part of Tuple sort operation state required by their implementations.
+ */
+typedef struct
+{
+ /*
+ * These function pointers decouple the routines that must know what kind
+ * of tuple we are sorting from the routines that don't need to know it.
+ * They are set up by the tuplesort_begin_xxx routines.
+ *
+ * Function to compare two tuples; result is per qsort() convention, ie:
+ * <0, 0, >0 according as a<b, a=b, a>b. The API must match
+ * qsort_arg_comparator.
+ */
+ SortTupleComparator comparetup;
+
+ /*
+ * Alter datum1 representation in the SortTuple's array back from the
+ * abbreviated key to the first column value.
+ */
+ void (*removeabbrev) (Tuplesortstate *state, SortTuple *stups,
+ int count);
+
+ /*
+ * Function to write a stored tuple onto tape. The representation of the
+ * tuple on tape need not be the same as it is in memory.
+ */
+ void (*writetup) (Tuplesortstate *state, LogicalTape *tape,
+ SortTuple *stup);
+
+ /*
+ * Function to read a stored tuple from tape back into memory. 'len' is
+ * the already-read length of the stored tuple. The tuple is allocated
+ * from the slab memory arena, or is palloc'd, see
+ * tuplesort_readtup_alloc().
+ */
+ void (*readtup) (Tuplesortstate *state, SortTuple *stup,
+ LogicalTape *tape, unsigned int len);
+
+ /*
+ * Function to do some specific release of resources for the sort variant.
+ * In particular, this function should free everything stored in the "arg"
+ * field, which wouldn't be cleared on reset of the Tuple sort memory
+ * contexts. This can be NULL if nothing specific needs to be done.
+ */
+ void (*freestate) (Tuplesortstate *state);
+
+ /*
+ * The subsequent fields are used in the implementations of the functions
+ * above.
+ */
+ MemoryContext maincontext; /* memory context for tuple sort metadata that
+ * persists across multiple batches */
+ MemoryContext sortcontext; /* memory context holding most sort data */
+ MemoryContext tuplecontext; /* sub-context of sortcontext for tuple data */
+
+ /*
+ * Whether SortTuple's datum1 and isnull1 members are maintained by the
+ * above routines. If not, some sort specializations are disabled.
+ */
+ bool haveDatum1;
+
+ /*
+ * The sortKeys variable is used by every case other than the hash index
+ * case; it is set by tuplesort_begin_xxx. tupDesc is only used by the
+ * MinimalTuple and CLUSTER routines, though.
+ */
+ int nKeys; /* number of columns in sort key */
+ SortSupport sortKeys; /* array of length nKeys */
+
+ /*
+ * This variable is shared by the single-key MinimalTuple case and the
+ * Datum case (which both use qsort_ssup()). Otherwise, it's NULL. The
+ * presence of a value in this field is also checked by various sort
+ * specialization functions as an optimization when comparing the leading
+ * key in a tiebreak situation to determine if there are any subsequent
+ * keys to sort on.
+ */
+ SortSupport onlyKey;
+
+ int sortopt; /* Bitmask of flags used to setup sort */
+
+ bool tuples; /* Can SortTuple.tuple ever be set? */
+
+ void *arg; /* Specific information for the sort variant */
+} TuplesortPublic;
+
+/* Sort parallel code from state for sort__start probes */
+#define PARALLEL_SORT(coordinate) (coordinate == NULL || \
+ (coordinate)->sharedsort == NULL ? 0 : \
+ (coordinate)->isWorker ? 1 : 2)
+
+#define TuplesortstateGetPublic(state) ((TuplesortPublic *) state)
+
+/* When using this macro, beware of double evaluation of len */
+#define LogicalTapeReadExact(tape, ptr, len) \
+ do { \
+ if (LogicalTapeRead(tape, ptr, len) != (size_t) (len)) \
+ elog(ERROR, "unexpected end of data"); \
+ } while(0)
+
+/*
+ * We provide multiple interfaces to what is essentially the same code,
+ * since different callers have different data to be sorted and want to
+ * specify the sort key information differently. There are two APIs for
+ * sorting HeapTuples and two more for sorting IndexTuples. Yet another
+ * API supports sorting bare Datums.
+ *
+ * Serial sort callers should pass NULL for their coordinate argument.
+ *
+ * The "heap" API actually stores/sorts MinimalTuples, which means it doesn't
+ * preserve the system columns (tuple identity and transaction visibility
+ * info). The sort keys are specified by column numbers within the tuples
+ * and sort operator OIDs. We save some cycles by passing and returning the
+ * tuples in TupleTableSlots, rather than forming actual HeapTuples (which'd
+ * have to be converted to MinimalTuples). This API works well for sorts
+ * executed as parts of plan trees.
+ *
+ * The "cluster" API stores/sorts full HeapTuples including all visibility
+ * info. The sort keys are specified by reference to a btree index that is
+ * defined on the relation to be sorted. Note that putheaptuple/getheaptuple
+ * go with this API, not the "begin_heap" one!
+ *
+ * The "index_btree" API stores/sorts IndexTuples (preserving all their
+ * header fields). The sort keys are specified by a btree index definition.
+ *
+ * The "index_hash" API is similar to index_btree, but the tuples are
+ * actually sorted by their hash codes not the raw data.
+ *
+ * Parallel sort callers are required to coordinate multiple tuplesort states
+ * in a leader process and one or more worker processes. The leader process
+ * must launch workers, and have each perform an independent "partial"
+ * tuplesort, typically fed by the parallel heap interface. The leader later
+ * produces the final output (internally, it merges runs output by workers).
+ *
+ * Callers must do the following to perform a sort in parallel using multiple
+ * worker processes:
+ *
+ * 1. Request tuplesort-private shared memory for n workers. Use
+ * tuplesort_estimate_shared() to get the required size.
+ * 2. Have leader process initialize allocated shared memory using
+ * tuplesort_initialize_shared(). Launch workers.
+ * 3. Initialize a coordinate argument within both the leader process, and
+ * for each worker process. This has a pointer to the shared
+ * tuplesort-private structure, as well as some caller-initialized fields.
+ * Leader's coordinate argument reliably indicates number of workers
+ * launched (this is unused by workers).
+ * 4. Begin a tuplesort using some appropriate tuplesort_begin* routine,
+ * (passing the coordinate argument) within each worker. The workMem
+ * arguments need not be identical. All other arguments should match
+ * exactly, though.
+ * 5. tuplesort_attach_shared() should be called by all workers. Feed tuples
+ * to each worker, and call tuplesort_performsort() within each when input
+ * is exhausted.
+ * 6. Call tuplesort_end() in each worker process. Worker processes can shut
+ * down once tuplesort_end() returns.
+ * 7. Begin a tuplesort in the leader using the same tuplesort_begin*
+ * routine, passing a leader-appropriate coordinate argument (this can
+ * happen as early as during step 3, actually, since we only need to know
+ * the number of workers successfully launched). The leader must now wait
+ * for workers to finish. Caller must use own mechanism for ensuring that
+ * next step isn't reached until all workers have called and returned from
+ * tuplesort_performsort(). (Note that it's okay if workers have already
+ * also called tuplesort_end() by then.)
+ * 8. Call tuplesort_performsort() in leader. Consume output using the
+ * appropriate tuplesort_get* routine. Leader can skip this step if
+ * tuplesort turns out to be unnecessary.
+ * 9. Call tuplesort_end() in leader.
+ *
+ * This division of labor assumes nothing about how input tuples are produced,
+ * but does require that caller combine the state of multiple tuplesorts for
+ * any purpose other than producing the final output. For example, callers
+ * must consider that tuplesort_get_stats() reports on only one worker's role
+ * in a sort (or the leader's role), and not statistics for the sort as a
+ * whole.
+ *
+ * Note that callers may use the leader process to sort runs as if it was an
+ * independent worker process (prior to the process performing a leader sort
+ * to produce the final sorted output). Doing so only requires a second
+ * "partial" tuplesort within the leader process, initialized like that of a
+ * worker process. The steps above don't touch on this directly. The only
+ * difference is that the tuplesort_attach_shared() call is never needed within
+ * leader process, because the backend as a whole holds the shared fileset
+ * reference. A worker Tuplesortstate in leader is expected to do exactly the
+ * same amount of total initial processing work as a worker process
+ * Tuplesortstate, since the leader process has nothing else to do before
+ * workers finish.
+ *
+ * Note that only a very small amount of memory will be allocated prior to
+ * the leader state first consuming input, and that workers will free the
+ * vast majority of their memory upon returning from tuplesort_performsort().
+ * Callers can rely on this to arrange for memory to be used in a way that
+ * respects a workMem-style budget across an entire parallel sort operation.
+ *
+ * Callers are responsible for parallel safety in general. However, they
+ * can at least rely on there being no parallel safety hazards within
+ * tuplesort, because tuplesort thinks of the sort as several independent
+ * sorts whose results are combined. Since, in general, the behavior of
+ * sort operators is immutable, caller need only worry about the parallel
+ * safety of whatever the process is through which input tuples are
+ * generated (typically, caller uses a parallel heap scan).
+ */
+
+
+extern Tuplesortstate *tuplesort_begin_common(int workMem,
+ SortCoordinate coordinate,
+ int sortopt);
+extern void tuplesort_set_bound(Tuplesortstate *state, int64 bound);
+extern bool tuplesort_used_bound(Tuplesortstate *state);
+extern void tuplesort_puttuple_common(Tuplesortstate *state,
+ SortTuple *tuple, bool useAbbrev);
+extern void tuplesort_performsort(Tuplesortstate *state);
+extern bool tuplesort_gettuple_common(Tuplesortstate *state, bool forward,
+ SortTuple *stup);
+extern bool tuplesort_skiptuples(Tuplesortstate *state, int64 ntuples,
+ bool forward);
+extern void tuplesort_end(Tuplesortstate *state);
+extern void tuplesort_reset(Tuplesortstate *state);
+
+extern void tuplesort_get_stats(Tuplesortstate *state,
+ TuplesortInstrumentation *stats);
+extern const char *tuplesort_method_name(TuplesortMethod m);
+extern const char *tuplesort_space_type_name(TuplesortSpaceType t);
+
+extern int tuplesort_merge_order(int64 allowedMem);
+
+extern Size tuplesort_estimate_shared(int nWorkers);
+extern void tuplesort_initialize_shared(Sharedsort *shared, int nWorkers,
+ dsm_segment *seg);
+extern void tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg);
+
+/*
+ * These routines may only be called if TUPLESORT_RANDOMACCESS was specified
+ * during tuplesort_begin_*. Additionally backwards scan in gettuple/getdatum
+ * also require TUPLESORT_RANDOMACCESS. Note that parallel sorts do not
+ * support random access.
+ */
+extern void tuplesort_rescan(Tuplesortstate *state);
+extern void tuplesort_markpos(Tuplesortstate *state);
+extern void tuplesort_restorepos(Tuplesortstate *state);
+
+extern void *tuplesort_readtup_alloc(Tuplesortstate *state, Size tuplen);
+
+
+/* tuplesortvariants.c */
+
+extern Tuplesortstate *tuplesort_begin_heap(TupleDesc tupDesc,
+ int nkeys, AttrNumber *attNums,
+ Oid *sortOperators, Oid *sortCollations,
+ bool *nullsFirstFlags,
+ int workMem, SortCoordinate coordinate,
+ int sortopt);
+extern Tuplesortstate *tuplesort_begin_cluster(TupleDesc tupDesc,
+ Relation indexRel, int workMem,
+ SortCoordinate coordinate,
+ int sortopt);
+extern Tuplesortstate *tuplesort_begin_index_btree(Relation heapRel,
+ Relation indexRel,
+ bool enforceUnique,
+ bool uniqueNullsNotDistinct,
+ int workMem, SortCoordinate coordinate,
+ int sortopt);
+extern Tuplesortstate *tuplesort_begin_index_hash(Relation heapRel,
+ Relation indexRel,
+ uint32 high_mask,
+ uint32 low_mask,
+ uint32 max_buckets,
+ int workMem, SortCoordinate coordinate,
+ int sortopt);
+extern Tuplesortstate *tuplesort_begin_index_gist(Relation heapRel,
+ Relation indexRel,
+ int workMem, SortCoordinate coordinate,
+ int sortopt);
+extern Tuplesortstate *tuplesort_begin_datum(Oid datumType,
+ Oid sortOperator, Oid sortCollation,
+ bool nullsFirstFlag,
+ int workMem, SortCoordinate coordinate,
+ int sortopt);
+
+extern void tuplesort_puttupleslot(Tuplesortstate *state,
+ TupleTableSlot *slot);
+extern void tuplesort_putheaptuple(Tuplesortstate *state, HeapTuple tup);
+extern void tuplesort_putindextuplevalues(Tuplesortstate *state,
+ Relation rel, ItemPointer self,
+ Datum *values, bool *isnull);
+extern void tuplesort_putdatum(Tuplesortstate *state, Datum val,
+ bool isNull);
+
+extern bool tuplesort_gettupleslot(Tuplesortstate *state, bool forward,
+ bool copy, TupleTableSlot *slot, Datum *abbrev);
+extern HeapTuple tuplesort_getheaptuple(Tuplesortstate *state, bool forward);
+extern IndexTuple tuplesort_getindextuple(Tuplesortstate *state, bool forward);
+extern bool tuplesort_getdatum(Tuplesortstate *state, bool forward, bool copy,
+ Datum *val, bool *isNull, Datum *abbrev);
+
+
+#endif /* TUPLESORT_H */
diff --git a/src/include/utils/tuplestore.h b/src/include/utils/tuplestore.h
new file mode 100644
index 0000000..36424b8
--- /dev/null
+++ b/src/include/utils/tuplestore.h
@@ -0,0 +1,91 @@
+/*-------------------------------------------------------------------------
+ *
+ * tuplestore.h
+ * Generalized routines for temporary tuple storage.
+ *
+ * This module handles temporary storage of tuples for purposes such
+ * as Materialize nodes, hashjoin batch files, etc. It is essentially
+ * a dumbed-down version of tuplesort.c; it does no sorting of tuples
+ * but can only store and regurgitate a sequence of tuples. However,
+ * because no sort is required, it is allowed to start reading the sequence
+ * before it has all been written. This is particularly useful for cursors,
+ * because it allows random access within the already-scanned portion of
+ * a query without having to process the underlying scan to completion.
+ * Also, it is possible to support multiple independent read pointers.
+ *
+ * A temporary file is used to handle the data if it exceeds the
+ * space limit specified by the caller.
+ *
+ * Beginning in Postgres 8.2, what is stored is just MinimalTuples;
+ * callers cannot expect valid system columns in regurgitated tuples.
+ * Also, we have changed the API to return tuples in TupleTableSlots,
+ * so that there is a check to prevent attempted access to system columns.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/tuplestore.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TUPLESTORE_H
+#define TUPLESTORE_H
+
+#include "executor/tuptable.h"
+
+
+/* Tuplestorestate is an opaque type whose details are not known outside
+ * tuplestore.c.
+ */
+typedef struct Tuplestorestate Tuplestorestate;
+
+/*
+ * Currently we only need to store MinimalTuples, but it would be easy
+ * to support the same behavior for IndexTuples and/or bare Datums.
+ */
+
+extern Tuplestorestate *tuplestore_begin_heap(bool randomAccess,
+ bool interXact,
+ int maxKBytes);
+
+extern void tuplestore_set_eflags(Tuplestorestate *state, int eflags);
+
+extern void tuplestore_puttupleslot(Tuplestorestate *state,
+ TupleTableSlot *slot);
+extern void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple);
+extern void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc,
+ Datum *values, bool *isnull);
+
+/* Backwards compatibility macro */
+#define tuplestore_donestoring(state) ((void) 0)
+
+extern int tuplestore_alloc_read_pointer(Tuplestorestate *state, int eflags);
+
+extern void tuplestore_select_read_pointer(Tuplestorestate *state, int ptr);
+
+extern void tuplestore_copy_read_pointer(Tuplestorestate *state,
+ int srcptr, int destptr);
+
+extern void tuplestore_trim(Tuplestorestate *state);
+
+extern bool tuplestore_in_memory(Tuplestorestate *state);
+
+extern bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward,
+ bool copy, TupleTableSlot *slot);
+
+extern bool tuplestore_advance(Tuplestorestate *state, bool forward);
+
+extern bool tuplestore_skiptuples(Tuplestorestate *state,
+ int64 ntuples, bool forward);
+
+extern int64 tuplestore_tuple_count(Tuplestorestate *state);
+
+extern bool tuplestore_ateof(Tuplestorestate *state);
+
+extern void tuplestore_rescan(Tuplestorestate *state);
+
+extern void tuplestore_clear(Tuplestorestate *state);
+
+extern void tuplestore_end(Tuplestorestate *state);
+
+#endif /* TUPLESTORE_H */
diff --git a/src/include/utils/typcache.h b/src/include/utils/typcache.h
new file mode 100644
index 0000000..95f3a9e
--- /dev/null
+++ b/src/include/utils/typcache.h
@@ -0,0 +1,209 @@
+/*-------------------------------------------------------------------------
+ *
+ * typcache.h
+ * Type cache definitions.
+ *
+ * The type cache exists to speed lookup of certain information about data
+ * types that is not directly available from a type's pg_type row.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/typcache.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TYPCACHE_H
+#define TYPCACHE_H
+
+#include "access/tupdesc.h"
+#include "fmgr.h"
+#include "storage/dsm.h"
+#include "utils/dsa.h"
+
+
+/* DomainConstraintCache is an opaque struct known only within typcache.c */
+typedef struct DomainConstraintCache DomainConstraintCache;
+
+/* TypeCacheEnumData is an opaque struct known only within typcache.c */
+struct TypeCacheEnumData;
+
+typedef struct TypeCacheEntry
+{
+ /* typeId is the hash lookup key and MUST BE FIRST */
+ Oid type_id; /* OID of the data type */
+
+ uint32 type_id_hash; /* hashed value of the OID */
+
+ /* some subsidiary information copied from the pg_type row */
+ int16 typlen;
+ bool typbyval;
+ char typalign;
+ char typstorage;
+ char typtype;
+ Oid typrelid;
+ Oid typsubscript;
+ Oid typelem;
+ Oid typcollation;
+
+ /*
+ * Information obtained from opfamily entries
+ *
+ * These will be InvalidOid if no match could be found, or if the
+ * information hasn't yet been requested. Also note that for array and
+ * composite types, typcache.c checks that the contained types are
+ * comparable or hashable before allowing eq_opr etc to become set.
+ */
+ Oid btree_opf; /* the default btree opclass' family */
+ Oid btree_opintype; /* the default btree opclass' opcintype */
+ Oid hash_opf; /* the default hash opclass' family */
+ Oid hash_opintype; /* the default hash opclass' opcintype */
+ Oid eq_opr; /* the equality operator */
+ Oid lt_opr; /* the less-than operator */
+ Oid gt_opr; /* the greater-than operator */
+ Oid cmp_proc; /* the btree comparison function */
+ Oid hash_proc; /* the hash calculation function */
+ Oid hash_extended_proc; /* the extended hash calculation function */
+
+ /*
+ * Pre-set-up fmgr call info for the equality operator, the btree
+ * comparison function, and the hash calculation function. These are kept
+ * in the type cache to avoid problems with memory leaks in repeated calls
+ * to functions such as array_eq, array_cmp, hash_array. There is not
+ * currently a need to maintain call info for the lt_opr or gt_opr.
+ */
+ FmgrInfo eq_opr_finfo;
+ FmgrInfo cmp_proc_finfo;
+ FmgrInfo hash_proc_finfo;
+ FmgrInfo hash_extended_proc_finfo;
+
+ /*
+ * Tuple descriptor if it's a composite type (row type). NULL if not
+ * composite or information hasn't yet been requested. (NOTE: this is a
+ * reference-counted tupledesc.)
+ *
+ * To simplify caching dependent info, tupDesc_identifier is an identifier
+ * for this tupledesc that is unique for the life of the process, and
+ * changes anytime the tupledesc does. Zero if not yet determined.
+ */
+ TupleDesc tupDesc;
+ uint64 tupDesc_identifier;
+
+ /*
+ * Fields computed when TYPECACHE_RANGE_INFO is requested. Zeroes if not
+ * a range type or information hasn't yet been requested. Note that
+ * rng_cmp_proc_finfo could be different from the element type's default
+ * btree comparison function.
+ */
+ struct TypeCacheEntry *rngelemtype; /* range's element type */
+ Oid rng_collation; /* collation for comparisons, if any */
+ FmgrInfo rng_cmp_proc_finfo; /* comparison function */
+ FmgrInfo rng_canonical_finfo; /* canonicalization function, if any */
+ FmgrInfo rng_subdiff_finfo; /* difference function, if any */
+
+ /*
+ * Fields computed when TYPECACHE_MULTIRANGE_INFO is required.
+ */
+ struct TypeCacheEntry *rngtype; /* multirange's range underlying type */
+
+ /*
+ * Domain's base type and typmod if it's a domain type. Zeroes if not
+ * domain, or if information hasn't been requested.
+ */
+ Oid domainBaseType;
+ int32 domainBaseTypmod;
+
+ /*
+ * Domain constraint data if it's a domain type. NULL if not domain, or
+ * if domain has no constraints, or if information hasn't been requested.
+ */
+ DomainConstraintCache *domainData;
+
+ /* Private data, for internal use of typcache.c only */
+ int flags; /* flags about what we've computed */
+
+ /*
+ * Private information about an enum type. NULL if not enum or
+ * information hasn't been requested.
+ */
+ struct TypeCacheEnumData *enumData;
+
+ /* We also maintain a list of all known domain-type cache entries */
+ struct TypeCacheEntry *nextDomain;
+} TypeCacheEntry;
+
+/* Bit flags to indicate which fields a given caller needs to have set */
+#define TYPECACHE_EQ_OPR 0x00001
+#define TYPECACHE_LT_OPR 0x00002
+#define TYPECACHE_GT_OPR 0x00004
+#define TYPECACHE_CMP_PROC 0x00008
+#define TYPECACHE_HASH_PROC 0x00010
+#define TYPECACHE_EQ_OPR_FINFO 0x00020
+#define TYPECACHE_CMP_PROC_FINFO 0x00040
+#define TYPECACHE_HASH_PROC_FINFO 0x00080
+#define TYPECACHE_TUPDESC 0x00100
+#define TYPECACHE_BTREE_OPFAMILY 0x00200
+#define TYPECACHE_HASH_OPFAMILY 0x00400
+#define TYPECACHE_RANGE_INFO 0x00800
+#define TYPECACHE_DOMAIN_BASE_INFO 0x01000
+#define TYPECACHE_DOMAIN_CONSTR_INFO 0x02000
+#define TYPECACHE_HASH_EXTENDED_PROC 0x04000
+#define TYPECACHE_HASH_EXTENDED_PROC_FINFO 0x08000
+#define TYPECACHE_MULTIRANGE_INFO 0x10000
+
+/* This value will not equal any valid tupledesc identifier, nor 0 */
+#define INVALID_TUPLEDESC_IDENTIFIER ((uint64) 1)
+
+/*
+ * Callers wishing to maintain a long-lived reference to a domain's constraint
+ * set must store it in one of these. Use InitDomainConstraintRef() and
+ * UpdateDomainConstraintRef() to manage it. Note: DomainConstraintState is
+ * considered an executable expression type, so it's defined in execnodes.h.
+ */
+typedef struct DomainConstraintRef
+{
+ List *constraints; /* list of DomainConstraintState nodes */
+ MemoryContext refctx; /* context holding DomainConstraintRef */
+ TypeCacheEntry *tcache; /* typcache entry for domain type */
+ bool need_exprstate; /* does caller need check_exprstate? */
+
+ /* Management data --- treat these fields as private to typcache.c */
+ DomainConstraintCache *dcc; /* current constraints, or NULL if none */
+ MemoryContextCallback callback; /* used to release refcount when done */
+} DomainConstraintRef;
+
+typedef struct SharedRecordTypmodRegistry SharedRecordTypmodRegistry;
+
+extern TypeCacheEntry *lookup_type_cache(Oid type_id, int flags);
+
+extern void InitDomainConstraintRef(Oid type_id, DomainConstraintRef *ref,
+ MemoryContext refctx, bool need_exprstate);
+
+extern void UpdateDomainConstraintRef(DomainConstraintRef *ref);
+
+extern bool DomainHasConstraints(Oid type_id);
+
+extern TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod);
+
+extern TupleDesc lookup_rowtype_tupdesc_noerror(Oid type_id, int32 typmod,
+ bool noError);
+
+extern TupleDesc lookup_rowtype_tupdesc_copy(Oid type_id, int32 typmod);
+
+extern TupleDesc lookup_rowtype_tupdesc_domain(Oid type_id, int32 typmod,
+ bool noError);
+
+extern void assign_record_type_typmod(TupleDesc tupDesc);
+
+extern uint64 assign_record_type_identifier(Oid type_id, int32 typmod);
+
+extern int compare_values_of_enum(TypeCacheEntry *tcache, Oid arg1, Oid arg2);
+
+extern size_t SharedRecordTypmodRegistryEstimate(void);
+
+extern void SharedRecordTypmodRegistryInit(SharedRecordTypmodRegistry *,
+ dsm_segment *segment, dsa_area *area);
+
+extern void SharedRecordTypmodRegistryAttach(SharedRecordTypmodRegistry *);
+
+#endif /* TYPCACHE_H */
diff --git a/src/include/utils/tzparser.h b/src/include/utils/tzparser.h
new file mode 100644
index 0000000..760785b
--- /dev/null
+++ b/src/include/utils/tzparser.h
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * tzparser.h
+ * Timezone offset file parsing definitions.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/tzparser.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TZPARSER_H
+#define TZPARSER_H
+
+#include "utils/datetime.h"
+
+/*
+ * The result of parsing a timezone configuration file is an array of
+ * these structs, in order by abbrev. We export this because datetime.c
+ * needs it.
+ */
+typedef struct tzEntry
+{
+ /* the actual data */
+ char *abbrev; /* TZ abbreviation (downcased) */
+ char *zone; /* zone name if dynamic abbrev, else NULL */
+ /* for a dynamic abbreviation, offset/is_dst are not used */
+ int offset; /* offset in seconds from UTC */
+ bool is_dst; /* true if a DST abbreviation */
+ /* source information (for error messages) */
+ int lineno;
+ const char *filename;
+} tzEntry;
+
+
+extern TimeZoneAbbrevTable *load_tzoffsets(const char *filename);
+
+#endif /* TZPARSER_H */
diff --git a/src/include/utils/usercontext.h b/src/include/utils/usercontext.h
new file mode 100644
index 0000000..a8195c1
--- /dev/null
+++ b/src/include/utils/usercontext.h
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ *
+ * usercontext.h
+ * Convenience functions for running code as a different database user.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef USERCONTEXT_H
+#define USERCONTEXT_H
+
+/*
+ * When temporarily changing to run as a different user, this structure
+ * holds the details needed to restore the original state.
+ */
+typedef struct UserContext
+{
+ Oid save_userid;
+ int save_sec_context;
+ int save_nestlevel;
+} UserContext;
+
+/* Function prototypes. */
+extern void SwitchToUntrustedUser(Oid userid, UserContext *context);
+extern void RestoreUserContext(UserContext *context);
+
+#endif /* USERCONTEXT_H */
diff --git a/src/include/utils/uuid.h b/src/include/utils/uuid.h
new file mode 100644
index 0000000..1117717
--- /dev/null
+++ b/src/include/utils/uuid.h
@@ -0,0 +1,42 @@
+/*-------------------------------------------------------------------------
+ *
+ * uuid.h
+ * Header file for the "uuid" ADT. In C, we use the name pg_uuid_t,
+ * to avoid conflicts with any uuid_t type that might be defined by
+ * the system headers.
+ *
+ * Copyright (c) 2007-2023, PostgreSQL Global Development Group
+ *
+ * src/include/utils/uuid.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef UUID_H
+#define UUID_H
+
+/* uuid size in bytes */
+#define UUID_LEN 16
+
+typedef struct pg_uuid_t
+{
+ unsigned char data[UUID_LEN];
+} pg_uuid_t;
+
+/* fmgr interface macros */
+static inline Datum
+UUIDPGetDatum(const pg_uuid_t *X)
+{
+ return PointerGetDatum(X);
+}
+
+#define PG_RETURN_UUID_P(X) return UUIDPGetDatum(X)
+
+static inline pg_uuid_t *
+DatumGetUUIDP(Datum X)
+{
+ return (pg_uuid_t *) DatumGetPointer(X);
+}
+
+#define PG_GETARG_UUID_P(X) DatumGetUUIDP(PG_GETARG_DATUM(X))
+
+#endif /* UUID_H */
diff --git a/src/include/utils/varbit.h b/src/include/utils/varbit.h
new file mode 100644
index 0000000..3bb7945
--- /dev/null
+++ b/src/include/utils/varbit.h
@@ -0,0 +1,89 @@
+/*-------------------------------------------------------------------------
+ *
+ * varbit.h
+ * Functions for the SQL datatypes BIT() and BIT VARYING().
+ *
+ * Code originally contributed by Adriaan Joubert.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/varbit.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef VARBIT_H
+#define VARBIT_H
+
+#include <limits.h>
+
+#include "fmgr.h"
+
+/*
+ * Modeled on struct varlena from postgres.h, but data type is bits8.
+ *
+ * Caution: if bit_len is not a multiple of BITS_PER_BYTE, the low-order
+ * bits of the last byte of bit_dat[] are unused and MUST be zeroes.
+ * (This allows bit_cmp() to not bother masking the last byte.)
+ * Also, there should not be any excess bytes counted in the header length.
+ */
+typedef struct
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ int32 bit_len; /* number of valid bits */
+ bits8 bit_dat[FLEXIBLE_ARRAY_MEMBER]; /* bit string, most sig. byte
+ * first */
+} VarBit;
+
+/*
+ * fmgr interface macros
+ *
+ * BIT and BIT VARYING are toastable varlena types. They are the same
+ * as far as representation goes, so we just have one set of macros.
+ */
+static inline VarBit *
+DatumGetVarBitP(Datum X)
+{
+ return (VarBit *) PG_DETOAST_DATUM(X);
+}
+
+static inline VarBit *
+DatumGetVarBitPCopy(Datum X)
+{
+ return (VarBit *) PG_DETOAST_DATUM_COPY(X);
+}
+
+static inline Datum
+VarBitPGetDatum(const VarBit *X)
+{
+ return PointerGetDatum(X);
+}
+
+#define PG_GETARG_VARBIT_P(n) DatumGetVarBitP(PG_GETARG_DATUM(n))
+#define PG_GETARG_VARBIT_P_COPY(n) DatumGetVarBitPCopy(PG_GETARG_DATUM(n))
+#define PG_RETURN_VARBIT_P(x) return VarBitPGetDatum(x)
+
+/* Header overhead *in addition to* VARHDRSZ */
+#define VARBITHDRSZ sizeof(int32)
+/* Number of bits in this bit string */
+#define VARBITLEN(PTR) (((VarBit *) (PTR))->bit_len)
+/* Pointer to the first byte containing bit string data */
+#define VARBITS(PTR) (((VarBit *) (PTR))->bit_dat)
+/* Number of bytes in the data section of a bit string */
+#define VARBITBYTES(PTR) (VARSIZE(PTR) - VARHDRSZ - VARBITHDRSZ)
+/* Padding of the bit string at the end (in bits) */
+#define VARBITPAD(PTR) (VARBITBYTES(PTR)*BITS_PER_BYTE - VARBITLEN(PTR))
+/* Number of bytes needed to store a bit string of a given length */
+#define VARBITTOTALLEN(BITLEN) (((BITLEN) + BITS_PER_BYTE-1)/BITS_PER_BYTE + \
+ VARHDRSZ + VARBITHDRSZ)
+/*
+ * Maximum number of bits. Several code sites assume no overflow from
+ * computing bitlen + X; VARBITTOTALLEN() has the largest such X.
+ */
+#define VARBITMAXLEN (INT_MAX - BITS_PER_BYTE + 1)
+/* pointer beyond the end of the bit string (like end() in STL containers) */
+#define VARBITEND(PTR) (((bits8 *) (PTR)) + VARSIZE(PTR))
+/* Mask that will cover exactly one byte, i.e. BITS_PER_BYTE bits */
+#define BITMASK 0xFF
+
+#endif
diff --git a/src/include/utils/varlena.h b/src/include/utils/varlena.h
new file mode 100644
index 0000000..77f5b24
--- /dev/null
+++ b/src/include/utils/varlena.h
@@ -0,0 +1,53 @@
+/*-------------------------------------------------------------------------
+ *
+ * varlena.h
+ * Functions for the variable-length built-in types.
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/varlena.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef VARLENA_H
+#define VARLENA_H
+
+#include "nodes/pg_list.h"
+#include "utils/sortsupport.h"
+
+extern int varstr_cmp(const char *arg1, int len1, const char *arg2, int len2, Oid collid);
+extern void varstr_sortsupport(SortSupport ssup, Oid typid, Oid collid);
+extern int varstr_levenshtein(const char *source, int slen,
+ const char *target, int tlen,
+ int ins_c, int del_c, int sub_c,
+ bool trusted);
+extern int varstr_levenshtein_less_equal(const char *source, int slen,
+ const char *target, int tlen,
+ int ins_c, int del_c, int sub_c,
+ int max_d, bool trusted);
+extern List *textToQualifiedNameList(text *textval);
+extern bool SplitIdentifierString(char *rawstring, char separator,
+ List **namelist);
+extern bool SplitDirectoriesString(char *rawstring, char separator,
+ List **namelist);
+extern bool SplitGUCList(char *rawstring, char separator,
+ List **namelist);
+extern text *replace_text_regexp(text *src_text, text *pattern_text,
+ text *replace_text,
+ int cflags, Oid collation,
+ int search_start, int n);
+
+typedef struct ClosestMatchState
+{
+ const char *source;
+ int min_d;
+ int max_d;
+ const char *match;
+} ClosestMatchState;
+
+extern void initClosestMatch(ClosestMatchState *state, const char *source, int max_d);
+extern void updateClosestMatch(ClosestMatchState *state, const char *candidate);
+extern const char *getClosestMatch(ClosestMatchState *state);
+
+#endif
diff --git a/src/include/utils/wait_event.h b/src/include/utils/wait_event.h
new file mode 100644
index 0000000..2adc5df
--- /dev/null
+++ b/src/include/utils/wait_event.h
@@ -0,0 +1,295 @@
+/*-------------------------------------------------------------------------
+ * wait_event.h
+ * Definitions related to wait event reporting
+ *
+ * Copyright (c) 2001-2023, PostgreSQL Global Development Group
+ *
+ * src/include/utils/wait_event.h
+ * ----------
+ */
+#ifndef WAIT_EVENT_H
+#define WAIT_EVENT_H
+
+
+/* ----------
+ * Wait Classes
+ * ----------
+ */
+#define PG_WAIT_LWLOCK 0x01000000U
+#define PG_WAIT_LOCK 0x03000000U
+#define PG_WAIT_BUFFER_PIN 0x04000000U
+#define PG_WAIT_ACTIVITY 0x05000000U
+#define PG_WAIT_CLIENT 0x06000000U
+#define PG_WAIT_EXTENSION 0x07000000U
+#define PG_WAIT_IPC 0x08000000U
+#define PG_WAIT_TIMEOUT 0x09000000U
+#define PG_WAIT_IO 0x0A000000U
+
+/* ----------
+ * Wait Events - Activity
+ *
+ * Use this category when a process is waiting because it has no work to do,
+ * unless the "Client" or "Timeout" category describes the situation better.
+ * Typically, this should only be used for background processes.
+ * ----------
+ */
+typedef enum
+{
+ WAIT_EVENT_ARCHIVER_MAIN = PG_WAIT_ACTIVITY,
+ WAIT_EVENT_AUTOVACUUM_MAIN,
+ WAIT_EVENT_BGWRITER_HIBERNATE,
+ WAIT_EVENT_BGWRITER_MAIN,
+ WAIT_EVENT_CHECKPOINTER_MAIN,
+ WAIT_EVENT_LOGICAL_APPLY_MAIN,
+ WAIT_EVENT_LOGICAL_LAUNCHER_MAIN,
+ WAIT_EVENT_LOGICAL_PARALLEL_APPLY_MAIN,
+ WAIT_EVENT_RECOVERY_WAL_STREAM,
+ WAIT_EVENT_SYSLOGGER_MAIN,
+ WAIT_EVENT_WAL_RECEIVER_MAIN,
+ WAIT_EVENT_WAL_SENDER_MAIN,
+ WAIT_EVENT_WAL_WRITER_MAIN
+} WaitEventActivity;
+
+/* ----------
+ * Wait Events - Client
+ *
+ * Use this category when a process is waiting to send data to or receive data
+ * from the frontend process to which it is connected. This is never used for
+ * a background process, which has no client connection.
+ * ----------
+ */
+typedef enum
+{
+ WAIT_EVENT_CLIENT_READ = PG_WAIT_CLIENT,
+ WAIT_EVENT_CLIENT_WRITE,
+ WAIT_EVENT_GSS_OPEN_SERVER,
+ WAIT_EVENT_LIBPQWALRECEIVER_CONNECT,
+ WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE,
+ WAIT_EVENT_SSL_OPEN_SERVER,
+ WAIT_EVENT_WAL_SENDER_WAIT_WAL,
+ WAIT_EVENT_WAL_SENDER_WRITE_DATA,
+} WaitEventClient;
+
+/* ----------
+ * Wait Events - IPC
+ *
+ * Use this category when a process cannot complete the work it is doing because
+ * it is waiting for a notification from another process.
+ * ----------
+ */
+typedef enum
+{
+ WAIT_EVENT_APPEND_READY = PG_WAIT_IPC,
+ WAIT_EVENT_ARCHIVE_CLEANUP_COMMAND,
+ WAIT_EVENT_ARCHIVE_COMMAND,
+ WAIT_EVENT_BACKEND_TERMINATION,
+ WAIT_EVENT_BACKUP_WAIT_WAL_ARCHIVE,
+ WAIT_EVENT_BGWORKER_SHUTDOWN,
+ WAIT_EVENT_BGWORKER_STARTUP,
+ WAIT_EVENT_BTREE_PAGE,
+ WAIT_EVENT_BUFFER_IO,
+ WAIT_EVENT_CHECKPOINT_DONE,
+ WAIT_EVENT_CHECKPOINT_START,
+ WAIT_EVENT_EXECUTE_GATHER,
+ WAIT_EVENT_HASH_BATCH_ALLOCATE,
+ WAIT_EVENT_HASH_BATCH_ELECT,
+ WAIT_EVENT_HASH_BATCH_LOAD,
+ WAIT_EVENT_HASH_BUILD_ALLOCATE,
+ WAIT_EVENT_HASH_BUILD_ELECT,
+ WAIT_EVENT_HASH_BUILD_HASH_INNER,
+ WAIT_EVENT_HASH_BUILD_HASH_OUTER,
+ WAIT_EVENT_HASH_GROW_BATCHES_DECIDE,
+ WAIT_EVENT_HASH_GROW_BATCHES_ELECT,
+ WAIT_EVENT_HASH_GROW_BATCHES_FINISH,
+ WAIT_EVENT_HASH_GROW_BATCHES_REALLOCATE,
+ WAIT_EVENT_HASH_GROW_BATCHES_REPARTITION,
+ WAIT_EVENT_HASH_GROW_BUCKETS_ELECT,
+ WAIT_EVENT_HASH_GROW_BUCKETS_REALLOCATE,
+ WAIT_EVENT_HASH_GROW_BUCKETS_REINSERT,
+ WAIT_EVENT_LOGICAL_APPLY_SEND_DATA,
+ WAIT_EVENT_LOGICAL_PARALLEL_APPLY_STATE_CHANGE,
+ WAIT_EVENT_LOGICAL_SYNC_DATA,
+ WAIT_EVENT_LOGICAL_SYNC_STATE_CHANGE,
+ WAIT_EVENT_MQ_INTERNAL,
+ WAIT_EVENT_MQ_PUT_MESSAGE,
+ WAIT_EVENT_MQ_RECEIVE,
+ WAIT_EVENT_MQ_SEND,
+ WAIT_EVENT_PARALLEL_BITMAP_SCAN,
+ WAIT_EVENT_PARALLEL_CREATE_INDEX_SCAN,
+ WAIT_EVENT_PARALLEL_FINISH,
+ WAIT_EVENT_PROCARRAY_GROUP_UPDATE,
+ WAIT_EVENT_PROC_SIGNAL_BARRIER,
+ WAIT_EVENT_PROMOTE,
+ WAIT_EVENT_RECOVERY_CONFLICT_SNAPSHOT,
+ WAIT_EVENT_RECOVERY_CONFLICT_TABLESPACE,
+ WAIT_EVENT_RECOVERY_END_COMMAND,
+ WAIT_EVENT_RECOVERY_PAUSE,
+ WAIT_EVENT_REPLICATION_ORIGIN_DROP,
+ WAIT_EVENT_REPLICATION_SLOT_DROP,
+ WAIT_EVENT_RESTORE_COMMAND,
+ WAIT_EVENT_SAFE_SNAPSHOT,
+ WAIT_EVENT_SYNC_REP,
+ WAIT_EVENT_WAL_RECEIVER_EXIT,
+ WAIT_EVENT_WAL_RECEIVER_WAIT_START,
+ WAIT_EVENT_XACT_GROUP_UPDATE
+} WaitEventIPC;
+
+/* ----------
+ * Wait Events - Timeout
+ *
+ * Use this category when a process is waiting for a timeout to expire.
+ * ----------
+ */
+typedef enum
+{
+ WAIT_EVENT_BASE_BACKUP_THROTTLE = PG_WAIT_TIMEOUT,
+ WAIT_EVENT_CHECKPOINT_WRITE_DELAY,
+ WAIT_EVENT_PG_SLEEP,
+ WAIT_EVENT_RECOVERY_APPLY_DELAY,
+ WAIT_EVENT_RECOVERY_RETRIEVE_RETRY_INTERVAL,
+ WAIT_EVENT_REGISTER_SYNC_REQUEST,
+ WAIT_EVENT_SPIN_DELAY,
+ WAIT_EVENT_VACUUM_DELAY,
+ WAIT_EVENT_VACUUM_TRUNCATE
+} WaitEventTimeout;
+
+/* ----------
+ * Wait Events - IO
+ *
+ * Use this category when a process is waiting for a IO.
+ * ----------
+ */
+typedef enum
+{
+ WAIT_EVENT_BASEBACKUP_READ = PG_WAIT_IO,
+ WAIT_EVENT_BASEBACKUP_SYNC,
+ WAIT_EVENT_BASEBACKUP_WRITE,
+ WAIT_EVENT_BUFFILE_READ,
+ WAIT_EVENT_BUFFILE_WRITE,
+ WAIT_EVENT_BUFFILE_TRUNCATE,
+ WAIT_EVENT_CONTROL_FILE_READ,
+ WAIT_EVENT_CONTROL_FILE_SYNC,
+ WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE,
+ WAIT_EVENT_CONTROL_FILE_WRITE,
+ WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE,
+ WAIT_EVENT_COPY_FILE_READ,
+ WAIT_EVENT_COPY_FILE_WRITE,
+ WAIT_EVENT_DATA_FILE_EXTEND,
+ WAIT_EVENT_DATA_FILE_FLUSH,
+ WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC,
+ WAIT_EVENT_DATA_FILE_PREFETCH,
+ WAIT_EVENT_DATA_FILE_READ,
+ WAIT_EVENT_DATA_FILE_SYNC,
+ WAIT_EVENT_DATA_FILE_TRUNCATE,
+ WAIT_EVENT_DATA_FILE_WRITE,
+ WAIT_EVENT_DSM_ALLOCATE,
+ WAIT_EVENT_DSM_FILL_ZERO_WRITE,
+ WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ,
+ WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC,
+ WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE,
+ WAIT_EVENT_LOCK_FILE_CREATE_READ,
+ WAIT_EVENT_LOCK_FILE_CREATE_SYNC,
+ WAIT_EVENT_LOCK_FILE_CREATE_WRITE,
+ WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ,
+ WAIT_EVENT_LOGICAL_REWRITE_CHECKPOINT_SYNC,
+ WAIT_EVENT_LOGICAL_REWRITE_MAPPING_SYNC,
+ WAIT_EVENT_LOGICAL_REWRITE_MAPPING_WRITE,
+ WAIT_EVENT_LOGICAL_REWRITE_SYNC,
+ WAIT_EVENT_LOGICAL_REWRITE_TRUNCATE,
+ WAIT_EVENT_LOGICAL_REWRITE_WRITE,
+ WAIT_EVENT_RELATION_MAP_READ,
+ WAIT_EVENT_RELATION_MAP_REPLACE,
+ WAIT_EVENT_RELATION_MAP_WRITE,
+ WAIT_EVENT_REORDER_BUFFER_READ,
+ WAIT_EVENT_REORDER_BUFFER_WRITE,
+ WAIT_EVENT_REORDER_LOGICAL_MAPPING_READ,
+ WAIT_EVENT_REPLICATION_SLOT_READ,
+ WAIT_EVENT_REPLICATION_SLOT_RESTORE_SYNC,
+ WAIT_EVENT_REPLICATION_SLOT_SYNC,
+ WAIT_EVENT_REPLICATION_SLOT_WRITE,
+ WAIT_EVENT_SLRU_FLUSH_SYNC,
+ WAIT_EVENT_SLRU_READ,
+ WAIT_EVENT_SLRU_SYNC,
+ WAIT_EVENT_SLRU_WRITE,
+ WAIT_EVENT_SNAPBUILD_READ,
+ WAIT_EVENT_SNAPBUILD_SYNC,
+ WAIT_EVENT_SNAPBUILD_WRITE,
+ WAIT_EVENT_TIMELINE_HISTORY_FILE_SYNC,
+ WAIT_EVENT_TIMELINE_HISTORY_FILE_WRITE,
+ WAIT_EVENT_TIMELINE_HISTORY_READ,
+ WAIT_EVENT_TIMELINE_HISTORY_SYNC,
+ WAIT_EVENT_TIMELINE_HISTORY_WRITE,
+ WAIT_EVENT_TWOPHASE_FILE_READ,
+ WAIT_EVENT_TWOPHASE_FILE_SYNC,
+ WAIT_EVENT_TWOPHASE_FILE_WRITE,
+ WAIT_EVENT_VERSION_FILE_WRITE,
+ WAIT_EVENT_WALSENDER_TIMELINE_HISTORY_READ,
+ WAIT_EVENT_WAL_BOOTSTRAP_SYNC,
+ WAIT_EVENT_WAL_BOOTSTRAP_WRITE,
+ WAIT_EVENT_WAL_COPY_READ,
+ WAIT_EVENT_WAL_COPY_SYNC,
+ WAIT_EVENT_WAL_COPY_WRITE,
+ WAIT_EVENT_WAL_INIT_SYNC,
+ WAIT_EVENT_WAL_INIT_WRITE,
+ WAIT_EVENT_WAL_READ,
+ WAIT_EVENT_WAL_SYNC,
+ WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN,
+ WAIT_EVENT_WAL_WRITE,
+ WAIT_EVENT_VERSION_FILE_SYNC
+} WaitEventIO;
+
+
+extern const char *pgstat_get_wait_event(uint32 wait_event_info);
+extern const char *pgstat_get_wait_event_type(uint32 wait_event_info);
+static inline void pgstat_report_wait_start(uint32 wait_event_info);
+static inline void pgstat_report_wait_end(void);
+extern void pgstat_set_wait_event_storage(uint32 *wait_event_info);
+extern void pgstat_reset_wait_event_storage(void);
+
+extern PGDLLIMPORT uint32 *my_wait_event_info;
+
+
+/* ----------
+ * pgstat_report_wait_start() -
+ *
+ * Called from places where server process needs to wait. This is called
+ * to report wait event information. The wait information is stored
+ * as 4-bytes where first byte represents the wait event class (type of
+ * wait, for different types of wait, refer WaitClass) and the next
+ * 3-bytes represent the actual wait event. Currently 2-bytes are used
+ * for wait event which is sufficient for current usage, 1-byte is
+ * reserved for future usage.
+ *
+ * Historically we used to make this reporting conditional on
+ * pgstat_track_activities, but the check for that seems to add more cost
+ * than it saves.
+ *
+ * my_wait_event_info initially points to local memory, making it safe to
+ * call this before MyProc has been initialized.
+ * ----------
+ */
+static inline void
+pgstat_report_wait_start(uint32 wait_event_info)
+{
+ /*
+ * Since this is a four-byte field which is always read and written as
+ * four-bytes, updates are atomic.
+ */
+ *(volatile uint32 *) my_wait_event_info = wait_event_info;
+}
+
+/* ----------
+ * pgstat_report_wait_end() -
+ *
+ * Called to report end of a wait.
+ * ----------
+ */
+static inline void
+pgstat_report_wait_end(void)
+{
+ /* see pgstat_report_wait_start() */
+ *(volatile uint32 *) my_wait_event_info = 0;
+}
+
+
+#endif /* WAIT_EVENT_H */
diff --git a/src/include/utils/xid8.h b/src/include/utils/xid8.h
new file mode 100644
index 0000000..2f5e14b
--- /dev/null
+++ b/src/include/utils/xid8.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * xid8.h
+ * Header file for the "xid8" ADT.
+ *
+ * Copyright (c) 2020-2023, PostgreSQL Global Development Group
+ *
+ * src/include/utils/xid8.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef XID8_H
+#define XID8_H
+
+#include "access/transam.h"
+
+static inline FullTransactionId
+DatumGetFullTransactionId(Datum X)
+{
+ return FullTransactionIdFromU64(DatumGetUInt64(X));
+}
+
+static inline Datum
+FullTransactionIdGetDatum(FullTransactionId X)
+{
+ return UInt64GetDatum(U64FromFullTransactionId(X));
+}
+
+#define PG_GETARG_FULLTRANSACTIONID(X) DatumGetFullTransactionId(PG_GETARG_DATUM(X))
+#define PG_RETURN_FULLTRANSACTIONID(X) return FullTransactionIdGetDatum(X)
+
+#endif /* XID8_H */
diff --git a/src/include/utils/xml.h b/src/include/utils/xml.h
new file mode 100644
index 0000000..224f6d7
--- /dev/null
+++ b/src/include/utils/xml.h
@@ -0,0 +1,94 @@
+/*-------------------------------------------------------------------------
+ *
+ * xml.h
+ * Declarations for XML data type support.
+ *
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/xml.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef XML_H
+#define XML_H
+
+#include "executor/tablefunc.h"
+#include "fmgr.h"
+#include "nodes/execnodes.h"
+#include "nodes/primnodes.h"
+
+typedef struct varlena xmltype;
+
+typedef enum
+{
+ XML_STANDALONE_YES,
+ XML_STANDALONE_NO,
+ XML_STANDALONE_NO_VALUE,
+ XML_STANDALONE_OMITTED
+} XmlStandaloneType;
+
+typedef enum
+{
+ XMLBINARY_BASE64,
+ XMLBINARY_HEX
+} XmlBinaryType;
+
+typedef enum
+{
+ PG_XML_STRICTNESS_LEGACY, /* ignore errors unless function result
+ * indicates error condition */
+ PG_XML_STRICTNESS_WELLFORMED, /* ignore non-parser messages */
+ PG_XML_STRICTNESS_ALL /* report all notices/warnings/errors */
+} PgXmlStrictness;
+
+/* struct PgXmlErrorContext is private to xml.c */
+typedef struct PgXmlErrorContext PgXmlErrorContext;
+
+static inline xmltype *
+DatumGetXmlP(Datum X)
+{
+ return (xmltype *) PG_DETOAST_DATUM(X);
+}
+
+static inline Datum
+XmlPGetDatum(const xmltype *X)
+{
+ return PointerGetDatum(X);
+}
+
+#define PG_GETARG_XML_P(n) DatumGetXmlP(PG_GETARG_DATUM(n))
+#define PG_RETURN_XML_P(x) PG_RETURN_POINTER(x)
+
+extern void pg_xml_init_library(void);
+extern PgXmlErrorContext *pg_xml_init(PgXmlStrictness strictness);
+extern void pg_xml_done(PgXmlErrorContext *errcxt, bool isError);
+extern bool pg_xml_error_occurred(PgXmlErrorContext *errcxt);
+extern void xml_ereport(PgXmlErrorContext *errcxt, int level, int sqlcode,
+ const char *msg);
+
+extern xmltype *xmlconcat(List *args);
+extern xmltype *xmlelement(XmlExpr *xexpr,
+ Datum *named_argvalue, bool *named_argnull,
+ Datum *argvalue, bool *argnull);
+extern xmltype *xmlparse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace);
+extern xmltype *xmlpi(const char *target, text *arg, bool arg_is_null, bool *result_is_null);
+extern xmltype *xmlroot(xmltype *data, text *version, int standalone);
+extern bool xml_is_document(xmltype *arg);
+extern text *xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg,
+ bool indent);
+extern char *escape_xml(const char *str);
+
+extern char *map_sql_identifier_to_xml_name(const char *ident, bool fully_escaped, bool escape_period);
+extern char *map_xml_name_to_sql_identifier(const char *name);
+extern char *map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings);
+
+extern PGDLLIMPORT int xmlbinary; /* XmlBinaryType, but int for guc enum */
+
+extern PGDLLIMPORT int xmloption; /* XmlOptionType, but int for guc enum */
+
+extern PGDLLIMPORT const TableFuncRoutine XmlTableRoutine;
+
+#endif /* XML_H */