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.h312
-rw-r--r--src/include/utils/aclchk_internal.h45
-rw-r--r--src/include/utils/array.h459
-rw-r--r--src/include/utils/arrayaccess.h118
-rw-r--r--src/include/utils/ascii.h16
-rw-r--r--src/include/utils/attoptcache.h28
-rw-r--r--src/include/utils/builtins.h127
-rw-r--r--src/include/utils/bytea.h27
-rw-r--r--src/include/utils/cash.h25
-rw-r--r--src/include/utils/catcache.h231
-rw-r--r--src/include/utils/combocid.h28
-rw-r--r--src/include/utils/date.h90
-rw-r--r--src/include/utils/datetime.h343
-rw-r--r--src/include/utils/datum.h68
-rw-r--r--src/include/utils/dsa.h123
-rw-r--r--src/include/utils/dynahash.h19
-rw-r--r--src/include/utils/elog.h439
-rw-r--r--src/include/utils/evtcache.h37
-rw-r--r--src/include/utils/expandeddatum.h159
-rw-r--r--src/include/utils/expandedrecord.h231
-rw-r--r--src/include/utils/float.h356
-rw-r--r--src/include/utils/fmgrtab.h48
-rw-r--r--src/include/utils/formatting.h33
-rw-r--r--src/include/utils/freepage.h99
-rw-r--r--src/include/utils/geo_decls.h180
-rw-r--r--src/include/utils/guc.h443
-rw-r--r--src/include/utils/guc_tables.h272
-rw-r--r--src/include/utils/help_config.h17
-rw-r--r--src/include/utils/hsearch.h149
-rw-r--r--src/include/utils/index_selfuncs.h74
-rw-r--r--src/include/utils/inet.h149
-rw-r--r--src/include/utils/int8.h25
-rw-r--r--src/include/utils/inval.h64
-rw-r--r--src/include/utils/json.h24
-rw-r--r--src/include/utils/jsonb.h411
-rw-r--r--src/include/utils/jsonfuncs.h58
-rw-r--r--src/include/utils/jsonpath.h251
-rw-r--r--src/include/utils/logtape.h80
-rw-r--r--src/include/utils/lsyscache.h198
-rw-r--r--src/include/utils/memdebug.h82
-rw-r--r--src/include/utils/memutils.h224
-rw-r--r--src/include/utils/numeric.h76
-rw-r--r--src/include/utils/palloc.h136
-rw-r--r--src/include/utils/partcache.h102
-rw-r--r--src/include/utils/pg_crc.h107
-rw-r--r--src/include/utils/pg_locale.h119
-rw-r--r--src/include/utils/pg_lsn.h29
-rw-r--r--src/include/utils/pg_rusage.h37
-rw-r--r--src/include/utils/pidfile.h56
-rw-r--r--src/include/utils/plancache.h235
-rw-r--r--src/include/utils/portal.h250
-rw-r--r--src/include/utils/ps_status.h25
-rw-r--r--src/include/utils/queryenvironment.h74
-rw-r--r--src/include/utils/rangetypes.h139
-rw-r--r--src/include/utils/regproc.h28
-rw-r--r--src/include/utils/rel.h644
-rw-r--r--src/include/utils/relcache.h151
-rw-r--r--src/include/utils/relfilenodemap.h18
-rw-r--r--src/include/utils/relmapper.h70
-rw-r--r--src/include/utils/relptr.h77
-rw-r--r--src/include/utils/reltrigger.h81
-rw-r--r--src/include/utils/resowner.h86
-rw-r--r--src/include/utils/resowner_private.h98
-rw-r--r--src/include/utils/rls.h50
-rw-r--r--src/include/utils/ruleutils.h44
-rw-r--r--src/include/utils/sampling.h65
-rw-r--r--src/include/utils/selfuncs.h223
-rw-r--r--src/include/utils/sharedtuplestore.h61
-rw-r--r--src/include/utils/snapmgr.h158
-rw-r--r--src/include/utils/snapshot.h206
-rw-r--r--src/include/utils/sortsupport.h276
-rw-r--r--src/include/utils/spccache.h21
-rw-r--r--src/include/utils/syscache.h219
-rw-r--r--src/include/utils/timeout.h88
-rw-r--r--src/include/utils/timestamp.h116
-rw-r--r--src/include/utils/tuplesort.h277
-rw-r--r--src/include/utils/tuplestore.h91
-rw-r--r--src/include/utils/typcache.h202
-rw-r--r--src/include/utils/tzparser.h39
-rw-r--r--src/include/utils/uuid.h31
-rw-r--r--src/include/utils/varbit.h74
-rw-r--r--src/include/utils/varlena.h39
-rw-r--r--src/include/utils/xid8.h22
-rw-r--r--src/include/utils/xml.h84
85 files changed, 11191 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..732aa01
--- /dev/null
+++ b/src/include/utils/acl.h
@@ -0,0 +1,312 @@
+/*-------------------------------------------------------------------------
+ *
+ * acl.h
+ * Definition of (and support for) access control list data structures.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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 16 bits of the ai_privs field of an AclItem are the grant option
+ * bits, and the lower 16 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 & 0xFFFF)
+#define ACLITEM_GET_GOPTIONS(item) (((item).ai_privs >> 16) & 0xFFFF)
+#define ACLITEM_GET_RIGHTS(item) ((item).ai_privs)
+
+#define ACL_GRANT_OPTION_FOR(privs) (((AclMode) (privs) & 0xFFFF) << 16)
+#define ACL_OPTION_TO_PRIVS(privs) (((AclMode) (privs) >> 16) & 0xFFFF)
+
+#define ACLITEM_SET_PRIVS(item,privs) \
+ ((item).ai_privs = ((item).ai_privs & ~((AclMode) 0xFFFF)) | \
+ ((AclMode) (privs) & 0xFFFF))
+#define ACLITEM_SET_GOPTIONS(item,goptions) \
+ ((item).ai_privs = ((item).ai_privs & ~(((AclMode) 0xFFFF) << 16)) | \
+ (((AclMode) (goptions) & 0xFFFF) << 16))
+#define ACLITEM_SET_RIGHTS(item,rights) \
+ ((item).ai_privs = (AclMode) (rights))
+
+#define ACLITEM_SET_PRIVS_GOPTIONS(item,privs,goptions) \
+ ((item).ai_privs = ((AclMode) (privs) & 0xFFFF) | \
+ (((AclMode) (goptions) & 0xFFFF) << 16))
+
+
+#define ACLITEM_ALL_PRIV_BITS ((AclMode) 0xFFFF)
+#define ACLITEM_ALL_GOPTION_BITS ((AclMode) 0xFFFF << 16)
+
+/*
+ * 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'
+
+/* string holding all privilege code chars, in order by bitmask position */
+#define ACL_ALL_RIGHTS_STR "arwdDxtXUCTc"
+
+/*
+ * 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_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 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 void check_is_member_of_role(Oid member, Oid role);
+extern Oid get_role_oid(const char *rolename, bool missing_ok);
+extern Oid get_role_oid_or_public(const char *rolename);
+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 void RemoveDefaultACLById(Oid defaclOid);
+
+extern AclMode pg_attribute_aclmask(Oid table_oid, AttrNumber attnum,
+ Oid roleid, AclMode mask, AclMaskHow how);
+extern AclMode pg_class_aclmask(Oid table_oid, Oid roleid,
+ AclMode mask, AclMaskHow how);
+extern AclMode pg_database_aclmask(Oid db_oid, Oid roleid,
+ AclMode mask, AclMaskHow how);
+extern AclMode pg_proc_aclmask(Oid proc_oid, Oid roleid,
+ AclMode mask, AclMaskHow how);
+extern AclMode pg_language_aclmask(Oid lang_oid, Oid roleid,
+ AclMode mask, AclMaskHow how);
+extern AclMode pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid,
+ AclMode mask, AclMaskHow how, Snapshot snapshot);
+extern AclMode pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
+ AclMode mask, AclMaskHow how);
+extern AclMode pg_tablespace_aclmask(Oid spc_oid, Oid roleid,
+ AclMode mask, AclMaskHow how);
+extern AclMode pg_foreign_data_wrapper_aclmask(Oid fdw_oid, Oid roleid,
+ AclMode mask, AclMaskHow how);
+extern AclMode pg_foreign_server_aclmask(Oid srv_oid, Oid roleid,
+ AclMode mask, AclMaskHow how);
+extern AclMode pg_type_aclmask(Oid type_oid, Oid roleid,
+ AclMode mask, AclMaskHow how);
+
+extern AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum,
+ Oid roleid, AclMode mode);
+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_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode);
+extern AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode);
+extern AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode);
+extern AclResult pg_largeobject_aclcheck_snapshot(Oid lang_oid, Oid roleid,
+ AclMode mode, Snapshot snapshot);
+extern AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode);
+extern AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode);
+extern AclResult pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, AclMode mode);
+extern AclResult pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode);
+extern AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode);
+
+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 pg_class_ownercheck(Oid class_oid, Oid roleid);
+extern bool pg_type_ownercheck(Oid type_oid, Oid roleid);
+extern bool pg_oper_ownercheck(Oid oper_oid, Oid roleid);
+extern bool pg_proc_ownercheck(Oid proc_oid, Oid roleid);
+extern bool pg_language_ownercheck(Oid lan_oid, Oid roleid);
+extern bool pg_largeobject_ownercheck(Oid lobj_oid, Oid roleid);
+extern bool pg_namespace_ownercheck(Oid nsp_oid, Oid roleid);
+extern bool pg_tablespace_ownercheck(Oid spc_oid, Oid roleid);
+extern bool pg_opclass_ownercheck(Oid opc_oid, Oid roleid);
+extern bool pg_opfamily_ownercheck(Oid opf_oid, Oid roleid);
+extern bool pg_database_ownercheck(Oid db_oid, Oid roleid);
+extern bool pg_collation_ownercheck(Oid coll_oid, Oid roleid);
+extern bool pg_conversion_ownercheck(Oid conv_oid, Oid roleid);
+extern bool pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid);
+extern bool pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid);
+extern bool pg_foreign_data_wrapper_ownercheck(Oid srv_oid, Oid roleid);
+extern bool pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid);
+extern bool pg_event_trigger_ownercheck(Oid et_oid, Oid roleid);
+extern bool pg_extension_ownercheck(Oid ext_oid, Oid roleid);
+extern bool pg_publication_ownercheck(Oid pub_oid, Oid roleid);
+extern bool pg_subscription_ownercheck(Oid sub_oid, Oid roleid);
+extern bool pg_statistics_object_ownercheck(Oid stat_oid, 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..81ddf93
--- /dev/null
+++ b/src/include/utils/aclchk_internal.h
@@ -0,0 +1,45 @@
+/*-------------------------------------------------------------------------
+ *
+ * aclchk_internal.h
+ *
+ * Portions Copyright (c) 1996-2020, 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..0dcc885
--- /dev/null
+++ b/src/include/utils/array.h
@@ -0,0 +1,459 @@
+/*-------------------------------------------------------------------------
+ *
+ * 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-2020, 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;
+
+
+/*
+ * 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 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_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 bool array_contains_nulls(ArrayType *array);
+
+extern ArrayBuildState *initArrayResult(Oid element_type,
+ MemoryContext rcontext, bool subcontext);
+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 void ArrayCheckBounds(int ndim, const int *dims, const int *lb);
+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..674bf51
--- /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-2020, 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..0fe0d48
--- /dev/null
+++ b/src/include/utils/ascii.h
@@ -0,0 +1,16 @@
+/*-----------------------------------------------------------------------
+ * ascii.h
+ *
+ * Portions Copyright (c) 1999-2020, PostgreSQL Global Development Group
+ *
+ * src/include/utils/ascii.h
+ *
+ *-----------------------------------------------------------------------
+ */
+
+#ifndef _ASCII_H_
+#define _ASCII_H_
+
+extern void ascii_safe_strlcpy(char *dest, const char *src, size_t destsiz);
+
+#endif /* _ASCII_H_ */
diff --git a/src/include/utils/attoptcache.h b/src/include/utils/attoptcache.h
new file mode 100644
index 0000000..80b5527
--- /dev/null
+++ b/src/include/utils/attoptcache.h
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+ *
+ * attoptcache.h
+ * Attribute options cache.
+ *
+ * Portions Copyright (c) 1996-2020, 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;
+
+AttributeOpts *get_attribute_options(Oid spcid, int attnum);
+
+#endif /* ATTOPTCACHE_H */
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
new file mode 100644
index 0000000..a5c8772
--- /dev/null
+++ b/src/include/utils/builtins.h
@@ -0,0 +1,127 @@
+/*-------------------------------------------------------------------------
+ *
+ * builtins.h
+ * Declarations for operations on built-in types.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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);
+
+/* int.c */
+extern int2vector *buildint2vector(const int16 *int2s, int n);
+
+/* name.c */
+extern int namecpy(Name n1, const NameData *n2);
+extern int namestrcpy(Name name, const char *str);
+extern int namestrcmp(Name name, const char *str);
+
+/* numutils.c */
+extern int32 pg_atoi(const char *s, int size, int c);
+extern int16 pg_strtoint16(const char *s);
+extern int32 pg_strtoint32(const char *s);
+extern void pg_itoa(int16 i, char *a);
+extern int pg_ultoa_n(uint32 l, char *a);
+extern int pg_ulltoa_n(uint64 l, char *a);
+extern void pg_ltoa(int32 l, char *a);
+extern void pg_lltoa(int64 ll, char *a);
+extern char *pg_ultostr_zeropad(char *str, uint32 value, int32 minwidth);
+extern char *pg_ultostr(char *str, uint32 value);
+extern uint64 pg_strtouint64(const char *str, char **endptr, int base);
+
+/* 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 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);
+
+/* 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 */
+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..d89ba2b
--- /dev/null
+++ b/src/include/utils/bytea.h
@@ -0,0 +1,27 @@
+/*-------------------------------------------------------------------------
+ *
+ * bytea.h
+ * Declarations for BYTEA data type support.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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 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..2e332d8
--- /dev/null
+++ b/src/include/utils/cash.h
@@ -0,0 +1,25 @@
+/*
+ * 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 */
+#define DatumGetCash(X) ((Cash) DatumGetInt64(X))
+#define CashGetDatum(X) 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..f4aa316
--- /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-2020, 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..b39166a
--- /dev/null
+++ b/src/include/utils/combocid.h
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+ *
+ * combocid.h
+ * Combo command ID support routines
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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/date.h b/src/include/utils/date.h
new file mode 100644
index 0000000..6fc491e
--- /dev/null
+++ b/src/include/utils/date.h
@@ -0,0 +1,90 @@
+/*-------------------------------------------------------------------------
+ *
+ * date.h
+ * Definitions for the SQL "date" and "time" types.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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))
+
+/*
+ * Macros 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!
+ */
+#define MAX_TIME_PRECISION 6
+
+#define DatumGetDateADT(X) ((DateADT) DatumGetInt32(X))
+#define DatumGetTimeADT(X) ((TimeADT) DatumGetInt64(X))
+#define DatumGetTimeTzADTP(X) ((TimeTzADT *) DatumGetPointer(X))
+
+#define DateADTGetDatum(X) Int32GetDatum(X)
+#define TimeADTGetDatum(X) Int64GetDatum(X)
+#define TimeTzADTPGetDatum(X) 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..711bd02
--- /dev/null
+++ b/src/include/utils/datetime.h
@@ -0,0 +1,343 @@
+/*-------------------------------------------------------------------------
+ *
+ * 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-2020, 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 "nodes/nodes.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 const char *const months[]; /* months (3-char abbreviations) */
+extern const char *const days[]; /* days (full names) */
+extern 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 correct ereport.
+ */
+#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)
+
+
+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);
+extern int DecodeTimezone(char *str, int *tzp);
+extern int DecodeTimeOnly(char **field, int *ftype,
+ int nf, int *dtype,
+ struct pg_tm *tm, fsec_t *fsec, int *tzp);
+extern int DecodeInterval(char **field, int *ftype, int nf, int range,
+ int *dtype, struct pg_tm *tm, fsec_t *fsec);
+extern int DecodeISO8601Interval(char *str,
+ int *dtype, struct pg_tm *tm, fsec_t *fsec);
+
+extern void DateTimeParseError(int dterr, const char *str,
+ const char *datatype) pg_attribute_noreturn();
+
+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_tm *tm, fsec_t fsec, 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, char *lowtoken,
+ int *offset, pg_tz **tz);
+extern int DecodeSpecial(int field, char *lowtoken, int *val);
+extern int DecodeUnits(int field, char *lowtoken, int *val);
+
+extern int j2day(int jd);
+
+extern Node *TemporalSimplify(int32 max_precis, Node *node);
+
+extern bool CheckDateTokenTables(void);
+
+extern TimeZoneAbbrevTable *ConvertTimeZoneAbbrevs(struct tzEntry *abbrevs,
+ int n);
+extern void InstallTimeZoneAbbrevs(TimeZoneAbbrevTable *tbl);
+
+extern void AdjustTimestampForTypmod(Timestamp *time, int32 typmod);
+extern bool AdjustTimestampForTypmodError(Timestamp *time, int32 typmod,
+ bool *error);
+
+#endif /* DATETIME_H */
diff --git a/src/include/utils/datum.h b/src/include/utils/datum.h
new file mode 100644
index 0000000..9118a93
--- /dev/null
+++ b/src/include/utils/datum.h
@@ -0,0 +1,68 @@
+/*-------------------------------------------------------------------------
+ *
+ * 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-2020, 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);
+
+/*
+ * 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..e07126b
--- /dev/null
+++ b/src/include/utils/dsa.h
@@ -0,0 +1,123 @@
+/*-------------------------------------------------------------------------
+ *
+ * dsa.h
+ * Dynamic shared memory areas.
+ *
+ * Portions Copyright (c) 1996-2020, 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;
+
+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..768b952
--- /dev/null
+++ b/src/include/utils/dynahash.h
@@ -0,0 +1,19 @@
+/*-------------------------------------------------------------------------
+ *
+ * dynahash
+ * POSTGRES dynahash.h file definitions
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * 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..1e09ee0
--- /dev/null
+++ b/src/include/utils/elog.h
@@ -0,0 +1,439 @@
+/*-------------------------------------------------------------------------
+ *
+ * elog.h
+ * POSTGRES error reporting/logging definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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>
+
+/* 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 ERROR 20 /* user error - abort transaction; return to
+ * known state */
+/* Save ERROR value in PGERROR so it can be restored when Win32 includes
+ * modify it. We have to use a constant rather than ERROR because macros
+ * are expanded only when referenced outside macros.
+ */
+#ifdef WIN32
+#define PGERROR 20
+#endif
+#define FATAL 21 /* fatal error - abort process */
+#define PANIC 22 /* take down the other backends with me */
+
+ /* #define DEBUG DEBUG1 */ /* Backward compatibility with pre-7.3 */
+
+
+/* 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.
+ *
+ * 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 (errstart(elevel, domain)) \
+ __VA_ARGS__, errfinish(__FILE__, __LINE__, PG_FUNCNAME_MACRO); \
+ 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__, PG_FUNCNAME_MACRO); \
+ 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 errstart(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);
+
+/*
+ * 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 errfunction(const char *funcname);
+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 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.
+ *----------
+ */
+#define PG_TRY() \
+ do { \
+ sigjmp_buf *_save_exception_stack = PG_exception_stack; \
+ ErrorContextCallback *_save_context_stack = error_context_stack; \
+ sigjmp_buf _local_sigjmp_buf; \
+ bool _do_rethrow = false; \
+ if (sigsetjmp(_local_sigjmp_buf, 0) == 0) \
+ { \
+ PG_exception_stack = &_local_sigjmp_buf
+
+#define PG_CATCH() \
+ } \
+ else \
+ { \
+ PG_exception_stack = _save_exception_stack; \
+ error_context_stack = _save_context_stack
+
+#define PG_FINALLY() \
+ } \
+ else \
+ _do_rethrow = true; \
+ { \
+ PG_exception_stack = _save_exception_stack; \
+ error_context_stack = _save_context_stack
+
+#define PG_END_TRY() \
+ } \
+ if (_do_rethrow) \
+ PG_RE_THROW(); \
+ PG_exception_stack = _save_exception_stack; \
+ error_context_stack = _save_context_stack; \
+ } 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 show_funcname; /* true to force funcname inclusion */
+ 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 int Log_error_verbosity;
+extern char *Log_line_prefix;
+extern int Log_destination;
+extern char *Log_destination_string;
+extern bool syslog_sequence_numbers;
+extern 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
+
+/* Other exported functions */
+extern void DebugFileOpen(void);
+extern char *unpack_sql_state(int sql_state);
+extern bool in_error_recursion_trouble(void);
+
+#ifdef HAVE_SYSLOG
+extern void set_syslog_parameters(const char *ident, int facility);
+#endif
+
+/*
+ * 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);
+
+#endif /* ELOG_H */
diff --git a/src/include/utils/evtcache.h b/src/include/utils/evtcache.h
new file mode 100644
index 0000000..bb1e39e
--- /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-2020, 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..be4970f
--- /dev/null
+++ b/src/include/utils/expandeddatum.h
@@ -0,0 +1,159 @@
+/*-------------------------------------------------------------------------
+ *
+ * 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-2020, 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
+
+/* 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.)
+ */
+
+#define EOHPGetRWDatum(eohptr) PointerGetDatum((eohptr)->eoh_rw_ptr)
+#define EOHPGetRODatum(eohptr) 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..75b5789
--- /dev/null
+++ b/src/include/utils/expandedrecord.h
@@ -0,0 +1,231 @@
+/*-------------------------------------------------------------------------
+ *
+ * expandedrecord.h
+ * Declarations for composite expanded objects.
+ *
+ * Portions Copyright (c) 1996-2020, 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 macros for expanded record objects */
+#define PG_GETARG_EXPANDED_RECORD(n) DatumGetExpandedRecord(PG_GETARG_DATUM(n))
+#define ExpandedRecordGetDatum(erh) EOHPGetRWDatum(&(erh)->hdr)
+#define ExpandedRecordGetRODatum(erh) EOHPGetRODatum(&(erh)->hdr)
+#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..8d4bbc5
--- /dev/null
+++ b/src/include/utils/float.h
@@ -0,0 +1,356 @@
+/*-------------------------------------------------------------------------
+ *
+ * float.h
+ * Definitions for the built-in floating-point types
+ *
+ * Portions Copyright (c) 1996-2020, 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>
+
+#ifndef M_PI
+/* From my RH5.2 gcc math.h file - thomas 2000-04-03 */
+#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);
+extern float8 float8in_internal_opt_error(char *num, char **endptr_p,
+ const char *type_name, const char *orig_string,
+ bool *have_error);
+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))
+ float_zero_divide_error();
+ result = val1 / val2;
+ if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
+ float_overflow_error();
+ if (unlikely(result == 0.0f) && val1 != 0.0f)
+ float_underflow_error();
+
+ return result;
+}
+
+static inline float8
+float8_div(const float8 val1, const float8 val2)
+{
+ float8 result;
+
+ if (unlikely(val2 == 0.0))
+ float_zero_divide_error();
+ result = val1 / val2;
+ if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
+ float_overflow_error();
+ if (unlikely(result == 0.0) && val1 != 0.0)
+ 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..8e822c4
--- /dev/null
+++ b/src/include/utils/fmgrtab.h
@@ -0,0 +1,48 @@
+/*-------------------------------------------------------------------------
+ *
+ * fmgrtab.h
+ * The function manager's table of internal functions.
+ *
+ * Portions Copyright (c) 1996-2020, 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 const FmgrBuiltin fmgr_builtins[];
+
+extern const int fmgr_nbuiltins; /* number of entries in table */
+
+extern 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 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..8f62aa3
--- /dev/null
+++ b/src/include/utils/formatting.h
@@ -0,0 +1,33 @@
+/* -----------------------------------------------------------------------
+ * formatting.h
+ *
+ * src/include/utils/formatting.h
+ *
+ *
+ * Portions Copyright (c) 1999-2020, 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,
+ bool *have_error);
+
+#endif
diff --git a/src/include/utils/freepage.h b/src/include/utils/freepage.h
new file mode 100644
index 0000000..b758faf
--- /dev/null
+++ b/src/include/utils/freepage.h
@@ -0,0 +1,99 @@
+/*-------------------------------------------------------------------------
+ *
+ * freepage.h
+ * Management of page-organized free memory.
+ *
+ * Portions Copyright (c) 1996-2020, 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).relptr_off % FPM_PAGE_SIZE == 0)
+
+/* Macro to find base address of the segment containing a FreePageManager. */
+#define fpm_segment_base(fpm) \
+ (((char *) fpm) - fpm->self.relptr_off)
+
+/* 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..d461755
--- /dev/null
+++ b/src/include/utils/geo_decls.h
@@ -0,0 +1,180 @@
+/*-------------------------------------------------------------------------
+ *
+ * geo_decls.h - Declarations for various 2D constructs.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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 "fmgr.h"
+
+/*--------------------------------------------------------------------
+ * Useful floating point utilities and constants.
+ *-------------------------------------------------------------------
+ *
+ * XXX: They are not NaN-aware.
+ */
+
+#define EPSILON 1.0E-06
+
+#ifdef EPSILON
+#define FPzero(A) (fabs(A) <= EPSILON)
+#define FPeq(A,B) (fabs((A) - (B)) <= EPSILON)
+#define FPne(A,B) (fabs((A) - (B)) > EPSILON)
+#define FPlt(A,B) ((B) - (A) > EPSILON)
+#define FPle(A,B) ((A) - (B) <= EPSILON)
+#define FPgt(A,B) ((A) - (B) > EPSILON)
+#define FPge(A,B) ((B) - (A) <= EPSILON)
+#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 macros
+ *
+ * Path and Polygon are toastable varlena types, the others are just
+ * fixed-size pass-by-reference types.
+ */
+
+#define DatumGetPointP(X) ((Point *) DatumGetPointer(X))
+#define PointPGetDatum(X) PointerGetDatum(X)
+#define PG_GETARG_POINT_P(n) DatumGetPointP(PG_GETARG_DATUM(n))
+#define PG_RETURN_POINT_P(x) return PointPGetDatum(x)
+
+#define DatumGetLsegP(X) ((LSEG *) DatumGetPointer(X))
+#define LsegPGetDatum(X) PointerGetDatum(X)
+#define PG_GETARG_LSEG_P(n) DatumGetLsegP(PG_GETARG_DATUM(n))
+#define PG_RETURN_LSEG_P(x) return LsegPGetDatum(x)
+
+#define DatumGetPathP(X) ((PATH *) PG_DETOAST_DATUM(X))
+#define DatumGetPathPCopy(X) ((PATH *) PG_DETOAST_DATUM_COPY(X))
+#define PathPGetDatum(X) 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)
+
+#define DatumGetLineP(X) ((LINE *) DatumGetPointer(X))
+#define LinePGetDatum(X) PointerGetDatum(X)
+#define PG_GETARG_LINE_P(n) DatumGetLineP(PG_GETARG_DATUM(n))
+#define PG_RETURN_LINE_P(x) return LinePGetDatum(x)
+
+#define DatumGetBoxP(X) ((BOX *) DatumGetPointer(X))
+#define BoxPGetDatum(X) PointerGetDatum(X)
+#define PG_GETARG_BOX_P(n) DatumGetBoxP(PG_GETARG_DATUM(n))
+#define PG_RETURN_BOX_P(x) return BoxPGetDatum(x)
+
+#define DatumGetPolygonP(X) ((POLYGON *) PG_DETOAST_DATUM(X))
+#define DatumGetPolygonPCopy(X) ((POLYGON *) PG_DETOAST_DATUM_COPY(X))
+#define PolygonPGetDatum(X) 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)
+
+#define DatumGetCircleP(X) ((CIRCLE *) DatumGetPointer(X))
+#define CirclePGetDatum(X) 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..2819282
--- /dev/null
+++ b/src/include/utils/guc.h
@@ -0,0 +1,443 @@
+/*--------------------------------------------------------------------
+ * guc.h
+ *
+ * External declarations pertaining to backend/utils/misc/guc.c and
+ * backend/utils/misc/guc-file.l
+ *
+ * Copyright (c) 2000-2020, 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. Note that source == PGC_S_OVERRIDE should be
+ * used when setting a PGC_INTERNAL option.
+ *
+ * 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 ("doit" will always
+ * be false, so this never gets stored as the actual source of any value).
+ * 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.
+ *
+ * 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);
+
+/*
+ * 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
+ */
+#define GUC_LIST_INPUT 0x0001 /* input can be list format */
+#define GUC_LIST_QUOTE 0x0002 /* double-quote list elements */
+#define GUC_NO_SHOW_ALL 0x0004 /* exclude from SHOW ALL */
+#define GUC_NO_RESET_ALL 0x0008 /* exclude from RESET ALL */
+#define GUC_REPORT 0x0010 /* auto-report changes to client */
+#define GUC_NOT_IN_SAMPLE 0x0020 /* not in postgresql.conf.sample */
+#define GUC_DISALLOW_IN_FILE 0x0040 /* can't set in postgresql.conf */
+#define GUC_CUSTOM_PLACEHOLDER 0x0080 /* placeholder for custom variable */
+#define GUC_SUPERUSER_ONLY 0x0100 /* show only to superusers */
+#define GUC_IS_NAME 0x0200 /* limit string to NAMEDATALEN-1 */
+#define GUC_NOT_WHILE_SEC_REST 0x0400 /* can't set if security restricted */
+#define GUC_DISALLOW_IN_AUTO_FILE 0x0800 /* can't set in
+ * PG_AUTOCONF_FILENAME */
+
+#define GUC_UNIT_KB 0x1000 /* value is in kilobytes */
+#define GUC_UNIT_BLOCKS 0x2000 /* value is in blocks */
+#define GUC_UNIT_XBLOCKS 0x3000 /* value is in xlog blocks */
+#define GUC_UNIT_MB 0x4000 /* value is in megabytes */
+#define GUC_UNIT_BYTE 0x8000 /* value is in bytes */
+#define GUC_UNIT_MEMORY 0xF000 /* mask for size-related units */
+
+#define GUC_UNIT_MS 0x10000 /* value is in milliseconds */
+#define GUC_UNIT_S 0x20000 /* value is in seconds */
+#define GUC_UNIT_MIN 0x30000 /* value is in minutes */
+#define GUC_UNIT_TIME 0xF0000 /* mask for time-related units */
+
+#define GUC_EXPLAIN 0x100000 /* include in explain */
+
+#define GUC_UNIT (GUC_UNIT_MEMORY | GUC_UNIT_TIME)
+
+
+/* GUC vars that are actually declared in guc.c, rather than elsewhere */
+extern bool Debug_print_plan;
+extern bool Debug_print_parse;
+extern bool Debug_print_rewritten;
+extern bool Debug_pretty_print;
+
+extern bool log_parser_stats;
+extern bool log_planner_stats;
+extern bool log_executor_stats;
+extern bool log_statement_stats;
+extern bool log_btree_build_stats;
+
+extern PGDLLIMPORT bool check_function_bodies;
+extern bool session_auth_is_superuser;
+
+extern bool log_duration;
+extern int log_parameter_max_length;
+extern int log_parameter_max_length_on_error;
+extern int log_min_error_statement;
+extern PGDLLIMPORT int log_min_messages;
+extern PGDLLIMPORT int client_min_messages;
+extern int log_min_duration_sample;
+extern int log_min_duration_statement;
+extern int log_temp_files;
+extern double log_statement_sample_rate;
+extern double log_xact_sample_rate;
+extern char *backtrace_functions;
+extern char *backtrace_symbol_list;
+
+extern int temp_file_limit;
+
+extern int num_temp_buffers;
+
+extern char *cluster_name;
+extern PGDLLIMPORT char *ConfigFileName;
+extern char *HbaFileName;
+extern char *IdentFileName;
+extern char *external_pid_file;
+
+extern PGDLLIMPORT char *application_name;
+
+extern int tcp_keepalives_idle;
+extern int tcp_keepalives_interval;
+extern int tcp_keepalives_count;
+extern int tcp_user_timeout;
+
+#ifdef TRACE_SORT
+extern 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);
+
+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);
+
+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);
+
+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);
+
+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);
+
+extern void EmitWarningsOnPlaceholders(const char *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 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 ParseLongOption(const char *string, char **name, char **value);
+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 void AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt);
+extern char *GetConfigOptionByName(const char *name, const char **varname,
+ bool missing_ok);
+extern void GetConfigOptionByNum(int varnum, const char **values, bool *noshow);
+extern int GetNumConfigOptions(void);
+
+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);
+
+extern void ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel);
+extern char *ExtractSetVariableArgs(VariableSetStmt *stmt);
+
+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);
+
+#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);
+
+/* 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
+
+
+/*
+ * The following functions are not in guc.c, but are declared here to avoid
+ * having to include guc.h in some widely used headers that it really doesn't
+ * belong in.
+ */
+
+/* in commands/tablespace.c */
+extern bool check_default_tablespace(char **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);
+
+/* in catalog/namespace.c */
+extern bool check_search_path(char **newval, void **extra, GucSource source);
+extern void assign_search_path(const char *newval, void *extra);
+
+/* in access/transam/xlog.c */
+extern bool check_wal_buffers(int *newval, void **extra, GucSource source);
+extern void assign_xlog_sync_method(int new_sync_method, void *extra);
+
+#endif /* GUC_H */
diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h
new file mode 100644
index 0000000..454c2df
--- /dev/null
+++ b/src/include/utils/guc_tables.h
@@ -0,0 +1,272 @@
+/*-------------------------------------------------------------------------
+ *
+ * guc_tables.h
+ * Declarations of tables used by GUC.
+ *
+ * See src/backend/utils/misc/README for design notes.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ *
+ * src/include/utils/guc_tables.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef GUC_TABLES_H
+#define GUC_TABLES_H 1
+
+#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
+ */
+enum config_group
+{
+ UNGROUPED,
+ FILE_LOCATIONS,
+ CONN_AUTH,
+ CONN_AUTH_SETTINGS,
+ CONN_AUTH_AUTH,
+ CONN_AUTH_SSL,
+ RESOURCES,
+ RESOURCES_MEM,
+ RESOURCES_DISK,
+ RESOURCES_KERNEL,
+ RESOURCES_VACUUM_DELAY,
+ RESOURCES_BGWRITER,
+ RESOURCES_ASYNCHRONOUS,
+ WAL,
+ WAL_SETTINGS,
+ WAL_CHECKPOINTS,
+ WAL_ARCHIVING,
+ WAL_ARCHIVE_RECOVERY,
+ WAL_RECOVERY_TARGET,
+ REPLICATION,
+ REPLICATION_SENDING,
+ REPLICATION_MASTER,
+ REPLICATION_STANDBY,
+ REPLICATION_SUBSCRIBERS,
+ QUERY_TUNING,
+ QUERY_TUNING_METHOD,
+ QUERY_TUNING_COST,
+ QUERY_TUNING_GEQO,
+ QUERY_TUNING_OTHER,
+ LOGGING,
+ LOGGING_WHERE,
+ LOGGING_WHEN,
+ LOGGING_WHAT,
+ PROCESS_TITLE,
+ STATS,
+ STATS_MONITORING,
+ STATS_COLLECTOR,
+ AUTOVACUUM,
+ CLIENT_CONN,
+ CLIENT_CONN_STATEMENT,
+ CLIENT_CONN_LOCALE,
+ CLIENT_CONN_PRELOAD,
+ CLIENT_CONN_OTHER,
+ LOCK_MANAGEMENT,
+ COMPAT_OPTIONS,
+ 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 */
+ 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 '. ')
+ *
+ * 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 */
+ GucStack *stack; /* stacked prior values */
+ void *extra; /* "extra" pointer for current actual value */
+ 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
+
+
+/* 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;
+};
+
+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 const char *const config_group_names[];
+extern const char *const config_type_names[];
+extern const char *const GucContext_Names[];
+extern const char *const GucSource_Names[];
+
+/* get the current set of variables */
+extern struct config_generic **get_guc_variables(void);
+
+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 struct config_generic **get_explain_guc_options(int *num);
+
+#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..1d2345e
--- /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-2020, 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..f1deb9b
--- /dev/null
+++ b/src/include/utils/hsearch.h
@@ -0,0 +1,149 @@
+/*-------------------------------------------------------------------------
+ *
+ * hsearch.h
+ * exported definitions for utils/hash/dynahash.c; see notes therein
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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
+{
+ long num_partitions; /* # partitions (must be power of 2) */
+ long ssize; /* segment size */
+ long dsize; /* (initial) directory size */
+ long max_dsize; /* limit to dsize if dir size is limited */
+ long ffactor; /* fill factor */
+ Size keysize; /* hash key length in bytes */
+ Size entrysize; /* total user element size in bytes */
+ HashValueFunc hash; /* hash function */
+ HashCompareFunc match; /* key comparison function */
+ HashCopyFunc keycopy; /* key copying function */
+ HashAllocFunc alloc; /* memory allocator */
+ MemoryContext hcxt; /* memory context to use for allocations */
+ HASHHDR *hctl; /* location of header in shared mem */
+} HASHCTL;
+
+/* Flags to 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_FFACTOR 0x0008 /* Set fill factor */
+#define HASH_ELEM 0x0010 /* Set keysize and entrysize */
+#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
+ *
+ * Note: It is deprecated for callers of hash_create to explicitly specify
+ * string_hash, tag_hash, uint32_hash, or oid_hash. Just set HASH_BLOBS or
+ * not. Use HASH_FUNCTION only when you want something other than those.
+ */
+extern HTAB *hash_create(const char *tabname, long nelem,
+ 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..1710c1d
--- /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-2020, 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..f88b075
--- /dev/null
+++ b/src/include/utils/inet.h
@@ -0,0 +1,149 @@
+/*-------------------------------------------------------------------------
+ *
+ * inet.h
+ * Declarations for operations on INET datatypes.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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 may not have the appropriate address family (like
+ * inet6 addresses when AF_INET6 isn't present) but doesn'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
+ */
+#define DatumGetInetPP(X) ((inet *) PG_DETOAST_DATUM_PACKED(X))
+#define InetPGetDatum(X) PointerGetDatum(X)
+#define PG_GETARG_INET_PP(n) DatumGetInetPP(PG_GETARG_DATUM(n))
+#define PG_RETURN_INET_P(x) return InetPGetDatum(x)
+/* obsolescent variants */
+#define DatumGetInetP(X) ((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 */
+#define DatumGetMacaddrP(X) ((macaddr *) DatumGetPointer(X))
+#define MacaddrPGetDatum(X) 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 */
+#define DatumGetMacaddr8P(X) ((macaddr8 *) DatumGetPointer(X))
+#define Macaddr8PGetDatum(X) 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/int8.h b/src/include/utils/int8.h
new file mode 100644
index 0000000..c4fec34
--- /dev/null
+++ b/src/include/utils/int8.h
@@ -0,0 +1,25 @@
+/*-------------------------------------------------------------------------
+ *
+ * int8.h
+ * Declarations for operations on 64-bit integers.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/int8.h
+ *
+ * NOTES
+ * These data types are supported on all 64-bit architectures, and may
+ * be supported through libraries on some 32-bit machines. If your machine
+ * is not currently supported, then please try to make it so, then post
+ * patches to the postgresql.org hackers mailing list.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef INT8_H
+#define INT8_H
+
+extern bool scanint8(const char *str, bool errorOK, int64 *result);
+
+#endif /* INT8_H */
diff --git a/src/include/utils/inval.h b/src/include/utils/inval.h
new file mode 100644
index 0000000..bc5081c
--- /dev/null
+++ b/src/include/utils/inval.h
@@ -0,0 +1,64 @@
+/*-------------------------------------------------------------------------
+ *
+ * inval.h
+ * POSTGRES cache invalidation dispatcher definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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/relfilenode.h"
+#include "utils/relcache.h"
+
+
+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(RelFileNodeBackend rnode);
+
+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);
+#endif /* INVAL_H */
diff --git a/src/include/utils/json.h b/src/include/utils/json.h
new file mode 100644
index 0000000..4345fbd
--- /dev/null
+++ b/src/include/utils/json.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * json.h
+ * Declarations for JSON data type support.
+ *
+ * Portions Copyright (c) 1996-2020, 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);
+
+#endif /* JSON_H */
diff --git a/src/include/utils/jsonb.h b/src/include/utils/jsonb.h
new file mode 100644
index 0000000..5860011
--- /dev/null
+++ b/src/include/utils/jsonb.h
@@ -0,0 +1,411 @@
+/*-------------------------------------------------------------------------
+ *
+ * jsonb.h
+ * Declarations for jsonb data type support.
+ *
+ * Copyright (c) 1996-2020, 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 */
+
+/* Convenience macros */
+#define DatumGetJsonbP(d) ((Jsonb *) PG_DETOAST_DATUM(d))
+#define DatumGetJsonbPCopy(d) ((Jsonb *) PG_DETOAST_DATUM_COPY(d))
+#define JsonbPGetDatum(p) 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)
+
+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;
+} 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;
+
+
+/* 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 *sheader,
+ uint32 flags,
+ JsonbValue *key);
+extern JsonbValue *getKeyJsonValueFromContainer(JsonbContainer *container,
+ const char *keyVal, int keyLen,
+ JsonbValue *res);
+extern JsonbValue *getIthJsonbValueFromContainer(JsonbContainer *sheader,
+ 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 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 *jb);
+
+
+#endif /* __JSONB_H__ */
diff --git a/src/include/utils/jsonfuncs.h b/src/include/utils/jsonfuncs.h
new file mode 100644
index 0000000..1f1b402
--- /dev/null
+++ b/src/include/utils/jsonfuncs.h
@@ -0,0 +1,58 @@
+/*-------------------------------------------------------------------------
+ *
+ * jsonfuncs.h
+ * Functions to process JSON data types.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/jsonapi.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 ereport(ERROR) on failure */
+extern void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem);
+
+/* report an error during json lexing or parsing */
+extern void json_ereport_error(JsonParseErrorType error, JsonLexContext *lex);
+
+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..4ef0880
--- /dev/null
+++ b/src/include/utils/jsonpath.h
@@ -0,0 +1,251 @@
+/*-------------------------------------------------------------------------
+ *
+ * jsonpath.h
+ * Definitions for jsonpath datatype
+ *
+ * Copyright (c) 2019-2020, 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))
+
+#define DatumGetJsonPathP(d) ((JsonPath *) DatumGetPointer(PG_DETOAST_DATUM(d)))
+#define DatumGetJsonPathPCopy(d) ((JsonPath *) DatumGetPointer(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);
+
+extern int jspConvertRegexFlags(uint32 xflags);
+
+#endif
diff --git a/src/include/utils/logtape.h b/src/include/utils/logtape.h
new file mode 100644
index 0000000..da5159e
--- /dev/null
+++ b/src/include/utils/logtape.h
@@ -0,0 +1,80 @@
+/*-------------------------------------------------------------------------
+ *
+ * logtape.h
+ * Management of "logical tapes" within temporary files.
+ *
+ * See logtape.c for explanations.
+ *
+ * Portions Copyright (c) 1996-2020, 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 is an opaque type whose details are not known outside logtape.c. */
+
+typedef struct LogicalTapeSet LogicalTapeSet;
+
+/*
+ * 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(int ntapes, bool preallocate,
+ TapeShare *shared,
+ SharedFileSet *fileset, int worker);
+extern void LogicalTapeSetClose(LogicalTapeSet *lts);
+extern void LogicalTapeSetForgetFreeSpace(LogicalTapeSet *lts);
+extern size_t LogicalTapeRead(LogicalTapeSet *lts, int tapenum,
+ void *ptr, size_t size);
+extern void LogicalTapeWrite(LogicalTapeSet *lts, int tapenum,
+ void *ptr, size_t size);
+extern void LogicalTapeRewindForRead(LogicalTapeSet *lts, int tapenum,
+ size_t buffer_size);
+extern void LogicalTapeRewindForWrite(LogicalTapeSet *lts, int tapenum);
+extern void LogicalTapeFreeze(LogicalTapeSet *lts, int tapenum,
+ TapeShare *share);
+extern void LogicalTapeSetExtend(LogicalTapeSet *lts, int nAdditional);
+extern size_t LogicalTapeBackspace(LogicalTapeSet *lts, int tapenum,
+ size_t size);
+extern void LogicalTapeSeek(LogicalTapeSet *lts, int tapenum,
+ long blocknum, int offset);
+extern void LogicalTapeTell(LogicalTapeSet *lts, int tapenum,
+ 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..ee35686
--- /dev/null
+++ b/src/include/utils/lsyscache.h
@@ -0,0 +1,198 @@
+/*-------------------------------------------------------------------------
+ *
+ * lsyscache.h
+ * Convenience routines for common queries in the system catalog cache.
+ *
+ * Portions Copyright (c) 1996-2020, 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"
+
+/* 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 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 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 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_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);
+
+#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..efa190a
--- /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-2020, 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..909bc2e
--- /dev/null
+++ b/src/include/utils/memutils.h
@@ -0,0 +1,224 @@
+/*-------------------------------------------------------------------------
+ *
+ * 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-2020, 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)
+
+#define MaxAllocHugeSize (SIZE_MAX / 2)
+
+#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 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);
+extern void MemoryContextAllowInCriticalSection(MemoryContext context,
+ bool allow);
+
+#ifdef MEMORY_CONTEXT_CHECKING
+extern void MemoryContextCheck(MemoryContext context);
+#endif
+extern bool MemoryContextContains(MemoryContext context, void *pointer);
+
+/* Handy macro for copying and assigning context ID ... but note double eval */
+#define MemoryContextCopyAndSetIdentifier(cxt, id) \
+ MemoryContextSetIdentifier(cxt, MemoryContextStrdup(cxt, id))
+
+/*
+ * GetMemoryChunkContext
+ * Given a currently-allocated chunk, determine the context
+ * it belongs to.
+ *
+ * All chunks allocated by any memory context manager are required to be
+ * preceded by the corresponding MemoryContext stored, without padding, in the
+ * preceding sizeof(void*) bytes. A currently-allocated chunk must contain a
+ * backpointer to its owning context. The backpointer is used by pfree() and
+ * repalloc() to find the context to call.
+ */
+#ifndef FRONTEND
+static inline MemoryContext
+GetMemoryChunkContext(void *pointer)
+{
+ MemoryContext context;
+
+ /*
+ * Try to detect bogus pointers handed to us, poorly though we can.
+ * Presumably, a pointer that isn't MAXALIGNED isn't pointing at an
+ * allocated chunk.
+ */
+ Assert(pointer != NULL);
+ Assert(pointer == (void *) MAXALIGN(pointer));
+
+ /*
+ * OK, it's probably safe to look at the context.
+ */
+ context = *(MemoryContext *) (((char *) pointer) - sizeof(void *));
+
+ AssertArg(MemoryContextIsValid(context));
+
+ return context;
+}
+#endif
+
+/*
+ * 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,
+ const MemoryContextMethods *methods,
+ MemoryContext parent,
+ const char *name);
+
+
+/*
+ * 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 blockSize);
+
+/*
+ * 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/numeric.h b/src/include/utils/numeric.h
new file mode 100644
index 0000000..0604cb6
--- /dev/null
+++ b/src/include/utils/numeric.h
@@ -0,0 +1,76 @@
+/*-------------------------------------------------------------------------
+ *
+ * numeric.h
+ * Definitions for the exact numeric data type of Postgres
+ *
+ * Original coding 1998, Jan Wieck. Heavily revised 2003, Tom Lane.
+ *
+ * Copyright (c) 1998-2020, PostgreSQL Global Development Group
+ *
+ * src/include/utils/numeric.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _PG_NUMERIC_H_
+#define _PG_NUMERIC_H_
+
+#include "fmgr.h"
+
+/*
+ * Limit on the precision (and hence scale) specifiable in a NUMERIC typmod.
+ * Note that the implementation limit on the length of a numeric value is
+ * much larger --- beware of what you use this for!
+ */
+#define NUMERIC_MAX_PRECISION 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
+ */
+
+#define DatumGetNumeric(X) ((Numeric) PG_DETOAST_DATUM(X))
+#define DatumGetNumericCopy(X) ((Numeric) PG_DETOAST_DATUM_COPY(X))
+#define NumericGetDatum(X) 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);
+int32 numeric_maximum_size(int32 typmod);
+extern char *numeric_out_sci(Numeric num, int scale);
+extern char *numeric_normalize(Numeric num);
+
+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 *error);
+
+#endif /* _PG_NUMERIC_H_ */
diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h
new file mode 100644
index 0000000..cc356a6
--- /dev/null
+++ b/src/include/utils/palloc.h
@@ -0,0 +1,136 @@
+/*-------------------------------------------------------------------------
+ *
+ * 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-2020, 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 *palloc(Size size);
+extern void *palloc0(Size size);
+extern void *palloc_extended(Size size, int flags);
+extern void *repalloc(void *pointer, Size size);
+extern void pfree(void *pointer);
+
+/*
+ * 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 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..19e35fe
--- /dev/null
+++ b/src/include/utils/partcache.h
@@ -0,0 +1,102 @@
+/*-------------------------------------------------------------------------
+ *
+ * partcache.h
+ *
+ * Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ *
+ * src/include/utils/partcache.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARTCACHE_H
+#define PARTCACHE_H
+
+#include "access/attnum.h"
+#include "fmgr.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
+{
+ char 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..5fea607
--- /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-2020, 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..9cb7d91
--- /dev/null
+++ b/src/include/utils/pg_locale.h
@@ -0,0 +1,119 @@
+/*-----------------------------------------------------------------------
+ *
+ * PostgreSQL locale utilities
+ *
+ * src/include/utils/pg_locale.h
+ *
+ * Copyright (c) 2002-2020, 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
+
+#include "utils/guc.h"
+
+#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
+
+
+/* GUC settings */
+extern char *locale_messages;
+extern char *locale_monetary;
+extern char *locale_numeric;
+extern char *locale_time;
+
+/* lc_time localization cache */
+extern char *localized_abbrev_days[];
+extern char *localized_full_days[];
+extern char *localized_abbrev_months[];
+extern char *localized_full_months[];
+
+
+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_locale(int category, const char *locale, char **canonname);
+extern char *pg_perm_setlocale(int category, const char *locale);
+extern void check_strxfrm_bug(void);
+
+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 pg_locale_t pg_newlocale_from_collation(Oid collid);
+
+extern char *get_collation_actual_version(char collprovider, const char *collcollate);
+
+#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..25d6c5b
--- /dev/null
+++ b/src/include/utils/pg_lsn.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_lsn.h
+ * Declarations for operations on log sequence numbers (LSNs) of
+ * PostgreSQL.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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"
+
+#define DatumGetLSN(X) ((XLogRecPtr) DatumGetInt64(X))
+#define LSNGetDatum(X) (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..685cd41
--- /dev/null
+++ b/src/include/utils/pg_rusage.h
@@ -0,0 +1,37 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_rusage.h
+ * header file for resource usage measurement support routines
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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/time.h>
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#else
+#include "rusagestub.h"
+#endif
+
+
+/* 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/pidfile.h b/src/include/utils/pidfile.h
new file mode 100644
index 0000000..63fefe5
--- /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-2020, 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..522020d
--- /dev/null
+++ b/src/include/utils/plancache.h
@@ -0,0 +1,235 @@
+/*-------------------------------------------------------------------------
+ *
+ * plancache.h
+ * Plan cache definitions.
+ *
+ * See plancache.c for comments.
+ *
+ * Portions Copyright (c) 1996-2020, 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 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 */
+ int num_custom_plans; /* number of plans included in total */
+} 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,
+ bool useResOwner,
+ QueryEnvironment *queryEnv);
+extern void ReleaseCachedPlan(CachedPlan *plan, bool useResOwner);
+
+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..cb40bfa
--- /dev/null
+++ b/src/include/utils/portal.h
@@ -0,0 +1,250 @@
+/*-------------------------------------------------------------------------
+ *
+ * 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-2020, 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 */
+
+ /* 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 */
+
+ /*
+ * 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? */
+
+ /*
+ * 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 */
+} 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,
+ 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..9f43e1f
--- /dev/null
+++ b/src/include/utils/ps_status.h
@@ -0,0 +1,25 @@
+/*-------------------------------------------------------------------------
+ *
+ * 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
+
+extern 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(const char *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..4b8e196
--- /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-2020, 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..b77c41c
--- /dev/null
+++ b/src/include/utils/rangetypes.h
@@ -0,0 +1,139 @@
+/*-------------------------------------------------------------------------
+ *
+ * rangetypes.h
+ * Declarations for Postgres range types.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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;
+
+/* 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 macros for range type objects
+ */
+#define DatumGetRangeTypeP(X) ((RangeType *) PG_DETOAST_DATUM(X))
+#define DatumGetRangeTypePCopy(X) ((RangeType *) PG_DETOAST_DATUM_COPY(X))
+#define RangeTypePGetDatum(X) 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);
+
+/* assorted support functions */
+extern TypeCacheEntry *range_get_typcache(FunctionCallInfo fcinfo,
+ Oid rngtypid);
+extern RangeType *range_serialize(TypeCacheEntry *typcache, RangeBound *lower,
+ RangeBound *upper, bool empty);
+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);
+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 bool bounds_adjacent(TypeCacheEntry *typcache, RangeBound bound1,
+ RangeBound bound2);
+extern RangeType *make_empty_range(TypeCacheEntry *typcache);
+
+#endif /* RANGETYPES_H */
diff --git a/src/include/utils/regproc.h b/src/include/utils/regproc.h
new file mode 100644
index 0000000..383dfe6
--- /dev/null
+++ b/src/include/utils/regproc.h
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+ *
+ * regproc.h
+ * Functions for the built-in types regproc, regclass, regtype, etc.
+ *
+ * Portions Copyright (c) 1996-2020, 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"
+
+extern List *stringToQualifiedNameList(const char *string);
+extern char *format_procedure(Oid procedure_oid);
+extern char *format_procedure_qualified(Oid procedure_oid);
+extern void format_procedure_parts(Oid operator_oid, List **objnames,
+ List **objargs);
+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);
+
+#endif
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
new file mode 100644
index 0000000..0b5957b
--- /dev/null
+++ b/src/include/utils/rel.h
@@ -0,0 +1,644 @@
+/*-------------------------------------------------------------------------
+ *
+ * rel.h
+ * POSTGRES relation descriptor (a/k/a relcache entry) definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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/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/relfilenode.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
+{
+ RelFileNode rd_node; /* relation physical identifier */
+ /* use "struct" here to avoid needing to include smgr.h: */
+ struct SMgrRelationData *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 rd_node was created before the
+ * current top transaction. (IndexStmt.oldNode leads to the case of a new
+ * rel with an old rd_node.) rd_firstRelfilenodeSubid is the ID of the
+ * highest subtransaction an rd_node change has survived into or zero if
+ * rd_node matches the value it had at the start of the current top
+ * transaction. (Rolling back the subtransaction that
+ * rd_firstRelfilenodeSubid denotes would restore rd_node 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_newRelfilenodeSubid is the ID of the highest subtransaction the
+ * most-recent relfilenode 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 relfilenodes 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_newRelfilenodeSubid is now forgotten
+ *
+ * If every rd_*Subid field is zero, they are read-only outside
+ * relcache.c. Files that trigger rd_node changes by updating
+ * pg_class.reltablespace and/or pg_class.relfilenode call
+ * RelationAssumeNewRelfilenode() 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_newRelfilenodeSubid; /* highest subxact changing
+ * rd_node to current value */
+ SubTransactionId rd_firstRelfilenodeSubid; /* highest subxact changing
+ * rd_node 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 */
+
+ /* 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: */
+ Bitmapset *rd_indexattr; /* identifies columns used in indexes */
+ 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 */
+
+ PublicationActions *rd_pubactions; /* publication actions */
+
+ /*
+ * 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 */
+
+ /* 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
+{
+ NodeTag type;
+ Oid conoid; /* oid of the constraint itself */
+ Oid conrelid; /* relation constrained by the foreign key */
+ Oid confrelid; /* relation referenced by the foreign key */
+ int nkeys; /* number of columns in the foreign key */
+ /* these arrays each have nkeys valid entries: */
+ AttrNumber conkey[INDEX_MAX_KEYS]; /* cols in referencing table */
+ AttrNumber confkey[INDEX_MAX_KEYS]; /* cols in referenced table */
+ Oid conpfeqop[INDEX_MAX_KEYS]; /* PK = FK operator OIDs */
+} 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;
+
+typedef struct StdRdOptions
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ int fillfactor; /* page fill factor in percent (0..100) */
+ /* fraction of newly inserted tuples prior to trigger index cleanup */
+ 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 */
+ bool vacuum_index_cleanup; /* enables index vacuuming and cleanup */
+ 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;
+ 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)
+
+/*
+ * 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 relfilenode map. Note multiple eval
+ * of argument!
+ */
+#define RelationIsMapped(relation) \
+ (RELKIND_HAS_STORAGE((relation)->rd_rel->relkind) && \
+ ((relation)->rd_rel->relfilenode == InvalidOid))
+
+/*
+ * RelationOpenSmgr
+ * Open the relation at the smgr level, if not already done.
+ */
+#define RelationOpenSmgr(relation) \
+ do { \
+ if ((relation)->rd_smgr == NULL) \
+ smgrsetowner(&((relation)->rd_smgr), smgropen((relation)->rd_node, (relation)->rd_backend)); \
+ } while (0)
+
+/*
+ * RelationCloseSmgr
+ * Close the relation at the smgr level, if not already done.
+ *
+ * Note: smgrclose should unhook from owner pointer, hence the Assert.
+ */
+#define RelationCloseSmgr(relation) \
+ do { \
+ if ((relation)->rd_smgr != NULL) \
+ { \
+ smgrclose((relation)->rd_smgr); \
+ Assert((relation)->rd_smgr == NULL); \
+ } \
+ } while (0)
+
+/*
+ * 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.
+ */
+#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 { \
+ RelationOpenSmgr(relation); \
+ (relation)->rd_smgr->smgr_targblock = (targblock); \
+ } while (0)
+
+/*
+ * 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
+ * RelFileNode" in src/backend/access/transam/README.
+ */
+#define RelationNeedsWAL(relation) \
+ ((relation)->rd_rel->relpersistence == RELPERSISTENCE_PERMANENT && \
+ (XLogIsNeeded() || \
+ (relation->rd_createSubid == InvalidSubTransactionId && \
+ relation->rd_firstRelfilenodeSubid == 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) 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) && \
+ !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..9a85b7d
--- /dev/null
+++ b/src/include/utils/relcache.h
@@ -0,0 +1,151 @@
+/*-------------------------------------------------------------------------
+ *
+ * relcache.h
+ * Relation descriptor cache definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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 "postgres.h"
+#include "access/tupdesc.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 relation);
+extern bytea **RelationGetIndexAttOptions(Relation relation, bool copy);
+
+typedef enum IndexAttrBitmapKind
+{
+ INDEX_ATTR_BITMAP_ALL,
+ INDEX_ATTR_BITMAP_KEY,
+ INDEX_ATTR_BITMAP_PRIMARY_KEY,
+ INDEX_ATTR_BITMAP_IDENTITY_KEY
+} IndexAttrBitmapKind;
+
+extern Bitmapset *RelationGetIndexAttrBitmap(Relation relation,
+ IndexAttrBitmapKind attrKind);
+
+extern void RelationGetExclusionInfo(Relation indexRelation,
+ Oid **operators,
+ Oid **procs,
+ uint16 **strategies);
+
+extern void RelationInitIndexAccessInfo(Relation relation);
+
+/* caller must include pg_publication.h */
+struct PublicationActions;
+extern struct PublicationActions *GetRelationPublicationActions(Relation relation);
+
+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,
+ Oid relfilenode,
+ Oid reltablespace,
+ bool shared_relation,
+ bool mapped_relation,
+ char relpersistence,
+ char relkind);
+
+/*
+ * Routines to manage assignment of new relfilenode to a relation
+ */
+extern void RelationSetNewRelfilenode(Relation relation, char persistence);
+extern void RelationAssumeNewRelfilenode(Relation relation);
+
+/*
+ * Routines for flushing/rebuilding relcache entries in various scenarios
+ */
+extern void RelationForgetRelation(Oid rid);
+
+extern void RelationCacheInvalidateEntry(Oid relationId);
+
+extern void RelationCacheInvalidate(void);
+
+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 bool criticalRelcachesBuilt;
+
+/* should be used only by relcache.c and postinit.c */
+extern bool criticalSharedRelcachesBuilt;
+
+#endif /* RELCACHE_H */
diff --git a/src/include/utils/relfilenodemap.h b/src/include/utils/relfilenodemap.h
new file mode 100644
index 0000000..e2e1c76
--- /dev/null
+++ b/src/include/utils/relfilenodemap.h
@@ -0,0 +1,18 @@
+/*-------------------------------------------------------------------------
+ *
+ * relfilenodemap.h
+ * relfilenode to oid mapping cache.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/relfilenodemap.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RELFILENODEMAP_H
+#define RELFILENODEMAP_H
+
+extern Oid RelidByRelfilenode(Oid reltablespace, Oid relfilenode);
+
+#endif /* RELFILENODEMAP_H */
diff --git a/src/include/utils/relmapper.h b/src/include/utils/relmapper.h
new file mode 100644
index 0000000..2626a74
--- /dev/null
+++ b/src/include/utils/relmapper.h
@@ -0,0 +1,70 @@
+/*-------------------------------------------------------------------------
+ *
+ * relmapper.h
+ * Catalog-to-filenode mapping
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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 Oid RelationMapOidToFilenode(Oid relationId, bool shared);
+
+extern Oid RelationMapFilenodeToOid(Oid relationId, bool shared);
+
+extern void RelationMapUpdateMap(Oid relationId, Oid fileNode, 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..c6bf4e4
--- /dev/null
+++ b/src/include/utils/relptr.h
@@ -0,0 +1,77 @@
+/*-------------------------------------------------------------------------
+ *
+ * relptr.h
+ * This file contains basic declarations for relative pointers.
+ *
+ * Portions Copyright (c) 1996-2020, 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)))
+#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)))
+#endif
+
+#define relptr_is_null(rp) \
+ ((rp).relptr_off == 0)
+
+#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
+#define relptr_store(base, rp, val) \
+ (AssertVariableIsOfTypeMacro(base, char *), \
+ AssertVariableIsOfTypeMacro(val, __typeof__((rp).relptr_type)), \
+ (rp).relptr_off = ((val) == NULL ? 0 : ((char *) (val)) - (base)))
+#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 = ((val) == NULL ? 0 : ((char *) (val)) - (base)))
+#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..b22acb0
--- /dev/null
+++ b/src/include/utils/reltrigger.h
@@ -0,0 +1,81 @@
+/*-------------------------------------------------------------------------
+ *
+ * reltrigger.h
+ * POSTGRES relation trigger definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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..878f39c
--- /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-2020, 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..a781a7a
--- /dev/null
+++ b/src/include/utils/resowner_private.h
@@ -0,0 +1,98 @@
+/*-------------------------------------------------------------------------
+ *
+ * resowner_private.h
+ * POSTGRES resource owner private definitions.
+ *
+ * See utils/resowner/README for more info.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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 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);
+
+#endif /* RESOWNER_PRIVATE_H */
diff --git a/src/include/utils/rls.h b/src/include/utils/rls.h
new file mode 100644
index 0000000..49542f3
--- /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-2020, PostgreSQL Global Development Group
+ *
+ * src/include/utils/rls.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RLS_H
+#define RLS_H
+
+/* GUC variable */
+extern 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..8306c76
--- /dev/null
+++ b/src/include/utils/ruleutils.h
@@ -0,0 +1,44 @@
+/*-------------------------------------------------------------------------
+ *
+ * ruleutils.h
+ * Declarations for ruleutils.c
+ *
+ * Portions Copyright (c) 1996-2020, 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;
+
+
+extern char *pg_get_indexdef_string(Oid indexrelid);
+extern char *pg_get_indexdef_columns(Oid indexrelid, 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);
+
+#endif /* RULEUTILS_H */
diff --git a/src/include/utils/sampling.h b/src/include/utils/sampling.h
new file mode 100644
index 0000000..7464684
--- /dev/null
+++ b/src/include/utils/sampling.h
@@ -0,0 +1,65 @@
+/*-------------------------------------------------------------------------
+ *
+ * sampling.h
+ * definitions for sampling functions
+ *
+ * Portions Copyright (c) 1996-2020, 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 "storage/block.h" /* for typedef BlockNumber */
+
+
+/* Random generator for sampling code */
+typedef unsigned short SamplerRandomState[3];
+
+extern void sampler_random_init_state(long seed,
+ SamplerRandomState randstate);
+extern double sampler_random_fract(SamplerRandomState 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 */
+ SamplerRandomState randstate; /* random generator state */
+} BlockSamplerData;
+
+typedef BlockSamplerData *BlockSampler;
+
+extern BlockNumber BlockSampler_Init(BlockSampler bs, BlockNumber nblocks,
+ int samplesize, long randseed);
+extern bool BlockSampler_HasMore(BlockSampler bs);
+extern BlockNumber BlockSampler_Next(BlockSampler bs);
+
+/* Reservoir sampling methods */
+
+typedef struct
+{
+ double W;
+ SamplerRandomState 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..7ac4a06
--- /dev/null
+++ b/src/include/utils/selfuncs.h
@@ -0,0 +1,223 @@
+/*-------------------------------------------------------------------------
+ *
+ * selfuncs.h
+ * Selectivity functions for standard operators, and assorted
+ * infrastructure for selectivity and cost estimation.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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 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)
+
+
+/* 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);
+
+extern void estimate_hash_bucket_stats(PlannerInfo *root,
+ Node *hashkey, double nbuckets,
+ Selectivity *mcv_freq,
+ Selectivity *bucketsize_frac);
+extern double estimate_hashagg_tablesize(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..9754504
--- /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-2020, 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..ad7c15d
--- /dev/null
+++ b/src/include/utils/snapmgr.h
@@ -0,0 +1,158 @@
+/*-------------------------------------------------------------------------
+ *
+ * snapmgr.h
+ * POSTGRES snapshot manager
+ *
+ * Portions Copyright (c) 1996-2020, 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) \
+( \
+ (rel)->rd_rel->relpersistence == RELPERSISTENCE_PERMANENT \
+ && !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 bool FirstSnapshotSet;
+
+extern PGDLLIMPORT TransactionId TransactionXmin;
+extern PGDLLIMPORT TransactionId RecentXmin;
+extern PGDLLIMPORT TransactionId RecentGlobalXmin;
+extern PGDLLIMPORT TransactionId RecentGlobalDataXmin;
+
+/* 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 xmin horizon to use (e.g., RecentGlobalXmin).
+ */
+#define InitNonVacuumableSnapshot(snapshotdata, xmin_horizon) \
+ ((snapshotdata).snapshot_type = SNAPSHOT_NON_VACUUMABLE, \
+ (snapshotdata).xmin = (xmin_horizon))
+
+/*
+ * 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)
+
+
+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 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 FullTransactionId GetFullRecentGlobalXmin(void);
+
+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 bool ThereAreNoPriorRegisteredSnapshots(void);
+extern TransactionId TransactionIdLimitedForOldSnapshots(TransactionId recentXmin,
+ Relation relation);
+extern void MaintainOldSnapshotTimeMapping(TimestampTz whenTaken,
+ TransactionId xmin);
+
+extern char *ExportSnapshot(Snapshot snapshot);
+
+/*
+ * 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 snapshot_now, 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 *master_pgproc);
+
+#endif /* SNAPMGR_H */
diff --git a/src/include/utils/snapshot.h b/src/include/utils/snapshot.h
new file mode 100644
index 0000000..4796edb
--- /dev/null
+++ b/src/include/utils/snapshot.h
@@ -0,0 +1,206 @@
+/*-------------------------------------------------------------------------
+ *
+ * snapshot.h
+ * POSTGRES snapshot definition
+ *
+ * Portions Copyright (c) 1996-2020, 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;
+
+ /*
+ * 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 */
+} SnapshotData;
+
+#endif /* SNAPSHOT_H */
diff --git a/src/include/utils/sortsupport.h b/src/include/utils/sortsupport.h
new file mode 100644
index 0000000..264aec8
--- /dev/null
+++ b/src/include/utils/sortsupport.h
@@ -0,0 +1,276 @@
+/*-------------------------------------------------------------------------
+ *
+ * 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-2020, 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;
+}
+
+/*
+ * 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;
+}
+
+/* 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);
+
+#endif /* SORTSUPPORT_H */
diff --git a/src/include/utils/spccache.h b/src/include/utils/spccache.h
new file mode 100644
index 0000000..7e4ec69
--- /dev/null
+++ b/src/include/utils/spccache.h
@@ -0,0 +1,21 @@
+/*-------------------------------------------------------------------------
+ *
+ * spccache.h
+ * Tablespace cache.
+ *
+ * Portions Copyright (c) 1996-2020, 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
+
+void get_tablespace_page_costs(Oid spcid, float8 *spc_random_page_cost,
+ float8 *spc_seq_page_cost);
+int get_tablespace_io_concurrency(Oid spcid);
+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..f27b73d
--- /dev/null
+++ b/src/include/utils/syscache.h
@@ -0,0 +1,219 @@
+/*-------------------------------------------------------------------------
+ *
+ * syscache.h
+ * System catalog cache definitions.
+ *
+ * See also lsyscache.h, which provides convenience routines for
+ * common cache-lookup operations.
+ *
+ * Portions Copyright (c) 1996-2020, 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,
+ PARTRELID,
+ PROCNAMEARGSNSP,
+ PROCOID,
+ PUBLICATIONNAME,
+ PUBLICATIONOID,
+ PUBLICATIONREL,
+ PUBLICATIONRELMAP,
+ 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 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..83a15f6
--- /dev/null
+++ b/src/include/utils/timeout.h
@@ -0,0 +1,88 @@
+/*-------------------------------------------------------------------------
+ *
+ * timeout.h
+ * Routines to multiplex SIGALRM interrupts for multiple timeout reasons.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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,
+ /* First user-definable timeout reason */
+ USER_TIMEOUT,
+ /* Maximum number of timeout reasons */
+ MAX_TIMEOUTS = 16
+} 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
+} TimeoutType;
+
+typedef struct
+{
+ TimeoutId id; /* timeout to set */
+ TimeoutType type; /* TMPARAM_AFTER or TMPARAM_AT */
+ int delay_ms; /* only used for TMPARAM_AFTER */
+ 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_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..d45bf2b
--- /dev/null
+++ b/src/include/utils/timestamp.h
@@ -0,0 +1,116 @@
+/*-------------------------------------------------------------------------
+ *
+ * timestamp.h
+ * Definitions for the SQL "timestamp" and "interval" types.
+ *
+ * Portions Copyright (c) 1996-2020, 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"
+
+
+/*
+ * Macros 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!
+ */
+#define DatumGetTimestamp(X) ((Timestamp) DatumGetInt64(X))
+#define DatumGetTimestampTz(X) ((TimestampTz) DatumGetInt64(X))
+#define DatumGetIntervalP(X) ((Interval *) DatumGetPointer(X))
+
+#define TimestampGetDatum(X) Int64GetDatum(X)
+#define TimestampTzGetDatum(X) Int64GetDatum(X)
+#define IntervalPGetDatum(X) 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)
+
+#define TimestampTzPlusMilliseconds(tz,ms) ((tz) + ((ms) * (int64) 1000))
+
+
+/* Set at postmaster start */
+extern TimestampTz PgStartTime;
+
+/* Set at configuration reload */
+extern 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 *dt);
+extern int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm,
+ fsec_t *fsec, const char **tzn, pg_tz *attimezone);
+extern void dt2time(Timestamp dt, int *hour, int *min, int *sec, fsec_t *fsec);
+
+extern int interval2tm(Interval span, struct pg_tm *tm, fsec_t *fsec);
+extern int tm2interval(struct pg_tm *tm, fsec_t fsec, 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..9e76666
--- /dev/null
+++ b/src/include/utils/tuplesort.h
@@ -0,0 +1,277 @@
+/*-------------------------------------------------------------------------
+ *
+ * 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-2020, 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/relcache.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;
+
+typedef struct TuplesortInstrumentation
+{
+ TuplesortMethod sortMethod; /* sort algorithm used */
+ TuplesortSpaceType spaceType; /* type of space spaceUsed represents */
+ int64 spaceUsed; /* space consumption, in kB */
+} TuplesortInstrumentation;
+
+
+/*
+ * 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_heap(TupleDesc tupDesc,
+ int nkeys, AttrNumber *attNums,
+ Oid *sortOperators, Oid *sortCollations,
+ bool *nullsFirstFlags,
+ int workMem, SortCoordinate coordinate,
+ bool randomAccess);
+extern Tuplesortstate *tuplesort_begin_cluster(TupleDesc tupDesc,
+ Relation indexRel, int workMem,
+ SortCoordinate coordinate, bool randomAccess);
+extern Tuplesortstate *tuplesort_begin_index_btree(Relation heapRel,
+ Relation indexRel,
+ bool enforceUnique,
+ int workMem, SortCoordinate coordinate,
+ bool randomAccess);
+extern Tuplesortstate *tuplesort_begin_index_hash(Relation heapRel,
+ Relation indexRel,
+ uint32 high_mask,
+ uint32 low_mask,
+ uint32 max_buckets,
+ int workMem, SortCoordinate coordinate,
+ bool randomAccess);
+extern Tuplesortstate *tuplesort_begin_datum(Oid datumType,
+ Oid sortOperator, Oid sortCollation,
+ bool nullsFirstFlag,
+ int workMem, SortCoordinate coordinate,
+ bool randomAccess);
+
+extern void tuplesort_set_bound(Tuplesortstate *state, int64 bound);
+extern bool tuplesort_used_bound(Tuplesortstate *state);
+
+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 void tuplesort_performsort(Tuplesortstate *state);
+
+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,
+ Datum *val, bool *isNull, Datum *abbrev);
+
+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 randomAccess was specified 'true'.
+ * Likewise, backwards scan in gettuple/getdatum is only allowed if
+ * randomAccess was specified. Note that parallel sorts do not support
+ * randomAccess.
+ */
+
+extern void tuplesort_rescan(Tuplesortstate *state);
+extern void tuplesort_markpos(Tuplesortstate *state);
+extern void tuplesort_restorepos(Tuplesortstate *state);
+
+#endif /* TUPLESORT_H */
diff --git a/src/include/utils/tuplestore.h b/src/include/utils/tuplestore.h
new file mode 100644
index 0000000..2c6403f
--- /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-2020, 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);
+
+/* tuplestore_donestoring() used to be required, but is no longer used */
+#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..cdd20e5
--- /dev/null
+++ b/src/include/utils/typcache.h
@@ -0,0 +1,202 @@
+/*-------------------------------------------------------------------------
+ *
+ * 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-2020, 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 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 */
+
+ /*
+ * 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 0x0001
+#define TYPECACHE_LT_OPR 0x0002
+#define TYPECACHE_GT_OPR 0x0004
+#define TYPECACHE_CMP_PROC 0x0008
+#define TYPECACHE_HASH_PROC 0x0010
+#define TYPECACHE_EQ_OPR_FINFO 0x0020
+#define TYPECACHE_CMP_PROC_FINFO 0x0040
+#define TYPECACHE_HASH_PROC_FINFO 0x0080
+#define TYPECACHE_TUPDESC 0x0100
+#define TYPECACHE_BTREE_OPFAMILY 0x0200
+#define TYPECACHE_HASH_OPFAMILY 0x0400
+#define TYPECACHE_RANGE_INFO 0x0800
+#define TYPECACHE_DOMAIN_BASE_INFO 0x1000
+#define TYPECACHE_DOMAIN_CONSTR_INFO 0x2000
+#define TYPECACHE_HASH_EXTENDED_PROC 0x4000
+#define TYPECACHE_HASH_EXTENDED_PROC_FINFO 0x8000
+
+/* 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..8eb602d
--- /dev/null
+++ b/src/include/utils/tzparser.h
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * tzparser.h
+ * Timezone offset file parsing definitions.
+ *
+ * Portions Copyright (c) 1996-2020, 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/uuid.h b/src/include/utils/uuid.h
new file mode 100644
index 0000000..281a1a6
--- /dev/null
+++ b/src/include/utils/uuid.h
@@ -0,0 +1,31 @@
+/*-------------------------------------------------------------------------
+ *
+ * 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-2020, 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 */
+#define UUIDPGetDatum(X) PointerGetDatum(X)
+#define PG_RETURN_UUID_P(X) return UUIDPGetDatum(X)
+#define DatumGetUUIDP(X) ((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..91f8de1
--- /dev/null
+++ b/src/include/utils/varbit.h
@@ -0,0 +1,74 @@
+/*-------------------------------------------------------------------------
+ *
+ * varbit.h
+ * Functions for the SQL datatypes BIT() and BIT VARYING().
+ *
+ * Code originally contributed by Adriaan Joubert.
+ *
+ * Portions Copyright (c) 1996-2020, 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.
+ */
+#define DatumGetVarBitP(X) ((VarBit *) PG_DETOAST_DATUM(X))
+#define DatumGetVarBitPCopy(X) ((VarBit *) PG_DETOAST_DATUM_COPY(X))
+#define VarBitPGetDatum(X) 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..85e838f
--- /dev/null
+++ b/src/include/utils/varlena.h
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * varlena.h
+ * Functions for the variable-length built-in types.
+ *
+ * Portions Copyright (c) 1996-2020, 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, void *regexp,
+ text *replace_text, bool glob);
+
+#endif
diff --git a/src/include/utils/xid8.h b/src/include/utils/xid8.h
new file mode 100644
index 0000000..288e62d
--- /dev/null
+++ b/src/include/utils/xid8.h
@@ -0,0 +1,22 @@
+/*-------------------------------------------------------------------------
+ *
+ * xid8.h
+ * Header file for the "xid8" ADT.
+ *
+ * Copyright (c) 2020, PostgreSQL Global Development Group
+ *
+ * src/include/utils/xid8.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef XID8_H
+#define XID8_H
+
+#include "access/transam.h"
+
+#define DatumGetFullTransactionId(X) (FullTransactionIdFromU64(DatumGetUInt64(X)))
+#define FullTransactionIdGetDatum(X) (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..cf0e61f
--- /dev/null
+++ b/src/include/utils/xml.h
@@ -0,0 +1,84 @@
+/*-------------------------------------------------------------------------
+ *
+ * xml.h
+ * Declarations for XML data type support.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, 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;
+
+#define DatumGetXmlP(X) ((xmltype *) PG_DETOAST_DATUM(X))
+#define XmlPGetDatum(X) 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, 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_xmloption(xmltype *data, XmlOptionType xmloption_arg);
+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 int xmlbinary; /* XmlBinaryType, but int for guc enum */
+
+extern int xmloption; /* XmlOptionType, but int for guc enum */
+
+extern const TableFuncRoutine XmlTableRoutine;
+
+#endif /* XML_H */