summaryrefslogtreecommitdiffstats
path: root/src/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/include')
-rw-r--r--src/include/.gitignore5
-rw-r--r--src/include/Makefile85
-rw-r--r--src/include/access/amapi.h246
-rw-r--r--src/include/access/amvalidate.h37
-rw-r--r--src/include/access/attmap.h52
-rw-r--r--src/include/access/attnum.h64
-rw-r--r--src/include/access/brin.h55
-rw-r--r--src/include/access/brin_internal.h111
-rw-r--r--src/include/access/brin_page.h96
-rw-r--r--src/include/access/brin_pageops.h38
-rw-r--r--src/include/access/brin_revmap.h41
-rw-r--r--src/include/access/brin_tuple.h102
-rw-r--r--src/include/access/brin_xlog.h151
-rw-r--r--src/include/access/bufmask.h32
-rw-r--r--src/include/access/clog.h61
-rw-r--r--src/include/access/commit_ts.h77
-rw-r--r--src/include/access/detoast.h92
-rw-r--r--src/include/access/genam.h228
-rw-r--r--src/include/access/generic_xlog.h45
-rw-r--r--src/include/access/gin.h78
-rw-r--r--src/include/access/gin_private.h495
-rw-r--r--src/include/access/ginblock.h346
-rw-r--r--src/include/access/ginxlog.h216
-rw-r--r--src/include/access/gist.h239
-rw-r--r--src/include/access/gist_private.h563
-rw-r--r--src/include/access/gistscan.h24
-rw-r--r--src/include/access/gistxlog.h114
-rw-r--r--src/include/access/hash.h478
-rw-r--r--src/include/access/hash_xlog.h267
-rw-r--r--src/include/access/heapam.h223
-rw-r--r--src/include/access/heapam_xlog.h418
-rw-r--r--src/include/access/heaptoast.h149
-rw-r--r--src/include/access/hio.h43
-rw-r--r--src/include/access/htup.h89
-rw-r--r--src/include/access/htup_details.h819
-rw-r--r--src/include/access/itup.h161
-rw-r--r--src/include/access/multixact.h160
-rw-r--r--src/include/access/nbtree.h1148
-rw-r--r--src/include/access/nbtxlog.h335
-rw-r--r--src/include/access/parallel.h82
-rw-r--r--src/include/access/printsimple.h23
-rw-r--r--src/include/access/printtup.h35
-rw-r--r--src/include/access/relation.h28
-rw-r--r--src/include/access/reloptions.h247
-rw-r--r--src/include/access/relscan.h176
-rw-r--r--src/include/access/rewriteheap.h57
-rw-r--r--src/include/access/rmgr.h35
-rw-r--r--src/include/access/rmgrlist.h49
-rw-r--r--src/include/access/sdir.h58
-rw-r--r--src/include/access/session.h44
-rw-r--r--src/include/access/skey.h151
-rw-r--r--src/include/access/slru.h170
-rw-r--r--src/include/access/spgist.h224
-rw-r--r--src/include/access/spgist_private.h494
-rw-r--r--src/include/access/spgxlog.h257
-rw-r--r--src/include/access/stratnum.h83
-rw-r--r--src/include/access/subtrans.h30
-rw-r--r--src/include/access/sysattr.h29
-rw-r--r--src/include/access/table.h27
-rw-r--r--src/include/access/tableam.h1825
-rw-r--r--src/include/access/timeline.h44
-rw-r--r--src/include/access/toast_helper.h115
-rw-r--r--src/include/access/toast_internals.h55
-rw-r--r--src/include/access/transam.h265
-rw-r--r--src/include/access/tsmapi.h82
-rw-r--r--src/include/access/tupconvert.h51
-rw-r--r--src/include/access/tupdesc.h154
-rw-r--r--src/include/access/tupdesc_details.h28
-rw-r--r--src/include/access/tupmacs.h247
-rw-r--r--src/include/access/twophase.h61
-rw-r--r--src/include/access/twophase_rmgr.h40
-rw-r--r--src/include/access/valid.h69
-rw-r--r--src/include/access/visibilitymap.h50
-rw-r--r--src/include/access/xact.h463
-rw-r--r--src/include/access/xlog.h398
-rw-r--r--src/include/access/xlog_internal.h330
-rw-r--r--src/include/access/xlogarchive.h35
-rw-r--r--src/include/access/xlogdefs.h109
-rw-r--r--src/include/access/xloginsert.h64
-rw-r--r--src/include/access/xlogreader.h327
-rw-r--r--src/include/access/xlogrecord.h227
-rw-r--r--src/include/access/xlogutils.h63
-rw-r--r--src/include/bootstrap/bootstrap.h62
-rw-r--r--src/include/c.h1332
-rw-r--r--src/include/catalog/.gitignore3
-rw-r--r--src/include/catalog/Makefile28
-rw-r--r--src/include/catalog/binary_upgrade.h30
-rw-r--r--src/include/catalog/catalog.h42
-rw-r--r--src/include/catalog/catversion.h58
-rw-r--r--src/include/catalog/dependency.h275
-rwxr-xr-xsrc/include/catalog/duplicate_oids49
-rw-r--r--src/include/catalog/genbki.h64
-rw-r--r--src/include/catalog/heap.h163
-rw-r--r--src/include/catalog/index.h199
-rw-r--r--src/include/catalog/indexing.h366
-rw-r--r--src/include/catalog/namespace.h188
-rw-r--r--src/include/catalog/objectaccess.h197
-rw-r--r--src/include/catalog/objectaddress.h84
-rw-r--r--src/include/catalog/opfam_internal.h28
-rw-r--r--src/include/catalog/partition.h34
-rw-r--r--src/include/catalog/pg_aggregate.dat598
-rw-r--r--src/include/catalog/pg_aggregate.h176
-rw-r--r--src/include/catalog/pg_am.dat37
-rw-r--r--src/include/catalog/pg_am.h60
-rw-r--r--src/include/catalog/pg_amop.dat2463
-rw-r--r--src/include/catalog/pg_amop.h98
-rw-r--r--src/include/catalog/pg_amproc.dat1316
-rw-r--r--src/include/catalog/pg_amproc.h70
-rw-r--r--src/include/catalog/pg_attrdef.h49
-rw-r--r--src/include/catalog/pg_attribute.h204
-rw-r--r--src/include/catalog/pg_auth_members.h45
-rw-r--r--src/include/catalog/pg_authid.dat64
-rw-r--r--src/include/catalog/pg_authid.h58
-rw-r--r--src/include/catalog/pg_cast.dat533
-rw-r--r--src/include/catalog/pg_cast.h99
-rw-r--r--src/include/catalog/pg_class.dat28
-rw-r--r--src/include/catalog/pg_class.h200
-rw-r--r--src/include/catalog/pg_collation.dat31
-rw-r--r--src/include/catalog/pg_collation.h73
-rw-r--r--src/include/catalog/pg_constraint.h247
-rw-r--r--src/include/catalog/pg_control.h250
-rw-r--r--src/include/catalog/pg_conversion.dat405
-rw-r--r--src/include/catalog/pg_conversion.h72
-rw-r--r--src/include/catalog/pg_database.dat22
-rw-r--r--src/include/catalog/pg_database.h83
-rw-r--r--src/include/catalog/pg_db_role_setting.h54
-rw-r--r--src/include/catalog/pg_default_acl.h65
-rw-r--r--src/include/catalog/pg_depend.h73
-rw-r--r--src/include/catalog/pg_description.h66
-rw-r--r--src/include/catalog/pg_enum.h62
-rw-r--r--src/include/catalog/pg_event_trigger.h51
-rw-r--r--src/include/catalog/pg_extension.h52
-rw-r--r--src/include/catalog/pg_foreign_data_wrapper.h50
-rw-r--r--src/include/catalog/pg_foreign_server.h50
-rw-r--r--src/include/catalog/pg_foreign_table.h45
-rw-r--r--src/include/catalog/pg_index.h80
-rw-r--r--src/include/catalog/pg_inherits.h57
-rw-r--r--src/include/catalog/pg_init_privs.h78
-rw-r--r--src/include/catalog/pg_language.dat25
-rw-r--r--src/include/catalog/pg_language.h67
-rw-r--r--src/include/catalog/pg_largeobject.h50
-rw-r--r--src/include/catalog/pg_largeobject_metadata.h48
-rw-r--r--src/include/catalog/pg_namespace.dat25
-rw-r--r--src/include/catalog/pg_namespace.h59
-rw-r--r--src/include/catalog/pg_opclass.dat350
-rw-r--r--src/include/catalog/pg_opclass.h85
-rw-r--r--src/include/catalog/pg_operator.dat3331
-rw-r--r--src/include/catalog/pg_operator.h102
-rw-r--r--src/include/catalog/pg_opfamily.dat234
-rw-r--r--src/include/catalog/pg_opfamily.h60
-rw-r--r--src/include/catalog/pg_partitioned_table.h63
-rw-r--r--src/include/catalog/pg_policy.h52
-rw-r--r--src/include/catalog/pg_proc.dat10940
-rw-r--r--src/include/catalog/pg_proc.h211
-rw-r--r--src/include/catalog/pg_publication.h115
-rw-r--r--src/include/catalog/pg_publication_rel.h43
-rw-r--r--src/include/catalog/pg_range.dat31
-rw-r--r--src/include/catalog/pg_range.h66
-rw-r--r--src/include/catalog/pg_replication_origin.h57
-rw-r--r--src/include/catalog/pg_rewrite.h54
-rw-r--r--src/include/catalog/pg_seclabel.h40
-rw-r--r--src/include/catalog/pg_sequence.h42
-rw-r--r--src/include/catalog/pg_shdepend.h72
-rw-r--r--src/include/catalog/pg_shdescription.h58
-rw-r--r--src/include/catalog/pg_shseclabel.h41
-rw-r--r--src/include/catalog/pg_statistic.h275
-rw-r--r--src/include/catalog/pg_statistic_ext.h74
-rw-r--r--src/include/catalog/pg_statistic_ext_data.h52
-rw-r--r--src/include/catalog/pg_subscription.h89
-rw-r--r--src/include/catalog/pg_subscription_rel.h90
-rw-r--r--src/include/catalog/pg_tablespace.dat22
-rw-r--r--src/include/catalog/pg_tablespace.h48
-rw-r--r--src/include/catalog/pg_transform.h45
-rw-r--r--src/include/catalog/pg_trigger.h137
-rw-r--r--src/include/catalog/pg_ts_config.dat18
-rw-r--r--src/include/catalog/pg_ts_config.h50
-rw-r--r--src/include/catalog/pg_ts_config_map.dat54
-rw-r--r--src/include/catalog/pg_ts_config_map.h47
-rw-r--r--src/include/catalog/pg_ts_dict.dat19
-rw-r--r--src/include/catalog/pg_ts_dict.h54
-rw-r--r--src/include/catalog/pg_ts_parser.dat20
-rw-r--r--src/include/catalog/pg_ts_parser.h57
-rw-r--r--src/include/catalog/pg_ts_template.dat30
-rw-r--r--src/include/catalog/pg_ts_template.h48
-rw-r--r--src/include/catalog/pg_type.dat633
-rw-r--r--src/include/catalog/pg_type.h372
-rw-r--r--src/include/catalog/pg_user_mapping.h48
-rwxr-xr-xsrc/include/catalog/reformat_dat_file.pl312
-rwxr-xr-xsrc/include/catalog/renumber_oids.pl291
-rw-r--r--src/include/catalog/storage.h48
-rw-r--r--src/include/catalog/storage_xlog.h59
-rw-r--r--src/include/catalog/toasting.h105
-rwxr-xr-xsrc/include/catalog/unused_oids78
-rw-r--r--src/include/commands/alter.h35
-rw-r--r--src/include/commands/async.h54
-rw-r--r--src/include/commands/cluster.h38
-rw-r--r--src/include/commands/collationcmds.h25
-rw-r--r--src/include/commands/comment.h45
-rw-r--r--src/include/commands/conversioncmds.h23
-rw-r--r--src/include/commands/copy.h44
-rw-r--r--src/include/commands/createas.h32
-rw-r--r--src/include/commands/dbcommands.h35
-rw-r--r--src/include/commands/dbcommands_xlog.h45
-rw-r--r--src/include/commands/defrem.h173
-rw-r--r--src/include/commands/discard.h20
-rw-r--r--src/include/commands/event_trigger.h88
-rw-r--r--src/include/commands/explain.h127
-rw-r--r--src/include/commands/extension.h55
-rw-r--r--src/include/commands/lockcmds.h24
-rw-r--r--src/include/commands/matview.h33
-rw-r--r--src/include/commands/policy.h38
-rw-r--r--src/include/commands/portalcmds.h34
-rw-r--r--src/include/commands/prepare.h61
-rw-r--r--src/include/commands/proclang.h24
-rw-r--r--src/include/commands/progress.h136
-rw-r--r--src/include/commands/publicationcmds.h29
-rw-r--r--src/include/commands/schemacmds.h31
-rw-r--r--src/include/commands/seclabel.h34
-rw-r--r--src/include/commands/sequence.h69
-rw-r--r--src/include/commands/subscriptioncmds.h29
-rw-r--r--src/include/commands/tablecmds.h97
-rw-r--r--src/include/commands/tablespace.h67
-rw-r--r--src/include/commands/trigger.h282
-rw-r--r--src/include/commands/typecmds.h59
-rw-r--r--src/include/commands/user.h37
-rw-r--r--src/include/commands/vacuum.h293
-rw-r--r--src/include/commands/variable.h38
-rw-r--r--src/include/commands/view.h25
-rw-r--r--src/include/common/archive.h21
-rw-r--r--src/include/common/base64.h19
-rw-r--r--src/include/common/checksum_helper.h74
-rw-r--r--src/include/common/config_info.h21
-rw-r--r--src/include/common/connect.h28
-rw-r--r--src/include/common/controldata_utils.h19
-rw-r--r--src/include/common/fe_memutils.h45
-rw-r--r--src/include/common/file_perm.h56
-rw-r--r--src/include/common/file_utils.h24
-rw-r--r--src/include/common/hashfn.h104
-rw-r--r--src/include/common/int.h437
-rw-r--r--src/include/common/int128.h276
-rw-r--r--src/include/common/ip.h37
-rw-r--r--src/include/common/jsonapi.h169
-rw-r--r--src/include/common/keywords.h33
-rw-r--r--src/include/common/kwlookup.h44
-rw-r--r--src/include/common/link-canary.h17
-rw-r--r--src/include/common/logging.h95
-rw-r--r--src/include/common/md5.h27
-rw-r--r--src/include/common/openssl.h49
-rw-r--r--src/include/common/pg_lzcompress.h93
-rw-r--r--src/include/common/relpath.h90
-rw-r--r--src/include/common/restricted_token.h24
-rw-r--r--src/include/common/saslprep.h30
-rw-r--r--src/include/common/scram-common.h70
-rw-r--r--src/include/common/sha2.h115
-rw-r--r--src/include/common/shortest_dec.h63
-rw-r--r--src/include/common/string.h19
-rw-r--r--src/include/common/unicode_combining_table.h196
-rw-r--r--src/include/common/unicode_norm.h39
-rw-r--r--src/include/common/unicode_norm_table.h8937
-rw-r--r--src/include/common/unicode_normprops_table.h6167
-rw-r--r--src/include/common/username.h15
-rw-r--r--src/include/datatype/timestamp.h197
-rw-r--r--src/include/executor/execExpr.h768
-rw-r--r--src/include/executor/execParallel.h51
-rw-r--r--src/include/executor/execPartition.h156
-rw-r--r--src/include/executor/execdebug.h130
-rw-r--r--src/include/executor/execdesc.h70
-rw-r--r--src/include/executor/executor.h620
-rw-r--r--src/include/executor/functions.h41
-rw-r--r--src/include/executor/hashjoin.h362
-rw-r--r--src/include/executor/instrument.h101
-rw-r--r--src/include/executor/nodeAgg.h333
-rw-r--r--src/include/executor/nodeAppend.h28
-rw-r--r--src/include/executor/nodeBitmapAnd.h24
-rw-r--r--src/include/executor/nodeBitmapHeapscan.h32
-rw-r--r--src/include/executor/nodeBitmapIndexscan.h24
-rw-r--r--src/include/executor/nodeBitmapOr.h24
-rw-r--r--src/include/executor/nodeCtescan.h23
-rw-r--r--src/include/executor/nodeCustom.h42
-rw-r--r--src/include/executor/nodeForeignscan.h34
-rw-r--r--src/include/executor/nodeFunctionscan.h23
-rw-r--r--src/include/executor/nodeGather.h24
-rw-r--r--src/include/executor/nodeGatherMerge.h26
-rw-r--r--src/include/executor/nodeGroup.h23
-rw-r--r--src/include/executor/nodeHash.h79
-rw-r--r--src/include/executor/nodeHashjoin.h34
-rw-r--r--src/include/executor/nodeIncrementalSort.h28
-rw-r--r--src/include/executor/nodeIndexonlyscan.h36
-rw-r--r--src/include/executor/nodeIndexscan.h47
-rw-r--r--src/include/executor/nodeLimit.h23
-rw-r--r--src/include/executor/nodeLockRows.h23
-rw-r--r--src/include/executor/nodeMaterial.h25
-rw-r--r--src/include/executor/nodeMergeAppend.h23
-rw-r--r--src/include/executor/nodeMergejoin.h23
-rw-r--r--src/include/executor/nodeModifyTable.h24
-rw-r--r--src/include/executor/nodeNamedtuplestorescan.h23
-rw-r--r--src/include/executor/nodeNestloop.h23
-rw-r--r--src/include/executor/nodeProjectSet.h23
-rw-r--r--src/include/executor/nodeRecursiveunion.h23
-rw-r--r--src/include/executor/nodeResult.h25
-rw-r--r--src/include/executor/nodeSamplescan.h23
-rw-r--r--src/include/executor/nodeSeqscan.h31
-rw-r--r--src/include/executor/nodeSetOp.h23
-rw-r--r--src/include/executor/nodeSort.h32
-rw-r--r--src/include/executor/nodeSubplan.h33
-rw-r--r--src/include/executor/nodeSubqueryscan.h23
-rw-r--r--src/include/executor/nodeTableFuncscan.h23
-rw-r--r--src/include/executor/nodeTidscan.h23
-rw-r--r--src/include/executor/nodeUnique.h23
-rw-r--r--src/include/executor/nodeValuesscan.h23
-rw-r--r--src/include/executor/nodeWindowAgg.h23
-rw-r--r--src/include/executor/nodeWorktablescan.h23
-rw-r--r--src/include/executor/spi.h175
-rw-r--r--src/include/executor/spi_priv.h105
-rw-r--r--src/include/executor/tablefunc.h67
-rw-r--r--src/include/executor/tqueue.h32
-rw-r--r--src/include/executor/tstoreReceiver.h29
-rw-r--r--src/include/executor/tuptable.h487
-rw-r--r--src/include/fe_utils/archive.h21
-rw-r--r--src/include/fe_utils/cancel.h32
-rw-r--r--src/include/fe_utils/conditional.h100
-rw-r--r--src/include/fe_utils/mbprint.h29
-rw-r--r--src/include/fe_utils/print.h219
-rw-r--r--src/include/fe_utils/psqlscan.h90
-rw-r--r--src/include/fe_utils/psqlscan_int.h149
-rw-r--r--src/include/fe_utils/recovery_gen.h28
-rw-r--r--src/include/fe_utils/simple_list.h70
-rw-r--r--src/include/fe_utils/string_utils.h59
-rw-r--r--src/include/fmgr.h775
-rw-r--r--src/include/foreign/fdwapi.h262
-rw-r--r--src/include/foreign/foreign.h84
-rw-r--r--src/include/funcapi.h348
-rw-r--r--src/include/getaddrinfo.h162
-rw-r--r--src/include/getopt_long.h36
-rw-r--r--src/include/jit/jit.h105
-rw-r--r--src/include/jit/llvmjit.h139
-rw-r--r--src/include/jit/llvmjit_emit.h274
-rw-r--r--src/include/lib/binaryheap.h54
-rw-r--r--src/include/lib/bipartite_match.h46
-rw-r--r--src/include/lib/bloomfilter.h27
-rw-r--r--src/include/lib/dshash.h90
-rw-r--r--src/include/lib/hyperloglog.h68
-rw-r--r--src/include/lib/ilist.h727
-rw-r--r--src/include/lib/integerset.h24
-rw-r--r--src/include/lib/knapsack.h16
-rw-r--r--src/include/lib/pairingheap.h102
-rw-r--r--src/include/lib/qunique.h67
-rw-r--r--src/include/lib/rbtree.h79
-rw-r--r--src/include/lib/simplehash.h1059
-rw-r--r--src/include/lib/stringinfo.h161
-rw-r--r--src/include/libpq/auth.h29
-rw-r--r--src/include/libpq/be-fsstubs.h32
-rw-r--r--src/include/libpq/be-gssapi-common.h26
-rw-r--r--src/include/libpq/crypt.h46
-rw-r--r--src/include/libpq/hba.h140
-rw-r--r--src/include/libpq/ifaddr.h30
-rw-r--r--src/include/libpq/libpq-be.h326
-rw-r--r--src/include/libpq/libpq-fs.h24
-rw-r--r--src/include/libpq/libpq.h133
-rw-r--r--src/include/libpq/pqcomm.h208
-rw-r--r--src/include/libpq/pqformat.h210
-rw-r--r--src/include/libpq/pqmq.h24
-rw-r--r--src/include/libpq/pqsignal.h42
-rw-r--r--src/include/libpq/scram.h37
-rw-r--r--src/include/mb/pg_wchar.h673
-rw-r--r--src/include/mb/stringinfo_mb.h24
-rw-r--r--src/include/miscadmin.h489
-rw-r--r--src/include/nodes/bitmapset.h122
-rw-r--r--src/include/nodes/execnodes.h2523
-rw-r--r--src/include/nodes/extensible.h160
-rw-r--r--src/include/nodes/lockoptions.h61
-rw-r--r--src/include/nodes/makefuncs.h108
-rw-r--r--src/include/nodes/memnodes.h108
-rw-r--r--src/include/nodes/nodeFuncs.h162
-rw-r--r--src/include/nodes/nodes.h842
-rw-r--r--src/include/nodes/params.h170
-rw-r--r--src/include/nodes/parsenodes.h3579
-rw-r--r--src/include/nodes/pathnodes.h2556
-rw-r--r--src/include/nodes/pg_list.h605
-rw-r--r--src/include/nodes/plannodes.h1251
-rw-r--r--src/include/nodes/primnodes.h1541
-rw-r--r--src/include/nodes/print.h34
-rw-r--r--src/include/nodes/readfuncs.h38
-rw-r--r--src/include/nodes/replnodes.h109
-rw-r--r--src/include/nodes/supportnodes.h242
-rw-r--r--src/include/nodes/tidbitmap.h75
-rw-r--r--src/include/nodes/value.h61
-rw-r--r--src/include/optimizer/appendinfo.h35
-rw-r--r--src/include/optimizer/clauses.h60
-rw-r--r--src/include/optimizer/cost.h206
-rw-r--r--src/include/optimizer/geqo.h88
-rw-r--r--src/include/optimizer/geqo_copy.h30
-rw-r--r--src/include/optimizer/geqo_gene.h45
-rw-r--r--src/include/optimizer/geqo_misc.h34
-rw-r--r--src/include/optimizer/geqo_mutation.h30
-rw-r--r--src/include/optimizer/geqo_pool.h40
-rw-r--r--src/include/optimizer/geqo_random.h41
-rw-r--r--src/include/optimizer/geqo_recombination.h89
-rw-r--r--src/include/optimizer/geqo_selection.h33
-rw-r--r--src/include/optimizer/inherit.h27
-rw-r--r--src/include/optimizer/joininfo.h30
-rw-r--r--src/include/optimizer/optimizer.h199
-rw-r--r--src/include/optimizer/orclauses.h21
-rw-r--r--src/include/optimizer/paramassign.h34
-rw-r--r--src/include/optimizer/pathnode.h324
-rw-r--r--src/include/optimizer/paths.h257
-rw-r--r--src/include/optimizer/placeholder.h32
-rw-r--r--src/include/optimizer/plancat.h77
-rw-r--r--src/include/optimizer/planmain.h119
-rw-r--r--src/include/optimizer/planner.h61
-rw-r--r--src/include/optimizer/prep.h46
-rw-r--r--src/include/optimizer/restrictinfo.h57
-rw-r--r--src/include/optimizer/subselect.h40
-rw-r--r--src/include/optimizer/tlist.h57
-rw-r--r--src/include/parser/.gitignore1
-rw-r--r--src/include/parser/analyze.h49
-rw-r--r--src/include/parser/gramparse.h75
-rw-r--r--src/include/parser/kwlist.h477
-rw-r--r--src/include/parser/parse_agg.h68
-rw-r--r--src/include/parser/parse_clause.h54
-rw-r--r--src/include/parser/parse_coerce.h97
-rw-r--r--src/include/parser/parse_collate.h27
-rw-r--r--src/include/parser/parse_cte.h24
-rw-r--r--src/include/parser/parse_enr.h22
-rw-r--r--src/include/parser/parse_expr.h26
-rw-r--r--src/include/parser/parse_func.h73
-rw-r--r--src/include/parser/parse_node.h327
-rw-r--r--src/include/parser/parse_oper.h67
-rw-r--r--src/include/parser/parse_param.h25
-rw-r--r--src/include/parser/parse_relation.h123
-rw-r--r--src/include/parser/parse_target.h46
-rw-r--r--src/include/parser/parse_type.h60
-rw-r--r--src/include/parser/parse_utilcmd.h41
-rw-r--r--src/include/parser/parser.h41
-rw-r--r--src/include/parser/parsetree.h61
-rw-r--r--src/include/parser/scanner.h150
-rw-r--r--src/include/parser/scansup.h30
-rw-r--r--src/include/partitioning/partbounds.h128
-rw-r--r--src/include/partitioning/partdefs.h26
-rw-r--r--src/include/partitioning/partdesc.h41
-rw-r--r--src/include/partitioning/partprune.h80
-rw-r--r--src/include/pg_config.h.in980
-rw-r--r--src/include/pg_config_ext.h.in7
-rw-r--r--src/include/pg_config_manual.h357
-rw-r--r--src/include/pg_getopt.h56
-rw-r--r--src/include/pg_trace.h17
-rw-r--r--src/include/pgstat.h1487
-rw-r--r--src/include/pgtar.h26
-rw-r--r--src/include/pgtime.h84
-rw-r--r--src/include/port.h528
-rw-r--r--src/include/port/aix.h14
-rw-r--r--src/include/port/atomics.h524
-rw-r--r--src/include/port/atomics/arch-arm.h26
-rw-r--r--src/include/port/atomics/arch-hppa.h17
-rw-r--r--src/include/port/atomics/arch-ia64.h29
-rw-r--r--src/include/port/atomics/arch-ppc.h254
-rw-r--r--src/include/port/atomics/arch-x86.h252
-rw-r--r--src/include/port/atomics/fallback.h170
-rw-r--r--src/include/port/atomics/generic-acc.h106
-rw-r--r--src/include/port/atomics/generic-gcc.h286
-rw-r--r--src/include/port/atomics/generic-msvc.h101
-rw-r--r--src/include/port/atomics/generic-sunpro.h106
-rw-r--r--src/include/port/atomics/generic.h401
-rw-r--r--src/include/port/cygwin.h26
-rw-r--r--src/include/port/darwin.h8
-rw-r--r--src/include/port/freebsd.h10
-rw-r--r--src/include/port/hpux.h3
-rw-r--r--src/include/port/linux.h22
-rw-r--r--src/include/port/netbsd.h1
-rw-r--r--src/include/port/openbsd.h1
-rw-r--r--src/include/port/pg_bitutils.h272
-rw-r--r--src/include/port/pg_bswap.h161
-rw-r--r--src/include/port/pg_crc32c.h101
-rw-r--r--src/include/port/solaris.h38
-rw-r--r--src/include/port/win32.h69
-rw-r--r--src/include/port/win32/arpa/inet.h3
-rw-r--r--src/include/port/win32/dlfcn.h1
-rw-r--r--src/include/port/win32/grp.h1
-rw-r--r--src/include/port/win32/netdb.h1
-rw-r--r--src/include/port/win32/netinet/in.h3
-rw-r--r--src/include/port/win32/pwd.h3
-rw-r--r--src/include/port/win32/sys/socket.h33
-rw-r--r--src/include/port/win32/sys/wait.h3
-rw-r--r--src/include/port/win32_msvc/dirent.h23
-rw-r--r--src/include/port/win32_msvc/sys/file.h1
-rw-r--r--src/include/port/win32_msvc/sys/param.h1
-rw-r--r--src/include/port/win32_msvc/sys/time.h1
-rw-r--r--src/include/port/win32_msvc/unistd.h1
-rw-r--r--src/include/port/win32_msvc/utime.h3
-rw-r--r--src/include/port/win32_port.h516
-rw-r--r--src/include/portability/instr_time.h256
-rw-r--r--src/include/portability/mem.h48
-rw-r--r--src/include/postgres.h764
-rw-r--r--src/include/postgres_ext.h74
-rw-r--r--src/include/postgres_fe.h29
-rw-r--r--src/include/postmaster/autovacuum.h83
-rw-r--r--src/include/postmaster/bgworker.h161
-rw-r--r--src/include/postmaster/bgworker_internals.h64
-rw-r--r--src/include/postmaster/bgwriter.h45
-rw-r--r--src/include/postmaster/fork_process.h17
-rw-r--r--src/include/postmaster/interrupt.h32
-rw-r--r--src/include/postmaster/pgarch.h39
-rw-r--r--src/include/postmaster/postmaster.h77
-rw-r--r--src/include/postmaster/startup.h22
-rw-r--r--src/include/postmaster/syslogger.h98
-rw-r--r--src/include/postmaster/walwriter.h21
-rw-r--r--src/include/regex/regcustom.h104
-rw-r--r--src/include/regex/regerrs.h87
-rw-r--r--src/include/regex/regex.h184
-rw-r--r--src/include/regex/regexport.h57
-rw-r--r--src/include/regex/regguts.h482
-rw-r--r--src/include/replication/backup_manifest.h52
-rw-r--r--src/include/replication/basebackup.h39
-rw-r--r--src/include/replication/decode.h20
-rw-r--r--src/include/replication/logical.h120
-rw-r--r--src/include/replication/logicallauncher.h31
-rw-r--r--src/include/replication/logicalproto.h110
-rw-r--r--src/include/replication/logicalrelation.h44
-rw-r--r--src/include/replication/logicalworker.h19
-rw-r--r--src/include/replication/message.h42
-rw-r--r--src/include/replication/origin.h73
-rw-r--r--src/include/replication/output_plugin.h122
-rw-r--r--src/include/replication/pgoutput.h30
-rw-r--r--src/include/replication/reorderbuffer.h468
-rw-r--r--src/include/replication/slot.h219
-rw-r--r--src/include/replication/snapbuild.h90
-rw-r--r--src/include/replication/syncrep.h115
-rw-r--r--src/include/replication/walreceiver.h340
-rw-r--r--src/include/replication/walsender.h74
-rw-r--r--src/include/replication/walsender_private.h127
-rw-r--r--src/include/replication/worker_internal.h95
-rw-r--r--src/include/rewrite/prs2lock.h46
-rw-r--r--src/include/rewrite/rewriteDefine.h44
-rw-r--r--src/include/rewrite/rewriteHandler.h40
-rw-r--r--src/include/rewrite/rewriteManip.h87
-rw-r--r--src/include/rewrite/rewriteRemove.h21
-rw-r--r--src/include/rewrite/rewriteSupport.h26
-rw-r--r--src/include/rewrite/rowsecurity.h49
-rw-r--r--src/include/rusagestub.h34
-rw-r--r--src/include/snowball/header.h67
-rw-r--r--src/include/snowball/libstemmer/api.h33
-rw-r--r--src/include/snowball/libstemmer/header.h60
-rw-r--r--src/include/snowball/libstemmer/stem_ISO_8859_1_danish.h16
-rw-r--r--src/include/snowball/libstemmer/stem_ISO_8859_1_dutch.h16
-rw-r--r--src/include/snowball/libstemmer/stem_ISO_8859_1_english.h16
-rw-r--r--src/include/snowball/libstemmer/stem_ISO_8859_1_finnish.h16
-rw-r--r--src/include/snowball/libstemmer/stem_ISO_8859_1_french.h16
-rw-r--r--src/include/snowball/libstemmer/stem_ISO_8859_1_german.h16
-rw-r--r--src/include/snowball/libstemmer/stem_ISO_8859_1_indonesian.h16
-rw-r--r--src/include/snowball/libstemmer/stem_ISO_8859_1_irish.h16
-rw-r--r--src/include/snowball/libstemmer/stem_ISO_8859_1_italian.h16
-rw-r--r--src/include/snowball/libstemmer/stem_ISO_8859_1_norwegian.h16
-rw-r--r--src/include/snowball/libstemmer/stem_ISO_8859_1_porter.h16
-rw-r--r--src/include/snowball/libstemmer/stem_ISO_8859_1_portuguese.h16
-rw-r--r--src/include/snowball/libstemmer/stem_ISO_8859_1_spanish.h16
-rw-r--r--src/include/snowball/libstemmer/stem_ISO_8859_1_swedish.h16
-rw-r--r--src/include/snowball/libstemmer/stem_ISO_8859_2_hungarian.h16
-rw-r--r--src/include/snowball/libstemmer/stem_ISO_8859_2_romanian.h16
-rw-r--r--src/include/snowball/libstemmer/stem_KOI8_R_russian.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_arabic.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_danish.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_dutch.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_english.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_finnish.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_french.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_german.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_greek.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_hungarian.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_indonesian.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_irish.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_italian.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_lithuanian.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_nepali.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_norwegian.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_porter.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_portuguese.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_romanian.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_russian.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_spanish.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_swedish.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_tamil.h16
-rw-r--r--src/include/snowball/libstemmer/stem_UTF_8_turkish.h16
-rw-r--r--src/include/statistics/extended_stats_internal.h112
-rw-r--r--src/include/statistics/statistics.h125
-rw-r--r--src/include/storage/.gitignore1
-rw-r--r--src/include/storage/backendid.h37
-rw-r--r--src/include/storage/barrier.h45
-rw-r--r--src/include/storage/block.h121
-rw-r--r--src/include/storage/buf.h46
-rw-r--r--src/include/storage/buf_internals.h341
-rw-r--r--src/include/storage/buffile.h54
-rw-r--r--src/include/storage/bufmgr.h292
-rw-r--r--src/include/storage/bufpage.h459
-rw-r--r--src/include/storage/checksum.h24
-rw-r--r--src/include/storage/checksum_impl.h215
-rw-r--r--src/include/storage/condition_variable.h62
-rw-r--r--src/include/storage/copydir.h19
-rw-r--r--src/include/storage/dsm.h61
-rw-r--r--src/include/storage/dsm_impl.h75
-rw-r--r--src/include/storage/fd.h168
-rw-r--r--src/include/storage/freespace.h39
-rw-r--r--src/include/storage/fsm_internals.h72
-rw-r--r--src/include/storage/indexfsm.h26
-rw-r--r--src/include/storage/ipc.h81
-rw-r--r--src/include/storage/item.h19
-rw-r--r--src/include/storage/itemid.h184
-rw-r--r--src/include/storage/itemptr.h206
-rw-r--r--src/include/storage/large_object.h100
-rw-r--r--src/include/storage/latch.h190
-rw-r--r--src/include/storage/lmgr.h114
-rw-r--r--src/include/storage/lock.h612
-rw-r--r--src/include/storage/lockdefs.h59
-rw-r--r--src/include/storage/lwlock.h232
-rw-r--r--src/include/storage/md.h52
-rw-r--r--src/include/storage/off.h57
-rw-r--r--src/include/storage/pg_sema.h61
-rw-r--r--src/include/storage/pg_shmem.h90
-rw-r--r--src/include/storage/pmsignal.h94
-rw-r--r--src/include/storage/predicate.h87
-rw-r--r--src/include/storage/predicate_internals.h493
-rw-r--r--src/include/storage/proc.h333
-rw-r--r--src/include/storage/procarray.h130
-rw-r--r--src/include/storage/proclist.h219
-rw-r--r--src/include/storage/proclist_types.h51
-rw-r--r--src/include/storage/procsignal.h75
-rw-r--r--src/include/storage/reinit.h28
-rw-r--r--src/include/storage/relfilenode.h99
-rw-r--r--src/include/storage/s_lock.h1047
-rw-r--r--src/include/storage/sharedfileset.h45
-rw-r--r--src/include/storage/shm_mq.h85
-rw-r--r--src/include/storage/shm_toc.h58
-rw-r--r--src/include/storage/shmem.h81
-rw-r--r--src/include/storage/sinval.h153
-rw-r--r--src/include/storage/sinvaladt.h43
-rw-r--r--src/include/storage/smgr.h109
-rw-r--r--src/include/storage/spin.h77
-rw-r--r--src/include/storage/standby.h91
-rw-r--r--src/include/storage/standbydefs.h74
-rw-r--r--src/include/storage/sync.h62
-rw-r--r--src/include/tcop/cmdtag.h58
-rw-r--r--src/include/tcop/cmdtaglist.h217
-rw-r--r--src/include/tcop/deparse_utility.h108
-rw-r--r--src/include/tcop/dest.h149
-rw-r--r--src/include/tcop/fastpath.h21
-rw-r--r--src/include/tcop/pquery.h51
-rw-r--r--src/include/tcop/tcopprot.h89
-rw-r--r--src/include/tcop/utility.h108
-rw-r--r--src/include/tsearch/dicts/regis.h49
-rw-r--r--src/include/tsearch/dicts/spell.h247
-rw-r--r--src/include/tsearch/ts_cache.h98
-rw-r--r--src/include/tsearch/ts_locale.h62
-rw-r--r--src/include/tsearch/ts_public.h132
-rw-r--r--src/include/tsearch/ts_type.h242
-rw-r--r--src/include/tsearch/ts_utils.h266
-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
-rw-r--r--src/include/windowapi.h64
740 files changed, 131799 insertions, 0 deletions
diff --git a/src/include/.gitignore b/src/include/.gitignore
new file mode 100644
index 0000000..51819fb
--- /dev/null
+++ b/src/include/.gitignore
@@ -0,0 +1,5 @@
+/stamp-h
+/stamp-ext-h
+/pg_config.h
+/pg_config_ext.h
+/pg_config_os.h
diff --git a/src/include/Makefile b/src/include/Makefile
new file mode 100644
index 0000000..c557375
--- /dev/null
+++ b/src/include/Makefile
@@ -0,0 +1,85 @@
+#-------------------------------------------------------------------------
+#
+# Makefile for src/include
+#
+# 'make install' installs whole contents of src/include.
+#
+# src/include/Makefile
+#
+#-------------------------------------------------------------------------
+
+subdir = src/include
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+
+
+all: pg_config.h pg_config_ext.h pg_config_os.h
+
+
+# Subdirectories containing installable headers
+SUBDIRS = access bootstrap catalog commands common datatype \
+ executor fe_utils foreign jit \
+ lib libpq mb nodes optimizer parser partitioning postmaster \
+ regex replication rewrite \
+ statistics storage tcop snowball snowball/libstemmer tsearch \
+ tsearch/dicts utils port port/atomics port/win32 port/win32_msvc \
+ port/win32_msvc/sys port/win32/arpa port/win32/netinet \
+ port/win32/sys portability
+
+# Install all headers
+install: all installdirs
+# These headers are needed by the public headers of the interfaces.
+ $(INSTALL_DATA) $(srcdir)/postgres_ext.h '$(DESTDIR)$(includedir)'
+ $(INSTALL_DATA) $(srcdir)/libpq/libpq-fs.h '$(DESTDIR)$(includedir)/libpq'
+ $(INSTALL_DATA) pg_config.h '$(DESTDIR)$(includedir)'
+ $(INSTALL_DATA) pg_config_ext.h '$(DESTDIR)$(includedir)'
+ $(INSTALL_DATA) pg_config_os.h '$(DESTDIR)$(includedir)'
+ $(INSTALL_DATA) $(srcdir)/pg_config_manual.h '$(DESTDIR)$(includedir)'
+# These headers are needed by the not-so-public headers of the interfaces.
+ $(INSTALL_DATA) $(srcdir)/c.h '$(DESTDIR)$(includedir_internal)'
+ $(INSTALL_DATA) $(srcdir)/port.h '$(DESTDIR)$(includedir_internal)'
+ $(INSTALL_DATA) $(srcdir)/postgres_fe.h '$(DESTDIR)$(includedir_internal)'
+ $(INSTALL_DATA) $(srcdir)/libpq/pqcomm.h '$(DESTDIR)$(includedir_internal)/libpq'
+# These headers are needed for server-side development
+ $(INSTALL_DATA) pg_config.h '$(DESTDIR)$(includedir_server)'
+ $(INSTALL_DATA) pg_config_ext.h '$(DESTDIR)$(includedir_server)'
+ $(INSTALL_DATA) pg_config_os.h '$(DESTDIR)$(includedir_server)'
+ $(INSTALL_DATA) utils/errcodes.h '$(DESTDIR)$(includedir_server)/utils'
+ $(INSTALL_DATA) utils/fmgroids.h '$(DESTDIR)$(includedir_server)/utils'
+ $(INSTALL_DATA) utils/fmgrprotos.h '$(DESTDIR)$(includedir_server)/utils'
+# We don't use INSTALL_DATA for performance reasons --- there are a lot of files
+# (in fact, we have to take some pains to avoid overlength shell commands here)
+ cp $(srcdir)/*.h '$(DESTDIR)$(includedir_server)'/
+ for dir in $(SUBDIRS); do \
+ cp $(srcdir)/$$dir/*.h '$(DESTDIR)$(includedir_server)'/$$dir/ || exit; \
+ done
+ifeq ($(vpath_build),yes)
+ for file in catalog/schemapg.h catalog/pg_*_d.h parser/gram.h storage/lwlocknames.h utils/probes.h; do \
+ cp $$file '$(DESTDIR)$(includedir_server)'/$$file || exit; \
+ done
+endif
+ cd '$(DESTDIR)$(includedir_server)' && chmod $(INSTALL_DATA_MODE) *.h
+ for dir in $(SUBDIRS); do \
+ cd '$(DESTDIR)$(includedir_server)'/$$dir || exit; \
+ chmod $(INSTALL_DATA_MODE) *.h || exit; \
+ done
+
+installdirs:
+ $(MKDIR_P) '$(DESTDIR)$(includedir)/libpq' '$(DESTDIR)$(includedir_internal)/libpq'
+ $(MKDIR_P) $(addprefix '$(DESTDIR)$(includedir_server)'/, $(SUBDIRS))
+
+
+uninstall:
+ rm -f $(addprefix '$(DESTDIR)$(includedir)'/, pg_config.h pg_config_ext.h pg_config_os.h pg_config_manual.h postgres_ext.h libpq/libpq-fs.h)
+ rm -f $(addprefix '$(DESTDIR)$(includedir_internal)'/, c.h port.h postgres_fe.h libpq/pqcomm.h)
+# heuristic...
+ rm -rf $(addprefix '$(DESTDIR)$(includedir_server)'/, $(SUBDIRS) *.h)
+
+
+clean:
+ rm -f utils/fmgroids.h utils/fmgrprotos.h utils/errcodes.h utils/header-stamp
+ rm -f parser/gram.h storage/lwlocknames.h utils/probes.h
+ rm -f catalog/schemapg.h catalog/pg_*_d.h catalog/header-stamp
+
+distclean maintainer-clean: clean
+ rm -f pg_config.h pg_config_ext.h pg_config_os.h stamp-h stamp-ext-h
diff --git a/src/include/access/amapi.h b/src/include/access/amapi.h
new file mode 100644
index 0000000..4325faa
--- /dev/null
+++ b/src/include/access/amapi.h
@@ -0,0 +1,246 @@
+/*-------------------------------------------------------------------------
+ *
+ * amapi.h
+ * API for Postgres index access methods.
+ *
+ * Copyright (c) 2015-2020, PostgreSQL Global Development Group
+ *
+ * src/include/access/amapi.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef AMAPI_H
+#define AMAPI_H
+
+#include "access/genam.h"
+
+/*
+ * We don't wish to include planner header files here, since most of an index
+ * AM's implementation isn't concerned with those data structures. To allow
+ * declaring amcostestimate_function here, use forward struct references.
+ */
+struct PlannerInfo;
+struct IndexPath;
+
+/* Likewise, this file shouldn't depend on execnodes.h. */
+struct IndexInfo;
+
+
+/*
+ * Properties for amproperty API. This list covers properties known to the
+ * core code, but an index AM can define its own properties, by matching the
+ * string property name.
+ */
+typedef enum IndexAMProperty
+{
+ AMPROP_UNKNOWN = 0, /* anything not known to core code */
+ AMPROP_ASC, /* column properties */
+ AMPROP_DESC,
+ AMPROP_NULLS_FIRST,
+ AMPROP_NULLS_LAST,
+ AMPROP_ORDERABLE,
+ AMPROP_DISTANCE_ORDERABLE,
+ AMPROP_RETURNABLE,
+ AMPROP_SEARCH_ARRAY,
+ AMPROP_SEARCH_NULLS,
+ AMPROP_CLUSTERABLE, /* index properties */
+ AMPROP_INDEX_SCAN,
+ AMPROP_BITMAP_SCAN,
+ AMPROP_BACKWARD_SCAN,
+ AMPROP_CAN_ORDER, /* AM properties */
+ AMPROP_CAN_UNIQUE,
+ AMPROP_CAN_MULTI_COL,
+ AMPROP_CAN_EXCLUDE,
+ AMPROP_CAN_INCLUDE
+} IndexAMProperty;
+
+
+/*
+ * Callback function signatures --- see indexam.sgml for more info.
+ */
+
+/* build new index */
+typedef IndexBuildResult *(*ambuild_function) (Relation heapRelation,
+ Relation indexRelation,
+ struct IndexInfo *indexInfo);
+
+/* build empty index */
+typedef void (*ambuildempty_function) (Relation indexRelation);
+
+/* insert this tuple */
+typedef bool (*aminsert_function) (Relation indexRelation,
+ Datum *values,
+ bool *isnull,
+ ItemPointer heap_tid,
+ Relation heapRelation,
+ IndexUniqueCheck checkUnique,
+ struct IndexInfo *indexInfo);
+
+/* bulk delete */
+typedef IndexBulkDeleteResult *(*ambulkdelete_function) (IndexVacuumInfo *info,
+ IndexBulkDeleteResult *stats,
+ IndexBulkDeleteCallback callback,
+ void *callback_state);
+
+/* post-VACUUM cleanup */
+typedef IndexBulkDeleteResult *(*amvacuumcleanup_function) (IndexVacuumInfo *info,
+ IndexBulkDeleteResult *stats);
+
+/* can indexscan return IndexTuples? */
+typedef bool (*amcanreturn_function) (Relation indexRelation, int attno);
+
+/* estimate cost of an indexscan */
+typedef void (*amcostestimate_function) (struct PlannerInfo *root,
+ struct IndexPath *path,
+ double loop_count,
+ Cost *indexStartupCost,
+ Cost *indexTotalCost,
+ Selectivity *indexSelectivity,
+ double *indexCorrelation,
+ double *indexPages);
+
+/* parse index reloptions */
+typedef bytea *(*amoptions_function) (Datum reloptions,
+ bool validate);
+
+/* report AM, index, or index column property */
+typedef bool (*amproperty_function) (Oid index_oid, int attno,
+ IndexAMProperty prop, const char *propname,
+ bool *res, bool *isnull);
+
+/* name of phase as used in progress reporting */
+typedef char *(*ambuildphasename_function) (int64 phasenum);
+
+/* validate definition of an opclass for this AM */
+typedef bool (*amvalidate_function) (Oid opclassoid);
+
+/* prepare for index scan */
+typedef IndexScanDesc (*ambeginscan_function) (Relation indexRelation,
+ int nkeys,
+ int norderbys);
+
+/* (re)start index scan */
+typedef void (*amrescan_function) (IndexScanDesc scan,
+ ScanKey keys,
+ int nkeys,
+ ScanKey orderbys,
+ int norderbys);
+
+/* next valid tuple */
+typedef bool (*amgettuple_function) (IndexScanDesc scan,
+ ScanDirection direction);
+
+/* fetch all valid tuples */
+typedef int64 (*amgetbitmap_function) (IndexScanDesc scan,
+ TIDBitmap *tbm);
+
+/* end index scan */
+typedef void (*amendscan_function) (IndexScanDesc scan);
+
+/* mark current scan position */
+typedef void (*ammarkpos_function) (IndexScanDesc scan);
+
+/* restore marked scan position */
+typedef void (*amrestrpos_function) (IndexScanDesc scan);
+
+/*
+ * Callback function signatures - for parallel index scans.
+ */
+
+/* estimate size of parallel scan descriptor */
+typedef Size (*amestimateparallelscan_function) (void);
+
+/* prepare for parallel index scan */
+typedef void (*aminitparallelscan_function) (void *target);
+
+/* (re)start parallel index scan */
+typedef void (*amparallelrescan_function) (IndexScanDesc scan);
+
+/*
+ * API struct for an index AM. Note this must be stored in a single palloc'd
+ * chunk of memory.
+ */
+typedef struct IndexAmRoutine
+{
+ NodeTag type;
+
+ /*
+ * Total number of strategies (operators) by which we can traverse/search
+ * this AM. Zero if AM does not have a fixed set of strategy assignments.
+ */
+ uint16 amstrategies;
+ /* total number of support functions that this AM uses */
+ uint16 amsupport;
+ /* opclass options support function number or 0 */
+ uint16 amoptsprocnum;
+ /* does AM support ORDER BY indexed column's value? */
+ bool amcanorder;
+ /* does AM support ORDER BY result of an operator on indexed column? */
+ bool amcanorderbyop;
+ /* does AM support backward scanning? */
+ bool amcanbackward;
+ /* does AM support UNIQUE indexes? */
+ bool amcanunique;
+ /* does AM support multi-column indexes? */
+ bool amcanmulticol;
+ /* does AM require scans to have a constraint on the first index column? */
+ bool amoptionalkey;
+ /* does AM handle ScalarArrayOpExpr quals? */
+ bool amsearcharray;
+ /* does AM handle IS NULL/IS NOT NULL quals? */
+ bool amsearchnulls;
+ /* can index storage data type differ from column data type? */
+ bool amstorage;
+ /* can an index of this type be clustered on? */
+ bool amclusterable;
+ /* does AM handle predicate locks? */
+ bool ampredlocks;
+ /* does AM support parallel scan? */
+ bool amcanparallel;
+ /* does AM support columns included with clause INCLUDE? */
+ bool amcaninclude;
+ /* does AM use maintenance_work_mem? */
+ bool amusemaintenanceworkmem;
+ /* OR of parallel vacuum flags. See vacuum.h for flags. */
+ uint8 amparallelvacuumoptions;
+ /* type of data stored in index, or InvalidOid if variable */
+ Oid amkeytype;
+
+ /*
+ * If you add new properties to either the above or the below lists, then
+ * they should also (usually) be exposed via the property API (see
+ * IndexAMProperty at the top of the file, and utils/adt/amutils.c).
+ */
+
+ /* interface functions */
+ ambuild_function ambuild;
+ ambuildempty_function ambuildempty;
+ aminsert_function aminsert;
+ ambulkdelete_function ambulkdelete;
+ amvacuumcleanup_function amvacuumcleanup;
+ amcanreturn_function amcanreturn; /* can be NULL */
+ amcostestimate_function amcostestimate;
+ amoptions_function amoptions;
+ amproperty_function amproperty; /* can be NULL */
+ ambuildphasename_function ambuildphasename; /* can be NULL */
+ amvalidate_function amvalidate;
+ ambeginscan_function ambeginscan;
+ amrescan_function amrescan;
+ amgettuple_function amgettuple; /* can be NULL */
+ amgetbitmap_function amgetbitmap; /* can be NULL */
+ amendscan_function amendscan;
+ ammarkpos_function ammarkpos; /* can be NULL */
+ amrestrpos_function amrestrpos; /* can be NULL */
+
+ /* interface functions to support parallel index scans */
+ amestimateparallelscan_function amestimateparallelscan; /* can be NULL */
+ aminitparallelscan_function aminitparallelscan; /* can be NULL */
+ amparallelrescan_function amparallelrescan; /* can be NULL */
+} IndexAmRoutine;
+
+
+/* Functions in access/index/amapi.c */
+extern IndexAmRoutine *GetIndexAmRoutine(Oid amhandler);
+extern IndexAmRoutine *GetIndexAmRoutineByAmId(Oid amoid, bool noerror);
+
+#endif /* AMAPI_H */
diff --git a/src/include/access/amvalidate.h b/src/include/access/amvalidate.h
new file mode 100644
index 0000000..f3a0e52
--- /dev/null
+++ b/src/include/access/amvalidate.h
@@ -0,0 +1,37 @@
+/*-------------------------------------------------------------------------
+ *
+ * amvalidate.h
+ * Support routines for index access methods' amvalidate functions.
+ *
+ * Copyright (c) 2016-2020, PostgreSQL Global Development Group
+ *
+ * src/include/access/amvalidate.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef AMVALIDATE_H
+#define AMVALIDATE_H
+
+#include "utils/catcache.h"
+
+
+/* Struct returned (in a list) by identify_opfamily_groups() */
+typedef struct OpFamilyOpFuncGroup
+{
+ Oid lefttype; /* amoplefttype/amproclefttype */
+ Oid righttype; /* amoprighttype/amprocrighttype */
+ uint64 operatorset; /* bitmask of operators with these types */
+ uint64 functionset; /* bitmask of support funcs with these types */
+} OpFamilyOpFuncGroup;
+
+
+/* Functions in access/index/amvalidate.c */
+extern List *identify_opfamily_groups(CatCList *oprlist, CatCList *proclist);
+extern bool check_amproc_signature(Oid funcid, Oid restype, bool exact,
+ int minargs, int maxargs,...);
+extern bool check_amoptsproc_signature(Oid funcid);
+extern bool check_amop_signature(Oid opno, Oid restype,
+ Oid lefttype, Oid righttype);
+extern bool opfamily_can_sort_type(Oid opfamilyoid, Oid datatypeoid);
+
+#endif /* AMVALIDATE_H */
diff --git a/src/include/access/attmap.h b/src/include/access/attmap.h
new file mode 100644
index 0000000..64bc715
--- /dev/null
+++ b/src/include/access/attmap.h
@@ -0,0 +1,52 @@
+/*-------------------------------------------------------------------------
+ *
+ * attmap.h
+ * Definitions for PostgreSQL attribute mappings
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/attmap.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ATTMAP_H
+#define ATTMAP_H
+
+#include "access/attnum.h"
+#include "access/tupdesc.h"
+
+/*
+ * Attribute mapping structure
+ *
+ * This maps attribute numbers between a pair of relations, designated
+ * 'input' and 'output' (most typically inheritance parent and child
+ * relations), whose common columns may have different attribute numbers.
+ * Such difference may arise due to the columns being ordered differently
+ * in the two relations or the two relations having dropped columns at
+ * different positions.
+ *
+ * 'maplen' is set to the number of attributes of the 'output' relation,
+ * taking into account any of its dropped attributes, with the corresponding
+ * elements of the 'attnums' array set to 0.
+ */
+typedef struct AttrMap
+{
+ AttrNumber *attnums;
+ int maplen;
+} AttrMap;
+
+extern AttrMap *make_attrmap(int maplen);
+extern void free_attrmap(AttrMap *map);
+
+/* Conversion routines to build mappings */
+extern AttrMap *build_attrmap_by_name(TupleDesc indesc,
+ TupleDesc outdesc);
+extern AttrMap *build_attrmap_by_name_if_req(TupleDesc indesc,
+ TupleDesc outdesc);
+extern AttrMap *build_attrmap_by_position(TupleDesc indesc,
+ TupleDesc outdesc,
+ const char *msg);
+
+#endif /* ATTMAP_H */
diff --git a/src/include/access/attnum.h b/src/include/access/attnum.h
new file mode 100644
index 0000000..87b208e
--- /dev/null
+++ b/src/include/access/attnum.h
@@ -0,0 +1,64 @@
+/*-------------------------------------------------------------------------
+ *
+ * attnum.h
+ * POSTGRES attribute number definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/attnum.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ATTNUM_H
+#define ATTNUM_H
+
+
+/*
+ * user defined attribute numbers start at 1. -ay 2/95
+ */
+typedef int16 AttrNumber;
+
+#define InvalidAttrNumber 0
+#define MaxAttrNumber 32767
+
+/* ----------------
+ * support macros
+ * ----------------
+ */
+/*
+ * AttributeNumberIsValid
+ * True iff the attribute number is valid.
+ */
+#define AttributeNumberIsValid(attributeNumber) \
+ ((bool) ((attributeNumber) != InvalidAttrNumber))
+
+/*
+ * AttrNumberIsForUserDefinedAttr
+ * True iff the attribute number corresponds to an user defined attribute.
+ */
+#define AttrNumberIsForUserDefinedAttr(attributeNumber) \
+ ((bool) ((attributeNumber) > 0))
+
+/*
+ * AttrNumberGetAttrOffset
+ * Returns the attribute offset for an attribute number.
+ *
+ * Note:
+ * Assumes the attribute number is for a user defined attribute.
+ */
+#define AttrNumberGetAttrOffset(attNum) \
+( \
+ AssertMacro(AttrNumberIsForUserDefinedAttr(attNum)), \
+ ((attNum) - 1) \
+)
+
+/*
+ * AttrOffsetGetAttrNumber
+ * Returns the attribute number for an attribute offset.
+ */
+#define AttrOffsetGetAttrNumber(attributeOffset) \
+ ((AttrNumber) (1 + (attributeOffset)))
+
+#endif /* ATTNUM_H */
diff --git a/src/include/access/brin.h b/src/include/access/brin.h
new file mode 100644
index 0000000..0987878
--- /dev/null
+++ b/src/include/access/brin.h
@@ -0,0 +1,55 @@
+/*
+ * AM-callable functions for BRIN indexes
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/access/brin.h
+ */
+#ifndef BRIN_H
+#define BRIN_H
+
+#include "nodes/execnodes.h"
+#include "utils/relcache.h"
+
+
+/*
+ * Storage type for BRIN's reloptions
+ */
+typedef struct BrinOptions
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ BlockNumber pagesPerRange;
+ bool autosummarize;
+} BrinOptions;
+
+
+/*
+ * BrinStatsData represents stats data for planner use
+ */
+typedef struct BrinStatsData
+{
+ BlockNumber pagesPerRange;
+ BlockNumber revmapNumPages;
+} BrinStatsData;
+
+
+#define BRIN_DEFAULT_PAGES_PER_RANGE 128
+#define BrinGetPagesPerRange(relation) \
+ (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \
+ relation->rd_rel->relam == BRIN_AM_OID), \
+ (relation)->rd_options ? \
+ ((BrinOptions *) (relation)->rd_options)->pagesPerRange : \
+ BRIN_DEFAULT_PAGES_PER_RANGE)
+#define BrinGetAutoSummarize(relation) \
+ (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \
+ relation->rd_rel->relam == BRIN_AM_OID), \
+ (relation)->rd_options ? \
+ ((BrinOptions *) (relation)->rd_options)->autosummarize : \
+ false)
+
+
+extern void brinGetStats(Relation index, BrinStatsData *stats);
+
+#endif /* BRIN_H */
diff --git a/src/include/access/brin_internal.h b/src/include/access/brin_internal.h
new file mode 100644
index 0000000..9ffc910
--- /dev/null
+++ b/src/include/access/brin_internal.h
@@ -0,0 +1,111 @@
+/*
+ * brin_internal.h
+ * internal declarations for BRIN indexes
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/access/brin_internal.h
+ */
+#ifndef BRIN_INTERNAL_H
+#define BRIN_INTERNAL_H
+
+#include "access/amapi.h"
+#include "storage/bufpage.h"
+#include "utils/typcache.h"
+
+
+/*
+ * A BrinDesc is a struct designed to enable decoding a BRIN tuple from the
+ * on-disk format to an in-memory tuple and vice-versa.
+ */
+
+/* struct returned by "OpcInfo" amproc */
+typedef struct BrinOpcInfo
+{
+ /* Number of columns stored in an index column of this opclass */
+ uint16 oi_nstored;
+
+ /* Opaque pointer for the opclass' private use */
+ void *oi_opaque;
+
+ /* Type cache entries of the stored columns */
+ TypeCacheEntry *oi_typcache[FLEXIBLE_ARRAY_MEMBER];
+} BrinOpcInfo;
+
+/* the size of a BrinOpcInfo for the given number of columns */
+#define SizeofBrinOpcInfo(ncols) \
+ (offsetof(BrinOpcInfo, oi_typcache) + sizeof(TypeCacheEntry *) * ncols)
+
+typedef struct BrinDesc
+{
+ /* Containing memory context */
+ MemoryContext bd_context;
+
+ /* the index relation itself */
+ Relation bd_index;
+
+ /* tuple descriptor of the index relation */
+ TupleDesc bd_tupdesc;
+
+ /* cached copy for on-disk tuples; generated at first use */
+ TupleDesc bd_disktdesc;
+
+ /* total number of Datum entries that are stored on-disk for all columns */
+ int bd_totalstored;
+
+ /* per-column info; bd_tupdesc->natts entries long */
+ BrinOpcInfo *bd_info[FLEXIBLE_ARRAY_MEMBER];
+} BrinDesc;
+
+/*
+ * Globally-known function support numbers for BRIN indexes. Individual
+ * opclasses can define more function support numbers, which must fall into
+ * BRIN_FIRST_OPTIONAL_PROCNUM .. BRIN_LAST_OPTIONAL_PROCNUM.
+ */
+#define BRIN_PROCNUM_OPCINFO 1
+#define BRIN_PROCNUM_ADDVALUE 2
+#define BRIN_PROCNUM_CONSISTENT 3
+#define BRIN_PROCNUM_UNION 4
+#define BRIN_MANDATORY_NPROCS 4
+#define BRIN_PROCNUM_OPTIONS 5 /* optional */
+/* procedure numbers up to 10 are reserved for BRIN future expansion */
+#define BRIN_FIRST_OPTIONAL_PROCNUM 11
+#define BRIN_LAST_OPTIONAL_PROCNUM 15
+
+#undef BRIN_DEBUG
+
+#ifdef BRIN_DEBUG
+#define BRIN_elog(args) elog args
+#else
+#define BRIN_elog(args) ((void) 0)
+#endif
+
+/* brin.c */
+extern BrinDesc *brin_build_desc(Relation rel);
+extern void brin_free_desc(BrinDesc *bdesc);
+extern IndexBuildResult *brinbuild(Relation heap, Relation index,
+ struct IndexInfo *indexInfo);
+extern void brinbuildempty(Relation index);
+extern bool brininsert(Relation idxRel, Datum *values, bool *nulls,
+ ItemPointer heaptid, Relation heapRel,
+ IndexUniqueCheck checkUnique,
+ struct IndexInfo *indexInfo);
+extern IndexScanDesc brinbeginscan(Relation r, int nkeys, int norderbys);
+extern int64 bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm);
+extern void brinrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
+ ScanKey orderbys, int norderbys);
+extern void brinendscan(IndexScanDesc scan);
+extern IndexBulkDeleteResult *brinbulkdelete(IndexVacuumInfo *info,
+ IndexBulkDeleteResult *stats,
+ IndexBulkDeleteCallback callback,
+ void *callback_state);
+extern IndexBulkDeleteResult *brinvacuumcleanup(IndexVacuumInfo *info,
+ IndexBulkDeleteResult *stats);
+extern bytea *brinoptions(Datum reloptions, bool validate);
+
+/* brin_validate.c */
+extern bool brinvalidate(Oid opclassoid);
+
+#endif /* BRIN_INTERNAL_H */
diff --git a/src/include/access/brin_page.h b/src/include/access/brin_page.h
new file mode 100644
index 0000000..77c2ac7
--- /dev/null
+++ b/src/include/access/brin_page.h
@@ -0,0 +1,96 @@
+/*
+ * brin_page.h
+ * Prototypes and definitions for BRIN page layouts
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/access/brin_page.h
+ *
+ * NOTES
+ *
+ * These structs should really be private to specific BRIN files, but it's
+ * useful to have them here so that they can be used by pageinspect and similar
+ * tools.
+ */
+#ifndef BRIN_PAGE_H
+#define BRIN_PAGE_H
+
+#include "storage/block.h"
+#include "storage/itemptr.h"
+
+/*
+ * Special area of BRIN pages.
+ *
+ * We define it in this odd way so that it always occupies the last
+ * MAXALIGN-sized element of each page.
+ */
+typedef struct BrinSpecialSpace
+{
+ uint16 vector[MAXALIGN(1) / sizeof(uint16)];
+} BrinSpecialSpace;
+
+/*
+ * Make the page type be the last half-word in the page, for consumption by
+ * pg_filedump and similar utilities. We don't really care much about the
+ * position of the "flags" half-word, but it's simpler to apply a consistent
+ * rule to both.
+ *
+ * See comments above GinPageOpaqueData.
+ */
+#define BrinPageType(page) \
+ (((BrinSpecialSpace *) \
+ PageGetSpecialPointer(page))->vector[MAXALIGN(1) / sizeof(uint16) - 1])
+
+#define BrinPageFlags(page) \
+ (((BrinSpecialSpace *) \
+ PageGetSpecialPointer(page))->vector[MAXALIGN(1) / sizeof(uint16) - 2])
+
+/* special space on all BRIN pages stores a "type" identifier */
+#define BRIN_PAGETYPE_META 0xF091
+#define BRIN_PAGETYPE_REVMAP 0xF092
+#define BRIN_PAGETYPE_REGULAR 0xF093
+
+#define BRIN_IS_META_PAGE(page) (BrinPageType(page) == BRIN_PAGETYPE_META)
+#define BRIN_IS_REVMAP_PAGE(page) (BrinPageType(page) == BRIN_PAGETYPE_REVMAP)
+#define BRIN_IS_REGULAR_PAGE(page) (BrinPageType(page) == BRIN_PAGETYPE_REGULAR)
+
+/* flags for BrinSpecialSpace */
+#define BRIN_EVACUATE_PAGE (1 << 0)
+
+
+/* Metapage definitions */
+typedef struct BrinMetaPageData
+{
+ uint32 brinMagic;
+ uint32 brinVersion;
+ BlockNumber pagesPerRange;
+ BlockNumber lastRevmapPage;
+} BrinMetaPageData;
+
+#define BRIN_CURRENT_VERSION 1
+#define BRIN_META_MAGIC 0xA8109CFA
+
+#define BRIN_METAPAGE_BLKNO 0
+
+/* Definitions for revmap pages */
+typedef struct RevmapContents
+{
+ /*
+ * This array will fill all available space on the page. It should be
+ * declared [FLEXIBLE_ARRAY_MEMBER], but for some reason you can't do that
+ * in an otherwise-empty struct.
+ */
+ ItemPointerData rm_tids[1];
+} RevmapContents;
+
+#define REVMAP_CONTENT_SIZE \
+ (BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - \
+ offsetof(RevmapContents, rm_tids) - \
+ MAXALIGN(sizeof(BrinSpecialSpace)))
+/* max num of items in the array */
+#define REVMAP_PAGE_MAXITEMS \
+ (REVMAP_CONTENT_SIZE / sizeof(ItemPointerData))
+
+#endif /* BRIN_PAGE_H */
diff --git a/src/include/access/brin_pageops.h b/src/include/access/brin_pageops.h
new file mode 100644
index 0000000..f202988
--- /dev/null
+++ b/src/include/access/brin_pageops.h
@@ -0,0 +1,38 @@
+/*
+ * brin_pageops.h
+ * Prototypes for operating on BRIN pages.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/access/brin_pageops.h
+ */
+#ifndef BRIN_PAGEOPS_H
+#define BRIN_PAGEOPS_H
+
+#include "access/brin_revmap.h"
+
+extern bool brin_doupdate(Relation idxrel, BlockNumber pagesPerRange,
+ BrinRevmap *revmap, BlockNumber heapBlk,
+ Buffer oldbuf, OffsetNumber oldoff,
+ const BrinTuple *origtup, Size origsz,
+ const BrinTuple *newtup, Size newsz,
+ bool samepage);
+extern bool brin_can_do_samepage_update(Buffer buffer, Size origsz,
+ Size newsz);
+extern OffsetNumber brin_doinsert(Relation idxrel, BlockNumber pagesPerRange,
+ BrinRevmap *revmap, Buffer *buffer, BlockNumber heapBlk,
+ BrinTuple *tup, Size itemsz);
+
+extern void brin_page_init(Page page, uint16 type);
+extern void brin_metapage_init(Page page, BlockNumber pagesPerRange,
+ uint16 version);
+
+extern bool brin_start_evacuating_page(Relation idxRel, Buffer buf);
+extern void brin_evacuate_page(Relation idxRel, BlockNumber pagesPerRange,
+ BrinRevmap *revmap, Buffer buf);
+
+extern void brin_page_cleanup(Relation idxrel, Buffer buf);
+
+#endif /* BRIN_PAGEOPS_H */
diff --git a/src/include/access/brin_revmap.h b/src/include/access/brin_revmap.h
new file mode 100644
index 0000000..4a31d43
--- /dev/null
+++ b/src/include/access/brin_revmap.h
@@ -0,0 +1,41 @@
+/*
+ * brin_revmap.h
+ * Prototypes for BRIN reverse range maps
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/access/brin_revmap.h
+ */
+
+#ifndef BRIN_REVMAP_H
+#define BRIN_REVMAP_H
+
+#include "access/brin_tuple.h"
+#include "storage/block.h"
+#include "storage/buf.h"
+#include "storage/itemptr.h"
+#include "storage/off.h"
+#include "utils/relcache.h"
+#include "utils/snapshot.h"
+
+/* struct definition lives in brin_revmap.c */
+typedef struct BrinRevmap BrinRevmap;
+
+extern BrinRevmap *brinRevmapInitialize(Relation idxrel,
+ BlockNumber *pagesPerRange, Snapshot snapshot);
+extern void brinRevmapTerminate(BrinRevmap *revmap);
+
+extern void brinRevmapExtend(BrinRevmap *revmap,
+ BlockNumber heapBlk);
+extern Buffer brinLockRevmapPageForUpdate(BrinRevmap *revmap,
+ BlockNumber heapBlk);
+extern void brinSetHeapBlockItemptr(Buffer buf, BlockNumber pagesPerRange,
+ BlockNumber heapBlk, ItemPointerData tid);
+extern BrinTuple *brinGetTupleForHeapBlock(BrinRevmap *revmap,
+ BlockNumber heapBlk, Buffer *buf, OffsetNumber *off,
+ Size *size, int mode, Snapshot snapshot);
+extern bool brinRevmapDesummarizeRange(Relation idxrel, BlockNumber heapBlk);
+
+#endif /* BRIN_REVMAP_H */
diff --git a/src/include/access/brin_tuple.h b/src/include/access/brin_tuple.h
new file mode 100644
index 0000000..a9ccc39
--- /dev/null
+++ b/src/include/access/brin_tuple.h
@@ -0,0 +1,102 @@
+/*
+ * brin_tuple.h
+ * Declarations for dealing with BRIN-specific tuples.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/access/brin_tuple.h
+ */
+#ifndef BRIN_TUPLE_H
+#define BRIN_TUPLE_H
+
+#include "access/brin_internal.h"
+#include "access/tupdesc.h"
+
+
+/*
+ * A BRIN index stores one index tuple per page range. Each index tuple
+ * has one BrinValues struct for each indexed column; in turn, each BrinValues
+ * has (besides the null flags) an array of Datum whose size is determined by
+ * the opclass.
+ */
+typedef struct BrinValues
+{
+ AttrNumber bv_attno; /* index attribute number */
+ bool bv_hasnulls; /* are there any nulls in the page range? */
+ bool bv_allnulls; /* are all values nulls in the page range? */
+ Datum *bv_values; /* current accumulated values */
+} BrinValues;
+
+/*
+ * This struct is used to represent an in-memory index tuple. The values can
+ * only be meaningfully decoded with an appropriate BrinDesc.
+ */
+typedef struct BrinMemTuple
+{
+ bool bt_placeholder; /* this is a placeholder tuple */
+ BlockNumber bt_blkno; /* heap blkno that the tuple is for */
+ MemoryContext bt_context; /* memcxt holding the bt_columns values */
+ /* output arrays for brin_deform_tuple: */
+ Datum *bt_values; /* values array */
+ bool *bt_allnulls; /* allnulls array */
+ bool *bt_hasnulls; /* hasnulls array */
+ /* not an output array, but must be last */
+ BrinValues bt_columns[FLEXIBLE_ARRAY_MEMBER];
+} BrinMemTuple;
+
+/*
+ * An on-disk BRIN tuple. This is possibly followed by a nulls bitmask, with
+ * room for 2 null bits (two bits for each indexed column); an opclass-defined
+ * number of Datum values for each column follow.
+ */
+typedef struct BrinTuple
+{
+ /* heap block number that the tuple is for */
+ BlockNumber bt_blkno;
+
+ /* ---------------
+ * bt_info is laid out in the following fashion:
+ *
+ * 7th (high) bit: has nulls
+ * 6th bit: is placeholder tuple
+ * 5th bit: unused
+ * 4-0 bit: offset of data
+ * ---------------
+ */
+ uint8 bt_info;
+} BrinTuple;
+
+#define SizeOfBrinTuple (offsetof(BrinTuple, bt_info) + sizeof(uint8))
+
+/*
+ * bt_info manipulation macros
+ */
+#define BRIN_OFFSET_MASK 0x1F
+/* bit 0x20 is not used at present */
+#define BRIN_PLACEHOLDER_MASK 0x40
+#define BRIN_NULLS_MASK 0x80
+
+#define BrinTupleDataOffset(tup) ((Size) (((BrinTuple *) (tup))->bt_info & BRIN_OFFSET_MASK))
+#define BrinTupleHasNulls(tup) (((((BrinTuple *) (tup))->bt_info & BRIN_NULLS_MASK)) != 0)
+#define BrinTupleIsPlaceholder(tup) (((((BrinTuple *) (tup))->bt_info & BRIN_PLACEHOLDER_MASK)) != 0)
+
+
+extern BrinTuple *brin_form_tuple(BrinDesc *brdesc, BlockNumber blkno,
+ BrinMemTuple *tuple, Size *size);
+extern BrinTuple *brin_form_placeholder_tuple(BrinDesc *brdesc,
+ BlockNumber blkno, Size *size);
+extern void brin_free_tuple(BrinTuple *tuple);
+extern BrinTuple *brin_copy_tuple(BrinTuple *tuple, Size len,
+ BrinTuple *dest, Size *destsz);
+extern bool brin_tuples_equal(const BrinTuple *a, Size alen,
+ const BrinTuple *b, Size blen);
+
+extern BrinMemTuple *brin_new_memtuple(BrinDesc *brdesc);
+extern BrinMemTuple *brin_memtuple_initialize(BrinMemTuple *dtuple,
+ BrinDesc *brdesc);
+extern BrinMemTuple *brin_deform_tuple(BrinDesc *brdesc,
+ BrinTuple *tuple, BrinMemTuple *dMemtuple);
+
+#endif /* BRIN_TUPLE_H */
diff --git a/src/include/access/brin_xlog.h b/src/include/access/brin_xlog.h
new file mode 100644
index 0000000..ecccebd
--- /dev/null
+++ b/src/include/access/brin_xlog.h
@@ -0,0 +1,151 @@
+/*-------------------------------------------------------------------------
+ *
+ * brin_xlog.h
+ * POSTGRES BRIN access XLOG definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/brin_xlog.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BRIN_XLOG_H
+#define BRIN_XLOG_H
+
+#include "access/xlogreader.h"
+#include "lib/stringinfo.h"
+#include "storage/bufpage.h"
+#include "storage/itemptr.h"
+#include "storage/relfilenode.h"
+#include "utils/relcache.h"
+
+
+/*
+ * WAL record definitions for BRIN's WAL operations
+ *
+ * XLOG allows to store some information in high 4 bits of log
+ * record xl_info field.
+ */
+#define XLOG_BRIN_CREATE_INDEX 0x00
+#define XLOG_BRIN_INSERT 0x10
+#define XLOG_BRIN_UPDATE 0x20
+#define XLOG_BRIN_SAMEPAGE_UPDATE 0x30
+#define XLOG_BRIN_REVMAP_EXTEND 0x40
+#define XLOG_BRIN_DESUMMARIZE 0x50
+
+#define XLOG_BRIN_OPMASK 0x70
+/*
+ * When we insert the first item on a new page, we restore the entire page in
+ * redo.
+ */
+#define XLOG_BRIN_INIT_PAGE 0x80
+
+/*
+ * This is what we need to know about a BRIN index create.
+ *
+ * Backup block 0: metapage
+ */
+typedef struct xl_brin_createidx
+{
+ BlockNumber pagesPerRange;
+ uint16 version;
+} xl_brin_createidx;
+#define SizeOfBrinCreateIdx (offsetof(xl_brin_createidx, version) + sizeof(uint16))
+
+/*
+ * This is what we need to know about a BRIN tuple insert
+ *
+ * Backup block 0: main page, block data is the new BrinTuple.
+ * Backup block 1: revmap page
+ */
+typedef struct xl_brin_insert
+{
+ BlockNumber heapBlk;
+
+ /* extra information needed to update the revmap */
+ BlockNumber pagesPerRange;
+
+ /* offset number in the main page to insert the tuple to. */
+ OffsetNumber offnum;
+} xl_brin_insert;
+
+#define SizeOfBrinInsert (offsetof(xl_brin_insert, offnum) + sizeof(OffsetNumber))
+
+/*
+ * A cross-page update is the same as an insert, but also stores information
+ * about the old tuple.
+ *
+ * Like in xl_brin_insert:
+ * Backup block 0: new page, block data includes the new BrinTuple.
+ * Backup block 1: revmap page
+ *
+ * And in addition:
+ * Backup block 2: old page
+ */
+typedef struct xl_brin_update
+{
+ /* offset number of old tuple on old page */
+ OffsetNumber oldOffnum;
+
+ xl_brin_insert insert;
+} xl_brin_update;
+
+#define SizeOfBrinUpdate (offsetof(xl_brin_update, insert) + SizeOfBrinInsert)
+
+/*
+ * This is what we need to know about a BRIN tuple samepage update
+ *
+ * Backup block 0: updated page, with new BrinTuple as block data
+ */
+typedef struct xl_brin_samepage_update
+{
+ OffsetNumber offnum;
+} xl_brin_samepage_update;
+
+#define SizeOfBrinSamepageUpdate (sizeof(OffsetNumber))
+
+/*
+ * This is what we need to know about a revmap extension
+ *
+ * Backup block 0: metapage
+ * Backup block 1: new revmap page
+ */
+typedef struct xl_brin_revmap_extend
+{
+ /*
+ * XXX: This is actually redundant - the block number is stored as part of
+ * backup block 1.
+ */
+ BlockNumber targetBlk;
+} xl_brin_revmap_extend;
+
+#define SizeOfBrinRevmapExtend (offsetof(xl_brin_revmap_extend, targetBlk) + \
+ sizeof(BlockNumber))
+
+/*
+ * This is what we need to know about a range de-summarization
+ *
+ * Backup block 0: revmap page
+ * Backup block 1: regular page
+ */
+typedef struct xl_brin_desummarize
+{
+ BlockNumber pagesPerRange;
+ /* page number location to set to invalid */
+ BlockNumber heapBlk;
+ /* offset of item to delete in regular index page */
+ OffsetNumber regOffset;
+} xl_brin_desummarize;
+
+#define SizeOfBrinDesummarize (offsetof(xl_brin_desummarize, regOffset) + \
+ sizeof(OffsetNumber))
+
+
+extern void brin_redo(XLogReaderState *record);
+extern void brin_desc(StringInfo buf, XLogReaderState *record);
+extern const char *brin_identify(uint8 info);
+extern void brin_mask(char *pagedata, BlockNumber blkno);
+
+#endif /* BRIN_XLOG_H */
diff --git a/src/include/access/bufmask.h b/src/include/access/bufmask.h
new file mode 100644
index 0000000..d86064c
--- /dev/null
+++ b/src/include/access/bufmask.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * bufmask.h
+ * Definitions for buffer masking routines, used to mask certain bits
+ * in a page which can be different when the WAL is generated
+ * and when the WAL is applied. This is really the job of each
+ * individual rmgr, but we make things easier by providing some
+ * common routines to handle cases which occur in multiple rmgrs.
+ *
+ * Portions Copyright (c) 2016-2020, PostgreSQL Global Development Group
+ *
+ * src/include/access/bufmask.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef BUFMASK_H
+#define BUFMASK_H
+
+#include "storage/block.h"
+#include "storage/bufmgr.h"
+
+/* Marker used to mask pages consistently */
+#define MASK_MARKER 0
+
+extern void mask_page_lsn_and_checksum(Page page);
+extern void mask_page_hint_bits(Page page);
+extern void mask_unused_space(Page page);
+extern void mask_lp_flags(Page page);
+extern void mask_page_content(Page page);
+
+#endif
diff --git a/src/include/access/clog.h b/src/include/access/clog.h
new file mode 100644
index 0000000..2db8acb
--- /dev/null
+++ b/src/include/access/clog.h
@@ -0,0 +1,61 @@
+/*
+ * clog.h
+ *
+ * PostgreSQL transaction-commit-log manager
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/clog.h
+ */
+#ifndef CLOG_H
+#define CLOG_H
+
+#include "access/xlogreader.h"
+#include "lib/stringinfo.h"
+
+/*
+ * Possible transaction statuses --- note that all-zeroes is the initial
+ * state.
+ *
+ * A "subcommitted" transaction is a committed subtransaction whose parent
+ * hasn't committed or aborted yet.
+ */
+typedef int XidStatus;
+
+#define TRANSACTION_STATUS_IN_PROGRESS 0x00
+#define TRANSACTION_STATUS_COMMITTED 0x01
+#define TRANSACTION_STATUS_ABORTED 0x02
+#define TRANSACTION_STATUS_SUB_COMMITTED 0x03
+
+typedef struct xl_clog_truncate
+{
+ int pageno;
+ TransactionId oldestXact;
+ Oid oldestXactDb;
+} xl_clog_truncate;
+
+extern void TransactionIdSetTreeStatus(TransactionId xid, int nsubxids,
+ TransactionId *subxids, XidStatus status, XLogRecPtr lsn);
+extern XidStatus TransactionIdGetStatus(TransactionId xid, XLogRecPtr *lsn);
+
+extern Size CLOGShmemBuffers(void);
+extern Size CLOGShmemSize(void);
+extern void CLOGShmemInit(void);
+extern void BootStrapCLOG(void);
+extern void StartupCLOG(void);
+extern void TrimCLOG(void);
+extern void ShutdownCLOG(void);
+extern void CheckPointCLOG(void);
+extern void ExtendCLOG(TransactionId newestXact);
+extern void TruncateCLOG(TransactionId oldestXact, Oid oldestxid_datoid);
+
+/* XLOG stuff */
+#define CLOG_ZEROPAGE 0x00
+#define CLOG_TRUNCATE 0x10
+
+extern void clog_redo(XLogReaderState *record);
+extern void clog_desc(StringInfo buf, XLogReaderState *record);
+extern const char *clog_identify(uint8 info);
+
+#endif /* CLOG_H */
diff --git a/src/include/access/commit_ts.h b/src/include/access/commit_ts.h
new file mode 100644
index 0000000..2740c02
--- /dev/null
+++ b/src/include/access/commit_ts.h
@@ -0,0 +1,77 @@
+/*
+ * commit_ts.h
+ *
+ * PostgreSQL commit timestamp manager
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/commit_ts.h
+ */
+#ifndef COMMIT_TS_H
+#define COMMIT_TS_H
+
+#include "access/xlog.h"
+#include "datatype/timestamp.h"
+#include "replication/origin.h"
+#include "utils/guc.h"
+
+
+extern PGDLLIMPORT bool track_commit_timestamp;
+
+extern bool check_track_commit_timestamp(bool *newval, void **extra,
+ GucSource source);
+
+extern void TransactionTreeSetCommitTsData(TransactionId xid, int nsubxids,
+ TransactionId *subxids, TimestampTz timestamp,
+ RepOriginId nodeid, bool write_xlog);
+extern bool TransactionIdGetCommitTsData(TransactionId xid,
+ TimestampTz *ts, RepOriginId *nodeid);
+extern TransactionId GetLatestCommitTsData(TimestampTz *ts,
+ RepOriginId *nodeid);
+
+extern Size CommitTsShmemBuffers(void);
+extern Size CommitTsShmemSize(void);
+extern void CommitTsShmemInit(void);
+extern void BootStrapCommitTs(void);
+extern void StartupCommitTs(void);
+extern void CommitTsParameterChange(bool newvalue, bool oldvalue);
+extern void CompleteCommitTsInitialization(void);
+extern void ShutdownCommitTs(void);
+extern void CheckPointCommitTs(void);
+extern void ExtendCommitTs(TransactionId newestXact);
+extern void TruncateCommitTs(TransactionId oldestXact);
+extern void SetCommitTsLimit(TransactionId oldestXact,
+ TransactionId newestXact);
+extern void AdvanceOldestCommitTsXid(TransactionId oldestXact);
+
+/* XLOG stuff */
+#define COMMIT_TS_ZEROPAGE 0x00
+#define COMMIT_TS_TRUNCATE 0x10
+#define COMMIT_TS_SETTS 0x20
+
+typedef struct xl_commit_ts_set
+{
+ TimestampTz timestamp;
+ RepOriginId nodeid;
+ TransactionId mainxid;
+ /* subxact Xids follow */
+} xl_commit_ts_set;
+
+#define SizeOfCommitTsSet (offsetof(xl_commit_ts_set, mainxid) + \
+ sizeof(TransactionId))
+
+typedef struct xl_commit_ts_truncate
+{
+ int pageno;
+ TransactionId oldestXid;
+} xl_commit_ts_truncate;
+
+#define SizeOfCommitTsTruncate (offsetof(xl_commit_ts_truncate, oldestXid) + \
+ sizeof(TransactionId))
+
+extern void commit_ts_redo(XLogReaderState *record);
+extern void commit_ts_desc(StringInfo buf, XLogReaderState *record);
+extern const char *commit_ts_identify(uint8 info);
+
+#endif /* COMMIT_TS_H */
diff --git a/src/include/access/detoast.h b/src/include/access/detoast.h
new file mode 100644
index 0000000..86bad7e
--- /dev/null
+++ b/src/include/access/detoast.h
@@ -0,0 +1,92 @@
+/*-------------------------------------------------------------------------
+ *
+ * detoast.h
+ * Access to compressed and external varlena values.
+ *
+ * Copyright (c) 2000-2020, PostgreSQL Global Development Group
+ *
+ * src/include/access/detoast.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DETOAST_H
+#define DETOAST_H
+
+/*
+ * Testing whether an externally-stored value is compressed now requires
+ * comparing extsize (the actual length of the external data) to rawsize
+ * (the original uncompressed datum's size). The latter includes VARHDRSZ
+ * overhead, the former doesn't. We never use compression unless it actually
+ * saves space, so we expect either equality or less-than.
+ */
+#define VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer) \
+ ((toast_pointer).va_extsize < (toast_pointer).va_rawsize - VARHDRSZ)
+
+/*
+ * Macro to fetch the possibly-unaligned contents of an EXTERNAL datum
+ * into a local "struct varatt_external" toast pointer. This should be
+ * just a memcpy, but some versions of gcc seem to produce broken code
+ * that assumes the datum contents are aligned. Introducing an explicit
+ * intermediate "varattrib_1b_e *" variable seems to fix it.
+ */
+#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr) \
+do { \
+ varattrib_1b_e *attre = (varattrib_1b_e *) (attr); \
+ Assert(VARATT_IS_EXTERNAL(attre)); \
+ Assert(VARSIZE_EXTERNAL(attre) == sizeof(toast_pointer) + VARHDRSZ_EXTERNAL); \
+ memcpy(&(toast_pointer), VARDATA_EXTERNAL(attre), sizeof(toast_pointer)); \
+} while (0)
+
+/* Size of an EXTERNAL datum that contains a standard TOAST pointer */
+#define TOAST_POINTER_SIZE (VARHDRSZ_EXTERNAL + sizeof(varatt_external))
+
+/* Size of an EXTERNAL datum that contains an indirection pointer */
+#define INDIRECT_POINTER_SIZE (VARHDRSZ_EXTERNAL + sizeof(varatt_indirect))
+
+/* ----------
+ * detoast_external_attr() -
+ *
+ * Fetches an external stored attribute from the toast
+ * relation. Does NOT decompress it, if stored external
+ * in compressed format.
+ * ----------
+ */
+extern struct varlena *detoast_external_attr(struct varlena *attr);
+
+/* ----------
+ * detoast_attr() -
+ *
+ * Fully detoasts one attribute, fetching and/or decompressing
+ * it as needed.
+ * ----------
+ */
+extern struct varlena *detoast_attr(struct varlena *attr);
+
+/* ----------
+ * detoast_attr_slice() -
+ *
+ * Fetches only the specified portion of an attribute.
+ * (Handles all cases for attribute storage)
+ * ----------
+ */
+extern struct varlena *detoast_attr_slice(struct varlena *attr,
+ int32 sliceoffset,
+ int32 slicelength);
+
+/* ----------
+ * toast_raw_datum_size -
+ *
+ * Return the raw (detoasted) size of a varlena datum
+ * ----------
+ */
+extern Size toast_raw_datum_size(Datum value);
+
+/* ----------
+ * toast_datum_size -
+ *
+ * Return the storage size of a varlena datum
+ * ----------
+ */
+extern Size toast_datum_size(Datum value);
+
+#endif /* DETOAST_H */
diff --git a/src/include/access/genam.h b/src/include/access/genam.h
new file mode 100644
index 0000000..931257b
--- /dev/null
+++ b/src/include/access/genam.h
@@ -0,0 +1,228 @@
+/*-------------------------------------------------------------------------
+ *
+ * genam.h
+ * POSTGRES generalized index access method definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/genam.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef GENAM_H
+#define GENAM_H
+
+#include "access/sdir.h"
+#include "access/skey.h"
+#include "nodes/tidbitmap.h"
+#include "storage/lockdefs.h"
+#include "utils/relcache.h"
+#include "utils/snapshot.h"
+
+/* We don't want this file to depend on execnodes.h. */
+struct IndexInfo;
+
+/*
+ * Struct for statistics returned by ambuild
+ */
+typedef struct IndexBuildResult
+{
+ double heap_tuples; /* # of tuples seen in parent table */
+ double index_tuples; /* # of tuples inserted into index */
+} IndexBuildResult;
+
+/*
+ * Struct for input arguments passed to ambulkdelete and amvacuumcleanup
+ *
+ * num_heap_tuples is accurate only when estimated_count is false;
+ * otherwise it's just an estimate (currently, the estimate is the
+ * prior value of the relation's pg_class.reltuples field). It will
+ * always just be an estimate during ambulkdelete.
+ */
+typedef struct IndexVacuumInfo
+{
+ Relation index; /* the index being vacuumed */
+ bool analyze_only; /* ANALYZE (without any actual vacuum) */
+ bool report_progress; /* emit progress.h status reports */
+ bool estimated_count; /* num_heap_tuples is an estimate */
+ int message_level; /* ereport level for progress messages */
+ double num_heap_tuples; /* tuples remaining in heap */
+ BufferAccessStrategy strategy; /* access strategy for reads */
+} IndexVacuumInfo;
+
+/*
+ * Struct for statistics returned by ambulkdelete and amvacuumcleanup
+ *
+ * This struct is normally allocated by the first ambulkdelete call and then
+ * passed along through subsequent ones until amvacuumcleanup; however,
+ * amvacuumcleanup must be prepared to allocate it in the case where no
+ * ambulkdelete calls were made (because no tuples needed deletion).
+ * Note that an index AM could choose to return a larger struct
+ * of which this is just the first field; this provides a way for ambulkdelete
+ * to communicate additional private data to amvacuumcleanup.
+ *
+ * Note: pages_removed is the amount by which the index physically shrank,
+ * if any (ie the change in its total size on disk). pages_deleted and
+ * pages_free refer to free space within the index file. Some index AMs
+ * may compute num_index_tuples by reference to num_heap_tuples, in which
+ * case they should copy the estimated_count field from IndexVacuumInfo.
+ */
+typedef struct IndexBulkDeleteResult
+{
+ BlockNumber num_pages; /* pages remaining in index */
+ BlockNumber pages_removed; /* # removed during vacuum operation */
+ bool estimated_count; /* num_index_tuples is an estimate */
+ double num_index_tuples; /* tuples remaining */
+ double tuples_removed; /* # removed during vacuum operation */
+ BlockNumber pages_deleted; /* # unused pages in index */
+ BlockNumber pages_free; /* # pages available for reuse */
+} IndexBulkDeleteResult;
+
+/* Typedef for callback function to determine if a tuple is bulk-deletable */
+typedef bool (*IndexBulkDeleteCallback) (ItemPointer itemptr, void *state);
+
+/* struct definitions appear in relscan.h */
+typedef struct IndexScanDescData *IndexScanDesc;
+typedef struct SysScanDescData *SysScanDesc;
+
+typedef struct ParallelIndexScanDescData *ParallelIndexScanDesc;
+
+/*
+ * Enumeration specifying the type of uniqueness check to perform in
+ * index_insert().
+ *
+ * UNIQUE_CHECK_YES is the traditional Postgres immediate check, possibly
+ * blocking to see if a conflicting transaction commits.
+ *
+ * For deferrable unique constraints, UNIQUE_CHECK_PARTIAL is specified at
+ * insertion time. The index AM should test if the tuple is unique, but
+ * should not throw error, block, or prevent the insertion if the tuple
+ * appears not to be unique. We'll recheck later when it is time for the
+ * constraint to be enforced. The AM must return true if the tuple is
+ * known unique, false if it is possibly non-unique. In the "true" case
+ * it is safe to omit the later recheck.
+ *
+ * When it is time to recheck the deferred constraint, a pseudo-insertion
+ * call is made with UNIQUE_CHECK_EXISTING. The tuple is already in the
+ * index in this case, so it should not be inserted again. Rather, just
+ * check for conflicting live tuples (possibly blocking).
+ */
+typedef enum IndexUniqueCheck
+{
+ UNIQUE_CHECK_NO, /* Don't do any uniqueness checking */
+ UNIQUE_CHECK_YES, /* Enforce uniqueness at insertion time */
+ UNIQUE_CHECK_PARTIAL, /* Test uniqueness, but no error */
+ UNIQUE_CHECK_EXISTING /* Check if existing tuple is unique */
+} IndexUniqueCheck;
+
+
+/* Nullable "ORDER BY col op const" distance */
+typedef struct IndexOrderByDistance
+{
+ double value;
+ bool isnull;
+} IndexOrderByDistance;
+
+/*
+ * generalized index_ interface routines (in indexam.c)
+ */
+
+/*
+ * IndexScanIsValid
+ * True iff the index scan is valid.
+ */
+#define IndexScanIsValid(scan) PointerIsValid(scan)
+
+extern Relation index_open(Oid relationId, LOCKMODE lockmode);
+extern void index_close(Relation relation, LOCKMODE lockmode);
+
+extern bool index_insert(Relation indexRelation,
+ Datum *values, bool *isnull,
+ ItemPointer heap_t_ctid,
+ Relation heapRelation,
+ IndexUniqueCheck checkUnique,
+ struct IndexInfo *indexInfo);
+
+extern IndexScanDesc index_beginscan(Relation heapRelation,
+ Relation indexRelation,
+ Snapshot snapshot,
+ int nkeys, int norderbys);
+extern IndexScanDesc index_beginscan_bitmap(Relation indexRelation,
+ Snapshot snapshot,
+ int nkeys);
+extern void index_rescan(IndexScanDesc scan,
+ ScanKey keys, int nkeys,
+ ScanKey orderbys, int norderbys);
+extern void index_endscan(IndexScanDesc scan);
+extern void index_markpos(IndexScanDesc scan);
+extern void index_restrpos(IndexScanDesc scan);
+extern Size index_parallelscan_estimate(Relation indexrel, Snapshot snapshot);
+extern void index_parallelscan_initialize(Relation heaprel, Relation indexrel,
+ Snapshot snapshot, ParallelIndexScanDesc target);
+extern void index_parallelrescan(IndexScanDesc scan);
+extern IndexScanDesc index_beginscan_parallel(Relation heaprel,
+ Relation indexrel, int nkeys, int norderbys,
+ ParallelIndexScanDesc pscan);
+extern ItemPointer index_getnext_tid(IndexScanDesc scan,
+ ScanDirection direction);
+struct TupleTableSlot;
+extern bool index_fetch_heap(IndexScanDesc scan, struct TupleTableSlot *slot);
+extern bool index_getnext_slot(IndexScanDesc scan, ScanDirection direction,
+ struct TupleTableSlot *slot);
+extern int64 index_getbitmap(IndexScanDesc scan, TIDBitmap *bitmap);
+
+extern IndexBulkDeleteResult *index_bulk_delete(IndexVacuumInfo *info,
+ IndexBulkDeleteResult *stats,
+ IndexBulkDeleteCallback callback,
+ void *callback_state);
+extern IndexBulkDeleteResult *index_vacuum_cleanup(IndexVacuumInfo *info,
+ IndexBulkDeleteResult *stats);
+extern bool index_can_return(Relation indexRelation, int attno);
+extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum,
+ uint16 procnum);
+extern FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum,
+ uint16 procnum);
+extern void index_store_float8_orderby_distances(IndexScanDesc scan,
+ Oid *orderByTypes,
+ IndexOrderByDistance *distances,
+ bool recheckOrderBy);
+extern bytea *index_opclass_options(Relation relation, AttrNumber attnum,
+ Datum attoptions, bool validate);
+
+
+/*
+ * index access method support routines (in genam.c)
+ */
+extern IndexScanDesc RelationGetIndexScan(Relation indexRelation,
+ int nkeys, int norderbys);
+extern void IndexScanEnd(IndexScanDesc scan);
+extern char *BuildIndexValueDescription(Relation indexRelation,
+ Datum *values, bool *isnull);
+extern TransactionId index_compute_xid_horizon_for_tuples(Relation irel,
+ Relation hrel,
+ Buffer ibuf,
+ OffsetNumber *itemnos,
+ int nitems);
+
+/*
+ * heap-or-index access to system catalogs (in genam.c)
+ */
+extern SysScanDesc systable_beginscan(Relation heapRelation,
+ Oid indexId,
+ bool indexOK,
+ Snapshot snapshot,
+ int nkeys, ScanKey key);
+extern HeapTuple systable_getnext(SysScanDesc sysscan);
+extern bool systable_recheck_tuple(SysScanDesc sysscan, HeapTuple tup);
+extern void systable_endscan(SysScanDesc sysscan);
+extern SysScanDesc systable_beginscan_ordered(Relation heapRelation,
+ Relation indexRelation,
+ Snapshot snapshot,
+ int nkeys, ScanKey key);
+extern HeapTuple systable_getnext_ordered(SysScanDesc sysscan,
+ ScanDirection direction);
+extern void systable_endscan_ordered(SysScanDesc sysscan);
+
+#endif /* GENAM_H */
diff --git a/src/include/access/generic_xlog.h b/src/include/access/generic_xlog.h
new file mode 100644
index 0000000..e0d4605
--- /dev/null
+++ b/src/include/access/generic_xlog.h
@@ -0,0 +1,45 @@
+/*-------------------------------------------------------------------------
+ *
+ * generic_xlog.h
+ * Generic xlog API definition.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/generic_xlog.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef GENERIC_XLOG_H
+#define GENERIC_XLOG_H
+
+#include "access/xlog.h"
+#include "access/xlog_internal.h"
+#include "access/xloginsert.h"
+#include "storage/bufpage.h"
+#include "utils/rel.h"
+
+#define MAX_GENERIC_XLOG_PAGES XLR_NORMAL_MAX_BLOCK_ID
+
+/* Flag bits for GenericXLogRegisterBuffer */
+#define GENERIC_XLOG_FULL_IMAGE 0x0001 /* write full-page image */
+
+/* state of generic xlog record construction */
+struct GenericXLogState;
+typedef struct GenericXLogState GenericXLogState;
+
+/* API for construction of generic xlog records */
+extern GenericXLogState *GenericXLogStart(Relation relation);
+extern Page GenericXLogRegisterBuffer(GenericXLogState *state, Buffer buffer,
+ int flags);
+extern XLogRecPtr GenericXLogFinish(GenericXLogState *state);
+extern void GenericXLogAbort(GenericXLogState *state);
+
+/* functions defined for rmgr */
+extern void generic_redo(XLogReaderState *record);
+extern const char *generic_identify(uint8 info);
+extern void generic_desc(StringInfo buf, XLogReaderState *record);
+extern void generic_mask(char *pagedata, BlockNumber blkno);
+
+#endif /* GENERIC_XLOG_H */
diff --git a/src/include/access/gin.h b/src/include/access/gin.h
new file mode 100644
index 0000000..990e8b3
--- /dev/null
+++ b/src/include/access/gin.h
@@ -0,0 +1,78 @@
+/*--------------------------------------------------------------------------
+ * gin.h
+ * Public header file for Generalized Inverted Index access method.
+ *
+ * Copyright (c) 2006-2020, PostgreSQL Global Development Group
+ *
+ * src/include/access/gin.h
+ *--------------------------------------------------------------------------
+ */
+#ifndef GIN_H
+#define GIN_H
+
+#include "access/xlogreader.h"
+#include "lib/stringinfo.h"
+#include "storage/block.h"
+#include "utils/relcache.h"
+
+
+/*
+ * amproc indexes for inverted indexes.
+ */
+#define GIN_COMPARE_PROC 1
+#define GIN_EXTRACTVALUE_PROC 2
+#define GIN_EXTRACTQUERY_PROC 3
+#define GIN_CONSISTENT_PROC 4
+#define GIN_COMPARE_PARTIAL_PROC 5
+#define GIN_TRICONSISTENT_PROC 6
+#define GIN_OPTIONS_PROC 7
+#define GINNProcs 7
+
+/*
+ * searchMode settings for extractQueryFn.
+ */
+#define GIN_SEARCH_MODE_DEFAULT 0
+#define GIN_SEARCH_MODE_INCLUDE_EMPTY 1
+#define GIN_SEARCH_MODE_ALL 2
+#define GIN_SEARCH_MODE_EVERYTHING 3 /* for internal use only */
+
+/*
+ * GinStatsData represents stats data for planner use
+ */
+typedef struct GinStatsData
+{
+ BlockNumber nPendingPages;
+ BlockNumber nTotalPages;
+ BlockNumber nEntryPages;
+ BlockNumber nDataPages;
+ int64 nEntries;
+ int32 ginVersion;
+} GinStatsData;
+
+/*
+ * A ternary value used by tri-consistent functions.
+ *
+ * This must be of the same size as a bool because some code will cast a
+ * pointer to a bool to a pointer to a GinTernaryValue.
+ */
+typedef char GinTernaryValue;
+
+#define GIN_FALSE 0 /* item is not present / does not match */
+#define GIN_TRUE 1 /* item is present / matches */
+#define GIN_MAYBE 2 /* don't know if item is present / don't know
+ * if matches */
+
+#define DatumGetGinTernaryValue(X) ((GinTernaryValue)(X))
+#define GinTernaryValueGetDatum(X) ((Datum)(X))
+#define PG_RETURN_GIN_TERNARY_VALUE(x) return GinTernaryValueGetDatum(x)
+
+/* GUC parameters */
+extern PGDLLIMPORT int GinFuzzySearchLimit;
+extern int gin_pending_list_limit;
+
+/* ginutil.c */
+extern void ginGetStats(Relation index, GinStatsData *stats);
+extern void ginUpdateStats(Relation index, const GinStatsData *stats,
+ bool is_build);
+
+#endif /* GIN_H */
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
new file mode 100644
index 0000000..71eeac2
--- /dev/null
+++ b/src/include/access/gin_private.h
@@ -0,0 +1,495 @@
+/*--------------------------------------------------------------------------
+ * gin_private.h
+ * header file for postgres inverted index access method implementation.
+ *
+ * Copyright (c) 2006-2020, PostgreSQL Global Development Group
+ *
+ * src/include/access/gin_private.h
+ *--------------------------------------------------------------------------
+ */
+#ifndef GIN_PRIVATE_H
+#define GIN_PRIVATE_H
+
+#include "access/amapi.h"
+#include "access/gin.h"
+#include "access/ginblock.h"
+#include "access/itup.h"
+#include "catalog/pg_am_d.h"
+#include "fmgr.h"
+#include "lib/rbtree.h"
+#include "storage/bufmgr.h"
+
+/*
+ * Storage type for GIN's reloptions
+ */
+typedef struct GinOptions
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ bool useFastUpdate; /* use fast updates? */
+ int pendingListCleanupSize; /* maximum size of pending list */
+} GinOptions;
+
+#define GIN_DEFAULT_USE_FASTUPDATE true
+#define GinGetUseFastUpdate(relation) \
+ (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \
+ relation->rd_rel->relam == GIN_AM_OID), \
+ (relation)->rd_options ? \
+ ((GinOptions *) (relation)->rd_options)->useFastUpdate : GIN_DEFAULT_USE_FASTUPDATE)
+#define GinGetPendingListCleanupSize(relation) \
+ (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \
+ relation->rd_rel->relam == GIN_AM_OID), \
+ (relation)->rd_options && \
+ ((GinOptions *) (relation)->rd_options)->pendingListCleanupSize != -1 ? \
+ ((GinOptions *) (relation)->rd_options)->pendingListCleanupSize : \
+ gin_pending_list_limit)
+
+
+/* Macros for buffer lock/unlock operations */
+#define GIN_UNLOCK BUFFER_LOCK_UNLOCK
+#define GIN_SHARE BUFFER_LOCK_SHARE
+#define GIN_EXCLUSIVE BUFFER_LOCK_EXCLUSIVE
+
+
+/*
+ * GinState: working data structure describing the index being worked on
+ */
+typedef struct GinState
+{
+ Relation index;
+ bool oneCol; /* true if single-column index */
+
+ /*
+ * origTupdesc is the nominal tuple descriptor of the index, ie, the i'th
+ * attribute shows the key type (not the input data type!) of the i'th
+ * index column. In a single-column index this describes the actual leaf
+ * index tuples. In a multi-column index, the actual leaf tuples contain
+ * a smallint column number followed by a key datum of the appropriate
+ * type for that column. We set up tupdesc[i] to describe the actual
+ * rowtype of the index tuples for the i'th column, ie, (int2, keytype).
+ * Note that in any case, leaf tuples contain more data than is known to
+ * the TupleDesc; see access/gin/README for details.
+ */
+ TupleDesc origTupdesc;
+ TupleDesc tupdesc[INDEX_MAX_KEYS];
+
+ /*
+ * Per-index-column opclass support functions
+ */
+ FmgrInfo compareFn[INDEX_MAX_KEYS];
+ FmgrInfo extractValueFn[INDEX_MAX_KEYS];
+ FmgrInfo extractQueryFn[INDEX_MAX_KEYS];
+ FmgrInfo consistentFn[INDEX_MAX_KEYS];
+ FmgrInfo triConsistentFn[INDEX_MAX_KEYS];
+ FmgrInfo comparePartialFn[INDEX_MAX_KEYS]; /* optional method */
+ /* canPartialMatch[i] is true if comparePartialFn[i] is valid */
+ bool canPartialMatch[INDEX_MAX_KEYS];
+ /* Collations to pass to the support functions */
+ Oid supportCollation[INDEX_MAX_KEYS];
+} GinState;
+
+
+/* ginutil.c */
+extern bytea *ginoptions(Datum reloptions, bool validate);
+extern void initGinState(GinState *state, Relation index);
+extern Buffer GinNewBuffer(Relation index);
+extern void GinInitBuffer(Buffer b, uint32 f);
+extern void GinInitPage(Page page, uint32 f, Size pageSize);
+extern void GinInitMetabuffer(Buffer b);
+extern int ginCompareEntries(GinState *ginstate, OffsetNumber attnum,
+ Datum a, GinNullCategory categorya,
+ Datum b, GinNullCategory categoryb);
+extern int ginCompareAttEntries(GinState *ginstate,
+ OffsetNumber attnuma, Datum a, GinNullCategory categorya,
+ OffsetNumber attnumb, Datum b, GinNullCategory categoryb);
+extern Datum *ginExtractEntries(GinState *ginstate, OffsetNumber attnum,
+ Datum value, bool isNull,
+ int32 *nentries, GinNullCategory **categories);
+
+extern OffsetNumber gintuple_get_attrnum(GinState *ginstate, IndexTuple tuple);
+extern Datum gintuple_get_key(GinState *ginstate, IndexTuple tuple,
+ GinNullCategory *category);
+
+/* gininsert.c */
+extern IndexBuildResult *ginbuild(Relation heap, Relation index,
+ struct IndexInfo *indexInfo);
+extern void ginbuildempty(Relation index);
+extern bool gininsert(Relation index, Datum *values, bool *isnull,
+ ItemPointer ht_ctid, Relation heapRel,
+ IndexUniqueCheck checkUnique,
+ struct IndexInfo *indexInfo);
+extern void ginEntryInsert(GinState *ginstate,
+ OffsetNumber attnum, Datum key, GinNullCategory category,
+ ItemPointerData *items, uint32 nitem,
+ GinStatsData *buildStats);
+
+/* ginbtree.c */
+
+typedef struct GinBtreeStack
+{
+ BlockNumber blkno;
+ Buffer buffer;
+ OffsetNumber off;
+ ItemPointerData iptr;
+ /* predictNumber contains predicted number of pages on current level */
+ uint32 predictNumber;
+ struct GinBtreeStack *parent;
+} GinBtreeStack;
+
+typedef struct GinBtreeData *GinBtree;
+
+/* Return codes for GinBtreeData.beginPlaceToPage method */
+typedef enum
+{
+ GPTP_NO_WORK,
+ GPTP_INSERT,
+ GPTP_SPLIT
+} GinPlaceToPageRC;
+
+typedef struct GinBtreeData
+{
+ /* search methods */
+ BlockNumber (*findChildPage) (GinBtree, GinBtreeStack *);
+ BlockNumber (*getLeftMostChild) (GinBtree, Page);
+ bool (*isMoveRight) (GinBtree, Page);
+ bool (*findItem) (GinBtree, GinBtreeStack *);
+
+ /* insert methods */
+ OffsetNumber (*findChildPtr) (GinBtree, Page, BlockNumber, OffsetNumber);
+ GinPlaceToPageRC (*beginPlaceToPage) (GinBtree, Buffer, GinBtreeStack *, void *, BlockNumber, void **, Page *, Page *);
+ void (*execPlaceToPage) (GinBtree, Buffer, GinBtreeStack *, void *, BlockNumber, void *);
+ void *(*prepareDownlink) (GinBtree, Buffer);
+ void (*fillRoot) (GinBtree, Page, BlockNumber, Page, BlockNumber, Page);
+
+ bool isData;
+
+ Relation index;
+ BlockNumber rootBlkno;
+ GinState *ginstate; /* not valid in a data scan */
+ bool fullScan;
+ bool isBuild;
+
+ /* Search key for Entry tree */
+ OffsetNumber entryAttnum;
+ Datum entryKey;
+ GinNullCategory entryCategory;
+
+ /* Search key for data tree (posting tree) */
+ ItemPointerData itemptr;
+} GinBtreeData;
+
+/* This represents a tuple to be inserted to entry tree. */
+typedef struct
+{
+ IndexTuple entry; /* tuple to insert */
+ bool isDelete; /* delete old tuple at same offset? */
+} GinBtreeEntryInsertData;
+
+/*
+ * This represents an itempointer, or many itempointers, to be inserted to
+ * a data (posting tree) leaf page
+ */
+typedef struct
+{
+ ItemPointerData *items;
+ uint32 nitem;
+ uint32 curitem;
+} GinBtreeDataLeafInsertData;
+
+/*
+ * For internal data (posting tree) pages, the insertion payload is a
+ * PostingItem
+ */
+
+extern GinBtreeStack *ginFindLeafPage(GinBtree btree, bool searchMode,
+ bool rootConflictCheck, Snapshot snapshot);
+extern Buffer ginStepRight(Buffer buffer, Relation index, int lockmode);
+extern void freeGinBtreeStack(GinBtreeStack *stack);
+extern void ginInsertValue(GinBtree btree, GinBtreeStack *stack,
+ void *insertdata, GinStatsData *buildStats);
+
+/* ginentrypage.c */
+extern IndexTuple GinFormTuple(GinState *ginstate,
+ OffsetNumber attnum, Datum key, GinNullCategory category,
+ Pointer data, Size dataSize, int nipd, bool errorTooBig);
+extern void ginPrepareEntryScan(GinBtree btree, OffsetNumber attnum,
+ Datum key, GinNullCategory category,
+ GinState *ginstate);
+extern void ginEntryFillRoot(GinBtree btree, Page root, BlockNumber lblkno, Page lpage, BlockNumber rblkno, Page rpage);
+extern ItemPointer ginReadTuple(GinState *ginstate, OffsetNumber attnum,
+ IndexTuple itup, int *nitems);
+
+/* gindatapage.c */
+extern ItemPointer GinDataLeafPageGetItems(Page page, int *nitems, ItemPointerData advancePast);
+extern int GinDataLeafPageGetItemsToTbm(Page page, TIDBitmap *tbm);
+extern BlockNumber createPostingTree(Relation index,
+ ItemPointerData *items, uint32 nitems,
+ GinStatsData *buildStats, Buffer entrybuffer);
+extern void GinDataPageAddPostingItem(Page page, PostingItem *data, OffsetNumber offset);
+extern void GinPageDeletePostingItem(Page page, OffsetNumber offset);
+extern void ginInsertItemPointers(Relation index, BlockNumber rootBlkno,
+ ItemPointerData *items, uint32 nitem,
+ GinStatsData *buildStats);
+extern GinBtreeStack *ginScanBeginPostingTree(GinBtree btree, Relation index, BlockNumber rootBlkno, Snapshot snapshot);
+extern void ginDataFillRoot(GinBtree btree, Page root, BlockNumber lblkno, Page lpage, BlockNumber rblkno, Page rpage);
+
+/*
+ * This is declared in ginvacuum.c, but is passed between ginVacuumItemPointers
+ * and ginVacuumPostingTreeLeaf and as an opaque struct, so we need a forward
+ * declaration for it.
+ */
+typedef struct GinVacuumState GinVacuumState;
+
+extern void ginVacuumPostingTreeLeaf(Relation rel, Buffer buf, GinVacuumState *gvs);
+
+/* ginscan.c */
+
+/*
+ * GinScanKeyData describes a single GIN index qualifier expression.
+ *
+ * From each qual expression, we extract one or more specific index search
+ * conditions, which are represented by GinScanEntryData. It's quite
+ * possible for identical search conditions to be requested by more than
+ * one qual expression, in which case we merge such conditions to have just
+ * one unique GinScanEntry --- this is particularly important for efficiency
+ * when dealing with full-index-scan entries. So there can be multiple
+ * GinScanKeyData.scanEntry pointers to the same GinScanEntryData.
+ *
+ * In each GinScanKeyData, nentries is the true number of entries, while
+ * nuserentries is the number that extractQueryFn returned (which is what
+ * we report to consistentFn). The "user" entries must come first.
+ */
+typedef struct GinScanKeyData *GinScanKey;
+
+typedef struct GinScanEntryData *GinScanEntry;
+
+typedef struct GinScanKeyData
+{
+ /* Real number of entries in scanEntry[] (always > 0) */
+ uint32 nentries;
+ /* Number of entries that extractQueryFn and consistentFn know about */
+ uint32 nuserentries;
+
+ /* array of GinScanEntry pointers, one per extracted search condition */
+ GinScanEntry *scanEntry;
+
+ /*
+ * At least one of the entries in requiredEntries must be present for a
+ * tuple to match the overall qual.
+ *
+ * additionalEntries contains entries that are needed by the consistent
+ * function to decide if an item matches, but are not sufficient to
+ * satisfy the qual without entries from requiredEntries.
+ */
+ GinScanEntry *requiredEntries;
+ int nrequired;
+ GinScanEntry *additionalEntries;
+ int nadditional;
+
+ /* array of check flags, reported to consistentFn */
+ GinTernaryValue *entryRes;
+ bool (*boolConsistentFn) (GinScanKey key);
+ GinTernaryValue (*triConsistentFn) (GinScanKey key);
+ FmgrInfo *consistentFmgrInfo;
+ FmgrInfo *triConsistentFmgrInfo;
+ Oid collation;
+
+ /* other data needed for calling consistentFn */
+ Datum query;
+ /* NB: these three arrays have only nuserentries elements! */
+ Datum *queryValues;
+ GinNullCategory *queryCategories;
+ Pointer *extra_data;
+ StrategyNumber strategy;
+ int32 searchMode;
+ OffsetNumber attnum;
+
+ /*
+ * An excludeOnly scan key is not able to enumerate all matching tuples.
+ * That is, to be semantically correct on its own, it would need to have a
+ * GIN_CAT_EMPTY_QUERY scanEntry, but it doesn't. Such a key can still be
+ * used to filter tuples returned by other scan keys, so we will get the
+ * right answers as long as there's at least one non-excludeOnly scan key
+ * for each index attribute considered by the search. For efficiency
+ * reasons we don't want to have unnecessary GIN_CAT_EMPTY_QUERY entries,
+ * so we will convert an excludeOnly scan key to non-excludeOnly (by
+ * adding a GIN_CAT_EMPTY_QUERY scanEntry) only if there are no other
+ * non-excludeOnly scan keys.
+ */
+ bool excludeOnly;
+
+ /*
+ * Match status data. curItem is the TID most recently tested (could be a
+ * lossy-page pointer). curItemMatches is true if it passes the
+ * consistentFn test; if so, recheckCurItem is the recheck flag.
+ * isFinished means that all the input entry streams are finished, so this
+ * key cannot succeed for any later TIDs.
+ */
+ ItemPointerData curItem;
+ bool curItemMatches;
+ bool recheckCurItem;
+ bool isFinished;
+} GinScanKeyData;
+
+typedef struct GinScanEntryData
+{
+ /* query key and other information from extractQueryFn */
+ Datum queryKey;
+ GinNullCategory queryCategory;
+ bool isPartialMatch;
+ Pointer extra_data;
+ StrategyNumber strategy;
+ int32 searchMode;
+ OffsetNumber attnum;
+
+ /* Current page in posting tree */
+ Buffer buffer;
+
+ /* current ItemPointer to heap */
+ ItemPointerData curItem;
+
+ /* for a partial-match or full-scan query, we accumulate all TIDs here */
+ TIDBitmap *matchBitmap;
+ TBMIterator *matchIterator;
+ TBMIterateResult *matchResult;
+
+ /* used for Posting list and one page in Posting tree */
+ ItemPointerData *list;
+ int nlist;
+ OffsetNumber offset;
+
+ bool isFinished;
+ bool reduceResult;
+ uint32 predictNumberResult;
+ GinBtreeData btree;
+} GinScanEntryData;
+
+typedef struct GinScanOpaqueData
+{
+ MemoryContext tempCtx;
+ GinState ginstate;
+
+ GinScanKey keys; /* one per scan qualifier expr */
+ uint32 nkeys;
+
+ GinScanEntry *entries; /* one per index search condition */
+ uint32 totalentries;
+ uint32 allocentries; /* allocated length of entries[] */
+
+ MemoryContext keyCtx; /* used to hold key and entry data */
+
+ bool isVoidRes; /* true if query is unsatisfiable */
+} GinScanOpaqueData;
+
+typedef GinScanOpaqueData *GinScanOpaque;
+
+extern IndexScanDesc ginbeginscan(Relation rel, int nkeys, int norderbys);
+extern void ginendscan(IndexScanDesc scan);
+extern void ginrescan(IndexScanDesc scan, ScanKey key, int nscankeys,
+ ScanKey orderbys, int norderbys);
+extern void ginNewScanKey(IndexScanDesc scan);
+extern void ginFreeScanKeys(GinScanOpaque so);
+
+/* ginget.c */
+extern int64 gingetbitmap(IndexScanDesc scan, TIDBitmap *tbm);
+
+/* ginlogic.c */
+extern void ginInitConsistentFunction(GinState *ginstate, GinScanKey key);
+
+/* ginvacuum.c */
+extern IndexBulkDeleteResult *ginbulkdelete(IndexVacuumInfo *info,
+ IndexBulkDeleteResult *stats,
+ IndexBulkDeleteCallback callback,
+ void *callback_state);
+extern IndexBulkDeleteResult *ginvacuumcleanup(IndexVacuumInfo *info,
+ IndexBulkDeleteResult *stats);
+extern ItemPointer ginVacuumItemPointers(GinVacuumState *gvs,
+ ItemPointerData *items, int nitem, int *nremaining);
+
+/* ginvalidate.c */
+extern bool ginvalidate(Oid opclassoid);
+
+/* ginbulk.c */
+typedef struct GinEntryAccumulator
+{
+ RBTNode rbtnode;
+ Datum key;
+ GinNullCategory category;
+ OffsetNumber attnum;
+ bool shouldSort;
+ ItemPointerData *list;
+ uint32 maxcount; /* allocated size of list[] */
+ uint32 count; /* current number of list[] entries */
+} GinEntryAccumulator;
+
+typedef struct
+{
+ GinState *ginstate;
+ Size allocatedMemory;
+ GinEntryAccumulator *entryallocator;
+ uint32 eas_used;
+ RBTree *tree;
+ RBTreeIterator tree_walk;
+} BuildAccumulator;
+
+extern void ginInitBA(BuildAccumulator *accum);
+extern void ginInsertBAEntries(BuildAccumulator *accum,
+ ItemPointer heapptr, OffsetNumber attnum,
+ Datum *entries, GinNullCategory *categories,
+ int32 nentries);
+extern void ginBeginBAScan(BuildAccumulator *accum);
+extern ItemPointerData *ginGetBAEntry(BuildAccumulator *accum,
+ OffsetNumber *attnum, Datum *key, GinNullCategory *category,
+ uint32 *n);
+
+/* ginfast.c */
+
+typedef struct GinTupleCollector
+{
+ IndexTuple *tuples;
+ uint32 ntuples;
+ uint32 lentuples;
+ uint32 sumsize;
+} GinTupleCollector;
+
+extern void ginHeapTupleFastInsert(GinState *ginstate,
+ GinTupleCollector *collector);
+extern void ginHeapTupleFastCollect(GinState *ginstate,
+ GinTupleCollector *collector,
+ OffsetNumber attnum, Datum value, bool isNull,
+ ItemPointer ht_ctid);
+extern void ginInsertCleanup(GinState *ginstate, bool full_clean,
+ bool fill_fsm, bool forceCleanup, IndexBulkDeleteResult *stats);
+
+/* ginpostinglist.c */
+
+extern GinPostingList *ginCompressPostingList(const ItemPointer ipd, int nipd,
+ int maxsize, int *nwritten);
+extern int ginPostingListDecodeAllSegmentsToTbm(GinPostingList *ptr, int totalsize, TIDBitmap *tbm);
+
+extern ItemPointer ginPostingListDecodeAllSegments(GinPostingList *ptr, int len, int *ndecoded);
+extern ItemPointer ginPostingListDecode(GinPostingList *ptr, int *ndecoded);
+extern ItemPointer ginMergeItemPointers(ItemPointerData *a, uint32 na,
+ ItemPointerData *b, uint32 nb,
+ int *nmerged);
+
+/*
+ * Merging the results of several gin scans compares item pointers a lot,
+ * so we want this to be inlined.
+ */
+static inline int
+ginCompareItemPointers(ItemPointer a, ItemPointer b)
+{
+ uint64 ia = (uint64) GinItemPointerGetBlockNumber(a) << 32 | GinItemPointerGetOffsetNumber(a);
+ uint64 ib = (uint64) GinItemPointerGetBlockNumber(b) << 32 | GinItemPointerGetOffsetNumber(b);
+
+ if (ia == ib)
+ return 0;
+ else if (ia > ib)
+ return 1;
+ else
+ return -1;
+}
+
+extern int ginTraverseLock(Buffer buffer, bool searchMode);
+
+#endif /* GIN_PRIVATE_H */
diff --git a/src/include/access/ginblock.h b/src/include/access/ginblock.h
new file mode 100644
index 0000000..3f64fd5
--- /dev/null
+++ b/src/include/access/ginblock.h
@@ -0,0 +1,346 @@
+/*--------------------------------------------------------------------------
+ * ginblock.h
+ * details of structures stored in GIN index blocks
+ *
+ * Copyright (c) 2006-2020, PostgreSQL Global Development Group
+ *
+ * src/include/access/ginblock.h
+ *--------------------------------------------------------------------------
+ */
+#ifndef GINBLOCK_H
+#define GINBLOCK_H
+
+#include "access/transam.h"
+#include "storage/block.h"
+#include "storage/itemptr.h"
+#include "storage/off.h"
+
+/*
+ * Page opaque data in an inverted index page.
+ *
+ * Note: GIN does not include a page ID word as do the other index types.
+ * This is OK because the opaque data is only 8 bytes and so can be reliably
+ * distinguished by size. Revisit this if the size ever increases.
+ * Further note: as of 9.2, SP-GiST also uses 8-byte special space, as does
+ * BRIN as of 9.5. This is still OK, as long as GIN isn't using all of the
+ * high-order bits in its flags word, because that way the flags word cannot
+ * match the page IDs used by SP-GiST and BRIN.
+ */
+typedef struct GinPageOpaqueData
+{
+ BlockNumber rightlink; /* next page if any */
+ OffsetNumber maxoff; /* number of PostingItems on GIN_DATA &
+ * ~GIN_LEAF page. On GIN_LIST page, number of
+ * heap tuples. */
+ uint16 flags; /* see bit definitions below */
+} GinPageOpaqueData;
+
+typedef GinPageOpaqueData *GinPageOpaque;
+
+#define GIN_DATA (1 << 0)
+#define GIN_LEAF (1 << 1)
+#define GIN_DELETED (1 << 2)
+#define GIN_META (1 << 3)
+#define GIN_LIST (1 << 4)
+#define GIN_LIST_FULLROW (1 << 5) /* makes sense only on GIN_LIST page */
+#define GIN_INCOMPLETE_SPLIT (1 << 6) /* page was split, but parent not
+ * updated */
+#define GIN_COMPRESSED (1 << 7)
+
+/* Page numbers of fixed-location pages */
+#define GIN_METAPAGE_BLKNO (0)
+#define GIN_ROOT_BLKNO (1)
+
+typedef struct GinMetaPageData
+{
+ /*
+ * Pointers to head and tail of pending list, which consists of GIN_LIST
+ * pages. These store fast-inserted entries that haven't yet been moved
+ * into the regular GIN structure.
+ */
+ BlockNumber head;
+ BlockNumber tail;
+
+ /*
+ * Free space in bytes in the pending list's tail page.
+ */
+ uint32 tailFreeSize;
+
+ /*
+ * We store both number of pages and number of heap tuples that are in the
+ * pending list.
+ */
+ BlockNumber nPendingPages;
+ int64 nPendingHeapTuples;
+
+ /*
+ * Statistics for planner use (accurate as of last VACUUM)
+ */
+ BlockNumber nTotalPages;
+ BlockNumber nEntryPages;
+ BlockNumber nDataPages;
+ int64 nEntries;
+
+ /*
+ * GIN version number (ideally this should have been at the front, but too
+ * late now. Don't move it!)
+ *
+ * Currently 2 (for indexes initialized in 9.4 or later)
+ *
+ * Version 1 (indexes initialized in version 9.1, 9.2 or 9.3), is
+ * compatible, but may contain uncompressed posting tree (leaf) pages and
+ * posting lists. They will be converted to compressed format when
+ * modified.
+ *
+ * Version 0 (indexes initialized in 9.0 or before) is compatible but may
+ * be missing null entries, including both null keys and placeholders.
+ * Reject full-index-scan attempts on such indexes.
+ */
+ int32 ginVersion;
+} GinMetaPageData;
+
+#define GIN_CURRENT_VERSION 2
+
+#define GinPageGetMeta(p) \
+ ((GinMetaPageData *) PageGetContents(p))
+
+/*
+ * Macros for accessing a GIN index page's opaque data
+ */
+#define GinPageGetOpaque(page) ( (GinPageOpaque) PageGetSpecialPointer(page) )
+
+#define GinPageIsLeaf(page) ( (GinPageGetOpaque(page)->flags & GIN_LEAF) != 0 )
+#define GinPageSetLeaf(page) ( GinPageGetOpaque(page)->flags |= GIN_LEAF )
+#define GinPageSetNonLeaf(page) ( GinPageGetOpaque(page)->flags &= ~GIN_LEAF )
+#define GinPageIsData(page) ( (GinPageGetOpaque(page)->flags & GIN_DATA) != 0 )
+#define GinPageSetData(page) ( GinPageGetOpaque(page)->flags |= GIN_DATA )
+#define GinPageIsList(page) ( (GinPageGetOpaque(page)->flags & GIN_LIST) != 0 )
+#define GinPageSetList(page) ( GinPageGetOpaque(page)->flags |= GIN_LIST )
+#define GinPageHasFullRow(page) ( (GinPageGetOpaque(page)->flags & GIN_LIST_FULLROW) != 0 )
+#define GinPageSetFullRow(page) ( GinPageGetOpaque(page)->flags |= GIN_LIST_FULLROW )
+#define GinPageIsCompressed(page) ( (GinPageGetOpaque(page)->flags & GIN_COMPRESSED) != 0 )
+#define GinPageSetCompressed(page) ( GinPageGetOpaque(page)->flags |= GIN_COMPRESSED )
+
+#define GinPageIsDeleted(page) ( (GinPageGetOpaque(page)->flags & GIN_DELETED) != 0 )
+#define GinPageSetDeleted(page) ( GinPageGetOpaque(page)->flags |= GIN_DELETED)
+#define GinPageSetNonDeleted(page) ( GinPageGetOpaque(page)->flags &= ~GIN_DELETED)
+#define GinPageIsIncompleteSplit(page) ( (GinPageGetOpaque(page)->flags & GIN_INCOMPLETE_SPLIT) != 0 )
+
+#define GinPageRightMost(page) ( GinPageGetOpaque(page)->rightlink == InvalidBlockNumber)
+
+/*
+ * We should reclaim deleted page only once every transaction started before
+ * its deletion is over.
+ */
+#define GinPageGetDeleteXid(page) ( ((PageHeader) (page))->pd_prune_xid )
+#define GinPageSetDeleteXid(page, xid) ( ((PageHeader) (page))->pd_prune_xid = xid)
+#define GinPageIsRecyclable(page) ( PageIsNew(page) || (GinPageIsDeleted(page) \
+ && TransactionIdPrecedes(GinPageGetDeleteXid(page), RecentGlobalXmin)))
+
+/*
+ * We use our own ItemPointerGet(BlockNumber|OffsetNumber)
+ * to avoid Asserts, since sometimes the ip_posid isn't "valid"
+ */
+#define GinItemPointerGetBlockNumber(pointer) \
+ (ItemPointerGetBlockNumberNoCheck(pointer))
+
+#define GinItemPointerGetOffsetNumber(pointer) \
+ (ItemPointerGetOffsetNumberNoCheck(pointer))
+
+#define GinItemPointerSetBlockNumber(pointer, blkno) \
+ (ItemPointerSetBlockNumber((pointer), (blkno)))
+
+#define GinItemPointerSetOffsetNumber(pointer, offnum) \
+ (ItemPointerSetOffsetNumber((pointer), (offnum)))
+
+
+/*
+ * Special-case item pointer values needed by the GIN search logic.
+ * MIN: sorts less than any valid item pointer
+ * MAX: sorts greater than any valid item pointer
+ * LOSSY PAGE: indicates a whole heap page, sorts after normal item
+ * pointers for that page
+ * Note that these are all distinguishable from an "invalid" item pointer
+ * (which is InvalidBlockNumber/0) as well as from all normal item
+ * pointers (which have item numbers in the range 1..MaxHeapTuplesPerPage).
+ */
+#define ItemPointerSetMin(p) \
+ ItemPointerSet((p), (BlockNumber)0, (OffsetNumber)0)
+#define ItemPointerIsMin(p) \
+ (GinItemPointerGetOffsetNumber(p) == (OffsetNumber)0 && \
+ GinItemPointerGetBlockNumber(p) == (BlockNumber)0)
+#define ItemPointerSetMax(p) \
+ ItemPointerSet((p), InvalidBlockNumber, (OffsetNumber)0xffff)
+#define ItemPointerSetLossyPage(p, b) \
+ ItemPointerSet((p), (b), (OffsetNumber)0xffff)
+#define ItemPointerIsLossyPage(p) \
+ (GinItemPointerGetOffsetNumber(p) == (OffsetNumber)0xffff && \
+ GinItemPointerGetBlockNumber(p) != InvalidBlockNumber)
+
+/*
+ * Posting item in a non-leaf posting-tree page
+ */
+typedef struct
+{
+ /* We use BlockIdData not BlockNumber to avoid padding space wastage */
+ BlockIdData child_blkno;
+ ItemPointerData key;
+} PostingItem;
+
+#define PostingItemGetBlockNumber(pointer) \
+ BlockIdGetBlockNumber(&(pointer)->child_blkno)
+
+#define PostingItemSetBlockNumber(pointer, blockNumber) \
+ BlockIdSet(&((pointer)->child_blkno), (blockNumber))
+
+/*
+ * Category codes to distinguish placeholder nulls from ordinary NULL keys.
+ *
+ * The first two code values were chosen to be compatible with the usual usage
+ * of bool isNull flags. However, casting between bool and GinNullCategory is
+ * risky because of the possibility of different bit patterns and type sizes,
+ * so it is no longer done.
+ *
+ * GIN_CAT_EMPTY_QUERY is never stored in the index; and notice that it is
+ * chosen to sort before not after regular key values.
+ */
+typedef signed char GinNullCategory;
+
+#define GIN_CAT_NORM_KEY 0 /* normal, non-null key value */
+#define GIN_CAT_NULL_KEY 1 /* null key value */
+#define GIN_CAT_EMPTY_ITEM 2 /* placeholder for zero-key item */
+#define GIN_CAT_NULL_ITEM 3 /* placeholder for null item */
+#define GIN_CAT_EMPTY_QUERY (-1) /* placeholder for full-scan query */
+
+/*
+ * Access macros for null category byte in entry tuples
+ */
+#define GinCategoryOffset(itup,ginstate) \
+ (IndexInfoFindDataOffset((itup)->t_info) + \
+ ((ginstate)->oneCol ? 0 : sizeof(int16)))
+#define GinGetNullCategory(itup,ginstate) \
+ (*((GinNullCategory *) ((char*)(itup) + GinCategoryOffset(itup,ginstate))))
+#define GinSetNullCategory(itup,ginstate,c) \
+ (*((GinNullCategory *) ((char*)(itup) + GinCategoryOffset(itup,ginstate))) = (c))
+
+/*
+ * Access macros for leaf-page entry tuples (see discussion in README)
+ */
+#define GinGetNPosting(itup) GinItemPointerGetOffsetNumber(&(itup)->t_tid)
+#define GinSetNPosting(itup,n) ItemPointerSetOffsetNumber(&(itup)->t_tid,n)
+#define GIN_TREE_POSTING ((OffsetNumber)0xffff)
+#define GinIsPostingTree(itup) (GinGetNPosting(itup) == GIN_TREE_POSTING)
+#define GinSetPostingTree(itup, blkno) ( GinSetNPosting((itup),GIN_TREE_POSTING), ItemPointerSetBlockNumber(&(itup)->t_tid, blkno) )
+#define GinGetPostingTree(itup) GinItemPointerGetBlockNumber(&(itup)->t_tid)
+
+#define GIN_ITUP_COMPRESSED (1U << 31)
+#define GinGetPostingOffset(itup) (GinItemPointerGetBlockNumber(&(itup)->t_tid) & (~GIN_ITUP_COMPRESSED))
+#define GinSetPostingOffset(itup,n) ItemPointerSetBlockNumber(&(itup)->t_tid,(n)|GIN_ITUP_COMPRESSED)
+#define GinGetPosting(itup) ((Pointer) ((char*)(itup) + GinGetPostingOffset(itup)))
+#define GinItupIsCompressed(itup) ((GinItemPointerGetBlockNumber(&(itup)->t_tid) & GIN_ITUP_COMPRESSED) != 0)
+
+/*
+ * Maximum size of an item on entry tree page. Make sure that we fit at least
+ * three items on each page. (On regular B-tree indexes, we must fit at least
+ * three items: two data items and the "high key". In GIN entry tree, we don't
+ * currently store the high key explicitly, we just use the rightmost item on
+ * the page, so it would actually be enough to fit two items.)
+ */
+#define GinMaxItemSize \
+ Min(INDEX_SIZE_MASK, \
+ MAXALIGN_DOWN(((BLCKSZ - \
+ MAXALIGN(SizeOfPageHeaderData + 3 * sizeof(ItemIdData)) - \
+ MAXALIGN(sizeof(GinPageOpaqueData))) / 3)))
+
+/*
+ * Access macros for non-leaf entry tuples
+ */
+#define GinGetDownlink(itup) GinItemPointerGetBlockNumber(&(itup)->t_tid)
+#define GinSetDownlink(itup,blkno) ItemPointerSet(&(itup)->t_tid, blkno, InvalidOffsetNumber)
+
+
+/*
+ * Data (posting tree) pages
+ *
+ * Posting tree pages don't store regular tuples. Non-leaf pages contain
+ * PostingItems, which are pairs of ItemPointers and child block numbers.
+ * Leaf pages contain GinPostingLists and an uncompressed array of item
+ * pointers.
+ *
+ * In a leaf page, the compressed posting lists are stored after the regular
+ * page header, one after each other. Although we don't store regular tuples,
+ * pd_lower is used to indicate the end of the posting lists. After that, free
+ * space follows. This layout is compatible with the "standard" heap and
+ * index page layout described in bufpage.h, so that we can e.g set buffer_std
+ * when writing WAL records.
+ *
+ * In the special space is the GinPageOpaque struct.
+ */
+#define GinDataLeafPageGetPostingList(page) \
+ (GinPostingList *) ((PageGetContents(page) + MAXALIGN(sizeof(ItemPointerData))))
+#define GinDataLeafPageGetPostingListSize(page) \
+ (((PageHeader) page)->pd_lower - MAXALIGN(SizeOfPageHeaderData) - MAXALIGN(sizeof(ItemPointerData)))
+
+#define GinDataLeafPageIsEmpty(page) \
+ (GinPageIsCompressed(page) ? (GinDataLeafPageGetPostingListSize(page) == 0) : (GinPageGetOpaque(page)->maxoff < FirstOffsetNumber))
+
+#define GinDataLeafPageGetFreeSpace(page) PageGetExactFreeSpace(page)
+
+#define GinDataPageGetRightBound(page) ((ItemPointer) PageGetContents(page))
+/*
+ * Pointer to the data portion of a posting tree page. For internal pages,
+ * that's the beginning of the array of PostingItems. For compressed leaf
+ * pages, the first compressed posting list. For uncompressed (pre-9.4) leaf
+ * pages, it's the beginning of the ItemPointer array.
+ */
+#define GinDataPageGetData(page) \
+ (PageGetContents(page) + MAXALIGN(sizeof(ItemPointerData)))
+/* non-leaf pages contain PostingItems */
+#define GinDataPageGetPostingItem(page, i) \
+ ((PostingItem *) (GinDataPageGetData(page) + ((i)-1) * sizeof(PostingItem)))
+
+/*
+ * Note: there is no GinDataPageGetDataSize macro, because before version
+ * 9.4, we didn't set pd_lower on data pages. There can be pages in the index
+ * that were binary-upgraded from earlier versions and still have an invalid
+ * pd_lower, so we cannot trust it in general. Compressed posting tree leaf
+ * pages are new in 9.4, however, so we can trust them; see
+ * GinDataLeafPageGetPostingListSize.
+ */
+#define GinDataPageSetDataSize(page, size) \
+ { \
+ Assert(size <= GinDataPageMaxDataSize); \
+ ((PageHeader) page)->pd_lower = (size) + MAXALIGN(SizeOfPageHeaderData) + MAXALIGN(sizeof(ItemPointerData)); \
+ }
+
+#define GinNonLeafDataPageGetFreeSpace(page) \
+ (GinDataPageMaxDataSize - \
+ GinPageGetOpaque(page)->maxoff * sizeof(PostingItem))
+
+#define GinDataPageMaxDataSize \
+ (BLCKSZ - MAXALIGN(SizeOfPageHeaderData) \
+ - MAXALIGN(sizeof(ItemPointerData)) \
+ - MAXALIGN(sizeof(GinPageOpaqueData)))
+
+/*
+ * List pages
+ */
+#define GinListPageSize \
+ ( BLCKSZ - SizeOfPageHeaderData - MAXALIGN(sizeof(GinPageOpaqueData)) )
+
+/*
+ * A compressed posting list.
+ *
+ * Note: This requires 2-byte alignment.
+ */
+typedef struct
+{
+ ItemPointerData first; /* first item in this posting list (unpacked) */
+ uint16 nbytes; /* number of bytes that follow */
+ unsigned char bytes[FLEXIBLE_ARRAY_MEMBER]; /* varbyte encoded items */
+} GinPostingList;
+
+#define SizeOfGinPostingList(plist) (offsetof(GinPostingList, bytes) + SHORTALIGN((plist)->nbytes) )
+#define GinNextPostingListSegment(cur) ((GinPostingList *) (((char *) (cur)) + SizeOfGinPostingList((cur))))
+
+#endif /* GINBLOCK_H */
diff --git a/src/include/access/ginxlog.h b/src/include/access/ginxlog.h
new file mode 100644
index 0000000..a7edf83
--- /dev/null
+++ b/src/include/access/ginxlog.h
@@ -0,0 +1,216 @@
+/*--------------------------------------------------------------------------
+ * ginxlog.h
+ * header file for postgres inverted index xlog implementation.
+ *
+ * Copyright (c) 2006-2020, PostgreSQL Global Development Group
+ *
+ * src/include/access/ginxlog.h
+ *--------------------------------------------------------------------------
+ */
+#ifndef GINXLOG_H
+#define GINXLOG_H
+
+#include "access/ginblock.h"
+#include "access/itup.h"
+#include "access/xlogreader.h"
+#include "lib/stringinfo.h"
+#include "storage/off.h"
+
+#define XLOG_GIN_CREATE_PTREE 0x10
+
+typedef struct ginxlogCreatePostingTree
+{
+ uint32 size;
+ /* A compressed posting list follows */
+} ginxlogCreatePostingTree;
+
+/*
+ * The format of the insertion record varies depending on the page type.
+ * ginxlogInsert is the common part between all variants.
+ *
+ * Backup Blk 0: target page
+ * Backup Blk 1: left child, if this insertion finishes an incomplete split
+ */
+
+#define XLOG_GIN_INSERT 0x20
+
+typedef struct
+{
+ uint16 flags; /* GIN_INSERT_ISLEAF and/or GIN_INSERT_ISDATA */
+
+ /*
+ * FOLLOWS:
+ *
+ * 1. if not leaf page, block numbers of the left and right child pages
+ * whose split this insertion finishes, as BlockIdData[2] (beware of
+ * adding fields in this struct that would make them not 16-bit aligned)
+ *
+ * 2. a ginxlogInsertEntry or ginxlogRecompressDataLeaf struct, depending
+ * on tree type.
+ *
+ * NB: the below structs are only 16-bit aligned when appended to a
+ * ginxlogInsert struct! Beware of adding fields to them that require
+ * stricter alignment.
+ */
+} ginxlogInsert;
+
+typedef struct
+{
+ OffsetNumber offset;
+ bool isDelete;
+ IndexTupleData tuple; /* variable length */
+} ginxlogInsertEntry;
+
+
+typedef struct
+{
+ uint16 nactions;
+
+ /* Variable number of 'actions' follow */
+} ginxlogRecompressDataLeaf;
+
+/*
+ * Note: this struct is currently not used in code, and only acts as
+ * documentation. The WAL record format is as specified here, but the code
+ * uses straight access through a Pointer and memcpy to read/write these.
+ */
+typedef struct
+{
+ uint8 segno; /* segment this action applies to */
+ char type; /* action type (see below) */
+
+ /*
+ * Action-specific data follows. For INSERT and REPLACE actions that is a
+ * GinPostingList struct. For ADDITEMS, a uint16 for the number of items
+ * added, followed by the items themselves as ItemPointers. DELETE actions
+ * have no further data.
+ */
+} ginxlogSegmentAction;
+
+/* Action types */
+#define GIN_SEGMENT_UNMODIFIED 0 /* no action (not used in WAL records) */
+#define GIN_SEGMENT_DELETE 1 /* a whole segment is removed */
+#define GIN_SEGMENT_INSERT 2 /* a whole segment is added */
+#define GIN_SEGMENT_REPLACE 3 /* a segment is replaced */
+#define GIN_SEGMENT_ADDITEMS 4 /* items are added to existing segment */
+
+typedef struct
+{
+ OffsetNumber offset;
+ PostingItem newitem;
+} ginxlogInsertDataInternal;
+
+/*
+ * Backup Blk 0: new left page (= original page, if not root split)
+ * Backup Blk 1: new right page
+ * Backup Blk 2: original page / new root page, if root split
+ * Backup Blk 3: left child, if this insertion completes an earlier split
+ */
+#define XLOG_GIN_SPLIT 0x30
+
+typedef struct ginxlogSplit
+{
+ RelFileNode node;
+ BlockNumber rrlink; /* right link, or root's blocknumber if root
+ * split */
+ BlockNumber leftChildBlkno; /* valid on a non-leaf split */
+ BlockNumber rightChildBlkno;
+ uint16 flags; /* see below */
+} ginxlogSplit;
+
+/*
+ * Flags used in ginxlogInsert and ginxlogSplit records
+ */
+#define GIN_INSERT_ISDATA 0x01 /* for both insert and split records */
+#define GIN_INSERT_ISLEAF 0x02 /* ditto */
+#define GIN_SPLIT_ROOT 0x04 /* only for split records */
+
+/*
+ * Vacuum simply WAL-logs the whole page, when anything is modified. This
+ * is functionally identical to XLOG_FPI records, but is kept separate for
+ * debugging purposes. (When inspecting the WAL stream, it's easier to see
+ * what's going on when GIN vacuum records are marked as such, not as heap
+ * records.) This is currently only used for entry tree leaf pages.
+ */
+#define XLOG_GIN_VACUUM_PAGE 0x40
+
+/*
+ * Vacuuming posting tree leaf page is WAL-logged like recompression caused
+ * by insertion.
+ */
+#define XLOG_GIN_VACUUM_DATA_LEAF_PAGE 0x90
+
+typedef struct ginxlogVacuumDataLeafPage
+{
+ ginxlogRecompressDataLeaf data;
+} ginxlogVacuumDataLeafPage;
+
+/*
+ * Backup Blk 0: deleted page
+ * Backup Blk 1: parent
+ * Backup Blk 2: left sibling
+ */
+#define XLOG_GIN_DELETE_PAGE 0x50
+
+typedef struct ginxlogDeletePage
+{
+ OffsetNumber parentOffset;
+ BlockNumber rightLink;
+ TransactionId deleteXid; /* last Xid which could see this page in scan */
+} ginxlogDeletePage;
+
+#define XLOG_GIN_UPDATE_META_PAGE 0x60
+
+/*
+ * Backup Blk 0: metapage
+ * Backup Blk 1: tail page
+ */
+typedef struct ginxlogUpdateMeta
+{
+ RelFileNode node;
+ GinMetaPageData metadata;
+ BlockNumber prevTail;
+ BlockNumber newRightlink;
+ int32 ntuples; /* if ntuples > 0 then metadata.tail was
+ * updated with that many tuples; else new sub
+ * list was inserted */
+ /* array of inserted tuples follows */
+} ginxlogUpdateMeta;
+
+#define XLOG_GIN_INSERT_LISTPAGE 0x70
+
+typedef struct ginxlogInsertListPage
+{
+ BlockNumber rightlink;
+ int32 ntuples;
+ /* array of inserted tuples follows */
+} ginxlogInsertListPage;
+
+/*
+ * Backup Blk 0: metapage
+ * Backup Blk 1 to (ndeleted + 1): deleted pages
+ */
+
+#define XLOG_GIN_DELETE_LISTPAGE 0x80
+
+/*
+ * The WAL record for deleting list pages must contain a block reference to
+ * all the deleted pages, so the number of pages that can be deleted in one
+ * record is limited by XLR_MAX_BLOCK_ID. (block_id 0 is used for the
+ * metapage.)
+ */
+#define GIN_NDELETE_AT_ONCE Min(16, XLR_MAX_BLOCK_ID - 1)
+typedef struct ginxlogDeleteListPages
+{
+ GinMetaPageData metadata;
+ int32 ndeleted;
+} ginxlogDeleteListPages;
+
+extern void gin_redo(XLogReaderState *record);
+extern void gin_desc(StringInfo buf, XLogReaderState *record);
+extern const char *gin_identify(uint8 info);
+extern void gin_xlog_startup(void);
+extern void gin_xlog_cleanup(void);
+extern void gin_mask(char *pagedata, BlockNumber blkno);
+
+#endif /* GINXLOG_H */
diff --git a/src/include/access/gist.h b/src/include/access/gist.h
new file mode 100644
index 0000000..4994351
--- /dev/null
+++ b/src/include/access/gist.h
@@ -0,0 +1,239 @@
+/*-------------------------------------------------------------------------
+ *
+ * gist.h
+ * The public API for GiST indexes. This API is exposed to
+ * individuals implementing GiST indexes, so backward-incompatible
+ * changes should be made with care.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/gist.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef GIST_H
+#define GIST_H
+
+#include "access/itup.h"
+#include "access/transam.h"
+#include "access/xlog.h"
+#include "access/xlogdefs.h"
+#include "storage/block.h"
+#include "storage/bufpage.h"
+#include "utils/relcache.h"
+
+/*
+ * amproc indexes for GiST indexes.
+ */
+#define GIST_CONSISTENT_PROC 1
+#define GIST_UNION_PROC 2
+#define GIST_COMPRESS_PROC 3
+#define GIST_DECOMPRESS_PROC 4
+#define GIST_PENALTY_PROC 5
+#define GIST_PICKSPLIT_PROC 6
+#define GIST_EQUAL_PROC 7
+#define GIST_DISTANCE_PROC 8
+#define GIST_FETCH_PROC 9
+#define GIST_OPTIONS_PROC 10
+#define GISTNProcs 10
+
+/*
+ * Page opaque data in a GiST index page.
+ */
+#define F_LEAF (1 << 0) /* leaf page */
+#define F_DELETED (1 << 1) /* the page has been deleted */
+#define F_TUPLES_DELETED (1 << 2) /* some tuples on the page were
+ * deleted */
+#define F_FOLLOW_RIGHT (1 << 3) /* page to the right has no downlink */
+#define F_HAS_GARBAGE (1 << 4) /* some tuples on the page are dead,
+ * but not deleted yet */
+
+typedef XLogRecPtr GistNSN;
+
+/*
+ * A bogus LSN / NSN value used during index build. Must be smaller than any
+ * real or fake unlogged LSN, so that after an index build finishes, all the
+ * splits are considered completed.
+ */
+#define GistBuildLSN ((XLogRecPtr) 1)
+
+/*
+ * For on-disk compatibility with pre-9.3 servers, NSN is stored as two
+ * 32-bit fields on disk, same as LSNs.
+ */
+typedef PageXLogRecPtr PageGistNSN;
+
+typedef struct GISTPageOpaqueData
+{
+ PageGistNSN nsn; /* this value must change on page split */
+ BlockNumber rightlink; /* next page if any */
+ uint16 flags; /* see bit definitions above */
+ uint16 gist_page_id; /* for identification of GiST indexes */
+} GISTPageOpaqueData;
+
+typedef GISTPageOpaqueData *GISTPageOpaque;
+
+/*
+ * Maximum possible sizes for GiST index tuple and index key. Calculation is
+ * based on assumption that GiST page should fit at least 4 tuples. In theory,
+ * GiST index can be functional when page can fit 3 tuples. But that seems
+ * rather inefficent, so we use a bit conservative estimate.
+ *
+ * The maximum size of index key is true for unicolumn index. Therefore, this
+ * estimation should be used to figure out which maximum size of GiST index key
+ * makes sense at all. For multicolumn indexes, user might be able to tune
+ * key size using opclass parameters.
+ */
+#define GISTMaxIndexTupleSize \
+ MAXALIGN_DOWN((BLCKSZ - SizeOfPageHeaderData - sizeof(GISTPageOpaqueData)) / \
+ 4 - sizeof(ItemIdData))
+
+#define GISTMaxIndexKeySize \
+ (GISTMaxIndexTupleSize - MAXALIGN(sizeof(IndexTupleData)))
+
+/*
+ * The page ID is for the convenience of pg_filedump and similar utilities,
+ * which otherwise would have a hard time telling pages of different index
+ * types apart. It should be the last 2 bytes on the page. This is more or
+ * less "free" due to alignment considerations.
+ */
+#define GIST_PAGE_ID 0xFF81
+
+/*
+ * This is the Split Vector to be returned by the PickSplit method.
+ * PickSplit should fill the indexes of tuples to go to the left side into
+ * spl_left[], and those to go to the right into spl_right[] (note the method
+ * is responsible for palloc'ing both of these arrays!). The tuple counts
+ * go into spl_nleft/spl_nright, and spl_ldatum/spl_rdatum must be set to
+ * the union keys for each side.
+ *
+ * If spl_ldatum_exists and spl_rdatum_exists are true, then we are performing
+ * a "secondary split" using a non-first index column. In this case some
+ * decisions have already been made about a page split, and the set of tuples
+ * being passed to PickSplit is just the tuples about which we are undecided.
+ * spl_ldatum/spl_rdatum then contain the union keys for the tuples already
+ * chosen to go left or right. Ideally the PickSplit method should take those
+ * keys into account while deciding what to do with the remaining tuples, ie
+ * it should try to "build out" from those unions so as to minimally expand
+ * them. If it does so, it should union the given tuples' keys into the
+ * existing spl_ldatum/spl_rdatum values rather than just setting those values
+ * from scratch, and then set spl_ldatum_exists/spl_rdatum_exists to false to
+ * show it has done this.
+ *
+ * If the PickSplit method fails to clear spl_ldatum_exists/spl_rdatum_exists,
+ * the core GiST code will make its own decision about how to merge the
+ * secondary-split results with the previously-chosen tuples, and will then
+ * recompute the union keys from scratch. This is a workable though often not
+ * optimal approach.
+ */
+typedef struct GIST_SPLITVEC
+{
+ OffsetNumber *spl_left; /* array of entries that go left */
+ int spl_nleft; /* size of this array */
+ Datum spl_ldatum; /* Union of keys in spl_left */
+ bool spl_ldatum_exists; /* true, if spl_ldatum already exists. */
+
+ OffsetNumber *spl_right; /* array of entries that go right */
+ int spl_nright; /* size of the array */
+ Datum spl_rdatum; /* Union of keys in spl_right */
+ bool spl_rdatum_exists; /* true, if spl_rdatum already exists. */
+} GIST_SPLITVEC;
+
+/*
+ * An entry on a GiST node. Contains the key, as well as its own
+ * location (rel,page,offset) which can supply the matching pointer.
+ * leafkey is a flag to tell us if the entry is in a leaf node.
+ */
+typedef struct GISTENTRY
+{
+ Datum key;
+ Relation rel;
+ Page page;
+ OffsetNumber offset;
+ bool leafkey;
+} GISTENTRY;
+
+#define GistPageGetOpaque(page) ( (GISTPageOpaque) PageGetSpecialPointer(page) )
+
+#define GistPageIsLeaf(page) ( GistPageGetOpaque(page)->flags & F_LEAF)
+#define GIST_LEAF(entry) (GistPageIsLeaf((entry)->page))
+
+#define GistPageIsDeleted(page) ( GistPageGetOpaque(page)->flags & F_DELETED)
+
+#define GistTuplesDeleted(page) ( GistPageGetOpaque(page)->flags & F_TUPLES_DELETED)
+#define GistMarkTuplesDeleted(page) ( GistPageGetOpaque(page)->flags |= F_TUPLES_DELETED)
+#define GistClearTuplesDeleted(page) ( GistPageGetOpaque(page)->flags &= ~F_TUPLES_DELETED)
+
+#define GistPageHasGarbage(page) ( GistPageGetOpaque(page)->flags & F_HAS_GARBAGE)
+#define GistMarkPageHasGarbage(page) ( GistPageGetOpaque(page)->flags |= F_HAS_GARBAGE)
+#define GistClearPageHasGarbage(page) ( GistPageGetOpaque(page)->flags &= ~F_HAS_GARBAGE)
+
+#define GistFollowRight(page) ( GistPageGetOpaque(page)->flags & F_FOLLOW_RIGHT)
+#define GistMarkFollowRight(page) ( GistPageGetOpaque(page)->flags |= F_FOLLOW_RIGHT)
+#define GistClearFollowRight(page) ( GistPageGetOpaque(page)->flags &= ~F_FOLLOW_RIGHT)
+
+#define GistPageGetNSN(page) ( PageXLogRecPtrGet(GistPageGetOpaque(page)->nsn))
+#define GistPageSetNSN(page, val) ( PageXLogRecPtrSet(GistPageGetOpaque(page)->nsn, val))
+
+
+/*
+ * On a deleted page, we store this struct. A deleted page doesn't contain any
+ * tuples, so we don't use the normal page layout with line pointers. Instead,
+ * this struct is stored right after the standard page header. pd_lower points
+ * to the end of this struct. If we add fields to this struct in the future, we
+ * can distinguish the old and new formats by pd_lower.
+ */
+typedef struct GISTDeletedPageContents
+{
+ /* last xid which could see the page in a scan */
+ FullTransactionId deleteXid;
+} GISTDeletedPageContents;
+
+static inline void
+GistPageSetDeleted(Page page, FullTransactionId deletexid)
+{
+ Assert(PageIsEmpty(page));
+
+ GistPageGetOpaque(page)->flags |= F_DELETED;
+ ((PageHeader) page)->pd_lower = MAXALIGN(SizeOfPageHeaderData) + sizeof(GISTDeletedPageContents);
+
+ ((GISTDeletedPageContents *) PageGetContents(page))->deleteXid = deletexid;
+}
+
+static inline FullTransactionId
+GistPageGetDeleteXid(Page page)
+{
+ Assert(GistPageIsDeleted(page));
+
+ /* Is the deleteXid field present? */
+ if (((PageHeader) page)->pd_lower >= MAXALIGN(SizeOfPageHeaderData) +
+ offsetof(GISTDeletedPageContents, deleteXid) + sizeof(FullTransactionId))
+ {
+ return ((GISTDeletedPageContents *) PageGetContents(page))->deleteXid;
+ }
+ else
+ return FullTransactionIdFromEpochAndXid(0, FirstNormalTransactionId);
+}
+
+/*
+ * Vector of GISTENTRY structs; user-defined methods union and picksplit
+ * take it as one of their arguments
+ */
+typedef struct
+{
+ int32 n; /* number of elements */
+ GISTENTRY vector[FLEXIBLE_ARRAY_MEMBER];
+} GistEntryVector;
+
+#define GEVHDRSZ (offsetof(GistEntryVector, vector))
+
+/*
+ * macro to initialize a GISTENTRY
+ */
+#define gistentryinit(e, k, r, pg, o, l) \
+ do { (e).key = (k); (e).rel = (r); (e).page = (pg); \
+ (e).offset = (o); (e).leafkey = (l); } while (0)
+
+#endif /* GIST_H */
diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h
new file mode 100644
index 0000000..4bfc628
--- /dev/null
+++ b/src/include/access/gist_private.h
@@ -0,0 +1,563 @@
+/*-------------------------------------------------------------------------
+ *
+ * gist_private.h
+ * private declarations for GiST -- declarations related to the
+ * internal implementation of GiST, not the public API
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/gist_private.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef GIST_PRIVATE_H
+#define GIST_PRIVATE_H
+
+#include "access/amapi.h"
+#include "access/gist.h"
+#include "access/itup.h"
+#include "lib/pairingheap.h"
+#include "storage/bufmgr.h"
+#include "storage/buffile.h"
+#include "utils/hsearch.h"
+#include "access/genam.h"
+
+/*
+ * Maximum number of "halves" a page can be split into in one operation.
+ * Typically a split produces 2 halves, but can be more if keys have very
+ * different lengths, or when inserting multiple keys in one operation (as
+ * when inserting downlinks to an internal node). There is no theoretical
+ * limit on this, but in practice if you get more than a handful page halves
+ * in one split, there's something wrong with the opclass implementation.
+ * GIST_MAX_SPLIT_PAGES is an arbitrary limit on that, used to size some
+ * local arrays used during split. Note that there is also a limit on the
+ * number of buffers that can be held locked at a time, MAX_SIMUL_LWLOCKS,
+ * so if you raise this higher than that limit, you'll just get a different
+ * error.
+ */
+#define GIST_MAX_SPLIT_PAGES 75
+
+/* Buffer lock modes */
+#define GIST_SHARE BUFFER_LOCK_SHARE
+#define GIST_EXCLUSIVE BUFFER_LOCK_EXCLUSIVE
+#define GIST_UNLOCK BUFFER_LOCK_UNLOCK
+
+typedef struct
+{
+ BlockNumber prev;
+ uint32 freespace;
+ char tupledata[FLEXIBLE_ARRAY_MEMBER];
+} GISTNodeBufferPage;
+
+#define BUFFER_PAGE_DATA_OFFSET MAXALIGN(offsetof(GISTNodeBufferPage, tupledata))
+/* Returns free space in node buffer page */
+#define PAGE_FREE_SPACE(nbp) (nbp->freespace)
+/* Checks if node buffer page is empty */
+#define PAGE_IS_EMPTY(nbp) (nbp->freespace == BLCKSZ - BUFFER_PAGE_DATA_OFFSET)
+/* Checks if node buffers page don't contain sufficient space for index tuple */
+#define PAGE_NO_SPACE(nbp, itup) (PAGE_FREE_SPACE(nbp) < \
+ MAXALIGN(IndexTupleSize(itup)))
+
+/*
+ * GISTSTATE: information needed for any GiST index operation
+ *
+ * This struct retains call info for the index's opclass-specific support
+ * functions (per index column), plus the index's tuple descriptor.
+ *
+ * scanCxt holds the GISTSTATE itself as well as any data that lives for the
+ * lifetime of the index operation. We pass this to the support functions
+ * via fn_mcxt, so that they can store scan-lifespan data in it. The
+ * functions are invoked in tempCxt, which is typically short-lifespan
+ * (that is, it's reset after each tuple). However, tempCxt can be the same
+ * as scanCxt if we're not bothering with per-tuple context resets.
+ */
+typedef struct GISTSTATE
+{
+ MemoryContext scanCxt; /* context for scan-lifespan data */
+ MemoryContext tempCxt; /* short-term context for calling functions */
+
+ TupleDesc leafTupdesc; /* index's tuple descriptor */
+ TupleDesc nonLeafTupdesc; /* truncated tuple descriptor for non-leaf
+ * pages */
+ TupleDesc fetchTupdesc; /* tuple descriptor for tuples returned in an
+ * index-only scan */
+
+ FmgrInfo consistentFn[INDEX_MAX_KEYS];
+ FmgrInfo unionFn[INDEX_MAX_KEYS];
+ FmgrInfo compressFn[INDEX_MAX_KEYS];
+ FmgrInfo decompressFn[INDEX_MAX_KEYS];
+ FmgrInfo penaltyFn[INDEX_MAX_KEYS];
+ FmgrInfo picksplitFn[INDEX_MAX_KEYS];
+ FmgrInfo equalFn[INDEX_MAX_KEYS];
+ FmgrInfo distanceFn[INDEX_MAX_KEYS];
+ FmgrInfo fetchFn[INDEX_MAX_KEYS];
+
+ /* Collations to pass to the support functions */
+ Oid supportCollation[INDEX_MAX_KEYS];
+} GISTSTATE;
+
+
+/*
+ * During a GiST index search, we must maintain a queue of unvisited items,
+ * which can be either individual heap tuples or whole index pages. If it
+ * is an ordered search, the unvisited items should be visited in distance
+ * order. Unvisited items at the same distance should be visited in
+ * depth-first order, that is heap items first, then lower index pages, then
+ * upper index pages; this rule avoids doing extra work during a search that
+ * ends early due to LIMIT.
+ *
+ * To perform an ordered search, we use a pairing heap to manage the
+ * distance-order queue. In a non-ordered search (no order-by operators),
+ * we use it to return heap tuples before unvisited index pages, to
+ * ensure depth-first order, but all entries are otherwise considered
+ * equal.
+ */
+
+/* Individual heap tuple to be visited */
+typedef struct GISTSearchHeapItem
+{
+ ItemPointerData heapPtr;
+ bool recheck; /* T if quals must be rechecked */
+ bool recheckDistances; /* T if distances must be rechecked */
+ HeapTuple recontup; /* data reconstructed from the index, used in
+ * index-only scans */
+ OffsetNumber offnum; /* track offset in page to mark tuple as
+ * LP_DEAD */
+} GISTSearchHeapItem;
+
+/* Unvisited item, either index page or heap tuple */
+typedef struct GISTSearchItem
+{
+ pairingheap_node phNode;
+ BlockNumber blkno; /* index page number, or InvalidBlockNumber */
+ union
+ {
+ GistNSN parentlsn; /* parent page's LSN, if index page */
+ /* we must store parentlsn to detect whether a split occurred */
+ GISTSearchHeapItem heap; /* heap info, if heap tuple */
+ } data;
+
+ /* numberOfOrderBys entries */
+ IndexOrderByDistance distances[FLEXIBLE_ARRAY_MEMBER];
+} GISTSearchItem;
+
+#define GISTSearchItemIsHeap(item) ((item).blkno == InvalidBlockNumber)
+
+#define SizeOfGISTSearchItem(n_distances) \
+ (offsetof(GISTSearchItem, distances) + \
+ sizeof(IndexOrderByDistance) * (n_distances))
+
+/*
+ * GISTScanOpaqueData: private state for a scan of a GiST index
+ */
+typedef struct GISTScanOpaqueData
+{
+ GISTSTATE *giststate; /* index information, see above */
+ Oid *orderByTypes; /* datatypes of ORDER BY expressions */
+
+ pairingheap *queue; /* queue of unvisited items */
+ MemoryContext queueCxt; /* context holding the queue */
+ bool qual_ok; /* false if qual can never be satisfied */
+ bool firstCall; /* true until first gistgettuple call */
+
+ /* pre-allocated workspace arrays */
+ IndexOrderByDistance *distances; /* output area for gistindex_keytest */
+
+ /* info about killed items if any (killedItems is NULL if never used) */
+ OffsetNumber *killedItems; /* offset numbers of killed items */
+ int numKilled; /* number of currently stored items */
+ BlockNumber curBlkno; /* current number of block */
+ GistNSN curPageLSN; /* pos in the WAL stream when page was read */
+
+ /* In a non-ordered search, returnable heap items are stored here: */
+ GISTSearchHeapItem pageData[BLCKSZ / sizeof(IndexTupleData)];
+ OffsetNumber nPageData; /* number of valid items in array */
+ OffsetNumber curPageData; /* next item to return */
+ MemoryContext pageDataCxt; /* context holding the fetched tuples, for
+ * index-only scans */
+} GISTScanOpaqueData;
+
+typedef GISTScanOpaqueData *GISTScanOpaque;
+
+/* despite the name, gistxlogPage is not part of any xlog record */
+typedef struct gistxlogPage
+{
+ BlockNumber blkno;
+ int num; /* number of index tuples following */
+} gistxlogPage;
+
+/* SplitedPageLayout - gistSplit function result */
+typedef struct SplitedPageLayout
+{
+ gistxlogPage block;
+ IndexTupleData *list;
+ int lenlist;
+ IndexTuple itup; /* union key for page */
+ Page page; /* to operate */
+ Buffer buffer; /* to write after all proceed */
+
+ struct SplitedPageLayout *next;
+} SplitedPageLayout;
+
+/*
+ * GISTInsertStack used for locking buffers and transfer arguments during
+ * insertion
+ */
+typedef struct GISTInsertStack
+{
+ /* current page */
+ BlockNumber blkno;
+ Buffer buffer;
+ Page page;
+
+ /*
+ * log sequence number from page->lsn to recognize page update and compare
+ * it with page's nsn to recognize page split
+ */
+ GistNSN lsn;
+
+ /*
+ * If set, we split the page while descending the tree to find an
+ * insertion target. It means that we need to retry from the parent,
+ * because the downlink of this page might no longer cover the new key.
+ */
+ bool retry_from_parent;
+
+ /* offset of the downlink in the parent page, that points to this page */
+ OffsetNumber downlinkoffnum;
+
+ /* pointer to parent */
+ struct GISTInsertStack *parent;
+} GISTInsertStack;
+
+/* Working state and results for multi-column split logic in gistsplit.c */
+typedef struct GistSplitVector
+{
+ GIST_SPLITVEC splitVector; /* passed to/from user PickSplit method */
+
+ Datum spl_lattr[INDEX_MAX_KEYS]; /* Union of subkeys in
+ * splitVector.spl_left */
+ bool spl_lisnull[INDEX_MAX_KEYS];
+
+ Datum spl_rattr[INDEX_MAX_KEYS]; /* Union of subkeys in
+ * splitVector.spl_right */
+ bool spl_risnull[INDEX_MAX_KEYS];
+
+ bool *spl_dontcare; /* flags tuples which could go to either side
+ * of the split for zero penalty */
+} GistSplitVector;
+
+typedef struct
+{
+ Relation r;
+ Relation heapRel;
+ Size freespace; /* free space to be left */
+ bool is_build;
+
+ GISTInsertStack *stack;
+} GISTInsertState;
+
+/* root page of a gist index */
+#define GIST_ROOT_BLKNO 0
+
+/*
+ * Before PostgreSQL 9.1, we used to rely on so-called "invalid tuples" on
+ * inner pages to finish crash recovery of incomplete page splits. If a crash
+ * happened in the middle of a page split, so that the downlink pointers were
+ * not yet inserted, crash recovery inserted a special downlink pointer. The
+ * semantics of an invalid tuple was that it if you encounter one in a scan,
+ * it must always be followed, because we don't know if the tuples on the
+ * child page match or not.
+ *
+ * We no longer create such invalid tuples, we now mark the left-half of such
+ * an incomplete split with the F_FOLLOW_RIGHT flag instead, and finish the
+ * split properly the next time we need to insert on that page. To retain
+ * on-disk compatibility for the sake of pg_upgrade, we still store 0xffff as
+ * the offset number of all inner tuples. If we encounter any invalid tuples
+ * with 0xfffe during insertion, we throw an error, though scans still handle
+ * them. You should only encounter invalid tuples if you pg_upgrade a pre-9.1
+ * gist index which already has invalid tuples in it because of a crash. That
+ * should be rare, and you are recommended to REINDEX anyway if you have any
+ * invalid tuples in an index, so throwing an error is as far as we go with
+ * supporting that.
+ */
+#define TUPLE_IS_VALID 0xffff
+#define TUPLE_IS_INVALID 0xfffe
+
+#define GistTupleIsInvalid(itup) ( ItemPointerGetOffsetNumber( &((itup)->t_tid) ) == TUPLE_IS_INVALID )
+#define GistTupleSetValid(itup) ItemPointerSetOffsetNumber( &((itup)->t_tid), TUPLE_IS_VALID )
+
+
+
+
+/*
+ * A buffer attached to an internal node, used when building an index in
+ * buffering mode.
+ */
+typedef struct
+{
+ BlockNumber nodeBlocknum; /* index block # this buffer is for */
+ int32 blocksCount; /* current # of blocks occupied by buffer */
+
+ BlockNumber pageBlocknum; /* temporary file block # */
+ GISTNodeBufferPage *pageBuffer; /* in-memory buffer page */
+
+ /* is this buffer queued for emptying? */
+ bool queuedForEmptying;
+
+ /* is this a temporary copy, not in the hash table? */
+ bool isTemp;
+
+ int level; /* 0 == leaf */
+} GISTNodeBuffer;
+
+/*
+ * Does specified level have buffers? (Beware of multiple evaluation of
+ * arguments.)
+ */
+#define LEVEL_HAS_BUFFERS(nlevel, gfbb) \
+ ((nlevel) != 0 && (nlevel) % (gfbb)->levelStep == 0 && \
+ (nlevel) != (gfbb)->rootlevel)
+
+/* Is specified buffer at least half-filled (should be queued for emptying)? */
+#define BUFFER_HALF_FILLED(nodeBuffer, gfbb) \
+ ((nodeBuffer)->blocksCount > (gfbb)->pagesPerBuffer / 2)
+
+/*
+ * Is specified buffer full? Our buffers can actually grow indefinitely,
+ * beyond the "maximum" size, so this just means whether the buffer has grown
+ * beyond the nominal maximum size.
+ */
+#define BUFFER_OVERFLOWED(nodeBuffer, gfbb) \
+ ((nodeBuffer)->blocksCount > (gfbb)->pagesPerBuffer)
+
+/*
+ * Data structure with general information about build buffers.
+ */
+typedef struct GISTBuildBuffers
+{
+ /* Persistent memory context for the buffers and metadata. */
+ MemoryContext context;
+
+ BufFile *pfile; /* Temporary file to store buffers in */
+ long nFileBlocks; /* Current size of the temporary file */
+
+ /*
+ * resizable array of free blocks.
+ */
+ long *freeBlocks;
+ int nFreeBlocks; /* # of currently free blocks in the array */
+ int freeBlocksLen; /* current allocated length of the array */
+
+ /* Hash for buffers by block number */
+ HTAB *nodeBuffersTab;
+
+ /* List of buffers scheduled for emptying */
+ List *bufferEmptyingQueue;
+
+ /*
+ * Parameters to the buffering build algorithm. levelStep determines which
+ * levels in the tree have buffers, and pagesPerBuffer determines how
+ * large each buffer is.
+ */
+ int levelStep;
+ int pagesPerBuffer;
+
+ /* Array of lists of buffers on each level, for final emptying */
+ List **buffersOnLevels;
+ int buffersOnLevelsLen;
+
+ /*
+ * Dynamically-sized array of buffers that currently have their last page
+ * loaded in main memory.
+ */
+ GISTNodeBuffer **loadedBuffers;
+ int loadedBuffersCount; /* # of entries in loadedBuffers */
+ int loadedBuffersLen; /* allocated size of loadedBuffers */
+
+ /* Level of the current root node (= height of the index tree - 1) */
+ int rootlevel;
+} GISTBuildBuffers;
+
+/* GiSTOptions->buffering_mode values */
+typedef enum GistOptBufferingMode
+{
+ GIST_OPTION_BUFFERING_AUTO,
+ GIST_OPTION_BUFFERING_ON,
+ GIST_OPTION_BUFFERING_OFF
+} GistOptBufferingMode;
+
+/*
+ * Storage type for GiST's reloptions
+ */
+typedef struct GiSTOptions
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ int fillfactor; /* page fill factor in percent (0..100) */
+ GistOptBufferingMode buffering_mode; /* buffering build mode */
+} GiSTOptions;
+
+/* gist.c */
+extern void gistbuildempty(Relation index);
+extern bool gistinsert(Relation r, Datum *values, bool *isnull,
+ ItemPointer ht_ctid, Relation heapRel,
+ IndexUniqueCheck checkUnique,
+ struct IndexInfo *indexInfo);
+extern MemoryContext createTempGistContext(void);
+extern GISTSTATE *initGISTstate(Relation index);
+extern void freeGISTstate(GISTSTATE *giststate);
+extern void gistdoinsert(Relation r,
+ IndexTuple itup,
+ Size freespace,
+ GISTSTATE *giststate,
+ Relation heapRel,
+ bool is_build);
+
+/* A List of these is returned from gistplacetopage() in *splitinfo */
+typedef struct
+{
+ Buffer buf; /* the split page "half" */
+ IndexTuple downlink; /* downlink for this half. */
+} GISTPageSplitInfo;
+
+extern bool gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
+ Buffer buffer,
+ IndexTuple *itup, int ntup,
+ OffsetNumber oldoffnum, BlockNumber *newblkno,
+ Buffer leftchildbuf,
+ List **splitinfo,
+ bool markfollowright,
+ Relation heapRel,
+ bool is_build);
+
+extern SplitedPageLayout *gistSplit(Relation r, Page page, IndexTuple *itup,
+ int len, GISTSTATE *giststate);
+
+/* gistxlog.c */
+extern XLogRecPtr gistXLogPageDelete(Buffer buffer,
+ FullTransactionId xid, Buffer parentBuffer,
+ OffsetNumber downlinkOffset);
+
+extern void gistXLogPageReuse(Relation rel, BlockNumber blkno,
+ FullTransactionId latestRemovedXid);
+
+extern XLogRecPtr gistXLogUpdate(Buffer buffer,
+ OffsetNumber *todelete, int ntodelete,
+ IndexTuple *itup, int ntup,
+ Buffer leftchild);
+
+extern XLogRecPtr gistXLogDelete(Buffer buffer, OffsetNumber *todelete,
+ int ntodelete, TransactionId latestRemovedXid);
+
+extern XLogRecPtr gistXLogSplit(bool page_is_leaf,
+ SplitedPageLayout *dist,
+ BlockNumber origrlink, GistNSN oldnsn,
+ Buffer leftchild, bool markfollowright);
+
+extern XLogRecPtr gistXLogAssignLSN(void);
+
+/* gistget.c */
+extern bool gistgettuple(IndexScanDesc scan, ScanDirection dir);
+extern int64 gistgetbitmap(IndexScanDesc scan, TIDBitmap *tbm);
+extern bool gistcanreturn(Relation index, int attno);
+
+/* gistvalidate.c */
+extern bool gistvalidate(Oid opclassoid);
+
+/* gistutil.c */
+
+#define GiSTPageSize \
+ ( BLCKSZ - SizeOfPageHeaderData - MAXALIGN(sizeof(GISTPageOpaqueData)) )
+
+#define GIST_MIN_FILLFACTOR 10
+#define GIST_DEFAULT_FILLFACTOR 90
+
+extern bytea *gistoptions(Datum reloptions, bool validate);
+extern bool gistproperty(Oid index_oid, int attno,
+ IndexAMProperty prop, const char *propname,
+ bool *res, bool *isnull);
+extern bool gistfitpage(IndexTuple *itvec, int len);
+extern bool gistnospace(Page page, IndexTuple *itvec, int len, OffsetNumber todelete, Size freespace);
+extern void gistcheckpage(Relation rel, Buffer buf);
+extern Buffer gistNewBuffer(Relation r);
+extern bool gistPageRecyclable(Page page);
+extern void gistfillbuffer(Page page, IndexTuple *itup, int len,
+ OffsetNumber off);
+extern IndexTuple *gistextractpage(Page page, int *len /* out */ );
+extern IndexTuple *gistjoinvector(IndexTuple *itvec, int *len,
+ IndexTuple *additvec, int addlen);
+extern IndexTupleData *gistfillitupvec(IndexTuple *vec, int veclen, int *memlen);
+
+extern IndexTuple gistunion(Relation r, IndexTuple *itvec,
+ int len, GISTSTATE *giststate);
+extern IndexTuple gistgetadjusted(Relation r,
+ IndexTuple oldtup,
+ IndexTuple addtup,
+ GISTSTATE *giststate);
+extern IndexTuple gistFormTuple(GISTSTATE *giststate,
+ Relation r, Datum *attdata, bool *isnull, bool isleaf);
+
+extern OffsetNumber gistchoose(Relation r, Page p,
+ IndexTuple it,
+ GISTSTATE *giststate);
+
+extern void GISTInitBuffer(Buffer b, uint32 f);
+extern void gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e,
+ Datum k, Relation r, Page pg, OffsetNumber o,
+ bool l, bool isNull);
+
+extern float gistpenalty(GISTSTATE *giststate, int attno,
+ GISTENTRY *key1, bool isNull1,
+ GISTENTRY *key2, bool isNull2);
+extern void gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len,
+ Datum *attr, bool *isnull);
+extern bool gistKeyIsEQ(GISTSTATE *giststate, int attno, Datum a, Datum b);
+extern void gistDeCompressAtt(GISTSTATE *giststate, Relation r, IndexTuple tuple, Page p,
+ OffsetNumber o, GISTENTRY *attdata, bool *isnull);
+extern HeapTuple gistFetchTuple(GISTSTATE *giststate, Relation r,
+ IndexTuple tuple);
+extern void gistMakeUnionKey(GISTSTATE *giststate, int attno,
+ GISTENTRY *entry1, bool isnull1,
+ GISTENTRY *entry2, bool isnull2,
+ Datum *dst, bool *dstisnull);
+
+extern XLogRecPtr gistGetFakeLSN(Relation rel);
+
+/* gistvacuum.c */
+extern IndexBulkDeleteResult *gistbulkdelete(IndexVacuumInfo *info,
+ IndexBulkDeleteResult *stats,
+ IndexBulkDeleteCallback callback,
+ void *callback_state);
+extern IndexBulkDeleteResult *gistvacuumcleanup(IndexVacuumInfo *info,
+ IndexBulkDeleteResult *stats);
+
+/* gistsplit.c */
+extern void gistSplitByKey(Relation r, Page page, IndexTuple *itup,
+ int len, GISTSTATE *giststate,
+ GistSplitVector *v,
+ int attno);
+
+/* gistbuild.c */
+extern IndexBuildResult *gistbuild(Relation heap, Relation index,
+ struct IndexInfo *indexInfo);
+extern void gistValidateBufferingOption(const char *value);
+
+/* gistbuildbuffers.c */
+extern GISTBuildBuffers *gistInitBuildBuffers(int pagesPerBuffer, int levelStep,
+ int maxLevel);
+extern GISTNodeBuffer *gistGetNodeBuffer(GISTBuildBuffers *gfbb,
+ GISTSTATE *giststate,
+ BlockNumber blkno, int level);
+extern void gistPushItupToNodeBuffer(GISTBuildBuffers *gfbb,
+ GISTNodeBuffer *nodeBuffer, IndexTuple item);
+extern bool gistPopItupFromNodeBuffer(GISTBuildBuffers *gfbb,
+ GISTNodeBuffer *nodeBuffer, IndexTuple *item);
+extern void gistFreeBuildBuffers(GISTBuildBuffers *gfbb);
+extern void gistRelocateBuildBuffersOnSplit(GISTBuildBuffers *gfbb,
+ GISTSTATE *giststate, Relation r,
+ int level, Buffer buffer,
+ List *splitinfo);
+extern void gistUnloadNodeBuffers(GISTBuildBuffers *gfbb);
+
+#endif /* GIST_PRIVATE_H */
diff --git a/src/include/access/gistscan.h b/src/include/access/gistscan.h
new file mode 100644
index 0000000..deeb4d0
--- /dev/null
+++ b/src/include/access/gistscan.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * gistscan.h
+ * routines defined in access/gist/gistscan.c
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/gistscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef GISTSCAN_H
+#define GISTSCAN_H
+
+#include "access/amapi.h"
+
+extern IndexScanDesc gistbeginscan(Relation r, int nkeys, int norderbys);
+extern void gistrescan(IndexScanDesc scan, ScanKey key, int nkeys,
+ ScanKey orderbys, int norderbys);
+extern void gistendscan(IndexScanDesc scan);
+
+#endif /* GISTSCAN_H */
diff --git a/src/include/access/gistxlog.h b/src/include/access/gistxlog.h
new file mode 100644
index 0000000..673afee
--- /dev/null
+++ b/src/include/access/gistxlog.h
@@ -0,0 +1,114 @@
+/*-------------------------------------------------------------------------
+ *
+ * gistxlog.h
+ * gist xlog routines
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/gistxlog.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef GIST_XLOG_H
+#define GIST_XLOG_H
+
+#include "access/gist.h"
+#include "access/xlogreader.h"
+#include "lib/stringinfo.h"
+
+#define XLOG_GIST_PAGE_UPDATE 0x00
+#define XLOG_GIST_DELETE 0x10 /* delete leaf index tuples for a
+ * page */
+#define XLOG_GIST_PAGE_REUSE 0x20 /* old page is about to be reused
+ * from FSM */
+#define XLOG_GIST_PAGE_SPLIT 0x30
+ /* #define XLOG_GIST_INSERT_COMPLETE 0x40 */ /* not used anymore */
+ /* #define XLOG_GIST_CREATE_INDEX 0x50 */ /* not used anymore */
+#define XLOG_GIST_PAGE_DELETE 0x60
+#define XLOG_GIST_ASSIGN_LSN 0x70 /* nop, assign new LSN */
+
+/*
+ * Backup Blk 0: updated page.
+ * Backup Blk 1: If this operation completes a page split, by inserting a
+ * downlink for the split page, the left half of the split
+ */
+typedef struct gistxlogPageUpdate
+{
+ /* number of deleted offsets */
+ uint16 ntodelete;
+ uint16 ntoinsert;
+
+ /*
+ * In payload of blk 0 : 1. todelete OffsetNumbers 2. tuples to insert
+ */
+} gistxlogPageUpdate;
+
+/*
+ * Backup Blk 0: Leaf page, whose index tuples are deleted.
+ */
+typedef struct gistxlogDelete
+{
+ TransactionId latestRemovedXid;
+ uint16 ntodelete; /* number of deleted offsets */
+
+ /*
+ * In payload of blk 0 : todelete OffsetNumbers
+ */
+} gistxlogDelete;
+
+#define SizeOfGistxlogDelete (offsetof(gistxlogDelete, ntodelete) + sizeof(uint16))
+
+/*
+ * Backup Blk 0: If this operation completes a page split, by inserting a
+ * downlink for the split page, the left half of the split
+ * Backup Blk 1 - npage: split pages (1 is the original page)
+ */
+typedef struct gistxlogPageSplit
+{
+ BlockNumber origrlink; /* rightlink of the page before split */
+ GistNSN orignsn; /* NSN of the page before split */
+ bool origleaf; /* was splitted page a leaf page? */
+
+ uint16 npage; /* # of pages in the split */
+ bool markfollowright; /* set F_FOLLOW_RIGHT flags */
+
+ /*
+ * follow: 1. gistxlogPage and array of IndexTupleData per page
+ */
+} gistxlogPageSplit;
+
+/*
+ * Backup Blk 0: page that was deleted.
+ * Backup Blk 1: parent page, containing the downlink to the deleted page.
+ */
+typedef struct gistxlogPageDelete
+{
+ FullTransactionId deleteXid; /* last Xid which could see page in scan */
+ OffsetNumber downlinkOffset; /* Offset of downlink referencing this
+ * page */
+} gistxlogPageDelete;
+
+#define SizeOfGistxlogPageDelete (offsetof(gistxlogPageDelete, downlinkOffset) + sizeof(OffsetNumber))
+
+
+/*
+ * This is what we need to know about page reuse, for hot standby.
+ */
+typedef struct gistxlogPageReuse
+{
+ RelFileNode node;
+ BlockNumber block;
+ FullTransactionId latestRemovedFullXid;
+} gistxlogPageReuse;
+
+#define SizeOfGistxlogPageReuse (offsetof(gistxlogPageReuse, latestRemovedFullXid) + sizeof(FullTransactionId))
+
+extern void gist_redo(XLogReaderState *record);
+extern void gist_desc(StringInfo buf, XLogReaderState *record);
+extern const char *gist_identify(uint8 info);
+extern void gist_xlog_startup(void);
+extern void gist_xlog_cleanup(void);
+extern void gist_mask(char *pagedata, BlockNumber blkno);
+
+#endif
diff --git a/src/include/access/hash.h b/src/include/access/hash.h
new file mode 100644
index 0000000..7e7b1b7
--- /dev/null
+++ b/src/include/access/hash.h
@@ -0,0 +1,478 @@
+/*-------------------------------------------------------------------------
+ *
+ * hash.h
+ * header file for postgres hash access method implementation
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/hash.h
+ *
+ * NOTES
+ * modeled after Margo Seltzer's hash implementation for unix.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef HASH_H
+#define HASH_H
+
+#include "access/amapi.h"
+#include "access/itup.h"
+#include "access/sdir.h"
+#include "catalog/pg_am_d.h"
+#include "common/hashfn.h"
+#include "lib/stringinfo.h"
+#include "storage/bufmgr.h"
+#include "storage/lockdefs.h"
+#include "utils/hsearch.h"
+#include "utils/relcache.h"
+
+/*
+ * Mapping from hash bucket number to physical block number of bucket's
+ * starting page. Beware of multiple evaluations of argument!
+ */
+typedef uint32 Bucket;
+
+#define InvalidBucket ((Bucket) 0xFFFFFFFF)
+
+#define BUCKET_TO_BLKNO(metap,B) \
+ ((BlockNumber) ((B) + ((B) ? (metap)->hashm_spares[_hash_spareindex((B)+1)-1] : 0)) + 1)
+
+/*
+ * Special space for hash index pages.
+ *
+ * hasho_flag's LH_PAGE_TYPE bits tell us which type of page we're looking at.
+ * Additional bits in the flag word are used for more transient purposes.
+ *
+ * To test a page's type, do (hasho_flag & LH_PAGE_TYPE) == LH_xxx_PAGE.
+ * However, we ensure that each used page type has a distinct bit so that
+ * we can OR together page types for uses such as the allowable-page-types
+ * argument of _hash_checkpage().
+ */
+#define LH_UNUSED_PAGE (0)
+#define LH_OVERFLOW_PAGE (1 << 0)
+#define LH_BUCKET_PAGE (1 << 1)
+#define LH_BITMAP_PAGE (1 << 2)
+#define LH_META_PAGE (1 << 3)
+#define LH_BUCKET_BEING_POPULATED (1 << 4)
+#define LH_BUCKET_BEING_SPLIT (1 << 5)
+#define LH_BUCKET_NEEDS_SPLIT_CLEANUP (1 << 6)
+#define LH_PAGE_HAS_DEAD_TUPLES (1 << 7)
+
+#define LH_PAGE_TYPE \
+ (LH_OVERFLOW_PAGE | LH_BUCKET_PAGE | LH_BITMAP_PAGE | LH_META_PAGE)
+
+/*
+ * In an overflow page, hasho_prevblkno stores the block number of the previous
+ * page in the bucket chain; in a bucket page, hasho_prevblkno stores the
+ * hashm_maxbucket value as of the last time the bucket was last split, or
+ * else as of the time the bucket was created. The latter convention is used
+ * to determine whether a cached copy of the metapage is too stale to be used
+ * without needing to lock or pin the metapage.
+ *
+ * hasho_nextblkno is always the block number of the next page in the
+ * bucket chain, or InvalidBlockNumber if there are no more such pages.
+ */
+typedef struct HashPageOpaqueData
+{
+ BlockNumber hasho_prevblkno; /* see above */
+ BlockNumber hasho_nextblkno; /* see above */
+ Bucket hasho_bucket; /* bucket number this pg belongs to */
+ uint16 hasho_flag; /* page type code + flag bits, see above */
+ uint16 hasho_page_id; /* for identification of hash indexes */
+} HashPageOpaqueData;
+
+typedef HashPageOpaqueData *HashPageOpaque;
+
+#define H_NEEDS_SPLIT_CLEANUP(opaque) (((opaque)->hasho_flag & LH_BUCKET_NEEDS_SPLIT_CLEANUP) != 0)
+#define H_BUCKET_BEING_SPLIT(opaque) (((opaque)->hasho_flag & LH_BUCKET_BEING_SPLIT) != 0)
+#define H_BUCKET_BEING_POPULATED(opaque) (((opaque)->hasho_flag & LH_BUCKET_BEING_POPULATED) != 0)
+#define H_HAS_DEAD_TUPLES(opaque) (((opaque)->hasho_flag & LH_PAGE_HAS_DEAD_TUPLES) != 0)
+
+/*
+ * The page ID is for the convenience of pg_filedump and similar utilities,
+ * which otherwise would have a hard time telling pages of different index
+ * types apart. It should be the last 2 bytes on the page. This is more or
+ * less "free" due to alignment considerations.
+ */
+#define HASHO_PAGE_ID 0xFF80
+
+typedef struct HashScanPosItem /* what we remember about each match */
+{
+ ItemPointerData heapTid; /* TID of referenced heap item */
+ OffsetNumber indexOffset; /* index item's location within page */
+} HashScanPosItem;
+
+typedef struct HashScanPosData
+{
+ Buffer buf; /* if valid, the buffer is pinned */
+ BlockNumber currPage; /* current hash index page */
+ BlockNumber nextPage; /* next overflow page */
+ BlockNumber prevPage; /* prev overflow or bucket page */
+
+ /*
+ * The items array is always ordered in index order (ie, increasing
+ * indexoffset). When scanning backwards it is convenient to fill the
+ * array back-to-front, so we start at the last slot and fill downwards.
+ * Hence we need both a first-valid-entry and a last-valid-entry counter.
+ * itemIndex is a cursor showing which entry was last returned to caller.
+ */
+ int firstItem; /* first valid index in items[] */
+ int lastItem; /* last valid index in items[] */
+ int itemIndex; /* current index in items[] */
+
+ HashScanPosItem items[MaxIndexTuplesPerPage]; /* MUST BE LAST */
+} HashScanPosData;
+
+#define HashScanPosIsPinned(scanpos) \
+( \
+ AssertMacro(BlockNumberIsValid((scanpos).currPage) || \
+ !BufferIsValid((scanpos).buf)), \
+ BufferIsValid((scanpos).buf) \
+)
+
+#define HashScanPosIsValid(scanpos) \
+( \
+ AssertMacro(BlockNumberIsValid((scanpos).currPage) || \
+ !BufferIsValid((scanpos).buf)), \
+ BlockNumberIsValid((scanpos).currPage) \
+)
+
+#define HashScanPosInvalidate(scanpos) \
+ do { \
+ (scanpos).buf = InvalidBuffer; \
+ (scanpos).currPage = InvalidBlockNumber; \
+ (scanpos).nextPage = InvalidBlockNumber; \
+ (scanpos).prevPage = InvalidBlockNumber; \
+ (scanpos).firstItem = 0; \
+ (scanpos).lastItem = 0; \
+ (scanpos).itemIndex = 0; \
+ } while (0)
+
+/*
+ * HashScanOpaqueData is private state for a hash index scan.
+ */
+typedef struct HashScanOpaqueData
+{
+ /* Hash value of the scan key, ie, the hash key we seek */
+ uint32 hashso_sk_hash;
+
+ /* remember the buffer associated with primary bucket */
+ Buffer hashso_bucket_buf;
+
+ /*
+ * remember the buffer associated with primary bucket page of bucket being
+ * split. it is required during the scan of the bucket which is being
+ * populated during split operation.
+ */
+ Buffer hashso_split_bucket_buf;
+
+ /* Whether scan starts on bucket being populated due to split */
+ bool hashso_buc_populated;
+
+ /*
+ * Whether scanning bucket being split? The value of this parameter is
+ * referred only when hashso_buc_populated is true.
+ */
+ bool hashso_buc_split;
+ /* info about killed items if any (killedItems is NULL if never used) */
+ int *killedItems; /* currPos.items indexes of killed items */
+ int numKilled; /* number of currently stored items */
+
+ /*
+ * Identify all the matching items on a page and save them in
+ * HashScanPosData
+ */
+ HashScanPosData currPos; /* current position data */
+} HashScanOpaqueData;
+
+typedef HashScanOpaqueData *HashScanOpaque;
+
+/*
+ * Definitions for metapage.
+ */
+
+#define HASH_METAPAGE 0 /* metapage is always block 0 */
+
+#define HASH_MAGIC 0x6440640
+#define HASH_VERSION 4
+
+/*
+ * spares[] holds the number of overflow pages currently allocated at or
+ * before a certain splitpoint. For example, if spares[3] = 7 then there are
+ * 7 ovflpages before splitpoint 3 (compare BUCKET_TO_BLKNO macro). The
+ * value in spares[ovflpoint] increases as overflow pages are added at the
+ * end of the index. Once ovflpoint increases (ie, we have actually allocated
+ * the bucket pages belonging to that splitpoint) the number of spares at the
+ * prior splitpoint cannot change anymore.
+ *
+ * ovflpages that have been recycled for reuse can be found by looking at
+ * bitmaps that are stored within ovflpages dedicated for the purpose.
+ * The blknos of these bitmap pages are kept in mapp[]; nmaps is the
+ * number of currently existing bitmaps.
+ *
+ * The limitation on the size of spares[] comes from the fact that there's
+ * no point in having more than 2^32 buckets with only uint32 hashcodes.
+ * (Note: The value of HASH_MAX_SPLITPOINTS which is the size of spares[] is
+ * adjusted in such a way to accommodate multi phased allocation of buckets
+ * after HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE).
+ *
+ * There is no particular upper limit on the size of mapp[], other than
+ * needing to fit into the metapage. (With 8K block size, 1024 bitmaps
+ * limit us to 256 GB of overflow space...). For smaller block size we
+ * can not use 1024 bitmaps as it will lead to the meta page data crossing
+ * the block size boundary. So we use BLCKSZ to determine the maximum number
+ * of bitmaps.
+ */
+#define HASH_MAX_BITMAPS Min(BLCKSZ / 8, 1024)
+
+#define HASH_SPLITPOINT_PHASE_BITS 2
+#define HASH_SPLITPOINT_PHASES_PER_GRP (1 << HASH_SPLITPOINT_PHASE_BITS)
+#define HASH_SPLITPOINT_PHASE_MASK (HASH_SPLITPOINT_PHASES_PER_GRP - 1)
+#define HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE 10
+
+/* defines max number of splitpoint phases a hash index can have */
+#define HASH_MAX_SPLITPOINT_GROUP 32
+#define HASH_MAX_SPLITPOINTS \
+ (((HASH_MAX_SPLITPOINT_GROUP - HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE) * \
+ HASH_SPLITPOINT_PHASES_PER_GRP) + \
+ HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE)
+
+typedef struct HashMetaPageData
+{
+ uint32 hashm_magic; /* magic no. for hash tables */
+ uint32 hashm_version; /* version ID */
+ double hashm_ntuples; /* number of tuples stored in the table */
+ uint16 hashm_ffactor; /* target fill factor (tuples/bucket) */
+ uint16 hashm_bsize; /* index page size (bytes) */
+ uint16 hashm_bmsize; /* bitmap array size (bytes) - must be a power
+ * of 2 */
+ uint16 hashm_bmshift; /* log2(bitmap array size in BITS) */
+ uint32 hashm_maxbucket; /* ID of maximum bucket in use */
+ uint32 hashm_highmask; /* mask to modulo into entire table */
+ uint32 hashm_lowmask; /* mask to modulo into lower half of table */
+ uint32 hashm_ovflpoint; /* splitpoint from which ovflpage being
+ * allocated */
+ uint32 hashm_firstfree; /* lowest-number free ovflpage (bit#) */
+ uint32 hashm_nmaps; /* number of bitmap pages */
+ RegProcedure hashm_procid; /* hash function id from pg_proc */
+ uint32 hashm_spares[HASH_MAX_SPLITPOINTS]; /* spare pages before each
+ * splitpoint */
+ BlockNumber hashm_mapp[HASH_MAX_BITMAPS]; /* blknos of ovfl bitmaps */
+} HashMetaPageData;
+
+typedef HashMetaPageData *HashMetaPage;
+
+typedef struct HashOptions
+{
+ int32 varlena_header_; /* varlena header (do not touch directly!) */
+ int fillfactor; /* page fill factor in percent (0..100) */
+} HashOptions;
+
+#define HashGetFillFactor(relation) \
+ (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \
+ relation->rd_rel->relam == HASH_AM_OID), \
+ (relation)->rd_options ? \
+ ((HashOptions *) (relation)->rd_options)->fillfactor : \
+ HASH_DEFAULT_FILLFACTOR)
+#define HashGetTargetPageUsage(relation) \
+ (BLCKSZ * HashGetFillFactor(relation) / 100)
+
+/*
+ * Maximum size of a hash index item (it's okay to have only one per page)
+ */
+#define HashMaxItemSize(page) \
+ MAXALIGN_DOWN(PageGetPageSize(page) - \
+ SizeOfPageHeaderData - \
+ sizeof(ItemIdData) - \
+ MAXALIGN(sizeof(HashPageOpaqueData)))
+
+#define INDEX_MOVED_BY_SPLIT_MASK INDEX_AM_RESERVED_BIT
+
+#define HASH_MIN_FILLFACTOR 10
+#define HASH_DEFAULT_FILLFACTOR 75
+
+/*
+ * Constants
+ */
+#define BYTE_TO_BIT 3 /* 2^3 bits/byte */
+#define ALL_SET ((uint32) ~0)
+
+/*
+ * Bitmap pages do not contain tuples. They do contain the standard
+ * page headers and trailers; however, everything in between is a
+ * giant bit array. The number of bits that fit on a page obviously
+ * depends on the page size and the header/trailer overhead. We require
+ * the number of bits per page to be a power of 2.
+ */
+#define BMPGSZ_BYTE(metap) ((metap)->hashm_bmsize)
+#define BMPGSZ_BIT(metap) ((metap)->hashm_bmsize << BYTE_TO_BIT)
+#define BMPG_SHIFT(metap) ((metap)->hashm_bmshift)
+#define BMPG_MASK(metap) (BMPGSZ_BIT(metap) - 1)
+
+#define HashPageGetBitmap(page) \
+ ((uint32 *) PageGetContents(page))
+
+#define HashGetMaxBitmapSize(page) \
+ (PageGetPageSize((Page) page) - \
+ (MAXALIGN(SizeOfPageHeaderData) + MAXALIGN(sizeof(HashPageOpaqueData))))
+
+#define HashPageGetMeta(page) \
+ ((HashMetaPage) PageGetContents(page))
+
+/*
+ * The number of bits in an ovflpage bitmap word.
+ */
+#define BITS_PER_MAP 32 /* Number of bits in uint32 */
+
+/* Given the address of the beginning of a bit map, clear/set the nth bit */
+#define CLRBIT(A, N) ((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP)))
+#define SETBIT(A, N) ((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP)))
+#define ISSET(A, N) ((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP)))
+
+/*
+ * page-level and high-level locking modes (see README)
+ */
+#define HASH_READ BUFFER_LOCK_SHARE
+#define HASH_WRITE BUFFER_LOCK_EXCLUSIVE
+#define HASH_NOLOCK (-1)
+
+/*
+ * When a new operator class is declared, we require that the user supply
+ * us with an amproc function for hashing a key of the new type, returning
+ * a 32-bit hash value. We call this the "standard" hash function. We
+ * also allow an optional "extended" hash function which accepts a salt and
+ * returns a 64-bit hash value. This is highly recommended but, for reasons
+ * of backward compatibility, optional.
+ *
+ * When the salt is 0, the low 32 bits of the value returned by the extended
+ * hash function should match the value that would have been returned by the
+ * standard hash function.
+ */
+#define HASHSTANDARD_PROC 1
+#define HASHEXTENDED_PROC 2
+#define HASHOPTIONS_PROC 3
+#define HASHNProcs 3
+
+
+/* public routines */
+
+extern IndexBuildResult *hashbuild(Relation heap, Relation index,
+ struct IndexInfo *indexInfo);
+extern void hashbuildempty(Relation index);
+extern bool hashinsert(Relation rel, Datum *values, bool *isnull,
+ ItemPointer ht_ctid, Relation heapRel,
+ IndexUniqueCheck checkUnique,
+ struct IndexInfo *indexInfo);
+extern bool hashgettuple(IndexScanDesc scan, ScanDirection dir);
+extern int64 hashgetbitmap(IndexScanDesc scan, TIDBitmap *tbm);
+extern IndexScanDesc hashbeginscan(Relation rel, int nkeys, int norderbys);
+extern void hashrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
+ ScanKey orderbys, int norderbys);
+extern void hashendscan(IndexScanDesc scan);
+extern IndexBulkDeleteResult *hashbulkdelete(IndexVacuumInfo *info,
+ IndexBulkDeleteResult *stats,
+ IndexBulkDeleteCallback callback,
+ void *callback_state);
+extern IndexBulkDeleteResult *hashvacuumcleanup(IndexVacuumInfo *info,
+ IndexBulkDeleteResult *stats);
+extern bytea *hashoptions(Datum reloptions, bool validate);
+extern bool hashvalidate(Oid opclassoid);
+
+/* private routines */
+
+/* hashinsert.c */
+extern void _hash_doinsert(Relation rel, IndexTuple itup, Relation heapRel);
+extern OffsetNumber _hash_pgaddtup(Relation rel, Buffer buf,
+ Size itemsize, IndexTuple itup);
+extern void _hash_pgaddmultitup(Relation rel, Buffer buf, IndexTuple *itups,
+ OffsetNumber *itup_offsets, uint16 nitups);
+
+/* hashovfl.c */
+extern Buffer _hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf, bool retain_pin);
+extern BlockNumber _hash_freeovflpage(Relation rel, Buffer bucketbuf, Buffer ovflbuf,
+ Buffer wbuf, IndexTuple *itups, OffsetNumber *itup_offsets,
+ Size *tups_size, uint16 nitups, BufferAccessStrategy bstrategy);
+extern void _hash_initbitmapbuffer(Buffer buf, uint16 bmsize, bool initpage);
+extern void _hash_squeezebucket(Relation rel,
+ Bucket bucket, BlockNumber bucket_blkno,
+ Buffer bucket_buf,
+ BufferAccessStrategy bstrategy);
+extern uint32 _hash_ovflblkno_to_bitno(HashMetaPage metap, BlockNumber ovflblkno);
+
+/* hashpage.c */
+extern Buffer _hash_getbuf(Relation rel, BlockNumber blkno,
+ int access, int flags);
+extern Buffer _hash_getbuf_with_condlock_cleanup(Relation rel,
+ BlockNumber blkno, int flags);
+extern HashMetaPage _hash_getcachedmetap(Relation rel, Buffer *metabuf,
+ bool force_refresh);
+extern Buffer _hash_getbucketbuf_from_hashkey(Relation rel, uint32 hashkey,
+ int access,
+ HashMetaPage *cachedmetap);
+extern Buffer _hash_getinitbuf(Relation rel, BlockNumber blkno);
+extern void _hash_initbuf(Buffer buf, uint32 max_bucket, uint32 num_bucket,
+ uint32 flag, bool initpage);
+extern Buffer _hash_getnewbuf(Relation rel, BlockNumber blkno,
+ ForkNumber forkNum);
+extern Buffer _hash_getbuf_with_strategy(Relation rel, BlockNumber blkno,
+ int access, int flags,
+ BufferAccessStrategy bstrategy);
+extern void _hash_relbuf(Relation rel, Buffer buf);
+extern void _hash_dropbuf(Relation rel, Buffer buf);
+extern void _hash_dropscanbuf(Relation rel, HashScanOpaque so);
+extern uint32 _hash_init(Relation rel, double num_tuples,
+ ForkNumber forkNum);
+extern void _hash_init_metabuffer(Buffer buf, double num_tuples,
+ RegProcedure procid, uint16 ffactor, bool initpage);
+extern void _hash_pageinit(Page page, Size size);
+extern void _hash_expandtable(Relation rel, Buffer metabuf);
+extern void _hash_finish_split(Relation rel, Buffer metabuf, Buffer obuf,
+ Bucket obucket, uint32 maxbucket, uint32 highmask,
+ uint32 lowmask);
+
+/* hashsearch.c */
+extern bool _hash_next(IndexScanDesc scan, ScanDirection dir);
+extern bool _hash_first(IndexScanDesc scan, ScanDirection dir);
+
+/* hashsort.c */
+typedef struct HSpool HSpool; /* opaque struct in hashsort.c */
+
+extern HSpool *_h_spoolinit(Relation heap, Relation index, uint32 num_buckets);
+extern void _h_spooldestroy(HSpool *hspool);
+extern void _h_spool(HSpool *hspool, ItemPointer self,
+ Datum *values, bool *isnull);
+extern void _h_indexbuild(HSpool *hspool, Relation heapRel);
+
+/* hashutil.c */
+extern bool _hash_checkqual(IndexScanDesc scan, IndexTuple itup);
+extern uint32 _hash_datum2hashkey(Relation rel, Datum key);
+extern uint32 _hash_datum2hashkey_type(Relation rel, Datum key, Oid keytype);
+extern Bucket _hash_hashkey2bucket(uint32 hashkey, uint32 maxbucket,
+ uint32 highmask, uint32 lowmask);
+extern uint32 _hash_spareindex(uint32 num_bucket);
+extern uint32 _hash_get_totalbuckets(uint32 splitpoint_phase);
+extern void _hash_checkpage(Relation rel, Buffer buf, int flags);
+extern uint32 _hash_get_indextuple_hashkey(IndexTuple itup);
+extern bool _hash_convert_tuple(Relation index,
+ Datum *user_values, bool *user_isnull,
+ Datum *index_values, bool *index_isnull);
+extern OffsetNumber _hash_binsearch(Page page, uint32 hash_value);
+extern OffsetNumber _hash_binsearch_last(Page page, uint32 hash_value);
+extern BlockNumber _hash_get_oldblock_from_newbucket(Relation rel, Bucket new_bucket);
+extern BlockNumber _hash_get_newblock_from_oldbucket(Relation rel, Bucket old_bucket);
+extern Bucket _hash_get_newbucket_from_oldbucket(Relation rel, Bucket old_bucket,
+ uint32 lowmask, uint32 maxbucket);
+extern void _hash_kill_items(IndexScanDesc scan);
+
+/* hash.c */
+extern void hashbucketcleanup(Relation rel, Bucket cur_bucket,
+ Buffer bucket_buf, BlockNumber bucket_blkno,
+ BufferAccessStrategy bstrategy,
+ uint32 maxbucket, uint32 highmask, uint32 lowmask,
+ double *tuples_removed, double *num_index_tuples,
+ bool split_cleanup,
+ IndexBulkDeleteCallback callback, void *callback_state);
+
+#endif /* HASH_H */
diff --git a/src/include/access/hash_xlog.h b/src/include/access/hash_xlog.h
new file mode 100644
index 0000000..d1aa6da
--- /dev/null
+++ b/src/include/access/hash_xlog.h
@@ -0,0 +1,267 @@
+/*-------------------------------------------------------------------------
+ *
+ * hash_xlog.h
+ * header file for Postgres hash AM implementation
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/hash_xlog.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef HASH_XLOG_H
+#define HASH_XLOG_H
+
+#include "access/xlogreader.h"
+#include "lib/stringinfo.h"
+#include "storage/off.h"
+
+/* Number of buffers required for XLOG_HASH_SQUEEZE_PAGE operation */
+#define HASH_XLOG_FREE_OVFL_BUFS 6
+
+/*
+ * XLOG records for hash operations
+ */
+#define XLOG_HASH_INIT_META_PAGE 0x00 /* initialize the meta page */
+#define XLOG_HASH_INIT_BITMAP_PAGE 0x10 /* initialize the bitmap page */
+#define XLOG_HASH_INSERT 0x20 /* add index tuple without split */
+#define XLOG_HASH_ADD_OVFL_PAGE 0x30 /* add overflow page */
+#define XLOG_HASH_SPLIT_ALLOCATE_PAGE 0x40 /* allocate new page for split */
+#define XLOG_HASH_SPLIT_PAGE 0x50 /* split page */
+#define XLOG_HASH_SPLIT_COMPLETE 0x60 /* completion of split operation */
+#define XLOG_HASH_MOVE_PAGE_CONTENTS 0x70 /* remove tuples from one page
+ * and add to another page */
+#define XLOG_HASH_SQUEEZE_PAGE 0x80 /* add tuples to one of the previous
+ * pages in chain and free the ovfl
+ * page */
+#define XLOG_HASH_DELETE 0x90 /* delete index tuples from a page */
+#define XLOG_HASH_SPLIT_CLEANUP 0xA0 /* clear split-cleanup flag in primary
+ * bucket page after deleting tuples
+ * that are moved due to split */
+#define XLOG_HASH_UPDATE_META_PAGE 0xB0 /* update meta page after vacuum */
+
+#define XLOG_HASH_VACUUM_ONE_PAGE 0xC0 /* remove dead tuples from index
+ * page */
+
+/*
+ * xl_hash_split_allocate_page flag values, 8 bits are available.
+ */
+#define XLH_SPLIT_META_UPDATE_MASKS (1<<0)
+#define XLH_SPLIT_META_UPDATE_SPLITPOINT (1<<1)
+
+/*
+ * This is what we need to know about simple (without split) insert.
+ *
+ * This data record is used for XLOG_HASH_INSERT
+ *
+ * Backup Blk 0: original page (data contains the inserted tuple)
+ * Backup Blk 1: metapage (HashMetaPageData)
+ */
+typedef struct xl_hash_insert
+{
+ OffsetNumber offnum;
+} xl_hash_insert;
+
+#define SizeOfHashInsert (offsetof(xl_hash_insert, offnum) + sizeof(OffsetNumber))
+
+/*
+ * This is what we need to know about addition of overflow page.
+ *
+ * This data record is used for XLOG_HASH_ADD_OVFL_PAGE
+ *
+ * Backup Blk 0: newly allocated overflow page
+ * Backup Blk 1: page before new overflow page in the bucket chain
+ * Backup Blk 2: bitmap page
+ * Backup Blk 3: new bitmap page
+ * Backup Blk 4: metapage
+ */
+typedef struct xl_hash_add_ovfl_page
+{
+ uint16 bmsize;
+ bool bmpage_found;
+} xl_hash_add_ovfl_page;
+
+#define SizeOfHashAddOvflPage \
+ (offsetof(xl_hash_add_ovfl_page, bmpage_found) + sizeof(bool))
+
+/*
+ * This is what we need to know about allocating a page for split.
+ *
+ * This data record is used for XLOG_HASH_SPLIT_ALLOCATE_PAGE
+ *
+ * Backup Blk 0: page for old bucket
+ * Backup Blk 1: page for new bucket
+ * Backup Blk 2: metapage
+ */
+typedef struct xl_hash_split_allocate_page
+{
+ uint32 new_bucket;
+ uint16 old_bucket_flag;
+ uint16 new_bucket_flag;
+ uint8 flags;
+} xl_hash_split_allocate_page;
+
+#define SizeOfHashSplitAllocPage \
+ (offsetof(xl_hash_split_allocate_page, flags) + sizeof(uint8))
+
+/*
+ * This is what we need to know about completing the split operation.
+ *
+ * This data record is used for XLOG_HASH_SPLIT_COMPLETE
+ *
+ * Backup Blk 0: page for old bucket
+ * Backup Blk 1: page for new bucket
+ */
+typedef struct xl_hash_split_complete
+{
+ uint16 old_bucket_flag;
+ uint16 new_bucket_flag;
+} xl_hash_split_complete;
+
+#define SizeOfHashSplitComplete \
+ (offsetof(xl_hash_split_complete, new_bucket_flag) + sizeof(uint16))
+
+/*
+ * This is what we need to know about move page contents required during
+ * squeeze operation.
+ *
+ * This data record is used for XLOG_HASH_MOVE_PAGE_CONTENTS
+ *
+ * Backup Blk 0: bucket page
+ * Backup Blk 1: page containing moved tuples
+ * Backup Blk 2: page from which tuples will be removed
+ */
+typedef struct xl_hash_move_page_contents
+{
+ uint16 ntups;
+ bool is_prim_bucket_same_wrt; /* true if the page to which
+ * tuples are moved is same as
+ * primary bucket page */
+} xl_hash_move_page_contents;
+
+#define SizeOfHashMovePageContents \
+ (offsetof(xl_hash_move_page_contents, is_prim_bucket_same_wrt) + sizeof(bool))
+
+/*
+ * This is what we need to know about the squeeze page operation.
+ *
+ * This data record is used for XLOG_HASH_SQUEEZE_PAGE
+ *
+ * Backup Blk 0: page containing tuples moved from freed overflow page
+ * Backup Blk 1: freed overflow page
+ * Backup Blk 2: page previous to the freed overflow page
+ * Backup Blk 3: page next to the freed overflow page
+ * Backup Blk 4: bitmap page containing info of freed overflow page
+ * Backup Blk 5: meta page
+ */
+typedef struct xl_hash_squeeze_page
+{
+ BlockNumber prevblkno;
+ BlockNumber nextblkno;
+ uint16 ntups;
+ bool is_prim_bucket_same_wrt; /* true if the page to which
+ * tuples are moved is same as
+ * primary bucket page */
+ bool is_prev_bucket_same_wrt; /* true if the page to which
+ * tuples are moved is the page
+ * previous to the freed overflow
+ * page */
+} xl_hash_squeeze_page;
+
+#define SizeOfHashSqueezePage \
+ (offsetof(xl_hash_squeeze_page, is_prev_bucket_same_wrt) + sizeof(bool))
+
+/*
+ * This is what we need to know about the deletion of index tuples from a page.
+ *
+ * This data record is used for XLOG_HASH_DELETE
+ *
+ * Backup Blk 0: primary bucket page
+ * Backup Blk 1: page from which tuples are deleted
+ */
+typedef struct xl_hash_delete
+{
+ bool clear_dead_marking; /* true if this operation clears
+ * LH_PAGE_HAS_DEAD_TUPLES flag */
+ bool is_primary_bucket_page; /* true if the operation is for
+ * primary bucket page */
+} xl_hash_delete;
+
+#define SizeOfHashDelete (offsetof(xl_hash_delete, is_primary_bucket_page) + sizeof(bool))
+
+/*
+ * This is what we need for metapage update operation.
+ *
+ * This data record is used for XLOG_HASH_UPDATE_META_PAGE
+ *
+ * Backup Blk 0: meta page
+ */
+typedef struct xl_hash_update_meta_page
+{
+ double ntuples;
+} xl_hash_update_meta_page;
+
+#define SizeOfHashUpdateMetaPage \
+ (offsetof(xl_hash_update_meta_page, ntuples) + sizeof(double))
+
+/*
+ * This is what we need to initialize metapage.
+ *
+ * This data record is used for XLOG_HASH_INIT_META_PAGE
+ *
+ * Backup Blk 0: meta page
+ */
+typedef struct xl_hash_init_meta_page
+{
+ double num_tuples;
+ RegProcedure procid;
+ uint16 ffactor;
+} xl_hash_init_meta_page;
+
+#define SizeOfHashInitMetaPage \
+ (offsetof(xl_hash_init_meta_page, ffactor) + sizeof(uint16))
+
+/*
+ * This is what we need to initialize bitmap page.
+ *
+ * This data record is used for XLOG_HASH_INIT_BITMAP_PAGE
+ *
+ * Backup Blk 0: bitmap page
+ * Backup Blk 1: meta page
+ */
+typedef struct xl_hash_init_bitmap_page
+{
+ uint16 bmsize;
+} xl_hash_init_bitmap_page;
+
+#define SizeOfHashInitBitmapPage \
+ (offsetof(xl_hash_init_bitmap_page, bmsize) + sizeof(uint16))
+
+/*
+ * This is what we need for index tuple deletion and to
+ * update the meta page.
+ *
+ * This data record is used for XLOG_HASH_VACUUM_ONE_PAGE
+ *
+ * Backup Blk 0: bucket page
+ * Backup Blk 1: meta page
+ */
+typedef struct xl_hash_vacuum_one_page
+{
+ TransactionId latestRemovedXid;
+ int ntuples;
+
+ /* TARGET OFFSET NUMBERS FOLLOW AT THE END */
+} xl_hash_vacuum_one_page;
+
+#define SizeOfHashVacuumOnePage \
+ (offsetof(xl_hash_vacuum_one_page, ntuples) + sizeof(int))
+
+extern void hash_redo(XLogReaderState *record);
+extern void hash_desc(StringInfo buf, XLogReaderState *record);
+extern const char *hash_identify(uint8 info);
+extern void hash_mask(char *pagedata, BlockNumber blkno);
+
+#endif /* HASH_XLOG_H */
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
new file mode 100644
index 0000000..f279edc
--- /dev/null
+++ b/src/include/access/heapam.h
@@ -0,0 +1,223 @@
+/*-------------------------------------------------------------------------
+ *
+ * heapam.h
+ * POSTGRES heap access method definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/heapam.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef HEAPAM_H
+#define HEAPAM_H
+
+#include "access/relation.h" /* for backward compatibility */
+#include "access/relscan.h"
+#include "access/sdir.h"
+#include "access/skey.h"
+#include "access/table.h" /* for backward compatibility */
+#include "access/tableam.h"
+#include "nodes/lockoptions.h"
+#include "nodes/primnodes.h"
+#include "storage/bufpage.h"
+#include "storage/dsm.h"
+#include "storage/lockdefs.h"
+#include "storage/shm_toc.h"
+#include "utils/relcache.h"
+#include "utils/snapshot.h"
+
+
+/* "options" flag bits for heap_insert */
+#define HEAP_INSERT_SKIP_FSM TABLE_INSERT_SKIP_FSM
+#define HEAP_INSERT_FROZEN TABLE_INSERT_FROZEN
+#define HEAP_INSERT_NO_LOGICAL TABLE_INSERT_NO_LOGICAL
+#define HEAP_INSERT_SPECULATIVE 0x0010
+
+typedef struct BulkInsertStateData *BulkInsertState;
+struct TupleTableSlot;
+
+#define MaxLockTupleMode LockTupleExclusive
+
+/*
+ * Descriptor for heap table scans.
+ */
+typedef struct HeapScanDescData
+{
+ TableScanDescData rs_base; /* AM independent part of the descriptor */
+
+ /* state set up at initscan time */
+ BlockNumber rs_nblocks; /* total number of blocks in rel */
+ BlockNumber rs_startblock; /* block # to start at */
+ BlockNumber rs_numblocks; /* max number of blocks to scan */
+ /* rs_numblocks is usually InvalidBlockNumber, meaning "scan whole rel" */
+
+ /* scan current state */
+ bool rs_inited; /* false = scan not init'd yet */
+ BlockNumber rs_cblock; /* current block # in scan, if any */
+ Buffer rs_cbuf; /* current buffer in scan, if any */
+ /* NB: if rs_cbuf is not InvalidBuffer, we hold a pin on that buffer */
+
+ /* rs_numblocks is usually InvalidBlockNumber, meaning "scan whole rel" */
+ BufferAccessStrategy rs_strategy; /* access strategy for reads */
+
+ HeapTupleData rs_ctup; /* current tuple in scan, if any */
+
+ /* these fields only used in page-at-a-time mode and for bitmap scans */
+ int rs_cindex; /* current tuple's index in vistuples */
+ int rs_ntuples; /* number of visible tuples on page */
+ OffsetNumber rs_vistuples[MaxHeapTuplesPerPage]; /* their offsets */
+} HeapScanDescData;
+typedef struct HeapScanDescData *HeapScanDesc;
+
+/*
+ * Descriptor for fetches from heap via an index.
+ */
+typedef struct IndexFetchHeapData
+{
+ IndexFetchTableData xs_base; /* AM independent part of the descriptor */
+
+ Buffer xs_cbuf; /* current heap buffer in scan, if any */
+ /* NB: if xs_cbuf is not InvalidBuffer, we hold a pin on that buffer */
+} IndexFetchHeapData;
+
+/* Result codes for HeapTupleSatisfiesVacuum */
+typedef enum
+{
+ HEAPTUPLE_DEAD, /* tuple is dead and deletable */
+ HEAPTUPLE_LIVE, /* tuple is live (committed, no deleter) */
+ HEAPTUPLE_RECENTLY_DEAD, /* tuple is dead, but not deletable yet */
+ HEAPTUPLE_INSERT_IN_PROGRESS, /* inserting xact is still in progress */
+ HEAPTUPLE_DELETE_IN_PROGRESS /* deleting xact is still in progress */
+} HTSV_Result;
+
+/* ----------------
+ * function prototypes for heap access method
+ *
+ * heap_create, heap_create_with_catalog, and heap_drop_with_catalog
+ * are declared in catalog/heap.h
+ * ----------------
+ */
+
+
+/*
+ * HeapScanIsValid
+ * True iff the heap scan is valid.
+ */
+#define HeapScanIsValid(scan) PointerIsValid(scan)
+
+extern TableScanDesc heap_beginscan(Relation relation, Snapshot snapshot,
+ int nkeys, ScanKey key,
+ ParallelTableScanDesc parallel_scan,
+ uint32 flags);
+extern void heap_setscanlimits(TableScanDesc scan, BlockNumber startBlk,
+ BlockNumber numBlks);
+extern void heapgetpage(TableScanDesc scan, BlockNumber page);
+extern void heap_rescan(TableScanDesc scan, ScanKey key, bool set_params,
+ bool allow_strat, bool allow_sync, bool allow_pagemode);
+extern void heap_endscan(TableScanDesc scan);
+extern HeapTuple heap_getnext(TableScanDesc scan, ScanDirection direction);
+extern bool heap_getnextslot(TableScanDesc sscan,
+ ScanDirection direction, struct TupleTableSlot *slot);
+
+extern bool heap_fetch(Relation relation, Snapshot snapshot,
+ HeapTuple tuple, Buffer *userbuf);
+extern bool heap_hot_search_buffer(ItemPointer tid, Relation relation,
+ Buffer buffer, Snapshot snapshot, HeapTuple heapTuple,
+ bool *all_dead, bool first_call);
+
+extern void heap_get_latest_tid(TableScanDesc scan, ItemPointer tid);
+extern void setLastTid(const ItemPointer tid);
+
+extern BulkInsertState GetBulkInsertState(void);
+extern void FreeBulkInsertState(BulkInsertState);
+extern void ReleaseBulkInsertStatePin(BulkInsertState bistate);
+
+extern void heap_insert(Relation relation, HeapTuple tup, CommandId cid,
+ int options, BulkInsertState bistate);
+extern void heap_multi_insert(Relation relation, struct TupleTableSlot **slots,
+ int ntuples, CommandId cid, int options,
+ BulkInsertState bistate);
+extern TM_Result heap_delete(Relation relation, ItemPointer tid,
+ CommandId cid, Snapshot crosscheck, bool wait,
+ struct TM_FailureData *tmfd, bool changingPart);
+extern void heap_finish_speculative(Relation relation, ItemPointer tid);
+extern void heap_abort_speculative(Relation relation, ItemPointer tid);
+extern TM_Result heap_update(Relation relation, ItemPointer otid,
+ HeapTuple newtup,
+ CommandId cid, Snapshot crosscheck, bool wait,
+ struct TM_FailureData *tmfd, LockTupleMode *lockmode);
+extern TM_Result heap_lock_tuple(Relation relation, HeapTuple tuple,
+ CommandId cid, LockTupleMode mode, LockWaitPolicy wait_policy,
+ bool follow_update,
+ Buffer *buffer, struct TM_FailureData *tmfd);
+
+extern void heap_inplace_update(Relation relation, HeapTuple tuple);
+extern bool heap_freeze_tuple(HeapTupleHeader tuple,
+ TransactionId relfrozenxid, TransactionId relminmxid,
+ TransactionId cutoff_xid, TransactionId cutoff_multi);
+extern bool heap_tuple_needs_freeze(HeapTupleHeader tuple, TransactionId cutoff_xid,
+ MultiXactId cutoff_multi, Buffer buf);
+extern bool heap_tuple_needs_eventual_freeze(HeapTupleHeader tuple);
+
+extern void simple_heap_insert(Relation relation, HeapTuple tup);
+extern void simple_heap_delete(Relation relation, ItemPointer tid);
+extern void simple_heap_update(Relation relation, ItemPointer otid,
+ HeapTuple tup);
+
+extern TransactionId heap_compute_xid_horizon_for_tuples(Relation rel,
+ ItemPointerData *items,
+ int nitems);
+
+/* in heap/pruneheap.c */
+extern void heap_page_prune_opt(Relation relation, Buffer buffer);
+extern int heap_page_prune(Relation relation, Buffer buffer,
+ TransactionId OldestXmin,
+ bool report_stats, TransactionId *latestRemovedXid);
+extern void heap_page_prune_execute(Buffer buffer,
+ OffsetNumber *redirected, int nredirected,
+ OffsetNumber *nowdead, int ndead,
+ OffsetNumber *nowunused, int nunused);
+extern void heap_get_root_tuples(Page page, OffsetNumber *root_offsets);
+
+/* in heap/syncscan.c */
+extern void ss_report_location(Relation rel, BlockNumber location);
+extern BlockNumber ss_get_location(Relation rel, BlockNumber relnblocks);
+extern void SyncScanShmemInit(void);
+extern Size SyncScanShmemSize(void);
+
+/* in heap/vacuumlazy.c */
+struct VacuumParams;
+extern void heap_vacuum_rel(Relation onerel,
+ struct VacuumParams *params, BufferAccessStrategy bstrategy);
+extern void parallel_vacuum_main(dsm_segment *seg, shm_toc *toc);
+
+/* in heap/heapam_visibility.c */
+extern bool HeapTupleSatisfiesVisibility(HeapTuple stup, Snapshot snapshot,
+ Buffer buffer);
+extern TM_Result HeapTupleSatisfiesUpdate(HeapTuple stup, CommandId curcid,
+ Buffer buffer);
+extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTuple stup, TransactionId OldestXmin,
+ Buffer buffer);
+extern void HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
+ uint16 infomask, TransactionId xid);
+extern bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple);
+extern bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot);
+extern bool HeapTupleIsSurelyDead(HeapTuple htup, TransactionId OldestXmin);
+
+/*
+ * To avoid leaking too much knowledge about reorderbuffer implementation
+ * details this is implemented in reorderbuffer.c not heapam_visibility.c
+ */
+struct HTAB;
+extern bool ResolveCminCmaxDuringDecoding(struct HTAB *tuplecid_data,
+ Snapshot snapshot,
+ HeapTuple htup,
+ Buffer buffer,
+ CommandId *cmin, CommandId *cmax);
+extern void HeapCheckForSerializableConflictOut(bool valid, Relation relation, HeapTuple tuple,
+ Buffer buffer, Snapshot snapshot);
+
+#endif /* HEAPAM_H */
diff --git a/src/include/access/heapam_xlog.h b/src/include/access/heapam_xlog.h
new file mode 100644
index 0000000..1949b98
--- /dev/null
+++ b/src/include/access/heapam_xlog.h
@@ -0,0 +1,418 @@
+/*-------------------------------------------------------------------------
+ *
+ * heapam_xlog.h
+ * POSTGRES heap access XLOG definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/heapam_xlog.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef HEAPAM_XLOG_H
+#define HEAPAM_XLOG_H
+
+#include "access/htup.h"
+#include "access/xlogreader.h"
+#include "lib/stringinfo.h"
+#include "storage/buf.h"
+#include "storage/bufpage.h"
+#include "storage/relfilenode.h"
+#include "utils/relcache.h"
+
+
+/*
+ * WAL record definitions for heapam.c's WAL operations
+ *
+ * XLOG allows to store some information in high 4 bits of log
+ * record xl_info field. We use 3 for opcode and one for init bit.
+ */
+#define XLOG_HEAP_INSERT 0x00
+#define XLOG_HEAP_DELETE 0x10
+#define XLOG_HEAP_UPDATE 0x20
+#define XLOG_HEAP_TRUNCATE 0x30
+#define XLOG_HEAP_HOT_UPDATE 0x40
+#define XLOG_HEAP_CONFIRM 0x50
+#define XLOG_HEAP_LOCK 0x60
+#define XLOG_HEAP_INPLACE 0x70
+
+#define XLOG_HEAP_OPMASK 0x70
+/*
+ * When we insert 1st item on new page in INSERT, UPDATE, HOT_UPDATE,
+ * or MULTI_INSERT, we can (and we do) restore entire page in redo
+ */
+#define XLOG_HEAP_INIT_PAGE 0x80
+/*
+ * We ran out of opcodes, so heapam.c now has a second RmgrId. These opcodes
+ * are associated with RM_HEAP2_ID, but are not logically different from
+ * the ones above associated with RM_HEAP_ID. XLOG_HEAP_OPMASK applies to
+ * these, too.
+ */
+#define XLOG_HEAP2_REWRITE 0x00
+#define XLOG_HEAP2_CLEAN 0x10
+#define XLOG_HEAP2_FREEZE_PAGE 0x20
+#define XLOG_HEAP2_CLEANUP_INFO 0x30
+#define XLOG_HEAP2_VISIBLE 0x40
+#define XLOG_HEAP2_MULTI_INSERT 0x50
+#define XLOG_HEAP2_LOCK_UPDATED 0x60
+#define XLOG_HEAP2_NEW_CID 0x70
+
+/*
+ * xl_heap_insert/xl_heap_multi_insert flag values, 8 bits are available.
+ */
+/* PD_ALL_VISIBLE was cleared */
+#define XLH_INSERT_ALL_VISIBLE_CLEARED (1<<0)
+#define XLH_INSERT_LAST_IN_MULTI (1<<1)
+#define XLH_INSERT_IS_SPECULATIVE (1<<2)
+#define XLH_INSERT_CONTAINS_NEW_TUPLE (1<<3)
+
+/*
+ * xl_heap_update flag values, 8 bits are available.
+ */
+/* PD_ALL_VISIBLE was cleared */
+#define XLH_UPDATE_OLD_ALL_VISIBLE_CLEARED (1<<0)
+/* PD_ALL_VISIBLE was cleared in the 2nd page */
+#define XLH_UPDATE_NEW_ALL_VISIBLE_CLEARED (1<<1)
+#define XLH_UPDATE_CONTAINS_OLD_TUPLE (1<<2)
+#define XLH_UPDATE_CONTAINS_OLD_KEY (1<<3)
+#define XLH_UPDATE_CONTAINS_NEW_TUPLE (1<<4)
+#define XLH_UPDATE_PREFIX_FROM_OLD (1<<5)
+#define XLH_UPDATE_SUFFIX_FROM_OLD (1<<6)
+
+/* convenience macro for checking whether any form of old tuple was logged */
+#define XLH_UPDATE_CONTAINS_OLD \
+ (XLH_UPDATE_CONTAINS_OLD_TUPLE | XLH_UPDATE_CONTAINS_OLD_KEY)
+
+/*
+ * xl_heap_delete flag values, 8 bits are available.
+ */
+/* PD_ALL_VISIBLE was cleared */
+#define XLH_DELETE_ALL_VISIBLE_CLEARED (1<<0)
+#define XLH_DELETE_CONTAINS_OLD_TUPLE (1<<1)
+#define XLH_DELETE_CONTAINS_OLD_KEY (1<<2)
+#define XLH_DELETE_IS_SUPER (1<<3)
+#define XLH_DELETE_IS_PARTITION_MOVE (1<<4)
+
+/* convenience macro for checking whether any form of old tuple was logged */
+#define XLH_DELETE_CONTAINS_OLD \
+ (XLH_DELETE_CONTAINS_OLD_TUPLE | XLH_DELETE_CONTAINS_OLD_KEY)
+
+/* This is what we need to know about delete */
+typedef struct xl_heap_delete
+{
+ TransactionId xmax; /* xmax of the deleted tuple */
+ OffsetNumber offnum; /* deleted tuple's offset */
+ uint8 infobits_set; /* infomask bits */
+ uint8 flags;
+} xl_heap_delete;
+
+#define SizeOfHeapDelete (offsetof(xl_heap_delete, flags) + sizeof(uint8))
+
+/*
+ * xl_heap_truncate flag values, 8 bits are available.
+ */
+#define XLH_TRUNCATE_CASCADE (1<<0)
+#define XLH_TRUNCATE_RESTART_SEQS (1<<1)
+
+/*
+ * For truncate we list all truncated relids in an array, followed by all
+ * sequence relids that need to be restarted, if any.
+ * All rels are always within the same database, so we just list dbid once.
+ */
+typedef struct xl_heap_truncate
+{
+ Oid dbId;
+ uint32 nrelids;
+ uint8 flags;
+ Oid relids[FLEXIBLE_ARRAY_MEMBER];
+} xl_heap_truncate;
+
+#define SizeOfHeapTruncate (offsetof(xl_heap_truncate, relids))
+
+/*
+ * We don't store the whole fixed part (HeapTupleHeaderData) of an inserted
+ * or updated tuple in WAL; we can save a few bytes by reconstructing the
+ * fields that are available elsewhere in the WAL record, or perhaps just
+ * plain needn't be reconstructed. These are the fields we must store.
+ */
+typedef struct xl_heap_header
+{
+ uint16 t_infomask2;
+ uint16 t_infomask;
+ uint8 t_hoff;
+} xl_heap_header;
+
+#define SizeOfHeapHeader (offsetof(xl_heap_header, t_hoff) + sizeof(uint8))
+
+/* This is what we need to know about insert */
+typedef struct xl_heap_insert
+{
+ OffsetNumber offnum; /* inserted tuple's offset */
+ uint8 flags;
+
+ /* xl_heap_header & TUPLE DATA in backup block 0 */
+} xl_heap_insert;
+
+#define SizeOfHeapInsert (offsetof(xl_heap_insert, flags) + sizeof(uint8))
+
+/*
+ * This is what we need to know about a multi-insert.
+ *
+ * The main data of the record consists of this xl_heap_multi_insert header.
+ * 'offsets' array is omitted if the whole page is reinitialized
+ * (XLOG_HEAP_INIT_PAGE).
+ *
+ * In block 0's data portion, there is an xl_multi_insert_tuple struct,
+ * followed by the tuple data for each tuple. There is padding to align
+ * each xl_multi_insert_tuple struct.
+ */
+typedef struct xl_heap_multi_insert
+{
+ uint8 flags;
+ uint16 ntuples;
+ OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+} xl_heap_multi_insert;
+
+#define SizeOfHeapMultiInsert offsetof(xl_heap_multi_insert, offsets)
+
+typedef struct xl_multi_insert_tuple
+{
+ uint16 datalen; /* size of tuple data that follows */
+ uint16 t_infomask2;
+ uint16 t_infomask;
+ uint8 t_hoff;
+ /* TUPLE DATA FOLLOWS AT END OF STRUCT */
+} xl_multi_insert_tuple;
+
+#define SizeOfMultiInsertTuple (offsetof(xl_multi_insert_tuple, t_hoff) + sizeof(uint8))
+
+/*
+ * This is what we need to know about update|hot_update
+ *
+ * Backup blk 0: new page
+ *
+ * If XLH_UPDATE_PREFIX_FROM_OLD or XLH_UPDATE_SUFFIX_FROM_OLD flags are set,
+ * the prefix and/or suffix come first, as one or two uint16s.
+ *
+ * After that, xl_heap_header and new tuple data follow. The new tuple
+ * data doesn't include the prefix and suffix, which are copied from the
+ * old tuple on replay.
+ *
+ * If XLH_UPDATE_CONTAINS_NEW_TUPLE flag is given, the tuple data is
+ * included even if a full-page image was taken.
+ *
+ * Backup blk 1: old page, if different. (no data, just a reference to the blk)
+ */
+typedef struct xl_heap_update
+{
+ TransactionId old_xmax; /* xmax of the old tuple */
+ OffsetNumber old_offnum; /* old tuple's offset */
+ uint8 old_infobits_set; /* infomask bits to set on old tuple */
+ uint8 flags;
+ TransactionId new_xmax; /* xmax of the new tuple */
+ OffsetNumber new_offnum; /* new tuple's offset */
+
+ /*
+ * If XLH_UPDATE_CONTAINS_OLD_TUPLE or XLH_UPDATE_CONTAINS_OLD_KEY flags
+ * are set, xl_heap_header and tuple data for the old tuple follow.
+ */
+} xl_heap_update;
+
+#define SizeOfHeapUpdate (offsetof(xl_heap_update, new_offnum) + sizeof(OffsetNumber))
+
+/*
+ * This is what we need to know about vacuum page cleanup/redirect
+ *
+ * The array of OffsetNumbers following the fixed part of the record contains:
+ * * for each redirected item: the item offset, then the offset redirected to
+ * * for each now-dead item: the item offset
+ * * for each now-unused item: the item offset
+ * The total number of OffsetNumbers is therefore 2*nredirected+ndead+nunused.
+ * Note that nunused is not explicitly stored, but may be found by reference
+ * to the total record length.
+ */
+typedef struct xl_heap_clean
+{
+ TransactionId latestRemovedXid;
+ uint16 nredirected;
+ uint16 ndead;
+ /* OFFSET NUMBERS are in the block reference 0 */
+} xl_heap_clean;
+
+#define SizeOfHeapClean (offsetof(xl_heap_clean, ndead) + sizeof(uint16))
+
+/*
+ * Cleanup_info is required in some cases during a lazy VACUUM.
+ * Used for reporting the results of HeapTupleHeaderAdvanceLatestRemovedXid()
+ * see vacuumlazy.c for full explanation
+ */
+typedef struct xl_heap_cleanup_info
+{
+ RelFileNode node;
+ TransactionId latestRemovedXid;
+} xl_heap_cleanup_info;
+
+#define SizeOfHeapCleanupInfo (sizeof(xl_heap_cleanup_info))
+
+/* flags for infobits_set */
+#define XLHL_XMAX_IS_MULTI 0x01
+#define XLHL_XMAX_LOCK_ONLY 0x02
+#define XLHL_XMAX_EXCL_LOCK 0x04
+#define XLHL_XMAX_KEYSHR_LOCK 0x08
+#define XLHL_KEYS_UPDATED 0x10
+
+/* flag bits for xl_heap_lock / xl_heap_lock_updated's flag field */
+#define XLH_LOCK_ALL_FROZEN_CLEARED 0x01
+
+/* This is what we need to know about lock */
+typedef struct xl_heap_lock
+{
+ TransactionId locking_xid; /* might be a MultiXactId not xid */
+ OffsetNumber offnum; /* locked tuple's offset on page */
+ int8 infobits_set; /* infomask and infomask2 bits to set */
+ uint8 flags; /* XLH_LOCK_* flag bits */
+} xl_heap_lock;
+
+#define SizeOfHeapLock (offsetof(xl_heap_lock, flags) + sizeof(int8))
+
+/* This is what we need to know about locking an updated version of a row */
+typedef struct xl_heap_lock_updated
+{
+ TransactionId xmax;
+ OffsetNumber offnum;
+ uint8 infobits_set;
+ uint8 flags;
+} xl_heap_lock_updated;
+
+#define SizeOfHeapLockUpdated (offsetof(xl_heap_lock_updated, flags) + sizeof(uint8))
+
+/* This is what we need to know about confirmation of speculative insertion */
+typedef struct xl_heap_confirm
+{
+ OffsetNumber offnum; /* confirmed tuple's offset on page */
+} xl_heap_confirm;
+
+#define SizeOfHeapConfirm (offsetof(xl_heap_confirm, offnum) + sizeof(OffsetNumber))
+
+/* This is what we need to know about in-place update */
+typedef struct xl_heap_inplace
+{
+ OffsetNumber offnum; /* updated tuple's offset on page */
+ /* TUPLE DATA FOLLOWS AT END OF STRUCT */
+} xl_heap_inplace;
+
+#define SizeOfHeapInplace (offsetof(xl_heap_inplace, offnum) + sizeof(OffsetNumber))
+
+/*
+ * This struct represents a 'freeze plan', which is what we need to know about
+ * a single tuple being frozen during vacuum.
+ */
+/* 0x01 was XLH_FREEZE_XMIN */
+#define XLH_FREEZE_XVAC 0x02
+#define XLH_INVALID_XVAC 0x04
+
+typedef struct xl_heap_freeze_tuple
+{
+ TransactionId xmax;
+ OffsetNumber offset;
+ uint16 t_infomask2;
+ uint16 t_infomask;
+ uint8 frzflags;
+} xl_heap_freeze_tuple;
+
+/*
+ * This is what we need to know about a block being frozen during vacuum
+ *
+ * Backup block 0's data contains an array of xl_heap_freeze_tuple structs,
+ * one for each tuple.
+ */
+typedef struct xl_heap_freeze_page
+{
+ TransactionId cutoff_xid;
+ uint16 ntuples;
+} xl_heap_freeze_page;
+
+#define SizeOfHeapFreezePage (offsetof(xl_heap_freeze_page, ntuples) + sizeof(uint16))
+
+/*
+ * This is what we need to know about setting a visibility map bit
+ *
+ * Backup blk 0: visibility map buffer
+ * Backup blk 1: heap buffer
+ */
+typedef struct xl_heap_visible
+{
+ TransactionId cutoff_xid;
+ uint8 flags;
+} xl_heap_visible;
+
+#define SizeOfHeapVisible (offsetof(xl_heap_visible, flags) + sizeof(uint8))
+
+typedef struct xl_heap_new_cid
+{
+ /*
+ * store toplevel xid so we don't have to merge cids from different
+ * transactions
+ */
+ TransactionId top_xid;
+ CommandId cmin;
+ CommandId cmax;
+ CommandId combocid; /* just for debugging */
+
+ /*
+ * Store the relfilenode/ctid pair to facilitate lookups.
+ */
+ RelFileNode target_node;
+ ItemPointerData target_tid;
+} xl_heap_new_cid;
+
+#define SizeOfHeapNewCid (offsetof(xl_heap_new_cid, target_tid) + sizeof(ItemPointerData))
+
+/* logical rewrite xlog record header */
+typedef struct xl_heap_rewrite_mapping
+{
+ TransactionId mapped_xid; /* xid that might need to see the row */
+ Oid mapped_db; /* DbOid or InvalidOid for shared rels */
+ Oid mapped_rel; /* Oid of the mapped relation */
+ off_t offset; /* How far have we written so far */
+ uint32 num_mappings; /* Number of in-memory mappings */
+ XLogRecPtr start_lsn; /* Insert LSN at begin of rewrite */
+} xl_heap_rewrite_mapping;
+
+extern void HeapTupleHeaderAdvanceLatestRemovedXid(HeapTupleHeader tuple,
+ TransactionId *latestRemovedXid);
+
+extern void heap_redo(XLogReaderState *record);
+extern void heap_desc(StringInfo buf, XLogReaderState *record);
+extern const char *heap_identify(uint8 info);
+extern void heap_mask(char *pagedata, BlockNumber blkno);
+extern void heap2_redo(XLogReaderState *record);
+extern void heap2_desc(StringInfo buf, XLogReaderState *record);
+extern const char *heap2_identify(uint8 info);
+extern void heap_xlog_logical_rewrite(XLogReaderState *r);
+
+extern XLogRecPtr log_heap_cleanup_info(RelFileNode rnode,
+ TransactionId latestRemovedXid);
+extern XLogRecPtr log_heap_clean(Relation reln, Buffer buffer,
+ OffsetNumber *redirected, int nredirected,
+ OffsetNumber *nowdead, int ndead,
+ OffsetNumber *nowunused, int nunused,
+ TransactionId latestRemovedXid);
+extern XLogRecPtr log_heap_freeze(Relation reln, Buffer buffer,
+ TransactionId cutoff_xid, xl_heap_freeze_tuple *tuples,
+ int ntuples);
+extern bool heap_prepare_freeze_tuple(HeapTupleHeader tuple,
+ TransactionId relfrozenxid,
+ TransactionId relminmxid,
+ TransactionId cutoff_xid,
+ TransactionId cutoff_multi,
+ xl_heap_freeze_tuple *frz,
+ bool *totally_frozen);
+extern void heap_execute_freeze_tuple(HeapTupleHeader tuple,
+ xl_heap_freeze_tuple *xlrec_tp);
+extern XLogRecPtr log_heap_visible(RelFileNode rnode, Buffer heap_buffer,
+ Buffer vm_buffer, TransactionId cutoff_xid, uint8 flags);
+
+#endif /* HEAPAM_XLOG_H */
diff --git a/src/include/access/heaptoast.h b/src/include/access/heaptoast.h
new file mode 100644
index 0000000..2635831
--- /dev/null
+++ b/src/include/access/heaptoast.h
@@ -0,0 +1,149 @@
+/*-------------------------------------------------------------------------
+ *
+ * heaptoast.h
+ * Heap-specific definitions for external and compressed storage
+ * of variable size attributes.
+ *
+ * Copyright (c) 2000-2020, PostgreSQL Global Development Group
+ *
+ * src/include/access/heaptoast.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef HEAPTOAST_H
+#define HEAPTOAST_H
+
+#include "access/htup_details.h"
+#include "storage/lockdefs.h"
+#include "utils/relcache.h"
+
+/*
+ * Find the maximum size of a tuple if there are to be N tuples per page.
+ */
+#define MaximumBytesPerTuple(tuplesPerPage) \
+ MAXALIGN_DOWN((BLCKSZ - \
+ MAXALIGN(SizeOfPageHeaderData + (tuplesPerPage) * sizeof(ItemIdData))) \
+ / (tuplesPerPage))
+
+/*
+ * These symbols control toaster activation. If a tuple is larger than
+ * TOAST_TUPLE_THRESHOLD, we will try to toast it down to no more than
+ * TOAST_TUPLE_TARGET bytes through compressing compressible fields and
+ * moving EXTENDED and EXTERNAL data out-of-line.
+ *
+ * The numbers need not be the same, though they currently are. It doesn't
+ * make sense for TARGET to exceed THRESHOLD, but it could be useful to make
+ * it be smaller.
+ *
+ * Currently we choose both values to match the largest tuple size for which
+ * TOAST_TUPLES_PER_PAGE tuples can fit on a heap page.
+ *
+ * XXX while these can be modified without initdb, some thought needs to be
+ * given to needs_toast_table() in toasting.c before unleashing random
+ * changes. Also see LOBLKSIZE in large_object.h, which can *not* be
+ * changed without initdb.
+ */
+#define TOAST_TUPLES_PER_PAGE 4
+
+#define TOAST_TUPLE_THRESHOLD MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE)
+
+#define TOAST_TUPLE_TARGET TOAST_TUPLE_THRESHOLD
+
+/*
+ * The code will also consider moving MAIN data out-of-line, but only as a
+ * last resort if the previous steps haven't reached the target tuple size.
+ * In this phase we use a different target size, currently equal to the
+ * largest tuple that will fit on a heap page. This is reasonable since
+ * the user has told us to keep the data in-line if at all possible.
+ */
+#define TOAST_TUPLES_PER_PAGE_MAIN 1
+
+#define TOAST_TUPLE_TARGET_MAIN MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE_MAIN)
+
+/*
+ * If an index value is larger than TOAST_INDEX_TARGET, we will try to
+ * compress it (we can't move it out-of-line, however). Note that this
+ * number is per-datum, not per-tuple, for simplicity in index_form_tuple().
+ */
+#define TOAST_INDEX_TARGET (MaxHeapTupleSize / 16)
+
+/*
+ * When we store an oversize datum externally, we divide it into chunks
+ * containing at most TOAST_MAX_CHUNK_SIZE data bytes. This number *must*
+ * be small enough that the completed toast-table tuple (including the
+ * ID and sequence fields and all overhead) will fit on a page.
+ * The coding here sets the size on the theory that we want to fit
+ * EXTERN_TUPLES_PER_PAGE tuples of maximum size onto a page.
+ *
+ * NB: Changing TOAST_MAX_CHUNK_SIZE requires an initdb.
+ */
+#define EXTERN_TUPLES_PER_PAGE 4 /* tweak only this */
+
+#define EXTERN_TUPLE_MAX_SIZE MaximumBytesPerTuple(EXTERN_TUPLES_PER_PAGE)
+
+#define TOAST_MAX_CHUNK_SIZE \
+ (EXTERN_TUPLE_MAX_SIZE - \
+ MAXALIGN(SizeofHeapTupleHeader) - \
+ sizeof(Oid) - \
+ sizeof(int32) - \
+ VARHDRSZ)
+
+/* ----------
+ * heap_toast_insert_or_update -
+ *
+ * Called by heap_insert() and heap_update().
+ * ----------
+ */
+extern HeapTuple heap_toast_insert_or_update(Relation rel, HeapTuple newtup,
+ HeapTuple oldtup, int options);
+
+/* ----------
+ * heap_toast_delete -
+ *
+ * Called by heap_delete().
+ * ----------
+ */
+extern void heap_toast_delete(Relation rel, HeapTuple oldtup,
+ bool is_speculative);
+
+/* ----------
+ * toast_flatten_tuple -
+ *
+ * "Flatten" a tuple to contain no out-of-line toasted fields.
+ * (This does not eliminate compressed or short-header datums.)
+ * ----------
+ */
+extern HeapTuple toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc);
+
+/* ----------
+ * toast_flatten_tuple_to_datum -
+ *
+ * "Flatten" a tuple containing out-of-line toasted fields into a Datum.
+ * ----------
+ */
+extern Datum toast_flatten_tuple_to_datum(HeapTupleHeader tup,
+ uint32 tup_len,
+ TupleDesc tupleDesc);
+
+/* ----------
+ * toast_build_flattened_tuple -
+ *
+ * Build a tuple containing no out-of-line toasted fields.
+ * (This does not eliminate compressed or short-header datums.)
+ * ----------
+ */
+extern HeapTuple toast_build_flattened_tuple(TupleDesc tupleDesc,
+ Datum *values,
+ bool *isnull);
+
+/* ----------
+ * heap_fetch_toast_slice
+ *
+ * Fetch a slice from a toast value stored in a heap table.
+ * ----------
+ */
+extern void heap_fetch_toast_slice(Relation toastrel, Oid valueid,
+ int32 attrsize, int32 sliceoffset,
+ int32 slicelength, struct varlena *result);
+
+#endif /* HEAPTOAST_H */
diff --git a/src/include/access/hio.h b/src/include/access/hio.h
new file mode 100644
index 0000000..f69a925
--- /dev/null
+++ b/src/include/access/hio.h
@@ -0,0 +1,43 @@
+/*-------------------------------------------------------------------------
+ *
+ * hio.h
+ * POSTGRES heap access method input/output definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/hio.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef HIO_H
+#define HIO_H
+
+#include "access/htup.h"
+#include "storage/buf.h"
+#include "utils/relcache.h"
+
+/*
+ * state for bulk inserts --- private to heapam.c and hio.c
+ *
+ * If current_buf isn't InvalidBuffer, then we are holding an extra pin
+ * on that buffer.
+ *
+ * "typedef struct BulkInsertStateData *BulkInsertState" is in heapam.h
+ */
+typedef struct BulkInsertStateData
+{
+ BufferAccessStrategy strategy; /* our BULKWRITE strategy object */
+ Buffer current_buf; /* current insertion target page */
+} BulkInsertStateData;
+
+
+extern void RelationPutHeapTuple(Relation relation, Buffer buffer,
+ HeapTuple tuple, bool token);
+extern Buffer RelationGetBufferForTuple(Relation relation, Size len,
+ Buffer otherBuffer, int options,
+ BulkInsertStateData *bistate,
+ Buffer *vmbuffer, Buffer *vmbuffer_other);
+
+#endif /* HIO_H */
diff --git a/src/include/access/htup.h b/src/include/access/htup.h
new file mode 100644
index 0000000..791883c
--- /dev/null
+++ b/src/include/access/htup.h
@@ -0,0 +1,89 @@
+/*-------------------------------------------------------------------------
+ *
+ * htup.h
+ * POSTGRES heap tuple definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/htup.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef HTUP_H
+#define HTUP_H
+
+#include "storage/itemptr.h"
+
+/* typedefs and forward declarations for structs defined in htup_details.h */
+
+typedef struct HeapTupleHeaderData HeapTupleHeaderData;
+
+typedef HeapTupleHeaderData *HeapTupleHeader;
+
+typedef struct MinimalTupleData MinimalTupleData;
+
+typedef MinimalTupleData *MinimalTuple;
+
+
+/*
+ * HeapTupleData is an in-memory data structure that points to a tuple.
+ *
+ * There are several ways in which this data structure is used:
+ *
+ * * Pointer to a tuple in a disk buffer: t_data points directly into the
+ * buffer (which the code had better be holding a pin on, but this is not
+ * reflected in HeapTupleData itself).
+ *
+ * * Pointer to nothing: t_data is NULL. This is used as a failure indication
+ * in some functions.
+ *
+ * * Part of a palloc'd tuple: the HeapTupleData itself and the tuple
+ * form a single palloc'd chunk. t_data points to the memory location
+ * immediately following the HeapTupleData struct (at offset HEAPTUPLESIZE).
+ * This is the output format of heap_form_tuple and related routines.
+ *
+ * * Separately allocated tuple: t_data points to a palloc'd chunk that
+ * is not adjacent to the HeapTupleData. (This case is deprecated since
+ * it's difficult to tell apart from case #1. It should be used only in
+ * limited contexts where the code knows that case #1 will never apply.)
+ *
+ * * Separately allocated minimal tuple: t_data points MINIMAL_TUPLE_OFFSET
+ * bytes before the start of a MinimalTuple. As with the previous case,
+ * this can't be told apart from case #1 by inspection; code setting up
+ * or destroying this representation has to know what it's doing.
+ *
+ * t_len should always be valid, except in the pointer-to-nothing case.
+ * t_self and t_tableOid should be valid if the HeapTupleData points to
+ * a disk buffer, or if it represents a copy of a tuple on disk. They
+ * should be explicitly set invalid in manufactured tuples.
+ */
+typedef struct HeapTupleData
+{
+ uint32 t_len; /* length of *t_data */
+ ItemPointerData t_self; /* SelfItemPointer */
+ Oid t_tableOid; /* table the tuple came from */
+#define FIELDNO_HEAPTUPLEDATA_DATA 3
+ HeapTupleHeader t_data; /* -> tuple header and data */
+} HeapTupleData;
+
+typedef HeapTupleData *HeapTuple;
+
+#define HEAPTUPLESIZE MAXALIGN(sizeof(HeapTupleData))
+
+/*
+ * Accessor macros to be used with HeapTuple pointers.
+ */
+#define HeapTupleIsValid(tuple) PointerIsValid(tuple)
+
+/* HeapTupleHeader functions implemented in utils/time/combocid.c */
+extern CommandId HeapTupleHeaderGetCmin(HeapTupleHeader tup);
+extern CommandId HeapTupleHeaderGetCmax(HeapTupleHeader tup);
+extern void HeapTupleHeaderAdjustCmax(HeapTupleHeader tup,
+ CommandId *cmax, bool *iscombo);
+
+/* Prototype for HeapTupleHeader accessors in heapam.c */
+extern TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple);
+
+#endif /* HTUP_H */
diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h
new file mode 100644
index 0000000..aebb108
--- /dev/null
+++ b/src/include/access/htup_details.h
@@ -0,0 +1,819 @@
+/*-------------------------------------------------------------------------
+ *
+ * htup_details.h
+ * POSTGRES heap tuple header definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/htup_details.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef HTUP_DETAILS_H
+#define HTUP_DETAILS_H
+
+#include "access/htup.h"
+#include "access/transam.h"
+#include "access/tupdesc.h"
+#include "access/tupmacs.h"
+#include "storage/bufpage.h"
+
+/*
+ * MaxTupleAttributeNumber limits the number of (user) columns in a tuple.
+ * The key limit on this value is that the size of the fixed overhead for
+ * a tuple, plus the size of the null-values bitmap (at 1 bit per column),
+ * plus MAXALIGN alignment, must fit into t_hoff which is uint8. On most
+ * machines the upper limit without making t_hoff wider would be a little
+ * over 1700. We use round numbers here and for MaxHeapAttributeNumber
+ * so that alterations in HeapTupleHeaderData layout won't change the
+ * supported max number of columns.
+ */
+#define MaxTupleAttributeNumber 1664 /* 8 * 208 */
+
+/*
+ * MaxHeapAttributeNumber limits the number of (user) columns in a table.
+ * This should be somewhat less than MaxTupleAttributeNumber. It must be
+ * at least one less, else we will fail to do UPDATEs on a maximal-width
+ * table (because UPDATE has to form working tuples that include CTID).
+ * In practice we want some additional daylight so that we can gracefully
+ * support operations that add hidden "resjunk" columns, for example
+ * SELECT * FROM wide_table ORDER BY foo, bar, baz.
+ * In any case, depending on column data types you will likely be running
+ * into the disk-block-based limit on overall tuple size if you have more
+ * than a thousand or so columns. TOAST won't help.
+ */
+#define MaxHeapAttributeNumber 1600 /* 8 * 200 */
+
+/*
+ * Heap tuple header. To avoid wasting space, the fields should be
+ * laid out in such a way as to avoid structure padding.
+ *
+ * Datums of composite types (row types) share the same general structure
+ * as on-disk tuples, so that the same routines can be used to build and
+ * examine them. However the requirements are slightly different: a Datum
+ * does not need any transaction visibility information, and it does need
+ * a length word and some embedded type information. We can achieve this
+ * by overlaying the xmin/cmin/xmax/cmax/xvac fields of a heap tuple
+ * with the fields needed in the Datum case. Typically, all tuples built
+ * in-memory will be initialized with the Datum fields; but when a tuple is
+ * about to be inserted in a table, the transaction fields will be filled,
+ * overwriting the datum fields.
+ *
+ * The overall structure of a heap tuple looks like:
+ * fixed fields (HeapTupleHeaderData struct)
+ * nulls bitmap (if HEAP_HASNULL is set in t_infomask)
+ * alignment padding (as needed to make user data MAXALIGN'd)
+ * object ID (if HEAP_HASOID_OLD is set in t_infomask, not created
+ * anymore)
+ * user data fields
+ *
+ * We store five "virtual" fields Xmin, Cmin, Xmax, Cmax, and Xvac in three
+ * physical fields. Xmin and Xmax are always really stored, but Cmin, Cmax
+ * and Xvac share a field. This works because we know that Cmin and Cmax
+ * are only interesting for the lifetime of the inserting and deleting
+ * transaction respectively. If a tuple is inserted and deleted in the same
+ * transaction, we store a "combo" command id that can be mapped to the real
+ * cmin and cmax, but only by use of local state within the originating
+ * backend. See combocid.c for more details. Meanwhile, Xvac is only set by
+ * old-style VACUUM FULL, which does not have any command sub-structure and so
+ * does not need either Cmin or Cmax. (This requires that old-style VACUUM
+ * FULL never try to move a tuple whose Cmin or Cmax is still interesting,
+ * ie, an insert-in-progress or delete-in-progress tuple.)
+ *
+ * A word about t_ctid: whenever a new tuple is stored on disk, its t_ctid
+ * is initialized with its own TID (location). If the tuple is ever updated,
+ * its t_ctid is changed to point to the replacement version of the tuple. Or
+ * if the tuple is moved from one partition to another, due to an update of
+ * the partition key, t_ctid is set to a special value to indicate that
+ * (see ItemPointerSetMovedPartitions). Thus, a tuple is the latest version
+ * of its row iff XMAX is invalid or
+ * t_ctid points to itself (in which case, if XMAX is valid, the tuple is
+ * either locked or deleted). One can follow the chain of t_ctid links
+ * to find the newest version of the row, unless it was moved to a different
+ * partition. Beware however that VACUUM might
+ * erase the pointed-to (newer) tuple before erasing the pointing (older)
+ * tuple. Hence, when following a t_ctid link, it is necessary to check
+ * to see if the referenced slot is empty or contains an unrelated tuple.
+ * Check that the referenced tuple has XMIN equal to the referencing tuple's
+ * XMAX to verify that it is actually the descendant version and not an
+ * unrelated tuple stored into a slot recently freed by VACUUM. If either
+ * check fails, one may assume that there is no live descendant version.
+ *
+ * t_ctid is sometimes used to store a speculative insertion token, instead
+ * of a real TID. A speculative token is set on a tuple that's being
+ * inserted, until the inserter is sure that it wants to go ahead with the
+ * insertion. Hence a token should only be seen on a tuple with an XMAX
+ * that's still in-progress, or invalid/aborted. The token is replaced with
+ * the tuple's real TID when the insertion is confirmed. One should never
+ * see a speculative insertion token while following a chain of t_ctid links,
+ * because they are not used on updates, only insertions.
+ *
+ * Following the fixed header fields, the nulls bitmap is stored (beginning
+ * at t_bits). The bitmap is *not* stored if t_infomask shows that there
+ * are no nulls in the tuple. If an OID field is present (as indicated by
+ * t_infomask), then it is stored just before the user data, which begins at
+ * the offset shown by t_hoff. Note that t_hoff must be a multiple of
+ * MAXALIGN.
+ */
+
+typedef struct HeapTupleFields
+{
+ TransactionId t_xmin; /* inserting xact ID */
+ TransactionId t_xmax; /* deleting or locking xact ID */
+
+ union
+ {
+ CommandId t_cid; /* inserting or deleting command ID, or both */
+ TransactionId t_xvac; /* old-style VACUUM FULL xact ID */
+ } t_field3;
+} HeapTupleFields;
+
+typedef struct DatumTupleFields
+{
+ int32 datum_len_; /* varlena header (do not touch directly!) */
+
+ int32 datum_typmod; /* -1, or identifier of a record type */
+
+ Oid datum_typeid; /* composite type OID, or RECORDOID */
+
+ /*
+ * datum_typeid cannot be a domain over composite, only plain composite,
+ * even if the datum is meant as a value of a domain-over-composite type.
+ * This is in line with the general principle that CoerceToDomain does not
+ * change the physical representation of the base type value.
+ *
+ * Note: field ordering is chosen with thought that Oid might someday
+ * widen to 64 bits.
+ */
+} DatumTupleFields;
+
+struct HeapTupleHeaderData
+{
+ union
+ {
+ HeapTupleFields t_heap;
+ DatumTupleFields t_datum;
+ } t_choice;
+
+ ItemPointerData t_ctid; /* current TID of this or newer tuple (or a
+ * speculative insertion token) */
+
+ /* Fields below here must match MinimalTupleData! */
+
+#define FIELDNO_HEAPTUPLEHEADERDATA_INFOMASK2 2
+ uint16 t_infomask2; /* number of attributes + various flags */
+
+#define FIELDNO_HEAPTUPLEHEADERDATA_INFOMASK 3
+ uint16 t_infomask; /* various flag bits, see below */
+
+#define FIELDNO_HEAPTUPLEHEADERDATA_HOFF 4
+ uint8 t_hoff; /* sizeof header incl. bitmap, padding */
+
+ /* ^ - 23 bytes - ^ */
+
+#define FIELDNO_HEAPTUPLEHEADERDATA_BITS 5
+ bits8 t_bits[FLEXIBLE_ARRAY_MEMBER]; /* bitmap of NULLs */
+
+ /* MORE DATA FOLLOWS AT END OF STRUCT */
+};
+
+/* typedef appears in htup.h */
+
+#define SizeofHeapTupleHeader offsetof(HeapTupleHeaderData, t_bits)
+
+/*
+ * information stored in t_infomask:
+ */
+#define HEAP_HASNULL 0x0001 /* has null attribute(s) */
+#define HEAP_HASVARWIDTH 0x0002 /* has variable-width attribute(s) */
+#define HEAP_HASEXTERNAL 0x0004 /* has external stored attribute(s) */
+#define HEAP_HASOID_OLD 0x0008 /* has an object-id field */
+#define HEAP_XMAX_KEYSHR_LOCK 0x0010 /* xmax is a key-shared locker */
+#define HEAP_COMBOCID 0x0020 /* t_cid is a combo cid */
+#define HEAP_XMAX_EXCL_LOCK 0x0040 /* xmax is exclusive locker */
+#define HEAP_XMAX_LOCK_ONLY 0x0080 /* xmax, if valid, is only a locker */
+
+ /* xmax is a shared locker */
+#define HEAP_XMAX_SHR_LOCK (HEAP_XMAX_EXCL_LOCK | HEAP_XMAX_KEYSHR_LOCK)
+
+#define HEAP_LOCK_MASK (HEAP_XMAX_SHR_LOCK | HEAP_XMAX_EXCL_LOCK | \
+ HEAP_XMAX_KEYSHR_LOCK)
+#define HEAP_XMIN_COMMITTED 0x0100 /* t_xmin committed */
+#define HEAP_XMIN_INVALID 0x0200 /* t_xmin invalid/aborted */
+#define HEAP_XMIN_FROZEN (HEAP_XMIN_COMMITTED|HEAP_XMIN_INVALID)
+#define HEAP_XMAX_COMMITTED 0x0400 /* t_xmax committed */
+#define HEAP_XMAX_INVALID 0x0800 /* t_xmax invalid/aborted */
+#define HEAP_XMAX_IS_MULTI 0x1000 /* t_xmax is a MultiXactId */
+#define HEAP_UPDATED 0x2000 /* this is UPDATEd version of row */
+#define HEAP_MOVED_OFF 0x4000 /* moved to another place by pre-9.0
+ * VACUUM FULL; kept for binary
+ * upgrade support */
+#define HEAP_MOVED_IN 0x8000 /* moved from another place by pre-9.0
+ * VACUUM FULL; kept for binary
+ * upgrade support */
+#define HEAP_MOVED (HEAP_MOVED_OFF | HEAP_MOVED_IN)
+
+#define HEAP_XACT_MASK 0xFFF0 /* visibility-related bits */
+
+/*
+ * A tuple is only locked (i.e. not updated by its Xmax) if the
+ * HEAP_XMAX_LOCK_ONLY bit is set; or, for pg_upgrade's sake, if the Xmax is
+ * not a multi and the EXCL_LOCK bit is set.
+ *
+ * See also HeapTupleHeaderIsOnlyLocked, which also checks for a possible
+ * aborted updater transaction.
+ *
+ * Beware of multiple evaluations of the argument.
+ */
+#define HEAP_XMAX_IS_LOCKED_ONLY(infomask) \
+ (((infomask) & HEAP_XMAX_LOCK_ONLY) || \
+ (((infomask) & (HEAP_XMAX_IS_MULTI | HEAP_LOCK_MASK)) == HEAP_XMAX_EXCL_LOCK))
+
+/*
+ * A tuple that has HEAP_XMAX_IS_MULTI and HEAP_XMAX_LOCK_ONLY but neither of
+ * HEAP_XMAX_EXCL_LOCK and HEAP_XMAX_KEYSHR_LOCK must come from a tuple that was
+ * share-locked in 9.2 or earlier and then pg_upgrade'd.
+ *
+ * In 9.2 and prior, HEAP_XMAX_IS_MULTI was only set when there were multiple
+ * FOR SHARE lockers of that tuple. That set HEAP_XMAX_LOCK_ONLY (with a
+ * different name back then) but neither of HEAP_XMAX_EXCL_LOCK and
+ * HEAP_XMAX_KEYSHR_LOCK. That combination is no longer possible in 9.3 and
+ * up, so if we see that combination we know for certain that the tuple was
+ * locked in an earlier release; since all such lockers are gone (they cannot
+ * survive through pg_upgrade), such tuples can safely be considered not
+ * locked.
+ *
+ * We must not resolve such multixacts locally, because the result would be
+ * bogus, regardless of where they stand with respect to the current valid
+ * multixact range.
+ */
+#define HEAP_LOCKED_UPGRADED(infomask) \
+( \
+ ((infomask) & HEAP_XMAX_IS_MULTI) != 0 && \
+ ((infomask) & HEAP_XMAX_LOCK_ONLY) != 0 && \
+ (((infomask) & (HEAP_XMAX_EXCL_LOCK | HEAP_XMAX_KEYSHR_LOCK)) == 0) \
+)
+
+/*
+ * Use these to test whether a particular lock is applied to a tuple
+ */
+#define HEAP_XMAX_IS_SHR_LOCKED(infomask) \
+ (((infomask) & HEAP_LOCK_MASK) == HEAP_XMAX_SHR_LOCK)
+#define HEAP_XMAX_IS_EXCL_LOCKED(infomask) \
+ (((infomask) & HEAP_LOCK_MASK) == HEAP_XMAX_EXCL_LOCK)
+#define HEAP_XMAX_IS_KEYSHR_LOCKED(infomask) \
+ (((infomask) & HEAP_LOCK_MASK) == HEAP_XMAX_KEYSHR_LOCK)
+
+/* turn these all off when Xmax is to change */
+#define HEAP_XMAX_BITS (HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID | \
+ HEAP_XMAX_IS_MULTI | HEAP_LOCK_MASK | HEAP_XMAX_LOCK_ONLY)
+
+/*
+ * information stored in t_infomask2:
+ */
+#define HEAP_NATTS_MASK 0x07FF /* 11 bits for number of attributes */
+/* bits 0x1800 are available */
+#define HEAP_KEYS_UPDATED 0x2000 /* tuple was updated and key cols
+ * modified, or tuple deleted */
+#define HEAP_HOT_UPDATED 0x4000 /* tuple was HOT-updated */
+#define HEAP_ONLY_TUPLE 0x8000 /* this is heap-only tuple */
+
+#define HEAP2_XACT_MASK 0xE000 /* visibility-related bits */
+
+/*
+ * HEAP_TUPLE_HAS_MATCH is a temporary flag used during hash joins. It is
+ * only used in tuples that are in the hash table, and those don't need
+ * any visibility information, so we can overlay it on a visibility flag
+ * instead of using up a dedicated bit.
+ */
+#define HEAP_TUPLE_HAS_MATCH HEAP_ONLY_TUPLE /* tuple has a join match */
+
+/*
+ * HeapTupleHeader accessor macros
+ *
+ * Note: beware of multiple evaluations of "tup" argument. But the Set
+ * macros evaluate their other argument only once.
+ */
+
+/*
+ * HeapTupleHeaderGetRawXmin returns the "raw" xmin field, which is the xid
+ * originally used to insert the tuple. However, the tuple might actually
+ * be frozen (via HeapTupleHeaderSetXminFrozen) in which case the tuple's xmin
+ * is visible to every snapshot. Prior to PostgreSQL 9.4, we actually changed
+ * the xmin to FrozenTransactionId, and that value may still be encountered
+ * on disk.
+ */
+#define HeapTupleHeaderGetRawXmin(tup) \
+( \
+ (tup)->t_choice.t_heap.t_xmin \
+)
+
+#define HeapTupleHeaderGetXmin(tup) \
+( \
+ HeapTupleHeaderXminFrozen(tup) ? \
+ FrozenTransactionId : HeapTupleHeaderGetRawXmin(tup) \
+)
+
+#define HeapTupleHeaderSetXmin(tup, xid) \
+( \
+ (tup)->t_choice.t_heap.t_xmin = (xid) \
+)
+
+#define HeapTupleHeaderXminCommitted(tup) \
+( \
+ ((tup)->t_infomask & HEAP_XMIN_COMMITTED) != 0 \
+)
+
+#define HeapTupleHeaderXminInvalid(tup) \
+( \
+ ((tup)->t_infomask & (HEAP_XMIN_COMMITTED|HEAP_XMIN_INVALID)) == \
+ HEAP_XMIN_INVALID \
+)
+
+#define HeapTupleHeaderXminFrozen(tup) \
+( \
+ ((tup)->t_infomask & (HEAP_XMIN_FROZEN)) == HEAP_XMIN_FROZEN \
+)
+
+#define HeapTupleHeaderSetXminCommitted(tup) \
+( \
+ AssertMacro(!HeapTupleHeaderXminInvalid(tup)), \
+ ((tup)->t_infomask |= HEAP_XMIN_COMMITTED) \
+)
+
+#define HeapTupleHeaderSetXminInvalid(tup) \
+( \
+ AssertMacro(!HeapTupleHeaderXminCommitted(tup)), \
+ ((tup)->t_infomask |= HEAP_XMIN_INVALID) \
+)
+
+#define HeapTupleHeaderSetXminFrozen(tup) \
+( \
+ AssertMacro(!HeapTupleHeaderXminInvalid(tup)), \
+ ((tup)->t_infomask |= HEAP_XMIN_FROZEN) \
+)
+
+/*
+ * HeapTupleHeaderGetRawXmax gets you the raw Xmax field. To find out the Xid
+ * that updated a tuple, you might need to resolve the MultiXactId if certain
+ * bits are set. HeapTupleHeaderGetUpdateXid checks those bits and takes care
+ * to resolve the MultiXactId if necessary. This might involve multixact I/O,
+ * so it should only be used if absolutely necessary.
+ */
+#define HeapTupleHeaderGetUpdateXid(tup) \
+( \
+ (!((tup)->t_infomask & HEAP_XMAX_INVALID) && \
+ ((tup)->t_infomask & HEAP_XMAX_IS_MULTI) && \
+ !((tup)->t_infomask & HEAP_XMAX_LOCK_ONLY)) ? \
+ HeapTupleGetUpdateXid(tup) \
+ : \
+ HeapTupleHeaderGetRawXmax(tup) \
+)
+
+#define HeapTupleHeaderGetRawXmax(tup) \
+( \
+ (tup)->t_choice.t_heap.t_xmax \
+)
+
+#define HeapTupleHeaderSetXmax(tup, xid) \
+( \
+ (tup)->t_choice.t_heap.t_xmax = (xid) \
+)
+
+/*
+ * HeapTupleHeaderGetRawCommandId will give you what's in the header whether
+ * it is useful or not. Most code should use HeapTupleHeaderGetCmin or
+ * HeapTupleHeaderGetCmax instead, but note that those Assert that you can
+ * get a legitimate result, ie you are in the originating transaction!
+ */
+#define HeapTupleHeaderGetRawCommandId(tup) \
+( \
+ (tup)->t_choice.t_heap.t_field3.t_cid \
+)
+
+/* SetCmin is reasonably simple since we never need a combo CID */
+#define HeapTupleHeaderSetCmin(tup, cid) \
+do { \
+ Assert(!((tup)->t_infomask & HEAP_MOVED)); \
+ (tup)->t_choice.t_heap.t_field3.t_cid = (cid); \
+ (tup)->t_infomask &= ~HEAP_COMBOCID; \
+} while (0)
+
+/* SetCmax must be used after HeapTupleHeaderAdjustCmax; see combocid.c */
+#define HeapTupleHeaderSetCmax(tup, cid, iscombo) \
+do { \
+ Assert(!((tup)->t_infomask & HEAP_MOVED)); \
+ (tup)->t_choice.t_heap.t_field3.t_cid = (cid); \
+ if (iscombo) \
+ (tup)->t_infomask |= HEAP_COMBOCID; \
+ else \
+ (tup)->t_infomask &= ~HEAP_COMBOCID; \
+} while (0)
+
+#define HeapTupleHeaderGetXvac(tup) \
+( \
+ ((tup)->t_infomask & HEAP_MOVED) ? \
+ (tup)->t_choice.t_heap.t_field3.t_xvac \
+ : \
+ InvalidTransactionId \
+)
+
+#define HeapTupleHeaderSetXvac(tup, xid) \
+do { \
+ Assert((tup)->t_infomask & HEAP_MOVED); \
+ (tup)->t_choice.t_heap.t_field3.t_xvac = (xid); \
+} while (0)
+
+#define HeapTupleHeaderIsSpeculative(tup) \
+( \
+ (ItemPointerGetOffsetNumberNoCheck(&(tup)->t_ctid) == SpecTokenOffsetNumber) \
+)
+
+#define HeapTupleHeaderGetSpeculativeToken(tup) \
+( \
+ AssertMacro(HeapTupleHeaderIsSpeculative(tup)), \
+ ItemPointerGetBlockNumber(&(tup)->t_ctid) \
+)
+
+#define HeapTupleHeaderSetSpeculativeToken(tup, token) \
+( \
+ ItemPointerSet(&(tup)->t_ctid, token, SpecTokenOffsetNumber) \
+)
+
+#define HeapTupleHeaderIndicatesMovedPartitions(tup) \
+ (ItemPointerGetOffsetNumber(&(tup)->t_ctid) == MovedPartitionsOffsetNumber && \
+ ItemPointerGetBlockNumberNoCheck(&(tup)->t_ctid) == MovedPartitionsBlockNumber)
+
+#define HeapTupleHeaderSetMovedPartitions(tup) \
+ ItemPointerSet(&(tup)->t_ctid, MovedPartitionsBlockNumber, MovedPartitionsOffsetNumber)
+
+#define HeapTupleHeaderGetDatumLength(tup) \
+ VARSIZE(tup)
+
+#define HeapTupleHeaderSetDatumLength(tup, len) \
+ SET_VARSIZE(tup, len)
+
+#define HeapTupleHeaderGetTypeId(tup) \
+( \
+ (tup)->t_choice.t_datum.datum_typeid \
+)
+
+#define HeapTupleHeaderSetTypeId(tup, typeid) \
+( \
+ (tup)->t_choice.t_datum.datum_typeid = (typeid) \
+)
+
+#define HeapTupleHeaderGetTypMod(tup) \
+( \
+ (tup)->t_choice.t_datum.datum_typmod \
+)
+
+#define HeapTupleHeaderSetTypMod(tup, typmod) \
+( \
+ (tup)->t_choice.t_datum.datum_typmod = (typmod) \
+)
+
+/*
+ * Note that we stop considering a tuple HOT-updated as soon as it is known
+ * aborted or the would-be updating transaction is known aborted. For best
+ * efficiency, check tuple visibility before using this macro, so that the
+ * INVALID bits will be as up to date as possible.
+ */
+#define HeapTupleHeaderIsHotUpdated(tup) \
+( \
+ ((tup)->t_infomask2 & HEAP_HOT_UPDATED) != 0 && \
+ ((tup)->t_infomask & HEAP_XMAX_INVALID) == 0 && \
+ !HeapTupleHeaderXminInvalid(tup) \
+)
+
+#define HeapTupleHeaderSetHotUpdated(tup) \
+( \
+ (tup)->t_infomask2 |= HEAP_HOT_UPDATED \
+)
+
+#define HeapTupleHeaderClearHotUpdated(tup) \
+( \
+ (tup)->t_infomask2 &= ~HEAP_HOT_UPDATED \
+)
+
+#define HeapTupleHeaderIsHeapOnly(tup) \
+( \
+ ((tup)->t_infomask2 & HEAP_ONLY_TUPLE) != 0 \
+)
+
+#define HeapTupleHeaderSetHeapOnly(tup) \
+( \
+ (tup)->t_infomask2 |= HEAP_ONLY_TUPLE \
+)
+
+#define HeapTupleHeaderClearHeapOnly(tup) \
+( \
+ (tup)->t_infomask2 &= ~HEAP_ONLY_TUPLE \
+)
+
+#define HeapTupleHeaderHasMatch(tup) \
+( \
+ ((tup)->t_infomask2 & HEAP_TUPLE_HAS_MATCH) != 0 \
+)
+
+#define HeapTupleHeaderSetMatch(tup) \
+( \
+ (tup)->t_infomask2 |= HEAP_TUPLE_HAS_MATCH \
+)
+
+#define HeapTupleHeaderClearMatch(tup) \
+( \
+ (tup)->t_infomask2 &= ~HEAP_TUPLE_HAS_MATCH \
+)
+
+#define HeapTupleHeaderGetNatts(tup) \
+ ((tup)->t_infomask2 & HEAP_NATTS_MASK)
+
+#define HeapTupleHeaderSetNatts(tup, natts) \
+( \
+ (tup)->t_infomask2 = ((tup)->t_infomask2 & ~HEAP_NATTS_MASK) | (natts) \
+)
+
+#define HeapTupleHeaderHasExternal(tup) \
+ (((tup)->t_infomask & HEAP_HASEXTERNAL) != 0)
+
+
+/*
+ * BITMAPLEN(NATTS) -
+ * Computes size of null bitmap given number of data columns.
+ */
+#define BITMAPLEN(NATTS) (((int)(NATTS) + 7) / 8)
+
+/*
+ * MaxHeapTupleSize is the maximum allowed size of a heap tuple, including
+ * header and MAXALIGN alignment padding. Basically it's BLCKSZ minus the
+ * other stuff that has to be on a disk page. Since heap pages use no
+ * "special space", there's no deduction for that.
+ *
+ * NOTE: we allow for the ItemId that must point to the tuple, ensuring that
+ * an otherwise-empty page can indeed hold a tuple of this size. Because
+ * ItemIds and tuples have different alignment requirements, don't assume that
+ * you can, say, fit 2 tuples of size MaxHeapTupleSize/2 on the same page.
+ */
+#define MaxHeapTupleSize (BLCKSZ - MAXALIGN(SizeOfPageHeaderData + sizeof(ItemIdData)))
+#define MinHeapTupleSize MAXALIGN(SizeofHeapTupleHeader)
+
+/*
+ * MaxHeapTuplesPerPage is an upper bound on the number of tuples that can
+ * fit on one heap page. (Note that indexes could have more, because they
+ * use a smaller tuple header.) We arrive at the divisor because each tuple
+ * must be maxaligned, and it must have an associated line pointer.
+ *
+ * Note: with HOT, there could theoretically be more line pointers (not actual
+ * tuples) than this on a heap page. However we constrain the number of line
+ * pointers to this anyway, to avoid excessive line-pointer bloat and not
+ * require increases in the size of work arrays.
+ */
+#define MaxHeapTuplesPerPage \
+ ((int) ((BLCKSZ - SizeOfPageHeaderData) / \
+ (MAXALIGN(SizeofHeapTupleHeader) + sizeof(ItemIdData))))
+
+/*
+ * MaxAttrSize is a somewhat arbitrary upper limit on the declared size of
+ * data fields of char(n) and similar types. It need not have anything
+ * directly to do with the *actual* upper limit of varlena values, which
+ * is currently 1Gb (see TOAST structures in postgres.h). I've set it
+ * at 10Mb which seems like a reasonable number --- tgl 8/6/00.
+ */
+#define MaxAttrSize (10 * 1024 * 1024)
+
+
+/*
+ * MinimalTuple is an alternative representation that is used for transient
+ * tuples inside the executor, in places where transaction status information
+ * is not required, the tuple rowtype is known, and shaving off a few bytes
+ * is worthwhile because we need to store many tuples. The representation
+ * is chosen so that tuple access routines can work with either full or
+ * minimal tuples via a HeapTupleData pointer structure. The access routines
+ * see no difference, except that they must not access the transaction status
+ * or t_ctid fields because those aren't there.
+ *
+ * For the most part, MinimalTuples should be accessed via TupleTableSlot
+ * routines. These routines will prevent access to the "system columns"
+ * and thereby prevent accidental use of the nonexistent fields.
+ *
+ * MinimalTupleData contains a length word, some padding, and fields matching
+ * HeapTupleHeaderData beginning with t_infomask2. The padding is chosen so
+ * that offsetof(t_infomask2) is the same modulo MAXIMUM_ALIGNOF in both
+ * structs. This makes data alignment rules equivalent in both cases.
+ *
+ * When a minimal tuple is accessed via a HeapTupleData pointer, t_data is
+ * set to point MINIMAL_TUPLE_OFFSET bytes before the actual start of the
+ * minimal tuple --- that is, where a full tuple matching the minimal tuple's
+ * data would start. This trick is what makes the structs seem equivalent.
+ *
+ * Note that t_hoff is computed the same as in a full tuple, hence it includes
+ * the MINIMAL_TUPLE_OFFSET distance. t_len does not include that, however.
+ *
+ * MINIMAL_TUPLE_DATA_OFFSET is the offset to the first useful (non-pad) data
+ * other than the length word. tuplesort.c and tuplestore.c use this to avoid
+ * writing the padding to disk.
+ */
+#define MINIMAL_TUPLE_OFFSET \
+ ((offsetof(HeapTupleHeaderData, t_infomask2) - sizeof(uint32)) / MAXIMUM_ALIGNOF * MAXIMUM_ALIGNOF)
+#define MINIMAL_TUPLE_PADDING \
+ ((offsetof(HeapTupleHeaderData, t_infomask2) - sizeof(uint32)) % MAXIMUM_ALIGNOF)
+#define MINIMAL_TUPLE_DATA_OFFSET \
+ offsetof(MinimalTupleData, t_infomask2)
+
+struct MinimalTupleData
+{
+ uint32 t_len; /* actual length of minimal tuple */
+
+ char mt_padding[MINIMAL_TUPLE_PADDING];
+
+ /* Fields below here must match HeapTupleHeaderData! */
+
+ uint16 t_infomask2; /* number of attributes + various flags */
+
+ uint16 t_infomask; /* various flag bits, see below */
+
+ uint8 t_hoff; /* sizeof header incl. bitmap, padding */
+
+ /* ^ - 23 bytes - ^ */
+
+ bits8 t_bits[FLEXIBLE_ARRAY_MEMBER]; /* bitmap of NULLs */
+
+ /* MORE DATA FOLLOWS AT END OF STRUCT */
+};
+
+/* typedef appears in htup.h */
+
+#define SizeofMinimalTupleHeader offsetof(MinimalTupleData, t_bits)
+
+
+/*
+ * GETSTRUCT - given a HeapTuple pointer, return address of the user data
+ */
+#define GETSTRUCT(TUP) ((char *) ((TUP)->t_data) + (TUP)->t_data->t_hoff)
+
+/*
+ * Accessor macros to be used with HeapTuple pointers.
+ */
+
+#define HeapTupleHasNulls(tuple) \
+ (((tuple)->t_data->t_infomask & HEAP_HASNULL) != 0)
+
+#define HeapTupleNoNulls(tuple) \
+ (!((tuple)->t_data->t_infomask & HEAP_HASNULL))
+
+#define HeapTupleHasVarWidth(tuple) \
+ (((tuple)->t_data->t_infomask & HEAP_HASVARWIDTH) != 0)
+
+#define HeapTupleAllFixed(tuple) \
+ (!((tuple)->t_data->t_infomask & HEAP_HASVARWIDTH))
+
+#define HeapTupleHasExternal(tuple) \
+ (((tuple)->t_data->t_infomask & HEAP_HASEXTERNAL) != 0)
+
+#define HeapTupleIsHotUpdated(tuple) \
+ HeapTupleHeaderIsHotUpdated((tuple)->t_data)
+
+#define HeapTupleSetHotUpdated(tuple) \
+ HeapTupleHeaderSetHotUpdated((tuple)->t_data)
+
+#define HeapTupleClearHotUpdated(tuple) \
+ HeapTupleHeaderClearHotUpdated((tuple)->t_data)
+
+#define HeapTupleIsHeapOnly(tuple) \
+ HeapTupleHeaderIsHeapOnly((tuple)->t_data)
+
+#define HeapTupleSetHeapOnly(tuple) \
+ HeapTupleHeaderSetHeapOnly((tuple)->t_data)
+
+#define HeapTupleClearHeapOnly(tuple) \
+ HeapTupleHeaderClearHeapOnly((tuple)->t_data)
+
+
+/* ----------------
+ * fastgetattr
+ *
+ * Fetch a user attribute's value as a Datum (might be either a
+ * value, or a pointer into the data area of the tuple).
+ *
+ * This must not be used when a system attribute might be requested.
+ * Furthermore, the passed attnum MUST be valid. Use heap_getattr()
+ * instead, if in doubt.
+ *
+ * This gets called many times, so we macro the cacheable and NULL
+ * lookups, and call nocachegetattr() for the rest.
+ * ----------------
+ */
+
+#if !defined(DISABLE_COMPLEX_MACRO)
+
+#define fastgetattr(tup, attnum, tupleDesc, isnull) \
+( \
+ AssertMacro((attnum) > 0), \
+ (*(isnull) = false), \
+ HeapTupleNoNulls(tup) ? \
+ ( \
+ TupleDescAttr((tupleDesc), (attnum)-1)->attcacheoff >= 0 ? \
+ ( \
+ fetchatt(TupleDescAttr((tupleDesc), (attnum)-1), \
+ (char *) (tup)->t_data + (tup)->t_data->t_hoff + \
+ TupleDescAttr((tupleDesc), (attnum)-1)->attcacheoff)\
+ ) \
+ : \
+ nocachegetattr((tup), (attnum), (tupleDesc)) \
+ ) \
+ : \
+ ( \
+ att_isnull((attnum)-1, (tup)->t_data->t_bits) ? \
+ ( \
+ (*(isnull) = true), \
+ (Datum)NULL \
+ ) \
+ : \
+ ( \
+ nocachegetattr((tup), (attnum), (tupleDesc)) \
+ ) \
+ ) \
+)
+#else /* defined(DISABLE_COMPLEX_MACRO) */
+
+extern Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
+ bool *isnull);
+#endif /* defined(DISABLE_COMPLEX_MACRO) */
+
+
+/* ----------------
+ * heap_getattr
+ *
+ * Extract an attribute of a heap tuple and return it as a Datum.
+ * This works for either system or user attributes. The given attnum
+ * is properly range-checked.
+ *
+ * If the field in question has a NULL value, we return a zero Datum
+ * and set *isnull == true. Otherwise, we set *isnull == false.
+ *
+ * <tup> is the pointer to the heap tuple. <attnum> is the attribute
+ * number of the column (field) caller wants. <tupleDesc> is a
+ * pointer to the structure describing the row and all its fields.
+ * ----------------
+ */
+#define heap_getattr(tup, attnum, tupleDesc, isnull) \
+ ( \
+ ((attnum) > 0) ? \
+ ( \
+ ((attnum) > (int) HeapTupleHeaderGetNatts((tup)->t_data)) ? \
+ getmissingattr((tupleDesc), (attnum), (isnull)) \
+ : \
+ fastgetattr((tup), (attnum), (tupleDesc), (isnull)) \
+ ) \
+ : \
+ heap_getsysattr((tup), (attnum), (tupleDesc), (isnull)) \
+ )
+
+
+/* prototypes for functions in common/heaptuple.c */
+extern Size heap_compute_data_size(TupleDesc tupleDesc,
+ Datum *values, bool *isnull);
+extern void heap_fill_tuple(TupleDesc tupleDesc,
+ Datum *values, bool *isnull,
+ char *data, Size data_size,
+ uint16 *infomask, bits8 *bit);
+extern bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc);
+extern Datum nocachegetattr(HeapTuple tup, int attnum,
+ TupleDesc att);
+extern Datum heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
+ bool *isnull);
+extern Datum getmissingattr(TupleDesc tupleDesc,
+ int attnum, bool *isnull);
+extern HeapTuple heap_copytuple(HeapTuple tuple);
+extern void heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest);
+extern Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc);
+extern HeapTuple heap_form_tuple(TupleDesc tupleDescriptor,
+ Datum *values, bool *isnull);
+extern HeapTuple heap_modify_tuple(HeapTuple tuple,
+ TupleDesc tupleDesc,
+ Datum *replValues,
+ bool *replIsnull,
+ bool *doReplace);
+extern HeapTuple heap_modify_tuple_by_cols(HeapTuple tuple,
+ TupleDesc tupleDesc,
+ int nCols,
+ int *replCols,
+ Datum *replValues,
+ bool *replIsnull);
+extern void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
+ Datum *values, bool *isnull);
+extern void heap_freetuple(HeapTuple htup);
+extern MinimalTuple heap_form_minimal_tuple(TupleDesc tupleDescriptor,
+ Datum *values, bool *isnull);
+extern void heap_free_minimal_tuple(MinimalTuple mtup);
+extern MinimalTuple heap_copy_minimal_tuple(MinimalTuple mtup);
+extern HeapTuple heap_tuple_from_minimal_tuple(MinimalTuple mtup);
+extern MinimalTuple minimal_tuple_from_heap_tuple(HeapTuple htup);
+extern size_t varsize_any(void *p);
+extern HeapTuple heap_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc);
+extern MinimalTuple minimal_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc);
+
+#endif /* HTUP_DETAILS_H */
diff --git a/src/include/access/itup.h b/src/include/access/itup.h
new file mode 100644
index 0000000..b9c41d3
--- /dev/null
+++ b/src/include/access/itup.h
@@ -0,0 +1,161 @@
+/*-------------------------------------------------------------------------
+ *
+ * itup.h
+ * POSTGRES index tuple definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/itup.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ITUP_H
+#define ITUP_H
+
+#include "access/tupdesc.h"
+#include "access/tupmacs.h"
+#include "storage/bufpage.h"
+#include "storage/itemptr.h"
+
+/*
+ * Index tuple header structure
+ *
+ * All index tuples start with IndexTupleData. If the HasNulls bit is set,
+ * this is followed by an IndexAttributeBitMapData. The index attribute
+ * values follow, beginning at a MAXALIGN boundary.
+ *
+ * Note that the space allocated for the bitmap does not vary with the number
+ * of attributes; that is because we don't have room to store the number of
+ * attributes in the header. Given the MAXALIGN constraint there's no space
+ * savings to be had anyway, for usual values of INDEX_MAX_KEYS.
+ */
+
+typedef struct IndexTupleData
+{
+ ItemPointerData t_tid; /* reference TID to heap tuple */
+
+ /* ---------------
+ * t_info is laid out in the following fashion:
+ *
+ * 15th (high) bit: has nulls
+ * 14th bit: has var-width attributes
+ * 13th bit: AM-defined meaning
+ * 12-0 bit: size of tuple
+ * ---------------
+ */
+
+ unsigned short t_info; /* various info about tuple */
+
+} IndexTupleData; /* MORE DATA FOLLOWS AT END OF STRUCT */
+
+typedef IndexTupleData *IndexTuple;
+
+typedef struct IndexAttributeBitMapData
+{
+ bits8 bits[(INDEX_MAX_KEYS + 8 - 1) / 8];
+} IndexAttributeBitMapData;
+
+typedef IndexAttributeBitMapData * IndexAttributeBitMap;
+
+/*
+ * t_info manipulation macros
+ */
+#define INDEX_SIZE_MASK 0x1FFF
+#define INDEX_AM_RESERVED_BIT 0x2000 /* reserved for index-AM specific
+ * usage */
+#define INDEX_VAR_MASK 0x4000
+#define INDEX_NULL_MASK 0x8000
+
+#define IndexTupleSize(itup) ((Size) ((itup)->t_info & INDEX_SIZE_MASK))
+#define IndexTupleHasNulls(itup) ((((IndexTuple) (itup))->t_info & INDEX_NULL_MASK))
+#define IndexTupleHasVarwidths(itup) ((((IndexTuple) (itup))->t_info & INDEX_VAR_MASK))
+
+
+/*
+ * Takes an infomask as argument (primarily because this needs to be usable
+ * at index_form_tuple time so enough space is allocated).
+ */
+#define IndexInfoFindDataOffset(t_info) \
+( \
+ (!((t_info) & INDEX_NULL_MASK)) ? \
+ ( \
+ (Size)MAXALIGN(sizeof(IndexTupleData)) \
+ ) \
+ : \
+ ( \
+ (Size)MAXALIGN(sizeof(IndexTupleData) + sizeof(IndexAttributeBitMapData)) \
+ ) \
+)
+
+/* ----------------
+ * index_getattr
+ *
+ * This gets called many times, so we macro the cacheable and NULL
+ * lookups, and call nocache_index_getattr() for the rest.
+ *
+ * ----------------
+ */
+#define index_getattr(tup, attnum, tupleDesc, isnull) \
+( \
+ AssertMacro(PointerIsValid(isnull) && (attnum) > 0), \
+ *(isnull) = false, \
+ !IndexTupleHasNulls(tup) ? \
+ ( \
+ TupleDescAttr((tupleDesc), (attnum)-1)->attcacheoff >= 0 ? \
+ ( \
+ fetchatt(TupleDescAttr((tupleDesc), (attnum)-1), \
+ (char *) (tup) + IndexInfoFindDataOffset((tup)->t_info) \
+ + TupleDescAttr((tupleDesc), (attnum)-1)->attcacheoff) \
+ ) \
+ : \
+ nocache_index_getattr((tup), (attnum), (tupleDesc)) \
+ ) \
+ : \
+ ( \
+ (att_isnull((attnum)-1, (char *)(tup) + sizeof(IndexTupleData))) ? \
+ ( \
+ *(isnull) = true, \
+ (Datum)NULL \
+ ) \
+ : \
+ ( \
+ nocache_index_getattr((tup), (attnum), (tupleDesc)) \
+ ) \
+ ) \
+)
+
+/*
+ * MaxIndexTuplesPerPage is an upper bound on the number of tuples that can
+ * fit on one index page. An index tuple must have either data or a null
+ * bitmap, so we can safely assume it's at least 1 byte bigger than a bare
+ * IndexTupleData struct. We arrive at the divisor because each tuple
+ * must be maxaligned, and it must have an associated line pointer.
+ *
+ * To be index-type-independent, this does not account for any special space
+ * on the page, and is thus conservative.
+ *
+ * Note: in btree non-leaf pages, the first tuple has no key (it's implicitly
+ * minus infinity), thus breaking the "at least 1 byte bigger" assumption.
+ * On such a page, N tuples could take one MAXALIGN quantum less space than
+ * estimated here, seemingly allowing one more tuple than estimated here.
+ * But such a page always has at least MAXALIGN special space, so we're safe.
+ */
+#define MaxIndexTuplesPerPage \
+ ((int) ((BLCKSZ - SizeOfPageHeaderData) / \
+ (MAXALIGN(sizeof(IndexTupleData) + 1) + sizeof(ItemIdData))))
+
+
+/* routines in indextuple.c */
+extern IndexTuple index_form_tuple(TupleDesc tupleDescriptor,
+ Datum *values, bool *isnull);
+extern Datum nocache_index_getattr(IndexTuple tup, int attnum,
+ TupleDesc tupleDesc);
+extern void index_deform_tuple(IndexTuple tup, TupleDesc tupleDescriptor,
+ Datum *values, bool *isnull);
+extern IndexTuple CopyIndexTuple(IndexTuple source);
+extern IndexTuple index_truncate_tuple(TupleDesc sourceDescriptor,
+ IndexTuple source, int leavenatts);
+
+#endif /* ITUP_H */
diff --git a/src/include/access/multixact.h b/src/include/access/multixact.h
new file mode 100644
index 0000000..6d72900
--- /dev/null
+++ b/src/include/access/multixact.h
@@ -0,0 +1,160 @@
+/*
+ * multixact.h
+ *
+ * PostgreSQL multi-transaction-log manager
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/multixact.h
+ */
+#ifndef MULTIXACT_H
+#define MULTIXACT_H
+
+#include "access/xlogreader.h"
+#include "lib/stringinfo.h"
+
+
+/*
+ * The first two MultiXactId values are reserved to store the truncation Xid
+ * and epoch of the first segment, so we start assigning multixact values from
+ * 2.
+ */
+#define InvalidMultiXactId ((MultiXactId) 0)
+#define FirstMultiXactId ((MultiXactId) 1)
+#define MaxMultiXactId ((MultiXactId) 0xFFFFFFFF)
+
+#define MultiXactIdIsValid(multi) ((multi) != InvalidMultiXactId)
+
+#define MaxMultiXactOffset ((MultiXactOffset) 0xFFFFFFFF)
+
+/* Number of SLRU buffers to use for multixact */
+#define NUM_MULTIXACTOFFSET_BUFFERS 8
+#define NUM_MULTIXACTMEMBER_BUFFERS 16
+
+/*
+ * Possible multixact lock modes ("status"). The first four modes are for
+ * tuple locks (FOR KEY SHARE, FOR SHARE, FOR NO KEY UPDATE, FOR UPDATE); the
+ * next two are used for update and delete modes.
+ */
+typedef enum
+{
+ MultiXactStatusForKeyShare = 0x00,
+ MultiXactStatusForShare = 0x01,
+ MultiXactStatusForNoKeyUpdate = 0x02,
+ MultiXactStatusForUpdate = 0x03,
+ /* an update that doesn't touch "key" columns */
+ MultiXactStatusNoKeyUpdate = 0x04,
+ /* other updates, and delete */
+ MultiXactStatusUpdate = 0x05
+} MultiXactStatus;
+
+#define MaxMultiXactStatus MultiXactStatusUpdate
+
+/* does a status value correspond to a tuple update? */
+#define ISUPDATE_from_mxstatus(status) \
+ ((status) > MultiXactStatusForUpdate)
+
+
+typedef struct MultiXactMember
+{
+ TransactionId xid;
+ MultiXactStatus status;
+} MultiXactMember;
+
+
+/* ----------------
+ * multixact-related XLOG entries
+ * ----------------
+ */
+
+#define XLOG_MULTIXACT_ZERO_OFF_PAGE 0x00
+#define XLOG_MULTIXACT_ZERO_MEM_PAGE 0x10
+#define XLOG_MULTIXACT_CREATE_ID 0x20
+#define XLOG_MULTIXACT_TRUNCATE_ID 0x30
+
+typedef struct xl_multixact_create
+{
+ MultiXactId mid; /* new MultiXact's ID */
+ MultiXactOffset moff; /* its starting offset in members file */
+ int32 nmembers; /* number of member XIDs */
+ MultiXactMember members[FLEXIBLE_ARRAY_MEMBER];
+} xl_multixact_create;
+
+#define SizeOfMultiXactCreate (offsetof(xl_multixact_create, members))
+
+typedef struct xl_multixact_truncate
+{
+ Oid oldestMultiDB;
+
+ /* to-be-truncated range of multixact offsets */
+ MultiXactId startTruncOff; /* just for completeness' sake */
+ MultiXactId endTruncOff;
+
+ /* to-be-truncated range of multixact members */
+ MultiXactOffset startTruncMemb;
+ MultiXactOffset endTruncMemb;
+} xl_multixact_truncate;
+
+#define SizeOfMultiXactTruncate (sizeof(xl_multixact_truncate))
+
+
+extern MultiXactId MultiXactIdCreate(TransactionId xid1,
+ MultiXactStatus status1, TransactionId xid2,
+ MultiXactStatus status2);
+extern MultiXactId MultiXactIdExpand(MultiXactId multi, TransactionId xid,
+ MultiXactStatus status);
+extern MultiXactId MultiXactIdCreateFromMembers(int nmembers,
+ MultiXactMember *members);
+
+extern MultiXactId ReadNextMultiXactId(void);
+extern bool MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly);
+extern void MultiXactIdSetOldestMember(void);
+extern int GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **xids,
+ bool allow_old, bool isLockOnly);
+extern bool MultiXactIdPrecedes(MultiXactId multi1, MultiXactId multi2);
+extern bool MultiXactIdPrecedesOrEquals(MultiXactId multi1,
+ MultiXactId multi2);
+
+extern void AtEOXact_MultiXact(void);
+extern void AtPrepare_MultiXact(void);
+extern void PostPrepare_MultiXact(TransactionId xid);
+
+extern Size MultiXactShmemSize(void);
+extern void MultiXactShmemInit(void);
+extern void BootStrapMultiXact(void);
+extern void StartupMultiXact(void);
+extern void TrimMultiXact(void);
+extern void ShutdownMultiXact(void);
+extern void SetMultiXactIdLimit(MultiXactId oldest_datminmxid,
+ Oid oldest_datoid,
+ bool is_startup);
+extern void MultiXactGetCheckptMulti(bool is_shutdown,
+ MultiXactId *nextMulti,
+ MultiXactOffset *nextMultiOffset,
+ MultiXactId *oldestMulti,
+ Oid *oldestMultiDB);
+extern void CheckPointMultiXact(void);
+extern MultiXactId GetOldestMultiXactId(void);
+extern void TruncateMultiXact(MultiXactId oldestMulti, Oid oldestMultiDB);
+extern void MultiXactSetNextMXact(MultiXactId nextMulti,
+ MultiXactOffset nextMultiOffset);
+extern void MultiXactAdvanceNextMXact(MultiXactId minMulti,
+ MultiXactOffset minMultiOffset);
+extern void MultiXactAdvanceOldest(MultiXactId oldestMulti, Oid oldestMultiDB);
+extern int MultiXactMemberFreezeThreshold(void);
+
+extern void multixact_twophase_recover(TransactionId xid, uint16 info,
+ void *recdata, uint32 len);
+extern void multixact_twophase_postcommit(TransactionId xid, uint16 info,
+ void *recdata, uint32 len);
+extern void multixact_twophase_postabort(TransactionId xid, uint16 info,
+ void *recdata, uint32 len);
+
+extern void multixact_redo(XLogReaderState *record);
+extern void multixact_desc(StringInfo buf, XLogReaderState *record);
+extern const char *multixact_identify(uint8 info);
+extern char *mxid_to_string(MultiXactId multi, int nmembers,
+ MultiXactMember *members);
+
+#endif /* MULTIXACT_H */
diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h
new file mode 100644
index 0000000..79506c7
--- /dev/null
+++ b/src/include/access/nbtree.h
@@ -0,0 +1,1148 @@
+/*-------------------------------------------------------------------------
+ *
+ * nbtree.h
+ * header file for postgres btree access method implementation.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/nbtree.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NBTREE_H
+#define NBTREE_H
+
+#include "access/amapi.h"
+#include "access/itup.h"
+#include "access/sdir.h"
+#include "access/xlogreader.h"
+#include "catalog/pg_am_d.h"
+#include "catalog/pg_index.h"
+#include "lib/stringinfo.h"
+#include "storage/bufmgr.h"
+#include "storage/shm_toc.h"
+
+/* There's room for a 16-bit vacuum cycle ID in BTPageOpaqueData */
+typedef uint16 BTCycleId;
+
+/*
+ * BTPageOpaqueData -- At the end of every page, we store a pointer
+ * to both siblings in the tree. This is used to do forward/backward
+ * index scans. The next-page link is also critical for recovery when
+ * a search has navigated to the wrong page due to concurrent page splits
+ * or deletions; see src/backend/access/nbtree/README for more info.
+ *
+ * In addition, we store the page's btree level (counting upwards from
+ * zero at a leaf page) as well as some flag bits indicating the page type
+ * and status. If the page is deleted, we replace the level with the
+ * next-transaction-ID value indicating when it is safe to reclaim the page.
+ *
+ * We also store a "vacuum cycle ID". When a page is split while VACUUM is
+ * processing the index, a nonzero value associated with the VACUUM run is
+ * stored into both halves of the split page. (If VACUUM is not running,
+ * both pages receive zero cycleids.) This allows VACUUM to detect whether
+ * a page was split since it started, with a small probability of false match
+ * if the page was last split some exact multiple of MAX_BT_CYCLE_ID VACUUMs
+ * ago. Also, during a split, the BTP_SPLIT_END flag is cleared in the left
+ * (original) page, and set in the right page, but only if the next page
+ * to its right has a different cycleid.
+ *
+ * NOTE: the BTP_LEAF flag bit is redundant since level==0 could be tested
+ * instead.
+ */
+
+typedef struct BTPageOpaqueData
+{
+ BlockNumber btpo_prev; /* left sibling, or P_NONE if leftmost */
+ BlockNumber btpo_next; /* right sibling, or P_NONE if rightmost */
+ union
+ {
+ uint32 level; /* tree level --- zero for leaf pages */
+ TransactionId xact; /* next transaction ID, if deleted */
+ } btpo;
+ uint16 btpo_flags; /* flag bits, see below */
+ BTCycleId btpo_cycleid; /* vacuum cycle ID of latest split */
+} BTPageOpaqueData;
+
+typedef BTPageOpaqueData *BTPageOpaque;
+
+/* Bits defined in btpo_flags */
+#define BTP_LEAF (1 << 0) /* leaf page, i.e. not internal page */
+#define BTP_ROOT (1 << 1) /* root page (has no parent) */
+#define BTP_DELETED (1 << 2) /* page has been deleted from tree */
+#define BTP_META (1 << 3) /* meta-page */
+#define BTP_HALF_DEAD (1 << 4) /* empty, but still in tree */
+#define BTP_SPLIT_END (1 << 5) /* rightmost page of split group */
+#define BTP_HAS_GARBAGE (1 << 6) /* page has LP_DEAD tuples */
+#define BTP_INCOMPLETE_SPLIT (1 << 7) /* right sibling's downlink is missing */
+
+/*
+ * The max allowed value of a cycle ID is a bit less than 64K. This is
+ * for convenience of pg_filedump and similar utilities: we want to use
+ * the last 2 bytes of special space as an index type indicator, and
+ * restricting cycle ID lets btree use that space for vacuum cycle IDs
+ * while still allowing index type to be identified.
+ */
+#define MAX_BT_CYCLE_ID 0xFF7F
+
+
+/*
+ * The Meta page is always the first page in the btree index.
+ * Its primary purpose is to point to the location of the btree root page.
+ * We also point to the "fast" root, which is the current effective root;
+ * see README for discussion.
+ */
+
+typedef struct BTMetaPageData
+{
+ uint32 btm_magic; /* should contain BTREE_MAGIC */
+ uint32 btm_version; /* nbtree version (always <= BTREE_VERSION) */
+ BlockNumber btm_root; /* current root location */
+ uint32 btm_level; /* tree level of the root page */
+ BlockNumber btm_fastroot; /* current "fast" root location */
+ uint32 btm_fastlevel; /* tree level of the "fast" root page */
+ /* remaining fields only valid when btm_version >= BTREE_NOVAC_VERSION */
+ TransactionId btm_oldest_btpo_xact; /* oldest btpo_xact among all deleted
+ * pages */
+ float8 btm_last_cleanup_num_heap_tuples; /* number of heap tuples
+ * during last cleanup */
+ bool btm_allequalimage; /* are all columns "equalimage"? */
+} BTMetaPageData;
+
+#define BTPageGetMeta(p) \
+ ((BTMetaPageData *) PageGetContents(p))
+
+/*
+ * The current Btree version is 4. That's what you'll get when you create
+ * a new index.
+ *
+ * Btree version 3 was used in PostgreSQL v11. It is mostly the same as
+ * version 4, but heap TIDs were not part of the keyspace. Index tuples
+ * with duplicate keys could be stored in any order. We continue to
+ * support reading and writing Btree versions 2 and 3, so that they don't
+ * need to be immediately re-indexed at pg_upgrade. In order to get the
+ * new heapkeyspace semantics, however, a REINDEX is needed.
+ *
+ * Deduplication is safe to use when the btm_allequalimage field is set to
+ * true. It's safe to read the btm_allequalimage field on version 3, but
+ * only version 4 indexes make use of deduplication. Even version 4
+ * indexes created on PostgreSQL v12 will need a REINDEX to make use of
+ * deduplication, though, since there is no other way to set
+ * btm_allequalimage to true (pg_upgrade hasn't been taught to set the
+ * metapage field).
+ *
+ * Btree version 2 is mostly the same as version 3. There are two new
+ * fields in the metapage that were introduced in version 3. A version 2
+ * metapage will be automatically upgraded to version 3 on the first
+ * insert to it. INCLUDE indexes cannot use version 2.
+ */
+#define BTREE_METAPAGE 0 /* first page is meta */
+#define BTREE_MAGIC 0x053162 /* magic number in metapage */
+#define BTREE_VERSION 4 /* current version number */
+#define BTREE_MIN_VERSION 2 /* minimum supported version */
+#define BTREE_NOVAC_VERSION 3 /* version with all meta fields set */
+
+/*
+ * Maximum size of a btree index entry, including its tuple header.
+ *
+ * We actually need to be able to fit three items on every page,
+ * so restrict any one item to 1/3 the per-page available space.
+ *
+ * There are rare cases where _bt_truncate() will need to enlarge
+ * a heap index tuple to make space for a tiebreaker heap TID
+ * attribute, which we account for here.
+ */
+#define BTMaxItemSize(page) \
+ MAXALIGN_DOWN((PageGetPageSize(page) - \
+ MAXALIGN(SizeOfPageHeaderData + \
+ 3*sizeof(ItemIdData) + \
+ 3*sizeof(ItemPointerData)) - \
+ MAXALIGN(sizeof(BTPageOpaqueData))) / 3)
+#define BTMaxItemSizeNoHeapTid(page) \
+ MAXALIGN_DOWN((PageGetPageSize(page) - \
+ MAXALIGN(SizeOfPageHeaderData + 3*sizeof(ItemIdData)) - \
+ MAXALIGN(sizeof(BTPageOpaqueData))) / 3)
+
+/*
+ * MaxTIDsPerBTreePage is an upper bound on the number of heap TIDs tuples
+ * that may be stored on a btree leaf page. It is used to size the
+ * per-page temporary buffers used by index scans.
+ *
+ * Note: we don't bother considering per-tuple overheads here to keep
+ * things simple (value is based on how many elements a single array of
+ * heap TIDs must have to fill the space between the page header and
+ * special area). The value is slightly higher (i.e. more conservative)
+ * than necessary as a result, which is considered acceptable.
+ */
+#define MaxTIDsPerBTreePage \
+ (int) ((BLCKSZ - SizeOfPageHeaderData - sizeof(BTPageOpaqueData)) / \
+ sizeof(ItemPointerData))
+
+/*
+ * The leaf-page fillfactor defaults to 90% but is user-adjustable.
+ * For pages above the leaf level, we use a fixed 70% fillfactor.
+ * The fillfactor is applied during index build and when splitting
+ * a rightmost page; when splitting non-rightmost pages we try to
+ * divide the data equally. When splitting a page that's entirely
+ * filled with a single value (duplicates), the effective leaf-page
+ * fillfactor is 96%, regardless of whether the page is a rightmost
+ * page.
+ */
+#define BTREE_MIN_FILLFACTOR 10
+#define BTREE_DEFAULT_FILLFACTOR 90
+#define BTREE_NONLEAF_FILLFACTOR 70
+#define BTREE_SINGLEVAL_FILLFACTOR 96
+
+/*
+ * In general, the btree code tries to localize its knowledge about
+ * page layout to a couple of routines. However, we need a special
+ * value to indicate "no page number" in those places where we expect
+ * page numbers. We can use zero for this because we never need to
+ * make a pointer to the metadata page.
+ */
+
+#define P_NONE 0
+
+/*
+ * Macros to test whether a page is leftmost or rightmost on its tree level,
+ * as well as other state info kept in the opaque data.
+ */
+#define P_LEFTMOST(opaque) ((opaque)->btpo_prev == P_NONE)
+#define P_RIGHTMOST(opaque) ((opaque)->btpo_next == P_NONE)
+#define P_ISLEAF(opaque) (((opaque)->btpo_flags & BTP_LEAF) != 0)
+#define P_ISROOT(opaque) (((opaque)->btpo_flags & BTP_ROOT) != 0)
+#define P_ISDELETED(opaque) (((opaque)->btpo_flags & BTP_DELETED) != 0)
+#define P_ISMETA(opaque) (((opaque)->btpo_flags & BTP_META) != 0)
+#define P_ISHALFDEAD(opaque) (((opaque)->btpo_flags & BTP_HALF_DEAD) != 0)
+#define P_IGNORE(opaque) (((opaque)->btpo_flags & (BTP_DELETED|BTP_HALF_DEAD)) != 0)
+#define P_HAS_GARBAGE(opaque) (((opaque)->btpo_flags & BTP_HAS_GARBAGE) != 0)
+#define P_INCOMPLETE_SPLIT(opaque) (((opaque)->btpo_flags & BTP_INCOMPLETE_SPLIT) != 0)
+
+/*
+ * Lehman and Yao's algorithm requires a ``high key'' on every non-rightmost
+ * page. The high key is not a tuple that is used to visit the heap. It is
+ * a pivot tuple (see "Notes on B-Tree tuple format" below for definition).
+ * The high key on a page is required to be greater than or equal to any
+ * other key that appears on the page. If we find ourselves trying to
+ * insert a key that is strictly > high key, we know we need to move right
+ * (this should only happen if the page was split since we examined the
+ * parent page).
+ *
+ * Our insertion algorithm guarantees that we can use the initial least key
+ * on our right sibling as the high key. Once a page is created, its high
+ * key changes only if the page is split.
+ *
+ * On a non-rightmost page, the high key lives in item 1 and data items
+ * start in item 2. Rightmost pages have no high key, so we store data
+ * items beginning in item 1.
+ */
+
+#define P_HIKEY ((OffsetNumber) 1)
+#define P_FIRSTKEY ((OffsetNumber) 2)
+#define P_FIRSTDATAKEY(opaque) (P_RIGHTMOST(opaque) ? P_HIKEY : P_FIRSTKEY)
+
+/*
+ * Notes on B-Tree tuple format, and key and non-key attributes:
+ *
+ * INCLUDE B-Tree indexes have non-key attributes. These are extra
+ * attributes that may be returned by index-only scans, but do not influence
+ * the order of items in the index (formally, non-key attributes are not
+ * considered to be part of the key space). Non-key attributes are only
+ * present in leaf index tuples whose item pointers actually point to heap
+ * tuples (non-pivot tuples). _bt_check_natts() enforces the rules
+ * described here.
+ *
+ * Non-pivot tuple format (plain/non-posting variant):
+ *
+ * t_tid | t_info | key values | INCLUDE columns, if any
+ *
+ * t_tid points to the heap TID, which is a tiebreaker key column as of
+ * BTREE_VERSION 4.
+ *
+ * Non-pivot tuples complement pivot tuples, which only have key columns.
+ * The sole purpose of pivot tuples is to represent how the key space is
+ * separated. In general, any B-Tree index that has more than one level
+ * (i.e. any index that does not just consist of a metapage and a single
+ * leaf root page) must have some number of pivot tuples, since pivot
+ * tuples are used for traversing the tree. Suffix truncation can omit
+ * trailing key columns when a new pivot is formed, which makes minus
+ * infinity their logical value. Since BTREE_VERSION 4 indexes treat heap
+ * TID as a trailing key column that ensures that all index tuples are
+ * physically unique, it is necessary to represent heap TID as a trailing
+ * key column in pivot tuples, though very often this can be truncated
+ * away, just like any other key column. (Actually, the heap TID is
+ * omitted rather than truncated, since its representation is different to
+ * the non-pivot representation.)
+ *
+ * Pivot tuple format:
+ *
+ * t_tid | t_info | key values | [heap TID]
+ *
+ * We store the number of columns present inside pivot tuples by abusing
+ * their t_tid offset field, since pivot tuples never need to store a real
+ * offset (pivot tuples generally store a downlink in t_tid, though). The
+ * offset field only stores the number of columns/attributes when the
+ * INDEX_ALT_TID_MASK bit is set, which doesn't count the trailing heap
+ * TID column sometimes stored in pivot tuples -- that's represented by
+ * the presence of BT_PIVOT_HEAP_TID_ATTR. The INDEX_ALT_TID_MASK bit in
+ * t_info is always set on BTREE_VERSION 4 pivot tuples, since
+ * BTreeTupleIsPivot() must work reliably on heapkeyspace versions.
+ *
+ * In version 2 or version 3 (!heapkeyspace) indexes, INDEX_ALT_TID_MASK
+ * might not be set in pivot tuples. BTreeTupleIsPivot() won't work
+ * reliably as a result. The number of columns stored is implicitly the
+ * same as the number of columns in the index, just like any non-pivot
+ * tuple. (The number of columns stored should not vary, since suffix
+ * truncation of key columns is unsafe within any !heapkeyspace index.)
+ *
+ * The 12 least significant bits from t_tid's offset number are used to
+ * represent the number of key columns within a pivot tuple. This leaves 4
+ * status bits (BT_STATUS_OFFSET_MASK bits), which are shared by all tuples
+ * that have the INDEX_ALT_TID_MASK bit set (set in t_info) to store basic
+ * tuple metadata. BTreeTupleIsPivot() and BTreeTupleIsPosting() use the
+ * BT_STATUS_OFFSET_MASK bits.
+ *
+ * Sometimes non-pivot tuples also use a representation that repurposes
+ * t_tid to store metadata rather than a TID. PostgreSQL v13 introduced a
+ * new non-pivot tuple format to support deduplication: posting list
+ * tuples. Deduplication merges together multiple equal non-pivot tuples
+ * into a logically equivalent, space efficient representation. A posting
+ * list is an array of ItemPointerData elements. Non-pivot tuples are
+ * merged together to form posting list tuples lazily, at the point where
+ * we'd otherwise have to split a leaf page.
+ *
+ * Posting tuple format (alternative non-pivot tuple representation):
+ *
+ * t_tid | t_info | key values | posting list (TID array)
+ *
+ * Posting list tuples are recognized as such by having the
+ * INDEX_ALT_TID_MASK status bit set in t_info and the BT_IS_POSTING status
+ * bit set in t_tid's offset number. These flags redefine the content of
+ * the posting tuple's t_tid to store the location of the posting list
+ * (instead of a block number), as well as the total number of heap TIDs
+ * present in the tuple (instead of a real offset number).
+ *
+ * The 12 least significant bits from t_tid's offset number are used to
+ * represent the number of heap TIDs present in the tuple, leaving 4 status
+ * bits (the BT_STATUS_OFFSET_MASK bits). Like any non-pivot tuple, the
+ * number of columns stored is always implicitly the total number in the
+ * index (in practice there can never be non-key columns stored, since
+ * deduplication is not supported with INCLUDE indexes).
+ */
+#define INDEX_ALT_TID_MASK INDEX_AM_RESERVED_BIT
+
+/* Item pointer offset bit masks */
+#define BT_OFFSET_MASK 0x0FFF
+#define BT_STATUS_OFFSET_MASK 0xF000
+/* BT_STATUS_OFFSET_MASK status bits */
+#define BT_PIVOT_HEAP_TID_ATTR 0x1000
+#define BT_IS_POSTING 0x2000
+
+/*
+ * Note: BTreeTupleIsPivot() can have false negatives (but not false
+ * positives) when used with !heapkeyspace indexes
+ */
+static inline bool
+BTreeTupleIsPivot(IndexTuple itup)
+{
+ if ((itup->t_info & INDEX_ALT_TID_MASK) == 0)
+ return false;
+ /* absence of BT_IS_POSTING in offset number indicates pivot tuple */
+ if ((ItemPointerGetOffsetNumberNoCheck(&itup->t_tid) & BT_IS_POSTING) != 0)
+ return false;
+
+ return true;
+}
+
+static inline bool
+BTreeTupleIsPosting(IndexTuple itup)
+{
+ if ((itup->t_info & INDEX_ALT_TID_MASK) == 0)
+ return false;
+ /* presence of BT_IS_POSTING in offset number indicates posting tuple */
+ if ((ItemPointerGetOffsetNumberNoCheck(&itup->t_tid) & BT_IS_POSTING) == 0)
+ return false;
+
+ return true;
+}
+
+static inline void
+BTreeTupleSetPosting(IndexTuple itup, uint16 nhtids, int postingoffset)
+{
+ Assert(nhtids > 1);
+ Assert((nhtids & BT_STATUS_OFFSET_MASK) == 0);
+ Assert((size_t) postingoffset == MAXALIGN(postingoffset));
+ Assert(postingoffset < INDEX_SIZE_MASK);
+ Assert(!BTreeTupleIsPivot(itup));
+
+ itup->t_info |= INDEX_ALT_TID_MASK;
+ ItemPointerSetOffsetNumber(&itup->t_tid, (nhtids | BT_IS_POSTING));
+ ItemPointerSetBlockNumber(&itup->t_tid, postingoffset);
+}
+
+static inline uint16
+BTreeTupleGetNPosting(IndexTuple posting)
+{
+ OffsetNumber existing;
+
+ Assert(BTreeTupleIsPosting(posting));
+
+ existing = ItemPointerGetOffsetNumberNoCheck(&posting->t_tid);
+ return (existing & BT_OFFSET_MASK);
+}
+
+static inline uint32
+BTreeTupleGetPostingOffset(IndexTuple posting)
+{
+ Assert(BTreeTupleIsPosting(posting));
+
+ return ItemPointerGetBlockNumberNoCheck(&posting->t_tid);
+}
+
+static inline ItemPointer
+BTreeTupleGetPosting(IndexTuple posting)
+{
+ return (ItemPointer) ((char *) posting +
+ BTreeTupleGetPostingOffset(posting));
+}
+
+static inline ItemPointer
+BTreeTupleGetPostingN(IndexTuple posting, int n)
+{
+ return BTreeTupleGetPosting(posting) + n;
+}
+
+/*
+ * Get/set downlink block number in pivot tuple.
+ *
+ * Note: Cannot assert that tuple is a pivot tuple. If we did so then
+ * !heapkeyspace indexes would exhibit false positive assertion failures.
+ */
+static inline BlockNumber
+BTreeTupleGetDownLink(IndexTuple pivot)
+{
+ return ItemPointerGetBlockNumberNoCheck(&pivot->t_tid);
+}
+
+static inline void
+BTreeTupleSetDownLink(IndexTuple pivot, BlockNumber blkno)
+{
+ ItemPointerSetBlockNumber(&pivot->t_tid, blkno);
+}
+
+/*
+ * Get number of attributes within tuple.
+ *
+ * Note that this does not include an implicit tiebreaker heap TID
+ * attribute, if any. Note also that the number of key attributes must be
+ * explicitly represented in all heapkeyspace pivot tuples.
+ *
+ * Note: This is defined as a macro rather than an inline function to
+ * avoid including rel.h.
+ */
+#define BTreeTupleGetNAtts(itup, rel) \
+ ( \
+ (BTreeTupleIsPivot(itup)) ? \
+ ( \
+ ItemPointerGetOffsetNumberNoCheck(&(itup)->t_tid) & BT_OFFSET_MASK \
+ ) \
+ : \
+ IndexRelationGetNumberOfAttributes(rel) \
+ )
+
+/*
+ * Set number of key attributes in tuple.
+ *
+ * The heap TID tiebreaker attribute bit may also be set here, indicating that
+ * a heap TID value will be stored at the end of the tuple (i.e. using the
+ * special pivot tuple representation).
+ */
+static inline void
+BTreeTupleSetNAtts(IndexTuple itup, uint16 nkeyatts, bool heaptid)
+{
+ Assert(nkeyatts <= INDEX_MAX_KEYS);
+ Assert((nkeyatts & BT_STATUS_OFFSET_MASK) == 0);
+ Assert(!heaptid || nkeyatts > 0);
+ Assert(!BTreeTupleIsPivot(itup) || nkeyatts == 0);
+
+ itup->t_info |= INDEX_ALT_TID_MASK;
+
+ if (heaptid)
+ nkeyatts |= BT_PIVOT_HEAP_TID_ATTR;
+
+ /* BT_IS_POSTING bit is deliberately unset here */
+ ItemPointerSetOffsetNumber(&itup->t_tid, nkeyatts);
+ Assert(BTreeTupleIsPivot(itup));
+}
+
+/*
+ * Get/set leaf page's "top parent" link from its high key. Used during page
+ * deletion.
+ *
+ * Note: Cannot assert that tuple is a pivot tuple. If we did so then
+ * !heapkeyspace indexes would exhibit false positive assertion failures.
+ */
+static inline BlockNumber
+BTreeTupleGetTopParent(IndexTuple leafhikey)
+{
+ return ItemPointerGetBlockNumberNoCheck(&leafhikey->t_tid);
+}
+
+static inline void
+BTreeTupleSetTopParent(IndexTuple leafhikey, BlockNumber blkno)
+{
+ ItemPointerSetBlockNumber(&leafhikey->t_tid, blkno);
+ BTreeTupleSetNAtts(leafhikey, 0, false);
+}
+
+/*
+ * Get tiebreaker heap TID attribute, if any.
+ *
+ * This returns the first/lowest heap TID in the case of a posting list tuple.
+ */
+static inline ItemPointer
+BTreeTupleGetHeapTID(IndexTuple itup)
+{
+ if (BTreeTupleIsPivot(itup))
+ {
+ /* Pivot tuple heap TID representation? */
+ if ((ItemPointerGetOffsetNumberNoCheck(&itup->t_tid) &
+ BT_PIVOT_HEAP_TID_ATTR) != 0)
+ return (ItemPointer) ((char *) itup + IndexTupleSize(itup) -
+ sizeof(ItemPointerData));
+
+ /* Heap TID attribute was truncated */
+ return NULL;
+ }
+ else if (BTreeTupleIsPosting(itup))
+ return BTreeTupleGetPosting(itup);
+
+ return &itup->t_tid;
+}
+
+/*
+ * Get maximum heap TID attribute, which could be the only TID in the case of
+ * a non-pivot tuple that does not have a posting list tuple.
+ *
+ * Works with non-pivot tuples only.
+ */
+static inline ItemPointer
+BTreeTupleGetMaxHeapTID(IndexTuple itup)
+{
+ Assert(!BTreeTupleIsPivot(itup));
+
+ if (BTreeTupleIsPosting(itup))
+ {
+ uint16 nposting = BTreeTupleGetNPosting(itup);
+
+ return BTreeTupleGetPostingN(itup, nposting - 1);
+ }
+
+ return &itup->t_tid;
+}
+
+/*
+ * Operator strategy numbers for B-tree have been moved to access/stratnum.h,
+ * because many places need to use them in ScanKeyInit() calls.
+ *
+ * The strategy numbers are chosen so that we can commute them by
+ * subtraction, thus:
+ */
+#define BTCommuteStrategyNumber(strat) (BTMaxStrategyNumber + 1 - (strat))
+
+/*
+ * When a new operator class is declared, we require that the user
+ * supply us with an amproc procedure (BTORDER_PROC) for determining
+ * whether, for two keys a and b, a < b, a = b, or a > b. This routine
+ * must return < 0, 0, > 0, respectively, in these three cases.
+ *
+ * To facilitate accelerated sorting, an operator class may choose to
+ * offer a second procedure (BTSORTSUPPORT_PROC). For full details, see
+ * src/include/utils/sortsupport.h.
+ *
+ * To support window frames defined by "RANGE offset PRECEDING/FOLLOWING",
+ * an operator class may choose to offer a third amproc procedure
+ * (BTINRANGE_PROC), independently of whether it offers sortsupport.
+ * For full details, see doc/src/sgml/btree.sgml.
+ *
+ * To facilitate B-Tree deduplication, an operator class may choose to
+ * offer a forth amproc procedure (BTEQUALIMAGE_PROC). For full details,
+ * see doc/src/sgml/btree.sgml.
+ */
+
+#define BTORDER_PROC 1
+#define BTSORTSUPPORT_PROC 2
+#define BTINRANGE_PROC 3
+#define BTEQUALIMAGE_PROC 4
+#define BTOPTIONS_PROC 5
+#define BTNProcs 5
+
+/*
+ * We need to be able to tell the difference between read and write
+ * requests for pages, in order to do locking correctly.
+ */
+
+#define BT_READ BUFFER_LOCK_SHARE
+#define BT_WRITE BUFFER_LOCK_EXCLUSIVE
+
+/*
+ * BTStackData -- As we descend a tree, we push the location of pivot
+ * tuples whose downlink we are about to follow onto a private stack. If
+ * we split a leaf, we use this stack to walk back up the tree and insert
+ * data into its parent page at the correct location. We also have to
+ * recursively insert into the grandparent page if and when the parent page
+ * splits. Our private stack can become stale due to concurrent page
+ * splits and page deletions, but it should never give us an irredeemably
+ * bad picture.
+ */
+typedef struct BTStackData
+{
+ BlockNumber bts_blkno;
+ OffsetNumber bts_offset;
+ struct BTStackData *bts_parent;
+} BTStackData;
+
+typedef BTStackData *BTStack;
+
+/*
+ * BTScanInsertData is the btree-private state needed to find an initial
+ * position for an indexscan, or to insert new tuples -- an "insertion
+ * scankey" (not to be confused with a search scankey). It's used to descend
+ * a B-Tree using _bt_search.
+ *
+ * heapkeyspace indicates if we expect all keys in the index to be physically
+ * unique because heap TID is used as a tiebreaker attribute, and if index may
+ * have truncated key attributes in pivot tuples. This is actually a property
+ * of the index relation itself (not an indexscan). heapkeyspace indexes are
+ * indexes whose version is >= version 4. It's convenient to keep this close
+ * by, rather than accessing the metapage repeatedly.
+ *
+ * allequalimage is set to indicate that deduplication is safe for the index.
+ * This is also a property of the index relation rather than an indexscan.
+ *
+ * anynullkeys indicates if any of the keys had NULL value when scankey was
+ * built from index tuple (note that already-truncated tuple key attributes
+ * set NULL as a placeholder key value, which also affects value of
+ * anynullkeys). This is a convenience for unique index non-pivot tuple
+ * insertion, which usually temporarily unsets scantid, but shouldn't iff
+ * anynullkeys is true. Value generally matches non-pivot tuple's HasNulls
+ * bit, but may not when inserting into an INCLUDE index (tuple header value
+ * is affected by the NULL-ness of both key and non-key attributes).
+ *
+ * When nextkey is false (the usual case), _bt_search and _bt_binsrch will
+ * locate the first item >= scankey. When nextkey is true, they will locate
+ * the first item > scan key.
+ *
+ * pivotsearch is set to true by callers that want to re-find a leaf page
+ * using a scankey built from a leaf page's high key. Most callers set this
+ * to false.
+ *
+ * scantid is the heap TID that is used as a final tiebreaker attribute. It
+ * is set to NULL when index scan doesn't need to find a position for a
+ * specific physical tuple. Must be set when inserting new tuples into
+ * heapkeyspace indexes, since every tuple in the tree unambiguously belongs
+ * in one exact position (it's never set with !heapkeyspace indexes, though).
+ * Despite the representational difference, nbtree search code considers
+ * scantid to be just another insertion scankey attribute.
+ *
+ * scankeys is an array of scan key entries for attributes that are compared
+ * before scantid (user-visible attributes). keysz is the size of the array.
+ * During insertion, there must be a scan key for every attribute, but when
+ * starting a regular index scan some can be omitted. The array is used as a
+ * flexible array member, though it's sized in a way that makes it possible to
+ * use stack allocations. See nbtree/README for full details.
+ */
+typedef struct BTScanInsertData
+{
+ bool heapkeyspace;
+ bool allequalimage;
+ bool anynullkeys;
+ bool nextkey;
+ bool pivotsearch;
+ ItemPointer scantid; /* tiebreaker for scankeys */
+ int keysz; /* Size of scankeys array */
+ ScanKeyData scankeys[INDEX_MAX_KEYS]; /* Must appear last */
+} BTScanInsertData;
+
+typedef BTScanInsertData *BTScanInsert;
+
+/*
+ * BTInsertStateData is a working area used during insertion.
+ *
+ * This is filled in after descending the tree to the first leaf page the new
+ * tuple might belong on. Tracks the current position while performing
+ * uniqueness check, before we have determined which exact page to insert
+ * to.
+ *
+ * (This should be private to nbtinsert.c, but it's also used by
+ * _bt_binsrch_insert)
+ */
+typedef struct BTInsertStateData
+{
+ IndexTuple itup; /* Item we're inserting */
+ Size itemsz; /* Size of itup -- should be MAXALIGN()'d */
+ BTScanInsert itup_key; /* Insertion scankey */
+
+ /* Buffer containing leaf page we're likely to insert itup on */
+ Buffer buf;
+
+ /*
+ * Cache of bounds within the current buffer. Only used for insertions
+ * where _bt_check_unique is called. See _bt_binsrch_insert and
+ * _bt_findinsertloc for details.
+ */
+ bool bounds_valid;
+ OffsetNumber low;
+ OffsetNumber stricthigh;
+
+ /*
+ * if _bt_binsrch_insert found the location inside existing posting list,
+ * save the position inside the list. -1 sentinel value indicates overlap
+ * with an existing posting list tuple that has its LP_DEAD bit set.
+ */
+ int postingoff;
+} BTInsertStateData;
+
+typedef BTInsertStateData *BTInsertState;
+
+/*
+ * State used to representing an individual pending tuple during
+ * deduplication.
+ */
+typedef struct BTDedupInterval
+{
+ OffsetNumber baseoff;
+ uint16 nitems;
+} BTDedupInterval;
+
+/*
+ * BTDedupStateData is a working area used during deduplication.
+ *
+ * The status info fields track the state of a whole-page deduplication pass.
+ * State about the current pending posting list is also tracked.
+ *
+ * A pending posting list is comprised of a contiguous group of equal items
+ * from the page, starting from page offset number 'baseoff'. This is the
+ * offset number of the "base" tuple for new posting list. 'nitems' is the
+ * current total number of existing items from the page that will be merged to
+ * make a new posting list tuple, including the base tuple item. (Existing
+ * items may themselves be posting list tuples, or regular non-pivot tuples.)
+ *
+ * The total size of the existing tuples to be freed when pending posting list
+ * is processed gets tracked by 'phystupsize'. This information allows
+ * deduplication to calculate the space saving for each new posting list
+ * tuple, and for the entire pass over the page as a whole.
+ */
+typedef struct BTDedupStateData
+{
+ /* Deduplication status info for entire pass over page */
+ bool deduplicate; /* Still deduplicating page? */
+ int nmaxitems; /* Number of max-sized tuples so far */
+ Size maxpostingsize; /* Limit on size of final tuple */
+
+ /* Metadata about base tuple of current pending posting list */
+ IndexTuple base; /* Use to form new posting list */
+ OffsetNumber baseoff; /* page offset of base */
+ Size basetupsize; /* base size without original posting list */
+
+ /* Other metadata about pending posting list */
+ ItemPointer htids; /* Heap TIDs in pending posting list */
+ int nhtids; /* Number of heap TIDs in htids array */
+ int nitems; /* Number of existing tuples/line pointers */
+ Size phystupsize; /* Includes line pointer overhead */
+
+ /*
+ * Array of tuples to go on new version of the page. Contains one entry
+ * for each group of consecutive items. Note that existing tuples that
+ * will not become posting list tuples do not appear in the array (they
+ * are implicitly unchanged by deduplication pass).
+ */
+ int nintervals; /* current number of intervals in array */
+ BTDedupInterval intervals[MaxIndexTuplesPerPage];
+} BTDedupStateData;
+
+typedef BTDedupStateData *BTDedupState;
+
+/*
+ * BTVacuumPostingData is state that represents how to VACUUM a posting list
+ * tuple when some (though not all) of its TIDs are to be deleted.
+ *
+ * Convention is that itup field is the original posting list tuple on input,
+ * and palloc()'d final tuple used to overwrite existing tuple on output.
+ */
+typedef struct BTVacuumPostingData
+{
+ /* Tuple that will be/was updated */
+ IndexTuple itup;
+ OffsetNumber updatedoffset;
+
+ /* State needed to describe final itup in WAL */
+ uint16 ndeletedtids;
+ uint16 deletetids[FLEXIBLE_ARRAY_MEMBER];
+} BTVacuumPostingData;
+
+typedef BTVacuumPostingData *BTVacuumPosting;
+
+/*
+ * BTScanOpaqueData is the btree-private state needed for an indexscan.
+ * This consists of preprocessed scan keys (see _bt_preprocess_keys() for
+ * details of the preprocessing), information about the current location
+ * of the scan, and information about the marked location, if any. (We use
+ * BTScanPosData to represent the data needed for each of current and marked
+ * locations.) In addition we can remember some known-killed index entries
+ * that must be marked before we can move off the current page.
+ *
+ * Index scans work a page at a time: we pin and read-lock the page, identify
+ * all the matching items on the page and save them in BTScanPosData, then
+ * release the read-lock while returning the items to the caller for
+ * processing. This approach minimizes lock/unlock traffic. Note that we
+ * keep the pin on the index page until the caller is done with all the items
+ * (this is needed for VACUUM synchronization, see nbtree/README). When we
+ * are ready to step to the next page, if the caller has told us any of the
+ * items were killed, we re-lock the page to mark them killed, then unlock.
+ * Finally we drop the pin and step to the next page in the appropriate
+ * direction.
+ *
+ * If we are doing an index-only scan, we save the entire IndexTuple for each
+ * matched item, otherwise only its heap TID and offset. The IndexTuples go
+ * into a separate workspace array; each BTScanPosItem stores its tuple's
+ * offset within that array. Posting list tuples store a "base" tuple once,
+ * allowing the same key to be returned for each TID in the posting list
+ * tuple.
+ */
+
+typedef struct BTScanPosItem /* what we remember about each match */
+{
+ ItemPointerData heapTid; /* TID of referenced heap item */
+ OffsetNumber indexOffset; /* index item's location within page */
+ LocationIndex tupleOffset; /* IndexTuple's offset in workspace, if any */
+} BTScanPosItem;
+
+typedef struct BTScanPosData
+{
+ Buffer buf; /* if valid, the buffer is pinned */
+
+ XLogRecPtr lsn; /* pos in the WAL stream when page was read */
+ BlockNumber currPage; /* page referenced by items array */
+ BlockNumber nextPage; /* page's right link when we scanned it */
+
+ /*
+ * moreLeft and moreRight track whether we think there may be matching
+ * index entries to the left and right of the current page, respectively.
+ * We can clear the appropriate one of these flags when _bt_checkkeys()
+ * returns continuescan = false.
+ */
+ bool moreLeft;
+ bool moreRight;
+
+ /*
+ * If we are doing an index-only scan, nextTupleOffset is the first free
+ * location in the associated tuple storage workspace.
+ */
+ int nextTupleOffset;
+
+ /*
+ * The items array is always ordered in index order (ie, increasing
+ * indexoffset). When scanning backwards it is convenient to fill the
+ * array back-to-front, so we start at the last slot and fill downwards.
+ * Hence we need both a first-valid-entry and a last-valid-entry counter.
+ * itemIndex is a cursor showing which entry was last returned to caller.
+ */
+ int firstItem; /* first valid index in items[] */
+ int lastItem; /* last valid index in items[] */
+ int itemIndex; /* current index in items[] */
+
+ BTScanPosItem items[MaxTIDsPerBTreePage]; /* MUST BE LAST */
+} BTScanPosData;
+
+typedef BTScanPosData *BTScanPos;
+
+#define BTScanPosIsPinned(scanpos) \
+( \
+ AssertMacro(BlockNumberIsValid((scanpos).currPage) || \
+ !BufferIsValid((scanpos).buf)), \
+ BufferIsValid((scanpos).buf) \
+)
+#define BTScanPosUnpin(scanpos) \
+ do { \
+ ReleaseBuffer((scanpos).buf); \
+ (scanpos).buf = InvalidBuffer; \
+ } while (0)
+#define BTScanPosUnpinIfPinned(scanpos) \
+ do { \
+ if (BTScanPosIsPinned(scanpos)) \
+ BTScanPosUnpin(scanpos); \
+ } while (0)
+
+#define BTScanPosIsValid(scanpos) \
+( \
+ AssertMacro(BlockNumberIsValid((scanpos).currPage) || \
+ !BufferIsValid((scanpos).buf)), \
+ BlockNumberIsValid((scanpos).currPage) \
+)
+#define BTScanPosInvalidate(scanpos) \
+ do { \
+ (scanpos).currPage = InvalidBlockNumber; \
+ (scanpos).nextPage = InvalidBlockNumber; \
+ (scanpos).buf = InvalidBuffer; \
+ (scanpos).lsn = InvalidXLogRecPtr; \
+ (scanpos).nextTupleOffset = 0; \
+ } while (0)
+
+/* We need one of these for each equality-type SK_SEARCHARRAY scan key */
+typedef struct BTArrayKeyInfo
+{
+ int scan_key; /* index of associated key in arrayKeyData */
+ int cur_elem; /* index of current element in elem_values */
+ int mark_elem; /* index of marked element in elem_values */
+ int num_elems; /* number of elems in current array value */
+ Datum *elem_values; /* array of num_elems Datums */
+} BTArrayKeyInfo;
+
+typedef struct BTScanOpaqueData
+{
+ /* these fields are set by _bt_preprocess_keys(): */
+ bool qual_ok; /* false if qual can never be satisfied */
+ int numberOfKeys; /* number of preprocessed scan keys */
+ ScanKey keyData; /* array of preprocessed scan keys */
+
+ /* workspace for SK_SEARCHARRAY support */
+ ScanKey arrayKeyData; /* modified copy of scan->keyData */
+ int numArrayKeys; /* number of equality-type array keys (-1 if
+ * there are any unsatisfiable array keys) */
+ int arrayKeyCount; /* count indicating number of array scan keys
+ * processed */
+ BTArrayKeyInfo *arrayKeys; /* info about each equality-type array key */
+ MemoryContext arrayContext; /* scan-lifespan context for array data */
+
+ /* info about killed items if any (killedItems is NULL if never used) */
+ int *killedItems; /* currPos.items indexes of killed items */
+ int numKilled; /* number of currently stored items */
+
+ /*
+ * If we are doing an index-only scan, these are the tuple storage
+ * workspaces for the currPos and markPos respectively. Each is of size
+ * BLCKSZ, so it can hold as much as a full page's worth of tuples.
+ */
+ char *currTuples; /* tuple storage for currPos */
+ char *markTuples; /* tuple storage for markPos */
+
+ /*
+ * If the marked position is on the same page as current position, we
+ * don't use markPos, but just keep the marked itemIndex in markItemIndex
+ * (all the rest of currPos is valid for the mark position). Hence, to
+ * determine if there is a mark, first look at markItemIndex, then at
+ * markPos.
+ */
+ int markItemIndex; /* itemIndex, or -1 if not valid */
+
+ /* keep these last in struct for efficiency */
+ BTScanPosData currPos; /* current position data */
+ BTScanPosData markPos; /* marked position, if any */
+} BTScanOpaqueData;
+
+typedef BTScanOpaqueData *BTScanOpaque;
+
+/*
+ * We use some private sk_flags bits in preprocessed scan keys. We're allowed
+ * to use bits 16-31 (see skey.h). The uppermost bits are copied from the
+ * index's indoption[] array entry for the index attribute.
+ */
+#define SK_BT_REQFWD 0x00010000 /* required to continue forward scan */
+#define SK_BT_REQBKWD 0x00020000 /* required to continue backward scan */
+#define SK_BT_INDOPTION_SHIFT 24 /* must clear the above bits */
+#define SK_BT_DESC (INDOPTION_DESC << SK_BT_INDOPTION_SHIFT)
+#define SK_BT_NULLS_FIRST (INDOPTION_NULLS_FIRST << SK_BT_INDOPTION_SHIFT)
+
+typedef struct BTOptions
+{
+ int32 varlena_header_; /* 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 */
+ float8 vacuum_cleanup_index_scale_factor;
+ bool deduplicate_items; /* Try to deduplicate items? */
+} BTOptions;
+
+#define BTGetFillFactor(relation) \
+ (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \
+ relation->rd_rel->relam == BTREE_AM_OID), \
+ (relation)->rd_options ? \
+ ((BTOptions *) (relation)->rd_options)->fillfactor : \
+ BTREE_DEFAULT_FILLFACTOR)
+#define BTGetTargetPageFreeSpace(relation) \
+ (BLCKSZ * (100 - BTGetFillFactor(relation)) / 100)
+#define BTGetDeduplicateItems(relation) \
+ (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \
+ relation->rd_rel->relam == BTREE_AM_OID), \
+ ((relation)->rd_options ? \
+ ((BTOptions *) (relation)->rd_options)->deduplicate_items : true))
+
+/*
+ * Constant definition for progress reporting. Phase numbers must match
+ * btbuildphasename.
+ */
+/* PROGRESS_CREATEIDX_SUBPHASE_INITIALIZE is 1 (see progress.h) */
+#define PROGRESS_BTREE_PHASE_INDEXBUILD_TABLESCAN 2
+#define PROGRESS_BTREE_PHASE_PERFORMSORT_1 3
+#define PROGRESS_BTREE_PHASE_PERFORMSORT_2 4
+#define PROGRESS_BTREE_PHASE_LEAF_LOAD 5
+
+/*
+ * external entry points for btree, in nbtree.c
+ */
+extern void btbuildempty(Relation index);
+extern bool btinsert(Relation rel, Datum *values, bool *isnull,
+ ItemPointer ht_ctid, Relation heapRel,
+ IndexUniqueCheck checkUnique,
+ struct IndexInfo *indexInfo);
+extern IndexScanDesc btbeginscan(Relation rel, int nkeys, int norderbys);
+extern Size btestimateparallelscan(void);
+extern void btinitparallelscan(void *target);
+extern bool btgettuple(IndexScanDesc scan, ScanDirection dir);
+extern int64 btgetbitmap(IndexScanDesc scan, TIDBitmap *tbm);
+extern void btrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
+ ScanKey orderbys, int norderbys);
+extern void btparallelrescan(IndexScanDesc scan);
+extern void btendscan(IndexScanDesc scan);
+extern void btmarkpos(IndexScanDesc scan);
+extern void btrestrpos(IndexScanDesc scan);
+extern IndexBulkDeleteResult *btbulkdelete(IndexVacuumInfo *info,
+ IndexBulkDeleteResult *stats,
+ IndexBulkDeleteCallback callback,
+ void *callback_state);
+extern IndexBulkDeleteResult *btvacuumcleanup(IndexVacuumInfo *info,
+ IndexBulkDeleteResult *stats);
+extern bool btcanreturn(Relation index, int attno);
+
+/*
+ * prototypes for internal functions in nbtree.c
+ */
+extern bool _bt_parallel_seize(IndexScanDesc scan, BlockNumber *pageno);
+extern void _bt_parallel_release(IndexScanDesc scan, BlockNumber scan_page);
+extern void _bt_parallel_done(IndexScanDesc scan);
+extern void _bt_parallel_advance_array_keys(IndexScanDesc scan);
+
+/*
+ * prototypes for functions in nbtdedup.c
+ */
+extern void _bt_dedup_one_page(Relation rel, Buffer buf, Relation heapRel,
+ IndexTuple newitem, Size newitemsz,
+ bool checkingunique);
+extern void _bt_dedup_start_pending(BTDedupState state, IndexTuple base,
+ OffsetNumber baseoff);
+extern bool _bt_dedup_save_htid(BTDedupState state, IndexTuple itup);
+extern Size _bt_dedup_finish_pending(Page newpage, BTDedupState state);
+extern IndexTuple _bt_form_posting(IndexTuple base, ItemPointer htids,
+ int nhtids);
+extern void _bt_update_posting(BTVacuumPosting vacposting);
+extern IndexTuple _bt_swap_posting(IndexTuple newitem, IndexTuple oposting,
+ int postingoff);
+
+/*
+ * prototypes for functions in nbtinsert.c
+ */
+extern bool _bt_doinsert(Relation rel, IndexTuple itup,
+ IndexUniqueCheck checkUnique, Relation heapRel);
+extern void _bt_finish_split(Relation rel, Buffer lbuf, BTStack stack);
+extern Buffer _bt_getstackbuf(Relation rel, BTStack stack, BlockNumber child);
+
+/*
+ * prototypes for functions in nbtsplitloc.c
+ */
+extern OffsetNumber _bt_findsplitloc(Relation rel, Page origpage,
+ OffsetNumber newitemoff, Size newitemsz, IndexTuple newitem,
+ bool *newitemonleft);
+
+/*
+ * prototypes for functions in nbtpage.c
+ */
+extern void _bt_initmetapage(Page page, BlockNumber rootbknum, uint32 level,
+ bool allequalimage);
+extern void _bt_update_meta_cleanup_info(Relation rel,
+ TransactionId oldestBtpoXact, float8 numHeapTuples);
+extern void _bt_upgrademetapage(Page page);
+extern Buffer _bt_getroot(Relation rel, int access);
+extern Buffer _bt_gettrueroot(Relation rel);
+extern int _bt_getrootheight(Relation rel);
+extern void _bt_metaversion(Relation rel, bool *heapkeyspace,
+ bool *allequalimage);
+extern void _bt_checkpage(Relation rel, Buffer buf);
+extern Buffer _bt_getbuf(Relation rel, BlockNumber blkno, int access);
+extern Buffer _bt_relandgetbuf(Relation rel, Buffer obuf,
+ BlockNumber blkno, int access);
+extern void _bt_relbuf(Relation rel, Buffer buf);
+extern void _bt_pageinit(Page page, Size size);
+extern bool _bt_page_recyclable(Page page);
+extern void _bt_delitems_vacuum(Relation rel, Buffer buf,
+ OffsetNumber *deletable, int ndeletable,
+ BTVacuumPosting *updatable, int nupdatable);
+extern void _bt_delitems_delete(Relation rel, Buffer buf,
+ OffsetNumber *deletable, int ndeletable,
+ Relation heapRel);
+extern uint32 _bt_pagedel(Relation rel, Buffer leafbuf,
+ TransactionId *oldestBtpoXact);
+
+/*
+ * prototypes for functions in nbtsearch.c
+ */
+extern BTStack _bt_search(Relation rel, BTScanInsert key, Buffer *bufP,
+ int access, Snapshot snapshot);
+extern Buffer _bt_moveright(Relation rel, BTScanInsert key, Buffer buf,
+ bool forupdate, BTStack stack, int access, Snapshot snapshot);
+extern OffsetNumber _bt_binsrch_insert(Relation rel, BTInsertState insertstate);
+extern int32 _bt_compare(Relation rel, BTScanInsert key, Page page, OffsetNumber offnum);
+extern bool _bt_first(IndexScanDesc scan, ScanDirection dir);
+extern bool _bt_next(IndexScanDesc scan, ScanDirection dir);
+extern Buffer _bt_get_endpoint(Relation rel, uint32 level, bool rightmost,
+ Snapshot snapshot);
+
+/*
+ * prototypes for functions in nbtutils.c
+ */
+extern BTScanInsert _bt_mkscankey(Relation rel, IndexTuple itup);
+extern void _bt_freestack(BTStack stack);
+extern void _bt_preprocess_array_keys(IndexScanDesc scan);
+extern void _bt_start_array_keys(IndexScanDesc scan, ScanDirection dir);
+extern bool _bt_advance_array_keys(IndexScanDesc scan, ScanDirection dir);
+extern void _bt_mark_array_keys(IndexScanDesc scan);
+extern void _bt_restore_array_keys(IndexScanDesc scan);
+extern void _bt_preprocess_keys(IndexScanDesc scan);
+extern bool _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
+ int tupnatts, ScanDirection dir, bool *continuescan);
+extern void _bt_killitems(IndexScanDesc scan);
+extern BTCycleId _bt_vacuum_cycleid(Relation rel);
+extern BTCycleId _bt_start_vacuum(Relation rel);
+extern void _bt_end_vacuum(Relation rel);
+extern void _bt_end_vacuum_callback(int code, Datum arg);
+extern Size BTreeShmemSize(void);
+extern void BTreeShmemInit(void);
+extern bytea *btoptions(Datum reloptions, bool validate);
+extern bool btproperty(Oid index_oid, int attno,
+ IndexAMProperty prop, const char *propname,
+ bool *res, bool *isnull);
+extern char *btbuildphasename(int64 phasenum);
+extern IndexTuple _bt_truncate(Relation rel, IndexTuple lastleft,
+ IndexTuple firstright, BTScanInsert itup_key);
+extern int _bt_keep_natts_fast(Relation rel, IndexTuple lastleft,
+ IndexTuple firstright);
+extern bool _bt_check_natts(Relation rel, bool heapkeyspace, Page page,
+ OffsetNumber offnum);
+extern void _bt_check_third_page(Relation rel, Relation heap,
+ bool needheaptidspace, Page page, IndexTuple newtup);
+extern bool _bt_allequalimage(Relation rel, bool debugmessage);
+
+/*
+ * prototypes for functions in nbtvalidate.c
+ */
+extern bool btvalidate(Oid opclassoid);
+
+/*
+ * prototypes for functions in nbtsort.c
+ */
+extern IndexBuildResult *btbuild(Relation heap, Relation index,
+ struct IndexInfo *indexInfo);
+extern void _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc);
+
+#endif /* NBTREE_H */
diff --git a/src/include/access/nbtxlog.h b/src/include/access/nbtxlog.h
new file mode 100644
index 0000000..5c014bd
--- /dev/null
+++ b/src/include/access/nbtxlog.h
@@ -0,0 +1,335 @@
+/*-------------------------------------------------------------------------
+ *
+ * nbtxlog.h
+ * header file for postgres btree xlog routines
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/nbtxlog.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NBTXLOG_H
+#define NBTXLOG_H
+
+#include "access/xlogreader.h"
+#include "lib/stringinfo.h"
+#include "storage/off.h"
+
+/*
+ * XLOG records for btree operations
+ *
+ * XLOG allows to store some information in high 4 bits of log
+ * record xl_info field
+ */
+#define XLOG_BTREE_INSERT_LEAF 0x00 /* add index tuple without split */
+#define XLOG_BTREE_INSERT_UPPER 0x10 /* same, on a non-leaf page */
+#define XLOG_BTREE_INSERT_META 0x20 /* same, plus update metapage */
+#define XLOG_BTREE_SPLIT_L 0x30 /* add index tuple with split */
+#define XLOG_BTREE_SPLIT_R 0x40 /* as above, new item on right */
+#define XLOG_BTREE_INSERT_POST 0x50 /* add index tuple with posting split */
+#define XLOG_BTREE_DEDUP 0x60 /* deduplicate tuples for a page */
+#define XLOG_BTREE_DELETE 0x70 /* delete leaf index tuples for a page */
+#define XLOG_BTREE_UNLINK_PAGE 0x80 /* delete a half-dead page */
+#define XLOG_BTREE_UNLINK_PAGE_META 0x90 /* same, and update metapage */
+#define XLOG_BTREE_NEWROOT 0xA0 /* new root page */
+#define XLOG_BTREE_MARK_PAGE_HALFDEAD 0xB0 /* mark a leaf as half-dead */
+#define XLOG_BTREE_VACUUM 0xC0 /* delete entries on a page during
+ * vacuum */
+#define XLOG_BTREE_REUSE_PAGE 0xD0 /* old page is about to be reused from
+ * FSM */
+#define XLOG_BTREE_META_CLEANUP 0xE0 /* update cleanup-related data in the
+ * metapage */
+
+/*
+ * All that we need to regenerate the meta-data page
+ */
+typedef struct xl_btree_metadata
+{
+ uint32 version;
+ BlockNumber root;
+ uint32 level;
+ BlockNumber fastroot;
+ uint32 fastlevel;
+ TransactionId oldest_btpo_xact;
+ float8 last_cleanup_num_heap_tuples;
+ bool allequalimage;
+} xl_btree_metadata;
+
+/*
+ * This is what we need to know about simple (without split) insert.
+ *
+ * This data record is used for INSERT_LEAF, INSERT_UPPER, INSERT_META, and
+ * INSERT_POST. Note that INSERT_META and INSERT_UPPER implies it's not a
+ * leaf page, while INSERT_POST and INSERT_LEAF imply that it must be a leaf
+ * page.
+ *
+ * Backup Blk 0: original page
+ * Backup Blk 1: child's left sibling, if INSERT_UPPER or INSERT_META
+ * Backup Blk 2: xl_btree_metadata, if INSERT_META
+ *
+ * Note: The new tuple is actually the "original" new item in the posting
+ * list split insert case (i.e. the INSERT_POST case). A split offset for
+ * the posting list is logged before the original new item. Recovery needs
+ * both, since it must do an in-place update of the existing posting list
+ * that was split as an extra step. Also, recovery generates a "final"
+ * newitem. See _bt_swap_posting() for details on posting list splits.
+ */
+typedef struct xl_btree_insert
+{
+ OffsetNumber offnum;
+
+ /* POSTING SPLIT OFFSET FOLLOWS (INSERT_POST case) */
+ /* NEW TUPLE ALWAYS FOLLOWS AT THE END */
+} xl_btree_insert;
+
+#define SizeOfBtreeInsert (offsetof(xl_btree_insert, offnum) + sizeof(OffsetNumber))
+
+/*
+ * On insert with split, we save all the items going into the right sibling
+ * so that we can restore it completely from the log record. This way takes
+ * less xlog space than the normal approach, because if we did it standardly,
+ * XLogInsert would almost always think the right page is new and store its
+ * whole page image. The left page, however, is handled in the normal
+ * incremental-update fashion.
+ *
+ * Note: XLOG_BTREE_SPLIT_L and XLOG_BTREE_SPLIT_R share this data record.
+ * There are two variants to indicate whether the inserted tuple went into the
+ * left or right split page (and thus, whether the new item is stored or not).
+ * We always log the left page high key because suffix truncation can generate
+ * a new leaf high key using user-defined code. This is also necessary on
+ * internal pages, since the firstright item that the left page's high key was
+ * based on will have been truncated to zero attributes in the right page (the
+ * separator key is unavailable from the right page).
+ *
+ * Backup Blk 0: original page / new left page
+ *
+ * The left page's data portion contains the new item, if it's the _L variant.
+ * _R variant split records generally do not have a newitem (_R variant leaf
+ * page split records that must deal with a posting list split will include an
+ * explicit newitem, though it is never used on the right page -- it is
+ * actually an orignewitem needed to update existing posting list). The new
+ * high key of the left/original page appears last of all (and must always be
+ * present).
+ *
+ * Page split records that need the REDO routine to deal with a posting list
+ * split directly will have an explicit newitem, which is actually an
+ * orignewitem (the newitem as it was before the posting list split, not
+ * after). A posting list split always has a newitem that comes immediately
+ * after the posting list being split (which would have overlapped with
+ * orignewitem prior to split). Usually REDO must deal with posting list
+ * splits with an _L variant page split record, and usually both the new
+ * posting list and the final newitem go on the left page (the existing
+ * posting list will be inserted instead of the old, and the final newitem
+ * will be inserted next to that). However, _R variant split records will
+ * include an orignewitem when the split point for the page happens to have a
+ * lastleft tuple that is also the posting list being split (leaving newitem
+ * as the page split's firstright tuple). The existence of this corner case
+ * does not change the basic fact about newitem/orignewitem for the REDO
+ * routine: it is always state used for the left page alone. (This is why the
+ * record's postingoff field isn't a reliable indicator of whether or not a
+ * posting list split occurred during the page split; a non-zero value merely
+ * indicates that the REDO routine must reconstruct a new posting list tuple
+ * that is needed for the left page.)
+ *
+ * This posting list split handling is equivalent to the xl_btree_insert REDO
+ * routine's INSERT_POST handling. While the details are more complicated
+ * here, the concept and goals are exactly the same. See _bt_swap_posting()
+ * for details on posting list splits.
+ *
+ * Backup Blk 1: new right page
+ *
+ * The right page's data portion contains the right page's tuples in the form
+ * used by _bt_restore_page. This includes the new item, if it's the _R
+ * variant. The right page's tuples also include the right page's high key
+ * with either variant (moved from the left/original page during the split),
+ * unless the split happened to be of the rightmost page on its level, where
+ * there is no high key for new right page.
+ *
+ * Backup Blk 2: next block (orig page's rightlink), if any
+ * Backup Blk 3: child's left sibling, if non-leaf split
+ */
+typedef struct xl_btree_split
+{
+ uint32 level; /* tree level of page being split */
+ OffsetNumber firstrightoff; /* first origpage item on rightpage */
+ OffsetNumber newitemoff; /* new item's offset */
+ uint16 postingoff; /* offset inside orig posting tuple */
+} xl_btree_split;
+
+#define SizeOfBtreeSplit (offsetof(xl_btree_split, postingoff) + sizeof(uint16))
+
+/*
+ * When page is deduplicated, consecutive groups of tuples with equal keys are
+ * merged together into posting list tuples.
+ *
+ * The WAL record represents a deduplication pass for a leaf page. An array
+ * of BTDedupInterval structs follows.
+ */
+typedef struct xl_btree_dedup
+{
+ uint16 nintervals;
+
+ /* DEDUPLICATION INTERVALS FOLLOW */
+} xl_btree_dedup;
+
+#define SizeOfBtreeDedup (offsetof(xl_btree_dedup, nintervals) + sizeof(uint16))
+
+/*
+ * This is what we need to know about delete of individual leaf index tuples.
+ * The WAL record can represent deletion of any number of index tuples on a
+ * single index page when *not* executed by VACUUM. Deletion of a subset of
+ * the TIDs within a posting list tuple is not supported.
+ *
+ * Backup Blk 0: index page
+ */
+typedef struct xl_btree_delete
+{
+ TransactionId latestRemovedXid;
+ uint32 ndeleted;
+
+ /* DELETED TARGET OFFSET NUMBERS FOLLOW */
+} xl_btree_delete;
+
+#define SizeOfBtreeDelete (offsetof(xl_btree_delete, ndeleted) + sizeof(uint32))
+
+/*
+ * This is what we need to know about page reuse within btree. This record
+ * only exists to generate a conflict point for Hot Standby.
+ *
+ * Note that we must include a RelFileNode in the record because we don't
+ * actually register the buffer with the record.
+ */
+typedef struct xl_btree_reuse_page
+{
+ RelFileNode node;
+ BlockNumber block;
+ TransactionId latestRemovedXid;
+} xl_btree_reuse_page;
+
+#define SizeOfBtreeReusePage (sizeof(xl_btree_reuse_page))
+
+/*
+ * This is what we need to know about which TIDs to remove from an individual
+ * posting list tuple during vacuuming. An array of these may appear at the
+ * end of xl_btree_vacuum records.
+ */
+typedef struct xl_btree_update
+{
+ uint16 ndeletedtids;
+
+ /* POSTING LIST uint16 OFFSETS TO A DELETED TID FOLLOW */
+} xl_btree_update;
+
+#define SizeOfBtreeUpdate (offsetof(xl_btree_update, ndeletedtids) + sizeof(uint16))
+
+/*
+ * This is what we need to know about a VACUUM of a leaf page. The WAL record
+ * can represent deletion of any number of index tuples on a single index page
+ * when executed by VACUUM. It can also support "updates" of index tuples,
+ * which is how deletes of a subset of TIDs contained in an existing posting
+ * list tuple are implemented. (Updates are only used when there will be some
+ * remaining TIDs once VACUUM finishes; otherwise the posting list tuple can
+ * just be deleted).
+ *
+ * Updated posting list tuples are represented using xl_btree_update metadata.
+ * The REDO routine uses each xl_btree_update (plus its corresponding original
+ * index tuple from the target leaf page) to generate the final updated tuple.
+ */
+typedef struct xl_btree_vacuum
+{
+ uint16 ndeleted;
+ uint16 nupdated;
+
+ /* DELETED TARGET OFFSET NUMBERS FOLLOW */
+ /* UPDATED TARGET OFFSET NUMBERS FOLLOW */
+ /* UPDATED TUPLES METADATA ARRAY FOLLOWS */
+} xl_btree_vacuum;
+
+#define SizeOfBtreeVacuum (offsetof(xl_btree_vacuum, nupdated) + sizeof(uint16))
+
+/*
+ * This is what we need to know about marking an empty subtree for deletion.
+ * The target identifies the tuple removed from the parent page (note that we
+ * remove this tuple's downlink and the *following* tuple's key). Note that
+ * the leaf page is empty, so we don't need to store its content --- it is
+ * just reinitialized during recovery using the rest of the fields.
+ *
+ * Backup Blk 0: leaf block
+ * Backup Blk 1: top parent
+ */
+typedef struct xl_btree_mark_page_halfdead
+{
+ OffsetNumber poffset; /* deleted tuple id in parent page */
+
+ /* information needed to recreate the leaf page: */
+ BlockNumber leafblk; /* leaf block ultimately being deleted */
+ BlockNumber leftblk; /* leaf block's left sibling, if any */
+ BlockNumber rightblk; /* leaf block's right sibling */
+ BlockNumber topparent; /* topmost internal page in the subtree */
+} xl_btree_mark_page_halfdead;
+
+#define SizeOfBtreeMarkPageHalfDead (offsetof(xl_btree_mark_page_halfdead, topparent) + sizeof(BlockNumber))
+
+/*
+ * This is what we need to know about deletion of a btree page. Note we do
+ * not store any content for the deleted page --- it is just rewritten as empty
+ * during recovery, apart from resetting the btpo.xact.
+ *
+ * Backup Blk 0: target block being deleted
+ * Backup Blk 1: target block's left sibling, if any
+ * Backup Blk 2: target block's right sibling
+ * Backup Blk 3: leaf block (if different from target)
+ * Backup Blk 4: metapage (if rightsib becomes new fast root)
+ */
+typedef struct xl_btree_unlink_page
+{
+ BlockNumber leftsib; /* target block's left sibling, if any */
+ BlockNumber rightsib; /* target block's right sibling */
+
+ /*
+ * Information needed to recreate the leaf page, when target is an
+ * internal page.
+ */
+ BlockNumber leafleftsib;
+ BlockNumber leafrightsib;
+ BlockNumber topparent; /* next child down in the subtree */
+
+ TransactionId btpo_xact; /* value of btpo.xact for use in recovery */
+ /* xl_btree_metadata FOLLOWS IF XLOG_BTREE_UNLINK_PAGE_META */
+} xl_btree_unlink_page;
+
+#define SizeOfBtreeUnlinkPage (offsetof(xl_btree_unlink_page, btpo_xact) + sizeof(TransactionId))
+
+/*
+ * New root log record. There are zero tuples if this is to establish an
+ * empty root, or two if it is the result of splitting an old root.
+ *
+ * Note that although this implies rewriting the metadata page, we don't need
+ * an xl_btree_metadata record --- the rootblk and level are sufficient.
+ *
+ * Backup Blk 0: new root page (2 tuples as payload, if splitting old root)
+ * Backup Blk 1: left child (if splitting an old root)
+ * Backup Blk 2: metapage
+ */
+typedef struct xl_btree_newroot
+{
+ BlockNumber rootblk; /* location of new root (redundant with blk 0) */
+ uint32 level; /* its tree level */
+} xl_btree_newroot;
+
+#define SizeOfBtreeNewroot (offsetof(xl_btree_newroot, level) + sizeof(uint32))
+
+
+/*
+ * prototypes for functions in nbtxlog.c
+ */
+extern void btree_redo(XLogReaderState *record);
+extern void btree_desc(StringInfo buf, XLogReaderState *record);
+extern const char *btree_identify(uint8 info);
+extern void btree_xlog_startup(void);
+extern void btree_xlog_cleanup(void);
+extern void btree_mask(char *pagedata, BlockNumber blkno);
+
+#endif /* NBTXLOG_H */
diff --git a/src/include/access/parallel.h b/src/include/access/parallel.h
new file mode 100644
index 0000000..fc6a560
--- /dev/null
+++ b/src/include/access/parallel.h
@@ -0,0 +1,82 @@
+/*-------------------------------------------------------------------------
+ *
+ * parallel.h
+ * Infrastructure for launching parallel workers
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/parallel.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef PARALLEL_H
+#define PARALLEL_H
+
+#include "access/xlogdefs.h"
+#include "lib/ilist.h"
+#include "postmaster/bgworker.h"
+#include "storage/shm_mq.h"
+#include "storage/shm_toc.h"
+
+typedef void (*parallel_worker_main_type) (dsm_segment *seg, shm_toc *toc);
+
+typedef struct ParallelWorkerInfo
+{
+ BackgroundWorkerHandle *bgwhandle;
+ shm_mq_handle *error_mqh;
+ int32 pid;
+} ParallelWorkerInfo;
+
+typedef struct ParallelContext
+{
+ dlist_node node;
+ SubTransactionId subid;
+ int nworkers; /* Maximum number of workers to launch */
+ int nworkers_to_launch; /* Actual number of workers to launch */
+ int nworkers_launched;
+ char *library_name;
+ char *function_name;
+ ErrorContextCallback *error_context_stack;
+ shm_toc_estimator estimator;
+ dsm_segment *seg;
+ void *private_memory;
+ shm_toc *toc;
+ ParallelWorkerInfo *worker;
+ int nknown_attached_workers;
+ bool *known_attached_workers;
+} ParallelContext;
+
+typedef struct ParallelWorkerContext
+{
+ dsm_segment *seg;
+ shm_toc *toc;
+} ParallelWorkerContext;
+
+extern volatile bool ParallelMessagePending;
+extern PGDLLIMPORT int ParallelWorkerNumber;
+extern PGDLLIMPORT bool InitializingParallelWorker;
+
+#define IsParallelWorker() (ParallelWorkerNumber >= 0)
+
+extern ParallelContext *CreateParallelContext(const char *library_name,
+ const char *function_name, int nworkers);
+extern void InitializeParallelDSM(ParallelContext *pcxt);
+extern void ReinitializeParallelDSM(ParallelContext *pcxt);
+extern void ReinitializeParallelWorkers(ParallelContext *pcxt, int nworkers_to_launch);
+extern void LaunchParallelWorkers(ParallelContext *pcxt);
+extern void WaitForParallelWorkersToAttach(ParallelContext *pcxt);
+extern void WaitForParallelWorkersToFinish(ParallelContext *pcxt);
+extern void DestroyParallelContext(ParallelContext *pcxt);
+extern bool ParallelContextActive(void);
+
+extern void HandleParallelMessageInterrupt(void);
+extern void HandleParallelMessages(void);
+extern void AtEOXact_Parallel(bool isCommit);
+extern void AtEOSubXact_Parallel(bool isCommit, SubTransactionId mySubId);
+extern void ParallelWorkerReportLastRecEnd(XLogRecPtr last_xlog_end);
+
+extern void ParallelWorkerMain(Datum main_arg);
+
+#endif /* PARALLEL_H */
diff --git a/src/include/access/printsimple.h b/src/include/access/printsimple.h
new file mode 100644
index 0000000..3f8a668
--- /dev/null
+++ b/src/include/access/printsimple.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * printsimple.h
+ * print simple tuples without catalog access
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/printsimple.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef PRINTSIMPLE_H
+#define PRINTSIMPLE_H
+
+#include "tcop/dest.h"
+
+extern bool printsimple(TupleTableSlot *slot, DestReceiver *self);
+extern void printsimple_startup(DestReceiver *self, int operation,
+ TupleDesc tupdesc);
+
+#endif /* PRINTSIMPLE_H */
diff --git a/src/include/access/printtup.h b/src/include/access/printtup.h
new file mode 100644
index 0000000..c367825
--- /dev/null
+++ b/src/include/access/printtup.h
@@ -0,0 +1,35 @@
+/*-------------------------------------------------------------------------
+ *
+ * printtup.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/printtup.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PRINTTUP_H
+#define PRINTTUP_H
+
+#include "utils/portal.h"
+
+extern DestReceiver *printtup_create_DR(CommandDest dest);
+
+extern void SetRemoteDestReceiverParams(DestReceiver *self, Portal portal);
+
+extern void SendRowDescriptionMessage(StringInfo buf,
+ TupleDesc typeinfo, List *targetlist, int16 *formats);
+
+extern void debugStartup(DestReceiver *self, int operation,
+ TupleDesc typeinfo);
+extern bool debugtup(TupleTableSlot *slot, DestReceiver *self);
+
+/* XXX these are really in executor/spi.c */
+extern void spi_dest_startup(DestReceiver *self, int operation,
+ TupleDesc typeinfo);
+extern bool spi_printtup(TupleTableSlot *slot, DestReceiver *self);
+
+#endif /* PRINTTUP_H */
diff --git a/src/include/access/relation.h b/src/include/access/relation.h
new file mode 100644
index 0000000..2ed0f8e
--- /dev/null
+++ b/src/include/access/relation.h
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+ *
+ * relation.h
+ * Generic relation related routines.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/relation.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ACCESS_RELATION_H
+#define ACCESS_RELATION_H
+
+#include "nodes/primnodes.h"
+#include "storage/lockdefs.h"
+#include "utils/relcache.h"
+
+extern Relation relation_open(Oid relationId, LOCKMODE lockmode);
+extern Relation try_relation_open(Oid relationId, LOCKMODE lockmode);
+extern Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode);
+extern Relation relation_openrv_extended(const RangeVar *relation,
+ LOCKMODE lockmode, bool missing_ok);
+extern void relation_close(Relation relation, LOCKMODE lockmode);
+
+#endif /* ACCESS_RELATION_H */
diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h
new file mode 100644
index 0000000..5964438
--- /dev/null
+++ b/src/include/access/reloptions.h
@@ -0,0 +1,247 @@
+/*-------------------------------------------------------------------------
+ *
+ * reloptions.h
+ * Core support for relation and tablespace options (pg_class.reloptions
+ * and pg_tablespace.spcoptions)
+ *
+ * Note: the functions dealing with text-array reloptions values declare
+ * them as Datum, not ArrayType *, to avoid needing to include array.h
+ * into a lot of low-level code.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/reloptions.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RELOPTIONS_H
+#define RELOPTIONS_H
+
+#include "access/amapi.h"
+#include "access/htup.h"
+#include "access/tupdesc.h"
+#include "nodes/pg_list.h"
+#include "storage/lock.h"
+
+/* types supported by reloptions */
+typedef enum relopt_type
+{
+ RELOPT_TYPE_BOOL,
+ RELOPT_TYPE_INT,
+ RELOPT_TYPE_REAL,
+ RELOPT_TYPE_ENUM,
+ RELOPT_TYPE_STRING
+} relopt_type;
+
+/* kinds supported by reloptions */
+typedef enum relopt_kind
+{
+ RELOPT_KIND_LOCAL = 0,
+ RELOPT_KIND_HEAP = (1 << 0),
+ RELOPT_KIND_TOAST = (1 << 1),
+ RELOPT_KIND_BTREE = (1 << 2),
+ RELOPT_KIND_HASH = (1 << 3),
+ RELOPT_KIND_GIN = (1 << 4),
+ RELOPT_KIND_GIST = (1 << 5),
+ RELOPT_KIND_ATTRIBUTE = (1 << 6),
+ RELOPT_KIND_TABLESPACE = (1 << 7),
+ RELOPT_KIND_SPGIST = (1 << 8),
+ RELOPT_KIND_VIEW = (1 << 9),
+ RELOPT_KIND_BRIN = (1 << 10),
+ RELOPT_KIND_PARTITIONED = (1 << 11),
+ /* if you add a new kind, make sure you update "last_default" too */
+ RELOPT_KIND_LAST_DEFAULT = RELOPT_KIND_PARTITIONED,
+ /* some compilers treat enums as signed ints, so we can't use 1 << 31 */
+ RELOPT_KIND_MAX = (1 << 30)
+} relopt_kind;
+
+/* reloption namespaces allowed for heaps -- currently only TOAST */
+#define HEAP_RELOPT_NAMESPACES { "toast", NULL }
+
+/* generic struct to hold shared data */
+typedef struct relopt_gen
+{
+ const char *name; /* must be first (used as list termination
+ * marker) */
+ const char *desc;
+ bits32 kinds;
+ LOCKMODE lockmode;
+ int namelen;
+ relopt_type type;
+} relopt_gen;
+
+/* holds a parsed value */
+typedef struct relopt_value
+{
+ relopt_gen *gen;
+ bool isset;
+ union
+ {
+ bool bool_val;
+ int int_val;
+ double real_val;
+ int enum_val;
+ char *string_val; /* allocated separately */
+ } values;
+} relopt_value;
+
+/* reloptions records for specific variable types */
+typedef struct relopt_bool
+{
+ relopt_gen gen;
+ bool default_val;
+} relopt_bool;
+
+typedef struct relopt_int
+{
+ relopt_gen gen;
+ int default_val;
+ int min;
+ int max;
+} relopt_int;
+
+typedef struct relopt_real
+{
+ relopt_gen gen;
+ double default_val;
+ double min;
+ double max;
+} relopt_real;
+
+/*
+ * relopt_enum_elt_def -- One member of the array of acceptable values
+ * of an enum reloption.
+ */
+typedef struct relopt_enum_elt_def
+{
+ const char *string_val;
+ int symbol_val;
+} relopt_enum_elt_def;
+
+typedef struct relopt_enum
+{
+ relopt_gen gen;
+ relopt_enum_elt_def *members;
+ int default_val;
+ const char *detailmsg;
+ /* null-terminated array of members */
+} relopt_enum;
+
+/* validation routines for strings */
+typedef void (*validate_string_relopt) (const char *value);
+typedef Size (*fill_string_relopt) (const char *value, void *ptr);
+
+/* validation routine for the whole option set */
+typedef void (*relopts_validator) (void *parsed_options, relopt_value *vals, int nvals);
+
+typedef struct relopt_string
+{
+ relopt_gen gen;
+ int default_len;
+ bool default_isnull;
+ validate_string_relopt validate_cb;
+ fill_string_relopt fill_cb;
+ char *default_val;
+} relopt_string;
+
+/* This is the table datatype for build_reloptions() */
+typedef struct
+{
+ const char *optname; /* option's name */
+ relopt_type opttype; /* option's datatype */
+ int offset; /* offset of field in result struct */
+} relopt_parse_elt;
+
+/* Local reloption definition */
+typedef struct local_relopt
+{
+ relopt_gen *option; /* option definition */
+ int offset; /* offset of parsed value in bytea structure */
+} local_relopt;
+
+/* Structure to hold local reloption data for build_local_reloptions() */
+typedef struct local_relopts
+{
+ List *options; /* list of local_relopt definitions */
+ List *validators; /* list of relopts_validator callbacks */
+ Size relopt_struct_size; /* size of parsed bytea structure */
+} local_relopts;
+
+/*
+ * Utility macro to get a value for a string reloption once the options
+ * are parsed. This gets a pointer to the string value itself. "optstruct"
+ * is the StdRdOptions struct or equivalent, "member" is the struct member
+ * corresponding to the string option.
+ */
+#define GET_STRING_RELOPTION(optstruct, member) \
+ ((optstruct)->member == 0 ? NULL : \
+ (char *)(optstruct) + (optstruct)->member)
+
+extern relopt_kind add_reloption_kind(void);
+extern void add_bool_reloption(bits32 kinds, const char *name, const char *desc,
+ bool default_val, LOCKMODE lockmode);
+extern void add_int_reloption(bits32 kinds, const char *name, const char *desc,
+ int default_val, int min_val, int max_val,
+ LOCKMODE lockmode);
+extern void add_real_reloption(bits32 kinds, const char *name, const char *desc,
+ double default_val, double min_val, double max_val,
+ LOCKMODE lockmode);
+extern void add_enum_reloption(bits32 kinds, const char *name, const char *desc,
+ relopt_enum_elt_def *members, int default_val,
+ const char *detailmsg, LOCKMODE lockmode);
+extern void add_string_reloption(bits32 kinds, const char *name, const char *desc,
+ const char *default_val, validate_string_relopt validator,
+ LOCKMODE lockmode);
+
+extern void init_local_reloptions(local_relopts *opts, Size relopt_struct_size);
+extern void register_reloptions_validator(local_relopts *opts,
+ relopts_validator validator);
+extern void add_local_bool_reloption(local_relopts *opts, const char *name,
+ const char *desc, bool default_val,
+ int offset);
+extern void add_local_int_reloption(local_relopts *opts, const char *name,
+ const char *desc, int default_val,
+ int min_val, int max_val, int offset);
+extern void add_local_real_reloption(local_relopts *opts, const char *name,
+ const char *desc, double default_val,
+ double min_val, double max_val,
+ int offset);
+extern void add_local_enum_reloption(local_relopts *relopts,
+ const char *name, const char *desc,
+ relopt_enum_elt_def *members,
+ int default_val, const char *detailmsg,
+ int offset);
+extern void add_local_string_reloption(local_relopts *opts, const char *name,
+ const char *desc,
+ const char *default_val,
+ validate_string_relopt validator,
+ fill_string_relopt filler, int offset);
+
+extern Datum transformRelOptions(Datum oldOptions, List *defList,
+ const char *namspace, char *validnsps[],
+ bool acceptOidsOff, bool isReset);
+extern List *untransformRelOptions(Datum options);
+extern bytea *extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
+ amoptions_function amoptions);
+extern void *build_reloptions(Datum reloptions, bool validate,
+ relopt_kind kind,
+ Size relopt_struct_size,
+ const relopt_parse_elt *relopt_elems,
+ int num_relopt_elems);
+extern void *build_local_reloptions(local_relopts *relopts, Datum options,
+ bool validate);
+
+extern bytea *default_reloptions(Datum reloptions, bool validate,
+ relopt_kind kind);
+extern bytea *heap_reloptions(char relkind, Datum reloptions, bool validate);
+extern bytea *view_reloptions(Datum reloptions, bool validate);
+extern bytea *partitioned_table_reloptions(Datum reloptions, bool validate);
+extern bytea *index_reloptions(amoptions_function amoptions, Datum reloptions,
+ bool validate);
+extern bytea *attribute_reloptions(Datum reloptions, bool validate);
+extern bytea *tablespace_reloptions(Datum reloptions, bool validate);
+extern LOCKMODE AlterTableGetRelOptionsLockLevel(List *defList);
+
+#endif /* RELOPTIONS_H */
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
new file mode 100644
index 0000000..6f02588
--- /dev/null
+++ b/src/include/access/relscan.h
@@ -0,0 +1,176 @@
+/*-------------------------------------------------------------------------
+ *
+ * relscan.h
+ * POSTGRES relation scan descriptor definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/relscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RELSCAN_H
+#define RELSCAN_H
+
+#include "access/htup_details.h"
+#include "access/itup.h"
+#include "port/atomics.h"
+#include "storage/buf.h"
+#include "storage/spin.h"
+#include "utils/relcache.h"
+
+
+struct ParallelTableScanDescData;
+
+/*
+ * Generic descriptor for table scans. This is the base-class for table scans,
+ * which needs to be embedded in the scans of individual AMs.
+ */
+typedef struct TableScanDescData
+{
+ /* scan parameters */
+ Relation rs_rd; /* heap relation descriptor */
+ struct SnapshotData *rs_snapshot; /* snapshot to see */
+ int rs_nkeys; /* number of scan keys */
+ struct ScanKeyData *rs_key; /* array of scan key descriptors */
+
+ /*
+ * Information about type and behaviour of the scan, a bitmask of members
+ * of the ScanOptions enum (see tableam.h).
+ */
+ uint32 rs_flags;
+
+ struct ParallelTableScanDescData *rs_parallel; /* parallel scan
+ * information */
+
+} TableScanDescData;
+typedef struct TableScanDescData *TableScanDesc;
+
+/*
+ * Shared state for parallel table scan.
+ *
+ * Each backend participating in a parallel table scan has its own
+ * TableScanDesc in backend-private memory, and those objects all contain a
+ * pointer to this structure. The information here must be sufficient to
+ * properly initialize each new TableScanDesc as workers join the scan, and it
+ * must act as a information what to scan for those workers.
+ */
+typedef struct ParallelTableScanDescData
+{
+ Oid phs_relid; /* OID of relation to scan */
+ bool phs_syncscan; /* report location to syncscan logic? */
+ bool phs_snapshot_any; /* SnapshotAny, not phs_snapshot_data? */
+ Size phs_snapshot_off; /* data for snapshot */
+} ParallelTableScanDescData;
+typedef struct ParallelTableScanDescData *ParallelTableScanDesc;
+
+/*
+ * Shared state for parallel table scans, for block oriented storage.
+ */
+typedef struct ParallelBlockTableScanDescData
+{
+ ParallelTableScanDescData base;
+
+ BlockNumber phs_nblocks; /* # blocks in relation at start of scan */
+ slock_t phs_mutex; /* mutual exclusion for setting startblock */
+ BlockNumber phs_startblock; /* starting block number */
+ pg_atomic_uint64 phs_nallocated; /* number of blocks allocated to
+ * workers so far. */
+} ParallelBlockTableScanDescData;
+typedef struct ParallelBlockTableScanDescData *ParallelBlockTableScanDesc;
+
+/*
+ * Base class for fetches from a table via an index. This is the base-class
+ * for such scans, which needs to be embedded in the respective struct for
+ * individual AMs.
+ */
+typedef struct IndexFetchTableData
+{
+ Relation rel;
+} IndexFetchTableData;
+
+/*
+ * We use the same IndexScanDescData structure for both amgettuple-based
+ * and amgetbitmap-based index scans. Some fields are only relevant in
+ * amgettuple-based scans.
+ */
+typedef struct IndexScanDescData
+{
+ /* scan parameters */
+ Relation heapRelation; /* heap relation descriptor, or NULL */
+ Relation indexRelation; /* index relation descriptor */
+ struct SnapshotData *xs_snapshot; /* snapshot to see */
+ int numberOfKeys; /* number of index qualifier conditions */
+ int numberOfOrderBys; /* number of ordering operators */
+ struct ScanKeyData *keyData; /* array of index qualifier descriptors */
+ struct ScanKeyData *orderByData; /* array of ordering op descriptors */
+ bool xs_want_itup; /* caller requests index tuples */
+ bool xs_temp_snap; /* unregister snapshot at scan end? */
+
+ /* signaling to index AM about killing index tuples */
+ bool kill_prior_tuple; /* last-returned tuple is dead */
+ bool ignore_killed_tuples; /* do not return killed entries */
+ bool xactStartedInRecovery; /* prevents killing/seeing killed
+ * tuples */
+
+ /* index access method's private state */
+ void *opaque; /* access-method-specific info */
+
+ /*
+ * In an index-only scan, a successful amgettuple call must fill either
+ * xs_itup (and xs_itupdesc) or xs_hitup (and xs_hitupdesc) to provide the
+ * data returned by the scan. It can fill both, in which case the heap
+ * format will be used.
+ */
+ IndexTuple xs_itup; /* index tuple returned by AM */
+ struct TupleDescData *xs_itupdesc; /* rowtype descriptor of xs_itup */
+ HeapTuple xs_hitup; /* index data returned by AM, as HeapTuple */
+ struct TupleDescData *xs_hitupdesc; /* rowtype descriptor of xs_hitup */
+
+ ItemPointerData xs_heaptid; /* result */
+ bool xs_heap_continue; /* T if must keep walking, potential
+ * further results */
+ IndexFetchTableData *xs_heapfetch;
+
+ bool xs_recheck; /* T means scan keys must be rechecked */
+
+ /*
+ * When fetching with an ordering operator, the values of the ORDER BY
+ * expressions of the last returned tuple, according to the index. If
+ * xs_recheckorderby is true, these need to be rechecked just like the
+ * scan keys, and the values returned here are a lower-bound on the actual
+ * values.
+ */
+ Datum *xs_orderbyvals;
+ bool *xs_orderbynulls;
+ bool xs_recheckorderby;
+
+ /* parallel index scan information, in shared memory */
+ struct ParallelIndexScanDescData *parallel_scan;
+} IndexScanDescData;
+
+/* Generic structure for parallel scans */
+typedef struct ParallelIndexScanDescData
+{
+ Oid ps_relid;
+ Oid ps_indexid;
+ Size ps_offset; /* Offset in bytes of am specific structure */
+ char ps_snapshot_data[FLEXIBLE_ARRAY_MEMBER];
+} ParallelIndexScanDescData;
+
+struct TupleTableSlot;
+
+/* Struct for storage-or-index scans of system tables */
+typedef struct SysScanDescData
+{
+ Relation heap_rel; /* catalog being scanned */
+ Relation irel; /* NULL if doing heap scan */
+ struct TableScanDescData *scan; /* only valid in storage-scan case */
+ struct IndexScanDescData *iscan; /* only valid in index-scan case */
+ struct SnapshotData *snapshot; /* snapshot to unregister at end of scan */
+ struct TupleTableSlot *slot;
+} SysScanDescData;
+
+#endif /* RELSCAN_H */
diff --git a/src/include/access/rewriteheap.h b/src/include/access/rewriteheap.h
new file mode 100644
index 0000000..e6d7fa1
--- /dev/null
+++ b/src/include/access/rewriteheap.h
@@ -0,0 +1,57 @@
+/*-------------------------------------------------------------------------
+ *
+ * rewriteheap.h
+ * Declarations for heap rewrite support functions
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994-5, Regents of the University of California
+ *
+ * src/include/access/rewriteheap.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef REWRITE_HEAP_H
+#define REWRITE_HEAP_H
+
+#include "access/htup.h"
+#include "storage/itemptr.h"
+#include "storage/relfilenode.h"
+#include "utils/relcache.h"
+
+/* struct definition is private to rewriteheap.c */
+typedef struct RewriteStateData *RewriteState;
+
+extern RewriteState begin_heap_rewrite(Relation OldHeap, Relation NewHeap,
+ TransactionId OldestXmin, TransactionId FreezeXid,
+ MultiXactId MultiXactCutoff);
+extern void end_heap_rewrite(RewriteState state);
+extern void rewrite_heap_tuple(RewriteState state, HeapTuple oldTuple,
+ HeapTuple newTuple);
+extern bool rewrite_heap_dead_tuple(RewriteState state, HeapTuple oldTuple);
+
+/*
+ * On-Disk data format for an individual logical rewrite mapping.
+ */
+typedef struct LogicalRewriteMappingData
+{
+ RelFileNode old_node;
+ RelFileNode new_node;
+ ItemPointerData old_tid;
+ ItemPointerData new_tid;
+} LogicalRewriteMappingData;
+
+/* ---
+ * The filename consists of the following, dash separated,
+ * components:
+ * 1) database oid or InvalidOid for shared relations
+ * 2) the oid of the relation
+ * 3) upper 32bit of the LSN at which a rewrite started
+ * 4) lower 32bit of the LSN at which a rewrite started
+ * 5) xid we are mapping for
+ * 6) xid of the xact performing the mapping
+ * ---
+ */
+#define LOGICAL_REWRITE_FORMAT "map-%x-%x-%X_%X-%x-%x"
+void CheckPointLogicalRewriteHeap(void);
+
+#endif /* REWRITE_HEAP_H */
diff --git a/src/include/access/rmgr.h b/src/include/access/rmgr.h
new file mode 100644
index 0000000..c9b5c56
--- /dev/null
+++ b/src/include/access/rmgr.h
@@ -0,0 +1,35 @@
+/*
+ * rmgr.h
+ *
+ * Resource managers definition
+ *
+ * src/include/access/rmgr.h
+ */
+#ifndef RMGR_H
+#define RMGR_H
+
+typedef uint8 RmgrId;
+
+/*
+ * Built-in resource managers
+ *
+ * The actual numerical values for each rmgr ID are defined by the order
+ * of entries in rmgrlist.h.
+ *
+ * Note: RM_MAX_ID must fit in RmgrId; widening that type will affect the XLOG
+ * file format.
+ */
+#define PG_RMGR(symname,name,redo,desc,identify,startup,cleanup,mask) \
+ symname,
+
+typedef enum RmgrIds
+{
+#include "access/rmgrlist.h"
+ RM_NEXT_ID
+} RmgrIds;
+
+#undef PG_RMGR
+
+#define RM_MAX_ID (RM_NEXT_ID - 1)
+
+#endif /* RMGR_H */
diff --git a/src/include/access/rmgrlist.h b/src/include/access/rmgrlist.h
new file mode 100644
index 0000000..6c15df7
--- /dev/null
+++ b/src/include/access/rmgrlist.h
@@ -0,0 +1,49 @@
+/*---------------------------------------------------------------------------
+ * rmgrlist.h
+ *
+ * The resource manager list is kept in its own source file for possible
+ * use by automatic tools. The exact representation of a rmgr is determined
+ * by the PG_RMGR macro, which is not defined in this file; it can be
+ * defined by the caller for special purposes.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/rmgrlist.h
+ *---------------------------------------------------------------------------
+ */
+
+/* there is deliberately not an #ifndef RMGRLIST_H here */
+
+/*
+ * List of resource manager entries. Note that order of entries defines the
+ * numerical values of each rmgr's ID, which is stored in WAL records. New
+ * entries should be added at the end, to avoid changing IDs of existing
+ * entries.
+ *
+ * Changes to this list possibly need an XLOG_PAGE_MAGIC bump.
+ */
+
+/* symbol name, textual name, redo, desc, identify, startup, cleanup */
+PG_RMGR(RM_XLOG_ID, "XLOG", xlog_redo, xlog_desc, xlog_identify, NULL, NULL, NULL)
+PG_RMGR(RM_XACT_ID, "Transaction", xact_redo, xact_desc, xact_identify, NULL, NULL, NULL)
+PG_RMGR(RM_SMGR_ID, "Storage", smgr_redo, smgr_desc, smgr_identify, NULL, NULL, NULL)
+PG_RMGR(RM_CLOG_ID, "CLOG", clog_redo, clog_desc, clog_identify, NULL, NULL, NULL)
+PG_RMGR(RM_DBASE_ID, "Database", dbase_redo, dbase_desc, dbase_identify, NULL, NULL, NULL)
+PG_RMGR(RM_TBLSPC_ID, "Tablespace", tblspc_redo, tblspc_desc, tblspc_identify, NULL, NULL, NULL)
+PG_RMGR(RM_MULTIXACT_ID, "MultiXact", multixact_redo, multixact_desc, multixact_identify, NULL, NULL, NULL)
+PG_RMGR(RM_RELMAP_ID, "RelMap", relmap_redo, relmap_desc, relmap_identify, NULL, NULL, NULL)
+PG_RMGR(RM_STANDBY_ID, "Standby", standby_redo, standby_desc, standby_identify, NULL, NULL, NULL)
+PG_RMGR(RM_HEAP2_ID, "Heap2", heap2_redo, heap2_desc, heap2_identify, NULL, NULL, heap_mask)
+PG_RMGR(RM_HEAP_ID, "Heap", heap_redo, heap_desc, heap_identify, NULL, NULL, heap_mask)
+PG_RMGR(RM_BTREE_ID, "Btree", btree_redo, btree_desc, btree_identify, btree_xlog_startup, btree_xlog_cleanup, btree_mask)
+PG_RMGR(RM_HASH_ID, "Hash", hash_redo, hash_desc, hash_identify, NULL, NULL, hash_mask)
+PG_RMGR(RM_GIN_ID, "Gin", gin_redo, gin_desc, gin_identify, gin_xlog_startup, gin_xlog_cleanup, gin_mask)
+PG_RMGR(RM_GIST_ID, "Gist", gist_redo, gist_desc, gist_identify, gist_xlog_startup, gist_xlog_cleanup, gist_mask)
+PG_RMGR(RM_SEQ_ID, "Sequence", seq_redo, seq_desc, seq_identify, NULL, NULL, seq_mask)
+PG_RMGR(RM_SPGIST_ID, "SPGist", spg_redo, spg_desc, spg_identify, spg_xlog_startup, spg_xlog_cleanup, spg_mask)
+PG_RMGR(RM_BRIN_ID, "BRIN", brin_redo, brin_desc, brin_identify, NULL, NULL, brin_mask)
+PG_RMGR(RM_COMMIT_TS_ID, "CommitTs", commit_ts_redo, commit_ts_desc, commit_ts_identify, NULL, NULL, NULL)
+PG_RMGR(RM_REPLORIGIN_ID, "ReplicationOrigin", replorigin_redo, replorigin_desc, replorigin_identify, NULL, NULL, NULL)
+PG_RMGR(RM_GENERIC_ID, "Generic", generic_redo, generic_desc, generic_identify, NULL, NULL, generic_mask)
+PG_RMGR(RM_LOGICALMSG_ID, "LogicalMessage", logicalmsg_redo, logicalmsg_desc, logicalmsg_identify, NULL, NULL, NULL)
diff --git a/src/include/access/sdir.h b/src/include/access/sdir.h
new file mode 100644
index 0000000..23feb90
--- /dev/null
+++ b/src/include/access/sdir.h
@@ -0,0 +1,58 @@
+/*-------------------------------------------------------------------------
+ *
+ * sdir.h
+ * POSTGRES scan direction definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/sdir.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SDIR_H
+#define SDIR_H
+
+
+/*
+ * ScanDirection was an int8 for no apparent reason. I kept the original
+ * values because I'm not sure if I'll break anything otherwise. -ay 2/95
+ */
+typedef enum ScanDirection
+{
+ BackwardScanDirection = -1,
+ NoMovementScanDirection = 0,
+ ForwardScanDirection = 1
+} ScanDirection;
+
+/*
+ * ScanDirectionIsValid
+ * True iff scan direction is valid.
+ */
+#define ScanDirectionIsValid(direction) \
+ ((bool) (BackwardScanDirection <= (direction) && \
+ (direction) <= ForwardScanDirection))
+
+/*
+ * ScanDirectionIsBackward
+ * True iff scan direction is backward.
+ */
+#define ScanDirectionIsBackward(direction) \
+ ((bool) ((direction) == BackwardScanDirection))
+
+/*
+ * ScanDirectionIsNoMovement
+ * True iff scan direction indicates no movement.
+ */
+#define ScanDirectionIsNoMovement(direction) \
+ ((bool) ((direction) == NoMovementScanDirection))
+
+/*
+ * ScanDirectionIsForward
+ * True iff scan direction is forward.
+ */
+#define ScanDirectionIsForward(direction) \
+ ((bool) ((direction) == ForwardScanDirection))
+
+#endif /* SDIR_H */
diff --git a/src/include/access/session.h b/src/include/access/session.h
new file mode 100644
index 0000000..4c1f6ff
--- /dev/null
+++ b/src/include/access/session.h
@@ -0,0 +1,44 @@
+/*-------------------------------------------------------------------------
+ *
+ * session.h
+ * Encapsulation of user session.
+ *
+ * Copyright (c) 2017-2020, PostgreSQL Global Development Group
+ *
+ * src/include/access/session.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SESSION_H
+#define SESSION_H
+
+#include "lib/dshash.h"
+
+/* Avoid including typcache.h */
+struct SharedRecordTypmodRegistry;
+
+/*
+ * A struct encapsulating some elements of a user's session. For now this
+ * manages state that applies to parallel query, but in principle it could
+ * include other things that are currently global variables.
+ */
+typedef struct Session
+{
+ dsm_segment *segment; /* The session-scoped DSM segment. */
+ dsa_area *area; /* The session-scoped DSA area. */
+
+ /* State managed by typcache.c. */
+ struct SharedRecordTypmodRegistry *shared_typmod_registry;
+ dshash_table *shared_record_table;
+ dshash_table *shared_typmod_table;
+} Session;
+
+extern void InitializeSession(void);
+extern dsm_handle GetSessionDsmHandle(void);
+extern void AttachSession(dsm_handle handle);
+extern void DetachSession(void);
+
+/* The current session, or NULL for none. */
+extern Session *CurrentSession;
+
+#endif /* SESSION_H */
diff --git a/src/include/access/skey.h b/src/include/access/skey.h
new file mode 100644
index 0000000..7d2df1b
--- /dev/null
+++ b/src/include/access/skey.h
@@ -0,0 +1,151 @@
+/*-------------------------------------------------------------------------
+ *
+ * skey.h
+ * POSTGRES scan key definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/skey.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SKEY_H
+#define SKEY_H
+
+#include "access/attnum.h"
+#include "access/stratnum.h"
+#include "fmgr.h"
+
+
+/*
+ * A ScanKey represents the application of a comparison operator between
+ * a table or index column and a constant. When it's part of an array of
+ * ScanKeys, the comparison conditions are implicitly ANDed. The index
+ * column is the left argument of the operator, if it's a binary operator.
+ * (The data structure can support unary indexable operators too; in that
+ * case sk_argument would go unused. This is not currently implemented.)
+ *
+ * For an index scan, sk_strategy and sk_subtype must be set correctly for
+ * the operator. When using a ScanKey in a heap scan, these fields are not
+ * used and may be set to InvalidStrategy/InvalidOid.
+ *
+ * If the operator is collation-sensitive, sk_collation must be set
+ * correctly as well.
+ *
+ * A ScanKey can also represent a ScalarArrayOpExpr, that is a condition
+ * "column op ANY(ARRAY[...])". This is signaled by the SK_SEARCHARRAY
+ * flag bit. The sk_argument is not a value of the operator's right-hand
+ * argument type, but rather an array of such values, and the per-element
+ * comparisons are to be ORed together.
+ *
+ * A ScanKey can also represent a condition "column IS NULL" or "column
+ * IS NOT NULL"; these cases are signaled by the SK_SEARCHNULL and
+ * SK_SEARCHNOTNULL flag bits respectively. The argument is always NULL,
+ * and the sk_strategy, sk_subtype, sk_collation, and sk_func fields are
+ * not used (unless set by the index AM).
+ *
+ * SK_SEARCHARRAY, SK_SEARCHNULL and SK_SEARCHNOTNULL are supported only
+ * for index scans, not heap scans; and not all index AMs support them,
+ * only those that set amsearcharray or amsearchnulls respectively.
+ *
+ * A ScanKey can also represent an ordering operator invocation, that is
+ * an ordering requirement "ORDER BY indexedcol op constant". This looks
+ * the same as a comparison operator, except that the operator doesn't
+ * (usually) yield boolean. We mark such ScanKeys with SK_ORDER_BY.
+ * SK_SEARCHARRAY, SK_SEARCHNULL, SK_SEARCHNOTNULL cannot be used here.
+ *
+ * Note: in some places, ScanKeys are used as a convenient representation
+ * for the invocation of an access method support procedure. In this case
+ * sk_strategy/sk_subtype are not meaningful (but sk_collation can be); and
+ * sk_func may refer to a function that returns something other than boolean.
+ */
+typedef struct ScanKeyData
+{
+ int sk_flags; /* flags, see below */
+ AttrNumber sk_attno; /* table or index column number */
+ StrategyNumber sk_strategy; /* operator strategy number */
+ Oid sk_subtype; /* strategy subtype */
+ Oid sk_collation; /* collation to use, if needed */
+ FmgrInfo sk_func; /* lookup info for function to call */
+ Datum sk_argument; /* data to compare */
+} ScanKeyData;
+
+typedef ScanKeyData *ScanKey;
+
+/*
+ * About row comparisons:
+ *
+ * The ScanKey data structure also supports row comparisons, that is ordered
+ * tuple comparisons like (x, y) > (c1, c2), having the SQL-spec semantics
+ * "x > c1 OR (x = c1 AND y > c2)". Note that this is currently only
+ * implemented for btree index searches, not for heapscans or any other index
+ * type. A row comparison is represented by a "header" ScanKey entry plus
+ * a separate array of ScanKeys, one for each column of the row comparison.
+ * The header entry has these properties:
+ * sk_flags = SK_ROW_HEADER
+ * sk_attno = index column number for leading column of row comparison
+ * sk_strategy = btree strategy code for semantics of row comparison
+ * (ie, < <= > or >=)
+ * sk_subtype, sk_collation, sk_func: not used
+ * sk_argument: pointer to subsidiary ScanKey array
+ * If the header is part of a ScanKey array that's sorted by attno, it
+ * must be sorted according to the leading column number.
+ *
+ * The subsidiary ScanKey array appears in logical column order of the row
+ * comparison, which may be different from index column order. The array
+ * elements are like a normal ScanKey array except that:
+ * sk_flags must include SK_ROW_MEMBER, plus SK_ROW_END in the last
+ * element (needed since row header does not include a count)
+ * sk_func points to the btree comparison support function for the
+ * opclass, NOT the operator's implementation function.
+ * sk_strategy must be the same in all elements of the subsidiary array,
+ * that is, the same as in the header entry.
+ * SK_SEARCHARRAY, SK_SEARCHNULL, SK_SEARCHNOTNULL cannot be used here.
+ */
+
+/*
+ * ScanKeyData sk_flags
+ *
+ * sk_flags bits 0-15 are reserved for system-wide use (symbols for those
+ * bits should be defined here). Bits 16-31 are reserved for use within
+ * individual index access methods.
+ */
+#define SK_ISNULL 0x0001 /* sk_argument is NULL */
+#define SK_UNARY 0x0002 /* unary operator (not supported!) */
+#define SK_ROW_HEADER 0x0004 /* row comparison header (see above) */
+#define SK_ROW_MEMBER 0x0008 /* row comparison member (see above) */
+#define SK_ROW_END 0x0010 /* last row comparison member */
+#define SK_SEARCHARRAY 0x0020 /* scankey represents ScalarArrayOp */
+#define SK_SEARCHNULL 0x0040 /* scankey represents "col IS NULL" */
+#define SK_SEARCHNOTNULL 0x0080 /* scankey represents "col IS NOT NULL" */
+#define SK_ORDER_BY 0x0100 /* scankey is for ORDER BY op */
+
+
+/*
+ * prototypes for functions in access/common/scankey.c
+ */
+extern void ScanKeyInit(ScanKey entry,
+ AttrNumber attributeNumber,
+ StrategyNumber strategy,
+ RegProcedure procedure,
+ Datum argument);
+extern void ScanKeyEntryInitialize(ScanKey entry,
+ int flags,
+ AttrNumber attributeNumber,
+ StrategyNumber strategy,
+ Oid subtype,
+ Oid collation,
+ RegProcedure procedure,
+ Datum argument);
+extern void ScanKeyEntryInitializeWithInfo(ScanKey entry,
+ int flags,
+ AttrNumber attributeNumber,
+ StrategyNumber strategy,
+ Oid subtype,
+ Oid collation,
+ FmgrInfo *finfo,
+ Datum argument);
+
+#endif /* SKEY_H */
diff --git a/src/include/access/slru.h b/src/include/access/slru.h
new file mode 100644
index 0000000..19982f6
--- /dev/null
+++ b/src/include/access/slru.h
@@ -0,0 +1,170 @@
+/*-------------------------------------------------------------------------
+ *
+ * slru.h
+ * Simple LRU buffering for transaction status logfiles
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/slru.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SLRU_H
+#define SLRU_H
+
+#include "access/xlogdefs.h"
+#include "storage/lwlock.h"
+
+
+/*
+ * Define SLRU segment size. A page is the same BLCKSZ as is used everywhere
+ * else in Postgres. The segment size can be chosen somewhat arbitrarily;
+ * we make it 32 pages by default, or 256Kb, i.e. 1M transactions for CLOG
+ * or 64K transactions for SUBTRANS.
+ *
+ * Note: because TransactionIds are 32 bits and wrap around at 0xFFFFFFFF,
+ * page numbering also wraps around at 0xFFFFFFFF/xxxx_XACTS_PER_PAGE (where
+ * xxxx is CLOG or SUBTRANS, respectively), and segment numbering at
+ * 0xFFFFFFFF/xxxx_XACTS_PER_PAGE/SLRU_PAGES_PER_SEGMENT. We need
+ * take no explicit notice of that fact in slru.c, except when comparing
+ * segment and page numbers in SimpleLruTruncate (see PagePrecedes()).
+ */
+#define SLRU_PAGES_PER_SEGMENT 32
+
+/*
+ * Page status codes. Note that these do not include the "dirty" bit.
+ * page_dirty can be true only in the VALID or WRITE_IN_PROGRESS states;
+ * in the latter case it implies that the page has been re-dirtied since
+ * the write started.
+ */
+typedef enum
+{
+ SLRU_PAGE_EMPTY, /* buffer is not in use */
+ SLRU_PAGE_READ_IN_PROGRESS, /* page is being read in */
+ SLRU_PAGE_VALID, /* page is valid and not being written */
+ SLRU_PAGE_WRITE_IN_PROGRESS /* page is being written out */
+} SlruPageStatus;
+
+/*
+ * Shared-memory state
+ */
+typedef struct SlruSharedData
+{
+ LWLock *ControlLock;
+
+ /* Number of buffers managed by this SLRU structure */
+ int num_slots;
+
+ /*
+ * Arrays holding info for each buffer slot. Page number is undefined
+ * when status is EMPTY, as is page_lru_count.
+ */
+ char **page_buffer;
+ SlruPageStatus *page_status;
+ bool *page_dirty;
+ int *page_number;
+ int *page_lru_count;
+ LWLockPadded *buffer_locks;
+
+ /*
+ * Optional array of WAL flush LSNs associated with entries in the SLRU
+ * pages. If not zero/NULL, we must flush WAL before writing pages (true
+ * for pg_xact, false for multixact, pg_subtrans, pg_notify). group_lsn[]
+ * has lsn_groups_per_page entries per buffer slot, each containing the
+ * highest LSN known for a contiguous group of SLRU entries on that slot's
+ * page.
+ */
+ XLogRecPtr *group_lsn;
+ int lsn_groups_per_page;
+
+ /*----------
+ * We mark a page "most recently used" by setting
+ * page_lru_count[slotno] = ++cur_lru_count;
+ * The oldest page is therefore the one with the highest value of
+ * cur_lru_count - page_lru_count[slotno]
+ * The counts will eventually wrap around, but this calculation still
+ * works as long as no page's age exceeds INT_MAX counts.
+ *----------
+ */
+ int cur_lru_count;
+
+ /*
+ * latest_page_number is the page number of the current end of the log;
+ * this is not critical data, since we use it only to avoid swapping out
+ * the latest page.
+ */
+ int latest_page_number;
+
+ /* SLRU's index for statistics purposes (might not be unique) */
+ int slru_stats_idx;
+} SlruSharedData;
+
+typedef SlruSharedData *SlruShared;
+
+/*
+ * SlruCtlData is an unshared structure that points to the active information
+ * in shared memory.
+ */
+typedef struct SlruCtlData
+{
+ SlruShared shared;
+
+ /*
+ * This flag tells whether to fsync writes (true for pg_xact and multixact
+ * stuff, false for pg_subtrans and pg_notify).
+ */
+ bool do_fsync;
+
+ /*
+ * Decide whether a page is "older" for truncation and as a hint for
+ * evicting pages in LRU order. Return true if every entry of the first
+ * argument is older than every entry of the second argument. Note that
+ * !PagePrecedes(a,b) && !PagePrecedes(b,a) need not imply a==b; it also
+ * arises when some entries are older and some are not. For SLRUs using
+ * SimpleLruTruncate(), this must use modular arithmetic. (For others,
+ * the behavior of this callback has no functional implications.) Use
+ * SlruPagePrecedesUnitTests() in SLRUs meeting its criteria.
+ */
+ bool (*PagePrecedes) (int, int);
+
+ /*
+ * Dir is set during SimpleLruInit and does not change thereafter. Since
+ * it's always the same, it doesn't need to be in shared memory.
+ */
+ char Dir[64];
+} SlruCtlData;
+
+typedef SlruCtlData *SlruCtl;
+
+
+extern Size SimpleLruShmemSize(int nslots, int nlsns);
+extern void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
+ LWLock *ctllock, const char *subdir, int tranche_id);
+extern int SimpleLruZeroPage(SlruCtl ctl, int pageno);
+extern int SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok,
+ TransactionId xid);
+extern int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno,
+ TransactionId xid);
+extern void SimpleLruWritePage(SlruCtl ctl, int slotno);
+extern void SimpleLruFlush(SlruCtl ctl, bool allow_redirtied);
+#ifdef USE_ASSERT_CHECKING
+extern void SlruPagePrecedesUnitTests(SlruCtl ctl, int per_page);
+#else
+#define SlruPagePrecedesUnitTests(ctl, per_page) do {} while (0)
+#endif
+extern void SimpleLruTruncate(SlruCtl ctl, int cutoffPage);
+extern bool SimpleLruDoesPhysicalPageExist(SlruCtl ctl, int pageno);
+
+typedef bool (*SlruScanCallback) (SlruCtl ctl, char *filename, int segpage,
+ void *data);
+extern bool SlruScanDirectory(SlruCtl ctl, SlruScanCallback callback, void *data);
+extern void SlruDeleteSegment(SlruCtl ctl, int segno);
+
+/* SlruScanDirectory public callbacks */
+extern bool SlruScanDirCbReportPresence(SlruCtl ctl, char *filename,
+ int segpage, void *data);
+extern bool SlruScanDirCbDeleteAll(SlruCtl ctl, char *filename, int segpage,
+ void *data);
+
+#endif /* SLRU_H */
diff --git a/src/include/access/spgist.h b/src/include/access/spgist.h
new file mode 100644
index 0000000..852d1e2
--- /dev/null
+++ b/src/include/access/spgist.h
@@ -0,0 +1,224 @@
+/*-------------------------------------------------------------------------
+ *
+ * spgist.h
+ * Public header file for SP-GiST access method.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/spgist.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SPGIST_H
+#define SPGIST_H
+
+#include "access/amapi.h"
+#include "access/xlogreader.h"
+#include "lib/stringinfo.h"
+
+
+/* SPGiST opclass support function numbers */
+#define SPGIST_CONFIG_PROC 1
+#define SPGIST_CHOOSE_PROC 2
+#define SPGIST_PICKSPLIT_PROC 3
+#define SPGIST_INNER_CONSISTENT_PROC 4
+#define SPGIST_LEAF_CONSISTENT_PROC 5
+#define SPGIST_COMPRESS_PROC 6
+#define SPGIST_OPTIONS_PROC 7
+#define SPGISTNRequiredProc 5
+#define SPGISTNProc 7
+
+/*
+ * Argument structs for spg_config method
+ */
+typedef struct spgConfigIn
+{
+ Oid attType; /* Data type to be indexed */
+} spgConfigIn;
+
+typedef struct spgConfigOut
+{
+ Oid prefixType; /* Data type of inner-tuple prefixes */
+ Oid labelType; /* Data type of inner-tuple node labels */
+ Oid leafType; /* Data type of leaf-tuple values */
+ bool canReturnData; /* Opclass can reconstruct original data */
+ bool longValuesOK; /* Opclass can cope with values > 1 page */
+} spgConfigOut;
+
+/*
+ * Argument structs for spg_choose method
+ */
+typedef struct spgChooseIn
+{
+ Datum datum; /* original datum to be indexed */
+ Datum leafDatum; /* current datum to be stored at leaf */
+ int level; /* current level (counting from zero) */
+
+ /* Data from current inner tuple */
+ bool allTheSame; /* tuple is marked all-the-same? */
+ bool hasPrefix; /* tuple has a prefix? */
+ Datum prefixDatum; /* if so, the prefix value */
+ int nNodes; /* number of nodes in the inner tuple */
+ Datum *nodeLabels; /* node label values (NULL if none) */
+} spgChooseIn;
+
+typedef enum spgChooseResultType
+{
+ spgMatchNode = 1, /* descend into existing node */
+ spgAddNode, /* add a node to the inner tuple */
+ spgSplitTuple /* split inner tuple (change its prefix) */
+} spgChooseResultType;
+
+typedef struct spgChooseOut
+{
+ spgChooseResultType resultType; /* action code, see above */
+ union
+ {
+ struct /* results for spgMatchNode */
+ {
+ int nodeN; /* descend to this node (index from 0) */
+ int levelAdd; /* increment level by this much */
+ Datum restDatum; /* new leaf datum */
+ } matchNode;
+ struct /* results for spgAddNode */
+ {
+ Datum nodeLabel; /* new node's label */
+ int nodeN; /* where to insert it (index from 0) */
+ } addNode;
+ struct /* results for spgSplitTuple */
+ {
+ /* Info to form new upper-level inner tuple with one child tuple */
+ bool prefixHasPrefix; /* tuple should have a prefix? */
+ Datum prefixPrefixDatum; /* if so, its value */
+ int prefixNNodes; /* number of nodes */
+ Datum *prefixNodeLabels; /* their labels (or NULL for no
+ * labels) */
+ int childNodeN; /* which node gets child tuple */
+
+ /* Info to form new lower-level inner tuple with all old nodes */
+ bool postfixHasPrefix; /* tuple should have a prefix? */
+ Datum postfixPrefixDatum; /* if so, its value */
+ } splitTuple;
+ } result;
+} spgChooseOut;
+
+/*
+ * Argument structs for spg_picksplit method
+ */
+typedef struct spgPickSplitIn
+{
+ int nTuples; /* number of leaf tuples */
+ Datum *datums; /* their datums (array of length nTuples) */
+ int level; /* current level (counting from zero) */
+} spgPickSplitIn;
+
+typedef struct spgPickSplitOut
+{
+ bool hasPrefix; /* new inner tuple should have a prefix? */
+ Datum prefixDatum; /* if so, its value */
+
+ int nNodes; /* number of nodes for new inner tuple */
+ Datum *nodeLabels; /* their labels (or NULL for no labels) */
+
+ int *mapTuplesToNodes; /* node index for each leaf tuple */
+ Datum *leafTupleDatums; /* datum to store in each new leaf tuple */
+} spgPickSplitOut;
+
+/*
+ * Argument structs for spg_inner_consistent method
+ */
+typedef struct spgInnerConsistentIn
+{
+ ScanKey scankeys; /* array of operators and comparison values */
+ ScanKey orderbys; /* array of ordering operators and comparison
+ * values */
+ int nkeys; /* length of scankeys array */
+ int norderbys; /* length of orderbys array */
+
+ Datum reconstructedValue; /* value reconstructed at parent */
+ void *traversalValue; /* opclass-specific traverse value */
+ MemoryContext traversalMemoryContext; /* put new traverse values here */
+ int level; /* current level (counting from zero) */
+ bool returnData; /* original data must be returned? */
+
+ /* Data from current inner tuple */
+ bool allTheSame; /* tuple is marked all-the-same? */
+ bool hasPrefix; /* tuple has a prefix? */
+ Datum prefixDatum; /* if so, the prefix value */
+ int nNodes; /* number of nodes in the inner tuple */
+ Datum *nodeLabels; /* node label values (NULL if none) */
+} spgInnerConsistentIn;
+
+typedef struct spgInnerConsistentOut
+{
+ int nNodes; /* number of child nodes to be visited */
+ int *nodeNumbers; /* their indexes in the node array */
+ int *levelAdds; /* increment level by this much for each */
+ Datum *reconstructedValues; /* associated reconstructed values */
+ void **traversalValues; /* opclass-specific traverse values */
+ double **distances; /* associated distances */
+} spgInnerConsistentOut;
+
+/*
+ * Argument structs for spg_leaf_consistent method
+ */
+typedef struct spgLeafConsistentIn
+{
+ ScanKey scankeys; /* array of operators and comparison values */
+ ScanKey orderbys; /* array of ordering operators and comparison
+ * values */
+ int nkeys; /* length of scankeys array */
+ int norderbys; /* length of orderbys array */
+
+ Datum reconstructedValue; /* value reconstructed at parent */
+ void *traversalValue; /* opclass-specific traverse value */
+ int level; /* current level (counting from zero) */
+ bool returnData; /* original data must be returned? */
+
+ Datum leafDatum; /* datum in leaf tuple */
+} spgLeafConsistentIn;
+
+typedef struct spgLeafConsistentOut
+{
+ Datum leafValue; /* reconstructed original data, if any */
+ bool recheck; /* set true if operator must be rechecked */
+ bool recheckDistances; /* set true if distances must be rechecked */
+ double *distances; /* associated distances */
+} spgLeafConsistentOut;
+
+
+/* spgutils.c */
+extern bytea *spgoptions(Datum reloptions, bool validate);
+
+/* spginsert.c */
+extern IndexBuildResult *spgbuild(Relation heap, Relation index,
+ struct IndexInfo *indexInfo);
+extern void spgbuildempty(Relation index);
+extern bool spginsert(Relation index, Datum *values, bool *isnull,
+ ItemPointer ht_ctid, Relation heapRel,
+ IndexUniqueCheck checkUnique,
+ struct IndexInfo *indexInfo);
+
+/* spgscan.c */
+extern IndexScanDesc spgbeginscan(Relation rel, int keysz, int orderbysz);
+extern void spgendscan(IndexScanDesc scan);
+extern void spgrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
+ ScanKey orderbys, int norderbys);
+extern int64 spggetbitmap(IndexScanDesc scan, TIDBitmap *tbm);
+extern bool spggettuple(IndexScanDesc scan, ScanDirection dir);
+extern bool spgcanreturn(Relation index, int attno);
+
+/* spgvacuum.c */
+extern IndexBulkDeleteResult *spgbulkdelete(IndexVacuumInfo *info,
+ IndexBulkDeleteResult *stats,
+ IndexBulkDeleteCallback callback,
+ void *callback_state);
+extern IndexBulkDeleteResult *spgvacuumcleanup(IndexVacuumInfo *info,
+ IndexBulkDeleteResult *stats);
+
+/* spgvalidate.c */
+extern bool spgvalidate(Oid opclassoid);
+
+#endif /* SPGIST_H */
diff --git a/src/include/access/spgist_private.h b/src/include/access/spgist_private.h
new file mode 100644
index 0000000..00b98ec
--- /dev/null
+++ b/src/include/access/spgist_private.h
@@ -0,0 +1,494 @@
+/*-------------------------------------------------------------------------
+ *
+ * spgist_private.h
+ * Private declarations for SP-GiST access method.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/spgist_private.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SPGIST_PRIVATE_H
+#define SPGIST_PRIVATE_H
+
+#include "access/itup.h"
+#include "access/spgist.h"
+#include "catalog/pg_am_d.h"
+#include "nodes/tidbitmap.h"
+#include "storage/buf.h"
+#include "utils/geo_decls.h"
+#include "utils/relcache.h"
+
+
+typedef struct SpGistOptions
+{
+ int32 varlena_header_; /* varlena header (do not touch directly!) */
+ int fillfactor; /* page fill factor in percent (0..100) */
+} SpGistOptions;
+
+#define SpGistGetFillFactor(relation) \
+ (AssertMacro(relation->rd_rel->relkind == RELKIND_INDEX && \
+ relation->rd_rel->relam == SPGIST_AM_OID), \
+ (relation)->rd_options ? \
+ ((SpGistOptions *) (relation)->rd_options)->fillfactor : \
+ SPGIST_DEFAULT_FILLFACTOR)
+#define SpGistGetTargetPageFreeSpace(relation) \
+ (BLCKSZ * (100 - SpGistGetFillFactor(relation)) / 100)
+
+
+/* Page numbers of fixed-location pages */
+#define SPGIST_METAPAGE_BLKNO (0) /* metapage */
+#define SPGIST_ROOT_BLKNO (1) /* root for normal entries */
+#define SPGIST_NULL_BLKNO (2) /* root for null-value entries */
+#define SPGIST_LAST_FIXED_BLKNO SPGIST_NULL_BLKNO
+
+#define SpGistBlockIsRoot(blkno) \
+ ((blkno) == SPGIST_ROOT_BLKNO || (blkno) == SPGIST_NULL_BLKNO)
+#define SpGistBlockIsFixed(blkno) \
+ ((BlockNumber) (blkno) <= (BlockNumber) SPGIST_LAST_FIXED_BLKNO)
+
+/*
+ * Contents of page special space on SPGiST index pages
+ */
+typedef struct SpGistPageOpaqueData
+{
+ uint16 flags; /* see bit definitions below */
+ uint16 nRedirection; /* number of redirection tuples on page */
+ uint16 nPlaceholder; /* number of placeholder tuples on page */
+ /* note there's no count of either LIVE or DEAD tuples ... */
+ uint16 spgist_page_id; /* for identification of SP-GiST indexes */
+} SpGistPageOpaqueData;
+
+typedef SpGistPageOpaqueData *SpGistPageOpaque;
+
+/* Flag bits in page special space */
+#define SPGIST_META (1<<0)
+#define SPGIST_DELETED (1<<1) /* never set, but keep for backwards
+ * compatibility */
+#define SPGIST_LEAF (1<<2)
+#define SPGIST_NULLS (1<<3)
+
+#define SpGistPageGetOpaque(page) ((SpGistPageOpaque) PageGetSpecialPointer(page))
+#define SpGistPageIsMeta(page) (SpGistPageGetOpaque(page)->flags & SPGIST_META)
+#define SpGistPageIsDeleted(page) (SpGistPageGetOpaque(page)->flags & SPGIST_DELETED)
+#define SpGistPageIsLeaf(page) (SpGistPageGetOpaque(page)->flags & SPGIST_LEAF)
+#define SpGistPageStoresNulls(page) (SpGistPageGetOpaque(page)->flags & SPGIST_NULLS)
+
+/*
+ * The page ID is for the convenience of pg_filedump and similar utilities,
+ * which otherwise would have a hard time telling pages of different index
+ * types apart. It should be the last 2 bytes on the page. This is more or
+ * less "free" due to alignment considerations.
+ *
+ * See comments above GinPageOpaqueData.
+ */
+#define SPGIST_PAGE_ID 0xFF82
+
+/*
+ * Each backend keeps a cache of last-used page info in its index->rd_amcache
+ * area. This is initialized from, and occasionally written back to,
+ * shared storage in the index metapage.
+ */
+typedef struct SpGistLastUsedPage
+{
+ BlockNumber blkno; /* block number, or InvalidBlockNumber */
+ int freeSpace; /* page's free space (could be obsolete!) */
+} SpGistLastUsedPage;
+
+/* Note: indexes in cachedPage[] match flag assignments for SpGistGetBuffer */
+#define SPGIST_CACHED_PAGES 8
+
+typedef struct SpGistLUPCache
+{
+ SpGistLastUsedPage cachedPage[SPGIST_CACHED_PAGES];
+} SpGistLUPCache;
+
+/*
+ * metapage
+ */
+typedef struct SpGistMetaPageData
+{
+ uint32 magicNumber; /* for identity cross-check */
+ SpGistLUPCache lastUsedPages; /* shared storage of last-used info */
+} SpGistMetaPageData;
+
+#define SPGIST_MAGIC_NUMBER (0xBA0BABEE)
+
+#define SpGistPageGetMeta(p) \
+ ((SpGistMetaPageData *) PageGetContents(p))
+
+/*
+ * Private state of index AM. SpGistState is common to both insert and
+ * search code; SpGistScanOpaque is for searches only.
+ */
+
+/* Per-datatype info needed in SpGistState */
+typedef struct SpGistTypeDesc
+{
+ Oid type;
+ bool attbyval;
+ int16 attlen;
+} SpGistTypeDesc;
+
+typedef struct SpGistState
+{
+ spgConfigOut config; /* filled in by opclass config method */
+
+ SpGistTypeDesc attType; /* type of values to be indexed/restored */
+ SpGistTypeDesc attLeafType; /* type of leaf-tuple values */
+ SpGistTypeDesc attPrefixType; /* type of inner-tuple prefix values */
+ SpGistTypeDesc attLabelType; /* type of node label values */
+
+ char *deadTupleStorage; /* workspace for spgFormDeadTuple */
+
+ TransactionId myXid; /* XID to use when creating a redirect tuple */
+ bool isBuild; /* true if doing index build */
+} SpGistState;
+
+typedef struct SpGistSearchItem
+{
+ pairingheap_node phNode; /* pairing heap node */
+ Datum value; /* value reconstructed from parent or
+ * leafValue if heaptuple */
+ void *traversalValue; /* opclass-specific traverse value */
+ int level; /* level of items on this page */
+ ItemPointerData heapPtr; /* heap info, if heap tuple */
+ bool isNull; /* SearchItem is NULL item */
+ bool isLeaf; /* SearchItem is heap item */
+ bool recheck; /* qual recheck is needed */
+ bool recheckDistances; /* distance recheck is needed */
+
+ /* array with numberOfOrderBys entries */
+ double distances[FLEXIBLE_ARRAY_MEMBER];
+} SpGistSearchItem;
+
+#define SizeOfSpGistSearchItem(n_distances) \
+ (offsetof(SpGistSearchItem, distances) + sizeof(double) * (n_distances))
+
+/*
+ * Private state of an index scan
+ */
+typedef struct SpGistScanOpaqueData
+{
+ SpGistState state; /* see above */
+ pairingheap *scanQueue; /* queue of to be visited items */
+ MemoryContext tempCxt; /* short-lived memory context */
+ MemoryContext traversalCxt; /* single scan lifetime memory context */
+
+ /* Control flags showing whether to search nulls and/or non-nulls */
+ bool searchNulls; /* scan matches (all) null entries */
+ bool searchNonNulls; /* scan matches (some) non-null entries */
+
+ /* Index quals to be passed to opclass (null-related quals removed) */
+ int numberOfKeys; /* number of index qualifier conditions */
+ ScanKey keyData; /* array of index qualifier descriptors */
+ int numberOfOrderBys; /* number of ordering operators */
+ int numberOfNonNullOrderBys; /* number of ordering operators
+ * with non-NULL arguments */
+ ScanKey orderByData; /* array of ordering op descriptors */
+ Oid *orderByTypes; /* array of ordering op return types */
+ int *nonNullOrderByOffsets; /* array of offset of non-NULL
+ * ordering keys in the original array */
+ Oid indexCollation; /* collation of index column */
+
+ /* Opclass defined functions: */
+ FmgrInfo innerConsistentFn;
+ FmgrInfo leafConsistentFn;
+
+ /* Pre-allocated workspace arrays: */
+ double *zeroDistances;
+ double *infDistances;
+
+ /* These fields are only used in amgetbitmap scans: */
+ TIDBitmap *tbm; /* bitmap being filled */
+ int64 ntids; /* number of TIDs passed to bitmap */
+
+ /* These fields are only used in amgettuple scans: */
+ bool want_itup; /* are we reconstructing tuples? */
+ TupleDesc indexTupDesc; /* if so, tuple descriptor for them */
+ int nPtrs; /* number of TIDs found on current page */
+ int iPtr; /* index for scanning through same */
+ ItemPointerData heapPtrs[MaxIndexTuplesPerPage]; /* TIDs from cur page */
+ bool recheck[MaxIndexTuplesPerPage]; /* their recheck flags */
+ bool recheckDistances[MaxIndexTuplesPerPage]; /* distance recheck
+ * flags */
+ HeapTuple reconTups[MaxIndexTuplesPerPage]; /* reconstructed tuples */
+
+ /* distances (for recheck) */
+ IndexOrderByDistance *distances[MaxIndexTuplesPerPage];
+
+ /*
+ * Note: using MaxIndexTuplesPerPage above is a bit hokey since
+ * SpGistLeafTuples aren't exactly IndexTuples; however, they are larger,
+ * so this is safe.
+ */
+} SpGistScanOpaqueData;
+
+typedef SpGistScanOpaqueData *SpGistScanOpaque;
+
+/*
+ * This struct is what we actually keep in index->rd_amcache. It includes
+ * static configuration information as well as the lastUsedPages cache.
+ */
+typedef struct SpGistCache
+{
+ spgConfigOut config; /* filled in by opclass config method */
+
+ SpGistTypeDesc attType; /* type of values to be indexed/restored */
+ SpGistTypeDesc attLeafType; /* type of leaf-tuple values */
+ SpGistTypeDesc attPrefixType; /* type of inner-tuple prefix values */
+ SpGistTypeDesc attLabelType; /* type of node label values */
+
+ SpGistLUPCache lastUsedPages; /* local storage of last-used info */
+} SpGistCache;
+
+
+/*
+ * SPGiST tuple types. Note: inner, leaf, and dead tuple structs
+ * must have the same tupstate field in the same position! Real inner and
+ * leaf tuples always have tupstate = LIVE; if the state is something else,
+ * use the SpGistDeadTuple struct to inspect the tuple.
+ */
+
+/* values of tupstate (see README for more info) */
+#define SPGIST_LIVE 0 /* normal live tuple (either inner or leaf) */
+#define SPGIST_REDIRECT 1 /* temporary redirection placeholder */
+#define SPGIST_DEAD 2 /* dead, cannot be removed because of links */
+#define SPGIST_PLACEHOLDER 3 /* placeholder, used to preserve offsets */
+
+/*
+ * SPGiST inner tuple: list of "nodes" that subdivide a set of tuples
+ *
+ * Inner tuple layout:
+ * header/optional prefix/array of nodes, which are SpGistNodeTuples
+ *
+ * size and prefixSize must be multiples of MAXALIGN
+ */
+typedef struct SpGistInnerTupleData
+{
+ unsigned int tupstate:2, /* LIVE/REDIRECT/DEAD/PLACEHOLDER */
+ allTheSame:1, /* all nodes in tuple are equivalent */
+ nNodes:13, /* number of nodes within inner tuple */
+ prefixSize:16; /* size of prefix, or 0 if none */
+ uint16 size; /* total size of inner tuple */
+ /* On most machines there will be a couple of wasted bytes here */
+ /* prefix datum follows, then nodes */
+} SpGistInnerTupleData;
+
+typedef SpGistInnerTupleData *SpGistInnerTuple;
+
+/* these must match largest values that fit in bit fields declared above */
+#define SGITMAXNNODES 0x1FFF
+#define SGITMAXPREFIXSIZE 0xFFFF
+#define SGITMAXSIZE 0xFFFF
+
+#define SGITHDRSZ MAXALIGN(sizeof(SpGistInnerTupleData))
+#define _SGITDATA(x) (((char *) (x)) + SGITHDRSZ)
+#define SGITDATAPTR(x) ((x)->prefixSize ? _SGITDATA(x) : NULL)
+#define SGITDATUM(x, s) ((x)->prefixSize ? \
+ ((s)->attPrefixType.attbyval ? \
+ *(Datum *) _SGITDATA(x) : \
+ PointerGetDatum(_SGITDATA(x))) \
+ : (Datum) 0)
+#define SGITNODEPTR(x) ((SpGistNodeTuple) (_SGITDATA(x) + (x)->prefixSize))
+
+/* Macro for iterating through the nodes of an inner tuple */
+#define SGITITERATE(x, i, nt) \
+ for ((i) = 0, (nt) = SGITNODEPTR(x); \
+ (i) < (x)->nNodes; \
+ (i)++, (nt) = (SpGistNodeTuple) (((char *) (nt)) + IndexTupleSize(nt)))
+
+/*
+ * SPGiST node tuple: one node within an inner tuple
+ *
+ * Node tuples use the same header as ordinary Postgres IndexTuples, but
+ * we do not use a null bitmap, because we know there is only one column
+ * so the INDEX_NULL_MASK bit suffices. Also, pass-by-value datums are
+ * stored as a full Datum, the same convention as for inner tuple prefixes
+ * and leaf tuple datums.
+ */
+
+typedef IndexTupleData SpGistNodeTupleData;
+
+typedef SpGistNodeTupleData *SpGistNodeTuple;
+
+#define SGNTHDRSZ MAXALIGN(sizeof(SpGistNodeTupleData))
+#define SGNTDATAPTR(x) (((char *) (x)) + SGNTHDRSZ)
+#define SGNTDATUM(x, s) ((s)->attLabelType.attbyval ? \
+ *(Datum *) SGNTDATAPTR(x) : \
+ PointerGetDatum(SGNTDATAPTR(x)))
+
+/*
+ * SPGiST leaf tuple: carries a datum and a heap tuple TID
+ *
+ * In the simplest case, the datum is the same as the indexed value; but
+ * it could also be a suffix or some other sort of delta that permits
+ * reconstruction given knowledge of the prefix path traversed to get here.
+ *
+ * The size field is wider than could possibly be needed for an on-disk leaf
+ * tuple, but this allows us to form leaf tuples even when the datum is too
+ * wide to be stored immediately, and it costs nothing because of alignment
+ * considerations.
+ *
+ * Normally, nextOffset links to the next tuple belonging to the same parent
+ * node (which must be on the same page). But when the root page is a leaf
+ * page, we don't chain its tuples, so nextOffset is always 0 on the root.
+ *
+ * size must be a multiple of MAXALIGN; also, it must be at least SGDTSIZE
+ * so that the tuple can be converted to REDIRECT status later. (This
+ * restriction only adds bytes for the null-datum case, otherwise alignment
+ * restrictions force it anyway.)
+ *
+ * In a leaf tuple for a NULL indexed value, there's no useful datum value;
+ * however, the SGDTSIZE limit ensures that's there's a Datum word there
+ * anyway, so SGLTDATUM can be applied safely as long as you don't do
+ * anything with the result.
+ */
+typedef struct SpGistLeafTupleData
+{
+ unsigned int tupstate:2, /* LIVE/REDIRECT/DEAD/PLACEHOLDER */
+ size:30; /* large enough for any palloc'able value */
+ OffsetNumber nextOffset; /* next tuple in chain, or InvalidOffsetNumber */
+ ItemPointerData heapPtr; /* TID of represented heap tuple */
+ /* leaf datum follows */
+} SpGistLeafTupleData;
+
+typedef SpGistLeafTupleData *SpGistLeafTuple;
+
+#define SGLTHDRSZ MAXALIGN(sizeof(SpGistLeafTupleData))
+#define SGLTDATAPTR(x) (((char *) (x)) + SGLTHDRSZ)
+#define SGLTDATUM(x, s) ((s)->attLeafType.attbyval ? \
+ *(Datum *) SGLTDATAPTR(x) : \
+ PointerGetDatum(SGLTDATAPTR(x)))
+
+/*
+ * SPGiST dead tuple: declaration for examining non-live tuples
+ *
+ * The tupstate field of this struct must match those of regular inner and
+ * leaf tuples, and its size field must match a leaf tuple's.
+ * Also, the pointer field must be in the same place as a leaf tuple's heapPtr
+ * field, to satisfy some Asserts that we make when replacing a leaf tuple
+ * with a dead tuple.
+ * We don't use nextOffset, but it's needed to align the pointer field.
+ * pointer and xid are only valid when tupstate = REDIRECT.
+ */
+typedef struct SpGistDeadTupleData
+{
+ unsigned int tupstate:2, /* LIVE/REDIRECT/DEAD/PLACEHOLDER */
+ size:30;
+ OffsetNumber nextOffset; /* not used in dead tuples */
+ ItemPointerData pointer; /* redirection inside index */
+ TransactionId xid; /* ID of xact that inserted this tuple */
+} SpGistDeadTupleData;
+
+typedef SpGistDeadTupleData *SpGistDeadTuple;
+
+#define SGDTSIZE MAXALIGN(sizeof(SpGistDeadTupleData))
+
+/*
+ * Macros for doing free-space calculations. Note that when adding up the
+ * space needed for tuples, we always consider each tuple to need the tuple's
+ * size plus sizeof(ItemIdData) (for the line pointer). This works correctly
+ * so long as tuple sizes are always maxaligned.
+ */
+
+/* Page capacity after allowing for fixed header and special space */
+#define SPGIST_PAGE_CAPACITY \
+ MAXALIGN_DOWN(BLCKSZ - \
+ SizeOfPageHeaderData - \
+ MAXALIGN(sizeof(SpGistPageOpaqueData)))
+
+/*
+ * Compute free space on page, assuming that up to n placeholders can be
+ * recycled if present (n should be the number of tuples to be inserted)
+ */
+#define SpGistPageGetFreeSpace(p, n) \
+ (PageGetExactFreeSpace(p) + \
+ Min(SpGistPageGetOpaque(p)->nPlaceholder, n) * \
+ (SGDTSIZE + sizeof(ItemIdData)))
+
+/*
+ * XLOG stuff
+ */
+
+#define STORE_STATE(s, d) \
+ do { \
+ (d).myXid = (s)->myXid; \
+ (d).isBuild = (s)->isBuild; \
+ } while(0)
+
+/*
+ * The "flags" argument for SpGistGetBuffer should be either GBUF_LEAF to
+ * get a leaf page, or GBUF_INNER_PARITY(blockNumber) to get an inner
+ * page in the same triple-parity group as the specified block number.
+ * (Typically, this should be GBUF_INNER_PARITY(parentBlockNumber + 1)
+ * to follow the rule described in spgist/README.)
+ * In addition, GBUF_NULLS can be OR'd in to get a page for storage of
+ * null-valued tuples.
+ *
+ * Note: these flag values are used as indexes into lastUsedPages.
+ */
+#define GBUF_LEAF 0x03
+#define GBUF_INNER_PARITY(x) ((x) % 3)
+#define GBUF_NULLS 0x04
+
+#define GBUF_PARITY_MASK 0x03
+#define GBUF_REQ_LEAF(flags) (((flags) & GBUF_PARITY_MASK) == GBUF_LEAF)
+#define GBUF_REQ_NULLS(flags) ((flags) & GBUF_NULLS)
+
+/* spgutils.c */
+
+/* reloption parameters */
+#define SPGIST_MIN_FILLFACTOR 10
+#define SPGIST_DEFAULT_FILLFACTOR 80
+
+extern SpGistCache *spgGetCache(Relation index);
+extern void initSpGistState(SpGistState *state, Relation index);
+extern Buffer SpGistNewBuffer(Relation index);
+extern void SpGistUpdateMetaPage(Relation index);
+extern Buffer SpGistGetBuffer(Relation index, int flags,
+ int needSpace, bool *isNew);
+extern void SpGistSetLastUsedPage(Relation index, Buffer buffer);
+extern void SpGistInitPage(Page page, uint16 f);
+extern void SpGistInitBuffer(Buffer b, uint16 f);
+extern void SpGistInitMetapage(Page page);
+extern unsigned int SpGistGetTypeSize(SpGistTypeDesc *att, Datum datum);
+extern SpGistLeafTuple spgFormLeafTuple(SpGistState *state,
+ ItemPointer heapPtr,
+ Datum datum, bool isnull);
+extern SpGistNodeTuple spgFormNodeTuple(SpGistState *state,
+ Datum label, bool isnull);
+extern SpGistInnerTuple spgFormInnerTuple(SpGistState *state,
+ bool hasPrefix, Datum prefix,
+ int nNodes, SpGistNodeTuple *nodes);
+extern SpGistDeadTuple spgFormDeadTuple(SpGistState *state, int tupstate,
+ BlockNumber blkno, OffsetNumber offnum);
+extern Datum *spgExtractNodeLabels(SpGistState *state,
+ SpGistInnerTuple innerTuple);
+extern OffsetNumber SpGistPageAddNewItem(SpGistState *state, Page page,
+ Item item, Size size,
+ OffsetNumber *startOffset,
+ bool errorOK);
+extern bool spgproperty(Oid index_oid, int attno,
+ IndexAMProperty prop, const char *propname,
+ bool *res, bool *isnull);
+
+/* spgdoinsert.c */
+extern void spgUpdateNodeLink(SpGistInnerTuple tup, int nodeN,
+ BlockNumber blkno, OffsetNumber offset);
+extern void spgPageIndexMultiDelete(SpGistState *state, Page page,
+ OffsetNumber *itemnos, int nitems,
+ int firststate, int reststate,
+ BlockNumber blkno, OffsetNumber offnum);
+extern bool spgdoinsert(Relation index, SpGistState *state,
+ ItemPointer heapPtr, Datum datum, bool isnull);
+
+/* spgproc.c */
+extern double *spg_key_orderbys_distances(Datum key, bool isLeaf,
+ ScanKey orderbys, int norderbys);
+extern BOX *box_copy(BOX *orig);
+
+#endif /* SPGIST_PRIVATE_H */
diff --git a/src/include/access/spgxlog.h b/src/include/access/spgxlog.h
new file mode 100644
index 0000000..63d3c63
--- /dev/null
+++ b/src/include/access/spgxlog.h
@@ -0,0 +1,257 @@
+/*-------------------------------------------------------------------------
+ *
+ * spgxlog.h
+ * xlog declarations for SP-GiST access method.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/spgxlog.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SPGXLOG_H
+#define SPGXLOG_H
+
+#include "access/xlogreader.h"
+#include "lib/stringinfo.h"
+#include "storage/off.h"
+
+/* XLOG record types for SPGiST */
+ /* #define XLOG_SPGIST_CREATE_INDEX 0x00 */ /* not used anymore */
+#define XLOG_SPGIST_ADD_LEAF 0x10
+#define XLOG_SPGIST_MOVE_LEAFS 0x20
+#define XLOG_SPGIST_ADD_NODE 0x30
+#define XLOG_SPGIST_SPLIT_TUPLE 0x40
+#define XLOG_SPGIST_PICKSPLIT 0x50
+#define XLOG_SPGIST_VACUUM_LEAF 0x60
+#define XLOG_SPGIST_VACUUM_ROOT 0x70
+#define XLOG_SPGIST_VACUUM_REDIRECT 0x80
+
+/*
+ * Some redo functions need an SpGistState, although only a few of its fields
+ * need to be valid. spgxlogState carries the required info in xlog records.
+ * (See fillFakeState in spgxlog.c for more comments.)
+ */
+typedef struct spgxlogState
+{
+ TransactionId myXid;
+ bool isBuild;
+} spgxlogState;
+
+/*
+ * Backup Blk 0: destination page for leaf tuple
+ * Backup Blk 1: parent page (if any)
+ */
+typedef struct spgxlogAddLeaf
+{
+ bool newPage; /* init dest page? */
+ bool storesNulls; /* page is in the nulls tree? */
+ OffsetNumber offnumLeaf; /* offset where leaf tuple gets placed */
+ OffsetNumber offnumHeadLeaf; /* offset of head tuple in chain, if any */
+
+ OffsetNumber offnumParent; /* where the parent downlink is, if any */
+ uint16 nodeI;
+
+ /* new leaf tuple follows (unaligned!) */
+} spgxlogAddLeaf;
+
+/*
+ * Backup Blk 0: source leaf page
+ * Backup Blk 1: destination leaf page
+ * Backup Blk 2: parent page
+ */
+typedef struct spgxlogMoveLeafs
+{
+ uint16 nMoves; /* number of tuples moved from source page */
+ bool newPage; /* init dest page? */
+ bool replaceDead; /* are we replacing a DEAD source tuple? */
+ bool storesNulls; /* pages are in the nulls tree? */
+
+ /* where the parent downlink is */
+ OffsetNumber offnumParent;
+ uint16 nodeI;
+
+ spgxlogState stateSrc;
+
+ /*----------
+ * data follows:
+ * array of deleted tuple numbers, length nMoves
+ * array of inserted tuple numbers, length nMoves + 1 or 1
+ * list of leaf tuples, length nMoves + 1 or 1 (unaligned!)
+ *
+ * Note: if replaceDead is true then there is only one inserted tuple
+ * number and only one leaf tuple in the data, because we are not copying
+ * the dead tuple from the source
+ *----------
+ */
+ OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+} spgxlogMoveLeafs;
+
+#define SizeOfSpgxlogMoveLeafs offsetof(spgxlogMoveLeafs, offsets)
+
+/*
+ * Backup Blk 0: original page
+ * Backup Blk 1: where new tuple goes, if not same place
+ * Backup Blk 2: where parent downlink is, if updated and different from
+ * the old and new
+ */
+typedef struct spgxlogAddNode
+{
+ /*
+ * Offset of the original inner tuple, in the original page (on backup
+ * block 0).
+ */
+ OffsetNumber offnum;
+
+ /*
+ * Offset of the new tuple, on the new page (on backup block 1). Invalid,
+ * if we overwrote the old tuple in the original page).
+ */
+ OffsetNumber offnumNew;
+ bool newPage; /* init new page? */
+
+ /*----
+ * Where is the parent downlink? parentBlk indicates which page it's on,
+ * and offnumParent is the offset within the page. The possible values for
+ * parentBlk are:
+ *
+ * 0: parent == original page
+ * 1: parent == new page
+ * 2: parent == different page (blk ref 2)
+ * -1: parent not updated
+ *----
+ */
+ int8 parentBlk;
+ OffsetNumber offnumParent; /* offset within the parent page */
+
+ uint16 nodeI;
+
+ spgxlogState stateSrc;
+
+ /*
+ * updated inner tuple follows (unaligned!)
+ */
+} spgxlogAddNode;
+
+/*
+ * Backup Blk 0: where the prefix tuple goes
+ * Backup Blk 1: where the postfix tuple goes (if different page)
+ */
+typedef struct spgxlogSplitTuple
+{
+ /* where the prefix tuple goes */
+ OffsetNumber offnumPrefix;
+
+ /* where the postfix tuple goes */
+ OffsetNumber offnumPostfix;
+ bool newPage; /* need to init that page? */
+ bool postfixBlkSame; /* was postfix tuple put on same page as
+ * prefix? */
+
+ /*
+ * new prefix inner tuple follows, then new postfix inner tuple (both are
+ * unaligned!)
+ */
+} spgxlogSplitTuple;
+
+/*
+ * Buffer references in the rdata array are:
+ * Backup Blk 0: Src page (only if not root)
+ * Backup Blk 1: Dest page (if used)
+ * Backup Blk 2: Inner page
+ * Backup Blk 3: Parent page (if any, and different from Inner)
+ */
+typedef struct spgxlogPickSplit
+{
+ bool isRootSplit;
+
+ uint16 nDelete; /* n to delete from Src */
+ uint16 nInsert; /* n to insert on Src and/or Dest */
+ bool initSrc; /* re-init the Src page? */
+ bool initDest; /* re-init the Dest page? */
+
+ /* where to put new inner tuple */
+ OffsetNumber offnumInner;
+ bool initInner; /* re-init the Inner page? */
+
+ bool storesNulls; /* pages are in the nulls tree? */
+
+ /* where the parent downlink is, if any */
+ bool innerIsParent; /* is parent the same as inner page? */
+ OffsetNumber offnumParent;
+ uint16 nodeI;
+
+ spgxlogState stateSrc;
+
+ /*----------
+ * data follows:
+ * array of deleted tuple numbers, length nDelete
+ * array of inserted tuple numbers, length nInsert
+ * array of page selector bytes for inserted tuples, length nInsert
+ * new inner tuple (unaligned!)
+ * list of leaf tuples, length nInsert (unaligned!)
+ *----------
+ */
+ OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+} spgxlogPickSplit;
+
+#define SizeOfSpgxlogPickSplit offsetof(spgxlogPickSplit, offsets)
+
+typedef struct spgxlogVacuumLeaf
+{
+ uint16 nDead; /* number of tuples to become DEAD */
+ uint16 nPlaceholder; /* number of tuples to become PLACEHOLDER */
+ uint16 nMove; /* number of tuples to move */
+ uint16 nChain; /* number of tuples to re-chain */
+
+ spgxlogState stateSrc;
+
+ /*----------
+ * data follows:
+ * tuple numbers to become DEAD
+ * tuple numbers to become PLACEHOLDER
+ * tuple numbers to move from (and replace with PLACEHOLDER)
+ * tuple numbers to move to (replacing what is there)
+ * tuple numbers to update nextOffset links of
+ * tuple numbers to insert in nextOffset links
+ *----------
+ */
+ OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+} spgxlogVacuumLeaf;
+
+#define SizeOfSpgxlogVacuumLeaf offsetof(spgxlogVacuumLeaf, offsets)
+
+typedef struct spgxlogVacuumRoot
+{
+ /* vacuum a root page when it is also a leaf */
+ uint16 nDelete; /* number of tuples to delete */
+
+ spgxlogState stateSrc;
+
+ /* offsets of tuples to delete follow */
+ OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+} spgxlogVacuumRoot;
+
+#define SizeOfSpgxlogVacuumRoot offsetof(spgxlogVacuumRoot, offsets)
+
+typedef struct spgxlogVacuumRedirect
+{
+ uint16 nToPlaceholder; /* number of redirects to make placeholders */
+ OffsetNumber firstPlaceholder; /* first placeholder tuple to remove */
+ TransactionId newestRedirectXid; /* newest XID of removed redirects */
+
+ /* offsets of redirect tuples to make placeholders follow */
+ OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+} spgxlogVacuumRedirect;
+
+#define SizeOfSpgxlogVacuumRedirect offsetof(spgxlogVacuumRedirect, offsets)
+
+extern void spg_redo(XLogReaderState *record);
+extern void spg_desc(StringInfo buf, XLogReaderState *record);
+extern const char *spg_identify(uint8 info);
+extern void spg_xlog_startup(void);
+extern void spg_xlog_cleanup(void);
+extern void spg_mask(char *pagedata, BlockNumber blkno);
+
+#endif /* SPGXLOG_H */
diff --git a/src/include/access/stratnum.h b/src/include/access/stratnum.h
new file mode 100644
index 0000000..d280f7e
--- /dev/null
+++ b/src/include/access/stratnum.h
@@ -0,0 +1,83 @@
+/*-------------------------------------------------------------------------
+ *
+ * stratnum.h
+ * POSTGRES strategy number definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/stratnum.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef STRATNUM_H
+#define STRATNUM_H
+
+/*
+ * Strategy numbers identify the semantics that particular operators have
+ * with respect to particular operator classes. In some cases a strategy
+ * subtype (an OID) is used as further information.
+ */
+typedef uint16 StrategyNumber;
+
+#define InvalidStrategy ((StrategyNumber) 0)
+
+/*
+ * Strategy numbers for B-tree indexes.
+ */
+#define BTLessStrategyNumber 1
+#define BTLessEqualStrategyNumber 2
+#define BTEqualStrategyNumber 3
+#define BTGreaterEqualStrategyNumber 4
+#define BTGreaterStrategyNumber 5
+
+#define BTMaxStrategyNumber 5
+
+/*
+ * Strategy numbers for hash indexes. There's only one valid strategy for
+ * hashing: equality.
+ */
+#define HTEqualStrategyNumber 1
+
+#define HTMaxStrategyNumber 1
+
+/*
+ * Strategy numbers common to (some) GiST, SP-GiST and BRIN opclasses.
+ *
+ * The first few of these come from the R-Tree indexing method (hence the
+ * names); the others have been added over time as they have been needed.
+ */
+#define RTLeftStrategyNumber 1 /* for << */
+#define RTOverLeftStrategyNumber 2 /* for &< */
+#define RTOverlapStrategyNumber 3 /* for && */
+#define RTOverRightStrategyNumber 4 /* for &> */
+#define RTRightStrategyNumber 5 /* for >> */
+#define RTSameStrategyNumber 6 /* for ~= */
+#define RTContainsStrategyNumber 7 /* for @> */
+#define RTContainedByStrategyNumber 8 /* for <@ */
+#define RTOverBelowStrategyNumber 9 /* for &<| */
+#define RTBelowStrategyNumber 10 /* for <<| */
+#define RTAboveStrategyNumber 11 /* for |>> */
+#define RTOverAboveStrategyNumber 12 /* for |&> */
+#define RTOldContainsStrategyNumber 13 /* for old spelling of @> */
+#define RTOldContainedByStrategyNumber 14 /* for old spelling of <@ */
+#define RTKNNSearchStrategyNumber 15 /* for <-> (distance) */
+#define RTContainsElemStrategyNumber 16 /* for range types @> elem */
+#define RTAdjacentStrategyNumber 17 /* for -|- */
+#define RTEqualStrategyNumber 18 /* for = */
+#define RTNotEqualStrategyNumber 19 /* for != */
+#define RTLessStrategyNumber 20 /* for < */
+#define RTLessEqualStrategyNumber 21 /* for <= */
+#define RTGreaterStrategyNumber 22 /* for > */
+#define RTGreaterEqualStrategyNumber 23 /* for >= */
+#define RTSubStrategyNumber 24 /* for inet >> */
+#define RTSubEqualStrategyNumber 25 /* for inet <<= */
+#define RTSuperStrategyNumber 26 /* for inet << */
+#define RTSuperEqualStrategyNumber 27 /* for inet >>= */
+#define RTPrefixStrategyNumber 28 /* for text ^@ */
+
+#define RTMaxStrategyNumber 28
+
+
+#endif /* STRATNUM_H */
diff --git a/src/include/access/subtrans.h b/src/include/access/subtrans.h
new file mode 100644
index 0000000..2bab8e2
--- /dev/null
+++ b/src/include/access/subtrans.h
@@ -0,0 +1,30 @@
+/*
+ * subtrans.h
+ *
+ * PostgreSQL subtransaction-log manager
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/subtrans.h
+ */
+#ifndef SUBTRANS_H
+#define SUBTRANS_H
+
+/* Number of SLRU buffers to use for subtrans */
+#define NUM_SUBTRANS_BUFFERS 32
+
+extern void SubTransSetParent(TransactionId xid, TransactionId parent);
+extern TransactionId SubTransGetParent(TransactionId xid);
+extern TransactionId SubTransGetTopmostTransaction(TransactionId xid);
+
+extern Size SUBTRANSShmemSize(void);
+extern void SUBTRANSShmemInit(void);
+extern void BootStrapSUBTRANS(void);
+extern void StartupSUBTRANS(TransactionId oldestActiveXID);
+extern void ShutdownSUBTRANS(void);
+extern void CheckPointSUBTRANS(void);
+extern void ExtendSUBTRANS(TransactionId newestXact);
+extern void TruncateSUBTRANS(TransactionId oldestXact);
+
+#endif /* SUBTRANS_H */
diff --git a/src/include/access/sysattr.h b/src/include/access/sysattr.h
new file mode 100644
index 0000000..734976d
--- /dev/null
+++ b/src/include/access/sysattr.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ *
+ * sysattr.h
+ * POSTGRES system attribute definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/sysattr.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SYSATTR_H
+#define SYSATTR_H
+
+
+/*
+ * Attribute numbers for the system-defined attributes
+ */
+#define SelfItemPointerAttributeNumber (-1)
+#define MinTransactionIdAttributeNumber (-2)
+#define MinCommandIdAttributeNumber (-3)
+#define MaxTransactionIdAttributeNumber (-4)
+#define MaxCommandIdAttributeNumber (-5)
+#define TableOidAttributeNumber (-6)
+#define FirstLowInvalidHeapAttributeNumber (-7)
+
+#endif /* SYSATTR_H */
diff --git a/src/include/access/table.h b/src/include/access/table.h
new file mode 100644
index 0000000..cf0ef7b
--- /dev/null
+++ b/src/include/access/table.h
@@ -0,0 +1,27 @@
+/*-------------------------------------------------------------------------
+ *
+ * table.h
+ * Generic routines for table related code.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/table.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TABLE_H
+#define TABLE_H
+
+#include "nodes/primnodes.h"
+#include "storage/lockdefs.h"
+#include "utils/relcache.h"
+
+extern Relation table_open(Oid relationId, LOCKMODE lockmode);
+extern Relation table_openrv(const RangeVar *relation, LOCKMODE lockmode);
+extern Relation table_openrv_extended(const RangeVar *relation,
+ LOCKMODE lockmode, bool missing_ok);
+extern void table_close(Relation relation, LOCKMODE lockmode);
+
+#endif /* TABLE_H */
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
new file mode 100644
index 0000000..0d28f01
--- /dev/null
+++ b/src/include/access/tableam.h
@@ -0,0 +1,1825 @@
+/*-------------------------------------------------------------------------
+ *
+ * tableam.h
+ * POSTGRES table access method definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/tableam.h
+ *
+ * NOTES
+ * See tableam.sgml for higher level documentation.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TABLEAM_H
+#define TABLEAM_H
+
+#include "access/relscan.h"
+#include "access/sdir.h"
+#include "utils/guc.h"
+#include "utils/rel.h"
+#include "utils/snapshot.h"
+
+
+#define DEFAULT_TABLE_ACCESS_METHOD "heap"
+
+/* GUCs */
+extern char *default_table_access_method;
+extern bool synchronize_seqscans;
+
+
+struct BulkInsertStateData;
+struct IndexInfo;
+struct SampleScanState;
+struct TBMIterateResult;
+struct VacuumParams;
+struct ValidateIndexState;
+
+/*
+ * Bitmask values for the flags argument to the scan_begin callback.
+ */
+typedef enum ScanOptions
+{
+ /* one of SO_TYPE_* may be specified */
+ SO_TYPE_SEQSCAN = 1 << 0,
+ SO_TYPE_BITMAPSCAN = 1 << 1,
+ SO_TYPE_SAMPLESCAN = 1 << 2,
+ SO_TYPE_TIDSCAN = 1 << 3,
+ SO_TYPE_ANALYZE = 1 << 4,
+
+ /* several of SO_ALLOW_* may be specified */
+ /* allow or disallow use of access strategy */
+ SO_ALLOW_STRAT = 1 << 5,
+ /* report location to syncscan logic? */
+ SO_ALLOW_SYNC = 1 << 6,
+ /* verify visibility page-at-a-time? */
+ SO_ALLOW_PAGEMODE = 1 << 7,
+
+ /* unregister snapshot at scan end? */
+ SO_TEMP_SNAPSHOT = 1 << 8
+} ScanOptions;
+
+/*
+ * Result codes for table_{update,delete,lock_tuple}, and for visibility
+ * routines inside table AMs.
+ */
+typedef enum TM_Result
+{
+ /*
+ * Signals that the action succeeded (i.e. update/delete performed, lock
+ * was acquired)
+ */
+ TM_Ok,
+
+ /* The affected tuple wasn't visible to the relevant snapshot */
+ TM_Invisible,
+
+ /* The affected tuple was already modified by the calling backend */
+ TM_SelfModified,
+
+ /*
+ * The affected tuple was updated by another transaction. This includes
+ * the case where tuple was moved to another partition.
+ */
+ TM_Updated,
+
+ /* The affected tuple was deleted by another transaction */
+ TM_Deleted,
+
+ /*
+ * The affected tuple is currently being modified by another session. This
+ * will only be returned if table_(update/delete/lock_tuple) are
+ * instructed not to wait.
+ */
+ TM_BeingModified,
+
+ /* lock couldn't be acquired, action skipped. Only used by lock_tuple */
+ TM_WouldBlock
+} TM_Result;
+
+/*
+ * When table_tuple_update, table_tuple_delete, or table_tuple_lock fail
+ * because the target tuple is already outdated, they fill in this struct to
+ * provide information to the caller about what happened.
+ *
+ * ctid is the target's ctid link: it is the same as the target's TID if the
+ * target was deleted, or the location of the replacement tuple if the target
+ * was updated.
+ *
+ * xmax is the outdating transaction's XID. If the caller wants to visit the
+ * replacement tuple, it must check that this matches before believing the
+ * replacement is really a match.
+ *
+ * cmax is the outdating command's CID, but only when the failure code is
+ * TM_SelfModified (i.e., something in the current transaction outdated the
+ * tuple); otherwise cmax is zero. (We make this restriction because
+ * HeapTupleHeaderGetCmax doesn't work for tuples outdated in other
+ * transactions.)
+ */
+typedef struct TM_FailureData
+{
+ ItemPointerData ctid;
+ TransactionId xmax;
+ CommandId cmax;
+ bool traversed;
+} TM_FailureData;
+
+/* "options" flag bits for table_tuple_insert */
+/* TABLE_INSERT_SKIP_WAL was 0x0001; RelationNeedsWAL() now governs */
+#define TABLE_INSERT_SKIP_FSM 0x0002
+#define TABLE_INSERT_FROZEN 0x0004
+#define TABLE_INSERT_NO_LOGICAL 0x0008
+
+/* flag bits for table_tuple_lock */
+/* Follow tuples whose update is in progress if lock modes don't conflict */
+#define TUPLE_LOCK_FLAG_LOCK_UPDATE_IN_PROGRESS (1 << 0)
+/* Follow update chain and lock latest version of tuple */
+#define TUPLE_LOCK_FLAG_FIND_LAST_VERSION (1 << 1)
+
+
+/* Typedef for callback function for table_index_build_scan */
+typedef void (*IndexBuildCallback) (Relation index,
+ ItemPointer tid,
+ Datum *values,
+ bool *isnull,
+ bool tupleIsAlive,
+ void *state);
+
+/*
+ * API struct for a table AM. Note this must be allocated in a
+ * server-lifetime manner, typically as a static const struct, which then gets
+ * returned by FormData_pg_am.amhandler.
+ *
+ * In most cases it's not appropriate to call the callbacks directly, use the
+ * table_* wrapper functions instead.
+ *
+ * GetTableAmRoutine() asserts that required callbacks are filled in, remember
+ * to update when adding a callback.
+ */
+typedef struct TableAmRoutine
+{
+ /* this must be set to T_TableAmRoutine */
+ NodeTag type;
+
+
+ /* ------------------------------------------------------------------------
+ * Slot related callbacks.
+ * ------------------------------------------------------------------------
+ */
+
+ /*
+ * Return slot implementation suitable for storing a tuple of this AM.
+ */
+ const TupleTableSlotOps *(*slot_callbacks) (Relation rel);
+
+
+ /* ------------------------------------------------------------------------
+ * Table scan callbacks.
+ * ------------------------------------------------------------------------
+ */
+
+ /*
+ * Start a scan of `rel`. The callback has to return a TableScanDesc,
+ * which will typically be embedded in a larger, AM specific, struct.
+ *
+ * If nkeys != 0, the results need to be filtered by those scan keys.
+ *
+ * pscan, if not NULL, will have already been initialized with
+ * parallelscan_initialize(), and has to be for the same relation. Will
+ * only be set coming from table_beginscan_parallel().
+ *
+ * `flags` is a bitmask indicating the type of scan (ScanOptions's
+ * SO_TYPE_*, currently only one may be specified), options controlling
+ * the scan's behaviour (ScanOptions's SO_ALLOW_*, several may be
+ * specified, an AM may ignore unsupported ones) and whether the snapshot
+ * needs to be deallocated at scan_end (ScanOptions's SO_TEMP_SNAPSHOT).
+ */
+ TableScanDesc (*scan_begin) (Relation rel,
+ Snapshot snapshot,
+ int nkeys, struct ScanKeyData *key,
+ ParallelTableScanDesc pscan,
+ uint32 flags);
+
+ /*
+ * Release resources and deallocate scan. If TableScanDesc.temp_snap,
+ * TableScanDesc.rs_snapshot needs to be unregistered.
+ */
+ void (*scan_end) (TableScanDesc scan);
+
+ /*
+ * Restart relation scan. If set_params is set to true, allow_{strat,
+ * sync, pagemode} (see scan_begin) changes should be taken into account.
+ */
+ void (*scan_rescan) (TableScanDesc scan, struct ScanKeyData *key,
+ bool set_params, bool allow_strat,
+ bool allow_sync, bool allow_pagemode);
+
+ /*
+ * Return next tuple from `scan`, store in slot.
+ */
+ bool (*scan_getnextslot) (TableScanDesc scan,
+ ScanDirection direction,
+ TupleTableSlot *slot);
+
+
+ /* ------------------------------------------------------------------------
+ * Parallel table scan related functions.
+ * ------------------------------------------------------------------------
+ */
+
+ /*
+ * Estimate the size of shared memory needed for a parallel scan of this
+ * relation. The snapshot does not need to be accounted for.
+ */
+ Size (*parallelscan_estimate) (Relation rel);
+
+ /*
+ * Initialize ParallelTableScanDesc for a parallel scan of this relation.
+ * `pscan` will be sized according to parallelscan_estimate() for the same
+ * relation.
+ */
+ Size (*parallelscan_initialize) (Relation rel,
+ ParallelTableScanDesc pscan);
+
+ /*
+ * Reinitialize `pscan` for a new scan. `rel` will be the same relation as
+ * when `pscan` was initialized by parallelscan_initialize.
+ */
+ void (*parallelscan_reinitialize) (Relation rel,
+ ParallelTableScanDesc pscan);
+
+
+ /* ------------------------------------------------------------------------
+ * Index Scan Callbacks
+ * ------------------------------------------------------------------------
+ */
+
+ /*
+ * Prepare to fetch tuples from the relation, as needed when fetching
+ * tuples for an index scan. The callback has to return an
+ * IndexFetchTableData, which the AM will typically embed in a larger
+ * structure with additional information.
+ *
+ * Tuples for an index scan can then be fetched via index_fetch_tuple.
+ */
+ struct IndexFetchTableData *(*index_fetch_begin) (Relation rel);
+
+ /*
+ * Reset index fetch. Typically this will release cross index fetch
+ * resources held in IndexFetchTableData.
+ */
+ void (*index_fetch_reset) (struct IndexFetchTableData *data);
+
+ /*
+ * Release resources and deallocate index fetch.
+ */
+ void (*index_fetch_end) (struct IndexFetchTableData *data);
+
+ /*
+ * Fetch tuple at `tid` into `slot`, after doing a visibility test
+ * according to `snapshot`. If a tuple was found and passed the visibility
+ * test, return true, false otherwise.
+ *
+ * Note that AMs that do not necessarily update indexes when indexed
+ * columns do not change, need to return the current/correct version of
+ * the tuple that is visible to the snapshot, even if the tid points to an
+ * older version of the tuple.
+ *
+ * *call_again is false on the first call to index_fetch_tuple for a tid.
+ * If there potentially is another tuple matching the tid, *call_again
+ * needs to be set to true by index_fetch_tuple, signaling to the caller
+ * that index_fetch_tuple should be called again for the same tid.
+ *
+ * *all_dead, if all_dead is not NULL, should be set to true by
+ * index_fetch_tuple iff it is guaranteed that no backend needs to see
+ * that tuple. Index AMs can use that to avoid returning that tid in
+ * future searches.
+ */
+ bool (*index_fetch_tuple) (struct IndexFetchTableData *scan,
+ ItemPointer tid,
+ Snapshot snapshot,
+ TupleTableSlot *slot,
+ bool *call_again, bool *all_dead);
+
+
+ /* ------------------------------------------------------------------------
+ * Callbacks for non-modifying operations on individual tuples
+ * ------------------------------------------------------------------------
+ */
+
+ /*
+ * Fetch tuple at `tid` into `slot`, after doing a visibility test
+ * according to `snapshot`. If a tuple was found and passed the visibility
+ * test, returns true, false otherwise.
+ */
+ bool (*tuple_fetch_row_version) (Relation rel,
+ ItemPointer tid,
+ Snapshot snapshot,
+ TupleTableSlot *slot);
+
+ /*
+ * Is tid valid for a scan of this relation.
+ */
+ bool (*tuple_tid_valid) (TableScanDesc scan,
+ ItemPointer tid);
+
+ /*
+ * Return the latest version of the tuple at `tid`, by updating `tid` to
+ * point at the newest version.
+ */
+ void (*tuple_get_latest_tid) (TableScanDesc scan,
+ ItemPointer tid);
+
+ /*
+ * Does the tuple in `slot` satisfy `snapshot`? The slot needs to be of
+ * the appropriate type for the AM.
+ */
+ bool (*tuple_satisfies_snapshot) (Relation rel,
+ TupleTableSlot *slot,
+ Snapshot snapshot);
+
+ /* see table_compute_xid_horizon_for_tuples() */
+ TransactionId (*compute_xid_horizon_for_tuples) (Relation rel,
+ ItemPointerData *items,
+ int nitems);
+
+
+ /* ------------------------------------------------------------------------
+ * Manipulations of physical tuples.
+ * ------------------------------------------------------------------------
+ */
+
+ /* see table_tuple_insert() for reference about parameters */
+ void (*tuple_insert) (Relation rel, TupleTableSlot *slot,
+ CommandId cid, int options,
+ struct BulkInsertStateData *bistate);
+
+ /* see table_tuple_insert_speculative() for reference about parameters */
+ void (*tuple_insert_speculative) (Relation rel,
+ TupleTableSlot *slot,
+ CommandId cid,
+ int options,
+ struct BulkInsertStateData *bistate,
+ uint32 specToken);
+
+ /* see table_tuple_complete_speculative() for reference about parameters */
+ void (*tuple_complete_speculative) (Relation rel,
+ TupleTableSlot *slot,
+ uint32 specToken,
+ bool succeeded);
+
+ /* see table_multi_insert() for reference about parameters */
+ void (*multi_insert) (Relation rel, TupleTableSlot **slots, int nslots,
+ CommandId cid, int options, struct BulkInsertStateData *bistate);
+
+ /* see table_tuple_delete() for reference about parameters */
+ TM_Result (*tuple_delete) (Relation rel,
+ ItemPointer tid,
+ CommandId cid,
+ Snapshot snapshot,
+ Snapshot crosscheck,
+ bool wait,
+ TM_FailureData *tmfd,
+ bool changingPart);
+
+ /* see table_tuple_update() for reference about parameters */
+ TM_Result (*tuple_update) (Relation rel,
+ ItemPointer otid,
+ TupleTableSlot *slot,
+ CommandId cid,
+ Snapshot snapshot,
+ Snapshot crosscheck,
+ bool wait,
+ TM_FailureData *tmfd,
+ LockTupleMode *lockmode,
+ bool *update_indexes);
+
+ /* see table_tuple_lock() for reference about parameters */
+ TM_Result (*tuple_lock) (Relation rel,
+ ItemPointer tid,
+ Snapshot snapshot,
+ TupleTableSlot *slot,
+ CommandId cid,
+ LockTupleMode mode,
+ LockWaitPolicy wait_policy,
+ uint8 flags,
+ TM_FailureData *tmfd);
+
+ /*
+ * Perform operations necessary to complete insertions made via
+ * tuple_insert and multi_insert with a BulkInsertState specified. In-tree
+ * access methods ceased to use this.
+ *
+ * Typically callers of tuple_insert and multi_insert will just pass all
+ * the flags that apply to them, and each AM has to decide which of them
+ * make sense for it, and then only take actions in finish_bulk_insert for
+ * those flags, and ignore others.
+ *
+ * Optional callback.
+ */
+ void (*finish_bulk_insert) (Relation rel, int options);
+
+
+ /* ------------------------------------------------------------------------
+ * DDL related functionality.
+ * ------------------------------------------------------------------------
+ */
+
+ /*
+ * This callback needs to create a new relation filenode for `rel`, with
+ * appropriate durability behaviour for `persistence`.
+ *
+ * Note that only the subset of the relcache filled by
+ * RelationBuildLocalRelation() can be relied upon and that the relation's
+ * catalog entries will either not yet exist (new relation), or will still
+ * reference the old relfilenode.
+ *
+ * As output *freezeXid, *minmulti must be set to the values appropriate
+ * for pg_class.{relfrozenxid, relminmxid}. For AMs that don't need those
+ * fields to be filled they can be set to InvalidTransactionId and
+ * InvalidMultiXactId, respectively.
+ *
+ * See also table_relation_set_new_filenode().
+ */
+ void (*relation_set_new_filenode) (Relation rel,
+ const RelFileNode *newrnode,
+ char persistence,
+ TransactionId *freezeXid,
+ MultiXactId *minmulti);
+
+ /*
+ * This callback needs to remove all contents from `rel`'s current
+ * relfilenode. No provisions for transactional behaviour need to be made.
+ * Often this can be implemented by truncating the underlying storage to
+ * its minimal size.
+ *
+ * See also table_relation_nontransactional_truncate().
+ */
+ void (*relation_nontransactional_truncate) (Relation rel);
+
+ /*
+ * See table_relation_copy_data().
+ *
+ * This can typically be implemented by directly copying the underlying
+ * storage, unless it contains references to the tablespace internally.
+ */
+ void (*relation_copy_data) (Relation rel,
+ const RelFileNode *newrnode);
+
+ /* See table_relation_copy_for_cluster() */
+ void (*relation_copy_for_cluster) (Relation NewTable,
+ Relation OldTable,
+ Relation OldIndex,
+ bool use_sort,
+ TransactionId OldestXmin,
+ TransactionId *xid_cutoff,
+ MultiXactId *multi_cutoff,
+ double *num_tuples,
+ double *tups_vacuumed,
+ double *tups_recently_dead);
+
+ /*
+ * React to VACUUM command on the relation. The VACUUM can be triggered by
+ * a user or by autovacuum. The specific actions performed by the AM will
+ * depend heavily on the individual AM.
+ *
+ * On entry a transaction is already established, and the relation is
+ * locked with a ShareUpdateExclusive lock.
+ *
+ * Note that neither VACUUM FULL (and CLUSTER), nor ANALYZE go through
+ * this routine, even if (for ANALYZE) it is part of the same VACUUM
+ * command.
+ *
+ * There probably, in the future, needs to be a separate callback to
+ * integrate with autovacuum's scheduling.
+ */
+ void (*relation_vacuum) (Relation onerel,
+ struct VacuumParams *params,
+ BufferAccessStrategy bstrategy);
+
+ /*
+ * Prepare to analyze block `blockno` of `scan`. The scan has been started
+ * with table_beginscan_analyze(). See also
+ * table_scan_analyze_next_block().
+ *
+ * The callback may acquire resources like locks that are held until
+ * table_scan_analyze_next_tuple() returns false. It e.g. can make sense
+ * to hold a lock until all tuples on a block have been analyzed by
+ * scan_analyze_next_tuple.
+ *
+ * The callback can return false if the block is not suitable for
+ * sampling, e.g. because it's a metapage that could never contain tuples.
+ *
+ * XXX: This obviously is primarily suited for block-based AMs. It's not
+ * clear what a good interface for non block based AMs would be, so there
+ * isn't one yet.
+ */
+ bool (*scan_analyze_next_block) (TableScanDesc scan,
+ BlockNumber blockno,
+ BufferAccessStrategy bstrategy);
+
+ /*
+ * See table_scan_analyze_next_tuple().
+ *
+ * Not every AM might have a meaningful concept of dead rows, in which
+ * case it's OK to not increment *deadrows - but note that that may
+ * influence autovacuum scheduling (see comment for relation_vacuum
+ * callback).
+ */
+ bool (*scan_analyze_next_tuple) (TableScanDesc scan,
+ TransactionId OldestXmin,
+ double *liverows,
+ double *deadrows,
+ TupleTableSlot *slot);
+
+ /* see table_index_build_range_scan for reference about parameters */
+ double (*index_build_range_scan) (Relation table_rel,
+ Relation index_rel,
+ struct IndexInfo *index_info,
+ bool allow_sync,
+ bool anyvisible,
+ bool progress,
+ BlockNumber start_blockno,
+ BlockNumber numblocks,
+ IndexBuildCallback callback,
+ void *callback_state,
+ TableScanDesc scan);
+
+ /* see table_index_validate_scan for reference about parameters */
+ void (*index_validate_scan) (Relation table_rel,
+ Relation index_rel,
+ struct IndexInfo *index_info,
+ Snapshot snapshot,
+ struct ValidateIndexState *state);
+
+
+ /* ------------------------------------------------------------------------
+ * Miscellaneous functions.
+ * ------------------------------------------------------------------------
+ */
+
+ /*
+ * See table_relation_size().
+ *
+ * Note that currently a few callers use the MAIN_FORKNUM size to figure
+ * out the range of potentially interesting blocks (brin, analyze). It's
+ * probable that we'll need to revise the interface for those at some
+ * point.
+ */
+ uint64 (*relation_size) (Relation rel, ForkNumber forkNumber);
+
+
+ /*
+ * This callback should return true if the relation requires a TOAST table
+ * and false if it does not. It may wish to examine the relation's tuple
+ * descriptor before making a decision, but if it uses some other method
+ * of storing large values (or if it does not support them) it can simply
+ * return false.
+ */
+ bool (*relation_needs_toast_table) (Relation rel);
+
+ /*
+ * This callback should return the OID of the table AM that implements
+ * TOAST tables for this AM. If the relation_needs_toast_table callback
+ * always returns false, this callback is not required.
+ */
+ Oid (*relation_toast_am) (Relation rel);
+
+ /*
+ * This callback is invoked when detoasting a value stored in a toast
+ * table implemented by this AM. See table_relation_fetch_toast_slice()
+ * for more details.
+ */
+ void (*relation_fetch_toast_slice) (Relation toastrel, Oid valueid,
+ int32 attrsize,
+ int32 sliceoffset,
+ int32 slicelength,
+ struct varlena *result);
+
+
+ /* ------------------------------------------------------------------------
+ * Planner related functions.
+ * ------------------------------------------------------------------------
+ */
+
+ /*
+ * See table_relation_estimate_size().
+ *
+ * While block oriented, it shouldn't be too hard for an AM that doesn't
+ * internally use blocks to convert into a usable representation.
+ *
+ * This differs from the relation_size callback by returning size
+ * estimates (both relation size and tuple count) for planning purposes,
+ * rather than returning a currently correct estimate.
+ */
+ void (*relation_estimate_size) (Relation rel, int32 *attr_widths,
+ BlockNumber *pages, double *tuples,
+ double *allvisfrac);
+
+
+ /* ------------------------------------------------------------------------
+ * Executor related functions.
+ * ------------------------------------------------------------------------
+ */
+
+ /*
+ * Prepare to fetch / check / return tuples from `tbmres->blockno` as part
+ * of a bitmap table scan. `scan` was started via table_beginscan_bm().
+ * Return false if there are no tuples to be found on the page, true
+ * otherwise.
+ *
+ * This will typically read and pin the target block, and do the necessary
+ * work to allow scan_bitmap_next_tuple() to return tuples (e.g. it might
+ * make sense to perform tuple visibility checks at this time). For some
+ * AMs it will make more sense to do all the work referencing `tbmres`
+ * contents here, for others it might be better to defer more work to
+ * scan_bitmap_next_tuple.
+ *
+ * If `tbmres->blockno` is -1, this is a lossy scan and all visible tuples
+ * on the page have to be returned, otherwise the tuples at offsets in
+ * `tbmres->offsets` need to be returned.
+ *
+ * XXX: Currently this may only be implemented if the AM uses md.c as its
+ * storage manager, and uses ItemPointer->ip_blkid in a manner that maps
+ * blockids directly to the underlying storage. nodeBitmapHeapscan.c
+ * performs prefetching directly using that interface. This probably
+ * needs to be rectified at a later point.
+ *
+ * XXX: Currently this may only be implemented if the AM uses the
+ * visibilitymap, as nodeBitmapHeapscan.c unconditionally accesses it to
+ * perform prefetching. This probably needs to be rectified at a later
+ * point.
+ *
+ * Optional callback, but either both scan_bitmap_next_block and
+ * scan_bitmap_next_tuple need to exist, or neither.
+ */
+ bool (*scan_bitmap_next_block) (TableScanDesc scan,
+ struct TBMIterateResult *tbmres);
+
+ /*
+ * Fetch the next tuple of a bitmap table scan into `slot` and return true
+ * if a visible tuple was found, false otherwise.
+ *
+ * For some AMs it will make more sense to do all the work referencing
+ * `tbmres` contents in scan_bitmap_next_block, for others it might be
+ * better to defer more work to this callback.
+ *
+ * Optional callback, but either both scan_bitmap_next_block and
+ * scan_bitmap_next_tuple need to exist, or neither.
+ */
+ bool (*scan_bitmap_next_tuple) (TableScanDesc scan,
+ struct TBMIterateResult *tbmres,
+ TupleTableSlot *slot);
+
+ /*
+ * Prepare to fetch tuples from the next block in a sample scan. Return
+ * false if the sample scan is finished, true otherwise. `scan` was
+ * started via table_beginscan_sampling().
+ *
+ * Typically this will first determine the target block by calling the
+ * TsmRoutine's NextSampleBlock() callback if not NULL, or alternatively
+ * perform a sequential scan over all blocks. The determined block is
+ * then typically read and pinned.
+ *
+ * As the TsmRoutine interface is block based, a block needs to be passed
+ * to NextSampleBlock(). If that's not appropriate for an AM, it
+ * internally needs to perform mapping between the internal and a block
+ * based representation.
+ *
+ * Note that it's not acceptable to hold deadlock prone resources such as
+ * lwlocks until scan_sample_next_tuple() has exhausted the tuples on the
+ * block - the tuple is likely to be returned to an upper query node, and
+ * the next call could be off a long while. Holding buffer pins and such
+ * is obviously OK.
+ *
+ * Currently it is required to implement this interface, as there's no
+ * alternative way (contrary e.g. to bitmap scans) to implement sample
+ * scans. If infeasible to implement, the AM may raise an error.
+ */
+ bool (*scan_sample_next_block) (TableScanDesc scan,
+ struct SampleScanState *scanstate);
+
+ /*
+ * This callback, only called after scan_sample_next_block has returned
+ * true, should determine the next tuple to be returned from the selected
+ * block using the TsmRoutine's NextSampleTuple() callback.
+ *
+ * The callback needs to perform visibility checks, and only return
+ * visible tuples. That obviously can mean calling NextSampleTuple()
+ * multiple times.
+ *
+ * The TsmRoutine interface assumes that there's a maximum offset on a
+ * given page, so if that doesn't apply to an AM, it needs to emulate that
+ * assumption somehow.
+ */
+ bool (*scan_sample_next_tuple) (TableScanDesc scan,
+ struct SampleScanState *scanstate,
+ TupleTableSlot *slot);
+
+} TableAmRoutine;
+
+
+/* ----------------------------------------------------------------------------
+ * Slot functions.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ * Returns slot callbacks suitable for holding tuples of the appropriate type
+ * for the relation. Works for tables, views, foreign tables and partitioned
+ * tables.
+ */
+extern const TupleTableSlotOps *table_slot_callbacks(Relation rel);
+
+/*
+ * Returns slot using the callbacks returned by table_slot_callbacks(), and
+ * registers it on *reglist.
+ */
+extern TupleTableSlot *table_slot_create(Relation rel, List **reglist);
+
+
+/* ----------------------------------------------------------------------------
+ * Table scan functions.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ * Start a scan of `rel`. Returned tuples pass a visibility test of
+ * `snapshot`, and if nkeys != 0, the results are filtered by those scan keys.
+ */
+static inline TableScanDesc
+table_beginscan(Relation rel, Snapshot snapshot,
+ int nkeys, struct ScanKeyData *key)
+{
+ uint32 flags = SO_TYPE_SEQSCAN |
+ SO_ALLOW_STRAT | SO_ALLOW_SYNC | SO_ALLOW_PAGEMODE;
+
+ return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+}
+
+/*
+ * Like table_beginscan(), but for scanning catalog. It'll automatically use a
+ * snapshot appropriate for scanning catalog relations.
+ */
+extern TableScanDesc table_beginscan_catalog(Relation rel, int nkeys,
+ struct ScanKeyData *key);
+
+/*
+ * Like table_beginscan(), but table_beginscan_strat() offers an extended API
+ * that lets the caller control whether a nondefault buffer access strategy
+ * can be used, and whether syncscan can be chosen (possibly resulting in the
+ * scan not starting from block zero). Both of these default to true with
+ * plain table_beginscan.
+ */
+static inline TableScanDesc
+table_beginscan_strat(Relation rel, Snapshot snapshot,
+ int nkeys, struct ScanKeyData *key,
+ bool allow_strat, bool allow_sync)
+{
+ uint32 flags = SO_TYPE_SEQSCAN | SO_ALLOW_PAGEMODE;
+
+ if (allow_strat)
+ flags |= SO_ALLOW_STRAT;
+ if (allow_sync)
+ flags |= SO_ALLOW_SYNC;
+
+ return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+}
+
+/*
+ * table_beginscan_bm is an alternative entry point for setting up a
+ * TableScanDesc for a bitmap heap scan. Although that scan technology is
+ * really quite unlike a standard seqscan, there is just enough commonality to
+ * make it worth using the same data structure.
+ */
+static inline TableScanDesc
+table_beginscan_bm(Relation rel, Snapshot snapshot,
+ int nkeys, struct ScanKeyData *key)
+{
+ uint32 flags = SO_TYPE_BITMAPSCAN | SO_ALLOW_PAGEMODE;
+
+ return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+}
+
+/*
+ * table_beginscan_sampling is an alternative entry point for setting up a
+ * TableScanDesc for a TABLESAMPLE scan. As with bitmap scans, it's worth
+ * using the same data structure although the behavior is rather different.
+ * In addition to the options offered by table_beginscan_strat, this call
+ * also allows control of whether page-mode visibility checking is used.
+ */
+static inline TableScanDesc
+table_beginscan_sampling(Relation rel, Snapshot snapshot,
+ int nkeys, struct ScanKeyData *key,
+ bool allow_strat, bool allow_sync,
+ bool allow_pagemode)
+{
+ uint32 flags = SO_TYPE_SAMPLESCAN;
+
+ if (allow_strat)
+ flags |= SO_ALLOW_STRAT;
+ if (allow_sync)
+ flags |= SO_ALLOW_SYNC;
+ if (allow_pagemode)
+ flags |= SO_ALLOW_PAGEMODE;
+
+ return rel->rd_tableam->scan_begin(rel, snapshot, nkeys, key, NULL, flags);
+}
+
+/*
+ * table_beginscan_tid is an alternative entry point for setting up a
+ * TableScanDesc for a Tid scan. As with bitmap scans, it's worth using
+ * the same data structure although the behavior is rather different.
+ */
+static inline TableScanDesc
+table_beginscan_tid(Relation rel, Snapshot snapshot)
+{
+ uint32 flags = SO_TYPE_TIDSCAN;
+
+ return rel->rd_tableam->scan_begin(rel, snapshot, 0, NULL, NULL, flags);
+}
+
+/*
+ * table_beginscan_analyze is an alternative entry point for setting up a
+ * TableScanDesc for an ANALYZE scan. As with bitmap scans, it's worth using
+ * the same data structure although the behavior is rather different.
+ */
+static inline TableScanDesc
+table_beginscan_analyze(Relation rel)
+{
+ uint32 flags = SO_TYPE_ANALYZE;
+
+ return rel->rd_tableam->scan_begin(rel, NULL, 0, NULL, NULL, flags);
+}
+
+/*
+ * End relation scan.
+ */
+static inline void
+table_endscan(TableScanDesc scan)
+{
+ scan->rs_rd->rd_tableam->scan_end(scan);
+}
+
+/*
+ * Restart a relation scan.
+ */
+static inline void
+table_rescan(TableScanDesc scan,
+ struct ScanKeyData *key)
+{
+ scan->rs_rd->rd_tableam->scan_rescan(scan, key, false, false, false, false);
+}
+
+/*
+ * Restart a relation scan after changing params.
+ *
+ * This call allows changing the buffer strategy, syncscan, and pagemode
+ * options before starting a fresh scan. Note that although the actual use of
+ * syncscan might change (effectively, enabling or disabling reporting), the
+ * previously selected startblock will be kept.
+ */
+static inline void
+table_rescan_set_params(TableScanDesc scan, struct ScanKeyData *key,
+ bool allow_strat, bool allow_sync, bool allow_pagemode)
+{
+ scan->rs_rd->rd_tableam->scan_rescan(scan, key, true,
+ allow_strat, allow_sync,
+ allow_pagemode);
+}
+
+/*
+ * Update snapshot used by the scan.
+ */
+extern void table_scan_update_snapshot(TableScanDesc scan, Snapshot snapshot);
+
+/*
+ * Return next tuple from `scan`, store in slot.
+ */
+static inline bool
+table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
+{
+ slot->tts_tableOid = RelationGetRelid(sscan->rs_rd);
+ return sscan->rs_rd->rd_tableam->scan_getnextslot(sscan, direction, slot);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Parallel table scan related functions.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ * Estimate the size of shared memory needed for a parallel scan of this
+ * relation.
+ */
+extern Size table_parallelscan_estimate(Relation rel, Snapshot snapshot);
+
+/*
+ * Initialize ParallelTableScanDesc for a parallel scan of this
+ * relation. `pscan` needs to be sized according to parallelscan_estimate()
+ * for the same relation. Call this just once in the leader process; then,
+ * individual workers attach via table_beginscan_parallel.
+ */
+extern void table_parallelscan_initialize(Relation rel,
+ ParallelTableScanDesc pscan,
+ Snapshot snapshot);
+
+/*
+ * Begin a parallel scan. `pscan` needs to have been initialized with
+ * table_parallelscan_initialize(), for the same relation. The initialization
+ * does not need to have happened in this backend.
+ *
+ * Caller must hold a suitable lock on the relation.
+ */
+extern TableScanDesc table_beginscan_parallel(Relation rel,
+ ParallelTableScanDesc pscan);
+
+/*
+ * Restart a parallel scan. Call this in the leader process. Caller is
+ * responsible for making sure that all workers have finished the scan
+ * beforehand.
+ */
+static inline void
+table_parallelscan_reinitialize(Relation rel, ParallelTableScanDesc pscan)
+{
+ rel->rd_tableam->parallelscan_reinitialize(rel, pscan);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Index scan related functions.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ * Prepare to fetch tuples from the relation, as needed when fetching tuples
+ * for an index scan.
+ *
+ * Tuples for an index scan can then be fetched via table_index_fetch_tuple().
+ */
+static inline IndexFetchTableData *
+table_index_fetch_begin(Relation rel)
+{
+ return rel->rd_tableam->index_fetch_begin(rel);
+}
+
+/*
+ * Reset index fetch. Typically this will release cross index fetch resources
+ * held in IndexFetchTableData.
+ */
+static inline void
+table_index_fetch_reset(struct IndexFetchTableData *scan)
+{
+ scan->rel->rd_tableam->index_fetch_reset(scan);
+}
+
+/*
+ * Release resources and deallocate index fetch.
+ */
+static inline void
+table_index_fetch_end(struct IndexFetchTableData *scan)
+{
+ scan->rel->rd_tableam->index_fetch_end(scan);
+}
+
+/*
+ * Fetches, as part of an index scan, tuple at `tid` into `slot`, after doing
+ * a visibility test according to `snapshot`. If a tuple was found and passed
+ * the visibility test, returns true, false otherwise. Note that *tid may be
+ * modified when we return true (see later remarks on multiple row versions
+ * reachable via a single index entry).
+ *
+ * *call_again needs to be false on the first call to table_index_fetch_tuple() for
+ * a tid. If there potentially is another tuple matching the tid, *call_again
+ * will be set to true, signaling that table_index_fetch_tuple() should be called
+ * again for the same tid.
+ *
+ * *all_dead, if all_dead is not NULL, will be set to true by
+ * table_index_fetch_tuple() iff it is guaranteed that no backend needs to see
+ * that tuple. Index AMs can use that to avoid returning that tid in future
+ * searches.
+ *
+ * The difference between this function and table_tuple_fetch_row_version()
+ * is that this function returns the currently visible version of a row if
+ * the AM supports storing multiple row versions reachable via a single index
+ * entry (like heap's HOT). Whereas table_tuple_fetch_row_version() only
+ * evaluates the tuple exactly at `tid`. Outside of index entry ->table tuple
+ * lookups, table_tuple_fetch_row_version() is what's usually needed.
+ */
+static inline bool
+table_index_fetch_tuple(struct IndexFetchTableData *scan,
+ ItemPointer tid,
+ Snapshot snapshot,
+ TupleTableSlot *slot,
+ bool *call_again, bool *all_dead)
+{
+
+ return scan->rel->rd_tableam->index_fetch_tuple(scan, tid, snapshot,
+ slot, call_again,
+ all_dead);
+}
+
+/*
+ * This is a convenience wrapper around table_index_fetch_tuple() which
+ * returns whether there are table tuple items corresponding to an index
+ * entry. This likely is only useful to verify if there's a conflict in a
+ * unique index.
+ */
+extern bool table_index_fetch_tuple_check(Relation rel,
+ ItemPointer tid,
+ Snapshot snapshot,
+ bool *all_dead);
+
+
+/* ------------------------------------------------------------------------
+ * Functions for non-modifying operations on individual tuples
+ * ------------------------------------------------------------------------
+ */
+
+
+/*
+ * Fetch tuple at `tid` into `slot`, after doing a visibility test according to
+ * `snapshot`. If a tuple was found and passed the visibility test, returns
+ * true, false otherwise.
+ *
+ * See table_index_fetch_tuple's comment about what the difference between
+ * these functions is. It is correct to use this function outside of index
+ * entry->table tuple lookups.
+ */
+static inline bool
+table_tuple_fetch_row_version(Relation rel,
+ ItemPointer tid,
+ Snapshot snapshot,
+ TupleTableSlot *slot)
+{
+ return rel->rd_tableam->tuple_fetch_row_version(rel, tid, snapshot, slot);
+}
+
+/*
+ * Verify that `tid` is a potentially valid tuple identifier. That doesn't
+ * mean that the pointed to row needs to exist or be visible, but that
+ * attempting to fetch the row (e.g. with table_tuple_get_latest_tid() or
+ * table_tuple_fetch_row_version()) should not error out if called with that
+ * tid.
+ *
+ * `scan` needs to have been started via table_beginscan().
+ */
+static inline bool
+table_tuple_tid_valid(TableScanDesc scan, ItemPointer tid)
+{
+ return scan->rs_rd->rd_tableam->tuple_tid_valid(scan, tid);
+}
+
+/*
+ * Return the latest version of the tuple at `tid`, by updating `tid` to
+ * point at the newest version.
+ */
+extern void table_tuple_get_latest_tid(TableScanDesc scan, ItemPointer tid);
+
+/*
+ * Return true iff tuple in slot satisfies the snapshot.
+ *
+ * This assumes the slot's tuple is valid, and of the appropriate type for the
+ * AM.
+ *
+ * Some AMs might modify the data underlying the tuple as a side-effect. If so
+ * they ought to mark the relevant buffer dirty.
+ */
+static inline bool
+table_tuple_satisfies_snapshot(Relation rel, TupleTableSlot *slot,
+ Snapshot snapshot)
+{
+ return rel->rd_tableam->tuple_satisfies_snapshot(rel, slot, snapshot);
+}
+
+/*
+ * Compute the newest xid among the tuples pointed to by items. This is used
+ * to compute what snapshots to conflict with when replaying WAL records for
+ * page-level index vacuums.
+ */
+static inline TransactionId
+table_compute_xid_horizon_for_tuples(Relation rel,
+ ItemPointerData *items,
+ int nitems)
+{
+ return rel->rd_tableam->compute_xid_horizon_for_tuples(rel, items, nitems);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Functions for manipulations of physical tuples.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ * Insert a tuple from a slot into table AM routine.
+ *
+ * The options bitmask allows the caller to specify options that may change the
+ * behaviour of the AM. The AM will ignore options that it does not support.
+ *
+ * If the TABLE_INSERT_SKIP_FSM option is specified, AMs are free to not reuse
+ * free space in the relation. This can save some cycles when we know the
+ * relation is new and doesn't contain useful amounts of free space.
+ * TABLE_INSERT_SKIP_FSM is commonly passed directly to
+ * RelationGetBufferForTuple. See that method for more information.
+ *
+ * TABLE_INSERT_FROZEN should only be specified for inserts into
+ * relfilenodes created during the current subtransaction and when
+ * there are no prior snapshots or pre-existing portals open.
+ * This causes rows to be frozen, which is an MVCC violation and
+ * requires explicit options chosen by user.
+ *
+ * TABLE_INSERT_NO_LOGICAL force-disables the emitting of logical decoding
+ * information for the tuple. This should solely be used during table rewrites
+ * where RelationIsLogicallyLogged(relation) is not yet accurate for the new
+ * relation.
+ *
+ * Note that most of these options will be applied when inserting into the
+ * heap's TOAST table, too, if the tuple requires any out-of-line data.
+ *
+ * The BulkInsertState object (if any; bistate can be NULL for default
+ * behavior) is also just passed through to RelationGetBufferForTuple. If
+ * `bistate` is provided, table_finish_bulk_insert() needs to be called.
+ *
+ * On return the slot's tts_tid and tts_tableOid are updated to reflect the
+ * insertion. But note that any toasting of fields within the slot is NOT
+ * reflected in the slots contents.
+ */
+static inline void
+table_tuple_insert(Relation rel, TupleTableSlot *slot, CommandId cid,
+ int options, struct BulkInsertStateData *bistate)
+{
+ rel->rd_tableam->tuple_insert(rel, slot, cid, options,
+ bistate);
+}
+
+/*
+ * Perform a "speculative insertion". These can be backed out afterwards
+ * without aborting the whole transaction. Other sessions can wait for the
+ * speculative insertion to be confirmed, turning it into a regular tuple, or
+ * aborted, as if it never existed. Speculatively inserted tuples behave as
+ * "value locks" of short duration, used to implement INSERT .. ON CONFLICT.
+ *
+ * A transaction having performed a speculative insertion has to either abort,
+ * or finish the speculative insertion with
+ * table_tuple_complete_speculative(succeeded = ...).
+ */
+static inline void
+table_tuple_insert_speculative(Relation rel, TupleTableSlot *slot,
+ CommandId cid, int options,
+ struct BulkInsertStateData *bistate,
+ uint32 specToken)
+{
+ rel->rd_tableam->tuple_insert_speculative(rel, slot, cid, options,
+ bistate, specToken);
+}
+
+/*
+ * Complete "speculative insertion" started in the same transaction. If
+ * succeeded is true, the tuple is fully inserted, if false, it's removed.
+ */
+static inline void
+table_tuple_complete_speculative(Relation rel, TupleTableSlot *slot,
+ uint32 specToken, bool succeeded)
+{
+ rel->rd_tableam->tuple_complete_speculative(rel, slot, specToken,
+ succeeded);
+}
+
+/*
+ * Insert multiple tuples into a table.
+ *
+ * This is like table_tuple_insert(), but inserts multiple tuples in one
+ * operation. That's often faster than calling table_tuple_insert() in a loop,
+ * because e.g. the AM can reduce WAL logging and page locking overhead.
+ *
+ * Except for taking `nslots` tuples as input, and an array of TupleTableSlots
+ * in `slots`, the parameters for table_multi_insert() are the same as for
+ * table_tuple_insert().
+ *
+ * Note: this leaks memory into the current memory context. You can create a
+ * temporary context before calling this, if that's a problem.
+ */
+static inline void
+table_multi_insert(Relation rel, TupleTableSlot **slots, int nslots,
+ CommandId cid, int options, struct BulkInsertStateData *bistate)
+{
+ rel->rd_tableam->multi_insert(rel, slots, nslots,
+ cid, options, bistate);
+}
+
+/*
+ * Delete a tuple.
+ *
+ * NB: do not call this directly unless prepared to deal with
+ * concurrent-update conditions. Use simple_table_tuple_delete instead.
+ *
+ * Input parameters:
+ * relation - table to be modified (caller must hold suitable lock)
+ * tid - TID of tuple to be deleted
+ * cid - delete command ID (used for visibility test, and stored into
+ * cmax if successful)
+ * crosscheck - if not InvalidSnapshot, also check tuple against this
+ * wait - true if should wait for any conflicting update to commit/abort
+ * Output parameters:
+ * tmfd - filled in failure cases (see below)
+ * changingPart - true iff the tuple is being moved to another partition
+ * table due to an update of the partition key. Otherwise, false.
+ *
+ * Normal, successful return value is TM_Ok, which means we did actually
+ * delete it. Failure return codes are TM_SelfModified, TM_Updated, and
+ * TM_BeingModified (the last only possible if wait == false).
+ *
+ * In the failure cases, the routine fills *tmfd with the tuple's t_ctid,
+ * t_xmax, and, if possible, and, if possible, t_cmax. See comments for
+ * struct TM_FailureData for additional info.
+ */
+static inline TM_Result
+table_tuple_delete(Relation rel, ItemPointer tid, CommandId cid,
+ Snapshot snapshot, Snapshot crosscheck, bool wait,
+ TM_FailureData *tmfd, bool changingPart)
+{
+ return rel->rd_tableam->tuple_delete(rel, tid, cid,
+ snapshot, crosscheck,
+ wait, tmfd, changingPart);
+}
+
+/*
+ * Update a tuple.
+ *
+ * NB: do not call this directly unless you are prepared to deal with
+ * concurrent-update conditions. Use simple_table_tuple_update instead.
+ *
+ * Input parameters:
+ * relation - table to be modified (caller must hold suitable lock)
+ * otid - TID of old tuple to be replaced
+ * slot - newly constructed tuple data to store
+ * cid - update command ID (used for visibility test, and stored into
+ * cmax/cmin if successful)
+ * crosscheck - if not InvalidSnapshot, also check old tuple against this
+ * wait - true if should wait for any conflicting update to commit/abort
+ * Output parameters:
+ * tmfd - filled in failure cases (see below)
+ * lockmode - filled with lock mode acquired on tuple
+ * update_indexes - in success cases this is set to true if new index entries
+ * are required for this tuple
+ *
+ * Normal, successful return value is TM_Ok, which means we did actually
+ * update it. Failure return codes are TM_SelfModified, TM_Updated, and
+ * TM_BeingModified (the last only possible if wait == false).
+ *
+ * On success, the slot's tts_tid and tts_tableOid are updated to match the new
+ * stored tuple; in particular, slot->tts_tid is set to the TID where the
+ * new tuple was inserted, and its HEAP_ONLY_TUPLE flag is set iff a HOT
+ * update was done. However, any TOAST changes in the new tuple's
+ * data are not reflected into *newtup.
+ *
+ * In the failure cases, the routine fills *tmfd with the tuple's t_ctid,
+ * t_xmax, and, if possible, t_cmax. See comments for struct TM_FailureData
+ * for additional info.
+ */
+static inline TM_Result
+table_tuple_update(Relation rel, ItemPointer otid, TupleTableSlot *slot,
+ CommandId cid, Snapshot snapshot, Snapshot crosscheck,
+ bool wait, TM_FailureData *tmfd, LockTupleMode *lockmode,
+ bool *update_indexes)
+{
+ return rel->rd_tableam->tuple_update(rel, otid, slot,
+ cid, snapshot, crosscheck,
+ wait, tmfd,
+ lockmode, update_indexes);
+}
+
+/*
+ * Lock a tuple in the specified mode.
+ *
+ * Input parameters:
+ * relation: relation containing tuple (caller must hold suitable lock)
+ * tid: TID of tuple to lock
+ * snapshot: snapshot to use for visibility determinations
+ * cid: current command ID (used for visibility test, and stored into
+ * tuple's cmax if lock is successful)
+ * mode: lock mode desired
+ * wait_policy: what to do if tuple lock is not available
+ * flags:
+ * If TUPLE_LOCK_FLAG_LOCK_UPDATE_IN_PROGRESS, follow the update chain to
+ * also lock descendant tuples if lock modes don't conflict.
+ * If TUPLE_LOCK_FLAG_FIND_LAST_VERSION, follow the update chain and lock
+ * latest version.
+ *
+ * Output parameters:
+ * *slot: contains the target tuple
+ * *tmfd: filled in failure cases (see below)
+ *
+ * Function result may be:
+ * TM_Ok: lock was successfully acquired
+ * TM_Invisible: lock failed because tuple was never visible to us
+ * TM_SelfModified: lock failed because tuple updated by self
+ * TM_Updated: lock failed because tuple updated by other xact
+ * TM_Deleted: lock failed because tuple deleted by other xact
+ * TM_WouldBlock: lock couldn't be acquired and wait_policy is skip
+ *
+ * In the failure cases other than TM_Invisible and TM_Deleted, the routine
+ * fills *tmfd with the tuple's t_ctid, t_xmax, and, if possible, t_cmax. See
+ * comments for struct TM_FailureData for additional info.
+ */
+static inline TM_Result
+table_tuple_lock(Relation rel, ItemPointer tid, Snapshot snapshot,
+ TupleTableSlot *slot, CommandId cid, LockTupleMode mode,
+ LockWaitPolicy wait_policy, uint8 flags,
+ TM_FailureData *tmfd)
+{
+ return rel->rd_tableam->tuple_lock(rel, tid, snapshot, slot,
+ cid, mode, wait_policy,
+ flags, tmfd);
+}
+
+/*
+ * Perform operations necessary to complete insertions made via
+ * tuple_insert and multi_insert with a BulkInsertState specified.
+ */
+static inline void
+table_finish_bulk_insert(Relation rel, int options)
+{
+ /* optional callback */
+ if (rel->rd_tableam && rel->rd_tableam->finish_bulk_insert)
+ rel->rd_tableam->finish_bulk_insert(rel, options);
+}
+
+
+/* ------------------------------------------------------------------------
+ * DDL related functionality.
+ * ------------------------------------------------------------------------
+ */
+
+/*
+ * Create storage for `rel` in `newrnode`, with persistence set to
+ * `persistence`.
+ *
+ * This is used both during relation creation and various DDL operations to
+ * create a new relfilenode that can be filled from scratch. When creating
+ * new storage for an existing relfilenode, this should be called before the
+ * relcache entry has been updated.
+ *
+ * *freezeXid, *minmulti are set to the xid / multixact horizon for the table
+ * that pg_class.{relfrozenxid, relminmxid} have to be set to.
+ */
+static inline void
+table_relation_set_new_filenode(Relation rel,
+ const RelFileNode *newrnode,
+ char persistence,
+ TransactionId *freezeXid,
+ MultiXactId *minmulti)
+{
+ rel->rd_tableam->relation_set_new_filenode(rel, newrnode, persistence,
+ freezeXid, minmulti);
+}
+
+/*
+ * Remove all table contents from `rel`, in a non-transactional manner.
+ * Non-transactional meaning that there's no need to support rollbacks. This
+ * commonly only is used to perform truncations for relfilenodes created in the
+ * current transaction.
+ */
+static inline void
+table_relation_nontransactional_truncate(Relation rel)
+{
+ rel->rd_tableam->relation_nontransactional_truncate(rel);
+}
+
+/*
+ * Copy data from `rel` into the new relfilenode `newrnode`. The new
+ * relfilenode may not have storage associated before this function is
+ * called. This is only supposed to be used for low level operations like
+ * changing a relation's tablespace.
+ */
+static inline void
+table_relation_copy_data(Relation rel, const RelFileNode *newrnode)
+{
+ rel->rd_tableam->relation_copy_data(rel, newrnode);
+}
+
+/*
+ * Copy data from `OldTable` into `NewTable`, as part of a CLUSTER or VACUUM
+ * FULL.
+ *
+ * Additional Input parameters:
+ * - use_sort - if true, the table contents are sorted appropriate for
+ * `OldIndex`; if false and OldIndex is not InvalidOid, the data is copied
+ * in that index's order; if false and OldIndex is InvalidOid, no sorting is
+ * performed
+ * - OldIndex - see use_sort
+ * - OldestXmin - computed by vacuum_set_xid_limits(), even when
+ * not needed for the relation's AM
+ * - *xid_cutoff - ditto
+ * - *multi_cutoff - ditto
+ *
+ * Output parameters:
+ * - *xid_cutoff - rel's new relfrozenxid value, may be invalid
+ * - *multi_cutoff - rel's new relminmxid value, may be invalid
+ * - *tups_vacuumed - stats, for logging, if appropriate for AM
+ * - *tups_recently_dead - stats, for logging, if appropriate for AM
+ */
+static inline void
+table_relation_copy_for_cluster(Relation OldTable, Relation NewTable,
+ Relation OldIndex,
+ bool use_sort,
+ TransactionId OldestXmin,
+ TransactionId *xid_cutoff,
+ MultiXactId *multi_cutoff,
+ double *num_tuples,
+ double *tups_vacuumed,
+ double *tups_recently_dead)
+{
+ OldTable->rd_tableam->relation_copy_for_cluster(OldTable, NewTable, OldIndex,
+ use_sort, OldestXmin,
+ xid_cutoff, multi_cutoff,
+ num_tuples, tups_vacuumed,
+ tups_recently_dead);
+}
+
+/*
+ * Perform VACUUM on the relation. The VACUUM can be triggered by a user or by
+ * autovacuum. The specific actions performed by the AM will depend heavily on
+ * the individual AM.
+ *
+ * On entry a transaction needs to already been established, and the
+ * table is locked with a ShareUpdateExclusive lock.
+ *
+ * Note that neither VACUUM FULL (and CLUSTER), nor ANALYZE go through this
+ * routine, even if (for ANALYZE) it is part of the same VACUUM command.
+ */
+static inline void
+table_relation_vacuum(Relation rel, struct VacuumParams *params,
+ BufferAccessStrategy bstrategy)
+{
+ rel->rd_tableam->relation_vacuum(rel, params, bstrategy);
+}
+
+/*
+ * Prepare to analyze block `blockno` of `scan`. The scan needs to have been
+ * started with table_beginscan_analyze(). Note that this routine might
+ * acquire resources like locks that are held until
+ * table_scan_analyze_next_tuple() returns false.
+ *
+ * Returns false if block is unsuitable for sampling, true otherwise.
+ */
+static inline bool
+table_scan_analyze_next_block(TableScanDesc scan, BlockNumber blockno,
+ BufferAccessStrategy bstrategy)
+{
+ return scan->rs_rd->rd_tableam->scan_analyze_next_block(scan, blockno,
+ bstrategy);
+}
+
+/*
+ * Iterate over tuples in the block selected with
+ * table_scan_analyze_next_block() (which needs to have returned true, and
+ * this routine may not have returned false for the same block before). If a
+ * tuple that's suitable for sampling is found, true is returned and a tuple
+ * is stored in `slot`.
+ *
+ * *liverows and *deadrows are incremented according to the encountered
+ * tuples.
+ */
+static inline bool
+table_scan_analyze_next_tuple(TableScanDesc scan, TransactionId OldestXmin,
+ double *liverows, double *deadrows,
+ TupleTableSlot *slot)
+{
+ return scan->rs_rd->rd_tableam->scan_analyze_next_tuple(scan, OldestXmin,
+ liverows, deadrows,
+ slot);
+}
+
+/*
+ * table_index_build_scan - scan the table to find tuples to be indexed
+ *
+ * This is called back from an access-method-specific index build procedure
+ * after the AM has done whatever setup it needs. The parent table relation
+ * is scanned to find tuples that should be entered into the index. Each
+ * such tuple is passed to the AM's callback routine, which does the right
+ * things to add it to the new index. After we return, the AM's index
+ * build procedure does whatever cleanup it needs.
+ *
+ * The total count of live tuples is returned. This is for updating pg_class
+ * statistics. (It's annoying not to be able to do that here, but we want to
+ * merge that update with others; see index_update_stats.) Note that the
+ * index AM itself must keep track of the number of index tuples; we don't do
+ * so here because the AM might reject some of the tuples for its own reasons,
+ * such as being unable to store NULLs.
+ *
+ * If 'progress', the PROGRESS_SCAN_BLOCKS_TOTAL counter is updated when
+ * starting the scan, and PROGRESS_SCAN_BLOCKS_DONE is updated as we go along.
+ *
+ * A side effect is to set indexInfo->ii_BrokenHotChain to true if we detect
+ * any potentially broken HOT chains. Currently, we set this if there are any
+ * RECENTLY_DEAD or DELETE_IN_PROGRESS entries in a HOT chain, without trying
+ * very hard to detect whether they're really incompatible with the chain tip.
+ * This only really makes sense for heap AM, it might need to be generalized
+ * for other AMs later.
+ */
+static inline double
+table_index_build_scan(Relation table_rel,
+ Relation index_rel,
+ struct IndexInfo *index_info,
+ bool allow_sync,
+ bool progress,
+ IndexBuildCallback callback,
+ void *callback_state,
+ TableScanDesc scan)
+{
+ return table_rel->rd_tableam->index_build_range_scan(table_rel,
+ index_rel,
+ index_info,
+ allow_sync,
+ false,
+ progress,
+ 0,
+ InvalidBlockNumber,
+ callback,
+ callback_state,
+ scan);
+}
+
+/*
+ * As table_index_build_scan(), except that instead of scanning the complete
+ * table, only the given number of blocks are scanned. Scan to end-of-rel can
+ * be signaled by passing InvalidBlockNumber as numblocks. Note that
+ * restricting the range to scan cannot be done when requesting syncscan.
+ *
+ * When "anyvisible" mode is requested, all tuples visible to any transaction
+ * are indexed and counted as live, including those inserted or deleted by
+ * transactions that are still in progress.
+ */
+static inline double
+table_index_build_range_scan(Relation table_rel,
+ Relation index_rel,
+ struct IndexInfo *index_info,
+ bool allow_sync,
+ bool anyvisible,
+ bool progress,
+ BlockNumber start_blockno,
+ BlockNumber numblocks,
+ IndexBuildCallback callback,
+ void *callback_state,
+ TableScanDesc scan)
+{
+ return table_rel->rd_tableam->index_build_range_scan(table_rel,
+ index_rel,
+ index_info,
+ allow_sync,
+ anyvisible,
+ progress,
+ start_blockno,
+ numblocks,
+ callback,
+ callback_state,
+ scan);
+}
+
+/*
+ * table_index_validate_scan - second table scan for concurrent index build
+ *
+ * See validate_index() for an explanation.
+ */
+static inline void
+table_index_validate_scan(Relation table_rel,
+ Relation index_rel,
+ struct IndexInfo *index_info,
+ Snapshot snapshot,
+ struct ValidateIndexState *state)
+{
+ table_rel->rd_tableam->index_validate_scan(table_rel,
+ index_rel,
+ index_info,
+ snapshot,
+ state);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Miscellaneous functionality
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ * Return the current size of `rel` in bytes. If `forkNumber` is
+ * InvalidForkNumber, return the relation's overall size, otherwise the size
+ * for the indicated fork.
+ *
+ * Note that the overall size might not be the equivalent of the sum of sizes
+ * for the individual forks for some AMs, e.g. because the AMs storage does
+ * not neatly map onto the builtin types of forks.
+ */
+static inline uint64
+table_relation_size(Relation rel, ForkNumber forkNumber)
+{
+ return rel->rd_tableam->relation_size(rel, forkNumber);
+}
+
+/*
+ * table_relation_needs_toast_table - does this relation need a toast table?
+ */
+static inline bool
+table_relation_needs_toast_table(Relation rel)
+{
+ return rel->rd_tableam->relation_needs_toast_table(rel);
+}
+
+/*
+ * Return the OID of the AM that should be used to implement the TOAST table
+ * for this relation.
+ */
+static inline Oid
+table_relation_toast_am(Relation rel)
+{
+ return rel->rd_tableam->relation_toast_am(rel);
+}
+
+/*
+ * Fetch all or part of a TOAST value from a TOAST table.
+ *
+ * If this AM is never used to implement a TOAST table, then this callback
+ * is not needed. But, if toasted values are ever stored in a table of this
+ * type, then you will need this callback.
+ *
+ * toastrel is the relation in which the toasted value is stored.
+ *
+ * valueid identifes which toast value is to be fetched. For the heap,
+ * this corresponds to the values stored in the chunk_id column.
+ *
+ * attrsize is the total size of the toast value to be fetched.
+ *
+ * sliceoffset is the offset within the toast value of the first byte that
+ * should be fetched.
+ *
+ * slicelength is the number of bytes from the toast value that should be
+ * fetched.
+ *
+ * result is caller-allocated space into which the fetched bytes should be
+ * stored.
+ */
+static inline void
+table_relation_fetch_toast_slice(Relation toastrel, Oid valueid,
+ int32 attrsize, int32 sliceoffset,
+ int32 slicelength, struct varlena *result)
+{
+ toastrel->rd_tableam->relation_fetch_toast_slice(toastrel, valueid,
+ attrsize,
+ sliceoffset, slicelength,
+ result);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Planner related functionality
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ * Estimate the current size of the relation, as an AM specific workhorse for
+ * estimate_rel_size(). Look there for an explanation of the parameters.
+ */
+static inline void
+table_relation_estimate_size(Relation rel, int32 *attr_widths,
+ BlockNumber *pages, double *tuples,
+ double *allvisfrac)
+{
+ rel->rd_tableam->relation_estimate_size(rel, attr_widths, pages, tuples,
+ allvisfrac);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Executor related functionality
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ * Prepare to fetch / check / return tuples from `tbmres->blockno` as part of
+ * a bitmap table scan. `scan` needs to have been started via
+ * table_beginscan_bm(). Returns false if there are no tuples to be found on
+ * the page, true otherwise.
+ *
+ * Note, this is an optionally implemented function, therefore should only be
+ * used after verifying the presence (at plan time or such).
+ */
+static inline bool
+table_scan_bitmap_next_block(TableScanDesc scan,
+ struct TBMIterateResult *tbmres)
+{
+ return scan->rs_rd->rd_tableam->scan_bitmap_next_block(scan,
+ tbmres);
+}
+
+/*
+ * Fetch the next tuple of a bitmap table scan into `slot` and return true if
+ * a visible tuple was found, false otherwise.
+ * table_scan_bitmap_next_block() needs to previously have selected a
+ * block (i.e. returned true), and no previous
+ * table_scan_bitmap_next_tuple() for the same block may have
+ * returned false.
+ */
+static inline bool
+table_scan_bitmap_next_tuple(TableScanDesc scan,
+ struct TBMIterateResult *tbmres,
+ TupleTableSlot *slot)
+{
+ return scan->rs_rd->rd_tableam->scan_bitmap_next_tuple(scan,
+ tbmres,
+ slot);
+}
+
+/*
+ * Prepare to fetch tuples from the next block in a sample scan. Returns false
+ * if the sample scan is finished, true otherwise. `scan` needs to have been
+ * started via table_beginscan_sampling().
+ *
+ * This will call the TsmRoutine's NextSampleBlock() callback if necessary
+ * (i.e. NextSampleBlock is not NULL), or perform a sequential scan over the
+ * underlying relation.
+ */
+static inline bool
+table_scan_sample_next_block(TableScanDesc scan,
+ struct SampleScanState *scanstate)
+{
+ return scan->rs_rd->rd_tableam->scan_sample_next_block(scan, scanstate);
+}
+
+/*
+ * Fetch the next sample tuple into `slot` and return true if a visible tuple
+ * was found, false otherwise. table_scan_sample_next_block() needs to
+ * previously have selected a block (i.e. returned true), and no previous
+ * table_scan_sample_next_tuple() for the same block may have returned false.
+ *
+ * This will call the TsmRoutine's NextSampleTuple() callback.
+ */
+static inline bool
+table_scan_sample_next_tuple(TableScanDesc scan,
+ struct SampleScanState *scanstate,
+ TupleTableSlot *slot)
+{
+ return scan->rs_rd->rd_tableam->scan_sample_next_tuple(scan, scanstate,
+ slot);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Functions to make modifications a bit simpler.
+ * ----------------------------------------------------------------------------
+ */
+
+extern void simple_table_tuple_insert(Relation rel, TupleTableSlot *slot);
+extern void simple_table_tuple_delete(Relation rel, ItemPointer tid,
+ Snapshot snapshot);
+extern void simple_table_tuple_update(Relation rel, ItemPointer otid,
+ TupleTableSlot *slot, Snapshot snapshot,
+ bool *update_indexes);
+
+
+/* ----------------------------------------------------------------------------
+ * Helper functions to implement parallel scans for block oriented AMs.
+ * ----------------------------------------------------------------------------
+ */
+
+extern Size table_block_parallelscan_estimate(Relation rel);
+extern Size table_block_parallelscan_initialize(Relation rel,
+ ParallelTableScanDesc pscan);
+extern void table_block_parallelscan_reinitialize(Relation rel,
+ ParallelTableScanDesc pscan);
+extern BlockNumber table_block_parallelscan_nextpage(Relation rel,
+ ParallelBlockTableScanDesc pbscan);
+extern void table_block_parallelscan_startblock_init(Relation rel,
+ ParallelBlockTableScanDesc pbscan);
+
+
+/* ----------------------------------------------------------------------------
+ * Helper functions to implement relation sizing for block oriented AMs.
+ * ----------------------------------------------------------------------------
+ */
+
+extern uint64 table_block_relation_size(Relation rel, ForkNumber forkNumber);
+extern void table_block_relation_estimate_size(Relation rel,
+ int32 *attr_widths,
+ BlockNumber *pages,
+ double *tuples,
+ double *allvisfrac,
+ Size overhead_bytes_per_tuple,
+ Size usable_bytes_per_page);
+
+/* ----------------------------------------------------------------------------
+ * Functions in tableamapi.c
+ * ----------------------------------------------------------------------------
+ */
+
+extern const TableAmRoutine *GetTableAmRoutine(Oid amhandler);
+extern const TableAmRoutine *GetHeapamTableAmRoutine(void);
+extern bool check_default_table_access_method(char **newval, void **extra,
+ GucSource source);
+
+#endif /* TABLEAM_H */
diff --git a/src/include/access/timeline.h b/src/include/access/timeline.h
new file mode 100644
index 0000000..2878f6d
--- /dev/null
+++ b/src/include/access/timeline.h
@@ -0,0 +1,44 @@
+/*
+ * timeline.h
+ *
+ * Functions for reading and writing timeline history files.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/timeline.h
+ */
+#ifndef TIMELINE_H
+#define TIMELINE_H
+
+#include "access/xlogdefs.h"
+#include "nodes/pg_list.h"
+
+/*
+ * A list of these structs describes the timeline history of the server. Each
+ * TimeLineHistoryEntry represents a piece of WAL belonging to the history,
+ * from newest to oldest. All WAL locations between 'begin' and 'end' belong to
+ * the timeline represented by the entry. Together the 'begin' and 'end'
+ * pointers of all the entries form a contiguous line from beginning of time
+ * to infinity.
+ */
+typedef struct
+{
+ TimeLineID tli;
+ XLogRecPtr begin; /* inclusive */
+ XLogRecPtr end; /* exclusive, InvalidXLogRecPtr means infinity */
+} TimeLineHistoryEntry;
+
+extern List *readTimeLineHistory(TimeLineID targetTLI);
+extern bool existsTimeLineHistory(TimeLineID probeTLI);
+extern TimeLineID findNewestTimeLine(TimeLineID startTLI);
+extern void writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
+ XLogRecPtr switchpoint, char *reason);
+extern void writeTimeLineHistoryFile(TimeLineID tli, char *content, int size);
+extern void restoreTimeLineHistoryFiles(TimeLineID begin, TimeLineID end);
+extern bool tliInHistory(TimeLineID tli, List *expectedTLEs);
+extern TimeLineID tliOfPointInHistory(XLogRecPtr ptr, List *history);
+extern XLogRecPtr tliSwitchPoint(TimeLineID tli, List *history,
+ TimeLineID *nextTLI);
+
+#endif /* TIMELINE_H */
diff --git a/src/include/access/toast_helper.h b/src/include/access/toast_helper.h
new file mode 100644
index 0000000..0e92acc
--- /dev/null
+++ b/src/include/access/toast_helper.h
@@ -0,0 +1,115 @@
+/*-------------------------------------------------------------------------
+ *
+ * toast_helper.h
+ * Helper functions for table AMs implementing compressed or
+ * out-of-line storage of varlena attributes.
+ *
+ * Copyright (c) 2000-2020, PostgreSQL Global Development Group
+ *
+ * src/include/access/toast_helper.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef TOAST_HELPER_H
+#define TOAST_HELPER_H
+
+#include "utils/rel.h"
+
+/*
+ * Information about one column of a tuple being toasted.
+ *
+ * NOTE: toast_action[i] can have these values:
+ * ' ' default handling
+ * TYPSTORAGE_PLAIN already processed --- don't touch it
+ * TYPSTORAGE_EXTENDED incompressible, but OK to move off
+ *
+ * NOTE: toast_attr[i].tai_size is only made valid for varlena attributes with
+ * toast_action[i] different from TYPSTORAGE_PLAIN.
+ */
+typedef struct
+{
+ struct varlena *tai_oldexternal;
+ int32 tai_size;
+ uint8 tai_colflags;
+} ToastAttrInfo;
+
+/*
+ * Information about one tuple being toasted.
+ */
+typedef struct
+{
+ /*
+ * Before calling toast_tuple_init, the caller must initialize the
+ * following fields. Each array must have a length equal to
+ * ttc_rel->rd_att->natts. The tts_oldvalues and tts_oldisnull fields
+ * should be NULL in the case of an insert.
+ */
+ Relation ttc_rel; /* the relation that contains the tuple */
+ Datum *ttc_values; /* values from the tuple columns */
+ bool *ttc_isnull; /* null flags for the tuple columns */
+ Datum *ttc_oldvalues; /* values from previous tuple */
+ bool *ttc_oldisnull; /* null flags from previous tuple */
+
+ /*
+ * Before calling toast_tuple_init, the caller should set tts_attr to
+ * point to an array of ToastAttrInfo structures of a length equal to
+ * tts_rel->rd_att->natts. The contents of the array need not be
+ * initialized. ttc_flags also does not need to be initialized.
+ */
+ uint8 ttc_flags;
+ ToastAttrInfo *ttc_attr;
+} ToastTupleContext;
+
+/*
+ * Flags indicating the overall state of a TOAST operation.
+ *
+ * TOAST_NEEDS_DELETE_OLD indicates that one or more old TOAST datums need
+ * to be deleted.
+ *
+ * TOAST_NEEDS_FREE indicates that one or more TOAST values need to be freed.
+ *
+ * TOAST_HAS_NULLS indicates that nulls were found in the tuple being toasted.
+ *
+ * TOAST_NEEDS_CHANGE indicates that a new tuple needs to built; in other
+ * words, the toaster did something.
+ */
+#define TOAST_NEEDS_DELETE_OLD 0x0001
+#define TOAST_NEEDS_FREE 0x0002
+#define TOAST_HAS_NULLS 0x0004
+#define TOAST_NEEDS_CHANGE 0x0008
+
+/*
+ * Flags indicating the status of a TOAST operation with respect to a
+ * particular column.
+ *
+ * TOASTCOL_NEEDS_DELETE_OLD indicates that the old TOAST datums for this
+ * column need to be deleted.
+ *
+ * TOASTCOL_NEEDS_FREE indicates that the value for this column needs to
+ * be freed.
+ *
+ * TOASTCOL_IGNORE indicates that the toaster should not further process
+ * this column.
+ *
+ * TOASTCOL_INCOMPRESSIBLE indicates that this column has been found to
+ * be incompressible, but could be moved out-of-line.
+ */
+#define TOASTCOL_NEEDS_DELETE_OLD TOAST_NEEDS_DELETE_OLD
+#define TOASTCOL_NEEDS_FREE TOAST_NEEDS_FREE
+#define TOASTCOL_IGNORE 0x0010
+#define TOASTCOL_INCOMPRESSIBLE 0x0020
+
+extern void toast_tuple_init(ToastTupleContext *ttc);
+extern int toast_tuple_find_biggest_attribute(ToastTupleContext *ttc,
+ bool for_compression,
+ bool check_main);
+extern void toast_tuple_try_compression(ToastTupleContext *ttc, int attribute);
+extern void toast_tuple_externalize(ToastTupleContext *ttc, int attribute,
+ int options);
+extern void toast_tuple_cleanup(ToastTupleContext *ttc);
+
+extern void toast_delete_external(Relation rel, Datum *values, bool *isnull,
+ bool is_speculative);
+
+#endif
diff --git a/src/include/access/toast_internals.h b/src/include/access/toast_internals.h
new file mode 100644
index 0000000..71e3ca2
--- /dev/null
+++ b/src/include/access/toast_internals.h
@@ -0,0 +1,55 @@
+/*-------------------------------------------------------------------------
+ *
+ * toast_internals.h
+ * Internal definitions for the TOAST system.
+ *
+ * Copyright (c) 2000-2020, PostgreSQL Global Development Group
+ *
+ * src/include/access/toast_internals.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TOAST_INTERNALS_H
+#define TOAST_INTERNALS_H
+
+#include "storage/lockdefs.h"
+#include "utils/relcache.h"
+#include "utils/snapshot.h"
+
+/*
+ * The information at the start of the compressed toast data.
+ */
+typedef struct toast_compress_header
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ int32 rawsize;
+} toast_compress_header;
+
+/*
+ * Utilities for manipulation of header information for compressed
+ * toast entries.
+ */
+#define TOAST_COMPRESS_HDRSZ ((int32) sizeof(toast_compress_header))
+#define TOAST_COMPRESS_RAWSIZE(ptr) (((toast_compress_header *) (ptr))->rawsize)
+#define TOAST_COMPRESS_SIZE(ptr) ((int32) VARSIZE_ANY(ptr) - TOAST_COMPRESS_HDRSZ)
+#define TOAST_COMPRESS_RAWDATA(ptr) \
+ (((char *) (ptr)) + TOAST_COMPRESS_HDRSZ)
+#define TOAST_COMPRESS_SET_RAWSIZE(ptr, len) \
+ (((toast_compress_header *) (ptr))->rawsize = (len))
+
+extern Datum toast_compress_datum(Datum value);
+extern Oid toast_get_valid_index(Oid toastoid, LOCKMODE lock);
+
+extern void toast_delete_datum(Relation rel, Datum value, bool is_speculative);
+extern Datum toast_save_datum(Relation rel, Datum value,
+ struct varlena *oldexternal, int options);
+
+extern int toast_open_indexes(Relation toastrel,
+ LOCKMODE lock,
+ Relation **toastidxs,
+ int *num_indexes);
+extern void toast_close_indexes(Relation *toastidxs, int num_indexes,
+ LOCKMODE lock);
+extern void init_toast_snapshot(Snapshot toast_snapshot);
+
+#endif /* TOAST_INTERNALS_H */
diff --git a/src/include/access/transam.h b/src/include/access/transam.h
new file mode 100644
index 0000000..a91a0c7
--- /dev/null
+++ b/src/include/access/transam.h
@@ -0,0 +1,265 @@
+/*-------------------------------------------------------------------------
+ *
+ * transam.h
+ * postgres transaction access method support code
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/transam.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TRANSAM_H
+#define TRANSAM_H
+
+#include "access/xlogdefs.h"
+
+
+/* ----------------
+ * Special transaction ID values
+ *
+ * BootstrapTransactionId is the XID for "bootstrap" operations, and
+ * FrozenTransactionId is used for very old tuples. Both should
+ * always be considered valid.
+ *
+ * FirstNormalTransactionId is the first "normal" transaction id.
+ * Note: if you need to change it, you must change pg_class.h as well.
+ * ----------------
+ */
+#define InvalidTransactionId ((TransactionId) 0)
+#define BootstrapTransactionId ((TransactionId) 1)
+#define FrozenTransactionId ((TransactionId) 2)
+#define FirstNormalTransactionId ((TransactionId) 3)
+#define MaxTransactionId ((TransactionId) 0xFFFFFFFF)
+
+/* ----------------
+ * transaction ID manipulation macros
+ * ----------------
+ */
+#define TransactionIdIsValid(xid) ((xid) != InvalidTransactionId)
+#define TransactionIdIsNormal(xid) ((xid) >= FirstNormalTransactionId)
+#define TransactionIdEquals(id1, id2) ((id1) == (id2))
+#define TransactionIdStore(xid, dest) (*(dest) = (xid))
+#define StoreInvalidTransactionId(dest) (*(dest) = InvalidTransactionId)
+
+#define EpochFromFullTransactionId(x) ((uint32) ((x).value >> 32))
+#define XidFromFullTransactionId(x) ((uint32) (x).value)
+#define U64FromFullTransactionId(x) ((x).value)
+#define FullTransactionIdEquals(a, b) ((a).value == (b).value)
+#define FullTransactionIdPrecedes(a, b) ((a).value < (b).value)
+#define FullTransactionIdPrecedesOrEquals(a, b) ((a).value <= (b).value)
+#define FullTransactionIdFollows(a, b) ((a).value > (b).value)
+#define FullTransactionIdFollowsOrEquals(a, b) ((a).value >= (b).value)
+#define FullTransactionIdIsValid(x) TransactionIdIsValid(XidFromFullTransactionId(x))
+#define InvalidFullTransactionId FullTransactionIdFromEpochAndXid(0, InvalidTransactionId)
+
+/*
+ * A 64 bit value that contains an epoch and a TransactionId. This is
+ * wrapped in a struct to prevent implicit conversion to/from TransactionId.
+ * Not all values represent valid normal XIDs.
+ */
+typedef struct FullTransactionId
+{
+ uint64 value;
+} FullTransactionId;
+
+static inline FullTransactionId
+FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
+{
+ FullTransactionId result;
+
+ result.value = ((uint64) epoch) << 32 | xid;
+
+ return result;
+}
+
+static inline FullTransactionId
+FullTransactionIdFromU64(uint64 value)
+{
+ FullTransactionId result;
+
+ result.value = value;
+
+ return result;
+}
+
+/* advance a transaction ID variable, handling wraparound correctly */
+#define TransactionIdAdvance(dest) \
+ do { \
+ (dest)++; \
+ if ((dest) < FirstNormalTransactionId) \
+ (dest) = FirstNormalTransactionId; \
+ } while(0)
+
+/* advance a FullTransactionId variable, stepping over special XIDs */
+static inline void
+FullTransactionIdAdvance(FullTransactionId *dest)
+{
+ dest->value++;
+ while (XidFromFullTransactionId(*dest) < FirstNormalTransactionId)
+ dest->value++;
+}
+
+/* back up a transaction ID variable, handling wraparound correctly */
+#define TransactionIdRetreat(dest) \
+ do { \
+ (dest)--; \
+ } while ((dest) < FirstNormalTransactionId)
+
+/* compare two XIDs already known to be normal; this is a macro for speed */
+#define NormalTransactionIdPrecedes(id1, id2) \
+ (AssertMacro(TransactionIdIsNormal(id1) && TransactionIdIsNormal(id2)), \
+ (int32) ((id1) - (id2)) < 0)
+
+/* compare two XIDs already known to be normal; this is a macro for speed */
+#define NormalTransactionIdFollows(id1, id2) \
+ (AssertMacro(TransactionIdIsNormal(id1) && TransactionIdIsNormal(id2)), \
+ (int32) ((id1) - (id2)) > 0)
+
+/* ----------
+ * Object ID (OID) zero is InvalidOid.
+ *
+ * OIDs 1-9999 are reserved for manual assignment (see .dat files in
+ * src/include/catalog/). Of these, 8000-9999 are reserved for
+ * development purposes (such as in-progress patches and forks);
+ * they should not appear in released versions.
+ *
+ * OIDs 10000-11999 are reserved for assignment by genbki.pl, for use
+ * when the .dat files in src/include/catalog/ do not specify an OID
+ * for a catalog entry that requires one.
+ *
+ * OIDS 12000-16383 are reserved for assignment during initdb
+ * using the OID generator. (We start the generator at 12000.)
+ *
+ * OIDs beginning at 16384 are assigned from the OID generator
+ * during normal multiuser operation. (We force the generator up to
+ * 16384 as soon as we are in normal operation.)
+ *
+ * The choices of 8000, 10000 and 12000 are completely arbitrary, and can be
+ * moved if we run low on OIDs in any category. Changing the macros below,
+ * and updating relevant documentation (see bki.sgml and RELEASE_CHANGES),
+ * should be sufficient to do this. Moving the 16384 boundary between
+ * initdb-assigned OIDs and user-defined objects would be substantially
+ * more painful, however, since some user-defined OIDs will appear in
+ * on-disk data; such a change would probably break pg_upgrade.
+ *
+ * NOTE: if the OID generator wraps around, we skip over OIDs 0-16383
+ * and resume with 16384. This minimizes the odds of OID conflict, by not
+ * reassigning OIDs that might have been assigned during initdb.
+ * ----------
+ */
+#define FirstGenbkiObjectId 10000
+#define FirstBootstrapObjectId 12000
+#define FirstNormalObjectId 16384
+
+/*
+ * VariableCache is a data structure in shared memory that is used to track
+ * OID and XID assignment state. For largely historical reasons, there is
+ * just one struct with different fields that are protected by different
+ * LWLocks.
+ *
+ * Note: xidWrapLimit and oldestXidDB are not "active" values, but are
+ * used just to generate useful messages when xidWarnLimit or xidStopLimit
+ * are exceeded.
+ */
+typedef struct VariableCacheData
+{
+ /*
+ * These fields are protected by OidGenLock.
+ */
+ Oid nextOid; /* next OID to assign */
+ uint32 oidCount; /* OIDs available before must do XLOG work */
+
+ /*
+ * These fields are protected by XidGenLock.
+ */
+ FullTransactionId nextFullXid; /* next full XID to assign */
+
+ TransactionId oldestXid; /* cluster-wide minimum datfrozenxid */
+ TransactionId xidVacLimit; /* start forcing autovacuums here */
+ TransactionId xidWarnLimit; /* start complaining here */
+ TransactionId xidStopLimit; /* refuse to advance nextFullXid beyond here */
+ TransactionId xidWrapLimit; /* where the world ends */
+ Oid oldestXidDB; /* database with minimum datfrozenxid */
+
+ /*
+ * These fields are protected by CommitTsLock
+ */
+ TransactionId oldestCommitTsXid;
+ TransactionId newestCommitTsXid;
+
+ /*
+ * These fields are protected by ProcArrayLock.
+ */
+ TransactionId latestCompletedXid; /* newest XID that has committed or
+ * aborted */
+
+ /*
+ * These fields are protected by XactTruncationLock
+ */
+ TransactionId oldestClogXid; /* oldest it's safe to look up in clog */
+
+} VariableCacheData;
+
+typedef VariableCacheData *VariableCache;
+
+
+/* ----------------
+ * extern declarations
+ * ----------------
+ */
+
+/* in transam/xact.c */
+extern bool TransactionStartedDuringRecovery(void);
+
+/* in transam/varsup.c */
+extern PGDLLIMPORT VariableCache ShmemVariableCache;
+
+/*
+ * prototypes for functions in transam/transam.c
+ */
+extern bool TransactionIdDidCommit(TransactionId transactionId);
+extern bool TransactionIdDidAbort(TransactionId transactionId);
+extern bool TransactionIdIsKnownCompleted(TransactionId transactionId);
+extern void TransactionIdCommitTree(TransactionId xid, int nxids, TransactionId *xids);
+extern void TransactionIdAsyncCommitTree(TransactionId xid, int nxids, TransactionId *xids, XLogRecPtr lsn);
+extern void TransactionIdAbortTree(TransactionId xid, int nxids, TransactionId *xids);
+extern bool TransactionIdPrecedes(TransactionId id1, TransactionId id2);
+extern bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2);
+extern bool TransactionIdFollows(TransactionId id1, TransactionId id2);
+extern bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2);
+extern TransactionId TransactionIdLatest(TransactionId mainxid,
+ int nxids, const TransactionId *xids);
+extern XLogRecPtr TransactionIdGetCommitLSN(TransactionId xid);
+
+/* in transam/varsup.c */
+extern FullTransactionId GetNewTransactionId(bool isSubXact);
+extern void AdvanceNextFullTransactionIdPastXid(TransactionId xid);
+extern FullTransactionId ReadNextFullTransactionId(void);
+extern void SetTransactionIdLimit(TransactionId oldest_datfrozenxid,
+ Oid oldest_datoid);
+extern void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid);
+extern bool ForceTransactionIdLimitUpdate(void);
+extern Oid GetNewObjectId(void);
+
+/*
+ * Some frontend programs include this header. For compilers that emit static
+ * inline functions even when they're unused, that leads to unsatisfied
+ * external references; hence hide them with #ifndef FRONTEND.
+ */
+#ifndef FRONTEND
+
+/*
+ * For callers that just need the XID part of the next transaction ID.
+ */
+static inline TransactionId
+ReadNewTransactionId(void)
+{
+ return XidFromFullTransactionId(ReadNextFullTransactionId());
+}
+
+#endif /* FRONTEND */
+
+#endif /* TRANSAM_H */
diff --git a/src/include/access/tsmapi.h b/src/include/access/tsmapi.h
new file mode 100644
index 0000000..ffc64bc
--- /dev/null
+++ b/src/include/access/tsmapi.h
@@ -0,0 +1,82 @@
+/*-------------------------------------------------------------------------
+ *
+ * tsmapi.h
+ * API for tablesample methods
+ *
+ * Copyright (c) 2015-2020, PostgreSQL Global Development Group
+ *
+ * src/include/access/tsmapi.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TSMAPI_H
+#define TSMAPI_H
+
+#include "nodes/execnodes.h"
+#include "nodes/pathnodes.h"
+
+
+/*
+ * Callback function signatures --- see tablesample-method.sgml for more info.
+ */
+
+typedef void (*SampleScanGetSampleSize_function) (PlannerInfo *root,
+ RelOptInfo *baserel,
+ List *paramexprs,
+ BlockNumber *pages,
+ double *tuples);
+
+typedef void (*InitSampleScan_function) (SampleScanState *node,
+ int eflags);
+
+typedef void (*BeginSampleScan_function) (SampleScanState *node,
+ Datum *params,
+ int nparams,
+ uint32 seed);
+
+typedef BlockNumber (*NextSampleBlock_function) (SampleScanState *node,
+ BlockNumber nblocks);
+
+typedef OffsetNumber (*NextSampleTuple_function) (SampleScanState *node,
+ BlockNumber blockno,
+ OffsetNumber maxoffset);
+
+typedef void (*EndSampleScan_function) (SampleScanState *node);
+
+/*
+ * TsmRoutine is the struct returned by a tablesample method's handler
+ * function. It provides pointers to the callback functions needed by the
+ * planner and executor, as well as additional information about the method.
+ *
+ * More function pointers are likely to be added in the future.
+ * Therefore it's recommended that the handler initialize the struct with
+ * makeNode(TsmRoutine) so that all fields are set to NULL. This will
+ * ensure that no fields are accidentally left undefined.
+ */
+typedef struct TsmRoutine
+{
+ NodeTag type;
+
+ /* List of datatype OIDs for the arguments of the TABLESAMPLE clause */
+ List *parameterTypes;
+
+ /* Can method produce repeatable samples across, or even within, queries? */
+ bool repeatable_across_queries;
+ bool repeatable_across_scans;
+
+ /* Functions for planning a SampleScan on a physical table */
+ SampleScanGetSampleSize_function SampleScanGetSampleSize;
+
+ /* Functions for executing a SampleScan on a physical table */
+ InitSampleScan_function InitSampleScan; /* can be NULL */
+ BeginSampleScan_function BeginSampleScan;
+ NextSampleBlock_function NextSampleBlock; /* can be NULL */
+ NextSampleTuple_function NextSampleTuple;
+ EndSampleScan_function EndSampleScan; /* can be NULL */
+} TsmRoutine;
+
+
+/* Functions in access/tablesample/tablesample.c */
+extern TsmRoutine *GetTsmRoutine(Oid tsmhandler);
+
+#endif /* TSMAPI_H */
diff --git a/src/include/access/tupconvert.h b/src/include/access/tupconvert.h
new file mode 100644
index 0000000..0861960
--- /dev/null
+++ b/src/include/access/tupconvert.h
@@ -0,0 +1,51 @@
+/*-------------------------------------------------------------------------
+ *
+ * tupconvert.h
+ * Tuple conversion support.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/tupconvert.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TUPCONVERT_H
+#define TUPCONVERT_H
+
+#include "access/attmap.h"
+#include "access/htup.h"
+#include "access/tupdesc.h"
+#include "executor/tuptable.h"
+#include "nodes/bitmapset.h"
+
+
+typedef struct TupleConversionMap
+{
+ TupleDesc indesc; /* tupdesc for source rowtype */
+ TupleDesc outdesc; /* tupdesc for result rowtype */
+ AttrMap *attrMap; /* indexes of input fields, or 0 for null */
+ Datum *invalues; /* workspace for deconstructing source */
+ bool *inisnull;
+ Datum *outvalues; /* workspace for constructing result */
+ bool *outisnull;
+} TupleConversionMap;
+
+
+extern TupleConversionMap *convert_tuples_by_position(TupleDesc indesc,
+ TupleDesc outdesc,
+ const char *msg);
+
+extern TupleConversionMap *convert_tuples_by_name(TupleDesc indesc,
+ TupleDesc outdesc);
+
+extern HeapTuple execute_attr_map_tuple(HeapTuple tuple, TupleConversionMap *map);
+extern TupleTableSlot *execute_attr_map_slot(AttrMap *attrMap,
+ TupleTableSlot *in_slot,
+ TupleTableSlot *out_slot);
+extern Bitmapset *execute_attr_map_cols(AttrMap *attrMap, Bitmapset *inbitmap);
+
+extern void free_conversion_map(TupleConversionMap *map);
+
+#endif /* TUPCONVERT_H */
diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h
new file mode 100644
index 0000000..d17af13
--- /dev/null
+++ b/src/include/access/tupdesc.h
@@ -0,0 +1,154 @@
+/*-------------------------------------------------------------------------
+ *
+ * tupdesc.h
+ * POSTGRES tuple descriptor definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/tupdesc.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TUPDESC_H
+#define TUPDESC_H
+
+#include "access/attnum.h"
+#include "catalog/pg_attribute.h"
+#include "nodes/pg_list.h"
+
+
+typedef struct AttrDefault
+{
+ AttrNumber adnum;
+ char *adbin; /* nodeToString representation of expr */
+} AttrDefault;
+
+typedef struct ConstrCheck
+{
+ char *ccname;
+ char *ccbin; /* nodeToString representation of expr */
+ bool ccvalid;
+ bool ccnoinherit; /* this is a non-inheritable constraint */
+} ConstrCheck;
+
+/* This structure contains constraints of a tuple */
+typedef struct TupleConstr
+{
+ AttrDefault *defval; /* array */
+ ConstrCheck *check; /* array */
+ struct AttrMissing *missing; /* missing attributes values, NULL if none */
+ uint16 num_defval;
+ uint16 num_check;
+ bool has_not_null;
+ bool has_generated_stored;
+} TupleConstr;
+
+/*
+ * This struct is passed around within the backend to describe the structure
+ * of tuples. For tuples coming from on-disk relations, the information is
+ * collected from the pg_attribute, pg_attrdef, and pg_constraint catalogs.
+ * Transient row types (such as the result of a join query) have anonymous
+ * TupleDesc structs that generally omit any constraint info; therefore the
+ * structure is designed to let the constraints be omitted efficiently.
+ *
+ * Note that only user attributes, not system attributes, are mentioned in
+ * TupleDesc.
+ *
+ * If the tupdesc is known to correspond to a named rowtype (such as a table's
+ * rowtype) then tdtypeid identifies that type and tdtypmod is -1. Otherwise
+ * tdtypeid is RECORDOID, and tdtypmod can be either -1 for a fully anonymous
+ * row type, or a value >= 0 to allow the rowtype to be looked up in the
+ * typcache.c type cache.
+ *
+ * Note that tdtypeid is never the OID of a domain over composite, even if
+ * we are dealing with values that are known (at some higher level) to be of
+ * a domain-over-composite type. This is because tdtypeid/tdtypmod need to
+ * match up with the type labeling of composite Datums, and those are never
+ * explicitly marked as being of a domain type, either.
+ *
+ * Tuple descriptors that live in caches (relcache or typcache, at present)
+ * are reference-counted: they can be deleted when their reference count goes
+ * to zero. Tuple descriptors created by the executor need no reference
+ * counting, however: they are simply created in the appropriate memory
+ * context and go away when the context is freed. We set the tdrefcount
+ * field of such a descriptor to -1, while reference-counted descriptors
+ * always have tdrefcount >= 0.
+ */
+typedef struct TupleDescData
+{
+ int natts; /* number of attributes in the tuple */
+ Oid tdtypeid; /* composite type ID for tuple type */
+ int32 tdtypmod; /* typmod for tuple type */
+ int tdrefcount; /* reference count, or -1 if not counting */
+ TupleConstr *constr; /* constraints, or NULL if none */
+ /* attrs[N] is the description of Attribute Number N+1 */
+ FormData_pg_attribute attrs[FLEXIBLE_ARRAY_MEMBER];
+} TupleDescData;
+typedef struct TupleDescData *TupleDesc;
+
+/* Accessor for the i'th attribute of tupdesc. */
+#define TupleDescAttr(tupdesc, i) (&(tupdesc)->attrs[(i)])
+
+extern TupleDesc CreateTemplateTupleDesc(int natts);
+
+extern TupleDesc CreateTupleDesc(int natts, Form_pg_attribute *attrs);
+
+extern TupleDesc CreateTupleDescCopy(TupleDesc tupdesc);
+
+extern TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc);
+
+#define TupleDescSize(src) \
+ (offsetof(struct TupleDescData, attrs) + \
+ (src)->natts * sizeof(FormData_pg_attribute))
+
+extern void TupleDescCopy(TupleDesc dst, TupleDesc src);
+
+extern void TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno,
+ TupleDesc src, AttrNumber srcAttno);
+
+extern void FreeTupleDesc(TupleDesc tupdesc);
+
+extern void IncrTupleDescRefCount(TupleDesc tupdesc);
+extern void DecrTupleDescRefCount(TupleDesc tupdesc);
+
+#define PinTupleDesc(tupdesc) \
+ do { \
+ if ((tupdesc)->tdrefcount >= 0) \
+ IncrTupleDescRefCount(tupdesc); \
+ } while (0)
+
+#define ReleaseTupleDesc(tupdesc) \
+ do { \
+ if ((tupdesc)->tdrefcount >= 0) \
+ DecrTupleDescRefCount(tupdesc); \
+ } while (0)
+
+extern bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2);
+
+extern uint32 hashTupleDesc(TupleDesc tupdesc);
+
+extern void TupleDescInitEntry(TupleDesc desc,
+ AttrNumber attributeNumber,
+ const char *attributeName,
+ Oid oidtypeid,
+ int32 typmod,
+ int attdim);
+
+extern void TupleDescInitBuiltinEntry(TupleDesc desc,
+ AttrNumber attributeNumber,
+ const char *attributeName,
+ Oid oidtypeid,
+ int32 typmod,
+ int attdim);
+
+extern void TupleDescInitEntryCollation(TupleDesc desc,
+ AttrNumber attributeNumber,
+ Oid collationid);
+
+extern TupleDesc BuildDescForRelation(List *schema);
+
+extern TupleDesc BuildDescFromLists(List *names, List *types, List *typmods, List *collations);
+
+#endif /* TUPDESC_H */
diff --git a/src/include/access/tupdesc_details.h b/src/include/access/tupdesc_details.h
new file mode 100644
index 0000000..01c4a11
--- /dev/null
+++ b/src/include/access/tupdesc_details.h
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+ *
+ * tupdesc_details.h
+ * POSTGRES tuple descriptor definitions we can't include everywhere
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/tupdesc_details.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef TUPDESC_DETAILS_H
+#define TUPDESC_DETAILS_H
+
+/*
+ * Structure used to represent value to be used when the attribute is not
+ * present at all in a tuple, i.e. when the column was created after the tuple
+ */
+typedef struct AttrMissing
+{
+ bool am_present; /* true if non-NULL missing value exists */
+ Datum am_value; /* value when attribute is missing */
+} AttrMissing;
+
+#endif /* TUPDESC_DETAILS_H */
diff --git a/src/include/access/tupmacs.h b/src/include/access/tupmacs.h
new file mode 100644
index 0000000..70157cf
--- /dev/null
+++ b/src/include/access/tupmacs.h
@@ -0,0 +1,247 @@
+/*-------------------------------------------------------------------------
+ *
+ * tupmacs.h
+ * Tuple macros used by both index tuples and heap tuples.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/tupmacs.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TUPMACS_H
+#define TUPMACS_H
+
+#include "catalog/pg_type_d.h" /* for TYPALIGN macros */
+
+
+/*
+ * Check a tuple's null bitmap to determine whether the attribute is null.
+ * Note that a 0 in the null bitmap indicates a null, while 1 indicates
+ * non-null.
+ */
+#define att_isnull(ATT, BITS) (!((BITS)[(ATT) >> 3] & (1 << ((ATT) & 0x07))))
+
+/*
+ * Given a Form_pg_attribute and a pointer into a tuple's data area,
+ * return the correct value or pointer.
+ *
+ * We return a Datum value in all cases. If the attribute has "byval" false,
+ * we return the same pointer into the tuple data area that we're passed.
+ * Otherwise, we return the correct number of bytes fetched from the data
+ * area and extended to Datum form.
+ *
+ * On machines where Datum is 8 bytes, we support fetching 8-byte byval
+ * attributes; otherwise, only 1, 2, and 4-byte values are supported.
+ *
+ * Note that T must already be properly aligned for this to work correctly.
+ */
+#define fetchatt(A,T) fetch_att(T, (A)->attbyval, (A)->attlen)
+
+/*
+ * Same, but work from byval/len parameters rather than Form_pg_attribute.
+ */
+#if SIZEOF_DATUM == 8
+
+#define fetch_att(T,attbyval,attlen) \
+( \
+ (attbyval) ? \
+ ( \
+ (attlen) == (int) sizeof(Datum) ? \
+ *((Datum *)(T)) \
+ : \
+ ( \
+ (attlen) == (int) sizeof(int32) ? \
+ Int32GetDatum(*((int32 *)(T))) \
+ : \
+ ( \
+ (attlen) == (int) sizeof(int16) ? \
+ Int16GetDatum(*((int16 *)(T))) \
+ : \
+ ( \
+ AssertMacro((attlen) == 1), \
+ CharGetDatum(*((char *)(T))) \
+ ) \
+ ) \
+ ) \
+ ) \
+ : \
+ PointerGetDatum((char *) (T)) \
+)
+#else /* SIZEOF_DATUM != 8 */
+
+#define fetch_att(T,attbyval,attlen) \
+( \
+ (attbyval) ? \
+ ( \
+ (attlen) == (int) sizeof(int32) ? \
+ Int32GetDatum(*((int32 *)(T))) \
+ : \
+ ( \
+ (attlen) == (int) sizeof(int16) ? \
+ Int16GetDatum(*((int16 *)(T))) \
+ : \
+ ( \
+ AssertMacro((attlen) == 1), \
+ CharGetDatum(*((char *)(T))) \
+ ) \
+ ) \
+ ) \
+ : \
+ PointerGetDatum((char *) (T)) \
+)
+#endif /* SIZEOF_DATUM == 8 */
+
+/*
+ * att_align_datum aligns the given offset as needed for a datum of alignment
+ * requirement attalign and typlen attlen. attdatum is the Datum variable
+ * we intend to pack into a tuple (it's only accessed if we are dealing with
+ * a varlena type). Note that this assumes the Datum will be stored as-is;
+ * callers that are intending to convert non-short varlena datums to short
+ * format have to account for that themselves.
+ */
+#define att_align_datum(cur_offset, attalign, attlen, attdatum) \
+( \
+ ((attlen) == -1 && VARATT_IS_SHORT(DatumGetPointer(attdatum))) ? \
+ (uintptr_t) (cur_offset) : \
+ att_align_nominal(cur_offset, attalign) \
+)
+
+/*
+ * att_align_pointer performs the same calculation as att_align_datum,
+ * but is used when walking a tuple. attptr is the current actual data
+ * pointer; when accessing a varlena field we have to "peek" to see if we
+ * are looking at a pad byte or the first byte of a 1-byte-header datum.
+ * (A zero byte must be either a pad byte, or the first byte of a correctly
+ * aligned 4-byte length word; in either case we can align safely. A non-zero
+ * byte must be either a 1-byte length word, or the first byte of a correctly
+ * aligned 4-byte length word; in either case we need not align.)
+ *
+ * Note: some callers pass a "char *" pointer for cur_offset. This is
+ * a bit of a hack but should work all right as long as uintptr_t is the
+ * correct width.
+ */
+#define att_align_pointer(cur_offset, attalign, attlen, attptr) \
+( \
+ ((attlen) == -1 && VARATT_NOT_PAD_BYTE(attptr)) ? \
+ (uintptr_t) (cur_offset) : \
+ att_align_nominal(cur_offset, attalign) \
+)
+
+/*
+ * att_align_nominal aligns the given offset as needed for a datum of alignment
+ * requirement attalign, ignoring any consideration of packed varlena datums.
+ * There are three main use cases for using this macro directly:
+ * * we know that the att in question is not varlena (attlen != -1);
+ * in this case it is cheaper than the above macros and just as good.
+ * * we need to estimate alignment padding cost abstractly, ie without
+ * reference to a real tuple. We must assume the worst case that
+ * all varlenas are aligned.
+ * * within arrays, we unconditionally align varlenas (XXX this should be
+ * revisited, probably).
+ *
+ * The attalign cases are tested in what is hopefully something like their
+ * frequency of occurrence.
+ */
+#define att_align_nominal(cur_offset, attalign) \
+( \
+ ((attalign) == TYPALIGN_INT) ? INTALIGN(cur_offset) : \
+ (((attalign) == TYPALIGN_CHAR) ? (uintptr_t) (cur_offset) : \
+ (((attalign) == TYPALIGN_DOUBLE) ? DOUBLEALIGN(cur_offset) : \
+ ( \
+ AssertMacro((attalign) == TYPALIGN_SHORT), \
+ SHORTALIGN(cur_offset) \
+ ))) \
+)
+
+/*
+ * att_addlength_datum increments the given offset by the space needed for
+ * the given Datum variable. attdatum is only accessed if we are dealing
+ * with a variable-length attribute.
+ */
+#define att_addlength_datum(cur_offset, attlen, attdatum) \
+ att_addlength_pointer(cur_offset, attlen, DatumGetPointer(attdatum))
+
+/*
+ * att_addlength_pointer performs the same calculation as att_addlength_datum,
+ * but is used when walking a tuple --- attptr is the pointer to the field
+ * within the tuple.
+ *
+ * Note: some callers pass a "char *" pointer for cur_offset. This is
+ * actually perfectly OK, but probably should be cleaned up along with
+ * the same practice for att_align_pointer.
+ */
+#define att_addlength_pointer(cur_offset, attlen, attptr) \
+( \
+ ((attlen) > 0) ? \
+ ( \
+ (cur_offset) + (attlen) \
+ ) \
+ : (((attlen) == -1) ? \
+ ( \
+ (cur_offset) + VARSIZE_ANY(attptr) \
+ ) \
+ : \
+ ( \
+ AssertMacro((attlen) == -2), \
+ (cur_offset) + (strlen((char *) (attptr)) + 1) \
+ )) \
+)
+
+/*
+ * store_att_byval is a partial inverse of fetch_att: store a given Datum
+ * value into a tuple data area at the specified address. However, it only
+ * handles the byval case, because in typical usage the caller needs to
+ * distinguish by-val and by-ref cases anyway, and so a do-it-all macro
+ * wouldn't be convenient.
+ */
+#if SIZEOF_DATUM == 8
+
+#define store_att_byval(T,newdatum,attlen) \
+ do { \
+ switch (attlen) \
+ { \
+ case sizeof(char): \
+ *(char *) (T) = DatumGetChar(newdatum); \
+ break; \
+ case sizeof(int16): \
+ *(int16 *) (T) = DatumGetInt16(newdatum); \
+ break; \
+ case sizeof(int32): \
+ *(int32 *) (T) = DatumGetInt32(newdatum); \
+ break; \
+ case sizeof(Datum): \
+ *(Datum *) (T) = (newdatum); \
+ break; \
+ default: \
+ elog(ERROR, "unsupported byval length: %d", \
+ (int) (attlen)); \
+ break; \
+ } \
+ } while (0)
+#else /* SIZEOF_DATUM != 8 */
+
+#define store_att_byval(T,newdatum,attlen) \
+ do { \
+ switch (attlen) \
+ { \
+ case sizeof(char): \
+ *(char *) (T) = DatumGetChar(newdatum); \
+ break; \
+ case sizeof(int16): \
+ *(int16 *) (T) = DatumGetInt16(newdatum); \
+ break; \
+ case sizeof(int32): \
+ *(int32 *) (T) = DatumGetInt32(newdatum); \
+ break; \
+ default: \
+ elog(ERROR, "unsupported byval length: %d", \
+ (int) (attlen)); \
+ break; \
+ } \
+ } while (0)
+#endif /* SIZEOF_DATUM == 8 */
+
+#endif
diff --git a/src/include/access/twophase.h b/src/include/access/twophase.h
new file mode 100644
index 0000000..2ca71c3
--- /dev/null
+++ b/src/include/access/twophase.h
@@ -0,0 +1,61 @@
+/*-------------------------------------------------------------------------
+ *
+ * twophase.h
+ * Two-phase-commit related declarations.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/twophase.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TWOPHASE_H
+#define TWOPHASE_H
+
+#include "access/xact.h"
+#include "access/xlogdefs.h"
+#include "datatype/timestamp.h"
+#include "storage/lock.h"
+
+/*
+ * GlobalTransactionData is defined in twophase.c; other places have no
+ * business knowing the internal definition.
+ */
+typedef struct GlobalTransactionData *GlobalTransaction;
+
+/* GUC variable */
+extern PGDLLIMPORT int max_prepared_xacts;
+
+extern Size TwoPhaseShmemSize(void);
+extern void TwoPhaseShmemInit(void);
+
+extern void AtAbort_Twophase(void);
+extern void PostPrepare_Twophase(void);
+
+extern PGPROC *TwoPhaseGetDummyProc(TransactionId xid, bool lock_held);
+extern BackendId TwoPhaseGetDummyBackendId(TransactionId xid, bool lock_held);
+
+extern GlobalTransaction MarkAsPreparing(TransactionId xid, const char *gid,
+ TimestampTz prepared_at,
+ Oid owner, Oid databaseid);
+
+extern void StartPrepare(GlobalTransaction gxact);
+extern void EndPrepare(GlobalTransaction gxact);
+extern bool StandbyTransactionIdIsPrepared(TransactionId xid);
+
+extern TransactionId PrescanPreparedTransactions(TransactionId **xids_p,
+ int *nxids_p);
+extern void StandbyRecoverPreparedTransactions(void);
+extern void RecoverPreparedTransactions(void);
+
+extern void CheckPointTwoPhase(XLogRecPtr redo_horizon);
+
+extern void FinishPreparedTransaction(const char *gid, bool isCommit);
+
+extern void PrepareRedoAdd(char *buf, XLogRecPtr start_lsn,
+ XLogRecPtr end_lsn, RepOriginId origin_id);
+extern void PrepareRedoRemove(TransactionId xid, bool giveWarning);
+extern void restoreTwoPhaseData(void);
+#endif /* TWOPHASE_H */
diff --git a/src/include/access/twophase_rmgr.h b/src/include/access/twophase_rmgr.h
new file mode 100644
index 0000000..65986a6
--- /dev/null
+++ b/src/include/access/twophase_rmgr.h
@@ -0,0 +1,40 @@
+/*-------------------------------------------------------------------------
+ *
+ * twophase_rmgr.h
+ * Two-phase-commit resource managers definition
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/twophase_rmgr.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TWOPHASE_RMGR_H
+#define TWOPHASE_RMGR_H
+
+typedef void (*TwoPhaseCallback) (TransactionId xid, uint16 info,
+ void *recdata, uint32 len);
+typedef uint8 TwoPhaseRmgrId;
+
+/*
+ * Built-in resource managers
+ */
+#define TWOPHASE_RM_END_ID 0
+#define TWOPHASE_RM_LOCK_ID 1
+#define TWOPHASE_RM_PGSTAT_ID 2
+#define TWOPHASE_RM_MULTIXACT_ID 3
+#define TWOPHASE_RM_PREDICATELOCK_ID 4
+#define TWOPHASE_RM_MAX_ID TWOPHASE_RM_PREDICATELOCK_ID
+
+extern const TwoPhaseCallback twophase_recover_callbacks[];
+extern const TwoPhaseCallback twophase_postcommit_callbacks[];
+extern const TwoPhaseCallback twophase_postabort_callbacks[];
+extern const TwoPhaseCallback twophase_standby_recover_callbacks[];
+
+
+extern void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info,
+ const void *data, uint32 len);
+
+#endif /* TWOPHASE_RMGR_H */
diff --git a/src/include/access/valid.h b/src/include/access/valid.h
new file mode 100644
index 0000000..443d4da
--- /dev/null
+++ b/src/include/access/valid.h
@@ -0,0 +1,69 @@
+/*-------------------------------------------------------------------------
+ *
+ * valid.h
+ * POSTGRES tuple qualification validity definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/valid.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef VALID_H
+#define VALID_H
+
+/*
+ * HeapKeyTest
+ *
+ * Test a heap tuple to see if it satisfies a scan key.
+ */
+#define HeapKeyTest(tuple, \
+ tupdesc, \
+ nkeys, \
+ keys, \
+ result) \
+do \
+{ \
+ /* Use underscores to protect the variables passed in as parameters */ \
+ int __cur_nkeys = (nkeys); \
+ ScanKey __cur_keys = (keys); \
+ \
+ (result) = true; /* may change */ \
+ for (; __cur_nkeys--; __cur_keys++) \
+ { \
+ Datum __atp; \
+ bool __isnull; \
+ Datum __test; \
+ \
+ if (__cur_keys->sk_flags & SK_ISNULL) \
+ { \
+ (result) = false; \
+ break; \
+ } \
+ \
+ __atp = heap_getattr((tuple), \
+ __cur_keys->sk_attno, \
+ (tupdesc), \
+ &__isnull); \
+ \
+ if (__isnull) \
+ { \
+ (result) = false; \
+ break; \
+ } \
+ \
+ __test = FunctionCall2Coll(&__cur_keys->sk_func, \
+ __cur_keys->sk_collation, \
+ __atp, __cur_keys->sk_argument); \
+ \
+ if (!DatumGetBool(__test)) \
+ { \
+ (result) = false; \
+ break; \
+ } \
+ } \
+} while (0)
+
+#endif /* VALID_H */
diff --git a/src/include/access/visibilitymap.h b/src/include/access/visibilitymap.h
new file mode 100644
index 0000000..b462e90
--- /dev/null
+++ b/src/include/access/visibilitymap.h
@@ -0,0 +1,50 @@
+/*-------------------------------------------------------------------------
+ *
+ * visibilitymap.h
+ * visibility map interface
+ *
+ *
+ * Portions Copyright (c) 2007-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/visibilitymap.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef VISIBILITYMAP_H
+#define VISIBILITYMAP_H
+
+#include "access/xlogdefs.h"
+#include "storage/block.h"
+#include "storage/buf.h"
+#include "utils/relcache.h"
+
+/* Number of bits for one heap page */
+#define BITS_PER_HEAPBLOCK 2
+
+/* Flags for bit map */
+#define VISIBILITYMAP_ALL_VISIBLE 0x01
+#define VISIBILITYMAP_ALL_FROZEN 0x02
+#define VISIBILITYMAP_VALID_BITS 0x03 /* OR of all valid visibilitymap
+ * flags bits */
+
+/* Macros for visibilitymap test */
+#define VM_ALL_VISIBLE(r, b, v) \
+ ((visibilitymap_get_status((r), (b), (v)) & VISIBILITYMAP_ALL_VISIBLE) != 0)
+#define VM_ALL_FROZEN(r, b, v) \
+ ((visibilitymap_get_status((r), (b), (v)) & VISIBILITYMAP_ALL_FROZEN) != 0)
+
+extern bool visibilitymap_clear(Relation rel, BlockNumber heapBlk,
+ Buffer vmbuf, uint8 flags);
+extern void visibilitymap_pin(Relation rel, BlockNumber heapBlk,
+ Buffer *vmbuf);
+extern bool visibilitymap_pin_ok(BlockNumber heapBlk, Buffer vmbuf);
+extern void visibilitymap_set(Relation rel, BlockNumber heapBlk, Buffer heapBuf,
+ XLogRecPtr recptr, Buffer vmBuf, TransactionId cutoff_xid,
+ uint8 flags);
+extern uint8 visibilitymap_get_status(Relation rel, BlockNumber heapBlk, Buffer *vmbuf);
+extern void visibilitymap_count(Relation rel, BlockNumber *all_visible, BlockNumber *all_frozen);
+extern BlockNumber visibilitymap_prepare_truncate(Relation rel,
+ BlockNumber nheapblocks);
+
+#endif /* VISIBILITYMAP_H */
diff --git a/src/include/access/xact.h b/src/include/access/xact.h
new file mode 100644
index 0000000..3c66119
--- /dev/null
+++ b/src/include/access/xact.h
@@ -0,0 +1,463 @@
+/*-------------------------------------------------------------------------
+ *
+ * xact.h
+ * postgres transaction system definitions
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/xact.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef XACT_H
+#define XACT_H
+
+#include "access/transam.h"
+#include "access/xlogreader.h"
+#include "lib/stringinfo.h"
+#include "nodes/pg_list.h"
+#include "storage/relfilenode.h"
+#include "storage/sinval.h"
+#include "utils/datetime.h"
+
+/*
+ * Maximum size of Global Transaction ID (including '\0').
+ *
+ * Note that the max value of GIDSIZE must fit in the uint16 gidlen,
+ * specified in TwoPhaseFileHeader.
+ */
+#define GIDSIZE 200
+
+/*
+ * Xact isolation levels
+ */
+#define XACT_READ_UNCOMMITTED 0
+#define XACT_READ_COMMITTED 1
+#define XACT_REPEATABLE_READ 2
+#define XACT_SERIALIZABLE 3
+
+extern int DefaultXactIsoLevel;
+extern PGDLLIMPORT int XactIsoLevel;
+
+/*
+ * We implement three isolation levels internally.
+ * The two stronger ones use one snapshot per database transaction;
+ * the others use one snapshot per statement.
+ * Serializable uses predicate locks in addition to snapshots.
+ * These macros should be used to check which isolation level is selected.
+ */
+#define IsolationUsesXactSnapshot() (XactIsoLevel >= XACT_REPEATABLE_READ)
+#define IsolationIsSerializable() (XactIsoLevel == XACT_SERIALIZABLE)
+
+/* Xact read-only state */
+extern bool DefaultXactReadOnly;
+extern bool XactReadOnly;
+
+/* flag for logging statements in this transaction */
+extern bool xact_is_sampled;
+
+/*
+ * Xact is deferrable -- only meaningful (currently) for read only
+ * SERIALIZABLE transactions
+ */
+extern bool DefaultXactDeferrable;
+extern bool XactDeferrable;
+
+typedef enum
+{
+ SYNCHRONOUS_COMMIT_OFF, /* asynchronous commit */
+ SYNCHRONOUS_COMMIT_LOCAL_FLUSH, /* wait for local flush only */
+ SYNCHRONOUS_COMMIT_REMOTE_WRITE, /* wait for local flush and remote
+ * write */
+ SYNCHRONOUS_COMMIT_REMOTE_FLUSH, /* wait for local and remote flush */
+ SYNCHRONOUS_COMMIT_REMOTE_APPLY /* wait for local and remote flush
+ and remote apply */
+} SyncCommitLevel;
+
+/* Define the default setting for synchronous_commit */
+#define SYNCHRONOUS_COMMIT_ON SYNCHRONOUS_COMMIT_REMOTE_FLUSH
+
+/* Synchronous commit level */
+extern int synchronous_commit;
+
+/*
+ * Miscellaneous flag bits to record events which occur on the top level
+ * transaction. These flags are only persisted in MyXactFlags and are intended
+ * so we remember to do certain things later in the transaction. This is
+ * globally accessible, so can be set from anywhere in the code which requires
+ * recording flags.
+ */
+extern int MyXactFlags;
+
+/*
+ * XACT_FLAGS_ACCESSEDTEMPNAMESPACE - set when a temporary object is accessed.
+ * We don't allow PREPARE TRANSACTION in that case.
+ */
+#define XACT_FLAGS_ACCESSEDTEMPNAMESPACE (1U << 0)
+
+/*
+ * XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK - records whether the top level xact
+ * logged any Access Exclusive Locks.
+ */
+#define XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK (1U << 1)
+
+/*
+ * start- and end-of-transaction callbacks for dynamically loaded modules
+ */
+typedef enum
+{
+ XACT_EVENT_COMMIT,
+ XACT_EVENT_PARALLEL_COMMIT,
+ XACT_EVENT_ABORT,
+ XACT_EVENT_PARALLEL_ABORT,
+ XACT_EVENT_PREPARE,
+ XACT_EVENT_PRE_COMMIT,
+ XACT_EVENT_PARALLEL_PRE_COMMIT,
+ XACT_EVENT_PRE_PREPARE
+} XactEvent;
+
+typedef void (*XactCallback) (XactEvent event, void *arg);
+
+typedef enum
+{
+ SUBXACT_EVENT_START_SUB,
+ SUBXACT_EVENT_COMMIT_SUB,
+ SUBXACT_EVENT_ABORT_SUB,
+ SUBXACT_EVENT_PRE_COMMIT_SUB
+} SubXactEvent;
+
+typedef void (*SubXactCallback) (SubXactEvent event, SubTransactionId mySubid,
+ SubTransactionId parentSubid, void *arg);
+
+
+/* ----------------
+ * transaction-related XLOG entries
+ * ----------------
+ */
+
+/*
+ * XLOG allows to store some information in high 4 bits of log record xl_info
+ * field. We use 3 for the opcode, and one about an optional flag variable.
+ */
+#define XLOG_XACT_COMMIT 0x00
+#define XLOG_XACT_PREPARE 0x10
+#define XLOG_XACT_ABORT 0x20
+#define XLOG_XACT_COMMIT_PREPARED 0x30
+#define XLOG_XACT_ABORT_PREPARED 0x40
+#define XLOG_XACT_ASSIGNMENT 0x50
+/* free opcode 0x60 */
+/* free opcode 0x70 */
+
+/* mask for filtering opcodes out of xl_info */
+#define XLOG_XACT_OPMASK 0x70
+
+/* does this record have a 'xinfo' field or not */
+#define XLOG_XACT_HAS_INFO 0x80
+
+/*
+ * The following flags, stored in xinfo, determine which information is
+ * contained in commit/abort records.
+ */
+#define XACT_XINFO_HAS_DBINFO (1U << 0)
+#define XACT_XINFO_HAS_SUBXACTS (1U << 1)
+#define XACT_XINFO_HAS_RELFILENODES (1U << 2)
+#define XACT_XINFO_HAS_INVALS (1U << 3)
+#define XACT_XINFO_HAS_TWOPHASE (1U << 4)
+#define XACT_XINFO_HAS_ORIGIN (1U << 5)
+#define XACT_XINFO_HAS_AE_LOCKS (1U << 6)
+#define XACT_XINFO_HAS_GID (1U << 7)
+
+/*
+ * Also stored in xinfo, these indicating a variety of additional actions that
+ * need to occur when emulating transaction effects during recovery.
+ *
+ * They are named XactCompletion... to differentiate them from
+ * EOXact... routines which run at the end of the original transaction
+ * completion.
+ */
+#define XACT_COMPLETION_APPLY_FEEDBACK (1U << 29)
+#define XACT_COMPLETION_UPDATE_RELCACHE_FILE (1U << 30)
+#define XACT_COMPLETION_FORCE_SYNC_COMMIT (1U << 31)
+
+/* Access macros for above flags */
+#define XactCompletionApplyFeedback(xinfo) \
+ ((xinfo & XACT_COMPLETION_APPLY_FEEDBACK) != 0)
+#define XactCompletionRelcacheInitFileInval(xinfo) \
+ ((xinfo & XACT_COMPLETION_UPDATE_RELCACHE_FILE) != 0)
+#define XactCompletionForceSyncCommit(xinfo) \
+ ((xinfo & XACT_COMPLETION_FORCE_SYNC_COMMIT) != 0)
+
+typedef struct xl_xact_assignment
+{
+ TransactionId xtop; /* assigned XID's top-level XID */
+ int nsubxacts; /* number of subtransaction XIDs */
+ TransactionId xsub[FLEXIBLE_ARRAY_MEMBER]; /* assigned subxids */
+} xl_xact_assignment;
+
+#define MinSizeOfXactAssignment offsetof(xl_xact_assignment, xsub)
+
+/*
+ * Commit and abort records can contain a lot of information. But a large
+ * portion of the records won't need all possible pieces of information. So we
+ * only include what's needed.
+ *
+ * A minimal commit/abort record only consists of a xl_xact_commit/abort
+ * struct. The presence of additional information is indicated by bits set in
+ * 'xl_xact_xinfo->xinfo'. The presence of the xinfo field itself is signaled
+ * by a set XLOG_XACT_HAS_INFO bit in the xl_info field.
+ *
+ * NB: All the individual data chunks should be sized to multiples of
+ * sizeof(int) and only require int32 alignment. If they require bigger
+ * alignment, they need to be copied upon reading.
+ */
+
+/* sub-records for commit/abort */
+
+typedef struct xl_xact_xinfo
+{
+ /*
+ * Even though we right now only require 1 byte of space in xinfo we use
+ * four so following records don't have to care about alignment. Commit
+ * records can be large, so copying large portions isn't attractive.
+ */
+ uint32 xinfo;
+} xl_xact_xinfo;
+
+typedef struct xl_xact_dbinfo
+{
+ Oid dbId; /* MyDatabaseId */
+ Oid tsId; /* MyDatabaseTableSpace */
+} xl_xact_dbinfo;
+
+typedef struct xl_xact_subxacts
+{
+ int nsubxacts; /* number of subtransaction XIDs */
+ TransactionId subxacts[FLEXIBLE_ARRAY_MEMBER];
+} xl_xact_subxacts;
+#define MinSizeOfXactSubxacts offsetof(xl_xact_subxacts, subxacts)
+
+typedef struct xl_xact_relfilenodes
+{
+ int nrels; /* number of relations */
+ RelFileNode xnodes[FLEXIBLE_ARRAY_MEMBER];
+} xl_xact_relfilenodes;
+#define MinSizeOfXactRelfilenodes offsetof(xl_xact_relfilenodes, xnodes)
+
+typedef struct xl_xact_invals
+{
+ int nmsgs; /* number of shared inval msgs */
+ SharedInvalidationMessage msgs[FLEXIBLE_ARRAY_MEMBER];
+} xl_xact_invals;
+#define MinSizeOfXactInvals offsetof(xl_xact_invals, msgs)
+
+typedef struct xl_xact_twophase
+{
+ TransactionId xid;
+} xl_xact_twophase;
+
+typedef struct xl_xact_origin
+{
+ XLogRecPtr origin_lsn;
+ TimestampTz origin_timestamp;
+} xl_xact_origin;
+
+typedef struct xl_xact_commit
+{
+ TimestampTz xact_time; /* time of commit */
+
+ /* xl_xact_xinfo follows if XLOG_XACT_HAS_INFO */
+ /* xl_xact_dbinfo follows if XINFO_HAS_DBINFO */
+ /* xl_xact_subxacts follows if XINFO_HAS_SUBXACT */
+ /* xl_xact_relfilenodes follows if XINFO_HAS_RELFILENODES */
+ /* xl_xact_invals follows if XINFO_HAS_INVALS */
+ /* xl_xact_twophase follows if XINFO_HAS_TWOPHASE */
+ /* twophase_gid follows if XINFO_HAS_GID. As a null-terminated string. */
+ /* xl_xact_origin follows if XINFO_HAS_ORIGIN, stored unaligned! */
+} xl_xact_commit;
+#define MinSizeOfXactCommit (offsetof(xl_xact_commit, xact_time) + sizeof(TimestampTz))
+
+typedef struct xl_xact_abort
+{
+ TimestampTz xact_time; /* time of abort */
+
+ /* xl_xact_xinfo follows if XLOG_XACT_HAS_INFO */
+ /* xl_xact_dbinfo follows if XINFO_HAS_DBINFO */
+ /* xl_xact_subxacts follows if XINFO_HAS_SUBXACT */
+ /* xl_xact_relfilenodes follows if XINFO_HAS_RELFILENODES */
+ /* No invalidation messages needed. */
+ /* xl_xact_twophase follows if XINFO_HAS_TWOPHASE */
+ /* twophase_gid follows if XINFO_HAS_GID. As a null-terminated string. */
+ /* xl_xact_origin follows if XINFO_HAS_ORIGIN, stored unaligned! */
+} xl_xact_abort;
+#define MinSizeOfXactAbort sizeof(xl_xact_abort)
+
+typedef struct xl_xact_prepare
+{
+ uint32 magic; /* format identifier */
+ uint32 total_len; /* actual file length */
+ TransactionId xid; /* original transaction XID */
+ Oid database; /* OID of database it was in */
+ TimestampTz prepared_at; /* time of preparation */
+ Oid owner; /* user running the transaction */
+ int32 nsubxacts; /* number of following subxact XIDs */
+ int32 ncommitrels; /* number of delete-on-commit rels */
+ int32 nabortrels; /* number of delete-on-abort rels */
+ int32 ninvalmsgs; /* number of cache invalidation messages */
+ bool initfileinval; /* does relcache init file need invalidation? */
+ uint16 gidlen; /* length of the GID - GID follows the header */
+ XLogRecPtr origin_lsn; /* lsn of this record at origin node */
+ TimestampTz origin_timestamp; /* time of prepare at origin node */
+} xl_xact_prepare;
+
+/*
+ * Commit/Abort records in the above form are a bit verbose to parse, so
+ * there's a deconstructed versions generated by ParseCommit/AbortRecord() for
+ * easier consumption.
+ */
+typedef struct xl_xact_parsed_commit
+{
+ TimestampTz xact_time;
+ uint32 xinfo;
+
+ Oid dbId; /* MyDatabaseId */
+ Oid tsId; /* MyDatabaseTableSpace */
+
+ int nsubxacts;
+ TransactionId *subxacts;
+
+ int nrels;
+ RelFileNode *xnodes;
+
+ int nmsgs;
+ SharedInvalidationMessage *msgs;
+
+ TransactionId twophase_xid; /* only for 2PC */
+ char twophase_gid[GIDSIZE]; /* only for 2PC */
+ int nabortrels; /* only for 2PC */
+ RelFileNode *abortnodes; /* only for 2PC */
+
+ XLogRecPtr origin_lsn;
+ TimestampTz origin_timestamp;
+} xl_xact_parsed_commit;
+
+typedef xl_xact_parsed_commit xl_xact_parsed_prepare;
+
+typedef struct xl_xact_parsed_abort
+{
+ TimestampTz xact_time;
+ uint32 xinfo;
+
+ Oid dbId; /* MyDatabaseId */
+ Oid tsId; /* MyDatabaseTableSpace */
+
+ int nsubxacts;
+ TransactionId *subxacts;
+
+ int nrels;
+ RelFileNode *xnodes;
+
+ TransactionId twophase_xid; /* only for 2PC */
+ char twophase_gid[GIDSIZE]; /* only for 2PC */
+
+ XLogRecPtr origin_lsn;
+ TimestampTz origin_timestamp;
+} xl_xact_parsed_abort;
+
+
+/* ----------------
+ * extern definitions
+ * ----------------
+ */
+extern bool IsTransactionState(void);
+extern bool IsAbortedTransactionBlockState(void);
+extern TransactionId GetTopTransactionId(void);
+extern TransactionId GetTopTransactionIdIfAny(void);
+extern TransactionId GetCurrentTransactionId(void);
+extern TransactionId GetCurrentTransactionIdIfAny(void);
+extern TransactionId GetStableLatestTransactionId(void);
+extern SubTransactionId GetCurrentSubTransactionId(void);
+extern FullTransactionId GetTopFullTransactionId(void);
+extern FullTransactionId GetTopFullTransactionIdIfAny(void);
+extern FullTransactionId GetCurrentFullTransactionId(void);
+extern FullTransactionId GetCurrentFullTransactionIdIfAny(void);
+extern void MarkCurrentTransactionIdLoggedIfAny(void);
+extern bool SubTransactionIsActive(SubTransactionId subxid);
+extern CommandId GetCurrentCommandId(bool used);
+extern void SetParallelStartTimestamps(TimestampTz xact_ts, TimestampTz stmt_ts);
+extern TimestampTz GetCurrentTransactionStartTimestamp(void);
+extern TimestampTz GetCurrentStatementStartTimestamp(void);
+extern TimestampTz GetCurrentTransactionStopTimestamp(void);
+extern void SetCurrentStatementStartTimestamp(void);
+extern int GetCurrentTransactionNestLevel(void);
+extern bool TransactionIdIsCurrentTransactionId(TransactionId xid);
+extern void CommandCounterIncrement(void);
+extern void ForceSyncCommit(void);
+extern void StartTransactionCommand(void);
+extern void SaveTransactionCharacteristics(void);
+extern void RestoreTransactionCharacteristics(void);
+extern void CommitTransactionCommand(void);
+extern void AbortCurrentTransaction(void);
+extern void BeginTransactionBlock(void);
+extern bool EndTransactionBlock(bool chain);
+extern bool PrepareTransactionBlock(const char *gid);
+extern void UserAbortTransactionBlock(bool chain);
+extern void BeginImplicitTransactionBlock(void);
+extern void EndImplicitTransactionBlock(void);
+extern void ReleaseSavepoint(const char *name);
+extern void DefineSavepoint(const char *name);
+extern void RollbackToSavepoint(const char *name);
+extern void BeginInternalSubTransaction(const char *name);
+extern void ReleaseCurrentSubTransaction(void);
+extern void RollbackAndReleaseCurrentSubTransaction(void);
+extern bool IsSubTransaction(void);
+extern Size EstimateTransactionStateSpace(void);
+extern void SerializeTransactionState(Size maxsize, char *start_address);
+extern void StartParallelWorkerTransaction(char *tstatespace);
+extern void EndParallelWorkerTransaction(void);
+extern bool IsTransactionBlock(void);
+extern bool IsTransactionOrTransactionBlock(void);
+extern char TransactionBlockStatusCode(void);
+extern void AbortOutOfAnyTransaction(void);
+extern void PreventInTransactionBlock(bool isTopLevel, const char *stmtType);
+extern void RequireTransactionBlock(bool isTopLevel, const char *stmtType);
+extern void WarnNoTransactionBlock(bool isTopLevel, const char *stmtType);
+extern bool IsInTransactionBlock(bool isTopLevel);
+extern void RegisterXactCallback(XactCallback callback, void *arg);
+extern void UnregisterXactCallback(XactCallback callback, void *arg);
+extern void RegisterSubXactCallback(SubXactCallback callback, void *arg);
+extern void UnregisterSubXactCallback(SubXactCallback callback, void *arg);
+
+extern int xactGetCommittedChildren(TransactionId **ptr);
+
+extern XLogRecPtr XactLogCommitRecord(TimestampTz commit_time,
+ int nsubxacts, TransactionId *subxacts,
+ int nrels, RelFileNode *rels,
+ int nmsgs, SharedInvalidationMessage *msgs,
+ bool relcacheInval, bool forceSync,
+ int xactflags,
+ TransactionId twophase_xid,
+ const char *twophase_gid);
+
+extern XLogRecPtr XactLogAbortRecord(TimestampTz abort_time,
+ int nsubxacts, TransactionId *subxacts,
+ int nrels, RelFileNode *rels,
+ int xactflags, TransactionId twophase_xid,
+ const char *twophase_gid);
+extern void xact_redo(XLogReaderState *record);
+
+/* xactdesc.c */
+extern void xact_desc(StringInfo buf, XLogReaderState *record);
+extern const char *xact_identify(uint8 info);
+
+/* also in xactdesc.c, so they can be shared between front/backend code */
+extern void ParseCommitRecord(uint8 info, xl_xact_commit *xlrec, xl_xact_parsed_commit *parsed);
+extern void ParseAbortRecord(uint8 info, xl_xact_abort *xlrec, xl_xact_parsed_abort *parsed);
+extern void ParsePrepareRecord(uint8 info, xl_xact_prepare *xlrec, xl_xact_parsed_prepare *parsed);
+
+extern void EnterParallelMode(void);
+extern void ExitParallelMode(void);
+extern bool IsInParallelMode(void);
+
+#endif /* XACT_H */
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
new file mode 100644
index 0000000..01b3b0a
--- /dev/null
+++ b/src/include/access/xlog.h
@@ -0,0 +1,398 @@
+/*
+ * xlog.h
+ *
+ * PostgreSQL write-ahead log manager
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/xlog.h
+ */
+#ifndef XLOG_H
+#define XLOG_H
+
+#include "access/rmgr.h"
+#include "access/xlogdefs.h"
+#include "access/xloginsert.h"
+#include "access/xlogreader.h"
+#include "datatype/timestamp.h"
+#include "lib/stringinfo.h"
+#include "nodes/pg_list.h"
+#include "storage/fd.h"
+
+
+/* Sync methods */
+#define SYNC_METHOD_FSYNC 0
+#define SYNC_METHOD_FDATASYNC 1
+#define SYNC_METHOD_OPEN 2 /* for O_SYNC */
+#define SYNC_METHOD_FSYNC_WRITETHROUGH 3
+#define SYNC_METHOD_OPEN_DSYNC 4 /* for O_DSYNC */
+extern int sync_method;
+
+extern PGDLLIMPORT TimeLineID ThisTimeLineID; /* current TLI */
+
+/*
+ * Prior to 8.4, all activity during recovery was carried out by the startup
+ * process. This local variable continues to be used in many parts of the
+ * code to indicate actions taken by RecoveryManagers. Other processes that
+ * potentially perform work during recovery should check RecoveryInProgress().
+ * See XLogCtl notes in xlog.c.
+ */
+extern bool InRecovery;
+
+/*
+ * Like InRecovery, standbyState is only valid in the startup process.
+ * In all other processes it will have the value STANDBY_DISABLED (so
+ * InHotStandby will read as false).
+ *
+ * In DISABLED state, we're performing crash recovery or hot standby was
+ * disabled in postgresql.conf.
+ *
+ * In INITIALIZED state, we've run InitRecoveryTransactionEnvironment, but
+ * we haven't yet processed a RUNNING_XACTS or shutdown-checkpoint WAL record
+ * to initialize our master-transaction tracking system.
+ *
+ * When the transaction tracking is initialized, we enter the SNAPSHOT_PENDING
+ * state. The tracked information might still be incomplete, so we can't allow
+ * connections yet, but redo functions must update the in-memory state when
+ * appropriate.
+ *
+ * In SNAPSHOT_READY mode, we have full knowledge of transactions that are
+ * (or were) running in the master at the current WAL location. Snapshots
+ * can be taken, and read-only queries can be run.
+ */
+typedef enum
+{
+ STANDBY_DISABLED,
+ STANDBY_INITIALIZED,
+ STANDBY_SNAPSHOT_PENDING,
+ STANDBY_SNAPSHOT_READY
+} HotStandbyState;
+
+extern HotStandbyState standbyState;
+
+#define InHotStandby (standbyState >= STANDBY_SNAPSHOT_PENDING)
+
+/*
+ * Recovery target type.
+ * Only set during a Point in Time recovery, not when in standby mode.
+ */
+typedef enum
+{
+ RECOVERY_TARGET_UNSET,
+ RECOVERY_TARGET_XID,
+ RECOVERY_TARGET_TIME,
+ RECOVERY_TARGET_NAME,
+ RECOVERY_TARGET_LSN,
+ RECOVERY_TARGET_IMMEDIATE
+} RecoveryTargetType;
+
+/*
+ * Recovery target TimeLine goal
+ */
+typedef enum
+{
+ RECOVERY_TARGET_TIMELINE_CONTROLFILE,
+ RECOVERY_TARGET_TIMELINE_LATEST,
+ RECOVERY_TARGET_TIMELINE_NUMERIC
+} RecoveryTargetTimeLineGoal;
+
+extern XLogRecPtr ProcLastRecPtr;
+extern XLogRecPtr XactLastRecEnd;
+extern PGDLLIMPORT XLogRecPtr XactLastCommitEnd;
+
+extern bool reachedConsistency;
+
+/* these variables are GUC parameters related to XLOG */
+extern int wal_segment_size;
+extern int min_wal_size_mb;
+extern int max_wal_size_mb;
+extern int wal_keep_size_mb;
+extern int max_slot_wal_keep_size_mb;
+extern int XLOGbuffers;
+extern int XLogArchiveTimeout;
+extern int wal_retrieve_retry_interval;
+extern char *XLogArchiveCommand;
+extern bool EnableHotStandby;
+extern bool fullPageWrites;
+extern bool wal_log_hints;
+extern bool wal_compression;
+extern bool wal_init_zero;
+extern bool wal_recycle;
+extern bool *wal_consistency_checking;
+extern char *wal_consistency_checking_string;
+extern bool log_checkpoints;
+extern char *recoveryRestoreCommand;
+extern char *recoveryEndCommand;
+extern char *archiveCleanupCommand;
+extern bool recoveryTargetInclusive;
+extern int recoveryTargetAction;
+extern int recovery_min_apply_delay;
+extern char *PrimaryConnInfo;
+extern char *PrimarySlotName;
+extern bool wal_receiver_create_temp_slot;
+
+/* indirectly set via GUC system */
+extern TransactionId recoveryTargetXid;
+extern char *recovery_target_time_string;
+extern const char *recoveryTargetName;
+extern XLogRecPtr recoveryTargetLSN;
+extern RecoveryTargetType recoveryTarget;
+extern char *PromoteTriggerFile;
+extern RecoveryTargetTimeLineGoal recoveryTargetTimeLineGoal;
+extern TimeLineID recoveryTargetTLIRequested;
+extern TimeLineID recoveryTargetTLI;
+
+extern int CheckPointSegments;
+
+/* option set locally in startup process only when signal files exist */
+extern bool StandbyModeRequested;
+extern bool StandbyMode;
+
+/* Archive modes */
+typedef enum ArchiveMode
+{
+ ARCHIVE_MODE_OFF = 0, /* disabled */
+ ARCHIVE_MODE_ON, /* enabled while server is running normally */
+ ARCHIVE_MODE_ALWAYS /* enabled always (even during recovery) */
+} ArchiveMode;
+extern int XLogArchiveMode;
+
+/* WAL levels */
+typedef enum WalLevel
+{
+ WAL_LEVEL_MINIMAL = 0,
+ WAL_LEVEL_REPLICA,
+ WAL_LEVEL_LOGICAL
+} WalLevel;
+
+/* Recovery states */
+typedef enum RecoveryState
+{
+ RECOVERY_STATE_CRASH = 0, /* crash recovery */
+ RECOVERY_STATE_ARCHIVE, /* archive recovery */
+ RECOVERY_STATE_DONE /* currently in production */
+} RecoveryState;
+
+extern PGDLLIMPORT int wal_level;
+
+/* Is WAL archiving enabled (always or only while server is running normally)? */
+#define XLogArchivingActive() \
+ (AssertMacro(XLogArchiveMode == ARCHIVE_MODE_OFF || wal_level >= WAL_LEVEL_REPLICA), XLogArchiveMode > ARCHIVE_MODE_OFF)
+/* Is WAL archiving enabled always (even during recovery)? */
+#define XLogArchivingAlways() \
+ (AssertMacro(XLogArchiveMode == ARCHIVE_MODE_OFF || wal_level >= WAL_LEVEL_REPLICA), XLogArchiveMode == ARCHIVE_MODE_ALWAYS)
+#define XLogArchiveCommandSet() (XLogArchiveCommand[0] != '\0')
+
+/*
+ * Is WAL-logging necessary for archival or log-shipping, or can we skip
+ * WAL-logging if we fsync() the data before committing instead?
+ */
+#define XLogIsNeeded() (wal_level >= WAL_LEVEL_REPLICA)
+
+/*
+ * Is a full-page image needed for hint bit updates?
+ *
+ * Normally, we don't WAL-log hint bit updates, but if checksums are enabled,
+ * we have to protect them against torn page writes. When you only set
+ * individual bits on a page, it's still consistent no matter what combination
+ * of the bits make it to disk, but the checksum wouldn't match. Also WAL-log
+ * them if forced by wal_log_hints=on.
+ */
+#define XLogHintBitIsNeeded() (DataChecksumsEnabled() || wal_log_hints)
+
+/* Do we need to WAL-log information required only for Hot Standby and logical replication? */
+#define XLogStandbyInfoActive() (wal_level >= WAL_LEVEL_REPLICA)
+
+/* Do we need to WAL-log information required only for logical replication? */
+#define XLogLogicalInfoActive() (wal_level >= WAL_LEVEL_LOGICAL)
+
+#ifdef WAL_DEBUG
+extern bool XLOG_DEBUG;
+#endif
+
+/*
+ * OR-able request flag bits for checkpoints. The "cause" bits are used only
+ * for logging purposes. Note: the flags must be defined so that it's
+ * sensible to OR together request flags arising from different requestors.
+ */
+
+/* These directly affect the behavior of CreateCheckPoint and subsidiaries */
+#define CHECKPOINT_IS_SHUTDOWN 0x0001 /* Checkpoint is for shutdown */
+#define CHECKPOINT_END_OF_RECOVERY 0x0002 /* Like shutdown checkpoint, but
+ * issued at end of WAL recovery */
+#define CHECKPOINT_IMMEDIATE 0x0004 /* Do it without delays */
+#define CHECKPOINT_FORCE 0x0008 /* Force even if no activity */
+#define CHECKPOINT_FLUSH_ALL 0x0010 /* Flush all pages, including those
+ * belonging to unlogged tables */
+/* These are important to RequestCheckpoint */
+#define CHECKPOINT_WAIT 0x0020 /* Wait for completion */
+#define CHECKPOINT_REQUESTED 0x0040 /* Checkpoint request has been made */
+/* These indicate the cause of a checkpoint request */
+#define CHECKPOINT_CAUSE_XLOG 0x0080 /* XLOG consumption */
+#define CHECKPOINT_CAUSE_TIME 0x0100 /* Elapsed time */
+
+/*
+ * Flag bits for the record being inserted, set using XLogSetRecordFlags().
+ */
+#define XLOG_INCLUDE_ORIGIN 0x01 /* include the replication origin */
+#define XLOG_MARK_UNIMPORTANT 0x02 /* record not important for durability */
+
+
+/* Checkpoint statistics */
+typedef struct CheckpointStatsData
+{
+ TimestampTz ckpt_start_t; /* start of checkpoint */
+ TimestampTz ckpt_write_t; /* start of flushing buffers */
+ TimestampTz ckpt_sync_t; /* start of fsyncs */
+ TimestampTz ckpt_sync_end_t; /* end of fsyncs */
+ TimestampTz ckpt_end_t; /* end of checkpoint */
+
+ int ckpt_bufs_written; /* # of buffers written */
+
+ int ckpt_segs_added; /* # of new xlog segments created */
+ int ckpt_segs_removed; /* # of xlog segments deleted */
+ int ckpt_segs_recycled; /* # of xlog segments recycled */
+
+ int ckpt_sync_rels; /* # of relations synced */
+ uint64 ckpt_longest_sync; /* Longest sync for one relation */
+ uint64 ckpt_agg_sync_time; /* The sum of all the individual sync
+ * times, which is not necessarily the
+ * same as the total elapsed time for the
+ * entire sync phase. */
+} CheckpointStatsData;
+
+extern CheckpointStatsData CheckpointStats;
+
+/*
+ * GetWALAvailability return codes
+ */
+typedef enum WALAvailability
+{
+ WALAVAIL_INVALID_LSN, /* parameter error */
+ WALAVAIL_RESERVED, /* WAL segment is within max_wal_size */
+ WALAVAIL_EXTENDED, /* WAL segment is reserved by a slot or
+ * wal_keep_size */
+ WALAVAIL_UNRESERVED, /* no longer reserved, but not removed yet */
+ WALAVAIL_REMOVED /* WAL segment has been removed */
+} WALAvailability;
+
+struct XLogRecData;
+
+extern XLogRecPtr XLogInsertRecord(struct XLogRecData *rdata,
+ XLogRecPtr fpw_lsn,
+ uint8 flags,
+ int num_fpi);
+extern void XLogFlush(XLogRecPtr RecPtr);
+extern bool XLogBackgroundFlush(void);
+extern bool XLogNeedsFlush(XLogRecPtr RecPtr);
+extern int XLogFileInit(XLogSegNo segno, bool *use_existent, bool use_lock);
+extern int XLogFileOpen(XLogSegNo segno);
+
+extern void CheckXLogRemoved(XLogSegNo segno, TimeLineID tli);
+extern XLogSegNo XLogGetLastRemovedSegno(void);
+extern void XLogSetAsyncXactLSN(XLogRecPtr record);
+extern void XLogSetReplicationSlotMinimumLSN(XLogRecPtr lsn);
+
+extern void xlog_redo(XLogReaderState *record);
+extern void xlog_desc(StringInfo buf, XLogReaderState *record);
+extern const char *xlog_identify(uint8 info);
+
+extern void issue_xlog_fsync(int fd, XLogSegNo segno);
+
+extern bool RecoveryInProgress(void);
+extern RecoveryState GetRecoveryState(void);
+extern bool HotStandbyActive(void);
+extern bool HotStandbyActiveInReplay(void);
+extern bool XLogInsertAllowed(void);
+extern void GetXLogReceiptTime(TimestampTz *rtime, bool *fromStream);
+extern XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI);
+extern XLogRecPtr GetXLogInsertRecPtr(void);
+extern XLogRecPtr GetXLogWriteRecPtr(void);
+extern bool RecoveryIsPaused(void);
+extern void SetRecoveryPause(bool recoveryPause);
+extern TimestampTz GetLatestXTime(void);
+extern TimestampTz GetCurrentChunkReplayStartTime(void);
+
+extern void UpdateControlFile(void);
+extern uint64 GetSystemIdentifier(void);
+extern char *GetMockAuthenticationNonce(void);
+extern bool DataChecksumsEnabled(void);
+extern XLogRecPtr GetFakeLSNForUnloggedRel(void);
+extern Size XLOGShmemSize(void);
+extern void XLOGShmemInit(void);
+extern void BootStrapXLOG(void);
+extern void LocalProcessControlFile(bool reset);
+extern void StartupXLOG(void);
+extern void ShutdownXLOG(int code, Datum arg);
+extern void InitXLOGAccess(void);
+extern void CreateCheckPoint(int flags);
+extern bool CreateRestartPoint(int flags);
+extern WALAvailability GetWALAvailability(XLogRecPtr targetLSN);
+extern XLogRecPtr CalculateMaxmumSafeLSN(void);
+extern void XLogPutNextOid(Oid nextOid);
+extern XLogRecPtr XLogRestorePoint(const char *rpName);
+extern void UpdateFullPageWrites(void);
+extern void GetFullPageWriteInfo(XLogRecPtr *RedoRecPtr_p, bool *doPageWrites_p);
+extern XLogRecPtr GetRedoRecPtr(void);
+extern XLogRecPtr GetInsertRecPtr(void);
+extern XLogRecPtr GetFlushRecPtr(void);
+extern XLogRecPtr GetLastImportantRecPtr(void);
+extern void RemovePromoteSignalFiles(void);
+
+extern bool PromoteIsTriggered(void);
+extern bool CheckPromoteSignal(void);
+extern void WakeupRecovery(void);
+extern void SetWalWriterSleeping(bool sleeping);
+
+extern void StartupRequestWalReceiverRestart(void);
+extern void XLogRequestWalReceiverReply(void);
+
+extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_checkpoint_completion_target(double newval, void *extra);
+
+/*
+ * Routines to start, stop, and get status of a base backup.
+ */
+
+/*
+ * Session-level status of base backups
+ *
+ * This is used in parallel with the shared memory status to control parallel
+ * execution of base backup functions for a given session, be it a backend
+ * dedicated to replication or a normal backend connected to a database. The
+ * update of the session-level status happens at the same time as the shared
+ * memory counters to keep a consistent global and local state of the backups
+ * running.
+ */
+typedef enum SessionBackupState
+{
+ SESSION_BACKUP_NONE,
+ SESSION_BACKUP_EXCLUSIVE,
+ SESSION_BACKUP_NON_EXCLUSIVE
+} SessionBackupState;
+
+extern XLogRecPtr do_pg_start_backup(const char *backupidstr, bool fast,
+ TimeLineID *starttli_p, StringInfo labelfile,
+ List **tablespaces, StringInfo tblspcmapfile, bool infotbssize,
+ bool needtblspcmapfile);
+extern XLogRecPtr do_pg_stop_backup(char *labelfile, bool waitforarchive,
+ TimeLineID *stoptli_p);
+extern void do_pg_abort_backup(int code, Datum arg);
+extern void register_persistent_abort_backup_handler(void);
+extern SessionBackupState get_backup_status(void);
+
+/* File path names (all relative to $PGDATA) */
+#define RECOVERY_SIGNAL_FILE "recovery.signal"
+#define STANDBY_SIGNAL_FILE "standby.signal"
+#define BACKUP_LABEL_FILE "backup_label"
+#define BACKUP_LABEL_OLD "backup_label.old"
+
+#define TABLESPACE_MAP "tablespace_map"
+#define TABLESPACE_MAP_OLD "tablespace_map.old"
+
+/* files to signal promotion to primary */
+#define PROMOTE_SIGNAL_FILE "promote"
+#define FALLBACK_PROMOTE_SIGNAL_FILE "fallback_promote"
+
+#endif /* XLOG_H */
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
new file mode 100644
index 0000000..88f3d76
--- /dev/null
+++ b/src/include/access/xlog_internal.h
@@ -0,0 +1,330 @@
+/*
+ * xlog_internal.h
+ *
+ * PostgreSQL write-ahead log internal declarations
+ *
+ * NOTE: this file is intended to contain declarations useful for
+ * manipulating the XLOG files directly, but it is not supposed to be
+ * needed by rmgr routines (redo support for individual record types).
+ * So the XLogRecord typedef and associated stuff appear in xlogrecord.h.
+ *
+ * Note: This file must be includable in both frontend and backend contexts,
+ * to allow stand-alone tools like pg_receivewal to deal with WAL files.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/xlog_internal.h
+ */
+#ifndef XLOG_INTERNAL_H
+#define XLOG_INTERNAL_H
+
+#include "access/xlogdefs.h"
+#include "access/xlogreader.h"
+#include "datatype/timestamp.h"
+#include "lib/stringinfo.h"
+#include "pgtime.h"
+#include "storage/block.h"
+#include "storage/relfilenode.h"
+
+
+/*
+ * Each page of XLOG file has a header like this:
+ */
+#define XLOG_PAGE_MAGIC 0xD106 /* can be used as WAL version indicator */
+
+typedef struct XLogPageHeaderData
+{
+ uint16 xlp_magic; /* magic value for correctness checks */
+ uint16 xlp_info; /* flag bits, see below */
+ TimeLineID xlp_tli; /* TimeLineID of first record on page */
+ XLogRecPtr xlp_pageaddr; /* XLOG address of this page */
+
+ /*
+ * When there is not enough space on current page for whole record, we
+ * continue on the next page. xlp_rem_len is the number of bytes
+ * remaining from a previous page.
+ *
+ * Note that xlp_rem_len includes backup-block data; that is, it tracks
+ * xl_tot_len not xl_len in the initial header. Also note that the
+ * continuation data isn't necessarily aligned.
+ */
+ uint32 xlp_rem_len; /* total len of remaining data for record */
+} XLogPageHeaderData;
+
+#define SizeOfXLogShortPHD MAXALIGN(sizeof(XLogPageHeaderData))
+
+typedef XLogPageHeaderData *XLogPageHeader;
+
+/*
+ * When the XLP_LONG_HEADER flag is set, we store additional fields in the
+ * page header. (This is ordinarily done just in the first page of an
+ * XLOG file.) The additional fields serve to identify the file accurately.
+ */
+typedef struct XLogLongPageHeaderData
+{
+ XLogPageHeaderData std; /* standard header fields */
+ uint64 xlp_sysid; /* system identifier from pg_control */
+ uint32 xlp_seg_size; /* just as a cross-check */
+ uint32 xlp_xlog_blcksz; /* just as a cross-check */
+} XLogLongPageHeaderData;
+
+#define SizeOfXLogLongPHD MAXALIGN(sizeof(XLogLongPageHeaderData))
+
+typedef XLogLongPageHeaderData *XLogLongPageHeader;
+
+/* When record crosses page boundary, set this flag in new page's header */
+#define XLP_FIRST_IS_CONTRECORD 0x0001
+/* This flag indicates a "long" page header */
+#define XLP_LONG_HEADER 0x0002
+/* This flag indicates backup blocks starting in this page are optional */
+#define XLP_BKP_REMOVABLE 0x0004
+/* All defined flag bits in xlp_info (used for validity checking of header) */
+#define XLP_ALL_FLAGS 0x0007
+
+#define XLogPageHeaderSize(hdr) \
+ (((hdr)->xlp_info & XLP_LONG_HEADER) ? SizeOfXLogLongPHD : SizeOfXLogShortPHD)
+
+/* wal_segment_size can range from 1MB to 1GB */
+#define WalSegMinSize 1024 * 1024
+#define WalSegMaxSize 1024 * 1024 * 1024
+/* default number of min and max wal segments */
+#define DEFAULT_MIN_WAL_SEGS 5
+#define DEFAULT_MAX_WAL_SEGS 64
+
+/* check that the given size is a valid wal_segment_size */
+#define IsPowerOf2(x) (x > 0 && ((x) & ((x)-1)) == 0)
+#define IsValidWalSegSize(size) \
+ (IsPowerOf2(size) && \
+ ((size) >= WalSegMinSize && (size) <= WalSegMaxSize))
+
+#define XLogSegmentsPerXLogId(wal_segsz_bytes) \
+ (UINT64CONST(0x100000000) / (wal_segsz_bytes))
+
+#define XLogSegNoOffsetToRecPtr(segno, offset, wal_segsz_bytes, dest) \
+ (dest) = (segno) * (wal_segsz_bytes) + (offset)
+
+#define XLogSegmentOffset(xlogptr, wal_segsz_bytes) \
+ ((xlogptr) & ((wal_segsz_bytes) - 1))
+
+/*
+ * Compute a segment number from an XLogRecPtr.
+ *
+ * For XLByteToSeg, do the computation at face value. For XLByteToPrevSeg,
+ * a boundary byte is taken to be in the previous segment. This is suitable
+ * for deciding which segment to write given a pointer to a record end,
+ * for example.
+ */
+#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes) \
+ logSegNo = (xlrp) / (wal_segsz_bytes)
+
+#define XLByteToPrevSeg(xlrp, logSegNo, wal_segsz_bytes) \
+ logSegNo = ((xlrp) - 1) / (wal_segsz_bytes)
+
+/*
+ * Convert values of GUCs measured in megabytes to equiv. segment count.
+ * Rounds down.
+ */
+#define XLogMBVarToSegs(mbvar, wal_segsz_bytes) \
+ ((mbvar) / ((wal_segsz_bytes) / (1024 * 1024)))
+
+/*
+ * Is an XLogRecPtr within a particular XLOG segment?
+ *
+ * For XLByteInSeg, do the computation at face value. For XLByteInPrevSeg,
+ * a boundary byte is taken to be in the previous segment.
+ */
+#define XLByteInSeg(xlrp, logSegNo, wal_segsz_bytes) \
+ (((xlrp) / (wal_segsz_bytes)) == (logSegNo))
+
+#define XLByteInPrevSeg(xlrp, logSegNo, wal_segsz_bytes) \
+ ((((xlrp) - 1) / (wal_segsz_bytes)) == (logSegNo))
+
+/* Check if an XLogRecPtr value is in a plausible range */
+#define XRecOffIsValid(xlrp) \
+ ((xlrp) % XLOG_BLCKSZ >= SizeOfXLogShortPHD)
+
+/*
+ * The XLog directory and control file (relative to $PGDATA)
+ */
+#define XLOGDIR "pg_wal"
+#define XLOG_CONTROL_FILE "global/pg_control"
+
+/*
+ * These macros encapsulate knowledge about the exact layout of XLog file
+ * names, timeline history file names, and archive-status file names.
+ */
+#define MAXFNAMELEN 64
+
+/* Length of XLog file name */
+#define XLOG_FNAME_LEN 24
+
+/*
+ * Generate a WAL segment file name. Do not use this macro in a helper
+ * function allocating the result generated.
+ */
+#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes) \
+ snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli, \
+ (uint32) ((logSegNo) / XLogSegmentsPerXLogId(wal_segsz_bytes)), \
+ (uint32) ((logSegNo) % XLogSegmentsPerXLogId(wal_segsz_bytes)))
+
+#define XLogFileNameById(fname, tli, log, seg) \
+ snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli, log, seg)
+
+#define IsXLogFileName(fname) \
+ (strlen(fname) == XLOG_FNAME_LEN && \
+ strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN)
+
+/*
+ * XLOG segment with .partial suffix. Used by pg_receivewal and at end of
+ * archive recovery, when we want to archive a WAL segment but it might not
+ * be complete yet.
+ */
+#define IsPartialXLogFileName(fname) \
+ (strlen(fname) == XLOG_FNAME_LEN + strlen(".partial") && \
+ strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN && \
+ strcmp((fname) + XLOG_FNAME_LEN, ".partial") == 0)
+
+#define XLogFromFileName(fname, tli, logSegNo, wal_segsz_bytes) \
+ do { \
+ uint32 log; \
+ uint32 seg; \
+ sscanf(fname, "%08X%08X%08X", tli, &log, &seg); \
+ *logSegNo = (uint64) log * XLogSegmentsPerXLogId(wal_segsz_bytes) + seg; \
+ } while (0)
+
+#define XLogFilePath(path, tli, logSegNo, wal_segsz_bytes) \
+ snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X", tli, \
+ (uint32) ((logSegNo) / XLogSegmentsPerXLogId(wal_segsz_bytes)), \
+ (uint32) ((logSegNo) % XLogSegmentsPerXLogId(wal_segsz_bytes)))
+
+#define TLHistoryFileName(fname, tli) \
+ snprintf(fname, MAXFNAMELEN, "%08X.history", tli)
+
+#define IsTLHistoryFileName(fname) \
+ (strlen(fname) == 8 + strlen(".history") && \
+ strspn(fname, "0123456789ABCDEF") == 8 && \
+ strcmp((fname) + 8, ".history") == 0)
+
+#define TLHistoryFilePath(path, tli) \
+ snprintf(path, MAXPGPATH, XLOGDIR "/%08X.history", tli)
+
+#define StatusFilePath(path, xlog, suffix) \
+ snprintf(path, MAXPGPATH, XLOGDIR "/archive_status/%s%s", xlog, suffix)
+
+#define BackupHistoryFileName(fname, tli, logSegNo, startpoint, wal_segsz_bytes) \
+ snprintf(fname, MAXFNAMELEN, "%08X%08X%08X.%08X.backup", tli, \
+ (uint32) ((logSegNo) / XLogSegmentsPerXLogId(wal_segsz_bytes)), \
+ (uint32) ((logSegNo) % XLogSegmentsPerXLogId(wal_segsz_bytes)), \
+ (uint32) (XLogSegmentOffset(startpoint, wal_segsz_bytes)))
+
+#define IsBackupHistoryFileName(fname) \
+ (strlen(fname) > XLOG_FNAME_LEN && \
+ strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN && \
+ strcmp((fname) + strlen(fname) - strlen(".backup"), ".backup") == 0)
+
+#define BackupHistoryFilePath(path, tli, logSegNo, startpoint, wal_segsz_bytes) \
+ snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X.%08X.backup", tli, \
+ (uint32) ((logSegNo) / XLogSegmentsPerXLogId(wal_segsz_bytes)), \
+ (uint32) ((logSegNo) % XLogSegmentsPerXLogId(wal_segsz_bytes)), \
+ (uint32) (XLogSegmentOffset((startpoint), wal_segsz_bytes)))
+
+/*
+ * Information logged when we detect a change in one of the parameters
+ * important for Hot Standby.
+ */
+typedef struct xl_parameter_change
+{
+ int MaxConnections;
+ int max_worker_processes;
+ int max_wal_senders;
+ int max_prepared_xacts;
+ int max_locks_per_xact;
+ int wal_level;
+ bool wal_log_hints;
+ bool track_commit_timestamp;
+} xl_parameter_change;
+
+/* logs restore point */
+typedef struct xl_restore_point
+{
+ TimestampTz rp_time;
+ char rp_name[MAXFNAMELEN];
+} xl_restore_point;
+
+/* End of recovery mark, when we don't do an END_OF_RECOVERY checkpoint */
+typedef struct xl_end_of_recovery
+{
+ TimestampTz end_time;
+ TimeLineID ThisTimeLineID; /* new TLI */
+ TimeLineID PrevTimeLineID; /* previous TLI we forked off from */
+} xl_end_of_recovery;
+
+/*
+ * The functions in xloginsert.c construct a chain of XLogRecData structs
+ * to represent the final WAL record.
+ */
+typedef struct XLogRecData
+{
+ struct XLogRecData *next; /* next struct in chain, or NULL */
+ char *data; /* start of rmgr data to include */
+ uint32 len; /* length of rmgr data to include */
+} XLogRecData;
+
+/*
+ * Recovery target action.
+ */
+typedef enum
+{
+ RECOVERY_TARGET_ACTION_PAUSE,
+ RECOVERY_TARGET_ACTION_PROMOTE,
+ RECOVERY_TARGET_ACTION_SHUTDOWN
+} RecoveryTargetAction;
+
+/*
+ * Method table for resource managers.
+ *
+ * This struct must be kept in sync with the PG_RMGR definition in
+ * rmgr.c.
+ *
+ * rm_identify must return a name for the record based on xl_info (without
+ * reference to the rmid). For example, XLOG_BTREE_VACUUM would be named
+ * "VACUUM". rm_desc can then be called to obtain additional detail for the
+ * record, if available (e.g. the last block).
+ *
+ * rm_mask takes as input a page modified by the resource manager and masks
+ * out bits that shouldn't be flagged by wal_consistency_checking.
+ *
+ * RmgrTable[] is indexed by RmgrId values (see rmgrlist.h).
+ */
+typedef struct RmgrData
+{
+ const char *rm_name;
+ void (*rm_redo) (XLogReaderState *record);
+ void (*rm_desc) (StringInfo buf, XLogReaderState *record);
+ const char *(*rm_identify) (uint8 info);
+ void (*rm_startup) (void);
+ void (*rm_cleanup) (void);
+ void (*rm_mask) (char *pagedata, BlockNumber blkno);
+} RmgrData;
+
+extern const RmgrData RmgrTable[];
+
+/*
+ * Exported to support xlog switching from checkpointer
+ */
+extern pg_time_t GetLastSegSwitchData(XLogRecPtr *lastSwitchLSN);
+extern XLogRecPtr RequestXLogSwitch(bool mark_unimportant);
+
+extern void GetOldestRestartPoint(XLogRecPtr *oldrecptr, TimeLineID *oldtli);
+
+/*
+ * Exported for the functions in timeline.c and xlogarchive.c. Only valid
+ * in the startup process.
+ */
+extern bool ArchiveRecoveryRequested;
+extern bool InArchiveRecovery;
+extern bool StandbyMode;
+extern char *recoveryRestoreCommand;
+
+#endif /* XLOG_INTERNAL_H */
diff --git a/src/include/access/xlogarchive.h b/src/include/access/xlogarchive.h
new file mode 100644
index 0000000..1c67de2
--- /dev/null
+++ b/src/include/access/xlogarchive.h
@@ -0,0 +1,35 @@
+/*------------------------------------------------------------------------
+ *
+ * xlogarchive.h
+ * Prototypes for WAL archives in the backend
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/access/xlogarchive.h
+ *
+ *------------------------------------------------------------------------
+ */
+
+#ifndef XLOG_ARCHIVE_H
+#define XLOG_ARCHIVE_H
+
+#include "access/xlogdefs.h"
+
+extern bool RestoreArchivedFile(char *path, const char *xlogfname,
+ const char *recovername, off_t expectedSize,
+ bool cleanupEnabled);
+extern void ExecuteRecoveryCommand(const char *command, const char *commandName,
+ bool failOnSignal);
+extern void KeepFileRestoredFromArchive(const char *path, const char *xlogfname);
+extern void XLogArchiveNotify(const char *xlog);
+extern void XLogArchiveNotifySeg(XLogSegNo segno);
+extern void XLogArchiveForceDone(const char *xlog);
+extern bool XLogArchiveCheckDone(const char *xlog);
+extern bool XLogArchiveIsBusy(const char *xlog);
+extern bool XLogArchiveIsReady(const char *xlog);
+extern bool XLogArchiveIsReadyOrDone(const char *xlog);
+extern void XLogArchiveCleanup(const char *xlog);
+
+#endif /* XLOG_ARCHIVE_H */
diff --git a/src/include/access/xlogdefs.h b/src/include/access/xlogdefs.h
new file mode 100644
index 0000000..e1f5812
--- /dev/null
+++ b/src/include/access/xlogdefs.h
@@ -0,0 +1,109 @@
+/*
+ * xlogdefs.h
+ *
+ * Postgres write-ahead log manager record pointer and
+ * timeline number definitions
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/xlogdefs.h
+ */
+#ifndef XLOG_DEFS_H
+#define XLOG_DEFS_H
+
+#include <fcntl.h> /* need open() flags */
+
+/*
+ * Pointer to a location in the XLOG. These pointers are 64 bits wide,
+ * because we don't want them ever to overflow.
+ */
+typedef uint64 XLogRecPtr;
+
+/*
+ * Zero is used indicate an invalid pointer. Bootstrap skips the first possible
+ * WAL segment, initializing the first WAL page at WAL segment size, so no XLOG
+ * record can begin at zero.
+ */
+#define InvalidXLogRecPtr 0
+#define XLogRecPtrIsInvalid(r) ((r) == InvalidXLogRecPtr)
+
+/*
+ * First LSN to use for "fake" LSNs.
+ *
+ * Values smaller than this can be used for special per-AM purposes.
+ */
+#define FirstNormalUnloggedLSN ((XLogRecPtr) 1000)
+
+/*
+ * XLogSegNo - physical log file sequence number.
+ */
+typedef uint64 XLogSegNo;
+
+/*
+ * TimeLineID (TLI) - identifies different database histories to prevent
+ * confusion after restoring a prior state of a database installation.
+ * TLI does not change in a normal stop/restart of the database (including
+ * crash-and-recover cases); but we must assign a new TLI after doing
+ * a recovery to a prior state, a/k/a point-in-time recovery. This makes
+ * the new WAL logfile sequence we generate distinguishable from the
+ * sequence that was generated in the previous incarnation.
+ */
+typedef uint32 TimeLineID;
+
+/*
+ * Replication origin id - this is located in this file to avoid having to
+ * include origin.h in a bunch of xlog related places.
+ */
+typedef uint16 RepOriginId;
+
+/*
+ * Because O_DIRECT bypasses the kernel buffers, and because we never
+ * read those buffers except during crash recovery or if wal_level != minimal,
+ * it is a win to use it in all cases where we sync on each write(). We could
+ * allow O_DIRECT with fsync(), but it is unclear if fsync() could process
+ * writes not buffered in the kernel. Also, O_DIRECT is never enough to force
+ * data to the drives, it merely tries to bypass the kernel cache, so we still
+ * need O_SYNC/O_DSYNC.
+ */
+#ifdef O_DIRECT
+#define PG_O_DIRECT O_DIRECT
+#else
+#define PG_O_DIRECT 0
+#endif
+
+/*
+ * This chunk of hackery attempts to determine which file sync methods
+ * are available on the current platform, and to choose an appropriate
+ * default method. We assume that fsync() is always available, and that
+ * configure determined whether fdatasync() is.
+ */
+#if defined(O_SYNC)
+#define OPEN_SYNC_FLAG O_SYNC
+#elif defined(O_FSYNC)
+#define OPEN_SYNC_FLAG O_FSYNC
+#endif
+
+#if defined(O_DSYNC)
+#if defined(OPEN_SYNC_FLAG)
+/* O_DSYNC is distinct? */
+#if O_DSYNC != OPEN_SYNC_FLAG
+#define OPEN_DATASYNC_FLAG O_DSYNC
+#endif
+#else /* !defined(OPEN_SYNC_FLAG) */
+/* Win32 only has O_DSYNC */
+#define OPEN_DATASYNC_FLAG O_DSYNC
+#endif
+#endif
+
+#if defined(PLATFORM_DEFAULT_SYNC_METHOD)
+#define DEFAULT_SYNC_METHOD PLATFORM_DEFAULT_SYNC_METHOD
+#elif defined(OPEN_DATASYNC_FLAG)
+#define DEFAULT_SYNC_METHOD SYNC_METHOD_OPEN_DSYNC
+#elif defined(HAVE_FDATASYNC)
+#define DEFAULT_SYNC_METHOD SYNC_METHOD_FDATASYNC
+#else
+#define DEFAULT_SYNC_METHOD SYNC_METHOD_FSYNC
+#endif
+
+#endif /* XLOG_DEFS_H */
diff --git a/src/include/access/xloginsert.h b/src/include/access/xloginsert.h
new file mode 100644
index 0000000..63df25a
--- /dev/null
+++ b/src/include/access/xloginsert.h
@@ -0,0 +1,64 @@
+/*
+ * xloginsert.h
+ *
+ * Functions for generating WAL records
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/xloginsert.h
+ */
+#ifndef XLOGINSERT_H
+#define XLOGINSERT_H
+
+#include "access/rmgr.h"
+#include "access/xlogdefs.h"
+#include "storage/block.h"
+#include "storage/buf.h"
+#include "storage/relfilenode.h"
+#include "utils/relcache.h"
+
+/*
+ * The minimum size of the WAL construction working area. If you need to
+ * register more than XLR_NORMAL_MAX_BLOCK_ID block references or have more
+ * than XLR_NORMAL_RDATAS data chunks in a single WAL record, you must call
+ * XLogEnsureRecordSpace() first to allocate more working memory.
+ */
+#define XLR_NORMAL_MAX_BLOCK_ID 4
+#define XLR_NORMAL_RDATAS 20
+
+/* flags for XLogRegisterBuffer */
+#define REGBUF_FORCE_IMAGE 0x01 /* force a full-page image */
+#define REGBUF_NO_IMAGE 0x02 /* don't take a full-page image */
+#define REGBUF_WILL_INIT (0x04 | 0x02) /* page will be re-initialized at
+ * replay (implies NO_IMAGE) */
+#define REGBUF_STANDARD 0x08 /* page follows "standard" page layout,
+ * (data between pd_lower and pd_upper
+ * will be skipped) */
+#define REGBUF_KEEP_DATA 0x10 /* include data even if a full-page image
+ * is taken */
+
+/* prototypes for public functions in xloginsert.c: */
+extern void XLogBeginInsert(void);
+extern void XLogSetRecordFlags(uint8 flags);
+extern XLogRecPtr XLogInsert(RmgrId rmid, uint8 info);
+extern void XLogEnsureRecordSpace(int max_block_id, int ndatas);
+extern void XLogRegisterData(char *data, int len);
+extern void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags);
+extern void XLogRegisterBlock(uint8 block_id, RelFileNode *rnode,
+ ForkNumber forknum, BlockNumber blknum, char *page,
+ uint8 flags);
+extern void XLogRegisterBufData(uint8 block_id, char *data, int len);
+extern void XLogResetInsertion(void);
+extern bool XLogCheckBufferNeedsBackup(Buffer buffer);
+
+extern XLogRecPtr log_newpage(RelFileNode *rnode, ForkNumber forkNum,
+ BlockNumber blk, char *page, bool page_std);
+extern XLogRecPtr log_newpage_buffer(Buffer buffer, bool page_std);
+extern void log_newpage_range(Relation rel, ForkNumber forkNum,
+ BlockNumber startblk, BlockNumber endblk, bool page_std);
+extern XLogRecPtr XLogSaveBufferForHint(Buffer buffer, bool buffer_std);
+
+extern void InitXLogInsert(void);
+
+#endif /* XLOGINSERT_H */
diff --git a/src/include/access/xlogreader.h b/src/include/access/xlogreader.h
new file mode 100644
index 0000000..b0f2a6e
--- /dev/null
+++ b/src/include/access/xlogreader.h
@@ -0,0 +1,327 @@
+/*-------------------------------------------------------------------------
+ *
+ * xlogreader.h
+ * Definitions for the generic XLog reading facility
+ *
+ * Portions Copyright (c) 2013-2020, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/access/xlogreader.h
+ *
+ * NOTES
+ * See the definition of the XLogReaderState struct for instructions on
+ * how to use the XLogReader infrastructure.
+ *
+ * The basic idea is to allocate an XLogReaderState via
+ * XLogReaderAllocate(), position the reader to the first record with
+ * XLogBeginRead() or XLogFindNextRecord(), and call XLogReadRecord()
+ * until it returns NULL.
+ *
+ * Callers supply a page_read callback if they want to to call
+ * XLogReadRecord or XLogFindNextRecord; it can be passed in as NULL
+ * otherwise. The WALRead function can be used as a helper to write
+ * page_read callbacks, but it is not mandatory; callers that use it,
+ * must supply segment_open callbacks. The segment_close callback
+ * must always be supplied.
+ *
+ * After reading a record with XLogReadRecord(), it's decomposed into
+ * the per-block and main data parts, and the parts can be accessed
+ * with the XLogRec* macros and functions. You can also decode a
+ * record that's already constructed in memory, without reading from
+ * disk, by calling the DecodeXLogRecord() function.
+ *-------------------------------------------------------------------------
+ */
+#ifndef XLOGREADER_H
+#define XLOGREADER_H
+
+#ifndef FRONTEND
+#include "access/transam.h"
+#endif
+
+#include "access/xlogrecord.h"
+
+/* WALOpenSegment represents a WAL segment being read. */
+typedef struct WALOpenSegment
+{
+ int ws_file; /* segment file descriptor */
+ XLogSegNo ws_segno; /* segment number */
+ TimeLineID ws_tli; /* timeline ID of the currently open file */
+} WALOpenSegment;
+
+/* WALSegmentContext carries context information about WAL segments to read */
+typedef struct WALSegmentContext
+{
+ char ws_dir[MAXPGPATH];
+ int ws_segsize;
+} WALSegmentContext;
+
+typedef struct XLogReaderState XLogReaderState;
+
+/* Function type definitions for various xlogreader interactions */
+typedef int (*XLogPageReadCB) (XLogReaderState *xlogreader,
+ XLogRecPtr targetPagePtr,
+ int reqLen,
+ XLogRecPtr targetRecPtr,
+ char *readBuf);
+typedef void (*WALSegmentOpenCB) (XLogReaderState *xlogreader,
+ XLogSegNo nextSegNo,
+ TimeLineID *tli_p);
+typedef void (*WALSegmentCloseCB) (XLogReaderState *xlogreader);
+
+typedef struct XLogReaderRoutine
+{
+ /*
+ * Data input callback
+ *
+ * This callback shall read at least reqLen valid bytes of the xlog page
+ * starting at targetPagePtr, and store them in readBuf. The callback
+ * shall return the number of bytes read (never more than XLOG_BLCKSZ), or
+ * -1 on failure. The callback shall sleep, if necessary, to wait for the
+ * requested bytes to become available. The callback will not be invoked
+ * again for the same page unless more than the returned number of bytes
+ * are needed.
+ *
+ * targetRecPtr is the position of the WAL record we're reading. Usually
+ * it is equal to targetPagePtr + reqLen, but sometimes xlogreader needs
+ * to read and verify the page or segment header, before it reads the
+ * actual WAL record it's interested in. In that case, targetRecPtr can
+ * be used to determine which timeline to read the page from.
+ *
+ * The callback shall set ->seg.ws_tli to the TLI of the file the page was
+ * read from.
+ */
+ XLogPageReadCB page_read;
+
+ /*
+ * Callback to open the specified WAL segment for reading. ->seg.ws_file
+ * shall be set to the file descriptor of the opened segment. In case of
+ * failure, an error shall be raised by the callback and it shall not
+ * return.
+ *
+ * "nextSegNo" is the number of the segment to be opened.
+ *
+ * "tli_p" is an input/output argument. WALRead() uses it to pass the
+ * timeline in which the new segment should be found, but the callback can
+ * use it to return the TLI that it actually opened.
+ */
+ WALSegmentOpenCB segment_open;
+
+ /*
+ * WAL segment close callback. ->seg.ws_file shall be set to a negative
+ * number.
+ */
+ WALSegmentCloseCB segment_close;
+} XLogReaderRoutine;
+
+#define XL_ROUTINE(...) &(XLogReaderRoutine){__VA_ARGS__}
+
+typedef struct
+{
+ /* Is this block ref in use? */
+ bool in_use;
+
+ /* Identify the block this refers to */
+ RelFileNode rnode;
+ ForkNumber forknum;
+ BlockNumber blkno;
+
+ /* copy of the fork_flags field from the XLogRecordBlockHeader */
+ uint8 flags;
+
+ /* Information on full-page image, if any */
+ bool has_image; /* has image, even for consistency checking */
+ bool apply_image; /* has image that should be restored */
+ char *bkp_image;
+ uint16 hole_offset;
+ uint16 hole_length;
+ uint16 bimg_len;
+ uint8 bimg_info;
+
+ /* Buffer holding the rmgr-specific data associated with this block */
+ bool has_data;
+ char *data;
+ uint16 data_len;
+ uint16 data_bufsz;
+} DecodedBkpBlock;
+
+struct XLogReaderState
+{
+ /*
+ * Operational callbacks
+ */
+ XLogReaderRoutine routine;
+
+ /* ----------------------------------------
+ * Public parameters
+ * ----------------------------------------
+ */
+
+ /*
+ * System identifier of the xlog files we're about to read. Set to zero
+ * (the default value) if unknown or unimportant.
+ */
+ uint64 system_identifier;
+
+ /*
+ * Opaque data for callbacks to use. Not used by XLogReader.
+ */
+ void *private_data;
+
+ /*
+ * Start and end point of last record read. EndRecPtr is also used as the
+ * position to read next. Calling XLogBeginRead() sets EndRecPtr to the
+ * starting position and ReadRecPtr to invalid.
+ */
+ XLogRecPtr ReadRecPtr; /* start of last record read */
+ XLogRecPtr EndRecPtr; /* end+1 of last record read */
+
+
+ /* ----------------------------------------
+ * Decoded representation of current record
+ *
+ * Use XLogRecGet* functions to investigate the record; these fields
+ * should not be accessed directly.
+ * ----------------------------------------
+ */
+ XLogRecord *decoded_record; /* currently decoded record */
+
+ char *main_data; /* record's main data portion */
+ uint32 main_data_len; /* main data portion's length */
+ uint32 main_data_bufsz; /* allocated size of the buffer */
+
+ RepOriginId record_origin;
+
+ /* information about blocks referenced by the record. */
+ DecodedBkpBlock blocks[XLR_MAX_BLOCK_ID + 1];
+
+ int max_block_id; /* highest block_id in use (-1 if none) */
+
+ /* ----------------------------------------
+ * private/internal state
+ * ----------------------------------------
+ */
+
+ /*
+ * Buffer for currently read page (XLOG_BLCKSZ bytes, valid up to at least
+ * readLen bytes)
+ */
+ char *readBuf;
+ uint32 readLen;
+
+ /* last read XLOG position for data currently in readBuf */
+ WALSegmentContext segcxt;
+ WALOpenSegment seg;
+ uint32 segoff;
+
+ /*
+ * beginning of prior page read, and its TLI. Doesn't necessarily
+ * correspond to what's in readBuf; used for timeline sanity checks.
+ */
+ XLogRecPtr latestPagePtr;
+ TimeLineID latestPageTLI;
+
+ /* beginning of the WAL record being read. */
+ XLogRecPtr currRecPtr;
+ /* timeline to read it from, 0 if a lookup is required */
+ TimeLineID currTLI;
+
+ /*
+ * Safe point to read to in currTLI if current TLI is historical
+ * (tliSwitchPoint) or InvalidXLogRecPtr if on current timeline.
+ *
+ * Actually set to the start of the segment containing the timeline switch
+ * that ends currTLI's validity, not the LSN of the switch its self, since
+ * we can't assume the old segment will be present.
+ */
+ XLogRecPtr currTLIValidUntil;
+
+ /*
+ * If currTLI is not the most recent known timeline, the next timeline to
+ * read from when currTLIValidUntil is reached.
+ */
+ TimeLineID nextTLI;
+
+ /*
+ * Buffer for current ReadRecord result (expandable), used when a record
+ * crosses a page boundary.
+ */
+ char *readRecordBuf;
+ uint32 readRecordBufSize;
+
+ /* Buffer to hold error message */
+ char *errormsg_buf;
+};
+
+/* Get a new XLogReader */
+extern XLogReaderState *XLogReaderAllocate(int wal_segment_size,
+ const char *waldir,
+ XLogReaderRoutine *routine,
+ void *private_data);
+extern XLogReaderRoutine *LocalXLogReaderRoutine(void);
+
+/* Free an XLogReader */
+extern void XLogReaderFree(XLogReaderState *state);
+
+/* Position the XLogReader to given record */
+extern void XLogBeginRead(XLogReaderState *state, XLogRecPtr RecPtr);
+#ifdef FRONTEND
+extern XLogRecPtr XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr);
+#endif /* FRONTEND */
+
+/* Read the next XLog record. Returns NULL on end-of-WAL or failure */
+extern struct XLogRecord *XLogReadRecord(XLogReaderState *state,
+ char **errormsg);
+
+/* Validate a page */
+extern bool XLogReaderValidatePageHeader(XLogReaderState *state,
+ XLogRecPtr recptr, char *phdr);
+
+/*
+ * Error information from WALRead that both backend and frontend caller can
+ * process. Currently only errors from pg_pread can be reported.
+ */
+typedef struct WALReadError
+{
+ int wre_errno; /* errno set by the last pg_pread() */
+ int wre_off; /* Offset we tried to read from. */
+ int wre_req; /* Bytes requested to be read. */
+ int wre_read; /* Bytes read by the last read(). */
+ WALOpenSegment wre_seg; /* Segment we tried to read from. */
+} WALReadError;
+
+extern bool WALRead(XLogReaderState *state,
+ char *buf, XLogRecPtr startptr, Size count,
+ TimeLineID tli, WALReadError *errinfo);
+
+/* Functions for decoding an XLogRecord */
+
+extern bool DecodeXLogRecord(XLogReaderState *state, XLogRecord *record,
+ char **errmsg);
+
+#define XLogRecGetTotalLen(decoder) ((decoder)->decoded_record->xl_tot_len)
+#define XLogRecGetPrev(decoder) ((decoder)->decoded_record->xl_prev)
+#define XLogRecGetInfo(decoder) ((decoder)->decoded_record->xl_info)
+#define XLogRecGetRmid(decoder) ((decoder)->decoded_record->xl_rmid)
+#define XLogRecGetXid(decoder) ((decoder)->decoded_record->xl_xid)
+#define XLogRecGetOrigin(decoder) ((decoder)->record_origin)
+#define XLogRecGetData(decoder) ((decoder)->main_data)
+#define XLogRecGetDataLen(decoder) ((decoder)->main_data_len)
+#define XLogRecHasAnyBlockRefs(decoder) ((decoder)->max_block_id >= 0)
+#define XLogRecHasBlockRef(decoder, block_id) \
+ ((decoder)->blocks[block_id].in_use)
+#define XLogRecHasBlockImage(decoder, block_id) \
+ ((decoder)->blocks[block_id].has_image)
+#define XLogRecBlockImageApply(decoder, block_id) \
+ ((decoder)->blocks[block_id].apply_image)
+
+#ifndef FRONTEND
+extern FullTransactionId XLogRecGetFullXid(XLogReaderState *record);
+#endif
+
+extern bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page);
+extern char *XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len);
+extern bool XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id,
+ RelFileNode *rnode, ForkNumber *forknum,
+ BlockNumber *blknum);
+
+#endif /* XLOGREADER_H */
diff --git a/src/include/access/xlogrecord.h b/src/include/access/xlogrecord.h
new file mode 100644
index 0000000..acd9af0
--- /dev/null
+++ b/src/include/access/xlogrecord.h
@@ -0,0 +1,227 @@
+/*
+ * xlogrecord.h
+ *
+ * Definitions for the WAL record format.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/xlogrecord.h
+ */
+#ifndef XLOGRECORD_H
+#define XLOGRECORD_H
+
+#include "access/rmgr.h"
+#include "access/xlogdefs.h"
+#include "port/pg_crc32c.h"
+#include "storage/block.h"
+#include "storage/relfilenode.h"
+
+/*
+ * The overall layout of an XLOG record is:
+ * Fixed-size header (XLogRecord struct)
+ * XLogRecordBlockHeader struct
+ * XLogRecordBlockHeader struct
+ * ...
+ * XLogRecordDataHeader[Short|Long] struct
+ * block data
+ * block data
+ * ...
+ * main data
+ *
+ * There can be zero or more XLogRecordBlockHeaders, and 0 or more bytes of
+ * rmgr-specific data not associated with a block. XLogRecord structs
+ * always start on MAXALIGN boundaries in the WAL files, but the rest of
+ * the fields are not aligned.
+ *
+ * The XLogRecordBlockHeader, XLogRecordDataHeaderShort and
+ * XLogRecordDataHeaderLong structs all begin with a single 'id' byte. It's
+ * used to distinguish between block references, and the main data structs.
+ */
+typedef struct XLogRecord
+{
+ uint32 xl_tot_len; /* total len of entire record */
+ TransactionId xl_xid; /* xact id */
+ XLogRecPtr xl_prev; /* ptr to previous record in log */
+ uint8 xl_info; /* flag bits, see below */
+ RmgrId xl_rmid; /* resource manager for this record */
+ /* 2 bytes of padding here, initialize to zero */
+ pg_crc32c xl_crc; /* CRC for this record */
+
+ /* XLogRecordBlockHeaders and XLogRecordDataHeader follow, no padding */
+
+} XLogRecord;
+
+#define SizeOfXLogRecord (offsetof(XLogRecord, xl_crc) + sizeof(pg_crc32c))
+
+/*
+ * The high 4 bits in xl_info may be used freely by rmgr. The
+ * XLR_SPECIAL_REL_UPDATE and XLR_CHECK_CONSISTENCY bits can be passed by
+ * XLogInsert caller. The rest are set internally by XLogInsert.
+ */
+#define XLR_INFO_MASK 0x0F
+#define XLR_RMGR_INFO_MASK 0xF0
+
+/*
+ * If a WAL record modifies any relation files, in ways not covered by the
+ * usual block references, this flag is set. This is not used for anything
+ * by PostgreSQL itself, but it allows external tools that read WAL and keep
+ * track of modified blocks to recognize such special record types.
+ */
+#define XLR_SPECIAL_REL_UPDATE 0x01
+
+/*
+ * Enforces consistency checks of replayed WAL at recovery. If enabled,
+ * each record will log a full-page write for each block modified by the
+ * record and will reuse it afterwards for consistency checks. The caller
+ * of XLogInsert can use this value if necessary, but if
+ * wal_consistency_checking is enabled for a rmgr this is set unconditionally.
+ */
+#define XLR_CHECK_CONSISTENCY 0x02
+
+/*
+ * Header info for block data appended to an XLOG record.
+ *
+ * 'data_length' is the length of the rmgr-specific payload data associated
+ * with this block. It does not include the possible full page image, nor
+ * XLogRecordBlockHeader struct itself.
+ *
+ * Note that we don't attempt to align the XLogRecordBlockHeader struct!
+ * So, the struct must be copied to aligned local storage before use.
+ */
+typedef struct XLogRecordBlockHeader
+{
+ uint8 id; /* block reference ID */
+ uint8 fork_flags; /* fork within the relation, and flags */
+ uint16 data_length; /* number of payload bytes (not including page
+ * image) */
+
+ /* If BKPBLOCK_HAS_IMAGE, an XLogRecordBlockImageHeader struct follows */
+ /* If BKPBLOCK_SAME_REL is not set, a RelFileNode follows */
+ /* BlockNumber follows */
+} XLogRecordBlockHeader;
+
+#define SizeOfXLogRecordBlockHeader (offsetof(XLogRecordBlockHeader, data_length) + sizeof(uint16))
+
+/*
+ * Additional header information when a full-page image is included
+ * (i.e. when BKPBLOCK_HAS_IMAGE is set).
+ *
+ * The XLOG code is aware that PG data pages usually contain an unused "hole"
+ * in the middle, which contains only zero bytes. Since we know that the
+ * "hole" is all zeros, we remove it from the stored data (and it's not counted
+ * in the XLOG record's CRC, either). Hence, the amount of block data actually
+ * present is (BLCKSZ - <length of "hole" bytes>).
+ *
+ * Additionally, when wal_compression is enabled, we will try to compress full
+ * page images using the PGLZ compression algorithm, after removing the "hole".
+ * This can reduce the WAL volume, but at some extra cost of CPU spent
+ * on the compression during WAL logging. In this case, since the "hole"
+ * length cannot be calculated by subtracting the number of page image bytes
+ * from BLCKSZ, basically it needs to be stored as an extra information.
+ * But when no "hole" exists, we can assume that the "hole" length is zero
+ * and no such an extra information needs to be stored. Note that
+ * the original version of page image is stored in WAL instead of the
+ * compressed one if the number of bytes saved by compression is less than
+ * the length of extra information. Hence, when a page image is successfully
+ * compressed, the amount of block data actually present is less than
+ * BLCKSZ - the length of "hole" bytes - the length of extra information.
+ */
+typedef struct XLogRecordBlockImageHeader
+{
+ uint16 length; /* number of page image bytes */
+ uint16 hole_offset; /* number of bytes before "hole" */
+ uint8 bimg_info; /* flag bits, see below */
+
+ /*
+ * If BKPIMAGE_HAS_HOLE and BKPIMAGE_IS_COMPRESSED, an
+ * XLogRecordBlockCompressHeader struct follows.
+ */
+} XLogRecordBlockImageHeader;
+
+#define SizeOfXLogRecordBlockImageHeader \
+ (offsetof(XLogRecordBlockImageHeader, bimg_info) + sizeof(uint8))
+
+/* Information stored in bimg_info */
+#define BKPIMAGE_HAS_HOLE 0x01 /* page image has "hole" */
+#define BKPIMAGE_IS_COMPRESSED 0x02 /* page image is compressed */
+#define BKPIMAGE_APPLY 0x04 /* page image should be restored during
+ * replay */
+
+/*
+ * Extra header information used when page image has "hole" and
+ * is compressed.
+ */
+typedef struct XLogRecordBlockCompressHeader
+{
+ uint16 hole_length; /* number of bytes in "hole" */
+} XLogRecordBlockCompressHeader;
+
+#define SizeOfXLogRecordBlockCompressHeader \
+ sizeof(XLogRecordBlockCompressHeader)
+
+/*
+ * Maximum size of the header for a block reference. This is used to size a
+ * temporary buffer for constructing the header.
+ */
+#define MaxSizeOfXLogRecordBlockHeader \
+ (SizeOfXLogRecordBlockHeader + \
+ SizeOfXLogRecordBlockImageHeader + \
+ SizeOfXLogRecordBlockCompressHeader + \
+ sizeof(RelFileNode) + \
+ sizeof(BlockNumber))
+
+/*
+ * The fork number fits in the lower 4 bits in the fork_flags field. The upper
+ * bits are used for flags.
+ */
+#define BKPBLOCK_FORK_MASK 0x0F
+#define BKPBLOCK_FLAG_MASK 0xF0
+#define BKPBLOCK_HAS_IMAGE 0x10 /* block data is an XLogRecordBlockImage */
+#define BKPBLOCK_HAS_DATA 0x20
+#define BKPBLOCK_WILL_INIT 0x40 /* redo will re-init the page */
+#define BKPBLOCK_SAME_REL 0x80 /* RelFileNode omitted, same as previous */
+
+/*
+ * XLogRecordDataHeaderShort/Long are used for the "main data" portion of
+ * the record. If the length of the data is less than 256 bytes, the short
+ * form is used, with a single byte to hold the length. Otherwise the long
+ * form is used.
+ *
+ * (These structs are currently not used in the code, they are here just for
+ * documentation purposes).
+ */
+typedef struct XLogRecordDataHeaderShort
+{
+ uint8 id; /* XLR_BLOCK_ID_DATA_SHORT */
+ uint8 data_length; /* number of payload bytes */
+} XLogRecordDataHeaderShort;
+
+#define SizeOfXLogRecordDataHeaderShort (sizeof(uint8) * 2)
+
+typedef struct XLogRecordDataHeaderLong
+{
+ uint8 id; /* XLR_BLOCK_ID_DATA_LONG */
+ /* followed by uint32 data_length, unaligned */
+} XLogRecordDataHeaderLong;
+
+#define SizeOfXLogRecordDataHeaderLong (sizeof(uint8) + sizeof(uint32))
+
+/*
+ * Block IDs used to distinguish different kinds of record fragments. Block
+ * references are numbered from 0 to XLR_MAX_BLOCK_ID. A rmgr is free to use
+ * any ID number in that range (although you should stick to small numbers,
+ * because the WAL machinery is optimized for that case). A couple of ID
+ * numbers are reserved to denote the "main" data portion of the record.
+ *
+ * The maximum is currently set at 32, quite arbitrarily. Most records only
+ * need a handful of block references, but there are a few exceptions that
+ * need more.
+ */
+#define XLR_MAX_BLOCK_ID 32
+
+#define XLR_BLOCK_ID_DATA_SHORT 255
+#define XLR_BLOCK_ID_DATA_LONG 254
+#define XLR_BLOCK_ID_ORIGIN 253
+
+#endif /* XLOGRECORD_H */
diff --git a/src/include/access/xlogutils.h b/src/include/access/xlogutils.h
new file mode 100644
index 0000000..e59b6cf
--- /dev/null
+++ b/src/include/access/xlogutils.h
@@ -0,0 +1,63 @@
+/*
+ * xlogutils.h
+ *
+ * Utilities for replaying WAL records.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/xlogutils.h
+ */
+#ifndef XLOG_UTILS_H
+#define XLOG_UTILS_H
+
+#include "access/xlogreader.h"
+#include "storage/bufmgr.h"
+
+
+extern bool XLogHaveInvalidPages(void);
+extern void XLogCheckInvalidPages(void);
+
+extern void XLogDropRelation(RelFileNode rnode, ForkNumber forknum);
+extern void XLogDropDatabase(Oid dbid);
+extern void XLogTruncateRelation(RelFileNode rnode, ForkNumber forkNum,
+ BlockNumber nblocks);
+
+/* Result codes for XLogReadBufferForRedo[Extended] */
+typedef enum
+{
+ BLK_NEEDS_REDO, /* changes from WAL record need to be applied */
+ BLK_DONE, /* block is already up-to-date */
+ BLK_RESTORED, /* block was restored from a full-page image */
+ BLK_NOTFOUND /* block was not found (and hence does not
+ * need to be replayed) */
+} XLogRedoAction;
+
+extern XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record,
+ uint8 buffer_id, Buffer *buf);
+extern Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id);
+extern XLogRedoAction XLogReadBufferForRedoExtended(XLogReaderState *record,
+ uint8 buffer_id,
+ ReadBufferMode mode, bool get_cleanup_lock,
+ Buffer *buf);
+
+extern Buffer XLogReadBufferExtended(RelFileNode rnode, ForkNumber forknum,
+ BlockNumber blkno, ReadBufferMode mode);
+
+extern Relation CreateFakeRelcacheEntry(RelFileNode rnode);
+extern void FreeFakeRelcacheEntry(Relation fakerel);
+
+extern int read_local_xlog_page(XLogReaderState *state,
+ XLogRecPtr targetPagePtr, int reqLen,
+ XLogRecPtr targetRecPtr, char *cur_page);
+extern void wal_segment_open(XLogReaderState *state,
+ XLogSegNo nextSegNo,
+ TimeLineID *tli_p);
+extern void wal_segment_close(XLogReaderState *state);
+
+extern void XLogReadDetermineTimeline(XLogReaderState *state,
+ XLogRecPtr wantPage, uint32 wantLength);
+
+extern void WALReadRaiseError(WALReadError *errinfo);
+
+#endif
diff --git a/src/include/bootstrap/bootstrap.h b/src/include/bootstrap/bootstrap.h
new file mode 100644
index 0000000..b67fa9a
--- /dev/null
+++ b/src/include/bootstrap/bootstrap.h
@@ -0,0 +1,62 @@
+/*-------------------------------------------------------------------------
+ *
+ * bootstrap.h
+ * include file for the bootstrapping code
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/bootstrap/bootstrap.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BOOTSTRAP_H
+#define BOOTSTRAP_H
+
+#include "nodes/execnodes.h"
+
+
+/*
+ * MAXATTR is the maximum number of attributes in a relation supported
+ * at bootstrap time (i.e., the max possible in a system table).
+ */
+#define MAXATTR 40
+
+#define BOOTCOL_NULL_AUTO 1
+#define BOOTCOL_NULL_FORCE_NULL 2
+#define BOOTCOL_NULL_FORCE_NOT_NULL 3
+
+extern Relation boot_reldesc;
+extern Form_pg_attribute attrtypes[MAXATTR];
+extern int numattr;
+
+
+extern void AuxiliaryProcessMain(int argc, char *argv[]) pg_attribute_noreturn();
+
+extern void closerel(char *name);
+extern void boot_openrel(char *name);
+
+extern void DefineAttr(char *name, char *type, int attnum, int nullness);
+extern void InsertOneTuple(void);
+extern void InsertOneValue(char *value, int i);
+extern void InsertOneNull(int i);
+
+extern void index_register(Oid heap, Oid ind, IndexInfo *indexInfo);
+extern void build_indices(void);
+
+extern void boot_get_type_io_data(Oid typid,
+ int16 *typlen,
+ bool *typbyval,
+ char *typalign,
+ char *typdelim,
+ Oid *typioparam,
+ Oid *typinput,
+ Oid *typoutput);
+
+extern int boot_yyparse(void);
+
+extern int boot_yylex(void);
+extern void boot_yyerror(const char *str) pg_attribute_noreturn();
+
+#endif /* BOOTSTRAP_H */
diff --git a/src/include/c.h b/src/include/c.h
new file mode 100644
index 0000000..d01504b
--- /dev/null
+++ b/src/include/c.h
@@ -0,0 +1,1332 @@
+/*-------------------------------------------------------------------------
+ *
+ * c.h
+ * Fundamental C definitions. This is included by every .c file in
+ * PostgreSQL (via either postgres.h or postgres_fe.h, as appropriate).
+ *
+ * Note that the definitions here are not intended to be exposed to clients
+ * of the frontend interface libraries --- so we don't worry much about
+ * polluting the namespace with lots of stuff...
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/c.h
+ *
+ *-------------------------------------------------------------------------
+ */
+/*
+ *----------------------------------------------------------------
+ * TABLE OF CONTENTS
+ *
+ * When adding stuff to this file, please try to put stuff
+ * into the relevant section, or add new sections as appropriate.
+ *
+ * section description
+ * ------- ------------------------------------------------
+ * 0) pg_config.h and standard system headers
+ * 1) compiler characteristics
+ * 2) bool, true, false
+ * 3) standard system types
+ * 4) IsValid macros for system types
+ * 5) offsetof, lengthof, alignment
+ * 6) assertions
+ * 7) widely useful macros
+ * 8) random stuff
+ * 9) system-specific hacks
+ *
+ * NOTE: since this file is included by both frontend and backend modules,
+ * it's usually wrong to put an "extern" declaration here, unless it's
+ * ifdef'd so that it's seen in only one case or the other.
+ * typedefs and macros are the kind of thing that might go here.
+ *
+ *----------------------------------------------------------------
+ */
+#ifndef C_H
+#define C_H
+
+#include "postgres_ext.h"
+
+/* Must undef pg_config_ext.h symbols before including pg_config.h */
+#undef PG_INT64_TYPE
+
+#include "pg_config.h"
+#include "pg_config_manual.h" /* must be after pg_config.h */
+#include "pg_config_os.h" /* must be before any system header files */
+
+/* System header files that should be available everywhere in Postgres */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdarg.h>
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#include <stdint.h>
+#include <sys/types.h>
+#include <errno.h>
+#if defined(WIN32) || defined(__CYGWIN__)
+#include <fcntl.h> /* ensure O_BINARY is available */
+#endif
+#include <locale.h>
+#ifdef ENABLE_NLS
+#include <libintl.h>
+#endif
+
+
+/* ----------------------------------------------------------------
+ * Section 1: compiler characteristics
+ *
+ * type prefixes (const, signed, volatile, inline) are handled in pg_config.h.
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * Disable "inline" if PG_FORCE_DISABLE_INLINE is defined.
+ * This is used to work around compiler bugs and might also be useful for
+ * investigatory purposes.
+ */
+#ifdef PG_FORCE_DISABLE_INLINE
+#undef inline
+#define inline
+#endif
+
+/*
+ * Attribute macros
+ *
+ * GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
+ * GCC: https://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html
+ * Sunpro: https://docs.oracle.com/cd/E18659_01/html/821-1384/gjzke.html
+ * XLC: https://www.ibm.com/support/knowledgecenter/SSGH2K_13.1.2/com.ibm.xlc131.aix.doc/language_ref/function_attributes.html
+ * XLC: https://www.ibm.com/support/knowledgecenter/SSGH2K_13.1.2/com.ibm.xlc131.aix.doc/language_ref/type_attrib.html
+ */
+
+/* only GCC supports the unused attribute */
+#ifdef __GNUC__
+#define pg_attribute_unused() __attribute__((unused))
+#else
+#define pg_attribute_unused()
+#endif
+
+/*
+ * Place this macro before functions that should be allowed to make misaligned
+ * accesses. Think twice before using it on non-x86-specific code!
+ * Testing can be done with "-fsanitize=alignment -fsanitize-trap=alignment"
+ * on clang, or "-fsanitize=alignment -fno-sanitize-recover=alignment" on gcc.
+ */
+#if __clang_major__ >= 7 || __GNUC__ >= 8
+#define pg_attribute_no_sanitize_alignment() __attribute__((no_sanitize("alignment")))
+#else
+#define pg_attribute_no_sanitize_alignment()
+#endif
+
+/*
+ * Append PG_USED_FOR_ASSERTS_ONLY to definitions of variables that are only
+ * used in assert-enabled builds, to avoid compiler warnings about unused
+ * variables in assert-disabled builds.
+ */
+#ifdef USE_ASSERT_CHECKING
+#define PG_USED_FOR_ASSERTS_ONLY
+#else
+#define PG_USED_FOR_ASSERTS_ONLY pg_attribute_unused()
+#endif
+
+/* GCC and XLC support format attributes */
+#if defined(__GNUC__) || defined(__IBMC__)
+#define pg_attribute_format_arg(a) __attribute__((format_arg(a)))
+#define pg_attribute_printf(f,a) __attribute__((format(PG_PRINTF_ATTRIBUTE, f, a)))
+#else
+#define pg_attribute_format_arg(a)
+#define pg_attribute_printf(f,a)
+#endif
+
+/* GCC, Sunpro and XLC support aligned, packed and noreturn */
+#if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__)
+#define pg_attribute_aligned(a) __attribute__((aligned(a)))
+#define pg_attribute_noreturn() __attribute__((noreturn))
+#define pg_attribute_packed() __attribute__((packed))
+#define HAVE_PG_ATTRIBUTE_NORETURN 1
+#else
+/*
+ * NB: aligned and packed are not given default definitions because they
+ * affect code functionality; they *must* be implemented by the compiler
+ * if they are to be used.
+ */
+#define pg_attribute_noreturn()
+#endif
+
+/*
+ * Use "pg_attribute_always_inline" in place of "inline" for functions that
+ * we wish to force inlining of, even when the compiler's heuristics would
+ * choose not to. But, if possible, don't force inlining in unoptimized
+ * debug builds.
+ */
+#if (defined(__GNUC__) && __GNUC__ > 3 && defined(__OPTIMIZE__)) || defined(__SUNPRO_C) || defined(__IBMC__)
+/* GCC > 3, Sunpro and XLC support always_inline via __attribute__ */
+#define pg_attribute_always_inline __attribute__((always_inline)) inline
+#elif defined(_MSC_VER)
+/* MSVC has a special keyword for this */
+#define pg_attribute_always_inline __forceinline
+#else
+/* Otherwise, the best we can do is to say "inline" */
+#define pg_attribute_always_inline inline
+#endif
+
+/*
+ * Forcing a function not to be inlined can be useful if it's the slow path of
+ * a performance-critical function, or should be visible in profiles to allow
+ * for proper cost attribution. Note that unlike the pg_attribute_XXX macros
+ * above, this should be placed before the function's return type and name.
+ */
+/* GCC, Sunpro and XLC support noinline via __attribute__ */
+#if (defined(__GNUC__) && __GNUC__ > 2) || defined(__SUNPRO_C) || defined(__IBMC__)
+#define pg_noinline __attribute__((noinline))
+/* msvc via declspec */
+#elif defined(_MSC_VER)
+#define pg_noinline __declspec(noinline)
+#else
+#define pg_noinline
+#endif
+
+/*
+ * Mark a point as unreachable in a portable fashion. This should preferably
+ * be something that the compiler understands, to aid code generation.
+ * In assert-enabled builds, we prefer abort() for debugging reasons.
+ */
+#if defined(HAVE__BUILTIN_UNREACHABLE) && !defined(USE_ASSERT_CHECKING)
+#define pg_unreachable() __builtin_unreachable()
+#elif defined(_MSC_VER) && !defined(USE_ASSERT_CHECKING)
+#define pg_unreachable() __assume(0)
+#else
+#define pg_unreachable() abort()
+#endif
+
+/*
+ * Hints to the compiler about the likelihood of a branch. Both likely() and
+ * unlikely() return the boolean value of the contained expression.
+ *
+ * These should only be used sparingly, in very hot code paths. It's very easy
+ * to mis-estimate likelihoods.
+ */
+#if __GNUC__ >= 3
+#define likely(x) __builtin_expect((x) != 0, 1)
+#define unlikely(x) __builtin_expect((x) != 0, 0)
+#else
+#define likely(x) ((x) != 0)
+#define unlikely(x) ((x) != 0)
+#endif
+
+/*
+ * CppAsString
+ * Convert the argument to a string, using the C preprocessor.
+ * CppAsString2
+ * Convert the argument to a string, after one round of macro expansion.
+ * CppConcat
+ * Concatenate two arguments together, using the C preprocessor.
+ *
+ * Note: There used to be support here for pre-ANSI C compilers that didn't
+ * support # and ##. Nowadays, these macros are just for clarity and/or
+ * backward compatibility with existing PostgreSQL code.
+ */
+#define CppAsString(identifier) #identifier
+#define CppAsString2(x) CppAsString(x)
+#define CppConcat(x, y) x##y
+
+/*
+ * VA_ARGS_NARGS
+ * Returns the number of macro arguments it is passed.
+ *
+ * An empty argument still counts as an argument, so effectively, this is
+ * "one more than the number of commas in the argument list".
+ *
+ * This works for up to 63 arguments. Internally, VA_ARGS_NARGS_() is passed
+ * 64+N arguments, and the C99 standard only requires macros to allow up to
+ * 127 arguments, so we can't portably go higher. The implementation is
+ * pretty trivial: VA_ARGS_NARGS_() returns its 64th argument, and we set up
+ * the call so that that is the appropriate one of the list of constants.
+ * This idea is due to Laurent Deniau.
+ */
+#define VA_ARGS_NARGS(...) \
+ VA_ARGS_NARGS_(__VA_ARGS__, \
+ 63,62,61,60, \
+ 59,58,57,56,55,54,53,52,51,50, \
+ 49,48,47,46,45,44,43,42,41,40, \
+ 39,38,37,36,35,34,33,32,31,30, \
+ 29,28,27,26,25,24,23,22,21,20, \
+ 19,18,17,16,15,14,13,12,11,10, \
+ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
+#define VA_ARGS_NARGS_( \
+ _01,_02,_03,_04,_05,_06,_07,_08,_09,_10, \
+ _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
+ _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
+ _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
+ _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
+ _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
+ _61,_62,_63, N, ...) \
+ (N)
+
+/*
+ * dummyret is used to set return values in macros that use ?: to make
+ * assignments. gcc wants these to be void, other compilers like char
+ */
+#ifdef __GNUC__ /* GNU cc */
+#define dummyret void
+#else
+#define dummyret char
+#endif
+
+/*
+ * We require C99, hence the compiler should understand flexible array
+ * members. However, for documentation purposes we still consider it to be
+ * project style to write "field[FLEXIBLE_ARRAY_MEMBER]" not just "field[]".
+ * When computing the size of such an object, use "offsetof(struct s, f)"
+ * for portability. Don't use "offsetof(struct s, f[0])", as this doesn't
+ * work with MSVC and with C++ compilers.
+ */
+#define FLEXIBLE_ARRAY_MEMBER /* empty */
+
+/* Which __func__ symbol do we have, if any? */
+#ifdef HAVE_FUNCNAME__FUNC
+#define PG_FUNCNAME_MACRO __func__
+#else
+#ifdef HAVE_FUNCNAME__FUNCTION
+#define PG_FUNCNAME_MACRO __FUNCTION__
+#else
+#define PG_FUNCNAME_MACRO NULL
+#endif
+#endif
+
+
+/* ----------------------------------------------------------------
+ * Section 2: bool, true, false
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * bool
+ * Boolean value, either true or false.
+ *
+ * We use stdbool.h if available and its bool has size 1. That's useful for
+ * better compiler and debugger output and for compatibility with third-party
+ * libraries. But PostgreSQL currently cannot deal with bool of other sizes;
+ * there are static assertions around the code to prevent that.
+ *
+ * For C++ compilers, we assume the compiler has a compatible built-in
+ * definition of bool.
+ *
+ * See also the version of this code in src/interfaces/ecpg/include/ecpglib.h.
+ */
+
+#ifndef __cplusplus
+
+#ifdef PG_USE_STDBOOL
+#include <stdbool.h>
+#else
+
+#ifndef bool
+typedef unsigned char bool;
+#endif
+
+#ifndef true
+#define true ((bool) 1)
+#endif
+
+#ifndef false
+#define false ((bool) 0)
+#endif
+
+#endif /* not PG_USE_STDBOOL */
+#endif /* not C++ */
+
+
+/* ----------------------------------------------------------------
+ * Section 3: standard system types
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * Pointer
+ * Variable holding address of any memory resident object.
+ *
+ * XXX Pointer arithmetic is done with this, so it can't be void *
+ * under "true" ANSI compilers.
+ */
+typedef char *Pointer;
+
+/*
+ * intN
+ * Signed integer, EXACTLY N BITS IN SIZE,
+ * used for numerical computations and the
+ * frontend/backend protocol.
+ */
+#ifndef HAVE_INT8
+typedef signed char int8; /* == 8 bits */
+typedef signed short int16; /* == 16 bits */
+typedef signed int int32; /* == 32 bits */
+#endif /* not HAVE_INT8 */
+
+/*
+ * uintN
+ * Unsigned integer, EXACTLY N BITS IN SIZE,
+ * used for numerical computations and the
+ * frontend/backend protocol.
+ */
+#ifndef HAVE_UINT8
+typedef unsigned char uint8; /* == 8 bits */
+typedef unsigned short uint16; /* == 16 bits */
+typedef unsigned int uint32; /* == 32 bits */
+#endif /* not HAVE_UINT8 */
+
+/*
+ * bitsN
+ * Unit of bitwise operation, AT LEAST N BITS IN SIZE.
+ */
+typedef uint8 bits8; /* >= 8 bits */
+typedef uint16 bits16; /* >= 16 bits */
+typedef uint32 bits32; /* >= 32 bits */
+
+/*
+ * 64-bit integers
+ */
+#ifdef HAVE_LONG_INT_64
+/* Plain "long int" fits, use it */
+
+#ifndef HAVE_INT64
+typedef long int int64;
+#endif
+#ifndef HAVE_UINT64
+typedef unsigned long int uint64;
+#endif
+#define INT64CONST(x) (x##L)
+#define UINT64CONST(x) (x##UL)
+#elif defined(HAVE_LONG_LONG_INT_64)
+/* We have working support for "long long int", use that */
+
+#ifndef HAVE_INT64
+typedef long long int int64;
+#endif
+#ifndef HAVE_UINT64
+typedef unsigned long long int uint64;
+#endif
+#define INT64CONST(x) (x##LL)
+#define UINT64CONST(x) (x##ULL)
+#else
+/* neither HAVE_LONG_INT_64 nor HAVE_LONG_LONG_INT_64 */
+#error must have a working 64-bit integer datatype
+#endif
+
+/* snprintf format strings to use for 64-bit integers */
+#define INT64_FORMAT "%" INT64_MODIFIER "d"
+#define UINT64_FORMAT "%" INT64_MODIFIER "u"
+
+/*
+ * 128-bit signed and unsigned integers
+ * There currently is only limited support for such types.
+ * E.g. 128bit literals and snprintf are not supported; but math is.
+ * Also, because we exclude such types when choosing MAXIMUM_ALIGNOF,
+ * it must be possible to coerce the compiler to allocate them on no
+ * more than MAXALIGN boundaries.
+ */
+#if defined(PG_INT128_TYPE)
+#if defined(pg_attribute_aligned) || ALIGNOF_PG_INT128_TYPE <= MAXIMUM_ALIGNOF
+#define HAVE_INT128 1
+
+typedef PG_INT128_TYPE int128
+#if defined(pg_attribute_aligned)
+ pg_attribute_aligned(MAXIMUM_ALIGNOF)
+#endif
+ ;
+
+typedef unsigned PG_INT128_TYPE uint128
+#if defined(pg_attribute_aligned)
+ pg_attribute_aligned(MAXIMUM_ALIGNOF)
+#endif
+ ;
+
+#endif
+#endif
+
+/*
+ * stdint.h limits aren't guaranteed to have compatible types with our fixed
+ * width types. So just define our own.
+ */
+#define PG_INT8_MIN (-0x7F-1)
+#define PG_INT8_MAX (0x7F)
+#define PG_UINT8_MAX (0xFF)
+#define PG_INT16_MIN (-0x7FFF-1)
+#define PG_INT16_MAX (0x7FFF)
+#define PG_UINT16_MAX (0xFFFF)
+#define PG_INT32_MIN (-0x7FFFFFFF-1)
+#define PG_INT32_MAX (0x7FFFFFFF)
+#define PG_UINT32_MAX (0xFFFFFFFFU)
+#define PG_INT64_MIN (-INT64CONST(0x7FFFFFFFFFFFFFFF) - 1)
+#define PG_INT64_MAX INT64CONST(0x7FFFFFFFFFFFFFFF)
+#define PG_UINT64_MAX UINT64CONST(0xFFFFFFFFFFFFFFFF)
+
+/*
+ * We now always use int64 timestamps, but keep this symbol defined for the
+ * benefit of external code that might test it.
+ */
+#define HAVE_INT64_TIMESTAMP
+
+/*
+ * Size
+ * Size of any memory resident object, as returned by sizeof.
+ */
+typedef size_t Size;
+
+/*
+ * Index
+ * Index into any memory resident array.
+ *
+ * Note:
+ * Indices are non negative.
+ */
+typedef unsigned int Index;
+
+/*
+ * Offset
+ * Offset into any memory resident array.
+ *
+ * Note:
+ * This differs from an Index in that an Index is always
+ * non negative, whereas Offset may be negative.
+ */
+typedef signed int Offset;
+
+/*
+ * Common Postgres datatype names (as used in the catalogs)
+ */
+typedef float float4;
+typedef double float8;
+
+#ifdef USE_FLOAT8_BYVAL
+#define FLOAT8PASSBYVAL true
+#else
+#define FLOAT8PASSBYVAL false
+#endif
+
+/*
+ * Oid, RegProcedure, TransactionId, SubTransactionId, MultiXactId,
+ * CommandId
+ */
+
+/* typedef Oid is in postgres_ext.h */
+
+/*
+ * regproc is the type name used in the include/catalog headers, but
+ * RegProcedure is the preferred name in C code.
+ */
+typedef Oid regproc;
+typedef regproc RegProcedure;
+
+typedef uint32 TransactionId;
+
+typedef uint32 LocalTransactionId;
+
+typedef uint32 SubTransactionId;
+
+#define InvalidSubTransactionId ((SubTransactionId) 0)
+#define TopSubTransactionId ((SubTransactionId) 1)
+
+/* MultiXactId must be equivalent to TransactionId, to fit in t_xmax */
+typedef TransactionId MultiXactId;
+
+typedef uint32 MultiXactOffset;
+
+typedef uint32 CommandId;
+
+#define FirstCommandId ((CommandId) 0)
+#define InvalidCommandId (~(CommandId)0)
+
+/*
+ * Array indexing support
+ */
+#define MAXDIM 6
+typedef struct
+{
+ int indx[MAXDIM];
+} IntArray;
+
+/* ----------------
+ * Variable-length datatypes all share the 'struct varlena' header.
+ *
+ * NOTE: for TOASTable types, this is an oversimplification, since the value
+ * may be compressed or moved out-of-line. However datatype-specific routines
+ * are mostly content to deal with de-TOASTed values only, and of course
+ * client-side routines should never see a TOASTed value. But even in a
+ * de-TOASTed value, beware of touching vl_len_ directly, as its
+ * representation is no longer convenient. It's recommended that code always
+ * use macros VARDATA_ANY, VARSIZE_ANY, VARSIZE_ANY_EXHDR, VARDATA, VARSIZE,
+ * and SET_VARSIZE instead of relying on direct mentions of the struct fields.
+ * See postgres.h for details of the TOASTed form.
+ * ----------------
+ */
+struct varlena
+{
+ char vl_len_[4]; /* Do not touch this field directly! */
+ char vl_dat[FLEXIBLE_ARRAY_MEMBER]; /* Data content is here */
+};
+
+#define VARHDRSZ ((int32) sizeof(int32))
+
+/*
+ * These widely-used datatypes are just a varlena header and the data bytes.
+ * There is no terminating null or anything like that --- the data length is
+ * always VARSIZE_ANY_EXHDR(ptr).
+ */
+typedef struct varlena bytea;
+typedef struct varlena text;
+typedef struct varlena BpChar; /* blank-padded char, ie SQL char(n) */
+typedef struct varlena VarChar; /* var-length char, ie SQL varchar(n) */
+
+/*
+ * Specialized array types. These are physically laid out just the same
+ * as regular arrays (so that the regular array subscripting code works
+ * with them). They exist as distinct types mostly for historical reasons:
+ * they have nonstandard I/O behavior which we don't want to change for fear
+ * of breaking applications that look at the system catalogs. There is also
+ * an implementation issue for oidvector: it's part of the primary key for
+ * pg_proc, and we can't use the normal btree array support routines for that
+ * without circularity.
+ */
+typedef struct
+{
+ int32 vl_len_; /* these fields must match ArrayType! */
+ int ndim; /* always 1 for int2vector */
+ int32 dataoffset; /* always 0 for int2vector */
+ Oid elemtype;
+ int dim1;
+ int lbound1;
+ int16 values[FLEXIBLE_ARRAY_MEMBER];
+} int2vector;
+
+typedef struct
+{
+ int32 vl_len_; /* these fields must match ArrayType! */
+ int ndim; /* always 1 for oidvector */
+ int32 dataoffset; /* always 0 for oidvector */
+ Oid elemtype;
+ int dim1;
+ int lbound1;
+ Oid values[FLEXIBLE_ARRAY_MEMBER];
+} oidvector;
+
+/*
+ * Representation of a Name: effectively just a C string, but null-padded to
+ * exactly NAMEDATALEN bytes. The use of a struct is historical.
+ */
+typedef struct nameData
+{
+ char data[NAMEDATALEN];
+} NameData;
+typedef NameData *Name;
+
+#define NameStr(name) ((name).data)
+
+
+/* ----------------------------------------------------------------
+ * Section 4: IsValid macros for system types
+ * ----------------------------------------------------------------
+ */
+/*
+ * BoolIsValid
+ * True iff bool is valid.
+ */
+#define BoolIsValid(boolean) ((boolean) == false || (boolean) == true)
+
+/*
+ * PointerIsValid
+ * True iff pointer is valid.
+ */
+#define PointerIsValid(pointer) ((const void*)(pointer) != NULL)
+
+/*
+ * PointerIsAligned
+ * True iff pointer is properly aligned to point to the given type.
+ */
+#define PointerIsAligned(pointer, type) \
+ (((uintptr_t)(pointer) % (sizeof (type))) == 0)
+
+#define OffsetToPointer(base, offset) \
+ ((void *)((char *) base + offset))
+
+#define OidIsValid(objectId) ((bool) ((objectId) != InvalidOid))
+
+#define RegProcedureIsValid(p) OidIsValid(p)
+
+
+/* ----------------------------------------------------------------
+ * Section 5: offsetof, lengthof, alignment
+ * ----------------------------------------------------------------
+ */
+/*
+ * offsetof
+ * Offset of a structure/union field within that structure/union.
+ *
+ * XXX This is supposed to be part of stddef.h, but isn't on
+ * some systems (like SunOS 4).
+ */
+#ifndef offsetof
+#define offsetof(type, field) ((long) &((type *)0)->field)
+#endif /* offsetof */
+
+/*
+ * lengthof
+ * Number of elements in an array.
+ */
+#define lengthof(array) (sizeof (array) / sizeof ((array)[0]))
+
+/* ----------------
+ * Alignment macros: align a length or address appropriately for a given type.
+ * The fooALIGN() macros round up to a multiple of the required alignment,
+ * while the fooALIGN_DOWN() macros round down. The latter are more useful
+ * for problems like "how many X-sized structures will fit in a page?".
+ *
+ * NOTE: TYPEALIGN[_DOWN] will not work if ALIGNVAL is not a power of 2.
+ * That case seems extremely unlikely to be needed in practice, however.
+ *
+ * NOTE: MAXIMUM_ALIGNOF, and hence MAXALIGN(), intentionally exclude any
+ * larger-than-8-byte types the compiler might have.
+ * ----------------
+ */
+
+#define TYPEALIGN(ALIGNVAL,LEN) \
+ (((uintptr_t) (LEN) + ((ALIGNVAL) - 1)) & ~((uintptr_t) ((ALIGNVAL) - 1)))
+
+#define SHORTALIGN(LEN) TYPEALIGN(ALIGNOF_SHORT, (LEN))
+#define INTALIGN(LEN) TYPEALIGN(ALIGNOF_INT, (LEN))
+#define LONGALIGN(LEN) TYPEALIGN(ALIGNOF_LONG, (LEN))
+#define DOUBLEALIGN(LEN) TYPEALIGN(ALIGNOF_DOUBLE, (LEN))
+#define MAXALIGN(LEN) TYPEALIGN(MAXIMUM_ALIGNOF, (LEN))
+/* MAXALIGN covers only built-in types, not buffers */
+#define BUFFERALIGN(LEN) TYPEALIGN(ALIGNOF_BUFFER, (LEN))
+#define CACHELINEALIGN(LEN) TYPEALIGN(PG_CACHE_LINE_SIZE, (LEN))
+
+#define TYPEALIGN_DOWN(ALIGNVAL,LEN) \
+ (((uintptr_t) (LEN)) & ~((uintptr_t) ((ALIGNVAL) - 1)))
+
+#define SHORTALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_SHORT, (LEN))
+#define INTALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_INT, (LEN))
+#define LONGALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_LONG, (LEN))
+#define DOUBLEALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_DOUBLE, (LEN))
+#define MAXALIGN_DOWN(LEN) TYPEALIGN_DOWN(MAXIMUM_ALIGNOF, (LEN))
+#define BUFFERALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_BUFFER, (LEN))
+
+/*
+ * The above macros will not work with types wider than uintptr_t, like with
+ * uint64 on 32-bit platforms. That's not problem for the usual use where a
+ * pointer or a length is aligned, but for the odd case that you need to
+ * align something (potentially) wider, use TYPEALIGN64.
+ */
+#define TYPEALIGN64(ALIGNVAL,LEN) \
+ (((uint64) (LEN) + ((ALIGNVAL) - 1)) & ~((uint64) ((ALIGNVAL) - 1)))
+
+/* we don't currently need wider versions of the other ALIGN macros */
+#define MAXALIGN64(LEN) TYPEALIGN64(MAXIMUM_ALIGNOF, (LEN))
+
+
+/* ----------------------------------------------------------------
+ * Section 6: assertions
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * USE_ASSERT_CHECKING, if defined, turns on all the assertions.
+ * - plai 9/5/90
+ *
+ * It should _NOT_ be defined in releases or in benchmark copies
+ */
+
+/*
+ * Assert() can be used in both frontend and backend code. In frontend code it
+ * just calls the standard assert, if it's available. If use of assertions is
+ * not configured, it does nothing.
+ */
+#ifndef USE_ASSERT_CHECKING
+
+#define Assert(condition) ((void)true)
+#define AssertMacro(condition) ((void)true)
+#define AssertArg(condition) ((void)true)
+#define AssertState(condition) ((void)true)
+#define AssertPointerAlignment(ptr, bndr) ((void)true)
+#define Trap(condition, errorType) ((void)true)
+#define TrapMacro(condition, errorType) (true)
+
+#elif defined(FRONTEND)
+
+#include <assert.h>
+#define Assert(p) assert(p)
+#define AssertMacro(p) ((void) assert(p))
+#define AssertArg(condition) assert(condition)
+#define AssertState(condition) assert(condition)
+#define AssertPointerAlignment(ptr, bndr) ((void)true)
+
+#else /* USE_ASSERT_CHECKING && !FRONTEND */
+
+/*
+ * Trap
+ * Generates an exception if the given condition is true.
+ */
+#define Trap(condition, errorType) \
+ do { \
+ if (condition) \
+ ExceptionalCondition(#condition, (errorType), \
+ __FILE__, __LINE__); \
+ } while (0)
+
+/*
+ * TrapMacro is the same as Trap but it's intended for use in macros:
+ *
+ * #define foo(x) (AssertMacro(x != 0), bar(x))
+ *
+ * Isn't CPP fun?
+ */
+#define TrapMacro(condition, errorType) \
+ ((bool) (! (condition) || \
+ (ExceptionalCondition(#condition, (errorType), \
+ __FILE__, __LINE__), 0)))
+
+#define Assert(condition) \
+ do { \
+ if (!(condition)) \
+ ExceptionalCondition(#condition, "FailedAssertion", \
+ __FILE__, __LINE__); \
+ } while (0)
+
+#define AssertMacro(condition) \
+ ((void) ((condition) || \
+ (ExceptionalCondition(#condition, "FailedAssertion", \
+ __FILE__, __LINE__), 0)))
+
+#define AssertArg(condition) \
+ do { \
+ if (!(condition)) \
+ ExceptionalCondition(#condition, "BadArgument", \
+ __FILE__, __LINE__); \
+ } while (0)
+
+#define AssertState(condition) \
+ do { \
+ if (!(condition)) \
+ ExceptionalCondition(#condition, "BadState", \
+ __FILE__, __LINE__); \
+ } while (0)
+
+/*
+ * Check that `ptr' is `bndr' aligned.
+ */
+#define AssertPointerAlignment(ptr, bndr) \
+ Trap(TYPEALIGN(bndr, (uintptr_t)(ptr)) != (uintptr_t)(ptr), \
+ "UnalignedPointer")
+
+#endif /* USE_ASSERT_CHECKING && !FRONTEND */
+
+/*
+ * ExceptionalCondition is compiled into the backend whether or not
+ * USE_ASSERT_CHECKING is defined, so as to support use of extensions
+ * that are built with that #define with a backend that isn't. Hence,
+ * we should declare it as long as !FRONTEND.
+ */
+#ifndef FRONTEND
+extern void ExceptionalCondition(const char *conditionName,
+ const char *errorType,
+ const char *fileName, int lineNumber) pg_attribute_noreturn();
+#endif
+
+/*
+ * Macros to support compile-time assertion checks.
+ *
+ * If the "condition" (a compile-time-constant expression) evaluates to false,
+ * throw a compile error using the "errmessage" (a string literal).
+ *
+ * gcc 4.6 and up supports _Static_assert(), but there are bizarre syntactic
+ * placement restrictions. Macros StaticAssertStmt() and StaticAssertExpr()
+ * make it safe to use as a statement or in an expression, respectively.
+ * The macro StaticAssertDecl() is suitable for use at file scope (outside of
+ * any function).
+ *
+ * Otherwise we fall back on a kluge that assumes the compiler will complain
+ * about a negative width for a struct bit-field. This will not include a
+ * helpful error message, but it beats not getting an error at all.
+ */
+#ifndef __cplusplus
+#ifdef HAVE__STATIC_ASSERT
+#define StaticAssertStmt(condition, errmessage) \
+ do { _Static_assert(condition, errmessage); } while(0)
+#define StaticAssertExpr(condition, errmessage) \
+ ((void) ({ StaticAssertStmt(condition, errmessage); true; }))
+#define StaticAssertDecl(condition, errmessage) \
+ _Static_assert(condition, errmessage)
+#else /* !HAVE__STATIC_ASSERT */
+#define StaticAssertStmt(condition, errmessage) \
+ ((void) sizeof(struct { int static_assert_failure : (condition) ? 1 : -1; }))
+#define StaticAssertExpr(condition, errmessage) \
+ StaticAssertStmt(condition, errmessage)
+#define StaticAssertDecl(condition, errmessage) \
+ extern void static_assert_func(int static_assert_failure[(condition) ? 1 : -1])
+#endif /* HAVE__STATIC_ASSERT */
+#else /* C++ */
+#if defined(__cpp_static_assert) && __cpp_static_assert >= 200410
+#define StaticAssertStmt(condition, errmessage) \
+ static_assert(condition, errmessage)
+#define StaticAssertExpr(condition, errmessage) \
+ ({ static_assert(condition, errmessage); })
+#define StaticAssertDecl(condition, errmessage) \
+ static_assert(condition, errmessage)
+#else /* !__cpp_static_assert */
+#define StaticAssertStmt(condition, errmessage) \
+ do { struct static_assert_struct { int static_assert_failure : (condition) ? 1 : -1; }; } while(0)
+#define StaticAssertExpr(condition, errmessage) \
+ ((void) ({ StaticAssertStmt(condition, errmessage); }))
+#define StaticAssertDecl(condition, errmessage) \
+ extern void static_assert_func(int static_assert_failure[(condition) ? 1 : -1])
+#endif /* __cpp_static_assert */
+#endif /* C++ */
+
+
+/*
+ * Compile-time checks that a variable (or expression) has the specified type.
+ *
+ * AssertVariableIsOfType() can be used as a statement.
+ * AssertVariableIsOfTypeMacro() is intended for use in macros, eg
+ * #define foo(x) (AssertVariableIsOfTypeMacro(x, int), bar(x))
+ *
+ * If we don't have __builtin_types_compatible_p, we can still assert that
+ * the types have the same size. This is far from ideal (especially on 32-bit
+ * platforms) but it provides at least some coverage.
+ */
+#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
+#define AssertVariableIsOfType(varname, typename) \
+ StaticAssertStmt(__builtin_types_compatible_p(__typeof__(varname), typename), \
+ CppAsString(varname) " does not have type " CppAsString(typename))
+#define AssertVariableIsOfTypeMacro(varname, typename) \
+ (StaticAssertExpr(__builtin_types_compatible_p(__typeof__(varname), typename), \
+ CppAsString(varname) " does not have type " CppAsString(typename)))
+#else /* !HAVE__BUILTIN_TYPES_COMPATIBLE_P */
+#define AssertVariableIsOfType(varname, typename) \
+ StaticAssertStmt(sizeof(varname) == sizeof(typename), \
+ CppAsString(varname) " does not have type " CppAsString(typename))
+#define AssertVariableIsOfTypeMacro(varname, typename) \
+ (StaticAssertExpr(sizeof(varname) == sizeof(typename), \
+ CppAsString(varname) " does not have type " CppAsString(typename)))
+#endif /* HAVE__BUILTIN_TYPES_COMPATIBLE_P */
+
+
+/* ----------------------------------------------------------------
+ * Section 7: widely useful macros
+ * ----------------------------------------------------------------
+ */
+/*
+ * Max
+ * Return the maximum of two numbers.
+ */
+#define Max(x, y) ((x) > (y) ? (x) : (y))
+
+/*
+ * Min
+ * Return the minimum of two numbers.
+ */
+#define Min(x, y) ((x) < (y) ? (x) : (y))
+
+/*
+ * Abs
+ * Return the absolute value of the argument.
+ */
+#define Abs(x) ((x) >= 0 ? (x) : -(x))
+
+/*
+ * StrNCpy
+ * Like standard library function strncpy(), except that result string
+ * is guaranteed to be null-terminated --- that is, at most N-1 bytes
+ * of the source string will be kept.
+ * Also, the macro returns no result (too hard to do that without
+ * evaluating the arguments multiple times, which seems worse).
+ *
+ * BTW: when you need to copy a non-null-terminated string (like a text
+ * datum) and add a null, do not do it with StrNCpy(..., len+1). That
+ * might seem to work, but it fetches one byte more than there is in the
+ * text object. One fine day you'll have a SIGSEGV because there isn't
+ * another byte before the end of memory. Don't laugh, we've had real
+ * live bug reports from real live users over exactly this mistake.
+ * Do it honestly with "memcpy(dst,src,len); dst[len] = '\0';", instead.
+ */
+#define StrNCpy(dst,src,len) \
+ do \
+ { \
+ char * _dst = (dst); \
+ Size _len = (len); \
+\
+ if (_len > 0) \
+ { \
+ strncpy(_dst, (src), _len); \
+ _dst[_len-1] = '\0'; \
+ } \
+ } while (0)
+
+
+/* Get a bit mask of the bits set in non-long aligned addresses */
+#define LONG_ALIGN_MASK (sizeof(long) - 1)
+
+/*
+ * MemSet
+ * Exactly the same as standard library function memset(), but considerably
+ * faster for zeroing small word-aligned structures (such as parsetree nodes).
+ * This has to be a macro because the main point is to avoid function-call
+ * overhead. However, we have also found that the loop is faster than
+ * native libc memset() on some platforms, even those with assembler
+ * memset() functions. More research needs to be done, perhaps with
+ * MEMSET_LOOP_LIMIT tests in configure.
+ */
+#define MemSet(start, val, len) \
+ do \
+ { \
+ /* must be void* because we don't know if it is integer aligned yet */ \
+ void *_vstart = (void *) (start); \
+ int _val = (val); \
+ Size _len = (len); \
+\
+ if ((((uintptr_t) _vstart) & LONG_ALIGN_MASK) == 0 && \
+ (_len & LONG_ALIGN_MASK) == 0 && \
+ _val == 0 && \
+ _len <= MEMSET_LOOP_LIMIT && \
+ /* \
+ * If MEMSET_LOOP_LIMIT == 0, optimizer should find \
+ * the whole "if" false at compile time. \
+ */ \
+ MEMSET_LOOP_LIMIT != 0) \
+ { \
+ long *_start = (long *) _vstart; \
+ long *_stop = (long *) ((char *) _start + _len); \
+ while (_start < _stop) \
+ *_start++ = 0; \
+ } \
+ else \
+ memset(_vstart, _val, _len); \
+ } while (0)
+
+/*
+ * MemSetAligned is the same as MemSet except it omits the test to see if
+ * "start" is word-aligned. This is okay to use if the caller knows a-priori
+ * that the pointer is suitably aligned (typically, because he just got it
+ * from palloc(), which always delivers a max-aligned pointer).
+ */
+#define MemSetAligned(start, val, len) \
+ do \
+ { \
+ long *_start = (long *) (start); \
+ int _val = (val); \
+ Size _len = (len); \
+\
+ if ((_len & LONG_ALIGN_MASK) == 0 && \
+ _val == 0 && \
+ _len <= MEMSET_LOOP_LIMIT && \
+ MEMSET_LOOP_LIMIT != 0) \
+ { \
+ long *_stop = (long *) ((char *) _start + _len); \
+ while (_start < _stop) \
+ *_start++ = 0; \
+ } \
+ else \
+ memset(_start, _val, _len); \
+ } while (0)
+
+
+/*
+ * MemSetTest/MemSetLoop are a variant version that allow all the tests in
+ * MemSet to be done at compile time in cases where "val" and "len" are
+ * constants *and* we know the "start" pointer must be word-aligned.
+ * If MemSetTest succeeds, then it is okay to use MemSetLoop, otherwise use
+ * MemSetAligned. Beware of multiple evaluations of the arguments when using
+ * this approach.
+ */
+#define MemSetTest(val, len) \
+ ( ((len) & LONG_ALIGN_MASK) == 0 && \
+ (len) <= MEMSET_LOOP_LIMIT && \
+ MEMSET_LOOP_LIMIT != 0 && \
+ (val) == 0 )
+
+#define MemSetLoop(start, val, len) \
+ do \
+ { \
+ long * _start = (long *) (start); \
+ long * _stop = (long *) ((char *) _start + (Size) (len)); \
+ \
+ while (_start < _stop) \
+ *_start++ = 0; \
+ } while (0)
+
+/*
+ * Macros for range-checking float values before converting to integer.
+ * We must be careful here that the boundary values are expressed exactly
+ * in the float domain. PG_INTnn_MIN is an exact power of 2, so it will
+ * be represented exactly; but PG_INTnn_MAX isn't, and might get rounded
+ * off, so avoid using that.
+ * The input must be rounded to an integer beforehand, typically with rint(),
+ * else we might draw the wrong conclusion about close-to-the-limit values.
+ * These macros will do the right thing for Inf, but not necessarily for NaN,
+ * so check isnan(num) first if that's a possibility.
+ */
+#define FLOAT4_FITS_IN_INT16(num) \
+ ((num) >= (float4) PG_INT16_MIN && (num) < -((float4) PG_INT16_MIN))
+#define FLOAT4_FITS_IN_INT32(num) \
+ ((num) >= (float4) PG_INT32_MIN && (num) < -((float4) PG_INT32_MIN))
+#define FLOAT4_FITS_IN_INT64(num) \
+ ((num) >= (float4) PG_INT64_MIN && (num) < -((float4) PG_INT64_MIN))
+#define FLOAT8_FITS_IN_INT16(num) \
+ ((num) >= (float8) PG_INT16_MIN && (num) < -((float8) PG_INT16_MIN))
+#define FLOAT8_FITS_IN_INT32(num) \
+ ((num) >= (float8) PG_INT32_MIN && (num) < -((float8) PG_INT32_MIN))
+#define FLOAT8_FITS_IN_INT64(num) \
+ ((num) >= (float8) PG_INT64_MIN && (num) < -((float8) PG_INT64_MIN))
+
+
+/* ----------------------------------------------------------------
+ * Section 8: random stuff
+ * ----------------------------------------------------------------
+ */
+
+#ifdef HAVE_STRUCT_SOCKADDR_UN
+#define HAVE_UNIX_SOCKETS 1
+#endif
+
+/*
+ * Invert the sign of a qsort-style comparison result, ie, exchange negative
+ * and positive integer values, being careful not to get the wrong answer
+ * for INT_MIN. The argument should be an integral variable.
+ */
+#define INVERT_COMPARE_RESULT(var) \
+ ((var) = ((var) < 0) ? 1 : -(var))
+
+/*
+ * Use this, not "char buf[BLCKSZ]", to declare a field or local variable
+ * holding a page buffer, if that page might be accessed as a page and not
+ * just a string of bytes. Otherwise the variable might be under-aligned,
+ * causing problems on alignment-picky hardware. (In some places, we use
+ * this to declare buffers even though we only pass them to read() and
+ * write(), because copying to/from aligned buffers is usually faster than
+ * using unaligned buffers.) We include both "double" and "int64" in the
+ * union to ensure that the compiler knows the value must be MAXALIGN'ed
+ * (cf. configure's computation of MAXIMUM_ALIGNOF).
+ */
+typedef union PGAlignedBlock
+{
+ char data[BLCKSZ];
+ double force_align_d;
+ int64 force_align_i64;
+} PGAlignedBlock;
+
+/* Same, but for an XLOG_BLCKSZ-sized buffer */
+typedef union PGAlignedXLogBlock
+{
+ char data[XLOG_BLCKSZ];
+ double force_align_d;
+ int64 force_align_i64;
+} PGAlignedXLogBlock;
+
+/* msb for char */
+#define HIGHBIT (0x80)
+#define IS_HIGHBIT_SET(ch) ((unsigned char)(ch) & HIGHBIT)
+
+/*
+ * Support macros for escaping strings. escape_backslash should be true
+ * if generating a non-standard-conforming string. Prefixing a string
+ * with ESCAPE_STRING_SYNTAX guarantees it is non-standard-conforming.
+ * Beware of multiple evaluation of the "ch" argument!
+ */
+#define SQL_STR_DOUBLE(ch, escape_backslash) \
+ ((ch) == '\'' || ((ch) == '\\' && (escape_backslash)))
+
+#define ESCAPE_STRING_SYNTAX 'E'
+
+
+#define STATUS_OK (0)
+#define STATUS_ERROR (-1)
+#define STATUS_EOF (-2)
+#define STATUS_WAITING (2)
+
+/*
+ * gettext support
+ */
+
+#ifndef ENABLE_NLS
+/* stuff we'd otherwise get from <libintl.h> */
+#define gettext(x) (x)
+#define dgettext(d,x) (x)
+#define ngettext(s,p,n) ((n) == 1 ? (s) : (p))
+#define dngettext(d,s,p,n) ((n) == 1 ? (s) : (p))
+#endif
+
+#define _(x) gettext(x)
+
+/*
+ * Use this to mark string constants as needing translation at some later
+ * time, rather than immediately. This is useful for cases where you need
+ * access to the original string and translated string, and for cases where
+ * immediate translation is not possible, like when initializing global
+ * variables.
+ * http://www.gnu.org/software/autoconf/manual/gettext/Special-cases.html
+ */
+#define gettext_noop(x) (x)
+
+/*
+ * To better support parallel installations of major PostgreSQL
+ * versions as well as parallel installations of major library soname
+ * versions, we mangle the gettext domain name by appending those
+ * version numbers. The coding rule ought to be that wherever the
+ * domain name is mentioned as a literal, it must be wrapped into
+ * PG_TEXTDOMAIN(). The macros below do not work on non-literals; but
+ * that is somewhat intentional because it avoids having to worry
+ * about multiple states of premangling and postmangling as the values
+ * are being passed around.
+ *
+ * Make sure this matches the installation rules in nls-global.mk.
+ */
+#ifdef SO_MAJOR_VERSION
+#define PG_TEXTDOMAIN(domain) (domain CppAsString2(SO_MAJOR_VERSION) "-" PG_MAJORVERSION)
+#else
+#define PG_TEXTDOMAIN(domain) (domain "-" PG_MAJORVERSION)
+#endif
+
+/*
+ * Macro that allows to cast constness and volatile away from an expression, but doesn't
+ * allow changing the underlying type. Enforcement of the latter
+ * currently only works for gcc like compilers.
+ *
+ * Please note IT IS NOT SAFE to cast constness away if the result will ever
+ * be modified (it would be undefined behaviour). Doing so anyway can cause
+ * compiler misoptimizations or runtime crashes (modifying readonly memory).
+ * It is only safe to use when the result will not be modified, but API
+ * design or language restrictions prevent you from declaring that
+ * (e.g. because a function returns both const and non-const variables).
+ *
+ * Note that this only works in function scope, not for global variables (it'd
+ * be nice, but not trivial, to improve that).
+ */
+#if defined(HAVE__BUILTIN_TYPES_COMPATIBLE_P)
+#define unconstify(underlying_type, expr) \
+ (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), const underlying_type), \
+ "wrong cast"), \
+ (underlying_type) (expr))
+#define unvolatize(underlying_type, expr) \
+ (StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), volatile underlying_type), \
+ "wrong cast"), \
+ (underlying_type) (expr))
+#else
+#define unconstify(underlying_type, expr) \
+ ((underlying_type) (expr))
+#define unvolatize(underlying_type, expr) \
+ ((underlying_type) (expr))
+#endif
+
+/* ----------------------------------------------------------------
+ * Section 9: system-specific hacks
+ *
+ * This should be limited to things that absolutely have to be
+ * included in every source file. The port-specific header file
+ * is usually a better place for this sort of thing.
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * NOTE: this is also used for opening text files.
+ * WIN32 treats Control-Z as EOF in files opened in text mode.
+ * Therefore, we open files in binary mode on Win32 so we can read
+ * literal control-Z. The other affect is that we see CRLF, but
+ * that is OK because we can already handle those cleanly.
+ */
+#if defined(WIN32) || defined(__CYGWIN__)
+#define PG_BINARY O_BINARY
+#define PG_BINARY_A "ab"
+#define PG_BINARY_R "rb"
+#define PG_BINARY_W "wb"
+#else
+#define PG_BINARY 0
+#define PG_BINARY_A "a"
+#define PG_BINARY_R "r"
+#define PG_BINARY_W "w"
+#endif
+
+/*
+ * Provide prototypes for routines not present in a particular machine's
+ * standard C library.
+ */
+
+#if defined(HAVE_FDATASYNC) && !HAVE_DECL_FDATASYNC
+extern int fdatasync(int fildes);
+#endif
+
+/* Older platforms may provide strto[u]ll functionality under other names */
+#if !defined(HAVE_STRTOLL) && defined(HAVE___STRTOLL)
+#define strtoll __strtoll
+#define HAVE_STRTOLL 1
+#endif
+
+#if !defined(HAVE_STRTOLL) && defined(HAVE_STRTOQ)
+#define strtoll strtoq
+#define HAVE_STRTOLL 1
+#endif
+
+#if !defined(HAVE_STRTOULL) && defined(HAVE___STRTOULL)
+#define strtoull __strtoull
+#define HAVE_STRTOULL 1
+#endif
+
+#if !defined(HAVE_STRTOULL) && defined(HAVE_STRTOUQ)
+#define strtoull strtouq
+#define HAVE_STRTOULL 1
+#endif
+
+#if defined(HAVE_STRTOLL) && !HAVE_DECL_STRTOLL
+extern long long strtoll(const char *str, char **endptr, int base);
+#endif
+
+#if defined(HAVE_STRTOULL) && !HAVE_DECL_STRTOULL
+extern unsigned long long strtoull(const char *str, char **endptr, int base);
+#endif
+
+/* no special DLL markers on most ports */
+#ifndef PGDLLIMPORT
+#define PGDLLIMPORT
+#endif
+#ifndef PGDLLEXPORT
+#define PGDLLEXPORT
+#endif
+
+/*
+ * The following is used as the arg list for signal handlers. Any ports
+ * that take something other than an int argument should override this in
+ * their pg_config_os.h file. Note that variable names are required
+ * because it is used in both the prototypes as well as the definitions.
+ * Note also the long name. We expect that this won't collide with
+ * other names causing compiler warnings.
+ */
+
+#ifndef SIGNAL_ARGS
+#define SIGNAL_ARGS int postgres_signal_arg
+#endif
+
+/*
+ * When there is no sigsetjmp, its functionality is provided by plain
+ * setjmp. Incidentally, nothing provides setjmp's functionality in
+ * that case. We now support the case only on Windows.
+ */
+#ifdef WIN32
+#define sigjmp_buf jmp_buf
+#define sigsetjmp(x,y) setjmp(x)
+#define siglongjmp longjmp
+#endif
+
+/* EXEC_BACKEND defines */
+#ifdef EXEC_BACKEND
+#define NON_EXEC_STATIC
+#else
+#define NON_EXEC_STATIC static
+#endif
+
+/* /port compatibility functions */
+#include "port.h"
+
+#endif /* C_H */
diff --git a/src/include/catalog/.gitignore b/src/include/catalog/.gitignore
new file mode 100644
index 0000000..6c8da54
--- /dev/null
+++ b/src/include/catalog/.gitignore
@@ -0,0 +1,3 @@
+/schemapg.h
+/pg_*_d.h
+/header-stamp
diff --git a/src/include/catalog/Makefile b/src/include/catalog/Makefile
new file mode 100644
index 0000000..67f02a0
--- /dev/null
+++ b/src/include/catalog/Makefile
@@ -0,0 +1,28 @@
+#-------------------------------------------------------------------------
+#
+# Makefile for src/include/catalog
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/Makefile
+#
+#-------------------------------------------------------------------------
+
+subdir = src/include/catalog
+top_builddir = ../../..
+include $(top_builddir)/src/Makefile.global
+
+# 'make reformat-dat-files' is a convenience target for rewriting the
+# catalog data files in our standard format. This includes collapsing
+# out any entries that are redundant with a BKI_DEFAULT annotation.
+reformat-dat-files:
+ $(PERL) $(srcdir)/reformat_dat_file.pl --output $(srcdir) $(srcdir)/pg_*.dat
+
+# 'make expand-dat-files' is a convenience target for expanding out all
+# default values in the catalog data files. This should be run before
+# altering or removing any BKI_DEFAULT annotation.
+expand-dat-files:
+ $(PERL) $(srcdir)/reformat_dat_file.pl --output $(srcdir) $(srcdir)/pg_*.dat --full-tuples
+
+.PHONY: reformat-dat-files expand-dat-files
diff --git a/src/include/catalog/binary_upgrade.h b/src/include/catalog/binary_upgrade.h
new file mode 100644
index 0000000..12d94fe
--- /dev/null
+++ b/src/include/catalog/binary_upgrade.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * binary_upgrade.h
+ * variables used for binary upgrades
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/binary_upgrade.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BINARY_UPGRADE_H
+#define BINARY_UPGRADE_H
+
+extern PGDLLIMPORT Oid binary_upgrade_next_pg_type_oid;
+extern PGDLLIMPORT Oid binary_upgrade_next_array_pg_type_oid;
+extern PGDLLIMPORT Oid binary_upgrade_next_toast_pg_type_oid;
+
+extern PGDLLIMPORT Oid binary_upgrade_next_heap_pg_class_oid;
+extern PGDLLIMPORT Oid binary_upgrade_next_index_pg_class_oid;
+extern PGDLLIMPORT Oid binary_upgrade_next_toast_pg_class_oid;
+
+extern PGDLLIMPORT Oid binary_upgrade_next_pg_enum_oid;
+extern PGDLLIMPORT Oid binary_upgrade_next_pg_authid_oid;
+
+extern PGDLLIMPORT bool binary_upgrade_record_init_privs;
+
+#endif /* BINARY_UPGRADE_H */
diff --git a/src/include/catalog/catalog.h b/src/include/catalog/catalog.h
new file mode 100644
index 0000000..7824a12
--- /dev/null
+++ b/src/include/catalog/catalog.h
@@ -0,0 +1,42 @@
+/*-------------------------------------------------------------------------
+ *
+ * catalog.h
+ * prototypes for functions in backend/catalog/catalog.c
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/catalog.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef CATALOG_H
+#define CATALOG_H
+
+#include "catalog/pg_class.h"
+#include "utils/relcache.h"
+
+
+extern bool IsSystemRelation(Relation relation);
+extern bool IsToastRelation(Relation relation);
+extern bool IsCatalogRelation(Relation relation);
+
+extern bool IsSystemClass(Oid relid, Form_pg_class reltuple);
+extern bool IsToastClass(Form_pg_class reltuple);
+
+extern bool IsCatalogRelationOid(Oid relid);
+
+extern bool IsCatalogNamespace(Oid namespaceId);
+extern bool IsToastNamespace(Oid namespaceId);
+
+extern bool IsReservedName(const char *name);
+
+extern bool IsSharedRelation(Oid relationId);
+
+extern Oid GetNewOidWithIndex(Relation relation, Oid indexId,
+ AttrNumber oidcolumn);
+extern Oid GetNewRelFileNode(Oid reltablespace, Relation pg_class,
+ char relpersistence);
+
+#endif /* CATALOG_H */
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
new file mode 100644
index 0000000..282019c
--- /dev/null
+++ b/src/include/catalog/catversion.h
@@ -0,0 +1,58 @@
+/*-------------------------------------------------------------------------
+ *
+ * catversion.h
+ * "Catalog version number" for PostgreSQL.
+ *
+ * The catalog version number is used to flag incompatible changes in
+ * the PostgreSQL system catalogs. Whenever anyone changes the format of
+ * a system catalog relation, or adds, deletes, or modifies standard
+ * catalog entries in such a way that an updated backend wouldn't work
+ * with an old database (or vice versa), the catalog version number
+ * should be changed. The version number stored in pg_control by initdb
+ * is checked against the version number compiled into the backend at
+ * startup time, so that a backend can refuse to run in an incompatible
+ * database.
+ *
+ * The point of this feature is to provide a finer grain of compatibility
+ * checking than is possible from looking at the major version number
+ * stored in PG_VERSION. It shouldn't matter to end users, but during
+ * development cycles we usually make quite a few incompatible changes
+ * to the contents of the system catalogs, and we don't want to bump the
+ * major version number for each one. What we can do instead is bump
+ * this internal version number. This should save some grief for
+ * developers who might otherwise waste time tracking down "bugs" that
+ * are really just code-vs-database incompatibilities.
+ *
+ * The rule for developers is: if you commit a change that requires
+ * an initdb, you should update the catalog version number (as well as
+ * notifying the pgsql-hackers mailing list, which has been the
+ * informal practice for a long time).
+ *
+ * The catalog version number is placed here since modifying files in
+ * include/catalog is the most common kind of initdb-forcing change.
+ * But it could be used to protect any kind of incompatible change in
+ * database contents or layout, such as altering tuple headers.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/catversion.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef CATVERSION_H
+#define CATVERSION_H
+
+/*
+ * We could use anything we wanted for version numbers, but I recommend
+ * following the "YYYYMMDDN" style often used for DNS zone serial numbers.
+ * YYYYMMDD are the date of the change, and N is the number of the change
+ * on that day. (Hopefully we'll never commit ten independent sets of
+ * catalog changes on the same day...)
+ */
+
+/* yyyymmddN */
+#define CATALOG_VERSION_NO 202007201
+
+#endif
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
new file mode 100644
index 0000000..7fe3fb7
--- /dev/null
+++ b/src/include/catalog/dependency.h
@@ -0,0 +1,275 @@
+/*-------------------------------------------------------------------------
+ *
+ * dependency.h
+ * Routines to support inter-object dependencies.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/dependency.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DEPENDENCY_H
+#define DEPENDENCY_H
+
+#include "catalog/objectaddress.h"
+
+
+/*
+ * Precise semantics of a dependency relationship are specified by the
+ * DependencyType code (which is stored in a "char" field in pg_depend,
+ * so we assign ASCII-code values to the enumeration members).
+ *
+ * In all cases, a dependency relationship indicates that the referenced
+ * object may not be dropped without also dropping the dependent object.
+ * However, there are several subflavors; see the description of pg_depend
+ * in catalogs.sgml for details.
+ */
+
+typedef enum DependencyType
+{
+ DEPENDENCY_NORMAL = 'n',
+ DEPENDENCY_AUTO = 'a',
+ DEPENDENCY_INTERNAL = 'i',
+ DEPENDENCY_PARTITION_PRI = 'P',
+ DEPENDENCY_PARTITION_SEC = 'S',
+ DEPENDENCY_EXTENSION = 'e',
+ DEPENDENCY_AUTO_EXTENSION = 'x',
+ DEPENDENCY_PIN = 'p'
+} DependencyType;
+
+/*
+ * There is also a SharedDependencyType enum type that determines the exact
+ * semantics of an entry in pg_shdepend. Just like regular dependency entries,
+ * any pg_shdepend entry means that the referenced object cannot be dropped
+ * unless the dependent object is dropped at the same time. There are some
+ * additional rules however:
+ *
+ * (a) For a SHARED_DEPENDENCY_PIN entry, there is no dependent object --
+ * rather, the referenced object is an essential part of the system. This
+ * applies to the initdb-created superuser. Entries of this type are only
+ * created by initdb; objects in this category don't need further pg_shdepend
+ * entries if more objects come to depend on them.
+ *
+ * (b) a SHARED_DEPENDENCY_OWNER entry means that the referenced object is
+ * the role owning the dependent object. The referenced object must be
+ * a pg_authid entry.
+ *
+ * (c) a SHARED_DEPENDENCY_ACL entry means that the referenced object is
+ * a role mentioned in the ACL field of the dependent object. The referenced
+ * object must be a pg_authid entry. (SHARED_DEPENDENCY_ACL entries are not
+ * created for the owner of an object; hence two objects may be linked by
+ * one or the other, but not both, of these dependency types.)
+ *
+ * (d) a SHARED_DEPENDENCY_POLICY entry means that the referenced object is
+ * a role mentioned in a policy object. The referenced object must be a
+ * pg_authid entry.
+ *
+ * (e) a SHARED_DEPENDENCY_TABLESPACE entry means that the referenced
+ * object is a tablespace mentioned in a relation without storage. The
+ * referenced object must be a pg_tablespace entry. (Relations that have
+ * storage don't need this: they are protected by the existence of a physical
+ * file in the tablespace.)
+ *
+ * SHARED_DEPENDENCY_INVALID is a value used as a parameter in internal
+ * routines, and is not valid in the catalog itself.
+ */
+typedef enum SharedDependencyType
+{
+ SHARED_DEPENDENCY_PIN = 'p',
+ SHARED_DEPENDENCY_OWNER = 'o',
+ SHARED_DEPENDENCY_ACL = 'a',
+ SHARED_DEPENDENCY_POLICY = 'r',
+ SHARED_DEPENDENCY_TABLESPACE = 't',
+ SHARED_DEPENDENCY_INVALID = 0
+} SharedDependencyType;
+
+/* expansible list of ObjectAddresses (private in dependency.c) */
+typedef struct ObjectAddresses ObjectAddresses;
+
+/*
+ * This enum covers all system catalogs whose OIDs can appear in
+ * pg_depend.classId or pg_shdepend.classId. Keep object_classes[] in sync.
+ */
+typedef enum ObjectClass
+{
+ OCLASS_CLASS, /* pg_class */
+ OCLASS_PROC, /* pg_proc */
+ OCLASS_TYPE, /* pg_type */
+ OCLASS_CAST, /* pg_cast */
+ OCLASS_COLLATION, /* pg_collation */
+ OCLASS_CONSTRAINT, /* pg_constraint */
+ OCLASS_CONVERSION, /* pg_conversion */
+ OCLASS_DEFAULT, /* pg_attrdef */
+ OCLASS_LANGUAGE, /* pg_language */
+ OCLASS_LARGEOBJECT, /* pg_largeobject */
+ OCLASS_OPERATOR, /* pg_operator */
+ OCLASS_OPCLASS, /* pg_opclass */
+ OCLASS_OPFAMILY, /* pg_opfamily */
+ OCLASS_AM, /* pg_am */
+ OCLASS_AMOP, /* pg_amop */
+ OCLASS_AMPROC, /* pg_amproc */
+ OCLASS_REWRITE, /* pg_rewrite */
+ OCLASS_TRIGGER, /* pg_trigger */
+ OCLASS_SCHEMA, /* pg_namespace */
+ OCLASS_STATISTIC_EXT, /* pg_statistic_ext */
+ OCLASS_TSPARSER, /* pg_ts_parser */
+ OCLASS_TSDICT, /* pg_ts_dict */
+ OCLASS_TSTEMPLATE, /* pg_ts_template */
+ OCLASS_TSCONFIG, /* pg_ts_config */
+ OCLASS_ROLE, /* pg_authid */
+ OCLASS_DATABASE, /* pg_database */
+ OCLASS_TBLSPACE, /* pg_tablespace */
+ OCLASS_FDW, /* pg_foreign_data_wrapper */
+ OCLASS_FOREIGN_SERVER, /* pg_foreign_server */
+ OCLASS_USER_MAPPING, /* pg_user_mapping */
+ OCLASS_DEFACL, /* pg_default_acl */
+ OCLASS_EXTENSION, /* pg_extension */
+ OCLASS_EVENT_TRIGGER, /* pg_event_trigger */
+ OCLASS_POLICY, /* pg_policy */
+ OCLASS_PUBLICATION, /* pg_publication */
+ OCLASS_PUBLICATION_REL, /* pg_publication_rel */
+ OCLASS_SUBSCRIPTION, /* pg_subscription */
+ OCLASS_TRANSFORM /* pg_transform */
+} ObjectClass;
+
+#define LAST_OCLASS OCLASS_TRANSFORM
+
+/* flag bits for performDeletion/performMultipleDeletions: */
+#define PERFORM_DELETION_INTERNAL 0x0001 /* internal action */
+#define PERFORM_DELETION_CONCURRENTLY 0x0002 /* concurrent drop */
+#define PERFORM_DELETION_QUIETLY 0x0004 /* suppress notices */
+#define PERFORM_DELETION_SKIP_ORIGINAL 0x0008 /* keep original obj */
+#define PERFORM_DELETION_SKIP_EXTENSIONS 0x0010 /* keep extensions */
+#define PERFORM_DELETION_CONCURRENT_LOCK 0x0020 /* normal drop with
+ * concurrent lock mode */
+
+
+/* in dependency.c */
+
+extern void AcquireDeletionLock(const ObjectAddress *object, int flags);
+
+extern void ReleaseDeletionLock(const ObjectAddress *object);
+
+extern void performDeletion(const ObjectAddress *object,
+ DropBehavior behavior, int flags);
+
+extern void performMultipleDeletions(const ObjectAddresses *objects,
+ DropBehavior behavior, int flags);
+
+extern void recordDependencyOnExpr(const ObjectAddress *depender,
+ Node *expr, List *rtable,
+ DependencyType behavior);
+
+extern void recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
+ Node *expr, Oid relId,
+ DependencyType behavior,
+ DependencyType self_behavior,
+ bool reverse_self);
+
+extern ObjectClass getObjectClass(const ObjectAddress *object);
+
+extern ObjectAddresses *new_object_addresses(void);
+
+extern void add_exact_object_address(const ObjectAddress *object,
+ ObjectAddresses *addrs);
+
+extern bool object_address_present(const ObjectAddress *object,
+ const ObjectAddresses *addrs);
+
+extern void record_object_address_dependencies(const ObjectAddress *depender,
+ ObjectAddresses *referenced,
+ DependencyType behavior);
+
+extern void sort_object_addresses(ObjectAddresses *addrs);
+
+extern void free_object_addresses(ObjectAddresses *addrs);
+
+/* in pg_depend.c */
+
+extern void recordDependencyOn(const ObjectAddress *depender,
+ const ObjectAddress *referenced,
+ DependencyType behavior);
+
+extern void recordMultipleDependencies(const ObjectAddress *depender,
+ const ObjectAddress *referenced,
+ int nreferenced,
+ DependencyType behavior);
+
+extern void recordDependencyOnCurrentExtension(const ObjectAddress *object,
+ bool isReplace);
+
+extern long deleteDependencyRecordsFor(Oid classId, Oid objectId,
+ bool skipExtensionDeps);
+
+extern long deleteDependencyRecordsForClass(Oid classId, Oid objectId,
+ Oid refclassId, char deptype);
+
+extern long deleteDependencyRecordsForSpecific(Oid classId, Oid objectId,
+ char deptype,
+ Oid refclassId, Oid refobjectId);
+
+extern long changeDependencyFor(Oid classId, Oid objectId,
+ Oid refClassId, Oid oldRefObjectId,
+ Oid newRefObjectId);
+
+extern long changeDependenciesOf(Oid classId, Oid oldObjectId,
+ Oid newObjectId);
+
+extern long changeDependenciesOn(Oid refClassId, Oid oldRefObjectId,
+ Oid newRefObjectId);
+
+extern Oid getExtensionOfObject(Oid classId, Oid objectId);
+extern List *getAutoExtensionsOfObject(Oid classId, Oid objectId);
+
+extern bool sequenceIsOwned(Oid seqId, char deptype, Oid *tableId, int32 *colId);
+extern List *getOwnedSequences(Oid relid);
+extern Oid getIdentitySequence(Oid relid, AttrNumber attnum, bool missing_ok);
+
+extern Oid get_constraint_index(Oid constraintId);
+
+extern Oid get_index_constraint(Oid indexId);
+
+extern List *get_index_ref_constraints(Oid indexId);
+
+/* in pg_shdepend.c */
+
+extern void recordSharedDependencyOn(ObjectAddress *depender,
+ ObjectAddress *referenced,
+ SharedDependencyType deptype);
+
+extern void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId,
+ int32 objectSubId);
+
+extern void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner);
+
+extern void changeDependencyOnOwner(Oid classId, Oid objectId,
+ Oid newOwnerId);
+
+extern void recordDependencyOnTablespace(Oid classId, Oid objectId,
+ Oid tablespace);
+
+extern void changeDependencyOnTablespace(Oid classId, Oid objectId,
+ Oid newTablespaceId);
+
+extern void updateAclDependencies(Oid classId, Oid objectId, int32 objectSubId,
+ Oid ownerId,
+ int noldmembers, Oid *oldmembers,
+ int nnewmembers, Oid *newmembers);
+
+extern bool checkSharedDependencies(Oid classId, Oid objectId,
+ char **detail_msg, char **detail_log_msg);
+
+extern void shdepLockAndCheckObject(Oid classId, Oid objectId);
+
+extern void copyTemplateDependencies(Oid templateDbId, Oid newDbId);
+
+extern void dropDatabaseDependencies(Oid databaseId);
+
+extern void shdepDropOwned(List *relids, DropBehavior behavior);
+
+extern void shdepReassignOwned(List *relids, Oid newrole);
+
+#endif /* DEPENDENCY_H */
diff --git a/src/include/catalog/duplicate_oids b/src/include/catalog/duplicate_oids
new file mode 100755
index 0000000..9e5e9a1
--- /dev/null
+++ b/src/include/catalog/duplicate_oids
@@ -0,0 +1,49 @@
+#!/usr/bin/perl
+#----------------------------------------------------------------------
+#
+# duplicate_oids
+# Identifies any manually-assigned OIDs that are used multiple times
+# in the Postgres catalog data.
+#
+# While duplicate OIDs would only cause a failure if they appear in
+# the same catalog, our project policy is that manually assigned OIDs
+# should be globally unique, to avoid confusion.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/duplicate_oids
+#
+#----------------------------------------------------------------------
+
+use strict;
+use warnings;
+
+# Must run in src/include/catalog
+use FindBin;
+chdir $FindBin::RealBin or die "could not cd to $FindBin::RealBin: $!\n";
+
+use lib "$FindBin::RealBin/../../backend/catalog/";
+use Catalog;
+
+my @input_files = (glob("pg_*.h"), qw(indexing.h toasting.h));
+
+my $oids = Catalog::FindAllOidsFromHeaders(@input_files);
+
+my %oidcounts;
+
+foreach my $oid (@{$oids})
+{
+ $oidcounts{$oid}++;
+}
+
+my $found = 0;
+
+foreach my $oid (sort { $a <=> $b } keys %oidcounts)
+{
+ next unless $oidcounts{$oid} > 1;
+ $found = 1;
+ print "$oid\n";
+}
+
+exit $found;
diff --git a/src/include/catalog/genbki.h b/src/include/catalog/genbki.h
new file mode 100644
index 0000000..4a6c863
--- /dev/null
+++ b/src/include/catalog/genbki.h
@@ -0,0 +1,64 @@
+/*-------------------------------------------------------------------------
+ *
+ * genbki.h
+ * Required include file for all POSTGRES catalog header files
+ *
+ * genbki.h defines CATALOG(), BKI_BOOTSTRAP and related macros
+ * so that the catalog header files can be read by the C compiler.
+ * (These same words are recognized by genbki.pl to build the BKI
+ * bootstrap file from these header files.)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/genbki.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef GENBKI_H
+#define GENBKI_H
+
+/* Introduces a catalog's structure definition */
+#define CATALOG(name,oid,oidmacro) typedef struct CppConcat(FormData_,name)
+
+/* Options that may appear after CATALOG (on the same line) */
+#define BKI_BOOTSTRAP
+#define BKI_SHARED_RELATION
+#define BKI_ROWTYPE_OID(oid,oidmacro)
+#define BKI_SCHEMA_MACRO
+
+/* Options that may appear after an attribute (on the same line) */
+#define BKI_FORCE_NULL
+#define BKI_FORCE_NOT_NULL
+/* Specifies a default value for a catalog field */
+#define BKI_DEFAULT(value)
+/* Specifies a default value for auto-generated array types */
+#define BKI_ARRAY_DEFAULT(value)
+/*
+ * Indicates how to perform name lookups, typically for an OID or
+ * OID-array field
+ */
+#define BKI_LOOKUP(catalog)
+
+/* The following are never defined; they are here only for documentation. */
+
+/*
+ * Variable-length catalog fields (except possibly the first not nullable one)
+ * should not be visible in C structures, so they are made invisible by #ifdefs
+ * of an undefined symbol. See also MARKNOTNULL in bootstrap.c for how this is
+ * handled.
+ */
+#undef CATALOG_VARLEN
+
+/*
+ * There is code in some catalog headers that needs to be visible to clients,
+ * but we don't want clients to include the full header because of safety
+ * issues with other code in the header. To handle that, surround code that
+ * should be visible to clients with "#ifdef EXPOSE_TO_CLIENT_CODE". That
+ * instructs genbki.pl to copy the section when generating the corresponding
+ * "_d" header, which can be included by both client and backend code.
+ */
+#undef EXPOSE_TO_CLIENT_CODE
+
+#endif /* GENBKI_H */
diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h
new file mode 100644
index 0000000..bec795a
--- /dev/null
+++ b/src/include/catalog/heap.h
@@ -0,0 +1,163 @@
+/*-------------------------------------------------------------------------
+ *
+ * heap.h
+ * prototypes for functions in backend/catalog/heap.c
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/heap.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef HEAP_H
+#define HEAP_H
+
+#include "catalog/indexing.h"
+#include "catalog/objectaddress.h"
+#include "parser/parse_node.h"
+
+
+/* flag bits for CheckAttributeType/CheckAttributeNamesTypes */
+#define CHKATYPE_ANYARRAY 0x01 /* allow ANYARRAY */
+#define CHKATYPE_ANYRECORD 0x02 /* allow RECORD and RECORD[] */
+#define CHKATYPE_IS_PARTKEY 0x04 /* attname is part key # not column */
+
+typedef struct RawColumnDefault
+{
+ AttrNumber attnum; /* attribute to attach default to */
+ Node *raw_default; /* default value (untransformed parse tree) */
+ bool missingMode; /* true if part of add column processing */
+ char generated; /* attgenerated setting */
+} RawColumnDefault;
+
+typedef struct CookedConstraint
+{
+ ConstrType contype; /* CONSTR_DEFAULT or CONSTR_CHECK */
+ Oid conoid; /* constr OID if created, otherwise Invalid */
+ char *name; /* name, or NULL if none */
+ AttrNumber attnum; /* which attr (only for DEFAULT) */
+ Node *expr; /* transformed default or check expr */
+ bool skip_validation; /* skip validation? (only for CHECK) */
+ bool is_local; /* constraint has local (non-inherited) def */
+ int inhcount; /* number of times constraint is inherited */
+ bool is_no_inherit; /* constraint has local def and cannot be
+ * inherited */
+} CookedConstraint;
+
+extern Relation heap_create(const char *relname,
+ Oid relnamespace,
+ Oid reltablespace,
+ Oid relid,
+ Oid relfilenode,
+ Oid accessmtd,
+ TupleDesc tupDesc,
+ char relkind,
+ char relpersistence,
+ bool shared_relation,
+ bool mapped_relation,
+ bool allow_system_table_mods,
+ TransactionId *relfrozenxid,
+ MultiXactId *relminmxid);
+
+extern Oid heap_create_with_catalog(const char *relname,
+ Oid relnamespace,
+ Oid reltablespace,
+ Oid relid,
+ Oid reltypeid,
+ Oid reloftypeid,
+ Oid ownerid,
+ Oid accessmtd,
+ TupleDesc tupdesc,
+ List *cooked_constraints,
+ char relkind,
+ char relpersistence,
+ bool shared_relation,
+ bool mapped_relation,
+ OnCommitAction oncommit,
+ Datum reloptions,
+ bool use_user_acl,
+ bool allow_system_table_mods,
+ bool is_internal,
+ Oid relrewrite,
+ ObjectAddress *typaddress);
+
+extern void heap_drop_with_catalog(Oid relid);
+
+extern void heap_truncate(List *relids);
+
+extern void heap_truncate_one_rel(Relation rel);
+
+extern void heap_truncate_check_FKs(List *relations, bool tempTables);
+
+extern List *heap_truncate_find_FKs(List *relationIds);
+
+extern void InsertPgAttributeTuple(Relation pg_attribute_rel,
+ Form_pg_attribute new_attribute,
+ Datum attoptions,
+ CatalogIndexState indstate);
+
+extern void InsertPgClassTuple(Relation pg_class_desc,
+ Relation new_rel_desc,
+ Oid new_rel_oid,
+ Datum relacl,
+ Datum reloptions);
+
+extern List *AddRelationNewConstraints(Relation rel,
+ List *newColDefaults,
+ List *newConstraints,
+ bool allow_merge,
+ bool is_local,
+ bool is_internal,
+ const char *queryString);
+
+extern void RelationClearMissing(Relation rel);
+extern void SetAttrMissing(Oid relid, char *attname, char *value);
+
+extern Oid StoreAttrDefault(Relation rel, AttrNumber attnum,
+ Node *expr, bool is_internal,
+ bool add_column_mode);
+
+extern Node *cookDefault(ParseState *pstate,
+ Node *raw_default,
+ Oid atttypid,
+ int32 atttypmod,
+ const char *attname,
+ char attgenerated);
+
+extern void DeleteRelationTuple(Oid relid);
+extern void DeleteAttributeTuples(Oid relid);
+extern void DeleteSystemAttributeTuples(Oid relid);
+extern void RemoveAttributeById(Oid relid, AttrNumber attnum);
+extern void RemoveAttrDefault(Oid relid, AttrNumber attnum,
+ DropBehavior behavior, bool complain, bool internal);
+extern void RemoveAttrDefaultById(Oid attrdefId);
+extern void CopyStatistics(Oid fromrelid, Oid torelid);
+extern void RemoveStatistics(Oid relid, AttrNumber attnum);
+
+extern const FormData_pg_attribute *SystemAttributeDefinition(AttrNumber attno);
+
+extern const FormData_pg_attribute *SystemAttributeByName(const char *attname);
+
+extern void CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind,
+ int flags);
+
+extern void CheckAttributeType(const char *attname,
+ Oid atttypid, Oid attcollation,
+ List *containing_rowtypes,
+ int flags);
+
+/* pg_partitioned_table catalog manipulation functions */
+extern void StorePartitionKey(Relation rel,
+ char strategy,
+ int16 partnatts,
+ AttrNumber *partattrs,
+ List *partexprs,
+ Oid *partopclass,
+ Oid *partcollation);
+extern void RemovePartitionKeyByRelId(Oid relid);
+extern void StorePartitionBound(Relation rel, Relation parent,
+ PartitionBoundSpec *bound);
+
+#endif /* HEAP_H */
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
new file mode 100644
index 0000000..f58e867
--- /dev/null
+++ b/src/include/catalog/index.h
@@ -0,0 +1,199 @@
+/*-------------------------------------------------------------------------
+ *
+ * index.h
+ * prototypes for catalog/index.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/index.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef INDEX_H
+#define INDEX_H
+
+#include "catalog/objectaddress.h"
+#include "nodes/execnodes.h"
+
+
+#define DEFAULT_INDEX_TYPE "btree"
+
+/* Action code for index_set_state_flags */
+typedef enum
+{
+ INDEX_CREATE_SET_READY,
+ INDEX_CREATE_SET_VALID,
+ INDEX_DROP_CLEAR_VALID,
+ INDEX_DROP_SET_DEAD
+} IndexStateFlagsAction;
+
+/* state info for validate_index bulkdelete callback */
+typedef struct ValidateIndexState
+{
+ Tuplesortstate *tuplesort; /* for sorting the index TIDs */
+ /* statistics (for debug purposes only): */
+ double htups,
+ itups,
+ tups_inserted;
+} ValidateIndexState;
+
+extern void index_check_primary_key(Relation heapRel,
+ IndexInfo *indexInfo,
+ bool is_alter_table,
+ IndexStmt *stmt);
+
+#define INDEX_CREATE_IS_PRIMARY (1 << 0)
+#define INDEX_CREATE_ADD_CONSTRAINT (1 << 1)
+#define INDEX_CREATE_SKIP_BUILD (1 << 2)
+#define INDEX_CREATE_CONCURRENT (1 << 3)
+#define INDEX_CREATE_IF_NOT_EXISTS (1 << 4)
+#define INDEX_CREATE_PARTITIONED (1 << 5)
+#define INDEX_CREATE_INVALID (1 << 6)
+
+extern Oid index_create(Relation heapRelation,
+ const char *indexRelationName,
+ Oid indexRelationId,
+ Oid parentIndexRelid,
+ Oid parentConstraintId,
+ Oid relFileNode,
+ IndexInfo *indexInfo,
+ List *indexColNames,
+ Oid accessMethodObjectId,
+ Oid tableSpaceId,
+ Oid *collationObjectId,
+ Oid *classObjectId,
+ int16 *coloptions,
+ Datum reloptions,
+ bits16 flags,
+ bits16 constr_flags,
+ bool allow_system_table_mods,
+ bool is_internal,
+ Oid *constraintId);
+
+#define INDEX_CONSTR_CREATE_MARK_AS_PRIMARY (1 << 0)
+#define INDEX_CONSTR_CREATE_DEFERRABLE (1 << 1)
+#define INDEX_CONSTR_CREATE_INIT_DEFERRED (1 << 2)
+#define INDEX_CONSTR_CREATE_UPDATE_INDEX (1 << 3)
+#define INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS (1 << 4)
+
+extern Oid index_concurrently_create_copy(Relation heapRelation,
+ Oid oldIndexId,
+ const char *newName);
+
+extern void index_concurrently_build(Oid heapRelationId,
+ Oid indexRelationId);
+
+extern void index_concurrently_swap(Oid newIndexId,
+ Oid oldIndexId,
+ const char *oldName);
+
+extern void index_concurrently_set_dead(Oid heapId,
+ Oid indexId);
+
+extern ObjectAddress index_constraint_create(Relation heapRelation,
+ Oid indexRelationId,
+ Oid parentConstraintId,
+ IndexInfo *indexInfo,
+ const char *constraintName,
+ char constraintType,
+ bits16 constr_flags,
+ bool allow_system_table_mods,
+ bool is_internal);
+
+extern void index_drop(Oid indexId, bool concurrent, bool concurrent_lock_mode);
+
+extern IndexInfo *BuildIndexInfo(Relation index);
+
+extern IndexInfo *BuildDummyIndexInfo(Relation index);
+
+extern bool CompareIndexInfo(IndexInfo *info1, IndexInfo *info2,
+ Oid *collations1, Oid *collations2,
+ Oid *opfamilies1, Oid *opfamilies2,
+ AttrMap *attmap);
+
+extern void BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii);
+
+extern void FormIndexDatum(IndexInfo *indexInfo,
+ TupleTableSlot *slot,
+ EState *estate,
+ Datum *values,
+ bool *isnull);
+
+extern void index_build(Relation heapRelation,
+ Relation indexRelation,
+ IndexInfo *indexInfo,
+ bool isreindex,
+ bool parallel);
+
+extern void validate_index(Oid heapId, Oid indexId, Snapshot snapshot);
+
+extern void index_set_state_flags(Oid indexId, IndexStateFlagsAction action);
+
+extern Oid IndexGetRelation(Oid indexId, bool missing_ok);
+
+extern void reindex_index(Oid indexId, bool skip_constraint_checks,
+ char relpersistence, int options);
+
+/* Flag bits for reindex_relation(): */
+#define REINDEX_REL_PROCESS_TOAST 0x01
+#define REINDEX_REL_SUPPRESS_INDEX_USE 0x02
+#define REINDEX_REL_CHECK_CONSTRAINTS 0x04
+#define REINDEX_REL_FORCE_INDEXES_UNLOGGED 0x08
+#define REINDEX_REL_FORCE_INDEXES_PERMANENT 0x10
+
+extern bool reindex_relation(Oid relid, int flags, int options);
+
+extern bool ReindexIsProcessingHeap(Oid heapOid);
+extern bool ReindexIsProcessingIndex(Oid indexOid);
+
+extern void ResetReindexState(int nestLevel);
+extern Size EstimateReindexStateSpace(void);
+extern void SerializeReindexState(Size maxsize, char *start_address);
+extern void RestoreReindexState(void *reindexstate);
+
+extern void IndexSetParentIndex(Relation idx, Oid parentOid);
+
+
+/*
+ * itemptr_encode - Encode ItemPointer as int64/int8
+ *
+ * This representation must produce values encoded as int64 that sort in the
+ * same order as their corresponding original TID values would (using the
+ * default int8 opclass to produce a result equivalent to the default TID
+ * opclass).
+ *
+ * As noted in validate_index(), this can be significantly faster.
+ */
+static inline int64
+itemptr_encode(ItemPointer itemptr)
+{
+ BlockNumber block = ItemPointerGetBlockNumber(itemptr);
+ OffsetNumber offset = ItemPointerGetOffsetNumber(itemptr);
+ int64 encoded;
+
+ /*
+ * Use the 16 least significant bits for the offset. 32 adjacent bits are
+ * used for the block number. Since remaining bits are unused, there
+ * cannot be negative encoded values (We assume a two's complement
+ * representation).
+ */
+ encoded = ((uint64) block << 16) | (uint16) offset;
+
+ return encoded;
+}
+
+/*
+ * itemptr_decode - Decode int64/int8 representation back to ItemPointer
+ */
+static inline void
+itemptr_decode(ItemPointer itemptr, int64 encoded)
+{
+ BlockNumber block = (BlockNumber) (encoded >> 16);
+ OffsetNumber offset = (OffsetNumber) (encoded & 0xFFFF);
+
+ ItemPointerSet(itemptr, block, offset);
+}
+
+#endif /* INDEX_H */
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
new file mode 100644
index 0000000..8be3038
--- /dev/null
+++ b/src/include/catalog/indexing.h
@@ -0,0 +1,366 @@
+/*-------------------------------------------------------------------------
+ *
+ * indexing.h
+ * This file provides some definitions to support indexing
+ * on system catalogs
+ *
+ * Caution: all #define's with numeric values in this file had better be
+ * object OIDs, else renumber_oids.pl might change them inappropriately.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/indexing.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef INDEXING_H
+#define INDEXING_H
+
+#include "access/htup.h"
+#include "utils/relcache.h"
+
+/*
+ * The state object used by CatalogOpenIndexes and friends is actually the
+ * same as the executor's ResultRelInfo, but we give it another type name
+ * to decouple callers from that fact.
+ */
+typedef struct ResultRelInfo *CatalogIndexState;
+
+/*
+ * indexing.c prototypes
+ */
+extern CatalogIndexState CatalogOpenIndexes(Relation heapRel);
+extern void CatalogCloseIndexes(CatalogIndexState indstate);
+extern void CatalogTupleInsert(Relation heapRel, HeapTuple tup);
+extern void CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup,
+ CatalogIndexState indstate);
+extern void CatalogTupleUpdate(Relation heapRel, ItemPointer otid,
+ HeapTuple tup);
+extern void CatalogTupleUpdateWithInfo(Relation heapRel,
+ ItemPointer otid, HeapTuple tup,
+ CatalogIndexState indstate);
+extern void CatalogTupleDelete(Relation heapRel, ItemPointer tid);
+
+
+/*
+ * These macros are just to keep the C compiler from spitting up on the
+ * upcoming commands for Catalog.pm.
+ */
+#define DECLARE_INDEX(name,oid,decl) extern int no_such_variable
+#define DECLARE_UNIQUE_INDEX(name,oid,decl) extern int no_such_variable
+
+
+/*
+ * What follows are lines processed by genbki.pl to create the statements
+ * the bootstrap parser will turn into DefineIndex calls.
+ *
+ * The keyword is DECLARE_INDEX or DECLARE_UNIQUE_INDEX. The first two
+ * arguments are the index name and OID, the rest is much like a standard
+ * 'create index' SQL command.
+ *
+ * For each index, we also provide a #define for its OID. References to
+ * the index in the C code should always use these #defines, not the actual
+ * index name (much less the numeric OID).
+ */
+
+DECLARE_UNIQUE_INDEX(pg_aggregate_fnoid_index, 2650, on pg_aggregate using btree(aggfnoid oid_ops));
+#define AggregateFnoidIndexId 2650
+
+DECLARE_UNIQUE_INDEX(pg_am_name_index, 2651, on pg_am using btree(amname name_ops));
+#define AmNameIndexId 2651
+DECLARE_UNIQUE_INDEX(pg_am_oid_index, 2652, on pg_am using btree(oid oid_ops));
+#define AmOidIndexId 2652
+
+DECLARE_UNIQUE_INDEX(pg_amop_fam_strat_index, 2653, on pg_amop using btree(amopfamily oid_ops, amoplefttype oid_ops, amoprighttype oid_ops, amopstrategy int2_ops));
+#define AccessMethodStrategyIndexId 2653
+DECLARE_UNIQUE_INDEX(pg_amop_opr_fam_index, 2654, on pg_amop using btree(amopopr oid_ops, amoppurpose char_ops, amopfamily oid_ops));
+#define AccessMethodOperatorIndexId 2654
+DECLARE_UNIQUE_INDEX(pg_amop_oid_index, 2756, on pg_amop using btree(oid oid_ops));
+#define AccessMethodOperatorOidIndexId 2756
+
+DECLARE_UNIQUE_INDEX(pg_amproc_fam_proc_index, 2655, on pg_amproc using btree(amprocfamily oid_ops, amproclefttype oid_ops, amprocrighttype oid_ops, amprocnum int2_ops));
+#define AccessMethodProcedureIndexId 2655
+DECLARE_UNIQUE_INDEX(pg_amproc_oid_index, 2757, on pg_amproc using btree(oid oid_ops));
+#define AccessMethodProcedureOidIndexId 2757
+
+DECLARE_UNIQUE_INDEX(pg_attrdef_adrelid_adnum_index, 2656, on pg_attrdef using btree(adrelid oid_ops, adnum int2_ops));
+#define AttrDefaultIndexId 2656
+DECLARE_UNIQUE_INDEX(pg_attrdef_oid_index, 2657, on pg_attrdef using btree(oid oid_ops));
+#define AttrDefaultOidIndexId 2657
+
+DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index, 2658, on pg_attribute using btree(attrelid oid_ops, attname name_ops));
+#define AttributeRelidNameIndexId 2658
+DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnum_index, 2659, on pg_attribute using btree(attrelid oid_ops, attnum int2_ops));
+#define AttributeRelidNumIndexId 2659
+
+DECLARE_UNIQUE_INDEX(pg_authid_rolname_index, 2676, on pg_authid using btree(rolname name_ops));
+#define AuthIdRolnameIndexId 2676
+DECLARE_UNIQUE_INDEX(pg_authid_oid_index, 2677, on pg_authid using btree(oid oid_ops));
+#define AuthIdOidIndexId 2677
+
+DECLARE_UNIQUE_INDEX(pg_auth_members_role_member_index, 2694, on pg_auth_members using btree(roleid oid_ops, member oid_ops));
+#define AuthMemRoleMemIndexId 2694
+DECLARE_UNIQUE_INDEX(pg_auth_members_member_role_index, 2695, on pg_auth_members using btree(member oid_ops, roleid oid_ops));
+#define AuthMemMemRoleIndexId 2695
+
+DECLARE_UNIQUE_INDEX(pg_cast_oid_index, 2660, on pg_cast using btree(oid oid_ops));
+#define CastOidIndexId 2660
+DECLARE_UNIQUE_INDEX(pg_cast_source_target_index, 2661, on pg_cast using btree(castsource oid_ops, casttarget oid_ops));
+#define CastSourceTargetIndexId 2661
+
+DECLARE_UNIQUE_INDEX(pg_class_oid_index, 2662, on pg_class using btree(oid oid_ops));
+#define ClassOidIndexId 2662
+DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index, 2663, on pg_class using btree(relname name_ops, relnamespace oid_ops));
+#define ClassNameNspIndexId 2663
+DECLARE_INDEX(pg_class_tblspc_relfilenode_index, 3455, on pg_class using btree(reltablespace oid_ops, relfilenode oid_ops));
+#define ClassTblspcRelfilenodeIndexId 3455
+
+DECLARE_UNIQUE_INDEX(pg_collation_name_enc_nsp_index, 3164, on pg_collation using btree(collname name_ops, collencoding int4_ops, collnamespace oid_ops));
+#define CollationNameEncNspIndexId 3164
+DECLARE_UNIQUE_INDEX(pg_collation_oid_index, 3085, on pg_collation using btree(oid oid_ops));
+#define CollationOidIndexId 3085
+
+DECLARE_INDEX(pg_constraint_conname_nsp_index, 2664, on pg_constraint using btree(conname name_ops, connamespace oid_ops));
+#define ConstraintNameNspIndexId 2664
+DECLARE_UNIQUE_INDEX(pg_constraint_conrelid_contypid_conname_index, 2665, on pg_constraint using btree(conrelid oid_ops, contypid oid_ops, conname name_ops));
+#define ConstraintRelidTypidNameIndexId 2665
+DECLARE_INDEX(pg_constraint_contypid_index, 2666, on pg_constraint using btree(contypid oid_ops));
+#define ConstraintTypidIndexId 2666
+DECLARE_UNIQUE_INDEX(pg_constraint_oid_index, 2667, on pg_constraint using btree(oid oid_ops));
+#define ConstraintOidIndexId 2667
+DECLARE_INDEX(pg_constraint_conparentid_index, 2579, on pg_constraint using btree(conparentid oid_ops));
+#define ConstraintParentIndexId 2579
+
+DECLARE_UNIQUE_INDEX(pg_conversion_default_index, 2668, on pg_conversion using btree(connamespace oid_ops, conforencoding int4_ops, contoencoding int4_ops, oid oid_ops));
+#define ConversionDefaultIndexId 2668
+DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index, 2669, on pg_conversion using btree(conname name_ops, connamespace oid_ops));
+#define ConversionNameNspIndexId 2669
+DECLARE_UNIQUE_INDEX(pg_conversion_oid_index, 2670, on pg_conversion using btree(oid oid_ops));
+#define ConversionOidIndexId 2670
+
+DECLARE_UNIQUE_INDEX(pg_database_datname_index, 2671, on pg_database using btree(datname name_ops));
+#define DatabaseNameIndexId 2671
+DECLARE_UNIQUE_INDEX(pg_database_oid_index, 2672, on pg_database using btree(oid oid_ops));
+#define DatabaseOidIndexId 2672
+
+DECLARE_INDEX(pg_depend_depender_index, 2673, on pg_depend using btree(classid oid_ops, objid oid_ops, objsubid int4_ops));
+#define DependDependerIndexId 2673
+DECLARE_INDEX(pg_depend_reference_index, 2674, on pg_depend using btree(refclassid oid_ops, refobjid oid_ops, refobjsubid int4_ops));
+#define DependReferenceIndexId 2674
+
+DECLARE_UNIQUE_INDEX(pg_description_o_c_o_index, 2675, on pg_description using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops));
+#define DescriptionObjIndexId 2675
+DECLARE_UNIQUE_INDEX(pg_shdescription_o_c_index, 2397, on pg_shdescription using btree(objoid oid_ops, classoid oid_ops));
+#define SharedDescriptionObjIndexId 2397
+
+DECLARE_UNIQUE_INDEX(pg_enum_oid_index, 3502, on pg_enum using btree(oid oid_ops));
+#define EnumOidIndexId 3502
+DECLARE_UNIQUE_INDEX(pg_enum_typid_label_index, 3503, on pg_enum using btree(enumtypid oid_ops, enumlabel name_ops));
+#define EnumTypIdLabelIndexId 3503
+DECLARE_UNIQUE_INDEX(pg_enum_typid_sortorder_index, 3534, on pg_enum using btree(enumtypid oid_ops, enumsortorder float4_ops));
+#define EnumTypIdSortOrderIndexId 3534
+
+DECLARE_INDEX(pg_index_indrelid_index, 2678, on pg_index using btree(indrelid oid_ops));
+#define IndexIndrelidIndexId 2678
+DECLARE_UNIQUE_INDEX(pg_index_indexrelid_index, 2679, on pg_index using btree(indexrelid oid_ops));
+#define IndexRelidIndexId 2679
+
+DECLARE_UNIQUE_INDEX(pg_inherits_relid_seqno_index, 2680, on pg_inherits using btree(inhrelid oid_ops, inhseqno int4_ops));
+#define InheritsRelidSeqnoIndexId 2680
+DECLARE_INDEX(pg_inherits_parent_index, 2187, on pg_inherits using btree(inhparent oid_ops));
+#define InheritsParentIndexId 2187
+
+DECLARE_UNIQUE_INDEX(pg_init_privs_o_c_o_index, 3395, on pg_init_privs using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops));
+#define InitPrivsObjIndexId 3395
+
+DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, on pg_language using btree(lanname name_ops));
+#define LanguageNameIndexId 2681
+DECLARE_UNIQUE_INDEX(pg_language_oid_index, 2682, on pg_language using btree(oid oid_ops));
+#define LanguageOidIndexId 2682
+
+DECLARE_UNIQUE_INDEX(pg_largeobject_loid_pn_index, 2683, on pg_largeobject using btree(loid oid_ops, pageno int4_ops));
+#define LargeObjectLOidPNIndexId 2683
+
+DECLARE_UNIQUE_INDEX(pg_largeobject_metadata_oid_index, 2996, on pg_largeobject_metadata using btree(oid oid_ops));
+#define LargeObjectMetadataOidIndexId 2996
+
+DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index, 2684, on pg_namespace using btree(nspname name_ops));
+#define NamespaceNameIndexId 2684
+DECLARE_UNIQUE_INDEX(pg_namespace_oid_index, 2685, on pg_namespace using btree(oid oid_ops));
+#define NamespaceOidIndexId 2685
+
+DECLARE_UNIQUE_INDEX(pg_opclass_am_name_nsp_index, 2686, on pg_opclass using btree(opcmethod oid_ops, opcname name_ops, opcnamespace oid_ops));
+#define OpclassAmNameNspIndexId 2686
+DECLARE_UNIQUE_INDEX(pg_opclass_oid_index, 2687, on pg_opclass using btree(oid oid_ops));
+#define OpclassOidIndexId 2687
+
+DECLARE_UNIQUE_INDEX(pg_operator_oid_index, 2688, on pg_operator using btree(oid oid_ops));
+#define OperatorOidIndexId 2688
+DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index, 2689, on pg_operator using btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops));
+#define OperatorNameNspIndexId 2689
+
+DECLARE_UNIQUE_INDEX(pg_opfamily_am_name_nsp_index, 2754, on pg_opfamily using btree(opfmethod oid_ops, opfname name_ops, opfnamespace oid_ops));
+#define OpfamilyAmNameNspIndexId 2754
+DECLARE_UNIQUE_INDEX(pg_opfamily_oid_index, 2755, on pg_opfamily using btree(oid oid_ops));
+#define OpfamilyOidIndexId 2755
+
+DECLARE_UNIQUE_INDEX(pg_proc_oid_index, 2690, on pg_proc using btree(oid oid_ops));
+#define ProcedureOidIndexId 2690
+DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index, 2691, on pg_proc using btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops));
+#define ProcedureNameArgsNspIndexId 2691
+
+DECLARE_UNIQUE_INDEX(pg_rewrite_oid_index, 2692, on pg_rewrite using btree(oid oid_ops));
+#define RewriteOidIndexId 2692
+DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index, 2693, on pg_rewrite using btree(ev_class oid_ops, rulename name_ops));
+#define RewriteRelRulenameIndexId 2693
+
+DECLARE_UNIQUE_INDEX(pg_sequence_seqrelid_index, 5002, on pg_sequence using btree(seqrelid oid_ops));
+#define SequenceRelidIndexId 5002
+
+DECLARE_INDEX(pg_shdepend_depender_index, 1232, on pg_shdepend using btree(dbid oid_ops, classid oid_ops, objid oid_ops, objsubid int4_ops));
+#define SharedDependDependerIndexId 1232
+DECLARE_INDEX(pg_shdepend_reference_index, 1233, on pg_shdepend using btree(refclassid oid_ops, refobjid oid_ops));
+#define SharedDependReferenceIndexId 1233
+
+DECLARE_UNIQUE_INDEX(pg_statistic_relid_att_inh_index, 2696, on pg_statistic using btree(starelid oid_ops, staattnum int2_ops, stainherit bool_ops));
+#define StatisticRelidAttnumInhIndexId 2696
+
+DECLARE_UNIQUE_INDEX(pg_statistic_ext_oid_index, 3380, on pg_statistic_ext using btree(oid oid_ops));
+#define StatisticExtOidIndexId 3380
+DECLARE_UNIQUE_INDEX(pg_statistic_ext_name_index, 3997, on pg_statistic_ext using btree(stxname name_ops, stxnamespace oid_ops));
+#define StatisticExtNameIndexId 3997
+DECLARE_INDEX(pg_statistic_ext_relid_index, 3379, on pg_statistic_ext using btree(stxrelid oid_ops));
+#define StatisticExtRelidIndexId 3379
+
+DECLARE_UNIQUE_INDEX(pg_statistic_ext_data_stxoid_index, 3433, on pg_statistic_ext_data using btree(stxoid oid_ops));
+#define StatisticExtDataStxoidIndexId 3433
+
+DECLARE_UNIQUE_INDEX(pg_tablespace_oid_index, 2697, on pg_tablespace using btree(oid oid_ops));
+#define TablespaceOidIndexId 2697
+DECLARE_UNIQUE_INDEX(pg_tablespace_spcname_index, 2698, on pg_tablespace using btree(spcname name_ops));
+#define TablespaceNameIndexId 2698
+
+DECLARE_UNIQUE_INDEX(pg_transform_oid_index, 3574, on pg_transform using btree(oid oid_ops));
+#define TransformOidIndexId 3574
+DECLARE_UNIQUE_INDEX(pg_transform_type_lang_index, 3575, on pg_transform using btree(trftype oid_ops, trflang oid_ops));
+#define TransformTypeLangIndexId 3575
+
+DECLARE_INDEX(pg_trigger_tgconstraint_index, 2699, on pg_trigger using btree(tgconstraint oid_ops));
+#define TriggerConstraintIndexId 2699
+DECLARE_UNIQUE_INDEX(pg_trigger_tgrelid_tgname_index, 2701, on pg_trigger using btree(tgrelid oid_ops, tgname name_ops));
+#define TriggerRelidNameIndexId 2701
+DECLARE_UNIQUE_INDEX(pg_trigger_oid_index, 2702, on pg_trigger using btree(oid oid_ops));
+#define TriggerOidIndexId 2702
+
+DECLARE_UNIQUE_INDEX(pg_event_trigger_evtname_index, 3467, on pg_event_trigger using btree(evtname name_ops));
+#define EventTriggerNameIndexId 3467
+DECLARE_UNIQUE_INDEX(pg_event_trigger_oid_index, 3468, on pg_event_trigger using btree(oid oid_ops));
+#define EventTriggerOidIndexId 3468
+
+DECLARE_UNIQUE_INDEX(pg_ts_config_cfgname_index, 3608, on pg_ts_config using btree(cfgname name_ops, cfgnamespace oid_ops));
+#define TSConfigNameNspIndexId 3608
+DECLARE_UNIQUE_INDEX(pg_ts_config_oid_index, 3712, on pg_ts_config using btree(oid oid_ops));
+#define TSConfigOidIndexId 3712
+
+DECLARE_UNIQUE_INDEX(pg_ts_config_map_index, 3609, on pg_ts_config_map using btree(mapcfg oid_ops, maptokentype int4_ops, mapseqno int4_ops));
+#define TSConfigMapIndexId 3609
+
+DECLARE_UNIQUE_INDEX(pg_ts_dict_dictname_index, 3604, on pg_ts_dict using btree(dictname name_ops, dictnamespace oid_ops));
+#define TSDictionaryNameNspIndexId 3604
+DECLARE_UNIQUE_INDEX(pg_ts_dict_oid_index, 3605, on pg_ts_dict using btree(oid oid_ops));
+#define TSDictionaryOidIndexId 3605
+
+DECLARE_UNIQUE_INDEX(pg_ts_parser_prsname_index, 3606, on pg_ts_parser using btree(prsname name_ops, prsnamespace oid_ops));
+#define TSParserNameNspIndexId 3606
+DECLARE_UNIQUE_INDEX(pg_ts_parser_oid_index, 3607, on pg_ts_parser using btree(oid oid_ops));
+#define TSParserOidIndexId 3607
+
+DECLARE_UNIQUE_INDEX(pg_ts_template_tmplname_index, 3766, on pg_ts_template using btree(tmplname name_ops, tmplnamespace oid_ops));
+#define TSTemplateNameNspIndexId 3766
+DECLARE_UNIQUE_INDEX(pg_ts_template_oid_index, 3767, on pg_ts_template using btree(oid oid_ops));
+#define TSTemplateOidIndexId 3767
+
+DECLARE_UNIQUE_INDEX(pg_type_oid_index, 2703, on pg_type using btree(oid oid_ops));
+#define TypeOidIndexId 2703
+DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index, 2704, on pg_type using btree(typname name_ops, typnamespace oid_ops));
+#define TypeNameNspIndexId 2704
+
+DECLARE_UNIQUE_INDEX(pg_foreign_data_wrapper_oid_index, 112, on pg_foreign_data_wrapper using btree(oid oid_ops));
+#define ForeignDataWrapperOidIndexId 112
+DECLARE_UNIQUE_INDEX(pg_foreign_data_wrapper_name_index, 548, on pg_foreign_data_wrapper using btree(fdwname name_ops));
+#define ForeignDataWrapperNameIndexId 548
+
+DECLARE_UNIQUE_INDEX(pg_foreign_server_oid_index, 113, on pg_foreign_server using btree(oid oid_ops));
+#define ForeignServerOidIndexId 113
+DECLARE_UNIQUE_INDEX(pg_foreign_server_name_index, 549, on pg_foreign_server using btree(srvname name_ops));
+#define ForeignServerNameIndexId 549
+
+DECLARE_UNIQUE_INDEX(pg_user_mapping_oid_index, 174, on pg_user_mapping using btree(oid oid_ops));
+#define UserMappingOidIndexId 174
+DECLARE_UNIQUE_INDEX(pg_user_mapping_user_server_index, 175, on pg_user_mapping using btree(umuser oid_ops, umserver oid_ops));
+#define UserMappingUserServerIndexId 175
+
+DECLARE_UNIQUE_INDEX(pg_foreign_table_relid_index, 3119, on pg_foreign_table using btree(ftrelid oid_ops));
+#define ForeignTableRelidIndexId 3119
+
+DECLARE_UNIQUE_INDEX(pg_default_acl_role_nsp_obj_index, 827, on pg_default_acl using btree(defaclrole oid_ops, defaclnamespace oid_ops, defaclobjtype char_ops));
+#define DefaultAclRoleNspObjIndexId 827
+DECLARE_UNIQUE_INDEX(pg_default_acl_oid_index, 828, on pg_default_acl using btree(oid oid_ops));
+#define DefaultAclOidIndexId 828
+
+DECLARE_UNIQUE_INDEX(pg_db_role_setting_databaseid_rol_index, 2965, on pg_db_role_setting using btree(setdatabase oid_ops, setrole oid_ops));
+#define DbRoleSettingDatidRolidIndexId 2965
+
+DECLARE_UNIQUE_INDEX(pg_seclabel_object_index, 3597, on pg_seclabel using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops, provider text_ops));
+#define SecLabelObjectIndexId 3597
+
+DECLARE_UNIQUE_INDEX(pg_shseclabel_object_index, 3593, on pg_shseclabel using btree(objoid oid_ops, classoid oid_ops, provider text_ops));
+#define SharedSecLabelObjectIndexId 3593
+
+DECLARE_UNIQUE_INDEX(pg_extension_oid_index, 3080, on pg_extension using btree(oid oid_ops));
+#define ExtensionOidIndexId 3080
+DECLARE_UNIQUE_INDEX(pg_extension_name_index, 3081, on pg_extension using btree(extname name_ops));
+#define ExtensionNameIndexId 3081
+
+DECLARE_UNIQUE_INDEX(pg_range_rngtypid_index, 3542, on pg_range using btree(rngtypid oid_ops));
+#define RangeTypidIndexId 3542
+
+DECLARE_UNIQUE_INDEX(pg_policy_oid_index, 3257, on pg_policy using btree(oid oid_ops));
+#define PolicyOidIndexId 3257
+
+DECLARE_UNIQUE_INDEX(pg_policy_polrelid_polname_index, 3258, on pg_policy using btree(polrelid oid_ops, polname name_ops));
+#define PolicyPolrelidPolnameIndexId 3258
+
+DECLARE_UNIQUE_INDEX(pg_replication_origin_roiident_index, 6001, on pg_replication_origin using btree(roident oid_ops));
+#define ReplicationOriginIdentIndex 6001
+
+DECLARE_UNIQUE_INDEX(pg_replication_origin_roname_index, 6002, on pg_replication_origin using btree(roname text_ops));
+#define ReplicationOriginNameIndex 6002
+
+DECLARE_UNIQUE_INDEX(pg_partitioned_table_partrelid_index, 3351, on pg_partitioned_table using btree(partrelid oid_ops));
+#define PartitionedRelidIndexId 3351
+
+DECLARE_UNIQUE_INDEX(pg_publication_oid_index, 6110, on pg_publication using btree(oid oid_ops));
+#define PublicationObjectIndexId 6110
+
+DECLARE_UNIQUE_INDEX(pg_publication_pubname_index, 6111, on pg_publication using btree(pubname name_ops));
+#define PublicationNameIndexId 6111
+
+DECLARE_UNIQUE_INDEX(pg_publication_rel_oid_index, 6112, on pg_publication_rel using btree(oid oid_ops));
+#define PublicationRelObjectIndexId 6112
+
+DECLARE_UNIQUE_INDEX(pg_publication_rel_prrelid_prpubid_index, 6113, on pg_publication_rel using btree(prrelid oid_ops, prpubid oid_ops));
+#define PublicationRelPrrelidPrpubidIndexId 6113
+
+DECLARE_UNIQUE_INDEX(pg_subscription_oid_index, 6114, on pg_subscription using btree(oid oid_ops));
+#define SubscriptionObjectIndexId 6114
+
+DECLARE_UNIQUE_INDEX(pg_subscription_subname_index, 6115, on pg_subscription using btree(subdbid oid_ops, subname name_ops));
+#define SubscriptionNameIndexId 6115
+
+DECLARE_UNIQUE_INDEX(pg_subscription_rel_srrelid_srsubid_index, 6117, on pg_subscription_rel using btree(srrelid oid_ops, srsubid oid_ops));
+#define SubscriptionRelSrrelidSrsubidIndexId 6117
+
+#endif /* INDEXING_H */
diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h
new file mode 100644
index 0000000..2456c08
--- /dev/null
+++ b/src/include/catalog/namespace.h
@@ -0,0 +1,188 @@
+/*-------------------------------------------------------------------------
+ *
+ * namespace.h
+ * prototypes for functions in backend/catalog/namespace.c
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/namespace.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NAMESPACE_H
+#define NAMESPACE_H
+
+#include "nodes/primnodes.h"
+#include "storage/lock.h"
+
+
+/*
+ * This structure holds a list of possible functions or operators
+ * found by namespace lookup. Each function/operator is identified
+ * by OID and by argument types; the list must be pruned by type
+ * resolution rules that are embodied in the parser, not here.
+ * See FuncnameGetCandidates's comments for more info.
+ */
+typedef struct _FuncCandidateList
+{
+ struct _FuncCandidateList *next;
+ int pathpos; /* for internal use of namespace lookup */
+ Oid oid; /* the function or operator's OID */
+ int nargs; /* number of arg types returned */
+ int nvargs; /* number of args to become variadic array */
+ int ndargs; /* number of defaulted args */
+ int *argnumbers; /* args' positional indexes, if named call */
+ Oid args[FLEXIBLE_ARRAY_MEMBER]; /* arg types */
+} *FuncCandidateList;
+
+/*
+ * Result of checkTempNamespaceStatus
+ */
+typedef enum TempNamespaceStatus
+{
+ TEMP_NAMESPACE_NOT_TEMP, /* nonexistent, or non-temp namespace */
+ TEMP_NAMESPACE_IDLE, /* exists, belongs to no active session */
+ TEMP_NAMESPACE_IN_USE /* belongs to some active session */
+} TempNamespaceStatus;
+
+/*
+ * Structure for xxxOverrideSearchPath functions
+ *
+ * The generation counter is private to namespace.c and shouldn't be touched
+ * by other code. It can be initialized to zero if necessary (that means
+ * "not known equal to the current active path").
+ */
+typedef struct OverrideSearchPath
+{
+ List *schemas; /* OIDs of explicitly named schemas */
+ bool addCatalog; /* implicitly prepend pg_catalog? */
+ bool addTemp; /* implicitly prepend temp schema? */
+ uint64 generation; /* for quick detection of equality to active */
+} OverrideSearchPath;
+
+/*
+ * Option flag bits for RangeVarGetRelidExtended().
+ */
+typedef enum RVROption
+{
+ RVR_MISSING_OK = 1 << 0, /* don't error if relation doesn't exist */
+ RVR_NOWAIT = 1 << 1, /* error if relation cannot be locked */
+ RVR_SKIP_LOCKED = 1 << 2 /* skip if relation cannot be locked */
+} RVROption;
+
+typedef void (*RangeVarGetRelidCallback) (const RangeVar *relation, Oid relId,
+ Oid oldRelId, void *callback_arg);
+
+#define RangeVarGetRelid(relation, lockmode, missing_ok) \
+ RangeVarGetRelidExtended(relation, lockmode, \
+ (missing_ok) ? RVR_MISSING_OK : 0, NULL, NULL)
+
+extern Oid RangeVarGetRelidExtended(const RangeVar *relation,
+ LOCKMODE lockmode, uint32 flags,
+ RangeVarGetRelidCallback callback,
+ void *callback_arg);
+extern Oid RangeVarGetCreationNamespace(const RangeVar *newRelation);
+extern Oid RangeVarGetAndCheckCreationNamespace(RangeVar *newRelation,
+ LOCKMODE lockmode,
+ Oid *existing_relation_id);
+extern void RangeVarAdjustRelationPersistence(RangeVar *newRelation, Oid nspid);
+extern Oid RelnameGetRelid(const char *relname);
+extern bool RelationIsVisible(Oid relid);
+
+extern Oid TypenameGetTypid(const char *typname);
+extern Oid TypenameGetTypidExtended(const char *typname, bool temp_ok);
+extern bool TypeIsVisible(Oid typid);
+
+extern FuncCandidateList FuncnameGetCandidates(List *names,
+ int nargs, List *argnames,
+ bool expand_variadic,
+ bool expand_defaults,
+ bool missing_ok);
+extern bool FunctionIsVisible(Oid funcid);
+
+extern Oid OpernameGetOprid(List *names, Oid oprleft, Oid oprright);
+extern FuncCandidateList OpernameGetCandidates(List *names, char oprkind,
+ bool missing_schema_ok);
+extern bool OperatorIsVisible(Oid oprid);
+
+extern Oid OpclassnameGetOpcid(Oid amid, const char *opcname);
+extern bool OpclassIsVisible(Oid opcid);
+
+extern Oid OpfamilynameGetOpfid(Oid amid, const char *opfname);
+extern bool OpfamilyIsVisible(Oid opfid);
+
+extern Oid CollationGetCollid(const char *collname);
+extern bool CollationIsVisible(Oid collid);
+
+extern Oid ConversionGetConid(const char *conname);
+extern bool ConversionIsVisible(Oid conid);
+
+extern Oid get_statistics_object_oid(List *names, bool missing_ok);
+extern bool StatisticsObjIsVisible(Oid relid);
+
+extern Oid get_ts_parser_oid(List *names, bool missing_ok);
+extern bool TSParserIsVisible(Oid prsId);
+
+extern Oid get_ts_dict_oid(List *names, bool missing_ok);
+extern bool TSDictionaryIsVisible(Oid dictId);
+
+extern Oid get_ts_template_oid(List *names, bool missing_ok);
+extern bool TSTemplateIsVisible(Oid tmplId);
+
+extern Oid get_ts_config_oid(List *names, bool missing_ok);
+extern bool TSConfigIsVisible(Oid cfgid);
+
+extern void DeconstructQualifiedName(List *names,
+ char **nspname_p,
+ char **objname_p);
+extern Oid LookupNamespaceNoError(const char *nspname);
+extern Oid LookupExplicitNamespace(const char *nspname, bool missing_ok);
+extern Oid get_namespace_oid(const char *nspname, bool missing_ok);
+
+extern Oid LookupCreationNamespace(const char *nspname);
+extern void CheckSetNamespace(Oid oldNspOid, Oid nspOid);
+extern Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p);
+extern RangeVar *makeRangeVarFromNameList(List *names);
+extern char *NameListToString(List *names);
+extern char *NameListToQuotedString(List *names);
+
+extern bool isTempNamespace(Oid namespaceId);
+extern bool isTempToastNamespace(Oid namespaceId);
+extern bool isTempOrTempToastNamespace(Oid namespaceId);
+extern bool isAnyTempNamespace(Oid namespaceId);
+extern bool isOtherTempNamespace(Oid namespaceId);
+extern TempNamespaceStatus checkTempNamespaceStatus(Oid namespaceId);
+extern int GetTempNamespaceBackendId(Oid namespaceId);
+extern Oid GetTempToastNamespace(void);
+extern void GetTempNamespaceState(Oid *tempNamespaceId,
+ Oid *tempToastNamespaceId);
+extern void SetTempNamespaceState(Oid tempNamespaceId,
+ Oid tempToastNamespaceId);
+extern void ResetTempTableNamespace(void);
+
+extern OverrideSearchPath *GetOverrideSearchPath(MemoryContext context);
+extern OverrideSearchPath *CopyOverrideSearchPath(OverrideSearchPath *path);
+extern bool OverrideSearchPathMatchesCurrent(OverrideSearchPath *path);
+extern void PushOverrideSearchPath(OverrideSearchPath *newpath);
+extern void PopOverrideSearchPath(void);
+
+extern Oid get_collation_oid(List *collname, bool missing_ok);
+extern Oid get_conversion_oid(List *conname, bool missing_ok);
+extern Oid FindDefaultConversionProc(int32 for_encoding, int32 to_encoding);
+
+
+/* initialization & transaction cleanup code */
+extern void InitializeSearchPath(void);
+extern void AtEOXact_Namespace(bool isCommit, bool parallel);
+extern void AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,
+ SubTransactionId parentSubid);
+
+/* stuff for search_path GUC variable */
+extern char *namespace_search_path;
+
+extern List *fetch_search_path(bool includeImplicit);
+extern int fetch_search_path_array(Oid *sarray, int sarray_len);
+
+#endif /* NAMESPACE_H */
diff --git a/src/include/catalog/objectaccess.h b/src/include/catalog/objectaccess.h
new file mode 100644
index 0000000..fef3836
--- /dev/null
+++ b/src/include/catalog/objectaccess.h
@@ -0,0 +1,197 @@
+/*
+ * objectaccess.h
+ *
+ * Object access hooks.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ */
+
+#ifndef OBJECTACCESS_H
+#define OBJECTACCESS_H
+
+/*
+ * Object access hooks are intended to be called just before or just after
+ * performing certain actions on a SQL object. This is intended as
+ * infrastructure for security or logging plugins.
+ *
+ * OAT_POST_CREATE should be invoked just after the object is created.
+ * Typically, this is done after inserting the primary catalog records and
+ * associated dependencies.
+ *
+ * OAT_DROP should be invoked just before deletion of objects; typically
+ * deleteOneObject(). Its arguments are packed within ObjectAccessDrop.
+ *
+ * OAT_POST_ALTER should be invoked just after the object is altered,
+ * but before the command counter is incremented. An extension using the
+ * hook can use a current MVCC snapshot to get the old version of the tuple,
+ * and can use SnapshotSelf to get the new version of the tuple.
+ *
+ * OAT_NAMESPACE_SEARCH should be invoked prior to object name lookup under
+ * a particular namespace. This event is equivalent to usage permission
+ * on a schema under the default access control mechanism.
+ *
+ * OAT_FUNCTION_EXECUTE should be invoked prior to function execution.
+ * This event is almost equivalent to execute permission on functions,
+ * except for the case when execute permission is checked during object
+ * creation or altering, because OAT_POST_CREATE or OAT_POST_ALTER are
+ * sufficient for extensions to track these kind of checks.
+ *
+ * OAT_TRUNCATE should be invoked just before truncation of objects. This
+ * event is equivalent to truncate permission on a relation under the
+ * default access control mechanism.
+ *
+ * Other types may be added in the future.
+ */
+typedef enum ObjectAccessType
+{
+ OAT_POST_CREATE,
+ OAT_DROP,
+ OAT_POST_ALTER,
+ OAT_NAMESPACE_SEARCH,
+ OAT_FUNCTION_EXECUTE,
+ OAT_TRUNCATE
+} ObjectAccessType;
+
+/*
+ * Arguments of OAT_POST_CREATE event
+ */
+typedef struct
+{
+ /*
+ * This flag informs extensions whether the context of this creation is
+ * invoked by user's operations, or not. E.g, it shall be dealt as
+ * internal stuff on toast tables or indexes due to type changes.
+ */
+ bool is_internal;
+} ObjectAccessPostCreate;
+
+/*
+ * Arguments of OAT_DROP event
+ */
+typedef struct
+{
+ /*
+ * Flags to inform extensions the context of this deletion. Also see
+ * PERFORM_DELETION_* in dependency.h
+ */
+ int dropflags;
+} ObjectAccessDrop;
+
+/*
+ * Arguments of OAT_POST_ALTER event
+ */
+typedef struct
+{
+ /*
+ * This identifier is used when system catalog takes two IDs to identify a
+ * particular tuple of the catalog. It is only used when the caller want
+ * to identify an entry of pg_inherits, pg_db_role_setting or
+ * pg_user_mapping. Elsewhere, InvalidOid should be set.
+ */
+ Oid auxiliary_id;
+
+ /*
+ * If this flag is set, the user hasn't requested that the object be
+ * altered, but we're doing it anyway for some internal reason.
+ * Permissions-checking hooks may want to skip checks if, say, we're alter
+ * the constraints of a temporary heap during CLUSTER.
+ */
+ bool is_internal;
+} ObjectAccessPostAlter;
+
+/*
+ * Arguments of OAT_NAMESPACE_SEARCH
+ */
+typedef struct
+{
+ /*
+ * If true, hook should report an error when permission to search this
+ * schema is denied.
+ */
+ bool ereport_on_violation;
+
+ /*
+ * This is, in essence, an out parameter. Core code should initialize
+ * this to true, and any extension that wants to deny access should reset
+ * it to false. But an extension should be careful never to store a true
+ * value here, so that in case there are multiple extensions access is
+ * only allowed if all extensions agree.
+ */
+ bool result;
+} ObjectAccessNamespaceSearch;
+
+/* Plugin provides a hook function matching this signature. */
+typedef void (*object_access_hook_type) (ObjectAccessType access,
+ Oid classId,
+ Oid objectId,
+ int subId,
+ void *arg);
+
+/* Plugin sets this variable to a suitable hook function. */
+extern PGDLLIMPORT object_access_hook_type object_access_hook;
+
+/* Core code uses these functions to call the hook (see macros below). */
+extern void RunObjectPostCreateHook(Oid classId, Oid objectId, int subId,
+ bool is_internal);
+extern void RunObjectDropHook(Oid classId, Oid objectId, int subId,
+ int dropflags);
+extern void RunObjectTruncateHook(Oid objectId);
+extern void RunObjectPostAlterHook(Oid classId, Oid objectId, int subId,
+ Oid auxiliaryId, bool is_internal);
+extern bool RunNamespaceSearchHook(Oid objectId, bool ereport_on_violation);
+extern void RunFunctionExecuteHook(Oid objectId);
+
+/*
+ * The following macros are wrappers around the functions above; these should
+ * normally be used to invoke the hook in lieu of calling the above functions
+ * directly.
+ */
+
+#define InvokeObjectPostCreateHook(classId,objectId,subId) \
+ InvokeObjectPostCreateHookArg((classId),(objectId),(subId),false)
+#define InvokeObjectPostCreateHookArg(classId,objectId,subId,is_internal) \
+ do { \
+ if (object_access_hook) \
+ RunObjectPostCreateHook((classId),(objectId),(subId), \
+ (is_internal)); \
+ } while(0)
+
+#define InvokeObjectDropHook(classId,objectId,subId) \
+ InvokeObjectDropHookArg((classId),(objectId),(subId),0)
+#define InvokeObjectDropHookArg(classId,objectId,subId,dropflags) \
+ do { \
+ if (object_access_hook) \
+ RunObjectDropHook((classId),(objectId),(subId), \
+ (dropflags)); \
+ } while(0)
+
+#define InvokeObjectTruncateHook(objectId) \
+ do { \
+ if (object_access_hook) \
+ RunObjectTruncateHook(objectId); \
+ } while(0)
+
+#define InvokeObjectPostAlterHook(classId,objectId,subId) \
+ InvokeObjectPostAlterHookArg((classId),(objectId),(subId), \
+ InvalidOid,false)
+#define InvokeObjectPostAlterHookArg(classId,objectId,subId, \
+ auxiliaryId,is_internal) \
+ do { \
+ if (object_access_hook) \
+ RunObjectPostAlterHook((classId),(objectId),(subId), \
+ (auxiliaryId),(is_internal)); \
+ } while(0)
+
+#define InvokeNamespaceSearchHook(objectId, ereport_on_violation) \
+ (!object_access_hook \
+ ? true \
+ : RunNamespaceSearchHook((objectId), (ereport_on_violation)))
+
+#define InvokeFunctionExecuteHook(objectId) \
+ do { \
+ if (object_access_hook) \
+ RunFunctionExecuteHook(objectId); \
+ } while(0)
+
+#endif /* OBJECTACCESS_H */
diff --git a/src/include/catalog/objectaddress.h b/src/include/catalog/objectaddress.h
new file mode 100644
index 0000000..7f15efd
--- /dev/null
+++ b/src/include/catalog/objectaddress.h
@@ -0,0 +1,84 @@
+/*-------------------------------------------------------------------------
+ *
+ * objectaddress.h
+ * functions for working with object addresses
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/objectaddress.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef OBJECTADDRESS_H
+#define OBJECTADDRESS_H
+
+#include "access/htup.h"
+#include "nodes/parsenodes.h"
+#include "storage/lockdefs.h"
+#include "utils/relcache.h"
+
+/*
+ * An ObjectAddress represents a database object of any type.
+ */
+typedef struct ObjectAddress
+{
+ Oid classId; /* Class Id from pg_class */
+ Oid objectId; /* OID of the object */
+ int32 objectSubId; /* Subitem within object (eg column), or 0 */
+} ObjectAddress;
+
+extern const ObjectAddress InvalidObjectAddress;
+
+#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id) \
+ do { \
+ (addr).classId = (class_id); \
+ (addr).objectId = (object_id); \
+ (addr).objectSubId = (object_sub_id); \
+ } while (0)
+
+#define ObjectAddressSet(addr, class_id, object_id) \
+ ObjectAddressSubSet(addr, class_id, object_id, 0)
+
+extern ObjectAddress get_object_address(ObjectType objtype, Node *object,
+ Relation *relp,
+ LOCKMODE lockmode, bool missing_ok);
+
+extern ObjectAddress get_object_address_rv(ObjectType objtype, RangeVar *rel,
+ List *object, Relation *relp,
+ LOCKMODE lockmode, bool missing_ok);
+
+extern void check_object_ownership(Oid roleid,
+ ObjectType objtype, ObjectAddress address,
+ Node *object, Relation relation);
+
+extern Oid get_object_namespace(const ObjectAddress *address);
+
+extern bool is_objectclass_supported(Oid class_id);
+extern Oid get_object_oid_index(Oid class_id);
+extern int get_object_catcache_oid(Oid class_id);
+extern int get_object_catcache_name(Oid class_id);
+extern AttrNumber get_object_attnum_oid(Oid class_id);
+extern AttrNumber get_object_attnum_name(Oid class_id);
+extern AttrNumber get_object_attnum_namespace(Oid class_id);
+extern AttrNumber get_object_attnum_owner(Oid class_id);
+extern AttrNumber get_object_attnum_acl(Oid class_id);
+extern ObjectType get_object_type(Oid class_id, Oid object_id);
+extern bool get_object_namensp_unique(Oid class_id);
+
+extern HeapTuple get_catalog_object_by_oid(Relation catalog,
+ AttrNumber oidcol, Oid objectId);
+
+extern char *getObjectDescription(const ObjectAddress *object);
+extern char *getObjectDescriptionOids(Oid classid, Oid objid);
+
+extern int read_objtype_from_string(const char *objtype);
+extern char *getObjectTypeDescription(const ObjectAddress *object);
+extern char *getObjectIdentity(const ObjectAddress *address);
+extern char *getObjectIdentityParts(const ObjectAddress *address,
+ List **objname, List **objargs);
+extern struct ArrayType *strlist_to_textarray(List *list);
+
+extern ObjectType get_relkind_objtype(char relkind);
+
+#endif /* OBJECTADDRESS_H */
diff --git a/src/include/catalog/opfam_internal.h b/src/include/catalog/opfam_internal.h
new file mode 100644
index 0000000..d63bd9f
--- /dev/null
+++ b/src/include/catalog/opfam_internal.h
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+ *
+ * opfam_internal.h
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/opfam_internal.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef OPFAM_INTERNAL_H
+#define OPFAM_INTERNAL_H
+
+/*
+ * We use lists of this struct type to keep track of both operators and
+ * procedures while building or adding to an opfamily.
+ */
+typedef struct
+{
+ Oid object; /* operator or support proc's OID */
+ int number; /* strategy or support proc number */
+ Oid lefttype; /* lefttype */
+ Oid righttype; /* righttype */
+ Oid sortfamily; /* ordering operator's sort opfamily, or 0 */
+} OpFamilyMember;
+
+#endif /* OPFAM_INTERNAL_H */
diff --git a/src/include/catalog/partition.h b/src/include/catalog/partition.h
new file mode 100644
index 0000000..27873af
--- /dev/null
+++ b/src/include/catalog/partition.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * partition.h
+ * Header file for structures and utility functions related to
+ * partitioning
+ *
+ * Copyright (c) 2007-2020, PostgreSQL Global Development Group
+ *
+ * src/include/catalog/partition.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARTITION_H
+#define PARTITION_H
+
+#include "partitioning/partdefs.h"
+#include "utils/relcache.h"
+
+/* Seed for the extended hash function */
+#define HASH_PARTITION_SEED UINT64CONST(0x7A5B22367996DCFD)
+
+extern Oid get_partition_parent(Oid relid);
+extern List *get_partition_ancestors(Oid relid);
+extern Oid index_get_partition(Relation partition, Oid indexId);
+extern List *map_partition_varattnos(List *expr, int fromrel_varno,
+ Relation to_rel, Relation from_rel);
+extern bool has_partition_attrs(Relation rel, Bitmapset *attnums,
+ bool *used_in_expr);
+
+extern Oid get_default_partition_oid(Oid parentId);
+extern void update_default_partition_oid(Oid parentId, Oid defaultPartId);
+extern List *get_proposed_default_constraint(List *new_part_constraints);
+
+#endif /* PARTITION_H */
diff --git a/src/include/catalog/pg_aggregate.dat b/src/include/catalog/pg_aggregate.dat
new file mode 100644
index 0000000..ffabe27
--- /dev/null
+++ b/src/include/catalog/pg_aggregate.dat
@@ -0,0 +1,598 @@
+#----------------------------------------------------------------------
+#
+# pg_aggregate.dat
+# Initial contents of the pg_aggregate system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_aggregate.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+# avg
+{ aggfnoid => 'avg(int8)', aggtransfn => 'int8_avg_accum',
+ aggfinalfn => 'numeric_poly_avg', aggcombinefn => 'int8_avg_combine',
+ aggserialfn => 'int8_avg_serialize', aggdeserialfn => 'int8_avg_deserialize',
+ aggmtransfn => 'int8_avg_accum', aggminvtransfn => 'int8_avg_accum_inv',
+ aggmfinalfn => 'numeric_poly_avg', aggtranstype => 'internal',
+ aggtransspace => '48', aggmtranstype => 'internal', aggmtransspace => '48' },
+{ aggfnoid => 'avg(int4)', aggtransfn => 'int4_avg_accum',
+ aggfinalfn => 'int8_avg', aggcombinefn => 'int4_avg_combine',
+ aggmtransfn => 'int4_avg_accum', aggminvtransfn => 'int4_avg_accum_inv',
+ aggmfinalfn => 'int8_avg', aggtranstype => '_int8', aggmtranstype => '_int8',
+ agginitval => '{0,0}', aggminitval => '{0,0}' },
+{ aggfnoid => 'avg(int2)', aggtransfn => 'int2_avg_accum',
+ aggfinalfn => 'int8_avg', aggcombinefn => 'int4_avg_combine',
+ aggmtransfn => 'int2_avg_accum', aggminvtransfn => 'int2_avg_accum_inv',
+ aggmfinalfn => 'int8_avg', aggtranstype => '_int8', aggmtranstype => '_int8',
+ agginitval => '{0,0}', aggminitval => '{0,0}' },
+{ aggfnoid => 'avg(numeric)', aggtransfn => 'numeric_avg_accum',
+ aggfinalfn => 'numeric_avg', aggcombinefn => 'numeric_avg_combine',
+ aggserialfn => 'numeric_avg_serialize',
+ aggdeserialfn => 'numeric_avg_deserialize',
+ aggmtransfn => 'numeric_avg_accum', aggminvtransfn => 'numeric_accum_inv',
+ aggmfinalfn => 'numeric_avg', aggtranstype => 'internal',
+ aggtransspace => '128', aggmtranstype => 'internal',
+ aggmtransspace => '128' },
+{ aggfnoid => 'avg(float4)', aggtransfn => 'float4_accum',
+ aggfinalfn => 'float8_avg', aggcombinefn => 'float8_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0}' },
+{ aggfnoid => 'avg(float8)', aggtransfn => 'float8_accum',
+ aggfinalfn => 'float8_avg', aggcombinefn => 'float8_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0}' },
+{ aggfnoid => 'avg(interval)', aggtransfn => 'interval_accum',
+ aggfinalfn => 'interval_avg', aggcombinefn => 'interval_combine',
+ aggmtransfn => 'interval_accum', aggminvtransfn => 'interval_accum_inv',
+ aggmfinalfn => 'interval_avg', aggtranstype => '_interval',
+ aggmtranstype => '_interval', agginitval => '{0 second,0 second}',
+ aggminitval => '{0 second,0 second}' },
+
+# sum
+{ aggfnoid => 'sum(int8)', aggtransfn => 'int8_avg_accum',
+ aggfinalfn => 'numeric_poly_sum', aggcombinefn => 'int8_avg_combine',
+ aggserialfn => 'int8_avg_serialize', aggdeserialfn => 'int8_avg_deserialize',
+ aggmtransfn => 'int8_avg_accum', aggminvtransfn => 'int8_avg_accum_inv',
+ aggmfinalfn => 'numeric_poly_sum', aggtranstype => 'internal',
+ aggtransspace => '48', aggmtranstype => 'internal', aggmtransspace => '48' },
+{ aggfnoid => 'sum(int4)', aggtransfn => 'int4_sum', aggcombinefn => 'int8pl',
+ aggmtransfn => 'int4_avg_accum', aggminvtransfn => 'int4_avg_accum_inv',
+ aggmfinalfn => 'int2int4_sum', aggtranstype => 'int8',
+ aggmtranstype => '_int8', aggminitval => '{0,0}' },
+{ aggfnoid => 'sum(int2)', aggtransfn => 'int2_sum', aggcombinefn => 'int8pl',
+ aggmtransfn => 'int2_avg_accum', aggminvtransfn => 'int2_avg_accum_inv',
+ aggmfinalfn => 'int2int4_sum', aggtranstype => 'int8',
+ aggmtranstype => '_int8', aggminitval => '{0,0}' },
+{ aggfnoid => 'sum(float4)', aggtransfn => 'float4pl',
+ aggcombinefn => 'float4pl', aggtranstype => 'float4' },
+{ aggfnoid => 'sum(float8)', aggtransfn => 'float8pl',
+ aggcombinefn => 'float8pl', aggtranstype => 'float8' },
+{ aggfnoid => 'sum(money)', aggtransfn => 'cash_pl', aggcombinefn => 'cash_pl',
+ aggmtransfn => 'cash_pl', aggminvtransfn => 'cash_mi',
+ aggtranstype => 'money', aggmtranstype => 'money' },
+{ aggfnoid => 'sum(interval)', aggtransfn => 'interval_pl',
+ aggcombinefn => 'interval_pl', aggmtransfn => 'interval_pl',
+ aggminvtransfn => 'interval_mi', aggtranstype => 'interval',
+ aggmtranstype => 'interval' },
+{ aggfnoid => 'sum(numeric)', aggtransfn => 'numeric_avg_accum',
+ aggfinalfn => 'numeric_sum', aggcombinefn => 'numeric_avg_combine',
+ aggserialfn => 'numeric_avg_serialize',
+ aggdeserialfn => 'numeric_avg_deserialize',
+ aggmtransfn => 'numeric_avg_accum', aggminvtransfn => 'numeric_accum_inv',
+ aggmfinalfn => 'numeric_sum', aggtranstype => 'internal',
+ aggtransspace => '128', aggmtranstype => 'internal',
+ aggmtransspace => '128' },
+
+# max
+{ aggfnoid => 'max(int8)', aggtransfn => 'int8larger',
+ aggcombinefn => 'int8larger', aggsortop => '>(int8,int8)',
+ aggtranstype => 'int8' },
+{ aggfnoid => 'max(int4)', aggtransfn => 'int4larger',
+ aggcombinefn => 'int4larger', aggsortop => '>(int4,int4)',
+ aggtranstype => 'int4' },
+{ aggfnoid => 'max(int2)', aggtransfn => 'int2larger',
+ aggcombinefn => 'int2larger', aggsortop => '>(int2,int2)',
+ aggtranstype => 'int2' },
+{ aggfnoid => 'max(oid)', aggtransfn => 'oidlarger',
+ aggcombinefn => 'oidlarger', aggsortop => '>(oid,oid)',
+ aggtranstype => 'oid' },
+{ aggfnoid => 'max(float4)', aggtransfn => 'float4larger',
+ aggcombinefn => 'float4larger', aggsortop => '>(float4,float4)',
+ aggtranstype => 'float4' },
+{ aggfnoid => 'max(float8)', aggtransfn => 'float8larger',
+ aggcombinefn => 'float8larger', aggsortop => '>(float8,float8)',
+ aggtranstype => 'float8' },
+{ aggfnoid => 'max(date)', aggtransfn => 'date_larger',
+ aggcombinefn => 'date_larger', aggsortop => '>(date,date)',
+ aggtranstype => 'date' },
+{ aggfnoid => 'max(time)', aggtransfn => 'time_larger',
+ aggcombinefn => 'time_larger', aggsortop => '>(time,time)',
+ aggtranstype => 'time' },
+{ aggfnoid => 'max(timetz)', aggtransfn => 'timetz_larger',
+ aggcombinefn => 'timetz_larger', aggsortop => '>(timetz,timetz)',
+ aggtranstype => 'timetz' },
+{ aggfnoid => 'max(money)', aggtransfn => 'cashlarger',
+ aggcombinefn => 'cashlarger', aggsortop => '>(money,money)',
+ aggtranstype => 'money' },
+{ aggfnoid => 'max(timestamp)', aggtransfn => 'timestamp_larger',
+ aggcombinefn => 'timestamp_larger', aggsortop => '>(timestamp,timestamp)',
+ aggtranstype => 'timestamp' },
+{ aggfnoid => 'max(timestamptz)', aggtransfn => 'timestamptz_larger',
+ aggcombinefn => 'timestamptz_larger',
+ aggsortop => '>(timestamptz,timestamptz)', aggtranstype => 'timestamptz' },
+{ aggfnoid => 'max(interval)', aggtransfn => 'interval_larger',
+ aggcombinefn => 'interval_larger', aggsortop => '>(interval,interval)',
+ aggtranstype => 'interval' },
+{ aggfnoid => 'max(text)', aggtransfn => 'text_larger',
+ aggcombinefn => 'text_larger', aggsortop => '>(text,text)',
+ aggtranstype => 'text' },
+{ aggfnoid => 'max(numeric)', aggtransfn => 'numeric_larger',
+ aggcombinefn => 'numeric_larger', aggsortop => '>(numeric,numeric)',
+ aggtranstype => 'numeric' },
+{ aggfnoid => 'max(anyarray)', aggtransfn => 'array_larger',
+ aggcombinefn => 'array_larger', aggsortop => '>(anyarray,anyarray)',
+ aggtranstype => 'anyarray' },
+{ aggfnoid => 'max(bpchar)', aggtransfn => 'bpchar_larger',
+ aggcombinefn => 'bpchar_larger', aggsortop => '>(bpchar,bpchar)',
+ aggtranstype => 'bpchar' },
+{ aggfnoid => 'max(tid)', aggtransfn => 'tidlarger',
+ aggcombinefn => 'tidlarger', aggsortop => '>(tid,tid)',
+ aggtranstype => 'tid' },
+{ aggfnoid => 'max(anyenum)', aggtransfn => 'enum_larger',
+ aggcombinefn => 'enum_larger', aggsortop => '>(anyenum,anyenum)',
+ aggtranstype => 'anyenum' },
+{ aggfnoid => 'max(inet)', aggtransfn => 'network_larger',
+ aggcombinefn => 'network_larger', aggsortop => '>(inet,inet)',
+ aggtranstype => 'inet' },
+{ aggfnoid => 'max(pg_lsn)', aggtransfn => 'pg_lsn_larger',
+ aggcombinefn => 'pg_lsn_larger', aggsortop => '>(pg_lsn,pg_lsn)',
+ aggtranstype => 'pg_lsn' },
+
+# min
+{ aggfnoid => 'min(int8)', aggtransfn => 'int8smaller',
+ aggcombinefn => 'int8smaller', aggsortop => '<(int8,int8)',
+ aggtranstype => 'int8' },
+{ aggfnoid => 'min(int4)', aggtransfn => 'int4smaller',
+ aggcombinefn => 'int4smaller', aggsortop => '<(int4,int4)',
+ aggtranstype => 'int4' },
+{ aggfnoid => 'min(int2)', aggtransfn => 'int2smaller',
+ aggcombinefn => 'int2smaller', aggsortop => '<(int2,int2)',
+ aggtranstype => 'int2' },
+{ aggfnoid => 'min(oid)', aggtransfn => 'oidsmaller',
+ aggcombinefn => 'oidsmaller', aggsortop => '<(oid,oid)',
+ aggtranstype => 'oid' },
+{ aggfnoid => 'min(float4)', aggtransfn => 'float4smaller',
+ aggcombinefn => 'float4smaller', aggsortop => '<(float4,float4)',
+ aggtranstype => 'float4' },
+{ aggfnoid => 'min(float8)', aggtransfn => 'float8smaller',
+ aggcombinefn => 'float8smaller', aggsortop => '<(float8,float8)',
+ aggtranstype => 'float8' },
+{ aggfnoid => 'min(date)', aggtransfn => 'date_smaller',
+ aggcombinefn => 'date_smaller', aggsortop => '<(date,date)',
+ aggtranstype => 'date' },
+{ aggfnoid => 'min(time)', aggtransfn => 'time_smaller',
+ aggcombinefn => 'time_smaller', aggsortop => '<(time,time)',
+ aggtranstype => 'time' },
+{ aggfnoid => 'min(timetz)', aggtransfn => 'timetz_smaller',
+ aggcombinefn => 'timetz_smaller', aggsortop => '<(timetz,timetz)',
+ aggtranstype => 'timetz' },
+{ aggfnoid => 'min(money)', aggtransfn => 'cashsmaller',
+ aggcombinefn => 'cashsmaller', aggsortop => '<(money,money)',
+ aggtranstype => 'money' },
+{ aggfnoid => 'min(timestamp)', aggtransfn => 'timestamp_smaller',
+ aggcombinefn => 'timestamp_smaller', aggsortop => '<(timestamp,timestamp)',
+ aggtranstype => 'timestamp' },
+{ aggfnoid => 'min(timestamptz)', aggtransfn => 'timestamptz_smaller',
+ aggcombinefn => 'timestamptz_smaller',
+ aggsortop => '<(timestamptz,timestamptz)', aggtranstype => 'timestamptz' },
+{ aggfnoid => 'min(interval)', aggtransfn => 'interval_smaller',
+ aggcombinefn => 'interval_smaller', aggsortop => '<(interval,interval)',
+ aggtranstype => 'interval' },
+{ aggfnoid => 'min(text)', aggtransfn => 'text_smaller',
+ aggcombinefn => 'text_smaller', aggsortop => '<(text,text)',
+ aggtranstype => 'text' },
+{ aggfnoid => 'min(numeric)', aggtransfn => 'numeric_smaller',
+ aggcombinefn => 'numeric_smaller', aggsortop => '<(numeric,numeric)',
+ aggtranstype => 'numeric' },
+{ aggfnoid => 'min(anyarray)', aggtransfn => 'array_smaller',
+ aggcombinefn => 'array_smaller', aggsortop => '<(anyarray,anyarray)',
+ aggtranstype => 'anyarray' },
+{ aggfnoid => 'min(bpchar)', aggtransfn => 'bpchar_smaller',
+ aggcombinefn => 'bpchar_smaller', aggsortop => '<(bpchar,bpchar)',
+ aggtranstype => 'bpchar' },
+{ aggfnoid => 'min(tid)', aggtransfn => 'tidsmaller',
+ aggcombinefn => 'tidsmaller', aggsortop => '<(tid,tid)',
+ aggtranstype => 'tid' },
+{ aggfnoid => 'min(anyenum)', aggtransfn => 'enum_smaller',
+ aggcombinefn => 'enum_smaller', aggsortop => '<(anyenum,anyenum)',
+ aggtranstype => 'anyenum' },
+{ aggfnoid => 'min(inet)', aggtransfn => 'network_smaller',
+ aggcombinefn => 'network_smaller', aggsortop => '<(inet,inet)',
+ aggtranstype => 'inet' },
+{ aggfnoid => 'min(pg_lsn)', aggtransfn => 'pg_lsn_smaller',
+ aggcombinefn => 'pg_lsn_smaller', aggsortop => '<(pg_lsn,pg_lsn)',
+ aggtranstype => 'pg_lsn' },
+
+# count
+{ aggfnoid => 'count(any)', aggtransfn => 'int8inc_any',
+ aggcombinefn => 'int8pl', aggmtransfn => 'int8inc_any',
+ aggminvtransfn => 'int8dec_any', aggtranstype => 'int8',
+ aggmtranstype => 'int8', agginitval => '0', aggminitval => '0' },
+{ aggfnoid => 'count()', aggtransfn => 'int8inc', aggcombinefn => 'int8pl',
+ aggmtransfn => 'int8inc', aggminvtransfn => 'int8dec', aggtranstype => 'int8',
+ aggmtranstype => 'int8', agginitval => '0', aggminitval => '0' },
+
+# var_pop
+{ aggfnoid => 'var_pop(int8)', aggtransfn => 'int8_accum',
+ aggfinalfn => 'numeric_var_pop', aggcombinefn => 'numeric_combine',
+ aggserialfn => 'numeric_serialize', aggdeserialfn => 'numeric_deserialize',
+ aggmtransfn => 'int8_accum', aggminvtransfn => 'int8_accum_inv',
+ aggmfinalfn => 'numeric_var_pop', aggtranstype => 'internal',
+ aggtransspace => '128', aggmtranstype => 'internal',
+ aggmtransspace => '128' },
+{ aggfnoid => 'var_pop(int4)', aggtransfn => 'int4_accum',
+ aggfinalfn => 'numeric_poly_var_pop', aggcombinefn => 'numeric_poly_combine',
+ aggserialfn => 'numeric_poly_serialize',
+ aggdeserialfn => 'numeric_poly_deserialize', aggmtransfn => 'int4_accum',
+ aggminvtransfn => 'int4_accum_inv', aggmfinalfn => 'numeric_poly_var_pop',
+ aggtranstype => 'internal', aggtransspace => '48',
+ aggmtranstype => 'internal', aggmtransspace => '48' },
+{ aggfnoid => 'var_pop(int2)', aggtransfn => 'int2_accum',
+ aggfinalfn => 'numeric_poly_var_pop', aggcombinefn => 'numeric_poly_combine',
+ aggserialfn => 'numeric_poly_serialize',
+ aggdeserialfn => 'numeric_poly_deserialize', aggmtransfn => 'int2_accum',
+ aggminvtransfn => 'int2_accum_inv', aggmfinalfn => 'numeric_poly_var_pop',
+ aggtranstype => 'internal', aggtransspace => '48',
+ aggmtranstype => 'internal', aggmtransspace => '48' },
+{ aggfnoid => 'var_pop(float4)', aggtransfn => 'float4_accum',
+ aggfinalfn => 'float8_var_pop', aggcombinefn => 'float8_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0}' },
+{ aggfnoid => 'var_pop(float8)', aggtransfn => 'float8_accum',
+ aggfinalfn => 'float8_var_pop', aggcombinefn => 'float8_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0}' },
+{ aggfnoid => 'var_pop(numeric)', aggtransfn => 'numeric_accum',
+ aggfinalfn => 'numeric_var_pop', aggcombinefn => 'numeric_combine',
+ aggserialfn => 'numeric_serialize', aggdeserialfn => 'numeric_deserialize',
+ aggmtransfn => 'numeric_accum', aggminvtransfn => 'numeric_accum_inv',
+ aggmfinalfn => 'numeric_var_pop', aggtranstype => 'internal',
+ aggtransspace => '128', aggmtranstype => 'internal',
+ aggmtransspace => '128' },
+
+# var_samp
+{ aggfnoid => 'var_samp(int8)', aggtransfn => 'int8_accum',
+ aggfinalfn => 'numeric_var_samp', aggcombinefn => 'numeric_combine',
+ aggserialfn => 'numeric_serialize', aggdeserialfn => 'numeric_deserialize',
+ aggmtransfn => 'int8_accum', aggminvtransfn => 'int8_accum_inv',
+ aggmfinalfn => 'numeric_var_samp', aggtranstype => 'internal',
+ aggtransspace => '128', aggmtranstype => 'internal',
+ aggmtransspace => '128' },
+{ aggfnoid => 'var_samp(int4)', aggtransfn => 'int4_accum',
+ aggfinalfn => 'numeric_poly_var_samp', aggcombinefn => 'numeric_poly_combine',
+ aggserialfn => 'numeric_poly_serialize',
+ aggdeserialfn => 'numeric_poly_deserialize', aggmtransfn => 'int4_accum',
+ aggminvtransfn => 'int4_accum_inv', aggmfinalfn => 'numeric_poly_var_samp',
+ aggtranstype => 'internal', aggtransspace => '48',
+ aggmtranstype => 'internal', aggmtransspace => '48' },
+{ aggfnoid => 'var_samp(int2)', aggtransfn => 'int2_accum',
+ aggfinalfn => 'numeric_poly_var_samp', aggcombinefn => 'numeric_poly_combine',
+ aggserialfn => 'numeric_poly_serialize',
+ aggdeserialfn => 'numeric_poly_deserialize', aggmtransfn => 'int2_accum',
+ aggminvtransfn => 'int2_accum_inv', aggmfinalfn => 'numeric_poly_var_samp',
+ aggtranstype => 'internal', aggtransspace => '48',
+ aggmtranstype => 'internal', aggmtransspace => '48' },
+{ aggfnoid => 'var_samp(float4)', aggtransfn => 'float4_accum',
+ aggfinalfn => 'float8_var_samp', aggcombinefn => 'float8_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0}' },
+{ aggfnoid => 'var_samp(float8)', aggtransfn => 'float8_accum',
+ aggfinalfn => 'float8_var_samp', aggcombinefn => 'float8_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0}' },
+{ aggfnoid => 'var_samp(numeric)', aggtransfn => 'numeric_accum',
+ aggfinalfn => 'numeric_var_samp', aggcombinefn => 'numeric_combine',
+ aggserialfn => 'numeric_serialize', aggdeserialfn => 'numeric_deserialize',
+ aggmtransfn => 'numeric_accum', aggminvtransfn => 'numeric_accum_inv',
+ aggmfinalfn => 'numeric_var_samp', aggtranstype => 'internal',
+ aggtransspace => '128', aggmtranstype => 'internal',
+ aggmtransspace => '128' },
+
+# variance: historical Postgres syntax for var_samp
+{ aggfnoid => 'variance(int8)', aggtransfn => 'int8_accum',
+ aggfinalfn => 'numeric_var_samp', aggcombinefn => 'numeric_combine',
+ aggserialfn => 'numeric_serialize', aggdeserialfn => 'numeric_deserialize',
+ aggmtransfn => 'int8_accum', aggminvtransfn => 'int8_accum_inv',
+ aggmfinalfn => 'numeric_var_samp', aggtranstype => 'internal',
+ aggtransspace => '128', aggmtranstype => 'internal',
+ aggmtransspace => '128' },
+{ aggfnoid => 'variance(int4)', aggtransfn => 'int4_accum',
+ aggfinalfn => 'numeric_poly_var_samp', aggcombinefn => 'numeric_poly_combine',
+ aggserialfn => 'numeric_poly_serialize',
+ aggdeserialfn => 'numeric_poly_deserialize', aggmtransfn => 'int4_accum',
+ aggminvtransfn => 'int4_accum_inv', aggmfinalfn => 'numeric_poly_var_samp',
+ aggtranstype => 'internal', aggtransspace => '48',
+ aggmtranstype => 'internal', aggmtransspace => '48' },
+{ aggfnoid => 'variance(int2)', aggtransfn => 'int2_accum',
+ aggfinalfn => 'numeric_poly_var_samp', aggcombinefn => 'numeric_poly_combine',
+ aggserialfn => 'numeric_poly_serialize',
+ aggdeserialfn => 'numeric_poly_deserialize', aggmtransfn => 'int2_accum',
+ aggminvtransfn => 'int2_accum_inv', aggmfinalfn => 'numeric_poly_var_samp',
+ aggtranstype => 'internal', aggtransspace => '48',
+ aggmtranstype => 'internal', aggmtransspace => '48' },
+{ aggfnoid => 'variance(float4)', aggtransfn => 'float4_accum',
+ aggfinalfn => 'float8_var_samp', aggcombinefn => 'float8_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0}' },
+{ aggfnoid => 'variance(float8)', aggtransfn => 'float8_accum',
+ aggfinalfn => 'float8_var_samp', aggcombinefn => 'float8_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0}' },
+{ aggfnoid => 'variance(numeric)', aggtransfn => 'numeric_accum',
+ aggfinalfn => 'numeric_var_samp', aggcombinefn => 'numeric_combine',
+ aggserialfn => 'numeric_serialize', aggdeserialfn => 'numeric_deserialize',
+ aggmtransfn => 'numeric_accum', aggminvtransfn => 'numeric_accum_inv',
+ aggmfinalfn => 'numeric_var_samp', aggtranstype => 'internal',
+ aggtransspace => '128', aggmtranstype => 'internal',
+ aggmtransspace => '128' },
+
+# stddev_pop
+{ aggfnoid => 'stddev_pop(int8)', aggtransfn => 'int8_accum',
+ aggfinalfn => 'numeric_stddev_pop', aggcombinefn => 'numeric_combine',
+ aggserialfn => 'numeric_serialize', aggdeserialfn => 'numeric_deserialize',
+ aggmtransfn => 'int8_accum', aggminvtransfn => 'int8_accum_inv',
+ aggmfinalfn => 'numeric_stddev_pop', aggtranstype => 'internal',
+ aggtransspace => '128', aggmtranstype => 'internal',
+ aggmtransspace => '128' },
+{ aggfnoid => 'stddev_pop(int4)', aggtransfn => 'int4_accum',
+ aggfinalfn => 'numeric_poly_stddev_pop',
+ aggcombinefn => 'numeric_poly_combine',
+ aggserialfn => 'numeric_poly_serialize',
+ aggdeserialfn => 'numeric_poly_deserialize', aggmtransfn => 'int4_accum',
+ aggminvtransfn => 'int4_accum_inv', aggmfinalfn => 'numeric_poly_stddev_pop',
+ aggtranstype => 'internal', aggtransspace => '48',
+ aggmtranstype => 'internal', aggmtransspace => '48' },
+{ aggfnoid => 'stddev_pop(int2)', aggtransfn => 'int2_accum',
+ aggfinalfn => 'numeric_poly_stddev_pop',
+ aggcombinefn => 'numeric_poly_combine',
+ aggserialfn => 'numeric_poly_serialize',
+ aggdeserialfn => 'numeric_poly_deserialize', aggmtransfn => 'int2_accum',
+ aggminvtransfn => 'int2_accum_inv', aggmfinalfn => 'numeric_poly_stddev_pop',
+ aggtranstype => 'internal', aggtransspace => '48',
+ aggmtranstype => 'internal', aggmtransspace => '48' },
+{ aggfnoid => 'stddev_pop(float4)', aggtransfn => 'float4_accum',
+ aggfinalfn => 'float8_stddev_pop', aggcombinefn => 'float8_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0}' },
+{ aggfnoid => 'stddev_pop(float8)', aggtransfn => 'float8_accum',
+ aggfinalfn => 'float8_stddev_pop', aggcombinefn => 'float8_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0}' },
+{ aggfnoid => 'stddev_pop(numeric)', aggtransfn => 'numeric_accum',
+ aggfinalfn => 'numeric_stddev_pop', aggcombinefn => 'numeric_combine',
+ aggserialfn => 'numeric_serialize', aggdeserialfn => 'numeric_deserialize',
+ aggmtransfn => 'numeric_accum', aggminvtransfn => 'numeric_accum_inv',
+ aggmfinalfn => 'numeric_stddev_pop', aggtranstype => 'internal',
+ aggtransspace => '128', aggmtranstype => 'internal',
+ aggmtransspace => '128' },
+
+# stddev_samp
+{ aggfnoid => 'stddev_samp(int8)', aggtransfn => 'int8_accum',
+ aggfinalfn => 'numeric_stddev_samp', aggcombinefn => 'numeric_combine',
+ aggserialfn => 'numeric_serialize', aggdeserialfn => 'numeric_deserialize',
+ aggmtransfn => 'int8_accum', aggminvtransfn => 'int8_accum_inv',
+ aggmfinalfn => 'numeric_stddev_samp', aggtranstype => 'internal',
+ aggtransspace => '128', aggmtranstype => 'internal',
+ aggmtransspace => '128' },
+{ aggfnoid => 'stddev_samp(int4)', aggtransfn => 'int4_accum',
+ aggfinalfn => 'numeric_poly_stddev_samp',
+ aggcombinefn => 'numeric_poly_combine',
+ aggserialfn => 'numeric_poly_serialize',
+ aggdeserialfn => 'numeric_poly_deserialize', aggmtransfn => 'int4_accum',
+ aggminvtransfn => 'int4_accum_inv', aggmfinalfn => 'numeric_poly_stddev_samp',
+ aggtranstype => 'internal', aggtransspace => '48',
+ aggmtranstype => 'internal', aggmtransspace => '48' },
+{ aggfnoid => 'stddev_samp(int2)', aggtransfn => 'int2_accum',
+ aggfinalfn => 'numeric_poly_stddev_samp',
+ aggcombinefn => 'numeric_poly_combine',
+ aggserialfn => 'numeric_poly_serialize',
+ aggdeserialfn => 'numeric_poly_deserialize', aggmtransfn => 'int2_accum',
+ aggminvtransfn => 'int2_accum_inv', aggmfinalfn => 'numeric_poly_stddev_samp',
+ aggtranstype => 'internal', aggtransspace => '48',
+ aggmtranstype => 'internal', aggmtransspace => '48' },
+{ aggfnoid => 'stddev_samp(float4)', aggtransfn => 'float4_accum',
+ aggfinalfn => 'float8_stddev_samp', aggcombinefn => 'float8_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0}' },
+{ aggfnoid => 'stddev_samp(float8)', aggtransfn => 'float8_accum',
+ aggfinalfn => 'float8_stddev_samp', aggcombinefn => 'float8_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0}' },
+{ aggfnoid => 'stddev_samp(numeric)', aggtransfn => 'numeric_accum',
+ aggfinalfn => 'numeric_stddev_samp', aggcombinefn => 'numeric_combine',
+ aggserialfn => 'numeric_serialize', aggdeserialfn => 'numeric_deserialize',
+ aggmtransfn => 'numeric_accum', aggminvtransfn => 'numeric_accum_inv',
+ aggmfinalfn => 'numeric_stddev_samp', aggtranstype => 'internal',
+ aggtransspace => '128', aggmtranstype => 'internal',
+ aggmtransspace => '128' },
+
+# stddev: historical Postgres syntax for stddev_samp
+{ aggfnoid => 'stddev(int8)', aggtransfn => 'int8_accum',
+ aggfinalfn => 'numeric_stddev_samp', aggcombinefn => 'numeric_combine',
+ aggserialfn => 'numeric_serialize', aggdeserialfn => 'numeric_deserialize',
+ aggmtransfn => 'int8_accum', aggminvtransfn => 'int8_accum_inv',
+ aggmfinalfn => 'numeric_stddev_samp', aggtranstype => 'internal',
+ aggtransspace => '128', aggmtranstype => 'internal',
+ aggmtransspace => '128' },
+{ aggfnoid => 'stddev(int4)', aggtransfn => 'int4_accum',
+ aggfinalfn => 'numeric_poly_stddev_samp',
+ aggcombinefn => 'numeric_poly_combine',
+ aggserialfn => 'numeric_poly_serialize',
+ aggdeserialfn => 'numeric_poly_deserialize', aggmtransfn => 'int4_accum',
+ aggminvtransfn => 'int4_accum_inv', aggmfinalfn => 'numeric_poly_stddev_samp',
+ aggtranstype => 'internal', aggtransspace => '48',
+ aggmtranstype => 'internal', aggmtransspace => '48' },
+{ aggfnoid => 'stddev(int2)', aggtransfn => 'int2_accum',
+ aggfinalfn => 'numeric_poly_stddev_samp',
+ aggcombinefn => 'numeric_poly_combine',
+ aggserialfn => 'numeric_poly_serialize',
+ aggdeserialfn => 'numeric_poly_deserialize', aggmtransfn => 'int2_accum',
+ aggminvtransfn => 'int2_accum_inv', aggmfinalfn => 'numeric_poly_stddev_samp',
+ aggtranstype => 'internal', aggtransspace => '48',
+ aggmtranstype => 'internal', aggmtransspace => '48' },
+{ aggfnoid => 'stddev(float4)', aggtransfn => 'float4_accum',
+ aggfinalfn => 'float8_stddev_samp', aggcombinefn => 'float8_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0}' },
+{ aggfnoid => 'stddev(float8)', aggtransfn => 'float8_accum',
+ aggfinalfn => 'float8_stddev_samp', aggcombinefn => 'float8_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0}' },
+{ aggfnoid => 'stddev(numeric)', aggtransfn => 'numeric_accum',
+ aggfinalfn => 'numeric_stddev_samp', aggcombinefn => 'numeric_combine',
+ aggserialfn => 'numeric_serialize', aggdeserialfn => 'numeric_deserialize',
+ aggmtransfn => 'numeric_accum', aggminvtransfn => 'numeric_accum_inv',
+ aggmfinalfn => 'numeric_stddev_samp', aggtranstype => 'internal',
+ aggtransspace => '128', aggmtranstype => 'internal',
+ aggmtransspace => '128' },
+
+# SQL2003 binary regression aggregates
+{ aggfnoid => 'regr_count', aggtransfn => 'int8inc_float8_float8',
+ aggcombinefn => 'int8pl', aggtranstype => 'int8', agginitval => '0' },
+{ aggfnoid => 'regr_sxx', aggtransfn => 'float8_regr_accum',
+ aggfinalfn => 'float8_regr_sxx', aggcombinefn => 'float8_regr_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0,0,0,0}' },
+{ aggfnoid => 'regr_syy', aggtransfn => 'float8_regr_accum',
+ aggfinalfn => 'float8_regr_syy', aggcombinefn => 'float8_regr_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0,0,0,0}' },
+{ aggfnoid => 'regr_sxy', aggtransfn => 'float8_regr_accum',
+ aggfinalfn => 'float8_regr_sxy', aggcombinefn => 'float8_regr_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0,0,0,0}' },
+{ aggfnoid => 'regr_avgx', aggtransfn => 'float8_regr_accum',
+ aggfinalfn => 'float8_regr_avgx', aggcombinefn => 'float8_regr_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0,0,0,0}' },
+{ aggfnoid => 'regr_avgy', aggtransfn => 'float8_regr_accum',
+ aggfinalfn => 'float8_regr_avgy', aggcombinefn => 'float8_regr_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0,0,0,0}' },
+{ aggfnoid => 'regr_r2', aggtransfn => 'float8_regr_accum',
+ aggfinalfn => 'float8_regr_r2', aggcombinefn => 'float8_regr_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0,0,0,0}' },
+{ aggfnoid => 'regr_slope', aggtransfn => 'float8_regr_accum',
+ aggfinalfn => 'float8_regr_slope', aggcombinefn => 'float8_regr_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0,0,0,0}' },
+{ aggfnoid => 'regr_intercept', aggtransfn => 'float8_regr_accum',
+ aggfinalfn => 'float8_regr_intercept', aggcombinefn => 'float8_regr_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0,0,0,0}' },
+{ aggfnoid => 'covar_pop', aggtransfn => 'float8_regr_accum',
+ aggfinalfn => 'float8_covar_pop', aggcombinefn => 'float8_regr_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0,0,0,0}' },
+{ aggfnoid => 'covar_samp', aggtransfn => 'float8_regr_accum',
+ aggfinalfn => 'float8_covar_samp', aggcombinefn => 'float8_regr_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0,0,0,0}' },
+{ aggfnoid => 'corr', aggtransfn => 'float8_regr_accum',
+ aggfinalfn => 'float8_corr', aggcombinefn => 'float8_regr_combine',
+ aggtranstype => '_float8', agginitval => '{0,0,0,0,0,0}' },
+
+# boolean-and and boolean-or
+{ aggfnoid => 'bool_and', aggtransfn => 'booland_statefunc',
+ aggcombinefn => 'booland_statefunc', aggmtransfn => 'bool_accum',
+ aggminvtransfn => 'bool_accum_inv', aggmfinalfn => 'bool_alltrue',
+ aggsortop => '<(bool,bool)', aggtranstype => 'bool',
+ aggmtranstype => 'internal', aggmtransspace => '16' },
+{ aggfnoid => 'bool_or', aggtransfn => 'boolor_statefunc',
+ aggcombinefn => 'boolor_statefunc', aggmtransfn => 'bool_accum',
+ aggminvtransfn => 'bool_accum_inv', aggmfinalfn => 'bool_anytrue',
+ aggsortop => '>(bool,bool)', aggtranstype => 'bool',
+ aggmtranstype => 'internal', aggmtransspace => '16' },
+{ aggfnoid => 'every', aggtransfn => 'booland_statefunc',
+ aggcombinefn => 'booland_statefunc', aggmtransfn => 'bool_accum',
+ aggminvtransfn => 'bool_accum_inv', aggmfinalfn => 'bool_alltrue',
+ aggsortop => '<(bool,bool)', aggtranstype => 'bool',
+ aggmtranstype => 'internal', aggmtransspace => '16' },
+
+# bitwise integer
+{ aggfnoid => 'bit_and(int2)', aggtransfn => 'int2and',
+ aggcombinefn => 'int2and', aggtranstype => 'int2' },
+{ aggfnoid => 'bit_or(int2)', aggtransfn => 'int2or', aggcombinefn => 'int2or',
+ aggtranstype => 'int2' },
+{ aggfnoid => 'bit_and(int4)', aggtransfn => 'int4and',
+ aggcombinefn => 'int4and', aggtranstype => 'int4' },
+{ aggfnoid => 'bit_or(int4)', aggtransfn => 'int4or', aggcombinefn => 'int4or',
+ aggtranstype => 'int4' },
+{ aggfnoid => 'bit_and(int8)', aggtransfn => 'int8and',
+ aggcombinefn => 'int8and', aggtranstype => 'int8' },
+{ aggfnoid => 'bit_or(int8)', aggtransfn => 'int8or', aggcombinefn => 'int8or',
+ aggtranstype => 'int8' },
+{ aggfnoid => 'bit_and(bit)', aggtransfn => 'bitand', aggcombinefn => 'bitand',
+ aggtranstype => 'bit' },
+{ aggfnoid => 'bit_or(bit)', aggtransfn => 'bitor', aggcombinefn => 'bitor',
+ aggtranstype => 'bit' },
+
+# xml
+{ aggfnoid => 'xmlagg', aggtransfn => 'xmlconcat2', aggtranstype => 'xml' },
+
+# array
+{ aggfnoid => 'array_agg(anynonarray)', aggtransfn => 'array_agg_transfn',
+ aggfinalfn => 'array_agg_finalfn', aggfinalextra => 't',
+ aggtranstype => 'internal' },
+{ aggfnoid => 'array_agg(anyarray)', aggtransfn => 'array_agg_array_transfn',
+ aggfinalfn => 'array_agg_array_finalfn', aggfinalextra => 't',
+ aggtranstype => 'internal' },
+
+# text
+{ aggfnoid => 'string_agg(text,text)', aggtransfn => 'string_agg_transfn',
+ aggfinalfn => 'string_agg_finalfn', aggtranstype => 'internal' },
+
+# bytea
+{ aggfnoid => 'string_agg(bytea,bytea)',
+ aggtransfn => 'bytea_string_agg_transfn',
+ aggfinalfn => 'bytea_string_agg_finalfn', aggtranstype => 'internal' },
+
+# json
+{ aggfnoid => 'json_agg', aggtransfn => 'json_agg_transfn',
+ aggfinalfn => 'json_agg_finalfn', aggtranstype => 'internal' },
+{ aggfnoid => 'json_object_agg', aggtransfn => 'json_object_agg_transfn',
+ aggfinalfn => 'json_object_agg_finalfn', aggtranstype => 'internal' },
+
+# jsonb
+{ aggfnoid => 'jsonb_agg', aggtransfn => 'jsonb_agg_transfn',
+ aggfinalfn => 'jsonb_agg_finalfn', aggtranstype => 'internal' },
+{ aggfnoid => 'jsonb_object_agg', aggtransfn => 'jsonb_object_agg_transfn',
+ aggfinalfn => 'jsonb_object_agg_finalfn', aggtranstype => 'internal' },
+
+# ordered-set and hypothetical-set aggregates
+{ aggfnoid => 'percentile_disc(float8,anyelement)', aggkind => 'o',
+ aggnumdirectargs => '1', aggtransfn => 'ordered_set_transition',
+ aggfinalfn => 'percentile_disc_final', aggfinalextra => 't',
+ aggfinalmodify => 's', aggmfinalmodify => 's', aggtranstype => 'internal' },
+{ aggfnoid => 'percentile_cont(float8,float8)', aggkind => 'o',
+ aggnumdirectargs => '1', aggtransfn => 'ordered_set_transition',
+ aggfinalfn => 'percentile_cont_float8_final', aggfinalmodify => 's',
+ aggmfinalmodify => 's', aggtranstype => 'internal' },
+{ aggfnoid => 'percentile_cont(float8,interval)', aggkind => 'o',
+ aggnumdirectargs => '1', aggtransfn => 'ordered_set_transition',
+ aggfinalfn => 'percentile_cont_interval_final', aggfinalmodify => 's',
+ aggmfinalmodify => 's', aggtranstype => 'internal' },
+{ aggfnoid => 'percentile_disc(_float8,anyelement)', aggkind => 'o',
+ aggnumdirectargs => '1', aggtransfn => 'ordered_set_transition',
+ aggfinalfn => 'percentile_disc_multi_final', aggfinalextra => 't',
+ aggfinalmodify => 's', aggmfinalmodify => 's', aggtranstype => 'internal' },
+{ aggfnoid => 'percentile_cont(_float8,float8)', aggkind => 'o',
+ aggnumdirectargs => '1', aggtransfn => 'ordered_set_transition',
+ aggfinalfn => 'percentile_cont_float8_multi_final', aggfinalmodify => 's',
+ aggmfinalmodify => 's', aggtranstype => 'internal' },
+{ aggfnoid => 'percentile_cont(_float8,interval)', aggkind => 'o',
+ aggnumdirectargs => '1', aggtransfn => 'ordered_set_transition',
+ aggfinalfn => 'percentile_cont_interval_multi_final', aggfinalmodify => 's',
+ aggmfinalmodify => 's', aggtranstype => 'internal' },
+{ aggfnoid => 'mode', aggkind => 'o', aggtransfn => 'ordered_set_transition',
+ aggfinalfn => 'mode_final', aggfinalextra => 't', aggfinalmodify => 's',
+ aggmfinalmodify => 's', aggtranstype => 'internal' },
+{ aggfnoid => 'rank(any)', aggkind => 'h', aggnumdirectargs => '1',
+ aggtransfn => 'ordered_set_transition_multi', aggfinalfn => 'rank_final',
+ aggfinalextra => 't', aggfinalmodify => 'w', aggmfinalmodify => 'w',
+ aggtranstype => 'internal' },
+{ aggfnoid => 'percent_rank(any)', aggkind => 'h', aggnumdirectargs => '1',
+ aggtransfn => 'ordered_set_transition_multi',
+ aggfinalfn => 'percent_rank_final', aggfinalextra => 't',
+ aggfinalmodify => 'w', aggmfinalmodify => 'w', aggtranstype => 'internal' },
+{ aggfnoid => 'cume_dist(any)', aggkind => 'h', aggnumdirectargs => '1',
+ aggtransfn => 'ordered_set_transition_multi', aggfinalfn => 'cume_dist_final',
+ aggfinalextra => 't', aggfinalmodify => 'w', aggmfinalmodify => 'w',
+ aggtranstype => 'internal' },
+{ aggfnoid => 'dense_rank(any)', aggkind => 'h', aggnumdirectargs => '1',
+ aggtransfn => 'ordered_set_transition_multi',
+ aggfinalfn => 'dense_rank_final', aggfinalextra => 't', aggfinalmodify => 'w',
+ aggmfinalmodify => 'w', aggtranstype => 'internal' },
+
+]
diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h
new file mode 100644
index 0000000..457ca18
--- /dev/null
+++ b/src/include/catalog/pg_aggregate.h
@@ -0,0 +1,176 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_aggregate.h
+ * definition of the "aggregate" system catalog (pg_aggregate)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_aggregate.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_AGGREGATE_H
+#define PG_AGGREGATE_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_aggregate_d.h"
+
+#include "catalog/objectaddress.h"
+#include "nodes/pg_list.h"
+
+/* ----------------------------------------------------------------
+ * pg_aggregate definition.
+ * cpp turns this into typedef struct FormData_pg_aggregate
+ * ----------------------------------------------------------------
+ */
+CATALOG(pg_aggregate,2600,AggregateRelationId)
+{
+ /* pg_proc OID of the aggregate itself */
+ regproc aggfnoid BKI_LOOKUP(pg_proc);
+
+ /* aggregate kind, see AGGKIND_ categories below */
+ char aggkind BKI_DEFAULT(n);
+
+ /* number of arguments that are "direct" arguments */
+ int16 aggnumdirectargs BKI_DEFAULT(0);
+
+ /* transition function */
+ regproc aggtransfn BKI_LOOKUP(pg_proc);
+
+ /* final function (0 if none) */
+ regproc aggfinalfn BKI_DEFAULT(-) BKI_LOOKUP(pg_proc);
+
+ /* combine function (0 if none) */
+ regproc aggcombinefn BKI_DEFAULT(-) BKI_LOOKUP(pg_proc);
+
+ /* function to convert transtype to bytea (0 if none) */
+ regproc aggserialfn BKI_DEFAULT(-) BKI_LOOKUP(pg_proc);
+
+ /* function to convert bytea to transtype (0 if none) */
+ regproc aggdeserialfn BKI_DEFAULT(-) BKI_LOOKUP(pg_proc);
+
+ /* forward function for moving-aggregate mode (0 if none) */
+ regproc aggmtransfn BKI_DEFAULT(-) BKI_LOOKUP(pg_proc);
+
+ /* inverse function for moving-aggregate mode (0 if none) */
+ regproc aggminvtransfn BKI_DEFAULT(-) BKI_LOOKUP(pg_proc);
+
+ /* final function for moving-aggregate mode (0 if none) */
+ regproc aggmfinalfn BKI_DEFAULT(-) BKI_LOOKUP(pg_proc);
+
+ /* true to pass extra dummy arguments to aggfinalfn */
+ bool aggfinalextra BKI_DEFAULT(f);
+
+ /* true to pass extra dummy arguments to aggmfinalfn */
+ bool aggmfinalextra BKI_DEFAULT(f);
+
+ /* tells whether aggfinalfn modifies transition state */
+ char aggfinalmodify BKI_DEFAULT(r);
+
+ /* tells whether aggmfinalfn modifies transition state */
+ char aggmfinalmodify BKI_DEFAULT(r);
+
+ /* associated sort operator (0 if none) */
+ Oid aggsortop BKI_DEFAULT(0) BKI_LOOKUP(pg_operator);
+
+ /* type of aggregate's transition (state) data */
+ Oid aggtranstype BKI_LOOKUP(pg_type);
+
+ /* estimated size of state data (0 for default estimate) */
+ int32 aggtransspace BKI_DEFAULT(0);
+
+ /* type of moving-aggregate state data (0 if none) */
+ Oid aggmtranstype BKI_DEFAULT(0) BKI_LOOKUP(pg_type);
+
+ /* estimated size of moving-agg state (0 for default est) */
+ int32 aggmtransspace BKI_DEFAULT(0);
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+
+ /* initial value for transition state (can be NULL) */
+ text agginitval BKI_DEFAULT(_null_);
+
+ /* initial value for moving-agg state (can be NULL) */
+ text aggminitval BKI_DEFAULT(_null_);
+#endif
+} FormData_pg_aggregate;
+
+/* ----------------
+ * Form_pg_aggregate corresponds to a pointer to a tuple with
+ * the format of pg_aggregate relation.
+ * ----------------
+ */
+typedef FormData_pg_aggregate *Form_pg_aggregate;
+
+#ifdef EXPOSE_TO_CLIENT_CODE
+
+/*
+ * Symbolic values for aggkind column. We distinguish normal aggregates
+ * from ordered-set aggregates (which have two sets of arguments, namely
+ * direct and aggregated arguments) and from hypothetical-set aggregates
+ * (which are a subclass of ordered-set aggregates in which the last
+ * direct arguments have to match up in number and datatypes with the
+ * aggregated arguments).
+ */
+#define AGGKIND_NORMAL 'n'
+#define AGGKIND_ORDERED_SET 'o'
+#define AGGKIND_HYPOTHETICAL 'h'
+
+/* Use this macro to test for "ordered-set agg including hypothetical case" */
+#define AGGKIND_IS_ORDERED_SET(kind) ((kind) != AGGKIND_NORMAL)
+
+/*
+ * Symbolic values for aggfinalmodify and aggmfinalmodify columns.
+ * Preferably, finalfns do not modify the transition state value at all,
+ * but in some cases that would cost too much performance. We distinguish
+ * "pure read only" and "trashes it arbitrarily" cases, as well as the
+ * intermediate case where multiple finalfn calls are allowed but the
+ * transfn cannot be applied anymore after the first finalfn call.
+ */
+#define AGGMODIFY_READ_ONLY 'r'
+#define AGGMODIFY_SHAREABLE 's'
+#define AGGMODIFY_READ_WRITE 'w'
+
+#endif /* EXPOSE_TO_CLIENT_CODE */
+
+
+extern ObjectAddress AggregateCreate(const char *aggName,
+ Oid aggNamespace,
+ bool replace,
+ char aggKind,
+ int numArgs,
+ int numDirectArgs,
+ oidvector *parameterTypes,
+ Datum allParameterTypes,
+ Datum parameterModes,
+ Datum parameterNames,
+ List *parameterDefaults,
+ Oid variadicArgType,
+ List *aggtransfnName,
+ List *aggfinalfnName,
+ List *aggcombinefnName,
+ List *aggserialfnName,
+ List *aggdeserialfnName,
+ List *aggmtransfnName,
+ List *aggminvtransfnName,
+ List *aggmfinalfnName,
+ bool finalfnExtraArgs,
+ bool mfinalfnExtraArgs,
+ char finalfnModify,
+ char mfinalfnModify,
+ List *aggsortopName,
+ Oid aggTransType,
+ int32 aggTransSpace,
+ Oid aggmTransType,
+ int32 aggmTransSpace,
+ const char *agginitval,
+ const char *aggminitval,
+ char proparallel);
+
+#endif /* PG_AGGREGATE_H */
diff --git a/src/include/catalog/pg_am.dat b/src/include/catalog/pg_am.dat
new file mode 100644
index 0000000..0f05127
--- /dev/null
+++ b/src/include/catalog/pg_am.dat
@@ -0,0 +1,37 @@
+#----------------------------------------------------------------------
+#
+# pg_am.dat
+# Initial contents of the pg_am system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_am.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+{ oid => '2', oid_symbol => 'HEAP_TABLE_AM_OID',
+ descr => 'heap table access method',
+ amname => 'heap', amhandler => 'heap_tableam_handler', amtype => 't' },
+{ oid => '403', oid_symbol => 'BTREE_AM_OID',
+ descr => 'b-tree index access method',
+ amname => 'btree', amhandler => 'bthandler', amtype => 'i' },
+{ oid => '405', oid_symbol => 'HASH_AM_OID',
+ descr => 'hash index access method',
+ amname => 'hash', amhandler => 'hashhandler', amtype => 'i' },
+{ oid => '783', oid_symbol => 'GIST_AM_OID',
+ descr => 'GiST index access method',
+ amname => 'gist', amhandler => 'gisthandler', amtype => 'i' },
+{ oid => '2742', oid_symbol => 'GIN_AM_OID',
+ descr => 'GIN index access method',
+ amname => 'gin', amhandler => 'ginhandler', amtype => 'i' },
+{ oid => '4000', oid_symbol => 'SPGIST_AM_OID',
+ descr => 'SP-GiST index access method',
+ amname => 'spgist', amhandler => 'spghandler', amtype => 'i' },
+{ oid => '3580', oid_symbol => 'BRIN_AM_OID',
+ descr => 'block range index (BRIN) access method',
+ amname => 'brin', amhandler => 'brinhandler', amtype => 'i' },
+
+]
diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h
new file mode 100644
index 0000000..63c03c4
--- /dev/null
+++ b/src/include/catalog/pg_am.h
@@ -0,0 +1,60 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_am.h
+ * definition of the "access method" system catalog (pg_am)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_am.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_AM_H
+#define PG_AM_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_am_d.h"
+
+/* ----------------
+ * pg_am definition. cpp turns this into
+ * typedef struct FormData_pg_am
+ * ----------------
+ */
+CATALOG(pg_am,2601,AccessMethodRelationId)
+{
+ Oid oid; /* oid */
+
+ /* access method name */
+ NameData amname;
+
+ /* handler function */
+ regproc amhandler BKI_LOOKUP(pg_proc);
+
+ /* see AMTYPE_xxx constants below */
+ char amtype;
+} FormData_pg_am;
+
+/* ----------------
+ * Form_pg_am corresponds to a pointer to a tuple with
+ * the format of pg_am relation.
+ * ----------------
+ */
+typedef FormData_pg_am *Form_pg_am;
+
+#ifdef EXPOSE_TO_CLIENT_CODE
+
+/*
+ * Allowed values for amtype
+ */
+#define AMTYPE_INDEX 'i' /* index access method */
+#define AMTYPE_TABLE 't' /* table access method */
+
+#endif /* EXPOSE_TO_CLIENT_CODE */
+
+#endif /* PG_AM_H */
diff --git a/src/include/catalog/pg_amop.dat b/src/include/catalog/pg_amop.dat
new file mode 100644
index 0000000..1dfb6fd
--- /dev/null
+++ b/src/include/catalog/pg_amop.dat
@@ -0,0 +1,2463 @@
+#----------------------------------------------------------------------
+#
+# pg_amop.dat
+# Initial contents of the pg_amop system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_amop.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+# btree integer_ops
+
+# default operators int2
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
+ amoprighttype => 'int2', amopstrategy => '1', amopopr => '<(int2,int2)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
+ amoprighttype => 'int2', amopstrategy => '2', amopopr => '<=(int2,int2)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
+ amoprighttype => 'int2', amopstrategy => '3', amopopr => '=(int2,int2)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
+ amoprighttype => 'int2', amopstrategy => '4', amopopr => '>=(int2,int2)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
+ amoprighttype => 'int2', amopstrategy => '5', amopopr => '>(int2,int2)',
+ amopmethod => 'btree' },
+
+# crosstype operators int24
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
+ amoprighttype => 'int4', amopstrategy => '1', amopopr => '<(int2,int4)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
+ amoprighttype => 'int4', amopstrategy => '2', amopopr => '<=(int2,int4)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
+ amoprighttype => 'int4', amopstrategy => '3', amopopr => '=(int2,int4)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
+ amoprighttype => 'int4', amopstrategy => '4', amopopr => '>=(int2,int4)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
+ amoprighttype => 'int4', amopstrategy => '5', amopopr => '>(int2,int4)',
+ amopmethod => 'btree' },
+
+# crosstype operators int28
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
+ amoprighttype => 'int8', amopstrategy => '1', amopopr => '<(int2,int8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
+ amoprighttype => 'int8', amopstrategy => '2', amopopr => '<=(int2,int8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
+ amoprighttype => 'int8', amopstrategy => '3', amopopr => '=(int2,int8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
+ amoprighttype => 'int8', amopstrategy => '4', amopopr => '>=(int2,int8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
+ amoprighttype => 'int8', amopstrategy => '5', amopopr => '>(int2,int8)',
+ amopmethod => 'btree' },
+
+# default operators int4
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
+ amoprighttype => 'int4', amopstrategy => '1', amopopr => '<(int4,int4)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
+ amoprighttype => 'int4', amopstrategy => '2', amopopr => '<=(int4,int4)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
+ amoprighttype => 'int4', amopstrategy => '3', amopopr => '=(int4,int4)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
+ amoprighttype => 'int4', amopstrategy => '4', amopopr => '>=(int4,int4)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
+ amoprighttype => 'int4', amopstrategy => '5', amopopr => '>(int4,int4)',
+ amopmethod => 'btree' },
+
+# crosstype operators int42
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
+ amoprighttype => 'int2', amopstrategy => '1', amopopr => '<(int4,int2)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
+ amoprighttype => 'int2', amopstrategy => '2', amopopr => '<=(int4,int2)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
+ amoprighttype => 'int2', amopstrategy => '3', amopopr => '=(int4,int2)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
+ amoprighttype => 'int2', amopstrategy => '4', amopopr => '>=(int4,int2)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
+ amoprighttype => 'int2', amopstrategy => '5', amopopr => '>(int4,int2)',
+ amopmethod => 'btree' },
+
+# crosstype operators int48
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
+ amoprighttype => 'int8', amopstrategy => '1', amopopr => '<(int4,int8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
+ amoprighttype => 'int8', amopstrategy => '2', amopopr => '<=(int4,int8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
+ amoprighttype => 'int8', amopstrategy => '3', amopopr => '=(int4,int8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
+ amoprighttype => 'int8', amopstrategy => '4', amopopr => '>=(int4,int8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
+ amoprighttype => 'int8', amopstrategy => '5', amopopr => '>(int4,int8)',
+ amopmethod => 'btree' },
+
+# default operators int8
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
+ amoprighttype => 'int8', amopstrategy => '1', amopopr => '<(int8,int8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
+ amoprighttype => 'int8', amopstrategy => '2', amopopr => '<=(int8,int8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
+ amoprighttype => 'int8', amopstrategy => '3', amopopr => '=(int8,int8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
+ amoprighttype => 'int8', amopstrategy => '4', amopopr => '>=(int8,int8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
+ amoprighttype => 'int8', amopstrategy => '5', amopopr => '>(int8,int8)',
+ amopmethod => 'btree' },
+
+# crosstype operators int82
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
+ amoprighttype => 'int2', amopstrategy => '1', amopopr => '<(int8,int2)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
+ amoprighttype => 'int2', amopstrategy => '2', amopopr => '<=(int8,int2)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
+ amoprighttype => 'int2', amopstrategy => '3', amopopr => '=(int8,int2)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
+ amoprighttype => 'int2', amopstrategy => '4', amopopr => '>=(int8,int2)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
+ amoprighttype => 'int2', amopstrategy => '5', amopopr => '>(int8,int2)',
+ amopmethod => 'btree' },
+
+# crosstype operators int84
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
+ amoprighttype => 'int4', amopstrategy => '1', amopopr => '<(int8,int4)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
+ amoprighttype => 'int4', amopstrategy => '2', amopopr => '<=(int8,int4)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
+ amoprighttype => 'int4', amopstrategy => '3', amopopr => '=(int8,int4)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
+ amoprighttype => 'int4', amopstrategy => '4', amopopr => '>=(int8,int4)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
+ amoprighttype => 'int4', amopstrategy => '5', amopopr => '>(int8,int4)',
+ amopmethod => 'btree' },
+
+# btree oid_ops
+
+{ amopfamily => 'btree/oid_ops', amoplefttype => 'oid', amoprighttype => 'oid',
+ amopstrategy => '1', amopopr => '<(oid,oid)', amopmethod => 'btree' },
+{ amopfamily => 'btree/oid_ops', amoplefttype => 'oid', amoprighttype => 'oid',
+ amopstrategy => '2', amopopr => '<=(oid,oid)', amopmethod => 'btree' },
+{ amopfamily => 'btree/oid_ops', amoplefttype => 'oid', amoprighttype => 'oid',
+ amopstrategy => '3', amopopr => '=(oid,oid)', amopmethod => 'btree' },
+{ amopfamily => 'btree/oid_ops', amoplefttype => 'oid', amoprighttype => 'oid',
+ amopstrategy => '4', amopopr => '>=(oid,oid)', amopmethod => 'btree' },
+{ amopfamily => 'btree/oid_ops', amoplefttype => 'oid', amoprighttype => 'oid',
+ amopstrategy => '5', amopopr => '>(oid,oid)', amopmethod => 'btree' },
+
+# btree xid8_ops
+
+{ amopfamily => 'btree/xid8_ops', amoplefttype => 'xid8',
+ amoprighttype => 'xid8', amopstrategy => '1', amopopr => '<(xid8,xid8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/xid8_ops', amoplefttype => 'xid8',
+ amoprighttype => 'xid8', amopstrategy => '2', amopopr => '<=(xid8,xid8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/xid8_ops', amoplefttype => 'xid8',
+ amoprighttype => 'xid8', amopstrategy => '3', amopopr => '=(xid8,xid8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/xid8_ops', amoplefttype => 'xid8',
+ amoprighttype => 'xid8', amopstrategy => '4', amopopr => '>=(xid8,xid8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/xid8_ops', amoplefttype => 'xid8',
+ amoprighttype => 'xid8', amopstrategy => '5', amopopr => '>(xid8,xid8)',
+ amopmethod => 'btree' },
+
+# btree tid_ops
+
+{ amopfamily => 'btree/tid_ops', amoplefttype => 'tid', amoprighttype => 'tid',
+ amopstrategy => '1', amopopr => '<(tid,tid)', amopmethod => 'btree' },
+{ amopfamily => 'btree/tid_ops', amoplefttype => 'tid', amoprighttype => 'tid',
+ amopstrategy => '2', amopopr => '<=(tid,tid)', amopmethod => 'btree' },
+{ amopfamily => 'btree/tid_ops', amoplefttype => 'tid', amoprighttype => 'tid',
+ amopstrategy => '3', amopopr => '=(tid,tid)', amopmethod => 'btree' },
+{ amopfamily => 'btree/tid_ops', amoplefttype => 'tid', amoprighttype => 'tid',
+ amopstrategy => '4', amopopr => '>=(tid,tid)', amopmethod => 'btree' },
+{ amopfamily => 'btree/tid_ops', amoplefttype => 'tid', amoprighttype => 'tid',
+ amopstrategy => '5', amopopr => '>(tid,tid)', amopmethod => 'btree' },
+
+# btree oidvector_ops
+
+{ amopfamily => 'btree/oidvector_ops', amoplefttype => 'oidvector',
+ amoprighttype => 'oidvector', amopstrategy => '1',
+ amopopr => '<(oidvector,oidvector)', amopmethod => 'btree' },
+{ amopfamily => 'btree/oidvector_ops', amoplefttype => 'oidvector',
+ amoprighttype => 'oidvector', amopstrategy => '2',
+ amopopr => '<=(oidvector,oidvector)', amopmethod => 'btree' },
+{ amopfamily => 'btree/oidvector_ops', amoplefttype => 'oidvector',
+ amoprighttype => 'oidvector', amopstrategy => '3',
+ amopopr => '=(oidvector,oidvector)', amopmethod => 'btree' },
+{ amopfamily => 'btree/oidvector_ops', amoplefttype => 'oidvector',
+ amoprighttype => 'oidvector', amopstrategy => '4',
+ amopopr => '>=(oidvector,oidvector)', amopmethod => 'btree' },
+{ amopfamily => 'btree/oidvector_ops', amoplefttype => 'oidvector',
+ amoprighttype => 'oidvector', amopstrategy => '5',
+ amopopr => '>(oidvector,oidvector)', amopmethod => 'btree' },
+
+# btree float_ops
+
+# default operators float4
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float4',
+ amoprighttype => 'float4', amopstrategy => '1', amopopr => '<(float4,float4)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float4',
+ amoprighttype => 'float4', amopstrategy => '2',
+ amopopr => '<=(float4,float4)', amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float4',
+ amoprighttype => 'float4', amopstrategy => '3', amopopr => '=(float4,float4)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float4',
+ amoprighttype => 'float4', amopstrategy => '4',
+ amopopr => '>=(float4,float4)', amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float4',
+ amoprighttype => 'float4', amopstrategy => '5', amopopr => '>(float4,float4)',
+ amopmethod => 'btree' },
+
+# crosstype operators float48
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float4',
+ amoprighttype => 'float8', amopstrategy => '1', amopopr => '<(float4,float8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float4',
+ amoprighttype => 'float8', amopstrategy => '2',
+ amopopr => '<=(float4,float8)', amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float4',
+ amoprighttype => 'float8', amopstrategy => '3', amopopr => '=(float4,float8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float4',
+ amoprighttype => 'float8', amopstrategy => '4',
+ amopopr => '>=(float4,float8)', amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float4',
+ amoprighttype => 'float8', amopstrategy => '5', amopopr => '>(float4,float8)',
+ amopmethod => 'btree' },
+
+# default operators float8
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float8',
+ amoprighttype => 'float8', amopstrategy => '1', amopopr => '<(float8,float8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float8',
+ amoprighttype => 'float8', amopstrategy => '2',
+ amopopr => '<=(float8,float8)', amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float8',
+ amoprighttype => 'float8', amopstrategy => '3', amopopr => '=(float8,float8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float8',
+ amoprighttype => 'float8', amopstrategy => '4',
+ amopopr => '>=(float8,float8)', amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float8',
+ amoprighttype => 'float8', amopstrategy => '5', amopopr => '>(float8,float8)',
+ amopmethod => 'btree' },
+
+# crosstype operators float84
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float8',
+ amoprighttype => 'float4', amopstrategy => '1', amopopr => '<(float8,float4)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float8',
+ amoprighttype => 'float4', amopstrategy => '2',
+ amopopr => '<=(float8,float4)', amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float8',
+ amoprighttype => 'float4', amopstrategy => '3', amopopr => '=(float8,float4)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float8',
+ amoprighttype => 'float4', amopstrategy => '4',
+ amopopr => '>=(float8,float4)', amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float8',
+ amoprighttype => 'float4', amopstrategy => '5', amopopr => '>(float8,float4)',
+ amopmethod => 'btree' },
+
+# btree char_ops
+
+{ amopfamily => 'btree/char_ops', amoplefttype => 'char',
+ amoprighttype => 'char', amopstrategy => '1', amopopr => '<(char,char)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/char_ops', amoplefttype => 'char',
+ amoprighttype => 'char', amopstrategy => '2', amopopr => '<=(char,char)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/char_ops', amoplefttype => 'char',
+ amoprighttype => 'char', amopstrategy => '3', amopopr => '=(char,char)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/char_ops', amoplefttype => 'char',
+ amoprighttype => 'char', amopstrategy => '4', amopopr => '>=(char,char)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/char_ops', amoplefttype => 'char',
+ amoprighttype => 'char', amopstrategy => '5', amopopr => '>(char,char)',
+ amopmethod => 'btree' },
+
+# btree text_ops
+
+{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '1', amopopr => '<(text,text)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '2', amopopr => '<=(text,text)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '3', amopopr => '=(text,text)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '4', amopopr => '>=(text,text)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '5', amopopr => '>(text,text)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
+ amoprighttype => 'name', amopstrategy => '1', amopopr => '<(name,name)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
+ amoprighttype => 'name', amopstrategy => '2', amopopr => '<=(name,name)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
+ amoprighttype => 'name', amopstrategy => '3', amopopr => '=(name,name)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
+ amoprighttype => 'name', amopstrategy => '4', amopopr => '>=(name,name)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
+ amoprighttype => 'name', amopstrategy => '5', amopopr => '>(name,name)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
+ amoprighttype => 'text', amopstrategy => '1', amopopr => '<(name,text)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
+ amoprighttype => 'text', amopstrategy => '2', amopopr => '<=(name,text)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
+ amoprighttype => 'text', amopstrategy => '3', amopopr => '=(name,text)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
+ amoprighttype => 'text', amopstrategy => '4', amopopr => '>=(name,text)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'name',
+ amoprighttype => 'text', amopstrategy => '5', amopopr => '>(name,text)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
+ amoprighttype => 'name', amopstrategy => '1', amopopr => '<(text,name)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
+ amoprighttype => 'name', amopstrategy => '2', amopopr => '<=(text,name)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
+ amoprighttype => 'name', amopstrategy => '3', amopopr => '=(text,name)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
+ amoprighttype => 'name', amopstrategy => '4', amopopr => '>=(text,name)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_ops', amoplefttype => 'text',
+ amoprighttype => 'name', amopstrategy => '5', amopopr => '>(text,name)',
+ amopmethod => 'btree' },
+
+# btree bpchar_ops
+
+{ amopfamily => 'btree/bpchar_ops', amoplefttype => 'bpchar',
+ amoprighttype => 'bpchar', amopstrategy => '1', amopopr => '<(bpchar,bpchar)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/bpchar_ops', amoplefttype => 'bpchar',
+ amoprighttype => 'bpchar', amopstrategy => '2',
+ amopopr => '<=(bpchar,bpchar)', amopmethod => 'btree' },
+{ amopfamily => 'btree/bpchar_ops', amoplefttype => 'bpchar',
+ amoprighttype => 'bpchar', amopstrategy => '3', amopopr => '=(bpchar,bpchar)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/bpchar_ops', amoplefttype => 'bpchar',
+ amoprighttype => 'bpchar', amopstrategy => '4',
+ amopopr => '>=(bpchar,bpchar)', amopmethod => 'btree' },
+{ amopfamily => 'btree/bpchar_ops', amoplefttype => 'bpchar',
+ amoprighttype => 'bpchar', amopstrategy => '5', amopopr => '>(bpchar,bpchar)',
+ amopmethod => 'btree' },
+
+# btree bytea_ops
+
+{ amopfamily => 'btree/bytea_ops', amoplefttype => 'bytea',
+ amoprighttype => 'bytea', amopstrategy => '1', amopopr => '<(bytea,bytea)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/bytea_ops', amoplefttype => 'bytea',
+ amoprighttype => 'bytea', amopstrategy => '2', amopopr => '<=(bytea,bytea)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/bytea_ops', amoplefttype => 'bytea',
+ amoprighttype => 'bytea', amopstrategy => '3', amopopr => '=(bytea,bytea)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/bytea_ops', amoplefttype => 'bytea',
+ amoprighttype => 'bytea', amopstrategy => '4', amopopr => '>=(bytea,bytea)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/bytea_ops', amoplefttype => 'bytea',
+ amoprighttype => 'bytea', amopstrategy => '5', amopopr => '>(bytea,bytea)',
+ amopmethod => 'btree' },
+
+# btree datetime_ops
+
+# default operators date
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
+ amoprighttype => 'date', amopstrategy => '1', amopopr => '<(date,date)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
+ amoprighttype => 'date', amopstrategy => '2', amopopr => '<=(date,date)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
+ amoprighttype => 'date', amopstrategy => '3', amopopr => '=(date,date)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
+ amoprighttype => 'date', amopstrategy => '4', amopopr => '>=(date,date)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
+ amoprighttype => 'date', amopstrategy => '5', amopopr => '>(date,date)',
+ amopmethod => 'btree' },
+
+# crosstype operators vs timestamp
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamp', amopstrategy => '1',
+ amopopr => '<(date,timestamp)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamp', amopstrategy => '2',
+ amopopr => '<=(date,timestamp)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamp', amopstrategy => '3',
+ amopopr => '=(date,timestamp)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamp', amopstrategy => '4',
+ amopopr => '>=(date,timestamp)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamp', amopstrategy => '5',
+ amopopr => '>(date,timestamp)', amopmethod => 'btree' },
+
+# crosstype operators vs timestamptz
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamptz', amopstrategy => '1',
+ amopopr => '<(date,timestamptz)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamptz', amopstrategy => '2',
+ amopopr => '<=(date,timestamptz)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamptz', amopstrategy => '3',
+ amopopr => '=(date,timestamptz)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamptz', amopstrategy => '4',
+ amopopr => '>=(date,timestamptz)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamptz', amopstrategy => '5',
+ amopopr => '>(date,timestamptz)', amopmethod => 'btree' },
+
+# default operators timestamp
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamp', amopstrategy => '1',
+ amopopr => '<(timestamp,timestamp)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamp', amopstrategy => '2',
+ amopopr => '<=(timestamp,timestamp)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamp', amopstrategy => '3',
+ amopopr => '=(timestamp,timestamp)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamp', amopstrategy => '4',
+ amopopr => '>=(timestamp,timestamp)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamp', amopstrategy => '5',
+ amopopr => '>(timestamp,timestamp)', amopmethod => 'btree' },
+
+# crosstype operators vs date
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'date', amopstrategy => '1', amopopr => '<(timestamp,date)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'date', amopstrategy => '2', amopopr => '<=(timestamp,date)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'date', amopstrategy => '3', amopopr => '=(timestamp,date)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'date', amopstrategy => '4', amopopr => '>=(timestamp,date)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'date', amopstrategy => '5', amopopr => '>(timestamp,date)',
+ amopmethod => 'btree' },
+
+# crosstype operators vs timestamptz
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamptz', amopstrategy => '1',
+ amopopr => '<(timestamp,timestamptz)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamptz', amopstrategy => '2',
+ amopopr => '<=(timestamp,timestamptz)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamptz', amopstrategy => '3',
+ amopopr => '=(timestamp,timestamptz)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamptz', amopstrategy => '4',
+ amopopr => '>=(timestamp,timestamptz)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamptz', amopstrategy => '5',
+ amopopr => '>(timestamp,timestamptz)', amopmethod => 'btree' },
+
+# default operators timestamptz
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamptz', amopstrategy => '1',
+ amopopr => '<(timestamptz,timestamptz)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamptz', amopstrategy => '2',
+ amopopr => '<=(timestamptz,timestamptz)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamptz', amopstrategy => '3',
+ amopopr => '=(timestamptz,timestamptz)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamptz', amopstrategy => '4',
+ amopopr => '>=(timestamptz,timestamptz)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamptz', amopstrategy => '5',
+ amopopr => '>(timestamptz,timestamptz)', amopmethod => 'btree' },
+
+# crosstype operators vs date
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'date', amopstrategy => '1',
+ amopopr => '<(timestamptz,date)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'date', amopstrategy => '2',
+ amopopr => '<=(timestamptz,date)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'date', amopstrategy => '3',
+ amopopr => '=(timestamptz,date)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'date', amopstrategy => '4',
+ amopopr => '>=(timestamptz,date)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'date', amopstrategy => '5',
+ amopopr => '>(timestamptz,date)', amopmethod => 'btree' },
+
+# crosstype operators vs timestamp
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamp', amopstrategy => '1',
+ amopopr => '<(timestamptz,timestamp)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamp', amopstrategy => '2',
+ amopopr => '<=(timestamptz,timestamp)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamp', amopstrategy => '3',
+ amopopr => '=(timestamptz,timestamp)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamp', amopstrategy => '4',
+ amopopr => '>=(timestamptz,timestamp)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamp', amopstrategy => '5',
+ amopopr => '>(timestamptz,timestamp)', amopmethod => 'btree' },
+
+# btree time_ops
+
+{ amopfamily => 'btree/time_ops', amoplefttype => 'time',
+ amoprighttype => 'time', amopstrategy => '1', amopopr => '<(time,time)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/time_ops', amoplefttype => 'time',
+ amoprighttype => 'time', amopstrategy => '2', amopopr => '<=(time,time)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/time_ops', amoplefttype => 'time',
+ amoprighttype => 'time', amopstrategy => '3', amopopr => '=(time,time)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/time_ops', amoplefttype => 'time',
+ amoprighttype => 'time', amopstrategy => '4', amopopr => '>=(time,time)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/time_ops', amoplefttype => 'time',
+ amoprighttype => 'time', amopstrategy => '5', amopopr => '>(time,time)',
+ amopmethod => 'btree' },
+
+# btree timetz_ops
+
+{ amopfamily => 'btree/timetz_ops', amoplefttype => 'timetz',
+ amoprighttype => 'timetz', amopstrategy => '1', amopopr => '<(timetz,timetz)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/timetz_ops', amoplefttype => 'timetz',
+ amoprighttype => 'timetz', amopstrategy => '2',
+ amopopr => '<=(timetz,timetz)', amopmethod => 'btree' },
+{ amopfamily => 'btree/timetz_ops', amoplefttype => 'timetz',
+ amoprighttype => 'timetz', amopstrategy => '3', amopopr => '=(timetz,timetz)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/timetz_ops', amoplefttype => 'timetz',
+ amoprighttype => 'timetz', amopstrategy => '4',
+ amopopr => '>=(timetz,timetz)', amopmethod => 'btree' },
+{ amopfamily => 'btree/timetz_ops', amoplefttype => 'timetz',
+ amoprighttype => 'timetz', amopstrategy => '5', amopopr => '>(timetz,timetz)',
+ amopmethod => 'btree' },
+
+# btree interval_ops
+
+{ amopfamily => 'btree/interval_ops', amoplefttype => 'interval',
+ amoprighttype => 'interval', amopstrategy => '1',
+ amopopr => '<(interval,interval)', amopmethod => 'btree' },
+{ amopfamily => 'btree/interval_ops', amoplefttype => 'interval',
+ amoprighttype => 'interval', amopstrategy => '2',
+ amopopr => '<=(interval,interval)', amopmethod => 'btree' },
+{ amopfamily => 'btree/interval_ops', amoplefttype => 'interval',
+ amoprighttype => 'interval', amopstrategy => '3',
+ amopopr => '=(interval,interval)', amopmethod => 'btree' },
+{ amopfamily => 'btree/interval_ops', amoplefttype => 'interval',
+ amoprighttype => 'interval', amopstrategy => '4',
+ amopopr => '>=(interval,interval)', amopmethod => 'btree' },
+{ amopfamily => 'btree/interval_ops', amoplefttype => 'interval',
+ amoprighttype => 'interval', amopstrategy => '5',
+ amopopr => '>(interval,interval)', amopmethod => 'btree' },
+
+# btree macaddr
+
+{ amopfamily => 'btree/macaddr_ops', amoplefttype => 'macaddr',
+ amoprighttype => 'macaddr', amopstrategy => '1',
+ amopopr => '<(macaddr,macaddr)', amopmethod => 'btree' },
+{ amopfamily => 'btree/macaddr_ops', amoplefttype => 'macaddr',
+ amoprighttype => 'macaddr', amopstrategy => '2',
+ amopopr => '<=(macaddr,macaddr)', amopmethod => 'btree' },
+{ amopfamily => 'btree/macaddr_ops', amoplefttype => 'macaddr',
+ amoprighttype => 'macaddr', amopstrategy => '3',
+ amopopr => '=(macaddr,macaddr)', amopmethod => 'btree' },
+{ amopfamily => 'btree/macaddr_ops', amoplefttype => 'macaddr',
+ amoprighttype => 'macaddr', amopstrategy => '4',
+ amopopr => '>=(macaddr,macaddr)', amopmethod => 'btree' },
+{ amopfamily => 'btree/macaddr_ops', amoplefttype => 'macaddr',
+ amoprighttype => 'macaddr', amopstrategy => '5',
+ amopopr => '>(macaddr,macaddr)', amopmethod => 'btree' },
+
+# btree macaddr8
+
+{ amopfamily => 'btree/macaddr8_ops', amoplefttype => 'macaddr8',
+ amoprighttype => 'macaddr8', amopstrategy => '1',
+ amopopr => '<(macaddr8,macaddr8)', amopmethod => 'btree' },
+{ amopfamily => 'btree/macaddr8_ops', amoplefttype => 'macaddr8',
+ amoprighttype => 'macaddr8', amopstrategy => '2',
+ amopopr => '<=(macaddr8,macaddr8)', amopmethod => 'btree' },
+{ amopfamily => 'btree/macaddr8_ops', amoplefttype => 'macaddr8',
+ amoprighttype => 'macaddr8', amopstrategy => '3',
+ amopopr => '=(macaddr8,macaddr8)', amopmethod => 'btree' },
+{ amopfamily => 'btree/macaddr8_ops', amoplefttype => 'macaddr8',
+ amoprighttype => 'macaddr8', amopstrategy => '4',
+ amopopr => '>=(macaddr8,macaddr8)', amopmethod => 'btree' },
+{ amopfamily => 'btree/macaddr8_ops', amoplefttype => 'macaddr8',
+ amoprighttype => 'macaddr8', amopstrategy => '5',
+ amopopr => '>(macaddr8,macaddr8)', amopmethod => 'btree' },
+
+# btree network
+
+{ amopfamily => 'btree/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '1', amopopr => '<(inet,inet)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '2', amopopr => '<=(inet,inet)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '3', amopopr => '=(inet,inet)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '4', amopopr => '>=(inet,inet)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '5', amopopr => '>(inet,inet)',
+ amopmethod => 'btree' },
+
+# btree numeric
+
+{ amopfamily => 'btree/numeric_ops', amoplefttype => 'numeric',
+ amoprighttype => 'numeric', amopstrategy => '1',
+ amopopr => '<(numeric,numeric)', amopmethod => 'btree' },
+{ amopfamily => 'btree/numeric_ops', amoplefttype => 'numeric',
+ amoprighttype => 'numeric', amopstrategy => '2',
+ amopopr => '<=(numeric,numeric)', amopmethod => 'btree' },
+{ amopfamily => 'btree/numeric_ops', amoplefttype => 'numeric',
+ amoprighttype => 'numeric', amopstrategy => '3',
+ amopopr => '=(numeric,numeric)', amopmethod => 'btree' },
+{ amopfamily => 'btree/numeric_ops', amoplefttype => 'numeric',
+ amoprighttype => 'numeric', amopstrategy => '4',
+ amopopr => '>=(numeric,numeric)', amopmethod => 'btree' },
+{ amopfamily => 'btree/numeric_ops', amoplefttype => 'numeric',
+ amoprighttype => 'numeric', amopstrategy => '5',
+ amopopr => '>(numeric,numeric)', amopmethod => 'btree' },
+
+# btree bool
+
+{ amopfamily => 'btree/bool_ops', amoplefttype => 'bool',
+ amoprighttype => 'bool', amopstrategy => '1', amopopr => '<(bool,bool)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/bool_ops', amoplefttype => 'bool',
+ amoprighttype => 'bool', amopstrategy => '2', amopopr => '<=(bool,bool)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/bool_ops', amoplefttype => 'bool',
+ amoprighttype => 'bool', amopstrategy => '3', amopopr => '=(bool,bool)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/bool_ops', amoplefttype => 'bool',
+ amoprighttype => 'bool', amopstrategy => '4', amopopr => '>=(bool,bool)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/bool_ops', amoplefttype => 'bool',
+ amoprighttype => 'bool', amopstrategy => '5', amopopr => '>(bool,bool)',
+ amopmethod => 'btree' },
+
+# btree bit
+
+{ amopfamily => 'btree/bit_ops', amoplefttype => 'bit', amoprighttype => 'bit',
+ amopstrategy => '1', amopopr => '<(bit,bit)', amopmethod => 'btree' },
+{ amopfamily => 'btree/bit_ops', amoplefttype => 'bit', amoprighttype => 'bit',
+ amopstrategy => '2', amopopr => '<=(bit,bit)', amopmethod => 'btree' },
+{ amopfamily => 'btree/bit_ops', amoplefttype => 'bit', amoprighttype => 'bit',
+ amopstrategy => '3', amopopr => '=(bit,bit)', amopmethod => 'btree' },
+{ amopfamily => 'btree/bit_ops', amoplefttype => 'bit', amoprighttype => 'bit',
+ amopstrategy => '4', amopopr => '>=(bit,bit)', amopmethod => 'btree' },
+{ amopfamily => 'btree/bit_ops', amoplefttype => 'bit', amoprighttype => 'bit',
+ amopstrategy => '5', amopopr => '>(bit,bit)', amopmethod => 'btree' },
+
+# btree varbit
+
+{ amopfamily => 'btree/varbit_ops', amoplefttype => 'varbit',
+ amoprighttype => 'varbit', amopstrategy => '1', amopopr => '<(varbit,varbit)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/varbit_ops', amoplefttype => 'varbit',
+ amoprighttype => 'varbit', amopstrategy => '2',
+ amopopr => '<=(varbit,varbit)', amopmethod => 'btree' },
+{ amopfamily => 'btree/varbit_ops', amoplefttype => 'varbit',
+ amoprighttype => 'varbit', amopstrategy => '3', amopopr => '=(varbit,varbit)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/varbit_ops', amoplefttype => 'varbit',
+ amoprighttype => 'varbit', amopstrategy => '4',
+ amopopr => '>=(varbit,varbit)', amopmethod => 'btree' },
+{ amopfamily => 'btree/varbit_ops', amoplefttype => 'varbit',
+ amoprighttype => 'varbit', amopstrategy => '5', amopopr => '>(varbit,varbit)',
+ amopmethod => 'btree' },
+
+# btree text pattern
+
+{ amopfamily => 'btree/text_pattern_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '1', amopopr => '~<~(text,text)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_pattern_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '2', amopopr => '~<=~(text,text)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_pattern_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '3', amopopr => '=(text,text)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_pattern_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '4', amopopr => '~>=~(text,text)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/text_pattern_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '5', amopopr => '~>~(text,text)',
+ amopmethod => 'btree' },
+
+# btree bpchar pattern
+
+{ amopfamily => 'btree/bpchar_pattern_ops', amoplefttype => 'bpchar',
+ amoprighttype => 'bpchar', amopstrategy => '1',
+ amopopr => '~<~(bpchar,bpchar)', amopmethod => 'btree' },
+{ amopfamily => 'btree/bpchar_pattern_ops', amoplefttype => 'bpchar',
+ amoprighttype => 'bpchar', amopstrategy => '2',
+ amopopr => '~<=~(bpchar,bpchar)', amopmethod => 'btree' },
+{ amopfamily => 'btree/bpchar_pattern_ops', amoplefttype => 'bpchar',
+ amoprighttype => 'bpchar', amopstrategy => '3', amopopr => '=(bpchar,bpchar)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/bpchar_pattern_ops', amoplefttype => 'bpchar',
+ amoprighttype => 'bpchar', amopstrategy => '4',
+ amopopr => '~>=~(bpchar,bpchar)', amopmethod => 'btree' },
+{ amopfamily => 'btree/bpchar_pattern_ops', amoplefttype => 'bpchar',
+ amoprighttype => 'bpchar', amopstrategy => '5',
+ amopopr => '~>~(bpchar,bpchar)', amopmethod => 'btree' },
+
+# btree money_ops
+
+{ amopfamily => 'btree/money_ops', amoplefttype => 'money',
+ amoprighttype => 'money', amopstrategy => '1', amopopr => '<(money,money)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/money_ops', amoplefttype => 'money',
+ amoprighttype => 'money', amopstrategy => '2', amopopr => '<=(money,money)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/money_ops', amoplefttype => 'money',
+ amoprighttype => 'money', amopstrategy => '3', amopopr => '=(money,money)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/money_ops', amoplefttype => 'money',
+ amoprighttype => 'money', amopstrategy => '4', amopopr => '>=(money,money)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/money_ops', amoplefttype => 'money',
+ amoprighttype => 'money', amopstrategy => '5', amopopr => '>(money,money)',
+ amopmethod => 'btree' },
+
+# btree array_ops
+
+{ amopfamily => 'btree/array_ops', amoplefttype => 'anyarray',
+ amoprighttype => 'anyarray', amopstrategy => '1',
+ amopopr => '<(anyarray,anyarray)', amopmethod => 'btree' },
+{ amopfamily => 'btree/array_ops', amoplefttype => 'anyarray',
+ amoprighttype => 'anyarray', amopstrategy => '2',
+ amopopr => '<=(anyarray,anyarray)', amopmethod => 'btree' },
+{ amopfamily => 'btree/array_ops', amoplefttype => 'anyarray',
+ amoprighttype => 'anyarray', amopstrategy => '3',
+ amopopr => '=(anyarray,anyarray)', amopmethod => 'btree' },
+{ amopfamily => 'btree/array_ops', amoplefttype => 'anyarray',
+ amoprighttype => 'anyarray', amopstrategy => '4',
+ amopopr => '>=(anyarray,anyarray)', amopmethod => 'btree' },
+{ amopfamily => 'btree/array_ops', amoplefttype => 'anyarray',
+ amoprighttype => 'anyarray', amopstrategy => '5',
+ amopopr => '>(anyarray,anyarray)', amopmethod => 'btree' },
+
+# btree record_ops
+
+{ amopfamily => 'btree/record_ops', amoplefttype => 'record',
+ amoprighttype => 'record', amopstrategy => '1', amopopr => '<(record,record)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/record_ops', amoplefttype => 'record',
+ amoprighttype => 'record', amopstrategy => '2',
+ amopopr => '<=(record,record)', amopmethod => 'btree' },
+{ amopfamily => 'btree/record_ops', amoplefttype => 'record',
+ amoprighttype => 'record', amopstrategy => '3', amopopr => '=(record,record)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/record_ops', amoplefttype => 'record',
+ amoprighttype => 'record', amopstrategy => '4',
+ amopopr => '>=(record,record)', amopmethod => 'btree' },
+{ amopfamily => 'btree/record_ops', amoplefttype => 'record',
+ amoprighttype => 'record', amopstrategy => '5', amopopr => '>(record,record)',
+ amopmethod => 'btree' },
+
+# btree record_image_ops
+
+{ amopfamily => 'btree/record_image_ops', amoplefttype => 'record',
+ amoprighttype => 'record', amopstrategy => '1',
+ amopopr => '*<(record,record)', amopmethod => 'btree' },
+{ amopfamily => 'btree/record_image_ops', amoplefttype => 'record',
+ amoprighttype => 'record', amopstrategy => '2',
+ amopopr => '*<=(record,record)', amopmethod => 'btree' },
+{ amopfamily => 'btree/record_image_ops', amoplefttype => 'record',
+ amoprighttype => 'record', amopstrategy => '3',
+ amopopr => '*=(record,record)', amopmethod => 'btree' },
+{ amopfamily => 'btree/record_image_ops', amoplefttype => 'record',
+ amoprighttype => 'record', amopstrategy => '4',
+ amopopr => '*>=(record,record)', amopmethod => 'btree' },
+{ amopfamily => 'btree/record_image_ops', amoplefttype => 'record',
+ amoprighttype => 'record', amopstrategy => '5',
+ amopopr => '*>(record,record)', amopmethod => 'btree' },
+
+# btree uuid_ops
+
+{ amopfamily => 'btree/uuid_ops', amoplefttype => 'uuid',
+ amoprighttype => 'uuid', amopstrategy => '1', amopopr => '<(uuid,uuid)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/uuid_ops', amoplefttype => 'uuid',
+ amoprighttype => 'uuid', amopstrategy => '2', amopopr => '<=(uuid,uuid)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/uuid_ops', amoplefttype => 'uuid',
+ amoprighttype => 'uuid', amopstrategy => '3', amopopr => '=(uuid,uuid)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/uuid_ops', amoplefttype => 'uuid',
+ amoprighttype => 'uuid', amopstrategy => '4', amopopr => '>=(uuid,uuid)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/uuid_ops', amoplefttype => 'uuid',
+ amoprighttype => 'uuid', amopstrategy => '5', amopopr => '>(uuid,uuid)',
+ amopmethod => 'btree' },
+
+# btree pg_lsn_ops
+
+{ amopfamily => 'btree/pg_lsn_ops', amoplefttype => 'pg_lsn',
+ amoprighttype => 'pg_lsn', amopstrategy => '1', amopopr => '<(pg_lsn,pg_lsn)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/pg_lsn_ops', amoplefttype => 'pg_lsn',
+ amoprighttype => 'pg_lsn', amopstrategy => '2',
+ amopopr => '<=(pg_lsn,pg_lsn)', amopmethod => 'btree' },
+{ amopfamily => 'btree/pg_lsn_ops', amoplefttype => 'pg_lsn',
+ amoprighttype => 'pg_lsn', amopstrategy => '3', amopopr => '=(pg_lsn,pg_lsn)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/pg_lsn_ops', amoplefttype => 'pg_lsn',
+ amoprighttype => 'pg_lsn', amopstrategy => '4',
+ amopopr => '>=(pg_lsn,pg_lsn)', amopmethod => 'btree' },
+{ amopfamily => 'btree/pg_lsn_ops', amoplefttype => 'pg_lsn',
+ amoprighttype => 'pg_lsn', amopstrategy => '5', amopopr => '>(pg_lsn,pg_lsn)',
+ amopmethod => 'btree' },
+
+# hash index_ops
+
+# bpchar_ops
+{ amopfamily => 'hash/bpchar_ops', amoplefttype => 'bpchar',
+ amoprighttype => 'bpchar', amopstrategy => '1', amopopr => '=(bpchar,bpchar)',
+ amopmethod => 'hash' },
+
+# char_ops
+{ amopfamily => 'hash/char_ops', amoplefttype => 'char',
+ amoprighttype => 'char', amopstrategy => '1', amopopr => '=(char,char)',
+ amopmethod => 'hash' },
+
+# date_ops
+{ amopfamily => 'hash/date_ops', amoplefttype => 'date',
+ amoprighttype => 'date', amopstrategy => '1', amopopr => '=(date,date)',
+ amopmethod => 'hash' },
+
+# float_ops
+{ amopfamily => 'hash/float_ops', amoplefttype => 'float4',
+ amoprighttype => 'float4', amopstrategy => '1', amopopr => '=(float4,float4)',
+ amopmethod => 'hash' },
+{ amopfamily => 'hash/float_ops', amoplefttype => 'float8',
+ amoprighttype => 'float8', amopstrategy => '1', amopopr => '=(float8,float8)',
+ amopmethod => 'hash' },
+{ amopfamily => 'hash/float_ops', amoplefttype => 'float4',
+ amoprighttype => 'float8', amopstrategy => '1', amopopr => '=(float4,float8)',
+ amopmethod => 'hash' },
+{ amopfamily => 'hash/float_ops', amoplefttype => 'float8',
+ amoprighttype => 'float4', amopstrategy => '1', amopopr => '=(float8,float4)',
+ amopmethod => 'hash' },
+
+# network_ops
+{ amopfamily => 'hash/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '1', amopopr => '=(inet,inet)',
+ amopmethod => 'hash' },
+
+# integer_ops
+{ amopfamily => 'hash/integer_ops', amoplefttype => 'int2',
+ amoprighttype => 'int2', amopstrategy => '1', amopopr => '=(int2,int2)',
+ amopmethod => 'hash' },
+{ amopfamily => 'hash/integer_ops', amoplefttype => 'int4',
+ amoprighttype => 'int4', amopstrategy => '1', amopopr => '=(int4,int4)',
+ amopmethod => 'hash' },
+{ amopfamily => 'hash/integer_ops', amoplefttype => 'int8',
+ amoprighttype => 'int8', amopstrategy => '1', amopopr => '=(int8,int8)',
+ amopmethod => 'hash' },
+{ amopfamily => 'hash/integer_ops', amoplefttype => 'int2',
+ amoprighttype => 'int4', amopstrategy => '1', amopopr => '=(int2,int4)',
+ amopmethod => 'hash' },
+{ amopfamily => 'hash/integer_ops', amoplefttype => 'int2',
+ amoprighttype => 'int8', amopstrategy => '1', amopopr => '=(int2,int8)',
+ amopmethod => 'hash' },
+{ amopfamily => 'hash/integer_ops', amoplefttype => 'int4',
+ amoprighttype => 'int2', amopstrategy => '1', amopopr => '=(int4,int2)',
+ amopmethod => 'hash' },
+{ amopfamily => 'hash/integer_ops', amoplefttype => 'int4',
+ amoprighttype => 'int8', amopstrategy => '1', amopopr => '=(int4,int8)',
+ amopmethod => 'hash' },
+{ amopfamily => 'hash/integer_ops', amoplefttype => 'int8',
+ amoprighttype => 'int2', amopstrategy => '1', amopopr => '=(int8,int2)',
+ amopmethod => 'hash' },
+{ amopfamily => 'hash/integer_ops', amoplefttype => 'int8',
+ amoprighttype => 'int4', amopstrategy => '1', amopopr => '=(int8,int4)',
+ amopmethod => 'hash' },
+
+# interval_ops
+{ amopfamily => 'hash/interval_ops', amoplefttype => 'interval',
+ amoprighttype => 'interval', amopstrategy => '1',
+ amopopr => '=(interval,interval)', amopmethod => 'hash' },
+
+# macaddr_ops
+{ amopfamily => 'hash/macaddr_ops', amoplefttype => 'macaddr',
+ amoprighttype => 'macaddr', amopstrategy => '1',
+ amopopr => '=(macaddr,macaddr)', amopmethod => 'hash' },
+
+# macaddr8_ops
+{ amopfamily => 'hash/macaddr8_ops', amoplefttype => 'macaddr8',
+ amoprighttype => 'macaddr8', amopstrategy => '1',
+ amopopr => '=(macaddr8,macaddr8)', amopmethod => 'hash' },
+
+# oid_ops
+{ amopfamily => 'hash/oid_ops', amoplefttype => 'oid', amoprighttype => 'oid',
+ amopstrategy => '1', amopopr => '=(oid,oid)', amopmethod => 'hash' },
+
+# oidvector_ops
+{ amopfamily => 'hash/oidvector_ops', amoplefttype => 'oidvector',
+ amoprighttype => 'oidvector', amopstrategy => '1',
+ amopopr => '=(oidvector,oidvector)', amopmethod => 'hash' },
+
+# text_ops
+{ amopfamily => 'hash/text_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '1', amopopr => '=(text,text)',
+ amopmethod => 'hash' },
+{ amopfamily => 'hash/text_ops', amoplefttype => 'name',
+ amoprighttype => 'name', amopstrategy => '1', amopopr => '=(name,name)',
+ amopmethod => 'hash' },
+{ amopfamily => 'hash/text_ops', amoplefttype => 'name',
+ amoprighttype => 'text', amopstrategy => '1', amopopr => '=(name,text)',
+ amopmethod => 'hash' },
+{ amopfamily => 'hash/text_ops', amoplefttype => 'text',
+ amoprighttype => 'name', amopstrategy => '1', amopopr => '=(text,name)',
+ amopmethod => 'hash' },
+
+# time_ops
+{ amopfamily => 'hash/time_ops', amoplefttype => 'time',
+ amoprighttype => 'time', amopstrategy => '1', amopopr => '=(time,time)',
+ amopmethod => 'hash' },
+
+# timestamptz_ops
+{ amopfamily => 'hash/timestamptz_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamptz', amopstrategy => '1',
+ amopopr => '=(timestamptz,timestamptz)', amopmethod => 'hash' },
+
+# timetz_ops
+{ amopfamily => 'hash/timetz_ops', amoplefttype => 'timetz',
+ amoprighttype => 'timetz', amopstrategy => '1', amopopr => '=(timetz,timetz)',
+ amopmethod => 'hash' },
+
+# timestamp_ops
+{ amopfamily => 'hash/timestamp_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamp', amopstrategy => '1',
+ amopopr => '=(timestamp,timestamp)', amopmethod => 'hash' },
+
+# bool_ops
+{ amopfamily => 'hash/bool_ops', amoplefttype => 'bool',
+ amoprighttype => 'bool', amopstrategy => '1', amopopr => '=(bool,bool)',
+ amopmethod => 'hash' },
+
+# bytea_ops
+{ amopfamily => 'hash/bytea_ops', amoplefttype => 'bytea',
+ amoprighttype => 'bytea', amopstrategy => '1', amopopr => '=(bytea,bytea)',
+ amopmethod => 'hash' },
+
+# xid_ops
+{ amopfamily => 'hash/xid_ops', amoplefttype => 'xid', amoprighttype => 'xid',
+ amopstrategy => '1', amopopr => '=(xid,xid)', amopmethod => 'hash' },
+
+# xid8_ops
+{ amopfamily => 'hash/xid8_ops', amoplefttype => 'xid8',
+ amoprighttype => 'xid8', amopstrategy => '1', amopopr => '=(xid8,xid8)',
+ amopmethod => 'hash' },
+
+# cid_ops
+{ amopfamily => 'hash/cid_ops', amoplefttype => 'cid', amoprighttype => 'cid',
+ amopstrategy => '1', amopopr => '=(cid,cid)', amopmethod => 'hash' },
+
+# tid_ops
+{ amopfamily => 'hash/tid_ops', amoplefttype => 'tid', amoprighttype => 'tid',
+ amopstrategy => '1', amopopr => '=(tid,tid)', amopmethod => 'hash' },
+
+# text_pattern_ops
+{ amopfamily => 'hash/text_pattern_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '1', amopopr => '=(text,text)',
+ amopmethod => 'hash' },
+
+# bpchar_pattern_ops
+{ amopfamily => 'hash/bpchar_pattern_ops', amoplefttype => 'bpchar',
+ amoprighttype => 'bpchar', amopstrategy => '1', amopopr => '=(bpchar,bpchar)',
+ amopmethod => 'hash' },
+
+# aclitem_ops
+{ amopfamily => 'hash/aclitem_ops', amoplefttype => 'aclitem',
+ amoprighttype => 'aclitem', amopstrategy => '1',
+ amopopr => '=(aclitem,aclitem)', amopmethod => 'hash' },
+
+# uuid_ops
+{ amopfamily => 'hash/uuid_ops', amoplefttype => 'uuid',
+ amoprighttype => 'uuid', amopstrategy => '1', amopopr => '=(uuid,uuid)',
+ amopmethod => 'hash' },
+
+# pg_lsn_ops
+{ amopfamily => 'hash/pg_lsn_ops', amoplefttype => 'pg_lsn',
+ amoprighttype => 'pg_lsn', amopstrategy => '1', amopopr => '=(pg_lsn,pg_lsn)',
+ amopmethod => 'hash' },
+
+# numeric_ops
+{ amopfamily => 'hash/numeric_ops', amoplefttype => 'numeric',
+ amoprighttype => 'numeric', amopstrategy => '1',
+ amopopr => '=(numeric,numeric)', amopmethod => 'hash' },
+
+# array_ops
+{ amopfamily => 'hash/array_ops', amoplefttype => 'anyarray',
+ amoprighttype => 'anyarray', amopstrategy => '1',
+ amopopr => '=(anyarray,anyarray)', amopmethod => 'hash' },
+
+# gist box_ops
+{ amopfamily => 'gist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '1', amopopr => '<<(box,box)', amopmethod => 'gist' },
+{ amopfamily => 'gist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '2', amopopr => '&<(box,box)', amopmethod => 'gist' },
+{ amopfamily => 'gist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '3', amopopr => '&&(box,box)', amopmethod => 'gist' },
+{ amopfamily => 'gist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '4', amopopr => '&>(box,box)', amopmethod => 'gist' },
+{ amopfamily => 'gist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '5', amopopr => '>>(box,box)', amopmethod => 'gist' },
+{ amopfamily => 'gist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '6', amopopr => '~=(box,box)', amopmethod => 'gist' },
+{ amopfamily => 'gist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '7', amopopr => '@>(box,box)', amopmethod => 'gist' },
+{ amopfamily => 'gist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '8', amopopr => '<@(box,box)', amopmethod => 'gist' },
+{ amopfamily => 'gist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '9', amopopr => '&<|(box,box)', amopmethod => 'gist' },
+{ amopfamily => 'gist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '10', amopopr => '<<|(box,box)', amopmethod => 'gist' },
+{ amopfamily => 'gist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '11', amopopr => '|>>(box,box)', amopmethod => 'gist' },
+{ amopfamily => 'gist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '12', amopopr => '|&>(box,box)', amopmethod => 'gist' },
+{ amopfamily => 'gist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '13', amopopr => '~(box,box)', amopmethod => 'gist' },
+{ amopfamily => 'gist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '14', amopopr => '@(box,box)', amopmethod => 'gist' },
+{ amopfamily => 'gist/box_ops', amoplefttype => 'box', amoprighttype => 'point',
+ amopstrategy => '15', amoppurpose => 'o', amopopr => '<->(box,point)',
+ amopmethod => 'gist', amopsortfamily => 'btree/float_ops' },
+
+# gist point_ops
+{ amopfamily => 'gist/point_ops', amoplefttype => 'point',
+ amoprighttype => 'point', amopstrategy => '11', amopopr => '>^(point,point)',
+ amopmethod => 'gist' },
+{ amopfamily => 'gist/point_ops', amoplefttype => 'point',
+ amoprighttype => 'point', amopstrategy => '1', amopopr => '<<(point,point)',
+ amopmethod => 'gist' },
+{ amopfamily => 'gist/point_ops', amoplefttype => 'point',
+ amoprighttype => 'point', amopstrategy => '5', amopopr => '>>(point,point)',
+ amopmethod => 'gist' },
+{ amopfamily => 'gist/point_ops', amoplefttype => 'point',
+ amoprighttype => 'point', amopstrategy => '10', amopopr => '<^(point,point)',
+ amopmethod => 'gist' },
+{ amopfamily => 'gist/point_ops', amoplefttype => 'point',
+ amoprighttype => 'point', amopstrategy => '6', amopopr => '~=(point,point)',
+ amopmethod => 'gist' },
+{ amopfamily => 'gist/point_ops', amoplefttype => 'point',
+ amoprighttype => 'point', amopstrategy => '15', amoppurpose => 'o',
+ amopopr => '<->(point,point)', amopmethod => 'gist',
+ amopsortfamily => 'btree/float_ops' },
+{ amopfamily => 'gist/point_ops', amoplefttype => 'point',
+ amoprighttype => 'box', amopstrategy => '28', amopopr => '<@(point,box)',
+ amopmethod => 'gist' },
+{ amopfamily => 'gist/point_ops', amoplefttype => 'point',
+ amoprighttype => 'polygon', amopstrategy => '48',
+ amopopr => '<@(point,polygon)', amopmethod => 'gist' },
+{ amopfamily => 'gist/point_ops', amoplefttype => 'point',
+ amoprighttype => 'circle', amopstrategy => '68',
+ amopopr => '<@(point,circle)', amopmethod => 'gist' },
+
+# gist poly_ops (supports polygons)
+{ amopfamily => 'gist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '1',
+ amopopr => '<<(polygon,polygon)', amopmethod => 'gist' },
+{ amopfamily => 'gist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '2',
+ amopopr => '&<(polygon,polygon)', amopmethod => 'gist' },
+{ amopfamily => 'gist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '3',
+ amopopr => '&&(polygon,polygon)', amopmethod => 'gist' },
+{ amopfamily => 'gist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '4',
+ amopopr => '&>(polygon,polygon)', amopmethod => 'gist' },
+{ amopfamily => 'gist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '5',
+ amopopr => '>>(polygon,polygon)', amopmethod => 'gist' },
+{ amopfamily => 'gist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '6',
+ amopopr => '~=(polygon,polygon)', amopmethod => 'gist' },
+{ amopfamily => 'gist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '7',
+ amopopr => '@>(polygon,polygon)', amopmethod => 'gist' },
+{ amopfamily => 'gist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '8',
+ amopopr => '<@(polygon,polygon)', amopmethod => 'gist' },
+{ amopfamily => 'gist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '9',
+ amopopr => '&<|(polygon,polygon)', amopmethod => 'gist' },
+{ amopfamily => 'gist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '10',
+ amopopr => '<<|(polygon,polygon)', amopmethod => 'gist' },
+{ amopfamily => 'gist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '11',
+ amopopr => '|>>(polygon,polygon)', amopmethod => 'gist' },
+{ amopfamily => 'gist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '12',
+ amopopr => '|&>(polygon,polygon)', amopmethod => 'gist' },
+{ amopfamily => 'gist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '13',
+ amopopr => '~(polygon,polygon)', amopmethod => 'gist' },
+{ amopfamily => 'gist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '14',
+ amopopr => '@(polygon,polygon)', amopmethod => 'gist' },
+{ amopfamily => 'gist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'point', amopstrategy => '15', amoppurpose => 'o',
+ amopopr => '<->(polygon,point)', amopmethod => 'gist',
+ amopsortfamily => 'btree/float_ops' },
+
+# gist circle_ops
+{ amopfamily => 'gist/circle_ops', amoplefttype => 'circle',
+ amoprighttype => 'circle', amopstrategy => '1',
+ amopopr => '<<(circle,circle)', amopmethod => 'gist' },
+{ amopfamily => 'gist/circle_ops', amoplefttype => 'circle',
+ amoprighttype => 'circle', amopstrategy => '2',
+ amopopr => '&<(circle,circle)', amopmethod => 'gist' },
+{ amopfamily => 'gist/circle_ops', amoplefttype => 'circle',
+ amoprighttype => 'circle', amopstrategy => '3',
+ amopopr => '&&(circle,circle)', amopmethod => 'gist' },
+{ amopfamily => 'gist/circle_ops', amoplefttype => 'circle',
+ amoprighttype => 'circle', amopstrategy => '4',
+ amopopr => '&>(circle,circle)', amopmethod => 'gist' },
+{ amopfamily => 'gist/circle_ops', amoplefttype => 'circle',
+ amoprighttype => 'circle', amopstrategy => '5',
+ amopopr => '>>(circle,circle)', amopmethod => 'gist' },
+{ amopfamily => 'gist/circle_ops', amoplefttype => 'circle',
+ amoprighttype => 'circle', amopstrategy => '6',
+ amopopr => '~=(circle,circle)', amopmethod => 'gist' },
+{ amopfamily => 'gist/circle_ops', amoplefttype => 'circle',
+ amoprighttype => 'circle', amopstrategy => '7',
+ amopopr => '@>(circle,circle)', amopmethod => 'gist' },
+{ amopfamily => 'gist/circle_ops', amoplefttype => 'circle',
+ amoprighttype => 'circle', amopstrategy => '8',
+ amopopr => '<@(circle,circle)', amopmethod => 'gist' },
+{ amopfamily => 'gist/circle_ops', amoplefttype => 'circle',
+ amoprighttype => 'circle', amopstrategy => '9',
+ amopopr => '&<|(circle,circle)', amopmethod => 'gist' },
+{ amopfamily => 'gist/circle_ops', amoplefttype => 'circle',
+ amoprighttype => 'circle', amopstrategy => '10',
+ amopopr => '<<|(circle,circle)', amopmethod => 'gist' },
+{ amopfamily => 'gist/circle_ops', amoplefttype => 'circle',
+ amoprighttype => 'circle', amopstrategy => '11',
+ amopopr => '|>>(circle,circle)', amopmethod => 'gist' },
+{ amopfamily => 'gist/circle_ops', amoplefttype => 'circle',
+ amoprighttype => 'circle', amopstrategy => '12',
+ amopopr => '|&>(circle,circle)', amopmethod => 'gist' },
+{ amopfamily => 'gist/circle_ops', amoplefttype => 'circle',
+ amoprighttype => 'circle', amopstrategy => '13',
+ amopopr => '~(circle,circle)', amopmethod => 'gist' },
+{ amopfamily => 'gist/circle_ops', amoplefttype => 'circle',
+ amoprighttype => 'circle', amopstrategy => '14',
+ amopopr => '@(circle,circle)', amopmethod => 'gist' },
+{ amopfamily => 'gist/circle_ops', amoplefttype => 'circle',
+ amoprighttype => 'point', amopstrategy => '15', amoppurpose => 'o',
+ amopopr => '<->(circle,point)', amopmethod => 'gist',
+ amopsortfamily => 'btree/float_ops' },
+
+# gin array_ops
+{ amopfamily => 'gin/array_ops', amoplefttype => 'anyarray',
+ amoprighttype => 'anyarray', amopstrategy => '1',
+ amopopr => '&&(anyarray,anyarray)', amopmethod => 'gin' },
+{ amopfamily => 'gin/array_ops', amoplefttype => 'anyarray',
+ amoprighttype => 'anyarray', amopstrategy => '2',
+ amopopr => '@>(anyarray,anyarray)', amopmethod => 'gin' },
+{ amopfamily => 'gin/array_ops', amoplefttype => 'anyarray',
+ amoprighttype => 'anyarray', amopstrategy => '3',
+ amopopr => '<@(anyarray,anyarray)', amopmethod => 'gin' },
+{ amopfamily => 'gin/array_ops', amoplefttype => 'anyarray',
+ amoprighttype => 'anyarray', amopstrategy => '4',
+ amopopr => '=(anyarray,anyarray)', amopmethod => 'gin' },
+
+# btree enum_ops
+{ amopfamily => 'btree/enum_ops', amoplefttype => 'anyenum',
+ amoprighttype => 'anyenum', amopstrategy => '1',
+ amopopr => '<(anyenum,anyenum)', amopmethod => 'btree' },
+{ amopfamily => 'btree/enum_ops', amoplefttype => 'anyenum',
+ amoprighttype => 'anyenum', amopstrategy => '2',
+ amopopr => '<=(anyenum,anyenum)', amopmethod => 'btree' },
+{ amopfamily => 'btree/enum_ops', amoplefttype => 'anyenum',
+ amoprighttype => 'anyenum', amopstrategy => '3',
+ amopopr => '=(anyenum,anyenum)', amopmethod => 'btree' },
+{ amopfamily => 'btree/enum_ops', amoplefttype => 'anyenum',
+ amoprighttype => 'anyenum', amopstrategy => '4',
+ amopopr => '>=(anyenum,anyenum)', amopmethod => 'btree' },
+{ amopfamily => 'btree/enum_ops', amoplefttype => 'anyenum',
+ amoprighttype => 'anyenum', amopstrategy => '5',
+ amopopr => '>(anyenum,anyenum)', amopmethod => 'btree' },
+
+# hash enum_ops
+{ amopfamily => 'hash/enum_ops', amoplefttype => 'anyenum',
+ amoprighttype => 'anyenum', amopstrategy => '1',
+ amopopr => '=(anyenum,anyenum)', amopmethod => 'hash' },
+
+# btree tsvector_ops
+{ amopfamily => 'btree/tsvector_ops', amoplefttype => 'tsvector',
+ amoprighttype => 'tsvector', amopstrategy => '1',
+ amopopr => '<(tsvector,tsvector)', amopmethod => 'btree' },
+{ amopfamily => 'btree/tsvector_ops', amoplefttype => 'tsvector',
+ amoprighttype => 'tsvector', amopstrategy => '2',
+ amopopr => '<=(tsvector,tsvector)', amopmethod => 'btree' },
+{ amopfamily => 'btree/tsvector_ops', amoplefttype => 'tsvector',
+ amoprighttype => 'tsvector', amopstrategy => '3',
+ amopopr => '=(tsvector,tsvector)', amopmethod => 'btree' },
+{ amopfamily => 'btree/tsvector_ops', amoplefttype => 'tsvector',
+ amoprighttype => 'tsvector', amopstrategy => '4',
+ amopopr => '>=(tsvector,tsvector)', amopmethod => 'btree' },
+{ amopfamily => 'btree/tsvector_ops', amoplefttype => 'tsvector',
+ amoprighttype => 'tsvector', amopstrategy => '5',
+ amopopr => '>(tsvector,tsvector)', amopmethod => 'btree' },
+
+# GiST tsvector_ops
+{ amopfamily => 'gist/tsvector_ops', amoplefttype => 'tsvector',
+ amoprighttype => 'tsquery', amopstrategy => '1',
+ amopopr => '@@(tsvector,tsquery)', amopmethod => 'gist' },
+
+# GIN tsvector_ops
+{ amopfamily => 'gin/tsvector_ops', amoplefttype => 'tsvector',
+ amoprighttype => 'tsquery', amopstrategy => '1',
+ amopopr => '@@(tsvector,tsquery)', amopmethod => 'gin' },
+{ amopfamily => 'gin/tsvector_ops', amoplefttype => 'tsvector',
+ amoprighttype => 'tsquery', amopstrategy => '2',
+ amopopr => '@@@(tsvector,tsquery)', amopmethod => 'gin' },
+
+# btree tsquery_ops
+{ amopfamily => 'btree/tsquery_ops', amoplefttype => 'tsquery',
+ amoprighttype => 'tsquery', amopstrategy => '1',
+ amopopr => '<(tsquery,tsquery)', amopmethod => 'btree' },
+{ amopfamily => 'btree/tsquery_ops', amoplefttype => 'tsquery',
+ amoprighttype => 'tsquery', amopstrategy => '2',
+ amopopr => '<=(tsquery,tsquery)', amopmethod => 'btree' },
+{ amopfamily => 'btree/tsquery_ops', amoplefttype => 'tsquery',
+ amoprighttype => 'tsquery', amopstrategy => '3',
+ amopopr => '=(tsquery,tsquery)', amopmethod => 'btree' },
+{ amopfamily => 'btree/tsquery_ops', amoplefttype => 'tsquery',
+ amoprighttype => 'tsquery', amopstrategy => '4',
+ amopopr => '>=(tsquery,tsquery)', amopmethod => 'btree' },
+{ amopfamily => 'btree/tsquery_ops', amoplefttype => 'tsquery',
+ amoprighttype => 'tsquery', amopstrategy => '5',
+ amopopr => '>(tsquery,tsquery)', amopmethod => 'btree' },
+
+# GiST tsquery_ops
+{ amopfamily => 'gist/tsquery_ops', amoplefttype => 'tsquery',
+ amoprighttype => 'tsquery', amopstrategy => '7',
+ amopopr => '@>(tsquery,tsquery)', amopmethod => 'gist' },
+{ amopfamily => 'gist/tsquery_ops', amoplefttype => 'tsquery',
+ amoprighttype => 'tsquery', amopstrategy => '8',
+ amopopr => '<@(tsquery,tsquery)', amopmethod => 'gist' },
+
+# btree range_ops
+{ amopfamily => 'btree/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '1',
+ amopopr => '<(anyrange,anyrange)', amopmethod => 'btree' },
+{ amopfamily => 'btree/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '2',
+ amopopr => '<=(anyrange,anyrange)', amopmethod => 'btree' },
+{ amopfamily => 'btree/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '3',
+ amopopr => '=(anyrange,anyrange)', amopmethod => 'btree' },
+{ amopfamily => 'btree/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '4',
+ amopopr => '>=(anyrange,anyrange)', amopmethod => 'btree' },
+{ amopfamily => 'btree/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '5',
+ amopopr => '>(anyrange,anyrange)', amopmethod => 'btree' },
+
+# hash range_ops
+{ amopfamily => 'hash/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '1',
+ amopopr => '=(anyrange,anyrange)', amopmethod => 'hash' },
+
+# GiST range_ops
+{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '1',
+ amopopr => '<<(anyrange,anyrange)', amopmethod => 'gist' },
+{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '2',
+ amopopr => '&<(anyrange,anyrange)', amopmethod => 'gist' },
+{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '3',
+ amopopr => '&&(anyrange,anyrange)', amopmethod => 'gist' },
+{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '4',
+ amopopr => '&>(anyrange,anyrange)', amopmethod => 'gist' },
+{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '5',
+ amopopr => '>>(anyrange,anyrange)', amopmethod => 'gist' },
+{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '6',
+ amopopr => '-|-(anyrange,anyrange)', amopmethod => 'gist' },
+{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '7',
+ amopopr => '@>(anyrange,anyrange)', amopmethod => 'gist' },
+{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '8',
+ amopopr => '<@(anyrange,anyrange)', amopmethod => 'gist' },
+{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyelement', amopstrategy => '16',
+ amopopr => '@>(anyrange,anyelement)', amopmethod => 'gist' },
+{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '18',
+ amopopr => '=(anyrange,anyrange)', amopmethod => 'gist' },
+
+# SP-GiST quad_point_ops
+{ amopfamily => 'spgist/quad_point_ops', amoplefttype => 'point',
+ amoprighttype => 'point', amopstrategy => '11', amopopr => '>^(point,point)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/quad_point_ops', amoplefttype => 'point',
+ amoprighttype => 'point', amopstrategy => '1', amopopr => '<<(point,point)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/quad_point_ops', amoplefttype => 'point',
+ amoprighttype => 'point', amopstrategy => '5', amopopr => '>>(point,point)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/quad_point_ops', amoplefttype => 'point',
+ amoprighttype => 'point', amopstrategy => '10', amopopr => '<^(point,point)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/quad_point_ops', amoplefttype => 'point',
+ amoprighttype => 'point', amopstrategy => '6', amopopr => '~=(point,point)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/quad_point_ops', amoplefttype => 'point',
+ amoprighttype => 'box', amopstrategy => '8', amopopr => '<@(point,box)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/quad_point_ops', amoplefttype => 'point',
+ amoprighttype => 'point', amopstrategy => '15', amoppurpose => 'o',
+ amopopr => '<->(point,point)', amopmethod => 'spgist',
+ amopsortfamily => 'btree/float_ops' },
+
+# SP-GiST kd_point_ops
+{ amopfamily => 'spgist/kd_point_ops', amoplefttype => 'point',
+ amoprighttype => 'point', amopstrategy => '11', amopopr => '>^(point,point)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/kd_point_ops', amoplefttype => 'point',
+ amoprighttype => 'point', amopstrategy => '1', amopopr => '<<(point,point)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/kd_point_ops', amoplefttype => 'point',
+ amoprighttype => 'point', amopstrategy => '5', amopopr => '>>(point,point)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/kd_point_ops', amoplefttype => 'point',
+ amoprighttype => 'point', amopstrategy => '10', amopopr => '<^(point,point)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/kd_point_ops', amoplefttype => 'point',
+ amoprighttype => 'point', amopstrategy => '6', amopopr => '~=(point,point)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/kd_point_ops', amoplefttype => 'point',
+ amoprighttype => 'box', amopstrategy => '8', amopopr => '<@(point,box)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/kd_point_ops', amoplefttype => 'point',
+ amoprighttype => 'point', amopstrategy => '15', amoppurpose => 'o',
+ amopopr => '<->(point,point)', amopmethod => 'spgist',
+ amopsortfamily => 'btree/float_ops' },
+
+# SP-GiST text_ops
+{ amopfamily => 'spgist/text_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '1', amopopr => '~<~(text,text)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/text_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '2', amopopr => '~<=~(text,text)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/text_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '3', amopopr => '=(text,text)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/text_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '4', amopopr => '~>=~(text,text)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/text_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '5', amopopr => '~>~(text,text)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/text_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '11', amopopr => '<(text,text)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/text_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '12', amopopr => '<=(text,text)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/text_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '14', amopopr => '>=(text,text)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/text_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '15', amopopr => '>(text,text)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/text_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '28', amopopr => '^@(text,text)',
+ amopmethod => 'spgist' },
+
+# btree jsonb_ops
+{ amopfamily => 'btree/jsonb_ops', amoplefttype => 'jsonb',
+ amoprighttype => 'jsonb', amopstrategy => '1', amopopr => '<(jsonb,jsonb)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/jsonb_ops', amoplefttype => 'jsonb',
+ amoprighttype => 'jsonb', amopstrategy => '2', amopopr => '<=(jsonb,jsonb)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/jsonb_ops', amoplefttype => 'jsonb',
+ amoprighttype => 'jsonb', amopstrategy => '3', amopopr => '=(jsonb,jsonb)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/jsonb_ops', amoplefttype => 'jsonb',
+ amoprighttype => 'jsonb', amopstrategy => '4', amopopr => '>=(jsonb,jsonb)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/jsonb_ops', amoplefttype => 'jsonb',
+ amoprighttype => 'jsonb', amopstrategy => '5', amopopr => '>(jsonb,jsonb)',
+ amopmethod => 'btree' },
+
+# hash jsonb_ops
+{ amopfamily => 'hash/jsonb_ops', amoplefttype => 'jsonb',
+ amoprighttype => 'jsonb', amopstrategy => '1', amopopr => '=(jsonb,jsonb)',
+ amopmethod => 'hash' },
+
+# GIN jsonb_ops
+{ amopfamily => 'gin/jsonb_ops', amoplefttype => 'jsonb',
+ amoprighttype => 'jsonb', amopstrategy => '7', amopopr => '@>(jsonb,jsonb)',
+ amopmethod => 'gin' },
+{ amopfamily => 'gin/jsonb_ops', amoplefttype => 'jsonb',
+ amoprighttype => 'text', amopstrategy => '9', amopopr => '?(jsonb,text)',
+ amopmethod => 'gin' },
+{ amopfamily => 'gin/jsonb_ops', amoplefttype => 'jsonb',
+ amoprighttype => '_text', amopstrategy => '10', amopopr => '?|(jsonb,_text)',
+ amopmethod => 'gin' },
+{ amopfamily => 'gin/jsonb_ops', amoplefttype => 'jsonb',
+ amoprighttype => '_text', amopstrategy => '11', amopopr => '?&(jsonb,_text)',
+ amopmethod => 'gin' },
+{ amopfamily => 'gin/jsonb_ops', amoplefttype => 'jsonb',
+ amoprighttype => 'jsonpath', amopstrategy => '15',
+ amopopr => '@?(jsonb,jsonpath)', amopmethod => 'gin' },
+{ amopfamily => 'gin/jsonb_ops', amoplefttype => 'jsonb',
+ amoprighttype => 'jsonpath', amopstrategy => '16',
+ amopopr => '@@(jsonb,jsonpath)', amopmethod => 'gin' },
+
+# GIN jsonb_path_ops
+{ amopfamily => 'gin/jsonb_path_ops', amoplefttype => 'jsonb',
+ amoprighttype => 'jsonb', amopstrategy => '7', amopopr => '@>(jsonb,jsonb)',
+ amopmethod => 'gin' },
+{ amopfamily => 'gin/jsonb_path_ops', amoplefttype => 'jsonb',
+ amoprighttype => 'jsonpath', amopstrategy => '15',
+ amopopr => '@?(jsonb,jsonpath)', amopmethod => 'gin' },
+{ amopfamily => 'gin/jsonb_path_ops', amoplefttype => 'jsonb',
+ amoprighttype => 'jsonpath', amopstrategy => '16',
+ amopopr => '@@(jsonb,jsonpath)', amopmethod => 'gin' },
+
+# SP-GiST range_ops
+{ amopfamily => 'spgist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '1',
+ amopopr => '<<(anyrange,anyrange)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '2',
+ amopopr => '&<(anyrange,anyrange)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '3',
+ amopopr => '&&(anyrange,anyrange)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '4',
+ amopopr => '&>(anyrange,anyrange)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '5',
+ amopopr => '>>(anyrange,anyrange)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '6',
+ amopopr => '-|-(anyrange,anyrange)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '7',
+ amopopr => '@>(anyrange,anyrange)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '8',
+ amopopr => '<@(anyrange,anyrange)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyelement', amopstrategy => '16',
+ amopopr => '@>(anyrange,anyelement)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/range_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '18',
+ amopopr => '=(anyrange,anyrange)', amopmethod => 'spgist' },
+
+# SP-GiST box_ops
+{ amopfamily => 'spgist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '1', amopopr => '<<(box,box)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '2', amopopr => '&<(box,box)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '3', amopopr => '&&(box,box)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '4', amopopr => '&>(box,box)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '5', amopopr => '>>(box,box)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '6', amopopr => '~=(box,box)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '7', amopopr => '@>(box,box)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '8', amopopr => '<@(box,box)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '9', amopopr => '&<|(box,box)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '10', amopopr => '<<|(box,box)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '11', amopopr => '|>>(box,box)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/box_ops', amoplefttype => 'box', amoprighttype => 'box',
+ amopstrategy => '12', amopopr => '|&>(box,box)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/box_ops', amoplefttype => 'box',
+ amoprighttype => 'point', amopstrategy => '15', amoppurpose => 'o',
+ amopopr => '<->(box,point)', amopmethod => 'spgist',
+ amopsortfamily => 'btree/float_ops' },
+
+# SP-GiST poly_ops (supports polygons)
+{ amopfamily => 'spgist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '1',
+ amopopr => '<<(polygon,polygon)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '2',
+ amopopr => '&<(polygon,polygon)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '3',
+ amopopr => '&&(polygon,polygon)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '4',
+ amopopr => '&>(polygon,polygon)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '5',
+ amopopr => '>>(polygon,polygon)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '6',
+ amopopr => '~=(polygon,polygon)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '7',
+ amopopr => '@>(polygon,polygon)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '8',
+ amopopr => '<@(polygon,polygon)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '9',
+ amopopr => '&<|(polygon,polygon)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '10',
+ amopopr => '<<|(polygon,polygon)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '11',
+ amopopr => '|>>(polygon,polygon)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'polygon', amopstrategy => '12',
+ amopopr => '|&>(polygon,polygon)', amopmethod => 'spgist' },
+{ amopfamily => 'spgist/poly_ops', amoplefttype => 'polygon',
+ amoprighttype => 'point', amopstrategy => '15', amoppurpose => 'o',
+ amopopr => '<->(polygon,point)', amopmethod => 'spgist',
+ amopsortfamily => 'btree/float_ops' },
+
+# GiST inet_ops
+{ amopfamily => 'gist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '3', amopopr => '&&(inet,inet)',
+ amopmethod => 'gist' },
+{ amopfamily => 'gist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '18', amopopr => '=(inet,inet)',
+ amopmethod => 'gist' },
+{ amopfamily => 'gist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '19', amopopr => '<>(inet,inet)',
+ amopmethod => 'gist' },
+{ amopfamily => 'gist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '20', amopopr => '<(inet,inet)',
+ amopmethod => 'gist' },
+{ amopfamily => 'gist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '21', amopopr => '<=(inet,inet)',
+ amopmethod => 'gist' },
+{ amopfamily => 'gist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '22', amopopr => '>(inet,inet)',
+ amopmethod => 'gist' },
+{ amopfamily => 'gist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '23', amopopr => '>=(inet,inet)',
+ amopmethod => 'gist' },
+{ amopfamily => 'gist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '24', amopopr => '<<(inet,inet)',
+ amopmethod => 'gist' },
+{ amopfamily => 'gist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '25', amopopr => '<<=(inet,inet)',
+ amopmethod => 'gist' },
+{ amopfamily => 'gist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '26', amopopr => '>>(inet,inet)',
+ amopmethod => 'gist' },
+{ amopfamily => 'gist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '27', amopopr => '>>=(inet,inet)',
+ amopmethod => 'gist' },
+
+# SP-GiST inet_ops
+{ amopfamily => 'spgist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '3', amopopr => '&&(inet,inet)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '18', amopopr => '=(inet,inet)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '19', amopopr => '<>(inet,inet)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '20', amopopr => '<(inet,inet)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '21', amopopr => '<=(inet,inet)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '22', amopopr => '>(inet,inet)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '23', amopopr => '>=(inet,inet)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '24', amopopr => '<<(inet,inet)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '25', amopopr => '<<=(inet,inet)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '26', amopopr => '>>(inet,inet)',
+ amopmethod => 'spgist' },
+{ amopfamily => 'spgist/network_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '27', amopopr => '>>=(inet,inet)',
+ amopmethod => 'spgist' },
+
+# BRIN opclasses
+
+# minmax bytea
+{ amopfamily => 'brin/bytea_minmax_ops', amoplefttype => 'bytea',
+ amoprighttype => 'bytea', amopstrategy => '1', amopopr => '<(bytea,bytea)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/bytea_minmax_ops', amoplefttype => 'bytea',
+ amoprighttype => 'bytea', amopstrategy => '2', amopopr => '<=(bytea,bytea)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/bytea_minmax_ops', amoplefttype => 'bytea',
+ amoprighttype => 'bytea', amopstrategy => '3', amopopr => '=(bytea,bytea)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/bytea_minmax_ops', amoplefttype => 'bytea',
+ amoprighttype => 'bytea', amopstrategy => '4', amopopr => '>=(bytea,bytea)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/bytea_minmax_ops', amoplefttype => 'bytea',
+ amoprighttype => 'bytea', amopstrategy => '5', amopopr => '>(bytea,bytea)',
+ amopmethod => 'brin' },
+
+# minmax "char"
+{ amopfamily => 'brin/char_minmax_ops', amoplefttype => 'char',
+ amoprighttype => 'char', amopstrategy => '1', amopopr => '<(char,char)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/char_minmax_ops', amoplefttype => 'char',
+ amoprighttype => 'char', amopstrategy => '2', amopopr => '<=(char,char)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/char_minmax_ops', amoplefttype => 'char',
+ amoprighttype => 'char', amopstrategy => '3', amopopr => '=(char,char)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/char_minmax_ops', amoplefttype => 'char',
+ amoprighttype => 'char', amopstrategy => '4', amopopr => '>=(char,char)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/char_minmax_ops', amoplefttype => 'char',
+ amoprighttype => 'char', amopstrategy => '5', amopopr => '>(char,char)',
+ amopmethod => 'brin' },
+
+# minmax name
+{ amopfamily => 'brin/name_minmax_ops', amoplefttype => 'name',
+ amoprighttype => 'name', amopstrategy => '1', amopopr => '<(name,name)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/name_minmax_ops', amoplefttype => 'name',
+ amoprighttype => 'name', amopstrategy => '2', amopopr => '<=(name,name)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/name_minmax_ops', amoplefttype => 'name',
+ amoprighttype => 'name', amopstrategy => '3', amopopr => '=(name,name)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/name_minmax_ops', amoplefttype => 'name',
+ amoprighttype => 'name', amopstrategy => '4', amopopr => '>=(name,name)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/name_minmax_ops', amoplefttype => 'name',
+ amoprighttype => 'name', amopstrategy => '5', amopopr => '>(name,name)',
+ amopmethod => 'brin' },
+
+# minmax integer
+
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int8',
+ amoprighttype => 'int8', amopstrategy => '1', amopopr => '<(int8,int8)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int8',
+ amoprighttype => 'int8', amopstrategy => '2', amopopr => '<=(int8,int8)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int8',
+ amoprighttype => 'int8', amopstrategy => '3', amopopr => '=(int8,int8)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int8',
+ amoprighttype => 'int8', amopstrategy => '4', amopopr => '>=(int8,int8)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int8',
+ amoprighttype => 'int8', amopstrategy => '5', amopopr => '>(int8,int8)',
+ amopmethod => 'brin' },
+
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int8',
+ amoprighttype => 'int2', amopstrategy => '1', amopopr => '<(int8,int2)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int8',
+ amoprighttype => 'int2', amopstrategy => '2', amopopr => '<=(int8,int2)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int8',
+ amoprighttype => 'int2', amopstrategy => '3', amopopr => '=(int8,int2)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int8',
+ amoprighttype => 'int2', amopstrategy => '4', amopopr => '>=(int8,int2)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int8',
+ amoprighttype => 'int2', amopstrategy => '5', amopopr => '>(int8,int2)',
+ amopmethod => 'brin' },
+
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int8',
+ amoprighttype => 'int4', amopstrategy => '1', amopopr => '<(int8,int4)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int8',
+ amoprighttype => 'int4', amopstrategy => '2', amopopr => '<=(int8,int4)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int8',
+ amoprighttype => 'int4', amopstrategy => '3', amopopr => '=(int8,int4)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int8',
+ amoprighttype => 'int4', amopstrategy => '4', amopopr => '>=(int8,int4)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int8',
+ amoprighttype => 'int4', amopstrategy => '5', amopopr => '>(int8,int4)',
+ amopmethod => 'brin' },
+
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int2',
+ amoprighttype => 'int2', amopstrategy => '1', amopopr => '<(int2,int2)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int2',
+ amoprighttype => 'int2', amopstrategy => '2', amopopr => '<=(int2,int2)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int2',
+ amoprighttype => 'int2', amopstrategy => '3', amopopr => '=(int2,int2)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int2',
+ amoprighttype => 'int2', amopstrategy => '4', amopopr => '>=(int2,int2)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int2',
+ amoprighttype => 'int2', amopstrategy => '5', amopopr => '>(int2,int2)',
+ amopmethod => 'brin' },
+
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int2',
+ amoprighttype => 'int8', amopstrategy => '1', amopopr => '<(int2,int8)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int2',
+ amoprighttype => 'int8', amopstrategy => '2', amopopr => '<=(int2,int8)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int2',
+ amoprighttype => 'int8', amopstrategy => '3', amopopr => '=(int2,int8)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int2',
+ amoprighttype => 'int8', amopstrategy => '4', amopopr => '>=(int2,int8)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int2',
+ amoprighttype => 'int8', amopstrategy => '5', amopopr => '>(int2,int8)',
+ amopmethod => 'brin' },
+
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int2',
+ amoprighttype => 'int4', amopstrategy => '1', amopopr => '<(int2,int4)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int2',
+ amoprighttype => 'int4', amopstrategy => '2', amopopr => '<=(int2,int4)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int2',
+ amoprighttype => 'int4', amopstrategy => '3', amopopr => '=(int2,int4)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int2',
+ amoprighttype => 'int4', amopstrategy => '4', amopopr => '>=(int2,int4)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int2',
+ amoprighttype => 'int4', amopstrategy => '5', amopopr => '>(int2,int4)',
+ amopmethod => 'brin' },
+
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int4',
+ amoprighttype => 'int4', amopstrategy => '1', amopopr => '<(int4,int4)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int4',
+ amoprighttype => 'int4', amopstrategy => '2', amopopr => '<=(int4,int4)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int4',
+ amoprighttype => 'int4', amopstrategy => '3', amopopr => '=(int4,int4)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int4',
+ amoprighttype => 'int4', amopstrategy => '4', amopopr => '>=(int4,int4)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int4',
+ amoprighttype => 'int4', amopstrategy => '5', amopopr => '>(int4,int4)',
+ amopmethod => 'brin' },
+
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int4',
+ amoprighttype => 'int2', amopstrategy => '1', amopopr => '<(int4,int2)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int4',
+ amoprighttype => 'int2', amopstrategy => '2', amopopr => '<=(int4,int2)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int4',
+ amoprighttype => 'int2', amopstrategy => '3', amopopr => '=(int4,int2)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int4',
+ amoprighttype => 'int2', amopstrategy => '4', amopopr => '>=(int4,int2)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int4',
+ amoprighttype => 'int2', amopstrategy => '5', amopopr => '>(int4,int2)',
+ amopmethod => 'brin' },
+
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int4',
+ amoprighttype => 'int8', amopstrategy => '1', amopopr => '<(int4,int8)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int4',
+ amoprighttype => 'int8', amopstrategy => '2', amopopr => '<=(int4,int8)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int4',
+ amoprighttype => 'int8', amopstrategy => '3', amopopr => '=(int4,int8)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int4',
+ amoprighttype => 'int8', amopstrategy => '4', amopopr => '>=(int4,int8)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/integer_minmax_ops', amoplefttype => 'int4',
+ amoprighttype => 'int8', amopstrategy => '5', amopopr => '>(int4,int8)',
+ amopmethod => 'brin' },
+
+# minmax text
+{ amopfamily => 'brin/text_minmax_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '1', amopopr => '<(text,text)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/text_minmax_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '2', amopopr => '<=(text,text)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/text_minmax_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '3', amopopr => '=(text,text)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/text_minmax_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '4', amopopr => '>=(text,text)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/text_minmax_ops', amoplefttype => 'text',
+ amoprighttype => 'text', amopstrategy => '5', amopopr => '>(text,text)',
+ amopmethod => 'brin' },
+
+# minmax oid
+{ amopfamily => 'brin/oid_minmax_ops', amoplefttype => 'oid',
+ amoprighttype => 'oid', amopstrategy => '1', amopopr => '<(oid,oid)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/oid_minmax_ops', amoplefttype => 'oid',
+ amoprighttype => 'oid', amopstrategy => '2', amopopr => '<=(oid,oid)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/oid_minmax_ops', amoplefttype => 'oid',
+ amoprighttype => 'oid', amopstrategy => '3', amopopr => '=(oid,oid)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/oid_minmax_ops', amoplefttype => 'oid',
+ amoprighttype => 'oid', amopstrategy => '4', amopopr => '>=(oid,oid)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/oid_minmax_ops', amoplefttype => 'oid',
+ amoprighttype => 'oid', amopstrategy => '5', amopopr => '>(oid,oid)',
+ amopmethod => 'brin' },
+
+# minmax tid
+{ amopfamily => 'brin/tid_minmax_ops', amoplefttype => 'tid',
+ amoprighttype => 'tid', amopstrategy => '1', amopopr => '<(tid,tid)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/tid_minmax_ops', amoplefttype => 'tid',
+ amoprighttype => 'tid', amopstrategy => '2', amopopr => '<=(tid,tid)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/tid_minmax_ops', amoplefttype => 'tid',
+ amoprighttype => 'tid', amopstrategy => '3', amopopr => '=(tid,tid)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/tid_minmax_ops', amoplefttype => 'tid',
+ amoprighttype => 'tid', amopstrategy => '4', amopopr => '>=(tid,tid)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/tid_minmax_ops', amoplefttype => 'tid',
+ amoprighttype => 'tid', amopstrategy => '5', amopopr => '>(tid,tid)',
+ amopmethod => 'brin' },
+
+# minmax float (float4, float8)
+
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float4',
+ amoprighttype => 'float4', amopstrategy => '1', amopopr => '<(float4,float4)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float4',
+ amoprighttype => 'float4', amopstrategy => '2',
+ amopopr => '<=(float4,float4)', amopmethod => 'brin' },
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float4',
+ amoprighttype => 'float4', amopstrategy => '3', amopopr => '=(float4,float4)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float4',
+ amoprighttype => 'float4', amopstrategy => '4',
+ amopopr => '>=(float4,float4)', amopmethod => 'brin' },
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float4',
+ amoprighttype => 'float4', amopstrategy => '5', amopopr => '>(float4,float4)',
+ amopmethod => 'brin' },
+
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float4',
+ amoprighttype => 'float8', amopstrategy => '1', amopopr => '<(float4,float8)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float4',
+ amoprighttype => 'float8', amopstrategy => '2',
+ amopopr => '<=(float4,float8)', amopmethod => 'brin' },
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float4',
+ amoprighttype => 'float8', amopstrategy => '3', amopopr => '=(float4,float8)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float4',
+ amoprighttype => 'float8', amopstrategy => '4',
+ amopopr => '>=(float4,float8)', amopmethod => 'brin' },
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float4',
+ amoprighttype => 'float8', amopstrategy => '5', amopopr => '>(float4,float8)',
+ amopmethod => 'brin' },
+
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float8',
+ amoprighttype => 'float4', amopstrategy => '1', amopopr => '<(float8,float4)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float8',
+ amoprighttype => 'float4', amopstrategy => '2',
+ amopopr => '<=(float8,float4)', amopmethod => 'brin' },
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float8',
+ amoprighttype => 'float4', amopstrategy => '3', amopopr => '=(float8,float4)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float8',
+ amoprighttype => 'float4', amopstrategy => '4',
+ amopopr => '>=(float8,float4)', amopmethod => 'brin' },
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float8',
+ amoprighttype => 'float4', amopstrategy => '5', amopopr => '>(float8,float4)',
+ amopmethod => 'brin' },
+
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float8',
+ amoprighttype => 'float8', amopstrategy => '1', amopopr => '<(float8,float8)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float8',
+ amoprighttype => 'float8', amopstrategy => '2',
+ amopopr => '<=(float8,float8)', amopmethod => 'brin' },
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float8',
+ amoprighttype => 'float8', amopstrategy => '3', amopopr => '=(float8,float8)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float8',
+ amoprighttype => 'float8', amopstrategy => '4',
+ amopopr => '>=(float8,float8)', amopmethod => 'brin' },
+{ amopfamily => 'brin/float_minmax_ops', amoplefttype => 'float8',
+ amoprighttype => 'float8', amopstrategy => '5', amopopr => '>(float8,float8)',
+ amopmethod => 'brin' },
+
+# minmax macaddr
+{ amopfamily => 'brin/macaddr_minmax_ops', amoplefttype => 'macaddr',
+ amoprighttype => 'macaddr', amopstrategy => '1',
+ amopopr => '<(macaddr,macaddr)', amopmethod => 'brin' },
+{ amopfamily => 'brin/macaddr_minmax_ops', amoplefttype => 'macaddr',
+ amoprighttype => 'macaddr', amopstrategy => '2',
+ amopopr => '<=(macaddr,macaddr)', amopmethod => 'brin' },
+{ amopfamily => 'brin/macaddr_minmax_ops', amoplefttype => 'macaddr',
+ amoprighttype => 'macaddr', amopstrategy => '3',
+ amopopr => '=(macaddr,macaddr)', amopmethod => 'brin' },
+{ amopfamily => 'brin/macaddr_minmax_ops', amoplefttype => 'macaddr',
+ amoprighttype => 'macaddr', amopstrategy => '4',
+ amopopr => '>=(macaddr,macaddr)', amopmethod => 'brin' },
+{ amopfamily => 'brin/macaddr_minmax_ops', amoplefttype => 'macaddr',
+ amoprighttype => 'macaddr', amopstrategy => '5',
+ amopopr => '>(macaddr,macaddr)', amopmethod => 'brin' },
+
+# minmax macaddr8
+{ amopfamily => 'brin/macaddr8_minmax_ops', amoplefttype => 'macaddr8',
+ amoprighttype => 'macaddr8', amopstrategy => '1',
+ amopopr => '<(macaddr8,macaddr8)', amopmethod => 'brin' },
+{ amopfamily => 'brin/macaddr8_minmax_ops', amoplefttype => 'macaddr8',
+ amoprighttype => 'macaddr8', amopstrategy => '2',
+ amopopr => '<=(macaddr8,macaddr8)', amopmethod => 'brin' },
+{ amopfamily => 'brin/macaddr8_minmax_ops', amoplefttype => 'macaddr8',
+ amoprighttype => 'macaddr8', amopstrategy => '3',
+ amopopr => '=(macaddr8,macaddr8)', amopmethod => 'brin' },
+{ amopfamily => 'brin/macaddr8_minmax_ops', amoplefttype => 'macaddr8',
+ amoprighttype => 'macaddr8', amopstrategy => '4',
+ amopopr => '>=(macaddr8,macaddr8)', amopmethod => 'brin' },
+{ amopfamily => 'brin/macaddr8_minmax_ops', amoplefttype => 'macaddr8',
+ amoprighttype => 'macaddr8', amopstrategy => '5',
+ amopopr => '>(macaddr8,macaddr8)', amopmethod => 'brin' },
+
+# minmax inet
+{ amopfamily => 'brin/network_minmax_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '1', amopopr => '<(inet,inet)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/network_minmax_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '2', amopopr => '<=(inet,inet)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/network_minmax_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '3', amopopr => '=(inet,inet)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/network_minmax_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '4', amopopr => '>=(inet,inet)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/network_minmax_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '5', amopopr => '>(inet,inet)',
+ amopmethod => 'brin' },
+
+# inclusion inet
+{ amopfamily => 'brin/network_inclusion_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '3', amopopr => '&&(inet,inet)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/network_inclusion_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '7', amopopr => '>>=(inet,inet)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/network_inclusion_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '8', amopopr => '<<=(inet,inet)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/network_inclusion_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '18', amopopr => '=(inet,inet)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/network_inclusion_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '24', amopopr => '>>(inet,inet)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/network_inclusion_ops', amoplefttype => 'inet',
+ amoprighttype => 'inet', amopstrategy => '26', amopopr => '<<(inet,inet)',
+ amopmethod => 'brin' },
+
+# minmax character
+{ amopfamily => 'brin/bpchar_minmax_ops', amoplefttype => 'bpchar',
+ amoprighttype => 'bpchar', amopstrategy => '1', amopopr => '<(bpchar,bpchar)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/bpchar_minmax_ops', amoplefttype => 'bpchar',
+ amoprighttype => 'bpchar', amopstrategy => '2',
+ amopopr => '<=(bpchar,bpchar)', amopmethod => 'brin' },
+{ amopfamily => 'brin/bpchar_minmax_ops', amoplefttype => 'bpchar',
+ amoprighttype => 'bpchar', amopstrategy => '3', amopopr => '=(bpchar,bpchar)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/bpchar_minmax_ops', amoplefttype => 'bpchar',
+ amoprighttype => 'bpchar', amopstrategy => '4',
+ amopopr => '>=(bpchar,bpchar)', amopmethod => 'brin' },
+{ amopfamily => 'brin/bpchar_minmax_ops', amoplefttype => 'bpchar',
+ amoprighttype => 'bpchar', amopstrategy => '5', amopopr => '>(bpchar,bpchar)',
+ amopmethod => 'brin' },
+
+# minmax time without time zone
+{ amopfamily => 'brin/time_minmax_ops', amoplefttype => 'time',
+ amoprighttype => 'time', amopstrategy => '1', amopopr => '<(time,time)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/time_minmax_ops', amoplefttype => 'time',
+ amoprighttype => 'time', amopstrategy => '2', amopopr => '<=(time,time)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/time_minmax_ops', amoplefttype => 'time',
+ amoprighttype => 'time', amopstrategy => '3', amopopr => '=(time,time)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/time_minmax_ops', amoplefttype => 'time',
+ amoprighttype => 'time', amopstrategy => '4', amopopr => '>=(time,time)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/time_minmax_ops', amoplefttype => 'time',
+ amoprighttype => 'time', amopstrategy => '5', amopopr => '>(time,time)',
+ amopmethod => 'brin' },
+
+# minmax datetime (date, timestamp, timestamptz)
+
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamp', amopstrategy => '1',
+ amopopr => '<(timestamp,timestamp)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamp', amopstrategy => '2',
+ amopopr => '<=(timestamp,timestamp)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamp', amopstrategy => '3',
+ amopopr => '=(timestamp,timestamp)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamp', amopstrategy => '4',
+ amopopr => '>=(timestamp,timestamp)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamp', amopstrategy => '5',
+ amopopr => '>(timestamp,timestamp)', amopmethod => 'brin' },
+
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'date', amopstrategy => '1', amopopr => '<(timestamp,date)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'date', amopstrategy => '2', amopopr => '<=(timestamp,date)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'date', amopstrategy => '3', amopopr => '=(timestamp,date)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'date', amopstrategy => '4', amopopr => '>=(timestamp,date)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'date', amopstrategy => '5', amopopr => '>(timestamp,date)',
+ amopmethod => 'brin' },
+
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamptz', amopstrategy => '1',
+ amopopr => '<(timestamp,timestamptz)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamptz', amopstrategy => '2',
+ amopopr => '<=(timestamp,timestamptz)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamptz', amopstrategy => '3',
+ amopopr => '=(timestamp,timestamptz)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamptz', amopstrategy => '4',
+ amopopr => '>=(timestamp,timestamptz)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamp',
+ amoprighttype => 'timestamptz', amopstrategy => '5',
+ amopopr => '>(timestamp,timestamptz)', amopmethod => 'brin' },
+
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'date',
+ amoprighttype => 'date', amopstrategy => '1', amopopr => '<(date,date)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'date',
+ amoprighttype => 'date', amopstrategy => '2', amopopr => '<=(date,date)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'date',
+ amoprighttype => 'date', amopstrategy => '3', amopopr => '=(date,date)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'date',
+ amoprighttype => 'date', amopstrategy => '4', amopopr => '>=(date,date)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'date',
+ amoprighttype => 'date', amopstrategy => '5', amopopr => '>(date,date)',
+ amopmethod => 'brin' },
+
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamp', amopstrategy => '1',
+ amopopr => '<(date,timestamp)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamp', amopstrategy => '2',
+ amopopr => '<=(date,timestamp)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamp', amopstrategy => '3',
+ amopopr => '=(date,timestamp)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamp', amopstrategy => '4',
+ amopopr => '>=(date,timestamp)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamp', amopstrategy => '5',
+ amopopr => '>(date,timestamp)', amopmethod => 'brin' },
+
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamptz', amopstrategy => '1',
+ amopopr => '<(date,timestamptz)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamptz', amopstrategy => '2',
+ amopopr => '<=(date,timestamptz)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamptz', amopstrategy => '3',
+ amopopr => '=(date,timestamptz)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamptz', amopstrategy => '4',
+ amopopr => '>=(date,timestamptz)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'date',
+ amoprighttype => 'timestamptz', amopstrategy => '5',
+ amopopr => '>(date,timestamptz)', amopmethod => 'brin' },
+
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'date', amopstrategy => '1',
+ amopopr => '<(timestamptz,date)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'date', amopstrategy => '2',
+ amopopr => '<=(timestamptz,date)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'date', amopstrategy => '3',
+ amopopr => '=(timestamptz,date)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'date', amopstrategy => '4',
+ amopopr => '>=(timestamptz,date)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'date', amopstrategy => '5',
+ amopopr => '>(timestamptz,date)', amopmethod => 'brin' },
+
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamp', amopstrategy => '1',
+ amopopr => '<(timestamptz,timestamp)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamp', amopstrategy => '2',
+ amopopr => '<=(timestamptz,timestamp)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamp', amopstrategy => '3',
+ amopopr => '=(timestamptz,timestamp)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamp', amopstrategy => '4',
+ amopopr => '>=(timestamptz,timestamp)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamp', amopstrategy => '5',
+ amopopr => '>(timestamptz,timestamp)', amopmethod => 'brin' },
+
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamptz', amopstrategy => '1',
+ amopopr => '<(timestamptz,timestamptz)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamptz', amopstrategy => '2',
+ amopopr => '<=(timestamptz,timestamptz)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamptz', amopstrategy => '3',
+ amopopr => '=(timestamptz,timestamptz)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamptz', amopstrategy => '4',
+ amopopr => '>=(timestamptz,timestamptz)', amopmethod => 'brin' },
+{ amopfamily => 'brin/datetime_minmax_ops', amoplefttype => 'timestamptz',
+ amoprighttype => 'timestamptz', amopstrategy => '5',
+ amopopr => '>(timestamptz,timestamptz)', amopmethod => 'brin' },
+
+# minmax interval
+{ amopfamily => 'brin/interval_minmax_ops', amoplefttype => 'interval',
+ amoprighttype => 'interval', amopstrategy => '1',
+ amopopr => '<(interval,interval)', amopmethod => 'brin' },
+{ amopfamily => 'brin/interval_minmax_ops', amoplefttype => 'interval',
+ amoprighttype => 'interval', amopstrategy => '2',
+ amopopr => '<=(interval,interval)', amopmethod => 'brin' },
+{ amopfamily => 'brin/interval_minmax_ops', amoplefttype => 'interval',
+ amoprighttype => 'interval', amopstrategy => '3',
+ amopopr => '=(interval,interval)', amopmethod => 'brin' },
+{ amopfamily => 'brin/interval_minmax_ops', amoplefttype => 'interval',
+ amoprighttype => 'interval', amopstrategy => '4',
+ amopopr => '>=(interval,interval)', amopmethod => 'brin' },
+{ amopfamily => 'brin/interval_minmax_ops', amoplefttype => 'interval',
+ amoprighttype => 'interval', amopstrategy => '5',
+ amopopr => '>(interval,interval)', amopmethod => 'brin' },
+
+# minmax time with time zone
+{ amopfamily => 'brin/timetz_minmax_ops', amoplefttype => 'timetz',
+ amoprighttype => 'timetz', amopstrategy => '1', amopopr => '<(timetz,timetz)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/timetz_minmax_ops', amoplefttype => 'timetz',
+ amoprighttype => 'timetz', amopstrategy => '2',
+ amopopr => '<=(timetz,timetz)', amopmethod => 'brin' },
+{ amopfamily => 'brin/timetz_minmax_ops', amoplefttype => 'timetz',
+ amoprighttype => 'timetz', amopstrategy => '3', amopopr => '=(timetz,timetz)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/timetz_minmax_ops', amoplefttype => 'timetz',
+ amoprighttype => 'timetz', amopstrategy => '4',
+ amopopr => '>=(timetz,timetz)', amopmethod => 'brin' },
+{ amopfamily => 'brin/timetz_minmax_ops', amoplefttype => 'timetz',
+ amoprighttype => 'timetz', amopstrategy => '5', amopopr => '>(timetz,timetz)',
+ amopmethod => 'brin' },
+
+# minmax bit
+{ amopfamily => 'brin/bit_minmax_ops', amoplefttype => 'bit',
+ amoprighttype => 'bit', amopstrategy => '1', amopopr => '<(bit,bit)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/bit_minmax_ops', amoplefttype => 'bit',
+ amoprighttype => 'bit', amopstrategy => '2', amopopr => '<=(bit,bit)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/bit_minmax_ops', amoplefttype => 'bit',
+ amoprighttype => 'bit', amopstrategy => '3', amopopr => '=(bit,bit)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/bit_minmax_ops', amoplefttype => 'bit',
+ amoprighttype => 'bit', amopstrategy => '4', amopopr => '>=(bit,bit)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/bit_minmax_ops', amoplefttype => 'bit',
+ amoprighttype => 'bit', amopstrategy => '5', amopopr => '>(bit,bit)',
+ amopmethod => 'brin' },
+
+# minmax bit varying
+{ amopfamily => 'brin/varbit_minmax_ops', amoplefttype => 'varbit',
+ amoprighttype => 'varbit', amopstrategy => '1', amopopr => '<(varbit,varbit)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/varbit_minmax_ops', amoplefttype => 'varbit',
+ amoprighttype => 'varbit', amopstrategy => '2',
+ amopopr => '<=(varbit,varbit)', amopmethod => 'brin' },
+{ amopfamily => 'brin/varbit_minmax_ops', amoplefttype => 'varbit',
+ amoprighttype => 'varbit', amopstrategy => '3', amopopr => '=(varbit,varbit)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/varbit_minmax_ops', amoplefttype => 'varbit',
+ amoprighttype => 'varbit', amopstrategy => '4',
+ amopopr => '>=(varbit,varbit)', amopmethod => 'brin' },
+{ amopfamily => 'brin/varbit_minmax_ops', amoplefttype => 'varbit',
+ amoprighttype => 'varbit', amopstrategy => '5', amopopr => '>(varbit,varbit)',
+ amopmethod => 'brin' },
+
+# minmax numeric
+{ amopfamily => 'brin/numeric_minmax_ops', amoplefttype => 'numeric',
+ amoprighttype => 'numeric', amopstrategy => '1',
+ amopopr => '<(numeric,numeric)', amopmethod => 'brin' },
+{ amopfamily => 'brin/numeric_minmax_ops', amoplefttype => 'numeric',
+ amoprighttype => 'numeric', amopstrategy => '2',
+ amopopr => '<=(numeric,numeric)', amopmethod => 'brin' },
+{ amopfamily => 'brin/numeric_minmax_ops', amoplefttype => 'numeric',
+ amoprighttype => 'numeric', amopstrategy => '3',
+ amopopr => '=(numeric,numeric)', amopmethod => 'brin' },
+{ amopfamily => 'brin/numeric_minmax_ops', amoplefttype => 'numeric',
+ amoprighttype => 'numeric', amopstrategy => '4',
+ amopopr => '>=(numeric,numeric)', amopmethod => 'brin' },
+{ amopfamily => 'brin/numeric_minmax_ops', amoplefttype => 'numeric',
+ amoprighttype => 'numeric', amopstrategy => '5',
+ amopopr => '>(numeric,numeric)', amopmethod => 'brin' },
+
+# minmax uuid
+{ amopfamily => 'brin/uuid_minmax_ops', amoplefttype => 'uuid',
+ amoprighttype => 'uuid', amopstrategy => '1', amopopr => '<(uuid,uuid)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/uuid_minmax_ops', amoplefttype => 'uuid',
+ amoprighttype => 'uuid', amopstrategy => '2', amopopr => '<=(uuid,uuid)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/uuid_minmax_ops', amoplefttype => 'uuid',
+ amoprighttype => 'uuid', amopstrategy => '3', amopopr => '=(uuid,uuid)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/uuid_minmax_ops', amoplefttype => 'uuid',
+ amoprighttype => 'uuid', amopstrategy => '4', amopopr => '>=(uuid,uuid)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/uuid_minmax_ops', amoplefttype => 'uuid',
+ amoprighttype => 'uuid', amopstrategy => '5', amopopr => '>(uuid,uuid)',
+ amopmethod => 'brin' },
+
+# inclusion range types
+{ amopfamily => 'brin/range_inclusion_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '1',
+ amopopr => '<<(anyrange,anyrange)', amopmethod => 'brin' },
+{ amopfamily => 'brin/range_inclusion_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '2',
+ amopopr => '&<(anyrange,anyrange)', amopmethod => 'brin' },
+{ amopfamily => 'brin/range_inclusion_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '3',
+ amopopr => '&&(anyrange,anyrange)', amopmethod => 'brin' },
+{ amopfamily => 'brin/range_inclusion_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '4',
+ amopopr => '&>(anyrange,anyrange)', amopmethod => 'brin' },
+{ amopfamily => 'brin/range_inclusion_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '5',
+ amopopr => '>>(anyrange,anyrange)', amopmethod => 'brin' },
+{ amopfamily => 'brin/range_inclusion_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '7',
+ amopopr => '@>(anyrange,anyrange)', amopmethod => 'brin' },
+{ amopfamily => 'brin/range_inclusion_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '8',
+ amopopr => '<@(anyrange,anyrange)', amopmethod => 'brin' },
+{ amopfamily => 'brin/range_inclusion_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyelement', amopstrategy => '16',
+ amopopr => '@>(anyrange,anyelement)', amopmethod => 'brin' },
+{ amopfamily => 'brin/range_inclusion_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '17',
+ amopopr => '-|-(anyrange,anyrange)', amopmethod => 'brin' },
+{ amopfamily => 'brin/range_inclusion_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '18',
+ amopopr => '=(anyrange,anyrange)', amopmethod => 'brin' },
+{ amopfamily => 'brin/range_inclusion_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '20',
+ amopopr => '<(anyrange,anyrange)', amopmethod => 'brin' },
+{ amopfamily => 'brin/range_inclusion_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '21',
+ amopopr => '<=(anyrange,anyrange)', amopmethod => 'brin' },
+{ amopfamily => 'brin/range_inclusion_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '22',
+ amopopr => '>(anyrange,anyrange)', amopmethod => 'brin' },
+{ amopfamily => 'brin/range_inclusion_ops', amoplefttype => 'anyrange',
+ amoprighttype => 'anyrange', amopstrategy => '23',
+ amopopr => '>=(anyrange,anyrange)', amopmethod => 'brin' },
+
+# minmax pg_lsn
+{ amopfamily => 'brin/pg_lsn_minmax_ops', amoplefttype => 'pg_lsn',
+ amoprighttype => 'pg_lsn', amopstrategy => '1', amopopr => '<(pg_lsn,pg_lsn)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/pg_lsn_minmax_ops', amoplefttype => 'pg_lsn',
+ amoprighttype => 'pg_lsn', amopstrategy => '2',
+ amopopr => '<=(pg_lsn,pg_lsn)', amopmethod => 'brin' },
+{ amopfamily => 'brin/pg_lsn_minmax_ops', amoplefttype => 'pg_lsn',
+ amoprighttype => 'pg_lsn', amopstrategy => '3', amopopr => '=(pg_lsn,pg_lsn)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/pg_lsn_minmax_ops', amoplefttype => 'pg_lsn',
+ amoprighttype => 'pg_lsn', amopstrategy => '4',
+ amopopr => '>=(pg_lsn,pg_lsn)', amopmethod => 'brin' },
+{ amopfamily => 'brin/pg_lsn_minmax_ops', amoplefttype => 'pg_lsn',
+ amoprighttype => 'pg_lsn', amopstrategy => '5', amopopr => '>(pg_lsn,pg_lsn)',
+ amopmethod => 'brin' },
+
+# inclusion box
+{ amopfamily => 'brin/box_inclusion_ops', amoplefttype => 'box',
+ amoprighttype => 'box', amopstrategy => '1', amopopr => '<<(box,box)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/box_inclusion_ops', amoplefttype => 'box',
+ amoprighttype => 'box', amopstrategy => '2', amopopr => '&<(box,box)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/box_inclusion_ops', amoplefttype => 'box',
+ amoprighttype => 'box', amopstrategy => '3', amopopr => '&&(box,box)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/box_inclusion_ops', amoplefttype => 'box',
+ amoprighttype => 'box', amopstrategy => '4', amopopr => '&>(box,box)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/box_inclusion_ops', amoplefttype => 'box',
+ amoprighttype => 'box', amopstrategy => '5', amopopr => '>>(box,box)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/box_inclusion_ops', amoplefttype => 'box',
+ amoprighttype => 'box', amopstrategy => '6', amopopr => '~=(box,box)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/box_inclusion_ops', amoplefttype => 'box',
+ amoprighttype => 'box', amopstrategy => '7', amopopr => '@>(box,box)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/box_inclusion_ops', amoplefttype => 'box',
+ amoprighttype => 'box', amopstrategy => '8', amopopr => '<@(box,box)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/box_inclusion_ops', amoplefttype => 'box',
+ amoprighttype => 'box', amopstrategy => '9', amopopr => '&<|(box,box)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/box_inclusion_ops', amoplefttype => 'box',
+ amoprighttype => 'box', amopstrategy => '10', amopopr => '<<|(box,box)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/box_inclusion_ops', amoplefttype => 'box',
+ amoprighttype => 'box', amopstrategy => '11', amopopr => '|>>(box,box)',
+ amopmethod => 'brin' },
+{ amopfamily => 'brin/box_inclusion_ops', amoplefttype => 'box',
+ amoprighttype => 'box', amopstrategy => '12', amopopr => '|&>(box,box)',
+ amopmethod => 'brin' },
+
+# we could, but choose not to, supply entries for strategies 13 and 14
+
+{ amopfamily => 'brin/box_inclusion_ops', amoplefttype => 'box',
+ amoprighttype => 'point', amopstrategy => '7', amopopr => '@>(box,point)',
+ amopmethod => 'brin' },
+
+]
diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h
new file mode 100644
index 0000000..81a7eb6
--- /dev/null
+++ b/src/include/catalog/pg_amop.h
@@ -0,0 +1,98 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_amop.h
+ * definition of the "access method operator" system catalog (pg_amop)
+ *
+ * The amop table identifies the operators associated with each index operator
+ * family and operator class (classes are subsets of families). An associated
+ * operator can be either a search operator or an ordering operator, as
+ * identified by amoppurpose.
+ *
+ * The primary key for this table is <amopfamily, amoplefttype, amoprighttype,
+ * amopstrategy>. amoplefttype and amoprighttype are just copies of the
+ * operator's oprleft/oprright, ie its declared input data types. The
+ * "default" operators for a particular opclass within the family are those
+ * with amoplefttype = amoprighttype = opclass's opcintype. An opfamily may
+ * also contain other operators, typically cross-data-type operators. All the
+ * operators within a family are supposed to be compatible, in a way that is
+ * defined by each individual index AM.
+ *
+ * We also keep a unique index on <amopopr, amoppurpose, amopfamily>, so that
+ * we can use a syscache to quickly answer questions of the form "is this
+ * operator in this opfamily, and if so what are its semantics with respect to
+ * the family?" This implies that the same operator cannot be listed for
+ * multiple strategy numbers within a single opfamily, with the exception that
+ * it's possible to list it for both search and ordering purposes (with
+ * different strategy numbers for the two purposes).
+ *
+ * amopmethod is a copy of the owning opfamily's opfmethod field. This is an
+ * intentional denormalization of the catalogs to buy lookup speed.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_amop.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_AMOP_H
+#define PG_AMOP_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_amop_d.h"
+
+/* ----------------
+ * pg_amop definition. cpp turns this into
+ * typedef struct FormData_pg_amop
+ * ----------------
+ */
+CATALOG(pg_amop,2602,AccessMethodOperatorRelationId)
+{
+ Oid oid; /* oid */
+
+ /* the index opfamily this entry is for */
+ Oid amopfamily BKI_LOOKUP(pg_opfamily);
+
+ /* operator's left input data type */
+ Oid amoplefttype BKI_LOOKUP(pg_type);
+
+ /* operator's right input data type */
+ Oid amoprighttype BKI_LOOKUP(pg_type);
+
+ /* operator strategy number */
+ int16 amopstrategy;
+
+ /* is operator for 's'earch or 'o'rdering? */
+ char amoppurpose BKI_DEFAULT(s);
+
+ /* the operator's pg_operator OID */
+ Oid amopopr BKI_LOOKUP(pg_operator);
+
+ /* the index access method this entry is for */
+ Oid amopmethod BKI_LOOKUP(pg_am);
+
+ /* ordering opfamily OID, or 0 if search op */
+ Oid amopsortfamily BKI_DEFAULT(0) BKI_LOOKUP(pg_opfamily);
+} FormData_pg_amop;
+
+/* ----------------
+ * Form_pg_amop corresponds to a pointer to a tuple with
+ * the format of pg_amop relation.
+ * ----------------
+ */
+typedef FormData_pg_amop *Form_pg_amop;
+
+#ifdef EXPOSE_TO_CLIENT_CODE
+
+/* allowed values of amoppurpose: */
+#define AMOP_SEARCH 's' /* operator is for search */
+#define AMOP_ORDER 'o' /* operator is for ordering */
+
+#endif /* EXPOSE_TO_CLIENT_CODE */
+
+#endif /* PG_AMOP_H */
diff --git a/src/include/catalog/pg_amproc.dat b/src/include/catalog/pg_amproc.dat
new file mode 100644
index 0000000..37b5808
--- /dev/null
+++ b/src/include/catalog/pg_amproc.dat
@@ -0,0 +1,1316 @@
+#----------------------------------------------------------------------
+#
+# pg_amproc.dat
+# Initial contents of the pg_amproc system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_amproc.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+# btree
+{ amprocfamily => 'btree/array_ops', amproclefttype => 'anyarray',
+ amprocrighttype => 'anyarray', amprocnum => '1', amproc => 'btarraycmp' },
+{ amprocfamily => 'btree/bit_ops', amproclefttype => 'bit',
+ amprocrighttype => 'bit', amprocnum => '1', amproc => 'bitcmp' },
+{ amprocfamily => 'btree/bit_ops', amproclefttype => 'bit',
+ amprocrighttype => 'bit', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/bool_ops', amproclefttype => 'bool',
+ amprocrighttype => 'bool', amprocnum => '1', amproc => 'btboolcmp' },
+{ amprocfamily => 'btree/bool_ops', amproclefttype => 'bool',
+ amprocrighttype => 'bool', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/bpchar_ops', amproclefttype => 'bpchar',
+ amprocrighttype => 'bpchar', amprocnum => '1', amproc => 'bpcharcmp' },
+{ amprocfamily => 'btree/bpchar_ops', amproclefttype => 'bpchar',
+ amprocrighttype => 'bpchar', amprocnum => '2',
+ amproc => 'bpchar_sortsupport' },
+{ amprocfamily => 'btree/bpchar_ops', amproclefttype => 'bpchar',
+ amprocrighttype => 'bpchar', amprocnum => '4',
+ amproc => 'btvarstrequalimage' },
+{ amprocfamily => 'btree/bytea_ops', amproclefttype => 'bytea',
+ amprocrighttype => 'bytea', amprocnum => '1', amproc => 'byteacmp' },
+{ amprocfamily => 'btree/bytea_ops', amproclefttype => 'bytea',
+ amprocrighttype => 'bytea', amprocnum => '2', amproc => 'bytea_sortsupport' },
+{ amprocfamily => 'btree/bytea_ops', amproclefttype => 'bytea',
+ amprocrighttype => 'bytea', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/char_ops', amproclefttype => 'char',
+ amprocrighttype => 'char', amprocnum => '1', amproc => 'btcharcmp' },
+{ amprocfamily => 'btree/char_ops', amproclefttype => 'char',
+ amprocrighttype => 'char', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'date',
+ amprocrighttype => 'date', amprocnum => '1', amproc => 'date_cmp' },
+{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'date',
+ amprocrighttype => 'date', amprocnum => '2', amproc => 'date_sortsupport' },
+{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'date',
+ amprocrighttype => 'date', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'date',
+ amprocrighttype => 'timestamp', amprocnum => '1',
+ amproc => 'date_cmp_timestamp' },
+{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'date',
+ amprocrighttype => 'timestamptz', amprocnum => '1',
+ amproc => 'date_cmp_timestamptz' },
+{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'timestamp', amprocnum => '1', amproc => 'timestamp_cmp' },
+{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'timestamp', amprocnum => '2',
+ amproc => 'timestamp_sortsupport' },
+{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'timestamp', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'date', amprocnum => '1', amproc => 'timestamp_cmp_date' },
+{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'timestamptz', amprocnum => '1',
+ amproc => 'timestamp_cmp_timestamptz' },
+{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'timestamptz', amprocnum => '1',
+ amproc => 'timestamptz_cmp' },
+{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'timestamptz', amprocnum => '2',
+ amproc => 'timestamp_sortsupport' },
+{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'timestamptz', amprocnum => '4',
+ amproc => 'btequalimage' },
+{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'date', amprocnum => '1',
+ amproc => 'timestamptz_cmp_date' },
+{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'timestamp', amprocnum => '1',
+ amproc => 'timestamptz_cmp_timestamp' },
+{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'date',
+ amprocrighttype => 'interval', amprocnum => '3',
+ amproc => 'in_range(date,date,interval,bool,bool)' },
+{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'interval', amprocnum => '3',
+ amproc => 'in_range(timestamp,timestamp,interval,bool,bool)' },
+{ amprocfamily => 'btree/datetime_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'interval', amprocnum => '3',
+ amproc => 'in_range(timestamptz,timestamptz,interval,bool,bool)' },
+{ amprocfamily => 'btree/float_ops', amproclefttype => 'float4',
+ amprocrighttype => 'float4', amprocnum => '1', amproc => 'btfloat4cmp' },
+{ amprocfamily => 'btree/float_ops', amproclefttype => 'float4',
+ amprocrighttype => 'float4', amprocnum => '2',
+ amproc => 'btfloat4sortsupport' },
+{ amprocfamily => 'btree/float_ops', amproclefttype => 'float4',
+ amprocrighttype => 'float8', amprocnum => '1', amproc => 'btfloat48cmp' },
+{ amprocfamily => 'btree/float_ops', amproclefttype => 'float8',
+ amprocrighttype => 'float8', amprocnum => '1', amproc => 'btfloat8cmp' },
+{ amprocfamily => 'btree/float_ops', amproclefttype => 'float8',
+ amprocrighttype => 'float8', amprocnum => '2',
+ amproc => 'btfloat8sortsupport' },
+{ amprocfamily => 'btree/float_ops', amproclefttype => 'float8',
+ amprocrighttype => 'float4', amprocnum => '1', amproc => 'btfloat84cmp' },
+{ amprocfamily => 'btree/float_ops', amproclefttype => 'float8',
+ amprocrighttype => 'float8', amprocnum => '3',
+ amproc => 'in_range(float8,float8,float8,bool,bool)' },
+{ amprocfamily => 'btree/float_ops', amproclefttype => 'float4',
+ amprocrighttype => 'float8', amprocnum => '3',
+ amproc => 'in_range(float4,float4,float8,bool,bool)' },
+{ amprocfamily => 'btree/network_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '1', amproc => 'network_cmp' },
+{ amprocfamily => 'btree/network_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '2',
+ amproc => 'network_sortsupport' },
+{ amprocfamily => 'btree/network_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int2', amprocnum => '1', amproc => 'btint2cmp' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int2', amprocnum => '2', amproc => 'btint2sortsupport' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int2', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int4', amprocnum => '1', amproc => 'btint24cmp' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int8', amprocnum => '1', amproc => 'btint28cmp' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int8', amprocnum => '3',
+ amproc => 'in_range(int2,int2,int8,bool,bool)' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int4', amprocnum => '3',
+ amproc => 'in_range(int2,int2,int4,bool,bool)' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int2', amprocnum => '3',
+ amproc => 'in_range(int2,int2,int2,bool,bool)' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int4', amprocnum => '1', amproc => 'btint4cmp' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int4', amprocnum => '2', amproc => 'btint4sortsupport' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int4', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int8', amprocnum => '1', amproc => 'btint48cmp' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int2', amprocnum => '1', amproc => 'btint42cmp' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int8', amprocnum => '3',
+ amproc => 'in_range(int4,int4,int8,bool,bool)' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int4', amprocnum => '3',
+ amproc => 'in_range(int4,int4,int4,bool,bool)' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int2', amprocnum => '3',
+ amproc => 'in_range(int4,int4,int2,bool,bool)' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int8', amprocnum => '1', amproc => 'btint8cmp' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int8', amprocnum => '2', amproc => 'btint8sortsupport' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int8', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int4', amprocnum => '1', amproc => 'btint84cmp' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int2', amprocnum => '1', amproc => 'btint82cmp' },
+{ amprocfamily => 'btree/integer_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int8', amprocnum => '3',
+ amproc => 'in_range(int8,int8,int8,bool,bool)' },
+{ amprocfamily => 'btree/interval_ops', amproclefttype => 'interval',
+ amprocrighttype => 'interval', amprocnum => '1', amproc => 'interval_cmp' },
+{ amprocfamily => 'btree/interval_ops', amproclefttype => 'interval',
+ amprocrighttype => 'interval', amprocnum => '3',
+ amproc => 'in_range(interval,interval,interval,bool,bool)' },
+{ amprocfamily => 'btree/interval_ops', amproclefttype => 'interval',
+ amprocrighttype => 'interval', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/macaddr_ops', amproclefttype => 'macaddr',
+ amprocrighttype => 'macaddr', amprocnum => '1', amproc => 'macaddr_cmp' },
+{ amprocfamily => 'btree/macaddr_ops', amproclefttype => 'macaddr',
+ amprocrighttype => 'macaddr', amprocnum => '2',
+ amproc => 'macaddr_sortsupport' },
+{ amprocfamily => 'btree/macaddr_ops', amproclefttype => 'macaddr',
+ amprocrighttype => 'macaddr', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/numeric_ops', amproclefttype => 'numeric',
+ amprocrighttype => 'numeric', amprocnum => '1', amproc => 'numeric_cmp' },
+{ amprocfamily => 'btree/numeric_ops', amproclefttype => 'numeric',
+ amprocrighttype => 'numeric', amprocnum => '2',
+ amproc => 'numeric_sortsupport' },
+{ amprocfamily => 'btree/numeric_ops', amproclefttype => 'numeric',
+ amprocrighttype => 'numeric', amprocnum => '3',
+ amproc => 'in_range(numeric,numeric,numeric,bool,bool)' },
+{ amprocfamily => 'btree/oid_ops', amproclefttype => 'oid',
+ amprocrighttype => 'oid', amprocnum => '1', amproc => 'btoidcmp' },
+{ amprocfamily => 'btree/oid_ops', amproclefttype => 'oid',
+ amprocrighttype => 'oid', amprocnum => '2', amproc => 'btoidsortsupport' },
+{ amprocfamily => 'btree/oid_ops', amproclefttype => 'oid',
+ amprocrighttype => 'oid', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/oidvector_ops', amproclefttype => 'oidvector',
+ amprocrighttype => 'oidvector', amprocnum => '1',
+ amproc => 'btoidvectorcmp' },
+{ amprocfamily => 'btree/oidvector_ops', amproclefttype => 'oidvector',
+ amprocrighttype => 'oidvector', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/text_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '1', amproc => 'bttextcmp' },
+{ amprocfamily => 'btree/text_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '2', amproc => 'bttextsortsupport' },
+{ amprocfamily => 'btree/text_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '4', amproc => 'btvarstrequalimage' },
+{ amprocfamily => 'btree/text_ops', amproclefttype => 'name',
+ amprocrighttype => 'name', amprocnum => '1', amproc => 'btnamecmp' },
+{ amprocfamily => 'btree/text_ops', amproclefttype => 'name',
+ amprocrighttype => 'name', amprocnum => '2', amproc => 'btnamesortsupport' },
+{ amprocfamily => 'btree/text_ops', amproclefttype => 'name',
+ amprocrighttype => 'name', amprocnum => '4', amproc => 'btvarstrequalimage' },
+{ amprocfamily => 'btree/text_ops', amproclefttype => 'name',
+ amprocrighttype => 'text', amprocnum => '1', amproc => 'btnametextcmp' },
+{ amprocfamily => 'btree/text_ops', amproclefttype => 'text',
+ amprocrighttype => 'name', amprocnum => '1', amproc => 'bttextnamecmp' },
+{ amprocfamily => 'btree/time_ops', amproclefttype => 'time',
+ amprocrighttype => 'time', amprocnum => '1', amproc => 'time_cmp' },
+{ amprocfamily => 'btree/time_ops', amproclefttype => 'time',
+ amprocrighttype => 'time', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/time_ops', amproclefttype => 'time',
+ amprocrighttype => 'interval', amprocnum => '3',
+ amproc => 'in_range(time,time,interval,bool,bool)' },
+{ amprocfamily => 'btree/timetz_ops', amproclefttype => 'timetz',
+ amprocrighttype => 'timetz', amprocnum => '1', amproc => 'timetz_cmp' },
+{ amprocfamily => 'btree/timetz_ops', amproclefttype => 'timetz',
+ amprocrighttype => 'timetz', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/timetz_ops', amproclefttype => 'timetz',
+ amprocrighttype => 'interval', amprocnum => '3',
+ amproc => 'in_range(timetz,timetz,interval,bool,bool)' },
+{ amprocfamily => 'btree/varbit_ops', amproclefttype => 'varbit',
+ amprocrighttype => 'varbit', amprocnum => '1', amproc => 'varbitcmp' },
+{ amprocfamily => 'btree/varbit_ops', amproclefttype => 'varbit',
+ amprocrighttype => 'varbit', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/text_pattern_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '1', amproc => 'bttext_pattern_cmp' },
+{ amprocfamily => 'btree/text_pattern_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '2',
+ amproc => 'bttext_pattern_sortsupport' },
+{ amprocfamily => 'btree/text_pattern_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/bpchar_pattern_ops', amproclefttype => 'bpchar',
+ amprocrighttype => 'bpchar', amprocnum => '1',
+ amproc => 'btbpchar_pattern_cmp' },
+{ amprocfamily => 'btree/bpchar_pattern_ops', amproclefttype => 'bpchar',
+ amprocrighttype => 'bpchar', amprocnum => '2',
+ amproc => 'btbpchar_pattern_sortsupport' },
+{ amprocfamily => 'btree/bpchar_pattern_ops', amproclefttype => 'bpchar',
+ amprocrighttype => 'bpchar', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/money_ops', amproclefttype => 'money',
+ amprocrighttype => 'money', amprocnum => '1', amproc => 'cash_cmp' },
+{ amprocfamily => 'btree/money_ops', amproclefttype => 'money',
+ amprocrighttype => 'money', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/tid_ops', amproclefttype => 'tid',
+ amprocrighttype => 'tid', amprocnum => '1', amproc => 'bttidcmp' },
+{ amprocfamily => 'btree/tid_ops', amproclefttype => 'tid',
+ amprocrighttype => 'tid', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/uuid_ops', amproclefttype => 'uuid',
+ amprocrighttype => 'uuid', amprocnum => '1', amproc => 'uuid_cmp' },
+{ amprocfamily => 'btree/uuid_ops', amproclefttype => 'uuid',
+ amprocrighttype => 'uuid', amprocnum => '2', amproc => 'uuid_sortsupport' },
+{ amprocfamily => 'btree/uuid_ops', amproclefttype => 'uuid',
+ amprocrighttype => 'uuid', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/record_ops', amproclefttype => 'record',
+ amprocrighttype => 'record', amprocnum => '1', amproc => 'btrecordcmp' },
+{ amprocfamily => 'btree/record_image_ops', amproclefttype => 'record',
+ amprocrighttype => 'record', amprocnum => '1', amproc => 'btrecordimagecmp' },
+{ amprocfamily => 'btree/pg_lsn_ops', amproclefttype => 'pg_lsn',
+ amprocrighttype => 'pg_lsn', amprocnum => '1', amproc => 'pg_lsn_cmp' },
+{ amprocfamily => 'btree/pg_lsn_ops', amproclefttype => 'pg_lsn',
+ amprocrighttype => 'pg_lsn', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/macaddr8_ops', amproclefttype => 'macaddr8',
+ amprocrighttype => 'macaddr8', amprocnum => '1', amproc => 'macaddr8_cmp' },
+{ amprocfamily => 'btree/macaddr8_ops', amproclefttype => 'macaddr8',
+ amprocrighttype => 'macaddr8', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/enum_ops', amproclefttype => 'anyenum',
+ amprocrighttype => 'anyenum', amprocnum => '1', amproc => 'enum_cmp' },
+{ amprocfamily => 'btree/enum_ops', amproclefttype => 'anyenum',
+ amprocrighttype => 'anyenum', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/tsvector_ops', amproclefttype => 'tsvector',
+ amprocrighttype => 'tsvector', amprocnum => '1', amproc => 'tsvector_cmp' },
+{ amprocfamily => 'btree/tsquery_ops', amproclefttype => 'tsquery',
+ amprocrighttype => 'tsquery', amprocnum => '1', amproc => 'tsquery_cmp' },
+{ amprocfamily => 'btree/range_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '1', amproc => 'range_cmp' },
+{ amprocfamily => 'btree/jsonb_ops', amproclefttype => 'jsonb',
+ amprocrighttype => 'jsonb', amprocnum => '1', amproc => 'jsonb_cmp' },
+{ amprocfamily => 'btree/xid8_ops', amproclefttype => 'xid8',
+ amprocrighttype => 'xid8', amprocnum => '1', amproc => 'xid8cmp' },
+{ amprocfamily => 'btree/xid8_ops', amproclefttype => 'xid8',
+ amprocrighttype => 'xid8', amprocnum => '4', amproc => 'btequalimage' },
+
+# hash
+{ amprocfamily => 'hash/bpchar_ops', amproclefttype => 'bpchar',
+ amprocrighttype => 'bpchar', amprocnum => '1', amproc => 'hashbpchar' },
+{ amprocfamily => 'hash/bpchar_ops', amproclefttype => 'bpchar',
+ amprocrighttype => 'bpchar', amprocnum => '2',
+ amproc => 'hashbpcharextended' },
+{ amprocfamily => 'hash/char_ops', amproclefttype => 'char',
+ amprocrighttype => 'char', amprocnum => '1', amproc => 'hashchar' },
+{ amprocfamily => 'hash/char_ops', amproclefttype => 'char',
+ amprocrighttype => 'char', amprocnum => '2', amproc => 'hashcharextended' },
+{ amprocfamily => 'hash/date_ops', amproclefttype => 'date',
+ amprocrighttype => 'date', amprocnum => '1', amproc => 'hashint4' },
+{ amprocfamily => 'hash/date_ops', amproclefttype => 'date',
+ amprocrighttype => 'date', amprocnum => '2', amproc => 'hashint4extended' },
+{ amprocfamily => 'hash/array_ops', amproclefttype => 'anyarray',
+ amprocrighttype => 'anyarray', amprocnum => '1', amproc => 'hash_array' },
+{ amprocfamily => 'hash/array_ops', amproclefttype => 'anyarray',
+ amprocrighttype => 'anyarray', amprocnum => '2',
+ amproc => 'hash_array_extended' },
+{ amprocfamily => 'hash/float_ops', amproclefttype => 'float4',
+ amprocrighttype => 'float4', amprocnum => '1', amproc => 'hashfloat4' },
+{ amprocfamily => 'hash/float_ops', amproclefttype => 'float4',
+ amprocrighttype => 'float4', amprocnum => '2',
+ amproc => 'hashfloat4extended' },
+{ amprocfamily => 'hash/float_ops', amproclefttype => 'float8',
+ amprocrighttype => 'float8', amprocnum => '1', amproc => 'hashfloat8' },
+{ amprocfamily => 'hash/float_ops', amproclefttype => 'float8',
+ amprocrighttype => 'float8', amprocnum => '2',
+ amproc => 'hashfloat8extended' },
+{ amprocfamily => 'hash/network_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '1', amproc => 'hashinet' },
+{ amprocfamily => 'hash/network_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '2', amproc => 'hashinetextended' },
+{ amprocfamily => 'hash/integer_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int2', amprocnum => '1', amproc => 'hashint2' },
+{ amprocfamily => 'hash/integer_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int2', amprocnum => '2', amproc => 'hashint2extended' },
+{ amprocfamily => 'hash/integer_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int4', amprocnum => '1', amproc => 'hashint4' },
+{ amprocfamily => 'hash/integer_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int4', amprocnum => '2', amproc => 'hashint4extended' },
+{ amprocfamily => 'hash/integer_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int8', amprocnum => '1', amproc => 'hashint8' },
+{ amprocfamily => 'hash/integer_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int8', amprocnum => '2', amproc => 'hashint8extended' },
+{ amprocfamily => 'hash/interval_ops', amproclefttype => 'interval',
+ amprocrighttype => 'interval', amprocnum => '1', amproc => 'interval_hash' },
+{ amprocfamily => 'hash/interval_ops', amproclefttype => 'interval',
+ amprocrighttype => 'interval', amprocnum => '2',
+ amproc => 'interval_hash_extended' },
+{ amprocfamily => 'hash/macaddr_ops', amproclefttype => 'macaddr',
+ amprocrighttype => 'macaddr', amprocnum => '1', amproc => 'hashmacaddr' },
+{ amprocfamily => 'hash/macaddr_ops', amproclefttype => 'macaddr',
+ amprocrighttype => 'macaddr', amprocnum => '2',
+ amproc => 'hashmacaddrextended' },
+{ amprocfamily => 'hash/oid_ops', amproclefttype => 'oid',
+ amprocrighttype => 'oid', amprocnum => '1', amproc => 'hashoid' },
+{ amprocfamily => 'hash/oid_ops', amproclefttype => 'oid',
+ amprocrighttype => 'oid', amprocnum => '2', amproc => 'hashoidextended' },
+{ amprocfamily => 'hash/oidvector_ops', amproclefttype => 'oidvector',
+ amprocrighttype => 'oidvector', amprocnum => '1', amproc => 'hashoidvector' },
+{ amprocfamily => 'hash/oidvector_ops', amproclefttype => 'oidvector',
+ amprocrighttype => 'oidvector', amprocnum => '2',
+ amproc => 'hashoidvectorextended' },
+{ amprocfamily => 'hash/text_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '1', amproc => 'hashtext' },
+{ amprocfamily => 'hash/text_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '2', amproc => 'hashtextextended' },
+{ amprocfamily => 'hash/text_ops', amproclefttype => 'name',
+ amprocrighttype => 'name', amprocnum => '1', amproc => 'hashname' },
+{ amprocfamily => 'hash/text_ops', amproclefttype => 'name',
+ amprocrighttype => 'name', amprocnum => '2', amproc => 'hashnameextended' },
+{ amprocfamily => 'hash/time_ops', amproclefttype => 'time',
+ amprocrighttype => 'time', amprocnum => '1', amproc => 'time_hash' },
+{ amprocfamily => 'hash/time_ops', amproclefttype => 'time',
+ amprocrighttype => 'time', amprocnum => '2', amproc => 'time_hash_extended' },
+{ amprocfamily => 'hash/numeric_ops', amproclefttype => 'numeric',
+ amprocrighttype => 'numeric', amprocnum => '1', amproc => 'hash_numeric' },
+{ amprocfamily => 'hash/numeric_ops', amproclefttype => 'numeric',
+ amprocrighttype => 'numeric', amprocnum => '2',
+ amproc => 'hash_numeric_extended' },
+{ amprocfamily => 'hash/timestamptz_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'timestamptz', amprocnum => '1',
+ amproc => 'timestamp_hash' },
+{ amprocfamily => 'hash/timestamptz_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'timestamptz', amprocnum => '2',
+ amproc => 'timestamp_hash_extended' },
+{ amprocfamily => 'hash/timetz_ops', amproclefttype => 'timetz',
+ amprocrighttype => 'timetz', amprocnum => '1', amproc => 'timetz_hash' },
+{ amprocfamily => 'hash/timetz_ops', amproclefttype => 'timetz',
+ amprocrighttype => 'timetz', amprocnum => '2',
+ amproc => 'timetz_hash_extended' },
+{ amprocfamily => 'hash/timestamp_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'timestamp', amprocnum => '1',
+ amproc => 'timestamp_hash' },
+{ amprocfamily => 'hash/timestamp_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'timestamp', amprocnum => '2',
+ amproc => 'timestamp_hash_extended' },
+{ amprocfamily => 'hash/bool_ops', amproclefttype => 'bool',
+ amprocrighttype => 'bool', amprocnum => '1', amproc => 'hashchar' },
+{ amprocfamily => 'hash/bool_ops', amproclefttype => 'bool',
+ amprocrighttype => 'bool', amprocnum => '2', amproc => 'hashcharextended' },
+{ amprocfamily => 'hash/bytea_ops', amproclefttype => 'bytea',
+ amprocrighttype => 'bytea', amprocnum => '1', amproc => 'hashvarlena' },
+{ amprocfamily => 'hash/bytea_ops', amproclefttype => 'bytea',
+ amprocrighttype => 'bytea', amprocnum => '2',
+ amproc => 'hashvarlenaextended' },
+{ amprocfamily => 'hash/xid_ops', amproclefttype => 'xid',
+ amprocrighttype => 'xid', amprocnum => '1', amproc => 'hashint4' },
+{ amprocfamily => 'hash/xid_ops', amproclefttype => 'xid',
+ amprocrighttype => 'xid', amprocnum => '2', amproc => 'hashint4extended' },
+{ amprocfamily => 'hash/xid8_ops', amproclefttype => 'xid8',
+ amprocrighttype => 'xid8', amprocnum => '1', amproc => 'hashint8' },
+{ amprocfamily => 'hash/xid8_ops', amproclefttype => 'xid8',
+ amprocrighttype => 'xid8', amprocnum => '2', amproc => 'hashint8extended' },
+{ amprocfamily => 'hash/cid_ops', amproclefttype => 'cid',
+ amprocrighttype => 'cid', amprocnum => '1', amproc => 'hashint4' },
+{ amprocfamily => 'hash/cid_ops', amproclefttype => 'cid',
+ amprocrighttype => 'cid', amprocnum => '2', amproc => 'hashint4extended' },
+{ amprocfamily => 'hash/tid_ops', amproclefttype => 'tid',
+ amprocrighttype => 'tid', amprocnum => '1', amproc => 'hashtid' },
+{ amprocfamily => 'hash/tid_ops', amproclefttype => 'tid',
+ amprocrighttype => 'tid', amprocnum => '2', amproc => 'hashtidextended' },
+{ amprocfamily => 'hash/text_pattern_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '1', amproc => 'hashtext' },
+{ amprocfamily => 'hash/text_pattern_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '2', amproc => 'hashtextextended' },
+{ amprocfamily => 'hash/bpchar_pattern_ops', amproclefttype => 'bpchar',
+ amprocrighttype => 'bpchar', amprocnum => '1', amproc => 'hashbpchar' },
+{ amprocfamily => 'hash/bpchar_pattern_ops', amproclefttype => 'bpchar',
+ amprocrighttype => 'bpchar', amprocnum => '2',
+ amproc => 'hashbpcharextended' },
+{ amprocfamily => 'hash/aclitem_ops', amproclefttype => 'aclitem',
+ amprocrighttype => 'aclitem', amprocnum => '1', amproc => 'hash_aclitem' },
+{ amprocfamily => 'hash/aclitem_ops', amproclefttype => 'aclitem',
+ amprocrighttype => 'aclitem', amprocnum => '2',
+ amproc => 'hash_aclitem_extended' },
+{ amprocfamily => 'hash/uuid_ops', amproclefttype => 'uuid',
+ amprocrighttype => 'uuid', amprocnum => '1', amproc => 'uuid_hash' },
+{ amprocfamily => 'hash/uuid_ops', amproclefttype => 'uuid',
+ amprocrighttype => 'uuid', amprocnum => '2', amproc => 'uuid_hash_extended' },
+{ amprocfamily => 'hash/pg_lsn_ops', amproclefttype => 'pg_lsn',
+ amprocrighttype => 'pg_lsn', amprocnum => '1', amproc => 'pg_lsn_hash' },
+{ amprocfamily => 'hash/pg_lsn_ops', amproclefttype => 'pg_lsn',
+ amprocrighttype => 'pg_lsn', amprocnum => '2',
+ amproc => 'pg_lsn_hash_extended' },
+{ amprocfamily => 'hash/macaddr8_ops', amproclefttype => 'macaddr8',
+ amprocrighttype => 'macaddr8', amprocnum => '1', amproc => 'hashmacaddr8' },
+{ amprocfamily => 'hash/macaddr8_ops', amproclefttype => 'macaddr8',
+ amprocrighttype => 'macaddr8', amprocnum => '2',
+ amproc => 'hashmacaddr8extended' },
+{ amprocfamily => 'hash/enum_ops', amproclefttype => 'anyenum',
+ amprocrighttype => 'anyenum', amprocnum => '1', amproc => 'hashenum' },
+{ amprocfamily => 'hash/enum_ops', amproclefttype => 'anyenum',
+ amprocrighttype => 'anyenum', amprocnum => '2',
+ amproc => 'hashenumextended' },
+{ amprocfamily => 'hash/range_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '1', amproc => 'hash_range' },
+{ amprocfamily => 'hash/range_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '2',
+ amproc => 'hash_range_extended' },
+{ amprocfamily => 'hash/jsonb_ops', amproclefttype => 'jsonb',
+ amprocrighttype => 'jsonb', amprocnum => '1', amproc => 'jsonb_hash' },
+{ amprocfamily => 'hash/jsonb_ops', amproclefttype => 'jsonb',
+ amprocrighttype => 'jsonb', amprocnum => '2',
+ amproc => 'jsonb_hash_extended' },
+
+# gist
+{ amprocfamily => 'gist/point_ops', amproclefttype => 'point',
+ amprocrighttype => 'point', amprocnum => '1',
+ amproc => 'gist_point_consistent' },
+{ amprocfamily => 'gist/point_ops', amproclefttype => 'point',
+ amprocrighttype => 'point', amprocnum => '2', amproc => 'gist_box_union' },
+{ amprocfamily => 'gist/point_ops', amproclefttype => 'point',
+ amprocrighttype => 'point', amprocnum => '3',
+ amproc => 'gist_point_compress' },
+{ amprocfamily => 'gist/point_ops', amproclefttype => 'point',
+ amprocrighttype => 'point', amprocnum => '5', amproc => 'gist_box_penalty' },
+{ amprocfamily => 'gist/point_ops', amproclefttype => 'point',
+ amprocrighttype => 'point', amprocnum => '6',
+ amproc => 'gist_box_picksplit' },
+{ amprocfamily => 'gist/point_ops', amproclefttype => 'point',
+ amprocrighttype => 'point', amprocnum => '7', amproc => 'gist_box_same' },
+{ amprocfamily => 'gist/point_ops', amproclefttype => 'point',
+ amprocrighttype => 'point', amprocnum => '8',
+ amproc => 'gist_point_distance' },
+{ amprocfamily => 'gist/point_ops', amproclefttype => 'point',
+ amprocrighttype => 'point', amprocnum => '9', amproc => 'gist_point_fetch' },
+{ amprocfamily => 'gist/box_ops', amproclefttype => 'box',
+ amprocrighttype => 'box', amprocnum => '1', amproc => 'gist_box_consistent' },
+{ amprocfamily => 'gist/box_ops', amproclefttype => 'box',
+ amprocrighttype => 'box', amprocnum => '2', amproc => 'gist_box_union' },
+{ amprocfamily => 'gist/box_ops', amproclefttype => 'box',
+ amprocrighttype => 'box', amprocnum => '5', amproc => 'gist_box_penalty' },
+{ amprocfamily => 'gist/box_ops', amproclefttype => 'box',
+ amprocrighttype => 'box', amprocnum => '6', amproc => 'gist_box_picksplit' },
+{ amprocfamily => 'gist/box_ops', amproclefttype => 'box',
+ amprocrighttype => 'box', amprocnum => '7', amproc => 'gist_box_same' },
+{ amprocfamily => 'gist/box_ops', amproclefttype => 'box',
+ amprocrighttype => 'box', amprocnum => '8', amproc => 'gist_box_distance' },
+{ amprocfamily => 'gist/poly_ops', amproclefttype => 'polygon',
+ amprocrighttype => 'polygon', amprocnum => '1',
+ amproc => 'gist_poly_consistent' },
+{ amprocfamily => 'gist/poly_ops', amproclefttype => 'polygon',
+ amprocrighttype => 'polygon', amprocnum => '2', amproc => 'gist_box_union' },
+{ amprocfamily => 'gist/poly_ops', amproclefttype => 'polygon',
+ amprocrighttype => 'polygon', amprocnum => '3',
+ amproc => 'gist_poly_compress' },
+{ amprocfamily => 'gist/poly_ops', amproclefttype => 'polygon',
+ amprocrighttype => 'polygon', amprocnum => '5',
+ amproc => 'gist_box_penalty' },
+{ amprocfamily => 'gist/poly_ops', amproclefttype => 'polygon',
+ amprocrighttype => 'polygon', amprocnum => '6',
+ amproc => 'gist_box_picksplit' },
+{ amprocfamily => 'gist/poly_ops', amproclefttype => 'polygon',
+ amprocrighttype => 'polygon', amprocnum => '7', amproc => 'gist_box_same' },
+{ amprocfamily => 'gist/poly_ops', amproclefttype => 'polygon',
+ amprocrighttype => 'polygon', amprocnum => '8',
+ amproc => 'gist_poly_distance' },
+{ amprocfamily => 'gist/circle_ops', amproclefttype => 'circle',
+ amprocrighttype => 'circle', amprocnum => '1',
+ amproc => 'gist_circle_consistent' },
+{ amprocfamily => 'gist/circle_ops', amproclefttype => 'circle',
+ amprocrighttype => 'circle', amprocnum => '2', amproc => 'gist_box_union' },
+{ amprocfamily => 'gist/circle_ops', amproclefttype => 'circle',
+ amprocrighttype => 'circle', amprocnum => '3',
+ amproc => 'gist_circle_compress' },
+{ amprocfamily => 'gist/circle_ops', amproclefttype => 'circle',
+ amprocrighttype => 'circle', amprocnum => '5', amproc => 'gist_box_penalty' },
+{ amprocfamily => 'gist/circle_ops', amproclefttype => 'circle',
+ amprocrighttype => 'circle', amprocnum => '6',
+ amproc => 'gist_box_picksplit' },
+{ amprocfamily => 'gist/circle_ops', amproclefttype => 'circle',
+ amprocrighttype => 'circle', amprocnum => '7', amproc => 'gist_box_same' },
+{ amprocfamily => 'gist/circle_ops', amproclefttype => 'circle',
+ amprocrighttype => 'circle', amprocnum => '8',
+ amproc => 'gist_circle_distance' },
+{ amprocfamily => 'gist/tsvector_ops', amproclefttype => 'tsvector',
+ amprocrighttype => 'tsvector', amprocnum => '1',
+ amproc => 'gtsvector_consistent(internal,tsvector,int2,oid,internal)' },
+{ amprocfamily => 'gist/tsvector_ops', amproclefttype => 'tsvector',
+ amprocrighttype => 'tsvector', amprocnum => '2',
+ amproc => 'gtsvector_union' },
+{ amprocfamily => 'gist/tsvector_ops', amproclefttype => 'tsvector',
+ amprocrighttype => 'tsvector', amprocnum => '3',
+ amproc => 'gtsvector_compress' },
+{ amprocfamily => 'gist/tsvector_ops', amproclefttype => 'tsvector',
+ amprocrighttype => 'tsvector', amprocnum => '4',
+ amproc => 'gtsvector_decompress' },
+{ amprocfamily => 'gist/tsvector_ops', amproclefttype => 'tsvector',
+ amprocrighttype => 'tsvector', amprocnum => '5',
+ amproc => 'gtsvector_penalty' },
+{ amprocfamily => 'gist/tsvector_ops', amproclefttype => 'tsvector',
+ amprocrighttype => 'tsvector', amprocnum => '6',
+ amproc => 'gtsvector_picksplit' },
+{ amprocfamily => 'gist/tsvector_ops', amproclefttype => 'tsvector',
+ amprocrighttype => 'tsvector', amprocnum => '7', amproc => 'gtsvector_same' },
+{ amprocfamily => 'gist/tsvector_ops', amproclefttype => 'tsvector',
+ amprocrighttype => 'tsvector', amprocnum => '10',
+ amproc => 'gtsvector_options' },
+{ amprocfamily => 'gist/tsquery_ops', amproclefttype => 'tsquery',
+ amprocrighttype => 'tsquery', amprocnum => '1',
+ amproc => 'gtsquery_consistent(internal,tsquery,int2,oid,internal)' },
+{ amprocfamily => 'gist/tsquery_ops', amproclefttype => 'tsquery',
+ amprocrighttype => 'tsquery', amprocnum => '2', amproc => 'gtsquery_union' },
+{ amprocfamily => 'gist/tsquery_ops', amproclefttype => 'tsquery',
+ amprocrighttype => 'tsquery', amprocnum => '3',
+ amproc => 'gtsquery_compress' },
+{ amprocfamily => 'gist/tsquery_ops', amproclefttype => 'tsquery',
+ amprocrighttype => 'tsquery', amprocnum => '5',
+ amproc => 'gtsquery_penalty' },
+{ amprocfamily => 'gist/tsquery_ops', amproclefttype => 'tsquery',
+ amprocrighttype => 'tsquery', amprocnum => '6',
+ amproc => 'gtsquery_picksplit' },
+{ amprocfamily => 'gist/tsquery_ops', amproclefttype => 'tsquery',
+ amprocrighttype => 'tsquery', amprocnum => '7', amproc => 'gtsquery_same' },
+{ amprocfamily => 'gist/range_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '1',
+ amproc => 'range_gist_consistent' },
+{ amprocfamily => 'gist/range_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '2',
+ amproc => 'range_gist_union' },
+{ amprocfamily => 'gist/range_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '5',
+ amproc => 'range_gist_penalty' },
+{ amprocfamily => 'gist/range_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '6',
+ amproc => 'range_gist_picksplit' },
+{ amprocfamily => 'gist/range_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '7',
+ amproc => 'range_gist_same' },
+{ amprocfamily => 'gist/network_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '1',
+ amproc => 'inet_gist_consistent' },
+{ amprocfamily => 'gist/network_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '2', amproc => 'inet_gist_union' },
+{ amprocfamily => 'gist/network_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '3', amproc => 'inet_gist_compress' },
+{ amprocfamily => 'gist/network_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '5', amproc => 'inet_gist_penalty' },
+{ amprocfamily => 'gist/network_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '6',
+ amproc => 'inet_gist_picksplit' },
+{ amprocfamily => 'gist/network_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '7', amproc => 'inet_gist_same' },
+{ amprocfamily => 'gist/network_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '9', amproc => 'inet_gist_fetch' },
+
+# gin
+{ amprocfamily => 'gin/array_ops', amproclefttype => 'anyarray',
+ amprocrighttype => 'anyarray', amprocnum => '2',
+ amproc => 'ginarrayextract(anyarray,internal,internal)' },
+{ amprocfamily => 'gin/array_ops', amproclefttype => 'anyarray',
+ amprocrighttype => 'anyarray', amprocnum => '3',
+ amproc => 'ginqueryarrayextract' },
+{ amprocfamily => 'gin/array_ops', amproclefttype => 'anyarray',
+ amprocrighttype => 'anyarray', amprocnum => '4',
+ amproc => 'ginarrayconsistent' },
+{ amprocfamily => 'gin/array_ops', amproclefttype => 'anyarray',
+ amprocrighttype => 'anyarray', amprocnum => '6',
+ amproc => 'ginarraytriconsistent' },
+{ amprocfamily => 'gin/tsvector_ops', amproclefttype => 'tsvector',
+ amprocrighttype => 'tsvector', amprocnum => '1',
+ amproc => 'gin_cmp_tslexeme' },
+{ amprocfamily => 'gin/tsvector_ops', amproclefttype => 'tsvector',
+ amprocrighttype => 'tsvector', amprocnum => '2',
+ amproc => 'gin_extract_tsvector(tsvector,internal,internal)' },
+{ amprocfamily => 'gin/tsvector_ops', amproclefttype => 'tsvector',
+ amprocrighttype => 'tsvector', amprocnum => '3',
+ amproc => 'gin_extract_tsquery(tsvector,internal,int2,internal,internal,internal,internal)' },
+{ amprocfamily => 'gin/tsvector_ops', amproclefttype => 'tsvector',
+ amprocrighttype => 'tsvector', amprocnum => '4',
+ amproc => 'gin_tsquery_consistent(internal,int2,tsvector,int4,internal,internal,internal,internal)' },
+{ amprocfamily => 'gin/tsvector_ops', amproclefttype => 'tsvector',
+ amprocrighttype => 'tsvector', amprocnum => '5', amproc => 'gin_cmp_prefix' },
+{ amprocfamily => 'gin/tsvector_ops', amproclefttype => 'tsvector',
+ amprocrighttype => 'tsvector', amprocnum => '6',
+ amproc => 'gin_tsquery_triconsistent' },
+{ amprocfamily => 'gin/jsonb_ops', amproclefttype => 'jsonb',
+ amprocrighttype => 'jsonb', amprocnum => '1', amproc => 'gin_compare_jsonb' },
+{ amprocfamily => 'gin/jsonb_ops', amproclefttype => 'jsonb',
+ amprocrighttype => 'jsonb', amprocnum => '2', amproc => 'gin_extract_jsonb' },
+{ amprocfamily => 'gin/jsonb_ops', amproclefttype => 'jsonb',
+ amprocrighttype => 'jsonb', amprocnum => '3',
+ amproc => 'gin_extract_jsonb_query' },
+{ amprocfamily => 'gin/jsonb_ops', amproclefttype => 'jsonb',
+ amprocrighttype => 'jsonb', amprocnum => '4',
+ amproc => 'gin_consistent_jsonb' },
+{ amprocfamily => 'gin/jsonb_ops', amproclefttype => 'jsonb',
+ amprocrighttype => 'jsonb', amprocnum => '6',
+ amproc => 'gin_triconsistent_jsonb' },
+{ amprocfamily => 'gin/jsonb_path_ops', amproclefttype => 'jsonb',
+ amprocrighttype => 'jsonb', amprocnum => '1', amproc => 'btint4cmp' },
+{ amprocfamily => 'gin/jsonb_path_ops', amproclefttype => 'jsonb',
+ amprocrighttype => 'jsonb', amprocnum => '2',
+ amproc => 'gin_extract_jsonb_path' },
+{ amprocfamily => 'gin/jsonb_path_ops', amproclefttype => 'jsonb',
+ amprocrighttype => 'jsonb', amprocnum => '3',
+ amproc => 'gin_extract_jsonb_query_path' },
+{ amprocfamily => 'gin/jsonb_path_ops', amproclefttype => 'jsonb',
+ amprocrighttype => 'jsonb', amprocnum => '4',
+ amproc => 'gin_consistent_jsonb_path' },
+{ amprocfamily => 'gin/jsonb_path_ops', amproclefttype => 'jsonb',
+ amprocrighttype => 'jsonb', amprocnum => '6',
+ amproc => 'gin_triconsistent_jsonb_path' },
+
+# sp-gist
+{ amprocfamily => 'spgist/range_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '1',
+ amproc => 'spg_range_quad_config' },
+{ amprocfamily => 'spgist/range_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '2',
+ amproc => 'spg_range_quad_choose' },
+{ amprocfamily => 'spgist/range_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '3',
+ amproc => 'spg_range_quad_picksplit' },
+{ amprocfamily => 'spgist/range_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '4',
+ amproc => 'spg_range_quad_inner_consistent' },
+{ amprocfamily => 'spgist/range_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '5',
+ amproc => 'spg_range_quad_leaf_consistent' },
+{ amprocfamily => 'spgist/network_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '1', amproc => 'inet_spg_config' },
+{ amprocfamily => 'spgist/network_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '2', amproc => 'inet_spg_choose' },
+{ amprocfamily => 'spgist/network_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '3', amproc => 'inet_spg_picksplit' },
+{ amprocfamily => 'spgist/network_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '4',
+ amproc => 'inet_spg_inner_consistent' },
+{ amprocfamily => 'spgist/network_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '5',
+ amproc => 'inet_spg_leaf_consistent' },
+{ amprocfamily => 'spgist/quad_point_ops', amproclefttype => 'point',
+ amprocrighttype => 'point', amprocnum => '1', amproc => 'spg_quad_config' },
+{ amprocfamily => 'spgist/quad_point_ops', amproclefttype => 'point',
+ amprocrighttype => 'point', amprocnum => '2', amproc => 'spg_quad_choose' },
+{ amprocfamily => 'spgist/quad_point_ops', amproclefttype => 'point',
+ amprocrighttype => 'point', amprocnum => '3',
+ amproc => 'spg_quad_picksplit' },
+{ amprocfamily => 'spgist/quad_point_ops', amproclefttype => 'point',
+ amprocrighttype => 'point', amprocnum => '4',
+ amproc => 'spg_quad_inner_consistent' },
+{ amprocfamily => 'spgist/quad_point_ops', amproclefttype => 'point',
+ amprocrighttype => 'point', amprocnum => '5',
+ amproc => 'spg_quad_leaf_consistent' },
+{ amprocfamily => 'spgist/kd_point_ops', amproclefttype => 'point',
+ amprocrighttype => 'point', amprocnum => '1', amproc => 'spg_kd_config' },
+{ amprocfamily => 'spgist/kd_point_ops', amproclefttype => 'point',
+ amprocrighttype => 'point', amprocnum => '2', amproc => 'spg_kd_choose' },
+{ amprocfamily => 'spgist/kd_point_ops', amproclefttype => 'point',
+ amprocrighttype => 'point', amprocnum => '3', amproc => 'spg_kd_picksplit' },
+{ amprocfamily => 'spgist/kd_point_ops', amproclefttype => 'point',
+ amprocrighttype => 'point', amprocnum => '4',
+ amproc => 'spg_kd_inner_consistent' },
+{ amprocfamily => 'spgist/kd_point_ops', amproclefttype => 'point',
+ amprocrighttype => 'point', amprocnum => '5',
+ amproc => 'spg_quad_leaf_consistent' },
+{ amprocfamily => 'spgist/text_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '1', amproc => 'spg_text_config' },
+{ amprocfamily => 'spgist/text_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '2', amproc => 'spg_text_choose' },
+{ amprocfamily => 'spgist/text_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '3', amproc => 'spg_text_picksplit' },
+{ amprocfamily => 'spgist/text_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '4',
+ amproc => 'spg_text_inner_consistent' },
+{ amprocfamily => 'spgist/text_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '5',
+ amproc => 'spg_text_leaf_consistent' },
+{ amprocfamily => 'spgist/box_ops', amproclefttype => 'box',
+ amprocrighttype => 'box', amprocnum => '1', amproc => 'spg_box_quad_config' },
+{ amprocfamily => 'spgist/box_ops', amproclefttype => 'box',
+ amprocrighttype => 'box', amprocnum => '2', amproc => 'spg_box_quad_choose' },
+{ amprocfamily => 'spgist/box_ops', amproclefttype => 'box',
+ amprocrighttype => 'box', amprocnum => '3',
+ amproc => 'spg_box_quad_picksplit' },
+{ amprocfamily => 'spgist/box_ops', amproclefttype => 'box',
+ amprocrighttype => 'box', amprocnum => '4',
+ amproc => 'spg_box_quad_inner_consistent' },
+{ amprocfamily => 'spgist/box_ops', amproclefttype => 'box',
+ amprocrighttype => 'box', amprocnum => '5',
+ amproc => 'spg_box_quad_leaf_consistent' },
+{ amprocfamily => 'spgist/poly_ops', amproclefttype => 'polygon',
+ amprocrighttype => 'polygon', amprocnum => '1',
+ amproc => 'spg_bbox_quad_config' },
+{ amprocfamily => 'spgist/poly_ops', amproclefttype => 'polygon',
+ amprocrighttype => 'polygon', amprocnum => '2',
+ amproc => 'spg_box_quad_choose' },
+{ amprocfamily => 'spgist/poly_ops', amproclefttype => 'polygon',
+ amprocrighttype => 'polygon', amprocnum => '3',
+ amproc => 'spg_box_quad_picksplit' },
+{ amprocfamily => 'spgist/poly_ops', amproclefttype => 'polygon',
+ amprocrighttype => 'polygon', amprocnum => '4',
+ amproc => 'spg_box_quad_inner_consistent' },
+{ amprocfamily => 'spgist/poly_ops', amproclefttype => 'polygon',
+ amprocrighttype => 'polygon', amprocnum => '5',
+ amproc => 'spg_box_quad_leaf_consistent' },
+{ amprocfamily => 'spgist/poly_ops', amproclefttype => 'polygon',
+ amprocrighttype => 'polygon', amprocnum => '6',
+ amproc => 'spg_poly_quad_compress' },
+
+# BRIN opclasses
+
+# minmax bytea
+{ amprocfamily => 'brin/bytea_minmax_ops', amproclefttype => 'bytea',
+ amprocrighttype => 'bytea', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/bytea_minmax_ops', amproclefttype => 'bytea',
+ amprocrighttype => 'bytea', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/bytea_minmax_ops', amproclefttype => 'bytea',
+ amprocrighttype => 'bytea', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/bytea_minmax_ops', amproclefttype => 'bytea',
+ amprocrighttype => 'bytea', amprocnum => '4', amproc => 'brin_minmax_union' },
+
+# minmax "char"
+{ amprocfamily => 'brin/char_minmax_ops', amproclefttype => 'char',
+ amprocrighttype => 'char', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/char_minmax_ops', amproclefttype => 'char',
+ amprocrighttype => 'char', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/char_minmax_ops', amproclefttype => 'char',
+ amprocrighttype => 'char', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/char_minmax_ops', amproclefttype => 'char',
+ amprocrighttype => 'char', amprocnum => '4', amproc => 'brin_minmax_union' },
+
+# minmax name
+{ amprocfamily => 'brin/name_minmax_ops', amproclefttype => 'name',
+ amprocrighttype => 'name', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/name_minmax_ops', amproclefttype => 'name',
+ amprocrighttype => 'name', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/name_minmax_ops', amproclefttype => 'name',
+ amprocrighttype => 'name', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/name_minmax_ops', amproclefttype => 'name',
+ amprocrighttype => 'name', amprocnum => '4', amproc => 'brin_minmax_union' },
+
+# minmax integer: int2, int4, int8
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int8', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int8', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int8', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int8', amprocnum => '4', amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int2', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int2', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int2', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int2', amprocnum => '4', amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int4', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int4', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int4', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int8',
+ amprocrighttype => 'int4', amprocnum => '4', amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int2', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int2', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int2', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int2', amprocnum => '4', amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int8', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int8', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int8', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int8', amprocnum => '4', amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int4', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int4', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int4', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int2',
+ amprocrighttype => 'int4', amprocnum => '4', amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int4', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int4', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int4', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int4', amprocnum => '4', amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int8', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int8', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int8', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int8', amprocnum => '4', amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int2', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int2', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int2', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/integer_minmax_ops', amproclefttype => 'int4',
+ amprocrighttype => 'int2', amprocnum => '4', amproc => 'brin_minmax_union' },
+
+# minmax text
+{ amprocfamily => 'brin/text_minmax_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/text_minmax_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/text_minmax_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/text_minmax_ops', amproclefttype => 'text',
+ amprocrighttype => 'text', amprocnum => '4', amproc => 'brin_minmax_union' },
+
+# minmax oid
+{ amprocfamily => 'brin/oid_minmax_ops', amproclefttype => 'oid',
+ amprocrighttype => 'oid', amprocnum => '1', amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/oid_minmax_ops', amproclefttype => 'oid',
+ amprocrighttype => 'oid', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/oid_minmax_ops', amproclefttype => 'oid',
+ amprocrighttype => 'oid', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/oid_minmax_ops', amproclefttype => 'oid',
+ amprocrighttype => 'oid', amprocnum => '4', amproc => 'brin_minmax_union' },
+
+# minmax tid
+{ amprocfamily => 'brin/tid_minmax_ops', amproclefttype => 'tid',
+ amprocrighttype => 'tid', amprocnum => '1', amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/tid_minmax_ops', amproclefttype => 'tid',
+ amprocrighttype => 'tid', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/tid_minmax_ops', amproclefttype => 'tid',
+ amprocrighttype => 'tid', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/tid_minmax_ops', amproclefttype => 'tid',
+ amprocrighttype => 'tid', amprocnum => '4', amproc => 'brin_minmax_union' },
+
+# minmax float
+{ amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float4',
+ amprocrighttype => 'float4', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float4',
+ amprocrighttype => 'float4', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float4',
+ amprocrighttype => 'float4', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float4',
+ amprocrighttype => 'float4', amprocnum => '4',
+ amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float4',
+ amprocrighttype => 'float8', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float4',
+ amprocrighttype => 'float8', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float4',
+ amprocrighttype => 'float8', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float4',
+ amprocrighttype => 'float8', amprocnum => '4',
+ amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float8',
+ amprocrighttype => 'float8', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float8',
+ amprocrighttype => 'float8', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float8',
+ amprocrighttype => 'float8', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float8',
+ amprocrighttype => 'float8', amprocnum => '4',
+ amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float8',
+ amprocrighttype => 'float4', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float8',
+ amprocrighttype => 'float4', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float8',
+ amprocrighttype => 'float4', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/float_minmax_ops', amproclefttype => 'float8',
+ amprocrighttype => 'float4', amprocnum => '4',
+ amproc => 'brin_minmax_union' },
+
+# minmax macaddr
+{ amprocfamily => 'brin/macaddr_minmax_ops', amproclefttype => 'macaddr',
+ amprocrighttype => 'macaddr', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/macaddr_minmax_ops', amproclefttype => 'macaddr',
+ amprocrighttype => 'macaddr', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/macaddr_minmax_ops', amproclefttype => 'macaddr',
+ amprocrighttype => 'macaddr', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/macaddr_minmax_ops', amproclefttype => 'macaddr',
+ amprocrighttype => 'macaddr', amprocnum => '4',
+ amproc => 'brin_minmax_union' },
+
+# minmax macaddr8
+{ amprocfamily => 'brin/macaddr8_minmax_ops', amproclefttype => 'macaddr8',
+ amprocrighttype => 'macaddr8', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/macaddr8_minmax_ops', amproclefttype => 'macaddr8',
+ amprocrighttype => 'macaddr8', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/macaddr8_minmax_ops', amproclefttype => 'macaddr8',
+ amprocrighttype => 'macaddr8', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/macaddr8_minmax_ops', amproclefttype => 'macaddr8',
+ amprocrighttype => 'macaddr8', amprocnum => '4',
+ amproc => 'brin_minmax_union' },
+
+# minmax inet
+{ amprocfamily => 'brin/network_minmax_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/network_minmax_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/network_minmax_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/network_minmax_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '4', amproc => 'brin_minmax_union' },
+
+# inclusion inet
+{ amprocfamily => 'brin/network_inclusion_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '1',
+ amproc => 'brin_inclusion_opcinfo' },
+{ amprocfamily => 'brin/network_inclusion_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '2',
+ amproc => 'brin_inclusion_add_value' },
+{ amprocfamily => 'brin/network_inclusion_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '3',
+ amproc => 'brin_inclusion_consistent' },
+{ amprocfamily => 'brin/network_inclusion_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '4',
+ amproc => 'brin_inclusion_union' },
+{ amprocfamily => 'brin/network_inclusion_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '11', amproc => 'inet_merge' },
+{ amprocfamily => 'brin/network_inclusion_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '12', amproc => 'inet_same_family' },
+{ amprocfamily => 'brin/network_inclusion_ops', amproclefttype => 'inet',
+ amprocrighttype => 'inet', amprocnum => '13', amproc => 'network_supeq' },
+
+# minmax character
+{ amprocfamily => 'brin/bpchar_minmax_ops', amproclefttype => 'bpchar',
+ amprocrighttype => 'bpchar', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/bpchar_minmax_ops', amproclefttype => 'bpchar',
+ amprocrighttype => 'bpchar', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/bpchar_minmax_ops', amproclefttype => 'bpchar',
+ amprocrighttype => 'bpchar', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/bpchar_minmax_ops', amproclefttype => 'bpchar',
+ amprocrighttype => 'bpchar', amprocnum => '4',
+ amproc => 'brin_minmax_union' },
+
+# minmax time without time zone
+{ amprocfamily => 'brin/time_minmax_ops', amproclefttype => 'time',
+ amprocrighttype => 'time', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/time_minmax_ops', amproclefttype => 'time',
+ amprocrighttype => 'time', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/time_minmax_ops', amproclefttype => 'time',
+ amprocrighttype => 'time', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/time_minmax_ops', amproclefttype => 'time',
+ amprocrighttype => 'time', amprocnum => '4', amproc => 'brin_minmax_union' },
+
+# minmax datetime (date, timestamp, timestamptz)
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'timestamp', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'timestamp', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'timestamp', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'timestamp', amprocnum => '4',
+ amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'timestamptz', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'timestamptz', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'timestamptz', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'timestamptz', amprocnum => '4',
+ amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'date', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'date', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'date', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamp',
+ amprocrighttype => 'date', amprocnum => '4', amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'timestamptz', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'timestamptz', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'timestamptz', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'timestamptz', amprocnum => '4',
+ amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'timestamp', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'timestamp', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'timestamp', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'timestamp', amprocnum => '4',
+ amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'date', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'date', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'date', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'timestamptz',
+ amprocrighttype => 'date', amprocnum => '4', amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'date',
+ amprocrighttype => 'date', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'date',
+ amprocrighttype => 'date', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'date',
+ amprocrighttype => 'date', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'date',
+ amprocrighttype => 'date', amprocnum => '4', amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'date',
+ amprocrighttype => 'timestamp', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'date',
+ amprocrighttype => 'timestamp', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'date',
+ amprocrighttype => 'timestamp', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'date',
+ amprocrighttype => 'timestamp', amprocnum => '4',
+ amproc => 'brin_minmax_union' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'date',
+ amprocrighttype => 'timestamptz', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'date',
+ amprocrighttype => 'timestamptz', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'date',
+ amprocrighttype => 'timestamptz', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/datetime_minmax_ops', amproclefttype => 'date',
+ amprocrighttype => 'timestamptz', amprocnum => '4',
+ amproc => 'brin_minmax_union' },
+
+# minmax interval
+{ amprocfamily => 'brin/interval_minmax_ops', amproclefttype => 'interval',
+ amprocrighttype => 'interval', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/interval_minmax_ops', amproclefttype => 'interval',
+ amprocrighttype => 'interval', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/interval_minmax_ops', amproclefttype => 'interval',
+ amprocrighttype => 'interval', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/interval_minmax_ops', amproclefttype => 'interval',
+ amprocrighttype => 'interval', amprocnum => '4',
+ amproc => 'brin_minmax_union' },
+
+# minmax time with time zone
+{ amprocfamily => 'brin/timetz_minmax_ops', amproclefttype => 'timetz',
+ amprocrighttype => 'timetz', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/timetz_minmax_ops', amproclefttype => 'timetz',
+ amprocrighttype => 'timetz', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/timetz_minmax_ops', amproclefttype => 'timetz',
+ amprocrighttype => 'timetz', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/timetz_minmax_ops', amproclefttype => 'timetz',
+ amprocrighttype => 'timetz', amprocnum => '4',
+ amproc => 'brin_minmax_union' },
+
+# minmax bit
+{ amprocfamily => 'brin/bit_minmax_ops', amproclefttype => 'bit',
+ amprocrighttype => 'bit', amprocnum => '1', amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/bit_minmax_ops', amproclefttype => 'bit',
+ amprocrighttype => 'bit', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/bit_minmax_ops', amproclefttype => 'bit',
+ amprocrighttype => 'bit', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/bit_minmax_ops', amproclefttype => 'bit',
+ amprocrighttype => 'bit', amprocnum => '4', amproc => 'brin_minmax_union' },
+
+# minmax bit varying
+{ amprocfamily => 'brin/varbit_minmax_ops', amproclefttype => 'varbit',
+ amprocrighttype => 'varbit', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/varbit_minmax_ops', amproclefttype => 'varbit',
+ amprocrighttype => 'varbit', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/varbit_minmax_ops', amproclefttype => 'varbit',
+ amprocrighttype => 'varbit', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/varbit_minmax_ops', amproclefttype => 'varbit',
+ amprocrighttype => 'varbit', amprocnum => '4',
+ amproc => 'brin_minmax_union' },
+
+# minmax numeric
+{ amprocfamily => 'brin/numeric_minmax_ops', amproclefttype => 'numeric',
+ amprocrighttype => 'numeric', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/numeric_minmax_ops', amproclefttype => 'numeric',
+ amprocrighttype => 'numeric', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/numeric_minmax_ops', amproclefttype => 'numeric',
+ amprocrighttype => 'numeric', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/numeric_minmax_ops', amproclefttype => 'numeric',
+ amprocrighttype => 'numeric', amprocnum => '4',
+ amproc => 'brin_minmax_union' },
+
+# minmax uuid
+{ amprocfamily => 'brin/uuid_minmax_ops', amproclefttype => 'uuid',
+ amprocrighttype => 'uuid', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/uuid_minmax_ops', amproclefttype => 'uuid',
+ amprocrighttype => 'uuid', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/uuid_minmax_ops', amproclefttype => 'uuid',
+ amprocrighttype => 'uuid', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/uuid_minmax_ops', amproclefttype => 'uuid',
+ amprocrighttype => 'uuid', amprocnum => '4', amproc => 'brin_minmax_union' },
+
+# inclusion range types
+{ amprocfamily => 'brin/range_inclusion_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '1',
+ amproc => 'brin_inclusion_opcinfo' },
+{ amprocfamily => 'brin/range_inclusion_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '2',
+ amproc => 'brin_inclusion_add_value' },
+{ amprocfamily => 'brin/range_inclusion_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '3',
+ amproc => 'brin_inclusion_consistent' },
+{ amprocfamily => 'brin/range_inclusion_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '4',
+ amproc => 'brin_inclusion_union' },
+{ amprocfamily => 'brin/range_inclusion_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '11', amproc => 'range_merge' },
+{ amprocfamily => 'brin/range_inclusion_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '13',
+ amproc => 'range_contains' },
+{ amprocfamily => 'brin/range_inclusion_ops', amproclefttype => 'anyrange',
+ amprocrighttype => 'anyrange', amprocnum => '14', amproc => 'isempty' },
+
+# minmax pg_lsn
+{ amprocfamily => 'brin/pg_lsn_minmax_ops', amproclefttype => 'pg_lsn',
+ amprocrighttype => 'pg_lsn', amprocnum => '1',
+ amproc => 'brin_minmax_opcinfo' },
+{ amprocfamily => 'brin/pg_lsn_minmax_ops', amproclefttype => 'pg_lsn',
+ amprocrighttype => 'pg_lsn', amprocnum => '2',
+ amproc => 'brin_minmax_add_value' },
+{ amprocfamily => 'brin/pg_lsn_minmax_ops', amproclefttype => 'pg_lsn',
+ amprocrighttype => 'pg_lsn', amprocnum => '3',
+ amproc => 'brin_minmax_consistent' },
+{ amprocfamily => 'brin/pg_lsn_minmax_ops', amproclefttype => 'pg_lsn',
+ amprocrighttype => 'pg_lsn', amprocnum => '4',
+ amproc => 'brin_minmax_union' },
+
+# inclusion box
+{ amprocfamily => 'brin/box_inclusion_ops', amproclefttype => 'box',
+ amprocrighttype => 'box', amprocnum => '1',
+ amproc => 'brin_inclusion_opcinfo' },
+{ amprocfamily => 'brin/box_inclusion_ops', amproclefttype => 'box',
+ amprocrighttype => 'box', amprocnum => '2',
+ amproc => 'brin_inclusion_add_value' },
+{ amprocfamily => 'brin/box_inclusion_ops', amproclefttype => 'box',
+ amprocrighttype => 'box', amprocnum => '3',
+ amproc => 'brin_inclusion_consistent' },
+{ amprocfamily => 'brin/box_inclusion_ops', amproclefttype => 'box',
+ amprocrighttype => 'box', amprocnum => '4',
+ amproc => 'brin_inclusion_union' },
+{ amprocfamily => 'brin/box_inclusion_ops', amproclefttype => 'box',
+ amprocrighttype => 'box', amprocnum => '11', amproc => 'bound_box' },
+{ amprocfamily => 'brin/box_inclusion_ops', amproclefttype => 'box',
+ amprocrighttype => 'box', amprocnum => '13', amproc => 'box_contain' },
+
+]
diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h
new file mode 100644
index 0000000..e39bd70
--- /dev/null
+++ b/src/include/catalog/pg_amproc.h
@@ -0,0 +1,70 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_amproc.h
+ * definition of the "access method procedure" system catalog (pg_amproc)
+ *
+ * The amproc table identifies support procedures associated with index
+ * operator families and classes. These procedures can't be listed in pg_amop
+ * since they are not the implementation of any indexable operator.
+ *
+ * The primary key for this table is <amprocfamily, amproclefttype,
+ * amprocrighttype, amprocnum>. The "default" support functions for a
+ * particular opclass within the family are those with amproclefttype =
+ * amprocrighttype = opclass's opcintype. These are the ones loaded into the
+ * relcache for an index and typically used for internal index operations.
+ * Other support functions are typically used to handle cross-type indexable
+ * operators with oprleft/oprright matching the entry's amproclefttype and
+ * amprocrighttype. The exact behavior depends on the index AM, however, and
+ * some don't pay attention to non-default functions at all.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_amproc.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_AMPROC_H
+#define PG_AMPROC_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_amproc_d.h"
+
+/* ----------------
+ * pg_amproc definition. cpp turns this into
+ * typedef struct FormData_pg_amproc
+ * ----------------
+ */
+CATALOG(pg_amproc,2603,AccessMethodProcedureRelationId)
+{
+ Oid oid; /* oid */
+
+ /* the index opfamily this entry is for */
+ Oid amprocfamily BKI_LOOKUP(pg_opfamily);
+
+ /* procedure's left input data type */
+ Oid amproclefttype BKI_LOOKUP(pg_type);
+
+ /* procedure's right input data type */
+ Oid amprocrighttype BKI_LOOKUP(pg_type);
+
+ /* support procedure index */
+ int16 amprocnum;
+
+ /* OID of the proc */
+ regproc amproc BKI_LOOKUP(pg_proc);
+} FormData_pg_amproc;
+
+/* ----------------
+ * Form_pg_amproc corresponds to a pointer to a tuple with
+ * the format of pg_amproc relation.
+ * ----------------
+ */
+typedef FormData_pg_amproc *Form_pg_amproc;
+
+#endif /* PG_AMPROC_H */
diff --git a/src/include/catalog/pg_attrdef.h b/src/include/catalog/pg_attrdef.h
new file mode 100644
index 0000000..7b661df
--- /dev/null
+++ b/src/include/catalog/pg_attrdef.h
@@ -0,0 +1,49 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_attrdef.h
+ * definition of the "attribute defaults" system catalog (pg_attrdef)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_attrdef.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_ATTRDEF_H
+#define PG_ATTRDEF_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_attrdef_d.h"
+
+/* ----------------
+ * pg_attrdef definition. cpp turns this into
+ * typedef struct FormData_pg_attrdef
+ * ----------------
+ */
+CATALOG(pg_attrdef,2604,AttrDefaultRelationId)
+{
+ Oid oid; /* oid */
+
+ Oid adrelid; /* OID of table containing attribute */
+ int16 adnum; /* attnum of attribute */
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ pg_node_tree adbin BKI_FORCE_NOT_NULL; /* nodeToString representation of
+ * default */
+#endif
+} FormData_pg_attrdef;
+
+/* ----------------
+ * Form_pg_attrdef corresponds to a pointer to a tuple with
+ * the format of pg_attrdef relation.
+ * ----------------
+ */
+typedef FormData_pg_attrdef *Form_pg_attrdef;
+
+#endif /* PG_ATTRDEF_H */
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
new file mode 100644
index 0000000..a4cc80a
--- /dev/null
+++ b/src/include/catalog/pg_attribute.h
@@ -0,0 +1,204 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_attribute.h
+ * definition of the "attribute" system catalog (pg_attribute)
+ *
+ * The initial contents of pg_attribute are generated at compile time by
+ * genbki.pl, so there is no pg_attribute.dat file. Only "bootstrapped"
+ * relations need be included.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_attribute.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_ATTRIBUTE_H
+#define PG_ATTRIBUTE_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_attribute_d.h"
+
+/* ----------------
+ * pg_attribute definition. cpp turns this into
+ * typedef struct FormData_pg_attribute
+ *
+ * If you change the following, make sure you change the structs for
+ * system attributes in catalog/heap.c also.
+ * You may need to change catalog/genbki.pl as well.
+ * ----------------
+ */
+CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75,AttributeRelation_Rowtype_Id) BKI_SCHEMA_MACRO
+{
+ Oid attrelid; /* OID of relation containing this attribute */
+ NameData attname; /* name of attribute */
+
+ /*
+ * atttypid is the OID of the instance in Catalog Class pg_type that
+ * defines the data type of this attribute (e.g. int4). Information in
+ * that instance is redundant with the attlen, attbyval, and attalign
+ * attributes of this instance, so they had better match or Postgres will
+ * fail.
+ */
+ Oid atttypid;
+
+ /*
+ * attstattarget is the target number of statistics datapoints to collect
+ * during VACUUM ANALYZE of this column. A zero here indicates that we do
+ * not wish to collect any stats about this column. A "-1" here indicates
+ * that no value has been explicitly set for this column, so ANALYZE
+ * should use the default setting.
+ */
+ int32 attstattarget BKI_DEFAULT(-1);
+
+ /*
+ * attlen is a copy of the typlen field from pg_type for this attribute.
+ * See atttypid comments above.
+ */
+ int16 attlen;
+
+ /*
+ * attnum is the "attribute number" for the attribute: A value that
+ * uniquely identifies this attribute within its class. For user
+ * attributes, Attribute numbers are greater than 0 and not greater than
+ * the number of attributes in the class. I.e. if the Class pg_class says
+ * that Class XYZ has 10 attributes, then the user attribute numbers in
+ * Class pg_attribute must be 1-10.
+ *
+ * System attributes have attribute numbers less than 0 that are unique
+ * within the class, but not constrained to any particular range.
+ *
+ * Note that (attnum - 1) is often used as the index to an array.
+ */
+ int16 attnum;
+
+ /*
+ * attndims is the declared number of dimensions, if an array type,
+ * otherwise zero.
+ */
+ int32 attndims;
+
+ /*
+ * fastgetattr() uses attcacheoff to cache byte offsets of attributes in
+ * heap tuples. The value actually stored in pg_attribute (-1) indicates
+ * no cached value. But when we copy these tuples into a tuple
+ * descriptor, we may then update attcacheoff in the copies. This speeds
+ * up the attribute walking process.
+ */
+ int32 attcacheoff BKI_DEFAULT(-1);
+
+ /*
+ * atttypmod records type-specific data supplied at table creation time
+ * (for example, the max length of a varchar field). It is passed to
+ * type-specific input and output functions as the third argument. The
+ * value will generally be -1 for types that do not need typmod.
+ */
+ int32 atttypmod BKI_DEFAULT(-1);
+
+ /*
+ * attbyval is a copy of the typbyval field from pg_type for this
+ * attribute. See atttypid comments above.
+ */
+ bool attbyval;
+
+ /*----------
+ * attstorage tells for VARLENA attributes, what the heap access
+ * methods can do to it if a given tuple doesn't fit into a page.
+ * Possible values are as for pg_type.typstorage (see TYPSTORAGE macros).
+ *----------
+ */
+ char attstorage;
+
+ /*
+ * attalign is a copy of the typalign field from pg_type for this
+ * attribute. See atttypid comments above.
+ */
+ char attalign;
+
+ /* This flag represents the "NOT NULL" constraint */
+ bool attnotnull;
+
+ /* Has DEFAULT value or not */
+ bool atthasdef BKI_DEFAULT(f);
+
+ /* Has a missing value or not */
+ bool atthasmissing BKI_DEFAULT(f);
+
+ /* One of the ATTRIBUTE_IDENTITY_* constants below, or '\0' */
+ char attidentity BKI_DEFAULT('\0');
+
+ /* One of the ATTRIBUTE_GENERATED_* constants below, or '\0' */
+ char attgenerated BKI_DEFAULT('\0');
+
+ /* Is dropped (ie, logically invisible) or not */
+ bool attisdropped BKI_DEFAULT(f);
+
+ /*
+ * This flag specifies whether this column has ever had a local
+ * definition. It is set for normal non-inherited columns, but also for
+ * columns that are inherited from parents if also explicitly listed in
+ * CREATE TABLE INHERITS. It is also set when inheritance is removed from
+ * a table with ALTER TABLE NO INHERIT. If the flag is set, the column is
+ * not dropped by a parent's DROP COLUMN even if this causes the column's
+ * attinhcount to become zero.
+ */
+ bool attislocal BKI_DEFAULT(t);
+
+ /* Number of times inherited from direct parent relation(s) */
+ int32 attinhcount BKI_DEFAULT(0);
+
+ /* attribute's collation */
+ Oid attcollation;
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ /* NOTE: The following fields are not present in tuple descriptors. */
+
+ /* Column-level access permissions */
+ aclitem attacl[1] BKI_DEFAULT(_null_);
+
+ /* Column-level options */
+ text attoptions[1] BKI_DEFAULT(_null_);
+
+ /* Column-level FDW options */
+ text attfdwoptions[1] BKI_DEFAULT(_null_);
+
+ /*
+ * Missing value for added columns. This is a one element array which lets
+ * us store a value of the attribute type here.
+ */
+ anyarray attmissingval BKI_DEFAULT(_null_);
+#endif
+} FormData_pg_attribute;
+
+/*
+ * ATTRIBUTE_FIXED_PART_SIZE is the size of the fixed-layout,
+ * guaranteed-not-null part of a pg_attribute row. This is in fact as much
+ * of the row as gets copied into tuple descriptors, so don't expect you
+ * can access fields beyond attcollation except in a real tuple!
+ */
+#define ATTRIBUTE_FIXED_PART_SIZE \
+ (offsetof(FormData_pg_attribute,attcollation) + sizeof(Oid))
+
+/* ----------------
+ * Form_pg_attribute corresponds to a pointer to a tuple with
+ * the format of pg_attribute relation.
+ * ----------------
+ */
+typedef FormData_pg_attribute *Form_pg_attribute;
+
+#ifdef EXPOSE_TO_CLIENT_CODE
+
+#define ATTRIBUTE_IDENTITY_ALWAYS 'a'
+#define ATTRIBUTE_IDENTITY_BY_DEFAULT 'd'
+
+#define ATTRIBUTE_GENERATED_STORED 's'
+
+#endif /* EXPOSE_TO_CLIENT_CODE */
+
+#endif /* PG_ATTRIBUTE_H */
diff --git a/src/include/catalog/pg_auth_members.h b/src/include/catalog/pg_auth_members.h
new file mode 100644
index 0000000..8563feb
--- /dev/null
+++ b/src/include/catalog/pg_auth_members.h
@@ -0,0 +1,45 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_auth_members.h
+ * definition of the "authorization identifier members" system catalog
+ * (pg_auth_members).
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_auth_members.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_AUTH_MEMBERS_H
+#define PG_AUTH_MEMBERS_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_auth_members_d.h"
+
+/* ----------------
+ * pg_auth_members definition. cpp turns this into
+ * typedef struct FormData_pg_auth_members
+ * ----------------
+ */
+CATALOG(pg_auth_members,1261,AuthMemRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_OID(2843,AuthMemRelation_Rowtype_Id) BKI_SCHEMA_MACRO
+{
+ Oid roleid; /* ID of a role */
+ Oid member; /* ID of a member of that role */
+ Oid grantor; /* who granted the membership */
+ bool admin_option; /* granted with admin option? */
+} FormData_pg_auth_members;
+
+/* ----------------
+ * Form_pg_auth_members corresponds to a pointer to a tuple with
+ * the format of pg_auth_members relation.
+ * ----------------
+ */
+typedef FormData_pg_auth_members *Form_pg_auth_members;
+
+#endif /* PG_AUTH_MEMBERS_H */
diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat
new file mode 100644
index 0000000..7c08851
--- /dev/null
+++ b/src/include/catalog/pg_authid.dat
@@ -0,0 +1,64 @@
+#----------------------------------------------------------------------
+#
+# pg_authid.dat
+# Initial contents of the pg_authid system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_authid.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+# The C code typically refers to these roles using the #define symbols,
+# so make sure every entry has an oid_symbol value.
+
+{ oid => '10', oid_symbol => 'BOOTSTRAP_SUPERUSERID',
+ rolname => 'POSTGRES', rolsuper => 't', rolinherit => 't',
+ rolcreaterole => 't', rolcreatedb => 't', rolcanlogin => 't',
+ rolreplication => 't', rolbypassrls => 't', rolconnlimit => '-1',
+ rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '3373', oid_symbol => 'DEFAULT_ROLE_MONITOR',
+ rolname => 'pg_monitor', rolsuper => 'f', rolinherit => 't',
+ rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+ rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
+ rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '3374', oid_symbol => 'DEFAULT_ROLE_READ_ALL_SETTINGS',
+ rolname => 'pg_read_all_settings', rolsuper => 'f', rolinherit => 't',
+ rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+ rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
+ rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '3375', oid_symbol => 'DEFAULT_ROLE_READ_ALL_STATS',
+ rolname => 'pg_read_all_stats', rolsuper => 'f', rolinherit => 't',
+ rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+ rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
+ rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '3377', oid_symbol => 'DEFAULT_ROLE_STAT_SCAN_TABLES',
+ rolname => 'pg_stat_scan_tables', rolsuper => 'f', rolinherit => 't',
+ rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+ rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
+ rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '4569', oid_symbol => 'DEFAULT_ROLE_READ_SERVER_FILES',
+ rolname => 'pg_read_server_files', rolsuper => 'f', rolinherit => 't',
+ rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+ rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
+ rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '4570', oid_symbol => 'DEFAULT_ROLE_WRITE_SERVER_FILES',
+ rolname => 'pg_write_server_files', rolsuper => 'f', rolinherit => 't',
+ rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+ rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
+ rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '4571', oid_symbol => 'DEFAULT_ROLE_EXECUTE_SERVER_PROGRAM',
+ rolname => 'pg_execute_server_program', rolsuper => 'f', rolinherit => 't',
+ rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+ rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
+ rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '4200', oid_symbol => 'DEFAULT_ROLE_SIGNAL_BACKENDID',
+ rolname => 'pg_signal_backend', rolsuper => 'f', rolinherit => 't',
+ rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+ rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
+ rolpassword => '_null_', rolvaliduntil => '_null_' },
+
+]
diff --git a/src/include/catalog/pg_authid.h b/src/include/catalog/pg_authid.h
new file mode 100644
index 0000000..88a5373
--- /dev/null
+++ b/src/include/catalog/pg_authid.h
@@ -0,0 +1,58 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_authid.h
+ * definition of the "authorization identifier" system catalog (pg_authid)
+ *
+ * pg_shadow and pg_group are now publicly accessible views on pg_authid.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_authid.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_AUTHID_H
+#define PG_AUTHID_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_authid_d.h"
+
+/* ----------------
+ * pg_authid definition. cpp turns this into
+ * typedef struct FormData_pg_authid
+ * ----------------
+ */
+CATALOG(pg_authid,1260,AuthIdRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_OID(2842,AuthIdRelation_Rowtype_Id) BKI_SCHEMA_MACRO
+{
+ Oid oid; /* oid */
+ NameData rolname; /* name of role */
+ bool rolsuper; /* read this field via superuser() only! */
+ bool rolinherit; /* inherit privileges from other roles? */
+ bool rolcreaterole; /* allowed to create more roles? */
+ bool rolcreatedb; /* allowed to create databases? */
+ bool rolcanlogin; /* allowed to log in as session user? */
+ bool rolreplication; /* role used for streaming replication */
+ bool rolbypassrls; /* bypasses row level security? */
+ int32 rolconnlimit; /* max connections allowed (-1=no limit) */
+
+ /* remaining fields may be null; use heap_getattr to read them! */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ text rolpassword; /* password, if any */
+ timestamptz rolvaliduntil; /* password expiration time, if any */
+#endif
+} FormData_pg_authid;
+
+/* ----------------
+ * Form_pg_authid corresponds to a pointer to a tuple with
+ * the format of pg_authid relation.
+ * ----------------
+ */
+typedef FormData_pg_authid *Form_pg_authid;
+
+#endif /* PG_AUTHID_H */
diff --git a/src/include/catalog/pg_cast.dat b/src/include/catalog/pg_cast.dat
new file mode 100644
index 0000000..5a58f50
--- /dev/null
+++ b/src/include/catalog/pg_cast.dat
@@ -0,0 +1,533 @@
+#----------------------------------------------------------------------
+#
+# pg_cast.dat
+# Initial contents of the pg_cast system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_cast.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+# Note: this table has OIDs, but we don't bother to assign them manually,
+# since nothing needs to know the specific OID of any built-in cast.
+
+# Numeric category: implicit casts are allowed in the direction
+# int2->int4->int8->numeric->float4->float8, while casts in the
+# reverse direction are assignment-only.
+{ castsource => 'int8', casttarget => 'int2', castfunc => 'int2(int8)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'int8', casttarget => 'int4', castfunc => 'int4(int8)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'int8', casttarget => 'float4', castfunc => 'float4(int8)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int8', casttarget => 'float8', castfunc => 'float8(int8)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int8', casttarget => 'numeric', castfunc => 'numeric(int8)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'int8', castfunc => 'int8(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'int4', castfunc => 'int4(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'float4', castfunc => 'float4(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'float8', castfunc => 'float8(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'numeric', castfunc => 'numeric(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'int8', castfunc => 'int8(int4)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'int2', castfunc => 'int2(int4)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'float4', castfunc => 'float4(int4)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'float8', castfunc => 'float8(int4)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'numeric', castfunc => 'numeric(int4)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'float4', casttarget => 'int8', castfunc => 'int8(float4)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'float4', casttarget => 'int2', castfunc => 'int2(float4)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'float4', casttarget => 'int4', castfunc => 'int4(float4)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'float4', casttarget => 'float8', castfunc => 'float8(float4)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'float4', casttarget => 'numeric',
+ castfunc => 'numeric(float4)', castcontext => 'a', castmethod => 'f' },
+{ castsource => 'float8', casttarget => 'int8', castfunc => 'int8(float8)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'float8', casttarget => 'int2', castfunc => 'int2(float8)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'float8', casttarget => 'int4', castfunc => 'int4(float8)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'float8', casttarget => 'float4', castfunc => 'float4(float8)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'float8', casttarget => 'numeric',
+ castfunc => 'numeric(float8)', castcontext => 'a', castmethod => 'f' },
+{ castsource => 'numeric', casttarget => 'int8', castfunc => 'int8(numeric)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'numeric', casttarget => 'int2', castfunc => 'int2(numeric)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'numeric', casttarget => 'int4', castfunc => 'int4(numeric)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'numeric', casttarget => 'float4',
+ castfunc => 'float4(numeric)', castcontext => 'i', castmethod => 'f' },
+{ castsource => 'numeric', casttarget => 'float8',
+ castfunc => 'float8(numeric)', castcontext => 'i', castmethod => 'f' },
+{ castsource => 'money', casttarget => 'numeric', castfunc => 'numeric(money)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'numeric', casttarget => 'money', castfunc => 'money(numeric)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'money', castfunc => 'money(int4)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'int8', casttarget => 'money', castfunc => 'money(int8)',
+ castcontext => 'a', castmethod => 'f' },
+
+# Allow explicit coercions between int4 and bool
+{ castsource => 'int4', casttarget => 'bool', castfunc => 'bool(int4)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'bool', casttarget => 'int4', castfunc => 'int4(bool)',
+ castcontext => 'e', castmethod => 'f' },
+
+# Allow explicit coercions between xid8 and xid
+{ castsource => 'xid8', casttarget => 'xid', castfunc => 'xid(xid8)',
+ castcontext => 'e', castmethod => 'f' },
+
+# OID category: allow implicit conversion from any integral type (including
+# int8, to support OID literals > 2G) to OID, as well as assignment coercion
+# from OID to int4 or int8. Similarly for each OID-alias type. Also allow
+# implicit coercions between OID and each OID-alias type, as well as
+# regproc<->regprocedure and regoper<->regoperator. (Other coercions
+# between alias types must pass through OID.) Lastly, there are implicit
+# casts from text and varchar to regclass, which exist mainly to support
+# legacy forms of nextval() and related functions.
+{ castsource => 'int8', casttarget => 'oid', castfunc => 'oid',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'oid', castfunc => 'int4(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'oid', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'oid', casttarget => 'int8', castfunc => 'int8(oid)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'oid', casttarget => 'int4', castfunc => '0',
+ castcontext => 'a', castmethod => 'b' },
+{ castsource => 'oid', casttarget => 'regproc', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regproc', casttarget => 'oid', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'int8', casttarget => 'regproc', castfunc => 'oid',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'regproc', castfunc => 'int4(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'regproc', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regproc', casttarget => 'int8', castfunc => 'int8(oid)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'regproc', casttarget => 'int4', castfunc => '0',
+ castcontext => 'a', castmethod => 'b' },
+{ castsource => 'regproc', casttarget => 'regprocedure', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regprocedure', casttarget => 'regproc', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'oid', casttarget => 'regprocedure', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regprocedure', casttarget => 'oid', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'int8', casttarget => 'regprocedure', castfunc => 'oid',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'regprocedure', castfunc => 'int4(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'regprocedure', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regprocedure', casttarget => 'int8', castfunc => 'int8(oid)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'regprocedure', casttarget => 'int4', castfunc => '0',
+ castcontext => 'a', castmethod => 'b' },
+{ castsource => 'oid', casttarget => 'regoper', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regoper', casttarget => 'oid', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'int8', casttarget => 'regoper', castfunc => 'oid',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'regoper', castfunc => 'int4(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'regoper', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regoper', casttarget => 'int8', castfunc => 'int8(oid)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'regoper', casttarget => 'int4', castfunc => '0',
+ castcontext => 'a', castmethod => 'b' },
+{ castsource => 'regoper', casttarget => 'regoperator', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regoperator', casttarget => 'regoper', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'oid', casttarget => 'regoperator', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regoperator', casttarget => 'oid', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'int8', casttarget => 'regoperator', castfunc => 'oid',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'regoperator', castfunc => 'int4(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'regoperator', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regoperator', casttarget => 'int8', castfunc => 'int8(oid)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'regoperator', casttarget => 'int4', castfunc => '0',
+ castcontext => 'a', castmethod => 'b' },
+{ castsource => 'oid', casttarget => 'regclass', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regclass', casttarget => 'oid', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'int8', casttarget => 'regclass', castfunc => 'oid',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'regclass', castfunc => 'int4(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'regclass', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regclass', casttarget => 'int8', castfunc => 'int8(oid)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'regclass', casttarget => 'int4', castfunc => '0',
+ castcontext => 'a', castmethod => 'b' },
+{ castsource => 'oid', casttarget => 'regcollation', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regcollation', casttarget => 'oid', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'int8', casttarget => 'regcollation', castfunc => 'oid',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'regcollation', castfunc => 'int4(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'regcollation', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regcollation', casttarget => 'int8', castfunc => 'int8(oid)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'regcollation', casttarget => 'int4', castfunc => '0',
+ castcontext => 'a', castmethod => 'b' },
+{ castsource => 'oid', casttarget => 'regtype', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regtype', casttarget => 'oid', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'int8', casttarget => 'regtype', castfunc => 'oid',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'regtype', castfunc => 'int4(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'regtype', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regtype', casttarget => 'int8', castfunc => 'int8(oid)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'regtype', casttarget => 'int4', castfunc => '0',
+ castcontext => 'a', castmethod => 'b' },
+{ castsource => 'oid', casttarget => 'regconfig', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regconfig', casttarget => 'oid', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'int8', casttarget => 'regconfig', castfunc => 'oid',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'regconfig', castfunc => 'int4(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'regconfig', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regconfig', casttarget => 'int8', castfunc => 'int8(oid)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'regconfig', casttarget => 'int4', castfunc => '0',
+ castcontext => 'a', castmethod => 'b' },
+{ castsource => 'oid', casttarget => 'regdictionary', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regdictionary', casttarget => 'oid', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'int8', casttarget => 'regdictionary', castfunc => 'oid',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'regdictionary', castfunc => 'int4(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'regdictionary', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regdictionary', casttarget => 'int8', castfunc => 'int8(oid)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'regdictionary', casttarget => 'int4', castfunc => '0',
+ castcontext => 'a', castmethod => 'b' },
+{ castsource => 'text', casttarget => 'regclass', castfunc => 'regclass',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'varchar', casttarget => 'regclass', castfunc => 'regclass',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'oid', casttarget => 'regrole', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regrole', casttarget => 'oid', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'int8', casttarget => 'regrole', castfunc => 'oid',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'regrole', castfunc => 'int4(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'regrole', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regrole', casttarget => 'int8', castfunc => 'int8(oid)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'regrole', casttarget => 'int4', castfunc => '0',
+ castcontext => 'a', castmethod => 'b' },
+{ castsource => 'oid', casttarget => 'regnamespace', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regnamespace', casttarget => 'oid', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'int8', casttarget => 'regnamespace', castfunc => 'oid',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int2', casttarget => 'regnamespace', castfunc => 'int4(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'regnamespace', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'regnamespace', casttarget => 'int8', castfunc => 'int8(oid)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'regnamespace', casttarget => 'int4', castfunc => '0',
+ castcontext => 'a', castmethod => 'b' },
+
+# String category
+{ castsource => 'text', casttarget => 'bpchar', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'text', casttarget => 'varchar', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'bpchar', casttarget => 'text', castfunc => 'text(bpchar)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'bpchar', casttarget => 'varchar', castfunc => 'text(bpchar)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'varchar', casttarget => 'text', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'varchar', casttarget => 'bpchar', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'char', casttarget => 'text', castfunc => 'text(char)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'char', casttarget => 'bpchar', castfunc => 'bpchar(char)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'char', casttarget => 'varchar', castfunc => 'text(char)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'name', casttarget => 'text', castfunc => 'text(name)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'name', casttarget => 'bpchar', castfunc => 'bpchar(name)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'name', casttarget => 'varchar', castfunc => 'varchar(name)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'text', casttarget => 'char', castfunc => 'char(text)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'bpchar', casttarget => 'char', castfunc => 'char(text)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'varchar', casttarget => 'char', castfunc => 'char(text)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'text', casttarget => 'name', castfunc => 'name(text)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'bpchar', casttarget => 'name', castfunc => 'name(bpchar)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'varchar', casttarget => 'name', castfunc => 'name(varchar)',
+ castcontext => 'i', castmethod => 'f' },
+
+# Allow explicit coercions between int4 and "char"
+{ castsource => 'char', casttarget => 'int4', castfunc => 'int4(char)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'char', castfunc => 'char(int4)',
+ castcontext => 'e', castmethod => 'f' },
+
+# pg_node_tree can be coerced to, but not from, text
+{ castsource => 'pg_node_tree', casttarget => 'text', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+
+# pg_ndistinct can be coerced to, but not from, bytea and text
+{ castsource => 'pg_ndistinct', casttarget => 'bytea', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'pg_ndistinct', casttarget => 'text', castfunc => '0',
+ castcontext => 'i', castmethod => 'i' },
+
+# pg_dependencies can be coerced to, but not from, bytea and text
+{ castsource => 'pg_dependencies', casttarget => 'bytea', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'pg_dependencies', casttarget => 'text', castfunc => '0',
+ castcontext => 'i', castmethod => 'i' },
+
+# pg_mcv_list can be coerced to, but not from, bytea and text
+{ castsource => 'pg_mcv_list', casttarget => 'bytea', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'pg_mcv_list', casttarget => 'text', castfunc => '0',
+ castcontext => 'i', castmethod => 'i' },
+
+# Datetime category
+{ castsource => 'date', casttarget => 'timestamp',
+ castfunc => 'timestamp(date)', castcontext => 'i', castmethod => 'f' },
+{ castsource => 'date', casttarget => 'timestamptz',
+ castfunc => 'timestamptz(date)', castcontext => 'i', castmethod => 'f' },
+{ castsource => 'time', casttarget => 'interval', castfunc => 'interval(time)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'time', casttarget => 'timetz', castfunc => 'timetz(time)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'timestamp', casttarget => 'date',
+ castfunc => 'date(timestamp)', castcontext => 'a', castmethod => 'f' },
+{ castsource => 'timestamp', casttarget => 'time',
+ castfunc => 'time(timestamp)', castcontext => 'a', castmethod => 'f' },
+{ castsource => 'timestamp', casttarget => 'timestamptz',
+ castfunc => 'timestamptz(timestamp)', castcontext => 'i', castmethod => 'f' },
+{ castsource => 'timestamptz', casttarget => 'date',
+ castfunc => 'date(timestamptz)', castcontext => 'a', castmethod => 'f' },
+{ castsource => 'timestamptz', casttarget => 'time',
+ castfunc => 'time(timestamptz)', castcontext => 'a', castmethod => 'f' },
+{ castsource => 'timestamptz', casttarget => 'timestamp',
+ castfunc => 'timestamp(timestamptz)', castcontext => 'a', castmethod => 'f' },
+{ castsource => 'timestamptz', casttarget => 'timetz',
+ castfunc => 'timetz(timestamptz)', castcontext => 'a', castmethod => 'f' },
+{ castsource => 'interval', casttarget => 'time', castfunc => 'time(interval)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'timetz', casttarget => 'time', castfunc => 'time(timetz)',
+ castcontext => 'a', castmethod => 'f' },
+
+# Geometric category
+{ castsource => 'point', casttarget => 'box', castfunc => 'box(point)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'lseg', casttarget => 'point', castfunc => 'point(lseg)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'path', casttarget => 'point', castfunc => 'point(path)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'path', casttarget => 'polygon', castfunc => 'polygon(path)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'box', casttarget => 'point', castfunc => 'point(box)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'box', casttarget => 'lseg', castfunc => 'lseg(box)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'box', casttarget => 'polygon', castfunc => 'polygon(box)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'box', casttarget => 'circle', castfunc => 'circle(box)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'polygon', casttarget => 'point', castfunc => 'point(polygon)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'polygon', casttarget => 'path', castfunc => 'path',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'polygon', casttarget => 'box', castfunc => 'box(polygon)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'polygon', casttarget => 'circle',
+ castfunc => 'circle(polygon)', castcontext => 'e', castmethod => 'f' },
+{ castsource => 'circle', casttarget => 'point', castfunc => 'point(circle)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'circle', casttarget => 'box', castfunc => 'box(circle)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'circle', casttarget => 'polygon',
+ castfunc => 'polygon(circle)', castcontext => 'e', castmethod => 'f' },
+
+# MAC address category
+{ castsource => 'macaddr', casttarget => 'macaddr8', castfunc => 'macaddr8',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'macaddr8', casttarget => 'macaddr', castfunc => 'macaddr',
+ castcontext => 'i', castmethod => 'f' },
+
+# INET category
+{ castsource => 'cidr', casttarget => 'inet', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'inet', casttarget => 'cidr', castfunc => 'cidr',
+ castcontext => 'a', castmethod => 'f' },
+
+# BitString category
+{ castsource => 'bit', casttarget => 'varbit', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'varbit', casttarget => 'bit', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+
+# Cross-category casts between bit and int4, int8
+{ castsource => 'int8', casttarget => 'bit', castfunc => 'bit(int8,int4)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'bit', castfunc => 'bit(int4,int4)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'bit', casttarget => 'int8', castfunc => 'int8(bit)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'bit', casttarget => 'int4', castfunc => 'int4(bit)',
+ castcontext => 'e', castmethod => 'f' },
+
+# Cross-category casts to and from TEXT
+# We need entries here only for a few specialized cases where the behavior
+# of the cast function differs from the datatype's I/O functions. Otherwise,
+# parse_coerce.c will generate CoerceViaIO operations without any prompting.
+# Note that the castcontext values specified here should be no stronger than
+# parse_coerce.c's automatic casts ('a' to text, 'e' from text) else odd
+# behavior will ensue when the automatic cast is applied instead of the
+# pg_cast entry!
+{ castsource => 'cidr', casttarget => 'text', castfunc => 'text(inet)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'inet', casttarget => 'text', castfunc => 'text(inet)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'bool', casttarget => 'text', castfunc => 'text(bool)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'xml', casttarget => 'text', castfunc => '0',
+ castcontext => 'a', castmethod => 'b' },
+{ castsource => 'text', casttarget => 'xml', castfunc => 'xml',
+ castcontext => 'e', castmethod => 'f' },
+
+# Cross-category casts to and from VARCHAR
+# We support all the same casts as for TEXT.
+{ castsource => 'cidr', casttarget => 'varchar', castfunc => 'text(inet)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'inet', casttarget => 'varchar', castfunc => 'text(inet)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'bool', casttarget => 'varchar', castfunc => 'text(bool)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'xml', casttarget => 'varchar', castfunc => '0',
+ castcontext => 'a', castmethod => 'b' },
+{ castsource => 'varchar', casttarget => 'xml', castfunc => 'xml',
+ castcontext => 'e', castmethod => 'f' },
+
+# Cross-category casts to and from BPCHAR
+# We support all the same casts as for TEXT.
+{ castsource => 'cidr', casttarget => 'bpchar', castfunc => 'text(inet)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'inet', casttarget => 'bpchar', castfunc => 'text(inet)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'bool', casttarget => 'bpchar', castfunc => 'text(bool)',
+ castcontext => 'a', castmethod => 'f' },
+{ castsource => 'xml', casttarget => 'bpchar', castfunc => '0',
+ castcontext => 'a', castmethod => 'b' },
+{ castsource => 'bpchar', casttarget => 'xml', castfunc => 'xml',
+ castcontext => 'e', castmethod => 'f' },
+
+# Length-coercion functions
+{ castsource => 'bpchar', casttarget => 'bpchar',
+ castfunc => 'bpchar(bpchar,int4,bool)', castcontext => 'i',
+ castmethod => 'f' },
+{ castsource => 'varchar', casttarget => 'varchar',
+ castfunc => 'varchar(varchar,int4,bool)', castcontext => 'i',
+ castmethod => 'f' },
+{ castsource => 'time', casttarget => 'time', castfunc => 'time(time,int4)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'timestamp', casttarget => 'timestamp',
+ castfunc => 'timestamp(timestamp,int4)', castcontext => 'i',
+ castmethod => 'f' },
+{ castsource => 'timestamptz', casttarget => 'timestamptz',
+ castfunc => 'timestamptz(timestamptz,int4)', castcontext => 'i',
+ castmethod => 'f' },
+{ castsource => 'interval', casttarget => 'interval',
+ castfunc => 'interval(interval,int4)', castcontext => 'i',
+ castmethod => 'f' },
+{ castsource => 'timetz', casttarget => 'timetz',
+ castfunc => 'timetz(timetz,int4)', castcontext => 'i', castmethod => 'f' },
+{ castsource => 'bit', casttarget => 'bit', castfunc => 'bit(bit,int4,bool)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'varbit', casttarget => 'varbit', castfunc => 'varbit',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'numeric', casttarget => 'numeric',
+ castfunc => 'numeric(numeric,int4)', castcontext => 'i', castmethod => 'f' },
+
+# json to/from jsonb
+{ castsource => 'json', casttarget => 'jsonb', castfunc => '0',
+ castcontext => 'a', castmethod => 'i' },
+{ castsource => 'jsonb', casttarget => 'json', castfunc => '0',
+ castcontext => 'a', castmethod => 'i' },
+
+# jsonb to numeric and bool types
+{ castsource => 'jsonb', casttarget => 'bool', castfunc => 'bool(jsonb)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'jsonb', casttarget => 'numeric', castfunc => 'numeric(jsonb)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'jsonb', casttarget => 'int2', castfunc => 'int2(jsonb)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'jsonb', casttarget => 'int4', castfunc => 'int4(jsonb)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'jsonb', casttarget => 'int8', castfunc => 'int8(jsonb)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'jsonb', casttarget => 'float4', castfunc => 'float4(jsonb)',
+ castcontext => 'e', castmethod => 'f' },
+{ castsource => 'jsonb', casttarget => 'float8', castfunc => 'float8(jsonb)',
+ castcontext => 'e', castmethod => 'f' },
+
+]
diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h
new file mode 100644
index 0000000..2620ff4
--- /dev/null
+++ b/src/include/catalog/pg_cast.h
@@ -0,0 +1,99 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_cast.h
+ * definition of the "type casts" system catalog (pg_cast)
+ *
+ * As of Postgres 8.0, pg_cast describes not only type coercion functions
+ * but also length coercion functions.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_cast.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_CAST_H
+#define PG_CAST_H
+
+#include "catalog/dependency.h"
+#include "catalog/genbki.h"
+#include "catalog/pg_cast_d.h"
+
+/* ----------------
+ * pg_cast definition. cpp turns this into
+ * typedef struct FormData_pg_cast
+ * ----------------
+ */
+CATALOG(pg_cast,2605,CastRelationId)
+{
+ Oid oid; /* oid */
+
+ /* source datatype for cast */
+ Oid castsource BKI_LOOKUP(pg_type);
+
+ /* destination datatype for cast */
+ Oid casttarget BKI_LOOKUP(pg_type);
+
+ /* cast function; 0 = binary coercible */
+ Oid castfunc BKI_LOOKUP(pg_proc);
+
+ /* contexts in which cast can be used */
+ char castcontext;
+
+ /* cast method */
+ char castmethod;
+} FormData_pg_cast;
+
+/* ----------------
+ * Form_pg_cast corresponds to a pointer to a tuple with
+ * the format of pg_cast relation.
+ * ----------------
+ */
+typedef FormData_pg_cast *Form_pg_cast;
+
+#ifdef EXPOSE_TO_CLIENT_CODE
+
+/*
+ * The allowable values for pg_cast.castcontext are specified by this enum.
+ * Since castcontext is stored as a "char", we use ASCII codes for human
+ * convenience in reading the table. Note that internally to the backend,
+ * these values are converted to the CoercionContext enum (see primnodes.h),
+ * which is defined to sort in a convenient order; the ASCII codes don't
+ * have to sort in any special order.
+ */
+
+typedef enum CoercionCodes
+{
+ COERCION_CODE_IMPLICIT = 'i', /* coercion in context of expression */
+ COERCION_CODE_ASSIGNMENT = 'a', /* coercion in context of assignment */
+ COERCION_CODE_EXPLICIT = 'e' /* explicit cast operation */
+} CoercionCodes;
+
+/*
+ * The allowable values for pg_cast.castmethod are specified by this enum.
+ * Since castmethod is stored as a "char", we use ASCII codes for human
+ * convenience in reading the table.
+ */
+typedef enum CoercionMethod
+{
+ COERCION_METHOD_FUNCTION = 'f', /* use a function */
+ COERCION_METHOD_BINARY = 'b', /* types are binary-compatible */
+ COERCION_METHOD_INOUT = 'i' /* use input/output functions */
+} CoercionMethod;
+
+#endif /* EXPOSE_TO_CLIENT_CODE */
+
+
+extern ObjectAddress CastCreate(Oid sourcetypeid,
+ Oid targettypeid,
+ Oid funcid,
+ char castcontext,
+ char castmethod,
+ DependencyType behavior);
+
+#endif /* PG_CAST_H */
diff --git a/src/include/catalog/pg_class.dat b/src/include/catalog/pg_class.dat
new file mode 100644
index 0000000..b28bba7
--- /dev/null
+++ b/src/include/catalog/pg_class.dat
@@ -0,0 +1,28 @@
+#----------------------------------------------------------------------
+#
+# pg_class.dat
+# Initial contents of the pg_class system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_class.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+# Note: only bootstrap catalogs, ie those marked BKI_BOOTSTRAP, need to
+# have entries here. Be sure that the OIDs listed here match those given in
+# their CATALOG and BKI_ROWTYPE_OID macros.
+
+{ oid => '1247',
+ relname => 'pg_type', reltype => 'pg_type' },
+{ oid => '1249',
+ relname => 'pg_attribute', reltype => 'pg_attribute' },
+{ oid => '1255',
+ relname => 'pg_proc', reltype => 'pg_proc' },
+{ oid => '1259',
+ relname => 'pg_class', reltype => 'pg_class' },
+
+]
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
new file mode 100644
index 0000000..78b33b2
--- /dev/null
+++ b/src/include/catalog/pg_class.h
@@ -0,0 +1,200 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_class.h
+ * definition of the "relation" system catalog (pg_class)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_class.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_CLASS_H
+#define PG_CLASS_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_class_d.h"
+
+/* ----------------
+ * pg_class definition. cpp turns this into
+ * typedef struct FormData_pg_class
+ *
+ * Note that the BKI_DEFAULT values below are only used for rows describing
+ * BKI_BOOTSTRAP catalogs, since only those rows appear in pg_class.dat.
+ * ----------------
+ */
+CATALOG(pg_class,1259,RelationRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83,RelationRelation_Rowtype_Id) BKI_SCHEMA_MACRO
+{
+ /* oid */
+ Oid oid;
+
+ /* class name */
+ NameData relname;
+
+ /* OID of namespace containing this class */
+ Oid relnamespace BKI_DEFAULT(PGNSP);
+
+ /* OID of entry in pg_type for table's implicit row type */
+ Oid reltype BKI_LOOKUP(pg_type);
+
+ /* OID of entry in pg_type for underlying composite type */
+ Oid reloftype BKI_DEFAULT(0) BKI_LOOKUP(pg_type);
+
+ /* class owner */
+ Oid relowner BKI_DEFAULT(PGUID);
+
+ /* access method; 0 if not a table / index */
+ Oid relam BKI_DEFAULT(heap) BKI_LOOKUP(pg_am);
+
+ /* identifier of physical storage file */
+ /* relfilenode == 0 means it is a "mapped" relation, see relmapper.c */
+ Oid relfilenode BKI_DEFAULT(0);
+
+ /* identifier of table space for relation (0 means default for database) */
+ Oid reltablespace BKI_DEFAULT(0) BKI_LOOKUP(pg_tablespace);
+
+ /* # of blocks (not always up-to-date) */
+ int32 relpages BKI_DEFAULT(0);
+
+ /* # of tuples (not always up-to-date) */
+ float4 reltuples BKI_DEFAULT(0);
+
+ /* # of all-visible blocks (not always up-to-date) */
+ int32 relallvisible BKI_DEFAULT(0);
+
+ /* OID of toast table; 0 if none */
+ Oid reltoastrelid BKI_DEFAULT(0);
+
+ /* T if has (or has had) any indexes */
+ bool relhasindex BKI_DEFAULT(f);
+
+ /* T if shared across databases */
+ bool relisshared BKI_DEFAULT(f);
+
+ /* see RELPERSISTENCE_xxx constants below */
+ char relpersistence BKI_DEFAULT(p);
+
+ /* see RELKIND_xxx constants below */
+ char relkind BKI_DEFAULT(r);
+
+ /* number of user attributes */
+ int16 relnatts BKI_DEFAULT(0); /* genbki.pl will fill this in */
+
+ /*
+ * Class pg_attribute must contain exactly "relnatts" user attributes
+ * (with attnums ranging from 1 to relnatts) for this class. It may also
+ * contain entries with negative attnums for system attributes.
+ */
+
+ /* # of CHECK constraints for class */
+ int16 relchecks BKI_DEFAULT(0);
+
+ /* has (or has had) any rules */
+ bool relhasrules BKI_DEFAULT(f);
+
+ /* has (or has had) any TRIGGERs */
+ bool relhastriggers BKI_DEFAULT(f);
+
+ /* has (or has had) child tables or indexes */
+ bool relhassubclass BKI_DEFAULT(f);
+
+ /* row security is enabled or not */
+ bool relrowsecurity BKI_DEFAULT(f);
+
+ /* row security forced for owners or not */
+ bool relforcerowsecurity BKI_DEFAULT(f);
+
+ /* matview currently holds query results */
+ bool relispopulated BKI_DEFAULT(t);
+
+ /* see REPLICA_IDENTITY_xxx constants */
+ char relreplident BKI_DEFAULT(n);
+
+ /* is relation a partition? */
+ bool relispartition BKI_DEFAULT(f);
+
+ /* heap for rewrite during DDL, link to original rel */
+ Oid relrewrite BKI_DEFAULT(0);
+
+ /* all Xids < this are frozen in this rel */
+ TransactionId relfrozenxid BKI_DEFAULT(3); /* FirstNormalTransactionId */
+
+ /* all multixacts in this rel are >= this; it is really a MultiXactId */
+ TransactionId relminmxid BKI_DEFAULT(1); /* FirstMultiXactId */
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ /* NOTE: These fields are not present in a relcache entry's rd_rel field. */
+ /* access permissions */
+ aclitem relacl[1] BKI_DEFAULT(_null_);
+
+ /* access-method-specific options */
+ text reloptions[1] BKI_DEFAULT(_null_);
+
+ /* partition bound node tree */
+ pg_node_tree relpartbound BKI_DEFAULT(_null_);
+#endif
+} FormData_pg_class;
+
+/* Size of fixed part of pg_class tuples, not counting var-length fields */
+#define CLASS_TUPLE_SIZE \
+ (offsetof(FormData_pg_class,relminmxid) + sizeof(TransactionId))
+
+/* ----------------
+ * Form_pg_class corresponds to a pointer to a tuple with
+ * the format of pg_class relation.
+ * ----------------
+ */
+typedef FormData_pg_class *Form_pg_class;
+
+#ifdef EXPOSE_TO_CLIENT_CODE
+
+#define RELKIND_RELATION 'r' /* ordinary table */
+#define RELKIND_INDEX 'i' /* secondary index */
+#define RELKIND_SEQUENCE 'S' /* sequence object */
+#define RELKIND_TOASTVALUE 't' /* for out-of-line values */
+#define RELKIND_VIEW 'v' /* view */
+#define RELKIND_MATVIEW 'm' /* materialized view */
+#define RELKIND_COMPOSITE_TYPE 'c' /* composite type */
+#define RELKIND_FOREIGN_TABLE 'f' /* foreign table */
+#define RELKIND_PARTITIONED_TABLE 'p' /* partitioned table */
+#define RELKIND_PARTITIONED_INDEX 'I' /* partitioned index */
+
+#define RELPERSISTENCE_PERMANENT 'p' /* regular table */
+#define RELPERSISTENCE_UNLOGGED 'u' /* unlogged permanent table */
+#define RELPERSISTENCE_TEMP 't' /* temporary table */
+
+/* default selection for replica identity (primary key or nothing) */
+#define REPLICA_IDENTITY_DEFAULT 'd'
+/* no replica identity is logged for this relation */
+#define REPLICA_IDENTITY_NOTHING 'n'
+/* all columns are logged as replica identity */
+#define REPLICA_IDENTITY_FULL 'f'
+/*
+ * an explicitly chosen candidate key's columns are used as replica identity.
+ * Note this will still be set if the index has been dropped; in that case it
+ * has the same meaning as 'd'.
+ */
+#define REPLICA_IDENTITY_INDEX 'i'
+
+/*
+ * Relation kinds that have physical storage. These relations normally have
+ * relfilenode set to non-zero, but it can also be zero if the relation is
+ * mapped.
+ */
+#define RELKIND_HAS_STORAGE(relkind) \
+ ((relkind) == RELKIND_RELATION || \
+ (relkind) == RELKIND_INDEX || \
+ (relkind) == RELKIND_SEQUENCE || \
+ (relkind) == RELKIND_TOASTVALUE || \
+ (relkind) == RELKIND_MATVIEW)
+
+
+#endif /* EXPOSE_TO_CLIENT_CODE */
+
+#endif /* PG_CLASS_H */
diff --git a/src/include/catalog/pg_collation.dat b/src/include/catalog/pg_collation.dat
new file mode 100644
index 0000000..ba1b3e2
--- /dev/null
+++ b/src/include/catalog/pg_collation.dat
@@ -0,0 +1,31 @@
+#----------------------------------------------------------------------
+#
+# pg_collation.dat
+# Initial contents of the pg_collation system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_collation.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+{ oid => '100', oid_symbol => 'DEFAULT_COLLATION_OID',
+ descr => 'database\'s default collation',
+ collname => 'default', collnamespace => 'PGNSP', collowner => 'PGUID',
+ collprovider => 'd', collencoding => '-1', collcollate => '', collctype => '',
+ collversion => '_null_' },
+{ oid => '950', oid_symbol => 'C_COLLATION_OID',
+ descr => 'standard C collation',
+ collname => 'C', collnamespace => 'PGNSP', collowner => 'PGUID',
+ collprovider => 'c', collencoding => '-1', collcollate => 'C',
+ collctype => 'C', collversion => '_null_' },
+{ oid => '951', oid_symbol => 'POSIX_COLLATION_OID',
+ descr => 'standard POSIX collation',
+ collname => 'POSIX', collnamespace => 'PGNSP', collowner => 'PGUID',
+ collprovider => 'c', collencoding => '-1', collcollate => 'POSIX',
+ collctype => 'POSIX', collversion => '_null_' },
+
+]
diff --git a/src/include/catalog/pg_collation.h b/src/include/catalog/pg_collation.h
new file mode 100644
index 0000000..6955bb1
--- /dev/null
+++ b/src/include/catalog/pg_collation.h
@@ -0,0 +1,73 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_collation.h
+ * definition of the "collation" system catalog (pg_collation)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_collation.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_COLLATION_H
+#define PG_COLLATION_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_collation_d.h"
+
+/* ----------------
+ * pg_collation definition. cpp turns this into
+ * typedef struct FormData_pg_collation
+ * ----------------
+ */
+CATALOG(pg_collation,3456,CollationRelationId)
+{
+ Oid oid; /* oid */
+ NameData collname; /* collation name */
+ Oid collnamespace; /* OID of namespace containing collation */
+ Oid collowner; /* owner of collation */
+ char collprovider; /* see constants below */
+ bool collisdeterministic BKI_DEFAULT(t);
+ int32 collencoding; /* encoding for this collation; -1 = "all" */
+ NameData collcollate; /* LC_COLLATE setting */
+ NameData collctype; /* LC_CTYPE setting */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ text collversion; /* provider-dependent version of collation
+ * data */
+#endif
+} FormData_pg_collation;
+
+/* ----------------
+ * Form_pg_collation corresponds to a pointer to a row with
+ * the format of pg_collation relation.
+ * ----------------
+ */
+typedef FormData_pg_collation *Form_pg_collation;
+
+#ifdef EXPOSE_TO_CLIENT_CODE
+
+#define COLLPROVIDER_DEFAULT 'd'
+#define COLLPROVIDER_ICU 'i'
+#define COLLPROVIDER_LIBC 'c'
+
+#endif /* EXPOSE_TO_CLIENT_CODE */
+
+
+extern Oid CollationCreate(const char *collname, Oid collnamespace,
+ Oid collowner,
+ char collprovider,
+ bool collisdeterministic,
+ int32 collencoding,
+ const char *collcollate, const char *collctype,
+ const char *collversion,
+ bool if_not_exists,
+ bool quiet);
+extern void RemoveCollationById(Oid collationOid);
+
+#endif /* PG_COLLATION_H */
diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
new file mode 100644
index 0000000..9600ece
--- /dev/null
+++ b/src/include/catalog/pg_constraint.h
@@ -0,0 +1,247 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_constraint.h
+ * definition of the "constraint" system catalog (pg_constraint)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_constraint.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_CONSTRAINT_H
+#define PG_CONSTRAINT_H
+
+#include "catalog/dependency.h"
+#include "catalog/genbki.h"
+#include "catalog/pg_constraint_d.h"
+#include "nodes/pg_list.h"
+
+/* ----------------
+ * pg_constraint definition. cpp turns this into
+ * typedef struct FormData_pg_constraint
+ * ----------------
+ */
+CATALOG(pg_constraint,2606,ConstraintRelationId)
+{
+ Oid oid; /* oid */
+
+ /*
+ * conname + connamespace is deliberately not unique; we allow, for
+ * example, the same name to be used for constraints of different
+ * relations. This is partly for backwards compatibility with past
+ * Postgres practice, and partly because we don't want to have to obtain a
+ * global lock to generate a globally unique name for a nameless
+ * constraint. We associate a namespace with constraint names only for
+ * SQL-spec compatibility.
+ *
+ * However, we do require conname to be unique among the constraints of a
+ * single relation or domain. This is enforced by a unique index on
+ * conrelid + contypid + conname.
+ */
+ NameData conname; /* name of this constraint */
+ Oid connamespace; /* OID of namespace containing constraint */
+ char contype; /* constraint type; see codes below */
+ bool condeferrable; /* deferrable constraint? */
+ bool condeferred; /* deferred by default? */
+ bool convalidated; /* constraint has been validated? */
+
+ /*
+ * conrelid and conkey are only meaningful if the constraint applies to a
+ * specific relation (this excludes domain constraints and assertions).
+ * Otherwise conrelid is 0 and conkey is NULL.
+ */
+ Oid conrelid; /* relation this constraint constrains */
+
+ /*
+ * contypid links to the pg_type row for a domain if this is a domain
+ * constraint. Otherwise it's 0.
+ *
+ * For SQL-style global ASSERTIONs, both conrelid and contypid would be
+ * zero. This is not presently supported, however.
+ */
+ Oid contypid; /* domain this constraint constrains */
+
+ /*
+ * conindid links to the index supporting the constraint, if any;
+ * otherwise it's 0. This is used for unique, primary-key, and exclusion
+ * constraints, and less obviously for foreign-key constraints (where the
+ * index is a unique index on the referenced relation's referenced
+ * columns). Notice that the index is on conrelid in the first case but
+ * confrelid in the second.
+ */
+ Oid conindid; /* index supporting this constraint */
+
+ /*
+ * If this constraint is on a partition inherited from a partitioned
+ * table, this is the OID of the corresponding constraint in the parent.
+ */
+ Oid conparentid;
+
+ /*
+ * These fields, plus confkey, are only meaningful for a foreign-key
+ * constraint. Otherwise confrelid is 0 and the char fields are spaces.
+ */
+ Oid confrelid; /* relation referenced by foreign key */
+ char confupdtype; /* foreign key's ON UPDATE action */
+ char confdeltype; /* foreign key's ON DELETE action */
+ char confmatchtype; /* foreign key's match type */
+
+ /* Has a local definition (hence, do not drop when coninhcount is 0) */
+ bool conislocal;
+
+ /* Number of times inherited from direct parent relation(s) */
+ int32 coninhcount;
+
+ /* Has a local definition and cannot be inherited */
+ bool connoinherit;
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+
+ /*
+ * Columns of conrelid that the constraint applies to, if known (this is
+ * NULL for trigger constraints)
+ */
+ int16 conkey[1];
+
+ /*
+ * If a foreign key, the referenced columns of confrelid
+ */
+ int16 confkey[1];
+
+ /*
+ * If a foreign key, the OIDs of the PK = FK equality operators for each
+ * column of the constraint
+ */
+ Oid conpfeqop[1];
+
+ /*
+ * If a foreign key, the OIDs of the PK = PK equality operators for each
+ * column of the constraint (i.e., equality for the referenced columns)
+ */
+ Oid conppeqop[1];
+
+ /*
+ * If a foreign key, the OIDs of the FK = FK equality operators for each
+ * column of the constraint (i.e., equality for the referencing columns)
+ */
+ Oid conffeqop[1];
+
+ /*
+ * If an exclusion constraint, the OIDs of the exclusion operators for
+ * each column of the constraint
+ */
+ Oid conexclop[1];
+
+ /*
+ * If a check constraint, nodeToString representation of expression
+ */
+ pg_node_tree conbin;
+#endif
+} FormData_pg_constraint;
+
+/* ----------------
+ * Form_pg_constraint corresponds to a pointer to a tuple with
+ * the format of pg_constraint relation.
+ * ----------------
+ */
+typedef FormData_pg_constraint *Form_pg_constraint;
+
+#ifdef EXPOSE_TO_CLIENT_CODE
+
+/* Valid values for contype */
+#define CONSTRAINT_CHECK 'c'
+#define CONSTRAINT_FOREIGN 'f'
+#define CONSTRAINT_PRIMARY 'p'
+#define CONSTRAINT_UNIQUE 'u'
+#define CONSTRAINT_TRIGGER 't'
+#define CONSTRAINT_EXCLUSION 'x'
+
+/*
+ * Valid values for confupdtype and confdeltype are the FKCONSTR_ACTION_xxx
+ * constants defined in parsenodes.h. Valid values for confmatchtype are
+ * the FKCONSTR_MATCH_xxx constants defined in parsenodes.h.
+ */
+
+#endif /* EXPOSE_TO_CLIENT_CODE */
+
+/*
+ * Identify constraint type for lookup purposes
+ */
+typedef enum ConstraintCategory
+{
+ CONSTRAINT_RELATION,
+ CONSTRAINT_DOMAIN,
+ CONSTRAINT_ASSERTION /* for future expansion */
+} ConstraintCategory;
+
+
+extern Oid CreateConstraintEntry(const char *constraintName,
+ Oid constraintNamespace,
+ char constraintType,
+ bool isDeferrable,
+ bool isDeferred,
+ bool isValidated,
+ Oid parentConstrId,
+ Oid relId,
+ const int16 *constraintKey,
+ int constraintNKeys,
+ int constraintNTotalKeys,
+ Oid domainId,
+ Oid indexRelId,
+ Oid foreignRelId,
+ const int16 *foreignKey,
+ const Oid *pfEqOp,
+ const Oid *ppEqOp,
+ const Oid *ffEqOp,
+ int foreignNKeys,
+ char foreignUpdateType,
+ char foreignDeleteType,
+ char foreignMatchType,
+ const Oid *exclOp,
+ Node *conExpr,
+ const char *conBin,
+ bool conIsLocal,
+ int conInhCount,
+ bool conNoInherit,
+ bool is_internal);
+
+extern void RemoveConstraintById(Oid conId);
+extern void RenameConstraintById(Oid conId, const char *newname);
+
+extern bool ConstraintNameIsUsed(ConstraintCategory conCat, Oid objId,
+ const char *conname);
+extern bool ConstraintNameExists(const char *conname, Oid namespaceid);
+extern char *ChooseConstraintName(const char *name1, const char *name2,
+ const char *label, Oid namespaceid,
+ List *others);
+
+extern void AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
+ Oid newNspId, bool isType, ObjectAddresses *objsMoved);
+extern void ConstraintSetParentConstraint(Oid childConstrId,
+ Oid parentConstrId,
+ Oid childTableId);
+extern Oid get_relation_constraint_oid(Oid relid, const char *conname, bool missing_ok);
+extern Bitmapset *get_relation_constraint_attnos(Oid relid, const char *conname,
+ bool missing_ok, Oid *constraintOid);
+extern Oid get_domain_constraint_oid(Oid typid, const char *conname, bool missing_ok);
+extern Oid get_relation_idx_constraint_oid(Oid relationId, Oid indexId);
+
+extern Bitmapset *get_primary_key_attnos(Oid relid, bool deferrableOk,
+ Oid *constraintOid);
+extern void DeconstructFkConstraintRow(HeapTuple tuple, int *numfks,
+ AttrNumber *conkey, AttrNumber *confkey,
+ Oid *pf_eq_oprs, Oid *pp_eq_oprs, Oid *ff_eq_oprs);
+
+extern bool check_functional_grouping(Oid relid,
+ Index varno, Index varlevelsup,
+ List *grouping_columns,
+ List **constraintDeps);
+
+#endif /* PG_CONSTRAINT_H */
diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h
new file mode 100644
index 0000000..de5670e
--- /dev/null
+++ b/src/include/catalog/pg_control.h
@@ -0,0 +1,250 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_control.h
+ * The system control file "pg_control" is not a heap relation.
+ * However, we define it here so that the format is documented.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_control.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_CONTROL_H
+#define PG_CONTROL_H
+
+#include "access/transam.h"
+#include "access/xlogdefs.h"
+#include "pgtime.h" /* for pg_time_t */
+#include "port/pg_crc32c.h"
+
+
+/* Version identifier for this pg_control format */
+#define PG_CONTROL_VERSION 1300
+
+/* Nonce key length, see below */
+#define MOCK_AUTH_NONCE_LEN 32
+
+/*
+ * Body of CheckPoint XLOG records. This is declared here because we keep
+ * a copy of the latest one in pg_control for possible disaster recovery.
+ * Changing this struct requires a PG_CONTROL_VERSION bump.
+ */
+typedef struct CheckPoint
+{
+ XLogRecPtr redo; /* next RecPtr available when we began to
+ * create CheckPoint (i.e. REDO start point) */
+ TimeLineID ThisTimeLineID; /* current TLI */
+ TimeLineID PrevTimeLineID; /* previous TLI, if this record begins a new
+ * timeline (equals ThisTimeLineID otherwise) */
+ bool fullPageWrites; /* current full_page_writes */
+ FullTransactionId nextFullXid; /* next free full transaction ID */
+ Oid nextOid; /* next free OID */
+ MultiXactId nextMulti; /* next free MultiXactId */
+ MultiXactOffset nextMultiOffset; /* next free MultiXact offset */
+ TransactionId oldestXid; /* cluster-wide minimum datfrozenxid */
+ Oid oldestXidDB; /* database with minimum datfrozenxid */
+ MultiXactId oldestMulti; /* cluster-wide minimum datminmxid */
+ Oid oldestMultiDB; /* database with minimum datminmxid */
+ pg_time_t time; /* time stamp of checkpoint */
+ TransactionId oldestCommitTsXid; /* oldest Xid with valid commit
+ * timestamp */
+ TransactionId newestCommitTsXid; /* newest Xid with valid commit
+ * timestamp */
+
+ /*
+ * Oldest XID still running. This is only needed to initialize hot standby
+ * mode from an online checkpoint, so we only bother calculating this for
+ * online checkpoints and only when wal_level is replica. Otherwise it's
+ * set to InvalidTransactionId.
+ */
+ TransactionId oldestActiveXid;
+} CheckPoint;
+
+/* XLOG info values for XLOG rmgr */
+#define XLOG_CHECKPOINT_SHUTDOWN 0x00
+#define XLOG_CHECKPOINT_ONLINE 0x10
+#define XLOG_NOOP 0x20
+#define XLOG_NEXTOID 0x30
+#define XLOG_SWITCH 0x40
+#define XLOG_BACKUP_END 0x50
+#define XLOG_PARAMETER_CHANGE 0x60
+#define XLOG_RESTORE_POINT 0x70
+#define XLOG_FPW_CHANGE 0x80
+#define XLOG_END_OF_RECOVERY 0x90
+#define XLOG_FPI_FOR_HINT 0xA0
+#define XLOG_FPI 0xB0
+
+
+/*
+ * System status indicator. Note this is stored in pg_control; if you change
+ * it, you must bump PG_CONTROL_VERSION
+ */
+typedef enum DBState
+{
+ DB_STARTUP = 0,
+ DB_SHUTDOWNED,
+ DB_SHUTDOWNED_IN_RECOVERY,
+ DB_SHUTDOWNING,
+ DB_IN_CRASH_RECOVERY,
+ DB_IN_ARCHIVE_RECOVERY,
+ DB_IN_PRODUCTION
+} DBState;
+
+/*
+ * Contents of pg_control.
+ */
+
+typedef struct ControlFileData
+{
+ /*
+ * Unique system identifier --- to ensure we match up xlog files with the
+ * installation that produced them.
+ */
+ uint64 system_identifier;
+
+ /*
+ * Version identifier information. Keep these fields at the same offset,
+ * especially pg_control_version; they won't be real useful if they move
+ * around. (For historical reasons they must be 8 bytes into the file
+ * rather than immediately at the front.)
+ *
+ * pg_control_version identifies the format of pg_control itself.
+ * catalog_version_no identifies the format of the system catalogs.
+ *
+ * There are additional version identifiers in individual files; for
+ * example, WAL logs contain per-page magic numbers that can serve as
+ * version cues for the WAL log.
+ */
+ uint32 pg_control_version; /* PG_CONTROL_VERSION */
+ uint32 catalog_version_no; /* see catversion.h */
+
+ /*
+ * System status data
+ */
+ DBState state; /* see enum above */
+ pg_time_t time; /* time stamp of last pg_control update */
+ XLogRecPtr checkPoint; /* last check point record ptr */
+
+ CheckPoint checkPointCopy; /* copy of last check point record */
+
+ XLogRecPtr unloggedLSN; /* current fake LSN value, for unlogged rels */
+
+ /*
+ * These two values determine the minimum point we must recover up to
+ * before starting up:
+ *
+ * minRecoveryPoint is updated to the latest replayed LSN whenever we
+ * flush a data change during archive recovery. That guards against
+ * starting archive recovery, aborting it, and restarting with an earlier
+ * stop location. If we've already flushed data changes from WAL record X
+ * to disk, we mustn't start up until we reach X again. Zero when not
+ * doing archive recovery.
+ *
+ * backupStartPoint is the redo pointer of the backup start checkpoint, if
+ * we are recovering from an online backup and haven't reached the end of
+ * backup yet. It is reset to zero when the end of backup is reached, and
+ * we mustn't start up before that. A boolean would suffice otherwise, but
+ * we use the redo pointer as a cross-check when we see an end-of-backup
+ * record, to make sure the end-of-backup record corresponds the base
+ * backup we're recovering from.
+ *
+ * backupEndPoint is the backup end location, if we are recovering from an
+ * online backup which was taken from the standby and haven't reached the
+ * end of backup yet. It is initialized to the minimum recovery point in
+ * pg_control which was backed up last. It is reset to zero when the end
+ * of backup is reached, and we mustn't start up before that.
+ *
+ * If backupEndRequired is true, we know for sure that we're restoring
+ * from a backup, and must see a backup-end record before we can safely
+ * start up. If it's false, but backupStartPoint is set, a backup_label
+ * file was found at startup but it may have been a leftover from a stray
+ * pg_start_backup() call, not accompanied by pg_stop_backup().
+ */
+ XLogRecPtr minRecoveryPoint;
+ TimeLineID minRecoveryPointTLI;
+ XLogRecPtr backupStartPoint;
+ XLogRecPtr backupEndPoint;
+ bool backupEndRequired;
+
+ /*
+ * Parameter settings that determine if the WAL can be used for archival
+ * or hot standby.
+ */
+ int wal_level;
+ bool wal_log_hints;
+ int MaxConnections;
+ int max_worker_processes;
+ int max_wal_senders;
+ int max_prepared_xacts;
+ int max_locks_per_xact;
+ bool track_commit_timestamp;
+
+ /*
+ * This data is used to check for hardware-architecture compatibility of
+ * the database and the backend executable. We need not check endianness
+ * explicitly, since the pg_control version will surely look wrong to a
+ * machine of different endianness, but we do need to worry about MAXALIGN
+ * and floating-point format. (Note: storage layout nominally also
+ * depends on SHORTALIGN and INTALIGN, but in practice these are the same
+ * on all architectures of interest.)
+ *
+ * Testing just one double value is not a very bulletproof test for
+ * floating-point compatibility, but it will catch most cases.
+ */
+ uint32 maxAlign; /* alignment requirement for tuples */
+ double floatFormat; /* constant 1234567.0 */
+#define FLOATFORMAT_VALUE 1234567.0
+
+ /*
+ * This data is used to make sure that configuration of this database is
+ * compatible with the backend executable.
+ */
+ uint32 blcksz; /* data block size for this DB */
+ uint32 relseg_size; /* blocks per segment of large relation */
+
+ uint32 xlog_blcksz; /* block size within WAL files */
+ uint32 xlog_seg_size; /* size of each WAL segment */
+
+ uint32 nameDataLen; /* catalog name field width */
+ uint32 indexMaxKeys; /* max number of columns in an index */
+
+ uint32 toast_max_chunk_size; /* chunk size in TOAST tables */
+ uint32 loblksize; /* chunk size in pg_largeobject */
+
+ bool float8ByVal; /* float8, int8, etc pass-by-value? */
+
+ /* Are data pages protected by checksums? Zero if no checksum version */
+ uint32 data_checksum_version;
+
+ /*
+ * Random nonce, used in authentication requests that need to proceed
+ * based on values that are cluster-unique, like a SASL exchange that
+ * failed at an early stage.
+ */
+ char mock_authentication_nonce[MOCK_AUTH_NONCE_LEN];
+
+ /* CRC of all above ... MUST BE LAST! */
+ pg_crc32c crc;
+} ControlFileData;
+
+/*
+ * Maximum safe value of sizeof(ControlFileData). For reliability's sake,
+ * it's critical that pg_control updates be atomic writes. That generally
+ * means the active data can't be more than one disk sector, which is 512
+ * bytes on common hardware. Be very careful about raising this limit.
+ */
+#define PG_CONTROL_MAX_SAFE_SIZE 512
+
+/*
+ * Physical size of the pg_control file. Note that this is considerably
+ * bigger than the actually used size (ie, sizeof(ControlFileData)).
+ * The idea is to keep the physical size constant independent of format
+ * changes, so that ReadControlFile will deliver a suitable wrong-version
+ * message instead of a read error if it's looking at an incompatible file.
+ */
+#define PG_CONTROL_FILE_SIZE 8192
+
+#endif /* PG_CONTROL_H */
diff --git a/src/include/catalog/pg_conversion.dat b/src/include/catalog/pg_conversion.dat
new file mode 100644
index 0000000..d7120f2
--- /dev/null
+++ b/src/include/catalog/pg_conversion.dat
@@ -0,0 +1,405 @@
+#----------------------------------------------------------------------
+#
+# pg_conversion.dat
+# Initial contents of the pg_conversion system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_conversion.dat
+#
+#----------------------------------------------------------------------
+
+# Note: conforencoding and contoencoding must match the spelling of
+# the labels used in the enum pg_enc in mb/pg_wchar.h.
+
+[
+
+{ oid => '4402', descr => 'conversion for KOI8R to MULE_INTERNAL',
+ conname => 'koi8_r_to_mic', conforencoding => 'PG_KOI8R',
+ contoencoding => 'PG_MULE_INTERNAL', conproc => 'koi8r_to_mic' },
+{ oid => '4403', descr => 'conversion for MULE_INTERNAL to KOI8R',
+ conname => 'mic_to_koi8_r', conforencoding => 'PG_MULE_INTERNAL',
+ contoencoding => 'PG_KOI8R', conproc => 'mic_to_koi8r' },
+{ oid => '4404', descr => 'conversion for ISO-8859-5 to MULE_INTERNAL',
+ conname => 'iso_8859_5_to_mic', conforencoding => 'PG_ISO_8859_5',
+ contoencoding => 'PG_MULE_INTERNAL', conproc => 'iso_to_mic' },
+{ oid => '4405', descr => 'conversion for MULE_INTERNAL to ISO-8859-5',
+ conname => 'mic_to_iso_8859_5', conforencoding => 'PG_MULE_INTERNAL',
+ contoencoding => 'PG_ISO_8859_5', conproc => 'mic_to_iso' },
+{ oid => '4406', descr => 'conversion for WIN1251 to MULE_INTERNAL',
+ conname => 'windows_1251_to_mic', conforencoding => 'PG_WIN1251',
+ contoencoding => 'PG_MULE_INTERNAL', conproc => 'win1251_to_mic' },
+{ oid => '4407', descr => 'conversion for MULE_INTERNAL to WIN1251',
+ conname => 'mic_to_windows_1251', conforencoding => 'PG_MULE_INTERNAL',
+ contoencoding => 'PG_WIN1251', conproc => 'mic_to_win1251' },
+{ oid => '4408', descr => 'conversion for WIN866 to MULE_INTERNAL',
+ conname => 'windows_866_to_mic', conforencoding => 'PG_WIN866',
+ contoencoding => 'PG_MULE_INTERNAL', conproc => 'win866_to_mic' },
+{ oid => '4409', descr => 'conversion for MULE_INTERNAL to WIN866',
+ conname => 'mic_to_windows_866', conforencoding => 'PG_MULE_INTERNAL',
+ contoencoding => 'PG_WIN866', conproc => 'mic_to_win866' },
+{ oid => '4410', descr => 'conversion for KOI8R to WIN1251',
+ conname => 'koi8_r_to_windows_1251', conforencoding => 'PG_KOI8R',
+ contoencoding => 'PG_WIN1251', conproc => 'koi8r_to_win1251' },
+{ oid => '4411', descr => 'conversion for WIN1251 to KOI8R',
+ conname => 'windows_1251_to_koi8_r', conforencoding => 'PG_WIN1251',
+ contoencoding => 'PG_KOI8R', conproc => 'win1251_to_koi8r' },
+{ oid => '4412', descr => 'conversion for KOI8R to WIN866',
+ conname => 'koi8_r_to_windows_866', conforencoding => 'PG_KOI8R',
+ contoencoding => 'PG_WIN866', conproc => 'koi8r_to_win866' },
+{ oid => '4413', descr => 'conversion for WIN866 to KOI8R',
+ conname => 'windows_866_to_koi8_r', conforencoding => 'PG_WIN866',
+ contoencoding => 'PG_KOI8R', conproc => 'win866_to_koi8r' },
+{ oid => '4414', descr => 'conversion for WIN866 to WIN1251',
+ conname => 'windows_866_to_windows_1251', conforencoding => 'PG_WIN866',
+ contoencoding => 'PG_WIN1251', conproc => 'win866_to_win1251' },
+{ oid => '4415', descr => 'conversion for WIN1251 to WIN866',
+ conname => 'windows_1251_to_windows_866', conforencoding => 'PG_WIN1251',
+ contoencoding => 'PG_WIN866', conproc => 'win1251_to_win866' },
+{ oid => '4416', descr => 'conversion for ISO-8859-5 to KOI8R',
+ conname => 'iso_8859_5_to_koi8_r', conforencoding => 'PG_ISO_8859_5',
+ contoencoding => 'PG_KOI8R', conproc => 'iso_to_koi8r' },
+{ oid => '4417', descr => 'conversion for KOI8R to ISO-8859-5',
+ conname => 'koi8_r_to_iso_8859_5', conforencoding => 'PG_KOI8R',
+ contoencoding => 'PG_ISO_8859_5', conproc => 'koi8r_to_iso' },
+{ oid => '4418', descr => 'conversion for ISO-8859-5 to WIN1251',
+ conname => 'iso_8859_5_to_windows_1251', conforencoding => 'PG_ISO_8859_5',
+ contoencoding => 'PG_WIN1251', conproc => 'iso_to_win1251' },
+{ oid => '4419', descr => 'conversion for WIN1251 to ISO-8859-5',
+ conname => 'windows_1251_to_iso_8859_5', conforencoding => 'PG_WIN1251',
+ contoencoding => 'PG_ISO_8859_5', conproc => 'win1251_to_iso' },
+{ oid => '4420', descr => 'conversion for ISO-8859-5 to WIN866',
+ conname => 'iso_8859_5_to_windows_866', conforencoding => 'PG_ISO_8859_5',
+ contoencoding => 'PG_WIN866', conproc => 'iso_to_win866' },
+{ oid => '4421', descr => 'conversion for WIN866 to ISO-8859-5',
+ conname => 'windows_866_to_iso_8859_5', conforencoding => 'PG_WIN866',
+ contoencoding => 'PG_ISO_8859_5', conproc => 'win866_to_iso' },
+{ oid => '4422', descr => 'conversion for EUC_CN to MULE_INTERNAL',
+ conname => 'euc_cn_to_mic', conforencoding => 'PG_EUC_CN',
+ contoencoding => 'PG_MULE_INTERNAL', conproc => 'euc_cn_to_mic' },
+{ oid => '4423', descr => 'conversion for MULE_INTERNAL to EUC_CN',
+ conname => 'mic_to_euc_cn', conforencoding => 'PG_MULE_INTERNAL',
+ contoencoding => 'PG_EUC_CN', conproc => 'mic_to_euc_cn' },
+{ oid => '4424', descr => 'conversion for EUC_JP to SJIS',
+ conname => 'euc_jp_to_sjis', conforencoding => 'PG_EUC_JP',
+ contoencoding => 'PG_SJIS', conproc => 'euc_jp_to_sjis' },
+{ oid => '4425', descr => 'conversion for SJIS to EUC_JP',
+ conname => 'sjis_to_euc_jp', conforencoding => 'PG_SJIS',
+ contoencoding => 'PG_EUC_JP', conproc => 'sjis_to_euc_jp' },
+{ oid => '4426', descr => 'conversion for EUC_JP to MULE_INTERNAL',
+ conname => 'euc_jp_to_mic', conforencoding => 'PG_EUC_JP',
+ contoencoding => 'PG_MULE_INTERNAL', conproc => 'euc_jp_to_mic' },
+{ oid => '4427', descr => 'conversion for SJIS to MULE_INTERNAL',
+ conname => 'sjis_to_mic', conforencoding => 'PG_SJIS',
+ contoencoding => 'PG_MULE_INTERNAL', conproc => 'sjis_to_mic' },
+{ oid => '4428', descr => 'conversion for MULE_INTERNAL to EUC_JP',
+ conname => 'mic_to_euc_jp', conforencoding => 'PG_MULE_INTERNAL',
+ contoencoding => 'PG_EUC_JP', conproc => 'mic_to_euc_jp' },
+{ oid => '4429', descr => 'conversion for MULE_INTERNAL to SJIS',
+ conname => 'mic_to_sjis', conforencoding => 'PG_MULE_INTERNAL',
+ contoencoding => 'PG_SJIS', conproc => 'mic_to_sjis' },
+{ oid => '4430', descr => 'conversion for EUC_KR to MULE_INTERNAL',
+ conname => 'euc_kr_to_mic', conforencoding => 'PG_EUC_KR',
+ contoencoding => 'PG_MULE_INTERNAL', conproc => 'euc_kr_to_mic' },
+{ oid => '4431', descr => 'conversion for MULE_INTERNAL to EUC_KR',
+ conname => 'mic_to_euc_kr', conforencoding => 'PG_MULE_INTERNAL',
+ contoencoding => 'PG_EUC_KR', conproc => 'mic_to_euc_kr' },
+{ oid => '4432', descr => 'conversion for EUC_TW to BIG5',
+ conname => 'euc_tw_to_big5', conforencoding => 'PG_EUC_TW',
+ contoencoding => 'PG_BIG5', conproc => 'euc_tw_to_big5' },
+{ oid => '4433', descr => 'conversion for BIG5 to EUC_TW',
+ conname => 'big5_to_euc_tw', conforencoding => 'PG_BIG5',
+ contoencoding => 'PG_EUC_TW', conproc => 'big5_to_euc_tw' },
+{ oid => '4434', descr => 'conversion for EUC_TW to MULE_INTERNAL',
+ conname => 'euc_tw_to_mic', conforencoding => 'PG_EUC_TW',
+ contoencoding => 'PG_MULE_INTERNAL', conproc => 'euc_tw_to_mic' },
+{ oid => '4435', descr => 'conversion for BIG5 to MULE_INTERNAL',
+ conname => 'big5_to_mic', conforencoding => 'PG_BIG5',
+ contoencoding => 'PG_MULE_INTERNAL', conproc => 'big5_to_mic' },
+{ oid => '4436', descr => 'conversion for MULE_INTERNAL to EUC_TW',
+ conname => 'mic_to_euc_tw', conforencoding => 'PG_MULE_INTERNAL',
+ contoencoding => 'PG_EUC_TW', conproc => 'mic_to_euc_tw' },
+{ oid => '4437', descr => 'conversion for MULE_INTERNAL to BIG5',
+ conname => 'mic_to_big5', conforencoding => 'PG_MULE_INTERNAL',
+ contoencoding => 'PG_BIG5', conproc => 'mic_to_big5' },
+{ oid => '4438', descr => 'conversion for LATIN2 to MULE_INTERNAL',
+ conname => 'iso_8859_2_to_mic', conforencoding => 'PG_LATIN2',
+ contoencoding => 'PG_MULE_INTERNAL', conproc => 'latin2_to_mic' },
+{ oid => '4439', descr => 'conversion for MULE_INTERNAL to LATIN2',
+ conname => 'mic_to_iso_8859_2', conforencoding => 'PG_MULE_INTERNAL',
+ contoencoding => 'PG_LATIN2', conproc => 'mic_to_latin2' },
+{ oid => '4440', descr => 'conversion for WIN1250 to MULE_INTERNAL',
+ conname => 'windows_1250_to_mic', conforencoding => 'PG_WIN1250',
+ contoencoding => 'PG_MULE_INTERNAL', conproc => 'win1250_to_mic' },
+{ oid => '4441', descr => 'conversion for MULE_INTERNAL to WIN1250',
+ conname => 'mic_to_windows_1250', conforencoding => 'PG_MULE_INTERNAL',
+ contoencoding => 'PG_WIN1250', conproc => 'mic_to_win1250' },
+{ oid => '4442', descr => 'conversion for LATIN2 to WIN1250',
+ conname => 'iso_8859_2_to_windows_1250', conforencoding => 'PG_LATIN2',
+ contoencoding => 'PG_WIN1250', conproc => 'latin2_to_win1250' },
+{ oid => '4443', descr => 'conversion for WIN1250 to LATIN2',
+ conname => 'windows_1250_to_iso_8859_2', conforencoding => 'PG_WIN1250',
+ contoencoding => 'PG_LATIN2', conproc => 'win1250_to_latin2' },
+{ oid => '4444', descr => 'conversion for LATIN1 to MULE_INTERNAL',
+ conname => 'iso_8859_1_to_mic', conforencoding => 'PG_LATIN1',
+ contoencoding => 'PG_MULE_INTERNAL', conproc => 'latin1_to_mic' },
+{ oid => '4445', descr => 'conversion for MULE_INTERNAL to LATIN1',
+ conname => 'mic_to_iso_8859_1', conforencoding => 'PG_MULE_INTERNAL',
+ contoencoding => 'PG_LATIN1', conproc => 'mic_to_latin1' },
+{ oid => '4446', descr => 'conversion for LATIN3 to MULE_INTERNAL',
+ conname => 'iso_8859_3_to_mic', conforencoding => 'PG_LATIN3',
+ contoencoding => 'PG_MULE_INTERNAL', conproc => 'latin3_to_mic' },
+{ oid => '4447', descr => 'conversion for MULE_INTERNAL to LATIN3',
+ conname => 'mic_to_iso_8859_3', conforencoding => 'PG_MULE_INTERNAL',
+ contoencoding => 'PG_LATIN3', conproc => 'mic_to_latin3' },
+{ oid => '4448', descr => 'conversion for LATIN4 to MULE_INTERNAL',
+ conname => 'iso_8859_4_to_mic', conforencoding => 'PG_LATIN4',
+ contoencoding => 'PG_MULE_INTERNAL', conproc => 'latin4_to_mic' },
+{ oid => '4449', descr => 'conversion for MULE_INTERNAL to LATIN4',
+ conname => 'mic_to_iso_8859_4', conforencoding => 'PG_MULE_INTERNAL',
+ contoencoding => 'PG_LATIN4', conproc => 'mic_to_latin4' },
+{ oid => '4452', descr => 'conversion for BIG5 to UTF8',
+ conname => 'big5_to_utf8', conforencoding => 'PG_BIG5',
+ contoencoding => 'PG_UTF8', conproc => 'big5_to_utf8' },
+{ oid => '4453', descr => 'conversion for UTF8 to BIG5',
+ conname => 'utf8_to_big5', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_BIG5', conproc => 'utf8_to_big5' },
+{ oid => '4454', descr => 'conversion for UTF8 to KOI8R',
+ conname => 'utf8_to_koi8_r', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_KOI8R', conproc => 'utf8_to_koi8r' },
+{ oid => '4455', descr => 'conversion for KOI8R to UTF8',
+ conname => 'koi8_r_to_utf8', conforencoding => 'PG_KOI8R',
+ contoencoding => 'PG_UTF8', conproc => 'koi8r_to_utf8' },
+{ oid => '4456', descr => 'conversion for UTF8 to KOI8U',
+ conname => 'utf8_to_koi8_u', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_KOI8U', conproc => 'utf8_to_koi8u' },
+{ oid => '4457', descr => 'conversion for KOI8U to UTF8',
+ conname => 'koi8_u_to_utf8', conforencoding => 'PG_KOI8U',
+ contoencoding => 'PG_UTF8', conproc => 'koi8u_to_utf8' },
+{ oid => '4458', descr => 'conversion for UTF8 to WIN866',
+ conname => 'utf8_to_windows_866', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_WIN866', conproc => 'utf8_to_win' },
+{ oid => '4459', descr => 'conversion for WIN866 to UTF8',
+ conname => 'windows_866_to_utf8', conforencoding => 'PG_WIN866',
+ contoencoding => 'PG_UTF8', conproc => 'win_to_utf8' },
+{ oid => '4460', descr => 'conversion for UTF8 to WIN874',
+ conname => 'utf8_to_windows_874', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_WIN874', conproc => 'utf8_to_win' },
+{ oid => '4461', descr => 'conversion for WIN874 to UTF8',
+ conname => 'windows_874_to_utf8', conforencoding => 'PG_WIN874',
+ contoencoding => 'PG_UTF8', conproc => 'win_to_utf8' },
+{ oid => '4462', descr => 'conversion for UTF8 to WIN1250',
+ conname => 'utf8_to_windows_1250', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_WIN1250', conproc => 'utf8_to_win' },
+{ oid => '4463', descr => 'conversion for WIN1250 to UTF8',
+ conname => 'windows_1250_to_utf8', conforencoding => 'PG_WIN1250',
+ contoencoding => 'PG_UTF8', conproc => 'win_to_utf8' },
+{ oid => '4464', descr => 'conversion for UTF8 to WIN1251',
+ conname => 'utf8_to_windows_1251', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_WIN1251', conproc => 'utf8_to_win' },
+{ oid => '4465', descr => 'conversion for WIN1251 to UTF8',
+ conname => 'windows_1251_to_utf8', conforencoding => 'PG_WIN1251',
+ contoencoding => 'PG_UTF8', conproc => 'win_to_utf8' },
+{ oid => '4466', descr => 'conversion for UTF8 to WIN1252',
+ conname => 'utf8_to_windows_1252', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_WIN1252', conproc => 'utf8_to_win' },
+{ oid => '4467', descr => 'conversion for WIN1252 to UTF8',
+ conname => 'windows_1252_to_utf8', conforencoding => 'PG_WIN1252',
+ contoencoding => 'PG_UTF8', conproc => 'win_to_utf8' },
+{ oid => '4468', descr => 'conversion for UTF8 to WIN1253',
+ conname => 'utf8_to_windows_1253', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_WIN1253', conproc => 'utf8_to_win' },
+{ oid => '4469', descr => 'conversion for WIN1253 to UTF8',
+ conname => 'windows_1253_to_utf8', conforencoding => 'PG_WIN1253',
+ contoencoding => 'PG_UTF8', conproc => 'win_to_utf8' },
+{ oid => '4470', descr => 'conversion for UTF8 to WIN1254',
+ conname => 'utf8_to_windows_1254', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_WIN1254', conproc => 'utf8_to_win' },
+{ oid => '4471', descr => 'conversion for WIN1254 to UTF8',
+ conname => 'windows_1254_to_utf8', conforencoding => 'PG_WIN1254',
+ contoencoding => 'PG_UTF8', conproc => 'win_to_utf8' },
+{ oid => '4472', descr => 'conversion for UTF8 to WIN1255',
+ conname => 'utf8_to_windows_1255', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_WIN1255', conproc => 'utf8_to_win' },
+{ oid => '4473', descr => 'conversion for WIN1255 to UTF8',
+ conname => 'windows_1255_to_utf8', conforencoding => 'PG_WIN1255',
+ contoencoding => 'PG_UTF8', conproc => 'win_to_utf8' },
+{ oid => '4474', descr => 'conversion for UTF8 to WIN1256',
+ conname => 'utf8_to_windows_1256', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_WIN1256', conproc => 'utf8_to_win' },
+{ oid => '4475', descr => 'conversion for WIN1256 to UTF8',
+ conname => 'windows_1256_to_utf8', conforencoding => 'PG_WIN1256',
+ contoencoding => 'PG_UTF8', conproc => 'win_to_utf8' },
+{ oid => '4476', descr => 'conversion for UTF8 to WIN1257',
+ conname => 'utf8_to_windows_1257', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_WIN1257', conproc => 'utf8_to_win' },
+{ oid => '4477', descr => 'conversion for WIN1257 to UTF8',
+ conname => 'windows_1257_to_utf8', conforencoding => 'PG_WIN1257',
+ contoencoding => 'PG_UTF8', conproc => 'win_to_utf8' },
+{ oid => '4478', descr => 'conversion for UTF8 to WIN1258',
+ conname => 'utf8_to_windows_1258', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_WIN1258', conproc => 'utf8_to_win' },
+{ oid => '4479', descr => 'conversion for WIN1258 to UTF8',
+ conname => 'windows_1258_to_utf8', conforencoding => 'PG_WIN1258',
+ contoencoding => 'PG_UTF8', conproc => 'win_to_utf8' },
+{ oid => '4480', descr => 'conversion for EUC_CN to UTF8',
+ conname => 'euc_cn_to_utf8', conforencoding => 'PG_EUC_CN',
+ contoencoding => 'PG_UTF8', conproc => 'euc_cn_to_utf8' },
+{ oid => '4481', descr => 'conversion for UTF8 to EUC_CN',
+ conname => 'utf8_to_euc_cn', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_EUC_CN', conproc => 'utf8_to_euc_cn' },
+{ oid => '4482', descr => 'conversion for EUC_JP to UTF8',
+ conname => 'euc_jp_to_utf8', conforencoding => 'PG_EUC_JP',
+ contoencoding => 'PG_UTF8', conproc => 'euc_jp_to_utf8' },
+{ oid => '4483', descr => 'conversion for UTF8 to EUC_JP',
+ conname => 'utf8_to_euc_jp', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_EUC_JP', conproc => 'utf8_to_euc_jp' },
+{ oid => '4484', descr => 'conversion for EUC_KR to UTF8',
+ conname => 'euc_kr_to_utf8', conforencoding => 'PG_EUC_KR',
+ contoencoding => 'PG_UTF8', conproc => 'euc_kr_to_utf8' },
+{ oid => '4485', descr => 'conversion for UTF8 to EUC_KR',
+ conname => 'utf8_to_euc_kr', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_EUC_KR', conproc => 'utf8_to_euc_kr' },
+{ oid => '4486', descr => 'conversion for EUC_TW to UTF8',
+ conname => 'euc_tw_to_utf8', conforencoding => 'PG_EUC_TW',
+ contoencoding => 'PG_UTF8', conproc => 'euc_tw_to_utf8' },
+{ oid => '4487', descr => 'conversion for UTF8 to EUC_TW',
+ conname => 'utf8_to_euc_tw', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_EUC_TW', conproc => 'utf8_to_euc_tw' },
+{ oid => '4488', descr => 'conversion for GB18030 to UTF8',
+ conname => 'gb18030_to_utf8', conforencoding => 'PG_GB18030',
+ contoencoding => 'PG_UTF8', conproc => 'gb18030_to_utf8' },
+{ oid => '4489', descr => 'conversion for UTF8 to GB18030',
+ conname => 'utf8_to_gb18030', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_GB18030', conproc => 'utf8_to_gb18030' },
+{ oid => '4490', descr => 'conversion for GBK to UTF8',
+ conname => 'gbk_to_utf8', conforencoding => 'PG_GBK',
+ contoencoding => 'PG_UTF8', conproc => 'gbk_to_utf8' },
+{ oid => '4491', descr => 'conversion for UTF8 to GBK',
+ conname => 'utf8_to_gbk', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_GBK', conproc => 'utf8_to_gbk' },
+{ oid => '4492', descr => 'conversion for UTF8 to LATIN2',
+ conname => 'utf8_to_iso_8859_2', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_LATIN2', conproc => 'utf8_to_iso8859' },
+{ oid => '4493', descr => 'conversion for LATIN2 to UTF8',
+ conname => 'iso_8859_2_to_utf8', conforencoding => 'PG_LATIN2',
+ contoencoding => 'PG_UTF8', conproc => 'iso8859_to_utf8' },
+{ oid => '4494', descr => 'conversion for UTF8 to LATIN3',
+ conname => 'utf8_to_iso_8859_3', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_LATIN3', conproc => 'utf8_to_iso8859' },
+{ oid => '4495', descr => 'conversion for LATIN3 to UTF8',
+ conname => 'iso_8859_3_to_utf8', conforencoding => 'PG_LATIN3',
+ contoencoding => 'PG_UTF8', conproc => 'iso8859_to_utf8' },
+{ oid => '4496', descr => 'conversion for UTF8 to LATIN4',
+ conname => 'utf8_to_iso_8859_4', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_LATIN4', conproc => 'utf8_to_iso8859' },
+{ oid => '4497', descr => 'conversion for LATIN4 to UTF8',
+ conname => 'iso_8859_4_to_utf8', conforencoding => 'PG_LATIN4',
+ contoencoding => 'PG_UTF8', conproc => 'iso8859_to_utf8' },
+{ oid => '4498', descr => 'conversion for UTF8 to LATIN5',
+ conname => 'utf8_to_iso_8859_9', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_LATIN5', conproc => 'utf8_to_iso8859' },
+{ oid => '4499', descr => 'conversion for LATIN5 to UTF8',
+ conname => 'iso_8859_9_to_utf8', conforencoding => 'PG_LATIN5',
+ contoencoding => 'PG_UTF8', conproc => 'iso8859_to_utf8' },
+{ oid => '4500', descr => 'conversion for UTF8 to LATIN6',
+ conname => 'utf8_to_iso_8859_10', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_LATIN6', conproc => 'utf8_to_iso8859' },
+{ oid => '4501', descr => 'conversion for LATIN6 to UTF8',
+ conname => 'iso_8859_10_to_utf8', conforencoding => 'PG_LATIN6',
+ contoencoding => 'PG_UTF8', conproc => 'iso8859_to_utf8' },
+{ oid => '4502', descr => 'conversion for UTF8 to LATIN7',
+ conname => 'utf8_to_iso_8859_13', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_LATIN7', conproc => 'utf8_to_iso8859' },
+{ oid => '4503', descr => 'conversion for LATIN7 to UTF8',
+ conname => 'iso_8859_13_to_utf8', conforencoding => 'PG_LATIN7',
+ contoencoding => 'PG_UTF8', conproc => 'iso8859_to_utf8' },
+{ oid => '4504', descr => 'conversion for UTF8 to LATIN8',
+ conname => 'utf8_to_iso_8859_14', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_LATIN8', conproc => 'utf8_to_iso8859' },
+{ oid => '4505', descr => 'conversion for LATIN8 to UTF8',
+ conname => 'iso_8859_14_to_utf8', conforencoding => 'PG_LATIN8',
+ contoencoding => 'PG_UTF8', conproc => 'iso8859_to_utf8' },
+{ oid => '4506', descr => 'conversion for UTF8 to LATIN9',
+ conname => 'utf8_to_iso_8859_15', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_LATIN9', conproc => 'utf8_to_iso8859' },
+{ oid => '4507', descr => 'conversion for LATIN9 to UTF8',
+ conname => 'iso_8859_15_to_utf8', conforencoding => 'PG_LATIN9',
+ contoencoding => 'PG_UTF8', conproc => 'iso8859_to_utf8' },
+{ oid => '4508', descr => 'conversion for UTF8 to LATIN10',
+ conname => 'utf8_to_iso_8859_16', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_LATIN10', conproc => 'utf8_to_iso8859' },
+{ oid => '4509', descr => 'conversion for LATIN10 to UTF8',
+ conname => 'iso_8859_16_to_utf8', conforencoding => 'PG_LATIN10',
+ contoencoding => 'PG_UTF8', conproc => 'iso8859_to_utf8' },
+{ oid => '4510', descr => 'conversion for UTF8 to ISO-8859-5',
+ conname => 'utf8_to_iso_8859_5', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_ISO_8859_5', conproc => 'utf8_to_iso8859' },
+{ oid => '4511', descr => 'conversion for ISO-8859-5 to UTF8',
+ conname => 'iso_8859_5_to_utf8', conforencoding => 'PG_ISO_8859_5',
+ contoencoding => 'PG_UTF8', conproc => 'iso8859_to_utf8' },
+{ oid => '4512', descr => 'conversion for UTF8 to ISO-8859-6',
+ conname => 'utf8_to_iso_8859_6', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_ISO_8859_6', conproc => 'utf8_to_iso8859' },
+{ oid => '4513', descr => 'conversion for ISO-8859-6 to UTF8',
+ conname => 'iso_8859_6_to_utf8', conforencoding => 'PG_ISO_8859_6',
+ contoencoding => 'PG_UTF8', conproc => 'iso8859_to_utf8' },
+{ oid => '4514', descr => 'conversion for UTF8 to ISO-8859-7',
+ conname => 'utf8_to_iso_8859_7', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_ISO_8859_7', conproc => 'utf8_to_iso8859' },
+{ oid => '4515', descr => 'conversion for ISO-8859-7 to UTF8',
+ conname => 'iso_8859_7_to_utf8', conforencoding => 'PG_ISO_8859_7',
+ contoencoding => 'PG_UTF8', conproc => 'iso8859_to_utf8' },
+{ oid => '4516', descr => 'conversion for UTF8 to ISO-8859-8',
+ conname => 'utf8_to_iso_8859_8', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_ISO_8859_8', conproc => 'utf8_to_iso8859' },
+{ oid => '4517', descr => 'conversion for ISO-8859-8 to UTF8',
+ conname => 'iso_8859_8_to_utf8', conforencoding => 'PG_ISO_8859_8',
+ contoencoding => 'PG_UTF8', conproc => 'iso8859_to_utf8' },
+{ oid => '4518', descr => 'conversion for LATIN1 to UTF8',
+ conname => 'iso_8859_1_to_utf8', conforencoding => 'PG_LATIN1',
+ contoencoding => 'PG_UTF8', conproc => 'iso8859_1_to_utf8' },
+{ oid => '4519', descr => 'conversion for UTF8 to LATIN1',
+ conname => 'utf8_to_iso_8859_1', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_LATIN1', conproc => 'utf8_to_iso8859_1' },
+{ oid => '4520', descr => 'conversion for JOHAB to UTF8',
+ conname => 'johab_to_utf8', conforencoding => 'PG_JOHAB',
+ contoencoding => 'PG_UTF8', conproc => 'johab_to_utf8' },
+{ oid => '4521', descr => 'conversion for UTF8 to JOHAB',
+ conname => 'utf8_to_johab', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_JOHAB', conproc => 'utf8_to_johab' },
+{ oid => '4522', descr => 'conversion for SJIS to UTF8',
+ conname => 'sjis_to_utf8', conforencoding => 'PG_SJIS',
+ contoencoding => 'PG_UTF8', conproc => 'sjis_to_utf8' },
+{ oid => '4523', descr => 'conversion for UTF8 to SJIS',
+ conname => 'utf8_to_sjis', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_SJIS', conproc => 'utf8_to_sjis' },
+{ oid => '4524', descr => 'conversion for UHC to UTF8',
+ conname => 'uhc_to_utf8', conforencoding => 'PG_UHC',
+ contoencoding => 'PG_UTF8', conproc => 'uhc_to_utf8' },
+{ oid => '4525', descr => 'conversion for UTF8 to UHC',
+ conname => 'utf8_to_uhc', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_UHC', conproc => 'utf8_to_uhc' },
+{ oid => '4526', descr => 'conversion for EUC_JIS_2004 to UTF8',
+ conname => 'euc_jis_2004_to_utf8', conforencoding => 'PG_EUC_JIS_2004',
+ contoencoding => 'PG_UTF8', conproc => 'euc_jis_2004_to_utf8' },
+{ oid => '4527', descr => 'conversion for UTF8 to EUC_JIS_2004',
+ conname => 'utf8_to_euc_jis_2004', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_EUC_JIS_2004', conproc => 'utf8_to_euc_jis_2004' },
+{ oid => '4528', descr => 'conversion for SHIFT_JIS_2004 to UTF8',
+ conname => 'shift_jis_2004_to_utf8', conforencoding => 'PG_SHIFT_JIS_2004',
+ contoencoding => 'PG_UTF8', conproc => 'shift_jis_2004_to_utf8' },
+{ oid => '4529', descr => 'conversion for UTF8 to SHIFT_JIS_2004',
+ conname => 'utf8_to_shift_jis_2004', conforencoding => 'PG_UTF8',
+ contoencoding => 'PG_SHIFT_JIS_2004', conproc => 'utf8_to_shift_jis_2004' },
+{ oid => '4530', descr => 'conversion for EUC_JIS_2004 to SHIFT_JIS_2004',
+ conname => 'euc_jis_2004_to_shift_jis_2004',
+ conforencoding => 'PG_EUC_JIS_2004', contoencoding => 'PG_SHIFT_JIS_2004',
+ conproc => 'euc_jis_2004_to_shift_jis_2004' },
+{ oid => '4531', descr => 'conversion for SHIFT_JIS_2004 to EUC_JIS_2004',
+ conname => 'shift_jis_2004_to_euc_jis_2004',
+ conforencoding => 'PG_SHIFT_JIS_2004', contoencoding => 'PG_EUC_JIS_2004',
+ conproc => 'shift_jis_2004_to_euc_jis_2004' },
+
+]
diff --git a/src/include/catalog/pg_conversion.h b/src/include/catalog/pg_conversion.h
new file mode 100644
index 0000000..0e7f13e
--- /dev/null
+++ b/src/include/catalog/pg_conversion.h
@@ -0,0 +1,72 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_conversion.h
+ * definition of the "conversion" system catalog (pg_conversion)
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_conversion.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_CONVERSION_H
+#define PG_CONVERSION_H
+
+#include "catalog/genbki.h"
+#include "catalog/objectaddress.h"
+#include "catalog/pg_conversion_d.h"
+
+/* ----------------
+ * pg_conversion definition. cpp turns this into
+ * typedef struct FormData_pg_conversion
+ * ----------------
+ */
+CATALOG(pg_conversion,2607,ConversionRelationId)
+{
+ /* oid */
+ Oid oid;
+
+ /* name of the conversion */
+ NameData conname;
+
+ /* namespace that the conversion belongs to */
+ Oid connamespace BKI_DEFAULT(PGNSP);
+
+ /* owner of the conversion */
+ Oid conowner BKI_DEFAULT(PGUID);
+
+ /* FOR encoding id */
+ int32 conforencoding BKI_LOOKUP(encoding);
+
+ /* TO encoding id */
+ int32 contoencoding BKI_LOOKUP(encoding);
+
+ /* OID of the conversion proc */
+ regproc conproc BKI_LOOKUP(pg_proc);
+
+ /* true if this is a default conversion */
+ bool condefault BKI_DEFAULT(t);
+} FormData_pg_conversion;
+
+/* ----------------
+ * Form_pg_conversion corresponds to a pointer to a tuple with
+ * the format of pg_conversion relation.
+ * ----------------
+ */
+typedef FormData_pg_conversion *Form_pg_conversion;
+
+
+extern ObjectAddress ConversionCreate(const char *conname, Oid connamespace,
+ Oid conowner,
+ int32 conforencoding, int32 contoencoding,
+ Oid conproc, bool def);
+extern void RemoveConversionById(Oid conversionOid);
+extern Oid FindDefaultConversion(Oid connamespace, int32 for_encoding,
+ int32 to_encoding);
+
+#endif /* PG_CONVERSION_H */
diff --git a/src/include/catalog/pg_database.dat b/src/include/catalog/pg_database.dat
new file mode 100644
index 0000000..21cd660
--- /dev/null
+++ b/src/include/catalog/pg_database.dat
@@ -0,0 +1,22 @@
+#----------------------------------------------------------------------
+#
+# pg_database.dat
+# Initial contents of the pg_database system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_database.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+{ oid => '1', oid_symbol => 'TemplateDbOid',
+ descr => 'default template for new databases',
+ datname => 'template1', encoding => 'ENCODING', datcollate => 'LC_COLLATE',
+ datctype => 'LC_CTYPE', datistemplate => 't', datallowconn => 't',
+ datconnlimit => '-1', datlastsysoid => '0', datfrozenxid => '0',
+ datminmxid => '1', dattablespace => 'pg_default', datacl => '_null_' },
+
+]
diff --git a/src/include/catalog/pg_database.h b/src/include/catalog/pg_database.h
new file mode 100644
index 0000000..f623ee8
--- /dev/null
+++ b/src/include/catalog/pg_database.h
@@ -0,0 +1,83 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_database.h
+ * definition of the "database" system catalog (pg_database)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_database.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_DATABASE_H
+#define PG_DATABASE_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_database_d.h"
+
+/* ----------------
+ * pg_database definition. cpp turns this into
+ * typedef struct FormData_pg_database
+ * ----------------
+ */
+CATALOG(pg_database,1262,DatabaseRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_OID(1248,DatabaseRelation_Rowtype_Id) BKI_SCHEMA_MACRO
+{
+ /* oid */
+ Oid oid;
+
+ /* database name */
+ NameData datname;
+
+ /* owner of database */
+ Oid datdba BKI_DEFAULT(PGUID);
+
+ /* character encoding */
+ int32 encoding;
+
+ /* LC_COLLATE setting */
+ NameData datcollate;
+
+ /* LC_CTYPE setting */
+ NameData datctype;
+
+ /* allowed as CREATE DATABASE template? */
+ bool datistemplate;
+
+ /* new connections allowed? */
+ bool datallowconn;
+
+ /* max connections allowed (-1=no limit) */
+ int32 datconnlimit;
+
+ /* highest OID to consider a system OID */
+ Oid datlastsysoid;
+
+ /* all Xids < this are frozen in this DB */
+ TransactionId datfrozenxid;
+
+ /* all multixacts in the DB are >= this */
+ TransactionId datminmxid;
+
+ /* default table space for this DB */
+ Oid dattablespace BKI_LOOKUP(pg_tablespace);
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ /* access permissions */
+ aclitem datacl[1];
+#endif
+} FormData_pg_database;
+
+/* ----------------
+ * Form_pg_database corresponds to a pointer to a tuple with
+ * the format of pg_database relation.
+ * ----------------
+ */
+typedef FormData_pg_database *Form_pg_database;
+
+#endif /* PG_DATABASE_H */
diff --git a/src/include/catalog/pg_db_role_setting.h b/src/include/catalog/pg_db_role_setting.h
new file mode 100644
index 0000000..5713fa2
--- /dev/null
+++ b/src/include/catalog/pg_db_role_setting.h
@@ -0,0 +1,54 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_db_role_setting.h
+ * definition of the system catalog for per-database/per-user
+ * configuration settings (pg_db_role_setting)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_db_role_setting.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_DB_ROLE_SETTING_H
+#define PG_DB_ROLE_SETTING_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_db_role_setting_d.h"
+
+#include "utils/guc.h"
+#include "utils/relcache.h"
+#include "utils/snapshot.h"
+
+/* ----------------
+ * pg_db_role_setting definition. cpp turns this into
+ * typedef struct FormData_pg_db_role_setting
+ * ----------------
+ */
+CATALOG(pg_db_role_setting,2964,DbRoleSettingRelationId) BKI_SHARED_RELATION
+{
+ Oid setdatabase; /* database */
+ Oid setrole; /* role */
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ text setconfig[1]; /* GUC settings to apply at login */
+#endif
+} FormData_pg_db_role_setting;
+
+typedef FormData_pg_db_role_setting * Form_pg_db_role_setting;
+
+/*
+ * prototypes for functions in pg_db_role_setting.h
+ */
+extern void AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt);
+extern void DropSetting(Oid databaseid, Oid roleid);
+extern void ApplySetting(Snapshot snapshot, Oid databaseid, Oid roleid,
+ Relation relsetting, GucSource source);
+
+#endif /* PG_DB_ROLE_SETTING_H */
diff --git a/src/include/catalog/pg_default_acl.h b/src/include/catalog/pg_default_acl.h
new file mode 100644
index 0000000..2bac5e2
--- /dev/null
+++ b/src/include/catalog/pg_default_acl.h
@@ -0,0 +1,65 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_default_acl.h
+ * definition of the system catalog for default ACLs of new objects
+ * (pg_default_acl)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_default_acl.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_DEFAULT_ACL_H
+#define PG_DEFAULT_ACL_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_default_acl_d.h"
+
+/* ----------------
+ * pg_default_acl definition. cpp turns this into
+ * typedef struct FormData_pg_default_acl
+ * ----------------
+ */
+CATALOG(pg_default_acl,826,DefaultAclRelationId)
+{
+ Oid oid; /* oid */
+ Oid defaclrole; /* OID of role owning this ACL */
+ Oid defaclnamespace; /* OID of namespace, or 0 for all */
+ char defaclobjtype; /* see DEFACLOBJ_xxx constants below */
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ aclitem defaclacl[1] BKI_FORCE_NOT_NULL; /* permissions to add at
+ * CREATE time */
+#endif
+} FormData_pg_default_acl;
+
+/* ----------------
+ * Form_pg_default_acl corresponds to a pointer to a tuple with
+ * the format of pg_default_acl relation.
+ * ----------------
+ */
+typedef FormData_pg_default_acl *Form_pg_default_acl;
+
+#ifdef EXPOSE_TO_CLIENT_CODE
+
+/*
+ * Types of objects for which the user is allowed to specify default
+ * permissions through pg_default_acl. These codes are used in the
+ * defaclobjtype column.
+ */
+#define DEFACLOBJ_RELATION 'r' /* table, view */
+#define DEFACLOBJ_SEQUENCE 'S' /* sequence */
+#define DEFACLOBJ_FUNCTION 'f' /* function */
+#define DEFACLOBJ_TYPE 'T' /* type */
+#define DEFACLOBJ_NAMESPACE 'n' /* namespace */
+
+#endif /* EXPOSE_TO_CLIENT_CODE */
+
+#endif /* PG_DEFAULT_ACL_H */
diff --git a/src/include/catalog/pg_depend.h b/src/include/catalog/pg_depend.h
new file mode 100644
index 0000000..ccf0a98
--- /dev/null
+++ b/src/include/catalog/pg_depend.h
@@ -0,0 +1,73 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_depend.h
+ * definition of the "dependency" system catalog (pg_depend)
+ *
+ * pg_depend has no preloaded contents, so there is no pg_depend.dat
+ * file; system-defined dependencies are loaded into it during a late stage
+ * of the initdb process.
+ *
+ * NOTE: we do not represent all possible dependency pairs in pg_depend;
+ * for example, there's not much value in creating an explicit dependency
+ * from an attribute to its relation. Usually we make a dependency for
+ * cases where the relationship is conditional rather than essential
+ * (for example, not all triggers are dependent on constraints, but all
+ * attributes are dependent on relations) or where the dependency is not
+ * convenient to find from the contents of other catalogs.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_depend.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_DEPEND_H
+#define PG_DEPEND_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_depend_d.h"
+
+/* ----------------
+ * pg_depend definition. cpp turns this into
+ * typedef struct FormData_pg_depend
+ * ----------------
+ */
+CATALOG(pg_depend,2608,DependRelationId)
+{
+ /*
+ * Identification of the dependent (referencing) object.
+ *
+ * These fields are all zeroes for a DEPENDENCY_PIN entry.
+ */
+ Oid classid; /* OID of table containing object */
+ Oid objid; /* OID of object itself */
+ int32 objsubid; /* column number, or 0 if not used */
+
+ /*
+ * Identification of the independent (referenced) object.
+ */
+ Oid refclassid; /* OID of table containing object */
+ Oid refobjid; /* OID of object itself */
+ int32 refobjsubid; /* column number, or 0 if not used */
+
+ /*
+ * Precise semantics of the relationship are specified by the deptype
+ * field. See DependencyType in catalog/dependency.h.
+ */
+ char deptype; /* see codes in dependency.h */
+} FormData_pg_depend;
+
+/* ----------------
+ * Form_pg_depend corresponds to a pointer to a row with
+ * the format of pg_depend relation.
+ * ----------------
+ */
+typedef FormData_pg_depend *Form_pg_depend;
+
+#endif /* PG_DEPEND_H */
diff --git a/src/include/catalog/pg_description.h b/src/include/catalog/pg_description.h
new file mode 100644
index 0000000..c40e8b7
--- /dev/null
+++ b/src/include/catalog/pg_description.h
@@ -0,0 +1,66 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_description.h
+ * definition of the "description" system catalog (pg_description)
+ *
+ * Because the contents of this table are taken from the *.dat files
+ * of other catalogs, there is no pg_description.dat file. The initial
+ * contents are assembled by genbki.pl and loaded during initdb.
+ *
+ * NOTE: an object is identified by the OID of the row that primarily
+ * defines the object, plus the OID of the table that that row appears in.
+ * For example, a function is identified by the OID of its pg_proc row
+ * plus the pg_class OID of table pg_proc. This allows unique identification
+ * of objects without assuming that OIDs are unique across tables.
+ *
+ * Since attributes don't have OIDs of their own, we identify an attribute
+ * comment by the objoid+classoid of its parent table, plus an "objsubid"
+ * giving the attribute column number. "objsubid" must be zero in a comment
+ * for a table itself, so that it is distinct from any column comment.
+ * Currently, objsubid is unused and zero for all other kinds of objects,
+ * but perhaps it might be useful someday to associate comments with
+ * constituent elements of other kinds of objects (arguments of a function,
+ * for example).
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_description.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_DESCRIPTION_H
+#define PG_DESCRIPTION_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_description_d.h"
+
+/* ----------------
+ * pg_description definition. cpp turns this into
+ * typedef struct FormData_pg_description
+ * ----------------
+ */
+CATALOG(pg_description,2609,DescriptionRelationId)
+{
+ Oid objoid; /* OID of object itself */
+ Oid classoid; /* OID of table containing object */
+ int32 objsubid; /* column number, or 0 if not used */
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ text description BKI_FORCE_NOT_NULL; /* description of object */
+#endif
+} FormData_pg_description;
+
+/* ----------------
+ * Form_pg_description corresponds to a pointer to a tuple with
+ * the format of pg_description relation.
+ * ----------------
+ */
+typedef FormData_pg_description * Form_pg_description;
+
+#endif /* PG_DESCRIPTION_H */
diff --git a/src/include/catalog/pg_enum.h b/src/include/catalog/pg_enum.h
new file mode 100644
index 0000000..b28d441
--- /dev/null
+++ b/src/include/catalog/pg_enum.h
@@ -0,0 +1,62 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_enum.h
+ * definition of the "enum" system catalog (pg_enum)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_enum.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_ENUM_H
+#define PG_ENUM_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_enum_d.h"
+
+#include "nodes/pg_list.h"
+
+/* ----------------
+ * pg_enum definition. cpp turns this into
+ * typedef struct FormData_pg_enum
+ * ----------------
+ */
+CATALOG(pg_enum,3501,EnumRelationId)
+{
+ Oid oid; /* oid */
+ Oid enumtypid; /* OID of owning enum type */
+ float4 enumsortorder; /* sort position of this enum value */
+ NameData enumlabel; /* text representation of enum value */
+} FormData_pg_enum;
+
+/* ----------------
+ * Form_pg_enum corresponds to a pointer to a tuple with
+ * the format of pg_enum relation.
+ * ----------------
+ */
+typedef FormData_pg_enum *Form_pg_enum;
+
+/*
+ * prototypes for functions in pg_enum.c
+ */
+extern void EnumValuesCreate(Oid enumTypeOid, List *vals);
+extern void EnumValuesDelete(Oid enumTypeOid);
+extern void AddEnumLabel(Oid enumTypeOid, const char *newVal,
+ const char *neighbor, bool newValIsAfter,
+ bool skipIfExists);
+extern void RenameEnumLabel(Oid enumTypeOid,
+ const char *oldVal, const char *newVal);
+extern bool EnumBlacklisted(Oid enum_id);
+extern Size EstimateEnumBlacklistSpace(void);
+extern void SerializeEnumBlacklist(void *space, Size size);
+extern void RestoreEnumBlacklist(void *space);
+extern void AtEOXact_Enum(void);
+
+#endif /* PG_ENUM_H */
diff --git a/src/include/catalog/pg_event_trigger.h b/src/include/catalog/pg_event_trigger.h
new file mode 100644
index 0000000..24e4b1a
--- /dev/null
+++ b/src/include/catalog/pg_event_trigger.h
@@ -0,0 +1,51 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_event_trigger.h
+ * definition of the "event trigger" system catalog (pg_event_trigger)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_event_trigger.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_EVENT_TRIGGER_H
+#define PG_EVENT_TRIGGER_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_event_trigger_d.h"
+
+/* ----------------
+ * pg_event_trigger definition. cpp turns this into
+ * typedef struct FormData_pg_event_trigger
+ * ----------------
+ */
+CATALOG(pg_event_trigger,3466,EventTriggerRelationId)
+{
+ Oid oid; /* oid */
+ NameData evtname; /* trigger's name */
+ NameData evtevent; /* trigger's event */
+ Oid evtowner; /* trigger's owner */
+ Oid evtfoid; /* OID of function to be called */
+ char evtenabled; /* trigger's firing configuration WRT
+ * session_replication_role */
+
+#ifdef CATALOG_VARLEN
+ text evttags[1]; /* command TAGs this event trigger targets */
+#endif
+} FormData_pg_event_trigger;
+
+/* ----------------
+ * Form_pg_event_trigger corresponds to a pointer to a tuple with
+ * the format of pg_event_trigger relation.
+ * ----------------
+ */
+typedef FormData_pg_event_trigger *Form_pg_event_trigger;
+
+#endif /* PG_EVENT_TRIGGER_H */
diff --git a/src/include/catalog/pg_extension.h b/src/include/catalog/pg_extension.h
new file mode 100644
index 0000000..b6f4128
--- /dev/null
+++ b/src/include/catalog/pg_extension.h
@@ -0,0 +1,52 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_extension.h
+ * definition of the "extension" system catalog (pg_extension)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_extension.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_EXTENSION_H
+#define PG_EXTENSION_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_extension_d.h"
+
+/* ----------------
+ * pg_extension definition. cpp turns this into
+ * typedef struct FormData_pg_extension
+ * ----------------
+ */
+CATALOG(pg_extension,3079,ExtensionRelationId)
+{
+ Oid oid; /* oid */
+ NameData extname; /* extension name */
+ Oid extowner; /* extension owner */
+ Oid extnamespace; /* namespace of contained objects */
+ bool extrelocatable; /* if true, allow ALTER EXTENSION SET SCHEMA */
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ /* extversion may never be null, but the others can be. */
+ text extversion BKI_FORCE_NOT_NULL; /* extension version name */
+ Oid extconfig[1]; /* dumpable configuration tables */
+ text extcondition[1]; /* WHERE clauses for config tables */
+#endif
+} FormData_pg_extension;
+
+/* ----------------
+ * Form_pg_extension corresponds to a pointer to a tuple with
+ * the format of pg_extension relation.
+ * ----------------
+ */
+typedef FormData_pg_extension *Form_pg_extension;
+
+#endif /* PG_EXTENSION_H */
diff --git a/src/include/catalog/pg_foreign_data_wrapper.h b/src/include/catalog/pg_foreign_data_wrapper.h
new file mode 100644
index 0000000..44d8558
--- /dev/null
+++ b/src/include/catalog/pg_foreign_data_wrapper.h
@@ -0,0 +1,50 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_foreign_data_wrapper.h
+ * definition of the "foreign-data wrapper" system catalog (pg_foreign_data_wrapper)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_foreign_data_wrapper.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_FOREIGN_DATA_WRAPPER_H
+#define PG_FOREIGN_DATA_WRAPPER_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_foreign_data_wrapper_d.h"
+
+/* ----------------
+ * pg_foreign_data_wrapper definition. cpp turns this into
+ * typedef struct FormData_pg_foreign_data_wrapper
+ * ----------------
+ */
+CATALOG(pg_foreign_data_wrapper,2328,ForeignDataWrapperRelationId)
+{
+ Oid oid; /* oid */
+ NameData fdwname; /* foreign-data wrapper name */
+ Oid fdwowner; /* FDW owner */
+ Oid fdwhandler; /* handler function, or 0 if none */
+ Oid fdwvalidator; /* option validation function, or 0 if none */
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ aclitem fdwacl[1]; /* access permissions */
+ text fdwoptions[1]; /* FDW options */
+#endif
+} FormData_pg_foreign_data_wrapper;
+
+/* ----------------
+ * Form_pg_foreign_data_wrapper corresponds to a pointer to a tuple with
+ * the format of pg_foreign_data_wrapper relation.
+ * ----------------
+ */
+typedef FormData_pg_foreign_data_wrapper *Form_pg_foreign_data_wrapper;
+
+#endif /* PG_FOREIGN_DATA_WRAPPER_H */
diff --git a/src/include/catalog/pg_foreign_server.h b/src/include/catalog/pg_foreign_server.h
new file mode 100644
index 0000000..5c17004
--- /dev/null
+++ b/src/include/catalog/pg_foreign_server.h
@@ -0,0 +1,50 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_foreign_server.h
+ * definition of the "foreign server" system catalog (pg_foreign_server)
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_foreign_server.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_FOREIGN_SERVER_H
+#define PG_FOREIGN_SERVER_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_foreign_server_d.h"
+
+/* ----------------
+ * pg_foreign_server definition. cpp turns this into
+ * typedef struct FormData_pg_foreign_server
+ * ----------------
+ */
+CATALOG(pg_foreign_server,1417,ForeignServerRelationId)
+{
+ Oid oid; /* oid */
+ NameData srvname; /* foreign server name */
+ Oid srvowner; /* server owner */
+ Oid srvfdw; /* server FDW */
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ text srvtype;
+ text srvversion;
+ aclitem srvacl[1]; /* access permissions */
+ text srvoptions[1]; /* FDW-specific options */
+#endif
+} FormData_pg_foreign_server;
+
+/* ----------------
+ * Form_pg_foreign_server corresponds to a pointer to a tuple with
+ * the format of pg_foreign_server relation.
+ * ----------------
+ */
+typedef FormData_pg_foreign_server *Form_pg_foreign_server;
+
+#endif /* PG_FOREIGN_SERVER_H */
diff --git a/src/include/catalog/pg_foreign_table.h b/src/include/catalog/pg_foreign_table.h
new file mode 100644
index 0000000..31c1fae
--- /dev/null
+++ b/src/include/catalog/pg_foreign_table.h
@@ -0,0 +1,45 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_foreign_table.h
+ * definition of the "foreign table" system catalog (pg_foreign_table)
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_foreign_table.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_FOREIGN_TABLE_H
+#define PG_FOREIGN_TABLE_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_foreign_table_d.h"
+
+/* ----------------
+ * pg_foreign_table definition. cpp turns this into
+ * typedef struct FormData_pg_foreign_table
+ * ----------------
+ */
+CATALOG(pg_foreign_table,3118,ForeignTableRelationId)
+{
+ Oid ftrelid; /* OID of foreign table */
+ Oid ftserver; /* OID of foreign server */
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ text ftoptions[1]; /* FDW-specific options */
+#endif
+} FormData_pg_foreign_table;
+
+/* ----------------
+ * Form_pg_foreign_table corresponds to a pointer to a tuple with
+ * the format of pg_foreign_table relation.
+ * ----------------
+ */
+typedef FormData_pg_foreign_table *Form_pg_foreign_table;
+
+#endif /* PG_FOREIGN_TABLE_H */
diff --git a/src/include/catalog/pg_index.h b/src/include/catalog/pg_index.h
new file mode 100644
index 0000000..d3d7ea7
--- /dev/null
+++ b/src/include/catalog/pg_index.h
@@ -0,0 +1,80 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_index.h
+ * definition of the "index" system catalog (pg_index)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_index.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_INDEX_H
+#define PG_INDEX_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_index_d.h"
+
+/* ----------------
+ * pg_index definition. cpp turns this into
+ * typedef struct FormData_pg_index.
+ * ----------------
+ */
+CATALOG(pg_index,2610,IndexRelationId) BKI_SCHEMA_MACRO
+{
+ Oid indexrelid; /* OID of the index */
+ Oid indrelid; /* OID of the relation it indexes */
+ int16 indnatts; /* total number of columns in index */
+ int16 indnkeyatts; /* number of key columns in index */
+ bool indisunique; /* is this a unique index? */
+ bool indisprimary; /* is this index for primary key? */
+ bool indisexclusion; /* is this index for exclusion constraint? */
+ bool indimmediate; /* is uniqueness enforced immediately? */
+ bool indisclustered; /* is this the index last clustered by? */
+ bool indisvalid; /* is this index valid for use by queries? */
+ bool indcheckxmin; /* must we wait for xmin to be old? */
+ bool indisready; /* is this index ready for inserts? */
+ bool indislive; /* is this index alive at all? */
+ bool indisreplident; /* is this index the identity for replication? */
+
+ /* variable-length fields start here, but we allow direct access to indkey */
+ int2vector indkey; /* column numbers of indexed cols, or 0 */
+
+#ifdef CATALOG_VARLEN
+ oidvector indcollation; /* collation identifiers */
+ oidvector indclass; /* opclass identifiers */
+ int2vector indoption; /* per-column flags (AM-specific meanings) */
+ pg_node_tree indexprs; /* expression trees for index attributes that
+ * are not simple column references; one for
+ * each zero entry in indkey[] */
+ pg_node_tree indpred; /* expression tree for predicate, if a partial
+ * index; else NULL */
+#endif
+} FormData_pg_index;
+
+/* ----------------
+ * Form_pg_index corresponds to a pointer to a tuple with
+ * the format of pg_index relation.
+ * ----------------
+ */
+typedef FormData_pg_index *Form_pg_index;
+
+#ifdef EXPOSE_TO_CLIENT_CODE
+
+/*
+ * Index AMs that support ordered scans must support these two indoption
+ * bits. Otherwise, the content of the per-column indoption fields is
+ * open for future definition.
+ */
+#define INDOPTION_DESC 0x0001 /* values are in reverse order */
+#define INDOPTION_NULLS_FIRST 0x0002 /* NULLs are first instead of last */
+
+#endif /* EXPOSE_TO_CLIENT_CODE */
+
+#endif /* PG_INDEX_H */
diff --git a/src/include/catalog/pg_inherits.h b/src/include/catalog/pg_inherits.h
new file mode 100644
index 0000000..0432c3a
--- /dev/null
+++ b/src/include/catalog/pg_inherits.h
@@ -0,0 +1,57 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_inherits.h
+ * definition of the "inherits" system catalog (pg_inherits)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_inherits.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_INHERITS_H
+#define PG_INHERITS_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_inherits_d.h"
+
+#include "nodes/pg_list.h"
+#include "storage/lock.h"
+
+/* ----------------
+ * pg_inherits definition. cpp turns this into
+ * typedef struct FormData_pg_inherits
+ * ----------------
+ */
+CATALOG(pg_inherits,2611,InheritsRelationId)
+{
+ Oid inhrelid;
+ Oid inhparent;
+ int32 inhseqno;
+} FormData_pg_inherits;
+
+/* ----------------
+ * Form_pg_inherits corresponds to a pointer to a tuple with
+ * the format of pg_inherits relation.
+ * ----------------
+ */
+typedef FormData_pg_inherits *Form_pg_inherits;
+
+
+extern List *find_inheritance_children(Oid parentrelId, LOCKMODE lockmode);
+extern List *find_all_inheritors(Oid parentrelId, LOCKMODE lockmode,
+ List **parents);
+extern bool has_subclass(Oid relationId);
+extern bool has_superclass(Oid relationId);
+extern bool typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId);
+extern void StoreSingleInheritance(Oid relationId, Oid parentOid,
+ int32 seqNumber);
+extern bool DeleteInheritsTuple(Oid inhrelid, Oid inhparent);
+
+#endif /* PG_INHERITS_H */
diff --git a/src/include/catalog/pg_init_privs.h b/src/include/catalog/pg_init_privs.h
new file mode 100644
index 0000000..7734b72
--- /dev/null
+++ b/src/include/catalog/pg_init_privs.h
@@ -0,0 +1,78 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_init_privs.h
+ * definition of the "initial privileges" system catalog (pg_init_privs)
+ *
+ * NOTE: an object is identified by the OID of the row that primarily
+ * defines the object, plus the OID of the table that that row appears in.
+ * For example, a function is identified by the OID of its pg_proc row
+ * plus the pg_class OID of table pg_proc. This allows unique identification
+ * of objects without assuming that OIDs are unique across tables.
+ *
+ * Since attributes don't have OIDs of their own, we identify an attribute
+ * privilege by the objoid+classoid of its parent table, plus an "objsubid"
+ * giving the attribute column number. "objsubid" must be zero in a privilege
+ * for a table itself, so that it is distinct from any column privilege.
+ * Currently, objsubid is unused and zero for all other kinds of objects.
+ *
+ * Because the contents of this table depend on what is done with the other
+ * objects in the system (and, in particular, may change due to changes in
+ * system_views.sql), there is no pg_init_privs.dat file. The initial contents
+ * are loaded near the end of initdb.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_init_privs.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_INIT_PRIVS_H
+#define PG_INIT_PRIVS_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_init_privs_d.h"
+
+/* ----------------
+ * pg_init_privs definition. cpp turns this into
+ * typedef struct FormData_pg_init_privs
+ * ----------------
+ */
+CATALOG(pg_init_privs,3394,InitPrivsRelationId)
+{
+ Oid objoid; /* OID of object itself */
+ Oid classoid; /* OID of table containing object */
+ int32 objsubid; /* column number, or 0 if not used */
+ char privtype; /* from initdb or extension? */
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ aclitem initprivs[1] BKI_FORCE_NOT_NULL; /* initial privs on object */
+#endif
+} FormData_pg_init_privs;
+
+/* ----------------
+ * Form_pg_init_privs corresponds to a pointer to a tuple with
+ * the format of pg_init_privs relation.
+ * ----------------
+ */
+typedef FormData_pg_init_privs * Form_pg_init_privs;
+
+/*
+ * It is important to know if the initial privileges are from initdb or from an
+ * extension. This enum is used to provide that differentiation and the two
+ * places which populate this table (initdb and during CREATE EXTENSION, see
+ * recordExtensionInitPriv()) know to use the correct values.
+ */
+
+typedef enum InitPrivsType
+{
+ INITPRIVS_INITDB = 'i',
+ INITPRIVS_EXTENSION = 'e'
+} InitPrivsType;
+
+#endif /* PG_INIT_PRIVS_H */
diff --git a/src/include/catalog/pg_language.dat b/src/include/catalog/pg_language.dat
new file mode 100644
index 0000000..2e44a27
--- /dev/null
+++ b/src/include/catalog/pg_language.dat
@@ -0,0 +1,25 @@
+#----------------------------------------------------------------------
+#
+# pg_language.dat
+# Initial contents of the pg_language system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_language.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+{ oid => '12', oid_symbol => 'INTERNALlanguageId',
+ descr => 'built-in functions',
+ lanname => 'internal', lanvalidator => 'fmgr_internal_validator' },
+{ oid => '13', oid_symbol => 'ClanguageId',
+ descr => 'dynamically-loaded C functions',
+ lanname => 'c', lanvalidator => 'fmgr_c_validator' },
+{ oid => '14', oid_symbol => 'SQLlanguageId',
+ descr => 'SQL-language functions',
+ lanname => 'sql', lanpltrusted => 't', lanvalidator => 'fmgr_sql_validator' },
+
+]
diff --git a/src/include/catalog/pg_language.h b/src/include/catalog/pg_language.h
new file mode 100644
index 0000000..937bacb
--- /dev/null
+++ b/src/include/catalog/pg_language.h
@@ -0,0 +1,67 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_language.h
+ * definition of the "language" system catalog (pg_language)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_language.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_LANGUAGE_H
+#define PG_LANGUAGE_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_language_d.h"
+
+/* ----------------
+ * pg_language definition. cpp turns this into
+ * typedef struct FormData_pg_language
+ * ----------------
+ */
+CATALOG(pg_language,2612,LanguageRelationId)
+{
+ Oid oid; /* oid */
+
+ /* Language name */
+ NameData lanname;
+
+ /* Language's owner */
+ Oid lanowner BKI_DEFAULT(PGUID);
+
+ /* Is a procedural language */
+ bool lanispl BKI_DEFAULT(f);
+
+ /* PL is trusted */
+ bool lanpltrusted BKI_DEFAULT(f);
+
+ /* Call handler, if it's a PL */
+ Oid lanplcallfoid BKI_DEFAULT(0) BKI_LOOKUP(pg_proc);
+
+ /* Optional anonymous-block handler function */
+ Oid laninline BKI_DEFAULT(0) BKI_LOOKUP(pg_proc);
+
+ /* Optional validation function */
+ Oid lanvalidator BKI_DEFAULT(0) BKI_LOOKUP(pg_proc);
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ /* Access privileges */
+ aclitem lanacl[1] BKI_DEFAULT(_null_);
+#endif
+} FormData_pg_language;
+
+/* ----------------
+ * Form_pg_language corresponds to a pointer to a tuple with
+ * the format of pg_language relation.
+ * ----------------
+ */
+typedef FormData_pg_language *Form_pg_language;
+
+#endif /* PG_LANGUAGE_H */
diff --git a/src/include/catalog/pg_largeobject.h b/src/include/catalog/pg_largeobject.h
new file mode 100644
index 0000000..f64703f
--- /dev/null
+++ b/src/include/catalog/pg_largeobject.h
@@ -0,0 +1,50 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_largeobject.h
+ * definition of the "large object" system catalog (pg_largeobject)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_largeobject.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_LARGEOBJECT_H
+#define PG_LARGEOBJECT_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_largeobject_d.h"
+
+/* ----------------
+ * pg_largeobject definition. cpp turns this into
+ * typedef struct FormData_pg_largeobject
+ * ----------------
+ */
+CATALOG(pg_largeobject,2613,LargeObjectRelationId)
+{
+ Oid loid; /* Identifier of large object */
+ int32 pageno; /* Page number (starting from 0) */
+
+ /* data has variable length, but we allow direct access; see inv_api.c */
+ bytea data BKI_FORCE_NOT_NULL; /* Data for page (may be
+ * zero-length) */
+} FormData_pg_largeobject;
+
+/* ----------------
+ * Form_pg_largeobject corresponds to a pointer to a tuple with
+ * the format of pg_largeobject relation.
+ * ----------------
+ */
+typedef FormData_pg_largeobject *Form_pg_largeobject;
+
+extern Oid LargeObjectCreate(Oid loid);
+extern void LargeObjectDrop(Oid loid);
+extern bool LargeObjectExists(Oid loid);
+
+#endif /* PG_LARGEOBJECT_H */
diff --git a/src/include/catalog/pg_largeobject_metadata.h b/src/include/catalog/pg_largeobject_metadata.h
new file mode 100644
index 0000000..8f6b472
--- /dev/null
+++ b/src/include/catalog/pg_largeobject_metadata.h
@@ -0,0 +1,48 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_largeobject_metadata.h
+ * definition of the "large object metadata" system catalog
+ * (pg_largeobject_metadata)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_largeobject_metadata.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_LARGEOBJECT_METADATA_H
+#define PG_LARGEOBJECT_METADATA_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_largeobject_metadata_d.h"
+
+/* ----------------
+ * pg_largeobject_metadata definition. cpp turns this into
+ * typedef struct FormData_pg_largeobject_metadata
+ * ----------------
+ */
+CATALOG(pg_largeobject_metadata,2995,LargeObjectMetadataRelationId)
+{
+ Oid oid; /* oid */
+
+ Oid lomowner; /* OID of the largeobject owner */
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ aclitem lomacl[1]; /* access permissions */
+#endif
+} FormData_pg_largeobject_metadata;
+
+/* ----------------
+ * Form_pg_largeobject_metadata corresponds to a pointer to a tuple
+ * with the format of pg_largeobject_metadata relation.
+ * ----------------
+ */
+typedef FormData_pg_largeobject_metadata *Form_pg_largeobject_metadata;
+
+#endif /* PG_LARGEOBJECT_METADATA_H */
diff --git a/src/include/catalog/pg_namespace.dat b/src/include/catalog/pg_namespace.dat
new file mode 100644
index 0000000..63a6102
--- /dev/null
+++ b/src/include/catalog/pg_namespace.dat
@@ -0,0 +1,25 @@
+#----------------------------------------------------------------------
+#
+# pg_namespace.dat
+# Initial contents of the pg_namespace system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_namespace.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+{ oid => '11', oid_symbol => 'PG_CATALOG_NAMESPACE',
+ descr => 'system catalog schema',
+ nspname => 'pg_catalog', nspowner => 'PGUID', nspacl => '_null_' },
+{ oid => '99', oid_symbol => 'PG_TOAST_NAMESPACE',
+ descr => 'reserved schema for TOAST tables',
+ nspname => 'pg_toast', nspowner => 'PGUID', nspacl => '_null_' },
+{ oid => '2200', oid_symbol => 'PG_PUBLIC_NAMESPACE',
+ descr => 'standard public schema',
+ nspname => 'public', nspowner => 'PGUID', nspacl => '_null_' },
+
+]
diff --git a/src/include/catalog/pg_namespace.h b/src/include/catalog/pg_namespace.h
new file mode 100644
index 0000000..db93b27
--- /dev/null
+++ b/src/include/catalog/pg_namespace.h
@@ -0,0 +1,59 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_namespace.h
+ * definition of the "namespace" system catalog (pg_namespace)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_namespace.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_NAMESPACE_H
+#define PG_NAMESPACE_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_namespace_d.h"
+#include "utils/acl.h"
+
+/* ----------------------------------------------------------------
+ * pg_namespace definition.
+ *
+ * cpp turns this into typedef struct FormData_pg_namespace
+ *
+ * nspname name of the namespace
+ * nspowner owner (creator) of the namespace
+ * nspacl access privilege list
+ * ----------------------------------------------------------------
+ */
+CATALOG(pg_namespace,2615,NamespaceRelationId)
+{
+ Oid oid; /* oid */
+
+ NameData nspname;
+ Oid nspowner;
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ aclitem nspacl[1];
+#endif
+} FormData_pg_namespace;
+
+/* ----------------
+ * Form_pg_namespace corresponds to a pointer to a tuple with
+ * the format of pg_namespace relation.
+ * ----------------
+ */
+typedef FormData_pg_namespace *Form_pg_namespace;
+
+/*
+ * prototypes for functions in pg_namespace.c
+ */
+extern Oid NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp);
+
+#endif /* PG_NAMESPACE_H */
diff --git a/src/include/catalog/pg_opclass.dat b/src/include/catalog/pg_opclass.dat
new file mode 100644
index 0000000..f2342bb
--- /dev/null
+++ b/src/include/catalog/pg_opclass.dat
@@ -0,0 +1,350 @@
+#----------------------------------------------------------------------
+#
+# pg_opclass.dat
+# Initial contents of the pg_opclass system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_opclass.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+# Note: we hard-wire an OID only for a few entries that have to be explicitly
+# referenced in the C code or in built-in catalog entries. The rest get OIDs
+# assigned on-the-fly during initdb.
+
+{ opcmethod => 'btree', opcname => 'array_ops', opcfamily => 'btree/array_ops',
+ opcintype => 'anyarray' },
+{ opcmethod => 'hash', opcname => 'array_ops', opcfamily => 'hash/array_ops',
+ opcintype => 'anyarray' },
+{ opcmethod => 'btree', opcname => 'bit_ops', opcfamily => 'btree/bit_ops',
+ opcintype => 'bit' },
+{ opcmethod => 'btree', opcname => 'bool_ops', opcfamily => 'btree/bool_ops',
+ opcintype => 'bool' },
+{ opcmethod => 'btree', opcname => 'bpchar_ops',
+ opcfamily => 'btree/bpchar_ops', opcintype => 'bpchar' },
+{ opcmethod => 'hash', opcname => 'bpchar_ops', opcfamily => 'hash/bpchar_ops',
+ opcintype => 'bpchar' },
+{ opcmethod => 'btree', opcname => 'bytea_ops', opcfamily => 'btree/bytea_ops',
+ opcintype => 'bytea' },
+{ opcmethod => 'btree', opcname => 'char_ops', opcfamily => 'btree/char_ops',
+ opcintype => 'char' },
+{ opcmethod => 'hash', opcname => 'char_ops', opcfamily => 'hash/char_ops',
+ opcintype => 'char' },
+{ opcmethod => 'btree', opcname => 'cidr_ops', opcfamily => 'btree/network_ops',
+ opcintype => 'inet', opcdefault => 'f' },
+{ opcmethod => 'hash', opcname => 'cidr_ops', opcfamily => 'hash/network_ops',
+ opcintype => 'inet', opcdefault => 'f' },
+{ oid => '3122', oid_symbol => 'DATE_BTREE_OPS_OID',
+ opcmethod => 'btree', opcname => 'date_ops',
+ opcfamily => 'btree/datetime_ops', opcintype => 'date' },
+{ opcmethod => 'hash', opcname => 'date_ops', opcfamily => 'hash/date_ops',
+ opcintype => 'date' },
+{ opcmethod => 'btree', opcname => 'float4_ops', opcfamily => 'btree/float_ops',
+ opcintype => 'float4' },
+{ opcmethod => 'hash', opcname => 'float4_ops', opcfamily => 'hash/float_ops',
+ opcintype => 'float4' },
+{ oid => '3123', oid_symbol => 'FLOAT8_BTREE_OPS_OID',
+ opcmethod => 'btree', opcname => 'float8_ops', opcfamily => 'btree/float_ops',
+ opcintype => 'float8' },
+{ opcmethod => 'hash', opcname => 'float8_ops', opcfamily => 'hash/float_ops',
+ opcintype => 'float8' },
+{ opcmethod => 'btree', opcname => 'inet_ops', opcfamily => 'btree/network_ops',
+ opcintype => 'inet' },
+{ opcmethod => 'hash', opcname => 'inet_ops', opcfamily => 'hash/network_ops',
+ opcintype => 'inet' },
+{ opcmethod => 'gist', opcname => 'inet_ops', opcfamily => 'gist/network_ops',
+ opcintype => 'inet', opcdefault => 'f' },
+{ opcmethod => 'spgist', opcname => 'inet_ops',
+ opcfamily => 'spgist/network_ops', opcintype => 'inet' },
+{ oid => '1979', oid_symbol => 'INT2_BTREE_OPS_OID',
+ opcmethod => 'btree', opcname => 'int2_ops', opcfamily => 'btree/integer_ops',
+ opcintype => 'int2' },
+{ opcmethod => 'hash', opcname => 'int2_ops', opcfamily => 'hash/integer_ops',
+ opcintype => 'int2' },
+{ oid => '1978', oid_symbol => 'INT4_BTREE_OPS_OID',
+ opcmethod => 'btree', opcname => 'int4_ops', opcfamily => 'btree/integer_ops',
+ opcintype => 'int4' },
+{ opcmethod => 'hash', opcname => 'int4_ops', opcfamily => 'hash/integer_ops',
+ opcintype => 'int4' },
+{ oid => '3124', oid_symbol => 'INT8_BTREE_OPS_OID',
+ opcmethod => 'btree', opcname => 'int8_ops', opcfamily => 'btree/integer_ops',
+ opcintype => 'int8' },
+{ opcmethod => 'hash', opcname => 'int8_ops', opcfamily => 'hash/integer_ops',
+ opcintype => 'int8' },
+{ opcmethod => 'btree', opcname => 'interval_ops',
+ opcfamily => 'btree/interval_ops', opcintype => 'interval' },
+{ opcmethod => 'hash', opcname => 'interval_ops',
+ opcfamily => 'hash/interval_ops', opcintype => 'interval' },
+{ opcmethod => 'btree', opcname => 'macaddr_ops',
+ opcfamily => 'btree/macaddr_ops', opcintype => 'macaddr' },
+{ opcmethod => 'hash', opcname => 'macaddr_ops',
+ opcfamily => 'hash/macaddr_ops', opcintype => 'macaddr' },
+{ opcmethod => 'btree', opcname => 'macaddr8_ops',
+ opcfamily => 'btree/macaddr8_ops', opcintype => 'macaddr8' },
+{ opcmethod => 'hash', opcname => 'macaddr8_ops',
+ opcfamily => 'hash/macaddr8_ops', opcintype => 'macaddr8' },
+
+# Here's an ugly little hack to save space in the system catalog indexes.
+# btree doesn't ordinarily allow a storage type different from input type;
+# but cstring and name are the same thing except for trailing padding,
+# and we can safely omit that within an index entry. So we declare the
+# btree opclass for name as using cstring storage type.
+{ opcmethod => 'btree', opcname => 'name_ops', opcfamily => 'btree/text_ops',
+ opcintype => 'name', opckeytype => 'cstring' },
+
+{ opcmethod => 'hash', opcname => 'name_ops', opcfamily => 'hash/text_ops',
+ opcintype => 'name' },
+{ oid => '3125', oid_symbol => 'NUMERIC_BTREE_OPS_OID',
+ opcmethod => 'btree', opcname => 'numeric_ops',
+ opcfamily => 'btree/numeric_ops', opcintype => 'numeric' },
+{ opcmethod => 'hash', opcname => 'numeric_ops',
+ opcfamily => 'hash/numeric_ops', opcintype => 'numeric' },
+{ oid => '1981', oid_symbol => 'OID_BTREE_OPS_OID',
+ opcmethod => 'btree', opcname => 'oid_ops', opcfamily => 'btree/oid_ops',
+ opcintype => 'oid' },
+{ opcmethod => 'hash', opcname => 'oid_ops', opcfamily => 'hash/oid_ops',
+ opcintype => 'oid' },
+{ opcmethod => 'btree', opcname => 'oidvector_ops',
+ opcfamily => 'btree/oidvector_ops', opcintype => 'oidvector' },
+{ opcmethod => 'hash', opcname => 'oidvector_ops',
+ opcfamily => 'hash/oidvector_ops', opcintype => 'oidvector' },
+{ opcmethod => 'btree', opcname => 'record_ops',
+ opcfamily => 'btree/record_ops', opcintype => 'record' },
+{ opcmethod => 'btree', opcname => 'record_image_ops',
+ opcfamily => 'btree/record_image_ops', opcintype => 'record',
+ opcdefault => 'f' },
+{ oid => '3126', oid_symbol => 'TEXT_BTREE_OPS_OID',
+ opcmethod => 'btree', opcname => 'text_ops', opcfamily => 'btree/text_ops',
+ opcintype => 'text' },
+{ opcmethod => 'hash', opcname => 'text_ops', opcfamily => 'hash/text_ops',
+ opcintype => 'text' },
+{ opcmethod => 'btree', opcname => 'time_ops', opcfamily => 'btree/time_ops',
+ opcintype => 'time' },
+{ opcmethod => 'hash', opcname => 'time_ops', opcfamily => 'hash/time_ops',
+ opcintype => 'time' },
+{ oid => '3127', oid_symbol => 'TIMESTAMPTZ_BTREE_OPS_OID',
+ opcmethod => 'btree', opcname => 'timestamptz_ops',
+ opcfamily => 'btree/datetime_ops', opcintype => 'timestamptz' },
+{ opcmethod => 'hash', opcname => 'timestamptz_ops',
+ opcfamily => 'hash/timestamptz_ops', opcintype => 'timestamptz' },
+{ opcmethod => 'btree', opcname => 'timetz_ops',
+ opcfamily => 'btree/timetz_ops', opcintype => 'timetz' },
+{ opcmethod => 'hash', opcname => 'timetz_ops', opcfamily => 'hash/timetz_ops',
+ opcintype => 'timetz' },
+{ opcmethod => 'btree', opcname => 'varbit_ops',
+ opcfamily => 'btree/varbit_ops', opcintype => 'varbit' },
+{ opcmethod => 'btree', opcname => 'varchar_ops', opcfamily => 'btree/text_ops',
+ opcintype => 'text', opcdefault => 'f' },
+{ opcmethod => 'hash', opcname => 'varchar_ops', opcfamily => 'hash/text_ops',
+ opcintype => 'text', opcdefault => 'f' },
+{ oid => '3128', oid_symbol => 'TIMESTAMP_BTREE_OPS_OID',
+ opcmethod => 'btree', opcname => 'timestamp_ops',
+ opcfamily => 'btree/datetime_ops', opcintype => 'timestamp' },
+{ opcmethod => 'hash', opcname => 'timestamp_ops',
+ opcfamily => 'hash/timestamp_ops', opcintype => 'timestamp' },
+{ oid => '4217', oid_symbol => 'TEXT_BTREE_PATTERN_OPS_OID',
+ opcmethod => 'btree', opcname => 'text_pattern_ops',
+ opcfamily => 'btree/text_pattern_ops', opcintype => 'text',
+ opcdefault => 'f' },
+{ oid => '4218', oid_symbol => 'VARCHAR_BTREE_PATTERN_OPS_OID',
+ opcmethod => 'btree', opcname => 'varchar_pattern_ops',
+ opcfamily => 'btree/text_pattern_ops', opcintype => 'text',
+ opcdefault => 'f' },
+{ oid => '4219', oid_symbol => 'BPCHAR_BTREE_PATTERN_OPS_OID',
+ opcmethod => 'btree', opcname => 'bpchar_pattern_ops',
+ opcfamily => 'btree/bpchar_pattern_ops', opcintype => 'bpchar',
+ opcdefault => 'f' },
+{ opcmethod => 'btree', opcname => 'money_ops', opcfamily => 'btree/money_ops',
+ opcintype => 'money' },
+{ opcmethod => 'hash', opcname => 'bool_ops', opcfamily => 'hash/bool_ops',
+ opcintype => 'bool' },
+{ opcmethod => 'hash', opcname => 'bytea_ops', opcfamily => 'hash/bytea_ops',
+ opcintype => 'bytea' },
+{ opcmethod => 'btree', opcname => 'tid_ops', opcfamily => 'btree/tid_ops',
+ opcintype => 'tid' },
+{ opcmethod => 'hash', opcname => 'xid_ops', opcfamily => 'hash/xid_ops',
+ opcintype => 'xid' },
+{ opcmethod => 'hash', opcname => 'xid8_ops', opcfamily => 'hash/xid8_ops',
+ opcintype => 'xid8' },
+{ opcmethod => 'btree', opcname => 'xid8_ops', opcfamily => 'btree/xid8_ops',
+ opcintype => 'xid8' },
+{ opcmethod => 'hash', opcname => 'cid_ops', opcfamily => 'hash/cid_ops',
+ opcintype => 'cid' },
+{ opcmethod => 'hash', opcname => 'tid_ops', opcfamily => 'hash/tid_ops',
+ opcintype => 'tid' },
+{ opcmethod => 'hash', opcname => 'text_pattern_ops',
+ opcfamily => 'hash/text_pattern_ops', opcintype => 'text',
+ opcdefault => 'f' },
+{ opcmethod => 'hash', opcname => 'varchar_pattern_ops',
+ opcfamily => 'hash/text_pattern_ops', opcintype => 'text',
+ opcdefault => 'f' },
+{ opcmethod => 'hash', opcname => 'bpchar_pattern_ops',
+ opcfamily => 'hash/bpchar_pattern_ops', opcintype => 'bpchar',
+ opcdefault => 'f' },
+{ opcmethod => 'hash', opcname => 'aclitem_ops',
+ opcfamily => 'hash/aclitem_ops', opcintype => 'aclitem' },
+{ opcmethod => 'gist', opcname => 'box_ops', opcfamily => 'gist/box_ops',
+ opcintype => 'box' },
+{ opcmethod => 'gist', opcname => 'point_ops', opcfamily => 'gist/point_ops',
+ opcintype => 'point', opckeytype => 'box' },
+{ opcmethod => 'gist', opcname => 'poly_ops', opcfamily => 'gist/poly_ops',
+ opcintype => 'polygon', opckeytype => 'box' },
+{ opcmethod => 'gist', opcname => 'circle_ops', opcfamily => 'gist/circle_ops',
+ opcintype => 'circle', opckeytype => 'box' },
+{ opcmethod => 'gin', opcname => 'array_ops', opcfamily => 'gin/array_ops',
+ opcintype => 'anyarray', opckeytype => 'anyelement' },
+{ opcmethod => 'btree', opcname => 'uuid_ops', opcfamily => 'btree/uuid_ops',
+ opcintype => 'uuid' },
+{ opcmethod => 'hash', opcname => 'uuid_ops', opcfamily => 'hash/uuid_ops',
+ opcintype => 'uuid' },
+{ opcmethod => 'btree', opcname => 'pg_lsn_ops',
+ opcfamily => 'btree/pg_lsn_ops', opcintype => 'pg_lsn' },
+{ opcmethod => 'hash', opcname => 'pg_lsn_ops', opcfamily => 'hash/pg_lsn_ops',
+ opcintype => 'pg_lsn' },
+{ opcmethod => 'btree', opcname => 'enum_ops', opcfamily => 'btree/enum_ops',
+ opcintype => 'anyenum' },
+{ opcmethod => 'hash', opcname => 'enum_ops', opcfamily => 'hash/enum_ops',
+ opcintype => 'anyenum' },
+{ opcmethod => 'btree', opcname => 'tsvector_ops',
+ opcfamily => 'btree/tsvector_ops', opcintype => 'tsvector' },
+{ opcmethod => 'gist', opcname => 'tsvector_ops',
+ opcfamily => 'gist/tsvector_ops', opcintype => 'tsvector',
+ opckeytype => 'gtsvector' },
+{ opcmethod => 'gin', opcname => 'tsvector_ops',
+ opcfamily => 'gin/tsvector_ops', opcintype => 'tsvector',
+ opckeytype => 'text' },
+{ opcmethod => 'btree', opcname => 'tsquery_ops',
+ opcfamily => 'btree/tsquery_ops', opcintype => 'tsquery' },
+{ opcmethod => 'gist', opcname => 'tsquery_ops',
+ opcfamily => 'gist/tsquery_ops', opcintype => 'tsquery',
+ opckeytype => 'int8' },
+{ opcmethod => 'btree', opcname => 'range_ops', opcfamily => 'btree/range_ops',
+ opcintype => 'anyrange' },
+{ opcmethod => 'hash', opcname => 'range_ops', opcfamily => 'hash/range_ops',
+ opcintype => 'anyrange' },
+{ opcmethod => 'gist', opcname => 'range_ops', opcfamily => 'gist/range_ops',
+ opcintype => 'anyrange' },
+{ opcmethod => 'spgist', opcname => 'range_ops',
+ opcfamily => 'spgist/range_ops', opcintype => 'anyrange' },
+{ opcmethod => 'spgist', opcname => 'box_ops', opcfamily => 'spgist/box_ops',
+ opcintype => 'box' },
+{ opcmethod => 'spgist', opcname => 'quad_point_ops',
+ opcfamily => 'spgist/quad_point_ops', opcintype => 'point' },
+{ opcmethod => 'spgist', opcname => 'kd_point_ops',
+ opcfamily => 'spgist/kd_point_ops', opcintype => 'point', opcdefault => 'f' },
+{ opcmethod => 'spgist', opcname => 'text_ops', opcfamily => 'spgist/text_ops',
+ opcintype => 'text' },
+{ opcmethod => 'spgist', opcname => 'poly_ops', opcfamily => 'spgist/poly_ops',
+ opcintype => 'polygon', opckeytype => 'box' },
+{ opcmethod => 'btree', opcname => 'jsonb_ops', opcfamily => 'btree/jsonb_ops',
+ opcintype => 'jsonb' },
+{ opcmethod => 'hash', opcname => 'jsonb_ops', opcfamily => 'hash/jsonb_ops',
+ opcintype => 'jsonb' },
+{ opcmethod => 'gin', opcname => 'jsonb_ops', opcfamily => 'gin/jsonb_ops',
+ opcintype => 'jsonb', opckeytype => 'text' },
+{ opcmethod => 'gin', opcname => 'jsonb_path_ops',
+ opcfamily => 'gin/jsonb_path_ops', opcintype => 'jsonb', opcdefault => 'f',
+ opckeytype => 'int4' },
+
+# BRIN operator classes
+
+# no brin opclass for bool
+
+{ opcmethod => 'brin', opcname => 'bytea_minmax_ops',
+ opcfamily => 'brin/bytea_minmax_ops', opcintype => 'bytea',
+ opckeytype => 'bytea' },
+{ opcmethod => 'brin', opcname => 'char_minmax_ops',
+ opcfamily => 'brin/char_minmax_ops', opcintype => 'char',
+ opckeytype => 'char' },
+{ opcmethod => 'brin', opcname => 'name_minmax_ops',
+ opcfamily => 'brin/name_minmax_ops', opcintype => 'name',
+ opckeytype => 'name' },
+{ opcmethod => 'brin', opcname => 'int8_minmax_ops',
+ opcfamily => 'brin/integer_minmax_ops', opcintype => 'int8',
+ opckeytype => 'int8' },
+{ opcmethod => 'brin', opcname => 'int2_minmax_ops',
+ opcfamily => 'brin/integer_minmax_ops', opcintype => 'int2',
+ opckeytype => 'int2' },
+{ opcmethod => 'brin', opcname => 'int4_minmax_ops',
+ opcfamily => 'brin/integer_minmax_ops', opcintype => 'int4',
+ opckeytype => 'int4' },
+{ opcmethod => 'brin', opcname => 'text_minmax_ops',
+ opcfamily => 'brin/text_minmax_ops', opcintype => 'text',
+ opckeytype => 'text' },
+{ opcmethod => 'brin', opcname => 'oid_minmax_ops',
+ opcfamily => 'brin/oid_minmax_ops', opcintype => 'oid', opckeytype => 'oid' },
+{ opcmethod => 'brin', opcname => 'tid_minmax_ops',
+ opcfamily => 'brin/tid_minmax_ops', opcintype => 'tid', opckeytype => 'tid' },
+{ opcmethod => 'brin', opcname => 'float4_minmax_ops',
+ opcfamily => 'brin/float_minmax_ops', opcintype => 'float4',
+ opckeytype => 'float4' },
+{ opcmethod => 'brin', opcname => 'float8_minmax_ops',
+ opcfamily => 'brin/float_minmax_ops', opcintype => 'float8',
+ opckeytype => 'float8' },
+{ opcmethod => 'brin', opcname => 'macaddr_minmax_ops',
+ opcfamily => 'brin/macaddr_minmax_ops', opcintype => 'macaddr',
+ opckeytype => 'macaddr' },
+{ opcmethod => 'brin', opcname => 'macaddr8_minmax_ops',
+ opcfamily => 'brin/macaddr8_minmax_ops', opcintype => 'macaddr8',
+ opckeytype => 'macaddr8' },
+{ opcmethod => 'brin', opcname => 'inet_minmax_ops',
+ opcfamily => 'brin/network_minmax_ops', opcintype => 'inet',
+ opcdefault => 'f', opckeytype => 'inet' },
+{ opcmethod => 'brin', opcname => 'inet_inclusion_ops',
+ opcfamily => 'brin/network_inclusion_ops', opcintype => 'inet',
+ opckeytype => 'inet' },
+{ opcmethod => 'brin', opcname => 'bpchar_minmax_ops',
+ opcfamily => 'brin/bpchar_minmax_ops', opcintype => 'bpchar',
+ opckeytype => 'bpchar' },
+{ opcmethod => 'brin', opcname => 'time_minmax_ops',
+ opcfamily => 'brin/time_minmax_ops', opcintype => 'time',
+ opckeytype => 'time' },
+{ opcmethod => 'brin', opcname => 'date_minmax_ops',
+ opcfamily => 'brin/datetime_minmax_ops', opcintype => 'date',
+ opckeytype => 'date' },
+{ opcmethod => 'brin', opcname => 'timestamp_minmax_ops',
+ opcfamily => 'brin/datetime_minmax_ops', opcintype => 'timestamp',
+ opckeytype => 'timestamp' },
+{ opcmethod => 'brin', opcname => 'timestamptz_minmax_ops',
+ opcfamily => 'brin/datetime_minmax_ops', opcintype => 'timestamptz',
+ opckeytype => 'timestamptz' },
+{ opcmethod => 'brin', opcname => 'interval_minmax_ops',
+ opcfamily => 'brin/interval_minmax_ops', opcintype => 'interval',
+ opckeytype => 'interval' },
+{ opcmethod => 'brin', opcname => 'timetz_minmax_ops',
+ opcfamily => 'brin/timetz_minmax_ops', opcintype => 'timetz',
+ opckeytype => 'timetz' },
+{ opcmethod => 'brin', opcname => 'bit_minmax_ops',
+ opcfamily => 'brin/bit_minmax_ops', opcintype => 'bit', opckeytype => 'bit' },
+{ opcmethod => 'brin', opcname => 'varbit_minmax_ops',
+ opcfamily => 'brin/varbit_minmax_ops', opcintype => 'varbit',
+ opckeytype => 'varbit' },
+{ opcmethod => 'brin', opcname => 'numeric_minmax_ops',
+ opcfamily => 'brin/numeric_minmax_ops', opcintype => 'numeric',
+ opckeytype => 'numeric' },
+
+# no brin opclass for record, anyarray
+
+{ opcmethod => 'brin', opcname => 'uuid_minmax_ops',
+ opcfamily => 'brin/uuid_minmax_ops', opcintype => 'uuid',
+ opckeytype => 'uuid' },
+{ opcmethod => 'brin', opcname => 'range_inclusion_ops',
+ opcfamily => 'brin/range_inclusion_ops', opcintype => 'anyrange',
+ opckeytype => 'anyrange' },
+{ opcmethod => 'brin', opcname => 'pg_lsn_minmax_ops',
+ opcfamily => 'brin/pg_lsn_minmax_ops', opcintype => 'pg_lsn',
+ opckeytype => 'pg_lsn' },
+
+# no brin opclass for enum, tsvector, tsquery, jsonb
+
+{ opcmethod => 'brin', opcname => 'box_inclusion_ops',
+ opcfamily => 'brin/box_inclusion_ops', opcintype => 'box',
+ opckeytype => 'box' },
+
+# no brin opclass for the geometric types except box
+
+]
diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h
new file mode 100644
index 0000000..963ab3e
--- /dev/null
+++ b/src/include/catalog/pg_opclass.h
@@ -0,0 +1,85 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_opclass.h
+ * definition of the "operator class" system catalog (pg_opclass)
+ *
+ * The primary key for this table is <opcmethod, opcname, opcnamespace> ---
+ * that is, there is a row for each valid combination of opclass name and
+ * index access method type. This row specifies the expected input data type
+ * for the opclass (the type of the heap column, or the expression output type
+ * in the case of an index expression). Note that types binary-coercible to
+ * the specified type will be accepted too.
+ *
+ * For a given <opcmethod, opcintype> pair, there can be at most one row that
+ * has opcdefault = true; this row is the default opclass for such data in
+ * such an index. (This is not currently enforced by an index, because we
+ * don't support partial indexes on system catalogs.)
+ *
+ * Normally opckeytype = InvalidOid (zero), indicating that the data stored
+ * in the index is the same as the data in the indexed column. If opckeytype
+ * is nonzero then it indicates that a conversion step is needed to produce
+ * the stored index data, which will be of type opckeytype (which might be
+ * the same or different from the input datatype). Performing such a
+ * conversion is the responsibility of the index access method --- not all
+ * AMs support this.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_opclass.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_OPCLASS_H
+#define PG_OPCLASS_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_opclass_d.h"
+
+/* ----------------
+ * pg_opclass definition. cpp turns this into
+ * typedef struct FormData_pg_opclass
+ * ----------------
+ */
+CATALOG(pg_opclass,2616,OperatorClassRelationId)
+{
+ Oid oid; /* oid */
+
+ /* index access method opclass is for */
+ Oid opcmethod BKI_LOOKUP(pg_am);
+
+ /* name of this opclass */
+ NameData opcname;
+
+ /* namespace of this opclass */
+ Oid opcnamespace BKI_DEFAULT(PGNSP);
+
+ /* opclass owner */
+ Oid opcowner BKI_DEFAULT(PGUID);
+
+ /* containing operator family */
+ Oid opcfamily BKI_LOOKUP(pg_opfamily);
+
+ /* type of data indexed by opclass */
+ Oid opcintype BKI_LOOKUP(pg_type);
+
+ /* T if opclass is default for opcintype */
+ bool opcdefault BKI_DEFAULT(t);
+
+ /* type of data in index, or InvalidOid */
+ Oid opckeytype BKI_DEFAULT(0) BKI_LOOKUP(pg_type);
+} FormData_pg_opclass;
+
+/* ----------------
+ * Form_pg_opclass corresponds to a pointer to a tuple with
+ * the format of pg_opclass relation.
+ * ----------------
+ */
+typedef FormData_pg_opclass *Form_pg_opclass;
+
+#endif /* PG_OPCLASS_H */
diff --git a/src/include/catalog/pg_operator.dat b/src/include/catalog/pg_operator.dat
new file mode 100644
index 0000000..3b3eb95
--- /dev/null
+++ b/src/include/catalog/pg_operator.dat
@@ -0,0 +1,3331 @@
+#----------------------------------------------------------------------
+#
+# pg_operator.dat
+# Initial contents of the pg_operator system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_operator.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+# Note: every entry in pg_operator.dat is expected to have a 'descr' comment.
+# If the operator is a deprecated equivalent of some other entry, be sure
+# to comment it as such so that initdb doesn't think it's a preferred name
+# for the underlying function.
+
+{ oid => '15', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'int4',
+ oprright => 'int8', oprresult => 'bool', oprcom => '=(int8,int4)',
+ oprnegate => '<>(int4,int8)', oprcode => 'int48eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '36', descr => 'not equal',
+ oprname => '<>', oprleft => 'int4', oprright => 'int8', oprresult => 'bool',
+ oprcom => '<>(int8,int4)', oprnegate => '=(int4,int8)', oprcode => 'int48ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '37', descr => 'less than',
+ oprname => '<', oprleft => 'int4', oprright => 'int8', oprresult => 'bool',
+ oprcom => '>(int8,int4)', oprnegate => '>=(int4,int8)', oprcode => 'int48lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '76', descr => 'greater than',
+ oprname => '>', oprleft => 'int4', oprright => 'int8', oprresult => 'bool',
+ oprcom => '<(int8,int4)', oprnegate => '<=(int4,int8)', oprcode => 'int48gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '80', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'int4', oprright => 'int8', oprresult => 'bool',
+ oprcom => '>=(int8,int4)', oprnegate => '>(int4,int8)', oprcode => 'int48le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '82', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'int4', oprright => 'int8', oprresult => 'bool',
+ oprcom => '<=(int8,int4)', oprnegate => '<(int4,int8)', oprcode => 'int48ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+{ oid => '58', descr => 'less than',
+ oprname => '<', oprleft => 'bool', oprright => 'bool', oprresult => 'bool',
+ oprcom => '>(bool,bool)', oprnegate => '>=(bool,bool)', oprcode => 'boollt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '59', descr => 'greater than',
+ oprname => '>', oprleft => 'bool', oprright => 'bool', oprresult => 'bool',
+ oprcom => '<(bool,bool)', oprnegate => '<=(bool,bool)', oprcode => 'boolgt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '85', oid_symbol => 'BooleanNotEqualOperator', descr => 'not equal',
+ oprname => '<>', oprleft => 'bool', oprright => 'bool', oprresult => 'bool',
+ oprcom => '<>(bool,bool)', oprnegate => '=(bool,bool)', oprcode => 'boolne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '91', oid_symbol => 'BooleanEqualOperator', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'bool',
+ oprright => 'bool', oprresult => 'bool', oprcom => '=(bool,bool)',
+ oprnegate => '<>(bool,bool)', oprcode => 'booleq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '1694', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'bool', oprright => 'bool', oprresult => 'bool',
+ oprcom => '>=(bool,bool)', oprnegate => '>(bool,bool)', oprcode => 'boolle',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '1695', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'bool', oprright => 'bool', oprresult => 'bool',
+ oprcom => '<=(bool,bool)', oprnegate => '<(bool,bool)', oprcode => 'boolge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+{ oid => '92', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'char',
+ oprright => 'char', oprresult => 'bool', oprcom => '=(char,char)',
+ oprnegate => '<>(char,char)', oprcode => 'chareq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '93', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'name',
+ oprright => 'name', oprresult => 'bool', oprcom => '=(name,name)',
+ oprnegate => '<>(name,name)', oprcode => 'nameeq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '94', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'int2',
+ oprright => 'int2', oprresult => 'bool', oprcom => '=(int2,int2)',
+ oprnegate => '<>(int2,int2)', oprcode => 'int2eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '95', descr => 'less than',
+ oprname => '<', oprleft => 'int2', oprright => 'int2', oprresult => 'bool',
+ oprcom => '>(int2,int2)', oprnegate => '>=(int2,int2)', oprcode => 'int2lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '96', oid_symbol => 'Int4EqualOperator', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'int4',
+ oprright => 'int4', oprresult => 'bool', oprcom => '=(int4,int4)',
+ oprnegate => '<>(int4,int4)', oprcode => 'int4eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '97', oid_symbol => 'Int4LessOperator', descr => 'less than',
+ oprname => '<', oprleft => 'int4', oprright => 'int4', oprresult => 'bool',
+ oprcom => '>(int4,int4)', oprnegate => '>=(int4,int4)', oprcode => 'int4lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '98', oid_symbol => 'TextEqualOperator', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'text',
+ oprright => 'text', oprresult => 'bool', oprcom => '=(text,text)',
+ oprnegate => '<>(text,text)', oprcode => 'texteq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '3877', descr => 'starts with',
+ oprname => '^@', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprcode => 'starts_with', oprrest => 'prefixsel',
+ oprjoin => 'prefixjoinsel' },
+
+{ oid => '254', oid_symbol => 'NameEqualTextOperator', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'name',
+ oprright => 'text', oprresult => 'bool', oprcom => '=(text,name)',
+ oprnegate => '<>(name,text)', oprcode => 'nameeqtext', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '255', oid_symbol => 'NameLessTextOperator', descr => 'less than',
+ oprname => '<', oprleft => 'name', oprright => 'text', oprresult => 'bool',
+ oprcom => '>(text,name)', oprnegate => '>=(name,text)',
+ oprcode => 'namelttext', oprrest => 'scalarltsel',
+ oprjoin => 'scalarltjoinsel' },
+{ oid => '256', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'name', oprright => 'text', oprresult => 'bool',
+ oprcom => '>=(text,name)', oprnegate => '>(name,text)',
+ oprcode => 'nameletext', oprrest => 'scalarlesel',
+ oprjoin => 'scalarlejoinsel' },
+{ oid => '257', oid_symbol => 'NameGreaterEqualTextOperator',
+ descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'name', oprright => 'text', oprresult => 'bool',
+ oprcom => '<=(text,name)', oprnegate => '<(name,text)',
+ oprcode => 'namegetext', oprrest => 'scalargesel',
+ oprjoin => 'scalargejoinsel' },
+{ oid => '258', descr => 'greater than',
+ oprname => '>', oprleft => 'name', oprright => 'text', oprresult => 'bool',
+ oprcom => '<(text,name)', oprnegate => '<=(name,text)',
+ oprcode => 'namegttext', oprrest => 'scalargtsel',
+ oprjoin => 'scalargtjoinsel' },
+{ oid => '259', descr => 'not equal',
+ oprname => '<>', oprleft => 'name', oprright => 'text', oprresult => 'bool',
+ oprcom => '<>(text,name)', oprnegate => '=(name,text)',
+ oprcode => 'namenetext', oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '260', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'text',
+ oprright => 'name', oprresult => 'bool', oprcom => '=(name,text)',
+ oprnegate => '<>(text,name)', oprcode => 'texteqname', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '261', descr => 'less than',
+ oprname => '<', oprleft => 'text', oprright => 'name', oprresult => 'bool',
+ oprcom => '>(name,text)', oprnegate => '>=(text,name)',
+ oprcode => 'textltname', oprrest => 'scalarltsel',
+ oprjoin => 'scalarltjoinsel' },
+{ oid => '262', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'text', oprright => 'name', oprresult => 'bool',
+ oprcom => '>=(name,text)', oprnegate => '>(text,name)',
+ oprcode => 'textlename', oprrest => 'scalarlesel',
+ oprjoin => 'scalarlejoinsel' },
+{ oid => '263', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'text', oprright => 'name', oprresult => 'bool',
+ oprcom => '<=(name,text)', oprnegate => '<(text,name)',
+ oprcode => 'textgename', oprrest => 'scalargesel',
+ oprjoin => 'scalargejoinsel' },
+{ oid => '264', descr => 'greater than',
+ oprname => '>', oprleft => 'text', oprright => 'name', oprresult => 'bool',
+ oprcom => '<(name,text)', oprnegate => '<=(text,name)',
+ oprcode => 'textgtname', oprrest => 'scalargtsel',
+ oprjoin => 'scalargtjoinsel' },
+{ oid => '265', descr => 'not equal',
+ oprname => '<>', oprleft => 'text', oprright => 'name', oprresult => 'bool',
+ oprcom => '<>(name,text)', oprnegate => '=(text,name)',
+ oprcode => 'textnename', oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+
+{ oid => '349', descr => 'append element onto end of array',
+ oprname => '||', oprleft => 'anyarray', oprright => 'anyelement',
+ oprresult => 'anyarray', oprcode => 'array_append' },
+{ oid => '374', descr => 'prepend element onto front of array',
+ oprname => '||', oprleft => 'anyelement', oprright => 'anyarray',
+ oprresult => 'anyarray', oprcode => 'array_prepend' },
+{ oid => '375', descr => 'concatenate',
+ oprname => '||', oprleft => 'anyarray', oprright => 'anyarray',
+ oprresult => 'anyarray', oprcode => 'array_cat' },
+
+{ oid => '352', descr => 'equal',
+ oprname => '=', oprcanhash => 't', oprleft => 'xid', oprright => 'xid',
+ oprresult => 'bool', oprcom => '=(xid,xid)', oprnegate => '<>(xid,xid)',
+ oprcode => 'xideq', oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '353', descr => 'equal',
+ oprname => '=', oprleft => 'xid', oprright => 'int4', oprresult => 'bool',
+ oprnegate => '<>(xid,int4)', oprcode => 'xideqint4', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '3315', descr => 'not equal',
+ oprname => '<>', oprleft => 'xid', oprright => 'xid', oprresult => 'bool',
+ oprcom => '<>(xid,xid)', oprnegate => '=(xid,xid)', oprcode => 'xidneq',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '3316', descr => 'not equal',
+ oprname => '<>', oprleft => 'xid', oprright => 'int4', oprresult => 'bool',
+ oprnegate => '=(xid,int4)', oprcode => 'xidneqint4', oprrest => 'neqsel',
+ oprjoin => 'neqjoinsel' },
+{ oid => '5068', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'xid8',
+ oprright => 'xid8', oprresult => 'bool', oprcom => '=(xid8,xid8)',
+ oprnegate => '<>(xid8,xid8)', oprcode => 'xid8eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '5072', descr => 'not equal',
+ oprname => '<>', oprleft => 'xid8', oprright => 'xid8', oprresult => 'bool',
+ oprcom => '<>(xid8,xid8)', oprnegate => '=(xid8,xid8)', oprcode => 'xid8ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '5073', descr => 'less than',
+ oprname => '<', oprleft => 'xid8', oprright => 'xid8', oprresult => 'bool',
+ oprcom => '>(xid8,xid8)', oprnegate => '>=(xid8,xid8)', oprcode => 'xid8lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '5074', descr => 'greater than',
+ oprname => '>', oprleft => 'xid8', oprright => 'xid8', oprresult => 'bool',
+ oprcom => '<(xid8,xid8)', oprnegate => '<=(xid8,xid8)', oprcode => 'xid8gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '5075', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'xid8', oprright => 'xid8', oprresult => 'bool',
+ oprcom => '>=(xid8,xid8)', oprnegate => '>(xid8,xid8)', oprcode => 'xid8le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '5076', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'xid8', oprright => 'xid8', oprresult => 'bool',
+ oprcom => '<=(xid8,xid8)', oprnegate => '<(xid8,xid8)', oprcode => 'xid8ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '388', descr => 'deprecated, use factorial() instead',
+ oprname => '!', oprkind => 'r', oprleft => 'int8', oprright => '0',
+ oprresult => 'numeric', oprcode => 'numeric_fac' },
+{ oid => '389', descr => 'deprecated, use factorial() instead',
+ oprname => '!!', oprkind => 'l', oprleft => '0', oprright => 'int8',
+ oprresult => 'numeric', oprcode => 'numeric_fac' },
+{ oid => '385', descr => 'equal',
+ oprname => '=', oprcanhash => 't', oprleft => 'cid', oprright => 'cid',
+ oprresult => 'bool', oprcom => '=(cid,cid)', oprcode => 'cideq',
+ oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+
+{ oid => '387', oid_symbol => 'TIDEqualOperator', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'tid',
+ oprright => 'tid', oprresult => 'bool', oprcom => '=(tid,tid)',
+ oprnegate => '<>(tid,tid)', oprcode => 'tideq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '402', descr => 'not equal',
+ oprname => '<>', oprleft => 'tid', oprright => 'tid', oprresult => 'bool',
+ oprcom => '<>(tid,tid)', oprnegate => '=(tid,tid)', oprcode => 'tidne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '2799', oid_symbol => 'TIDLessOperator', descr => 'less than',
+ oprname => '<', oprleft => 'tid', oprright => 'tid', oprresult => 'bool',
+ oprcom => '>(tid,tid)', oprnegate => '>=(tid,tid)', oprcode => 'tidlt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '2800', descr => 'greater than',
+ oprname => '>', oprleft => 'tid', oprright => 'tid', oprresult => 'bool',
+ oprcom => '<(tid,tid)', oprnegate => '<=(tid,tid)', oprcode => 'tidgt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '2801', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'tid', oprright => 'tid', oprresult => 'bool',
+ oprcom => '>=(tid,tid)', oprnegate => '>(tid,tid)', oprcode => 'tidle',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '2802', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'tid', oprright => 'tid', oprresult => 'bool',
+ oprcom => '<=(tid,tid)', oprnegate => '<(tid,tid)', oprcode => 'tidge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+{ oid => '410', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'int8',
+ oprright => 'int8', oprresult => 'bool', oprcom => '=(int8,int8)',
+ oprnegate => '<>(int8,int8)', oprcode => 'int8eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '411', descr => 'not equal',
+ oprname => '<>', oprleft => 'int8', oprright => 'int8', oprresult => 'bool',
+ oprcom => '<>(int8,int8)', oprnegate => '=(int8,int8)', oprcode => 'int8ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '412', oid_symbol => 'Int8LessOperator', descr => 'less than',
+ oprname => '<', oprleft => 'int8', oprright => 'int8', oprresult => 'bool',
+ oprcom => '>(int8,int8)', oprnegate => '>=(int8,int8)', oprcode => 'int8lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '413', descr => 'greater than',
+ oprname => '>', oprleft => 'int8', oprright => 'int8', oprresult => 'bool',
+ oprcom => '<(int8,int8)', oprnegate => '<=(int8,int8)', oprcode => 'int8gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '414', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'int8', oprright => 'int8', oprresult => 'bool',
+ oprcom => '>=(int8,int8)', oprnegate => '>(int8,int8)', oprcode => 'int8le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '415', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'int8', oprright => 'int8', oprresult => 'bool',
+ oprcom => '<=(int8,int8)', oprnegate => '<(int8,int8)', oprcode => 'int8ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+{ oid => '416', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'int8',
+ oprright => 'int4', oprresult => 'bool', oprcom => '=(int4,int8)',
+ oprnegate => '<>(int8,int4)', oprcode => 'int84eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '417', descr => 'not equal',
+ oprname => '<>', oprleft => 'int8', oprright => 'int4', oprresult => 'bool',
+ oprcom => '<>(int4,int8)', oprnegate => '=(int8,int4)', oprcode => 'int84ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '418', descr => 'less than',
+ oprname => '<', oprleft => 'int8', oprright => 'int4', oprresult => 'bool',
+ oprcom => '>(int4,int8)', oprnegate => '>=(int8,int4)', oprcode => 'int84lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '419', descr => 'greater than',
+ oprname => '>', oprleft => 'int8', oprright => 'int4', oprresult => 'bool',
+ oprcom => '<(int4,int8)', oprnegate => '<=(int8,int4)', oprcode => 'int84gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '420', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'int8', oprright => 'int4', oprresult => 'bool',
+ oprcom => '>=(int4,int8)', oprnegate => '>(int8,int4)', oprcode => 'int84le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '430', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'int8', oprright => 'int4', oprresult => 'bool',
+ oprcom => '<=(int4,int8)', oprnegate => '<(int8,int4)', oprcode => 'int84ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '439', descr => 'modulus',
+ oprname => '%', oprleft => 'int8', oprright => 'int8', oprresult => 'int8',
+ oprcode => 'int8mod' },
+{ oid => '473', descr => 'absolute value',
+ oprname => '@', oprkind => 'l', oprleft => '0', oprright => 'int8',
+ oprresult => 'int8', oprcode => 'int8abs' },
+
+{ oid => '484', descr => 'negate',
+ oprname => '-', oprkind => 'l', oprleft => '0', oprright => 'int8',
+ oprresult => 'int8', oprcode => 'int8um' },
+{ oid => '485', descr => 'is left of',
+ oprname => '<<', oprleft => 'polygon', oprright => 'polygon',
+ oprresult => 'bool', oprcode => 'poly_left', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '486', descr => 'overlaps or is left of',
+ oprname => '&<', oprleft => 'polygon', oprright => 'polygon',
+ oprresult => 'bool', oprcode => 'poly_overleft', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '487', descr => 'overlaps or is right of',
+ oprname => '&>', oprleft => 'polygon', oprright => 'polygon',
+ oprresult => 'bool', oprcode => 'poly_overright', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '488', descr => 'is right of',
+ oprname => '>>', oprleft => 'polygon', oprright => 'polygon',
+ oprresult => 'bool', oprcode => 'poly_right', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '489', descr => 'is contained by',
+ oprname => '<@', oprleft => 'polygon', oprright => 'polygon',
+ oprresult => 'bool', oprcom => '@>(polygon,polygon)',
+ oprcode => 'poly_contained', oprrest => 'contsel', oprjoin => 'contjoinsel' },
+{ oid => '490', descr => 'contains',
+ oprname => '@>', oprleft => 'polygon', oprright => 'polygon',
+ oprresult => 'bool', oprcom => '<@(polygon,polygon)',
+ oprcode => 'poly_contain', oprrest => 'contsel', oprjoin => 'contjoinsel' },
+{ oid => '491', descr => 'same as',
+ oprname => '~=', oprleft => 'polygon', oprright => 'polygon',
+ oprresult => 'bool', oprcom => '~=(polygon,polygon)', oprcode => 'poly_same',
+ oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '492', descr => 'overlaps',
+ oprname => '&&', oprleft => 'polygon', oprright => 'polygon',
+ oprresult => 'bool', oprcom => '&&(polygon,polygon)',
+ oprcode => 'poly_overlap', oprrest => 'areasel', oprjoin => 'areajoinsel' },
+{ oid => '493', descr => 'is left of',
+ oprname => '<<', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcode => 'box_left', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '494', descr => 'overlaps or is left of',
+ oprname => '&<', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcode => 'box_overleft', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '495', descr => 'overlaps or is right of',
+ oprname => '&>', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcode => 'box_overright', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '496', descr => 'is right of',
+ oprname => '>>', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcode => 'box_right', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '497', descr => 'is contained by',
+ oprname => '<@', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcom => '@>(box,box)', oprcode => 'box_contained', oprrest => 'contsel',
+ oprjoin => 'contjoinsel' },
+{ oid => '498', descr => 'contains',
+ oprname => '@>', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcom => '<@(box,box)', oprcode => 'box_contain', oprrest => 'contsel',
+ oprjoin => 'contjoinsel' },
+{ oid => '499', descr => 'same as',
+ oprname => '~=', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcom => '~=(box,box)', oprcode => 'box_same', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '500', descr => 'overlaps',
+ oprname => '&&', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcom => '&&(box,box)', oprcode => 'box_overlap', oprrest => 'areasel',
+ oprjoin => 'areajoinsel' },
+{ oid => '501', descr => 'greater than or equal by area',
+ oprname => '>=', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcom => '<=(box,box)', oprnegate => '<(box,box)', oprcode => 'box_ge',
+ oprrest => 'areasel', oprjoin => 'areajoinsel' },
+{ oid => '502', descr => 'greater than by area',
+ oprname => '>', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcom => '<(box,box)', oprnegate => '<=(box,box)', oprcode => 'box_gt',
+ oprrest => 'areasel', oprjoin => 'areajoinsel' },
+{ oid => '503', descr => 'equal by area',
+ oprname => '=', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcom => '=(box,box)', oprcode => 'box_eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '504', descr => 'less than by area',
+ oprname => '<', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcom => '>(box,box)', oprnegate => '>=(box,box)', oprcode => 'box_lt',
+ oprrest => 'areasel', oprjoin => 'areajoinsel' },
+{ oid => '505', descr => 'less than or equal by area',
+ oprname => '<=', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcom => '>=(box,box)', oprnegate => '>(box,box)', oprcode => 'box_le',
+ oprrest => 'areasel', oprjoin => 'areajoinsel' },
+{ oid => '506', descr => 'is above',
+ oprname => '>^', oprleft => 'point', oprright => 'point', oprresult => 'bool',
+ oprcode => 'point_above', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '507', descr => 'is left of',
+ oprname => '<<', oprleft => 'point', oprright => 'point', oprresult => 'bool',
+ oprcode => 'point_left', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '508', descr => 'is right of',
+ oprname => '>>', oprleft => 'point', oprright => 'point', oprresult => 'bool',
+ oprcode => 'point_right', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '509', descr => 'is below',
+ oprname => '<^', oprleft => 'point', oprright => 'point', oprresult => 'bool',
+ oprcode => 'point_below', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '510', descr => 'same as',
+ oprname => '~=', oprleft => 'point', oprright => 'point', oprresult => 'bool',
+ oprcom => '~=(point,point)', oprnegate => '<>(point,point)',
+ oprcode => 'point_eq', oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '511', descr => 'point inside box',
+ oprname => '<@', oprleft => 'point', oprright => 'box', oprresult => 'bool',
+ oprcom => '@>(box,point)', oprcode => 'on_pb', oprrest => 'contsel',
+ oprjoin => 'contjoinsel' },
+{ oid => '433', descr => 'contains',
+ oprname => '@>', oprleft => 'box', oprright => 'point', oprresult => 'bool',
+ oprcom => '<@(point,box)', oprcode => 'box_contain_pt', oprrest => 'contsel',
+ oprjoin => 'contjoinsel' },
+{ oid => '512', descr => 'point within closed path, or point on open path',
+ oprname => '<@', oprleft => 'point', oprright => 'path', oprresult => 'bool',
+ oprcom => '@>(path,point)', oprcode => 'on_ppath' },
+{ oid => '513', descr => 'center of',
+ oprname => '@@', oprkind => 'l', oprleft => '0', oprright => 'box',
+ oprresult => 'point', oprcode => 'box_center' },
+{ oid => '514', descr => 'multiply',
+ oprname => '*', oprleft => 'int4', oprright => 'int4', oprresult => 'int4',
+ oprcom => '*(int4,int4)', oprcode => 'int4mul' },
+{ oid => '517', descr => 'distance between',
+ oprname => '<->', oprleft => 'point', oprright => 'point',
+ oprresult => 'float8', oprcom => '<->(point,point)',
+ oprcode => 'point_distance' },
+{ oid => '518', descr => 'not equal',
+ oprname => '<>', oprleft => 'int4', oprright => 'int4', oprresult => 'bool',
+ oprcom => '<>(int4,int4)', oprnegate => '=(int4,int4)', oprcode => 'int4ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '519', descr => 'not equal',
+ oprname => '<>', oprleft => 'int2', oprright => 'int2', oprresult => 'bool',
+ oprcom => '<>(int2,int2)', oprnegate => '=(int2,int2)', oprcode => 'int2ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '520', descr => 'greater than',
+ oprname => '>', oprleft => 'int2', oprright => 'int2', oprresult => 'bool',
+ oprcom => '<(int2,int2)', oprnegate => '<=(int2,int2)', oprcode => 'int2gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '521', descr => 'greater than',
+ oprname => '>', oprleft => 'int4', oprright => 'int4', oprresult => 'bool',
+ oprcom => '<(int4,int4)', oprnegate => '<=(int4,int4)', oprcode => 'int4gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '522', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'int2', oprright => 'int2', oprresult => 'bool',
+ oprcom => '>=(int2,int2)', oprnegate => '>(int2,int2)', oprcode => 'int2le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '523', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'int4', oprright => 'int4', oprresult => 'bool',
+ oprcom => '>=(int4,int4)', oprnegate => '>(int4,int4)', oprcode => 'int4le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '524', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'int2', oprright => 'int2', oprresult => 'bool',
+ oprcom => '<=(int2,int2)', oprnegate => '<(int2,int2)', oprcode => 'int2ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '525', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'int4', oprright => 'int4', oprresult => 'bool',
+ oprcom => '<=(int4,int4)', oprnegate => '<(int4,int4)', oprcode => 'int4ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '526', descr => 'multiply',
+ oprname => '*', oprleft => 'int2', oprright => 'int2', oprresult => 'int2',
+ oprcom => '*(int2,int2)', oprcode => 'int2mul' },
+{ oid => '527', descr => 'divide',
+ oprname => '/', oprleft => 'int2', oprright => 'int2', oprresult => 'int2',
+ oprcode => 'int2div' },
+{ oid => '528', descr => 'divide',
+ oprname => '/', oprleft => 'int4', oprright => 'int4', oprresult => 'int4',
+ oprcode => 'int4div' },
+{ oid => '529', descr => 'modulus',
+ oprname => '%', oprleft => 'int2', oprright => 'int2', oprresult => 'int2',
+ oprcode => 'int2mod' },
+{ oid => '530', descr => 'modulus',
+ oprname => '%', oprleft => 'int4', oprright => 'int4', oprresult => 'int4',
+ oprcode => 'int4mod' },
+{ oid => '531', descr => 'not equal',
+ oprname => '<>', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprcom => '<>(text,text)', oprnegate => '=(text,text)', oprcode => 'textne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '532', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'int2',
+ oprright => 'int4', oprresult => 'bool', oprcom => '=(int4,int2)',
+ oprnegate => '<>(int2,int4)', oprcode => 'int24eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '533', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'int4',
+ oprright => 'int2', oprresult => 'bool', oprcom => '=(int2,int4)',
+ oprnegate => '<>(int4,int2)', oprcode => 'int42eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '534', descr => 'less than',
+ oprname => '<', oprleft => 'int2', oprright => 'int4', oprresult => 'bool',
+ oprcom => '>(int4,int2)', oprnegate => '>=(int2,int4)', oprcode => 'int24lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '535', descr => 'less than',
+ oprname => '<', oprleft => 'int4', oprright => 'int2', oprresult => 'bool',
+ oprcom => '>(int2,int4)', oprnegate => '>=(int4,int2)', oprcode => 'int42lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '536', descr => 'greater than',
+ oprname => '>', oprleft => 'int2', oprright => 'int4', oprresult => 'bool',
+ oprcom => '<(int4,int2)', oprnegate => '<=(int2,int4)', oprcode => 'int24gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '537', descr => 'greater than',
+ oprname => '>', oprleft => 'int4', oprright => 'int2', oprresult => 'bool',
+ oprcom => '<(int2,int4)', oprnegate => '<=(int4,int2)', oprcode => 'int42gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '538', descr => 'not equal',
+ oprname => '<>', oprleft => 'int2', oprright => 'int4', oprresult => 'bool',
+ oprcom => '<>(int4,int2)', oprnegate => '=(int2,int4)', oprcode => 'int24ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '539', descr => 'not equal',
+ oprname => '<>', oprleft => 'int4', oprright => 'int2', oprresult => 'bool',
+ oprcom => '<>(int2,int4)', oprnegate => '=(int4,int2)', oprcode => 'int42ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '540', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'int2', oprright => 'int4', oprresult => 'bool',
+ oprcom => '>=(int4,int2)', oprnegate => '>(int2,int4)', oprcode => 'int24le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '541', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'int4', oprright => 'int2', oprresult => 'bool',
+ oprcom => '>=(int2,int4)', oprnegate => '>(int4,int2)', oprcode => 'int42le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '542', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'int2', oprright => 'int4', oprresult => 'bool',
+ oprcom => '<=(int4,int2)', oprnegate => '<(int2,int4)', oprcode => 'int24ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '543', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'int4', oprright => 'int2', oprresult => 'bool',
+ oprcom => '<=(int2,int4)', oprnegate => '<(int4,int2)', oprcode => 'int42ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '544', descr => 'multiply',
+ oprname => '*', oprleft => 'int2', oprright => 'int4', oprresult => 'int4',
+ oprcom => '*(int4,int2)', oprcode => 'int24mul' },
+{ oid => '545', descr => 'multiply',
+ oprname => '*', oprleft => 'int4', oprright => 'int2', oprresult => 'int4',
+ oprcom => '*(int2,int4)', oprcode => 'int42mul' },
+{ oid => '546', descr => 'divide',
+ oprname => '/', oprleft => 'int2', oprright => 'int4', oprresult => 'int4',
+ oprcode => 'int24div' },
+{ oid => '547', descr => 'divide',
+ oprname => '/', oprleft => 'int4', oprright => 'int2', oprresult => 'int4',
+ oprcode => 'int42div' },
+{ oid => '550', descr => 'add',
+ oprname => '+', oprleft => 'int2', oprright => 'int2', oprresult => 'int2',
+ oprcom => '+(int2,int2)', oprcode => 'int2pl' },
+{ oid => '551', descr => 'add',
+ oprname => '+', oprleft => 'int4', oprright => 'int4', oprresult => 'int4',
+ oprcom => '+(int4,int4)', oprcode => 'int4pl' },
+{ oid => '552', descr => 'add',
+ oprname => '+', oprleft => 'int2', oprright => 'int4', oprresult => 'int4',
+ oprcom => '+(int4,int2)', oprcode => 'int24pl' },
+{ oid => '553', descr => 'add',
+ oprname => '+', oprleft => 'int4', oprright => 'int2', oprresult => 'int4',
+ oprcom => '+(int2,int4)', oprcode => 'int42pl' },
+{ oid => '554', descr => 'subtract',
+ oprname => '-', oprleft => 'int2', oprright => 'int2', oprresult => 'int2',
+ oprcode => 'int2mi' },
+{ oid => '555', descr => 'subtract',
+ oprname => '-', oprleft => 'int4', oprright => 'int4', oprresult => 'int4',
+ oprcode => 'int4mi' },
+{ oid => '556', descr => 'subtract',
+ oprname => '-', oprleft => 'int2', oprright => 'int4', oprresult => 'int4',
+ oprcode => 'int24mi' },
+{ oid => '557', descr => 'subtract',
+ oprname => '-', oprleft => 'int4', oprright => 'int2', oprresult => 'int4',
+ oprcode => 'int42mi' },
+{ oid => '558', descr => 'negate',
+ oprname => '-', oprkind => 'l', oprleft => '0', oprright => 'int4',
+ oprresult => 'int4', oprcode => 'int4um' },
+{ oid => '559', descr => 'negate',
+ oprname => '-', oprkind => 'l', oprleft => '0', oprright => 'int2',
+ oprresult => 'int2', oprcode => 'int2um' },
+{ oid => '584', descr => 'negate',
+ oprname => '-', oprkind => 'l', oprleft => '0', oprright => 'float4',
+ oprresult => 'float4', oprcode => 'float4um' },
+{ oid => '585', descr => 'negate',
+ oprname => '-', oprkind => 'l', oprleft => '0', oprright => 'float8',
+ oprresult => 'float8', oprcode => 'float8um' },
+{ oid => '586', descr => 'add',
+ oprname => '+', oprleft => 'float4', oprright => 'float4',
+ oprresult => 'float4', oprcom => '+(float4,float4)', oprcode => 'float4pl' },
+{ oid => '587', descr => 'subtract',
+ oprname => '-', oprleft => 'float4', oprright => 'float4',
+ oprresult => 'float4', oprcode => 'float4mi' },
+{ oid => '588', descr => 'divide',
+ oprname => '/', oprleft => 'float4', oprright => 'float4',
+ oprresult => 'float4', oprcode => 'float4div' },
+{ oid => '589', descr => 'multiply',
+ oprname => '*', oprleft => 'float4', oprright => 'float4',
+ oprresult => 'float4', oprcom => '*(float4,float4)', oprcode => 'float4mul' },
+{ oid => '590', descr => 'absolute value',
+ oprname => '@', oprkind => 'l', oprleft => '0', oprright => 'float4',
+ oprresult => 'float4', oprcode => 'float4abs' },
+{ oid => '591', descr => 'add',
+ oprname => '+', oprleft => 'float8', oprright => 'float8',
+ oprresult => 'float8', oprcom => '+(float8,float8)', oprcode => 'float8pl' },
+{ oid => '592', descr => 'subtract',
+ oprname => '-', oprleft => 'float8', oprright => 'float8',
+ oprresult => 'float8', oprcode => 'float8mi' },
+{ oid => '593', descr => 'divide',
+ oprname => '/', oprleft => 'float8', oprright => 'float8',
+ oprresult => 'float8', oprcode => 'float8div' },
+{ oid => '594', descr => 'multiply',
+ oprname => '*', oprleft => 'float8', oprright => 'float8',
+ oprresult => 'float8', oprcom => '*(float8,float8)', oprcode => 'float8mul' },
+{ oid => '595', descr => 'absolute value',
+ oprname => '@', oprkind => 'l', oprleft => '0', oprright => 'float8',
+ oprresult => 'float8', oprcode => 'float8abs' },
+{ oid => '596', descr => 'square root',
+ oprname => '|/', oprkind => 'l', oprleft => '0', oprright => 'float8',
+ oprresult => 'float8', oprcode => 'dsqrt' },
+{ oid => '597', descr => 'cube root',
+ oprname => '||/', oprkind => 'l', oprleft => '0', oprright => 'float8',
+ oprresult => 'float8', oprcode => 'dcbrt' },
+
+{ oid => '607', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'oid',
+ oprright => 'oid', oprresult => 'bool', oprcom => '=(oid,oid)',
+ oprnegate => '<>(oid,oid)', oprcode => 'oideq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '608', descr => 'not equal',
+ oprname => '<>', oprleft => 'oid', oprright => 'oid', oprresult => 'bool',
+ oprcom => '<>(oid,oid)', oprnegate => '=(oid,oid)', oprcode => 'oidne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '609', descr => 'less than',
+ oprname => '<', oprleft => 'oid', oprright => 'oid', oprresult => 'bool',
+ oprcom => '>(oid,oid)', oprnegate => '>=(oid,oid)', oprcode => 'oidlt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '610', descr => 'greater than',
+ oprname => '>', oprleft => 'oid', oprright => 'oid', oprresult => 'bool',
+ oprcom => '<(oid,oid)', oprnegate => '<=(oid,oid)', oprcode => 'oidgt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '611', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'oid', oprright => 'oid', oprresult => 'bool',
+ oprcom => '>=(oid,oid)', oprnegate => '>(oid,oid)', oprcode => 'oidle',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '612', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'oid', oprright => 'oid', oprresult => 'bool',
+ oprcom => '<=(oid,oid)', oprnegate => '<(oid,oid)', oprcode => 'oidge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+{ oid => '644', descr => 'not equal',
+ oprname => '<>', oprleft => 'oidvector', oprright => 'oidvector',
+ oprresult => 'bool', oprcom => '<>(oidvector,oidvector)',
+ oprnegate => '=(oidvector,oidvector)', oprcode => 'oidvectorne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '645', descr => 'less than',
+ oprname => '<', oprleft => 'oidvector', oprright => 'oidvector',
+ oprresult => 'bool', oprcom => '>(oidvector,oidvector)',
+ oprnegate => '>=(oidvector,oidvector)', oprcode => 'oidvectorlt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '646', descr => 'greater than',
+ oprname => '>', oprleft => 'oidvector', oprright => 'oidvector',
+ oprresult => 'bool', oprcom => '<(oidvector,oidvector)',
+ oprnegate => '<=(oidvector,oidvector)', oprcode => 'oidvectorgt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '647', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'oidvector', oprright => 'oidvector',
+ oprresult => 'bool', oprcom => '>=(oidvector,oidvector)',
+ oprnegate => '>(oidvector,oidvector)', oprcode => 'oidvectorle',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '648', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'oidvector', oprright => 'oidvector',
+ oprresult => 'bool', oprcom => '<=(oidvector,oidvector)',
+ oprnegate => '<(oidvector,oidvector)', oprcode => 'oidvectorge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '649', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'oidvector',
+ oprright => 'oidvector', oprresult => 'bool',
+ oprcom => '=(oidvector,oidvector)', oprnegate => '<>(oidvector,oidvector)',
+ oprcode => 'oidvectoreq', oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+
+{ oid => '613', descr => 'distance between',
+ oprname => '<->', oprleft => 'point', oprright => 'line',
+ oprresult => 'float8', oprcom => '<->(line,point)', oprcode => 'dist_pl' },
+{ oid => '760', descr => 'distance between',
+ oprname => '<->', oprleft => 'line', oprright => 'point',
+ oprresult => 'float8', oprcom => '<->(point,line)', oprcode => 'dist_lp' },
+{ oid => '614', descr => 'distance between',
+ oprname => '<->', oprleft => 'point', oprright => 'lseg',
+ oprresult => 'float8', oprcom => '<->(lseg,point)', oprcode => 'dist_ps' },
+{ oid => '761', descr => 'distance between',
+ oprname => '<->', oprleft => 'lseg', oprright => 'point',
+ oprresult => 'float8', oprcom => '<->(point,lseg)', oprcode => 'dist_sp' },
+{ oid => '615', descr => 'distance between',
+ oprname => '<->', oprleft => 'point', oprright => 'box',
+ oprresult => 'float8', oprcom => '<->(box,point)', oprcode => 'dist_pb' },
+{ oid => '606', descr => 'distance between',
+ oprname => '<->', oprleft => 'box', oprright => 'point',
+ oprresult => 'float8', oprcom => '<->(point,box)', oprcode => 'dist_bp' },
+{ oid => '616', descr => 'distance between',
+ oprname => '<->', oprleft => 'lseg', oprright => 'line',
+ oprresult => 'float8', oprcom => '<->(line,lseg)', oprcode => 'dist_sl' },
+{ oid => '762', descr => 'distance between',
+ oprname => '<->', oprleft => 'line', oprright => 'lseg',
+ oprresult => 'float8', oprcom => '<->(lseg,line)', oprcode => 'dist_ls' },
+{ oid => '617', descr => 'distance between',
+ oprname => '<->', oprleft => 'lseg', oprright => 'box', oprresult => 'float8',
+ oprcom => '<->(box,lseg)', oprcode => 'dist_sb' },
+{ oid => '763', descr => 'distance between',
+ oprname => '<->', oprleft => 'box', oprright => 'lseg', oprresult => 'float8',
+ oprcom => '<->(lseg,box)', oprcode => 'dist_bs' },
+{ oid => '618', descr => 'distance between',
+ oprname => '<->', oprleft => 'point', oprright => 'path',
+ oprresult => 'float8', oprcom => '<->(path,point)', oprcode => 'dist_ppath' },
+{ oid => '784', descr => 'distance between',
+ oprname => '<->', oprleft => 'path', oprright => 'point',
+ oprresult => 'float8', oprcom => '<->(point,path)', oprcode => 'dist_pathp' },
+
+{ oid => '620', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'float4',
+ oprright => 'float4', oprresult => 'bool', oprcom => '=(float4,float4)',
+ oprnegate => '<>(float4,float4)', oprcode => 'float4eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '621', descr => 'not equal',
+ oprname => '<>', oprleft => 'float4', oprright => 'float4',
+ oprresult => 'bool', oprcom => '<>(float4,float4)',
+ oprnegate => '=(float4,float4)', oprcode => 'float4ne', oprrest => 'neqsel',
+ oprjoin => 'neqjoinsel' },
+{ oid => '622', descr => 'less than',
+ oprname => '<', oprleft => 'float4', oprright => 'float4',
+ oprresult => 'bool', oprcom => '>(float4,float4)',
+ oprnegate => '>=(float4,float4)', oprcode => 'float4lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '623', descr => 'greater than',
+ oprname => '>', oprleft => 'float4', oprright => 'float4',
+ oprresult => 'bool', oprcom => '<(float4,float4)',
+ oprnegate => '<=(float4,float4)', oprcode => 'float4gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '624', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'float4', oprright => 'float4',
+ oprresult => 'bool', oprcom => '>=(float4,float4)',
+ oprnegate => '>(float4,float4)', oprcode => 'float4le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '625', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'float4', oprright => 'float4',
+ oprresult => 'bool', oprcom => '<=(float4,float4)',
+ oprnegate => '<(float4,float4)', oprcode => 'float4ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '630', descr => 'not equal',
+ oprname => '<>', oprleft => 'char', oprright => 'char', oprresult => 'bool',
+ oprcom => '<>(char,char)', oprnegate => '=(char,char)', oprcode => 'charne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+
+{ oid => '631', descr => 'less than',
+ oprname => '<', oprleft => 'char', oprright => 'char', oprresult => 'bool',
+ oprcom => '>(char,char)', oprnegate => '>=(char,char)', oprcode => 'charlt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '632', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'char', oprright => 'char', oprresult => 'bool',
+ oprcom => '>=(char,char)', oprnegate => '>(char,char)', oprcode => 'charle',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '633', descr => 'greater than',
+ oprname => '>', oprleft => 'char', oprright => 'char', oprresult => 'bool',
+ oprcom => '<(char,char)', oprnegate => '<=(char,char)', oprcode => 'chargt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '634', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'char', oprright => 'char', oprresult => 'bool',
+ oprcom => '<=(char,char)', oprnegate => '<(char,char)', oprcode => 'charge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+{ oid => '639', oid_symbol => 'OID_NAME_REGEXEQ_OP',
+ descr => 'matches regular expression, case-sensitive',
+ oprname => '~', oprleft => 'name', oprright => 'text', oprresult => 'bool',
+ oprnegate => '!~(name,text)', oprcode => 'nameregexeq',
+ oprrest => 'regexeqsel', oprjoin => 'regexeqjoinsel' },
+{ oid => '640', descr => 'does not match regular expression, case-sensitive',
+ oprname => '!~', oprleft => 'name', oprright => 'text', oprresult => 'bool',
+ oprnegate => '~(name,text)', oprcode => 'nameregexne',
+ oprrest => 'regexnesel', oprjoin => 'regexnejoinsel' },
+{ oid => '641', oid_symbol => 'OID_TEXT_REGEXEQ_OP',
+ descr => 'matches regular expression, case-sensitive',
+ oprname => '~', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprnegate => '!~(text,text)', oprcode => 'textregexeq',
+ oprrest => 'regexeqsel', oprjoin => 'regexeqjoinsel' },
+{ oid => '642', descr => 'does not match regular expression, case-sensitive',
+ oprname => '!~', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprnegate => '~(text,text)', oprcode => 'textregexne',
+ oprrest => 'regexnesel', oprjoin => 'regexnejoinsel' },
+{ oid => '643', descr => 'not equal',
+ oprname => '<>', oprleft => 'name', oprright => 'name', oprresult => 'bool',
+ oprcom => '<>(name,name)', oprnegate => '=(name,name)', oprcode => 'namene',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '654', descr => 'concatenate',
+ oprname => '||', oprleft => 'text', oprright => 'text', oprresult => 'text',
+ oprcode => 'textcat' },
+
+{ oid => '660', descr => 'less than',
+ oprname => '<', oprleft => 'name', oprright => 'name', oprresult => 'bool',
+ oprcom => '>(name,name)', oprnegate => '>=(name,name)', oprcode => 'namelt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '661', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'name', oprright => 'name', oprresult => 'bool',
+ oprcom => '>=(name,name)', oprnegate => '>(name,name)', oprcode => 'namele',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '662', descr => 'greater than',
+ oprname => '>', oprleft => 'name', oprright => 'name', oprresult => 'bool',
+ oprcom => '<(name,name)', oprnegate => '<=(name,name)', oprcode => 'namegt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '663', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'name', oprright => 'name', oprresult => 'bool',
+ oprcom => '<=(name,name)', oprnegate => '<(name,name)', oprcode => 'namege',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '664', oid_symbol => 'TextLessOperator', descr => 'less than',
+ oprname => '<', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprcom => '>(text,text)', oprnegate => '>=(text,text)', oprcode => 'text_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '665', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprcom => '>=(text,text)', oprnegate => '>(text,text)', oprcode => 'text_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '666', descr => 'greater than',
+ oprname => '>', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprcom => '<(text,text)', oprnegate => '<=(text,text)', oprcode => 'text_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '667', oid_symbol => 'TextGreaterEqualOperator',
+ descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprcom => '<=(text,text)', oprnegate => '<(text,text)', oprcode => 'text_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+{ oid => '670', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'float8',
+ oprright => 'float8', oprresult => 'bool', oprcom => '=(float8,float8)',
+ oprnegate => '<>(float8,float8)', oprcode => 'float8eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '671', descr => 'not equal',
+ oprname => '<>', oprleft => 'float8', oprright => 'float8',
+ oprresult => 'bool', oprcom => '<>(float8,float8)',
+ oprnegate => '=(float8,float8)', oprcode => 'float8ne', oprrest => 'neqsel',
+ oprjoin => 'neqjoinsel' },
+{ oid => '672', oid_symbol => 'Float8LessOperator', descr => 'less than',
+ oprname => '<', oprleft => 'float8', oprright => 'float8',
+ oprresult => 'bool', oprcom => '>(float8,float8)',
+ oprnegate => '>=(float8,float8)', oprcode => 'float8lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '673', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'float8', oprright => 'float8',
+ oprresult => 'bool', oprcom => '>=(float8,float8)',
+ oprnegate => '>(float8,float8)', oprcode => 'float8le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '674', descr => 'greater than',
+ oprname => '>', oprleft => 'float8', oprright => 'float8',
+ oprresult => 'bool', oprcom => '<(float8,float8)',
+ oprnegate => '<=(float8,float8)', oprcode => 'float8gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '675', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'float8', oprright => 'float8',
+ oprresult => 'bool', oprcom => '<=(float8,float8)',
+ oprnegate => '<(float8,float8)', oprcode => 'float8ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+{ oid => '682', descr => 'absolute value',
+ oprname => '@', oprkind => 'l', oprleft => '0', oprright => 'int2',
+ oprresult => 'int2', oprcode => 'int2abs' },
+{ oid => '684', descr => 'add',
+ oprname => '+', oprleft => 'int8', oprright => 'int8', oprresult => 'int8',
+ oprcom => '+(int8,int8)', oprcode => 'int8pl' },
+{ oid => '685', descr => 'subtract',
+ oprname => '-', oprleft => 'int8', oprright => 'int8', oprresult => 'int8',
+ oprcode => 'int8mi' },
+{ oid => '686', descr => 'multiply',
+ oprname => '*', oprleft => 'int8', oprright => 'int8', oprresult => 'int8',
+ oprcom => '*(int8,int8)', oprcode => 'int8mul' },
+{ oid => '687', descr => 'divide',
+ oprname => '/', oprleft => 'int8', oprright => 'int8', oprresult => 'int8',
+ oprcode => 'int8div' },
+
+{ oid => '688', descr => 'add',
+ oprname => '+', oprleft => 'int8', oprright => 'int4', oprresult => 'int8',
+ oprcom => '+(int4,int8)', oprcode => 'int84pl' },
+{ oid => '689', descr => 'subtract',
+ oprname => '-', oprleft => 'int8', oprright => 'int4', oprresult => 'int8',
+ oprcode => 'int84mi' },
+{ oid => '690', descr => 'multiply',
+ oprname => '*', oprleft => 'int8', oprright => 'int4', oprresult => 'int8',
+ oprcom => '*(int4,int8)', oprcode => 'int84mul' },
+{ oid => '691', descr => 'divide',
+ oprname => '/', oprleft => 'int8', oprright => 'int4', oprresult => 'int8',
+ oprcode => 'int84div' },
+{ oid => '692', descr => 'add',
+ oprname => '+', oprleft => 'int4', oprright => 'int8', oprresult => 'int8',
+ oprcom => '+(int8,int4)', oprcode => 'int48pl' },
+{ oid => '693', descr => 'subtract',
+ oprname => '-', oprleft => 'int4', oprright => 'int8', oprresult => 'int8',
+ oprcode => 'int48mi' },
+{ oid => '694', descr => 'multiply',
+ oprname => '*', oprleft => 'int4', oprright => 'int8', oprresult => 'int8',
+ oprcom => '*(int8,int4)', oprcode => 'int48mul' },
+{ oid => '695', descr => 'divide',
+ oprname => '/', oprleft => 'int4', oprright => 'int8', oprresult => 'int8',
+ oprcode => 'int48div' },
+
+{ oid => '818', descr => 'add',
+ oprname => '+', oprleft => 'int8', oprright => 'int2', oprresult => 'int8',
+ oprcom => '+(int2,int8)', oprcode => 'int82pl' },
+{ oid => '819', descr => 'subtract',
+ oprname => '-', oprleft => 'int8', oprright => 'int2', oprresult => 'int8',
+ oprcode => 'int82mi' },
+{ oid => '820', descr => 'multiply',
+ oprname => '*', oprleft => 'int8', oprright => 'int2', oprresult => 'int8',
+ oprcom => '*(int2,int8)', oprcode => 'int82mul' },
+{ oid => '821', descr => 'divide',
+ oprname => '/', oprleft => 'int8', oprright => 'int2', oprresult => 'int8',
+ oprcode => 'int82div' },
+{ oid => '822', descr => 'add',
+ oprname => '+', oprleft => 'int2', oprright => 'int8', oprresult => 'int8',
+ oprcom => '+(int8,int2)', oprcode => 'int28pl' },
+{ oid => '823', descr => 'subtract',
+ oprname => '-', oprleft => 'int2', oprright => 'int8', oprresult => 'int8',
+ oprcode => 'int28mi' },
+{ oid => '824', descr => 'multiply',
+ oprname => '*', oprleft => 'int2', oprright => 'int8', oprresult => 'int8',
+ oprcom => '*(int8,int2)', oprcode => 'int28mul' },
+{ oid => '825', descr => 'divide',
+ oprname => '/', oprleft => 'int2', oprright => 'int8', oprresult => 'int8',
+ oprcode => 'int28div' },
+
+{ oid => '706', descr => 'distance between',
+ oprname => '<->', oprleft => 'box', oprright => 'box', oprresult => 'float8',
+ oprcom => '<->(box,box)', oprcode => 'box_distance' },
+{ oid => '707', descr => 'distance between',
+ oprname => '<->', oprleft => 'path', oprright => 'path',
+ oprresult => 'float8', oprcom => '<->(path,path)',
+ oprcode => 'path_distance' },
+{ oid => '708', descr => 'distance between',
+ oprname => '<->', oprleft => 'line', oprright => 'line',
+ oprresult => 'float8', oprcom => '<->(line,line)',
+ oprcode => 'line_distance' },
+{ oid => '709', descr => 'distance between',
+ oprname => '<->', oprleft => 'lseg', oprright => 'lseg',
+ oprresult => 'float8', oprcom => '<->(lseg,lseg)',
+ oprcode => 'lseg_distance' },
+{ oid => '712', descr => 'distance between',
+ oprname => '<->', oprleft => 'polygon', oprright => 'polygon',
+ oprresult => 'float8', oprcom => '<->(polygon,polygon)',
+ oprcode => 'poly_distance' },
+
+{ oid => '713', descr => 'not equal',
+ oprname => '<>', oprleft => 'point', oprright => 'point', oprresult => 'bool',
+ oprcom => '<>(point,point)', oprnegate => '~=(point,point)',
+ oprcode => 'point_ne', oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+
+# add translation/rotation/scaling operators for geometric types. - thomas 97/05/10
+{ oid => '731', descr => 'add points (translate)',
+ oprname => '+', oprleft => 'point', oprright => 'point', oprresult => 'point',
+ oprcom => '+(point,point)', oprcode => 'point_add' },
+{ oid => '732', descr => 'subtract points (translate)',
+ oprname => '-', oprleft => 'point', oprright => 'point', oprresult => 'point',
+ oprcode => 'point_sub' },
+{ oid => '733', descr => 'multiply points (scale/rotate)',
+ oprname => '*', oprleft => 'point', oprright => 'point', oprresult => 'point',
+ oprcom => '*(point,point)', oprcode => 'point_mul' },
+{ oid => '734', descr => 'divide points (scale/rotate)',
+ oprname => '/', oprleft => 'point', oprright => 'point', oprresult => 'point',
+ oprcode => 'point_div' },
+{ oid => '735', descr => 'concatenate',
+ oprname => '+', oprleft => 'path', oprright => 'path', oprresult => 'path',
+ oprcom => '+(path,path)', oprcode => 'path_add' },
+{ oid => '736', descr => 'add (translate path)',
+ oprname => '+', oprleft => 'path', oprright => 'point', oprresult => 'path',
+ oprcode => 'path_add_pt' },
+{ oid => '737', descr => 'subtract (translate path)',
+ oprname => '-', oprleft => 'path', oprright => 'point', oprresult => 'path',
+ oprcode => 'path_sub_pt' },
+{ oid => '738', descr => 'multiply (rotate/scale path)',
+ oprname => '*', oprleft => 'path', oprright => 'point', oprresult => 'path',
+ oprcode => 'path_mul_pt' },
+{ oid => '739', descr => 'divide (rotate/scale path)',
+ oprname => '/', oprleft => 'path', oprright => 'point', oprresult => 'path',
+ oprcode => 'path_div_pt' },
+{ oid => '755', descr => 'contains',
+ oprname => '@>', oprleft => 'path', oprright => 'point', oprresult => 'bool',
+ oprcom => '<@(point,path)', oprcode => 'path_contain_pt' },
+{ oid => '756', descr => 'is contained by',
+ oprname => '<@', oprleft => 'point', oprright => 'polygon',
+ oprresult => 'bool', oprcom => '@>(polygon,point)',
+ oprcode => 'pt_contained_poly', oprrest => 'contsel',
+ oprjoin => 'contjoinsel' },
+{ oid => '757', descr => 'contains',
+ oprname => '@>', oprleft => 'polygon', oprright => 'point',
+ oprresult => 'bool', oprcom => '<@(point,polygon)',
+ oprcode => 'poly_contain_pt', oprrest => 'contsel',
+ oprjoin => 'contjoinsel' },
+{ oid => '758', descr => 'is contained by',
+ oprname => '<@', oprleft => 'point', oprright => 'circle',
+ oprresult => 'bool', oprcom => '@>(circle,point)',
+ oprcode => 'pt_contained_circle', oprrest => 'contsel',
+ oprjoin => 'contjoinsel' },
+{ oid => '759', descr => 'contains',
+ oprname => '@>', oprleft => 'circle', oprright => 'point',
+ oprresult => 'bool', oprcom => '<@(point,circle)',
+ oprcode => 'circle_contain_pt', oprrest => 'contsel',
+ oprjoin => 'contjoinsel' },
+
+{ oid => '773', descr => 'absolute value',
+ oprname => '@', oprkind => 'l', oprleft => '0', oprright => 'int4',
+ oprresult => 'int4', oprcode => 'int4abs' },
+
+# additional operators for geometric types - thomas 1997-07-09
+{ oid => '792', descr => 'equal',
+ oprname => '=', oprleft => 'path', oprright => 'path', oprresult => 'bool',
+ oprcom => '=(path,path)', oprcode => 'path_n_eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '793', descr => 'less than',
+ oprname => '<', oprleft => 'path', oprright => 'path', oprresult => 'bool',
+ oprcom => '>(path,path)', oprcode => 'path_n_lt' },
+{ oid => '794', descr => 'greater than',
+ oprname => '>', oprleft => 'path', oprright => 'path', oprresult => 'bool',
+ oprcom => '<(path,path)', oprcode => 'path_n_gt' },
+{ oid => '795', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'path', oprright => 'path', oprresult => 'bool',
+ oprcom => '>=(path,path)', oprcode => 'path_n_le' },
+{ oid => '796', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'path', oprright => 'path', oprresult => 'bool',
+ oprcom => '<=(path,path)', oprcode => 'path_n_ge' },
+{ oid => '797', descr => 'number of points',
+ oprname => '#', oprkind => 'l', oprleft => '0', oprright => 'path',
+ oprresult => 'int4', oprcode => 'path_npoints' },
+{ oid => '798', descr => 'intersect',
+ oprname => '?#', oprleft => 'path', oprright => 'path', oprresult => 'bool',
+ oprcode => 'path_inter' },
+{ oid => '799', descr => 'sum of path segment lengths',
+ oprname => '@-@', oprkind => 'l', oprleft => '0', oprright => 'path',
+ oprresult => 'float8', oprcode => 'path_length' },
+{ oid => '800', descr => 'is above (allows touching)',
+ oprname => '>^', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcode => 'box_above_eq', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '801', descr => 'is below (allows touching)',
+ oprname => '<^', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcode => 'box_below_eq', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '802', descr => 'deprecated, use && instead',
+ oprname => '?#', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcode => 'box_overlap', oprrest => 'areasel', oprjoin => 'areajoinsel' },
+{ oid => '803', descr => 'box intersection',
+ oprname => '#', oprleft => 'box', oprright => 'box', oprresult => 'box',
+ oprcode => 'box_intersect' },
+{ oid => '804', descr => 'add point to box (translate)',
+ oprname => '+', oprleft => 'box', oprright => 'point', oprresult => 'box',
+ oprcode => 'box_add' },
+{ oid => '805', descr => 'subtract point from box (translate)',
+ oprname => '-', oprleft => 'box', oprright => 'point', oprresult => 'box',
+ oprcode => 'box_sub' },
+{ oid => '806', descr => 'multiply box by point (scale)',
+ oprname => '*', oprleft => 'box', oprright => 'point', oprresult => 'box',
+ oprcode => 'box_mul' },
+{ oid => '807', descr => 'divide box by point (scale)',
+ oprname => '/', oprleft => 'box', oprright => 'point', oprresult => 'box',
+ oprcode => 'box_div' },
+{ oid => '808', descr => 'horizontally aligned',
+ oprname => '?-', oprleft => 'point', oprright => 'point', oprresult => 'bool',
+ oprcom => '?-(point,point)', oprcode => 'point_horiz' },
+{ oid => '809', descr => 'vertically aligned',
+ oprname => '?|', oprleft => 'point', oprright => 'point', oprresult => 'bool',
+ oprcom => '?|(point,point)', oprcode => 'point_vert' },
+
+{ oid => '843', descr => 'multiply',
+ oprname => '*', oprleft => 'money', oprright => 'float4',
+ oprresult => 'money', oprcom => '*(float4,money)',
+ oprcode => 'cash_mul_flt4' },
+{ oid => '844', descr => 'divide',
+ oprname => '/', oprleft => 'money', oprright => 'float4',
+ oprresult => 'money', oprcode => 'cash_div_flt4' },
+{ oid => '845', descr => 'multiply',
+ oprname => '*', oprleft => 'float4', oprright => 'money',
+ oprresult => 'money', oprcom => '*(money,float4)',
+ oprcode => 'flt4_mul_cash' },
+
+{ oid => '900', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprleft => 'money', oprright => 'money',
+ oprresult => 'bool', oprcom => '=(money,money)',
+ oprnegate => '<>(money,money)', oprcode => 'cash_eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '901', descr => 'not equal',
+ oprname => '<>', oprleft => 'money', oprright => 'money', oprresult => 'bool',
+ oprcom => '<>(money,money)', oprnegate => '=(money,money)',
+ oprcode => 'cash_ne', oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '902', descr => 'less than',
+ oprname => '<', oprleft => 'money', oprright => 'money', oprresult => 'bool',
+ oprcom => '>(money,money)', oprnegate => '>=(money,money)',
+ oprcode => 'cash_lt', oprrest => 'scalarltsel',
+ oprjoin => 'scalarltjoinsel' },
+{ oid => '903', descr => 'greater than',
+ oprname => '>', oprleft => 'money', oprright => 'money', oprresult => 'bool',
+ oprcom => '<(money,money)', oprnegate => '<=(money,money)',
+ oprcode => 'cash_gt', oprrest => 'scalargtsel',
+ oprjoin => 'scalargtjoinsel' },
+{ oid => '904', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'money', oprright => 'money', oprresult => 'bool',
+ oprcom => '>=(money,money)', oprnegate => '>(money,money)',
+ oprcode => 'cash_le', oprrest => 'scalarlesel',
+ oprjoin => 'scalarlejoinsel' },
+{ oid => '905', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'money', oprright => 'money', oprresult => 'bool',
+ oprcom => '<=(money,money)', oprnegate => '<(money,money)',
+ oprcode => 'cash_ge', oprrest => 'scalargesel',
+ oprjoin => 'scalargejoinsel' },
+{ oid => '906', descr => 'add',
+ oprname => '+', oprleft => 'money', oprright => 'money', oprresult => 'money',
+ oprcom => '+(money,money)', oprcode => 'cash_pl' },
+{ oid => '907', descr => 'subtract',
+ oprname => '-', oprleft => 'money', oprright => 'money', oprresult => 'money',
+ oprcode => 'cash_mi' },
+{ oid => '908', descr => 'multiply',
+ oprname => '*', oprleft => 'money', oprright => 'float8',
+ oprresult => 'money', oprcom => '*(float8,money)',
+ oprcode => 'cash_mul_flt8' },
+{ oid => '909', descr => 'divide',
+ oprname => '/', oprleft => 'money', oprright => 'float8',
+ oprresult => 'money', oprcode => 'cash_div_flt8' },
+{ oid => '3346', descr => 'multiply',
+ oprname => '*', oprleft => 'money', oprright => 'int8', oprresult => 'money',
+ oprcom => '*(int8,money)', oprcode => 'cash_mul_int8' },
+{ oid => '3347', descr => 'divide',
+ oprname => '/', oprleft => 'money', oprright => 'int8', oprresult => 'money',
+ oprcode => 'cash_div_int8' },
+{ oid => '912', descr => 'multiply',
+ oprname => '*', oprleft => 'money', oprright => 'int4', oprresult => 'money',
+ oprcom => '*(int4,money)', oprcode => 'cash_mul_int4' },
+{ oid => '913', descr => 'divide',
+ oprname => '/', oprleft => 'money', oprright => 'int4', oprresult => 'money',
+ oprcode => 'cash_div_int4' },
+{ oid => '914', descr => 'multiply',
+ oprname => '*', oprleft => 'money', oprright => 'int2', oprresult => 'money',
+ oprcom => '*(int2,money)', oprcode => 'cash_mul_int2' },
+{ oid => '915', descr => 'divide',
+ oprname => '/', oprleft => 'money', oprright => 'int2', oprresult => 'money',
+ oprcode => 'cash_div_int2' },
+{ oid => '916', descr => 'multiply',
+ oprname => '*', oprleft => 'float8', oprright => 'money',
+ oprresult => 'money', oprcom => '*(money,float8)',
+ oprcode => 'flt8_mul_cash' },
+{ oid => '3349', descr => 'multiply',
+ oprname => '*', oprleft => 'int8', oprright => 'money', oprresult => 'money',
+ oprcom => '*(money,int8)', oprcode => 'int8_mul_cash' },
+{ oid => '917', descr => 'multiply',
+ oprname => '*', oprleft => 'int4', oprright => 'money', oprresult => 'money',
+ oprcom => '*(money,int4)', oprcode => 'int4_mul_cash' },
+{ oid => '918', descr => 'multiply',
+ oprname => '*', oprleft => 'int2', oprright => 'money', oprresult => 'money',
+ oprcom => '*(money,int2)', oprcode => 'int2_mul_cash' },
+{ oid => '3825', descr => 'divide',
+ oprname => '/', oprleft => 'money', oprright => 'money',
+ oprresult => 'float8', oprcode => 'cash_div_cash' },
+
+{ oid => '965', descr => 'exponentiation',
+ oprname => '^', oprleft => 'float8', oprright => 'float8',
+ oprresult => 'float8', oprcode => 'dpow' },
+{ oid => '966', descr => 'add/update ACL item',
+ oprname => '+', oprleft => '_aclitem', oprright => 'aclitem',
+ oprresult => '_aclitem', oprcode => 'aclinsert' },
+{ oid => '967', descr => 'remove ACL item',
+ oprname => '-', oprleft => '_aclitem', oprright => 'aclitem',
+ oprresult => '_aclitem', oprcode => 'aclremove' },
+{ oid => '968', descr => 'contains',
+ oprname => '@>', oprleft => '_aclitem', oprright => 'aclitem',
+ oprresult => 'bool', oprcode => 'aclcontains' },
+{ oid => '974', descr => 'equal',
+ oprname => '=', oprcanhash => 't', oprleft => 'aclitem',
+ oprright => 'aclitem', oprresult => 'bool', oprcom => '=(aclitem,aclitem)',
+ oprcode => 'aclitemeq', oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+
+# additional geometric operators - thomas 1997-07-09
+{ oid => '969', descr => 'center of',
+ oprname => '@@', oprkind => 'l', oprleft => '0', oprright => 'lseg',
+ oprresult => 'point', oprcode => 'lseg_center' },
+{ oid => '970', descr => 'center of',
+ oprname => '@@', oprkind => 'l', oprleft => '0', oprright => 'path',
+ oprresult => 'point', oprcode => 'path_center' },
+{ oid => '971', descr => 'center of',
+ oprname => '@@', oprkind => 'l', oprleft => '0', oprright => 'polygon',
+ oprresult => 'point', oprcode => 'poly_center' },
+
+{ oid => '1054', oid_symbol => 'BpcharEqualOperator', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'bpchar',
+ oprright => 'bpchar', oprresult => 'bool', oprcom => '=(bpchar,bpchar)',
+ oprnegate => '<>(bpchar,bpchar)', oprcode => 'bpchareq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+
+{ oid => '1055', oid_symbol => 'OID_BPCHAR_REGEXEQ_OP',
+ descr => 'matches regular expression, case-sensitive',
+ oprname => '~', oprleft => 'bpchar', oprright => 'text', oprresult => 'bool',
+ oprnegate => '!~(bpchar,text)', oprcode => 'bpcharregexeq',
+ oprrest => 'regexeqsel', oprjoin => 'regexeqjoinsel' },
+{ oid => '1056', descr => 'does not match regular expression, case-sensitive',
+ oprname => '!~', oprleft => 'bpchar', oprright => 'text', oprresult => 'bool',
+ oprnegate => '~(bpchar,text)', oprcode => 'bpcharregexne',
+ oprrest => 'regexnesel', oprjoin => 'regexnejoinsel' },
+{ oid => '1057', descr => 'not equal',
+ oprname => '<>', oprleft => 'bpchar', oprright => 'bpchar',
+ oprresult => 'bool', oprcom => '<>(bpchar,bpchar)',
+ oprnegate => '=(bpchar,bpchar)', oprcode => 'bpcharne', oprrest => 'neqsel',
+ oprjoin => 'neqjoinsel' },
+{ oid => '1058', oid_symbol => 'BpcharLessOperator', descr => 'less than',
+ oprname => '<', oprleft => 'bpchar', oprright => 'bpchar',
+ oprresult => 'bool', oprcom => '>(bpchar,bpchar)',
+ oprnegate => '>=(bpchar,bpchar)', oprcode => 'bpcharlt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '1059', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'bpchar', oprright => 'bpchar',
+ oprresult => 'bool', oprcom => '>=(bpchar,bpchar)',
+ oprnegate => '>(bpchar,bpchar)', oprcode => 'bpcharle',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '1060', descr => 'greater than',
+ oprname => '>', oprleft => 'bpchar', oprright => 'bpchar',
+ oprresult => 'bool', oprcom => '<(bpchar,bpchar)',
+ oprnegate => '<=(bpchar,bpchar)', oprcode => 'bpchargt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '1061', oid_symbol => 'BpcharGreaterEqualOperator',
+ descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'bpchar', oprright => 'bpchar',
+ oprresult => 'bool', oprcom => '<=(bpchar,bpchar)',
+ oprnegate => '<(bpchar,bpchar)', oprcode => 'bpcharge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+# generic array comparison operators
+{ oid => '1070', oid_symbol => 'ARRAY_EQ_OP', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'anyarray',
+ oprright => 'anyarray', oprresult => 'bool', oprcom => '=(anyarray,anyarray)',
+ oprnegate => '<>(anyarray,anyarray)', oprcode => 'array_eq',
+ oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '1071', descr => 'not equal',
+ oprname => '<>', oprleft => 'anyarray', oprright => 'anyarray',
+ oprresult => 'bool', oprcom => '<>(anyarray,anyarray)',
+ oprnegate => '=(anyarray,anyarray)', oprcode => 'array_ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '1072', oid_symbol => 'ARRAY_LT_OP', descr => 'less than',
+ oprname => '<', oprleft => 'anyarray', oprright => 'anyarray',
+ oprresult => 'bool', oprcom => '>(anyarray,anyarray)',
+ oprnegate => '>=(anyarray,anyarray)', oprcode => 'array_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '1073', oid_symbol => 'ARRAY_GT_OP', descr => 'greater than',
+ oprname => '>', oprleft => 'anyarray', oprright => 'anyarray',
+ oprresult => 'bool', oprcom => '<(anyarray,anyarray)',
+ oprnegate => '<=(anyarray,anyarray)', oprcode => 'array_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '1074', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'anyarray', oprright => 'anyarray',
+ oprresult => 'bool', oprcom => '>=(anyarray,anyarray)',
+ oprnegate => '>(anyarray,anyarray)', oprcode => 'array_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '1075', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'anyarray', oprright => 'anyarray',
+ oprresult => 'bool', oprcom => '<=(anyarray,anyarray)',
+ oprnegate => '<(anyarray,anyarray)', oprcode => 'array_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+# date operators
+{ oid => '1076', descr => 'add',
+ oprname => '+', oprleft => 'date', oprright => 'interval',
+ oprresult => 'timestamp', oprcom => '+(interval,date)',
+ oprcode => 'date_pl_interval' },
+{ oid => '1077', descr => 'subtract',
+ oprname => '-', oprleft => 'date', oprright => 'interval',
+ oprresult => 'timestamp', oprcode => 'date_mi_interval' },
+{ oid => '1093', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'date',
+ oprright => 'date', oprresult => 'bool', oprcom => '=(date,date)',
+ oprnegate => '<>(date,date)', oprcode => 'date_eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '1094', descr => 'not equal',
+ oprname => '<>', oprleft => 'date', oprright => 'date', oprresult => 'bool',
+ oprcom => '<>(date,date)', oprnegate => '=(date,date)', oprcode => 'date_ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '1095', descr => 'less than',
+ oprname => '<', oprleft => 'date', oprright => 'date', oprresult => 'bool',
+ oprcom => '>(date,date)', oprnegate => '>=(date,date)', oprcode => 'date_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '1096', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'date', oprright => 'date', oprresult => 'bool',
+ oprcom => '>=(date,date)', oprnegate => '>(date,date)', oprcode => 'date_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '1097', descr => 'greater than',
+ oprname => '>', oprleft => 'date', oprright => 'date', oprresult => 'bool',
+ oprcom => '<(date,date)', oprnegate => '<=(date,date)', oprcode => 'date_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '1098', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'date', oprright => 'date', oprresult => 'bool',
+ oprcom => '<=(date,date)', oprnegate => '<(date,date)', oprcode => 'date_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '1099', descr => 'subtract',
+ oprname => '-', oprleft => 'date', oprright => 'date', oprresult => 'int4',
+ oprcode => 'date_mi' },
+{ oid => '1100', descr => 'add',
+ oprname => '+', oprleft => 'date', oprright => 'int4', oprresult => 'date',
+ oprcom => '+(int4,date)', oprcode => 'date_pli' },
+{ oid => '1101', descr => 'subtract',
+ oprname => '-', oprleft => 'date', oprright => 'int4', oprresult => 'date',
+ oprcode => 'date_mii' },
+
+# time operators
+{ oid => '1108', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'time',
+ oprright => 'time', oprresult => 'bool', oprcom => '=(time,time)',
+ oprnegate => '<>(time,time)', oprcode => 'time_eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '1109', descr => 'not equal',
+ oprname => '<>', oprleft => 'time', oprright => 'time', oprresult => 'bool',
+ oprcom => '<>(time,time)', oprnegate => '=(time,time)', oprcode => 'time_ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '1110', descr => 'less than',
+ oprname => '<', oprleft => 'time', oprright => 'time', oprresult => 'bool',
+ oprcom => '>(time,time)', oprnegate => '>=(time,time)', oprcode => 'time_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '1111', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'time', oprright => 'time', oprresult => 'bool',
+ oprcom => '>=(time,time)', oprnegate => '>(time,time)', oprcode => 'time_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '1112', descr => 'greater than',
+ oprname => '>', oprleft => 'time', oprright => 'time', oprresult => 'bool',
+ oprcom => '<(time,time)', oprnegate => '<=(time,time)', oprcode => 'time_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '1113', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'time', oprright => 'time', oprresult => 'bool',
+ oprcom => '<=(time,time)', oprnegate => '<(time,time)', oprcode => 'time_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+# timetz operators
+{ oid => '1550', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'timetz',
+ oprright => 'timetz', oprresult => 'bool', oprcom => '=(timetz,timetz)',
+ oprnegate => '<>(timetz,timetz)', oprcode => 'timetz_eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '1551', descr => 'not equal',
+ oprname => '<>', oprleft => 'timetz', oprright => 'timetz',
+ oprresult => 'bool', oprcom => '<>(timetz,timetz)',
+ oprnegate => '=(timetz,timetz)', oprcode => 'timetz_ne', oprrest => 'neqsel',
+ oprjoin => 'neqjoinsel' },
+{ oid => '1552', descr => 'less than',
+ oprname => '<', oprleft => 'timetz', oprright => 'timetz',
+ oprresult => 'bool', oprcom => '>(timetz,timetz)',
+ oprnegate => '>=(timetz,timetz)', oprcode => 'timetz_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '1553', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'timetz', oprright => 'timetz',
+ oprresult => 'bool', oprcom => '>=(timetz,timetz)',
+ oprnegate => '>(timetz,timetz)', oprcode => 'timetz_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '1554', descr => 'greater than',
+ oprname => '>', oprleft => 'timetz', oprright => 'timetz',
+ oprresult => 'bool', oprcom => '<(timetz,timetz)',
+ oprnegate => '<=(timetz,timetz)', oprcode => 'timetz_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '1555', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'timetz', oprright => 'timetz',
+ oprresult => 'bool', oprcom => '<=(timetz,timetz)',
+ oprnegate => '<(timetz,timetz)', oprcode => 'timetz_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+# float48 operators
+{ oid => '1116', descr => 'add',
+ oprname => '+', oprleft => 'float4', oprright => 'float8',
+ oprresult => 'float8', oprcom => '+(float8,float4)', oprcode => 'float48pl' },
+{ oid => '1117', descr => 'subtract',
+ oprname => '-', oprleft => 'float4', oprright => 'float8',
+ oprresult => 'float8', oprcode => 'float48mi' },
+{ oid => '1118', descr => 'divide',
+ oprname => '/', oprleft => 'float4', oprright => 'float8',
+ oprresult => 'float8', oprcode => 'float48div' },
+{ oid => '1119', descr => 'multiply',
+ oprname => '*', oprleft => 'float4', oprright => 'float8',
+ oprresult => 'float8', oprcom => '*(float8,float4)',
+ oprcode => 'float48mul' },
+{ oid => '1120', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'float4',
+ oprright => 'float8', oprresult => 'bool', oprcom => '=(float8,float4)',
+ oprnegate => '<>(float4,float8)', oprcode => 'float48eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '1121', descr => 'not equal',
+ oprname => '<>', oprleft => 'float4', oprright => 'float8',
+ oprresult => 'bool', oprcom => '<>(float8,float4)',
+ oprnegate => '=(float4,float8)', oprcode => 'float48ne', oprrest => 'neqsel',
+ oprjoin => 'neqjoinsel' },
+{ oid => '1122', descr => 'less than',
+ oprname => '<', oprleft => 'float4', oprright => 'float8',
+ oprresult => 'bool', oprcom => '>(float8,float4)',
+ oprnegate => '>=(float4,float8)', oprcode => 'float48lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '1123', descr => 'greater than',
+ oprname => '>', oprleft => 'float4', oprright => 'float8',
+ oprresult => 'bool', oprcom => '<(float8,float4)',
+ oprnegate => '<=(float4,float8)', oprcode => 'float48gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '1124', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'float4', oprright => 'float8',
+ oprresult => 'bool', oprcom => '>=(float8,float4)',
+ oprnegate => '>(float4,float8)', oprcode => 'float48le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '1125', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'float4', oprright => 'float8',
+ oprresult => 'bool', oprcom => '<=(float8,float4)',
+ oprnegate => '<(float4,float8)', oprcode => 'float48ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+# float84 operators
+{ oid => '1126', descr => 'add',
+ oprname => '+', oprleft => 'float8', oprright => 'float4',
+ oprresult => 'float8', oprcom => '+(float4,float8)', oprcode => 'float84pl' },
+{ oid => '1127', descr => 'subtract',
+ oprname => '-', oprleft => 'float8', oprright => 'float4',
+ oprresult => 'float8', oprcode => 'float84mi' },
+{ oid => '1128', descr => 'divide',
+ oprname => '/', oprleft => 'float8', oprright => 'float4',
+ oprresult => 'float8', oprcode => 'float84div' },
+{ oid => '1129', descr => 'multiply',
+ oprname => '*', oprleft => 'float8', oprright => 'float4',
+ oprresult => 'float8', oprcom => '*(float4,float8)',
+ oprcode => 'float84mul' },
+{ oid => '1130', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'float8',
+ oprright => 'float4', oprresult => 'bool', oprcom => '=(float4,float8)',
+ oprnegate => '<>(float8,float4)', oprcode => 'float84eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '1131', descr => 'not equal',
+ oprname => '<>', oprleft => 'float8', oprright => 'float4',
+ oprresult => 'bool', oprcom => '<>(float4,float8)',
+ oprnegate => '=(float8,float4)', oprcode => 'float84ne', oprrest => 'neqsel',
+ oprjoin => 'neqjoinsel' },
+{ oid => '1132', descr => 'less than',
+ oprname => '<', oprleft => 'float8', oprright => 'float4',
+ oprresult => 'bool', oprcom => '>(float4,float8)',
+ oprnegate => '>=(float8,float4)', oprcode => 'float84lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '1133', descr => 'greater than',
+ oprname => '>', oprleft => 'float8', oprright => 'float4',
+ oprresult => 'bool', oprcom => '<(float4,float8)',
+ oprnegate => '<=(float8,float4)', oprcode => 'float84gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '1134', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'float8', oprright => 'float4',
+ oprresult => 'bool', oprcom => '>=(float4,float8)',
+ oprnegate => '>(float8,float4)', oprcode => 'float84le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '1135', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'float8', oprright => 'float4',
+ oprresult => 'bool', oprcom => '<=(float4,float8)',
+ oprnegate => '<(float8,float4)', oprcode => 'float84ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+# LIKE hacks by Keith Parks.
+{ oid => '1207', oid_symbol => 'OID_NAME_LIKE_OP',
+ descr => 'matches LIKE expression',
+ oprname => '~~', oprleft => 'name', oprright => 'text', oprresult => 'bool',
+ oprnegate => '!~~(name,text)', oprcode => 'namelike', oprrest => 'likesel',
+ oprjoin => 'likejoinsel' },
+{ oid => '1208', descr => 'does not match LIKE expression',
+ oprname => '!~~', oprleft => 'name', oprright => 'text', oprresult => 'bool',
+ oprnegate => '~~(name,text)', oprcode => 'namenlike', oprrest => 'nlikesel',
+ oprjoin => 'nlikejoinsel' },
+{ oid => '1209', oid_symbol => 'OID_TEXT_LIKE_OP',
+ descr => 'matches LIKE expression',
+ oprname => '~~', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprnegate => '!~~(text,text)', oprcode => 'textlike', oprrest => 'likesel',
+ oprjoin => 'likejoinsel' },
+{ oid => '1210', descr => 'does not match LIKE expression',
+ oprname => '!~~', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprnegate => '~~(text,text)', oprcode => 'textnlike', oprrest => 'nlikesel',
+ oprjoin => 'nlikejoinsel' },
+{ oid => '1211', oid_symbol => 'OID_BPCHAR_LIKE_OP',
+ descr => 'matches LIKE expression',
+ oprname => '~~', oprleft => 'bpchar', oprright => 'text', oprresult => 'bool',
+ oprnegate => '!~~(bpchar,text)', oprcode => 'bpcharlike',
+ oprrest => 'likesel', oprjoin => 'likejoinsel' },
+{ oid => '1212', descr => 'does not match LIKE expression',
+ oprname => '!~~', oprleft => 'bpchar', oprright => 'text',
+ oprresult => 'bool', oprnegate => '~~(bpchar,text)', oprcode => 'bpcharnlike',
+ oprrest => 'nlikesel', oprjoin => 'nlikejoinsel' },
+
+# case-insensitive regex hacks
+{ oid => '1226', oid_symbol => 'OID_NAME_ICREGEXEQ_OP',
+ descr => 'matches regular expression, case-insensitive',
+ oprname => '~*', oprleft => 'name', oprright => 'text', oprresult => 'bool',
+ oprnegate => '!~*(name,text)', oprcode => 'nameicregexeq',
+ oprrest => 'icregexeqsel', oprjoin => 'icregexeqjoinsel' },
+{ oid => '1227',
+ descr => 'does not match regular expression, case-insensitive',
+ oprname => '!~*', oprleft => 'name', oprright => 'text', oprresult => 'bool',
+ oprnegate => '~*(name,text)', oprcode => 'nameicregexne',
+ oprrest => 'icregexnesel', oprjoin => 'icregexnejoinsel' },
+{ oid => '1228', oid_symbol => 'OID_TEXT_ICREGEXEQ_OP',
+ descr => 'matches regular expression, case-insensitive',
+ oprname => '~*', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprnegate => '!~*(text,text)', oprcode => 'texticregexeq',
+ oprrest => 'icregexeqsel', oprjoin => 'icregexeqjoinsel' },
+{ oid => '1229',
+ descr => 'does not match regular expression, case-insensitive',
+ oprname => '!~*', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprnegate => '~*(text,text)', oprcode => 'texticregexne',
+ oprrest => 'icregexnesel', oprjoin => 'icregexnejoinsel' },
+{ oid => '1234', oid_symbol => 'OID_BPCHAR_ICREGEXEQ_OP',
+ descr => 'matches regular expression, case-insensitive',
+ oprname => '~*', oprleft => 'bpchar', oprright => 'text', oprresult => 'bool',
+ oprnegate => '!~*(bpchar,text)', oprcode => 'bpcharicregexeq',
+ oprrest => 'icregexeqsel', oprjoin => 'icregexeqjoinsel' },
+{ oid => '1235',
+ descr => 'does not match regular expression, case-insensitive',
+ oprname => '!~*', oprleft => 'bpchar', oprright => 'text',
+ oprresult => 'bool', oprnegate => '~*(bpchar,text)',
+ oprcode => 'bpcharicregexne', oprrest => 'icregexnesel',
+ oprjoin => 'icregexnejoinsel' },
+
+# timestamptz operators
+{ oid => '1320', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't',
+ oprleft => 'timestamptz', oprright => 'timestamptz', oprresult => 'bool',
+ oprcom => '=(timestamptz,timestamptz)',
+ oprnegate => '<>(timestamptz,timestamptz)', oprcode => 'timestamptz_eq',
+ oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '1321', descr => 'not equal',
+ oprname => '<>', oprleft => 'timestamptz', oprright => 'timestamptz',
+ oprresult => 'bool', oprcom => '<>(timestamptz,timestamptz)',
+ oprnegate => '=(timestamptz,timestamptz)', oprcode => 'timestamptz_ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '1322', descr => 'less than',
+ oprname => '<', oprleft => 'timestamptz', oprright => 'timestamptz',
+ oprresult => 'bool', oprcom => '>(timestamptz,timestamptz)',
+ oprnegate => '>=(timestamptz,timestamptz)', oprcode => 'timestamptz_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '1323', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'timestamptz', oprright => 'timestamptz',
+ oprresult => 'bool', oprcom => '>=(timestamptz,timestamptz)',
+ oprnegate => '>(timestamptz,timestamptz)', oprcode => 'timestamptz_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '1324', descr => 'greater than',
+ oprname => '>', oprleft => 'timestamptz', oprright => 'timestamptz',
+ oprresult => 'bool', oprcom => '<(timestamptz,timestamptz)',
+ oprnegate => '<=(timestamptz,timestamptz)', oprcode => 'timestamptz_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '1325', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'timestamptz', oprright => 'timestamptz',
+ oprresult => 'bool', oprcom => '<=(timestamptz,timestamptz)',
+ oprnegate => '<(timestamptz,timestamptz)', oprcode => 'timestamptz_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '1327', descr => 'add',
+ oprname => '+', oprleft => 'timestamptz', oprright => 'interval',
+ oprresult => 'timestamptz', oprcom => '+(interval,timestamptz)',
+ oprcode => 'timestamptz_pl_interval' },
+{ oid => '1328', descr => 'subtract',
+ oprname => '-', oprleft => 'timestamptz', oprright => 'timestamptz',
+ oprresult => 'interval', oprcode => 'timestamptz_mi' },
+{ oid => '1329', descr => 'subtract',
+ oprname => '-', oprleft => 'timestamptz', oprright => 'interval',
+ oprresult => 'timestamptz', oprcode => 'timestamptz_mi_interval' },
+
+# interval operators
+{ oid => '1330', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'interval',
+ oprright => 'interval', oprresult => 'bool', oprcom => '=(interval,interval)',
+ oprnegate => '<>(interval,interval)', oprcode => 'interval_eq',
+ oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '1331', descr => 'not equal',
+ oprname => '<>', oprleft => 'interval', oprright => 'interval',
+ oprresult => 'bool', oprcom => '<>(interval,interval)',
+ oprnegate => '=(interval,interval)', oprcode => 'interval_ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '1332', descr => 'less than',
+ oprname => '<', oprleft => 'interval', oprright => 'interval',
+ oprresult => 'bool', oprcom => '>(interval,interval)',
+ oprnegate => '>=(interval,interval)', oprcode => 'interval_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '1333', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'interval', oprright => 'interval',
+ oprresult => 'bool', oprcom => '>=(interval,interval)',
+ oprnegate => '>(interval,interval)', oprcode => 'interval_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '1334', descr => 'greater than',
+ oprname => '>', oprleft => 'interval', oprright => 'interval',
+ oprresult => 'bool', oprcom => '<(interval,interval)',
+ oprnegate => '<=(interval,interval)', oprcode => 'interval_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '1335', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'interval', oprright => 'interval',
+ oprresult => 'bool', oprcom => '<=(interval,interval)',
+ oprnegate => '<(interval,interval)', oprcode => 'interval_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+{ oid => '1336', descr => 'negate',
+ oprname => '-', oprkind => 'l', oprleft => '0', oprright => 'interval',
+ oprresult => 'interval', oprcode => 'interval_um' },
+{ oid => '1337', descr => 'add',
+ oprname => '+', oprleft => 'interval', oprright => 'interval',
+ oprresult => 'interval', oprcom => '+(interval,interval)',
+ oprcode => 'interval_pl' },
+{ oid => '1338', descr => 'subtract',
+ oprname => '-', oprleft => 'interval', oprright => 'interval',
+ oprresult => 'interval', oprcode => 'interval_mi' },
+
+{ oid => '1360', descr => 'convert date and time to timestamp',
+ oprname => '+', oprleft => 'date', oprright => 'time',
+ oprresult => 'timestamp', oprcom => '+(time,date)',
+ oprcode => 'datetime_pl' },
+{ oid => '1361',
+ descr => 'convert date and time with time zone to timestamp with time zone',
+ oprname => '+', oprleft => 'date', oprright => 'timetz',
+ oprresult => 'timestamptz', oprcom => '+(timetz,date)',
+ oprcode => 'datetimetz_pl' },
+{ oid => '1363', descr => 'convert time and date to timestamp',
+ oprname => '+', oprleft => 'time', oprright => 'date',
+ oprresult => 'timestamp', oprcom => '+(date,time)',
+ oprcode => 'timedate_pl' },
+{ oid => '1366',
+ descr => 'convert time with time zone and date to timestamp with time zone',
+ oprname => '+', oprleft => 'timetz', oprright => 'date',
+ oprresult => 'timestamptz', oprcom => '+(date,timetz)',
+ oprcode => 'timetzdate_pl' },
+
+{ oid => '1399', descr => 'subtract',
+ oprname => '-', oprleft => 'time', oprright => 'time',
+ oprresult => 'interval', oprcode => 'time_mi_time' },
+
+# additional geometric operators - thomas 97/04/18
+{ oid => '1420', descr => 'center of',
+ oprname => '@@', oprkind => 'l', oprleft => '0', oprright => 'circle',
+ oprresult => 'point', oprcode => 'circle_center' },
+{ oid => '1500', descr => 'equal by area',
+ oprname => '=', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcom => '=(circle,circle)',
+ oprnegate => '<>(circle,circle)', oprcode => 'circle_eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '1501', descr => 'not equal by area',
+ oprname => '<>', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcom => '<>(circle,circle)',
+ oprnegate => '=(circle,circle)', oprcode => 'circle_ne', oprrest => 'neqsel',
+ oprjoin => 'neqjoinsel' },
+{ oid => '1502', descr => 'less than by area',
+ oprname => '<', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcom => '>(circle,circle)',
+ oprnegate => '>=(circle,circle)', oprcode => 'circle_lt',
+ oprrest => 'areasel', oprjoin => 'areajoinsel' },
+{ oid => '1503', descr => 'greater than by area',
+ oprname => '>', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcom => '<(circle,circle)',
+ oprnegate => '<=(circle,circle)', oprcode => 'circle_gt',
+ oprrest => 'areasel', oprjoin => 'areajoinsel' },
+{ oid => '1504', descr => 'less than or equal by area',
+ oprname => '<=', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcom => '>=(circle,circle)',
+ oprnegate => '>(circle,circle)', oprcode => 'circle_le', oprrest => 'areasel',
+ oprjoin => 'areajoinsel' },
+{ oid => '1505', descr => 'greater than or equal by area',
+ oprname => '>=', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcom => '<=(circle,circle)',
+ oprnegate => '<(circle,circle)', oprcode => 'circle_ge', oprrest => 'areasel',
+ oprjoin => 'areajoinsel' },
+
+{ oid => '1506', descr => 'is left of',
+ oprname => '<<', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcode => 'circle_left', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '1507', descr => 'overlaps or is left of',
+ oprname => '&<', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcode => 'circle_overleft', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '1508', descr => 'overlaps or is right of',
+ oprname => '&>', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcode => 'circle_overright', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '1509', descr => 'is right of',
+ oprname => '>>', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcode => 'circle_right', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '1510', descr => 'is contained by',
+ oprname => '<@', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcom => '@>(circle,circle)',
+ oprcode => 'circle_contained', oprrest => 'contsel',
+ oprjoin => 'contjoinsel' },
+{ oid => '1511', descr => 'contains',
+ oprname => '@>', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcom => '<@(circle,circle)',
+ oprcode => 'circle_contain', oprrest => 'contsel', oprjoin => 'contjoinsel' },
+{ oid => '1512', descr => 'same as',
+ oprname => '~=', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcom => '~=(circle,circle)', oprcode => 'circle_same',
+ oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '1513', descr => 'overlaps',
+ oprname => '&&', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcom => '&&(circle,circle)',
+ oprcode => 'circle_overlap', oprrest => 'areasel', oprjoin => 'areajoinsel' },
+{ oid => '1514', descr => 'is above',
+ oprname => '|>>', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcode => 'circle_above', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '1515', descr => 'is below',
+ oprname => '<<|', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcode => 'circle_below', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+
+{ oid => '1516', descr => 'add',
+ oprname => '+', oprleft => 'circle', oprright => 'point',
+ oprresult => 'circle', oprcode => 'circle_add_pt' },
+{ oid => '1517', descr => 'subtract',
+ oprname => '-', oprleft => 'circle', oprright => 'point',
+ oprresult => 'circle', oprcode => 'circle_sub_pt' },
+{ oid => '1518', descr => 'multiply',
+ oprname => '*', oprleft => 'circle', oprright => 'point',
+ oprresult => 'circle', oprcode => 'circle_mul_pt' },
+{ oid => '1519', descr => 'divide',
+ oprname => '/', oprleft => 'circle', oprright => 'point',
+ oprresult => 'circle', oprcode => 'circle_div_pt' },
+
+{ oid => '1520', descr => 'distance between',
+ oprname => '<->', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'float8', oprcom => '<->(circle,circle)',
+ oprcode => 'circle_distance' },
+{ oid => '1521', descr => 'number of points',
+ oprname => '#', oprkind => 'l', oprleft => '0', oprright => 'polygon',
+ oprresult => 'int4', oprcode => 'poly_npoints' },
+{ oid => '1522', descr => 'distance between',
+ oprname => '<->', oprleft => 'point', oprright => 'circle',
+ oprresult => 'float8', oprcom => '<->(circle,point)', oprcode => 'dist_pc' },
+{ oid => '3291', descr => 'distance between',
+ oprname => '<->', oprleft => 'circle', oprright => 'point',
+ oprresult => 'float8', oprcom => '<->(point,circle)',
+ oprcode => 'dist_cpoint' },
+{ oid => '3276', descr => 'distance between',
+ oprname => '<->', oprleft => 'point', oprright => 'polygon',
+ oprresult => 'float8', oprcom => '<->(polygon,point)',
+ oprcode => 'dist_ppoly' },
+{ oid => '3289', descr => 'distance between',
+ oprname => '<->', oprleft => 'polygon', oprright => 'point',
+ oprresult => 'float8', oprcom => '<->(point,polygon)',
+ oprcode => 'dist_polyp' },
+{ oid => '1523', descr => 'distance between',
+ oprname => '<->', oprleft => 'circle', oprright => 'polygon',
+ oprresult => 'float8', oprcom => '<->(polygon,circle)',
+ oprcode => 'dist_cpoly' },
+{ oid => '1383', descr => 'distance between',
+ oprname => '<->', oprleft => 'polygon', oprright => 'circle',
+ oprresult => 'float8', oprcom => '<->(circle,polygon)',
+ oprcode => 'dist_polyc' },
+
+# additional geometric operators - thomas 1997-07-09
+{ oid => '1524', descr => 'distance between',
+ oprname => '<->', oprleft => 'line', oprright => 'box', oprresult => 'float8',
+ oprcom => '<->(box,line)', oprcode => 'dist_lb' },
+{ oid => '1382', descr => 'distance between',
+ oprname => '<->', oprleft => 'box', oprright => 'line', oprresult => 'float8',
+ oprcom => '<->(line,box)', oprcode => 'dist_bl' },
+
+{ oid => '1525', descr => 'intersect',
+ oprname => '?#', oprleft => 'lseg', oprright => 'lseg', oprresult => 'bool',
+ oprcom => '?#(lseg,lseg)', oprcode => 'lseg_intersect' },
+{ oid => '1526', descr => 'parallel',
+ oprname => '?||', oprleft => 'lseg', oprright => 'lseg', oprresult => 'bool',
+ oprcom => '?||(lseg,lseg)', oprcode => 'lseg_parallel' },
+{ oid => '1527', descr => 'perpendicular',
+ oprname => '?-|', oprleft => 'lseg', oprright => 'lseg', oprresult => 'bool',
+ oprcom => '?-|(lseg,lseg)', oprcode => 'lseg_perp' },
+{ oid => '1528', descr => 'horizontal',
+ oprname => '?-', oprkind => 'l', oprleft => '0', oprright => 'lseg',
+ oprresult => 'bool', oprcode => 'lseg_horizontal' },
+{ oid => '1529', descr => 'vertical',
+ oprname => '?|', oprkind => 'l', oprleft => '0', oprright => 'lseg',
+ oprresult => 'bool', oprcode => 'lseg_vertical' },
+{ oid => '1535', descr => 'equal',
+ oprname => '=', oprleft => 'lseg', oprright => 'lseg', oprresult => 'bool',
+ oprcom => '=(lseg,lseg)', oprnegate => '<>(lseg,lseg)', oprcode => 'lseg_eq',
+ oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '1536', descr => 'intersection point',
+ oprname => '#', oprleft => 'lseg', oprright => 'lseg', oprresult => 'point',
+ oprcom => '#(lseg,lseg)', oprcode => 'lseg_interpt' },
+{ oid => '1537', descr => 'intersect',
+ oprname => '?#', oprleft => 'lseg', oprright => 'line', oprresult => 'bool',
+ oprcode => 'inter_sl' },
+{ oid => '1538', descr => 'intersect',
+ oprname => '?#', oprleft => 'lseg', oprright => 'box', oprresult => 'bool',
+ oprcode => 'inter_sb' },
+{ oid => '1539', descr => 'intersect',
+ oprname => '?#', oprleft => 'line', oprright => 'box', oprresult => 'bool',
+ oprcode => 'inter_lb' },
+
+{ oid => '1546', descr => 'point on line',
+ oprname => '<@', oprleft => 'point', oprright => 'line', oprresult => 'bool',
+ oprcode => 'on_pl' },
+{ oid => '1547', descr => 'is contained by',
+ oprname => '<@', oprleft => 'point', oprright => 'lseg', oprresult => 'bool',
+ oprcode => 'on_ps' },
+{ oid => '1548', descr => 'lseg on line',
+ oprname => '<@', oprleft => 'lseg', oprright => 'line', oprresult => 'bool',
+ oprcode => 'on_sl' },
+{ oid => '1549', descr => 'is contained by',
+ oprname => '<@', oprleft => 'lseg', oprright => 'box', oprresult => 'bool',
+ oprcode => 'on_sb' },
+
+{ oid => '1557', descr => 'closest point to A on B',
+ oprname => '##', oprleft => 'point', oprright => 'line', oprresult => 'point',
+ oprcode => 'close_pl' },
+{ oid => '1558', descr => 'closest point to A on B',
+ oprname => '##', oprleft => 'point', oprright => 'lseg', oprresult => 'point',
+ oprcode => 'close_ps' },
+{ oid => '1559', descr => 'closest point to A on B',
+ oprname => '##', oprleft => 'point', oprright => 'box', oprresult => 'point',
+ oprcode => 'close_pb' },
+
+{ oid => '1566', descr => 'closest point to A on B',
+ oprname => '##', oprleft => 'lseg', oprright => 'line', oprresult => 'point',
+ oprcode => 'close_sl' },
+{ oid => '1567', descr => 'closest point to A on B',
+ oprname => '##', oprleft => 'lseg', oprright => 'box', oprresult => 'point',
+ oprcode => 'close_sb' },
+{ oid => '1568', descr => 'closest point to A on B',
+ oprname => '##', oprleft => 'line', oprright => 'box', oprresult => 'point',
+ oprcode => 'close_lb' },
+{ oid => '1577', descr => 'closest point to A on B',
+ oprname => '##', oprleft => 'line', oprright => 'lseg', oprresult => 'point',
+ oprcode => 'close_ls' },
+{ oid => '1578', descr => 'closest point to A on B',
+ oprname => '##', oprleft => 'lseg', oprright => 'lseg', oprresult => 'point',
+ oprcode => 'close_lseg' },
+{ oid => '1583', descr => 'multiply',
+ oprname => '*', oprleft => 'interval', oprright => 'float8',
+ oprresult => 'interval', oprcom => '*(float8,interval)',
+ oprcode => 'interval_mul' },
+{ oid => '1584', descr => 'multiply',
+ oprname => '*', oprleft => 'float8', oprright => 'interval',
+ oprresult => 'interval', oprcom => '*(interval,float8)',
+ oprcode => 'mul_d_interval' },
+{ oid => '1585', descr => 'divide',
+ oprname => '/', oprleft => 'interval', oprright => 'float8',
+ oprresult => 'interval', oprcode => 'interval_div' },
+
+{ oid => '1586', descr => 'not equal',
+ oprname => '<>', oprleft => 'lseg', oprright => 'lseg', oprresult => 'bool',
+ oprcom => '<>(lseg,lseg)', oprnegate => '=(lseg,lseg)', oprcode => 'lseg_ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '1587', descr => 'less than by length',
+ oprname => '<', oprleft => 'lseg', oprright => 'lseg', oprresult => 'bool',
+ oprcom => '>(lseg,lseg)', oprnegate => '>=(lseg,lseg)',
+ oprcode => 'lseg_lt' },
+{ oid => '1588', descr => 'less than or equal by length',
+ oprname => '<=', oprleft => 'lseg', oprright => 'lseg', oprresult => 'bool',
+ oprcom => '>=(lseg,lseg)', oprnegate => '>(lseg,lseg)',
+ oprcode => 'lseg_le' },
+{ oid => '1589', descr => 'greater than by length',
+ oprname => '>', oprleft => 'lseg', oprright => 'lseg', oprresult => 'bool',
+ oprcom => '<(lseg,lseg)', oprnegate => '<=(lseg,lseg)',
+ oprcode => 'lseg_gt' },
+{ oid => '1590', descr => 'greater than or equal by length',
+ oprname => '>=', oprleft => 'lseg', oprright => 'lseg', oprresult => 'bool',
+ oprcom => '<=(lseg,lseg)', oprnegate => '<(lseg,lseg)',
+ oprcode => 'lseg_ge' },
+
+{ oid => '1591', descr => 'distance between endpoints',
+ oprname => '@-@', oprkind => 'l', oprleft => '0', oprright => 'lseg',
+ oprresult => 'float8', oprcode => 'lseg_length' },
+
+{ oid => '1611', descr => 'intersect',
+ oprname => '?#', oprleft => 'line', oprright => 'line', oprresult => 'bool',
+ oprcom => '?#(line,line)', oprcode => 'line_intersect' },
+{ oid => '1612', descr => 'parallel',
+ oprname => '?||', oprleft => 'line', oprright => 'line', oprresult => 'bool',
+ oprcom => '?||(line,line)', oprcode => 'line_parallel' },
+{ oid => '1613', descr => 'perpendicular',
+ oprname => '?-|', oprleft => 'line', oprright => 'line', oprresult => 'bool',
+ oprcom => '?-|(line,line)', oprcode => 'line_perp' },
+{ oid => '1614', descr => 'horizontal',
+ oprname => '?-', oprkind => 'l', oprleft => '0', oprright => 'line',
+ oprresult => 'bool', oprcode => 'line_horizontal' },
+{ oid => '1615', descr => 'vertical',
+ oprname => '?|', oprkind => 'l', oprleft => '0', oprright => 'line',
+ oprresult => 'bool', oprcode => 'line_vertical' },
+{ oid => '1616', descr => 'equal',
+ oprname => '=', oprleft => 'line', oprright => 'line', oprresult => 'bool',
+ oprcom => '=(line,line)', oprcode => 'line_eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '1617', descr => 'intersection point',
+ oprname => '#', oprleft => 'line', oprright => 'line', oprresult => 'point',
+ oprcom => '#(line,line)', oprcode => 'line_interpt' },
+
+# MACADDR type
+{ oid => '1220', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'macaddr',
+ oprright => 'macaddr', oprresult => 'bool', oprcom => '=(macaddr,macaddr)',
+ oprnegate => '<>(macaddr,macaddr)', oprcode => 'macaddr_eq',
+ oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '1221', descr => 'not equal',
+ oprname => '<>', oprleft => 'macaddr', oprright => 'macaddr',
+ oprresult => 'bool', oprcom => '<>(macaddr,macaddr)',
+ oprnegate => '=(macaddr,macaddr)', oprcode => 'macaddr_ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '1222', descr => 'less than',
+ oprname => '<', oprleft => 'macaddr', oprright => 'macaddr',
+ oprresult => 'bool', oprcom => '>(macaddr,macaddr)',
+ oprnegate => '>=(macaddr,macaddr)', oprcode => 'macaddr_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '1223', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'macaddr', oprright => 'macaddr',
+ oprresult => 'bool', oprcom => '>=(macaddr,macaddr)',
+ oprnegate => '>(macaddr,macaddr)', oprcode => 'macaddr_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '1224', descr => 'greater than',
+ oprname => '>', oprleft => 'macaddr', oprright => 'macaddr',
+ oprresult => 'bool', oprcom => '<(macaddr,macaddr)',
+ oprnegate => '<=(macaddr,macaddr)', oprcode => 'macaddr_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '1225', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'macaddr', oprright => 'macaddr',
+ oprresult => 'bool', oprcom => '<=(macaddr,macaddr)',
+ oprnegate => '<(macaddr,macaddr)', oprcode => 'macaddr_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+{ oid => '3147', descr => 'bitwise not',
+ oprname => '~', oprkind => 'l', oprleft => '0', oprright => 'macaddr',
+ oprresult => 'macaddr', oprcode => 'macaddr_not' },
+{ oid => '3148', descr => 'bitwise and',
+ oprname => '&', oprleft => 'macaddr', oprright => 'macaddr',
+ oprresult => 'macaddr', oprcode => 'macaddr_and' },
+{ oid => '3149', descr => 'bitwise or',
+ oprname => '|', oprleft => 'macaddr', oprright => 'macaddr',
+ oprresult => 'macaddr', oprcode => 'macaddr_or' },
+
+# MACADDR8 type
+{ oid => '3362', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'macaddr8',
+ oprright => 'macaddr8', oprresult => 'bool', oprcom => '=(macaddr8,macaddr8)',
+ oprnegate => '<>(macaddr8,macaddr8)', oprcode => 'macaddr8_eq',
+ oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '3363', descr => 'not equal',
+ oprname => '<>', oprleft => 'macaddr8', oprright => 'macaddr8',
+ oprresult => 'bool', oprcom => '<>(macaddr8,macaddr8)',
+ oprnegate => '=(macaddr8,macaddr8)', oprcode => 'macaddr8_ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '3364', descr => 'less than',
+ oprname => '<', oprleft => 'macaddr8', oprright => 'macaddr8',
+ oprresult => 'bool', oprcom => '>(macaddr8,macaddr8)',
+ oprnegate => '>=(macaddr8,macaddr8)', oprcode => 'macaddr8_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '3365', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'macaddr8', oprright => 'macaddr8',
+ oprresult => 'bool', oprcom => '>=(macaddr8,macaddr8)',
+ oprnegate => '>(macaddr8,macaddr8)', oprcode => 'macaddr8_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '3366', descr => 'greater than',
+ oprname => '>', oprleft => 'macaddr8', oprright => 'macaddr8',
+ oprresult => 'bool', oprcom => '<(macaddr8,macaddr8)',
+ oprnegate => '<=(macaddr8,macaddr8)', oprcode => 'macaddr8_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '3367', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'macaddr8', oprright => 'macaddr8',
+ oprresult => 'bool', oprcom => '<=(macaddr8,macaddr8)',
+ oprnegate => '<(macaddr8,macaddr8)', oprcode => 'macaddr8_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+{ oid => '3368', descr => 'bitwise not',
+ oprname => '~', oprkind => 'l', oprleft => '0', oprright => 'macaddr8',
+ oprresult => 'macaddr8', oprcode => 'macaddr8_not' },
+{ oid => '3369', descr => 'bitwise and',
+ oprname => '&', oprleft => 'macaddr8', oprright => 'macaddr8',
+ oprresult => 'macaddr8', oprcode => 'macaddr8_and' },
+{ oid => '3370', descr => 'bitwise or',
+ oprname => '|', oprleft => 'macaddr8', oprright => 'macaddr8',
+ oprresult => 'macaddr8', oprcode => 'macaddr8_or' },
+
+# INET type (these also support CIDR via implicit cast)
+{ oid => '1201', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'inet',
+ oprright => 'inet', oprresult => 'bool', oprcom => '=(inet,inet)',
+ oprnegate => '<>(inet,inet)', oprcode => 'network_eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '1202', descr => 'not equal',
+ oprname => '<>', oprleft => 'inet', oprright => 'inet', oprresult => 'bool',
+ oprcom => '<>(inet,inet)', oprnegate => '=(inet,inet)',
+ oprcode => 'network_ne', oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '1203', descr => 'less than',
+ oprname => '<', oprleft => 'inet', oprright => 'inet', oprresult => 'bool',
+ oprcom => '>(inet,inet)', oprnegate => '>=(inet,inet)',
+ oprcode => 'network_lt', oprrest => 'scalarltsel',
+ oprjoin => 'scalarltjoinsel' },
+{ oid => '1204', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'inet', oprright => 'inet', oprresult => 'bool',
+ oprcom => '>=(inet,inet)', oprnegate => '>(inet,inet)',
+ oprcode => 'network_le', oprrest => 'scalarlesel',
+ oprjoin => 'scalarlejoinsel' },
+{ oid => '1205', descr => 'greater than',
+ oprname => '>', oprleft => 'inet', oprright => 'inet', oprresult => 'bool',
+ oprcom => '<(inet,inet)', oprnegate => '<=(inet,inet)',
+ oprcode => 'network_gt', oprrest => 'scalargtsel',
+ oprjoin => 'scalargtjoinsel' },
+{ oid => '1206', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'inet', oprright => 'inet', oprresult => 'bool',
+ oprcom => '<=(inet,inet)', oprnegate => '<(inet,inet)',
+ oprcode => 'network_ge', oprrest => 'scalargesel',
+ oprjoin => 'scalargejoinsel' },
+{ oid => '931', oid_symbol => 'OID_INET_SUB_OP', descr => 'is subnet',
+ oprname => '<<', oprleft => 'inet', oprright => 'inet', oprresult => 'bool',
+ oprcom => '>>(inet,inet)', oprcode => 'network_sub', oprrest => 'networksel',
+ oprjoin => 'networkjoinsel' },
+{ oid => '932', oid_symbol => 'OID_INET_SUBEQ_OP',
+ descr => 'is subnet or equal',
+ oprname => '<<=', oprleft => 'inet', oprright => 'inet', oprresult => 'bool',
+ oprcom => '>>=(inet,inet)', oprcode => 'network_subeq',
+ oprrest => 'networksel', oprjoin => 'networkjoinsel' },
+{ oid => '933', oid_symbol => 'OID_INET_SUP_OP', descr => 'is supernet',
+ oprname => '>>', oprleft => 'inet', oprright => 'inet', oprresult => 'bool',
+ oprcom => '<<(inet,inet)', oprcode => 'network_sup', oprrest => 'networksel',
+ oprjoin => 'networkjoinsel' },
+{ oid => '934', oid_symbol => 'OID_INET_SUPEQ_OP',
+ descr => 'is supernet or equal',
+ oprname => '>>=', oprleft => 'inet', oprright => 'inet', oprresult => 'bool',
+ oprcom => '<<=(inet,inet)', oprcode => 'network_supeq',
+ oprrest => 'networksel', oprjoin => 'networkjoinsel' },
+{ oid => '3552', oid_symbol => 'OID_INET_OVERLAP_OP',
+ descr => 'overlaps (is subnet or supernet)',
+ oprname => '&&', oprleft => 'inet', oprright => 'inet', oprresult => 'bool',
+ oprcom => '&&(inet,inet)', oprcode => 'network_overlap',
+ oprrest => 'networksel', oprjoin => 'networkjoinsel' },
+
+{ oid => '2634', descr => 'bitwise not',
+ oprname => '~', oprkind => 'l', oprleft => '0', oprright => 'inet',
+ oprresult => 'inet', oprcode => 'inetnot' },
+{ oid => '2635', descr => 'bitwise and',
+ oprname => '&', oprleft => 'inet', oprright => 'inet', oprresult => 'inet',
+ oprcode => 'inetand' },
+{ oid => '2636', descr => 'bitwise or',
+ oprname => '|', oprleft => 'inet', oprright => 'inet', oprresult => 'inet',
+ oprcode => 'inetor' },
+{ oid => '2637', descr => 'add',
+ oprname => '+', oprleft => 'inet', oprright => 'int8', oprresult => 'inet',
+ oprcom => '+(int8,inet)', oprcode => 'inetpl' },
+{ oid => '2638', descr => 'add',
+ oprname => '+', oprleft => 'int8', oprright => 'inet', oprresult => 'inet',
+ oprcom => '+(inet,int8)', oprcode => 'int8pl_inet' },
+{ oid => '2639', descr => 'subtract',
+ oprname => '-', oprleft => 'inet', oprright => 'int8', oprresult => 'inet',
+ oprcode => 'inetmi_int8' },
+{ oid => '2640', descr => 'subtract',
+ oprname => '-', oprleft => 'inet', oprright => 'inet', oprresult => 'int8',
+ oprcode => 'inetmi' },
+
+# case-insensitive LIKE hacks
+{ oid => '1625', oid_symbol => 'OID_NAME_ICLIKE_OP',
+ descr => 'matches LIKE expression, case-insensitive',
+ oprname => '~~*', oprleft => 'name', oprright => 'text', oprresult => 'bool',
+ oprnegate => '!~~*(name,text)', oprcode => 'nameiclike',
+ oprrest => 'iclikesel', oprjoin => 'iclikejoinsel' },
+{ oid => '1626', descr => 'does not match LIKE expression, case-insensitive',
+ oprname => '!~~*', oprleft => 'name', oprright => 'text', oprresult => 'bool',
+ oprnegate => '~~*(name,text)', oprcode => 'nameicnlike',
+ oprrest => 'icnlikesel', oprjoin => 'icnlikejoinsel' },
+{ oid => '1627', oid_symbol => 'OID_TEXT_ICLIKE_OP',
+ descr => 'matches LIKE expression, case-insensitive',
+ oprname => '~~*', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprnegate => '!~~*(text,text)', oprcode => 'texticlike',
+ oprrest => 'iclikesel', oprjoin => 'iclikejoinsel' },
+{ oid => '1628', descr => 'does not match LIKE expression, case-insensitive',
+ oprname => '!~~*', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprnegate => '~~*(text,text)', oprcode => 'texticnlike',
+ oprrest => 'icnlikesel', oprjoin => 'icnlikejoinsel' },
+{ oid => '1629', oid_symbol => 'OID_BPCHAR_ICLIKE_OP',
+ descr => 'matches LIKE expression, case-insensitive',
+ oprname => '~~*', oprleft => 'bpchar', oprright => 'text',
+ oprresult => 'bool', oprnegate => '!~~*(bpchar,text)',
+ oprcode => 'bpchariclike', oprrest => 'iclikesel',
+ oprjoin => 'iclikejoinsel' },
+{ oid => '1630', descr => 'does not match LIKE expression, case-insensitive',
+ oprname => '!~~*', oprleft => 'bpchar', oprright => 'text',
+ oprresult => 'bool', oprnegate => '~~*(bpchar,text)',
+ oprcode => 'bpcharicnlike', oprrest => 'icnlikesel',
+ oprjoin => 'icnlikejoinsel' },
+
+# NUMERIC type - OID's 1700-1799
+{ oid => '1751', descr => 'negate',
+ oprname => '-', oprkind => 'l', oprleft => '0', oprright => 'numeric',
+ oprresult => 'numeric', oprcode => 'numeric_uminus' },
+{ oid => '1752', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'numeric',
+ oprright => 'numeric', oprresult => 'bool', oprcom => '=(numeric,numeric)',
+ oprnegate => '<>(numeric,numeric)', oprcode => 'numeric_eq',
+ oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '1753', descr => 'not equal',
+ oprname => '<>', oprleft => 'numeric', oprright => 'numeric',
+ oprresult => 'bool', oprcom => '<>(numeric,numeric)',
+ oprnegate => '=(numeric,numeric)', oprcode => 'numeric_ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '1754', descr => 'less than',
+ oprname => '<', oprleft => 'numeric', oprright => 'numeric',
+ oprresult => 'bool', oprcom => '>(numeric,numeric)',
+ oprnegate => '>=(numeric,numeric)', oprcode => 'numeric_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '1755', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'numeric', oprright => 'numeric',
+ oprresult => 'bool', oprcom => '>=(numeric,numeric)',
+ oprnegate => '>(numeric,numeric)', oprcode => 'numeric_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '1756', descr => 'greater than',
+ oprname => '>', oprleft => 'numeric', oprright => 'numeric',
+ oprresult => 'bool', oprcom => '<(numeric,numeric)',
+ oprnegate => '<=(numeric,numeric)', oprcode => 'numeric_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '1757', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'numeric', oprright => 'numeric',
+ oprresult => 'bool', oprcom => '<=(numeric,numeric)',
+ oprnegate => '<(numeric,numeric)', oprcode => 'numeric_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '1758', descr => 'add',
+ oprname => '+', oprleft => 'numeric', oprright => 'numeric',
+ oprresult => 'numeric', oprcom => '+(numeric,numeric)',
+ oprcode => 'numeric_add' },
+{ oid => '1759', descr => 'subtract',
+ oprname => '-', oprleft => 'numeric', oprright => 'numeric',
+ oprresult => 'numeric', oprcode => 'numeric_sub' },
+{ oid => '1760', descr => 'multiply',
+ oprname => '*', oprleft => 'numeric', oprright => 'numeric',
+ oprresult => 'numeric', oprcom => '*(numeric,numeric)',
+ oprcode => 'numeric_mul' },
+{ oid => '1761', descr => 'divide',
+ oprname => '/', oprleft => 'numeric', oprright => 'numeric',
+ oprresult => 'numeric', oprcode => 'numeric_div' },
+{ oid => '1762', descr => 'modulus',
+ oprname => '%', oprleft => 'numeric', oprright => 'numeric',
+ oprresult => 'numeric', oprcode => 'numeric_mod' },
+{ oid => '1038', descr => 'exponentiation',
+ oprname => '^', oprleft => 'numeric', oprright => 'numeric',
+ oprresult => 'numeric', oprcode => 'numeric_power' },
+{ oid => '1763', descr => 'absolute value',
+ oprname => '@', oprkind => 'l', oprleft => '0', oprright => 'numeric',
+ oprresult => 'numeric', oprcode => 'numeric_abs' },
+
+{ oid => '1784', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprleft => 'bit', oprright => 'bit',
+ oprresult => 'bool', oprcom => '=(bit,bit)', oprnegate => '<>(bit,bit)',
+ oprcode => 'biteq', oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '1785', descr => 'not equal',
+ oprname => '<>', oprleft => 'bit', oprright => 'bit', oprresult => 'bool',
+ oprcom => '<>(bit,bit)', oprnegate => '=(bit,bit)', oprcode => 'bitne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '1786', descr => 'less than',
+ oprname => '<', oprleft => 'bit', oprright => 'bit', oprresult => 'bool',
+ oprcom => '>(bit,bit)', oprnegate => '>=(bit,bit)', oprcode => 'bitlt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '1787', descr => 'greater than',
+ oprname => '>', oprleft => 'bit', oprright => 'bit', oprresult => 'bool',
+ oprcom => '<(bit,bit)', oprnegate => '<=(bit,bit)', oprcode => 'bitgt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '1788', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'bit', oprright => 'bit', oprresult => 'bool',
+ oprcom => '>=(bit,bit)', oprnegate => '>(bit,bit)', oprcode => 'bitle',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '1789', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'bit', oprright => 'bit', oprresult => 'bool',
+ oprcom => '<=(bit,bit)', oprnegate => '<(bit,bit)', oprcode => 'bitge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '1791', descr => 'bitwise and',
+ oprname => '&', oprleft => 'bit', oprright => 'bit', oprresult => 'bit',
+ oprcom => '&(bit,bit)', oprcode => 'bitand' },
+{ oid => '1792', descr => 'bitwise or',
+ oprname => '|', oprleft => 'bit', oprright => 'bit', oprresult => 'bit',
+ oprcom => '|(bit,bit)', oprcode => 'bitor' },
+{ oid => '1793', descr => 'bitwise exclusive or',
+ oprname => '#', oprleft => 'bit', oprright => 'bit', oprresult => 'bit',
+ oprcom => '#(bit,bit)', oprcode => 'bitxor' },
+{ oid => '1794', descr => 'bitwise not',
+ oprname => '~', oprkind => 'l', oprleft => '0', oprright => 'bit',
+ oprresult => 'bit', oprcode => 'bitnot' },
+{ oid => '1795', descr => 'bitwise shift left',
+ oprname => '<<', oprleft => 'bit', oprright => 'int4', oprresult => 'bit',
+ oprcode => 'bitshiftleft' },
+{ oid => '1796', descr => 'bitwise shift right',
+ oprname => '>>', oprleft => 'bit', oprright => 'int4', oprresult => 'bit',
+ oprcode => 'bitshiftright' },
+{ oid => '1797', descr => 'concatenate',
+ oprname => '||', oprleft => 'varbit', oprright => 'varbit',
+ oprresult => 'varbit', oprcode => 'bitcat' },
+
+{ oid => '1800', descr => 'add',
+ oprname => '+', oprleft => 'time', oprright => 'interval',
+ oprresult => 'time', oprcom => '+(interval,time)',
+ oprcode => 'time_pl_interval' },
+{ oid => '1801', descr => 'subtract',
+ oprname => '-', oprleft => 'time', oprright => 'interval',
+ oprresult => 'time', oprcode => 'time_mi_interval' },
+{ oid => '1802', descr => 'add',
+ oprname => '+', oprleft => 'timetz', oprright => 'interval',
+ oprresult => 'timetz', oprcom => '+(interval,timetz)',
+ oprcode => 'timetz_pl_interval' },
+{ oid => '1803', descr => 'subtract',
+ oprname => '-', oprleft => 'timetz', oprright => 'interval',
+ oprresult => 'timetz', oprcode => 'timetz_mi_interval' },
+
+{ oid => '1804', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprleft => 'varbit', oprright => 'varbit',
+ oprresult => 'bool', oprcom => '=(varbit,varbit)',
+ oprnegate => '<>(varbit,varbit)', oprcode => 'varbiteq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '1805', descr => 'not equal',
+ oprname => '<>', oprleft => 'varbit', oprright => 'varbit',
+ oprresult => 'bool', oprcom => '<>(varbit,varbit)',
+ oprnegate => '=(varbit,varbit)', oprcode => 'varbitne', oprrest => 'neqsel',
+ oprjoin => 'neqjoinsel' },
+{ oid => '1806', descr => 'less than',
+ oprname => '<', oprleft => 'varbit', oprright => 'varbit',
+ oprresult => 'bool', oprcom => '>(varbit,varbit)',
+ oprnegate => '>=(varbit,varbit)', oprcode => 'varbitlt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '1807', descr => 'greater than',
+ oprname => '>', oprleft => 'varbit', oprright => 'varbit',
+ oprresult => 'bool', oprcom => '<(varbit,varbit)',
+ oprnegate => '<=(varbit,varbit)', oprcode => 'varbitgt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '1808', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'varbit', oprright => 'varbit',
+ oprresult => 'bool', oprcom => '>=(varbit,varbit)',
+ oprnegate => '>(varbit,varbit)', oprcode => 'varbitle',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '1809', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'varbit', oprright => 'varbit',
+ oprresult => 'bool', oprcom => '<=(varbit,varbit)',
+ oprnegate => '<(varbit,varbit)', oprcode => 'varbitge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+{ oid => '1849', descr => 'add',
+ oprname => '+', oprleft => 'interval', oprright => 'time',
+ oprresult => 'time', oprcom => '+(time,interval)',
+ oprcode => 'interval_pl_time' },
+
+{ oid => '1862', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'int2',
+ oprright => 'int8', oprresult => 'bool', oprcom => '=(int8,int2)',
+ oprnegate => '<>(int2,int8)', oprcode => 'int28eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '1863', descr => 'not equal',
+ oprname => '<>', oprleft => 'int2', oprright => 'int8', oprresult => 'bool',
+ oprcom => '<>(int8,int2)', oprnegate => '=(int2,int8)', oprcode => 'int28ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '1864', descr => 'less than',
+ oprname => '<', oprleft => 'int2', oprright => 'int8', oprresult => 'bool',
+ oprcom => '>(int8,int2)', oprnegate => '>=(int2,int8)', oprcode => 'int28lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '1865', descr => 'greater than',
+ oprname => '>', oprleft => 'int2', oprright => 'int8', oprresult => 'bool',
+ oprcom => '<(int8,int2)', oprnegate => '<=(int2,int8)', oprcode => 'int28gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '1866', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'int2', oprright => 'int8', oprresult => 'bool',
+ oprcom => '>=(int8,int2)', oprnegate => '>(int2,int8)', oprcode => 'int28le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '1867', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'int2', oprright => 'int8', oprresult => 'bool',
+ oprcom => '<=(int8,int2)', oprnegate => '<(int2,int8)', oprcode => 'int28ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+{ oid => '1868', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'int8',
+ oprright => 'int2', oprresult => 'bool', oprcom => '=(int2,int8)',
+ oprnegate => '<>(int8,int2)', oprcode => 'int82eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '1869', descr => 'not equal',
+ oprname => '<>', oprleft => 'int8', oprright => 'int2', oprresult => 'bool',
+ oprcom => '<>(int2,int8)', oprnegate => '=(int8,int2)', oprcode => 'int82ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '1870', descr => 'less than',
+ oprname => '<', oprleft => 'int8', oprright => 'int2', oprresult => 'bool',
+ oprcom => '>(int2,int8)', oprnegate => '>=(int8,int2)', oprcode => 'int82lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '1871', descr => 'greater than',
+ oprname => '>', oprleft => 'int8', oprright => 'int2', oprresult => 'bool',
+ oprcom => '<(int2,int8)', oprnegate => '<=(int8,int2)', oprcode => 'int82gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '1872', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'int8', oprright => 'int2', oprresult => 'bool',
+ oprcom => '>=(int2,int8)', oprnegate => '>(int8,int2)', oprcode => 'int82le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '1873', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'int8', oprright => 'int2', oprresult => 'bool',
+ oprcom => '<=(int2,int8)', oprnegate => '<(int8,int2)', oprcode => 'int82ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+{ oid => '1874', descr => 'bitwise and',
+ oprname => '&', oprleft => 'int2', oprright => 'int2', oprresult => 'int2',
+ oprcom => '&(int2,int2)', oprcode => 'int2and' },
+{ oid => '1875', descr => 'bitwise or',
+ oprname => '|', oprleft => 'int2', oprright => 'int2', oprresult => 'int2',
+ oprcom => '|(int2,int2)', oprcode => 'int2or' },
+{ oid => '1876', descr => 'bitwise exclusive or',
+ oprname => '#', oprleft => 'int2', oprright => 'int2', oprresult => 'int2',
+ oprcom => '#(int2,int2)', oprcode => 'int2xor' },
+{ oid => '1877', descr => 'bitwise not',
+ oprname => '~', oprkind => 'l', oprleft => '0', oprright => 'int2',
+ oprresult => 'int2', oprcode => 'int2not' },
+{ oid => '1878', descr => 'bitwise shift left',
+ oprname => '<<', oprleft => 'int2', oprright => 'int4', oprresult => 'int2',
+ oprcode => 'int2shl' },
+{ oid => '1879', descr => 'bitwise shift right',
+ oprname => '>>', oprleft => 'int2', oprright => 'int4', oprresult => 'int2',
+ oprcode => 'int2shr' },
+
+{ oid => '1880', descr => 'bitwise and',
+ oprname => '&', oprleft => 'int4', oprright => 'int4', oprresult => 'int4',
+ oprcom => '&(int4,int4)', oprcode => 'int4and' },
+{ oid => '1881', descr => 'bitwise or',
+ oprname => '|', oprleft => 'int4', oprright => 'int4', oprresult => 'int4',
+ oprcom => '|(int4,int4)', oprcode => 'int4or' },
+{ oid => '1882', descr => 'bitwise exclusive or',
+ oprname => '#', oprleft => 'int4', oprright => 'int4', oprresult => 'int4',
+ oprcom => '#(int4,int4)', oprcode => 'int4xor' },
+{ oid => '1883', descr => 'bitwise not',
+ oprname => '~', oprkind => 'l', oprleft => '0', oprright => 'int4',
+ oprresult => 'int4', oprcode => 'int4not' },
+{ oid => '1884', descr => 'bitwise shift left',
+ oprname => '<<', oprleft => 'int4', oprright => 'int4', oprresult => 'int4',
+ oprcode => 'int4shl' },
+{ oid => '1885', descr => 'bitwise shift right',
+ oprname => '>>', oprleft => 'int4', oprright => 'int4', oprresult => 'int4',
+ oprcode => 'int4shr' },
+
+{ oid => '1886', descr => 'bitwise and',
+ oprname => '&', oprleft => 'int8', oprright => 'int8', oprresult => 'int8',
+ oprcom => '&(int8,int8)', oprcode => 'int8and' },
+{ oid => '1887', descr => 'bitwise or',
+ oprname => '|', oprleft => 'int8', oprright => 'int8', oprresult => 'int8',
+ oprcom => '|(int8,int8)', oprcode => 'int8or' },
+{ oid => '1888', descr => 'bitwise exclusive or',
+ oprname => '#', oprleft => 'int8', oprright => 'int8', oprresult => 'int8',
+ oprcom => '#(int8,int8)', oprcode => 'int8xor' },
+{ oid => '1889', descr => 'bitwise not',
+ oprname => '~', oprkind => 'l', oprleft => '0', oprright => 'int8',
+ oprresult => 'int8', oprcode => 'int8not' },
+{ oid => '1890', descr => 'bitwise shift left',
+ oprname => '<<', oprleft => 'int8', oprright => 'int4', oprresult => 'int8',
+ oprcode => 'int8shl' },
+{ oid => '1891', descr => 'bitwise shift right',
+ oprname => '>>', oprleft => 'int8', oprright => 'int4', oprresult => 'int8',
+ oprcode => 'int8shr' },
+
+{ oid => '1916', descr => 'unary plus',
+ oprname => '+', oprkind => 'l', oprleft => '0', oprright => 'int8',
+ oprresult => 'int8', oprcode => 'int8up' },
+{ oid => '1917', descr => 'unary plus',
+ oprname => '+', oprkind => 'l', oprleft => '0', oprright => 'int2',
+ oprresult => 'int2', oprcode => 'int2up' },
+{ oid => '1918', descr => 'unary plus',
+ oprname => '+', oprkind => 'l', oprleft => '0', oprright => 'int4',
+ oprresult => 'int4', oprcode => 'int4up' },
+{ oid => '1919', descr => 'unary plus',
+ oprname => '+', oprkind => 'l', oprleft => '0', oprright => 'float4',
+ oprresult => 'float4', oprcode => 'float4up' },
+{ oid => '1920', descr => 'unary plus',
+ oprname => '+', oprkind => 'l', oprleft => '0', oprright => 'float8',
+ oprresult => 'float8', oprcode => 'float8up' },
+{ oid => '1921', descr => 'unary plus',
+ oprname => '+', oprkind => 'l', oprleft => '0', oprright => 'numeric',
+ oprresult => 'numeric', oprcode => 'numeric_uplus' },
+
+# bytea operators
+{ oid => '1955', oid_symbol => 'ByteaEqualOperator', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'bytea',
+ oprright => 'bytea', oprresult => 'bool', oprcom => '=(bytea,bytea)',
+ oprnegate => '<>(bytea,bytea)', oprcode => 'byteaeq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '1956', descr => 'not equal',
+ oprname => '<>', oprleft => 'bytea', oprright => 'bytea', oprresult => 'bool',
+ oprcom => '<>(bytea,bytea)', oprnegate => '=(bytea,bytea)',
+ oprcode => 'byteane', oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '1957', oid_symbol => 'ByteaLessOperator', descr => 'less than',
+ oprname => '<', oprleft => 'bytea', oprright => 'bytea', oprresult => 'bool',
+ oprcom => '>(bytea,bytea)', oprnegate => '>=(bytea,bytea)',
+ oprcode => 'bytealt', oprrest => 'scalarltsel',
+ oprjoin => 'scalarltjoinsel' },
+{ oid => '1958', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'bytea', oprright => 'bytea', oprresult => 'bool',
+ oprcom => '>=(bytea,bytea)', oprnegate => '>(bytea,bytea)',
+ oprcode => 'byteale', oprrest => 'scalarlesel',
+ oprjoin => 'scalarlejoinsel' },
+{ oid => '1959', descr => 'greater than',
+ oprname => '>', oprleft => 'bytea', oprright => 'bytea', oprresult => 'bool',
+ oprcom => '<(bytea,bytea)', oprnegate => '<=(bytea,bytea)',
+ oprcode => 'byteagt', oprrest => 'scalargtsel',
+ oprjoin => 'scalargtjoinsel' },
+{ oid => '1960', oid_symbol => 'ByteaGreaterEqualOperator',
+ descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'bytea', oprright => 'bytea', oprresult => 'bool',
+ oprcom => '<=(bytea,bytea)', oprnegate => '<(bytea,bytea)',
+ oprcode => 'byteage', oprrest => 'scalargesel',
+ oprjoin => 'scalargejoinsel' },
+
+{ oid => '2016', oid_symbol => 'OID_BYTEA_LIKE_OP',
+ descr => 'matches LIKE expression',
+ oprname => '~~', oprleft => 'bytea', oprright => 'bytea', oprresult => 'bool',
+ oprnegate => '!~~(bytea,bytea)', oprcode => 'bytealike', oprrest => 'likesel',
+ oprjoin => 'likejoinsel' },
+{ oid => '2017', descr => 'does not match LIKE expression',
+ oprname => '!~~', oprleft => 'bytea', oprright => 'bytea',
+ oprresult => 'bool', oprnegate => '~~(bytea,bytea)', oprcode => 'byteanlike',
+ oprrest => 'nlikesel', oprjoin => 'nlikejoinsel' },
+{ oid => '2018', descr => 'concatenate',
+ oprname => '||', oprleft => 'bytea', oprright => 'bytea',
+ oprresult => 'bytea', oprcode => 'byteacat' },
+
+# timestamp operators
+{ oid => '2060', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'timestamp',
+ oprright => 'timestamp', oprresult => 'bool',
+ oprcom => '=(timestamp,timestamp)', oprnegate => '<>(timestamp,timestamp)',
+ oprcode => 'timestamp_eq', oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '2061', descr => 'not equal',
+ oprname => '<>', oprleft => 'timestamp', oprright => 'timestamp',
+ oprresult => 'bool', oprcom => '<>(timestamp,timestamp)',
+ oprnegate => '=(timestamp,timestamp)', oprcode => 'timestamp_ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '2062', descr => 'less than',
+ oprname => '<', oprleft => 'timestamp', oprright => 'timestamp',
+ oprresult => 'bool', oprcom => '>(timestamp,timestamp)',
+ oprnegate => '>=(timestamp,timestamp)', oprcode => 'timestamp_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '2063', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'timestamp', oprright => 'timestamp',
+ oprresult => 'bool', oprcom => '>=(timestamp,timestamp)',
+ oprnegate => '>(timestamp,timestamp)', oprcode => 'timestamp_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '2064', descr => 'greater than',
+ oprname => '>', oprleft => 'timestamp', oprright => 'timestamp',
+ oprresult => 'bool', oprcom => '<(timestamp,timestamp)',
+ oprnegate => '<=(timestamp,timestamp)', oprcode => 'timestamp_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '2065', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'timestamp', oprright => 'timestamp',
+ oprresult => 'bool', oprcom => '<=(timestamp,timestamp)',
+ oprnegate => '<(timestamp,timestamp)', oprcode => 'timestamp_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '2066', descr => 'add',
+ oprname => '+', oprleft => 'timestamp', oprright => 'interval',
+ oprresult => 'timestamp', oprcom => '+(interval,timestamp)',
+ oprcode => 'timestamp_pl_interval' },
+{ oid => '2067', descr => 'subtract',
+ oprname => '-', oprleft => 'timestamp', oprright => 'timestamp',
+ oprresult => 'interval', oprcode => 'timestamp_mi' },
+{ oid => '2068', descr => 'subtract',
+ oprname => '-', oprleft => 'timestamp', oprright => 'interval',
+ oprresult => 'timestamp', oprcode => 'timestamp_mi_interval' },
+
+# character-by-character (not collation order) comparison operators for character types
+{ oid => '2314', oid_symbol => 'TextPatternLessOperator',
+ descr => 'less than',
+ oprname => '~<~', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprcom => '~>~(text,text)', oprnegate => '~>=~(text,text)',
+ oprcode => 'text_pattern_lt', oprrest => 'scalarltsel',
+ oprjoin => 'scalarltjoinsel' },
+{ oid => '2315', descr => 'less than or equal',
+ oprname => '~<=~', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprcom => '~>=~(text,text)', oprnegate => '~>~(text,text)',
+ oprcode => 'text_pattern_le', oprrest => 'scalarlesel',
+ oprjoin => 'scalarlejoinsel' },
+{ oid => '2317', oid_symbol => 'TextPatternGreaterEqualOperator',
+ descr => 'greater than or equal',
+ oprname => '~>=~', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprcom => '~<=~(text,text)', oprnegate => '~<~(text,text)',
+ oprcode => 'text_pattern_ge', oprrest => 'scalargesel',
+ oprjoin => 'scalargejoinsel' },
+{ oid => '2318', descr => 'greater than',
+ oprname => '~>~', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprcom => '~<~(text,text)', oprnegate => '~<=~(text,text)',
+ oprcode => 'text_pattern_gt', oprrest => 'scalargtsel',
+ oprjoin => 'scalargtjoinsel' },
+
+{ oid => '2326', oid_symbol => 'BpcharPatternLessOperator',
+ descr => 'less than',
+ oprname => '~<~', oprleft => 'bpchar', oprright => 'bpchar',
+ oprresult => 'bool', oprcom => '~>~(bpchar,bpchar)',
+ oprnegate => '~>=~(bpchar,bpchar)', oprcode => 'bpchar_pattern_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '2327', descr => 'less than or equal',
+ oprname => '~<=~', oprleft => 'bpchar', oprright => 'bpchar',
+ oprresult => 'bool', oprcom => '~>=~(bpchar,bpchar)',
+ oprnegate => '~>~(bpchar,bpchar)', oprcode => 'bpchar_pattern_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '2329', oid_symbol => 'BpcharPatternGreaterEqualOperator',
+ descr => 'greater than or equal',
+ oprname => '~>=~', oprleft => 'bpchar', oprright => 'bpchar',
+ oprresult => 'bool', oprcom => '~<=~(bpchar,bpchar)',
+ oprnegate => '~<~(bpchar,bpchar)', oprcode => 'bpchar_pattern_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '2330', descr => 'greater than',
+ oprname => '~>~', oprleft => 'bpchar', oprright => 'bpchar',
+ oprresult => 'bool', oprcom => '~<~(bpchar,bpchar)',
+ oprnegate => '~<=~(bpchar,bpchar)', oprcode => 'bpchar_pattern_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+
+# crosstype operations for date vs. timestamp and timestamptz
+{ oid => '2345', descr => 'less than',
+ oprname => '<', oprleft => 'date', oprright => 'timestamp',
+ oprresult => 'bool', oprcom => '>(timestamp,date)',
+ oprnegate => '>=(date,timestamp)', oprcode => 'date_lt_timestamp',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '2346', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'date', oprright => 'timestamp',
+ oprresult => 'bool', oprcom => '>=(timestamp,date)',
+ oprnegate => '>(date,timestamp)', oprcode => 'date_le_timestamp',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '2347', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprleft => 'date',
+ oprright => 'timestamp', oprresult => 'bool', oprcom => '=(timestamp,date)',
+ oprnegate => '<>(date,timestamp)', oprcode => 'date_eq_timestamp',
+ oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '2348', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'date', oprright => 'timestamp',
+ oprresult => 'bool', oprcom => '<=(timestamp,date)',
+ oprnegate => '<(date,timestamp)', oprcode => 'date_ge_timestamp',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '2349', descr => 'greater than',
+ oprname => '>', oprleft => 'date', oprright => 'timestamp',
+ oprresult => 'bool', oprcom => '<(timestamp,date)',
+ oprnegate => '<=(date,timestamp)', oprcode => 'date_gt_timestamp',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '2350', descr => 'not equal',
+ oprname => '<>', oprleft => 'date', oprright => 'timestamp',
+ oprresult => 'bool', oprcom => '<>(timestamp,date)',
+ oprnegate => '=(date,timestamp)', oprcode => 'date_ne_timestamp',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+
+{ oid => '2358', descr => 'less than',
+ oprname => '<', oprleft => 'date', oprright => 'timestamptz',
+ oprresult => 'bool', oprcom => '>(timestamptz,date)',
+ oprnegate => '>=(date,timestamptz)', oprcode => 'date_lt_timestamptz',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '2359', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'date', oprright => 'timestamptz',
+ oprresult => 'bool', oprcom => '>=(timestamptz,date)',
+ oprnegate => '>(date,timestamptz)', oprcode => 'date_le_timestamptz',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '2360', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprleft => 'date',
+ oprright => 'timestamptz', oprresult => 'bool',
+ oprcom => '=(timestamptz,date)', oprnegate => '<>(date,timestamptz)',
+ oprcode => 'date_eq_timestamptz', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '2361', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'date', oprright => 'timestamptz',
+ oprresult => 'bool', oprcom => '<=(timestamptz,date)',
+ oprnegate => '<(date,timestamptz)', oprcode => 'date_ge_timestamptz',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '2362', descr => 'greater than',
+ oprname => '>', oprleft => 'date', oprright => 'timestamptz',
+ oprresult => 'bool', oprcom => '<(timestamptz,date)',
+ oprnegate => '<=(date,timestamptz)', oprcode => 'date_gt_timestamptz',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '2363', descr => 'not equal',
+ oprname => '<>', oprleft => 'date', oprright => 'timestamptz',
+ oprresult => 'bool', oprcom => '<>(timestamptz,date)',
+ oprnegate => '=(date,timestamptz)', oprcode => 'date_ne_timestamptz',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+
+{ oid => '2371', descr => 'less than',
+ oprname => '<', oprleft => 'timestamp', oprright => 'date',
+ oprresult => 'bool', oprcom => '>(date,timestamp)',
+ oprnegate => '>=(timestamp,date)', oprcode => 'timestamp_lt_date',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '2372', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'timestamp', oprright => 'date',
+ oprresult => 'bool', oprcom => '>=(date,timestamp)',
+ oprnegate => '>(timestamp,date)', oprcode => 'timestamp_le_date',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '2373', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprleft => 'timestamp',
+ oprright => 'date', oprresult => 'bool', oprcom => '=(date,timestamp)',
+ oprnegate => '<>(timestamp,date)', oprcode => 'timestamp_eq_date',
+ oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '2374', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'timestamp', oprright => 'date',
+ oprresult => 'bool', oprcom => '<=(date,timestamp)',
+ oprnegate => '<(timestamp,date)', oprcode => 'timestamp_ge_date',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '2375', descr => 'greater than',
+ oprname => '>', oprleft => 'timestamp', oprright => 'date',
+ oprresult => 'bool', oprcom => '<(date,timestamp)',
+ oprnegate => '<=(timestamp,date)', oprcode => 'timestamp_gt_date',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '2376', descr => 'not equal',
+ oprname => '<>', oprleft => 'timestamp', oprright => 'date',
+ oprresult => 'bool', oprcom => '<>(date,timestamp)',
+ oprnegate => '=(timestamp,date)', oprcode => 'timestamp_ne_date',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+
+{ oid => '2384', descr => 'less than',
+ oprname => '<', oprleft => 'timestamptz', oprright => 'date',
+ oprresult => 'bool', oprcom => '>(date,timestamptz)',
+ oprnegate => '>=(timestamptz,date)', oprcode => 'timestamptz_lt_date',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '2385', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'timestamptz', oprright => 'date',
+ oprresult => 'bool', oprcom => '>=(date,timestamptz)',
+ oprnegate => '>(timestamptz,date)', oprcode => 'timestamptz_le_date',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '2386', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprleft => 'timestamptz',
+ oprright => 'date', oprresult => 'bool', oprcom => '=(date,timestamptz)',
+ oprnegate => '<>(timestamptz,date)', oprcode => 'timestamptz_eq_date',
+ oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '2387', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'timestamptz', oprright => 'date',
+ oprresult => 'bool', oprcom => '<=(date,timestamptz)',
+ oprnegate => '<(timestamptz,date)', oprcode => 'timestamptz_ge_date',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '2388', descr => 'greater than',
+ oprname => '>', oprleft => 'timestamptz', oprright => 'date',
+ oprresult => 'bool', oprcom => '<(date,timestamptz)',
+ oprnegate => '<=(timestamptz,date)', oprcode => 'timestamptz_gt_date',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '2389', descr => 'not equal',
+ oprname => '<>', oprleft => 'timestamptz', oprright => 'date',
+ oprresult => 'bool', oprcom => '<>(date,timestamptz)',
+ oprnegate => '=(timestamptz,date)', oprcode => 'timestamptz_ne_date',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+
+# crosstype operations for timestamp vs. timestamptz
+{ oid => '2534', descr => 'less than',
+ oprname => '<', oprleft => 'timestamp', oprright => 'timestamptz',
+ oprresult => 'bool', oprcom => '>(timestamptz,timestamp)',
+ oprnegate => '>=(timestamp,timestamptz)',
+ oprcode => 'timestamp_lt_timestamptz', oprrest => 'scalarltsel',
+ oprjoin => 'scalarltjoinsel' },
+{ oid => '2535', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'timestamp', oprright => 'timestamptz',
+ oprresult => 'bool', oprcom => '>=(timestamptz,timestamp)',
+ oprnegate => '>(timestamp,timestamptz)',
+ oprcode => 'timestamp_le_timestamptz', oprrest => 'scalarlesel',
+ oprjoin => 'scalarlejoinsel' },
+{ oid => '2536', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprleft => 'timestamp',
+ oprright => 'timestamptz', oprresult => 'bool',
+ oprcom => '=(timestamptz,timestamp)',
+ oprnegate => '<>(timestamp,timestamptz)',
+ oprcode => 'timestamp_eq_timestamptz', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '2537', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'timestamp', oprright => 'timestamptz',
+ oprresult => 'bool', oprcom => '<=(timestamptz,timestamp)',
+ oprnegate => '<(timestamp,timestamptz)',
+ oprcode => 'timestamp_ge_timestamptz', oprrest => 'scalargesel',
+ oprjoin => 'scalargejoinsel' },
+{ oid => '2538', descr => 'greater than',
+ oprname => '>', oprleft => 'timestamp', oprright => 'timestamptz',
+ oprresult => 'bool', oprcom => '<(timestamptz,timestamp)',
+ oprnegate => '<=(timestamp,timestamptz)',
+ oprcode => 'timestamp_gt_timestamptz', oprrest => 'scalargtsel',
+ oprjoin => 'scalargtjoinsel' },
+{ oid => '2539', descr => 'not equal',
+ oprname => '<>', oprleft => 'timestamp', oprright => 'timestamptz',
+ oprresult => 'bool', oprcom => '<>(timestamptz,timestamp)',
+ oprnegate => '=(timestamp,timestamptz)',
+ oprcode => 'timestamp_ne_timestamptz', oprrest => 'neqsel',
+ oprjoin => 'neqjoinsel' },
+
+{ oid => '2540', descr => 'less than',
+ oprname => '<', oprleft => 'timestamptz', oprright => 'timestamp',
+ oprresult => 'bool', oprcom => '>(timestamp,timestamptz)',
+ oprnegate => '>=(timestamptz,timestamp)',
+ oprcode => 'timestamptz_lt_timestamp', oprrest => 'scalarltsel',
+ oprjoin => 'scalarltjoinsel' },
+{ oid => '2541', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'timestamptz', oprright => 'timestamp',
+ oprresult => 'bool', oprcom => '>=(timestamp,timestamptz)',
+ oprnegate => '>(timestamptz,timestamp)',
+ oprcode => 'timestamptz_le_timestamp', oprrest => 'scalarlesel',
+ oprjoin => 'scalarlejoinsel' },
+{ oid => '2542', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprleft => 'timestamptz',
+ oprright => 'timestamp', oprresult => 'bool',
+ oprcom => '=(timestamp,timestamptz)',
+ oprnegate => '<>(timestamptz,timestamp)',
+ oprcode => 'timestamptz_eq_timestamp', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '2543', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'timestamptz', oprright => 'timestamp',
+ oprresult => 'bool', oprcom => '<=(timestamp,timestamptz)',
+ oprnegate => '<(timestamptz,timestamp)',
+ oprcode => 'timestamptz_ge_timestamp', oprrest => 'scalargesel',
+ oprjoin => 'scalargejoinsel' },
+{ oid => '2544', descr => 'greater than',
+ oprname => '>', oprleft => 'timestamptz', oprright => 'timestamp',
+ oprresult => 'bool', oprcom => '<(timestamp,timestamptz)',
+ oprnegate => '<=(timestamptz,timestamp)',
+ oprcode => 'timestamptz_gt_timestamp', oprrest => 'scalargtsel',
+ oprjoin => 'scalargtjoinsel' },
+{ oid => '2545', descr => 'not equal',
+ oprname => '<>', oprleft => 'timestamptz', oprright => 'timestamp',
+ oprresult => 'bool', oprcom => '<>(timestamp,timestamptz)',
+ oprnegate => '=(timestamptz,timestamp)',
+ oprcode => 'timestamptz_ne_timestamp', oprrest => 'neqsel',
+ oprjoin => 'neqjoinsel' },
+
+# formerly-missing interval + datetime operators
+{ oid => '2551', descr => 'add',
+ oprname => '+', oprleft => 'interval', oprright => 'date',
+ oprresult => 'timestamp', oprcom => '+(date,interval)',
+ oprcode => 'interval_pl_date' },
+{ oid => '2552', descr => 'add',
+ oprname => '+', oprleft => 'interval', oprright => 'timetz',
+ oprresult => 'timetz', oprcom => '+(timetz,interval)',
+ oprcode => 'interval_pl_timetz' },
+{ oid => '2553', descr => 'add',
+ oprname => '+', oprleft => 'interval', oprright => 'timestamp',
+ oprresult => 'timestamp', oprcom => '+(timestamp,interval)',
+ oprcode => 'interval_pl_timestamp' },
+{ oid => '2554', descr => 'add',
+ oprname => '+', oprleft => 'interval', oprright => 'timestamptz',
+ oprresult => 'timestamptz', oprcom => '+(timestamptz,interval)',
+ oprcode => 'interval_pl_timestamptz' },
+{ oid => '2555', descr => 'add',
+ oprname => '+', oprleft => 'int4', oprright => 'date', oprresult => 'date',
+ oprcom => '+(date,int4)', oprcode => 'integer_pl_date' },
+
+# new operators for Y-direction rtree opfamilies
+{ oid => '2570', descr => 'is below',
+ oprname => '<<|', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcode => 'box_below', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '2571', descr => 'overlaps or is below',
+ oprname => '&<|', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcode => 'box_overbelow', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '2572', descr => 'overlaps or is above',
+ oprname => '|&>', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcode => 'box_overabove', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '2573', descr => 'is above',
+ oprname => '|>>', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcode => 'box_above', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '2574', descr => 'is below',
+ oprname => '<<|', oprleft => 'polygon', oprright => 'polygon',
+ oprresult => 'bool', oprcode => 'poly_below', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '2575', descr => 'overlaps or is below',
+ oprname => '&<|', oprleft => 'polygon', oprright => 'polygon',
+ oprresult => 'bool', oprcode => 'poly_overbelow', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '2576', descr => 'overlaps or is above',
+ oprname => '|&>', oprleft => 'polygon', oprright => 'polygon',
+ oprresult => 'bool', oprcode => 'poly_overabove', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '2577', descr => 'is above',
+ oprname => '|>>', oprleft => 'polygon', oprright => 'polygon',
+ oprresult => 'bool', oprcode => 'poly_above', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '2589', descr => 'overlaps or is below',
+ oprname => '&<|', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcode => 'circle_overbelow', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+{ oid => '2590', descr => 'overlaps or is above',
+ oprname => '|&>', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcode => 'circle_overabove', oprrest => 'positionsel',
+ oprjoin => 'positionjoinsel' },
+
+# overlap/contains/contained for arrays
+{ oid => '2750', oid_symbol => 'OID_ARRAY_OVERLAP_OP', descr => 'overlaps',
+ oprname => '&&', oprleft => 'anyarray', oprright => 'anyarray',
+ oprresult => 'bool', oprcom => '&&(anyarray,anyarray)',
+ oprcode => 'arrayoverlap', oprrest => 'arraycontsel',
+ oprjoin => 'arraycontjoinsel' },
+{ oid => '2751', oid_symbol => 'OID_ARRAY_CONTAINS_OP', descr => 'contains',
+ oprname => '@>', oprleft => 'anyarray', oprright => 'anyarray',
+ oprresult => 'bool', oprcom => '<@(anyarray,anyarray)',
+ oprcode => 'arraycontains', oprrest => 'arraycontsel',
+ oprjoin => 'arraycontjoinsel' },
+{ oid => '2752', oid_symbol => 'OID_ARRAY_CONTAINED_OP',
+ descr => 'is contained by',
+ oprname => '<@', oprleft => 'anyarray', oprright => 'anyarray',
+ oprresult => 'bool', oprcom => '@>(anyarray,anyarray)',
+ oprcode => 'arraycontained', oprrest => 'arraycontsel',
+ oprjoin => 'arraycontjoinsel' },
+
+# capturing operators to preserve pre-8.3 behavior of text concatenation
+{ oid => '2779', descr => 'concatenate',
+ oprname => '||', oprleft => 'text', oprright => 'anynonarray',
+ oprresult => 'text', oprcode => 'textanycat' },
+{ oid => '2780', descr => 'concatenate',
+ oprname => '||', oprleft => 'anynonarray', oprright => 'text',
+ oprresult => 'text', oprcode => 'anytextcat' },
+
+# obsolete names for contains/contained-by operators; remove these someday
+{ oid => '2860', descr => 'deprecated, use <@ instead',
+ oprname => '@', oprleft => 'polygon', oprright => 'polygon',
+ oprresult => 'bool', oprcom => '~(polygon,polygon)',
+ oprcode => 'poly_contained', oprrest => 'contsel', oprjoin => 'contjoinsel' },
+{ oid => '2861', descr => 'deprecated, use @> instead',
+ oprname => '~', oprleft => 'polygon', oprright => 'polygon',
+ oprresult => 'bool', oprcom => '@(polygon,polygon)',
+ oprcode => 'poly_contain', oprrest => 'contsel', oprjoin => 'contjoinsel' },
+{ oid => '2862', descr => 'deprecated, use <@ instead',
+ oprname => '@', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcom => '~(box,box)', oprcode => 'box_contained', oprrest => 'contsel',
+ oprjoin => 'contjoinsel' },
+{ oid => '2863', descr => 'deprecated, use @> instead',
+ oprname => '~', oprleft => 'box', oprright => 'box', oprresult => 'bool',
+ oprcom => '@(box,box)', oprcode => 'box_contain', oprrest => 'contsel',
+ oprjoin => 'contjoinsel' },
+{ oid => '2864', descr => 'deprecated, use <@ instead',
+ oprname => '@', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcom => '~(circle,circle)',
+ oprcode => 'circle_contained', oprrest => 'contsel',
+ oprjoin => 'contjoinsel' },
+{ oid => '2865', descr => 'deprecated, use @> instead',
+ oprname => '~', oprleft => 'circle', oprright => 'circle',
+ oprresult => 'bool', oprcom => '@(circle,circle)',
+ oprcode => 'circle_contain', oprrest => 'contsel', oprjoin => 'contjoinsel' },
+{ oid => '2866', descr => 'deprecated, use <@ instead',
+ oprname => '@', oprleft => 'point', oprright => 'box', oprresult => 'bool',
+ oprcode => 'on_pb' },
+{ oid => '2867', descr => 'deprecated, use <@ instead',
+ oprname => '@', oprleft => 'point', oprright => 'path', oprresult => 'bool',
+ oprcom => '~(path,point)', oprcode => 'on_ppath' },
+{ oid => '2868', descr => 'deprecated, use @> instead',
+ oprname => '~', oprleft => 'path', oprright => 'point', oprresult => 'bool',
+ oprcom => '@(point,path)', oprcode => 'path_contain_pt' },
+{ oid => '2869', descr => 'deprecated, use <@ instead',
+ oprname => '@', oprleft => 'point', oprright => 'polygon',
+ oprresult => 'bool', oprcom => '~(polygon,point)',
+ oprcode => 'pt_contained_poly' },
+{ oid => '2870', descr => 'deprecated, use @> instead',
+ oprname => '~', oprleft => 'polygon', oprright => 'point',
+ oprresult => 'bool', oprcom => '@(point,polygon)',
+ oprcode => 'poly_contain_pt' },
+{ oid => '2871', descr => 'deprecated, use <@ instead',
+ oprname => '@', oprleft => 'point', oprright => 'circle', oprresult => 'bool',
+ oprcom => '~(circle,point)', oprcode => 'pt_contained_circle' },
+{ oid => '2872', descr => 'deprecated, use @> instead',
+ oprname => '~', oprleft => 'circle', oprright => 'point', oprresult => 'bool',
+ oprcom => '@(point,circle)', oprcode => 'circle_contain_pt' },
+{ oid => '2873', descr => 'deprecated, use <@ instead',
+ oprname => '@', oprleft => 'point', oprright => 'line', oprresult => 'bool',
+ oprcode => 'on_pl' },
+{ oid => '2874', descr => 'deprecated, use <@ instead',
+ oprname => '@', oprleft => 'point', oprright => 'lseg', oprresult => 'bool',
+ oprcode => 'on_ps' },
+{ oid => '2875', descr => 'deprecated, use <@ instead',
+ oprname => '@', oprleft => 'lseg', oprright => 'line', oprresult => 'bool',
+ oprcode => 'on_sl' },
+{ oid => '2876', descr => 'deprecated, use <@ instead',
+ oprname => '@', oprleft => 'lseg', oprright => 'box', oprresult => 'bool',
+ oprcode => 'on_sb' },
+{ oid => '2877', descr => 'deprecated, use @> instead',
+ oprname => '~', oprleft => '_aclitem', oprright => 'aclitem',
+ oprresult => 'bool', oprcode => 'aclcontains' },
+
+# uuid operators
+{ oid => '2972', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'uuid',
+ oprright => 'uuid', oprresult => 'bool', oprcom => '=(uuid,uuid)',
+ oprnegate => '<>(uuid,uuid)', oprcode => 'uuid_eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '2973', descr => 'not equal',
+ oprname => '<>', oprleft => 'uuid', oprright => 'uuid', oprresult => 'bool',
+ oprcom => '<>(uuid,uuid)', oprnegate => '=(uuid,uuid)', oprcode => 'uuid_ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '2974', descr => 'less than',
+ oprname => '<', oprleft => 'uuid', oprright => 'uuid', oprresult => 'bool',
+ oprcom => '>(uuid,uuid)', oprnegate => '>=(uuid,uuid)', oprcode => 'uuid_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '2975', descr => 'greater than',
+ oprname => '>', oprleft => 'uuid', oprright => 'uuid', oprresult => 'bool',
+ oprcom => '<(uuid,uuid)', oprnegate => '<=(uuid,uuid)', oprcode => 'uuid_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '2976', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'uuid', oprright => 'uuid', oprresult => 'bool',
+ oprcom => '>=(uuid,uuid)', oprnegate => '>(uuid,uuid)', oprcode => 'uuid_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '2977', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'uuid', oprright => 'uuid', oprresult => 'bool',
+ oprcom => '<=(uuid,uuid)', oprnegate => '<(uuid,uuid)', oprcode => 'uuid_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+# pg_lsn operators
+{ oid => '3222', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'pg_lsn',
+ oprright => 'pg_lsn', oprresult => 'bool', oprcom => '=(pg_lsn,pg_lsn)',
+ oprnegate => '<>(pg_lsn,pg_lsn)', oprcode => 'pg_lsn_eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '3223', descr => 'not equal',
+ oprname => '<>', oprleft => 'pg_lsn', oprright => 'pg_lsn',
+ oprresult => 'bool', oprcom => '<>(pg_lsn,pg_lsn)',
+ oprnegate => '=(pg_lsn,pg_lsn)', oprcode => 'pg_lsn_ne', oprrest => 'neqsel',
+ oprjoin => 'neqjoinsel' },
+{ oid => '3224', descr => 'less than',
+ oprname => '<', oprleft => 'pg_lsn', oprright => 'pg_lsn',
+ oprresult => 'bool', oprcom => '>(pg_lsn,pg_lsn)',
+ oprnegate => '>=(pg_lsn,pg_lsn)', oprcode => 'pg_lsn_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '3225', descr => 'greater than',
+ oprname => '>', oprleft => 'pg_lsn', oprright => 'pg_lsn',
+ oprresult => 'bool', oprcom => '<(pg_lsn,pg_lsn)',
+ oprnegate => '<=(pg_lsn,pg_lsn)', oprcode => 'pg_lsn_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '3226', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'pg_lsn', oprright => 'pg_lsn',
+ oprresult => 'bool', oprcom => '>=(pg_lsn,pg_lsn)',
+ oprnegate => '>(pg_lsn,pg_lsn)', oprcode => 'pg_lsn_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '3227', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'pg_lsn', oprright => 'pg_lsn',
+ oprresult => 'bool', oprcom => '<=(pg_lsn,pg_lsn)',
+ oprnegate => '<(pg_lsn,pg_lsn)', oprcode => 'pg_lsn_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '3228', descr => 'minus',
+ oprname => '-', oprleft => 'pg_lsn', oprright => 'pg_lsn',
+ oprresult => 'numeric', oprcode => 'pg_lsn_mi' },
+
+# enum operators
+{ oid => '3516', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'anyenum',
+ oprright => 'anyenum', oprresult => 'bool', oprcom => '=(anyenum,anyenum)',
+ oprnegate => '<>(anyenum,anyenum)', oprcode => 'enum_eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '3517', descr => 'not equal',
+ oprname => '<>', oprleft => 'anyenum', oprright => 'anyenum',
+ oprresult => 'bool', oprcom => '<>(anyenum,anyenum)',
+ oprnegate => '=(anyenum,anyenum)', oprcode => 'enum_ne', oprrest => 'neqsel',
+ oprjoin => 'neqjoinsel' },
+{ oid => '3518', descr => 'less than',
+ oprname => '<', oprleft => 'anyenum', oprright => 'anyenum',
+ oprresult => 'bool', oprcom => '>(anyenum,anyenum)',
+ oprnegate => '>=(anyenum,anyenum)', oprcode => 'enum_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '3519', descr => 'greater than',
+ oprname => '>', oprleft => 'anyenum', oprright => 'anyenum',
+ oprresult => 'bool', oprcom => '<(anyenum,anyenum)',
+ oprnegate => '<=(anyenum,anyenum)', oprcode => 'enum_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '3520', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'anyenum', oprright => 'anyenum',
+ oprresult => 'bool', oprcom => '>=(anyenum,anyenum)',
+ oprnegate => '>(anyenum,anyenum)', oprcode => 'enum_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '3521', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'anyenum', oprright => 'anyenum',
+ oprresult => 'bool', oprcom => '<=(anyenum,anyenum)',
+ oprnegate => '<(anyenum,anyenum)', oprcode => 'enum_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+# tsearch operations
+{ oid => '3627', descr => 'less than',
+ oprname => '<', oprleft => 'tsvector', oprright => 'tsvector',
+ oprresult => 'bool', oprcom => '>(tsvector,tsvector)',
+ oprnegate => '>=(tsvector,tsvector)', oprcode => 'tsvector_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '3628', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'tsvector', oprright => 'tsvector',
+ oprresult => 'bool', oprcom => '>=(tsvector,tsvector)',
+ oprnegate => '>(tsvector,tsvector)', oprcode => 'tsvector_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '3629', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprleft => 'tsvector',
+ oprright => 'tsvector', oprresult => 'bool', oprcom => '=(tsvector,tsvector)',
+ oprnegate => '<>(tsvector,tsvector)', oprcode => 'tsvector_eq',
+ oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '3630', descr => 'not equal',
+ oprname => '<>', oprleft => 'tsvector', oprright => 'tsvector',
+ oprresult => 'bool', oprcom => '<>(tsvector,tsvector)',
+ oprnegate => '=(tsvector,tsvector)', oprcode => 'tsvector_ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '3631', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'tsvector', oprright => 'tsvector',
+ oprresult => 'bool', oprcom => '<=(tsvector,tsvector)',
+ oprnegate => '<(tsvector,tsvector)', oprcode => 'tsvector_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '3632', descr => 'greater than',
+ oprname => '>', oprleft => 'tsvector', oprright => 'tsvector',
+ oprresult => 'bool', oprcom => '<(tsvector,tsvector)',
+ oprnegate => '<=(tsvector,tsvector)', oprcode => 'tsvector_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '3633', descr => 'concatenate',
+ oprname => '||', oprleft => 'tsvector', oprright => 'tsvector',
+ oprresult => 'tsvector', oprcode => 'tsvector_concat' },
+{ oid => '3636', descr => 'text search match',
+ oprname => '@@', oprleft => 'tsvector', oprright => 'tsquery',
+ oprresult => 'bool', oprcom => '@@(tsquery,tsvector)',
+ oprcode => 'ts_match_vq', oprrest => 'tsmatchsel',
+ oprjoin => 'tsmatchjoinsel' },
+{ oid => '3637', descr => 'text search match',
+ oprname => '@@', oprleft => 'tsquery', oprright => 'tsvector',
+ oprresult => 'bool', oprcom => '@@(tsvector,tsquery)',
+ oprcode => 'ts_match_qv', oprrest => 'tsmatchsel',
+ oprjoin => 'tsmatchjoinsel' },
+{ oid => '3660', descr => 'deprecated, use @@ instead',
+ oprname => '@@@', oprleft => 'tsvector', oprright => 'tsquery',
+ oprresult => 'bool', oprcom => '@@@(tsquery,tsvector)',
+ oprcode => 'ts_match_vq', oprrest => 'tsmatchsel',
+ oprjoin => 'tsmatchjoinsel' },
+{ oid => '3661', descr => 'deprecated, use @@ instead',
+ oprname => '@@@', oprleft => 'tsquery', oprright => 'tsvector',
+ oprresult => 'bool', oprcom => '@@@(tsvector,tsquery)',
+ oprcode => 'ts_match_qv', oprrest => 'tsmatchsel',
+ oprjoin => 'tsmatchjoinsel' },
+{ oid => '3674', descr => 'less than',
+ oprname => '<', oprleft => 'tsquery', oprright => 'tsquery',
+ oprresult => 'bool', oprcom => '>(tsquery,tsquery)',
+ oprnegate => '>=(tsquery,tsquery)', oprcode => 'tsquery_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '3675', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'tsquery', oprright => 'tsquery',
+ oprresult => 'bool', oprcom => '>=(tsquery,tsquery)',
+ oprnegate => '>(tsquery,tsquery)', oprcode => 'tsquery_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '3676', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprleft => 'tsquery',
+ oprright => 'tsquery', oprresult => 'bool', oprcom => '=(tsquery,tsquery)',
+ oprnegate => '<>(tsquery,tsquery)', oprcode => 'tsquery_eq',
+ oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '3677', descr => 'not equal',
+ oprname => '<>', oprleft => 'tsquery', oprright => 'tsquery',
+ oprresult => 'bool', oprcom => '<>(tsquery,tsquery)',
+ oprnegate => '=(tsquery,tsquery)', oprcode => 'tsquery_ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '3678', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'tsquery', oprright => 'tsquery',
+ oprresult => 'bool', oprcom => '<=(tsquery,tsquery)',
+ oprnegate => '<(tsquery,tsquery)', oprcode => 'tsquery_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+{ oid => '3679', descr => 'greater than',
+ oprname => '>', oprleft => 'tsquery', oprright => 'tsquery',
+ oprresult => 'bool', oprcom => '<(tsquery,tsquery)',
+ oprnegate => '<=(tsquery,tsquery)', oprcode => 'tsquery_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '3680', descr => 'AND-concatenate',
+ oprname => '&&', oprleft => 'tsquery', oprright => 'tsquery',
+ oprresult => 'tsquery', oprcode => 'tsquery_and' },
+{ oid => '3681', descr => 'OR-concatenate',
+ oprname => '||', oprleft => 'tsquery', oprright => 'tsquery',
+ oprresult => 'tsquery', oprcode => 'tsquery_or' },
+{ oid => '5005', descr => 'phrase-concatenate',
+ oprname => '<->', oprleft => 'tsquery', oprright => 'tsquery',
+ oprresult => 'tsquery', oprcode => 'tsquery_phrase(tsquery,tsquery)' },
+{ oid => '3682', descr => 'NOT tsquery',
+ oprname => '!!', oprkind => 'l', oprleft => '0', oprright => 'tsquery',
+ oprresult => 'tsquery', oprcode => 'tsquery_not' },
+{ oid => '3693', descr => 'contains',
+ oprname => '@>', oprleft => 'tsquery', oprright => 'tsquery',
+ oprresult => 'bool', oprcom => '<@(tsquery,tsquery)',
+ oprcode => 'tsq_mcontains', oprrest => 'matchingsel',
+ oprjoin => 'matchingjoinsel' },
+{ oid => '3694', descr => 'is contained by',
+ oprname => '<@', oprleft => 'tsquery', oprright => 'tsquery',
+ oprresult => 'bool', oprcom => '@>(tsquery,tsquery)',
+ oprcode => 'tsq_mcontained', oprrest => 'matchingsel',
+ oprjoin => 'matchingjoinsel' },
+{ oid => '3762', descr => 'text search match',
+ oprname => '@@', oprleft => 'text', oprright => 'text', oprresult => 'bool',
+ oprcode => 'ts_match_tt', oprrest => 'matchingsel',
+ oprjoin => 'matchingjoinsel' },
+{ oid => '3763', descr => 'text search match',
+ oprname => '@@', oprleft => 'text', oprright => 'tsquery',
+ oprresult => 'bool', oprcode => 'ts_match_tq', oprrest => 'matchingsel',
+ oprjoin => 'matchingjoinsel' },
+
+# generic record comparison operators
+{ oid => '2988', oid_symbol => 'RECORD_EQ_OP', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprleft => 'record', oprright => 'record',
+ oprresult => 'bool', oprcom => '=(record,record)',
+ oprnegate => '<>(record,record)', oprcode => 'record_eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '2989', descr => 'not equal',
+ oprname => '<>', oprleft => 'record', oprright => 'record',
+ oprresult => 'bool', oprcom => '<>(record,record)',
+ oprnegate => '=(record,record)', oprcode => 'record_ne', oprrest => 'neqsel',
+ oprjoin => 'neqjoinsel' },
+{ oid => '2990', oid_symbol => 'RECORD_LT_OP', descr => 'less than',
+ oprname => '<', oprleft => 'record', oprright => 'record',
+ oprresult => 'bool', oprcom => '>(record,record)',
+ oprnegate => '>=(record,record)', oprcode => 'record_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '2991', oid_symbol => 'RECORD_GT_OP', descr => 'greater than',
+ oprname => '>', oprleft => 'record', oprright => 'record',
+ oprresult => 'bool', oprcom => '<(record,record)',
+ oprnegate => '<=(record,record)', oprcode => 'record_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '2992', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'record', oprright => 'record',
+ oprresult => 'bool', oprcom => '>=(record,record)',
+ oprnegate => '>(record,record)', oprcode => 'record_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '2993', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'record', oprright => 'record',
+ oprresult => 'bool', oprcom => '<=(record,record)',
+ oprnegate => '<(record,record)', oprcode => 'record_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+# byte-oriented tests for identical rows and fast sorting
+{ oid => '3188', descr => 'identical',
+ oprname => '*=', oprcanmerge => 't', oprleft => 'record',
+ oprright => 'record', oprresult => 'bool', oprcom => '*=(record,record)',
+ oprnegate => '*<>(record,record)', oprcode => 'record_image_eq',
+ oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '3189', descr => 'not identical',
+ oprname => '*<>', oprleft => 'record', oprright => 'record',
+ oprresult => 'bool', oprcom => '*<>(record,record)',
+ oprnegate => '*=(record,record)', oprcode => 'record_image_ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '3190', descr => 'less than',
+ oprname => '*<', oprleft => 'record', oprright => 'record',
+ oprresult => 'bool', oprcom => '*>(record,record)',
+ oprnegate => '*>=(record,record)', oprcode => 'record_image_lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '3191', descr => 'greater than',
+ oprname => '*>', oprleft => 'record', oprright => 'record',
+ oprresult => 'bool', oprcom => '*<(record,record)',
+ oprnegate => '*<=(record,record)', oprcode => 'record_image_gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '3192', descr => 'less than or equal',
+ oprname => '*<=', oprleft => 'record', oprright => 'record',
+ oprresult => 'bool', oprcom => '*>=(record,record)',
+ oprnegate => '*>(record,record)', oprcode => 'record_image_le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '3193', descr => 'greater than or equal',
+ oprname => '*>=', oprleft => 'record', oprright => 'record',
+ oprresult => 'bool', oprcom => '*<=(record,record)',
+ oprnegate => '*<(record,record)', oprcode => 'record_image_ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
+# generic range type operators
+{ oid => '3882', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'anyrange',
+ oprright => 'anyrange', oprresult => 'bool', oprcom => '=(anyrange,anyrange)',
+ oprnegate => '<>(anyrange,anyrange)', oprcode => 'range_eq',
+ oprrest => 'eqsel', oprjoin => 'eqjoinsel' },
+{ oid => '3883', descr => 'not equal',
+ oprname => '<>', oprleft => 'anyrange', oprright => 'anyrange',
+ oprresult => 'bool', oprcom => '<>(anyrange,anyrange)',
+ oprnegate => '=(anyrange,anyrange)', oprcode => 'range_ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '3884', oid_symbol => 'OID_RANGE_LESS_OP', descr => 'less than',
+ oprname => '<', oprleft => 'anyrange', oprright => 'anyrange',
+ oprresult => 'bool', oprcom => '>(anyrange,anyrange)',
+ oprnegate => '>=(anyrange,anyrange)', oprcode => 'range_lt',
+ oprrest => 'rangesel', oprjoin => 'scalarltjoinsel' },
+{ oid => '3885', oid_symbol => 'OID_RANGE_LESS_EQUAL_OP',
+ descr => 'less than or equal',
+ oprname => '<=', oprleft => 'anyrange', oprright => 'anyrange',
+ oprresult => 'bool', oprcom => '>=(anyrange,anyrange)',
+ oprnegate => '>(anyrange,anyrange)', oprcode => 'range_le',
+ oprrest => 'rangesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '3886', oid_symbol => 'OID_RANGE_GREATER_EQUAL_OP',
+ descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'anyrange', oprright => 'anyrange',
+ oprresult => 'bool', oprcom => '<=(anyrange,anyrange)',
+ oprnegate => '<(anyrange,anyrange)', oprcode => 'range_ge',
+ oprrest => 'rangesel', oprjoin => 'scalargejoinsel' },
+{ oid => '3887', oid_symbol => 'OID_RANGE_GREATER_OP',
+ descr => 'greater than',
+ oprname => '>', oprleft => 'anyrange', oprright => 'anyrange',
+ oprresult => 'bool', oprcom => '<(anyrange,anyrange)',
+ oprnegate => '<=(anyrange,anyrange)', oprcode => 'range_gt',
+ oprrest => 'rangesel', oprjoin => 'scalargtjoinsel' },
+{ oid => '3888', oid_symbol => 'OID_RANGE_OVERLAP_OP', descr => 'overlaps',
+ oprname => '&&', oprleft => 'anyrange', oprright => 'anyrange',
+ oprresult => 'bool', oprcom => '&&(anyrange,anyrange)',
+ oprcode => 'range_overlaps', oprrest => 'rangesel',
+ oprjoin => 'areajoinsel' },
+{ oid => '3889', oid_symbol => 'OID_RANGE_CONTAINS_ELEM_OP',
+ descr => 'contains',
+ oprname => '@>', oprleft => 'anyrange', oprright => 'anyelement',
+ oprresult => 'bool', oprcom => '<@(anyelement,anyrange)',
+ oprcode => 'range_contains_elem', oprrest => 'rangesel',
+ oprjoin => 'contjoinsel' },
+{ oid => '3890', oid_symbol => 'OID_RANGE_CONTAINS_OP', descr => 'contains',
+ oprname => '@>', oprleft => 'anyrange', oprright => 'anyrange',
+ oprresult => 'bool', oprcom => '<@(anyrange,anyrange)',
+ oprcode => 'range_contains', oprrest => 'rangesel',
+ oprjoin => 'contjoinsel' },
+{ oid => '3891', oid_symbol => 'OID_RANGE_ELEM_CONTAINED_OP',
+ descr => 'is contained by',
+ oprname => '<@', oprleft => 'anyelement', oprright => 'anyrange',
+ oprresult => 'bool', oprcom => '@>(anyrange,anyelement)',
+ oprcode => 'elem_contained_by_range', oprrest => 'rangesel',
+ oprjoin => 'contjoinsel' },
+{ oid => '3892', oid_symbol => 'OID_RANGE_CONTAINED_OP',
+ descr => 'is contained by',
+ oprname => '<@', oprleft => 'anyrange', oprright => 'anyrange',
+ oprresult => 'bool', oprcom => '@>(anyrange,anyrange)',
+ oprcode => 'range_contained_by', oprrest => 'rangesel',
+ oprjoin => 'contjoinsel' },
+{ oid => '3893', oid_symbol => 'OID_RANGE_LEFT_OP', descr => 'is left of',
+ oprname => '<<', oprleft => 'anyrange', oprright => 'anyrange',
+ oprresult => 'bool', oprcom => '>>(anyrange,anyrange)',
+ oprcode => 'range_before', oprrest => 'rangesel',
+ oprjoin => 'scalarltjoinsel' },
+{ oid => '3894', oid_symbol => 'OID_RANGE_RIGHT_OP', descr => 'is right of',
+ oprname => '>>', oprleft => 'anyrange', oprright => 'anyrange',
+ oprresult => 'bool', oprcom => '<<(anyrange,anyrange)',
+ oprcode => 'range_after', oprrest => 'rangesel',
+ oprjoin => 'scalargtjoinsel' },
+{ oid => '3895', oid_symbol => 'OID_RANGE_OVERLAPS_LEFT_OP',
+ descr => 'overlaps or is left of',
+ oprname => '&<', oprleft => 'anyrange', oprright => 'anyrange',
+ oprresult => 'bool', oprcode => 'range_overleft', oprrest => 'rangesel',
+ oprjoin => 'scalarltjoinsel' },
+{ oid => '3896', oid_symbol => 'OID_RANGE_OVERLAPS_RIGHT_OP',
+ descr => 'overlaps or is right of',
+ oprname => '&>', oprleft => 'anyrange', oprright => 'anyrange',
+ oprresult => 'bool', oprcode => 'range_overright', oprrest => 'rangesel',
+ oprjoin => 'scalargtjoinsel' },
+{ oid => '3897', descr => 'is adjacent to',
+ oprname => '-|-', oprleft => 'anyrange', oprright => 'anyrange',
+ oprresult => 'bool', oprcom => '-|-(anyrange,anyrange)',
+ oprcode => 'range_adjacent', oprrest => 'matchingsel',
+ oprjoin => 'matchingjoinsel' },
+{ oid => '3898', descr => 'range union',
+ oprname => '+', oprleft => 'anyrange', oprright => 'anyrange',
+ oprresult => 'anyrange', oprcom => '+(anyrange,anyrange)',
+ oprcode => 'range_union' },
+{ oid => '3899', descr => 'range difference',
+ oprname => '-', oprleft => 'anyrange', oprright => 'anyrange',
+ oprresult => 'anyrange', oprcode => 'range_minus' },
+{ oid => '3900', descr => 'range intersection',
+ oprname => '*', oprleft => 'anyrange', oprright => 'anyrange',
+ oprresult => 'anyrange', oprcom => '*(anyrange,anyrange)',
+ oprcode => 'range_intersect' },
+{ oid => '3962', descr => 'get json object field',
+ oprname => '->', oprleft => 'json', oprright => 'text', oprresult => 'json',
+ oprcode => 'json_object_field' },
+{ oid => '3963', descr => 'get json object field as text',
+ oprname => '->>', oprleft => 'json', oprright => 'text', oprresult => 'text',
+ oprcode => 'json_object_field_text' },
+{ oid => '3964', descr => 'get json array element',
+ oprname => '->', oprleft => 'json', oprright => 'int4', oprresult => 'json',
+ oprcode => 'json_array_element' },
+{ oid => '3965', descr => 'get json array element as text',
+ oprname => '->>', oprleft => 'json', oprright => 'int4', oprresult => 'text',
+ oprcode => 'json_array_element_text' },
+{ oid => '3966', descr => 'get value from json with path elements',
+ oprname => '#>', oprleft => 'json', oprright => '_text', oprresult => 'json',
+ oprcode => 'json_extract_path' },
+{ oid => '3967', descr => 'get value from json as text with path elements',
+ oprname => '#>>', oprleft => 'json', oprright => '_text', oprresult => 'text',
+ oprcode => 'json_extract_path_text' },
+{ oid => '3211', descr => 'get jsonb object field',
+ oprname => '->', oprleft => 'jsonb', oprright => 'text', oprresult => 'jsonb',
+ oprcode => 'jsonb_object_field' },
+{ oid => '3477', descr => 'get jsonb object field as text',
+ oprname => '->>', oprleft => 'jsonb', oprright => 'text', oprresult => 'text',
+ oprcode => 'jsonb_object_field_text' },
+{ oid => '3212', descr => 'get jsonb array element',
+ oprname => '->', oprleft => 'jsonb', oprright => 'int4', oprresult => 'jsonb',
+ oprcode => 'jsonb_array_element' },
+{ oid => '3481', descr => 'get jsonb array element as text',
+ oprname => '->>', oprleft => 'jsonb', oprright => 'int4', oprresult => 'text',
+ oprcode => 'jsonb_array_element_text' },
+{ oid => '3213', descr => 'get value from jsonb with path elements',
+ oprname => '#>', oprleft => 'jsonb', oprright => '_text',
+ oprresult => 'jsonb', oprcode => 'jsonb_extract_path' },
+{ oid => '3206', descr => 'get value from jsonb as text with path elements',
+ oprname => '#>>', oprleft => 'jsonb', oprright => '_text',
+ oprresult => 'text', oprcode => 'jsonb_extract_path_text' },
+{ oid => '3240', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'jsonb',
+ oprright => 'jsonb', oprresult => 'bool', oprcom => '=(jsonb,jsonb)',
+ oprnegate => '<>(jsonb,jsonb)', oprcode => 'jsonb_eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '3241', descr => 'not equal',
+ oprname => '<>', oprleft => 'jsonb', oprright => 'jsonb', oprresult => 'bool',
+ oprcom => '<>(jsonb,jsonb)', oprnegate => '=(jsonb,jsonb)',
+ oprcode => 'jsonb_ne', oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '3242', descr => 'less than',
+ oprname => '<', oprleft => 'jsonb', oprright => 'jsonb', oprresult => 'bool',
+ oprcom => '>(jsonb,jsonb)', oprnegate => '>=(jsonb,jsonb)',
+ oprcode => 'jsonb_lt', oprrest => 'scalarltsel',
+ oprjoin => 'scalarltjoinsel' },
+{ oid => '3243', descr => 'greater than',
+ oprname => '>', oprleft => 'jsonb', oprright => 'jsonb', oprresult => 'bool',
+ oprcom => '<(jsonb,jsonb)', oprnegate => '<=(jsonb,jsonb)',
+ oprcode => 'jsonb_gt', oprrest => 'scalargtsel',
+ oprjoin => 'scalargtjoinsel' },
+{ oid => '3244', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'jsonb', oprright => 'jsonb', oprresult => 'bool',
+ oprcom => '>=(jsonb,jsonb)', oprnegate => '>(jsonb,jsonb)',
+ oprcode => 'jsonb_le', oprrest => 'scalarlesel',
+ oprjoin => 'scalarlejoinsel' },
+{ oid => '3245', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'jsonb', oprright => 'jsonb', oprresult => 'bool',
+ oprcom => '<=(jsonb,jsonb)', oprnegate => '<(jsonb,jsonb)',
+ oprcode => 'jsonb_ge', oprrest => 'scalargesel',
+ oprjoin => 'scalargejoinsel' },
+{ oid => '3246', descr => 'contains',
+ oprname => '@>', oprleft => 'jsonb', oprright => 'jsonb', oprresult => 'bool',
+ oprcom => '<@(jsonb,jsonb)', oprcode => 'jsonb_contains',
+ oprrest => 'matchingsel', oprjoin => 'matchingjoinsel' },
+{ oid => '3247', descr => 'key exists',
+ oprname => '?', oprleft => 'jsonb', oprright => 'text', oprresult => 'bool',
+ oprcode => 'jsonb_exists', oprrest => 'matchingsel',
+ oprjoin => 'matchingjoinsel' },
+{ oid => '3248', descr => 'any key exists',
+ oprname => '?|', oprleft => 'jsonb', oprright => '_text', oprresult => 'bool',
+ oprcode => 'jsonb_exists_any', oprrest => 'matchingsel',
+ oprjoin => 'matchingjoinsel' },
+{ oid => '3249', descr => 'all keys exist',
+ oprname => '?&', oprleft => 'jsonb', oprright => '_text', oprresult => 'bool',
+ oprcode => 'jsonb_exists_all', oprrest => 'matchingsel',
+ oprjoin => 'matchingjoinsel' },
+{ oid => '3250', descr => 'is contained by',
+ oprname => '<@', oprleft => 'jsonb', oprright => 'jsonb', oprresult => 'bool',
+ oprcom => '@>(jsonb,jsonb)', oprcode => 'jsonb_contained',
+ oprrest => 'matchingsel', oprjoin => 'matchingjoinsel' },
+{ oid => '3284', descr => 'concatenate',
+ oprname => '||', oprleft => 'jsonb', oprright => 'jsonb',
+ oprresult => 'jsonb', oprcode => 'jsonb_concat' },
+{ oid => '3285', descr => 'delete object field',
+ oprname => '-', oprleft => 'jsonb', oprright => 'text', oprresult => 'jsonb',
+ oprcode => 'jsonb_delete(jsonb,text)' },
+{ oid => '3398', descr => 'delete object fields',
+ oprname => '-', oprleft => 'jsonb', oprright => '_text', oprresult => 'jsonb',
+ oprcode => 'jsonb_delete(jsonb,_text)' },
+{ oid => '3286', descr => 'delete array element',
+ oprname => '-', oprleft => 'jsonb', oprright => 'int4', oprresult => 'jsonb',
+ oprcode => 'jsonb_delete(jsonb,int4)' },
+{ oid => '3287', descr => 'delete path',
+ oprname => '#-', oprleft => 'jsonb', oprright => '_text',
+ oprresult => 'jsonb', oprcode => 'jsonb_delete_path' },
+{ oid => '4012', descr => 'jsonpath exists',
+ oprname => '@?', oprleft => 'jsonb', oprright => 'jsonpath',
+ oprresult => 'bool', oprcode => 'jsonb_path_exists_opr(jsonb,jsonpath)',
+ oprrest => 'matchingsel', oprjoin => 'matchingjoinsel' },
+{ oid => '4013', descr => 'jsonpath match',
+ oprname => '@@', oprleft => 'jsonb', oprright => 'jsonpath',
+ oprresult => 'bool', oprcode => 'jsonb_path_match_opr(jsonb,jsonpath)',
+ oprrest => 'matchingsel', oprjoin => 'matchingjoinsel' },
+
+]
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
new file mode 100644
index 0000000..1daa263
--- /dev/null
+++ b/src/include/catalog/pg_operator.h
@@ -0,0 +1,102 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_operator.h
+ * definition of the "operator" system catalog (pg_operator)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_operator.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_OPERATOR_H
+#define PG_OPERATOR_H
+
+#include "catalog/genbki.h"
+#include "catalog/objectaddress.h"
+#include "catalog/pg_operator_d.h"
+#include "nodes/pg_list.h"
+
+/* ----------------
+ * pg_operator definition. cpp turns this into
+ * typedef struct FormData_pg_operator
+ * ----------------
+ */
+CATALOG(pg_operator,2617,OperatorRelationId)
+{
+ Oid oid; /* oid */
+
+ /* name of operator */
+ NameData oprname;
+
+ /* OID of namespace containing this oper */
+ Oid oprnamespace BKI_DEFAULT(PGNSP);
+
+ /* operator owner */
+ Oid oprowner BKI_DEFAULT(PGUID);
+
+ /* 'l', 'r', or 'b' */
+ char oprkind BKI_DEFAULT(b);
+
+ /* can be used in merge join? */
+ bool oprcanmerge BKI_DEFAULT(f);
+
+ /* can be used in hash join? */
+ bool oprcanhash BKI_DEFAULT(f);
+
+ /* left arg type, or 0 if 'l' oprkind */
+ Oid oprleft BKI_LOOKUP(pg_type);
+
+ /* right arg type, or 0 if 'r' oprkind */
+ Oid oprright BKI_LOOKUP(pg_type);
+
+ /* result datatype */
+ Oid oprresult BKI_LOOKUP(pg_type);
+
+ /* OID of commutator oper, or 0 if none */
+ Oid oprcom BKI_DEFAULT(0) BKI_LOOKUP(pg_operator);
+
+ /* OID of negator oper, or 0 if none */
+ Oid oprnegate BKI_DEFAULT(0) BKI_LOOKUP(pg_operator);
+
+ /* OID of underlying function */
+ regproc oprcode BKI_LOOKUP(pg_proc);
+
+ /* OID of restriction estimator, or 0 */
+ regproc oprrest BKI_DEFAULT(-) BKI_LOOKUP(pg_proc);
+
+ /* OID of join estimator, or 0 */
+ regproc oprjoin BKI_DEFAULT(-) BKI_LOOKUP(pg_proc);
+} FormData_pg_operator;
+
+/* ----------------
+ * Form_pg_operator corresponds to a pointer to a tuple with
+ * the format of pg_operator relation.
+ * ----------------
+ */
+typedef FormData_pg_operator *Form_pg_operator;
+
+
+extern ObjectAddress OperatorCreate(const char *operatorName,
+ Oid operatorNamespace,
+ Oid leftTypeId,
+ Oid rightTypeId,
+ Oid procedureId,
+ List *commutatorName,
+ List *negatorName,
+ Oid restrictionId,
+ Oid joinId,
+ bool canMerge,
+ bool canHash);
+
+extern ObjectAddress makeOperatorDependencies(HeapTuple tuple, bool isUpdate);
+
+extern void OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete);
+
+#endif /* PG_OPERATOR_H */
diff --git a/src/include/catalog/pg_opfamily.dat b/src/include/catalog/pg_opfamily.dat
new file mode 100644
index 0000000..cf0fb32
--- /dev/null
+++ b/src/include/catalog/pg_opfamily.dat
@@ -0,0 +1,234 @@
+#----------------------------------------------------------------------
+#
+# pg_opfamily.dat
+# Initial contents of the pg_opfamily system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_opfamily.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+{ oid => '397',
+ opfmethod => 'btree', opfname => 'array_ops' },
+{ oid => '627',
+ opfmethod => 'hash', opfname => 'array_ops' },
+{ oid => '423',
+ opfmethod => 'btree', opfname => 'bit_ops' },
+{ oid => '424', oid_symbol => 'BOOL_BTREE_FAM_OID',
+ opfmethod => 'btree', opfname => 'bool_ops' },
+{ oid => '426', oid_symbol => 'BPCHAR_BTREE_FAM_OID',
+ opfmethod => 'btree', opfname => 'bpchar_ops' },
+{ oid => '427',
+ opfmethod => 'hash', opfname => 'bpchar_ops' },
+{ oid => '428', oid_symbol => 'BYTEA_BTREE_FAM_OID',
+ opfmethod => 'btree', opfname => 'bytea_ops' },
+{ oid => '429',
+ opfmethod => 'btree', opfname => 'char_ops' },
+{ oid => '431',
+ opfmethod => 'hash', opfname => 'char_ops' },
+{ oid => '434',
+ opfmethod => 'btree', opfname => 'datetime_ops' },
+{ oid => '435',
+ opfmethod => 'hash', opfname => 'date_ops' },
+{ oid => '1970',
+ opfmethod => 'btree', opfname => 'float_ops' },
+{ oid => '1971',
+ opfmethod => 'hash', opfname => 'float_ops' },
+{ oid => '1974', oid_symbol => 'NETWORK_BTREE_FAM_OID',
+ opfmethod => 'btree', opfname => 'network_ops' },
+{ oid => '1975',
+ opfmethod => 'hash', opfname => 'network_ops' },
+{ oid => '3550',
+ opfmethod => 'gist', opfname => 'network_ops' },
+{ oid => '3794',
+ opfmethod => 'spgist', opfname => 'network_ops' },
+{ oid => '1976', oid_symbol => 'INTEGER_BTREE_FAM_OID',
+ opfmethod => 'btree', opfname => 'integer_ops' },
+{ oid => '1977',
+ opfmethod => 'hash', opfname => 'integer_ops' },
+{ oid => '1982',
+ opfmethod => 'btree', opfname => 'interval_ops' },
+{ oid => '1983',
+ opfmethod => 'hash', opfname => 'interval_ops' },
+{ oid => '1984',
+ opfmethod => 'btree', opfname => 'macaddr_ops' },
+{ oid => '1985',
+ opfmethod => 'hash', opfname => 'macaddr_ops' },
+{ oid => '3371',
+ opfmethod => 'btree', opfname => 'macaddr8_ops' },
+{ oid => '3372',
+ opfmethod => 'hash', opfname => 'macaddr8_ops' },
+{ oid => '1988',
+ opfmethod => 'btree', opfname => 'numeric_ops' },
+{ oid => '1998',
+ opfmethod => 'hash', opfname => 'numeric_ops' },
+{ oid => '1989', oid_symbol => 'OID_BTREE_FAM_OID',
+ opfmethod => 'btree', opfname => 'oid_ops' },
+{ oid => '1990',
+ opfmethod => 'hash', opfname => 'oid_ops' },
+{ oid => '1991',
+ opfmethod => 'btree', opfname => 'oidvector_ops' },
+{ oid => '1992',
+ opfmethod => 'hash', opfname => 'oidvector_ops' },
+{ oid => '2994',
+ opfmethod => 'btree', opfname => 'record_ops' },
+{ oid => '3194',
+ opfmethod => 'btree', opfname => 'record_image_ops' },
+{ oid => '1994', oid_symbol => 'TEXT_BTREE_FAM_OID',
+ opfmethod => 'btree', opfname => 'text_ops' },
+{ oid => '1995',
+ opfmethod => 'hash', opfname => 'text_ops' },
+{ oid => '1996',
+ opfmethod => 'btree', opfname => 'time_ops' },
+{ oid => '1997',
+ opfmethod => 'hash', opfname => 'time_ops' },
+{ oid => '1999',
+ opfmethod => 'hash', opfname => 'timestamptz_ops' },
+{ oid => '2000',
+ opfmethod => 'btree', opfname => 'timetz_ops' },
+{ oid => '2001',
+ opfmethod => 'hash', opfname => 'timetz_ops' },
+{ oid => '2002',
+ opfmethod => 'btree', opfname => 'varbit_ops' },
+{ oid => '2040',
+ opfmethod => 'hash', opfname => 'timestamp_ops' },
+{ oid => '2095', oid_symbol => 'TEXT_PATTERN_BTREE_FAM_OID',
+ opfmethod => 'btree', opfname => 'text_pattern_ops' },
+{ oid => '2097', oid_symbol => 'BPCHAR_PATTERN_BTREE_FAM_OID',
+ opfmethod => 'btree', opfname => 'bpchar_pattern_ops' },
+{ oid => '2099',
+ opfmethod => 'btree', opfname => 'money_ops' },
+{ oid => '2222', oid_symbol => 'BOOL_HASH_FAM_OID',
+ opfmethod => 'hash', opfname => 'bool_ops' },
+{ oid => '2223',
+ opfmethod => 'hash', opfname => 'bytea_ops' },
+{ oid => '2789',
+ opfmethod => 'btree', opfname => 'tid_ops' },
+{ oid => '2225',
+ opfmethod => 'hash', opfname => 'xid_ops' },
+{ oid => '5032',
+ opfmethod => 'hash', opfname => 'xid8_ops' },
+{ oid => '5067',
+ opfmethod => 'btree', opfname => 'xid8_ops' },
+{ oid => '2226',
+ opfmethod => 'hash', opfname => 'cid_ops' },
+{ oid => '2227',
+ opfmethod => 'hash', opfname => 'tid_ops' },
+{ oid => '2229',
+ opfmethod => 'hash', opfname => 'text_pattern_ops' },
+{ oid => '2231',
+ opfmethod => 'hash', opfname => 'bpchar_pattern_ops' },
+{ oid => '2235',
+ opfmethod => 'hash', opfname => 'aclitem_ops' },
+{ oid => '2593',
+ opfmethod => 'gist', opfname => 'box_ops' },
+{ oid => '2594',
+ opfmethod => 'gist', opfname => 'poly_ops' },
+{ oid => '2595',
+ opfmethod => 'gist', opfname => 'circle_ops' },
+{ oid => '1029',
+ opfmethod => 'gist', opfname => 'point_ops' },
+{ oid => '2745',
+ opfmethod => 'gin', opfname => 'array_ops' },
+{ oid => '2968',
+ opfmethod => 'btree', opfname => 'uuid_ops' },
+{ oid => '2969',
+ opfmethod => 'hash', opfname => 'uuid_ops' },
+{ oid => '3253',
+ opfmethod => 'btree', opfname => 'pg_lsn_ops' },
+{ oid => '3254',
+ opfmethod => 'hash', opfname => 'pg_lsn_ops' },
+{ oid => '3522',
+ opfmethod => 'btree', opfname => 'enum_ops' },
+{ oid => '3523',
+ opfmethod => 'hash', opfname => 'enum_ops' },
+{ oid => '3626',
+ opfmethod => 'btree', opfname => 'tsvector_ops' },
+{ oid => '3655',
+ opfmethod => 'gist', opfname => 'tsvector_ops' },
+{ oid => '3659',
+ opfmethod => 'gin', opfname => 'tsvector_ops' },
+{ oid => '3683',
+ opfmethod => 'btree', opfname => 'tsquery_ops' },
+{ oid => '3702',
+ opfmethod => 'gist', opfname => 'tsquery_ops' },
+{ oid => '3901',
+ opfmethod => 'btree', opfname => 'range_ops' },
+{ oid => '3903',
+ opfmethod => 'hash', opfname => 'range_ops' },
+{ oid => '3919',
+ opfmethod => 'gist', opfname => 'range_ops' },
+{ oid => '3474',
+ opfmethod => 'spgist', opfname => 'range_ops' },
+{ oid => '4015',
+ opfmethod => 'spgist', opfname => 'quad_point_ops' },
+{ oid => '4016',
+ opfmethod => 'spgist', opfname => 'kd_point_ops' },
+{ oid => '4017', oid_symbol => 'TEXT_SPGIST_FAM_OID',
+ opfmethod => 'spgist', opfname => 'text_ops' },
+{ oid => '4033',
+ opfmethod => 'btree', opfname => 'jsonb_ops' },
+{ oid => '4034',
+ opfmethod => 'hash', opfname => 'jsonb_ops' },
+{ oid => '4036',
+ opfmethod => 'gin', opfname => 'jsonb_ops' },
+{ oid => '4037',
+ opfmethod => 'gin', opfname => 'jsonb_path_ops' },
+{ oid => '4054',
+ opfmethod => 'brin', opfname => 'integer_minmax_ops' },
+{ oid => '4055',
+ opfmethod => 'brin', opfname => 'numeric_minmax_ops' },
+{ oid => '4056',
+ opfmethod => 'brin', opfname => 'text_minmax_ops' },
+{ oid => '4058',
+ opfmethod => 'brin', opfname => 'timetz_minmax_ops' },
+{ oid => '4059',
+ opfmethod => 'brin', opfname => 'datetime_minmax_ops' },
+{ oid => '4062',
+ opfmethod => 'brin', opfname => 'char_minmax_ops' },
+{ oid => '4064',
+ opfmethod => 'brin', opfname => 'bytea_minmax_ops' },
+{ oid => '4065',
+ opfmethod => 'brin', opfname => 'name_minmax_ops' },
+{ oid => '4068',
+ opfmethod => 'brin', opfname => 'oid_minmax_ops' },
+{ oid => '4069',
+ opfmethod => 'brin', opfname => 'tid_minmax_ops' },
+{ oid => '4070',
+ opfmethod => 'brin', opfname => 'float_minmax_ops' },
+{ oid => '4074',
+ opfmethod => 'brin', opfname => 'macaddr_minmax_ops' },
+{ oid => '4109',
+ opfmethod => 'brin', opfname => 'macaddr8_minmax_ops' },
+{ oid => '4075',
+ opfmethod => 'brin', opfname => 'network_minmax_ops' },
+{ oid => '4102',
+ opfmethod => 'brin', opfname => 'network_inclusion_ops' },
+{ oid => '4076',
+ opfmethod => 'brin', opfname => 'bpchar_minmax_ops' },
+{ oid => '4077',
+ opfmethod => 'brin', opfname => 'time_minmax_ops' },
+{ oid => '4078',
+ opfmethod => 'brin', opfname => 'interval_minmax_ops' },
+{ oid => '4079',
+ opfmethod => 'brin', opfname => 'bit_minmax_ops' },
+{ oid => '4080',
+ opfmethod => 'brin', opfname => 'varbit_minmax_ops' },
+{ oid => '4081',
+ opfmethod => 'brin', opfname => 'uuid_minmax_ops' },
+{ oid => '4103',
+ opfmethod => 'brin', opfname => 'range_inclusion_ops' },
+{ oid => '4082',
+ opfmethod => 'brin', opfname => 'pg_lsn_minmax_ops' },
+{ oid => '4104',
+ opfmethod => 'brin', opfname => 'box_inclusion_ops' },
+{ oid => '5000',
+ opfmethod => 'spgist', opfname => 'box_ops' },
+{ oid => '5008',
+ opfmethod => 'spgist', opfname => 'poly_ops' },
+
+]
diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h
new file mode 100644
index 0000000..503f0d2
--- /dev/null
+++ b/src/include/catalog/pg_opfamily.h
@@ -0,0 +1,60 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_opfamily.h
+ * definition of the "operator family" system catalog (pg_opfamily)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_opfamily.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_OPFAMILY_H
+#define PG_OPFAMILY_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_opfamily_d.h"
+
+/* ----------------
+ * pg_opfamily definition. cpp turns this into
+ * typedef struct FormData_pg_opfamily
+ * ----------------
+ */
+CATALOG(pg_opfamily,2753,OperatorFamilyRelationId)
+{
+ Oid oid; /* oid */
+
+ /* index access method opfamily is for */
+ Oid opfmethod BKI_LOOKUP(pg_am);
+
+ /* name of this opfamily */
+ NameData opfname;
+
+ /* namespace of this opfamily */
+ Oid opfnamespace BKI_DEFAULT(PGNSP);
+
+ /* opfamily owner */
+ Oid opfowner BKI_DEFAULT(PGUID);
+} FormData_pg_opfamily;
+
+/* ----------------
+ * Form_pg_opfamily corresponds to a pointer to a tuple with
+ * the format of pg_opfamily relation.
+ * ----------------
+ */
+typedef FormData_pg_opfamily *Form_pg_opfamily;
+
+#ifdef EXPOSE_TO_CLIENT_CODE
+
+#define IsBooleanOpfamily(opfamily) \
+ ((opfamily) == BOOL_BTREE_FAM_OID || (opfamily) == BOOL_HASH_FAM_OID)
+
+#endif /* EXPOSE_TO_CLIENT_CODE */
+
+#endif /* PG_OPFAMILY_H */
diff --git a/src/include/catalog/pg_partitioned_table.h b/src/include/catalog/pg_partitioned_table.h
new file mode 100644
index 0000000..a73cd0d
--- /dev/null
+++ b/src/include/catalog/pg_partitioned_table.h
@@ -0,0 +1,63 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_partitioned_table.h
+ * definition of the "partitioned table" system catalog
+ * (pg_partitioned_table)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_partitioned_table.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_PARTITIONED_TABLE_H
+#define PG_PARTITIONED_TABLE_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_partitioned_table_d.h"
+
+/* ----------------
+ * pg_partitioned_table definition. cpp turns this into
+ * typedef struct FormData_pg_partitioned_table
+ * ----------------
+ */
+CATALOG(pg_partitioned_table,3350,PartitionedRelationId)
+{
+ Oid partrelid; /* partitioned table oid */
+ char partstrat; /* partitioning strategy */
+ int16 partnatts; /* number of partition key columns */
+ Oid partdefid; /* default partition oid; InvalidOid if there
+ * isn't one */
+
+ /*
+ * variable-length fields start here, but we allow direct access to
+ * partattrs via the C struct. That's because the first variable-length
+ * field of a heap tuple can be reliably accessed using its C struct
+ * offset, as previous fields are all non-nullable fixed-length fields.
+ */
+ int2vector partattrs; /* each member of the array is the attribute
+ * number of a partition key column, or 0 if
+ * the column is actually an expression */
+
+#ifdef CATALOG_VARLEN
+ oidvector partclass; /* operator class to compare keys */
+ oidvector partcollation; /* user-specified collation for keys */
+ pg_node_tree partexprs; /* list of expressions in the partition key;
+ * one item for each zero entry in partattrs[] */
+#endif
+} FormData_pg_partitioned_table;
+
+/* ----------------
+ * Form_pg_partitioned_table corresponds to a pointer to a tuple with
+ * the format of pg_partitioned_table relation.
+ * ----------------
+ */
+typedef FormData_pg_partitioned_table *Form_pg_partitioned_table;
+
+#endif /* PG_PARTITIONED_TABLE_H */
diff --git a/src/include/catalog/pg_policy.h b/src/include/catalog/pg_policy.h
new file mode 100644
index 0000000..97954cd
--- /dev/null
+++ b/src/include/catalog/pg_policy.h
@@ -0,0 +1,52 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_policy.h
+ * definition of the "policy" system catalog (pg_policy)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_policy.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_POLICY_H
+#define PG_POLICY_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_policy_d.h"
+
+/* ----------------
+ * pg_policy definition. cpp turns this into
+ * typedef struct FormData_pg_policy
+ * ----------------
+ */
+CATALOG(pg_policy,3256,PolicyRelationId)
+{
+ Oid oid; /* oid */
+ NameData polname; /* Policy name. */
+ Oid polrelid; /* Oid of the relation with policy. */
+ char polcmd; /* One of ACL_*_CHR, or '*' for all */
+ bool polpermissive; /* restrictive or permissive policy */
+
+#ifdef CATALOG_VARLEN
+ Oid polroles[1] BKI_FORCE_NOT_NULL; /* Roles associated with
+ * policy */
+ pg_node_tree polqual; /* Policy quals. */
+ pg_node_tree polwithcheck; /* WITH CHECK quals. */
+#endif
+} FormData_pg_policy;
+
+/* ----------------
+ * Form_pg_policy corresponds to a pointer to a row with
+ * the format of pg_policy relation.
+ * ----------------
+ */
+typedef FormData_pg_policy *Form_pg_policy;
+
+#endif /* PG_POLICY_H */
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
new file mode 100644
index 0000000..c228727
--- /dev/null
+++ b/src/include/catalog/pg_proc.dat
@@ -0,0 +1,10940 @@
+#----------------------------------------------------------------------
+#
+# pg_proc.dat
+# Initial contents of the pg_proc system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_proc.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+# Note: every entry in pg_proc.dat is expected to have a 'descr' comment,
+# except for functions that implement pg_operator.dat operators and don't
+# have a good reason to be called directly rather than via the operator.
+# (If you do expect such a function to be used directly, you should
+# duplicate the operator's comment.) initdb will supply suitable default
+# comments for functions referenced by pg_operator.
+
+# Try to follow the style of existing functions' comments.
+# Some recommended conventions:
+#
+# "I/O" for typinput, typoutput, typreceive, typsend functions
+# "I/O typmod" for typmodin, typmodout functions
+# "aggregate transition function" for aggtransfn functions, unless
+# they are reasonably useful in their own right
+# "aggregate final function" for aggfinalfn functions (likewise)
+# "convert srctypename to desttypename" for cast functions
+# "less-equal-greater" for B-tree comparison functions
+
+# Note: pronargs is computed when this file is read, so it does not need
+# to be specified in entries here. See AddDefaultValues() in Catalog.pm.
+
+# Once upon a time these entries were ordered by OID. Lately it's often
+# been the custom to insert new entries adjacent to related older entries.
+# Try to do one or the other though, don't just insert entries at random.
+
+# OIDS 1 - 99
+
+{ oid => '1242', descr => 'I/O',
+ proname => 'boolin', prorettype => 'bool', proargtypes => 'cstring',
+ prosrc => 'boolin' },
+{ oid => '1243', descr => 'I/O',
+ proname => 'boolout', prorettype => 'cstring', proargtypes => 'bool',
+ prosrc => 'boolout' },
+{ oid => '1244', descr => 'I/O',
+ proname => 'byteain', prorettype => 'bytea', proargtypes => 'cstring',
+ prosrc => 'byteain' },
+{ oid => '31', descr => 'I/O',
+ proname => 'byteaout', prorettype => 'cstring', proargtypes => 'bytea',
+ prosrc => 'byteaout' },
+{ oid => '1245', descr => 'I/O',
+ proname => 'charin', prorettype => 'char', proargtypes => 'cstring',
+ prosrc => 'charin' },
+{ oid => '33', descr => 'I/O',
+ proname => 'charout', prorettype => 'cstring', proargtypes => 'char',
+ prosrc => 'charout' },
+{ oid => '34', descr => 'I/O',
+ proname => 'namein', prorettype => 'name', proargtypes => 'cstring',
+ prosrc => 'namein' },
+{ oid => '35', descr => 'I/O',
+ proname => 'nameout', prorettype => 'cstring', proargtypes => 'name',
+ prosrc => 'nameout' },
+{ oid => '38', descr => 'I/O',
+ proname => 'int2in', prorettype => 'int2', proargtypes => 'cstring',
+ prosrc => 'int2in' },
+{ oid => '39', descr => 'I/O',
+ proname => 'int2out', prorettype => 'cstring', proargtypes => 'int2',
+ prosrc => 'int2out' },
+{ oid => '40', descr => 'I/O',
+ proname => 'int2vectorin', prorettype => 'int2vector',
+ proargtypes => 'cstring', prosrc => 'int2vectorin' },
+{ oid => '41', descr => 'I/O',
+ proname => 'int2vectorout', prorettype => 'cstring',
+ proargtypes => 'int2vector', prosrc => 'int2vectorout' },
+{ oid => '42', descr => 'I/O',
+ proname => 'int4in', prorettype => 'int4', proargtypes => 'cstring',
+ prosrc => 'int4in' },
+{ oid => '43', descr => 'I/O',
+ proname => 'int4out', prorettype => 'cstring', proargtypes => 'int4',
+ prosrc => 'int4out' },
+{ oid => '44', descr => 'I/O',
+ proname => 'regprocin', provolatile => 's', prorettype => 'regproc',
+ proargtypes => 'cstring', prosrc => 'regprocin' },
+{ oid => '45', descr => 'I/O',
+ proname => 'regprocout', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'regproc', prosrc => 'regprocout' },
+{ oid => '3494', descr => 'convert proname to regproc',
+ proname => 'to_regproc', provolatile => 's', prorettype => 'regproc',
+ proargtypes => 'text', prosrc => 'to_regproc' },
+{ oid => '3479', descr => 'convert proname to regprocedure',
+ proname => 'to_regprocedure', provolatile => 's',
+ prorettype => 'regprocedure', proargtypes => 'text',
+ prosrc => 'to_regprocedure' },
+{ oid => '46', descr => 'I/O',
+ proname => 'textin', prorettype => 'text', proargtypes => 'cstring',
+ prosrc => 'textin' },
+{ oid => '47', descr => 'I/O',
+ proname => 'textout', prorettype => 'cstring', proargtypes => 'text',
+ prosrc => 'textout' },
+{ oid => '48', descr => 'I/O',
+ proname => 'tidin', prorettype => 'tid', proargtypes => 'cstring',
+ prosrc => 'tidin' },
+{ oid => '49', descr => 'I/O',
+ proname => 'tidout', prorettype => 'cstring', proargtypes => 'tid',
+ prosrc => 'tidout' },
+{ oid => '50', descr => 'I/O',
+ proname => 'xidin', prorettype => 'xid', proargtypes => 'cstring',
+ prosrc => 'xidin' },
+{ oid => '51', descr => 'I/O',
+ proname => 'xidout', prorettype => 'cstring', proargtypes => 'xid',
+ prosrc => 'xidout' },
+{ oid => '5070', descr => 'I/O',
+ proname => 'xid8in', prorettype => 'xid8', proargtypes => 'cstring',
+ prosrc => 'xid8in' },
+{ oid => '5081', descr => 'I/O',
+ proname => 'xid8out', prorettype => 'cstring', proargtypes => 'xid8',
+ prosrc => 'xid8out' },
+{ oid => '5082', descr => 'I/O',
+ proname => 'xid8recv', prorettype => 'xid8', proargtypes => 'internal',
+ prosrc => 'xid8recv' },
+{ oid => '5083', descr => 'I/O',
+ proname => 'xid8send', prorettype => 'bytea', proargtypes => 'xid8',
+ prosrc => 'xid8send' },
+{ oid => '52', descr => 'I/O',
+ proname => 'cidin', prorettype => 'cid', proargtypes => 'cstring',
+ prosrc => 'cidin' },
+{ oid => '53', descr => 'I/O',
+ proname => 'cidout', prorettype => 'cstring', proargtypes => 'cid',
+ prosrc => 'cidout' },
+{ oid => '54', descr => 'I/O',
+ proname => 'oidvectorin', prorettype => 'oidvector', proargtypes => 'cstring',
+ prosrc => 'oidvectorin' },
+{ oid => '55', descr => 'I/O',
+ proname => 'oidvectorout', prorettype => 'cstring',
+ proargtypes => 'oidvector', prosrc => 'oidvectorout' },
+{ oid => '56',
+ proname => 'boollt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bool bool', prosrc => 'boollt' },
+{ oid => '57',
+ proname => 'boolgt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bool bool', prosrc => 'boolgt' },
+{ oid => '60',
+ proname => 'booleq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bool bool', prosrc => 'booleq' },
+{ oid => '61',
+ proname => 'chareq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'char char', prosrc => 'chareq' },
+{ oid => '62',
+ proname => 'nameeq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'name name', prosrc => 'nameeq' },
+{ oid => '63',
+ proname => 'int2eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int2 int2', prosrc => 'int2eq' },
+{ oid => '64',
+ proname => 'int2lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int2 int2', prosrc => 'int2lt' },
+{ oid => '65',
+ proname => 'int4eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int4 int4', prosrc => 'int4eq' },
+{ oid => '66',
+ proname => 'int4lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int4 int4', prosrc => 'int4lt' },
+{ oid => '67',
+ proname => 'texteq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'texteq' },
+{ oid => '3696',
+ proname => 'starts_with', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'text_starts_with' },
+{ oid => '68',
+ proname => 'xideq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'xid xid', prosrc => 'xideq' },
+{ oid => '3308',
+ proname => 'xidneq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'xid xid', prosrc => 'xidneq' },
+{ oid => '5084',
+ proname => 'xid8eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'xid8 xid8', prosrc => 'xid8eq' },
+{ oid => '5085',
+ proname => 'xid8ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'xid8 xid8', prosrc => 'xid8ne' },
+{ oid => '5034',
+ proname => 'xid8lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'xid8 xid8', prosrc => 'xid8lt' },
+{ oid => '5035',
+ proname => 'xid8gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'xid8 xid8', prosrc => 'xid8gt' },
+{ oid => '5036',
+ proname => 'xid8le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'xid8 xid8', prosrc => 'xid8le' },
+{ oid => '5037',
+ proname => 'xid8ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'xid8 xid8', prosrc => 'xid8ge' },
+{ oid => '5096', descr => 'less-equal-greater',
+ proname => 'xid8cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'xid8 xid8', prosrc => 'xid8cmp' },
+{ oid => '5071', descr => 'convert xid8 to xid',
+ proname => 'xid', prorettype => 'xid', proargtypes => 'xid8',
+ prosrc => 'xid8toxid' },
+{ oid => '69',
+ proname => 'cideq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'cid cid', prosrc => 'cideq' },
+{ oid => '70',
+ proname => 'charne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'char char', prosrc => 'charne' },
+{ oid => '1246',
+ proname => 'charlt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'char char', prosrc => 'charlt' },
+{ oid => '72',
+ proname => 'charle', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'char char', prosrc => 'charle' },
+{ oid => '73',
+ proname => 'chargt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'char char', prosrc => 'chargt' },
+{ oid => '74',
+ proname => 'charge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'char char', prosrc => 'charge' },
+{ oid => '77', descr => 'convert char to int4',
+ proname => 'int4', prorettype => 'int4', proargtypes => 'char',
+ prosrc => 'chartoi4' },
+{ oid => '78', descr => 'convert int4 to char',
+ proname => 'char', prorettype => 'char', proargtypes => 'int4',
+ prosrc => 'i4tochar' },
+
+{ oid => '79',
+ proname => 'nameregexeq', prosupport => 'textregexeq_support',
+ prorettype => 'bool', proargtypes => 'name text', prosrc => 'nameregexeq' },
+{ oid => '1252',
+ proname => 'nameregexne', prorettype => 'bool', proargtypes => 'name text',
+ prosrc => 'nameregexne' },
+{ oid => '1254',
+ proname => 'textregexeq', prosupport => 'textregexeq_support',
+ prorettype => 'bool', proargtypes => 'text text', prosrc => 'textregexeq' },
+{ oid => '1256',
+ proname => 'textregexne', prorettype => 'bool', proargtypes => 'text text',
+ prosrc => 'textregexne' },
+{ oid => '1364', descr => 'planner support for textregexeq',
+ proname => 'textregexeq_support', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'textregexeq_support' },
+
+{ oid => '1257', descr => 'length',
+ proname => 'textlen', prorettype => 'int4', proargtypes => 'text',
+ prosrc => 'textlen' },
+{ oid => '1258',
+ proname => 'textcat', prorettype => 'text', proargtypes => 'text text',
+ prosrc => 'textcat' },
+
+{ oid => '84',
+ proname => 'boolne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bool bool', prosrc => 'boolne' },
+{ oid => '89', descr => 'PostgreSQL version string',
+ proname => 'version', provolatile => 's', prorettype => 'text',
+ proargtypes => '', prosrc => 'pgsql_version' },
+
+{ oid => '86', descr => 'I/O',
+ proname => 'pg_ddl_command_in', prorettype => 'pg_ddl_command',
+ proargtypes => 'cstring', prosrc => 'pg_ddl_command_in' },
+{ oid => '87', descr => 'I/O',
+ proname => 'pg_ddl_command_out', prorettype => 'cstring',
+ proargtypes => 'pg_ddl_command', prosrc => 'pg_ddl_command_out' },
+{ oid => '88', descr => 'I/O',
+ proname => 'pg_ddl_command_recv', prorettype => 'pg_ddl_command',
+ proargtypes => 'internal', prosrc => 'pg_ddl_command_recv' },
+{ oid => '90', descr => 'I/O',
+ proname => 'pg_ddl_command_send', prorettype => 'bytea',
+ proargtypes => 'pg_ddl_command', prosrc => 'pg_ddl_command_send' },
+
+# OIDS 100 - 199
+
+{ oid => '101', descr => 'restriction selectivity of = and related operators',
+ proname => 'eqsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'eqsel' },
+{ oid => '102',
+ descr => 'restriction selectivity of <> and related operators',
+ proname => 'neqsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'neqsel' },
+{ oid => '103',
+ descr => 'restriction selectivity of < and related operators on scalar datatypes',
+ proname => 'scalarltsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'scalarltsel' },
+{ oid => '104',
+ descr => 'restriction selectivity of > and related operators on scalar datatypes',
+ proname => 'scalargtsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'scalargtsel' },
+{ oid => '105', descr => 'join selectivity of = and related operators',
+ proname => 'eqjoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal', prosrc => 'eqjoinsel' },
+{ oid => '106', descr => 'join selectivity of <> and related operators',
+ proname => 'neqjoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'neqjoinsel' },
+{ oid => '107',
+ descr => 'join selectivity of < and related operators on scalar datatypes',
+ proname => 'scalarltjoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'scalarltjoinsel' },
+{ oid => '108',
+ descr => 'join selectivity of > and related operators on scalar datatypes',
+ proname => 'scalargtjoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'scalargtjoinsel' },
+
+{ oid => '336',
+ descr => 'restriction selectivity of <= and related operators on scalar datatypes',
+ proname => 'scalarlesel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'scalarlesel' },
+{ oid => '337',
+ descr => 'restriction selectivity of >= and related operators on scalar datatypes',
+ proname => 'scalargesel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'scalargesel' },
+{ oid => '386',
+ descr => 'join selectivity of <= and related operators on scalar datatypes',
+ proname => 'scalarlejoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'scalarlejoinsel' },
+{ oid => '398',
+ descr => 'join selectivity of >= and related operators on scalar datatypes',
+ proname => 'scalargejoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'scalargejoinsel' },
+
+{ oid => '109', descr => 'I/O',
+ proname => 'unknownin', prorettype => 'unknown', proargtypes => 'cstring',
+ prosrc => 'unknownin' },
+{ oid => '110', descr => 'I/O',
+ proname => 'unknownout', prorettype => 'cstring', proargtypes => 'unknown',
+ prosrc => 'unknownout' },
+{ oid => '111',
+ descr => 'implementation of deprecated ! and !! factorial operators',
+ proname => 'numeric_fac', prorettype => 'numeric', proargtypes => 'int8',
+ prosrc => 'numeric_fac' },
+
+{ oid => '115',
+ proname => 'box_above_eq', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_above_eq' },
+{ oid => '116',
+ proname => 'box_below_eq', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_below_eq' },
+
+{ oid => '117', descr => 'I/O',
+ proname => 'point_in', prorettype => 'point', proargtypes => 'cstring',
+ prosrc => 'point_in' },
+{ oid => '118', descr => 'I/O',
+ proname => 'point_out', prorettype => 'cstring', proargtypes => 'point',
+ prosrc => 'point_out' },
+{ oid => '119', descr => 'I/O',
+ proname => 'lseg_in', prorettype => 'lseg', proargtypes => 'cstring',
+ prosrc => 'lseg_in' },
+{ oid => '120', descr => 'I/O',
+ proname => 'lseg_out', prorettype => 'cstring', proargtypes => 'lseg',
+ prosrc => 'lseg_out' },
+{ oid => '121', descr => 'I/O',
+ proname => 'path_in', prorettype => 'path', proargtypes => 'cstring',
+ prosrc => 'path_in' },
+{ oid => '122', descr => 'I/O',
+ proname => 'path_out', prorettype => 'cstring', proargtypes => 'path',
+ prosrc => 'path_out' },
+{ oid => '123', descr => 'I/O',
+ proname => 'box_in', prorettype => 'box', proargtypes => 'cstring',
+ prosrc => 'box_in' },
+{ oid => '124', descr => 'I/O',
+ proname => 'box_out', prorettype => 'cstring', proargtypes => 'box',
+ prosrc => 'box_out' },
+{ oid => '125',
+ proname => 'box_overlap', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_overlap' },
+{ oid => '126',
+ proname => 'box_ge', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_ge' },
+{ oid => '127',
+ proname => 'box_gt', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_gt' },
+{ oid => '128',
+ proname => 'box_eq', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_eq' },
+{ oid => '129',
+ proname => 'box_lt', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_lt' },
+{ oid => '130',
+ proname => 'box_le', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_le' },
+{ oid => '131',
+ proname => 'point_above', prorettype => 'bool', proargtypes => 'point point',
+ prosrc => 'point_above' },
+{ oid => '132',
+ proname => 'point_left', prorettype => 'bool', proargtypes => 'point point',
+ prosrc => 'point_left' },
+{ oid => '133',
+ proname => 'point_right', prorettype => 'bool', proargtypes => 'point point',
+ prosrc => 'point_right' },
+{ oid => '134',
+ proname => 'point_below', prorettype => 'bool', proargtypes => 'point point',
+ prosrc => 'point_below' },
+{ oid => '135',
+ proname => 'point_eq', prorettype => 'bool', proargtypes => 'point point',
+ prosrc => 'point_eq' },
+{ oid => '136',
+ proname => 'on_pb', prorettype => 'bool', proargtypes => 'point box',
+ prosrc => 'on_pb' },
+{ oid => '137',
+ proname => 'on_ppath', prorettype => 'bool', proargtypes => 'point path',
+ prosrc => 'on_ppath' },
+{ oid => '138',
+ proname => 'box_center', prorettype => 'point', proargtypes => 'box',
+ prosrc => 'box_center' },
+{ oid => '139',
+ descr => 'restriction selectivity for area-comparison operators',
+ proname => 'areasel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'areasel' },
+{ oid => '140', descr => 'join selectivity for area-comparison operators',
+ proname => 'areajoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'areajoinsel' },
+{ oid => '141',
+ proname => 'int4mul', prorettype => 'int4', proargtypes => 'int4 int4',
+ prosrc => 'int4mul' },
+{ oid => '144',
+ proname => 'int4ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int4 int4', prosrc => 'int4ne' },
+{ oid => '145',
+ proname => 'int2ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int2 int2', prosrc => 'int2ne' },
+{ oid => '146',
+ proname => 'int2gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int2 int2', prosrc => 'int2gt' },
+{ oid => '147',
+ proname => 'int4gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int4 int4', prosrc => 'int4gt' },
+{ oid => '148',
+ proname => 'int2le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int2 int2', prosrc => 'int2le' },
+{ oid => '149',
+ proname => 'int4le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int4 int4', prosrc => 'int4le' },
+{ oid => '150',
+ proname => 'int4ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int4 int4', prosrc => 'int4ge' },
+{ oid => '151',
+ proname => 'int2ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int2 int2', prosrc => 'int2ge' },
+{ oid => '152',
+ proname => 'int2mul', prorettype => 'int2', proargtypes => 'int2 int2',
+ prosrc => 'int2mul' },
+{ oid => '153',
+ proname => 'int2div', prorettype => 'int2', proargtypes => 'int2 int2',
+ prosrc => 'int2div' },
+{ oid => '154',
+ proname => 'int4div', prorettype => 'int4', proargtypes => 'int4 int4',
+ prosrc => 'int4div' },
+{ oid => '155',
+ proname => 'int2mod', prorettype => 'int2', proargtypes => 'int2 int2',
+ prosrc => 'int2mod' },
+{ oid => '156',
+ proname => 'int4mod', prorettype => 'int4', proargtypes => 'int4 int4',
+ prosrc => 'int4mod' },
+{ oid => '157',
+ proname => 'textne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'textne' },
+{ oid => '158',
+ proname => 'int24eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int2 int4', prosrc => 'int24eq' },
+{ oid => '159',
+ proname => 'int42eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int4 int2', prosrc => 'int42eq' },
+{ oid => '160',
+ proname => 'int24lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int2 int4', prosrc => 'int24lt' },
+{ oid => '161',
+ proname => 'int42lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int4 int2', prosrc => 'int42lt' },
+{ oid => '162',
+ proname => 'int24gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int2 int4', prosrc => 'int24gt' },
+{ oid => '163',
+ proname => 'int42gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int4 int2', prosrc => 'int42gt' },
+{ oid => '164',
+ proname => 'int24ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int2 int4', prosrc => 'int24ne' },
+{ oid => '165',
+ proname => 'int42ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int4 int2', prosrc => 'int42ne' },
+{ oid => '166',
+ proname => 'int24le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int2 int4', prosrc => 'int24le' },
+{ oid => '167',
+ proname => 'int42le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int4 int2', prosrc => 'int42le' },
+{ oid => '168',
+ proname => 'int24ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int2 int4', prosrc => 'int24ge' },
+{ oid => '169',
+ proname => 'int42ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int4 int2', prosrc => 'int42ge' },
+{ oid => '170',
+ proname => 'int24mul', prorettype => 'int4', proargtypes => 'int2 int4',
+ prosrc => 'int24mul' },
+{ oid => '171',
+ proname => 'int42mul', prorettype => 'int4', proargtypes => 'int4 int2',
+ prosrc => 'int42mul' },
+{ oid => '172',
+ proname => 'int24div', prorettype => 'int4', proargtypes => 'int2 int4',
+ prosrc => 'int24div' },
+{ oid => '173',
+ proname => 'int42div', prorettype => 'int4', proargtypes => 'int4 int2',
+ prosrc => 'int42div' },
+{ oid => '176',
+ proname => 'int2pl', prorettype => 'int2', proargtypes => 'int2 int2',
+ prosrc => 'int2pl' },
+{ oid => '177',
+ proname => 'int4pl', prorettype => 'int4', proargtypes => 'int4 int4',
+ prosrc => 'int4pl' },
+{ oid => '178',
+ proname => 'int24pl', prorettype => 'int4', proargtypes => 'int2 int4',
+ prosrc => 'int24pl' },
+{ oid => '179',
+ proname => 'int42pl', prorettype => 'int4', proargtypes => 'int4 int2',
+ prosrc => 'int42pl' },
+{ oid => '180',
+ proname => 'int2mi', prorettype => 'int2', proargtypes => 'int2 int2',
+ prosrc => 'int2mi' },
+{ oid => '181',
+ proname => 'int4mi', prorettype => 'int4', proargtypes => 'int4 int4',
+ prosrc => 'int4mi' },
+{ oid => '182',
+ proname => 'int24mi', prorettype => 'int4', proargtypes => 'int2 int4',
+ prosrc => 'int24mi' },
+{ oid => '183',
+ proname => 'int42mi', prorettype => 'int4', proargtypes => 'int4 int2',
+ prosrc => 'int42mi' },
+{ oid => '184',
+ proname => 'oideq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'oid oid', prosrc => 'oideq' },
+{ oid => '185',
+ proname => 'oidne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'oid oid', prosrc => 'oidne' },
+{ oid => '186',
+ proname => 'box_same', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_same' },
+{ oid => '187',
+ proname => 'box_contain', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_contain' },
+{ oid => '188',
+ proname => 'box_left', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_left' },
+{ oid => '189',
+ proname => 'box_overleft', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_overleft' },
+{ oid => '190',
+ proname => 'box_overright', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_overright' },
+{ oid => '191',
+ proname => 'box_right', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_right' },
+{ oid => '192',
+ proname => 'box_contained', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_contained' },
+{ oid => '193',
+ proname => 'box_contain_pt', prorettype => 'bool', proargtypes => 'box point',
+ prosrc => 'box_contain_pt' },
+
+{ oid => '195', descr => 'I/O',
+ proname => 'pg_node_tree_in', prorettype => 'pg_node_tree',
+ proargtypes => 'cstring', prosrc => 'pg_node_tree_in' },
+{ oid => '196', descr => 'I/O',
+ proname => 'pg_node_tree_out', prorettype => 'cstring',
+ proargtypes => 'pg_node_tree', prosrc => 'pg_node_tree_out' },
+{ oid => '197', descr => 'I/O',
+ proname => 'pg_node_tree_recv', provolatile => 's',
+ prorettype => 'pg_node_tree', proargtypes => 'internal',
+ prosrc => 'pg_node_tree_recv' },
+{ oid => '198', descr => 'I/O',
+ proname => 'pg_node_tree_send', provolatile => 's', prorettype => 'bytea',
+ proargtypes => 'pg_node_tree', prosrc => 'pg_node_tree_send' },
+
+# OIDS 200 - 299
+
+{ oid => '200', descr => 'I/O',
+ proname => 'float4in', prorettype => 'float4', proargtypes => 'cstring',
+ prosrc => 'float4in' },
+{ oid => '201', descr => 'I/O',
+ proname => 'float4out', prorettype => 'cstring', proargtypes => 'float4',
+ prosrc => 'float4out' },
+{ oid => '202',
+ proname => 'float4mul', prorettype => 'float4',
+ proargtypes => 'float4 float4', prosrc => 'float4mul' },
+{ oid => '203',
+ proname => 'float4div', prorettype => 'float4',
+ proargtypes => 'float4 float4', prosrc => 'float4div' },
+{ oid => '204',
+ proname => 'float4pl', prorettype => 'float4', proargtypes => 'float4 float4',
+ prosrc => 'float4pl' },
+{ oid => '205',
+ proname => 'float4mi', prorettype => 'float4', proargtypes => 'float4 float4',
+ prosrc => 'float4mi' },
+{ oid => '206',
+ proname => 'float4um', prorettype => 'float4', proargtypes => 'float4',
+ prosrc => 'float4um' },
+{ oid => '207',
+ proname => 'float4abs', prorettype => 'float4', proargtypes => 'float4',
+ prosrc => 'float4abs' },
+{ oid => '208', descr => 'aggregate transition function',
+ proname => 'float4_accum', prorettype => '_float8',
+ proargtypes => '_float8 float4', prosrc => 'float4_accum' },
+{ oid => '209', descr => 'larger of two',
+ proname => 'float4larger', prorettype => 'float4',
+ proargtypes => 'float4 float4', prosrc => 'float4larger' },
+{ oid => '211', descr => 'smaller of two',
+ proname => 'float4smaller', prorettype => 'float4',
+ proargtypes => 'float4 float4', prosrc => 'float4smaller' },
+
+{ oid => '212',
+ proname => 'int4um', prorettype => 'int4', proargtypes => 'int4',
+ prosrc => 'int4um' },
+{ oid => '213',
+ proname => 'int2um', prorettype => 'int2', proargtypes => 'int2',
+ prosrc => 'int2um' },
+
+{ oid => '214', descr => 'I/O',
+ proname => 'float8in', prorettype => 'float8', proargtypes => 'cstring',
+ prosrc => 'float8in' },
+{ oid => '215', descr => 'I/O',
+ proname => 'float8out', prorettype => 'cstring', proargtypes => 'float8',
+ prosrc => 'float8out' },
+{ oid => '216',
+ proname => 'float8mul', prorettype => 'float8',
+ proargtypes => 'float8 float8', prosrc => 'float8mul' },
+{ oid => '217',
+ proname => 'float8div', prorettype => 'float8',
+ proargtypes => 'float8 float8', prosrc => 'float8div' },
+{ oid => '218',
+ proname => 'float8pl', prorettype => 'float8', proargtypes => 'float8 float8',
+ prosrc => 'float8pl' },
+{ oid => '219',
+ proname => 'float8mi', prorettype => 'float8', proargtypes => 'float8 float8',
+ prosrc => 'float8mi' },
+{ oid => '220',
+ proname => 'float8um', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'float8um' },
+{ oid => '221',
+ proname => 'float8abs', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'float8abs' },
+{ oid => '222', descr => 'aggregate transition function',
+ proname => 'float8_accum', prorettype => '_float8',
+ proargtypes => '_float8 float8', prosrc => 'float8_accum' },
+{ oid => '276', descr => 'aggregate combine function',
+ proname => 'float8_combine', prorettype => '_float8',
+ proargtypes => '_float8 _float8', prosrc => 'float8_combine' },
+{ oid => '223', descr => 'larger of two',
+ proname => 'float8larger', prorettype => 'float8',
+ proargtypes => 'float8 float8', prosrc => 'float8larger' },
+{ oid => '224', descr => 'smaller of two',
+ proname => 'float8smaller', prorettype => 'float8',
+ proargtypes => 'float8 float8', prosrc => 'float8smaller' },
+
+{ oid => '225',
+ proname => 'lseg_center', prorettype => 'point', proargtypes => 'lseg',
+ prosrc => 'lseg_center' },
+{ oid => '226',
+ proname => 'path_center', prorettype => 'point', proargtypes => 'path',
+ prosrc => 'path_center' },
+{ oid => '227',
+ proname => 'poly_center', prorettype => 'point', proargtypes => 'polygon',
+ prosrc => 'poly_center' },
+
+{ oid => '228', descr => 'round to nearest integer',
+ proname => 'dround', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dround' },
+{ oid => '229', descr => 'truncate to integer',
+ proname => 'dtrunc', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dtrunc' },
+{ oid => '2308', descr => 'nearest integer >= value',
+ proname => 'ceil', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dceil' },
+{ oid => '2320', descr => 'nearest integer >= value',
+ proname => 'ceiling', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dceil' },
+{ oid => '2309', descr => 'nearest integer <= value',
+ proname => 'floor', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dfloor' },
+{ oid => '2310', descr => 'sign of value',
+ proname => 'sign', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dsign' },
+{ oid => '230',
+ proname => 'dsqrt', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dsqrt' },
+{ oid => '231',
+ proname => 'dcbrt', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dcbrt' },
+{ oid => '232',
+ proname => 'dpow', prorettype => 'float8', proargtypes => 'float8 float8',
+ prosrc => 'dpow' },
+{ oid => '233', descr => 'natural exponential (e^x)',
+ proname => 'dexp', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dexp' },
+{ oid => '234', descr => 'natural logarithm',
+ proname => 'dlog1', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dlog1' },
+{ oid => '235', descr => 'convert int2 to float8',
+ proname => 'float8', prorettype => 'float8', proargtypes => 'int2',
+ prosrc => 'i2tod' },
+{ oid => '236', descr => 'convert int2 to float4',
+ proname => 'float4', prorettype => 'float4', proargtypes => 'int2',
+ prosrc => 'i2tof' },
+{ oid => '237', descr => 'convert float8 to int2',
+ proname => 'int2', prorettype => 'int2', proargtypes => 'float8',
+ prosrc => 'dtoi2' },
+{ oid => '238', descr => 'convert float4 to int2',
+ proname => 'int2', prorettype => 'int2', proargtypes => 'float4',
+ prosrc => 'ftoi2' },
+{ oid => '239',
+ proname => 'line_distance', prorettype => 'float8',
+ proargtypes => 'line line', prosrc => 'line_distance' },
+
+{ oid => '240',
+ proname => 'nameeqtext', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'name text', prosrc => 'nameeqtext' },
+{ oid => '241',
+ proname => 'namelttext', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'name text', prosrc => 'namelttext' },
+{ oid => '242',
+ proname => 'nameletext', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'name text', prosrc => 'nameletext' },
+{ oid => '243',
+ proname => 'namegetext', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'name text', prosrc => 'namegetext' },
+{ oid => '244',
+ proname => 'namegttext', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'name text', prosrc => 'namegttext' },
+{ oid => '245',
+ proname => 'namenetext', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'name text', prosrc => 'namenetext' },
+{ oid => '246', descr => 'less-equal-greater',
+ proname => 'btnametextcmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'name text', prosrc => 'btnametextcmp' },
+{ oid => '247',
+ proname => 'texteqname', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'text name', prosrc => 'texteqname' },
+{ oid => '248',
+ proname => 'textltname', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'text name', prosrc => 'textltname' },
+{ oid => '249',
+ proname => 'textlename', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'text name', prosrc => 'textlename' },
+{ oid => '250',
+ proname => 'textgename', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'text name', prosrc => 'textgename' },
+{ oid => '251',
+ proname => 'textgtname', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'text name', prosrc => 'textgtname' },
+{ oid => '252',
+ proname => 'textnename', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'text name', prosrc => 'textnename' },
+{ oid => '253', descr => 'less-equal-greater',
+ proname => 'bttextnamecmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'text name', prosrc => 'bttextnamecmp' },
+
+{ oid => '266', descr => 'concatenate name and oid',
+ proname => 'nameconcatoid', prorettype => 'name', proargtypes => 'name oid',
+ prosrc => 'nameconcatoid' },
+
+{ oid => '274',
+ descr => 'current date and time - increments during transactions',
+ proname => 'timeofday', provolatile => 'v', prorettype => 'text',
+ proargtypes => '', prosrc => 'timeofday' },
+
+{ oid => '277',
+ proname => 'inter_sl', prorettype => 'bool', proargtypes => 'lseg line',
+ prosrc => 'inter_sl' },
+{ oid => '278',
+ proname => 'inter_lb', prorettype => 'bool', proargtypes => 'line box',
+ prosrc => 'inter_lb' },
+
+{ oid => '279',
+ proname => 'float48mul', prorettype => 'float8',
+ proargtypes => 'float4 float8', prosrc => 'float48mul' },
+{ oid => '280',
+ proname => 'float48div', prorettype => 'float8',
+ proargtypes => 'float4 float8', prosrc => 'float48div' },
+{ oid => '281',
+ proname => 'float48pl', prorettype => 'float8',
+ proargtypes => 'float4 float8', prosrc => 'float48pl' },
+{ oid => '282',
+ proname => 'float48mi', prorettype => 'float8',
+ proargtypes => 'float4 float8', prosrc => 'float48mi' },
+{ oid => '283',
+ proname => 'float84mul', prorettype => 'float8',
+ proargtypes => 'float8 float4', prosrc => 'float84mul' },
+{ oid => '284',
+ proname => 'float84div', prorettype => 'float8',
+ proargtypes => 'float8 float4', prosrc => 'float84div' },
+{ oid => '285',
+ proname => 'float84pl', prorettype => 'float8',
+ proargtypes => 'float8 float4', prosrc => 'float84pl' },
+{ oid => '286',
+ proname => 'float84mi', prorettype => 'float8',
+ proargtypes => 'float8 float4', prosrc => 'float84mi' },
+
+{ oid => '287',
+ proname => 'float4eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float4 float4', prosrc => 'float4eq' },
+{ oid => '288',
+ proname => 'float4ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float4 float4', prosrc => 'float4ne' },
+{ oid => '289',
+ proname => 'float4lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float4 float4', prosrc => 'float4lt' },
+{ oid => '290',
+ proname => 'float4le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float4 float4', prosrc => 'float4le' },
+{ oid => '291',
+ proname => 'float4gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float4 float4', prosrc => 'float4gt' },
+{ oid => '292',
+ proname => 'float4ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float4 float4', prosrc => 'float4ge' },
+
+{ oid => '293',
+ proname => 'float8eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float8 float8', prosrc => 'float8eq' },
+{ oid => '294',
+ proname => 'float8ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float8 float8', prosrc => 'float8ne' },
+{ oid => '295',
+ proname => 'float8lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float8 float8', prosrc => 'float8lt' },
+{ oid => '296',
+ proname => 'float8le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float8 float8', prosrc => 'float8le' },
+{ oid => '297',
+ proname => 'float8gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float8 float8', prosrc => 'float8gt' },
+{ oid => '298',
+ proname => 'float8ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float8 float8', prosrc => 'float8ge' },
+
+{ oid => '299',
+ proname => 'float48eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float4 float8', prosrc => 'float48eq' },
+
+# OIDS 300 - 399
+
+{ oid => '300',
+ proname => 'float48ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float4 float8', prosrc => 'float48ne' },
+{ oid => '301',
+ proname => 'float48lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float4 float8', prosrc => 'float48lt' },
+{ oid => '302',
+ proname => 'float48le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float4 float8', prosrc => 'float48le' },
+{ oid => '303',
+ proname => 'float48gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float4 float8', prosrc => 'float48gt' },
+{ oid => '304',
+ proname => 'float48ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float4 float8', prosrc => 'float48ge' },
+{ oid => '305',
+ proname => 'float84eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float8 float4', prosrc => 'float84eq' },
+{ oid => '306',
+ proname => 'float84ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float8 float4', prosrc => 'float84ne' },
+{ oid => '307',
+ proname => 'float84lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float8 float4', prosrc => 'float84lt' },
+{ oid => '308',
+ proname => 'float84le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float8 float4', prosrc => 'float84le' },
+{ oid => '309',
+ proname => 'float84gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float8 float4', prosrc => 'float84gt' },
+{ oid => '310',
+ proname => 'float84ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'float8 float4', prosrc => 'float84ge' },
+{ oid => '320', descr => 'bucket number of operand in equal-width histogram',
+ proname => 'width_bucket', prorettype => 'int4',
+ proargtypes => 'float8 float8 float8 int4', prosrc => 'width_bucket_float8' },
+
+{ oid => '311', descr => 'convert float4 to float8',
+ proname => 'float8', prorettype => 'float8', proargtypes => 'float4',
+ prosrc => 'ftod' },
+{ oid => '312', descr => 'convert float8 to float4',
+ proname => 'float4', prorettype => 'float4', proargtypes => 'float8',
+ prosrc => 'dtof' },
+{ oid => '313', descr => 'convert int2 to int4',
+ proname => 'int4', prorettype => 'int4', proargtypes => 'int2',
+ prosrc => 'i2toi4' },
+{ oid => '314', descr => 'convert int4 to int2',
+ proname => 'int2', prorettype => 'int2', proargtypes => 'int4',
+ prosrc => 'i4toi2' },
+{ oid => '316', descr => 'convert int4 to float8',
+ proname => 'float8', prorettype => 'float8', proargtypes => 'int4',
+ prosrc => 'i4tod' },
+{ oid => '317', descr => 'convert float8 to int4',
+ proname => 'int4', prorettype => 'int4', proargtypes => 'float8',
+ prosrc => 'dtoi4' },
+{ oid => '318', descr => 'convert int4 to float4',
+ proname => 'float4', prorettype => 'float4', proargtypes => 'int4',
+ prosrc => 'i4tof' },
+{ oid => '319', descr => 'convert float4 to int4',
+ proname => 'int4', prorettype => 'int4', proargtypes => 'float4',
+ prosrc => 'ftoi4' },
+
+# Table access method handlers
+{ oid => '3', oid_symbol => 'HEAP_TABLE_AM_HANDLER_OID',
+ descr => 'row-oriented heap table access method handler',
+ proname => 'heap_tableam_handler', provolatile => 'v',
+ prorettype => 'table_am_handler', proargtypes => 'internal',
+ prosrc => 'heap_tableam_handler' },
+
+# Index access method handlers
+{ oid => '330', descr => 'btree index access method handler',
+ proname => 'bthandler', provolatile => 'v', prorettype => 'index_am_handler',
+ proargtypes => 'internal', prosrc => 'bthandler' },
+{ oid => '331', descr => 'hash index access method handler',
+ proname => 'hashhandler', provolatile => 'v',
+ prorettype => 'index_am_handler', proargtypes => 'internal',
+ prosrc => 'hashhandler' },
+{ oid => '332', descr => 'gist index access method handler',
+ proname => 'gisthandler', provolatile => 'v',
+ prorettype => 'index_am_handler', proargtypes => 'internal',
+ prosrc => 'gisthandler' },
+{ oid => '333', descr => 'gin index access method handler',
+ proname => 'ginhandler', provolatile => 'v', prorettype => 'index_am_handler',
+ proargtypes => 'internal', prosrc => 'ginhandler' },
+{ oid => '334', descr => 'spgist index access method handler',
+ proname => 'spghandler', provolatile => 'v', prorettype => 'index_am_handler',
+ proargtypes => 'internal', prosrc => 'spghandler' },
+{ oid => '335', descr => 'brin index access method handler',
+ proname => 'brinhandler', provolatile => 'v',
+ prorettype => 'index_am_handler', proargtypes => 'internal',
+ prosrc => 'brinhandler' },
+{ oid => '3952', descr => 'brin: standalone scan new table pages',
+ proname => 'brin_summarize_new_values', provolatile => 'v',
+ proparallel => 'u', prorettype => 'int4', proargtypes => 'regclass',
+ prosrc => 'brin_summarize_new_values' },
+{ oid => '3999', descr => 'brin: standalone scan new table pages',
+ proname => 'brin_summarize_range', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int4', proargtypes => 'regclass int8',
+ prosrc => 'brin_summarize_range' },
+{ oid => '4014', descr => 'brin: desummarize page range',
+ proname => 'brin_desummarize_range', provolatile => 'v', proparallel => 'u',
+ prorettype => 'void', proargtypes => 'regclass int8',
+ prosrc => 'brin_desummarize_range' },
+
+{ oid => '338', descr => 'validate an operator class',
+ proname => 'amvalidate', provolatile => 'v', prorettype => 'bool',
+ proargtypes => 'oid', prosrc => 'amvalidate' },
+
+{ oid => '636', descr => 'test property of an index access method',
+ proname => 'pg_indexam_has_property', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid text',
+ prosrc => 'pg_indexam_has_property' },
+{ oid => '637', descr => 'test property of an index',
+ proname => 'pg_index_has_property', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'regclass text', prosrc => 'pg_index_has_property' },
+{ oid => '638', descr => 'test property of an index column',
+ proname => 'pg_index_column_has_property', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'regclass int4 text',
+ prosrc => 'pg_index_column_has_property' },
+{ oid => '676', descr => 'return name of given index build phase',
+ proname => 'pg_indexam_progress_phasename', prorettype => 'text',
+ proargtypes => 'oid int8', prosrc => 'pg_indexam_progress_phasename' },
+
+{ oid => '339',
+ proname => 'poly_same', prorettype => 'bool',
+ proargtypes => 'polygon polygon', prosrc => 'poly_same' },
+{ oid => '340',
+ proname => 'poly_contain', prorettype => 'bool',
+ proargtypes => 'polygon polygon', prosrc => 'poly_contain' },
+{ oid => '341',
+ proname => 'poly_left', prorettype => 'bool',
+ proargtypes => 'polygon polygon', prosrc => 'poly_left' },
+{ oid => '342',
+ proname => 'poly_overleft', prorettype => 'bool',
+ proargtypes => 'polygon polygon', prosrc => 'poly_overleft' },
+{ oid => '343',
+ proname => 'poly_overright', prorettype => 'bool',
+ proargtypes => 'polygon polygon', prosrc => 'poly_overright' },
+{ oid => '344',
+ proname => 'poly_right', prorettype => 'bool',
+ proargtypes => 'polygon polygon', prosrc => 'poly_right' },
+{ oid => '345',
+ proname => 'poly_contained', prorettype => 'bool',
+ proargtypes => 'polygon polygon', prosrc => 'poly_contained' },
+{ oid => '346',
+ proname => 'poly_overlap', prorettype => 'bool',
+ proargtypes => 'polygon polygon', prosrc => 'poly_overlap' },
+{ oid => '347', descr => 'I/O',
+ proname => 'poly_in', prorettype => 'polygon', proargtypes => 'cstring',
+ prosrc => 'poly_in' },
+{ oid => '348', descr => 'I/O',
+ proname => 'poly_out', prorettype => 'cstring', proargtypes => 'polygon',
+ prosrc => 'poly_out' },
+
+{ oid => '350', descr => 'less-equal-greater',
+ proname => 'btint2cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'int2 int2', prosrc => 'btint2cmp' },
+{ oid => '3129', descr => 'sort support',
+ proname => 'btint2sortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'btint2sortsupport' },
+{ oid => '351', descr => 'less-equal-greater',
+ proname => 'btint4cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'int4 int4', prosrc => 'btint4cmp' },
+{ oid => '3130', descr => 'sort support',
+ proname => 'btint4sortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'btint4sortsupport' },
+{ oid => '842', descr => 'less-equal-greater',
+ proname => 'btint8cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'int8 int8', prosrc => 'btint8cmp' },
+{ oid => '3131', descr => 'sort support',
+ proname => 'btint8sortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'btint8sortsupport' },
+{ oid => '354', descr => 'less-equal-greater',
+ proname => 'btfloat4cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'float4 float4', prosrc => 'btfloat4cmp' },
+{ oid => '3132', descr => 'sort support',
+ proname => 'btfloat4sortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'btfloat4sortsupport' },
+{ oid => '355', descr => 'less-equal-greater',
+ proname => 'btfloat8cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'float8 float8', prosrc => 'btfloat8cmp' },
+{ oid => '3133', descr => 'sort support',
+ proname => 'btfloat8sortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'btfloat8sortsupport' },
+{ oid => '356', descr => 'less-equal-greater',
+ proname => 'btoidcmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'oid oid', prosrc => 'btoidcmp' },
+{ oid => '3134', descr => 'sort support',
+ proname => 'btoidsortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'btoidsortsupport' },
+{ oid => '404', descr => 'less-equal-greater',
+ proname => 'btoidvectorcmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'oidvector oidvector', prosrc => 'btoidvectorcmp' },
+{ oid => '358', descr => 'less-equal-greater',
+ proname => 'btcharcmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'char char', prosrc => 'btcharcmp' },
+{ oid => '359', descr => 'less-equal-greater',
+ proname => 'btnamecmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'name name', prosrc => 'btnamecmp' },
+{ oid => '3135', descr => 'sort support',
+ proname => 'btnamesortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'btnamesortsupport' },
+{ oid => '360', descr => 'less-equal-greater',
+ proname => 'bttextcmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'text text', prosrc => 'bttextcmp' },
+{ oid => '3255', descr => 'sort support',
+ proname => 'bttextsortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'bttextsortsupport' },
+{ oid => '5050', descr => 'equal image',
+ proname => 'btvarstrequalimage', prorettype => 'bool', proargtypes => 'oid',
+ prosrc => 'btvarstrequalimage' },
+{ oid => '377', descr => 'less-equal-greater',
+ proname => 'cash_cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'money money', prosrc => 'cash_cmp' },
+{ oid => '382', descr => 'less-equal-greater',
+ proname => 'btarraycmp', prorettype => 'int4',
+ proargtypes => 'anyarray anyarray', prosrc => 'btarraycmp' },
+{ oid => '4126', descr => 'window RANGE support',
+ proname => 'in_range', prorettype => 'bool',
+ proargtypes => 'int8 int8 int8 bool bool', prosrc => 'in_range_int8_int8' },
+{ oid => '4127', descr => 'window RANGE support',
+ proname => 'in_range', prorettype => 'bool',
+ proargtypes => 'int4 int4 int8 bool bool', prosrc => 'in_range_int4_int8' },
+{ oid => '4128', descr => 'window RANGE support',
+ proname => 'in_range', prorettype => 'bool',
+ proargtypes => 'int4 int4 int4 bool bool', prosrc => 'in_range_int4_int4' },
+{ oid => '4129', descr => 'window RANGE support',
+ proname => 'in_range', prorettype => 'bool',
+ proargtypes => 'int4 int4 int2 bool bool', prosrc => 'in_range_int4_int2' },
+{ oid => '4130', descr => 'window RANGE support',
+ proname => 'in_range', prorettype => 'bool',
+ proargtypes => 'int2 int2 int8 bool bool', prosrc => 'in_range_int2_int8' },
+{ oid => '4131', descr => 'window RANGE support',
+ proname => 'in_range', prorettype => 'bool',
+ proargtypes => 'int2 int2 int4 bool bool', prosrc => 'in_range_int2_int4' },
+{ oid => '4132', descr => 'window RANGE support',
+ proname => 'in_range', prorettype => 'bool',
+ proargtypes => 'int2 int2 int2 bool bool', prosrc => 'in_range_int2_int2' },
+{ oid => '4139', descr => 'window RANGE support',
+ proname => 'in_range', prorettype => 'bool',
+ proargtypes => 'float8 float8 float8 bool bool',
+ prosrc => 'in_range_float8_float8' },
+{ oid => '4140', descr => 'window RANGE support',
+ proname => 'in_range', prorettype => 'bool',
+ proargtypes => 'float4 float4 float8 bool bool',
+ prosrc => 'in_range_float4_float8' },
+{ oid => '4141', descr => 'window RANGE support',
+ proname => 'in_range', prorettype => 'bool',
+ proargtypes => 'numeric numeric numeric bool bool',
+ prosrc => 'in_range_numeric_numeric' },
+
+{ oid => '361',
+ proname => 'lseg_distance', prorettype => 'float8',
+ proargtypes => 'lseg lseg', prosrc => 'lseg_distance' },
+{ oid => '362',
+ proname => 'lseg_interpt', prorettype => 'point', proargtypes => 'lseg lseg',
+ prosrc => 'lseg_interpt' },
+{ oid => '363',
+ proname => 'dist_ps', prorettype => 'float8', proargtypes => 'point lseg',
+ prosrc => 'dist_ps' },
+{ oid => '380',
+ proname => 'dist_sp', prorettype => 'float8', proargtypes => 'lseg point',
+ prosrc => 'dist_sp' },
+{ oid => '364',
+ proname => 'dist_pb', prorettype => 'float8', proargtypes => 'point box',
+ prosrc => 'dist_pb' },
+{ oid => '357',
+ proname => 'dist_bp', prorettype => 'float8', proargtypes => 'box point',
+ prosrc => 'dist_bp' },
+{ oid => '365',
+ proname => 'dist_sb', prorettype => 'float8', proargtypes => 'lseg box',
+ prosrc => 'dist_sb' },
+{ oid => '381',
+ proname => 'dist_bs', prorettype => 'float8', proargtypes => 'box lseg',
+ prosrc => 'dist_bs' },
+{ oid => '366',
+ proname => 'close_ps', prorettype => 'point', proargtypes => 'point lseg',
+ prosrc => 'close_ps' },
+{ oid => '367',
+ proname => 'close_pb', prorettype => 'point', proargtypes => 'point box',
+ prosrc => 'close_pb' },
+{ oid => '368',
+ proname => 'close_sb', prorettype => 'point', proargtypes => 'lseg box',
+ prosrc => 'close_sb' },
+{ oid => '369',
+ proname => 'on_ps', prorettype => 'bool', proargtypes => 'point lseg',
+ prosrc => 'on_ps' },
+{ oid => '370',
+ proname => 'path_distance', prorettype => 'float8',
+ proargtypes => 'path path', prosrc => 'path_distance' },
+{ oid => '371',
+ proname => 'dist_ppath', prorettype => 'float8', proargtypes => 'point path',
+ prosrc => 'dist_ppath' },
+{ oid => '421',
+ proname => 'dist_pathp', prorettype => 'float8', proargtypes => 'path point',
+ prosrc => 'dist_pathp' },
+{ oid => '372',
+ proname => 'on_sb', prorettype => 'bool', proargtypes => 'lseg box',
+ prosrc => 'on_sb' },
+{ oid => '373',
+ proname => 'inter_sb', prorettype => 'bool', proargtypes => 'lseg box',
+ prosrc => 'inter_sb' },
+
+# OIDS 400 - 499
+
+{ oid => '401', descr => 'convert char(n) to text',
+ proname => 'text', prorettype => 'text', proargtypes => 'bpchar',
+ prosrc => 'rtrim1' },
+{ oid => '406', descr => 'convert name to text',
+ proname => 'text', prorettype => 'text', proargtypes => 'name',
+ prosrc => 'name_text' },
+{ oid => '407', descr => 'convert text to name',
+ proname => 'name', prorettype => 'name', proargtypes => 'text',
+ prosrc => 'text_name' },
+{ oid => '408', descr => 'convert name to char(n)',
+ proname => 'bpchar', prorettype => 'bpchar', proargtypes => 'name',
+ prosrc => 'name_bpchar' },
+{ oid => '409', descr => 'convert char(n) to name',
+ proname => 'name', prorettype => 'name', proargtypes => 'bpchar',
+ prosrc => 'bpchar_name' },
+
+{ oid => '449', descr => 'hash',
+ proname => 'hashint2', prorettype => 'int4', proargtypes => 'int2',
+ prosrc => 'hashint2' },
+{ oid => '441', descr => 'hash',
+ proname => 'hashint2extended', prorettype => 'int8',
+ proargtypes => 'int2 int8', prosrc => 'hashint2extended' },
+{ oid => '450', descr => 'hash',
+ proname => 'hashint4', prorettype => 'int4', proargtypes => 'int4',
+ prosrc => 'hashint4' },
+{ oid => '425', descr => 'hash',
+ proname => 'hashint4extended', prorettype => 'int8',
+ proargtypes => 'int4 int8', prosrc => 'hashint4extended' },
+{ oid => '949', descr => 'hash',
+ proname => 'hashint8', prorettype => 'int4', proargtypes => 'int8',
+ prosrc => 'hashint8' },
+{ oid => '442', descr => 'hash',
+ proname => 'hashint8extended', prorettype => 'int8',
+ proargtypes => 'int8 int8', prosrc => 'hashint8extended' },
+{ oid => '451', descr => 'hash',
+ proname => 'hashfloat4', prorettype => 'int4', proargtypes => 'float4',
+ prosrc => 'hashfloat4' },
+{ oid => '443', descr => 'hash',
+ proname => 'hashfloat4extended', prorettype => 'int8',
+ proargtypes => 'float4 int8', prosrc => 'hashfloat4extended' },
+{ oid => '452', descr => 'hash',
+ proname => 'hashfloat8', prorettype => 'int4', proargtypes => 'float8',
+ prosrc => 'hashfloat8' },
+{ oid => '444', descr => 'hash',
+ proname => 'hashfloat8extended', prorettype => 'int8',
+ proargtypes => 'float8 int8', prosrc => 'hashfloat8extended' },
+{ oid => '453', descr => 'hash',
+ proname => 'hashoid', prorettype => 'int4', proargtypes => 'oid',
+ prosrc => 'hashoid' },
+{ oid => '445', descr => 'hash',
+ proname => 'hashoidextended', prorettype => 'int8', proargtypes => 'oid int8',
+ prosrc => 'hashoidextended' },
+{ oid => '454', descr => 'hash',
+ proname => 'hashchar', prorettype => 'int4', proargtypes => 'char',
+ prosrc => 'hashchar' },
+{ oid => '446', descr => 'hash',
+ proname => 'hashcharextended', prorettype => 'int8',
+ proargtypes => 'char int8', prosrc => 'hashcharextended' },
+{ oid => '455', descr => 'hash',
+ proname => 'hashname', prorettype => 'int4', proargtypes => 'name',
+ prosrc => 'hashname' },
+{ oid => '447', descr => 'hash',
+ proname => 'hashnameextended', prorettype => 'int8',
+ proargtypes => 'name int8', prosrc => 'hashnameextended' },
+{ oid => '400', descr => 'hash',
+ proname => 'hashtext', prorettype => 'int4', proargtypes => 'text',
+ prosrc => 'hashtext' },
+{ oid => '448', descr => 'hash',
+ proname => 'hashtextextended', prorettype => 'int8',
+ proargtypes => 'text int8', prosrc => 'hashtextextended' },
+{ oid => '456', descr => 'hash',
+ proname => 'hashvarlena', prorettype => 'int4', proargtypes => 'internal',
+ prosrc => 'hashvarlena' },
+{ oid => '772', descr => 'hash',
+ proname => 'hashvarlenaextended', prorettype => 'int8',
+ proargtypes => 'internal int8', prosrc => 'hashvarlenaextended' },
+{ oid => '457', descr => 'hash',
+ proname => 'hashoidvector', prorettype => 'int4', proargtypes => 'oidvector',
+ prosrc => 'hashoidvector' },
+{ oid => '776', descr => 'hash',
+ proname => 'hashoidvectorextended', prorettype => 'int8',
+ proargtypes => 'oidvector int8', prosrc => 'hashoidvectorextended' },
+{ oid => '329', descr => 'hash',
+ proname => 'hash_aclitem', prorettype => 'int4', proargtypes => 'aclitem',
+ prosrc => 'hash_aclitem' },
+{ oid => '777', descr => 'hash',
+ proname => 'hash_aclitem_extended', prorettype => 'int8',
+ proargtypes => 'aclitem int8', prosrc => 'hash_aclitem_extended' },
+{ oid => '399', descr => 'hash',
+ proname => 'hashmacaddr', prorettype => 'int4', proargtypes => 'macaddr',
+ prosrc => 'hashmacaddr' },
+{ oid => '778', descr => 'hash',
+ proname => 'hashmacaddrextended', prorettype => 'int8',
+ proargtypes => 'macaddr int8', prosrc => 'hashmacaddrextended' },
+{ oid => '422', descr => 'hash',
+ proname => 'hashinet', prorettype => 'int4', proargtypes => 'inet',
+ prosrc => 'hashinet' },
+{ oid => '779', descr => 'hash',
+ proname => 'hashinetextended', prorettype => 'int8',
+ proargtypes => 'inet int8', prosrc => 'hashinetextended' },
+{ oid => '432', descr => 'hash',
+ proname => 'hash_numeric', prorettype => 'int4', proargtypes => 'numeric',
+ prosrc => 'hash_numeric' },
+{ oid => '780', descr => 'hash',
+ proname => 'hash_numeric_extended', prorettype => 'int8',
+ proargtypes => 'numeric int8', prosrc => 'hash_numeric_extended' },
+{ oid => '328', descr => 'hash',
+ proname => 'hashmacaddr8', prorettype => 'int4', proargtypes => 'macaddr8',
+ prosrc => 'hashmacaddr8' },
+{ oid => '781', descr => 'hash',
+ proname => 'hashmacaddr8extended', prorettype => 'int8',
+ proargtypes => 'macaddr8 int8', prosrc => 'hashmacaddr8extended' },
+
+{ oid => '438', descr => 'count the number of NULL arguments',
+ proname => 'num_nulls', provariadic => 'any', proisstrict => 'f',
+ prorettype => 'int4', proargtypes => 'any', proallargtypes => '{any}',
+ proargmodes => '{v}', prosrc => 'pg_num_nulls' },
+{ oid => '440', descr => 'count the number of non-NULL arguments',
+ proname => 'num_nonnulls', provariadic => 'any', proisstrict => 'f',
+ prorettype => 'int4', proargtypes => 'any', proallargtypes => '{any}',
+ proargmodes => '{v}', prosrc => 'pg_num_nonnulls' },
+
+{ oid => '458', descr => 'larger of two',
+ proname => 'text_larger', proleakproof => 't', prorettype => 'text',
+ proargtypes => 'text text', prosrc => 'text_larger' },
+{ oid => '459', descr => 'smaller of two',
+ proname => 'text_smaller', proleakproof => 't', prorettype => 'text',
+ proargtypes => 'text text', prosrc => 'text_smaller' },
+
+{ oid => '460', descr => 'I/O',
+ proname => 'int8in', prorettype => 'int8', proargtypes => 'cstring',
+ prosrc => 'int8in' },
+{ oid => '461', descr => 'I/O',
+ proname => 'int8out', prorettype => 'cstring', proargtypes => 'int8',
+ prosrc => 'int8out' },
+{ oid => '462',
+ proname => 'int8um', prorettype => 'int8', proargtypes => 'int8',
+ prosrc => 'int8um' },
+{ oid => '463',
+ proname => 'int8pl', prorettype => 'int8', proargtypes => 'int8 int8',
+ prosrc => 'int8pl' },
+{ oid => '464',
+ proname => 'int8mi', prorettype => 'int8', proargtypes => 'int8 int8',
+ prosrc => 'int8mi' },
+{ oid => '465',
+ proname => 'int8mul', prorettype => 'int8', proargtypes => 'int8 int8',
+ prosrc => 'int8mul' },
+{ oid => '466',
+ proname => 'int8div', prorettype => 'int8', proargtypes => 'int8 int8',
+ prosrc => 'int8div' },
+{ oid => '467',
+ proname => 'int8eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int8 int8', prosrc => 'int8eq' },
+{ oid => '468',
+ proname => 'int8ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int8 int8', prosrc => 'int8ne' },
+{ oid => '469',
+ proname => 'int8lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int8 int8', prosrc => 'int8lt' },
+{ oid => '470',
+ proname => 'int8gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int8 int8', prosrc => 'int8gt' },
+{ oid => '471',
+ proname => 'int8le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int8 int8', prosrc => 'int8le' },
+{ oid => '472',
+ proname => 'int8ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int8 int8', prosrc => 'int8ge' },
+
+{ oid => '474',
+ proname => 'int84eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int8 int4', prosrc => 'int84eq' },
+{ oid => '475',
+ proname => 'int84ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int8 int4', prosrc => 'int84ne' },
+{ oid => '476',
+ proname => 'int84lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int8 int4', prosrc => 'int84lt' },
+{ oid => '477',
+ proname => 'int84gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int8 int4', prosrc => 'int84gt' },
+{ oid => '478',
+ proname => 'int84le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int8 int4', prosrc => 'int84le' },
+{ oid => '479',
+ proname => 'int84ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int8 int4', prosrc => 'int84ge' },
+
+{ oid => '480', descr => 'convert int8 to int4',
+ proname => 'int4', prorettype => 'int4', proargtypes => 'int8',
+ prosrc => 'int84' },
+{ oid => '481', descr => 'convert int4 to int8',
+ proname => 'int8', prorettype => 'int8', proargtypes => 'int4',
+ prosrc => 'int48' },
+{ oid => '482', descr => 'convert int8 to float8',
+ proname => 'float8', prorettype => 'float8', proargtypes => 'int8',
+ prosrc => 'i8tod' },
+{ oid => '483', descr => 'convert float8 to int8',
+ proname => 'int8', prorettype => 'int8', proargtypes => 'float8',
+ prosrc => 'dtoi8' },
+
+# OIDS 500 - 599
+
+# OIDS 600 - 699
+
+{ oid => '626', descr => 'hash',
+ proname => 'hash_array', prorettype => 'int4', proargtypes => 'anyarray',
+ prosrc => 'hash_array' },
+{ oid => '782', descr => 'hash',
+ proname => 'hash_array_extended', prorettype => 'int8',
+ proargtypes => 'anyarray int8', prosrc => 'hash_array_extended' },
+
+{ oid => '652', descr => 'convert int8 to float4',
+ proname => 'float4', prorettype => 'float4', proargtypes => 'int8',
+ prosrc => 'i8tof' },
+{ oid => '653', descr => 'convert float4 to int8',
+ proname => 'int8', prorettype => 'int8', proargtypes => 'float4',
+ prosrc => 'ftoi8' },
+
+{ oid => '714', descr => 'convert int8 to int2',
+ proname => 'int2', prorettype => 'int2', proargtypes => 'int8',
+ prosrc => 'int82' },
+{ oid => '754', descr => 'convert int2 to int8',
+ proname => 'int8', prorettype => 'int8', proargtypes => 'int2',
+ prosrc => 'int28' },
+
+{ oid => '655',
+ proname => 'namelt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'name name', prosrc => 'namelt' },
+{ oid => '656',
+ proname => 'namele', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'name name', prosrc => 'namele' },
+{ oid => '657',
+ proname => 'namegt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'name name', prosrc => 'namegt' },
+{ oid => '658',
+ proname => 'namege', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'name name', prosrc => 'namege' },
+{ oid => '659',
+ proname => 'namene', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'name name', prosrc => 'namene' },
+
+{ oid => '668', descr => 'adjust char() to typmod length',
+ proname => 'bpchar', prorettype => 'bpchar',
+ proargtypes => 'bpchar int4 bool', prosrc => 'bpchar' },
+{ oid => '3097', descr => 'planner support for varchar length coercion',
+ proname => 'varchar_support', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'varchar_support' },
+{ oid => '669', descr => 'adjust varchar() to typmod length',
+ proname => 'varchar', prosupport => 'varchar_support',
+ prorettype => 'varchar', proargtypes => 'varchar int4 bool',
+ prosrc => 'varchar' },
+
+{ oid => '619',
+ proname => 'oidvectorne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'oidvector oidvector', prosrc => 'oidvectorne' },
+{ oid => '677',
+ proname => 'oidvectorlt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'oidvector oidvector', prosrc => 'oidvectorlt' },
+{ oid => '678',
+ proname => 'oidvectorle', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'oidvector oidvector', prosrc => 'oidvectorle' },
+{ oid => '679',
+ proname => 'oidvectoreq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'oidvector oidvector', prosrc => 'oidvectoreq' },
+{ oid => '680',
+ proname => 'oidvectorge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'oidvector oidvector', prosrc => 'oidvectorge' },
+{ oid => '681',
+ proname => 'oidvectorgt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'oidvector oidvector', prosrc => 'oidvectorgt' },
+
+# OIDS 700 - 799
+{ oid => '710', descr => 'deprecated, use current_user instead',
+ proname => 'getpgusername', provolatile => 's', prorettype => 'name',
+ proargtypes => '', prosrc => 'current_user' },
+{ oid => '716',
+ proname => 'oidlt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'oid oid', prosrc => 'oidlt' },
+{ oid => '717',
+ proname => 'oidle', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'oid oid', prosrc => 'oidle' },
+
+{ oid => '720', descr => 'octet length',
+ proname => 'octet_length', prorettype => 'int4', proargtypes => 'bytea',
+ prosrc => 'byteaoctetlen' },
+{ oid => '721', descr => 'get byte',
+ proname => 'get_byte', prorettype => 'int4', proargtypes => 'bytea int4',
+ prosrc => 'byteaGetByte' },
+{ oid => '722', descr => 'set byte',
+ proname => 'set_byte', prorettype => 'bytea',
+ proargtypes => 'bytea int4 int4', prosrc => 'byteaSetByte' },
+{ oid => '723', descr => 'get bit',
+ proname => 'get_bit', prorettype => 'int4', proargtypes => 'bytea int8',
+ prosrc => 'byteaGetBit' },
+{ oid => '724', descr => 'set bit',
+ proname => 'set_bit', prorettype => 'bytea', proargtypes => 'bytea int8 int4',
+ prosrc => 'byteaSetBit' },
+{ oid => '749', descr => 'substitute portion of string',
+ proname => 'overlay', prorettype => 'bytea',
+ proargtypes => 'bytea bytea int4 int4', prosrc => 'byteaoverlay' },
+{ oid => '752', descr => 'substitute portion of string',
+ proname => 'overlay', prorettype => 'bytea',
+ proargtypes => 'bytea bytea int4', prosrc => 'byteaoverlay_no_len' },
+
+{ oid => '725',
+ proname => 'dist_pl', prorettype => 'float8', proargtypes => 'point line',
+ prosrc => 'dist_pl' },
+{ oid => '702',
+ proname => 'dist_lp', prorettype => 'float8', proargtypes => 'line point',
+ prosrc => 'dist_lp' },
+{ oid => '726',
+ proname => 'dist_lb', prorettype => 'float8', proargtypes => 'line box',
+ prosrc => 'dist_lb' },
+{ oid => '703',
+ proname => 'dist_bl', prorettype => 'float8', proargtypes => 'box line',
+ prosrc => 'dist_bl' },
+{ oid => '727',
+ proname => 'dist_sl', prorettype => 'float8', proargtypes => 'lseg line',
+ prosrc => 'dist_sl' },
+{ oid => '704',
+ proname => 'dist_ls', prorettype => 'float8', proargtypes => 'line lseg',
+ prosrc => 'dist_ls' },
+
+{ oid => '728',
+ proname => 'dist_cpoly', prorettype => 'float8',
+ proargtypes => 'circle polygon', prosrc => 'dist_cpoly' },
+{ oid => '785',
+ proname => 'dist_polyc', prorettype => 'float8',
+ proargtypes => 'polygon circle', prosrc => 'dist_polyc' },
+{ oid => '729',
+ proname => 'poly_distance', prorettype => 'float8',
+ proargtypes => 'polygon polygon', prosrc => 'poly_distance' },
+{ oid => '3275',
+ proname => 'dist_ppoly', prorettype => 'float8',
+ proargtypes => 'point polygon', prosrc => 'dist_ppoly' },
+{ oid => '3292',
+ proname => 'dist_polyp', prorettype => 'float8',
+ proargtypes => 'polygon point', prosrc => 'dist_polyp' },
+{ oid => '3290',
+ proname => 'dist_cpoint', prorettype => 'float8',
+ proargtypes => 'circle point', prosrc => 'dist_cpoint' },
+
+{ oid => '740',
+ proname => 'text_lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'text_lt' },
+{ oid => '741',
+ proname => 'text_le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'text_le' },
+{ oid => '742',
+ proname => 'text_gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'text_gt' },
+{ oid => '743',
+ proname => 'text_ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'text_ge' },
+
+{ oid => '745', descr => 'current user name',
+ proname => 'current_user', provolatile => 's', prorettype => 'name',
+ proargtypes => '', prosrc => 'current_user' },
+{ oid => '746', descr => 'session user name',
+ proname => 'session_user', provolatile => 's', prorettype => 'name',
+ proargtypes => '', prosrc => 'session_user' },
+
+{ oid => '744',
+ proname => 'array_eq', prorettype => 'bool',
+ proargtypes => 'anyarray anyarray', prosrc => 'array_eq' },
+{ oid => '390',
+ proname => 'array_ne', prorettype => 'bool',
+ proargtypes => 'anyarray anyarray', prosrc => 'array_ne' },
+{ oid => '391',
+ proname => 'array_lt', prorettype => 'bool',
+ proargtypes => 'anyarray anyarray', prosrc => 'array_lt' },
+{ oid => '392',
+ proname => 'array_gt', prorettype => 'bool',
+ proargtypes => 'anyarray anyarray', prosrc => 'array_gt' },
+{ oid => '393',
+ proname => 'array_le', prorettype => 'bool',
+ proargtypes => 'anyarray anyarray', prosrc => 'array_le' },
+{ oid => '396',
+ proname => 'array_ge', prorettype => 'bool',
+ proargtypes => 'anyarray anyarray', prosrc => 'array_ge' },
+{ oid => '747', descr => 'array dimensions',
+ proname => 'array_dims', prorettype => 'text', proargtypes => 'anyarray',
+ prosrc => 'array_dims' },
+{ oid => '748', descr => 'number of array dimensions',
+ proname => 'array_ndims', prorettype => 'int4', proargtypes => 'anyarray',
+ prosrc => 'array_ndims' },
+{ oid => '750', descr => 'I/O',
+ proname => 'array_in', provolatile => 's', prorettype => 'anyarray',
+ proargtypes => 'cstring oid int4', prosrc => 'array_in' },
+{ oid => '751', descr => 'I/O',
+ proname => 'array_out', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'anyarray', prosrc => 'array_out' },
+{ oid => '2091', descr => 'array lower dimension',
+ proname => 'array_lower', prorettype => 'int4',
+ proargtypes => 'anyarray int4', prosrc => 'array_lower' },
+{ oid => '2092', descr => 'array upper dimension',
+ proname => 'array_upper', prorettype => 'int4',
+ proargtypes => 'anyarray int4', prosrc => 'array_upper' },
+{ oid => '2176', descr => 'array length',
+ proname => 'array_length', prorettype => 'int4',
+ proargtypes => 'anyarray int4', prosrc => 'array_length' },
+{ oid => '3179', descr => 'array cardinality',
+ proname => 'cardinality', prorettype => 'int4', proargtypes => 'anyarray',
+ prosrc => 'array_cardinality' },
+{ oid => '378', descr => 'append element onto end of array',
+ proname => 'array_append', proisstrict => 'f', prorettype => 'anyarray',
+ proargtypes => 'anyarray anyelement', prosrc => 'array_append' },
+{ oid => '379', descr => 'prepend element onto front of array',
+ proname => 'array_prepend', proisstrict => 'f', prorettype => 'anyarray',
+ proargtypes => 'anyelement anyarray', prosrc => 'array_prepend' },
+{ oid => '383',
+ proname => 'array_cat', proisstrict => 'f', prorettype => 'anyarray',
+ proargtypes => 'anyarray anyarray', prosrc => 'array_cat' },
+{ oid => '394', descr => 'split delimited text into text[]',
+ proname => 'string_to_array', proisstrict => 'f', prorettype => '_text',
+ proargtypes => 'text text', prosrc => 'text_to_array' },
+{ oid => '395',
+ descr => 'concatenate array elements, using delimiter, into text',
+ proname => 'array_to_string', provolatile => 's', prorettype => 'text',
+ proargtypes => 'anyarray text', prosrc => 'array_to_text' },
+{ oid => '376', descr => 'split delimited text into text[], with null string',
+ proname => 'string_to_array', proisstrict => 'f', prorettype => '_text',
+ proargtypes => 'text text text', prosrc => 'text_to_array_null' },
+{ oid => '384',
+ descr => 'concatenate array elements, using delimiter and null string, into text',
+ proname => 'array_to_string', proisstrict => 'f', provolatile => 's',
+ prorettype => 'text', proargtypes => 'anyarray text text',
+ prosrc => 'array_to_text_null' },
+{ oid => '515', descr => 'larger of two',
+ proname => 'array_larger', prorettype => 'anyarray',
+ proargtypes => 'anyarray anyarray', prosrc => 'array_larger' },
+{ oid => '516', descr => 'smaller of two',
+ proname => 'array_smaller', prorettype => 'anyarray',
+ proargtypes => 'anyarray anyarray', prosrc => 'array_smaller' },
+{ oid => '3277', descr => 'returns an offset of value in array',
+ proname => 'array_position', proisstrict => 'f', prorettype => 'int4',
+ proargtypes => 'anyarray anyelement', prosrc => 'array_position' },
+{ oid => '3278',
+ descr => 'returns an offset of value in array with start index',
+ proname => 'array_position', proisstrict => 'f', prorettype => 'int4',
+ proargtypes => 'anyarray anyelement int4', prosrc => 'array_position_start' },
+{ oid => '3279',
+ descr => 'returns an array of offsets of some value in array',
+ proname => 'array_positions', proisstrict => 'f', prorettype => '_int4',
+ proargtypes => 'anyarray anyelement', prosrc => 'array_positions' },
+{ oid => '1191', descr => 'array subscripts generator',
+ proname => 'generate_subscripts', prorows => '1000', proretset => 't',
+ prorettype => 'int4', proargtypes => 'anyarray int4 bool',
+ prosrc => 'generate_subscripts' },
+{ oid => '1192', descr => 'array subscripts generator',
+ proname => 'generate_subscripts', prorows => '1000', proretset => 't',
+ prorettype => 'int4', proargtypes => 'anyarray int4',
+ prosrc => 'generate_subscripts_nodir' },
+{ oid => '1193', descr => 'array constructor with value',
+ proname => 'array_fill', proisstrict => 'f', prorettype => 'anyarray',
+ proargtypes => 'anyelement _int4', prosrc => 'array_fill' },
+{ oid => '1286', descr => 'array constructor with value',
+ proname => 'array_fill', proisstrict => 'f', prorettype => 'anyarray',
+ proargtypes => 'anyelement _int4 _int4',
+ prosrc => 'array_fill_with_lower_bounds' },
+{ oid => '2331', descr => 'expand array to set of rows',
+ proname => 'unnest', prorows => '100', prosupport => 'array_unnest_support',
+ proretset => 't', prorettype => 'anyelement', proargtypes => 'anyarray',
+ prosrc => 'array_unnest' },
+{ oid => '3996', descr => 'planner support for array_unnest',
+ proname => 'array_unnest_support', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'array_unnest_support' },
+{ oid => '3167',
+ descr => 'remove any occurrences of an element from an array',
+ proname => 'array_remove', proisstrict => 'f', prorettype => 'anyarray',
+ proargtypes => 'anyarray anyelement', prosrc => 'array_remove' },
+{ oid => '3168', descr => 'replace any occurrences of an element in an array',
+ proname => 'array_replace', proisstrict => 'f', prorettype => 'anyarray',
+ proargtypes => 'anyarray anyelement anyelement', prosrc => 'array_replace' },
+{ oid => '2333', descr => 'aggregate transition function',
+ proname => 'array_agg_transfn', proisstrict => 'f', prorettype => 'internal',
+ proargtypes => 'internal anynonarray', prosrc => 'array_agg_transfn' },
+{ oid => '2334', descr => 'aggregate final function',
+ proname => 'array_agg_finalfn', proisstrict => 'f', prorettype => 'anyarray',
+ proargtypes => 'internal anynonarray', prosrc => 'array_agg_finalfn' },
+{ oid => '2335', descr => 'concatenate aggregate input into an array',
+ proname => 'array_agg', prokind => 'a', proisstrict => 'f',
+ prorettype => 'anyarray', proargtypes => 'anynonarray',
+ prosrc => 'aggregate_dummy' },
+{ oid => '4051', descr => 'aggregate transition function',
+ proname => 'array_agg_array_transfn', proisstrict => 'f',
+ prorettype => 'internal', proargtypes => 'internal anyarray',
+ prosrc => 'array_agg_array_transfn' },
+{ oid => '4052', descr => 'aggregate final function',
+ proname => 'array_agg_array_finalfn', proisstrict => 'f',
+ prorettype => 'anyarray', proargtypes => 'internal anyarray',
+ prosrc => 'array_agg_array_finalfn' },
+{ oid => '4053', descr => 'concatenate aggregate input into an array',
+ proname => 'array_agg', prokind => 'a', proisstrict => 'f',
+ prorettype => 'anyarray', proargtypes => 'anyarray',
+ prosrc => 'aggregate_dummy' },
+{ oid => '3218',
+ descr => 'bucket number of operand given a sorted array of bucket lower bounds',
+ proname => 'width_bucket', prorettype => 'int4',
+ proargtypes => 'anyelement anyarray', prosrc => 'width_bucket_array' },
+{ oid => '3816', descr => 'array typanalyze',
+ proname => 'array_typanalyze', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'internal', prosrc => 'array_typanalyze' },
+{ oid => '3817',
+ descr => 'restriction selectivity for array-containment operators',
+ proname => 'arraycontsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'arraycontsel' },
+{ oid => '3818', descr => 'join selectivity for array-containment operators',
+ proname => 'arraycontjoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'arraycontjoinsel' },
+
+{ oid => '764', descr => 'large object import',
+ proname => 'lo_import', provolatile => 'v', proparallel => 'u',
+ prorettype => 'oid', proargtypes => 'text', prosrc => 'be_lo_import' },
+{ oid => '767', descr => 'large object import',
+ proname => 'lo_import', provolatile => 'v', proparallel => 'u',
+ prorettype => 'oid', proargtypes => 'text oid',
+ prosrc => 'be_lo_import_with_oid' },
+{ oid => '765', descr => 'large object export',
+ proname => 'lo_export', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int4', proargtypes => 'oid text', prosrc => 'be_lo_export' },
+
+{ oid => '766', descr => 'increment',
+ proname => 'int4inc', prorettype => 'int4', proargtypes => 'int4',
+ prosrc => 'int4inc' },
+{ oid => '768', descr => 'larger of two',
+ proname => 'int4larger', prorettype => 'int4', proargtypes => 'int4 int4',
+ prosrc => 'int4larger' },
+{ oid => '769', descr => 'smaller of two',
+ proname => 'int4smaller', prorettype => 'int4', proargtypes => 'int4 int4',
+ prosrc => 'int4smaller' },
+{ oid => '770', descr => 'larger of two',
+ proname => 'int2larger', prorettype => 'int2', proargtypes => 'int2 int2',
+ prosrc => 'int2larger' },
+{ oid => '771', descr => 'smaller of two',
+ proname => 'int2smaller', prorettype => 'int2', proargtypes => 'int2 int2',
+ prosrc => 'int2smaller' },
+
+# OIDS 800 - 899
+
+{ oid => '846',
+ proname => 'cash_mul_flt4', prorettype => 'money',
+ proargtypes => 'money float4', prosrc => 'cash_mul_flt4' },
+{ oid => '847',
+ proname => 'cash_div_flt4', prorettype => 'money',
+ proargtypes => 'money float4', prosrc => 'cash_div_flt4' },
+{ oid => '848',
+ proname => 'flt4_mul_cash', prorettype => 'money',
+ proargtypes => 'float4 money', prosrc => 'flt4_mul_cash' },
+
+{ oid => '849', descr => 'position of substring',
+ proname => 'position', prorettype => 'int4', proargtypes => 'text text',
+ prosrc => 'textpos' },
+{ oid => '850',
+ proname => 'textlike', prosupport => 'textlike_support', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'textlike' },
+{ oid => '1023', descr => 'planner support for textlike',
+ proname => 'textlike_support', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'textlike_support' },
+{ oid => '851',
+ proname => 'textnlike', prorettype => 'bool', proargtypes => 'text text',
+ prosrc => 'textnlike' },
+
+{ oid => '852',
+ proname => 'int48eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int4 int8', prosrc => 'int48eq' },
+{ oid => '853',
+ proname => 'int48ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int4 int8', prosrc => 'int48ne' },
+{ oid => '854',
+ proname => 'int48lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int4 int8', prosrc => 'int48lt' },
+{ oid => '855',
+ proname => 'int48gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int4 int8', prosrc => 'int48gt' },
+{ oid => '856',
+ proname => 'int48le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int4 int8', prosrc => 'int48le' },
+{ oid => '857',
+ proname => 'int48ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int4 int8', prosrc => 'int48ge' },
+
+{ oid => '858',
+ proname => 'namelike', prosupport => 'textlike_support', prorettype => 'bool',
+ proargtypes => 'name text', prosrc => 'namelike' },
+{ oid => '859',
+ proname => 'namenlike', prorettype => 'bool', proargtypes => 'name text',
+ prosrc => 'namenlike' },
+
+{ oid => '860', descr => 'convert char to char(n)',
+ proname => 'bpchar', prorettype => 'bpchar', proargtypes => 'char',
+ prosrc => 'char_bpchar' },
+
+{ oid => '861', descr => 'name of the current database',
+ proname => 'current_database', provolatile => 's', prorettype => 'name',
+ proargtypes => '', prosrc => 'current_database' },
+{ oid => '817', descr => 'get the currently executing query',
+ proname => 'current_query', proisstrict => 'f', provolatile => 'v',
+ proparallel => 'r', prorettype => 'text', proargtypes => '',
+ prosrc => 'current_query' },
+
+{ oid => '3399',
+ proname => 'int8_mul_cash', prorettype => 'money',
+ proargtypes => 'int8 money', prosrc => 'int8_mul_cash' },
+{ oid => '862',
+ proname => 'int4_mul_cash', prorettype => 'money',
+ proargtypes => 'int4 money', prosrc => 'int4_mul_cash' },
+{ oid => '863',
+ proname => 'int2_mul_cash', prorettype => 'money',
+ proargtypes => 'int2 money', prosrc => 'int2_mul_cash' },
+{ oid => '3344',
+ proname => 'cash_mul_int8', prorettype => 'money',
+ proargtypes => 'money int8', prosrc => 'cash_mul_int8' },
+{ oid => '3345',
+ proname => 'cash_div_int8', prorettype => 'money',
+ proargtypes => 'money int8', prosrc => 'cash_div_int8' },
+{ oid => '864',
+ proname => 'cash_mul_int4', prorettype => 'money',
+ proargtypes => 'money int4', prosrc => 'cash_mul_int4' },
+{ oid => '865',
+ proname => 'cash_div_int4', prorettype => 'money',
+ proargtypes => 'money int4', prosrc => 'cash_div_int4' },
+{ oid => '866',
+ proname => 'cash_mul_int2', prorettype => 'money',
+ proargtypes => 'money int2', prosrc => 'cash_mul_int2' },
+{ oid => '867',
+ proname => 'cash_div_int2', prorettype => 'money',
+ proargtypes => 'money int2', prosrc => 'cash_div_int2' },
+
+{ oid => '886', descr => 'I/O',
+ proname => 'cash_in', provolatile => 's', prorettype => 'money',
+ proargtypes => 'cstring', prosrc => 'cash_in' },
+{ oid => '887', descr => 'I/O',
+ proname => 'cash_out', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'money', prosrc => 'cash_out' },
+{ oid => '888',
+ proname => 'cash_eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'money money', prosrc => 'cash_eq' },
+{ oid => '889',
+ proname => 'cash_ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'money money', prosrc => 'cash_ne' },
+{ oid => '890',
+ proname => 'cash_lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'money money', prosrc => 'cash_lt' },
+{ oid => '891',
+ proname => 'cash_le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'money money', prosrc => 'cash_le' },
+{ oid => '892',
+ proname => 'cash_gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'money money', prosrc => 'cash_gt' },
+{ oid => '893',
+ proname => 'cash_ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'money money', prosrc => 'cash_ge' },
+{ oid => '894',
+ proname => 'cash_pl', prorettype => 'money', proargtypes => 'money money',
+ prosrc => 'cash_pl' },
+{ oid => '895',
+ proname => 'cash_mi', prorettype => 'money', proargtypes => 'money money',
+ prosrc => 'cash_mi' },
+{ oid => '896',
+ proname => 'cash_mul_flt8', prorettype => 'money',
+ proargtypes => 'money float8', prosrc => 'cash_mul_flt8' },
+{ oid => '897',
+ proname => 'cash_div_flt8', prorettype => 'money',
+ proargtypes => 'money float8', prosrc => 'cash_div_flt8' },
+{ oid => '898', descr => 'larger of two',
+ proname => 'cashlarger', prorettype => 'money', proargtypes => 'money money',
+ prosrc => 'cashlarger' },
+{ oid => '899', descr => 'smaller of two',
+ proname => 'cashsmaller', prorettype => 'money', proargtypes => 'money money',
+ prosrc => 'cashsmaller' },
+{ oid => '919',
+ proname => 'flt8_mul_cash', prorettype => 'money',
+ proargtypes => 'float8 money', prosrc => 'flt8_mul_cash' },
+{ oid => '935', descr => 'output money amount as words',
+ proname => 'cash_words', prorettype => 'text', proargtypes => 'money',
+ prosrc => 'cash_words' },
+{ oid => '3822',
+ proname => 'cash_div_cash', prorettype => 'float8',
+ proargtypes => 'money money', prosrc => 'cash_div_cash' },
+{ oid => '3823', descr => 'convert money to numeric',
+ proname => 'numeric', provolatile => 's', prorettype => 'numeric',
+ proargtypes => 'money', prosrc => 'cash_numeric' },
+{ oid => '3824', descr => 'convert numeric to money',
+ proname => 'money', provolatile => 's', prorettype => 'money',
+ proargtypes => 'numeric', prosrc => 'numeric_cash' },
+{ oid => '3811', descr => 'convert int4 to money',
+ proname => 'money', provolatile => 's', prorettype => 'money',
+ proargtypes => 'int4', prosrc => 'int4_cash' },
+{ oid => '3812', descr => 'convert int8 to money',
+ proname => 'money', provolatile => 's', prorettype => 'money',
+ proargtypes => 'int8', prosrc => 'int8_cash' },
+
+# OIDS 900 - 999
+
+{ oid => '940', descr => 'modulus',
+ proname => 'mod', prorettype => 'int2', proargtypes => 'int2 int2',
+ prosrc => 'int2mod' },
+{ oid => '941', descr => 'modulus',
+ proname => 'mod', prorettype => 'int4', proargtypes => 'int4 int4',
+ prosrc => 'int4mod' },
+
+{ oid => '945',
+ proname => 'int8mod', prorettype => 'int8', proargtypes => 'int8 int8',
+ prosrc => 'int8mod' },
+{ oid => '947', descr => 'modulus',
+ proname => 'mod', prorettype => 'int8', proargtypes => 'int8 int8',
+ prosrc => 'int8mod' },
+
+{ oid => '5044', descr => 'greatest common divisor',
+ proname => 'gcd', prorettype => 'int4', proargtypes => 'int4 int4',
+ prosrc => 'int4gcd' },
+{ oid => '5045', descr => 'greatest common divisor',
+ proname => 'gcd', prorettype => 'int8', proargtypes => 'int8 int8',
+ prosrc => 'int8gcd' },
+
+{ oid => '5046', descr => 'least common multiple',
+ proname => 'lcm', prorettype => 'int4', proargtypes => 'int4 int4',
+ prosrc => 'int4lcm' },
+{ oid => '5047', descr => 'least common multiple',
+ proname => 'lcm', prorettype => 'int8', proargtypes => 'int8 int8',
+ prosrc => 'int8lcm' },
+
+{ oid => '944', descr => 'convert text to char',
+ proname => 'char', prorettype => 'char', proargtypes => 'text',
+ prosrc => 'text_char' },
+{ oid => '946', descr => 'convert char to text',
+ proname => 'text', prorettype => 'text', proargtypes => 'char',
+ prosrc => 'char_text' },
+
+{ oid => '952', descr => 'large object open',
+ proname => 'lo_open', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int4', proargtypes => 'oid int4', prosrc => 'be_lo_open' },
+{ oid => '953', descr => 'large object close',
+ proname => 'lo_close', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int4', proargtypes => 'int4', prosrc => 'be_lo_close' },
+{ oid => '954', descr => 'large object read',
+ proname => 'loread', provolatile => 'v', proparallel => 'u',
+ prorettype => 'bytea', proargtypes => 'int4 int4', prosrc => 'be_loread' },
+{ oid => '955', descr => 'large object write',
+ proname => 'lowrite', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int4', proargtypes => 'int4 bytea', prosrc => 'be_lowrite' },
+{ oid => '956', descr => 'large object seek',
+ proname => 'lo_lseek', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int4', proargtypes => 'int4 int4 int4',
+ prosrc => 'be_lo_lseek' },
+{ oid => '3170', descr => 'large object seek (64 bit)',
+ proname => 'lo_lseek64', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int8', proargtypes => 'int4 int8 int4',
+ prosrc => 'be_lo_lseek64' },
+{ oid => '957', descr => 'large object create',
+ proname => 'lo_creat', provolatile => 'v', proparallel => 'u',
+ prorettype => 'oid', proargtypes => 'int4', prosrc => 'be_lo_creat' },
+{ oid => '715', descr => 'large object create',
+ proname => 'lo_create', provolatile => 'v', proparallel => 'u',
+ prorettype => 'oid', proargtypes => 'oid', prosrc => 'be_lo_create' },
+{ oid => '958', descr => 'large object position',
+ proname => 'lo_tell', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int4', proargtypes => 'int4', prosrc => 'be_lo_tell' },
+{ oid => '3171', descr => 'large object position (64 bit)',
+ proname => 'lo_tell64', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int8', proargtypes => 'int4', prosrc => 'be_lo_tell64' },
+{ oid => '1004', descr => 'truncate large object',
+ proname => 'lo_truncate', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int4', proargtypes => 'int4 int4',
+ prosrc => 'be_lo_truncate' },
+{ oid => '3172', descr => 'truncate large object (64 bit)',
+ proname => 'lo_truncate64', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int4', proargtypes => 'int4 int8',
+ prosrc => 'be_lo_truncate64' },
+
+{ oid => '3457', descr => 'create new large object with given content',
+ proname => 'lo_from_bytea', provolatile => 'v', proparallel => 'u',
+ prorettype => 'oid', proargtypes => 'oid bytea',
+ prosrc => 'be_lo_from_bytea' },
+{ oid => '3458', descr => 'read entire large object',
+ proname => 'lo_get', provolatile => 'v', proparallel => 'u',
+ prorettype => 'bytea', proargtypes => 'oid', prosrc => 'be_lo_get' },
+{ oid => '3459', descr => 'read large object from offset for length',
+ proname => 'lo_get', provolatile => 'v', proparallel => 'u',
+ prorettype => 'bytea', proargtypes => 'oid int8 int4',
+ prosrc => 'be_lo_get_fragment' },
+{ oid => '3460', descr => 'write data at offset',
+ proname => 'lo_put', provolatile => 'v', proparallel => 'u',
+ prorettype => 'void', proargtypes => 'oid int8 bytea',
+ prosrc => 'be_lo_put' },
+
+{ oid => '959',
+ proname => 'on_pl', prorettype => 'bool', proargtypes => 'point line',
+ prosrc => 'on_pl' },
+{ oid => '960',
+ proname => 'on_sl', prorettype => 'bool', proargtypes => 'lseg line',
+ prosrc => 'on_sl' },
+{ oid => '961',
+ proname => 'close_pl', prorettype => 'point', proargtypes => 'point line',
+ prosrc => 'close_pl' },
+{ oid => '962',
+ proname => 'close_sl', prorettype => 'point', proargtypes => 'lseg line',
+ prosrc => 'close_sl' },
+{ oid => '963',
+ proname => 'close_lb', prorettype => 'point', proargtypes => 'line box',
+ prosrc => 'close_lb' },
+
+{ oid => '964', descr => 'large object unlink (delete)',
+ proname => 'lo_unlink', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int4', proargtypes => 'oid', prosrc => 'be_lo_unlink' },
+
+{ oid => '973',
+ proname => 'path_inter', prorettype => 'bool', proargtypes => 'path path',
+ prosrc => 'path_inter' },
+{ oid => '975', descr => 'box area',
+ proname => 'area', prorettype => 'float8', proargtypes => 'box',
+ prosrc => 'box_area' },
+{ oid => '976', descr => 'box width',
+ proname => 'width', prorettype => 'float8', proargtypes => 'box',
+ prosrc => 'box_width' },
+{ oid => '977', descr => 'box height',
+ proname => 'height', prorettype => 'float8', proargtypes => 'box',
+ prosrc => 'box_height' },
+{ oid => '978',
+ proname => 'box_distance', prorettype => 'float8', proargtypes => 'box box',
+ prosrc => 'box_distance' },
+{ oid => '979', descr => 'area of a closed path',
+ proname => 'area', prorettype => 'float8', proargtypes => 'path',
+ prosrc => 'path_area' },
+{ oid => '980',
+ proname => 'box_intersect', prorettype => 'box', proargtypes => 'box box',
+ prosrc => 'box_intersect' },
+{ oid => '4067', descr => 'bounding box of two boxes',
+ proname => 'bound_box', prorettype => 'box', proargtypes => 'box box',
+ prosrc => 'boxes_bound_box' },
+{ oid => '981', descr => 'box diagonal',
+ proname => 'diagonal', prorettype => 'lseg', proargtypes => 'box',
+ prosrc => 'box_diagonal' },
+{ oid => '982',
+ proname => 'path_n_lt', prorettype => 'bool', proargtypes => 'path path',
+ prosrc => 'path_n_lt' },
+{ oid => '983',
+ proname => 'path_n_gt', prorettype => 'bool', proargtypes => 'path path',
+ prosrc => 'path_n_gt' },
+{ oid => '984',
+ proname => 'path_n_eq', prorettype => 'bool', proargtypes => 'path path',
+ prosrc => 'path_n_eq' },
+{ oid => '985',
+ proname => 'path_n_le', prorettype => 'bool', proargtypes => 'path path',
+ prosrc => 'path_n_le' },
+{ oid => '986',
+ proname => 'path_n_ge', prorettype => 'bool', proargtypes => 'path path',
+ prosrc => 'path_n_ge' },
+{ oid => '987',
+ proname => 'path_length', prorettype => 'float8', proargtypes => 'path',
+ prosrc => 'path_length' },
+{ oid => '988',
+ proname => 'point_ne', prorettype => 'bool', proargtypes => 'point point',
+ prosrc => 'point_ne' },
+{ oid => '989',
+ proname => 'point_vert', prorettype => 'bool', proargtypes => 'point point',
+ prosrc => 'point_vert' },
+{ oid => '990',
+ proname => 'point_horiz', prorettype => 'bool', proargtypes => 'point point',
+ prosrc => 'point_horiz' },
+{ oid => '991',
+ proname => 'point_distance', prorettype => 'float8',
+ proargtypes => 'point point', prosrc => 'point_distance' },
+{ oid => '992', descr => 'slope between points',
+ proname => 'slope', prorettype => 'float8', proargtypes => 'point point',
+ prosrc => 'point_slope' },
+{ oid => '993', descr => 'convert points to line segment',
+ proname => 'lseg', prorettype => 'lseg', proargtypes => 'point point',
+ prosrc => 'lseg_construct' },
+{ oid => '994',
+ proname => 'lseg_intersect', prorettype => 'bool', proargtypes => 'lseg lseg',
+ prosrc => 'lseg_intersect' },
+{ oid => '995',
+ proname => 'lseg_parallel', prorettype => 'bool', proargtypes => 'lseg lseg',
+ prosrc => 'lseg_parallel' },
+{ oid => '996',
+ proname => 'lseg_perp', prorettype => 'bool', proargtypes => 'lseg lseg',
+ prosrc => 'lseg_perp' },
+{ oid => '997',
+ proname => 'lseg_vertical', prorettype => 'bool', proargtypes => 'lseg',
+ prosrc => 'lseg_vertical' },
+{ oid => '998',
+ proname => 'lseg_horizontal', prorettype => 'bool', proargtypes => 'lseg',
+ prosrc => 'lseg_horizontal' },
+{ oid => '999',
+ proname => 'lseg_eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'lseg lseg', prosrc => 'lseg_eq' },
+
+# OIDS 1000 - 1999
+
+{ oid => '1026', descr => 'adjust timestamp to new time zone',
+ proname => 'timezone', prorettype => 'timestamp',
+ proargtypes => 'interval timestamptz', prosrc => 'timestamptz_izone' },
+
+{ oid => '1031', descr => 'I/O',
+ proname => 'aclitemin', provolatile => 's', prorettype => 'aclitem',
+ proargtypes => 'cstring', prosrc => 'aclitemin' },
+{ oid => '1032', descr => 'I/O',
+ proname => 'aclitemout', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'aclitem', prosrc => 'aclitemout' },
+{ oid => '1035', descr => 'add/update ACL item',
+ proname => 'aclinsert', prorettype => '_aclitem',
+ proargtypes => '_aclitem aclitem', prosrc => 'aclinsert' },
+{ oid => '1036', descr => 'remove ACL item',
+ proname => 'aclremove', prorettype => '_aclitem',
+ proargtypes => '_aclitem aclitem', prosrc => 'aclremove' },
+{ oid => '1037', descr => 'contains',
+ proname => 'aclcontains', prorettype => 'bool',
+ proargtypes => '_aclitem aclitem', prosrc => 'aclcontains' },
+{ oid => '1062',
+ proname => 'aclitemeq', prorettype => 'bool',
+ proargtypes => 'aclitem aclitem', prosrc => 'aclitem_eq' },
+{ oid => '1365', descr => 'make ACL item',
+ proname => 'makeaclitem', prorettype => 'aclitem',
+ proargtypes => 'oid oid text bool', prosrc => 'makeaclitem' },
+{ oid => '3943',
+ descr => 'show hardwired default privileges, primarily for use by the information schema',
+ proname => 'acldefault', prorettype => '_aclitem', proargtypes => 'char oid',
+ prosrc => 'acldefault_sql' },
+{ oid => '1689',
+ descr => 'convert ACL item array to table, primarily for use by information schema',
+ proname => 'aclexplode', prorows => '10', proretset => 't',
+ provolatile => 's', prorettype => 'record', proargtypes => '_aclitem',
+ proallargtypes => '{_aclitem,oid,oid,text,bool}',
+ proargmodes => '{i,o,o,o,o}',
+ proargnames => '{acl,grantor,grantee,privilege_type,is_grantable}',
+ prosrc => 'aclexplode' },
+{ oid => '1044', descr => 'I/O',
+ proname => 'bpcharin', prorettype => 'bpchar',
+ proargtypes => 'cstring oid int4', prosrc => 'bpcharin' },
+{ oid => '1045', descr => 'I/O',
+ proname => 'bpcharout', prorettype => 'cstring', proargtypes => 'bpchar',
+ prosrc => 'bpcharout' },
+{ oid => '2913', descr => 'I/O typmod',
+ proname => 'bpchartypmodin', prorettype => 'int4', proargtypes => '_cstring',
+ prosrc => 'bpchartypmodin' },
+{ oid => '2914', descr => 'I/O typmod',
+ proname => 'bpchartypmodout', prorettype => 'cstring', proargtypes => 'int4',
+ prosrc => 'bpchartypmodout' },
+{ oid => '1046', descr => 'I/O',
+ proname => 'varcharin', prorettype => 'varchar',
+ proargtypes => 'cstring oid int4', prosrc => 'varcharin' },
+{ oid => '1047', descr => 'I/O',
+ proname => 'varcharout', prorettype => 'cstring', proargtypes => 'varchar',
+ prosrc => 'varcharout' },
+{ oid => '2915', descr => 'I/O typmod',
+ proname => 'varchartypmodin', prorettype => 'int4', proargtypes => '_cstring',
+ prosrc => 'varchartypmodin' },
+{ oid => '2916', descr => 'I/O typmod',
+ proname => 'varchartypmodout', prorettype => 'cstring', proargtypes => 'int4',
+ prosrc => 'varchartypmodout' },
+{ oid => '1048',
+ proname => 'bpchareq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bpchar bpchar', prosrc => 'bpchareq' },
+{ oid => '1049',
+ proname => 'bpcharlt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bpchar bpchar', prosrc => 'bpcharlt' },
+{ oid => '1050',
+ proname => 'bpcharle', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bpchar bpchar', prosrc => 'bpcharle' },
+{ oid => '1051',
+ proname => 'bpchargt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bpchar bpchar', prosrc => 'bpchargt' },
+{ oid => '1052',
+ proname => 'bpcharge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bpchar bpchar', prosrc => 'bpcharge' },
+{ oid => '1053',
+ proname => 'bpcharne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bpchar bpchar', prosrc => 'bpcharne' },
+{ oid => '1063', descr => 'larger of two',
+ proname => 'bpchar_larger', proleakproof => 't', prorettype => 'bpchar',
+ proargtypes => 'bpchar bpchar', prosrc => 'bpchar_larger' },
+{ oid => '1064', descr => 'smaller of two',
+ proname => 'bpchar_smaller', proleakproof => 't', prorettype => 'bpchar',
+ proargtypes => 'bpchar bpchar', prosrc => 'bpchar_smaller' },
+{ oid => '1078', descr => 'less-equal-greater',
+ proname => 'bpcharcmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'bpchar bpchar', prosrc => 'bpcharcmp' },
+{ oid => '3328', descr => 'sort support',
+ proname => 'bpchar_sortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'bpchar_sortsupport' },
+{ oid => '1080', descr => 'hash',
+ proname => 'hashbpchar', prorettype => 'int4', proargtypes => 'bpchar',
+ prosrc => 'hashbpchar' },
+{ oid => '972', descr => 'hash',
+ proname => 'hashbpcharextended', prorettype => 'int8',
+ proargtypes => 'bpchar int8', prosrc => 'hashbpcharextended' },
+{ oid => '1081', descr => 'format a type oid and atttypmod to canonical SQL',
+ proname => 'format_type', proisstrict => 'f', provolatile => 's',
+ prorettype => 'text', proargtypes => 'oid int4', prosrc => 'format_type' },
+{ oid => '1084', descr => 'I/O',
+ proname => 'date_in', provolatile => 's', prorettype => 'date',
+ proargtypes => 'cstring', prosrc => 'date_in' },
+{ oid => '1085', descr => 'I/O',
+ proname => 'date_out', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'date', prosrc => 'date_out' },
+{ oid => '1086',
+ proname => 'date_eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'date date', prosrc => 'date_eq' },
+{ oid => '1087',
+ proname => 'date_lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'date date', prosrc => 'date_lt' },
+{ oid => '1088',
+ proname => 'date_le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'date date', prosrc => 'date_le' },
+{ oid => '1089',
+ proname => 'date_gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'date date', prosrc => 'date_gt' },
+{ oid => '1090',
+ proname => 'date_ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'date date', prosrc => 'date_ge' },
+{ oid => '1091',
+ proname => 'date_ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'date date', prosrc => 'date_ne' },
+{ oid => '1092', descr => 'less-equal-greater',
+ proname => 'date_cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'date date', prosrc => 'date_cmp' },
+{ oid => '3136', descr => 'sort support',
+ proname => 'date_sortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'date_sortsupport' },
+{ oid => '4133', descr => 'window RANGE support',
+ proname => 'in_range', prorettype => 'bool',
+ proargtypes => 'date date interval bool bool',
+ prosrc => 'in_range_date_interval' },
+
+# OIDS 1100 - 1199
+
+{ oid => '1102',
+ proname => 'time_lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'time time', prosrc => 'time_lt' },
+{ oid => '1103',
+ proname => 'time_le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'time time', prosrc => 'time_le' },
+{ oid => '1104',
+ proname => 'time_gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'time time', prosrc => 'time_gt' },
+{ oid => '1105',
+ proname => 'time_ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'time time', prosrc => 'time_ge' },
+{ oid => '1106',
+ proname => 'time_ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'time time', prosrc => 'time_ne' },
+{ oid => '1107', descr => 'less-equal-greater',
+ proname => 'time_cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'time time', prosrc => 'time_cmp' },
+{ oid => '1138', descr => 'larger of two',
+ proname => 'date_larger', prorettype => 'date', proargtypes => 'date date',
+ prosrc => 'date_larger' },
+{ oid => '1139', descr => 'smaller of two',
+ proname => 'date_smaller', prorettype => 'date', proargtypes => 'date date',
+ prosrc => 'date_smaller' },
+{ oid => '1140',
+ proname => 'date_mi', prorettype => 'int4', proargtypes => 'date date',
+ prosrc => 'date_mi' },
+{ oid => '1141',
+ proname => 'date_pli', prorettype => 'date', proargtypes => 'date int4',
+ prosrc => 'date_pli' },
+{ oid => '1142',
+ proname => 'date_mii', prorettype => 'date', proargtypes => 'date int4',
+ prosrc => 'date_mii' },
+{ oid => '1143', descr => 'I/O',
+ proname => 'time_in', provolatile => 's', prorettype => 'time',
+ proargtypes => 'cstring oid int4', prosrc => 'time_in' },
+{ oid => '1144', descr => 'I/O',
+ proname => 'time_out', prorettype => 'cstring', proargtypes => 'time',
+ prosrc => 'time_out' },
+{ oid => '2909', descr => 'I/O typmod',
+ proname => 'timetypmodin', prorettype => 'int4', proargtypes => '_cstring',
+ prosrc => 'timetypmodin' },
+{ oid => '2910', descr => 'I/O typmod',
+ proname => 'timetypmodout', prorettype => 'cstring', proargtypes => 'int4',
+ prosrc => 'timetypmodout' },
+{ oid => '1145',
+ proname => 'time_eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'time time', prosrc => 'time_eq' },
+
+{ oid => '1146',
+ proname => 'circle_add_pt', prorettype => 'circle',
+ proargtypes => 'circle point', prosrc => 'circle_add_pt' },
+{ oid => '1147',
+ proname => 'circle_sub_pt', prorettype => 'circle',
+ proargtypes => 'circle point', prosrc => 'circle_sub_pt' },
+{ oid => '1148',
+ proname => 'circle_mul_pt', prorettype => 'circle',
+ proargtypes => 'circle point', prosrc => 'circle_mul_pt' },
+{ oid => '1149',
+ proname => 'circle_div_pt', prorettype => 'circle',
+ proargtypes => 'circle point', prosrc => 'circle_div_pt' },
+
+{ oid => '1150', descr => 'I/O',
+ proname => 'timestamptz_in', provolatile => 's', prorettype => 'timestamptz',
+ proargtypes => 'cstring oid int4', prosrc => 'timestamptz_in' },
+{ oid => '1151', descr => 'I/O',
+ proname => 'timestamptz_out', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'timestamptz', prosrc => 'timestamptz_out' },
+{ oid => '2907', descr => 'I/O typmod',
+ proname => 'timestamptztypmodin', prorettype => 'int4',
+ proargtypes => '_cstring', prosrc => 'timestamptztypmodin' },
+{ oid => '2908', descr => 'I/O typmod',
+ proname => 'timestamptztypmodout', prorettype => 'cstring',
+ proargtypes => 'int4', prosrc => 'timestamptztypmodout' },
+{ oid => '1152',
+ proname => 'timestamptz_eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'timestamptz timestamptz', prosrc => 'timestamp_eq' },
+{ oid => '1153',
+ proname => 'timestamptz_ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'timestamptz timestamptz', prosrc => 'timestamp_ne' },
+{ oid => '1154',
+ proname => 'timestamptz_lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'timestamptz timestamptz', prosrc => 'timestamp_lt' },
+{ oid => '1155',
+ proname => 'timestamptz_le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'timestamptz timestamptz', prosrc => 'timestamp_le' },
+{ oid => '1156',
+ proname => 'timestamptz_ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'timestamptz timestamptz', prosrc => 'timestamp_ge' },
+{ oid => '1157',
+ proname => 'timestamptz_gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'timestamptz timestamptz', prosrc => 'timestamp_gt' },
+{ oid => '1158', descr => 'convert UNIX epoch to timestamptz',
+ proname => 'to_timestamp', prorettype => 'timestamptz',
+ proargtypes => 'float8', prosrc => 'float8_timestamptz' },
+{ oid => '1159', descr => 'adjust timestamp to new time zone',
+ proname => 'timezone', prorettype => 'timestamp',
+ proargtypes => 'text timestamptz', prosrc => 'timestamptz_zone' },
+
+{ oid => '1160', descr => 'I/O',
+ proname => 'interval_in', provolatile => 's', prorettype => 'interval',
+ proargtypes => 'cstring oid int4', prosrc => 'interval_in' },
+{ oid => '1161', descr => 'I/O',
+ proname => 'interval_out', prorettype => 'cstring', proargtypes => 'interval',
+ prosrc => 'interval_out' },
+{ oid => '2903', descr => 'I/O typmod',
+ proname => 'intervaltypmodin', prorettype => 'int4',
+ proargtypes => '_cstring', prosrc => 'intervaltypmodin' },
+{ oid => '2904', descr => 'I/O typmod',
+ proname => 'intervaltypmodout', prorettype => 'cstring',
+ proargtypes => 'int4', prosrc => 'intervaltypmodout' },
+{ oid => '1162',
+ proname => 'interval_eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'interval interval', prosrc => 'interval_eq' },
+{ oid => '1163',
+ proname => 'interval_ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'interval interval', prosrc => 'interval_ne' },
+{ oid => '1164',
+ proname => 'interval_lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'interval interval', prosrc => 'interval_lt' },
+{ oid => '1165',
+ proname => 'interval_le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'interval interval', prosrc => 'interval_le' },
+{ oid => '1166',
+ proname => 'interval_ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'interval interval', prosrc => 'interval_ge' },
+{ oid => '1167',
+ proname => 'interval_gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'interval interval', prosrc => 'interval_gt' },
+{ oid => '1168',
+ proname => 'interval_um', prorettype => 'interval', proargtypes => 'interval',
+ prosrc => 'interval_um' },
+{ oid => '1169',
+ proname => 'interval_pl', prorettype => 'interval',
+ proargtypes => 'interval interval', prosrc => 'interval_pl' },
+{ oid => '1170',
+ proname => 'interval_mi', prorettype => 'interval',
+ proargtypes => 'interval interval', prosrc => 'interval_mi' },
+{ oid => '1171', descr => 'extract field from timestamp with time zone',
+ proname => 'date_part', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'text timestamptz', prosrc => 'timestamptz_part' },
+{ oid => '1172', descr => 'extract field from interval',
+ proname => 'date_part', prorettype => 'float8',
+ proargtypes => 'text interval', prosrc => 'interval_part' },
+{ oid => '1174', descr => 'convert date to timestamp with time zone',
+ proname => 'timestamptz', provolatile => 's', prorettype => 'timestamptz',
+ proargtypes => 'date', prosrc => 'date_timestamptz' },
+{ oid => '2711',
+ descr => 'promote groups of 24 hours to numbers of days and promote groups of 30 days to numbers of months',
+ proname => 'justify_interval', prorettype => 'interval',
+ proargtypes => 'interval', prosrc => 'interval_justify_interval' },
+{ oid => '1175', descr => 'promote groups of 24 hours to numbers of days',
+ proname => 'justify_hours', prorettype => 'interval',
+ proargtypes => 'interval', prosrc => 'interval_justify_hours' },
+{ oid => '1295', descr => 'promote groups of 30 days to numbers of months',
+ proname => 'justify_days', prorettype => 'interval',
+ proargtypes => 'interval', prosrc => 'interval_justify_days' },
+{ oid => '1176', descr => 'convert date and time to timestamp with time zone',
+ proname => 'timestamptz', prolang => 'sql', provolatile => 's',
+ prorettype => 'timestamptz', proargtypes => 'date time',
+ prosrc => 'select cast(($1 + $2) as timestamp with time zone)' },
+{ oid => '1178', descr => 'convert timestamp with time zone to date',
+ proname => 'date', provolatile => 's', prorettype => 'date',
+ proargtypes => 'timestamptz', prosrc => 'timestamptz_date' },
+{ oid => '1181',
+ descr => 'age of a transaction ID, in transactions before current transaction',
+ proname => 'age', provolatile => 's', proparallel => 'r',
+ prorettype => 'int4', proargtypes => 'xid', prosrc => 'xid_age' },
+{ oid => '3939',
+ descr => 'age of a multi-transaction ID, in multi-transactions before current multi-transaction',
+ proname => 'mxid_age', provolatile => 's', prorettype => 'int4',
+ proargtypes => 'xid', prosrc => 'mxid_age' },
+
+{ oid => '1188',
+ proname => 'timestamptz_mi', prorettype => 'interval',
+ proargtypes => 'timestamptz timestamptz', prosrc => 'timestamp_mi' },
+{ oid => '1189',
+ proname => 'timestamptz_pl_interval', provolatile => 's',
+ prorettype => 'timestamptz', proargtypes => 'timestamptz interval',
+ prosrc => 'timestamptz_pl_interval' },
+{ oid => '1190',
+ proname => 'timestamptz_mi_interval', provolatile => 's',
+ prorettype => 'timestamptz', proargtypes => 'timestamptz interval',
+ prosrc => 'timestamptz_mi_interval' },
+{ oid => '1195', descr => 'smaller of two',
+ proname => 'timestamptz_smaller', prorettype => 'timestamptz',
+ proargtypes => 'timestamptz timestamptz', prosrc => 'timestamp_smaller' },
+{ oid => '1196', descr => 'larger of two',
+ proname => 'timestamptz_larger', prorettype => 'timestamptz',
+ proargtypes => 'timestamptz timestamptz', prosrc => 'timestamp_larger' },
+{ oid => '1197', descr => 'smaller of two',
+ proname => 'interval_smaller', prorettype => 'interval',
+ proargtypes => 'interval interval', prosrc => 'interval_smaller' },
+{ oid => '1198', descr => 'larger of two',
+ proname => 'interval_larger', prorettype => 'interval',
+ proargtypes => 'interval interval', prosrc => 'interval_larger' },
+{ oid => '1199', descr => 'date difference preserving months and years',
+ proname => 'age', prorettype => 'interval',
+ proargtypes => 'timestamptz timestamptz', prosrc => 'timestamptz_age' },
+
+# OIDS 1200 - 1299
+
+{ oid => '3918', descr => 'planner support for interval length coercion',
+ proname => 'interval_support', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'interval_support' },
+{ oid => '1200', descr => 'adjust interval precision',
+ proname => 'interval', prosupport => 'interval_support',
+ prorettype => 'interval', proargtypes => 'interval int4',
+ prosrc => 'interval_scale' },
+
+{ oid => '1215', descr => 'get description for object id and catalog name',
+ proname => 'obj_description', prolang => 'sql', procost => '100',
+ provolatile => 's', prorettype => 'text', proargtypes => 'oid name',
+ prosrc => 'select description from pg_catalog.pg_description where objoid = $1 and classoid = (select oid from pg_catalog.pg_class where relname = $2 and relnamespace = PGNSP) and objsubid = 0' },
+{ oid => '1216', descr => 'get description for table column',
+ proname => 'col_description', prolang => 'sql', procost => '100',
+ provolatile => 's', prorettype => 'text', proargtypes => 'oid int4',
+ prosrc => 'select description from pg_catalog.pg_description where objoid = $1 and classoid = \'pg_catalog.pg_class\'::pg_catalog.regclass and objsubid = $2' },
+{ oid => '1993',
+ descr => 'get description for object id and shared catalog name',
+ proname => 'shobj_description', prolang => 'sql', procost => '100',
+ provolatile => 's', prorettype => 'text', proargtypes => 'oid name',
+ prosrc => 'select description from pg_catalog.pg_shdescription where objoid = $1 and classoid = (select oid from pg_catalog.pg_class where relname = $2 and relnamespace = PGNSP)' },
+
+{ oid => '1217',
+ descr => 'truncate timestamp with time zone to specified units',
+ proname => 'date_trunc', provolatile => 's', prorettype => 'timestamptz',
+ proargtypes => 'text timestamptz', prosrc => 'timestamptz_trunc' },
+{ oid => '1284',
+ descr => 'truncate timestamp with time zone to specified units in specified time zone',
+ proname => 'date_trunc', provolatile => 's', prorettype => 'timestamptz',
+ proargtypes => 'text timestamptz text', prosrc => 'timestamptz_trunc_zone' },
+{ oid => '1218', descr => 'truncate interval to specified units',
+ proname => 'date_trunc', prorettype => 'interval',
+ proargtypes => 'text interval', prosrc => 'interval_trunc' },
+
+{ oid => '1219', descr => 'increment',
+ proname => 'int8inc', prorettype => 'int8', proargtypes => 'int8',
+ prosrc => 'int8inc' },
+{ oid => '3546', descr => 'decrement',
+ proname => 'int8dec', prorettype => 'int8', proargtypes => 'int8',
+ prosrc => 'int8dec' },
+{ oid => '2804', descr => 'increment, ignores second argument',
+ proname => 'int8inc_any', prorettype => 'int8', proargtypes => 'int8 any',
+ prosrc => 'int8inc_any' },
+{ oid => '3547', descr => 'decrement, ignores second argument',
+ proname => 'int8dec_any', prorettype => 'int8', proargtypes => 'int8 any',
+ prosrc => 'int8dec_any' },
+{ oid => '1230',
+ proname => 'int8abs', prorettype => 'int8', proargtypes => 'int8',
+ prosrc => 'int8abs' },
+
+{ oid => '1236', descr => 'larger of two',
+ proname => 'int8larger', prorettype => 'int8', proargtypes => 'int8 int8',
+ prosrc => 'int8larger' },
+{ oid => '1237', descr => 'smaller of two',
+ proname => 'int8smaller', prorettype => 'int8', proargtypes => 'int8 int8',
+ prosrc => 'int8smaller' },
+
+{ oid => '1238',
+ proname => 'texticregexeq', prosupport => 'texticregexeq_support',
+ prorettype => 'bool', proargtypes => 'text text', prosrc => 'texticregexeq' },
+{ oid => '1024', descr => 'planner support for texticregexeq',
+ proname => 'texticregexeq_support', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'texticregexeq_support' },
+{ oid => '1239',
+ proname => 'texticregexne', prorettype => 'bool', proargtypes => 'text text',
+ prosrc => 'texticregexne' },
+{ oid => '1240',
+ proname => 'nameicregexeq', prosupport => 'texticregexeq_support',
+ prorettype => 'bool', proargtypes => 'name text', prosrc => 'nameicregexeq' },
+{ oid => '1241',
+ proname => 'nameicregexne', prorettype => 'bool', proargtypes => 'name text',
+ prosrc => 'nameicregexne' },
+
+{ oid => '1251',
+ proname => 'int4abs', prorettype => 'int4', proargtypes => 'int4',
+ prosrc => 'int4abs' },
+{ oid => '1253',
+ proname => 'int2abs', prorettype => 'int2', proargtypes => 'int2',
+ prosrc => 'int2abs' },
+
+{ oid => '1271', descr => 'intervals overlap?',
+ proname => 'overlaps', proisstrict => 'f', prorettype => 'bool',
+ proargtypes => 'timetz timetz timetz timetz', prosrc => 'overlaps_timetz' },
+{ oid => '1272',
+ proname => 'datetime_pl', prorettype => 'timestamp',
+ proargtypes => 'date time', prosrc => 'datetime_timestamp' },
+{ oid => '1273', descr => 'extract field from time with time zone',
+ proname => 'date_part', prorettype => 'float8', proargtypes => 'text timetz',
+ prosrc => 'timetz_part' },
+{ oid => '1274',
+ proname => 'int84pl', prorettype => 'int8', proargtypes => 'int8 int4',
+ prosrc => 'int84pl' },
+{ oid => '1275',
+ proname => 'int84mi', prorettype => 'int8', proargtypes => 'int8 int4',
+ prosrc => 'int84mi' },
+{ oid => '1276',
+ proname => 'int84mul', prorettype => 'int8', proargtypes => 'int8 int4',
+ prosrc => 'int84mul' },
+{ oid => '1277',
+ proname => 'int84div', prorettype => 'int8', proargtypes => 'int8 int4',
+ prosrc => 'int84div' },
+{ oid => '1278',
+ proname => 'int48pl', prorettype => 'int8', proargtypes => 'int4 int8',
+ prosrc => 'int48pl' },
+{ oid => '1279',
+ proname => 'int48mi', prorettype => 'int8', proargtypes => 'int4 int8',
+ prosrc => 'int48mi' },
+{ oid => '1280',
+ proname => 'int48mul', prorettype => 'int8', proargtypes => 'int4 int8',
+ prosrc => 'int48mul' },
+{ oid => '1281',
+ proname => 'int48div', prorettype => 'int8', proargtypes => 'int4 int8',
+ prosrc => 'int48div' },
+
+{ oid => '837',
+ proname => 'int82pl', prorettype => 'int8', proargtypes => 'int8 int2',
+ prosrc => 'int82pl' },
+{ oid => '838',
+ proname => 'int82mi', prorettype => 'int8', proargtypes => 'int8 int2',
+ prosrc => 'int82mi' },
+{ oid => '839',
+ proname => 'int82mul', prorettype => 'int8', proargtypes => 'int8 int2',
+ prosrc => 'int82mul' },
+{ oid => '840',
+ proname => 'int82div', prorettype => 'int8', proargtypes => 'int8 int2',
+ prosrc => 'int82div' },
+{ oid => '841',
+ proname => 'int28pl', prorettype => 'int8', proargtypes => 'int2 int8',
+ prosrc => 'int28pl' },
+{ oid => '942',
+ proname => 'int28mi', prorettype => 'int8', proargtypes => 'int2 int8',
+ prosrc => 'int28mi' },
+{ oid => '943',
+ proname => 'int28mul', prorettype => 'int8', proargtypes => 'int2 int8',
+ prosrc => 'int28mul' },
+{ oid => '948',
+ proname => 'int28div', prorettype => 'int8', proargtypes => 'int2 int8',
+ prosrc => 'int28div' },
+
+{ oid => '1287', descr => 'convert int8 to oid',
+ proname => 'oid', prorettype => 'oid', proargtypes => 'int8',
+ prosrc => 'i8tooid' },
+{ oid => '1288', descr => 'convert oid to int8',
+ proname => 'int8', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'oidtoi8' },
+
+{ oid => '1291',
+ descr => 'trigger to suppress updates when new and old records match',
+ proname => 'suppress_redundant_updates_trigger', provolatile => 'v',
+ prorettype => 'trigger', proargtypes => '',
+ prosrc => 'suppress_redundant_updates_trigger' },
+
+{ oid => '1292',
+ proname => 'tideq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'tid tid', prosrc => 'tideq' },
+{ oid => '1293', descr => 'latest tid of a tuple',
+ proname => 'currtid', provolatile => 'v', proparallel => 'u',
+ prorettype => 'tid', proargtypes => 'oid tid', prosrc => 'currtid_byreloid' },
+{ oid => '1294', descr => 'latest tid of a tuple',
+ proname => 'currtid2', provolatile => 'v', proparallel => 'u',
+ prorettype => 'tid', proargtypes => 'text tid',
+ prosrc => 'currtid_byrelname' },
+{ oid => '1265',
+ proname => 'tidne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'tid tid', prosrc => 'tidne' },
+{ oid => '2790',
+ proname => 'tidgt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'tid tid', prosrc => 'tidgt' },
+{ oid => '2791',
+ proname => 'tidlt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'tid tid', prosrc => 'tidlt' },
+{ oid => '2792',
+ proname => 'tidge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'tid tid', prosrc => 'tidge' },
+{ oid => '2793',
+ proname => 'tidle', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'tid tid', prosrc => 'tidle' },
+{ oid => '2794', descr => 'less-equal-greater',
+ proname => 'bttidcmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'tid tid', prosrc => 'bttidcmp' },
+{ oid => '2795', descr => 'larger of two',
+ proname => 'tidlarger', prorettype => 'tid', proargtypes => 'tid tid',
+ prosrc => 'tidlarger' },
+{ oid => '2796', descr => 'smaller of two',
+ proname => 'tidsmaller', prorettype => 'tid', proargtypes => 'tid tid',
+ prosrc => 'tidsmaller' },
+{ oid => '2233', descr => 'hash',
+ proname => 'hashtid', prorettype => 'int4', proargtypes => 'tid',
+ prosrc => 'hashtid' },
+{ oid => '2234', descr => 'hash',
+ proname => 'hashtidextended', prorettype => 'int8', proargtypes => 'tid int8',
+ prosrc => 'hashtidextended' },
+
+{ oid => '1296',
+ proname => 'timedate_pl', prolang => 'sql', prorettype => 'timestamp',
+ proargtypes => 'time date', prosrc => 'select ($2 + $1)' },
+{ oid => '1297',
+ proname => 'datetimetz_pl', prorettype => 'timestamptz',
+ proargtypes => 'date timetz', prosrc => 'datetimetz_timestamptz' },
+{ oid => '1298',
+ proname => 'timetzdate_pl', prolang => 'sql', prorettype => 'timestamptz',
+ proargtypes => 'timetz date', prosrc => 'select ($2 + $1)' },
+{ oid => '1299', descr => 'current transaction time',
+ proname => 'now', provolatile => 's', prorettype => 'timestamptz',
+ proargtypes => '', prosrc => 'now' },
+{ oid => '2647', descr => 'current transaction time',
+ proname => 'transaction_timestamp', provolatile => 's',
+ prorettype => 'timestamptz', proargtypes => '', prosrc => 'now' },
+{ oid => '2648', descr => 'current statement time',
+ proname => 'statement_timestamp', provolatile => 's',
+ prorettype => 'timestamptz', proargtypes => '',
+ prosrc => 'statement_timestamp' },
+{ oid => '2649', descr => 'current clock time',
+ proname => 'clock_timestamp', provolatile => 'v', prorettype => 'timestamptz',
+ proargtypes => '', prosrc => 'clock_timestamp' },
+
+# OIDS 1300 - 1399
+
+{ oid => '1300',
+ descr => 'restriction selectivity for position-comparison operators',
+ proname => 'positionsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'positionsel' },
+{ oid => '1301',
+ descr => 'join selectivity for position-comparison operators',
+ proname => 'positionjoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'positionjoinsel' },
+{ oid => '1302',
+ descr => 'restriction selectivity for containment comparison operators',
+ proname => 'contsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'contsel' },
+{ oid => '1303',
+ descr => 'join selectivity for containment comparison operators',
+ proname => 'contjoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'contjoinsel' },
+
+{ oid => '1304', descr => 'intervals overlap?',
+ proname => 'overlaps', proisstrict => 'f', prorettype => 'bool',
+ proargtypes => 'timestamptz timestamptz timestamptz timestamptz',
+ prosrc => 'overlaps_timestamp' },
+{ oid => '1305', descr => 'intervals overlap?',
+ proname => 'overlaps', prolang => 'sql', proisstrict => 'f',
+ provolatile => 's', prorettype => 'bool',
+ proargtypes => 'timestamptz interval timestamptz interval',
+ prosrc => 'select ($1, ($1 + $2)) overlaps ($3, ($3 + $4))' },
+{ oid => '1306', descr => 'intervals overlap?',
+ proname => 'overlaps', prolang => 'sql', proisstrict => 'f',
+ provolatile => 's', prorettype => 'bool',
+ proargtypes => 'timestamptz timestamptz timestamptz interval',
+ prosrc => 'select ($1, $2) overlaps ($3, ($3 + $4))' },
+{ oid => '1307', descr => 'intervals overlap?',
+ proname => 'overlaps', prolang => 'sql', proisstrict => 'f',
+ provolatile => 's', prorettype => 'bool',
+ proargtypes => 'timestamptz interval timestamptz timestamptz',
+ prosrc => 'select ($1, ($1 + $2)) overlaps ($3, $4)' },
+
+{ oid => '1308', descr => 'intervals overlap?',
+ proname => 'overlaps', proisstrict => 'f', prorettype => 'bool',
+ proargtypes => 'time time time time', prosrc => 'overlaps_time' },
+{ oid => '1309', descr => 'intervals overlap?',
+ proname => 'overlaps', prolang => 'sql', proisstrict => 'f',
+ prorettype => 'bool', proargtypes => 'time interval time interval',
+ prosrc => 'select ($1, ($1 + $2)) overlaps ($3, ($3 + $4))' },
+{ oid => '1310', descr => 'intervals overlap?',
+ proname => 'overlaps', prolang => 'sql', proisstrict => 'f',
+ prorettype => 'bool', proargtypes => 'time time time interval',
+ prosrc => 'select ($1, $2) overlaps ($3, ($3 + $4))' },
+{ oid => '1311', descr => 'intervals overlap?',
+ proname => 'overlaps', prolang => 'sql', proisstrict => 'f',
+ prorettype => 'bool', proargtypes => 'time interval time time',
+ prosrc => 'select ($1, ($1 + $2)) overlaps ($3, $4)' },
+
+{ oid => '1312', descr => 'I/O',
+ proname => 'timestamp_in', provolatile => 's', prorettype => 'timestamp',
+ proargtypes => 'cstring oid int4', prosrc => 'timestamp_in' },
+{ oid => '1313', descr => 'I/O',
+ proname => 'timestamp_out', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'timestamp', prosrc => 'timestamp_out' },
+{ oid => '2905', descr => 'I/O typmod',
+ proname => 'timestamptypmodin', prorettype => 'int4',
+ proargtypes => '_cstring', prosrc => 'timestamptypmodin' },
+{ oid => '2906', descr => 'I/O typmod',
+ proname => 'timestamptypmodout', prorettype => 'cstring',
+ proargtypes => 'int4', prosrc => 'timestamptypmodout' },
+{ oid => '1314', descr => 'less-equal-greater',
+ proname => 'timestamptz_cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'timestamptz timestamptz', prosrc => 'timestamp_cmp' },
+{ oid => '1315', descr => 'less-equal-greater',
+ proname => 'interval_cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'interval interval', prosrc => 'interval_cmp' },
+{ oid => '1316', descr => 'convert timestamp to time',
+ proname => 'time', prorettype => 'time', proargtypes => 'timestamp',
+ prosrc => 'timestamp_time' },
+
+{ oid => '1317', descr => 'length',
+ proname => 'length', prorettype => 'int4', proargtypes => 'text',
+ prosrc => 'textlen' },
+{ oid => '1318', descr => 'character length',
+ proname => 'length', prorettype => 'int4', proargtypes => 'bpchar',
+ prosrc => 'bpcharlen' },
+
+{ oid => '1319',
+ proname => 'xideqint4', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'xid int4', prosrc => 'xideq' },
+{ oid => '3309',
+ proname => 'xidneqint4', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'xid int4', prosrc => 'xidneq' },
+
+{ oid => '1326',
+ proname => 'interval_div', prorettype => 'interval',
+ proargtypes => 'interval float8', prosrc => 'interval_div' },
+
+{ oid => '1339', descr => 'base 10 logarithm',
+ proname => 'dlog10', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dlog10' },
+{ oid => '1340', descr => 'base 10 logarithm',
+ proname => 'log', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dlog10' },
+{ oid => '1194', descr => 'base 10 logarithm',
+ proname => 'log10', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dlog10' },
+{ oid => '1341', descr => 'natural logarithm',
+ proname => 'ln', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dlog1' },
+{ oid => '1342', descr => 'round to nearest integer',
+ proname => 'round', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dround' },
+{ oid => '1343', descr => 'truncate to integer',
+ proname => 'trunc', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dtrunc' },
+{ oid => '1344', descr => 'square root',
+ proname => 'sqrt', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dsqrt' },
+{ oid => '1345', descr => 'cube root',
+ proname => 'cbrt', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dcbrt' },
+{ oid => '1346', descr => 'exponentiation',
+ proname => 'pow', prorettype => 'float8', proargtypes => 'float8 float8',
+ prosrc => 'dpow' },
+{ oid => '1368', descr => 'exponentiation',
+ proname => 'power', prorettype => 'float8', proargtypes => 'float8 float8',
+ prosrc => 'dpow' },
+{ oid => '1347', descr => 'natural exponential (e^x)',
+ proname => 'exp', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dexp' },
+
+# This form of obj_description is now deprecated, since it will fail if
+# OIDs are not unique across system catalogs. Use the other form instead.
+{ oid => '1348', descr => 'deprecated, use two-argument form instead',
+ proname => 'obj_description', prolang => 'sql', procost => '100',
+ provolatile => 's', prorettype => 'text', proargtypes => 'oid',
+ prosrc => 'select description from pg_catalog.pg_description where objoid = $1 and objsubid = 0' },
+
+{ oid => '1349', descr => 'print type names of oidvector field',
+ proname => 'oidvectortypes', provolatile => 's', prorettype => 'text',
+ proargtypes => 'oidvector', prosrc => 'oidvectortypes' },
+
+{ oid => '1350', descr => 'I/O',
+ proname => 'timetz_in', provolatile => 's', prorettype => 'timetz',
+ proargtypes => 'cstring oid int4', prosrc => 'timetz_in' },
+{ oid => '1351', descr => 'I/O',
+ proname => 'timetz_out', prorettype => 'cstring', proargtypes => 'timetz',
+ prosrc => 'timetz_out' },
+{ oid => '2911', descr => 'I/O typmod',
+ proname => 'timetztypmodin', prorettype => 'int4', proargtypes => '_cstring',
+ prosrc => 'timetztypmodin' },
+{ oid => '2912', descr => 'I/O typmod',
+ proname => 'timetztypmodout', prorettype => 'cstring', proargtypes => 'int4',
+ prosrc => 'timetztypmodout' },
+{ oid => '1352',
+ proname => 'timetz_eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'timetz timetz', prosrc => 'timetz_eq' },
+{ oid => '1353',
+ proname => 'timetz_ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'timetz timetz', prosrc => 'timetz_ne' },
+{ oid => '1354',
+ proname => 'timetz_lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'timetz timetz', prosrc => 'timetz_lt' },
+{ oid => '1355',
+ proname => 'timetz_le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'timetz timetz', prosrc => 'timetz_le' },
+{ oid => '1356',
+ proname => 'timetz_ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'timetz timetz', prosrc => 'timetz_ge' },
+{ oid => '1357',
+ proname => 'timetz_gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'timetz timetz', prosrc => 'timetz_gt' },
+{ oid => '1358', descr => 'less-equal-greater',
+ proname => 'timetz_cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'timetz timetz', prosrc => 'timetz_cmp' },
+{ oid => '1359',
+ descr => 'convert date and time with time zone to timestamp with time zone',
+ proname => 'timestamptz', prorettype => 'timestamptz',
+ proargtypes => 'date timetz', prosrc => 'datetimetz_timestamptz' },
+
+{ oid => '1367', descr => 'character length',
+ proname => 'character_length', prorettype => 'int4', proargtypes => 'bpchar',
+ prosrc => 'bpcharlen' },
+{ oid => '1369', descr => 'character length',
+ proname => 'character_length', prorettype => 'int4', proargtypes => 'text',
+ prosrc => 'textlen' },
+
+{ oid => '1370', descr => 'convert time to interval',
+ proname => 'interval', prorettype => 'interval', proargtypes => 'time',
+ prosrc => 'time_interval' },
+{ oid => '1372', descr => 'character length',
+ proname => 'char_length', prorettype => 'int4', proargtypes => 'bpchar',
+ prosrc => 'bpcharlen' },
+{ oid => '1374', descr => 'octet length',
+ proname => 'octet_length', prorettype => 'int4', proargtypes => 'text',
+ prosrc => 'textoctetlen' },
+{ oid => '1375', descr => 'octet length',
+ proname => 'octet_length', prorettype => 'int4', proargtypes => 'bpchar',
+ prosrc => 'bpcharoctetlen' },
+
+{ oid => '1377', descr => 'larger of two',
+ proname => 'time_larger', prorettype => 'time', proargtypes => 'time time',
+ prosrc => 'time_larger' },
+{ oid => '1378', descr => 'smaller of two',
+ proname => 'time_smaller', prorettype => 'time', proargtypes => 'time time',
+ prosrc => 'time_smaller' },
+{ oid => '1379', descr => 'larger of two',
+ proname => 'timetz_larger', prorettype => 'timetz',
+ proargtypes => 'timetz timetz', prosrc => 'timetz_larger' },
+{ oid => '1380', descr => 'smaller of two',
+ proname => 'timetz_smaller', prorettype => 'timetz',
+ proargtypes => 'timetz timetz', prosrc => 'timetz_smaller' },
+
+{ oid => '1381', descr => 'character length',
+ proname => 'char_length', prorettype => 'int4', proargtypes => 'text',
+ prosrc => 'textlen' },
+
+{ oid => '1384', descr => 'extract field from date',
+ proname => 'date_part', prolang => 'sql', prorettype => 'float8',
+ proargtypes => 'text date',
+ prosrc => 'select pg_catalog.date_part($1, cast($2 as timestamp without time zone))' },
+{ oid => '1385', descr => 'extract field from time',
+ proname => 'date_part', prorettype => 'float8', proargtypes => 'text time',
+ prosrc => 'time_part' },
+{ oid => '1386',
+ descr => 'date difference from today preserving months and years',
+ proname => 'age', prolang => 'sql', provolatile => 's',
+ prorettype => 'interval', proargtypes => 'timestamptz',
+ prosrc => 'select pg_catalog.age(cast(current_date as timestamp with time zone), $1)' },
+
+{ oid => '1388',
+ descr => 'convert timestamp with time zone to time with time zone',
+ proname => 'timetz', provolatile => 's', prorettype => 'timetz',
+ proargtypes => 'timestamptz', prosrc => 'timestamptz_timetz' },
+
+{ oid => '1373', descr => 'finite date?',
+ proname => 'isfinite', prorettype => 'bool', proargtypes => 'date',
+ prosrc => 'date_finite' },
+{ oid => '1389', descr => 'finite timestamp?',
+ proname => 'isfinite', prorettype => 'bool', proargtypes => 'timestamptz',
+ prosrc => 'timestamp_finite' },
+{ oid => '1390', descr => 'finite interval?',
+ proname => 'isfinite', prorettype => 'bool', proargtypes => 'interval',
+ prosrc => 'interval_finite' },
+
+{ oid => '1376', descr => 'factorial',
+ proname => 'factorial', prorettype => 'numeric', proargtypes => 'int8',
+ prosrc => 'numeric_fac' },
+{ oid => '1394', descr => 'absolute value',
+ proname => 'abs', prorettype => 'float4', proargtypes => 'float4',
+ prosrc => 'float4abs' },
+{ oid => '1395', descr => 'absolute value',
+ proname => 'abs', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'float8abs' },
+{ oid => '1396', descr => 'absolute value',
+ proname => 'abs', prorettype => 'int8', proargtypes => 'int8',
+ prosrc => 'int8abs' },
+{ oid => '1397', descr => 'absolute value',
+ proname => 'abs', prorettype => 'int4', proargtypes => 'int4',
+ prosrc => 'int4abs' },
+{ oid => '1398', descr => 'absolute value',
+ proname => 'abs', prorettype => 'int2', proargtypes => 'int2',
+ prosrc => 'int2abs' },
+
+# OIDS 1400 - 1499
+
+{ oid => '1400', descr => 'convert varchar to name',
+ proname => 'name', prorettype => 'name', proargtypes => 'varchar',
+ prosrc => 'text_name' },
+{ oid => '1401', descr => 'convert name to varchar',
+ proname => 'varchar', prorettype => 'varchar', proargtypes => 'name',
+ prosrc => 'name_text' },
+
+{ oid => '1402', descr => 'current schema name',
+ proname => 'current_schema', provolatile => 's', proparallel => 'u',
+ prorettype => 'name', proargtypes => '', prosrc => 'current_schema' },
+{ oid => '1403', descr => 'current schema search list',
+ proname => 'current_schemas', provolatile => 's', proparallel => 'u',
+ prorettype => '_name', proargtypes => 'bool', prosrc => 'current_schemas' },
+
+{ oid => '1404', descr => 'substitute portion of string',
+ proname => 'overlay', prorettype => 'text',
+ proargtypes => 'text text int4 int4', prosrc => 'textoverlay' },
+{ oid => '1405', descr => 'substitute portion of string',
+ proname => 'overlay', prorettype => 'text', proargtypes => 'text text int4',
+ prosrc => 'textoverlay_no_len' },
+
+{ oid => '1406', descr => 'vertically aligned',
+ proname => 'isvertical', prorettype => 'bool', proargtypes => 'point point',
+ prosrc => 'point_vert' },
+{ oid => '1407', descr => 'horizontally aligned',
+ proname => 'ishorizontal', prorettype => 'bool', proargtypes => 'point point',
+ prosrc => 'point_horiz' },
+{ oid => '1408', descr => 'parallel',
+ proname => 'isparallel', prorettype => 'bool', proargtypes => 'lseg lseg',
+ prosrc => 'lseg_parallel' },
+{ oid => '1409', descr => 'perpendicular',
+ proname => 'isperp', prorettype => 'bool', proargtypes => 'lseg lseg',
+ prosrc => 'lseg_perp' },
+{ oid => '1410', descr => 'vertical',
+ proname => 'isvertical', prorettype => 'bool', proargtypes => 'lseg',
+ prosrc => 'lseg_vertical' },
+{ oid => '1411', descr => 'horizontal',
+ proname => 'ishorizontal', prorettype => 'bool', proargtypes => 'lseg',
+ prosrc => 'lseg_horizontal' },
+{ oid => '1412', descr => 'parallel',
+ proname => 'isparallel', prorettype => 'bool', proargtypes => 'line line',
+ prosrc => 'line_parallel' },
+{ oid => '1413', descr => 'perpendicular',
+ proname => 'isperp', prorettype => 'bool', proargtypes => 'line line',
+ prosrc => 'line_perp' },
+{ oid => '1414', descr => 'vertical',
+ proname => 'isvertical', prorettype => 'bool', proargtypes => 'line',
+ prosrc => 'line_vertical' },
+{ oid => '1415', descr => 'horizontal',
+ proname => 'ishorizontal', prorettype => 'bool', proargtypes => 'line',
+ prosrc => 'line_horizontal' },
+{ oid => '1416', descr => 'center of',
+ proname => 'point', prorettype => 'point', proargtypes => 'circle',
+ prosrc => 'circle_center' },
+
+{ oid => '1419', descr => 'convert interval to time',
+ proname => 'time', prorettype => 'time', proargtypes => 'interval',
+ prosrc => 'interval_time' },
+
+{ oid => '1421', descr => 'convert points to box',
+ proname => 'box', prorettype => 'box', proargtypes => 'point point',
+ prosrc => 'points_box' },
+{ oid => '1422',
+ proname => 'box_add', prorettype => 'box', proargtypes => 'box point',
+ prosrc => 'box_add' },
+{ oid => '1423',
+ proname => 'box_sub', prorettype => 'box', proargtypes => 'box point',
+ prosrc => 'box_sub' },
+{ oid => '1424',
+ proname => 'box_mul', prorettype => 'box', proargtypes => 'box point',
+ prosrc => 'box_mul' },
+{ oid => '1425',
+ proname => 'box_div', prorettype => 'box', proargtypes => 'box point',
+ prosrc => 'box_div' },
+{ oid => '1426',
+ proname => 'path_contain_pt', prolang => 'sql', prorettype => 'bool',
+ proargtypes => 'path point', prosrc => 'select pg_catalog.on_ppath($2, $1)' },
+{ oid => '1428',
+ proname => 'poly_contain_pt', prorettype => 'bool',
+ proargtypes => 'polygon point', prosrc => 'poly_contain_pt' },
+{ oid => '1429',
+ proname => 'pt_contained_poly', prorettype => 'bool',
+ proargtypes => 'point polygon', prosrc => 'pt_contained_poly' },
+
+{ oid => '1430', descr => 'path closed?',
+ proname => 'isclosed', prorettype => 'bool', proargtypes => 'path',
+ prosrc => 'path_isclosed' },
+{ oid => '1431', descr => 'path open?',
+ proname => 'isopen', prorettype => 'bool', proargtypes => 'path',
+ prosrc => 'path_isopen' },
+{ oid => '1432',
+ proname => 'path_npoints', prorettype => 'int4', proargtypes => 'path',
+ prosrc => 'path_npoints' },
+
+# pclose and popen might better be named close and open, but that crashes initdb.
+# - thomas 97/04/20
+{ oid => '1433', descr => 'close path',
+ proname => 'pclose', prorettype => 'path', proargtypes => 'path',
+ prosrc => 'path_close' },
+{ oid => '1434', descr => 'open path',
+ proname => 'popen', prorettype => 'path', proargtypes => 'path',
+ prosrc => 'path_open' },
+
+{ oid => '1435',
+ proname => 'path_add', prorettype => 'path', proargtypes => 'path path',
+ prosrc => 'path_add' },
+{ oid => '1436',
+ proname => 'path_add_pt', prorettype => 'path', proargtypes => 'path point',
+ prosrc => 'path_add_pt' },
+{ oid => '1437',
+ proname => 'path_sub_pt', prorettype => 'path', proargtypes => 'path point',
+ prosrc => 'path_sub_pt' },
+{ oid => '1438',
+ proname => 'path_mul_pt', prorettype => 'path', proargtypes => 'path point',
+ prosrc => 'path_mul_pt' },
+{ oid => '1439',
+ proname => 'path_div_pt', prorettype => 'path', proargtypes => 'path point',
+ prosrc => 'path_div_pt' },
+
+{ oid => '1440', descr => 'convert x, y to point',
+ proname => 'point', prorettype => 'point', proargtypes => 'float8 float8',
+ prosrc => 'construct_point' },
+{ oid => '1441',
+ proname => 'point_add', prorettype => 'point', proargtypes => 'point point',
+ prosrc => 'point_add' },
+{ oid => '1442',
+ proname => 'point_sub', prorettype => 'point', proargtypes => 'point point',
+ prosrc => 'point_sub' },
+{ oid => '1443',
+ proname => 'point_mul', prorettype => 'point', proargtypes => 'point point',
+ prosrc => 'point_mul' },
+{ oid => '1444',
+ proname => 'point_div', prorettype => 'point', proargtypes => 'point point',
+ prosrc => 'point_div' },
+
+{ oid => '1445',
+ proname => 'poly_npoints', prorettype => 'int4', proargtypes => 'polygon',
+ prosrc => 'poly_npoints' },
+{ oid => '1446', descr => 'convert polygon to bounding box',
+ proname => 'box', prorettype => 'box', proargtypes => 'polygon',
+ prosrc => 'poly_box' },
+{ oid => '1447', descr => 'convert polygon to path',
+ proname => 'path', prorettype => 'path', proargtypes => 'polygon',
+ prosrc => 'poly_path' },
+{ oid => '1448', descr => 'convert box to polygon',
+ proname => 'polygon', prorettype => 'polygon', proargtypes => 'box',
+ prosrc => 'box_poly' },
+{ oid => '1449', descr => 'convert path to polygon',
+ proname => 'polygon', prorettype => 'polygon', proargtypes => 'path',
+ prosrc => 'path_poly' },
+
+{ oid => '1450', descr => 'I/O',
+ proname => 'circle_in', prorettype => 'circle', proargtypes => 'cstring',
+ prosrc => 'circle_in' },
+{ oid => '1451', descr => 'I/O',
+ proname => 'circle_out', prorettype => 'cstring', proargtypes => 'circle',
+ prosrc => 'circle_out' },
+{ oid => '1452',
+ proname => 'circle_same', prorettype => 'bool',
+ proargtypes => 'circle circle', prosrc => 'circle_same' },
+{ oid => '1453',
+ proname => 'circle_contain', prorettype => 'bool',
+ proargtypes => 'circle circle', prosrc => 'circle_contain' },
+{ oid => '1454',
+ proname => 'circle_left', prorettype => 'bool',
+ proargtypes => 'circle circle', prosrc => 'circle_left' },
+{ oid => '1455',
+ proname => 'circle_overleft', prorettype => 'bool',
+ proargtypes => 'circle circle', prosrc => 'circle_overleft' },
+{ oid => '1456',
+ proname => 'circle_overright', prorettype => 'bool',
+ proargtypes => 'circle circle', prosrc => 'circle_overright' },
+{ oid => '1457',
+ proname => 'circle_right', prorettype => 'bool',
+ proargtypes => 'circle circle', prosrc => 'circle_right' },
+{ oid => '1458',
+ proname => 'circle_contained', prorettype => 'bool',
+ proargtypes => 'circle circle', prosrc => 'circle_contained' },
+{ oid => '1459',
+ proname => 'circle_overlap', prorettype => 'bool',
+ proargtypes => 'circle circle', prosrc => 'circle_overlap' },
+{ oid => '1460',
+ proname => 'circle_below', prorettype => 'bool',
+ proargtypes => 'circle circle', prosrc => 'circle_below' },
+{ oid => '1461',
+ proname => 'circle_above', prorettype => 'bool',
+ proargtypes => 'circle circle', prosrc => 'circle_above' },
+{ oid => '1462',
+ proname => 'circle_eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'circle circle', prosrc => 'circle_eq' },
+{ oid => '1463',
+ proname => 'circle_ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'circle circle', prosrc => 'circle_ne' },
+{ oid => '1464',
+ proname => 'circle_lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'circle circle', prosrc => 'circle_lt' },
+{ oid => '1465',
+ proname => 'circle_gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'circle circle', prosrc => 'circle_gt' },
+{ oid => '1466',
+ proname => 'circle_le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'circle circle', prosrc => 'circle_le' },
+{ oid => '1467',
+ proname => 'circle_ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'circle circle', prosrc => 'circle_ge' },
+{ oid => '1468', descr => 'area of circle',
+ proname => 'area', prorettype => 'float8', proargtypes => 'circle',
+ prosrc => 'circle_area' },
+{ oid => '1469', descr => 'diameter of circle',
+ proname => 'diameter', prorettype => 'float8', proargtypes => 'circle',
+ prosrc => 'circle_diameter' },
+{ oid => '1470', descr => 'radius of circle',
+ proname => 'radius', prorettype => 'float8', proargtypes => 'circle',
+ prosrc => 'circle_radius' },
+{ oid => '1471',
+ proname => 'circle_distance', prorettype => 'float8',
+ proargtypes => 'circle circle', prosrc => 'circle_distance' },
+{ oid => '1472',
+ proname => 'circle_center', prorettype => 'point', proargtypes => 'circle',
+ prosrc => 'circle_center' },
+{ oid => '1473', descr => 'convert point and radius to circle',
+ proname => 'circle', prorettype => 'circle', proargtypes => 'point float8',
+ prosrc => 'cr_circle' },
+{ oid => '1474', descr => 'convert polygon to circle',
+ proname => 'circle', prorettype => 'circle', proargtypes => 'polygon',
+ prosrc => 'poly_circle' },
+{ oid => '1475', descr => 'convert vertex count and circle to polygon',
+ proname => 'polygon', prorettype => 'polygon', proargtypes => 'int4 circle',
+ prosrc => 'circle_poly' },
+{ oid => '1476',
+ proname => 'dist_pc', prorettype => 'float8', proargtypes => 'point circle',
+ prosrc => 'dist_pc' },
+{ oid => '1477',
+ proname => 'circle_contain_pt', prorettype => 'bool',
+ proargtypes => 'circle point', prosrc => 'circle_contain_pt' },
+{ oid => '1478',
+ proname => 'pt_contained_circle', prorettype => 'bool',
+ proargtypes => 'point circle', prosrc => 'pt_contained_circle' },
+{ oid => '4091', descr => 'convert point to empty box',
+ proname => 'box', prorettype => 'box', proargtypes => 'point',
+ prosrc => 'point_box' },
+{ oid => '1479', descr => 'convert box to circle',
+ proname => 'circle', prorettype => 'circle', proargtypes => 'box',
+ prosrc => 'box_circle' },
+{ oid => '1480', descr => 'convert circle to box',
+ proname => 'box', prorettype => 'box', proargtypes => 'circle',
+ prosrc => 'circle_box' },
+
+{ oid => '1482',
+ proname => 'lseg_ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'lseg lseg', prosrc => 'lseg_ne' },
+{ oid => '1483',
+ proname => 'lseg_lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'lseg lseg', prosrc => 'lseg_lt' },
+{ oid => '1484',
+ proname => 'lseg_le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'lseg lseg', prosrc => 'lseg_le' },
+{ oid => '1485',
+ proname => 'lseg_gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'lseg lseg', prosrc => 'lseg_gt' },
+{ oid => '1486',
+ proname => 'lseg_ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'lseg lseg', prosrc => 'lseg_ge' },
+{ oid => '1487',
+ proname => 'lseg_length', prorettype => 'float8', proargtypes => 'lseg',
+ prosrc => 'lseg_length' },
+{ oid => '1488',
+ proname => 'close_ls', prorettype => 'point', proargtypes => 'line lseg',
+ prosrc => 'close_ls' },
+{ oid => '1489',
+ proname => 'close_lseg', prorettype => 'point', proargtypes => 'lseg lseg',
+ prosrc => 'close_lseg' },
+
+{ oid => '1490', descr => 'I/O',
+ proname => 'line_in', prorettype => 'line', proargtypes => 'cstring',
+ prosrc => 'line_in' },
+{ oid => '1491', descr => 'I/O',
+ proname => 'line_out', prorettype => 'cstring', proargtypes => 'line',
+ prosrc => 'line_out' },
+{ oid => '1492',
+ proname => 'line_eq', prorettype => 'bool', proargtypes => 'line line',
+ prosrc => 'line_eq' },
+{ oid => '1493', descr => 'construct line from points',
+ proname => 'line', prorettype => 'line', proargtypes => 'point point',
+ prosrc => 'line_construct_pp' },
+{ oid => '1494',
+ proname => 'line_interpt', prorettype => 'point', proargtypes => 'line line',
+ prosrc => 'line_interpt' },
+{ oid => '1495',
+ proname => 'line_intersect', prorettype => 'bool', proargtypes => 'line line',
+ prosrc => 'line_intersect' },
+{ oid => '1496',
+ proname => 'line_parallel', prorettype => 'bool', proargtypes => 'line line',
+ prosrc => 'line_parallel' },
+{ oid => '1497',
+ proname => 'line_perp', prorettype => 'bool', proargtypes => 'line line',
+ prosrc => 'line_perp' },
+{ oid => '1498',
+ proname => 'line_vertical', prorettype => 'bool', proargtypes => 'line',
+ prosrc => 'line_vertical' },
+{ oid => '1499',
+ proname => 'line_horizontal', prorettype => 'bool', proargtypes => 'line',
+ prosrc => 'line_horizontal' },
+
+# OIDS 1500 - 1599
+
+{ oid => '1530', descr => 'distance between endpoints',
+ proname => 'length', prorettype => 'float8', proargtypes => 'lseg',
+ prosrc => 'lseg_length' },
+{ oid => '1531', descr => 'sum of path segments',
+ proname => 'length', prorettype => 'float8', proargtypes => 'path',
+ prosrc => 'path_length' },
+
+{ oid => '1532', descr => 'center of',
+ proname => 'point', prorettype => 'point', proargtypes => 'lseg',
+ prosrc => 'lseg_center' },
+{ oid => '1533', descr => 'center of',
+ proname => 'point', prorettype => 'point', proargtypes => 'path',
+ prosrc => 'path_center' },
+{ oid => '1534', descr => 'center of',
+ proname => 'point', prorettype => 'point', proargtypes => 'box',
+ prosrc => 'box_center' },
+{ oid => '1540', descr => 'center of',
+ proname => 'point', prorettype => 'point', proargtypes => 'polygon',
+ prosrc => 'poly_center' },
+{ oid => '1541', descr => 'diagonal of',
+ proname => 'lseg', prorettype => 'lseg', proargtypes => 'box',
+ prosrc => 'box_diagonal' },
+{ oid => '1542', descr => 'center of',
+ proname => 'center', prorettype => 'point', proargtypes => 'box',
+ prosrc => 'box_center' },
+{ oid => '1543', descr => 'center of',
+ proname => 'center', prorettype => 'point', proargtypes => 'circle',
+ prosrc => 'circle_center' },
+{ oid => '1544', descr => 'convert circle to 12-vertex polygon',
+ proname => 'polygon', prolang => 'sql', prorettype => 'polygon',
+ proargtypes => 'circle', prosrc => 'select pg_catalog.polygon(12, $1)' },
+{ oid => '1545', descr => 'number of points',
+ proname => 'npoints', prorettype => 'int4', proargtypes => 'path',
+ prosrc => 'path_npoints' },
+{ oid => '1556', descr => 'number of points',
+ proname => 'npoints', prorettype => 'int4', proargtypes => 'polygon',
+ prosrc => 'poly_npoints' },
+
+{ oid => '1564', descr => 'I/O',
+ proname => 'bit_in', prorettype => 'bit', proargtypes => 'cstring oid int4',
+ prosrc => 'bit_in' },
+{ oid => '1565', descr => 'I/O',
+ proname => 'bit_out', prorettype => 'cstring', proargtypes => 'bit',
+ prosrc => 'bit_out' },
+{ oid => '2919', descr => 'I/O typmod',
+ proname => 'bittypmodin', prorettype => 'int4', proargtypes => '_cstring',
+ prosrc => 'bittypmodin' },
+{ oid => '2920', descr => 'I/O typmod',
+ proname => 'bittypmodout', prorettype => 'cstring', proargtypes => 'int4',
+ prosrc => 'bittypmodout' },
+
+{ oid => '1569', descr => 'matches LIKE expression',
+ proname => 'like', prosupport => 'textlike_support', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'textlike' },
+{ oid => '1570', descr => 'does not match LIKE expression',
+ proname => 'notlike', prorettype => 'bool', proargtypes => 'text text',
+ prosrc => 'textnlike' },
+{ oid => '1571', descr => 'matches LIKE expression',
+ proname => 'like', prosupport => 'textlike_support', prorettype => 'bool',
+ proargtypes => 'name text', prosrc => 'namelike' },
+{ oid => '1572', descr => 'does not match LIKE expression',
+ proname => 'notlike', prorettype => 'bool', proargtypes => 'name text',
+ prosrc => 'namenlike' },
+
+# SEQUENCE functions
+{ oid => '1574', descr => 'sequence next value',
+ proname => 'nextval', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int8', proargtypes => 'regclass', prosrc => 'nextval_oid' },
+{ oid => '1575', descr => 'sequence current value',
+ proname => 'currval', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int8', proargtypes => 'regclass', prosrc => 'currval_oid' },
+{ oid => '1576', descr => 'set sequence value',
+ proname => 'setval', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int8', proargtypes => 'regclass int8',
+ prosrc => 'setval_oid' },
+{ oid => '1765', descr => 'set sequence value and is_called status',
+ proname => 'setval', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int8', proargtypes => 'regclass int8 bool',
+ prosrc => 'setval3_oid' },
+{ oid => '3078',
+ descr => 'sequence parameters, for use by information schema',
+ proname => 'pg_sequence_parameters', provolatile => 's',
+ prorettype => 'record', proargtypes => 'oid',
+ proallargtypes => '{oid,int8,int8,int8,int8,bool,int8,oid}',
+ proargmodes => '{i,o,o,o,o,o,o,o}',
+ proargnames => '{sequence_oid,start_value,minimum_value,maximum_value,increment,cycle_option,cache_size,data_type}',
+ prosrc => 'pg_sequence_parameters' },
+{ oid => '4032', descr => 'sequence last value',
+ proname => 'pg_sequence_last_value', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int8', proargtypes => 'regclass',
+ prosrc => 'pg_sequence_last_value' },
+
+{ oid => '275', descr => 'return the next oid for a system table',
+ proname => 'pg_nextoid', provolatile => 'v', proparallel => 'u',
+ prorettype => 'oid', proargtypes => 'regclass name regclass',
+ prosrc => 'pg_nextoid' },
+
+{ oid => '1579', descr => 'I/O',
+ proname => 'varbit_in', prorettype => 'varbit',
+ proargtypes => 'cstring oid int4', prosrc => 'varbit_in' },
+{ oid => '1580', descr => 'I/O',
+ proname => 'varbit_out', prorettype => 'cstring', proargtypes => 'varbit',
+ prosrc => 'varbit_out' },
+{ oid => '2902', descr => 'I/O typmod',
+ proname => 'varbittypmodin', prorettype => 'int4', proargtypes => '_cstring',
+ prosrc => 'varbittypmodin' },
+{ oid => '2921', descr => 'I/O typmod',
+ proname => 'varbittypmodout', prorettype => 'cstring', proargtypes => 'int4',
+ prosrc => 'varbittypmodout' },
+
+{ oid => '1581',
+ proname => 'biteq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bit bit', prosrc => 'biteq' },
+{ oid => '1582',
+ proname => 'bitne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bit bit', prosrc => 'bitne' },
+{ oid => '1592',
+ proname => 'bitge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bit bit', prosrc => 'bitge' },
+{ oid => '1593',
+ proname => 'bitgt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bit bit', prosrc => 'bitgt' },
+{ oid => '1594',
+ proname => 'bitle', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bit bit', prosrc => 'bitle' },
+{ oid => '1595',
+ proname => 'bitlt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bit bit', prosrc => 'bitlt' },
+{ oid => '1596', descr => 'less-equal-greater',
+ proname => 'bitcmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'bit bit', prosrc => 'bitcmp' },
+
+{ oid => '1598', descr => 'random value',
+ proname => 'random', provolatile => 'v', proparallel => 'r',
+ prorettype => 'float8', proargtypes => '', prosrc => 'drandom' },
+{ oid => '1599', descr => 'set random seed',
+ proname => 'setseed', provolatile => 'v', proparallel => 'r',
+ prorettype => 'void', proargtypes => 'float8', prosrc => 'setseed' },
+
+# OIDS 1600 - 1699
+
+{ oid => '1600', descr => 'arcsine',
+ proname => 'asin', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dasin' },
+{ oid => '1601', descr => 'arccosine',
+ proname => 'acos', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dacos' },
+{ oid => '1602', descr => 'arctangent',
+ proname => 'atan', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'datan' },
+{ oid => '1603', descr => 'arctangent, two arguments',
+ proname => 'atan2', prorettype => 'float8', proargtypes => 'float8 float8',
+ prosrc => 'datan2' },
+{ oid => '1604', descr => 'sine',
+ proname => 'sin', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dsin' },
+{ oid => '1605', descr => 'cosine',
+ proname => 'cos', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dcos' },
+{ oid => '1606', descr => 'tangent',
+ proname => 'tan', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dtan' },
+{ oid => '1607', descr => 'cotangent',
+ proname => 'cot', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dcot' },
+
+{ oid => '2731', descr => 'arcsine, degrees',
+ proname => 'asind', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dasind' },
+{ oid => '2732', descr => 'arccosine, degrees',
+ proname => 'acosd', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dacosd' },
+{ oid => '2733', descr => 'arctangent, degrees',
+ proname => 'atand', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'datand' },
+{ oid => '2734', descr => 'arctangent, two arguments, degrees',
+ proname => 'atan2d', prorettype => 'float8', proargtypes => 'float8 float8',
+ prosrc => 'datan2d' },
+{ oid => '2735', descr => 'sine, degrees',
+ proname => 'sind', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dsind' },
+{ oid => '2736', descr => 'cosine, degrees',
+ proname => 'cosd', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dcosd' },
+{ oid => '2737', descr => 'tangent, degrees',
+ proname => 'tand', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dtand' },
+{ oid => '2738', descr => 'cotangent, degrees',
+ proname => 'cotd', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dcotd' },
+
+{ oid => '1608', descr => 'radians to degrees',
+ proname => 'degrees', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'degrees' },
+{ oid => '1609', descr => 'degrees to radians',
+ proname => 'radians', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'radians' },
+{ oid => '1610', descr => 'PI',
+ proname => 'pi', prorettype => 'float8', proargtypes => '', prosrc => 'dpi' },
+
+{ oid => '2462', descr => 'hyperbolic sine',
+ proname => 'sinh', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dsinh' },
+{ oid => '2463', descr => 'hyperbolic cosine',
+ proname => 'cosh', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dcosh' },
+{ oid => '2464', descr => 'hyperbolic tangent',
+ proname => 'tanh', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dtanh' },
+{ oid => '2465', descr => 'inverse hyperbolic sine',
+ proname => 'asinh', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dasinh' },
+{ oid => '2466', descr => 'inverse hyperbolic cosine',
+ proname => 'acosh', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'dacosh' },
+{ oid => '2467', descr => 'inverse hyperbolic tangent',
+ proname => 'atanh', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'datanh' },
+
+{ oid => '1618',
+ proname => 'interval_mul', prorettype => 'interval',
+ proargtypes => 'interval float8', prosrc => 'interval_mul' },
+
+{ oid => '1620', descr => 'convert first char to int4',
+ proname => 'ascii', prorettype => 'int4', proargtypes => 'text',
+ prosrc => 'ascii' },
+{ oid => '1621', descr => 'convert int4 to char',
+ proname => 'chr', prorettype => 'text', proargtypes => 'int4',
+ prosrc => 'chr' },
+{ oid => '1622', descr => 'replicate string n times',
+ proname => 'repeat', prorettype => 'text', proargtypes => 'text int4',
+ prosrc => 'repeat' },
+
+{ oid => '1623', descr => 'convert SQL regexp pattern to POSIX style',
+ proname => 'similar_escape', proisstrict => 'f', prorettype => 'text',
+ proargtypes => 'text text', prosrc => 'similar_escape' },
+{ oid => '1986', descr => 'convert SQL regexp pattern to POSIX style',
+ proname => 'similar_to_escape', prorettype => 'text',
+ proargtypes => 'text text', prosrc => 'similar_to_escape_2' },
+{ oid => '1987', descr => 'convert SQL regexp pattern to POSIX style',
+ proname => 'similar_to_escape', prorettype => 'text', proargtypes => 'text',
+ prosrc => 'similar_to_escape_1' },
+
+{ oid => '1624',
+ proname => 'mul_d_interval', prorettype => 'interval',
+ proargtypes => 'float8 interval', prosrc => 'mul_d_interval' },
+
+{ oid => '1631',
+ proname => 'bpcharlike', prosupport => 'textlike_support',
+ prorettype => 'bool', proargtypes => 'bpchar text', prosrc => 'textlike' },
+{ oid => '1632',
+ proname => 'bpcharnlike', prorettype => 'bool', proargtypes => 'bpchar text',
+ prosrc => 'textnlike' },
+
+{ oid => '1633',
+ proname => 'texticlike', prosupport => 'texticlike_support',
+ prorettype => 'bool', proargtypes => 'text text', prosrc => 'texticlike' },
+{ oid => '1025', descr => 'planner support for texticlike',
+ proname => 'texticlike_support', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'texticlike_support' },
+{ oid => '1634',
+ proname => 'texticnlike', prorettype => 'bool', proargtypes => 'text text',
+ prosrc => 'texticnlike' },
+{ oid => '1635',
+ proname => 'nameiclike', prosupport => 'texticlike_support',
+ prorettype => 'bool', proargtypes => 'name text', prosrc => 'nameiclike' },
+{ oid => '1636',
+ proname => 'nameicnlike', prorettype => 'bool', proargtypes => 'name text',
+ prosrc => 'nameicnlike' },
+{ oid => '1637', descr => 'convert LIKE pattern to use backslash escapes',
+ proname => 'like_escape', prorettype => 'text', proargtypes => 'text text',
+ prosrc => 'like_escape' },
+
+{ oid => '1656',
+ proname => 'bpcharicregexeq', prosupport => 'texticregexeq_support',
+ prorettype => 'bool', proargtypes => 'bpchar text',
+ prosrc => 'texticregexeq' },
+{ oid => '1657',
+ proname => 'bpcharicregexne', prorettype => 'bool',
+ proargtypes => 'bpchar text', prosrc => 'texticregexne' },
+{ oid => '1658',
+ proname => 'bpcharregexeq', prosupport => 'textregexeq_support',
+ prorettype => 'bool', proargtypes => 'bpchar text', prosrc => 'textregexeq' },
+{ oid => '1659',
+ proname => 'bpcharregexne', prorettype => 'bool',
+ proargtypes => 'bpchar text', prosrc => 'textregexne' },
+{ oid => '1660',
+ proname => 'bpchariclike', prosupport => 'texticlike_support',
+ prorettype => 'bool', proargtypes => 'bpchar text', prosrc => 'texticlike' },
+{ oid => '1661',
+ proname => 'bpcharicnlike', prorettype => 'bool',
+ proargtypes => 'bpchar text', prosrc => 'texticnlike' },
+
+# Oracle Compatibility Related Functions - By Edmund Mergl <E.Mergl@bawue.de>
+{ oid => '868', descr => 'position of substring',
+ proname => 'strpos', prorettype => 'int4', proargtypes => 'text text',
+ prosrc => 'textpos' },
+{ oid => '870', descr => 'lowercase',
+ proname => 'lower', prorettype => 'text', proargtypes => 'text',
+ prosrc => 'lower' },
+{ oid => '871', descr => 'uppercase',
+ proname => 'upper', prorettype => 'text', proargtypes => 'text',
+ prosrc => 'upper' },
+{ oid => '872', descr => 'capitalize each word',
+ proname => 'initcap', prorettype => 'text', proargtypes => 'text',
+ prosrc => 'initcap' },
+{ oid => '873', descr => 'left-pad string to length',
+ proname => 'lpad', prorettype => 'text', proargtypes => 'text int4 text',
+ prosrc => 'lpad' },
+{ oid => '874', descr => 'right-pad string to length',
+ proname => 'rpad', prorettype => 'text', proargtypes => 'text int4 text',
+ prosrc => 'rpad' },
+{ oid => '875', descr => 'trim selected characters from left end of string',
+ proname => 'ltrim', prorettype => 'text', proargtypes => 'text text',
+ prosrc => 'ltrim' },
+{ oid => '876', descr => 'trim selected characters from right end of string',
+ proname => 'rtrim', prorettype => 'text', proargtypes => 'text text',
+ prosrc => 'rtrim' },
+{ oid => '877', descr => 'extract portion of string',
+ proname => 'substr', prorettype => 'text', proargtypes => 'text int4 int4',
+ prosrc => 'text_substr' },
+{ oid => '878', descr => 'map a set of characters appearing in string',
+ proname => 'translate', prorettype => 'text', proargtypes => 'text text text',
+ prosrc => 'translate' },
+{ oid => '879', descr => 'left-pad string to length',
+ proname => 'lpad', prolang => 'sql', prorettype => 'text',
+ proargtypes => 'text int4',
+ prosrc => 'select pg_catalog.lpad($1, $2, \' \')' },
+{ oid => '880', descr => 'right-pad string to length',
+ proname => 'rpad', prolang => 'sql', prorettype => 'text',
+ proargtypes => 'text int4',
+ prosrc => 'select pg_catalog.rpad($1, $2, \' \')' },
+{ oid => '881', descr => 'trim spaces from left end of string',
+ proname => 'ltrim', prorettype => 'text', proargtypes => 'text',
+ prosrc => 'ltrim1' },
+{ oid => '882', descr => 'trim spaces from right end of string',
+ proname => 'rtrim', prorettype => 'text', proargtypes => 'text',
+ prosrc => 'rtrim1' },
+{ oid => '883', descr => 'extract portion of string',
+ proname => 'substr', prorettype => 'text', proargtypes => 'text int4',
+ prosrc => 'text_substr_no_len' },
+{ oid => '884', descr => 'trim selected characters from both ends of string',
+ proname => 'btrim', prorettype => 'text', proargtypes => 'text text',
+ prosrc => 'btrim' },
+{ oid => '885', descr => 'trim spaces from both ends of string',
+ proname => 'btrim', prorettype => 'text', proargtypes => 'text',
+ prosrc => 'btrim1' },
+
+{ oid => '936', descr => 'extract portion of string',
+ proname => 'substring', prorettype => 'text', proargtypes => 'text int4 int4',
+ prosrc => 'text_substr' },
+{ oid => '937', descr => 'extract portion of string',
+ proname => 'substring', prorettype => 'text', proargtypes => 'text int4',
+ prosrc => 'text_substr_no_len' },
+{ oid => '2087',
+ descr => 'replace all occurrences in string of old_substr with new_substr',
+ proname => 'replace', prorettype => 'text', proargtypes => 'text text text',
+ prosrc => 'replace_text' },
+{ oid => '2284', descr => 'replace text using regexp',
+ proname => 'regexp_replace', prorettype => 'text',
+ proargtypes => 'text text text', prosrc => 'textregexreplace_noopt' },
+{ oid => '2285', descr => 'replace text using regexp',
+ proname => 'regexp_replace', prorettype => 'text',
+ proargtypes => 'text text text text', prosrc => 'textregexreplace' },
+{ oid => '3396', descr => 'find first match for regexp',
+ proname => 'regexp_match', prorettype => '_text', proargtypes => 'text text',
+ prosrc => 'regexp_match_no_flags' },
+{ oid => '3397', descr => 'find first match for regexp',
+ proname => 'regexp_match', prorettype => '_text',
+ proargtypes => 'text text text', prosrc => 'regexp_match' },
+{ oid => '2763', descr => 'find match(es) for regexp',
+ proname => 'regexp_matches', prorows => '1', proretset => 't',
+ prorettype => '_text', proargtypes => 'text text',
+ prosrc => 'regexp_matches_no_flags' },
+{ oid => '2764', descr => 'find match(es) for regexp',
+ proname => 'regexp_matches', prorows => '10', proretset => 't',
+ prorettype => '_text', proargtypes => 'text text text',
+ prosrc => 'regexp_matches' },
+{ oid => '2088', descr => 'split string by field_sep and return field_num',
+ proname => 'split_part', prorettype => 'text',
+ proargtypes => 'text text int4', prosrc => 'split_text' },
+{ oid => '2765', descr => 'split string by pattern',
+ proname => 'regexp_split_to_table', prorows => '1000', proretset => 't',
+ prorettype => 'text', proargtypes => 'text text',
+ prosrc => 'regexp_split_to_table_no_flags' },
+{ oid => '2766', descr => 'split string by pattern',
+ proname => 'regexp_split_to_table', prorows => '1000', proretset => 't',
+ prorettype => 'text', proargtypes => 'text text text',
+ prosrc => 'regexp_split_to_table' },
+{ oid => '2767', descr => 'split string by pattern',
+ proname => 'regexp_split_to_array', prorettype => '_text',
+ proargtypes => 'text text', prosrc => 'regexp_split_to_array_no_flags' },
+{ oid => '2768', descr => 'split string by pattern',
+ proname => 'regexp_split_to_array', prorettype => '_text',
+ proargtypes => 'text text text', prosrc => 'regexp_split_to_array' },
+{ oid => '2089', descr => 'convert int4 number to hex',
+ proname => 'to_hex', prorettype => 'text', proargtypes => 'int4',
+ prosrc => 'to_hex32' },
+{ oid => '2090', descr => 'convert int8 number to hex',
+ proname => 'to_hex', prorettype => 'text', proargtypes => 'int8',
+ prosrc => 'to_hex64' },
+
+# for character set encoding support
+
+# return database encoding name
+{ oid => '1039', descr => 'encoding name of current database',
+ proname => 'getdatabaseencoding', provolatile => 's', prorettype => 'name',
+ proargtypes => '', prosrc => 'getdatabaseencoding' },
+
+# return client encoding name i.e. session encoding
+{ oid => '810', descr => 'encoding name of current database',
+ proname => 'pg_client_encoding', provolatile => 's', prorettype => 'name',
+ proargtypes => '', prosrc => 'pg_client_encoding' },
+
+{ oid => '1713', descr => 'length of string in specified encoding',
+ proname => 'length', provolatile => 's', prorettype => 'int4',
+ proargtypes => 'bytea name', prosrc => 'length_in_encoding' },
+
+{ oid => '1714',
+ descr => 'convert string with specified source encoding name',
+ proname => 'convert_from', provolatile => 's', prorettype => 'text',
+ proargtypes => 'bytea name', prosrc => 'pg_convert_from' },
+
+{ oid => '1717',
+ descr => 'convert string with specified destination encoding name',
+ proname => 'convert_to', provolatile => 's', prorettype => 'bytea',
+ proargtypes => 'text name', prosrc => 'pg_convert_to' },
+
+{ oid => '1813', descr => 'convert string with specified encoding names',
+ proname => 'convert', provolatile => 's', prorettype => 'bytea',
+ proargtypes => 'bytea name name', prosrc => 'pg_convert' },
+
+{ oid => '1264', descr => 'convert encoding name to encoding id',
+ proname => 'pg_char_to_encoding', provolatile => 's', prorettype => 'int4',
+ proargtypes => 'name', prosrc => 'PG_char_to_encoding' },
+
+{ oid => '1597', descr => 'convert encoding id to encoding name',
+ proname => 'pg_encoding_to_char', provolatile => 's', prorettype => 'name',
+ proargtypes => 'int4', prosrc => 'PG_encoding_to_char' },
+
+{ oid => '2319',
+ descr => 'maximum octet length of a character in given encoding',
+ proname => 'pg_encoding_max_length', prorettype => 'int4',
+ proargtypes => 'int4', prosrc => 'pg_encoding_max_length_sql' },
+
+{ oid => '1638',
+ proname => 'oidgt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'oid oid', prosrc => 'oidgt' },
+{ oid => '1639',
+ proname => 'oidge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'oid oid', prosrc => 'oidge' },
+
+# System-view support functions
+{ oid => '1573', descr => 'source text of a rule',
+ proname => 'pg_get_ruledef', provolatile => 's', prorettype => 'text',
+ proargtypes => 'oid', prosrc => 'pg_get_ruledef' },
+{ oid => '1640', descr => 'select statement of a view',
+ proname => 'pg_get_viewdef', provolatile => 's', proparallel => 'r',
+ prorettype => 'text', proargtypes => 'text',
+ prosrc => 'pg_get_viewdef_name' },
+{ oid => '1641', descr => 'select statement of a view',
+ proname => 'pg_get_viewdef', provolatile => 's', proparallel => 'r',
+ prorettype => 'text', proargtypes => 'oid', prosrc => 'pg_get_viewdef' },
+{ oid => '1642', descr => 'role name by OID (with fallback)',
+ proname => 'pg_get_userbyid', provolatile => 's', prorettype => 'name',
+ proargtypes => 'oid', prosrc => 'pg_get_userbyid' },
+{ oid => '1643', descr => 'index description',
+ proname => 'pg_get_indexdef', provolatile => 's', prorettype => 'text',
+ proargtypes => 'oid', prosrc => 'pg_get_indexdef' },
+{ oid => '3415', descr => 'extended statistics object description',
+ proname => 'pg_get_statisticsobjdef', provolatile => 's',
+ prorettype => 'text', proargtypes => 'oid',
+ prosrc => 'pg_get_statisticsobjdef' },
+{ oid => '3352', descr => 'partition key description',
+ proname => 'pg_get_partkeydef', provolatile => 's', prorettype => 'text',
+ proargtypes => 'oid', prosrc => 'pg_get_partkeydef' },
+{ oid => '3408', descr => 'partition constraint description',
+ proname => 'pg_get_partition_constraintdef', provolatile => 's',
+ prorettype => 'text', proargtypes => 'oid',
+ prosrc => 'pg_get_partition_constraintdef' },
+{ oid => '1662', descr => 'trigger description',
+ proname => 'pg_get_triggerdef', provolatile => 's', prorettype => 'text',
+ proargtypes => 'oid', prosrc => 'pg_get_triggerdef' },
+{ oid => '1387', descr => 'constraint description',
+ proname => 'pg_get_constraintdef', provolatile => 's', prorettype => 'text',
+ proargtypes => 'oid', prosrc => 'pg_get_constraintdef' },
+{ oid => '1716', descr => 'deparse an encoded expression',
+ proname => 'pg_get_expr', provolatile => 's', prorettype => 'text',
+ proargtypes => 'pg_node_tree oid', prosrc => 'pg_get_expr' },
+{ oid => '1665', descr => 'name of sequence for a serial column',
+ proname => 'pg_get_serial_sequence', provolatile => 's', prorettype => 'text',
+ proargtypes => 'text text', prosrc => 'pg_get_serial_sequence' },
+{ oid => '2098', descr => 'definition of a function',
+ proname => 'pg_get_functiondef', provolatile => 's', prorettype => 'text',
+ proargtypes => 'oid', prosrc => 'pg_get_functiondef' },
+{ oid => '2162', descr => 'argument list of a function',
+ proname => 'pg_get_function_arguments', provolatile => 's',
+ prorettype => 'text', proargtypes => 'oid',
+ prosrc => 'pg_get_function_arguments' },
+{ oid => '2232', descr => 'identity argument list of a function',
+ proname => 'pg_get_function_identity_arguments', provolatile => 's',
+ prorettype => 'text', proargtypes => 'oid',
+ prosrc => 'pg_get_function_identity_arguments' },
+{ oid => '2165', descr => 'result type of a function',
+ proname => 'pg_get_function_result', provolatile => 's', prorettype => 'text',
+ proargtypes => 'oid', prosrc => 'pg_get_function_result' },
+{ oid => '3808', descr => 'function argument default',
+ proname => 'pg_get_function_arg_default', provolatile => 's',
+ prorettype => 'text', proargtypes => 'oid int4',
+ prosrc => 'pg_get_function_arg_default' },
+
+{ oid => '1686', descr => 'list of SQL keywords',
+ proname => 'pg_get_keywords', procost => '10', prorows => '400',
+ proretset => 't', provolatile => 's', prorettype => 'record',
+ proargtypes => '', proallargtypes => '{text,char,text}',
+ proargmodes => '{o,o,o}', proargnames => '{word,catcode,catdesc}',
+ prosrc => 'pg_get_keywords' },
+
+{ oid => '2289', descr => 'convert generic options array to name/value table',
+ proname => 'pg_options_to_table', prorows => '3', proretset => 't',
+ provolatile => 's', prorettype => 'record', proargtypes => '_text',
+ proallargtypes => '{_text,text,text}', proargmodes => '{i,o,o}',
+ proargnames => '{options_array,option_name,option_value}',
+ prosrc => 'pg_options_to_table' },
+
+{ oid => '1619', descr => 'type of the argument',
+ proname => 'pg_typeof', proisstrict => 'f', provolatile => 's',
+ prorettype => 'regtype', proargtypes => 'any', prosrc => 'pg_typeof' },
+{ oid => '3162',
+ descr => 'collation of the argument; implementation of the COLLATION FOR expression',
+ proname => 'pg_collation_for', proisstrict => 'f', provolatile => 's',
+ prorettype => 'text', proargtypes => 'any', prosrc => 'pg_collation_for' },
+
+{ oid => '3842', descr => 'is a relation insertable/updatable/deletable',
+ proname => 'pg_relation_is_updatable', procost => '10', provolatile => 's',
+ prorettype => 'int4', proargtypes => 'regclass bool',
+ prosrc => 'pg_relation_is_updatable' },
+{ oid => '3843', descr => 'is a column updatable',
+ proname => 'pg_column_is_updatable', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'regclass int2 bool',
+ prosrc => 'pg_column_is_updatable' },
+
+{ oid => '6120', descr => 'oid of replica identity index if any',
+ proname => 'pg_get_replica_identity_index', procost => '10',
+ provolatile => 's', prorettype => 'regclass', proargtypes => 'regclass',
+ prosrc => 'pg_get_replica_identity_index' },
+
+# Deferrable unique constraint trigger
+{ oid => '1250', descr => 'deferred UNIQUE constraint check',
+ proname => 'unique_key_recheck', provolatile => 'v', prorettype => 'trigger',
+ proargtypes => '', prosrc => 'unique_key_recheck' },
+
+# Generic referential integrity constraint triggers
+{ oid => '1644', descr => 'referential integrity FOREIGN KEY ... REFERENCES',
+ proname => 'RI_FKey_check_ins', provolatile => 'v', prorettype => 'trigger',
+ proargtypes => '', prosrc => 'RI_FKey_check_ins' },
+{ oid => '1645', descr => 'referential integrity FOREIGN KEY ... REFERENCES',
+ proname => 'RI_FKey_check_upd', provolatile => 'v', prorettype => 'trigger',
+ proargtypes => '', prosrc => 'RI_FKey_check_upd' },
+{ oid => '1646', descr => 'referential integrity ON DELETE CASCADE',
+ proname => 'RI_FKey_cascade_del', provolatile => 'v', prorettype => 'trigger',
+ proargtypes => '', prosrc => 'RI_FKey_cascade_del' },
+{ oid => '1647', descr => 'referential integrity ON UPDATE CASCADE',
+ proname => 'RI_FKey_cascade_upd', provolatile => 'v', prorettype => 'trigger',
+ proargtypes => '', prosrc => 'RI_FKey_cascade_upd' },
+{ oid => '1648', descr => 'referential integrity ON DELETE RESTRICT',
+ proname => 'RI_FKey_restrict_del', provolatile => 'v',
+ prorettype => 'trigger', proargtypes => '',
+ prosrc => 'RI_FKey_restrict_del' },
+{ oid => '1649', descr => 'referential integrity ON UPDATE RESTRICT',
+ proname => 'RI_FKey_restrict_upd', provolatile => 'v',
+ prorettype => 'trigger', proargtypes => '',
+ prosrc => 'RI_FKey_restrict_upd' },
+{ oid => '1650', descr => 'referential integrity ON DELETE SET NULL',
+ proname => 'RI_FKey_setnull_del', provolatile => 'v', prorettype => 'trigger',
+ proargtypes => '', prosrc => 'RI_FKey_setnull_del' },
+{ oid => '1651', descr => 'referential integrity ON UPDATE SET NULL',
+ proname => 'RI_FKey_setnull_upd', provolatile => 'v', prorettype => 'trigger',
+ proargtypes => '', prosrc => 'RI_FKey_setnull_upd' },
+{ oid => '1652', descr => 'referential integrity ON DELETE SET DEFAULT',
+ proname => 'RI_FKey_setdefault_del', provolatile => 'v',
+ prorettype => 'trigger', proargtypes => '',
+ prosrc => 'RI_FKey_setdefault_del' },
+{ oid => '1653', descr => 'referential integrity ON UPDATE SET DEFAULT',
+ proname => 'RI_FKey_setdefault_upd', provolatile => 'v',
+ prorettype => 'trigger', proargtypes => '',
+ prosrc => 'RI_FKey_setdefault_upd' },
+{ oid => '1654', descr => 'referential integrity ON DELETE NO ACTION',
+ proname => 'RI_FKey_noaction_del', provolatile => 'v',
+ prorettype => 'trigger', proargtypes => '',
+ prosrc => 'RI_FKey_noaction_del' },
+{ oid => '1655', descr => 'referential integrity ON UPDATE NO ACTION',
+ proname => 'RI_FKey_noaction_upd', provolatile => 'v',
+ prorettype => 'trigger', proargtypes => '',
+ prosrc => 'RI_FKey_noaction_upd' },
+
+{ oid => '1666',
+ proname => 'varbiteq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'varbit varbit', prosrc => 'biteq' },
+{ oid => '1667',
+ proname => 'varbitne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'varbit varbit', prosrc => 'bitne' },
+{ oid => '1668',
+ proname => 'varbitge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'varbit varbit', prosrc => 'bitge' },
+{ oid => '1669',
+ proname => 'varbitgt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'varbit varbit', prosrc => 'bitgt' },
+{ oid => '1670',
+ proname => 'varbitle', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'varbit varbit', prosrc => 'bitle' },
+{ oid => '1671',
+ proname => 'varbitlt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'varbit varbit', prosrc => 'bitlt' },
+{ oid => '1672', descr => 'less-equal-greater',
+ proname => 'varbitcmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'varbit varbit', prosrc => 'bitcmp' },
+
+# avoid the C names bitand and bitor, since they are C++ keywords
+{ oid => '1673',
+ proname => 'bitand', prorettype => 'bit', proargtypes => 'bit bit',
+ prosrc => 'bit_and' },
+{ oid => '1674',
+ proname => 'bitor', prorettype => 'bit', proargtypes => 'bit bit',
+ prosrc => 'bit_or' },
+{ oid => '1675',
+ proname => 'bitxor', prorettype => 'bit', proargtypes => 'bit bit',
+ prosrc => 'bitxor' },
+{ oid => '1676',
+ proname => 'bitnot', prorettype => 'bit', proargtypes => 'bit',
+ prosrc => 'bitnot' },
+{ oid => '1677',
+ proname => 'bitshiftleft', prorettype => 'bit', proargtypes => 'bit int4',
+ prosrc => 'bitshiftleft' },
+{ oid => '1678',
+ proname => 'bitshiftright', prorettype => 'bit', proargtypes => 'bit int4',
+ prosrc => 'bitshiftright' },
+{ oid => '1679',
+ proname => 'bitcat', prorettype => 'varbit', proargtypes => 'varbit varbit',
+ prosrc => 'bitcat' },
+{ oid => '1680', descr => 'extract portion of bitstring',
+ proname => 'substring', prorettype => 'bit', proargtypes => 'bit int4 int4',
+ prosrc => 'bitsubstr' },
+{ oid => '1681', descr => 'bitstring length',
+ proname => 'length', prorettype => 'int4', proargtypes => 'bit',
+ prosrc => 'bitlength' },
+{ oid => '1682', descr => 'octet length',
+ proname => 'octet_length', prorettype => 'int4', proargtypes => 'bit',
+ prosrc => 'bitoctetlength' },
+{ oid => '1683', descr => 'convert int4 to bitstring',
+ proname => 'bit', prorettype => 'bit', proargtypes => 'int4 int4',
+ prosrc => 'bitfromint4' },
+{ oid => '1684', descr => 'convert bitstring to int4',
+ proname => 'int4', prorettype => 'int4', proargtypes => 'bit',
+ prosrc => 'bittoint4' },
+
+{ oid => '1685', descr => 'adjust bit() to typmod length',
+ proname => 'bit', prorettype => 'bit', proargtypes => 'bit int4 bool',
+ prosrc => 'bit' },
+{ oid => '3158', descr => 'planner support for varbit length coercion',
+ proname => 'varbit_support', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'varbit_support' },
+{ oid => '1687', descr => 'adjust varbit() to typmod length',
+ proname => 'varbit', prosupport => 'varbit_support', prorettype => 'varbit',
+ proargtypes => 'varbit int4 bool', prosrc => 'varbit' },
+
+{ oid => '1698', descr => 'position of sub-bitstring',
+ proname => 'position', prorettype => 'int4', proargtypes => 'bit bit',
+ prosrc => 'bitposition' },
+{ oid => '1699', descr => 'extract portion of bitstring',
+ proname => 'substring', prorettype => 'bit', proargtypes => 'bit int4',
+ prosrc => 'bitsubstr_no_len' },
+
+{ oid => '3030', descr => 'substitute portion of bitstring',
+ proname => 'overlay', prorettype => 'bit', proargtypes => 'bit bit int4 int4',
+ prosrc => 'bitoverlay' },
+{ oid => '3031', descr => 'substitute portion of bitstring',
+ proname => 'overlay', prorettype => 'bit', proargtypes => 'bit bit int4',
+ prosrc => 'bitoverlay_no_len' },
+{ oid => '3032', descr => 'get bit',
+ proname => 'get_bit', prorettype => 'int4', proargtypes => 'bit int4',
+ prosrc => 'bitgetbit' },
+{ oid => '3033', descr => 'set bit',
+ proname => 'set_bit', prorettype => 'bit', proargtypes => 'bit int4 int4',
+ prosrc => 'bitsetbit' },
+
+# for macaddr type support
+{ oid => '436', descr => 'I/O',
+ proname => 'macaddr_in', prorettype => 'macaddr', proargtypes => 'cstring',
+ prosrc => 'macaddr_in' },
+{ oid => '437', descr => 'I/O',
+ proname => 'macaddr_out', prorettype => 'cstring', proargtypes => 'macaddr',
+ prosrc => 'macaddr_out' },
+
+{ oid => '753', descr => 'MACADDR manufacturer fields',
+ proname => 'trunc', prorettype => 'macaddr', proargtypes => 'macaddr',
+ prosrc => 'macaddr_trunc' },
+
+{ oid => '830',
+ proname => 'macaddr_eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'macaddr macaddr', prosrc => 'macaddr_eq' },
+{ oid => '831',
+ proname => 'macaddr_lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'macaddr macaddr', prosrc => 'macaddr_lt' },
+{ oid => '832',
+ proname => 'macaddr_le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'macaddr macaddr', prosrc => 'macaddr_le' },
+{ oid => '833',
+ proname => 'macaddr_gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'macaddr macaddr', prosrc => 'macaddr_gt' },
+{ oid => '834',
+ proname => 'macaddr_ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'macaddr macaddr', prosrc => 'macaddr_ge' },
+{ oid => '835',
+ proname => 'macaddr_ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'macaddr macaddr', prosrc => 'macaddr_ne' },
+{ oid => '836', descr => 'less-equal-greater',
+ proname => 'macaddr_cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'macaddr macaddr', prosrc => 'macaddr_cmp' },
+{ oid => '3144',
+ proname => 'macaddr_not', prorettype => 'macaddr', proargtypes => 'macaddr',
+ prosrc => 'macaddr_not' },
+{ oid => '3145',
+ proname => 'macaddr_and', prorettype => 'macaddr',
+ proargtypes => 'macaddr macaddr', prosrc => 'macaddr_and' },
+{ oid => '3146',
+ proname => 'macaddr_or', prorettype => 'macaddr',
+ proargtypes => 'macaddr macaddr', prosrc => 'macaddr_or' },
+{ oid => '3359', descr => 'sort support',
+ proname => 'macaddr_sortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'macaddr_sortsupport' },
+
+# for macaddr8 type support
+{ oid => '4110', descr => 'I/O',
+ proname => 'macaddr8_in', prorettype => 'macaddr8', proargtypes => 'cstring',
+ prosrc => 'macaddr8_in' },
+{ oid => '4111', descr => 'I/O',
+ proname => 'macaddr8_out', prorettype => 'cstring', proargtypes => 'macaddr8',
+ prosrc => 'macaddr8_out' },
+
+{ oid => '4112', descr => 'MACADDR8 manufacturer fields',
+ proname => 'trunc', prorettype => 'macaddr8', proargtypes => 'macaddr8',
+ prosrc => 'macaddr8_trunc' },
+
+{ oid => '4113',
+ proname => 'macaddr8_eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'macaddr8 macaddr8', prosrc => 'macaddr8_eq' },
+{ oid => '4114',
+ proname => 'macaddr8_lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'macaddr8 macaddr8', prosrc => 'macaddr8_lt' },
+{ oid => '4115',
+ proname => 'macaddr8_le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'macaddr8 macaddr8', prosrc => 'macaddr8_le' },
+{ oid => '4116',
+ proname => 'macaddr8_gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'macaddr8 macaddr8', prosrc => 'macaddr8_gt' },
+{ oid => '4117',
+ proname => 'macaddr8_ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'macaddr8 macaddr8', prosrc => 'macaddr8_ge' },
+{ oid => '4118',
+ proname => 'macaddr8_ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'macaddr8 macaddr8', prosrc => 'macaddr8_ne' },
+{ oid => '4119', descr => 'less-equal-greater',
+ proname => 'macaddr8_cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'macaddr8 macaddr8', prosrc => 'macaddr8_cmp' },
+{ oid => '4120',
+ proname => 'macaddr8_not', prorettype => 'macaddr8',
+ proargtypes => 'macaddr8', prosrc => 'macaddr8_not' },
+{ oid => '4121',
+ proname => 'macaddr8_and', prorettype => 'macaddr8',
+ proargtypes => 'macaddr8 macaddr8', prosrc => 'macaddr8_and' },
+{ oid => '4122',
+ proname => 'macaddr8_or', prorettype => 'macaddr8',
+ proargtypes => 'macaddr8 macaddr8', prosrc => 'macaddr8_or' },
+{ oid => '4123', descr => 'convert macaddr to macaddr8',
+ proname => 'macaddr8', prorettype => 'macaddr8', proargtypes => 'macaddr',
+ prosrc => 'macaddrtomacaddr8' },
+{ oid => '4124', descr => 'convert macaddr8 to macaddr',
+ proname => 'macaddr', prorettype => 'macaddr', proargtypes => 'macaddr8',
+ prosrc => 'macaddr8tomacaddr' },
+{ oid => '4125', descr => 'set 7th bit in macaddr8',
+ proname => 'macaddr8_set7bit', prorettype => 'macaddr8',
+ proargtypes => 'macaddr8', prosrc => 'macaddr8_set7bit' },
+
+# for inet type support
+{ oid => '910', descr => 'I/O',
+ proname => 'inet_in', prorettype => 'inet', proargtypes => 'cstring',
+ prosrc => 'inet_in' },
+{ oid => '911', descr => 'I/O',
+ proname => 'inet_out', prorettype => 'cstring', proargtypes => 'inet',
+ prosrc => 'inet_out' },
+
+# for cidr type support
+{ oid => '1267', descr => 'I/O',
+ proname => 'cidr_in', prorettype => 'cidr', proargtypes => 'cstring',
+ prosrc => 'cidr_in' },
+{ oid => '1427', descr => 'I/O',
+ proname => 'cidr_out', prorettype => 'cstring', proargtypes => 'cidr',
+ prosrc => 'cidr_out' },
+
+# these are used for both inet and cidr
+{ oid => '920',
+ proname => 'network_eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'inet inet', prosrc => 'network_eq' },
+{ oid => '921',
+ proname => 'network_lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'inet inet', prosrc => 'network_lt' },
+{ oid => '922',
+ proname => 'network_le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'inet inet', prosrc => 'network_le' },
+{ oid => '923',
+ proname => 'network_gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'inet inet', prosrc => 'network_gt' },
+{ oid => '924',
+ proname => 'network_ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'inet inet', prosrc => 'network_ge' },
+{ oid => '925',
+ proname => 'network_ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'inet inet', prosrc => 'network_ne' },
+{ oid => '3562', descr => 'larger of two',
+ proname => 'network_larger', prorettype => 'inet', proargtypes => 'inet inet',
+ prosrc => 'network_larger' },
+{ oid => '3563', descr => 'smaller of two',
+ proname => 'network_smaller', prorettype => 'inet',
+ proargtypes => 'inet inet', prosrc => 'network_smaller' },
+{ oid => '926', descr => 'less-equal-greater',
+ proname => 'network_cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'inet inet', prosrc => 'network_cmp' },
+{ oid => '927',
+ proname => 'network_sub', prosupport => 'network_subset_support',
+ prorettype => 'bool', proargtypes => 'inet inet', prosrc => 'network_sub' },
+{ oid => '928',
+ proname => 'network_subeq', prosupport => 'network_subset_support',
+ prorettype => 'bool', proargtypes => 'inet inet', prosrc => 'network_subeq' },
+{ oid => '929',
+ proname => 'network_sup', prosupport => 'network_subset_support',
+ prorettype => 'bool', proargtypes => 'inet inet', prosrc => 'network_sup' },
+{ oid => '930',
+ proname => 'network_supeq', prosupport => 'network_subset_support',
+ prorettype => 'bool', proargtypes => 'inet inet', prosrc => 'network_supeq' },
+{ oid => '1173', descr => 'planner support for network_sub/superset',
+ proname => 'network_subset_support', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'network_subset_support' },
+
+{ oid => '3551',
+ proname => 'network_overlap', prorettype => 'bool',
+ proargtypes => 'inet inet', prosrc => 'network_overlap' },
+{ oid => '5033', descr => 'sort support',
+ proname => 'network_sortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'network_sortsupport' },
+
+# inet/cidr functions
+{ oid => '598', descr => 'abbreviated display of inet value',
+ proname => 'abbrev', prorettype => 'text', proargtypes => 'inet',
+ prosrc => 'inet_abbrev' },
+{ oid => '599', descr => 'abbreviated display of cidr value',
+ proname => 'abbrev', prorettype => 'text', proargtypes => 'cidr',
+ prosrc => 'cidr_abbrev' },
+{ oid => '605', descr => 'change netmask of inet',
+ proname => 'set_masklen', prorettype => 'inet', proargtypes => 'inet int4',
+ prosrc => 'inet_set_masklen' },
+{ oid => '635', descr => 'change netmask of cidr',
+ proname => 'set_masklen', prorettype => 'cidr', proargtypes => 'cidr int4',
+ prosrc => 'cidr_set_masklen' },
+{ oid => '711', descr => 'address family (4 for IPv4, 6 for IPv6)',
+ proname => 'family', prorettype => 'int4', proargtypes => 'inet',
+ prosrc => 'network_family' },
+{ oid => '683', descr => 'network part of address',
+ proname => 'network', prorettype => 'cidr', proargtypes => 'inet',
+ prosrc => 'network_network' },
+{ oid => '696', descr => 'netmask of address',
+ proname => 'netmask', prorettype => 'inet', proargtypes => 'inet',
+ prosrc => 'network_netmask' },
+{ oid => '697', descr => 'netmask length',
+ proname => 'masklen', prorettype => 'int4', proargtypes => 'inet',
+ prosrc => 'network_masklen' },
+{ oid => '698', descr => 'broadcast address of network',
+ proname => 'broadcast', prorettype => 'inet', proargtypes => 'inet',
+ prosrc => 'network_broadcast' },
+{ oid => '699', descr => 'show address octets only',
+ proname => 'host', prorettype => 'text', proargtypes => 'inet',
+ prosrc => 'network_host' },
+{ oid => '730', descr => 'show all parts of inet/cidr value',
+ proname => 'text', prorettype => 'text', proargtypes => 'inet',
+ prosrc => 'network_show' },
+{ oid => '1362', descr => 'hostmask of address',
+ proname => 'hostmask', prorettype => 'inet', proargtypes => 'inet',
+ prosrc => 'network_hostmask' },
+{ oid => '1715', descr => 'convert inet to cidr',
+ proname => 'cidr', prorettype => 'cidr', proargtypes => 'inet',
+ prosrc => 'inet_to_cidr' },
+
+{ oid => '2196', descr => 'inet address of the client',
+ proname => 'inet_client_addr', proisstrict => 'f', provolatile => 's',
+ proparallel => 'r', prorettype => 'inet', proargtypes => '',
+ prosrc => 'inet_client_addr' },
+{ oid => '2197', descr => 'client\'s port number for this connection',
+ proname => 'inet_client_port', proisstrict => 'f', provolatile => 's',
+ proparallel => 'r', prorettype => 'int4', proargtypes => '',
+ prosrc => 'inet_client_port' },
+{ oid => '2198', descr => 'inet address of the server',
+ proname => 'inet_server_addr', proisstrict => 'f', provolatile => 's',
+ prorettype => 'inet', proargtypes => '', prosrc => 'inet_server_addr' },
+{ oid => '2199', descr => 'server\'s port number for this connection',
+ proname => 'inet_server_port', proisstrict => 'f', provolatile => 's',
+ prorettype => 'int4', proargtypes => '', prosrc => 'inet_server_port' },
+
+{ oid => '2627',
+ proname => 'inetnot', prorettype => 'inet', proargtypes => 'inet',
+ prosrc => 'inetnot' },
+{ oid => '2628',
+ proname => 'inetand', prorettype => 'inet', proargtypes => 'inet inet',
+ prosrc => 'inetand' },
+{ oid => '2629',
+ proname => 'inetor', prorettype => 'inet', proargtypes => 'inet inet',
+ prosrc => 'inetor' },
+{ oid => '2630',
+ proname => 'inetpl', prorettype => 'inet', proargtypes => 'inet int8',
+ prosrc => 'inetpl' },
+{ oid => '2631',
+ proname => 'int8pl_inet', prolang => 'sql', prorettype => 'inet',
+ proargtypes => 'int8 inet', prosrc => 'select $2 + $1' },
+{ oid => '2632',
+ proname => 'inetmi_int8', prorettype => 'inet', proargtypes => 'inet int8',
+ prosrc => 'inetmi_int8' },
+{ oid => '2633',
+ proname => 'inetmi', prorettype => 'int8', proargtypes => 'inet inet',
+ prosrc => 'inetmi' },
+{ oid => '4071', descr => 'are the addresses from the same family?',
+ proname => 'inet_same_family', prorettype => 'bool',
+ proargtypes => 'inet inet', prosrc => 'inet_same_family' },
+{ oid => '4063',
+ descr => 'the smallest network which includes both of the given networks',
+ proname => 'inet_merge', prorettype => 'cidr', proargtypes => 'inet inet',
+ prosrc => 'inet_merge' },
+
+# GiST support for inet and cidr
+{ oid => '3553', descr => 'GiST support',
+ proname => 'inet_gist_consistent', prorettype => 'bool',
+ proargtypes => 'internal inet int2 oid internal',
+ prosrc => 'inet_gist_consistent' },
+{ oid => '3554', descr => 'GiST support',
+ proname => 'inet_gist_union', prorettype => 'inet',
+ proargtypes => 'internal internal', prosrc => 'inet_gist_union' },
+{ oid => '3555', descr => 'GiST support',
+ proname => 'inet_gist_compress', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'inet_gist_compress' },
+{ oid => '3573', descr => 'GiST support',
+ proname => 'inet_gist_fetch', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'inet_gist_fetch' },
+{ oid => '3557', descr => 'GiST support',
+ proname => 'inet_gist_penalty', prorettype => 'internal',
+ proargtypes => 'internal internal internal', prosrc => 'inet_gist_penalty' },
+{ oid => '3558', descr => 'GiST support',
+ proname => 'inet_gist_picksplit', prorettype => 'internal',
+ proargtypes => 'internal internal', prosrc => 'inet_gist_picksplit' },
+{ oid => '3559', descr => 'GiST support',
+ proname => 'inet_gist_same', prorettype => 'internal',
+ proargtypes => 'inet inet internal', prosrc => 'inet_gist_same' },
+
+# SP-GiST support for inet and cidr
+{ oid => '3795', descr => 'SP-GiST support',
+ proname => 'inet_spg_config', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'inet_spg_config' },
+{ oid => '3796', descr => 'SP-GiST support',
+ proname => 'inet_spg_choose', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'inet_spg_choose' },
+{ oid => '3797', descr => 'SP-GiST support',
+ proname => 'inet_spg_picksplit', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'inet_spg_picksplit' },
+{ oid => '3798', descr => 'SP-GiST support',
+ proname => 'inet_spg_inner_consistent', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'inet_spg_inner_consistent' },
+{ oid => '3799', descr => 'SP-GiST support',
+ proname => 'inet_spg_leaf_consistent', prorettype => 'bool',
+ proargtypes => 'internal internal', prosrc => 'inet_spg_leaf_consistent' },
+
+# Selectivity estimation for inet and cidr
+{ oid => '3560', descr => 'restriction selectivity for network operators',
+ proname => 'networksel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'networksel' },
+{ oid => '3561', descr => 'join selectivity for network operators',
+ proname => 'networkjoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'networkjoinsel' },
+
+{ oid => '1690',
+ proname => 'time_mi_time', prorettype => 'interval',
+ proargtypes => 'time time', prosrc => 'time_mi_time' },
+
+{ oid => '1691',
+ proname => 'boolle', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bool bool', prosrc => 'boolle' },
+{ oid => '1692',
+ proname => 'boolge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bool bool', prosrc => 'boolge' },
+{ oid => '1693', descr => 'less-equal-greater',
+ proname => 'btboolcmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'bool bool', prosrc => 'btboolcmp' },
+
+{ oid => '1688', descr => 'hash',
+ proname => 'time_hash', prorettype => 'int4', proargtypes => 'time',
+ prosrc => 'time_hash' },
+{ oid => '3409', descr => 'hash',
+ proname => 'time_hash_extended', prorettype => 'int8',
+ proargtypes => 'time int8', prosrc => 'time_hash_extended' },
+{ oid => '1696', descr => 'hash',
+ proname => 'timetz_hash', prorettype => 'int4', proargtypes => 'timetz',
+ prosrc => 'timetz_hash' },
+{ oid => '3410', descr => 'hash',
+ proname => 'timetz_hash_extended', prorettype => 'int8',
+ proargtypes => 'timetz int8', prosrc => 'timetz_hash_extended' },
+{ oid => '1697', descr => 'hash',
+ proname => 'interval_hash', prorettype => 'int4', proargtypes => 'interval',
+ prosrc => 'interval_hash' },
+{ oid => '3418', descr => 'hash',
+ proname => 'interval_hash_extended', prorettype => 'int8',
+ proargtypes => 'interval int8', prosrc => 'interval_hash_extended' },
+
+# OID's 1700 - 1799 NUMERIC data type
+
+{ oid => '1701', descr => 'I/O',
+ proname => 'numeric_in', prorettype => 'numeric',
+ proargtypes => 'cstring oid int4', prosrc => 'numeric_in' },
+{ oid => '1702', descr => 'I/O',
+ proname => 'numeric_out', prorettype => 'cstring', proargtypes => 'numeric',
+ prosrc => 'numeric_out' },
+{ oid => '2917', descr => 'I/O typmod',
+ proname => 'numerictypmodin', prorettype => 'int4', proargtypes => '_cstring',
+ prosrc => 'numerictypmodin' },
+{ oid => '2918', descr => 'I/O typmod',
+ proname => 'numerictypmodout', prorettype => 'cstring', proargtypes => 'int4',
+ prosrc => 'numerictypmodout' },
+{ oid => '3157', descr => 'planner support for numeric length coercion',
+ proname => 'numeric_support', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'numeric_support' },
+{ oid => '1703', descr => 'adjust numeric to typmod precision/scale',
+ proname => 'numeric', prosupport => 'numeric_support',
+ prorettype => 'numeric', proargtypes => 'numeric int4', prosrc => 'numeric' },
+{ oid => '1704',
+ proname => 'numeric_abs', prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'numeric_abs' },
+{ oid => '1705', descr => 'absolute value',
+ proname => 'abs', prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'numeric_abs' },
+{ oid => '1706', descr => 'sign of value',
+ proname => 'sign', prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'numeric_sign' },
+{ oid => '1707', descr => 'value rounded to \'scale\'',
+ proname => 'round', prorettype => 'numeric', proargtypes => 'numeric int4',
+ prosrc => 'numeric_round' },
+{ oid => '1708', descr => 'value rounded to \'scale\' of zero',
+ proname => 'round', prolang => 'sql', prorettype => 'numeric',
+ proargtypes => 'numeric', prosrc => 'select pg_catalog.round($1,0)' },
+{ oid => '1709', descr => 'value truncated to \'scale\'',
+ proname => 'trunc', prorettype => 'numeric', proargtypes => 'numeric int4',
+ prosrc => 'numeric_trunc' },
+{ oid => '1710', descr => 'value truncated to \'scale\' of zero',
+ proname => 'trunc', prolang => 'sql', prorettype => 'numeric',
+ proargtypes => 'numeric', prosrc => 'select pg_catalog.trunc($1,0)' },
+{ oid => '1711', descr => 'nearest integer >= value',
+ proname => 'ceil', prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'numeric_ceil' },
+{ oid => '2167', descr => 'nearest integer >= value',
+ proname => 'ceiling', prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'numeric_ceil' },
+{ oid => '1712', descr => 'nearest integer <= value',
+ proname => 'floor', prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'numeric_floor' },
+{ oid => '1718',
+ proname => 'numeric_eq', prorettype => 'bool',
+ proargtypes => 'numeric numeric', prosrc => 'numeric_eq' },
+{ oid => '1719',
+ proname => 'numeric_ne', prorettype => 'bool',
+ proargtypes => 'numeric numeric', prosrc => 'numeric_ne' },
+{ oid => '1720',
+ proname => 'numeric_gt', prorettype => 'bool',
+ proargtypes => 'numeric numeric', prosrc => 'numeric_gt' },
+{ oid => '1721',
+ proname => 'numeric_ge', prorettype => 'bool',
+ proargtypes => 'numeric numeric', prosrc => 'numeric_ge' },
+{ oid => '1722',
+ proname => 'numeric_lt', prorettype => 'bool',
+ proargtypes => 'numeric numeric', prosrc => 'numeric_lt' },
+{ oid => '1723',
+ proname => 'numeric_le', prorettype => 'bool',
+ proargtypes => 'numeric numeric', prosrc => 'numeric_le' },
+{ oid => '1724',
+ proname => 'numeric_add', prorettype => 'numeric',
+ proargtypes => 'numeric numeric', prosrc => 'numeric_add' },
+{ oid => '1725',
+ proname => 'numeric_sub', prorettype => 'numeric',
+ proargtypes => 'numeric numeric', prosrc => 'numeric_sub' },
+{ oid => '1726',
+ proname => 'numeric_mul', prorettype => 'numeric',
+ proargtypes => 'numeric numeric', prosrc => 'numeric_mul' },
+{ oid => '1727',
+ proname => 'numeric_div', prorettype => 'numeric',
+ proargtypes => 'numeric numeric', prosrc => 'numeric_div' },
+{ oid => '1728', descr => 'modulus',
+ proname => 'mod', prorettype => 'numeric', proargtypes => 'numeric numeric',
+ prosrc => 'numeric_mod' },
+{ oid => '1729',
+ proname => 'numeric_mod', prorettype => 'numeric',
+ proargtypes => 'numeric numeric', prosrc => 'numeric_mod' },
+{ oid => '5048', descr => 'greatest common divisor',
+ proname => 'gcd', prorettype => 'numeric', proargtypes => 'numeric numeric',
+ prosrc => 'numeric_gcd' },
+{ oid => '5049', descr => 'least common multiple',
+ proname => 'lcm', prorettype => 'numeric', proargtypes => 'numeric numeric',
+ prosrc => 'numeric_lcm' },
+{ oid => '1730', descr => 'square root',
+ proname => 'sqrt', prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'numeric_sqrt' },
+{ oid => '1731', descr => 'square root',
+ proname => 'numeric_sqrt', prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'numeric_sqrt' },
+{ oid => '1732', descr => 'natural exponential (e^x)',
+ proname => 'exp', prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'numeric_exp' },
+{ oid => '1733', descr => 'natural exponential (e^x)',
+ proname => 'numeric_exp', prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'numeric_exp' },
+{ oid => '1734', descr => 'natural logarithm',
+ proname => 'ln', prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'numeric_ln' },
+{ oid => '1735', descr => 'natural logarithm',
+ proname => 'numeric_ln', prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'numeric_ln' },
+{ oid => '1736', descr => 'logarithm base m of n',
+ proname => 'log', prorettype => 'numeric', proargtypes => 'numeric numeric',
+ prosrc => 'numeric_log' },
+{ oid => '1737', descr => 'logarithm base m of n',
+ proname => 'numeric_log', prorettype => 'numeric',
+ proargtypes => 'numeric numeric', prosrc => 'numeric_log' },
+{ oid => '1738', descr => 'exponentiation',
+ proname => 'pow', prorettype => 'numeric', proargtypes => 'numeric numeric',
+ prosrc => 'numeric_power' },
+{ oid => '2169', descr => 'exponentiation',
+ proname => 'power', prorettype => 'numeric', proargtypes => 'numeric numeric',
+ prosrc => 'numeric_power' },
+{ oid => '1739',
+ proname => 'numeric_power', prorettype => 'numeric',
+ proargtypes => 'numeric numeric', prosrc => 'numeric_power' },
+{ oid => '3281', descr => 'number of decimal digits in the fractional part',
+ proname => 'scale', prorettype => 'int4', proargtypes => 'numeric',
+ prosrc => 'numeric_scale' },
+{ oid => '5042', descr => 'minimum scale needed to represent the value',
+ proname => 'min_scale', prorettype => 'int4', proargtypes => 'numeric',
+ prosrc => 'numeric_min_scale' },
+{ oid => '5043',
+ descr => 'numeric with minimum scale needed to represent the value',
+ proname => 'trim_scale', prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'numeric_trim_scale' },
+{ oid => '1740', descr => 'convert int4 to numeric',
+ proname => 'numeric', prorettype => 'numeric', proargtypes => 'int4',
+ prosrc => 'int4_numeric' },
+{ oid => '1741', descr => 'base 10 logarithm',
+ proname => 'log', prolang => 'sql', prorettype => 'numeric',
+ proargtypes => 'numeric', prosrc => 'select pg_catalog.log(10, $1)' },
+{ oid => '1481', descr => 'base 10 logarithm',
+ proname => 'log10', prolang => 'sql', prorettype => 'numeric',
+ proargtypes => 'numeric', prosrc => 'select pg_catalog.log(10, $1)' },
+{ oid => '1742', descr => 'convert float4 to numeric',
+ proname => 'numeric', prorettype => 'numeric', proargtypes => 'float4',
+ prosrc => 'float4_numeric' },
+{ oid => '1743', descr => 'convert float8 to numeric',
+ proname => 'numeric', prorettype => 'numeric', proargtypes => 'float8',
+ prosrc => 'float8_numeric' },
+{ oid => '1744', descr => 'convert numeric to int4',
+ proname => 'int4', prorettype => 'int4', proargtypes => 'numeric',
+ prosrc => 'numeric_int4' },
+{ oid => '1745', descr => 'convert numeric to float4',
+ proname => 'float4', prorettype => 'float4', proargtypes => 'numeric',
+ prosrc => 'numeric_float4' },
+{ oid => '1746', descr => 'convert numeric to float8',
+ proname => 'float8', prorettype => 'float8', proargtypes => 'numeric',
+ prosrc => 'numeric_float8' },
+{ oid => '1973', descr => 'trunc(x/y)',
+ proname => 'div', prorettype => 'numeric', proargtypes => 'numeric numeric',
+ prosrc => 'numeric_div_trunc' },
+{ oid => '1980', descr => 'trunc(x/y)',
+ proname => 'numeric_div_trunc', prorettype => 'numeric',
+ proargtypes => 'numeric numeric', prosrc => 'numeric_div_trunc' },
+{ oid => '2170', descr => 'bucket number of operand in equal-width histogram',
+ proname => 'width_bucket', prorettype => 'int4',
+ proargtypes => 'numeric numeric numeric int4',
+ prosrc => 'width_bucket_numeric' },
+
+{ oid => '1747',
+ proname => 'time_pl_interval', prorettype => 'time',
+ proargtypes => 'time interval', prosrc => 'time_pl_interval' },
+{ oid => '1748',
+ proname => 'time_mi_interval', prorettype => 'time',
+ proargtypes => 'time interval', prosrc => 'time_mi_interval' },
+{ oid => '1749',
+ proname => 'timetz_pl_interval', prorettype => 'timetz',
+ proargtypes => 'timetz interval', prosrc => 'timetz_pl_interval' },
+{ oid => '1750',
+ proname => 'timetz_mi_interval', prorettype => 'timetz',
+ proargtypes => 'timetz interval', prosrc => 'timetz_mi_interval' },
+
+{ oid => '1764', descr => 'increment by one',
+ proname => 'numeric_inc', prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'numeric_inc' },
+{ oid => '1766', descr => 'smaller of two',
+ proname => 'numeric_smaller', prorettype => 'numeric',
+ proargtypes => 'numeric numeric', prosrc => 'numeric_smaller' },
+{ oid => '1767', descr => 'larger of two',
+ proname => 'numeric_larger', prorettype => 'numeric',
+ proargtypes => 'numeric numeric', prosrc => 'numeric_larger' },
+{ oid => '1769', descr => 'less-equal-greater',
+ proname => 'numeric_cmp', prorettype => 'int4',
+ proargtypes => 'numeric numeric', prosrc => 'numeric_cmp' },
+{ oid => '3283', descr => 'sort support',
+ proname => 'numeric_sortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'numeric_sortsupport' },
+{ oid => '1771',
+ proname => 'numeric_uminus', prorettype => 'numeric',
+ proargtypes => 'numeric', prosrc => 'numeric_uminus' },
+{ oid => '1779', descr => 'convert numeric to int8',
+ proname => 'int8', prorettype => 'int8', proargtypes => 'numeric',
+ prosrc => 'numeric_int8' },
+{ oid => '1781', descr => 'convert int8 to numeric',
+ proname => 'numeric', prorettype => 'numeric', proargtypes => 'int8',
+ prosrc => 'int8_numeric' },
+{ oid => '1782', descr => 'convert int2 to numeric',
+ proname => 'numeric', prorettype => 'numeric', proargtypes => 'int2',
+ prosrc => 'int2_numeric' },
+{ oid => '1783', descr => 'convert numeric to int2',
+ proname => 'int2', prorettype => 'int2', proargtypes => 'numeric',
+ prosrc => 'numeric_int2' },
+
+{ oid => '3556', descr => 'convert jsonb to boolean',
+ proname => 'bool', prorettype => 'bool', proargtypes => 'jsonb',
+ prosrc => 'jsonb_bool' },
+{ oid => '3449', descr => 'convert jsonb to numeric',
+ proname => 'numeric', prorettype => 'numeric', proargtypes => 'jsonb',
+ prosrc => 'jsonb_numeric' },
+{ oid => '3450', descr => 'convert jsonb to int2',
+ proname => 'int2', prorettype => 'int2', proargtypes => 'jsonb',
+ prosrc => 'jsonb_int2' },
+{ oid => '3451', descr => 'convert jsonb to int4',
+ proname => 'int4', prorettype => 'int4', proargtypes => 'jsonb',
+ prosrc => 'jsonb_int4' },
+{ oid => '3452', descr => 'convert jsonb to int8',
+ proname => 'int8', prorettype => 'int8', proargtypes => 'jsonb',
+ prosrc => 'jsonb_int8' },
+{ oid => '3453', descr => 'convert jsonb to float4',
+ proname => 'float4', prorettype => 'float4', proargtypes => 'jsonb',
+ prosrc => 'jsonb_float4' },
+{ oid => '2580', descr => 'convert jsonb to float8',
+ proname => 'float8', prorettype => 'float8', proargtypes => 'jsonb',
+ prosrc => 'jsonb_float8' },
+
+# formatting
+{ oid => '1770', descr => 'format timestamp with time zone to text',
+ proname => 'to_char', provolatile => 's', prorettype => 'text',
+ proargtypes => 'timestamptz text', prosrc => 'timestamptz_to_char' },
+{ oid => '1772', descr => 'format numeric to text',
+ proname => 'to_char', provolatile => 's', prorettype => 'text',
+ proargtypes => 'numeric text', prosrc => 'numeric_to_char' },
+{ oid => '1773', descr => 'format int4 to text',
+ proname => 'to_char', provolatile => 's', prorettype => 'text',
+ proargtypes => 'int4 text', prosrc => 'int4_to_char' },
+{ oid => '1774', descr => 'format int8 to text',
+ proname => 'to_char', provolatile => 's', prorettype => 'text',
+ proargtypes => 'int8 text', prosrc => 'int8_to_char' },
+{ oid => '1775', descr => 'format float4 to text',
+ proname => 'to_char', provolatile => 's', prorettype => 'text',
+ proargtypes => 'float4 text', prosrc => 'float4_to_char' },
+{ oid => '1776', descr => 'format float8 to text',
+ proname => 'to_char', provolatile => 's', prorettype => 'text',
+ proargtypes => 'float8 text', prosrc => 'float8_to_char' },
+{ oid => '1777', descr => 'convert text to numeric',
+ proname => 'to_number', provolatile => 's', prorettype => 'numeric',
+ proargtypes => 'text text', prosrc => 'numeric_to_number' },
+{ oid => '1778', descr => 'convert text to timestamp with time zone',
+ proname => 'to_timestamp', provolatile => 's', prorettype => 'timestamptz',
+ proargtypes => 'text text', prosrc => 'to_timestamp' },
+{ oid => '1780', descr => 'convert text to date',
+ proname => 'to_date', provolatile => 's', prorettype => 'date',
+ proargtypes => 'text text', prosrc => 'to_date' },
+{ oid => '1768', descr => 'format interval to text',
+ proname => 'to_char', provolatile => 's', prorettype => 'text',
+ proargtypes => 'interval text', prosrc => 'interval_to_char' },
+
+{ oid => '1282', descr => 'quote an identifier for usage in a querystring',
+ proname => 'quote_ident', prorettype => 'text', proargtypes => 'text',
+ prosrc => 'quote_ident' },
+{ oid => '1283', descr => 'quote a literal for usage in a querystring',
+ proname => 'quote_literal', prorettype => 'text', proargtypes => 'text',
+ prosrc => 'quote_literal' },
+{ oid => '1285', descr => 'quote a data value for usage in a querystring',
+ proname => 'quote_literal', prolang => 'sql', provolatile => 's',
+ prorettype => 'text', proargtypes => 'anyelement',
+ prosrc => 'select pg_catalog.quote_literal($1::pg_catalog.text)' },
+{ oid => '1289',
+ descr => 'quote a possibly-null literal for usage in a querystring',
+ proname => 'quote_nullable', proisstrict => 'f', prorettype => 'text',
+ proargtypes => 'text', prosrc => 'quote_nullable' },
+{ oid => '1290',
+ descr => 'quote a possibly-null data value for usage in a querystring',
+ proname => 'quote_nullable', prolang => 'sql', proisstrict => 'f',
+ provolatile => 's', prorettype => 'text', proargtypes => 'anyelement',
+ prosrc => 'select pg_catalog.quote_nullable($1::pg_catalog.text)' },
+
+{ oid => '1798', descr => 'I/O',
+ proname => 'oidin', prorettype => 'oid', proargtypes => 'cstring',
+ prosrc => 'oidin' },
+{ oid => '1799', descr => 'I/O',
+ proname => 'oidout', prorettype => 'cstring', proargtypes => 'oid',
+ prosrc => 'oidout' },
+
+{ oid => '3058', descr => 'concatenate values',
+ proname => 'concat', provariadic => 'any', proisstrict => 'f',
+ provolatile => 's', prorettype => 'text', proargtypes => 'any',
+ proallargtypes => '{any}', proargmodes => '{v}', prosrc => 'text_concat' },
+{ oid => '3059', descr => 'concatenate values with separators',
+ proname => 'concat_ws', provariadic => 'any', proisstrict => 'f',
+ provolatile => 's', prorettype => 'text', proargtypes => 'text any',
+ proallargtypes => '{text,any}', proargmodes => '{i,v}',
+ prosrc => 'text_concat_ws' },
+{ oid => '3060', descr => 'extract the first n characters',
+ proname => 'left', prorettype => 'text', proargtypes => 'text int4',
+ prosrc => 'text_left' },
+{ oid => '3061', descr => 'extract the last n characters',
+ proname => 'right', prorettype => 'text', proargtypes => 'text int4',
+ prosrc => 'text_right' },
+{ oid => '3062', descr => 'reverse text',
+ proname => 'reverse', prorettype => 'text', proargtypes => 'text',
+ prosrc => 'text_reverse' },
+{ oid => '3539', descr => 'format text message',
+ proname => 'format', provariadic => 'any', proisstrict => 'f',
+ provolatile => 's', prorettype => 'text', proargtypes => 'text any',
+ proallargtypes => '{text,any}', proargmodes => '{i,v}',
+ prosrc => 'text_format' },
+{ oid => '3540', descr => 'format text message',
+ proname => 'format', proisstrict => 'f', provolatile => 's',
+ prorettype => 'text', proargtypes => 'text', prosrc => 'text_format_nv' },
+
+{ oid => '1810', descr => 'length in bits',
+ proname => 'bit_length', prolang => 'sql', prorettype => 'int4',
+ proargtypes => 'bytea', prosrc => 'select pg_catalog.octet_length($1) * 8' },
+{ oid => '1811', descr => 'length in bits',
+ proname => 'bit_length', prolang => 'sql', prorettype => 'int4',
+ proargtypes => 'text', prosrc => 'select pg_catalog.octet_length($1) * 8' },
+{ oid => '1812', descr => 'length in bits',
+ proname => 'bit_length', prolang => 'sql', prorettype => 'int4',
+ proargtypes => 'bit', prosrc => 'select pg_catalog.length($1)' },
+
+# Selectivity estimators for LIKE and related operators
+{ oid => '1814', descr => 'restriction selectivity of ILIKE',
+ proname => 'iclikesel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'iclikesel' },
+{ oid => '1815', descr => 'restriction selectivity of NOT ILIKE',
+ proname => 'icnlikesel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'icnlikesel' },
+{ oid => '1816', descr => 'join selectivity of ILIKE',
+ proname => 'iclikejoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'iclikejoinsel' },
+{ oid => '1817', descr => 'join selectivity of NOT ILIKE',
+ proname => 'icnlikejoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'icnlikejoinsel' },
+{ oid => '1818', descr => 'restriction selectivity of regex match',
+ proname => 'regexeqsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'regexeqsel' },
+{ oid => '1819', descr => 'restriction selectivity of LIKE',
+ proname => 'likesel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'likesel' },
+{ oid => '1820',
+ descr => 'restriction selectivity of case-insensitive regex match',
+ proname => 'icregexeqsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'icregexeqsel' },
+{ oid => '1821', descr => 'restriction selectivity of regex non-match',
+ proname => 'regexnesel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'regexnesel' },
+{ oid => '1822', descr => 'restriction selectivity of NOT LIKE',
+ proname => 'nlikesel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'nlikesel' },
+{ oid => '1823',
+ descr => 'restriction selectivity of case-insensitive regex non-match',
+ proname => 'icregexnesel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'icregexnesel' },
+{ oid => '1824', descr => 'join selectivity of regex match',
+ proname => 'regexeqjoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'regexeqjoinsel' },
+{ oid => '1825', descr => 'join selectivity of LIKE',
+ proname => 'likejoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'likejoinsel' },
+{ oid => '1826', descr => 'join selectivity of case-insensitive regex match',
+ proname => 'icregexeqjoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'icregexeqjoinsel' },
+{ oid => '1827', descr => 'join selectivity of regex non-match',
+ proname => 'regexnejoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'regexnejoinsel' },
+{ oid => '1828', descr => 'join selectivity of NOT LIKE',
+ proname => 'nlikejoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'nlikejoinsel' },
+{ oid => '1829',
+ descr => 'join selectivity of case-insensitive regex non-match',
+ proname => 'icregexnejoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'icregexnejoinsel' },
+{ oid => '3437', descr => 'restriction selectivity of exact prefix',
+ proname => 'prefixsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'prefixsel' },
+{ oid => '3438', descr => 'join selectivity of exact prefix',
+ proname => 'prefixjoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'prefixjoinsel' },
+
+# Aggregate-related functions
+{ oid => '1830', descr => 'aggregate final function',
+ proname => 'float8_avg', prorettype => 'float8', proargtypes => '_float8',
+ prosrc => 'float8_avg' },
+{ oid => '2512', descr => 'aggregate final function',
+ proname => 'float8_var_pop', prorettype => 'float8', proargtypes => '_float8',
+ prosrc => 'float8_var_pop' },
+{ oid => '1831', descr => 'aggregate final function',
+ proname => 'float8_var_samp', prorettype => 'float8',
+ proargtypes => '_float8', prosrc => 'float8_var_samp' },
+{ oid => '2513', descr => 'aggregate final function',
+ proname => 'float8_stddev_pop', prorettype => 'float8',
+ proargtypes => '_float8', prosrc => 'float8_stddev_pop' },
+{ oid => '1832', descr => 'aggregate final function',
+ proname => 'float8_stddev_samp', prorettype => 'float8',
+ proargtypes => '_float8', prosrc => 'float8_stddev_samp' },
+{ oid => '1833', descr => 'aggregate transition function',
+ proname => 'numeric_accum', proisstrict => 'f', prorettype => 'internal',
+ proargtypes => 'internal numeric', prosrc => 'numeric_accum' },
+{ oid => '3341', descr => 'aggregate combine function',
+ proname => 'numeric_combine', proisstrict => 'f', prorettype => 'internal',
+ proargtypes => 'internal internal', prosrc => 'numeric_combine' },
+{ oid => '2858', descr => 'aggregate transition function',
+ proname => 'numeric_avg_accum', proisstrict => 'f', prorettype => 'internal',
+ proargtypes => 'internal numeric', prosrc => 'numeric_avg_accum' },
+{ oid => '3337', descr => 'aggregate combine function',
+ proname => 'numeric_avg_combine', proisstrict => 'f',
+ prorettype => 'internal', proargtypes => 'internal internal',
+ prosrc => 'numeric_avg_combine' },
+{ oid => '2740', descr => 'aggregate serial function',
+ proname => 'numeric_avg_serialize', prorettype => 'bytea',
+ proargtypes => 'internal', prosrc => 'numeric_avg_serialize' },
+{ oid => '2741', descr => 'aggregate deserial function',
+ proname => 'numeric_avg_deserialize', prorettype => 'internal',
+ proargtypes => 'bytea internal', prosrc => 'numeric_avg_deserialize' },
+{ oid => '3335', descr => 'aggregate serial function',
+ proname => 'numeric_serialize', prorettype => 'bytea',
+ proargtypes => 'internal', prosrc => 'numeric_serialize' },
+{ oid => '3336', descr => 'aggregate deserial function',
+ proname => 'numeric_deserialize', prorettype => 'internal',
+ proargtypes => 'bytea internal', prosrc => 'numeric_deserialize' },
+{ oid => '3548', descr => 'aggregate transition function',
+ proname => 'numeric_accum_inv', proisstrict => 'f', prorettype => 'internal',
+ proargtypes => 'internal numeric', prosrc => 'numeric_accum_inv' },
+{ oid => '1834', descr => 'aggregate transition function',
+ proname => 'int2_accum', proisstrict => 'f', prorettype => 'internal',
+ proargtypes => 'internal int2', prosrc => 'int2_accum' },
+{ oid => '1835', descr => 'aggregate transition function',
+ proname => 'int4_accum', proisstrict => 'f', prorettype => 'internal',
+ proargtypes => 'internal int4', prosrc => 'int4_accum' },
+{ oid => '1836', descr => 'aggregate transition function',
+ proname => 'int8_accum', proisstrict => 'f', prorettype => 'internal',
+ proargtypes => 'internal int8', prosrc => 'int8_accum' },
+{ oid => '3338', descr => 'aggregate combine function',
+ proname => 'numeric_poly_combine', proisstrict => 'f',
+ prorettype => 'internal', proargtypes => 'internal internal',
+ prosrc => 'numeric_poly_combine' },
+{ oid => '3339', descr => 'aggregate serial function',
+ proname => 'numeric_poly_serialize', prorettype => 'bytea',
+ proargtypes => 'internal', prosrc => 'numeric_poly_serialize' },
+{ oid => '3340', descr => 'aggregate deserial function',
+ proname => 'numeric_poly_deserialize', prorettype => 'internal',
+ proargtypes => 'bytea internal', prosrc => 'numeric_poly_deserialize' },
+{ oid => '2746', descr => 'aggregate transition function',
+ proname => 'int8_avg_accum', proisstrict => 'f', prorettype => 'internal',
+ proargtypes => 'internal int8', prosrc => 'int8_avg_accum' },
+{ oid => '3567', descr => 'aggregate transition function',
+ proname => 'int2_accum_inv', proisstrict => 'f', prorettype => 'internal',
+ proargtypes => 'internal int2', prosrc => 'int2_accum_inv' },
+{ oid => '3568', descr => 'aggregate transition function',
+ proname => 'int4_accum_inv', proisstrict => 'f', prorettype => 'internal',
+ proargtypes => 'internal int4', prosrc => 'int4_accum_inv' },
+{ oid => '3569', descr => 'aggregate transition function',
+ proname => 'int8_accum_inv', proisstrict => 'f', prorettype => 'internal',
+ proargtypes => 'internal int8', prosrc => 'int8_accum_inv' },
+{ oid => '3387', descr => 'aggregate transition function',
+ proname => 'int8_avg_accum_inv', proisstrict => 'f', prorettype => 'internal',
+ proargtypes => 'internal int8', prosrc => 'int8_avg_accum_inv' },
+{ oid => '2785', descr => 'aggregate combine function',
+ proname => 'int8_avg_combine', proisstrict => 'f', prorettype => 'internal',
+ proargtypes => 'internal internal', prosrc => 'int8_avg_combine' },
+{ oid => '2786', descr => 'aggregate serial function',
+ proname => 'int8_avg_serialize', prorettype => 'bytea',
+ proargtypes => 'internal', prosrc => 'int8_avg_serialize' },
+{ oid => '2787', descr => 'aggregate deserial function',
+ proname => 'int8_avg_deserialize', prorettype => 'internal',
+ proargtypes => 'bytea internal', prosrc => 'int8_avg_deserialize' },
+{ oid => '3324', descr => 'aggregate combine function',
+ proname => 'int4_avg_combine', prorettype => '_int8',
+ proargtypes => '_int8 _int8', prosrc => 'int4_avg_combine' },
+{ oid => '3178', descr => 'aggregate final function',
+ proname => 'numeric_sum', proisstrict => 'f', prorettype => 'numeric',
+ proargtypes => 'internal', prosrc => 'numeric_sum' },
+{ oid => '1837', descr => 'aggregate final function',
+ proname => 'numeric_avg', proisstrict => 'f', prorettype => 'numeric',
+ proargtypes => 'internal', prosrc => 'numeric_avg' },
+{ oid => '2514', descr => 'aggregate final function',
+ proname => 'numeric_var_pop', proisstrict => 'f', prorettype => 'numeric',
+ proargtypes => 'internal', prosrc => 'numeric_var_pop' },
+{ oid => '1838', descr => 'aggregate final function',
+ proname => 'numeric_var_samp', proisstrict => 'f', prorettype => 'numeric',
+ proargtypes => 'internal', prosrc => 'numeric_var_samp' },
+{ oid => '2596', descr => 'aggregate final function',
+ proname => 'numeric_stddev_pop', proisstrict => 'f', prorettype => 'numeric',
+ proargtypes => 'internal', prosrc => 'numeric_stddev_pop' },
+{ oid => '1839', descr => 'aggregate final function',
+ proname => 'numeric_stddev_samp', proisstrict => 'f', prorettype => 'numeric',
+ proargtypes => 'internal', prosrc => 'numeric_stddev_samp' },
+{ oid => '1840', descr => 'aggregate transition function',
+ proname => 'int2_sum', proisstrict => 'f', prorettype => 'int8',
+ proargtypes => 'int8 int2', prosrc => 'int2_sum' },
+{ oid => '1841', descr => 'aggregate transition function',
+ proname => 'int4_sum', proisstrict => 'f', prorettype => 'int8',
+ proargtypes => 'int8 int4', prosrc => 'int4_sum' },
+{ oid => '1842', descr => 'aggregate transition function',
+ proname => 'int8_sum', proisstrict => 'f', prorettype => 'numeric',
+ proargtypes => 'numeric int8', prosrc => 'int8_sum' },
+{ oid => '3388', descr => 'aggregate final function',
+ proname => 'numeric_poly_sum', proisstrict => 'f', prorettype => 'numeric',
+ proargtypes => 'internal', prosrc => 'numeric_poly_sum' },
+{ oid => '3389', descr => 'aggregate final function',
+ proname => 'numeric_poly_avg', proisstrict => 'f', prorettype => 'numeric',
+ proargtypes => 'internal', prosrc => 'numeric_poly_avg' },
+{ oid => '3390', descr => 'aggregate final function',
+ proname => 'numeric_poly_var_pop', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'internal',
+ prosrc => 'numeric_poly_var_pop' },
+{ oid => '3391', descr => 'aggregate final function',
+ proname => 'numeric_poly_var_samp', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'internal',
+ prosrc => 'numeric_poly_var_samp' },
+{ oid => '3392', descr => 'aggregate final function',
+ proname => 'numeric_poly_stddev_pop', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'internal',
+ prosrc => 'numeric_poly_stddev_pop' },
+{ oid => '3393', descr => 'aggregate final function',
+ proname => 'numeric_poly_stddev_samp', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'internal',
+ prosrc => 'numeric_poly_stddev_samp' },
+
+{ oid => '1843', descr => 'aggregate transition function',
+ proname => 'interval_accum', prorettype => '_interval',
+ proargtypes => '_interval interval', prosrc => 'interval_accum' },
+{ oid => '3325', descr => 'aggregate combine function',
+ proname => 'interval_combine', prorettype => '_interval',
+ proargtypes => '_interval _interval', prosrc => 'interval_combine' },
+{ oid => '3549', descr => 'aggregate transition function',
+ proname => 'interval_accum_inv', prorettype => '_interval',
+ proargtypes => '_interval interval', prosrc => 'interval_accum_inv' },
+{ oid => '1844', descr => 'aggregate final function',
+ proname => 'interval_avg', prorettype => 'interval',
+ proargtypes => '_interval', prosrc => 'interval_avg' },
+{ oid => '1962', descr => 'aggregate transition function',
+ proname => 'int2_avg_accum', prorettype => '_int8',
+ proargtypes => '_int8 int2', prosrc => 'int2_avg_accum' },
+{ oid => '1963', descr => 'aggregate transition function',
+ proname => 'int4_avg_accum', prorettype => '_int8',
+ proargtypes => '_int8 int4', prosrc => 'int4_avg_accum' },
+{ oid => '3570', descr => 'aggregate transition function',
+ proname => 'int2_avg_accum_inv', prorettype => '_int8',
+ proargtypes => '_int8 int2', prosrc => 'int2_avg_accum_inv' },
+{ oid => '3571', descr => 'aggregate transition function',
+ proname => 'int4_avg_accum_inv', prorettype => '_int8',
+ proargtypes => '_int8 int4', prosrc => 'int4_avg_accum_inv' },
+{ oid => '1964', descr => 'aggregate final function',
+ proname => 'int8_avg', prorettype => 'numeric', proargtypes => '_int8',
+ prosrc => 'int8_avg' },
+{ oid => '3572', descr => 'aggregate final function',
+ proname => 'int2int4_sum', prorettype => 'int8', proargtypes => '_int8',
+ prosrc => 'int2int4_sum' },
+{ oid => '2805', descr => 'aggregate transition function',
+ proname => 'int8inc_float8_float8', prorettype => 'int8',
+ proargtypes => 'int8 float8 float8', prosrc => 'int8inc_float8_float8' },
+{ oid => '2806', descr => 'aggregate transition function',
+ proname => 'float8_regr_accum', prorettype => '_float8',
+ proargtypes => '_float8 float8 float8', prosrc => 'float8_regr_accum' },
+{ oid => '3342', descr => 'aggregate combine function',
+ proname => 'float8_regr_combine', prorettype => '_float8',
+ proargtypes => '_float8 _float8', prosrc => 'float8_regr_combine' },
+{ oid => '2807', descr => 'aggregate final function',
+ proname => 'float8_regr_sxx', prorettype => 'float8',
+ proargtypes => '_float8', prosrc => 'float8_regr_sxx' },
+{ oid => '2808', descr => 'aggregate final function',
+ proname => 'float8_regr_syy', prorettype => 'float8',
+ proargtypes => '_float8', prosrc => 'float8_regr_syy' },
+{ oid => '2809', descr => 'aggregate final function',
+ proname => 'float8_regr_sxy', prorettype => 'float8',
+ proargtypes => '_float8', prosrc => 'float8_regr_sxy' },
+{ oid => '2810', descr => 'aggregate final function',
+ proname => 'float8_regr_avgx', prorettype => 'float8',
+ proargtypes => '_float8', prosrc => 'float8_regr_avgx' },
+{ oid => '2811', descr => 'aggregate final function',
+ proname => 'float8_regr_avgy', prorettype => 'float8',
+ proargtypes => '_float8', prosrc => 'float8_regr_avgy' },
+{ oid => '2812', descr => 'aggregate final function',
+ proname => 'float8_regr_r2', prorettype => 'float8', proargtypes => '_float8',
+ prosrc => 'float8_regr_r2' },
+{ oid => '2813', descr => 'aggregate final function',
+ proname => 'float8_regr_slope', prorettype => 'float8',
+ proargtypes => '_float8', prosrc => 'float8_regr_slope' },
+{ oid => '2814', descr => 'aggregate final function',
+ proname => 'float8_regr_intercept', prorettype => 'float8',
+ proargtypes => '_float8', prosrc => 'float8_regr_intercept' },
+{ oid => '2815', descr => 'aggregate final function',
+ proname => 'float8_covar_pop', prorettype => 'float8',
+ proargtypes => '_float8', prosrc => 'float8_covar_pop' },
+{ oid => '2816', descr => 'aggregate final function',
+ proname => 'float8_covar_samp', prorettype => 'float8',
+ proargtypes => '_float8', prosrc => 'float8_covar_samp' },
+{ oid => '2817', descr => 'aggregate final function',
+ proname => 'float8_corr', prorettype => 'float8', proargtypes => '_float8',
+ prosrc => 'float8_corr' },
+
+{ oid => '3535', descr => 'aggregate transition function',
+ proname => 'string_agg_transfn', proisstrict => 'f', prorettype => 'internal',
+ proargtypes => 'internal text text', prosrc => 'string_agg_transfn' },
+{ oid => '3536', descr => 'aggregate final function',
+ proname => 'string_agg_finalfn', proisstrict => 'f', prorettype => 'text',
+ proargtypes => 'internal', prosrc => 'string_agg_finalfn' },
+{ oid => '3538', descr => 'concatenate aggregate input into a string',
+ proname => 'string_agg', prokind => 'a', proisstrict => 'f',
+ prorettype => 'text', proargtypes => 'text text',
+ prosrc => 'aggregate_dummy' },
+{ oid => '3543', descr => 'aggregate transition function',
+ proname => 'bytea_string_agg_transfn', proisstrict => 'f',
+ prorettype => 'internal', proargtypes => 'internal bytea bytea',
+ prosrc => 'bytea_string_agg_transfn' },
+{ oid => '3544', descr => 'aggregate final function',
+ proname => 'bytea_string_agg_finalfn', proisstrict => 'f',
+ prorettype => 'bytea', proargtypes => 'internal',
+ prosrc => 'bytea_string_agg_finalfn' },
+{ oid => '3545', descr => 'concatenate aggregate input into a bytea',
+ proname => 'string_agg', prokind => 'a', proisstrict => 'f',
+ prorettype => 'bytea', proargtypes => 'bytea bytea',
+ prosrc => 'aggregate_dummy' },
+
+# To ASCII conversion
+{ oid => '1845', descr => 'encode text from DB encoding to ASCII text',
+ proname => 'to_ascii', prorettype => 'text', proargtypes => 'text',
+ prosrc => 'to_ascii_default' },
+{ oid => '1846', descr => 'encode text from encoding to ASCII text',
+ proname => 'to_ascii', prorettype => 'text', proargtypes => 'text int4',
+ prosrc => 'to_ascii_enc' },
+{ oid => '1847', descr => 'encode text from encoding to ASCII text',
+ proname => 'to_ascii', prorettype => 'text', proargtypes => 'text name',
+ prosrc => 'to_ascii_encname' },
+
+{ oid => '1848',
+ proname => 'interval_pl_time', prolang => 'sql', prorettype => 'time',
+ proargtypes => 'interval time', prosrc => 'select $2 + $1' },
+
+{ oid => '1850',
+ proname => 'int28eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int2 int8', prosrc => 'int28eq' },
+{ oid => '1851',
+ proname => 'int28ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int2 int8', prosrc => 'int28ne' },
+{ oid => '1852',
+ proname => 'int28lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int2 int8', prosrc => 'int28lt' },
+{ oid => '1853',
+ proname => 'int28gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int2 int8', prosrc => 'int28gt' },
+{ oid => '1854',
+ proname => 'int28le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int2 int8', prosrc => 'int28le' },
+{ oid => '1855',
+ proname => 'int28ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int2 int8', prosrc => 'int28ge' },
+
+{ oid => '1856',
+ proname => 'int82eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int8 int2', prosrc => 'int82eq' },
+{ oid => '1857',
+ proname => 'int82ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int8 int2', prosrc => 'int82ne' },
+{ oid => '1858',
+ proname => 'int82lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int8 int2', prosrc => 'int82lt' },
+{ oid => '1859',
+ proname => 'int82gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int8 int2', prosrc => 'int82gt' },
+{ oid => '1860',
+ proname => 'int82le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int8 int2', prosrc => 'int82le' },
+{ oid => '1861',
+ proname => 'int82ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'int8 int2', prosrc => 'int82ge' },
+
+{ oid => '1892',
+ proname => 'int2and', prorettype => 'int2', proargtypes => 'int2 int2',
+ prosrc => 'int2and' },
+{ oid => '1893',
+ proname => 'int2or', prorettype => 'int2', proargtypes => 'int2 int2',
+ prosrc => 'int2or' },
+{ oid => '1894',
+ proname => 'int2xor', prorettype => 'int2', proargtypes => 'int2 int2',
+ prosrc => 'int2xor' },
+{ oid => '1895',
+ proname => 'int2not', prorettype => 'int2', proargtypes => 'int2',
+ prosrc => 'int2not' },
+{ oid => '1896',
+ proname => 'int2shl', prorettype => 'int2', proargtypes => 'int2 int4',
+ prosrc => 'int2shl' },
+{ oid => '1897',
+ proname => 'int2shr', prorettype => 'int2', proargtypes => 'int2 int4',
+ prosrc => 'int2shr' },
+
+{ oid => '1898',
+ proname => 'int4and', prorettype => 'int4', proargtypes => 'int4 int4',
+ prosrc => 'int4and' },
+{ oid => '1899',
+ proname => 'int4or', prorettype => 'int4', proargtypes => 'int4 int4',
+ prosrc => 'int4or' },
+{ oid => '1900',
+ proname => 'int4xor', prorettype => 'int4', proargtypes => 'int4 int4',
+ prosrc => 'int4xor' },
+{ oid => '1901',
+ proname => 'int4not', prorettype => 'int4', proargtypes => 'int4',
+ prosrc => 'int4not' },
+{ oid => '1902',
+ proname => 'int4shl', prorettype => 'int4', proargtypes => 'int4 int4',
+ prosrc => 'int4shl' },
+{ oid => '1903',
+ proname => 'int4shr', prorettype => 'int4', proargtypes => 'int4 int4',
+ prosrc => 'int4shr' },
+
+{ oid => '1904',
+ proname => 'int8and', prorettype => 'int8', proargtypes => 'int8 int8',
+ prosrc => 'int8and' },
+{ oid => '1905',
+ proname => 'int8or', prorettype => 'int8', proargtypes => 'int8 int8',
+ prosrc => 'int8or' },
+{ oid => '1906',
+ proname => 'int8xor', prorettype => 'int8', proargtypes => 'int8 int8',
+ prosrc => 'int8xor' },
+{ oid => '1907',
+ proname => 'int8not', prorettype => 'int8', proargtypes => 'int8',
+ prosrc => 'int8not' },
+{ oid => '1908',
+ proname => 'int8shl', prorettype => 'int8', proargtypes => 'int8 int4',
+ prosrc => 'int8shl' },
+{ oid => '1909',
+ proname => 'int8shr', prorettype => 'int8', proargtypes => 'int8 int4',
+ prosrc => 'int8shr' },
+
+{ oid => '1910',
+ proname => 'int8up', prorettype => 'int8', proargtypes => 'int8',
+ prosrc => 'int8up' },
+{ oid => '1911',
+ proname => 'int2up', prorettype => 'int2', proargtypes => 'int2',
+ prosrc => 'int2up' },
+{ oid => '1912',
+ proname => 'int4up', prorettype => 'int4', proargtypes => 'int4',
+ prosrc => 'int4up' },
+{ oid => '1913',
+ proname => 'float4up', prorettype => 'float4', proargtypes => 'float4',
+ prosrc => 'float4up' },
+{ oid => '1914',
+ proname => 'float8up', prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'float8up' },
+{ oid => '1915',
+ proname => 'numeric_uplus', prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'numeric_uplus' },
+
+{ oid => '1922', descr => 'user privilege on relation by username, rel name',
+ proname => 'has_table_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name text text', prosrc => 'has_table_privilege_name_name' },
+{ oid => '1923', descr => 'user privilege on relation by username, rel oid',
+ proname => 'has_table_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name oid text', prosrc => 'has_table_privilege_name_id' },
+{ oid => '1924', descr => 'user privilege on relation by user oid, rel name',
+ proname => 'has_table_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text text', prosrc => 'has_table_privilege_id_name' },
+{ oid => '1925', descr => 'user privilege on relation by user oid, rel oid',
+ proname => 'has_table_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid oid text', prosrc => 'has_table_privilege_id_id' },
+{ oid => '1926', descr => 'current user privilege on relation by rel name',
+ proname => 'has_table_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'has_table_privilege_name' },
+{ oid => '1927', descr => 'current user privilege on relation by rel oid',
+ proname => 'has_table_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text', prosrc => 'has_table_privilege_id' },
+
+{ oid => '2181', descr => 'user privilege on sequence by username, seq name',
+ proname => 'has_sequence_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name text text',
+ prosrc => 'has_sequence_privilege_name_name' },
+{ oid => '2182', descr => 'user privilege on sequence by username, seq oid',
+ proname => 'has_sequence_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name oid text', prosrc => 'has_sequence_privilege_name_id' },
+{ oid => '2183', descr => 'user privilege on sequence by user oid, seq name',
+ proname => 'has_sequence_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text text', prosrc => 'has_sequence_privilege_id_name' },
+{ oid => '2184', descr => 'user privilege on sequence by user oid, seq oid',
+ proname => 'has_sequence_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid oid text', prosrc => 'has_sequence_privilege_id_id' },
+{ oid => '2185', descr => 'current user privilege on sequence by seq name',
+ proname => 'has_sequence_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'has_sequence_privilege_name' },
+{ oid => '2186', descr => 'current user privilege on sequence by seq oid',
+ proname => 'has_sequence_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text', prosrc => 'has_sequence_privilege_id' },
+
+{ oid => '3012',
+ descr => 'user privilege on column by username, rel name, col name',
+ proname => 'has_column_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name text text text',
+ prosrc => 'has_column_privilege_name_name_name' },
+{ oid => '3013',
+ descr => 'user privilege on column by username, rel name, col attnum',
+ proname => 'has_column_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name text int2 text',
+ prosrc => 'has_column_privilege_name_name_attnum' },
+{ oid => '3014',
+ descr => 'user privilege on column by username, rel oid, col name',
+ proname => 'has_column_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name oid text text',
+ prosrc => 'has_column_privilege_name_id_name' },
+{ oid => '3015',
+ descr => 'user privilege on column by username, rel oid, col attnum',
+ proname => 'has_column_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name oid int2 text',
+ prosrc => 'has_column_privilege_name_id_attnum' },
+{ oid => '3016',
+ descr => 'user privilege on column by user oid, rel name, col name',
+ proname => 'has_column_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text text text',
+ prosrc => 'has_column_privilege_id_name_name' },
+{ oid => '3017',
+ descr => 'user privilege on column by user oid, rel name, col attnum',
+ proname => 'has_column_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text int2 text',
+ prosrc => 'has_column_privilege_id_name_attnum' },
+{ oid => '3018',
+ descr => 'user privilege on column by user oid, rel oid, col name',
+ proname => 'has_column_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid oid text text',
+ prosrc => 'has_column_privilege_id_id_name' },
+{ oid => '3019',
+ descr => 'user privilege on column by user oid, rel oid, col attnum',
+ proname => 'has_column_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid oid int2 text',
+ prosrc => 'has_column_privilege_id_id_attnum' },
+{ oid => '3020',
+ descr => 'current user privilege on column by rel name, col name',
+ proname => 'has_column_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'text text text', prosrc => 'has_column_privilege_name_name' },
+{ oid => '3021',
+ descr => 'current user privilege on column by rel name, col attnum',
+ proname => 'has_column_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'text int2 text',
+ prosrc => 'has_column_privilege_name_attnum' },
+{ oid => '3022',
+ descr => 'current user privilege on column by rel oid, col name',
+ proname => 'has_column_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text text', prosrc => 'has_column_privilege_id_name' },
+{ oid => '3023',
+ descr => 'current user privilege on column by rel oid, col attnum',
+ proname => 'has_column_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid int2 text', prosrc => 'has_column_privilege_id_attnum' },
+
+{ oid => '3024',
+ descr => 'user privilege on any column by username, rel name',
+ proname => 'has_any_column_privilege', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'name text text',
+ prosrc => 'has_any_column_privilege_name_name' },
+{ oid => '3025', descr => 'user privilege on any column by username, rel oid',
+ proname => 'has_any_column_privilege', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'name oid text',
+ prosrc => 'has_any_column_privilege_name_id' },
+{ oid => '3026',
+ descr => 'user privilege on any column by user oid, rel name',
+ proname => 'has_any_column_privilege', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid text text',
+ prosrc => 'has_any_column_privilege_id_name' },
+{ oid => '3027', descr => 'user privilege on any column by user oid, rel oid',
+ proname => 'has_any_column_privilege', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid oid text',
+ prosrc => 'has_any_column_privilege_id_id' },
+{ oid => '3028', descr => 'current user privilege on any column by rel name',
+ proname => 'has_any_column_privilege', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'text text',
+ prosrc => 'has_any_column_privilege_name' },
+{ oid => '3029', descr => 'current user privilege on any column by rel oid',
+ proname => 'has_any_column_privilege', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid text',
+ prosrc => 'has_any_column_privilege_id' },
+
+{ oid => '3355', descr => 'I/O',
+ proname => 'pg_ndistinct_in', prorettype => 'pg_ndistinct',
+ proargtypes => 'cstring', prosrc => 'pg_ndistinct_in' },
+{ oid => '3356', descr => 'I/O',
+ proname => 'pg_ndistinct_out', prorettype => 'cstring',
+ proargtypes => 'pg_ndistinct', prosrc => 'pg_ndistinct_out' },
+{ oid => '3357', descr => 'I/O',
+ proname => 'pg_ndistinct_recv', provolatile => 's',
+ prorettype => 'pg_ndistinct', proargtypes => 'internal',
+ prosrc => 'pg_ndistinct_recv' },
+{ oid => '3358', descr => 'I/O',
+ proname => 'pg_ndistinct_send', provolatile => 's', prorettype => 'bytea',
+ proargtypes => 'pg_ndistinct', prosrc => 'pg_ndistinct_send' },
+
+{ oid => '3404', descr => 'I/O',
+ proname => 'pg_dependencies_in', prorettype => 'pg_dependencies',
+ proargtypes => 'cstring', prosrc => 'pg_dependencies_in' },
+{ oid => '3405', descr => 'I/O',
+ proname => 'pg_dependencies_out', prorettype => 'cstring',
+ proargtypes => 'pg_dependencies', prosrc => 'pg_dependencies_out' },
+{ oid => '3406', descr => 'I/O',
+ proname => 'pg_dependencies_recv', provolatile => 's',
+ prorettype => 'pg_dependencies', proargtypes => 'internal',
+ prosrc => 'pg_dependencies_recv' },
+{ oid => '3407', descr => 'I/O',
+ proname => 'pg_dependencies_send', provolatile => 's', prorettype => 'bytea',
+ proargtypes => 'pg_dependencies', prosrc => 'pg_dependencies_send' },
+
+{ oid => '5018', descr => 'I/O',
+ proname => 'pg_mcv_list_in', prorettype => 'pg_mcv_list',
+ proargtypes => 'cstring', prosrc => 'pg_mcv_list_in' },
+{ oid => '5019', descr => 'I/O',
+ proname => 'pg_mcv_list_out', prorettype => 'cstring',
+ proargtypes => 'pg_mcv_list', prosrc => 'pg_mcv_list_out' },
+{ oid => '5020', descr => 'I/O',
+ proname => 'pg_mcv_list_recv', provolatile => 's',
+ prorettype => 'pg_mcv_list', proargtypes => 'internal',
+ prosrc => 'pg_mcv_list_recv' },
+{ oid => '5021', descr => 'I/O',
+ proname => 'pg_mcv_list_send', provolatile => 's', prorettype => 'bytea',
+ proargtypes => 'pg_mcv_list', prosrc => 'pg_mcv_list_send' },
+
+{ oid => '3427', descr => 'details about MCV list items',
+ proname => 'pg_mcv_list_items', prorows => '1000', proretset => 't',
+ provolatile => 's', prorettype => 'record', proargtypes => 'pg_mcv_list',
+ proallargtypes => '{pg_mcv_list,int4,_text,_bool,float8,float8}',
+ proargmodes => '{i,o,o,o,o,o}',
+ proargnames => '{mcv_list,index,values,nulls,frequency,base_frequency}',
+ prosrc => 'pg_stats_ext_mcvlist_items' },
+
+{ oid => '1928', descr => 'statistics: number of scans done for table/index',
+ proname => 'pg_stat_get_numscans', provolatile => 's', proparallel => 'r',
+ prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_numscans' },
+{ oid => '1929', descr => 'statistics: number of tuples read by seqscan',
+ proname => 'pg_stat_get_tuples_returned', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_tuples_returned' },
+{ oid => '1930', descr => 'statistics: number of tuples fetched by idxscan',
+ proname => 'pg_stat_get_tuples_fetched', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_tuples_fetched' },
+{ oid => '1931', descr => 'statistics: number of tuples inserted',
+ proname => 'pg_stat_get_tuples_inserted', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_tuples_inserted' },
+{ oid => '1932', descr => 'statistics: number of tuples updated',
+ proname => 'pg_stat_get_tuples_updated', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_tuples_updated' },
+{ oid => '1933', descr => 'statistics: number of tuples deleted',
+ proname => 'pg_stat_get_tuples_deleted', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_tuples_deleted' },
+{ oid => '1972', descr => 'statistics: number of tuples hot updated',
+ proname => 'pg_stat_get_tuples_hot_updated', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_tuples_hot_updated' },
+{ oid => '2878', descr => 'statistics: number of live tuples',
+ proname => 'pg_stat_get_live_tuples', provolatile => 's', proparallel => 'r',
+ prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_live_tuples' },
+{ oid => '2879', descr => 'statistics: number of dead tuples',
+ proname => 'pg_stat_get_dead_tuples', provolatile => 's', proparallel => 'r',
+ prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_dead_tuples' },
+{ oid => '3177',
+ descr => 'statistics: number of tuples changed since last analyze',
+ proname => 'pg_stat_get_mod_since_analyze', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_mod_since_analyze' },
+{ oid => '5053',
+ descr => 'statistics: number of tuples inserted since last vacuum',
+ proname => 'pg_stat_get_ins_since_vacuum', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_ins_since_vacuum' },
+{ oid => '1934', descr => 'statistics: number of blocks fetched',
+ proname => 'pg_stat_get_blocks_fetched', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_blocks_fetched' },
+{ oid => '1935', descr => 'statistics: number of blocks found in cache',
+ proname => 'pg_stat_get_blocks_hit', provolatile => 's', proparallel => 'r',
+ prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_blocks_hit' },
+{ oid => '2781', descr => 'statistics: last manual vacuum time for a table',
+ proname => 'pg_stat_get_last_vacuum_time', provolatile => 's',
+ proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_last_vacuum_time' },
+{ oid => '2782', descr => 'statistics: last auto vacuum time for a table',
+ proname => 'pg_stat_get_last_autovacuum_time', provolatile => 's',
+ proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_last_autovacuum_time' },
+{ oid => '2783', descr => 'statistics: last manual analyze time for a table',
+ proname => 'pg_stat_get_last_analyze_time', provolatile => 's',
+ proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_last_analyze_time' },
+{ oid => '2784', descr => 'statistics: last auto analyze time for a table',
+ proname => 'pg_stat_get_last_autoanalyze_time', provolatile => 's',
+ proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_last_autoanalyze_time' },
+{ oid => '3054', descr => 'statistics: number of manual vacuums for a table',
+ proname => 'pg_stat_get_vacuum_count', provolatile => 's', proparallel => 'r',
+ prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_vacuum_count' },
+{ oid => '3055', descr => 'statistics: number of auto vacuums for a table',
+ proname => 'pg_stat_get_autovacuum_count', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_autovacuum_count' },
+{ oid => '3056', descr => 'statistics: number of manual analyzes for a table',
+ proname => 'pg_stat_get_analyze_count', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_analyze_count' },
+{ oid => '3057', descr => 'statistics: number of auto analyzes for a table',
+ proname => 'pg_stat_get_autoanalyze_count', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_autoanalyze_count' },
+{ oid => '1936', descr => 'statistics: currently active backend IDs',
+ proname => 'pg_stat_get_backend_idset', prorows => '100', proretset => 't',
+ provolatile => 's', proparallel => 'r', prorettype => 'int4',
+ proargtypes => '', prosrc => 'pg_stat_get_backend_idset' },
+{ oid => '2022',
+ descr => 'statistics: information about currently active backends',
+ proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
+ proretset => 't', provolatile => 's', proparallel => 'r',
+ prorettype => 'record', proargtypes => 'int4',
+ proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,bool,text,numeric,text,bool,text,bool,int4}',
+ proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,sslcompression,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid}',
+ prosrc => 'pg_stat_get_activity' },
+{ oid => '3318',
+ descr => 'statistics: information about progress of backends running maintenance command',
+ proname => 'pg_stat_get_progress_info', prorows => '100', proretset => 't',
+ provolatile => 's', proparallel => 'r', prorettype => 'record',
+ proargtypes => 'text',
+ proallargtypes => '{text,int4,oid,oid,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8}',
+ proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{cmdtype,pid,datid,relid,param1,param2,param3,param4,param5,param6,param7,param8,param9,param10,param11,param12,param13,param14,param15,param16,param17,param18,param19,param20}',
+ prosrc => 'pg_stat_get_progress_info' },
+{ oid => '3099',
+ descr => 'statistics: information about currently active replication',
+ proname => 'pg_stat_get_wal_senders', prorows => '10', proisstrict => 'f',
+ proretset => 't', provolatile => 's', proparallel => 'r',
+ prorettype => 'record', proargtypes => '',
+ proallargtypes => '{int4,text,pg_lsn,pg_lsn,pg_lsn,pg_lsn,interval,interval,interval,int4,text,timestamptz}',
+ proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{pid,state,sent_lsn,write_lsn,flush_lsn,replay_lsn,write_lag,flush_lag,replay_lag,sync_priority,sync_state,reply_time}',
+ prosrc => 'pg_stat_get_wal_senders' },
+{ oid => '3317', descr => 'statistics: information about WAL receiver',
+ proname => 'pg_stat_get_wal_receiver', proisstrict => 'f', provolatile => 's',
+ proparallel => 'r', prorettype => 'record', proargtypes => '',
+ proallargtypes => '{int4,text,pg_lsn,int4,pg_lsn,pg_lsn,int4,timestamptz,timestamptz,pg_lsn,timestamptz,text,text,int4,text}',
+ proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{pid,status,receive_start_lsn,receive_start_tli,written_lsn,flushed_lsn,received_tli,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time,slot_name,sender_host,sender_port,conninfo}',
+ prosrc => 'pg_stat_get_wal_receiver' },
+{ oid => '6118', descr => 'statistics: information about subscription',
+ proname => 'pg_stat_get_subscription', proisstrict => 'f', provolatile => 's',
+ proparallel => 'r', prorettype => 'record', proargtypes => 'oid',
+ proallargtypes => '{oid,oid,oid,int4,pg_lsn,timestamptz,timestamptz,pg_lsn,timestamptz}',
+ proargmodes => '{i,o,o,o,o,o,o,o,o}',
+ proargnames => '{subid,subid,relid,pid,received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time}',
+ prosrc => 'pg_stat_get_subscription' },
+{ oid => '2026', descr => 'statistics: current backend PID',
+ proname => 'pg_backend_pid', provolatile => 's', proparallel => 'r',
+ prorettype => 'int4', proargtypes => '', prosrc => 'pg_backend_pid' },
+{ oid => '1937', descr => 'statistics: PID of backend',
+ proname => 'pg_stat_get_backend_pid', provolatile => 's', proparallel => 'r',
+ prorettype => 'int4', proargtypes => 'int4',
+ prosrc => 'pg_stat_get_backend_pid' },
+{ oid => '1938', descr => 'statistics: database ID of backend',
+ proname => 'pg_stat_get_backend_dbid', provolatile => 's', proparallel => 'r',
+ prorettype => 'oid', proargtypes => 'int4',
+ prosrc => 'pg_stat_get_backend_dbid' },
+{ oid => '1939', descr => 'statistics: user ID of backend',
+ proname => 'pg_stat_get_backend_userid', provolatile => 's',
+ proparallel => 'r', prorettype => 'oid', proargtypes => 'int4',
+ prosrc => 'pg_stat_get_backend_userid' },
+{ oid => '1940', descr => 'statistics: current query of backend',
+ proname => 'pg_stat_get_backend_activity', provolatile => 's',
+ proparallel => 'r', prorettype => 'text', proargtypes => 'int4',
+ prosrc => 'pg_stat_get_backend_activity' },
+{ oid => '2788',
+ descr => 'statistics: wait event type on which backend is currently waiting',
+ proname => 'pg_stat_get_backend_wait_event_type', provolatile => 's',
+ proparallel => 'r', prorettype => 'text', proargtypes => 'int4',
+ prosrc => 'pg_stat_get_backend_wait_event_type' },
+{ oid => '2853',
+ descr => 'statistics: wait event on which backend is currently waiting',
+ proname => 'pg_stat_get_backend_wait_event', provolatile => 's',
+ proparallel => 'r', prorettype => 'text', proargtypes => 'int4',
+ prosrc => 'pg_stat_get_backend_wait_event' },
+{ oid => '2094',
+ descr => 'statistics: start time for current query of backend',
+ proname => 'pg_stat_get_backend_activity_start', provolatile => 's',
+ proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'int4',
+ prosrc => 'pg_stat_get_backend_activity_start' },
+{ oid => '2857',
+ descr => 'statistics: start time for backend\'s current transaction',
+ proname => 'pg_stat_get_backend_xact_start', provolatile => 's',
+ proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'int4',
+ prosrc => 'pg_stat_get_backend_xact_start' },
+{ oid => '1391',
+ descr => 'statistics: start time for current backend session',
+ proname => 'pg_stat_get_backend_start', provolatile => 's',
+ proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'int4',
+ prosrc => 'pg_stat_get_backend_start' },
+{ oid => '1392',
+ descr => 'statistics: address of client connected to backend',
+ proname => 'pg_stat_get_backend_client_addr', provolatile => 's',
+ proparallel => 'r', prorettype => 'inet', proargtypes => 'int4',
+ prosrc => 'pg_stat_get_backend_client_addr' },
+{ oid => '1393',
+ descr => 'statistics: port number of client connected to backend',
+ proname => 'pg_stat_get_backend_client_port', provolatile => 's',
+ proparallel => 'r', prorettype => 'int4', proargtypes => 'int4',
+ prosrc => 'pg_stat_get_backend_client_port' },
+{ oid => '1941', descr => 'statistics: number of backends in database',
+ proname => 'pg_stat_get_db_numbackends', provolatile => 's',
+ proparallel => 'r', prorettype => 'int4', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_numbackends' },
+{ oid => '1942', descr => 'statistics: transactions committed',
+ proname => 'pg_stat_get_db_xact_commit', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_xact_commit' },
+{ oid => '1943', descr => 'statistics: transactions rolled back',
+ proname => 'pg_stat_get_db_xact_rollback', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_xact_rollback' },
+{ oid => '1944', descr => 'statistics: blocks fetched for database',
+ proname => 'pg_stat_get_db_blocks_fetched', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_blocks_fetched' },
+{ oid => '1945', descr => 'statistics: blocks found in cache for database',
+ proname => 'pg_stat_get_db_blocks_hit', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_blocks_hit' },
+{ oid => '2758', descr => 'statistics: tuples returned for database',
+ proname => 'pg_stat_get_db_tuples_returned', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_tuples_returned' },
+{ oid => '2759', descr => 'statistics: tuples fetched for database',
+ proname => 'pg_stat_get_db_tuples_fetched', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_tuples_fetched' },
+{ oid => '2760', descr => 'statistics: tuples inserted in database',
+ proname => 'pg_stat_get_db_tuples_inserted', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_tuples_inserted' },
+{ oid => '2761', descr => 'statistics: tuples updated in database',
+ proname => 'pg_stat_get_db_tuples_updated', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_tuples_updated' },
+{ oid => '2762', descr => 'statistics: tuples deleted in database',
+ proname => 'pg_stat_get_db_tuples_deleted', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_tuples_deleted' },
+{ oid => '3065',
+ descr => 'statistics: recovery conflicts in database caused by drop tablespace',
+ proname => 'pg_stat_get_db_conflict_tablespace', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_conflict_tablespace' },
+{ oid => '3066',
+ descr => 'statistics: recovery conflicts in database caused by relation lock',
+ proname => 'pg_stat_get_db_conflict_lock', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_conflict_lock' },
+{ oid => '3067',
+ descr => 'statistics: recovery conflicts in database caused by snapshot expiry',
+ proname => 'pg_stat_get_db_conflict_snapshot', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_conflict_snapshot' },
+{ oid => '3068',
+ descr => 'statistics: recovery conflicts in database caused by shared buffer pin',
+ proname => 'pg_stat_get_db_conflict_bufferpin', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_conflict_bufferpin' },
+{ oid => '3069',
+ descr => 'statistics: recovery conflicts in database caused by buffer deadlock',
+ proname => 'pg_stat_get_db_conflict_startup_deadlock', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_conflict_startup_deadlock' },
+{ oid => '3070', descr => 'statistics: recovery conflicts in database',
+ proname => 'pg_stat_get_db_conflict_all', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_conflict_all' },
+{ oid => '3152', descr => 'statistics: deadlocks detected in database',
+ proname => 'pg_stat_get_db_deadlocks', provolatile => 's', proparallel => 'r',
+ prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_deadlocks' },
+{ oid => '3426',
+ descr => 'statistics: checksum failures detected in database',
+ proname => 'pg_stat_get_db_checksum_failures', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_checksum_failures' },
+{ oid => '3428',
+ descr => 'statistics: when last checksum failure was detected in database',
+ proname => 'pg_stat_get_db_checksum_last_failure', provolatile => 's',
+ proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_checksum_last_failure' },
+{ oid => '3074', descr => 'statistics: last reset for a database',
+ proname => 'pg_stat_get_db_stat_reset_time', provolatile => 's',
+ proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_stat_reset_time' },
+{ oid => '3150', descr => 'statistics: number of temporary files written',
+ proname => 'pg_stat_get_db_temp_files', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_temp_files' },
+{ oid => '3151',
+ descr => 'statistics: number of bytes in temporary files written',
+ proname => 'pg_stat_get_db_temp_bytes', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_temp_bytes' },
+{ oid => '2844', descr => 'statistics: block read time, in milliseconds',
+ proname => 'pg_stat_get_db_blk_read_time', provolatile => 's',
+ proparallel => 'r', prorettype => 'float8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_blk_read_time' },
+{ oid => '2845', descr => 'statistics: block write time, in milliseconds',
+ proname => 'pg_stat_get_db_blk_write_time', provolatile => 's',
+ proparallel => 'r', prorettype => 'float8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_db_blk_write_time' },
+{ oid => '3195', descr => 'statistics: information about WAL archiver',
+ proname => 'pg_stat_get_archiver', proisstrict => 'f', provolatile => 's',
+ proparallel => 'r', prorettype => 'record', proargtypes => '',
+ proallargtypes => '{int8,text,timestamptz,int8,text,timestamptz,timestamptz}',
+ proargmodes => '{o,o,o,o,o,o,o}',
+ proargnames => '{archived_count,last_archived_wal,last_archived_time,failed_count,last_failed_wal,last_failed_time,stats_reset}',
+ prosrc => 'pg_stat_get_archiver' },
+{ oid => '2769',
+ descr => 'statistics: number of timed checkpoints started by the bgwriter',
+ proname => 'pg_stat_get_bgwriter_timed_checkpoints', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => '',
+ prosrc => 'pg_stat_get_bgwriter_timed_checkpoints' },
+{ oid => '2770',
+ descr => 'statistics: number of backend requested checkpoints started by the bgwriter',
+ proname => 'pg_stat_get_bgwriter_requested_checkpoints', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => '',
+ prosrc => 'pg_stat_get_bgwriter_requested_checkpoints' },
+{ oid => '2771',
+ descr => 'statistics: number of buffers written by the bgwriter during checkpoints',
+ proname => 'pg_stat_get_bgwriter_buf_written_checkpoints', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => '',
+ prosrc => 'pg_stat_get_bgwriter_buf_written_checkpoints' },
+{ oid => '2772',
+ descr => 'statistics: number of buffers written by the bgwriter for cleaning dirty buffers',
+ proname => 'pg_stat_get_bgwriter_buf_written_clean', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => '',
+ prosrc => 'pg_stat_get_bgwriter_buf_written_clean' },
+{ oid => '2773',
+ descr => 'statistics: number of times the bgwriter stopped processing when it had written too many buffers while cleaning',
+ proname => 'pg_stat_get_bgwriter_maxwritten_clean', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => '',
+ prosrc => 'pg_stat_get_bgwriter_maxwritten_clean' },
+{ oid => '3075', descr => 'statistics: last reset for the bgwriter',
+ proname => 'pg_stat_get_bgwriter_stat_reset_time', provolatile => 's',
+ proparallel => 'r', prorettype => 'timestamptz', proargtypes => '',
+ prosrc => 'pg_stat_get_bgwriter_stat_reset_time' },
+{ oid => '3160',
+ descr => 'statistics: checkpoint time spent writing buffers to disk, in milliseconds',
+ proname => 'pg_stat_get_checkpoint_write_time', provolatile => 's',
+ proparallel => 'r', prorettype => 'float8', proargtypes => '',
+ prosrc => 'pg_stat_get_checkpoint_write_time' },
+{ oid => '3161',
+ descr => 'statistics: checkpoint time spent synchronizing buffers to disk, in milliseconds',
+ proname => 'pg_stat_get_checkpoint_sync_time', provolatile => 's',
+ proparallel => 'r', prorettype => 'float8', proargtypes => '',
+ prosrc => 'pg_stat_get_checkpoint_sync_time' },
+{ oid => '2775', descr => 'statistics: number of buffers written by backends',
+ proname => 'pg_stat_get_buf_written_backend', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => '',
+ prosrc => 'pg_stat_get_buf_written_backend' },
+{ oid => '3063',
+ descr => 'statistics: number of backend buffer writes that did their own fsync',
+ proname => 'pg_stat_get_buf_fsync_backend', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => '',
+ prosrc => 'pg_stat_get_buf_fsync_backend' },
+{ oid => '2859', descr => 'statistics: number of buffer allocations',
+ proname => 'pg_stat_get_buf_alloc', provolatile => 's', proparallel => 'r',
+ prorettype => 'int8', proargtypes => '', prosrc => 'pg_stat_get_buf_alloc' },
+
+{ oid => '2306', descr => 'statistics: information about SLRU caches',
+ proname => 'pg_stat_get_slru', prorows => '100', proisstrict => 'f',
+ proretset => 't', provolatile => 's', proparallel => 'r',
+ prorettype => 'record', proargtypes => '',
+ proallargtypes => '{text,int8,int8,int8,int8,int8,int8,int8,timestamptz}',
+ proargmodes => '{o,o,o,o,o,o,o,o,o}',
+ proargnames => '{name,blks_zeroed,blks_hit,blks_read,blks_written,blks_exists,flushes,truncates,stats_reset}',
+ prosrc => 'pg_stat_get_slru' },
+
+{ oid => '2978', descr => 'statistics: number of function calls',
+ proname => 'pg_stat_get_function_calls', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_function_calls' },
+{ oid => '2979',
+ descr => 'statistics: total execution time of function, in milliseconds',
+ proname => 'pg_stat_get_function_total_time', provolatile => 's',
+ proparallel => 'r', prorettype => 'float8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_function_total_time' },
+{ oid => '2980',
+ descr => 'statistics: self execution time of function, in milliseconds',
+ proname => 'pg_stat_get_function_self_time', provolatile => 's',
+ proparallel => 'r', prorettype => 'float8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_function_self_time' },
+
+{ oid => '3037',
+ descr => 'statistics: number of scans done for table/index in current transaction',
+ proname => 'pg_stat_get_xact_numscans', provolatile => 'v',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_xact_numscans' },
+{ oid => '3038',
+ descr => 'statistics: number of tuples read by seqscan in current transaction',
+ proname => 'pg_stat_get_xact_tuples_returned', provolatile => 'v',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_xact_tuples_returned' },
+{ oid => '3039',
+ descr => 'statistics: number of tuples fetched by idxscan in current transaction',
+ proname => 'pg_stat_get_xact_tuples_fetched', provolatile => 'v',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_xact_tuples_fetched' },
+{ oid => '3040',
+ descr => 'statistics: number of tuples inserted in current transaction',
+ proname => 'pg_stat_get_xact_tuples_inserted', provolatile => 'v',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_xact_tuples_inserted' },
+{ oid => '3041',
+ descr => 'statistics: number of tuples updated in current transaction',
+ proname => 'pg_stat_get_xact_tuples_updated', provolatile => 'v',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_xact_tuples_updated' },
+{ oid => '3042',
+ descr => 'statistics: number of tuples deleted in current transaction',
+ proname => 'pg_stat_get_xact_tuples_deleted', provolatile => 'v',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_xact_tuples_deleted' },
+{ oid => '3043',
+ descr => 'statistics: number of tuples hot updated in current transaction',
+ proname => 'pg_stat_get_xact_tuples_hot_updated', provolatile => 'v',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_xact_tuples_hot_updated' },
+{ oid => '3044',
+ descr => 'statistics: number of blocks fetched in current transaction',
+ proname => 'pg_stat_get_xact_blocks_fetched', provolatile => 'v',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_xact_blocks_fetched' },
+{ oid => '3045',
+ descr => 'statistics: number of blocks found in cache in current transaction',
+ proname => 'pg_stat_get_xact_blocks_hit', provolatile => 'v',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_xact_blocks_hit' },
+{ oid => '3046',
+ descr => 'statistics: number of function calls in current transaction',
+ proname => 'pg_stat_get_xact_function_calls', provolatile => 'v',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_xact_function_calls' },
+{ oid => '3047',
+ descr => 'statistics: total execution time of function in current transaction, in milliseconds',
+ proname => 'pg_stat_get_xact_function_total_time', provolatile => 'v',
+ proparallel => 'r', prorettype => 'float8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_xact_function_total_time' },
+{ oid => '3048',
+ descr => 'statistics: self execution time of function in current transaction, in milliseconds',
+ proname => 'pg_stat_get_xact_function_self_time', provolatile => 'v',
+ proparallel => 'r', prorettype => 'float8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_xact_function_self_time' },
+
+{ oid => '3788',
+ descr => 'statistics: timestamp of the current statistics snapshot',
+ proname => 'pg_stat_get_snapshot_timestamp', provolatile => 's',
+ proparallel => 'r', prorettype => 'timestamptz', proargtypes => '',
+ prosrc => 'pg_stat_get_snapshot_timestamp' },
+{ oid => '2230',
+ descr => 'statistics: discard current transaction\'s statistics snapshot',
+ proname => 'pg_stat_clear_snapshot', proisstrict => 'f', provolatile => 'v',
+ proparallel => 'r', prorettype => 'void', proargtypes => '',
+ prosrc => 'pg_stat_clear_snapshot' },
+{ oid => '2274',
+ descr => 'statistics: reset collected statistics for current database',
+ proname => 'pg_stat_reset', proisstrict => 'f', provolatile => 'v',
+ prorettype => 'void', proargtypes => '', prosrc => 'pg_stat_reset' },
+{ oid => '3775',
+ descr => 'statistics: reset collected statistics shared across the cluster',
+ proname => 'pg_stat_reset_shared', provolatile => 'v', prorettype => 'void',
+ proargtypes => 'text', prosrc => 'pg_stat_reset_shared' },
+{ oid => '3776',
+ descr => 'statistics: reset collected statistics for a single table or index in the current database',
+ proname => 'pg_stat_reset_single_table_counters', provolatile => 'v',
+ prorettype => 'void', proargtypes => 'oid',
+ prosrc => 'pg_stat_reset_single_table_counters' },
+{ oid => '3777',
+ descr => 'statistics: reset collected statistics for a single function in the current database',
+ proname => 'pg_stat_reset_single_function_counters', provolatile => 'v',
+ prorettype => 'void', proargtypes => 'oid',
+ prosrc => 'pg_stat_reset_single_function_counters' },
+{ oid => '2307',
+ descr => 'statistics: reset collected statistics for a single SLRU',
+ proname => 'pg_stat_reset_slru', proisstrict => 'f', provolatile => 'v',
+ prorettype => 'void', proargtypes => 'text', prosrc => 'pg_stat_reset_slru' },
+
+{ oid => '3163', descr => 'current trigger depth',
+ proname => 'pg_trigger_depth', provolatile => 's', proparallel => 'r',
+ prorettype => 'int4', proargtypes => '', prosrc => 'pg_trigger_depth' },
+
+{ oid => '3778', descr => 'tablespace location',
+ proname => 'pg_tablespace_location', provolatile => 's', prorettype => 'text',
+ proargtypes => 'oid', prosrc => 'pg_tablespace_location' },
+
+{ oid => '1946',
+ descr => 'convert bytea value into some ascii-only text string',
+ proname => 'encode', prorettype => 'text', proargtypes => 'bytea text',
+ prosrc => 'binary_encode' },
+{ oid => '1947',
+ descr => 'convert ascii-encoded text string into bytea value',
+ proname => 'decode', prorettype => 'bytea', proargtypes => 'text text',
+ prosrc => 'binary_decode' },
+
+{ oid => '1948',
+ proname => 'byteaeq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bytea bytea', prosrc => 'byteaeq' },
+{ oid => '1949',
+ proname => 'bytealt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bytea bytea', prosrc => 'bytealt' },
+{ oid => '1950',
+ proname => 'byteale', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bytea bytea', prosrc => 'byteale' },
+{ oid => '1951',
+ proname => 'byteagt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bytea bytea', prosrc => 'byteagt' },
+{ oid => '1952',
+ proname => 'byteage', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bytea bytea', prosrc => 'byteage' },
+{ oid => '1953',
+ proname => 'byteane', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bytea bytea', prosrc => 'byteane' },
+{ oid => '1954', descr => 'less-equal-greater',
+ proname => 'byteacmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'bytea bytea', prosrc => 'byteacmp' },
+{ oid => '3331', descr => 'sort support',
+ proname => 'bytea_sortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'bytea_sortsupport' },
+
+{ oid => '3917', descr => 'planner support for timestamp length coercion',
+ proname => 'timestamp_support', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'timestamp_support' },
+{ oid => '3944', descr => 'planner support for time length coercion',
+ proname => 'time_support', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'time_support' },
+
+{ oid => '1961', descr => 'adjust timestamp precision',
+ proname => 'timestamp', prosupport => 'timestamp_support',
+ prorettype => 'timestamp', proargtypes => 'timestamp int4',
+ prosrc => 'timestamp_scale' },
+
+{ oid => '1965', descr => 'larger of two',
+ proname => 'oidlarger', prorettype => 'oid', proargtypes => 'oid oid',
+ prosrc => 'oidlarger' },
+{ oid => '1966', descr => 'smaller of two',
+ proname => 'oidsmaller', prorettype => 'oid', proargtypes => 'oid oid',
+ prosrc => 'oidsmaller' },
+
+{ oid => '1967', descr => 'adjust timestamptz precision',
+ proname => 'timestamptz', prosupport => 'timestamp_support',
+ prorettype => 'timestamptz', proargtypes => 'timestamptz int4',
+ prosrc => 'timestamptz_scale' },
+{ oid => '1968', descr => 'adjust time precision',
+ proname => 'time', prosupport => 'time_support', prorettype => 'time',
+ proargtypes => 'time int4', prosrc => 'time_scale' },
+{ oid => '1969', descr => 'adjust time with time zone precision',
+ proname => 'timetz', prosupport => 'time_support', prorettype => 'timetz',
+ proargtypes => 'timetz int4', prosrc => 'timetz_scale' },
+
+{ oid => '2003',
+ proname => 'textanycat', prolang => 'sql', provolatile => 's',
+ prorettype => 'text', proargtypes => 'text anynonarray',
+ prosrc => 'select $1 || $2::pg_catalog.text' },
+{ oid => '2004',
+ proname => 'anytextcat', prolang => 'sql', provolatile => 's',
+ prorettype => 'text', proargtypes => 'anynonarray text',
+ prosrc => 'select $1::pg_catalog.text || $2' },
+
+{ oid => '2005',
+ proname => 'bytealike', prosupport => 'textlike_support',
+ prorettype => 'bool', proargtypes => 'bytea bytea', prosrc => 'bytealike' },
+{ oid => '2006',
+ proname => 'byteanlike', prorettype => 'bool', proargtypes => 'bytea bytea',
+ prosrc => 'byteanlike' },
+{ oid => '2007', descr => 'matches LIKE expression',
+ proname => 'like', prosupport => 'textlike_support', prorettype => 'bool',
+ proargtypes => 'bytea bytea', prosrc => 'bytealike' },
+{ oid => '2008', descr => 'does not match LIKE expression',
+ proname => 'notlike', prorettype => 'bool', proargtypes => 'bytea bytea',
+ prosrc => 'byteanlike' },
+{ oid => '2009', descr => 'convert LIKE pattern to use backslash escapes',
+ proname => 'like_escape', prorettype => 'bytea', proargtypes => 'bytea bytea',
+ prosrc => 'like_escape_bytea' },
+{ oid => '2010', descr => 'octet length',
+ proname => 'length', prorettype => 'int4', proargtypes => 'bytea',
+ prosrc => 'byteaoctetlen' },
+{ oid => '2011',
+ proname => 'byteacat', prorettype => 'bytea', proargtypes => 'bytea bytea',
+ prosrc => 'byteacat' },
+{ oid => '2012', descr => 'extract portion of string',
+ proname => 'substring', prorettype => 'bytea',
+ proargtypes => 'bytea int4 int4', prosrc => 'bytea_substr' },
+{ oid => '2013', descr => 'extract portion of string',
+ proname => 'substring', prorettype => 'bytea', proargtypes => 'bytea int4',
+ prosrc => 'bytea_substr_no_len' },
+{ oid => '2085', descr => 'extract portion of string',
+ proname => 'substr', prorettype => 'bytea', proargtypes => 'bytea int4 int4',
+ prosrc => 'bytea_substr' },
+{ oid => '2086', descr => 'extract portion of string',
+ proname => 'substr', prorettype => 'bytea', proargtypes => 'bytea int4',
+ prosrc => 'bytea_substr_no_len' },
+{ oid => '2014', descr => 'position of substring',
+ proname => 'position', prorettype => 'int4', proargtypes => 'bytea bytea',
+ prosrc => 'byteapos' },
+{ oid => '2015', descr => 'trim both ends of string',
+ proname => 'btrim', prorettype => 'bytea', proargtypes => 'bytea bytea',
+ prosrc => 'byteatrim' },
+
+{ oid => '2019', descr => 'convert timestamp with time zone to time',
+ proname => 'time', provolatile => 's', prorettype => 'time',
+ proargtypes => 'timestamptz', prosrc => 'timestamptz_time' },
+{ oid => '2020', descr => 'truncate timestamp to specified units',
+ proname => 'date_trunc', prorettype => 'timestamp',
+ proargtypes => 'text timestamp', prosrc => 'timestamp_trunc' },
+{ oid => '2021', descr => 'extract field from timestamp',
+ proname => 'date_part', prorettype => 'float8',
+ proargtypes => 'text timestamp', prosrc => 'timestamp_part' },
+{ oid => '2024', descr => 'convert date to timestamp',
+ proname => 'timestamp', prorettype => 'timestamp', proargtypes => 'date',
+ prosrc => 'date_timestamp' },
+{ oid => '2025', descr => 'convert date and time to timestamp',
+ proname => 'timestamp', prorettype => 'timestamp', proargtypes => 'date time',
+ prosrc => 'datetime_timestamp' },
+{ oid => '2027', descr => 'convert timestamp with time zone to timestamp',
+ proname => 'timestamp', provolatile => 's', prorettype => 'timestamp',
+ proargtypes => 'timestamptz', prosrc => 'timestamptz_timestamp' },
+{ oid => '2028', descr => 'convert timestamp to timestamp with time zone',
+ proname => 'timestamptz', provolatile => 's', prorettype => 'timestamptz',
+ proargtypes => 'timestamp', prosrc => 'timestamp_timestamptz' },
+{ oid => '2029', descr => 'convert timestamp to date',
+ proname => 'date', prorettype => 'date', proargtypes => 'timestamp',
+ prosrc => 'timestamp_date' },
+{ oid => '2031',
+ proname => 'timestamp_mi', prorettype => 'interval',
+ proargtypes => 'timestamp timestamp', prosrc => 'timestamp_mi' },
+{ oid => '2032',
+ proname => 'timestamp_pl_interval', prorettype => 'timestamp',
+ proargtypes => 'timestamp interval', prosrc => 'timestamp_pl_interval' },
+{ oid => '2033',
+ proname => 'timestamp_mi_interval', prorettype => 'timestamp',
+ proargtypes => 'timestamp interval', prosrc => 'timestamp_mi_interval' },
+{ oid => '2035', descr => 'smaller of two',
+ proname => 'timestamp_smaller', prorettype => 'timestamp',
+ proargtypes => 'timestamp timestamp', prosrc => 'timestamp_smaller' },
+{ oid => '2036', descr => 'larger of two',
+ proname => 'timestamp_larger', prorettype => 'timestamp',
+ proargtypes => 'timestamp timestamp', prosrc => 'timestamp_larger' },
+{ oid => '2037', descr => 'adjust time with time zone to new zone',
+ proname => 'timezone', provolatile => 'v', prorettype => 'timetz',
+ proargtypes => 'text timetz', prosrc => 'timetz_zone' },
+{ oid => '2038', descr => 'adjust time with time zone to new zone',
+ proname => 'timezone', prorettype => 'timetz',
+ proargtypes => 'interval timetz', prosrc => 'timetz_izone' },
+{ oid => '2039', descr => 'hash',
+ proname => 'timestamp_hash', prorettype => 'int4', proargtypes => 'timestamp',
+ prosrc => 'timestamp_hash' },
+{ oid => '3411', descr => 'hash',
+ proname => 'timestamp_hash_extended', prorettype => 'int8',
+ proargtypes => 'timestamp int8', prosrc => 'timestamp_hash_extended' },
+{ oid => '2041', descr => 'intervals overlap?',
+ proname => 'overlaps', proisstrict => 'f', prorettype => 'bool',
+ proargtypes => 'timestamp timestamp timestamp timestamp',
+ prosrc => 'overlaps_timestamp' },
+{ oid => '2042', descr => 'intervals overlap?',
+ proname => 'overlaps', prolang => 'sql', proisstrict => 'f',
+ prorettype => 'bool', proargtypes => 'timestamp interval timestamp interval',
+ prosrc => 'select ($1, ($1 + $2)) overlaps ($3, ($3 + $4))' },
+{ oid => '2043', descr => 'intervals overlap?',
+ proname => 'overlaps', prolang => 'sql', proisstrict => 'f',
+ prorettype => 'bool', proargtypes => 'timestamp timestamp timestamp interval',
+ prosrc => 'select ($1, $2) overlaps ($3, ($3 + $4))' },
+{ oid => '2044', descr => 'intervals overlap?',
+ proname => 'overlaps', prolang => 'sql', proisstrict => 'f',
+ prorettype => 'bool', proargtypes => 'timestamp interval timestamp timestamp',
+ prosrc => 'select ($1, ($1 + $2)) overlaps ($3, $4)' },
+{ oid => '2045', descr => 'less-equal-greater',
+ proname => 'timestamp_cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'timestamp timestamp', prosrc => 'timestamp_cmp' },
+{ oid => '3137', descr => 'sort support',
+ proname => 'timestamp_sortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'timestamp_sortsupport' },
+
+{ oid => '4134', descr => 'window RANGE support',
+ proname => 'in_range', prorettype => 'bool',
+ proargtypes => 'timestamp timestamp interval bool bool',
+ prosrc => 'in_range_timestamp_interval' },
+{ oid => '4135', descr => 'window RANGE support',
+ proname => 'in_range', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'timestamptz timestamptz interval bool bool',
+ prosrc => 'in_range_timestamptz_interval' },
+{ oid => '4136', descr => 'window RANGE support',
+ proname => 'in_range', prorettype => 'bool',
+ proargtypes => 'interval interval interval bool bool',
+ prosrc => 'in_range_interval_interval' },
+{ oid => '4137', descr => 'window RANGE support',
+ proname => 'in_range', prorettype => 'bool',
+ proargtypes => 'time time interval bool bool',
+ prosrc => 'in_range_time_interval' },
+{ oid => '4138', descr => 'window RANGE support',
+ proname => 'in_range', prorettype => 'bool',
+ proargtypes => 'timetz timetz interval bool bool',
+ prosrc => 'in_range_timetz_interval' },
+
+{ oid => '2046', descr => 'convert time with time zone to time',
+ proname => 'time', prorettype => 'time', proargtypes => 'timetz',
+ prosrc => 'timetz_time' },
+{ oid => '2047', descr => 'convert time to time with time zone',
+ proname => 'timetz', provolatile => 's', prorettype => 'timetz',
+ proargtypes => 'time', prosrc => 'time_timetz' },
+{ oid => '2048', descr => 'finite timestamp?',
+ proname => 'isfinite', prorettype => 'bool', proargtypes => 'timestamp',
+ prosrc => 'timestamp_finite' },
+{ oid => '2049', descr => 'format timestamp to text',
+ proname => 'to_char', provolatile => 's', prorettype => 'text',
+ proargtypes => 'timestamp text', prosrc => 'timestamp_to_char' },
+{ oid => '2052',
+ proname => 'timestamp_eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'timestamp timestamp', prosrc => 'timestamp_eq' },
+{ oid => '2053',
+ proname => 'timestamp_ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'timestamp timestamp', prosrc => 'timestamp_ne' },
+{ oid => '2054',
+ proname => 'timestamp_lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'timestamp timestamp', prosrc => 'timestamp_lt' },
+{ oid => '2055',
+ proname => 'timestamp_le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'timestamp timestamp', prosrc => 'timestamp_le' },
+{ oid => '2056',
+ proname => 'timestamp_ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'timestamp timestamp', prosrc => 'timestamp_ge' },
+{ oid => '2057',
+ proname => 'timestamp_gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'timestamp timestamp', prosrc => 'timestamp_gt' },
+{ oid => '2058', descr => 'date difference preserving months and years',
+ proname => 'age', prorettype => 'interval',
+ proargtypes => 'timestamp timestamp', prosrc => 'timestamp_age' },
+{ oid => '2059',
+ descr => 'date difference from today preserving months and years',
+ proname => 'age', prolang => 'sql', provolatile => 's',
+ prorettype => 'interval', proargtypes => 'timestamp',
+ prosrc => 'select pg_catalog.age(cast(current_date as timestamp without time zone), $1)' },
+
+{ oid => '2069', descr => 'adjust timestamp to new time zone',
+ proname => 'timezone', prorettype => 'timestamptz',
+ proargtypes => 'text timestamp', prosrc => 'timestamp_zone' },
+{ oid => '2070', descr => 'adjust timestamp to new time zone',
+ proname => 'timezone', prorettype => 'timestamptz',
+ proargtypes => 'interval timestamp', prosrc => 'timestamp_izone' },
+{ oid => '2071',
+ proname => 'date_pl_interval', prorettype => 'timestamp',
+ proargtypes => 'date interval', prosrc => 'date_pl_interval' },
+{ oid => '2072',
+ proname => 'date_mi_interval', prorettype => 'timestamp',
+ proargtypes => 'date interval', prosrc => 'date_mi_interval' },
+
+{ oid => '2073', descr => 'extract text matching regular expression',
+ proname => 'substring', prorettype => 'text', proargtypes => 'text text',
+ prosrc => 'textregexsubstr' },
+{ oid => '2074', descr => 'extract text matching SQL regular expression',
+ proname => 'substring', prolang => 'sql', prorettype => 'text',
+ proargtypes => 'text text text',
+ prosrc => 'select pg_catalog.substring($1, pg_catalog.similar_to_escape($2, $3))' },
+
+{ oid => '2075', descr => 'convert int8 to bitstring',
+ proname => 'bit', prorettype => 'bit', proargtypes => 'int8 int4',
+ prosrc => 'bitfromint8' },
+{ oid => '2076', descr => 'convert bitstring to int8',
+ proname => 'int8', prorettype => 'int8', proargtypes => 'bit',
+ prosrc => 'bittoint8' },
+
+{ oid => '2077', descr => 'SHOW X as a function',
+ proname => 'current_setting', provolatile => 's', prorettype => 'text',
+ proargtypes => 'text', prosrc => 'show_config_by_name' },
+{ oid => '3294',
+ descr => 'SHOW X as a function, optionally no error for missing variable',
+ proname => 'current_setting', provolatile => 's', prorettype => 'text',
+ proargtypes => 'text bool', prosrc => 'show_config_by_name_missing_ok' },
+{ oid => '2078', descr => 'SET X as a function',
+ proname => 'set_config', proisstrict => 'f', provolatile => 'v',
+ proparallel => 'u', prorettype => 'text', proargtypes => 'text text bool',
+ prosrc => 'set_config_by_name' },
+{ oid => '2084', descr => 'SHOW ALL as a function',
+ proname => 'pg_show_all_settings', prorows => '1000', proretset => 't',
+ provolatile => 's', prorettype => 'record', proargtypes => '',
+ proallargtypes => '{text,text,text,text,text,text,text,text,text,text,text,_text,text,text,text,int4,bool}',
+ proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{name,setting,unit,category,short_desc,extra_desc,context,vartype,source,min_val,max_val,enumvals,boot_val,reset_val,sourcefile,sourceline,pending_restart}',
+ prosrc => 'show_all_settings' },
+{ oid => '3329', descr => 'show config file settings',
+ proname => 'pg_show_all_file_settings', prorows => '1000', proretset => 't',
+ provolatile => 'v', prorettype => 'record', proargtypes => '',
+ proallargtypes => '{text,int4,int4,text,text,bool,text}',
+ proargmodes => '{o,o,o,o,o,o,o}',
+ proargnames => '{sourcefile,sourceline,seqno,name,setting,applied,error}',
+ prosrc => 'show_all_file_settings' },
+{ oid => '3401', descr => 'show pg_hba.conf rules',
+ proname => 'pg_hba_file_rules', prorows => '1000', proretset => 't',
+ provolatile => 'v', prorettype => 'record', proargtypes => '',
+ proallargtypes => '{int4,text,_text,_text,text,text,text,_text,text}',
+ proargmodes => '{o,o,o,o,o,o,o,o,o}',
+ proargnames => '{line_number,type,database,user_name,address,netmask,auth_method,options,error}',
+ prosrc => 'pg_hba_file_rules' },
+{ oid => '1371', descr => 'view system lock information',
+ proname => 'pg_lock_status', prorows => '1000', proretset => 't',
+ provolatile => 'v', prorettype => 'record', proargtypes => '',
+ proallargtypes => '{text,oid,oid,int4,int2,text,xid,oid,oid,int2,text,int4,text,bool,bool}',
+ proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{locktype,database,relation,page,tuple,virtualxid,transactionid,classid,objid,objsubid,virtualtransaction,pid,mode,granted,fastpath}',
+ prosrc => 'pg_lock_status' },
+{ oid => '2561',
+ descr => 'get array of PIDs of sessions blocking specified backend PID from acquiring a heavyweight lock',
+ proname => 'pg_blocking_pids', provolatile => 'v', prorettype => '_int4',
+ proargtypes => 'int4', prosrc => 'pg_blocking_pids' },
+{ oid => '3376',
+ descr => 'get array of PIDs of sessions blocking specified backend PID from acquiring a safe snapshot',
+ proname => 'pg_safe_snapshot_blocking_pids', provolatile => 'v',
+ prorettype => '_int4', proargtypes => 'int4',
+ prosrc => 'pg_safe_snapshot_blocking_pids' },
+{ oid => '3378', descr => 'isolationtester support function',
+ proname => 'pg_isolation_test_session_is_blocked', provolatile => 'v',
+ prorettype => 'bool', proargtypes => 'int4 _int4',
+ prosrc => 'pg_isolation_test_session_is_blocked' },
+{ oid => '1065', descr => 'view two-phase transactions',
+ proname => 'pg_prepared_xact', prorows => '1000', proretset => 't',
+ provolatile => 'v', prorettype => 'record', proargtypes => '',
+ proallargtypes => '{xid,text,timestamptz,oid,oid}',
+ proargmodes => '{o,o,o,o,o}',
+ proargnames => '{transaction,gid,prepared,ownerid,dbid}',
+ prosrc => 'pg_prepared_xact' },
+{ oid => '3819', descr => 'view members of a multixactid',
+ proname => 'pg_get_multixact_members', prorows => '1000', proretset => 't',
+ provolatile => 'v', prorettype => 'record', proargtypes => 'xid',
+ proallargtypes => '{xid,xid,text}', proargmodes => '{i,o,o}',
+ proargnames => '{multixid,xid,mode}', prosrc => 'pg_get_multixact_members' },
+
+{ oid => '3581', descr => 'get commit timestamp of a transaction',
+ proname => 'pg_xact_commit_timestamp', provolatile => 'v',
+ prorettype => 'timestamptz', proargtypes => 'xid',
+ prosrc => 'pg_xact_commit_timestamp' },
+
+{ oid => '3583',
+ descr => 'get transaction Id and commit timestamp of latest transaction commit',
+ proname => 'pg_last_committed_xact', provolatile => 'v',
+ prorettype => 'record', proargtypes => '',
+ proallargtypes => '{xid,timestamptz}', proargmodes => '{o,o}',
+ proargnames => '{xid,timestamp}', prosrc => 'pg_last_committed_xact' },
+
+{ oid => '3537', descr => 'get identification of SQL object',
+ proname => 'pg_describe_object', provolatile => 's', prorettype => 'text',
+ proargtypes => 'oid oid int4', prosrc => 'pg_describe_object' },
+
+{ oid => '3839',
+ descr => 'get machine-parseable identification of SQL object',
+ proname => 'pg_identify_object', provolatile => 's', prorettype => 'record',
+ proargtypes => 'oid oid int4',
+ proallargtypes => '{oid,oid,int4,text,text,text,text}',
+ proargmodes => '{i,i,i,o,o,o,o}',
+ proargnames => '{classid,objid,objsubid,type,schema,name,identity}',
+ prosrc => 'pg_identify_object' },
+
+{ oid => '3382',
+ descr => 'get identification of SQL object for pg_get_object_address()',
+ proname => 'pg_identify_object_as_address', provolatile => 's',
+ prorettype => 'record', proargtypes => 'oid oid int4',
+ proallargtypes => '{oid,oid,int4,text,_text,_text}',
+ proargmodes => '{i,i,i,o,o,o}',
+ proargnames => '{classid,objid,objsubid,type,object_names,object_args}',
+ prosrc => 'pg_identify_object_as_address' },
+
+{ oid => '3954',
+ descr => 'get OID-based object address from name/args arrays',
+ proname => 'pg_get_object_address', provolatile => 's',
+ prorettype => 'record', proargtypes => 'text _text _text',
+ proallargtypes => '{text,_text,_text,oid,oid,int4}',
+ proargmodes => '{i,i,i,o,o,o}',
+ proargnames => '{type,object_names,object_args,classid,objid,objsubid}',
+ prosrc => 'pg_get_object_address' },
+
+{ oid => '2079', descr => 'is table visible in search path?',
+ proname => 'pg_table_is_visible', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid', prosrc => 'pg_table_is_visible' },
+{ oid => '2080', descr => 'is type visible in search path?',
+ proname => 'pg_type_is_visible', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid', prosrc => 'pg_type_is_visible' },
+{ oid => '2081', descr => 'is function visible in search path?',
+ proname => 'pg_function_is_visible', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid',
+ prosrc => 'pg_function_is_visible' },
+{ oid => '2082', descr => 'is operator visible in search path?',
+ proname => 'pg_operator_is_visible', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid',
+ prosrc => 'pg_operator_is_visible' },
+{ oid => '2083', descr => 'is opclass visible in search path?',
+ proname => 'pg_opclass_is_visible', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid',
+ prosrc => 'pg_opclass_is_visible' },
+{ oid => '3829', descr => 'is opfamily visible in search path?',
+ proname => 'pg_opfamily_is_visible', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid',
+ prosrc => 'pg_opfamily_is_visible' },
+{ oid => '2093', descr => 'is conversion visible in search path?',
+ proname => 'pg_conversion_is_visible', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid',
+ prosrc => 'pg_conversion_is_visible' },
+{ oid => '3403', descr => 'is statistics object visible in search path?',
+ proname => 'pg_statistics_obj_is_visible', procost => '10',
+ provolatile => 's', prorettype => 'bool', proargtypes => 'oid',
+ prosrc => 'pg_statistics_obj_is_visible' },
+{ oid => '3756', descr => 'is text search parser visible in search path?',
+ proname => 'pg_ts_parser_is_visible', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid',
+ prosrc => 'pg_ts_parser_is_visible' },
+{ oid => '3757', descr => 'is text search dictionary visible in search path?',
+ proname => 'pg_ts_dict_is_visible', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid',
+ prosrc => 'pg_ts_dict_is_visible' },
+{ oid => '3768', descr => 'is text search template visible in search path?',
+ proname => 'pg_ts_template_is_visible', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid',
+ prosrc => 'pg_ts_template_is_visible' },
+{ oid => '3758',
+ descr => 'is text search configuration visible in search path?',
+ proname => 'pg_ts_config_is_visible', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid',
+ prosrc => 'pg_ts_config_is_visible' },
+{ oid => '3815', descr => 'is collation visible in search path?',
+ proname => 'pg_collation_is_visible', procost => '10', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid',
+ prosrc => 'pg_collation_is_visible' },
+
+{ oid => '2854', descr => 'get OID of current session\'s temp schema, if any',
+ proname => 'pg_my_temp_schema', provolatile => 's', proparallel => 'r',
+ prorettype => 'oid', proargtypes => '', prosrc => 'pg_my_temp_schema' },
+{ oid => '2855', descr => 'is schema another session\'s temp schema?',
+ proname => 'pg_is_other_temp_schema', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid',
+ prosrc => 'pg_is_other_temp_schema' },
+
+{ oid => '2171', descr => 'cancel a server process\' current query',
+ proname => 'pg_cancel_backend', provolatile => 'v', prorettype => 'bool',
+ proargtypes => 'int4', prosrc => 'pg_cancel_backend' },
+{ oid => '2096', descr => 'terminate a server process',
+ proname => 'pg_terminate_backend', provolatile => 'v', prorettype => 'bool',
+ proargtypes => 'int4', prosrc => 'pg_terminate_backend' },
+{ oid => '2172', descr => 'prepare for taking an online backup',
+ proname => 'pg_start_backup', provolatile => 'v', proparallel => 'r',
+ prorettype => 'pg_lsn', proargtypes => 'text bool bool',
+ prosrc => 'pg_start_backup' },
+{ oid => '2173', descr => 'finish taking an online backup',
+ proname => 'pg_stop_backup', provolatile => 'v', proparallel => 'r',
+ prorettype => 'pg_lsn', proargtypes => '', prosrc => 'pg_stop_backup' },
+{ oid => '2739', descr => 'finish taking an online backup',
+ proname => 'pg_stop_backup', prorows => '1', proretset => 't',
+ provolatile => 'v', proparallel => 'r', prorettype => 'record',
+ proargtypes => 'bool bool', proallargtypes => '{bool,bool,pg_lsn,text,text}',
+ proargmodes => '{i,i,o,o,o}',
+ proargnames => '{exclusive,wait_for_archive,lsn,labelfile,spcmapfile}',
+ prosrc => 'pg_stop_backup_v2' },
+{ oid => '3813', descr => 'true if server is in online backup',
+ proname => 'pg_is_in_backup', provolatile => 'v', prorettype => 'bool',
+ proargtypes => '', prosrc => 'pg_is_in_backup' },
+{ oid => '3814', descr => 'start time of an online backup',
+ proname => 'pg_backup_start_time', provolatile => 's',
+ prorettype => 'timestamptz', proargtypes => '',
+ prosrc => 'pg_backup_start_time' },
+{ oid => '3436', descr => 'promote standby server',
+ proname => 'pg_promote', provolatile => 'v', prorettype => 'bool',
+ proargtypes => 'bool int4', proargnames => '{wait,wait_seconds}',
+ prosrc => 'pg_promote' },
+{ oid => '2848', descr => 'switch to new wal file',
+ proname => 'pg_switch_wal', provolatile => 'v', prorettype => 'pg_lsn',
+ proargtypes => '', prosrc => 'pg_switch_wal' },
+{ oid => '3098', descr => 'create a named restore point',
+ proname => 'pg_create_restore_point', provolatile => 'v',
+ prorettype => 'pg_lsn', proargtypes => 'text',
+ prosrc => 'pg_create_restore_point' },
+{ oid => '2849', descr => 'current wal write location',
+ proname => 'pg_current_wal_lsn', provolatile => 'v', prorettype => 'pg_lsn',
+ proargtypes => '', prosrc => 'pg_current_wal_lsn' },
+{ oid => '2852', descr => 'current wal insert location',
+ proname => 'pg_current_wal_insert_lsn', provolatile => 'v',
+ prorettype => 'pg_lsn', proargtypes => '',
+ prosrc => 'pg_current_wal_insert_lsn' },
+{ oid => '3330', descr => 'current wal flush location',
+ proname => 'pg_current_wal_flush_lsn', provolatile => 'v',
+ prorettype => 'pg_lsn', proargtypes => '',
+ prosrc => 'pg_current_wal_flush_lsn' },
+{ oid => '2850',
+ descr => 'wal filename and byte offset, given a wal location',
+ proname => 'pg_walfile_name_offset', prorettype => 'record',
+ proargtypes => 'pg_lsn', proallargtypes => '{pg_lsn,text,int4}',
+ proargmodes => '{i,o,o}', proargnames => '{lsn,file_name,file_offset}',
+ prosrc => 'pg_walfile_name_offset' },
+{ oid => '2851', descr => 'wal filename, given a wal location',
+ proname => 'pg_walfile_name', prorettype => 'text', proargtypes => 'pg_lsn',
+ prosrc => 'pg_walfile_name' },
+
+{ oid => '3165', descr => 'difference in bytes, given two wal locations',
+ proname => 'pg_wal_lsn_diff', prorettype => 'numeric',
+ proargtypes => 'pg_lsn pg_lsn', prosrc => 'pg_wal_lsn_diff' },
+
+{ oid => '3809', descr => 'export a snapshot',
+ proname => 'pg_export_snapshot', provolatile => 'v', proparallel => 'u',
+ prorettype => 'text', proargtypes => '', prosrc => 'pg_export_snapshot' },
+
+{ oid => '3810', descr => 'true if server is in recovery',
+ proname => 'pg_is_in_recovery', provolatile => 'v', prorettype => 'bool',
+ proargtypes => '', prosrc => 'pg_is_in_recovery' },
+
+{ oid => '3820', descr => 'current wal flush location',
+ proname => 'pg_last_wal_receive_lsn', provolatile => 'v',
+ prorettype => 'pg_lsn', proargtypes => '',
+ prosrc => 'pg_last_wal_receive_lsn' },
+{ oid => '3821', descr => 'last wal replay location',
+ proname => 'pg_last_wal_replay_lsn', provolatile => 'v',
+ prorettype => 'pg_lsn', proargtypes => '',
+ prosrc => 'pg_last_wal_replay_lsn' },
+{ oid => '3830', descr => 'timestamp of last replay xact',
+ proname => 'pg_last_xact_replay_timestamp', provolatile => 'v',
+ prorettype => 'timestamptz', proargtypes => '',
+ prosrc => 'pg_last_xact_replay_timestamp' },
+
+{ oid => '3071', descr => 'pause wal replay',
+ proname => 'pg_wal_replay_pause', provolatile => 'v', prorettype => 'void',
+ proargtypes => '', prosrc => 'pg_wal_replay_pause' },
+{ oid => '3072', descr => 'resume wal replay, if it was paused',
+ proname => 'pg_wal_replay_resume', provolatile => 'v', prorettype => 'void',
+ proargtypes => '', prosrc => 'pg_wal_replay_resume' },
+{ oid => '3073', descr => 'true if wal replay is paused',
+ proname => 'pg_is_wal_replay_paused', provolatile => 'v',
+ prorettype => 'bool', proargtypes => '',
+ prosrc => 'pg_is_wal_replay_paused' },
+
+{ oid => '2621', descr => 'reload configuration files',
+ proname => 'pg_reload_conf', provolatile => 'v', prorettype => 'bool',
+ proargtypes => '', prosrc => 'pg_reload_conf' },
+{ oid => '2622', descr => 'rotate log file',
+ proname => 'pg_rotate_logfile', provolatile => 'v', prorettype => 'bool',
+ proargtypes => '', prosrc => 'pg_rotate_logfile_v2' },
+{ oid => '4099', descr => 'rotate log file - old version for adminpack 1.0',
+ proname => 'pg_rotate_logfile_old', provolatile => 'v', prorettype => 'bool',
+ proargtypes => '', prosrc => 'pg_rotate_logfile' },
+{ oid => '3800', descr => 'current logging collector file location',
+ proname => 'pg_current_logfile', proisstrict => 'f', provolatile => 'v',
+ prorettype => 'text', proargtypes => '', prosrc => 'pg_current_logfile' },
+{ oid => '3801', descr => 'current logging collector file location',
+ proname => 'pg_current_logfile', proisstrict => 'f', provolatile => 'v',
+ prorettype => 'text', proargtypes => 'text',
+ prosrc => 'pg_current_logfile_1arg' },
+
+{ oid => '2623', descr => 'get information about file',
+ proname => 'pg_stat_file', provolatile => 'v', prorettype => 'record',
+ proargtypes => 'text',
+ proallargtypes => '{text,int8,timestamptz,timestamptz,timestamptz,timestamptz,bool}',
+ proargmodes => '{i,o,o,o,o,o,o}',
+ proargnames => '{filename,size,access,modification,change,creation,isdir}',
+ prosrc => 'pg_stat_file_1arg' },
+{ oid => '3307', descr => 'get information about file',
+ proname => 'pg_stat_file', provolatile => 'v', prorettype => 'record',
+ proargtypes => 'text bool',
+ proallargtypes => '{text,bool,int8,timestamptz,timestamptz,timestamptz,timestamptz,bool}',
+ proargmodes => '{i,i,o,o,o,o,o,o}',
+ proargnames => '{filename,missing_ok,size,access,modification,change,creation,isdir}',
+ prosrc => 'pg_stat_file' },
+{ oid => '2624', descr => 'read text from a file',
+ proname => 'pg_read_file', provolatile => 'v', prorettype => 'text',
+ proargtypes => 'text int8 int8', prosrc => 'pg_read_file_off_len' },
+{ oid => '3293', descr => 'read text from a file',
+ proname => 'pg_read_file', provolatile => 'v', prorettype => 'text',
+ proargtypes => 'text int8 int8 bool', prosrc => 'pg_read_file_v2' },
+{ oid => '4100',
+ descr => 'read text from a file - old version for adminpack 1.0',
+ proname => 'pg_read_file_old', provolatile => 'v', prorettype => 'text',
+ proargtypes => 'text int8 int8', prosrc => 'pg_read_file' },
+{ oid => '3826', descr => 'read text from a file',
+ proname => 'pg_read_file', provolatile => 'v', prorettype => 'text',
+ proargtypes => 'text', prosrc => 'pg_read_file_all' },
+{ oid => '3827', descr => 'read bytea from a file',
+ proname => 'pg_read_binary_file', provolatile => 'v', prorettype => 'bytea',
+ proargtypes => 'text int8 int8', prosrc => 'pg_read_binary_file_off_len' },
+{ oid => '3295', descr => 'read bytea from a file',
+ proname => 'pg_read_binary_file', provolatile => 'v', prorettype => 'bytea',
+ proargtypes => 'text int8 int8 bool', prosrc => 'pg_read_binary_file' },
+{ oid => '3828', descr => 'read bytea from a file',
+ proname => 'pg_read_binary_file', provolatile => 'v', prorettype => 'bytea',
+ proargtypes => 'text', prosrc => 'pg_read_binary_file_all' },
+{ oid => '2625', descr => 'list all files in a directory',
+ proname => 'pg_ls_dir', prorows => '1000', proretset => 't',
+ provolatile => 'v', prorettype => 'text', proargtypes => 'text',
+ prosrc => 'pg_ls_dir_1arg' },
+{ oid => '3297', descr => 'list all files in a directory',
+ proname => 'pg_ls_dir', prorows => '1000', proretset => 't',
+ provolatile => 'v', prorettype => 'text', proargtypes => 'text bool bool',
+ prosrc => 'pg_ls_dir' },
+{ oid => '2626', descr => 'sleep for the specified time in seconds',
+ proname => 'pg_sleep', provolatile => 'v', prorettype => 'void',
+ proargtypes => 'float8', prosrc => 'pg_sleep' },
+{ oid => '3935', descr => 'sleep for the specified interval',
+ proname => 'pg_sleep_for', prolang => 'sql', provolatile => 'v',
+ prorettype => 'void', proargtypes => 'interval',
+ prosrc => 'select pg_catalog.pg_sleep(extract(epoch from pg_catalog.clock_timestamp() operator(pg_catalog.+) $1) operator(pg_catalog.-) extract(epoch from pg_catalog.clock_timestamp()))' },
+{ oid => '3936', descr => 'sleep until the specified time',
+ proname => 'pg_sleep_until', prolang => 'sql', provolatile => 'v',
+ prorettype => 'void', proargtypes => 'timestamptz',
+ prosrc => 'select pg_catalog.pg_sleep(extract(epoch from $1) operator(pg_catalog.-) extract(epoch from pg_catalog.clock_timestamp()))' },
+{ oid => '315', descr => 'Is JIT compilation available in this session?',
+ proname => 'pg_jit_available', provolatile => 'v', prorettype => 'bool',
+ proargtypes => '', prosrc => 'pg_jit_available' },
+
+{ oid => '2971', descr => 'convert boolean to text',
+ proname => 'text', prorettype => 'text', proargtypes => 'bool',
+ prosrc => 'booltext' },
+
+# Aggregates (moved here from pg_aggregate for 7.3)
+
+{ oid => '2100',
+ descr => 'the average (arithmetic mean) as numeric of all bigint values',
+ proname => 'avg', prokind => 'a', proisstrict => 'f', prorettype => 'numeric',
+ proargtypes => 'int8', prosrc => 'aggregate_dummy' },
+{ oid => '2101',
+ descr => 'the average (arithmetic mean) as numeric of all integer values',
+ proname => 'avg', prokind => 'a', proisstrict => 'f', prorettype => 'numeric',
+ proargtypes => 'int4', prosrc => 'aggregate_dummy' },
+{ oid => '2102',
+ descr => 'the average (arithmetic mean) as numeric of all smallint values',
+ proname => 'avg', prokind => 'a', proisstrict => 'f', prorettype => 'numeric',
+ proargtypes => 'int2', prosrc => 'aggregate_dummy' },
+{ oid => '2103',
+ descr => 'the average (arithmetic mean) as numeric of all numeric values',
+ proname => 'avg', prokind => 'a', proisstrict => 'f', prorettype => 'numeric',
+ proargtypes => 'numeric', prosrc => 'aggregate_dummy' },
+{ oid => '2104',
+ descr => 'the average (arithmetic mean) as float8 of all float4 values',
+ proname => 'avg', prokind => 'a', proisstrict => 'f', prorettype => 'float8',
+ proargtypes => 'float4', prosrc => 'aggregate_dummy' },
+{ oid => '2105',
+ descr => 'the average (arithmetic mean) as float8 of all float8 values',
+ proname => 'avg', prokind => 'a', proisstrict => 'f', prorettype => 'float8',
+ proargtypes => 'float8', prosrc => 'aggregate_dummy' },
+{ oid => '2106',
+ descr => 'the average (arithmetic mean) as interval of all interval values',
+ proname => 'avg', prokind => 'a', proisstrict => 'f',
+ prorettype => 'interval', proargtypes => 'interval',
+ prosrc => 'aggregate_dummy' },
+
+{ oid => '2107', descr => 'sum as numeric across all bigint input values',
+ proname => 'sum', prokind => 'a', proisstrict => 'f', prorettype => 'numeric',
+ proargtypes => 'int8', prosrc => 'aggregate_dummy' },
+{ oid => '2108', descr => 'sum as bigint across all integer input values',
+ proname => 'sum', prokind => 'a', proisstrict => 'f', prorettype => 'int8',
+ proargtypes => 'int4', prosrc => 'aggregate_dummy' },
+{ oid => '2109', descr => 'sum as bigint across all smallint input values',
+ proname => 'sum', prokind => 'a', proisstrict => 'f', prorettype => 'int8',
+ proargtypes => 'int2', prosrc => 'aggregate_dummy' },
+{ oid => '2110', descr => 'sum as float4 across all float4 input values',
+ proname => 'sum', prokind => 'a', proisstrict => 'f', prorettype => 'float4',
+ proargtypes => 'float4', prosrc => 'aggregate_dummy' },
+{ oid => '2111', descr => 'sum as float8 across all float8 input values',
+ proname => 'sum', prokind => 'a', proisstrict => 'f', prorettype => 'float8',
+ proargtypes => 'float8', prosrc => 'aggregate_dummy' },
+{ oid => '2112', descr => 'sum as money across all money input values',
+ proname => 'sum', prokind => 'a', proisstrict => 'f', prorettype => 'money',
+ proargtypes => 'money', prosrc => 'aggregate_dummy' },
+{ oid => '2113', descr => 'sum as interval across all interval input values',
+ proname => 'sum', prokind => 'a', proisstrict => 'f',
+ prorettype => 'interval', proargtypes => 'interval',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2114', descr => 'sum as numeric across all numeric input values',
+ proname => 'sum', prokind => 'a', proisstrict => 'f', prorettype => 'numeric',
+ proargtypes => 'numeric', prosrc => 'aggregate_dummy' },
+
+{ oid => '2115', descr => 'maximum value of all bigint input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'int8',
+ proargtypes => 'int8', prosrc => 'aggregate_dummy' },
+{ oid => '2116', descr => 'maximum value of all integer input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'int4',
+ proargtypes => 'int4', prosrc => 'aggregate_dummy' },
+{ oid => '2117', descr => 'maximum value of all smallint input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'int2',
+ proargtypes => 'int2', prosrc => 'aggregate_dummy' },
+{ oid => '2118', descr => 'maximum value of all oid input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'oid',
+ proargtypes => 'oid', prosrc => 'aggregate_dummy' },
+{ oid => '2119', descr => 'maximum value of all float4 input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'float4',
+ proargtypes => 'float4', prosrc => 'aggregate_dummy' },
+{ oid => '2120', descr => 'maximum value of all float8 input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'float8',
+ proargtypes => 'float8', prosrc => 'aggregate_dummy' },
+{ oid => '2122', descr => 'maximum value of all date input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'date',
+ proargtypes => 'date', prosrc => 'aggregate_dummy' },
+{ oid => '2123', descr => 'maximum value of all time input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'time',
+ proargtypes => 'time', prosrc => 'aggregate_dummy' },
+{ oid => '2124',
+ descr => 'maximum value of all time with time zone input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'timetz',
+ proargtypes => 'timetz', prosrc => 'aggregate_dummy' },
+{ oid => '2125', descr => 'maximum value of all money input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'money',
+ proargtypes => 'money', prosrc => 'aggregate_dummy' },
+{ oid => '2126', descr => 'maximum value of all timestamp input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f',
+ prorettype => 'timestamp', proargtypes => 'timestamp',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2127',
+ descr => 'maximum value of all timestamp with time zone input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f',
+ prorettype => 'timestamptz', proargtypes => 'timestamptz',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2128', descr => 'maximum value of all interval input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f',
+ prorettype => 'interval', proargtypes => 'interval',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2129', descr => 'maximum value of all text input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'text',
+ proargtypes => 'text', prosrc => 'aggregate_dummy' },
+{ oid => '2130', descr => 'maximum value of all numeric input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'numeric',
+ proargtypes => 'numeric', prosrc => 'aggregate_dummy' },
+{ oid => '2050', descr => 'maximum value of all anyarray input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f',
+ prorettype => 'anyarray', proargtypes => 'anyarray',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2244', descr => 'maximum value of all bpchar input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'bpchar',
+ proargtypes => 'bpchar', prosrc => 'aggregate_dummy' },
+{ oid => '2797', descr => 'maximum value of all tid input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'tid',
+ proargtypes => 'tid', prosrc => 'aggregate_dummy' },
+{ oid => '3564', descr => 'maximum value of all inet input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'inet',
+ proargtypes => 'inet', prosrc => 'aggregate_dummy' },
+{ oid => '4189', descr => 'maximum value of all pg_lsn input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'pg_lsn',
+ proargtypes => 'pg_lsn', prosrc => 'aggregate_dummy' },
+
+{ oid => '2131', descr => 'minimum value of all bigint input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'int8',
+ proargtypes => 'int8', prosrc => 'aggregate_dummy' },
+{ oid => '2132', descr => 'minimum value of all integer input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'int4',
+ proargtypes => 'int4', prosrc => 'aggregate_dummy' },
+{ oid => '2133', descr => 'minimum value of all smallint input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'int2',
+ proargtypes => 'int2', prosrc => 'aggregate_dummy' },
+{ oid => '2134', descr => 'minimum value of all oid input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'oid',
+ proargtypes => 'oid', prosrc => 'aggregate_dummy' },
+{ oid => '2135', descr => 'minimum value of all float4 input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'float4',
+ proargtypes => 'float4', prosrc => 'aggregate_dummy' },
+{ oid => '2136', descr => 'minimum value of all float8 input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'float8',
+ proargtypes => 'float8', prosrc => 'aggregate_dummy' },
+{ oid => '2138', descr => 'minimum value of all date input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'date',
+ proargtypes => 'date', prosrc => 'aggregate_dummy' },
+{ oid => '2139', descr => 'minimum value of all time input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'time',
+ proargtypes => 'time', prosrc => 'aggregate_dummy' },
+{ oid => '2140',
+ descr => 'minimum value of all time with time zone input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'timetz',
+ proargtypes => 'timetz', prosrc => 'aggregate_dummy' },
+{ oid => '2141', descr => 'minimum value of all money input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'money',
+ proargtypes => 'money', prosrc => 'aggregate_dummy' },
+{ oid => '2142', descr => 'minimum value of all timestamp input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f',
+ prorettype => 'timestamp', proargtypes => 'timestamp',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2143',
+ descr => 'minimum value of all timestamp with time zone input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f',
+ prorettype => 'timestamptz', proargtypes => 'timestamptz',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2144', descr => 'minimum value of all interval input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f',
+ prorettype => 'interval', proargtypes => 'interval',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2145', descr => 'minimum value of all text values',
+ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'text',
+ proargtypes => 'text', prosrc => 'aggregate_dummy' },
+{ oid => '2146', descr => 'minimum value of all numeric input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'numeric',
+ proargtypes => 'numeric', prosrc => 'aggregate_dummy' },
+{ oid => '2051', descr => 'minimum value of all anyarray input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f',
+ prorettype => 'anyarray', proargtypes => 'anyarray',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2245', descr => 'minimum value of all bpchar input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'bpchar',
+ proargtypes => 'bpchar', prosrc => 'aggregate_dummy' },
+{ oid => '2798', descr => 'minimum value of all tid input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'tid',
+ proargtypes => 'tid', prosrc => 'aggregate_dummy' },
+{ oid => '3565', descr => 'minimum value of all inet input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'inet',
+ proargtypes => 'inet', prosrc => 'aggregate_dummy' },
+{ oid => '4190', descr => 'minimum value of all pg_lsn input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'pg_lsn',
+ proargtypes => 'pg_lsn', prosrc => 'aggregate_dummy' },
+
+# count has two forms: count(any) and count(*)
+{ oid => '2147',
+ descr => 'number of input rows for which the input expression is not null',
+ proname => 'count', prokind => 'a', proisstrict => 'f', prorettype => 'int8',
+ proargtypes => 'any', prosrc => 'aggregate_dummy' },
+{ oid => '2803', descr => 'number of input rows',
+ proname => 'count', prokind => 'a', proisstrict => 'f', prorettype => 'int8',
+ proargtypes => '', prosrc => 'aggregate_dummy' },
+
+{ oid => '2718',
+ descr => 'population variance of bigint input values (square of the population standard deviation)',
+ proname => 'var_pop', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'int8', prosrc => 'aggregate_dummy' },
+{ oid => '2719',
+ descr => 'population variance of integer input values (square of the population standard deviation)',
+ proname => 'var_pop', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'int4', prosrc => 'aggregate_dummy' },
+{ oid => '2720',
+ descr => 'population variance of smallint input values (square of the population standard deviation)',
+ proname => 'var_pop', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'int2', prosrc => 'aggregate_dummy' },
+{ oid => '2721',
+ descr => 'population variance of float4 input values (square of the population standard deviation)',
+ proname => 'var_pop', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float4',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2722',
+ descr => 'population variance of float8 input values (square of the population standard deviation)',
+ proname => 'var_pop', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2723',
+ descr => 'population variance of numeric input values (square of the population standard deviation)',
+ proname => 'var_pop', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'aggregate_dummy' },
+
+{ oid => '2641',
+ descr => 'sample variance of bigint input values (square of the sample standard deviation)',
+ proname => 'var_samp', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'int8', prosrc => 'aggregate_dummy' },
+{ oid => '2642',
+ descr => 'sample variance of integer input values (square of the sample standard deviation)',
+ proname => 'var_samp', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'int4', prosrc => 'aggregate_dummy' },
+{ oid => '2643',
+ descr => 'sample variance of smallint input values (square of the sample standard deviation)',
+ proname => 'var_samp', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'int2', prosrc => 'aggregate_dummy' },
+{ oid => '2644',
+ descr => 'sample variance of float4 input values (square of the sample standard deviation)',
+ proname => 'var_samp', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float4',
+ prosrc => 'aggregate_dummy' },
+
+{ oid => '2645',
+ descr => 'sample variance of float8 input values (square of the sample standard deviation)',
+ proname => 'var_samp', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2646',
+ descr => 'sample variance of numeric input values (square of the sample standard deviation)',
+ proname => 'var_samp', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'aggregate_dummy' },
+
+{ oid => '2148', descr => 'historical alias for var_samp',
+ proname => 'variance', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'int8', prosrc => 'aggregate_dummy' },
+{ oid => '2149', descr => 'historical alias for var_samp',
+ proname => 'variance', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'int4', prosrc => 'aggregate_dummy' },
+{ oid => '2150', descr => 'historical alias for var_samp',
+ proname => 'variance', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'int2', prosrc => 'aggregate_dummy' },
+{ oid => '2151', descr => 'historical alias for var_samp',
+ proname => 'variance', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float4',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2152', descr => 'historical alias for var_samp',
+ proname => 'variance', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2153', descr => 'historical alias for var_samp',
+ proname => 'variance', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'aggregate_dummy' },
+
+{ oid => '2724',
+ descr => 'population standard deviation of bigint input values',
+ proname => 'stddev_pop', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'int8', prosrc => 'aggregate_dummy' },
+{ oid => '2725',
+ descr => 'population standard deviation of integer input values',
+ proname => 'stddev_pop', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'int4', prosrc => 'aggregate_dummy' },
+{ oid => '2726',
+ descr => 'population standard deviation of smallint input values',
+ proname => 'stddev_pop', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'int2', prosrc => 'aggregate_dummy' },
+{ oid => '2727',
+ descr => 'population standard deviation of float4 input values',
+ proname => 'stddev_pop', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float4',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2728',
+ descr => 'population standard deviation of float8 input values',
+ proname => 'stddev_pop', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2729',
+ descr => 'population standard deviation of numeric input values',
+ proname => 'stddev_pop', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'aggregate_dummy' },
+
+{ oid => '2712', descr => 'sample standard deviation of bigint input values',
+ proname => 'stddev_samp', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'int8', prosrc => 'aggregate_dummy' },
+{ oid => '2713', descr => 'sample standard deviation of integer input values',
+ proname => 'stddev_samp', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'int4', prosrc => 'aggregate_dummy' },
+{ oid => '2714',
+ descr => 'sample standard deviation of smallint input values',
+ proname => 'stddev_samp', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'int2', prosrc => 'aggregate_dummy' },
+{ oid => '2715', descr => 'sample standard deviation of float4 input values',
+ proname => 'stddev_samp', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float4',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2716', descr => 'sample standard deviation of float8 input values',
+ proname => 'stddev_samp', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2717', descr => 'sample standard deviation of numeric input values',
+ proname => 'stddev_samp', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'aggregate_dummy' },
+
+{ oid => '2154', descr => 'historical alias for stddev_samp',
+ proname => 'stddev', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'int8', prosrc => 'aggregate_dummy' },
+{ oid => '2155', descr => 'historical alias for stddev_samp',
+ proname => 'stddev', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'int4', prosrc => 'aggregate_dummy' },
+{ oid => '2156', descr => 'historical alias for stddev_samp',
+ proname => 'stddev', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'int2', prosrc => 'aggregate_dummy' },
+{ oid => '2157', descr => 'historical alias for stddev_samp',
+ proname => 'stddev', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float4',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2158', descr => 'historical alias for stddev_samp',
+ proname => 'stddev', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float8',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2159', descr => 'historical alias for stddev_samp',
+ proname => 'stddev', prokind => 'a', proisstrict => 'f',
+ prorettype => 'numeric', proargtypes => 'numeric',
+ prosrc => 'aggregate_dummy' },
+
+{ oid => '2818',
+ descr => 'number of input rows in which both expressions are not null',
+ proname => 'regr_count', prokind => 'a', proisstrict => 'f',
+ prorettype => 'int8', proargtypes => 'float8 float8',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2819',
+ descr => 'sum of squares of the independent variable (sum(X^2) - sum(X)^2/N)',
+ proname => 'regr_sxx', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float8 float8',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2820',
+ descr => 'sum of squares of the dependent variable (sum(Y^2) - sum(Y)^2/N)',
+ proname => 'regr_syy', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float8 float8',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2821',
+ descr => 'sum of products of independent times dependent variable (sum(X*Y) - sum(X) * sum(Y)/N)',
+ proname => 'regr_sxy', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float8 float8',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2822', descr => 'average of the independent variable (sum(X)/N)',
+ proname => 'regr_avgx', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float8 float8',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2823', descr => 'average of the dependent variable (sum(Y)/N)',
+ proname => 'regr_avgy', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float8 float8',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2824', descr => 'square of the correlation coefficient',
+ proname => 'regr_r2', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float8 float8',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2825',
+ descr => 'slope of the least-squares-fit linear equation determined by the (X, Y) pairs',
+ proname => 'regr_slope', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float8 float8',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2826',
+ descr => 'y-intercept of the least-squares-fit linear equation determined by the (X, Y) pairs',
+ proname => 'regr_intercept', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float8 float8',
+ prosrc => 'aggregate_dummy' },
+
+{ oid => '2827', descr => 'population covariance',
+ proname => 'covar_pop', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float8 float8',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2828', descr => 'sample covariance',
+ proname => 'covar_samp', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float8 float8',
+ prosrc => 'aggregate_dummy' },
+{ oid => '2829', descr => 'correlation coefficient',
+ proname => 'corr', prokind => 'a', proisstrict => 'f', prorettype => 'float8',
+ proargtypes => 'float8 float8', prosrc => 'aggregate_dummy' },
+
+{ oid => '2160',
+ proname => 'text_pattern_lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'text_pattern_lt' },
+{ oid => '2161',
+ proname => 'text_pattern_le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'text_pattern_le' },
+{ oid => '2163',
+ proname => 'text_pattern_ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'text_pattern_ge' },
+{ oid => '2164',
+ proname => 'text_pattern_gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'text_pattern_gt' },
+{ oid => '2166', descr => 'less-equal-greater',
+ proname => 'bttext_pattern_cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'text text', prosrc => 'bttext_pattern_cmp' },
+{ oid => '3332', descr => 'sort support',
+ proname => 'bttext_pattern_sortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'bttext_pattern_sortsupport' },
+
+{ oid => '2174',
+ proname => 'bpchar_pattern_lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bpchar bpchar', prosrc => 'bpchar_pattern_lt' },
+{ oid => '2175',
+ proname => 'bpchar_pattern_le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bpchar bpchar', prosrc => 'bpchar_pattern_le' },
+{ oid => '2177',
+ proname => 'bpchar_pattern_ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bpchar bpchar', prosrc => 'bpchar_pattern_ge' },
+{ oid => '2178',
+ proname => 'bpchar_pattern_gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'bpchar bpchar', prosrc => 'bpchar_pattern_gt' },
+{ oid => '2180', descr => 'less-equal-greater',
+ proname => 'btbpchar_pattern_cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'bpchar bpchar', prosrc => 'btbpchar_pattern_cmp' },
+{ oid => '3333', descr => 'sort support',
+ proname => 'btbpchar_pattern_sortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'btbpchar_pattern_sortsupport' },
+
+{ oid => '2188', descr => 'less-equal-greater',
+ proname => 'btint48cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'int4 int8', prosrc => 'btint48cmp' },
+{ oid => '2189', descr => 'less-equal-greater',
+ proname => 'btint84cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'int8 int4', prosrc => 'btint84cmp' },
+{ oid => '2190', descr => 'less-equal-greater',
+ proname => 'btint24cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'int2 int4', prosrc => 'btint24cmp' },
+{ oid => '2191', descr => 'less-equal-greater',
+ proname => 'btint42cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'int4 int2', prosrc => 'btint42cmp' },
+{ oid => '2192', descr => 'less-equal-greater',
+ proname => 'btint28cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'int2 int8', prosrc => 'btint28cmp' },
+{ oid => '2193', descr => 'less-equal-greater',
+ proname => 'btint82cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'int8 int2', prosrc => 'btint82cmp' },
+{ oid => '2194', descr => 'less-equal-greater',
+ proname => 'btfloat48cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'float4 float8', prosrc => 'btfloat48cmp' },
+{ oid => '2195', descr => 'less-equal-greater',
+ proname => 'btfloat84cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'float8 float4', prosrc => 'btfloat84cmp' },
+
+{ oid => '2212', descr => 'I/O',
+ proname => 'regprocedurein', provolatile => 's', prorettype => 'regprocedure',
+ proargtypes => 'cstring', prosrc => 'regprocedurein' },
+{ oid => '2213', descr => 'I/O',
+ proname => 'regprocedureout', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'regprocedure', prosrc => 'regprocedureout' },
+{ oid => '2214', descr => 'I/O',
+ proname => 'regoperin', provolatile => 's', prorettype => 'regoper',
+ proargtypes => 'cstring', prosrc => 'regoperin' },
+{ oid => '2215', descr => 'I/O',
+ proname => 'regoperout', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'regoper', prosrc => 'regoperout' },
+{ oid => '3492', descr => 'convert operator name to regoper',
+ proname => 'to_regoper', provolatile => 's', prorettype => 'regoper',
+ proargtypes => 'text', prosrc => 'to_regoper' },
+{ oid => '3476', descr => 'convert operator name to regoperator',
+ proname => 'to_regoperator', provolatile => 's', prorettype => 'regoperator',
+ proargtypes => 'text', prosrc => 'to_regoperator' },
+{ oid => '2216', descr => 'I/O',
+ proname => 'regoperatorin', provolatile => 's', prorettype => 'regoperator',
+ proargtypes => 'cstring', prosrc => 'regoperatorin' },
+{ oid => '2217', descr => 'I/O',
+ proname => 'regoperatorout', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'regoperator', prosrc => 'regoperatorout' },
+{ oid => '2218', descr => 'I/O',
+ proname => 'regclassin', provolatile => 's', prorettype => 'regclass',
+ proargtypes => 'cstring', prosrc => 'regclassin' },
+{ oid => '2219', descr => 'I/O',
+ proname => 'regclassout', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'regclass', prosrc => 'regclassout' },
+{ oid => '3495', descr => 'convert classname to regclass',
+ proname => 'to_regclass', provolatile => 's', prorettype => 'regclass',
+ proargtypes => 'text', prosrc => 'to_regclass' },
+{ oid => '4193', descr => 'I/O',
+ proname => 'regcollationin', provolatile => 's', prorettype => 'regcollation',
+ proargtypes => 'cstring', prosrc => 'regcollationin' },
+{ oid => '4194', descr => 'I/O',
+ proname => 'regcollationout', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'regcollation', prosrc => 'regcollationout' },
+{ oid => '4195', descr => 'convert classname to regcollation',
+ proname => 'to_regcollation', provolatile => 's',
+ prorettype => 'regcollation', proargtypes => 'text',
+ prosrc => 'to_regcollation' },
+{ oid => '2220', descr => 'I/O',
+ proname => 'regtypein', provolatile => 's', prorettype => 'regtype',
+ proargtypes => 'cstring', prosrc => 'regtypein' },
+{ oid => '2221', descr => 'I/O',
+ proname => 'regtypeout', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'regtype', prosrc => 'regtypeout' },
+{ oid => '3493', descr => 'convert type name to regtype',
+ proname => 'to_regtype', provolatile => 's', prorettype => 'regtype',
+ proargtypes => 'text', prosrc => 'to_regtype' },
+{ oid => '1079', descr => 'convert text to regclass',
+ proname => 'regclass', provolatile => 's', prorettype => 'regclass',
+ proargtypes => 'text', prosrc => 'text_regclass' },
+
+{ oid => '4098', descr => 'I/O',
+ proname => 'regrolein', provolatile => 's', prorettype => 'regrole',
+ proargtypes => 'cstring', prosrc => 'regrolein' },
+{ oid => '4092', descr => 'I/O',
+ proname => 'regroleout', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'regrole', prosrc => 'regroleout' },
+{ oid => '4093', descr => 'convert role name to regrole',
+ proname => 'to_regrole', provolatile => 's', prorettype => 'regrole',
+ proargtypes => 'text', prosrc => 'to_regrole' },
+
+{ oid => '4084', descr => 'I/O',
+ proname => 'regnamespacein', provolatile => 's', prorettype => 'regnamespace',
+ proargtypes => 'cstring', prosrc => 'regnamespacein' },
+{ oid => '4085', descr => 'I/O',
+ proname => 'regnamespaceout', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'regnamespace', prosrc => 'regnamespaceout' },
+{ oid => '4086', descr => 'convert namespace name to regnamespace',
+ proname => 'to_regnamespace', provolatile => 's',
+ prorettype => 'regnamespace', proargtypes => 'text',
+ prosrc => 'to_regnamespace' },
+
+{ oid => '1268',
+ descr => 'parse qualified identifier to array of identifiers',
+ proname => 'parse_ident', prorettype => '_text', proargtypes => 'text bool',
+ proargnames => '{str,strict}', prosrc => 'parse_ident' },
+
+{ oid => '2246', descr => '(internal)',
+ proname => 'fmgr_internal_validator', provolatile => 's',
+ prorettype => 'void', proargtypes => 'oid',
+ prosrc => 'fmgr_internal_validator' },
+{ oid => '2247', descr => '(internal)',
+ proname => 'fmgr_c_validator', provolatile => 's', prorettype => 'void',
+ proargtypes => 'oid', prosrc => 'fmgr_c_validator' },
+{ oid => '2248', descr => '(internal)',
+ proname => 'fmgr_sql_validator', provolatile => 's', prorettype => 'void',
+ proargtypes => 'oid', prosrc => 'fmgr_sql_validator' },
+
+{ oid => '2250',
+ descr => 'user privilege on database by username, database name',
+ proname => 'has_database_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name text text',
+ prosrc => 'has_database_privilege_name_name' },
+{ oid => '2251',
+ descr => 'user privilege on database by username, database oid',
+ proname => 'has_database_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name oid text', prosrc => 'has_database_privilege_name_id' },
+{ oid => '2252',
+ descr => 'user privilege on database by user oid, database name',
+ proname => 'has_database_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text text', prosrc => 'has_database_privilege_id_name' },
+{ oid => '2253',
+ descr => 'user privilege on database by user oid, database oid',
+ proname => 'has_database_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid oid text', prosrc => 'has_database_privilege_id_id' },
+{ oid => '2254',
+ descr => 'current user privilege on database by database name',
+ proname => 'has_database_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'has_database_privilege_name' },
+{ oid => '2255',
+ descr => 'current user privilege on database by database oid',
+ proname => 'has_database_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text', prosrc => 'has_database_privilege_id' },
+
+{ oid => '2256',
+ descr => 'user privilege on function by username, function name',
+ proname => 'has_function_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name text text',
+ prosrc => 'has_function_privilege_name_name' },
+{ oid => '2257',
+ descr => 'user privilege on function by username, function oid',
+ proname => 'has_function_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name oid text', prosrc => 'has_function_privilege_name_id' },
+{ oid => '2258',
+ descr => 'user privilege on function by user oid, function name',
+ proname => 'has_function_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text text', prosrc => 'has_function_privilege_id_name' },
+{ oid => '2259',
+ descr => 'user privilege on function by user oid, function oid',
+ proname => 'has_function_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid oid text', prosrc => 'has_function_privilege_id_id' },
+{ oid => '2260',
+ descr => 'current user privilege on function by function name',
+ proname => 'has_function_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'has_function_privilege_name' },
+{ oid => '2261',
+ descr => 'current user privilege on function by function oid',
+ proname => 'has_function_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text', prosrc => 'has_function_privilege_id' },
+
+{ oid => '2262',
+ descr => 'user privilege on language by username, language name',
+ proname => 'has_language_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name text text',
+ prosrc => 'has_language_privilege_name_name' },
+{ oid => '2263',
+ descr => 'user privilege on language by username, language oid',
+ proname => 'has_language_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name oid text', prosrc => 'has_language_privilege_name_id' },
+{ oid => '2264',
+ descr => 'user privilege on language by user oid, language name',
+ proname => 'has_language_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text text', prosrc => 'has_language_privilege_id_name' },
+{ oid => '2265',
+ descr => 'user privilege on language by user oid, language oid',
+ proname => 'has_language_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid oid text', prosrc => 'has_language_privilege_id_id' },
+{ oid => '2266',
+ descr => 'current user privilege on language by language name',
+ proname => 'has_language_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'has_language_privilege_name' },
+{ oid => '2267',
+ descr => 'current user privilege on language by language oid',
+ proname => 'has_language_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text', prosrc => 'has_language_privilege_id' },
+
+{ oid => '2268', descr => 'user privilege on schema by username, schema name',
+ proname => 'has_schema_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name text text', prosrc => 'has_schema_privilege_name_name' },
+{ oid => '2269', descr => 'user privilege on schema by username, schema oid',
+ proname => 'has_schema_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name oid text', prosrc => 'has_schema_privilege_name_id' },
+{ oid => '2270', descr => 'user privilege on schema by user oid, schema name',
+ proname => 'has_schema_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text text', prosrc => 'has_schema_privilege_id_name' },
+{ oid => '2271', descr => 'user privilege on schema by user oid, schema oid',
+ proname => 'has_schema_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid oid text', prosrc => 'has_schema_privilege_id_id' },
+{ oid => '2272', descr => 'current user privilege on schema by schema name',
+ proname => 'has_schema_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'has_schema_privilege_name' },
+{ oid => '2273', descr => 'current user privilege on schema by schema oid',
+ proname => 'has_schema_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text', prosrc => 'has_schema_privilege_id' },
+
+{ oid => '2390',
+ descr => 'user privilege on tablespace by username, tablespace name',
+ proname => 'has_tablespace_privilege', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'name text text',
+ prosrc => 'has_tablespace_privilege_name_name' },
+{ oid => '2391',
+ descr => 'user privilege on tablespace by username, tablespace oid',
+ proname => 'has_tablespace_privilege', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'name oid text',
+ prosrc => 'has_tablespace_privilege_name_id' },
+{ oid => '2392',
+ descr => 'user privilege on tablespace by user oid, tablespace name',
+ proname => 'has_tablespace_privilege', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid text text',
+ prosrc => 'has_tablespace_privilege_id_name' },
+{ oid => '2393',
+ descr => 'user privilege on tablespace by user oid, tablespace oid',
+ proname => 'has_tablespace_privilege', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid oid text',
+ prosrc => 'has_tablespace_privilege_id_id' },
+{ oid => '2394',
+ descr => 'current user privilege on tablespace by tablespace name',
+ proname => 'has_tablespace_privilege', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'text text',
+ prosrc => 'has_tablespace_privilege_name' },
+{ oid => '2395',
+ descr => 'current user privilege on tablespace by tablespace oid',
+ proname => 'has_tablespace_privilege', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid text',
+ prosrc => 'has_tablespace_privilege_id' },
+
+{ oid => '3000',
+ descr => 'user privilege on foreign data wrapper by username, foreign data wrapper name',
+ proname => 'has_foreign_data_wrapper_privilege', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'name text text',
+ prosrc => 'has_foreign_data_wrapper_privilege_name_name' },
+{ oid => '3001',
+ descr => 'user privilege on foreign data wrapper by username, foreign data wrapper oid',
+ proname => 'has_foreign_data_wrapper_privilege', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'name oid text',
+ prosrc => 'has_foreign_data_wrapper_privilege_name_id' },
+{ oid => '3002',
+ descr => 'user privilege on foreign data wrapper by user oid, foreign data wrapper name',
+ proname => 'has_foreign_data_wrapper_privilege', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid text text',
+ prosrc => 'has_foreign_data_wrapper_privilege_id_name' },
+{ oid => '3003',
+ descr => 'user privilege on foreign data wrapper by user oid, foreign data wrapper oid',
+ proname => 'has_foreign_data_wrapper_privilege', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid oid text',
+ prosrc => 'has_foreign_data_wrapper_privilege_id_id' },
+{ oid => '3004',
+ descr => 'current user privilege on foreign data wrapper by foreign data wrapper name',
+ proname => 'has_foreign_data_wrapper_privilege', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'text text',
+ prosrc => 'has_foreign_data_wrapper_privilege_name' },
+{ oid => '3005',
+ descr => 'current user privilege on foreign data wrapper by foreign data wrapper oid',
+ proname => 'has_foreign_data_wrapper_privilege', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'oid text',
+ prosrc => 'has_foreign_data_wrapper_privilege_id' },
+
+{ oid => '3006', descr => 'user privilege on server by username, server name',
+ proname => 'has_server_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name text text', prosrc => 'has_server_privilege_name_name' },
+{ oid => '3007', descr => 'user privilege on server by username, server oid',
+ proname => 'has_server_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name oid text', prosrc => 'has_server_privilege_name_id' },
+{ oid => '3008', descr => 'user privilege on server by user oid, server name',
+ proname => 'has_server_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text text', prosrc => 'has_server_privilege_id_name' },
+{ oid => '3009', descr => 'user privilege on server by user oid, server oid',
+ proname => 'has_server_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid oid text', prosrc => 'has_server_privilege_id_id' },
+{ oid => '3010', descr => 'current user privilege on server by server name',
+ proname => 'has_server_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'has_server_privilege_name' },
+{ oid => '3011', descr => 'current user privilege on server by server oid',
+ proname => 'has_server_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text', prosrc => 'has_server_privilege_id' },
+
+{ oid => '3138', descr => 'user privilege on type by username, type name',
+ proname => 'has_type_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name text text', prosrc => 'has_type_privilege_name_name' },
+{ oid => '3139', descr => 'user privilege on type by username, type oid',
+ proname => 'has_type_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name oid text', prosrc => 'has_type_privilege_name_id' },
+{ oid => '3140', descr => 'user privilege on type by user oid, type name',
+ proname => 'has_type_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text text', prosrc => 'has_type_privilege_id_name' },
+{ oid => '3141', descr => 'user privilege on type by user oid, type oid',
+ proname => 'has_type_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid oid text', prosrc => 'has_type_privilege_id_id' },
+{ oid => '3142', descr => 'current user privilege on type by type name',
+ proname => 'has_type_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'text text', prosrc => 'has_type_privilege_name' },
+{ oid => '3143', descr => 'current user privilege on type by type oid',
+ proname => 'has_type_privilege', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text', prosrc => 'has_type_privilege_id' },
+
+{ oid => '2705', descr => 'user privilege on role by username, role name',
+ proname => 'pg_has_role', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name name text', prosrc => 'pg_has_role_name_name' },
+{ oid => '2706', descr => 'user privilege on role by username, role oid',
+ proname => 'pg_has_role', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name oid text', prosrc => 'pg_has_role_name_id' },
+{ oid => '2707', descr => 'user privilege on role by user oid, role name',
+ proname => 'pg_has_role', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid name text', prosrc => 'pg_has_role_id_name' },
+{ oid => '2708', descr => 'user privilege on role by user oid, role oid',
+ proname => 'pg_has_role', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid oid text', prosrc => 'pg_has_role_id_id' },
+{ oid => '2709', descr => 'current user privilege on role by role name',
+ proname => 'pg_has_role', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'name text', prosrc => 'pg_has_role_name' },
+{ oid => '2710', descr => 'current user privilege on role by role oid',
+ proname => 'pg_has_role', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid text', prosrc => 'pg_has_role_id' },
+
+{ oid => '1269',
+ descr => 'bytes required to store the value, perhaps with compression',
+ proname => 'pg_column_size', provolatile => 's', prorettype => 'int4',
+ proargtypes => 'any', prosrc => 'pg_column_size' },
+{ oid => '2322',
+ descr => 'total disk space usage for the specified tablespace',
+ proname => 'pg_tablespace_size', provolatile => 'v', prorettype => 'int8',
+ proargtypes => 'oid', prosrc => 'pg_tablespace_size_oid' },
+{ oid => '2323',
+ descr => 'total disk space usage for the specified tablespace',
+ proname => 'pg_tablespace_size', provolatile => 'v', prorettype => 'int8',
+ proargtypes => 'name', prosrc => 'pg_tablespace_size_name' },
+{ oid => '2324', descr => 'total disk space usage for the specified database',
+ proname => 'pg_database_size', provolatile => 'v', prorettype => 'int8',
+ proargtypes => 'oid', prosrc => 'pg_database_size_oid' },
+{ oid => '2168', descr => 'total disk space usage for the specified database',
+ proname => 'pg_database_size', provolatile => 'v', prorettype => 'int8',
+ proargtypes => 'name', prosrc => 'pg_database_size_name' },
+{ oid => '2325',
+ descr => 'disk space usage for the main fork of the specified table or index',
+ proname => 'pg_relation_size', prolang => 'sql', provolatile => 'v',
+ prorettype => 'int8', proargtypes => 'regclass',
+ prosrc => 'select pg_catalog.pg_relation_size($1, \'main\')' },
+{ oid => '2332',
+ descr => 'disk space usage for the specified fork of a table or index',
+ proname => 'pg_relation_size', provolatile => 'v', prorettype => 'int8',
+ proargtypes => 'regclass text', prosrc => 'pg_relation_size' },
+{ oid => '2286',
+ descr => 'total disk space usage for the specified table and associated indexes',
+ proname => 'pg_total_relation_size', provolatile => 'v', prorettype => 'int8',
+ proargtypes => 'regclass', prosrc => 'pg_total_relation_size' },
+{ oid => '2288',
+ descr => 'convert a long int to a human readable text using size units',
+ proname => 'pg_size_pretty', prorettype => 'text', proargtypes => 'int8',
+ prosrc => 'pg_size_pretty' },
+{ oid => '3166',
+ descr => 'convert a numeric to a human readable text using size units',
+ proname => 'pg_size_pretty', prorettype => 'text', proargtypes => 'numeric',
+ prosrc => 'pg_size_pretty_numeric' },
+{ oid => '3334',
+ descr => 'convert a size in human-readable format with size units into bytes',
+ proname => 'pg_size_bytes', prorettype => 'int8', proargtypes => 'text',
+ prosrc => 'pg_size_bytes' },
+{ oid => '2997',
+ descr => 'disk space usage for the specified table, including TOAST, free space and visibility map',
+ proname => 'pg_table_size', provolatile => 'v', prorettype => 'int8',
+ proargtypes => 'regclass', prosrc => 'pg_table_size' },
+{ oid => '2998',
+ descr => 'disk space usage for all indexes attached to the specified table',
+ proname => 'pg_indexes_size', provolatile => 'v', prorettype => 'int8',
+ proargtypes => 'regclass', prosrc => 'pg_indexes_size' },
+{ oid => '2999', descr => 'filenode identifier of relation',
+ proname => 'pg_relation_filenode', provolatile => 's', prorettype => 'oid',
+ proargtypes => 'regclass', prosrc => 'pg_relation_filenode' },
+{ oid => '3454', descr => 'relation OID for filenode and tablespace',
+ proname => 'pg_filenode_relation', provolatile => 's',
+ prorettype => 'regclass', proargtypes => 'oid oid',
+ prosrc => 'pg_filenode_relation' },
+{ oid => '3034', descr => 'file path of relation',
+ proname => 'pg_relation_filepath', provolatile => 's', prorettype => 'text',
+ proargtypes => 'regclass', prosrc => 'pg_relation_filepath' },
+
+{ oid => '2316', descr => '(internal)',
+ proname => 'postgresql_fdw_validator', prorettype => 'bool',
+ proargtypes => '_text oid', prosrc => 'postgresql_fdw_validator' },
+
+{ oid => '2290', descr => 'I/O',
+ proname => 'record_in', provolatile => 's', prorettype => 'record',
+ proargtypes => 'cstring oid int4', prosrc => 'record_in' },
+{ oid => '2291', descr => 'I/O',
+ proname => 'record_out', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'record', prosrc => 'record_out' },
+{ oid => '2292', descr => 'I/O',
+ proname => 'cstring_in', prorettype => 'cstring', proargtypes => 'cstring',
+ prosrc => 'cstring_in' },
+{ oid => '2293', descr => 'I/O',
+ proname => 'cstring_out', prorettype => 'cstring', proargtypes => 'cstring',
+ prosrc => 'cstring_out' },
+{ oid => '2294', descr => 'I/O',
+ proname => 'any_in', prorettype => 'any', proargtypes => 'cstring',
+ prosrc => 'any_in' },
+{ oid => '2295', descr => 'I/O',
+ proname => 'any_out', prorettype => 'cstring', proargtypes => 'any',
+ prosrc => 'any_out' },
+{ oid => '2296', descr => 'I/O',
+ proname => 'anyarray_in', prorettype => 'anyarray', proargtypes => 'cstring',
+ prosrc => 'anyarray_in' },
+{ oid => '2297', descr => 'I/O',
+ proname => 'anyarray_out', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'anyarray', prosrc => 'anyarray_out' },
+{ oid => '2298', descr => 'I/O',
+ proname => 'void_in', prorettype => 'void', proargtypes => 'cstring',
+ prosrc => 'void_in' },
+{ oid => '2299', descr => 'I/O',
+ proname => 'void_out', prorettype => 'cstring', proargtypes => 'void',
+ prosrc => 'void_out' },
+{ oid => '2300', descr => 'I/O',
+ proname => 'trigger_in', proisstrict => 'f', prorettype => 'trigger',
+ proargtypes => 'cstring', prosrc => 'trigger_in' },
+{ oid => '2301', descr => 'I/O',
+ proname => 'trigger_out', prorettype => 'cstring', proargtypes => 'trigger',
+ prosrc => 'trigger_out' },
+{ oid => '3594', descr => 'I/O',
+ proname => 'event_trigger_in', proisstrict => 'f',
+ prorettype => 'event_trigger', proargtypes => 'cstring',
+ prosrc => 'event_trigger_in' },
+{ oid => '3595', descr => 'I/O',
+ proname => 'event_trigger_out', prorettype => 'cstring',
+ proargtypes => 'event_trigger', prosrc => 'event_trigger_out' },
+{ oid => '2302', descr => 'I/O',
+ proname => 'language_handler_in', proisstrict => 'f',
+ prorettype => 'language_handler', proargtypes => 'cstring',
+ prosrc => 'language_handler_in' },
+{ oid => '2303', descr => 'I/O',
+ proname => 'language_handler_out', prorettype => 'cstring',
+ proargtypes => 'language_handler', prosrc => 'language_handler_out' },
+{ oid => '2304', descr => 'I/O',
+ proname => 'internal_in', proisstrict => 'f', prorettype => 'internal',
+ proargtypes => 'cstring', prosrc => 'internal_in' },
+{ oid => '2305', descr => 'I/O',
+ proname => 'internal_out', prorettype => 'cstring', proargtypes => 'internal',
+ prosrc => 'internal_out' },
+{ oid => '2312', descr => 'I/O',
+ proname => 'anyelement_in', prorettype => 'anyelement',
+ proargtypes => 'cstring', prosrc => 'anyelement_in' },
+{ oid => '2313', descr => 'I/O',
+ proname => 'anyelement_out', prorettype => 'cstring',
+ proargtypes => 'anyelement', prosrc => 'anyelement_out' },
+{ oid => '2398', descr => 'I/O',
+ proname => 'shell_in', proisstrict => 'f', prorettype => 'void',
+ proargtypes => 'cstring', prosrc => 'shell_in' },
+{ oid => '2399', descr => 'I/O',
+ proname => 'shell_out', prorettype => 'cstring', proargtypes => 'void',
+ prosrc => 'shell_out' },
+{ oid => '2597', descr => 'I/O',
+ proname => 'domain_in', proisstrict => 'f', provolatile => 's',
+ prorettype => 'any', proargtypes => 'cstring oid int4',
+ prosrc => 'domain_in' },
+{ oid => '2598', descr => 'I/O',
+ proname => 'domain_recv', proisstrict => 'f', provolatile => 's',
+ prorettype => 'any', proargtypes => 'internal oid int4',
+ prosrc => 'domain_recv' },
+{ oid => '2777', descr => 'I/O',
+ proname => 'anynonarray_in', prorettype => 'anynonarray',
+ proargtypes => 'cstring', prosrc => 'anynonarray_in' },
+{ oid => '2778', descr => 'I/O',
+ proname => 'anynonarray_out', prorettype => 'cstring',
+ proargtypes => 'anynonarray', prosrc => 'anynonarray_out' },
+{ oid => '3116', descr => 'I/O',
+ proname => 'fdw_handler_in', proisstrict => 'f', prorettype => 'fdw_handler',
+ proargtypes => 'cstring', prosrc => 'fdw_handler_in' },
+{ oid => '3117', descr => 'I/O',
+ proname => 'fdw_handler_out', prorettype => 'cstring',
+ proargtypes => 'fdw_handler', prosrc => 'fdw_handler_out' },
+{ oid => '326', descr => 'I/O',
+ proname => 'index_am_handler_in', proisstrict => 'f',
+ prorettype => 'index_am_handler', proargtypes => 'cstring',
+ prosrc => 'index_am_handler_in' },
+{ oid => '327', descr => 'I/O',
+ proname => 'index_am_handler_out', prorettype => 'cstring',
+ proargtypes => 'index_am_handler', prosrc => 'index_am_handler_out' },
+{ oid => '3311', descr => 'I/O',
+ proname => 'tsm_handler_in', proisstrict => 'f', prorettype => 'tsm_handler',
+ proargtypes => 'cstring', prosrc => 'tsm_handler_in' },
+{ oid => '3312', descr => 'I/O',
+ proname => 'tsm_handler_out', prorettype => 'cstring',
+ proargtypes => 'tsm_handler', prosrc => 'tsm_handler_out' },
+{ oid => '267', descr => 'I/O',
+ proname => 'table_am_handler_in', proisstrict => 'f',
+ prorettype => 'table_am_handler', proargtypes => 'cstring',
+ prosrc => 'table_am_handler_in' },
+{ oid => '268', descr => 'I/O',
+ proname => 'table_am_handler_out', prorettype => 'cstring',
+ proargtypes => 'table_am_handler', prosrc => 'table_am_handler_out' },
+{ oid => '5086', descr => 'I/O',
+ proname => 'anycompatible_in', prorettype => 'anycompatible',
+ proargtypes => 'cstring', prosrc => 'anycompatible_in' },
+{ oid => '5087', descr => 'I/O',
+ proname => 'anycompatible_out', prorettype => 'cstring',
+ proargtypes => 'anycompatible', prosrc => 'anycompatible_out' },
+{ oid => '5088', descr => 'I/O',
+ proname => 'anycompatiblearray_in', prorettype => 'anycompatiblearray',
+ proargtypes => 'cstring', prosrc => 'anycompatiblearray_in' },
+{ oid => '5089', descr => 'I/O',
+ proname => 'anycompatiblearray_out', provolatile => 's',
+ prorettype => 'cstring', proargtypes => 'anycompatiblearray',
+ prosrc => 'anycompatiblearray_out' },
+{ oid => '5090', descr => 'I/O',
+ proname => 'anycompatiblearray_recv', provolatile => 's',
+ prorettype => 'anycompatiblearray', proargtypes => 'internal',
+ prosrc => 'anycompatiblearray_recv' },
+{ oid => '5091', descr => 'I/O',
+ proname => 'anycompatiblearray_send', provolatile => 's',
+ prorettype => 'bytea', proargtypes => 'anycompatiblearray',
+ prosrc => 'anycompatiblearray_send' },
+{ oid => '5092', descr => 'I/O',
+ proname => 'anycompatiblenonarray_in', prorettype => 'anycompatiblenonarray',
+ proargtypes => 'cstring', prosrc => 'anycompatiblenonarray_in' },
+{ oid => '5093', descr => 'I/O',
+ proname => 'anycompatiblenonarray_out', prorettype => 'cstring',
+ proargtypes => 'anycompatiblenonarray',
+ prosrc => 'anycompatiblenonarray_out' },
+{ oid => '5094', descr => 'I/O',
+ proname => 'anycompatiblerange_in', provolatile => 's',
+ prorettype => 'anycompatiblerange', proargtypes => 'cstring oid int4',
+ prosrc => 'anycompatiblerange_in' },
+{ oid => '5095', descr => 'I/O',
+ proname => 'anycompatiblerange_out', provolatile => 's',
+ prorettype => 'cstring', proargtypes => 'anycompatiblerange',
+ prosrc => 'anycompatiblerange_out' },
+
+# tablesample method handlers
+{ oid => '3313', descr => 'BERNOULLI tablesample method handler',
+ proname => 'bernoulli', provolatile => 'v', prorettype => 'tsm_handler',
+ proargtypes => 'internal', prosrc => 'tsm_bernoulli_handler' },
+{ oid => '3314', descr => 'SYSTEM tablesample method handler',
+ proname => 'system', provolatile => 'v', prorettype => 'tsm_handler',
+ proargtypes => 'internal', prosrc => 'tsm_system_handler' },
+
+# cryptographic
+{ oid => '2311', descr => 'MD5 hash',
+ proname => 'md5', proleakproof => 't', prorettype => 'text',
+ proargtypes => 'text', prosrc => 'md5_text' },
+{ oid => '2321', descr => 'MD5 hash',
+ proname => 'md5', proleakproof => 't', prorettype => 'text',
+ proargtypes => 'bytea', prosrc => 'md5_bytea' },
+{ oid => '3419', descr => 'SHA-224 hash',
+ proname => 'sha224', proleakproof => 't', prorettype => 'bytea',
+ proargtypes => 'bytea', prosrc => 'sha224_bytea' },
+{ oid => '3420', descr => 'SHA-256 hash',
+ proname => 'sha256', proleakproof => 't', prorettype => 'bytea',
+ proargtypes => 'bytea', prosrc => 'sha256_bytea' },
+{ oid => '3421', descr => 'SHA-384 hash',
+ proname => 'sha384', proleakproof => 't', prorettype => 'bytea',
+ proargtypes => 'bytea', prosrc => 'sha384_bytea' },
+{ oid => '3422', descr => 'SHA-512 hash',
+ proname => 'sha512', proleakproof => 't', prorettype => 'bytea',
+ proargtypes => 'bytea', prosrc => 'sha512_bytea' },
+
+# crosstype operations for date vs. timestamp and timestamptz
+{ oid => '2338',
+ proname => 'date_lt_timestamp', prorettype => 'bool',
+ proargtypes => 'date timestamp', prosrc => 'date_lt_timestamp' },
+{ oid => '2339',
+ proname => 'date_le_timestamp', prorettype => 'bool',
+ proargtypes => 'date timestamp', prosrc => 'date_le_timestamp' },
+{ oid => '2340',
+ proname => 'date_eq_timestamp', prorettype => 'bool',
+ proargtypes => 'date timestamp', prosrc => 'date_eq_timestamp' },
+{ oid => '2341',
+ proname => 'date_gt_timestamp', prorettype => 'bool',
+ proargtypes => 'date timestamp', prosrc => 'date_gt_timestamp' },
+{ oid => '2342',
+ proname => 'date_ge_timestamp', prorettype => 'bool',
+ proargtypes => 'date timestamp', prosrc => 'date_ge_timestamp' },
+{ oid => '2343',
+ proname => 'date_ne_timestamp', prorettype => 'bool',
+ proargtypes => 'date timestamp', prosrc => 'date_ne_timestamp' },
+{ oid => '2344', descr => 'less-equal-greater',
+ proname => 'date_cmp_timestamp', prorettype => 'int4',
+ proargtypes => 'date timestamp', prosrc => 'date_cmp_timestamp' },
+
+{ oid => '2351',
+ proname => 'date_lt_timestamptz', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'date timestamptz', prosrc => 'date_lt_timestamptz' },
+{ oid => '2352',
+ proname => 'date_le_timestamptz', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'date timestamptz', prosrc => 'date_le_timestamptz' },
+{ oid => '2353',
+ proname => 'date_eq_timestamptz', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'date timestamptz', prosrc => 'date_eq_timestamptz' },
+{ oid => '2354',
+ proname => 'date_gt_timestamptz', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'date timestamptz', prosrc => 'date_gt_timestamptz' },
+{ oid => '2355',
+ proname => 'date_ge_timestamptz', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'date timestamptz', prosrc => 'date_ge_timestamptz' },
+{ oid => '2356',
+ proname => 'date_ne_timestamptz', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'date timestamptz', prosrc => 'date_ne_timestamptz' },
+{ oid => '2357', descr => 'less-equal-greater',
+ proname => 'date_cmp_timestamptz', provolatile => 's', prorettype => 'int4',
+ proargtypes => 'date timestamptz', prosrc => 'date_cmp_timestamptz' },
+
+{ oid => '2364',
+ proname => 'timestamp_lt_date', prorettype => 'bool',
+ proargtypes => 'timestamp date', prosrc => 'timestamp_lt_date' },
+{ oid => '2365',
+ proname => 'timestamp_le_date', prorettype => 'bool',
+ proargtypes => 'timestamp date', prosrc => 'timestamp_le_date' },
+{ oid => '2366',
+ proname => 'timestamp_eq_date', prorettype => 'bool',
+ proargtypes => 'timestamp date', prosrc => 'timestamp_eq_date' },
+{ oid => '2367',
+ proname => 'timestamp_gt_date', prorettype => 'bool',
+ proargtypes => 'timestamp date', prosrc => 'timestamp_gt_date' },
+{ oid => '2368',
+ proname => 'timestamp_ge_date', prorettype => 'bool',
+ proargtypes => 'timestamp date', prosrc => 'timestamp_ge_date' },
+{ oid => '2369',
+ proname => 'timestamp_ne_date', prorettype => 'bool',
+ proargtypes => 'timestamp date', prosrc => 'timestamp_ne_date' },
+{ oid => '2370', descr => 'less-equal-greater',
+ proname => 'timestamp_cmp_date', prorettype => 'int4',
+ proargtypes => 'timestamp date', prosrc => 'timestamp_cmp_date' },
+
+{ oid => '2377',
+ proname => 'timestamptz_lt_date', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'timestamptz date', prosrc => 'timestamptz_lt_date' },
+{ oid => '2378',
+ proname => 'timestamptz_le_date', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'timestamptz date', prosrc => 'timestamptz_le_date' },
+{ oid => '2379',
+ proname => 'timestamptz_eq_date', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'timestamptz date', prosrc => 'timestamptz_eq_date' },
+{ oid => '2380',
+ proname => 'timestamptz_gt_date', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'timestamptz date', prosrc => 'timestamptz_gt_date' },
+{ oid => '2381',
+ proname => 'timestamptz_ge_date', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'timestamptz date', prosrc => 'timestamptz_ge_date' },
+{ oid => '2382',
+ proname => 'timestamptz_ne_date', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'timestamptz date', prosrc => 'timestamptz_ne_date' },
+{ oid => '2383', descr => 'less-equal-greater',
+ proname => 'timestamptz_cmp_date', provolatile => 's', prorettype => 'int4',
+ proargtypes => 'timestamptz date', prosrc => 'timestamptz_cmp_date' },
+
+# crosstype operations for timestamp vs. timestamptz
+{ oid => '2520',
+ proname => 'timestamp_lt_timestamptz', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'timestamp timestamptz',
+ prosrc => 'timestamp_lt_timestamptz' },
+{ oid => '2521',
+ proname => 'timestamp_le_timestamptz', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'timestamp timestamptz',
+ prosrc => 'timestamp_le_timestamptz' },
+{ oid => '2522',
+ proname => 'timestamp_eq_timestamptz', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'timestamp timestamptz',
+ prosrc => 'timestamp_eq_timestamptz' },
+{ oid => '2523',
+ proname => 'timestamp_gt_timestamptz', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'timestamp timestamptz',
+ prosrc => 'timestamp_gt_timestamptz' },
+{ oid => '2524',
+ proname => 'timestamp_ge_timestamptz', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'timestamp timestamptz',
+ prosrc => 'timestamp_ge_timestamptz' },
+{ oid => '2525',
+ proname => 'timestamp_ne_timestamptz', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'timestamp timestamptz',
+ prosrc => 'timestamp_ne_timestamptz' },
+{ oid => '2526', descr => 'less-equal-greater',
+ proname => 'timestamp_cmp_timestamptz', provolatile => 's',
+ prorettype => 'int4', proargtypes => 'timestamp timestamptz',
+ prosrc => 'timestamp_cmp_timestamptz' },
+
+{ oid => '2527',
+ proname => 'timestamptz_lt_timestamp', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'timestamptz timestamp',
+ prosrc => 'timestamptz_lt_timestamp' },
+{ oid => '2528',
+ proname => 'timestamptz_le_timestamp', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'timestamptz timestamp',
+ prosrc => 'timestamptz_le_timestamp' },
+{ oid => '2529',
+ proname => 'timestamptz_eq_timestamp', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'timestamptz timestamp',
+ prosrc => 'timestamptz_eq_timestamp' },
+{ oid => '2530',
+ proname => 'timestamptz_gt_timestamp', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'timestamptz timestamp',
+ prosrc => 'timestamptz_gt_timestamp' },
+{ oid => '2531',
+ proname => 'timestamptz_ge_timestamp', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'timestamptz timestamp',
+ prosrc => 'timestamptz_ge_timestamp' },
+{ oid => '2532',
+ proname => 'timestamptz_ne_timestamp', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'timestamptz timestamp',
+ prosrc => 'timestamptz_ne_timestamp' },
+{ oid => '2533', descr => 'less-equal-greater',
+ proname => 'timestamptz_cmp_timestamp', provolatile => 's',
+ prorettype => 'int4', proargtypes => 'timestamptz timestamp',
+ prosrc => 'timestamptz_cmp_timestamp' },
+
+# send/receive functions
+{ oid => '2400', descr => 'I/O',
+ proname => 'array_recv', provolatile => 's', prorettype => 'anyarray',
+ proargtypes => 'internal oid int4', prosrc => 'array_recv' },
+{ oid => '2401', descr => 'I/O',
+ proname => 'array_send', provolatile => 's', prorettype => 'bytea',
+ proargtypes => 'anyarray', prosrc => 'array_send' },
+{ oid => '2402', descr => 'I/O',
+ proname => 'record_recv', provolatile => 's', prorettype => 'record',
+ proargtypes => 'internal oid int4', prosrc => 'record_recv' },
+{ oid => '2403', descr => 'I/O',
+ proname => 'record_send', provolatile => 's', prorettype => 'bytea',
+ proargtypes => 'record', prosrc => 'record_send' },
+{ oid => '2404', descr => 'I/O',
+ proname => 'int2recv', prorettype => 'int2', proargtypes => 'internal',
+ prosrc => 'int2recv' },
+{ oid => '2405', descr => 'I/O',
+ proname => 'int2send', prorettype => 'bytea', proargtypes => 'int2',
+ prosrc => 'int2send' },
+{ oid => '2406', descr => 'I/O',
+ proname => 'int4recv', prorettype => 'int4', proargtypes => 'internal',
+ prosrc => 'int4recv' },
+{ oid => '2407', descr => 'I/O',
+ proname => 'int4send', prorettype => 'bytea', proargtypes => 'int4',
+ prosrc => 'int4send' },
+{ oid => '2408', descr => 'I/O',
+ proname => 'int8recv', prorettype => 'int8', proargtypes => 'internal',
+ prosrc => 'int8recv' },
+{ oid => '2409', descr => 'I/O',
+ proname => 'int8send', prorettype => 'bytea', proargtypes => 'int8',
+ prosrc => 'int8send' },
+{ oid => '2410', descr => 'I/O',
+ proname => 'int2vectorrecv', prorettype => 'int2vector',
+ proargtypes => 'internal', prosrc => 'int2vectorrecv' },
+{ oid => '2411', descr => 'I/O',
+ proname => 'int2vectorsend', prorettype => 'bytea',
+ proargtypes => 'int2vector', prosrc => 'int2vectorsend' },
+{ oid => '2412', descr => 'I/O',
+ proname => 'bytearecv', prorettype => 'bytea', proargtypes => 'internal',
+ prosrc => 'bytearecv' },
+{ oid => '2413', descr => 'I/O',
+ proname => 'byteasend', prorettype => 'bytea', proargtypes => 'bytea',
+ prosrc => 'byteasend' },
+{ oid => '2414', descr => 'I/O',
+ proname => 'textrecv', provolatile => 's', prorettype => 'text',
+ proargtypes => 'internal', prosrc => 'textrecv' },
+{ oid => '2415', descr => 'I/O',
+ proname => 'textsend', provolatile => 's', prorettype => 'bytea',
+ proargtypes => 'text', prosrc => 'textsend' },
+{ oid => '2416', descr => 'I/O',
+ proname => 'unknownrecv', prorettype => 'unknown', proargtypes => 'internal',
+ prosrc => 'unknownrecv' },
+{ oid => '2417', descr => 'I/O',
+ proname => 'unknownsend', prorettype => 'bytea', proargtypes => 'unknown',
+ prosrc => 'unknownsend' },
+{ oid => '2418', descr => 'I/O',
+ proname => 'oidrecv', prorettype => 'oid', proargtypes => 'internal',
+ prosrc => 'oidrecv' },
+{ oid => '2419', descr => 'I/O',
+ proname => 'oidsend', prorettype => 'bytea', proargtypes => 'oid',
+ prosrc => 'oidsend' },
+{ oid => '2420', descr => 'I/O',
+ proname => 'oidvectorrecv', prorettype => 'oidvector',
+ proargtypes => 'internal', prosrc => 'oidvectorrecv' },
+{ oid => '2421', descr => 'I/O',
+ proname => 'oidvectorsend', prorettype => 'bytea', proargtypes => 'oidvector',
+ prosrc => 'oidvectorsend' },
+{ oid => '2422', descr => 'I/O',
+ proname => 'namerecv', provolatile => 's', prorettype => 'name',
+ proargtypes => 'internal', prosrc => 'namerecv' },
+{ oid => '2423', descr => 'I/O',
+ proname => 'namesend', provolatile => 's', prorettype => 'bytea',
+ proargtypes => 'name', prosrc => 'namesend' },
+{ oid => '2424', descr => 'I/O',
+ proname => 'float4recv', prorettype => 'float4', proargtypes => 'internal',
+ prosrc => 'float4recv' },
+{ oid => '2425', descr => 'I/O',
+ proname => 'float4send', prorettype => 'bytea', proargtypes => 'float4',
+ prosrc => 'float4send' },
+{ oid => '2426', descr => 'I/O',
+ proname => 'float8recv', prorettype => 'float8', proargtypes => 'internal',
+ prosrc => 'float8recv' },
+{ oid => '2427', descr => 'I/O',
+ proname => 'float8send', prorettype => 'bytea', proargtypes => 'float8',
+ prosrc => 'float8send' },
+{ oid => '2428', descr => 'I/O',
+ proname => 'point_recv', prorettype => 'point', proargtypes => 'internal',
+ prosrc => 'point_recv' },
+{ oid => '2429', descr => 'I/O',
+ proname => 'point_send', prorettype => 'bytea', proargtypes => 'point',
+ prosrc => 'point_send' },
+{ oid => '2430', descr => 'I/O',
+ proname => 'bpcharrecv', provolatile => 's', prorettype => 'bpchar',
+ proargtypes => 'internal oid int4', prosrc => 'bpcharrecv' },
+{ oid => '2431', descr => 'I/O',
+ proname => 'bpcharsend', provolatile => 's', prorettype => 'bytea',
+ proargtypes => 'bpchar', prosrc => 'bpcharsend' },
+{ oid => '2432', descr => 'I/O',
+ proname => 'varcharrecv', provolatile => 's', prorettype => 'varchar',
+ proargtypes => 'internal oid int4', prosrc => 'varcharrecv' },
+{ oid => '2433', descr => 'I/O',
+ proname => 'varcharsend', provolatile => 's', prorettype => 'bytea',
+ proargtypes => 'varchar', prosrc => 'varcharsend' },
+{ oid => '2434', descr => 'I/O',
+ proname => 'charrecv', prorettype => 'char', proargtypes => 'internal',
+ prosrc => 'charrecv' },
+{ oid => '2435', descr => 'I/O',
+ proname => 'charsend', prorettype => 'bytea', proargtypes => 'char',
+ prosrc => 'charsend' },
+{ oid => '2436', descr => 'I/O',
+ proname => 'boolrecv', prorettype => 'bool', proargtypes => 'internal',
+ prosrc => 'boolrecv' },
+{ oid => '2437', descr => 'I/O',
+ proname => 'boolsend', prorettype => 'bytea', proargtypes => 'bool',
+ prosrc => 'boolsend' },
+{ oid => '2438', descr => 'I/O',
+ proname => 'tidrecv', prorettype => 'tid', proargtypes => 'internal',
+ prosrc => 'tidrecv' },
+{ oid => '2439', descr => 'I/O',
+ proname => 'tidsend', prorettype => 'bytea', proargtypes => 'tid',
+ prosrc => 'tidsend' },
+{ oid => '2440', descr => 'I/O',
+ proname => 'xidrecv', prorettype => 'xid', proargtypes => 'internal',
+ prosrc => 'xidrecv' },
+{ oid => '2441', descr => 'I/O',
+ proname => 'xidsend', prorettype => 'bytea', proargtypes => 'xid',
+ prosrc => 'xidsend' },
+{ oid => '2442', descr => 'I/O',
+ proname => 'cidrecv', prorettype => 'cid', proargtypes => 'internal',
+ prosrc => 'cidrecv' },
+{ oid => '2443', descr => 'I/O',
+ proname => 'cidsend', prorettype => 'bytea', proargtypes => 'cid',
+ prosrc => 'cidsend' },
+{ oid => '2444', descr => 'I/O',
+ proname => 'regprocrecv', prorettype => 'regproc', proargtypes => 'internal',
+ prosrc => 'regprocrecv' },
+{ oid => '2445', descr => 'I/O',
+ proname => 'regprocsend', prorettype => 'bytea', proargtypes => 'regproc',
+ prosrc => 'regprocsend' },
+{ oid => '2446', descr => 'I/O',
+ proname => 'regprocedurerecv', prorettype => 'regprocedure',
+ proargtypes => 'internal', prosrc => 'regprocedurerecv' },
+{ oid => '2447', descr => 'I/O',
+ proname => 'regproceduresend', prorettype => 'bytea',
+ proargtypes => 'regprocedure', prosrc => 'regproceduresend' },
+{ oid => '2448', descr => 'I/O',
+ proname => 'regoperrecv', prorettype => 'regoper', proargtypes => 'internal',
+ prosrc => 'regoperrecv' },
+{ oid => '2449', descr => 'I/O',
+ proname => 'regopersend', prorettype => 'bytea', proargtypes => 'regoper',
+ prosrc => 'regopersend' },
+{ oid => '2450', descr => 'I/O',
+ proname => 'regoperatorrecv', prorettype => 'regoperator',
+ proargtypes => 'internal', prosrc => 'regoperatorrecv' },
+{ oid => '2451', descr => 'I/O',
+ proname => 'regoperatorsend', prorettype => 'bytea',
+ proargtypes => 'regoperator', prosrc => 'regoperatorsend' },
+{ oid => '2452', descr => 'I/O',
+ proname => 'regclassrecv', prorettype => 'regclass',
+ proargtypes => 'internal', prosrc => 'regclassrecv' },
+{ oid => '2453', descr => 'I/O',
+ proname => 'regclasssend', prorettype => 'bytea', proargtypes => 'regclass',
+ prosrc => 'regclasssend' },
+{ oid => '4196', descr => 'I/O',
+ proname => 'regcollationrecv', prorettype => 'regcollation',
+ proargtypes => 'internal', prosrc => 'regcollationrecv' },
+{ oid => '4197', descr => 'I/O',
+ proname => 'regcollationsend', prorettype => 'bytea',
+ proargtypes => 'regcollation', prosrc => 'regcollationsend' },
+{ oid => '2454', descr => 'I/O',
+ proname => 'regtyperecv', prorettype => 'regtype', proargtypes => 'internal',
+ prosrc => 'regtyperecv' },
+{ oid => '2455', descr => 'I/O',
+ proname => 'regtypesend', prorettype => 'bytea', proargtypes => 'regtype',
+ prosrc => 'regtypesend' },
+
+{ oid => '4094', descr => 'I/O',
+ proname => 'regrolerecv', prorettype => 'regrole', proargtypes => 'internal',
+ prosrc => 'regrolerecv' },
+{ oid => '4095', descr => 'I/O',
+ proname => 'regrolesend', prorettype => 'bytea', proargtypes => 'regrole',
+ prosrc => 'regrolesend' },
+{ oid => '4087', descr => 'I/O',
+ proname => 'regnamespacerecv', prorettype => 'regnamespace',
+ proargtypes => 'internal', prosrc => 'regnamespacerecv' },
+{ oid => '4088', descr => 'I/O',
+ proname => 'regnamespacesend', prorettype => 'bytea',
+ proargtypes => 'regnamespace', prosrc => 'regnamespacesend' },
+{ oid => '2456', descr => 'I/O',
+ proname => 'bit_recv', prorettype => 'bit',
+ proargtypes => 'internal oid int4', prosrc => 'bit_recv' },
+{ oid => '2457', descr => 'I/O',
+ proname => 'bit_send', prorettype => 'bytea', proargtypes => 'bit',
+ prosrc => 'bit_send' },
+{ oid => '2458', descr => 'I/O',
+ proname => 'varbit_recv', prorettype => 'varbit',
+ proargtypes => 'internal oid int4', prosrc => 'varbit_recv' },
+{ oid => '2459', descr => 'I/O',
+ proname => 'varbit_send', prorettype => 'bytea', proargtypes => 'varbit',
+ prosrc => 'varbit_send' },
+{ oid => '2460', descr => 'I/O',
+ proname => 'numeric_recv', prorettype => 'numeric',
+ proargtypes => 'internal oid int4', prosrc => 'numeric_recv' },
+{ oid => '2461', descr => 'I/O',
+ proname => 'numeric_send', prorettype => 'bytea', proargtypes => 'numeric',
+ prosrc => 'numeric_send' },
+{ oid => '2468', descr => 'I/O',
+ proname => 'date_recv', prorettype => 'date', proargtypes => 'internal',
+ prosrc => 'date_recv' },
+{ oid => '2469', descr => 'I/O',
+ proname => 'date_send', prorettype => 'bytea', proargtypes => 'date',
+ prosrc => 'date_send' },
+{ oid => '2470', descr => 'I/O',
+ proname => 'time_recv', prorettype => 'time',
+ proargtypes => 'internal oid int4', prosrc => 'time_recv' },
+{ oid => '2471', descr => 'I/O',
+ proname => 'time_send', prorettype => 'bytea', proargtypes => 'time',
+ prosrc => 'time_send' },
+{ oid => '2472', descr => 'I/O',
+ proname => 'timetz_recv', prorettype => 'timetz',
+ proargtypes => 'internal oid int4', prosrc => 'timetz_recv' },
+{ oid => '2473', descr => 'I/O',
+ proname => 'timetz_send', prorettype => 'bytea', proargtypes => 'timetz',
+ prosrc => 'timetz_send' },
+{ oid => '2474', descr => 'I/O',
+ proname => 'timestamp_recv', prorettype => 'timestamp',
+ proargtypes => 'internal oid int4', prosrc => 'timestamp_recv' },
+{ oid => '2475', descr => 'I/O',
+ proname => 'timestamp_send', prorettype => 'bytea',
+ proargtypes => 'timestamp', prosrc => 'timestamp_send' },
+{ oid => '2476', descr => 'I/O',
+ proname => 'timestamptz_recv', prorettype => 'timestamptz',
+ proargtypes => 'internal oid int4', prosrc => 'timestamptz_recv' },
+{ oid => '2477', descr => 'I/O',
+ proname => 'timestamptz_send', prorettype => 'bytea',
+ proargtypes => 'timestamptz', prosrc => 'timestamptz_send' },
+{ oid => '2478', descr => 'I/O',
+ proname => 'interval_recv', prorettype => 'interval',
+ proargtypes => 'internal oid int4', prosrc => 'interval_recv' },
+{ oid => '2479', descr => 'I/O',
+ proname => 'interval_send', prorettype => 'bytea', proargtypes => 'interval',
+ prosrc => 'interval_send' },
+{ oid => '2480', descr => 'I/O',
+ proname => 'lseg_recv', prorettype => 'lseg', proargtypes => 'internal',
+ prosrc => 'lseg_recv' },
+{ oid => '2481', descr => 'I/O',
+ proname => 'lseg_send', prorettype => 'bytea', proargtypes => 'lseg',
+ prosrc => 'lseg_send' },
+{ oid => '2482', descr => 'I/O',
+ proname => 'path_recv', prorettype => 'path', proargtypes => 'internal',
+ prosrc => 'path_recv' },
+{ oid => '2483', descr => 'I/O',
+ proname => 'path_send', prorettype => 'bytea', proargtypes => 'path',
+ prosrc => 'path_send' },
+{ oid => '2484', descr => 'I/O',
+ proname => 'box_recv', prorettype => 'box', proargtypes => 'internal',
+ prosrc => 'box_recv' },
+{ oid => '2485', descr => 'I/O',
+ proname => 'box_send', prorettype => 'bytea', proargtypes => 'box',
+ prosrc => 'box_send' },
+{ oid => '2486', descr => 'I/O',
+ proname => 'poly_recv', prorettype => 'polygon', proargtypes => 'internal',
+ prosrc => 'poly_recv' },
+{ oid => '2487', descr => 'I/O',
+ proname => 'poly_send', prorettype => 'bytea', proargtypes => 'polygon',
+ prosrc => 'poly_send' },
+{ oid => '2488', descr => 'I/O',
+ proname => 'line_recv', prorettype => 'line', proargtypes => 'internal',
+ prosrc => 'line_recv' },
+{ oid => '2489', descr => 'I/O',
+ proname => 'line_send', prorettype => 'bytea', proargtypes => 'line',
+ prosrc => 'line_send' },
+{ oid => '2490', descr => 'I/O',
+ proname => 'circle_recv', prorettype => 'circle', proargtypes => 'internal',
+ prosrc => 'circle_recv' },
+{ oid => '2491', descr => 'I/O',
+ proname => 'circle_send', prorettype => 'bytea', proargtypes => 'circle',
+ prosrc => 'circle_send' },
+{ oid => '2492', descr => 'I/O',
+ proname => 'cash_recv', prorettype => 'money', proargtypes => 'internal',
+ prosrc => 'cash_recv' },
+{ oid => '2493', descr => 'I/O',
+ proname => 'cash_send', prorettype => 'bytea', proargtypes => 'money',
+ prosrc => 'cash_send' },
+{ oid => '2494', descr => 'I/O',
+ proname => 'macaddr_recv', prorettype => 'macaddr', proargtypes => 'internal',
+ prosrc => 'macaddr_recv' },
+{ oid => '2495', descr => 'I/O',
+ proname => 'macaddr_send', prorettype => 'bytea', proargtypes => 'macaddr',
+ prosrc => 'macaddr_send' },
+{ oid => '2496', descr => 'I/O',
+ proname => 'inet_recv', prorettype => 'inet', proargtypes => 'internal',
+ prosrc => 'inet_recv' },
+{ oid => '2497', descr => 'I/O',
+ proname => 'inet_send', prorettype => 'bytea', proargtypes => 'inet',
+ prosrc => 'inet_send' },
+{ oid => '2498', descr => 'I/O',
+ proname => 'cidr_recv', prorettype => 'cidr', proargtypes => 'internal',
+ prosrc => 'cidr_recv' },
+{ oid => '2499', descr => 'I/O',
+ proname => 'cidr_send', prorettype => 'bytea', proargtypes => 'cidr',
+ prosrc => 'cidr_send' },
+{ oid => '2500', descr => 'I/O',
+ proname => 'cstring_recv', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'internal', prosrc => 'cstring_recv' },
+{ oid => '2501', descr => 'I/O',
+ proname => 'cstring_send', provolatile => 's', prorettype => 'bytea',
+ proargtypes => 'cstring', prosrc => 'cstring_send' },
+{ oid => '2502', descr => 'I/O',
+ proname => 'anyarray_recv', provolatile => 's', prorettype => 'anyarray',
+ proargtypes => 'internal', prosrc => 'anyarray_recv' },
+{ oid => '2503', descr => 'I/O',
+ proname => 'anyarray_send', provolatile => 's', prorettype => 'bytea',
+ proargtypes => 'anyarray', prosrc => 'anyarray_send' },
+{ oid => '3120', descr => 'I/O',
+ proname => 'void_recv', prorettype => 'void', proargtypes => 'internal',
+ prosrc => 'void_recv' },
+{ oid => '3121', descr => 'I/O',
+ proname => 'void_send', prorettype => 'bytea', proargtypes => 'void',
+ prosrc => 'void_send' },
+{ oid => '3446', descr => 'I/O',
+ proname => 'macaddr8_recv', prorettype => 'macaddr8',
+ proargtypes => 'internal', prosrc => 'macaddr8_recv' },
+{ oid => '3447', descr => 'I/O',
+ proname => 'macaddr8_send', prorettype => 'bytea', proargtypes => 'macaddr8',
+ prosrc => 'macaddr8_send' },
+
+# System-view support functions with pretty-print option
+{ oid => '2504', descr => 'source text of a rule with pretty-print option',
+ proname => 'pg_get_ruledef', provolatile => 's', prorettype => 'text',
+ proargtypes => 'oid bool', prosrc => 'pg_get_ruledef_ext' },
+{ oid => '2505',
+ descr => 'select statement of a view with pretty-print option',
+ proname => 'pg_get_viewdef', provolatile => 's', proparallel => 'r',
+ prorettype => 'text', proargtypes => 'text bool',
+ prosrc => 'pg_get_viewdef_name_ext' },
+{ oid => '2506',
+ descr => 'select statement of a view with pretty-print option',
+ proname => 'pg_get_viewdef', provolatile => 's', proparallel => 'r',
+ prorettype => 'text', proargtypes => 'oid bool',
+ prosrc => 'pg_get_viewdef_ext' },
+{ oid => '3159',
+ descr => 'select statement of a view with pretty-printing and specified line wrapping',
+ proname => 'pg_get_viewdef', provolatile => 's', proparallel => 'r',
+ prorettype => 'text', proargtypes => 'oid int4',
+ prosrc => 'pg_get_viewdef_wrap' },
+{ oid => '2507',
+ descr => 'index description (full create statement or single expression) with pretty-print option',
+ proname => 'pg_get_indexdef', provolatile => 's', prorettype => 'text',
+ proargtypes => 'oid int4 bool', prosrc => 'pg_get_indexdef_ext' },
+{ oid => '2508', descr => 'constraint description with pretty-print option',
+ proname => 'pg_get_constraintdef', provolatile => 's', prorettype => 'text',
+ proargtypes => 'oid bool', prosrc => 'pg_get_constraintdef_ext' },
+{ oid => '2509',
+ descr => 'deparse an encoded expression with pretty-print option',
+ proname => 'pg_get_expr', provolatile => 's', prorettype => 'text',
+ proargtypes => 'pg_node_tree oid bool', prosrc => 'pg_get_expr_ext' },
+{ oid => '2510', descr => 'get the prepared statements for this session',
+ proname => 'pg_prepared_statement', prorows => '1000', proretset => 't',
+ provolatile => 's', proparallel => 'r', prorettype => 'record',
+ proargtypes => '', proallargtypes => '{text,text,timestamptz,_regtype,bool}',
+ proargmodes => '{o,o,o,o,o}',
+ proargnames => '{name,statement,prepare_time,parameter_types,from_sql}',
+ prosrc => 'pg_prepared_statement' },
+{ oid => '2511', descr => 'get the open cursors for this session',
+ proname => 'pg_cursor', prorows => '1000', proretset => 't',
+ provolatile => 's', proparallel => 'r', prorettype => 'record',
+ proargtypes => '', proallargtypes => '{text,text,bool,bool,bool,timestamptz}',
+ proargmodes => '{o,o,o,o,o,o}',
+ proargnames => '{name,statement,is_holdable,is_binary,is_scrollable,creation_time}',
+ prosrc => 'pg_cursor' },
+{ oid => '2599', descr => 'get the available time zone abbreviations',
+ proname => 'pg_timezone_abbrevs', prorows => '1000', proretset => 't',
+ provolatile => 's', prorettype => 'record', proargtypes => '',
+ proallargtypes => '{text,interval,bool}', proargmodes => '{o,o,o}',
+ proargnames => '{abbrev,utc_offset,is_dst}',
+ prosrc => 'pg_timezone_abbrevs' },
+{ oid => '2856', descr => 'get the available time zone names',
+ proname => 'pg_timezone_names', prorows => '1000', proretset => 't',
+ provolatile => 's', prorettype => 'record', proargtypes => '',
+ proallargtypes => '{text,text,interval,bool}', proargmodes => '{o,o,o,o}',
+ proargnames => '{name,abbrev,utc_offset,is_dst}',
+ prosrc => 'pg_timezone_names' },
+{ oid => '2730', descr => 'trigger description with pretty-print option',
+ proname => 'pg_get_triggerdef', provolatile => 's', prorettype => 'text',
+ proargtypes => 'oid bool', prosrc => 'pg_get_triggerdef_ext' },
+
+# asynchronous notifications
+{ oid => '3035',
+ descr => 'get the channels that the current backend listens to',
+ proname => 'pg_listening_channels', prorows => '10', proretset => 't',
+ provolatile => 's', proparallel => 'r', prorettype => 'text',
+ proargtypes => '', prosrc => 'pg_listening_channels' },
+{ oid => '3036', descr => 'send a notification event',
+ proname => 'pg_notify', proisstrict => 'f', provolatile => 'v',
+ proparallel => 'r', prorettype => 'void', proargtypes => 'text text',
+ prosrc => 'pg_notify' },
+{ oid => '3296',
+ descr => 'get the fraction of the asynchronous notification queue currently in use',
+ proname => 'pg_notification_queue_usage', provolatile => 'v',
+ proparallel => 'r', prorettype => 'float8', proargtypes => '',
+ prosrc => 'pg_notification_queue_usage' },
+
+# shared memory usage
+{ oid => '5052', descr => 'allocations from the main shared memory segment',
+ proname => 'pg_get_shmem_allocations', prorows => '50', proretset => 't',
+ provolatile => 'v', prorettype => 'record', proargtypes => '',
+ proallargtypes => '{text,int8,int8,int8}', proargmodes => '{o,o,o,o}',
+ proargnames => '{name,off,size,allocated_size}',
+ prosrc => 'pg_get_shmem_allocations' },
+
+# non-persistent series generator
+{ oid => '1066', descr => 'non-persistent series generator',
+ proname => 'generate_series', prorows => '1000',
+ prosupport => 'generate_series_int4_support', proretset => 't',
+ prorettype => 'int4', proargtypes => 'int4 int4 int4',
+ prosrc => 'generate_series_step_int4' },
+{ oid => '1067', descr => 'non-persistent series generator',
+ proname => 'generate_series', prorows => '1000',
+ prosupport => 'generate_series_int4_support', proretset => 't',
+ prorettype => 'int4', proargtypes => 'int4 int4',
+ prosrc => 'generate_series_int4' },
+{ oid => '3994', descr => 'planner support for generate_series',
+ proname => 'generate_series_int4_support', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'generate_series_int4_support' },
+{ oid => '1068', descr => 'non-persistent series generator',
+ proname => 'generate_series', prorows => '1000',
+ prosupport => 'generate_series_int8_support', proretset => 't',
+ prorettype => 'int8', proargtypes => 'int8 int8 int8',
+ prosrc => 'generate_series_step_int8' },
+{ oid => '1069', descr => 'non-persistent series generator',
+ proname => 'generate_series', prorows => '1000',
+ prosupport => 'generate_series_int8_support', proretset => 't',
+ prorettype => 'int8', proargtypes => 'int8 int8',
+ prosrc => 'generate_series_int8' },
+{ oid => '3995', descr => 'planner support for generate_series',
+ proname => 'generate_series_int8_support', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'generate_series_int8_support' },
+{ oid => '3259', descr => 'non-persistent series generator',
+ proname => 'generate_series', prorows => '1000', proretset => 't',
+ prorettype => 'numeric', proargtypes => 'numeric numeric numeric',
+ prosrc => 'generate_series_step_numeric' },
+{ oid => '3260', descr => 'non-persistent series generator',
+ proname => 'generate_series', prorows => '1000', proretset => 't',
+ prorettype => 'numeric', proargtypes => 'numeric numeric',
+ prosrc => 'generate_series_numeric' },
+{ oid => '938', descr => 'non-persistent series generator',
+ proname => 'generate_series', prorows => '1000', proretset => 't',
+ prorettype => 'timestamp', proargtypes => 'timestamp timestamp interval',
+ prosrc => 'generate_series_timestamp' },
+{ oid => '939', descr => 'non-persistent series generator',
+ proname => 'generate_series', prorows => '1000', proretset => 't',
+ provolatile => 's', prorettype => 'timestamptz',
+ proargtypes => 'timestamptz timestamptz interval',
+ prosrc => 'generate_series_timestamptz' },
+
+# boolean aggregates
+{ oid => '2515', descr => 'aggregate transition function',
+ proname => 'booland_statefunc', prorettype => 'bool',
+ proargtypes => 'bool bool', prosrc => 'booland_statefunc' },
+{ oid => '2516', descr => 'aggregate transition function',
+ proname => 'boolor_statefunc', prorettype => 'bool',
+ proargtypes => 'bool bool', prosrc => 'boolor_statefunc' },
+{ oid => '3496', descr => 'aggregate transition function',
+ proname => 'bool_accum', proisstrict => 'f', prorettype => 'internal',
+ proargtypes => 'internal bool', prosrc => 'bool_accum' },
+{ oid => '3497', descr => 'aggregate transition function',
+ proname => 'bool_accum_inv', proisstrict => 'f', prorettype => 'internal',
+ proargtypes => 'internal bool', prosrc => 'bool_accum_inv' },
+{ oid => '3498', descr => 'aggregate final function',
+ proname => 'bool_alltrue', prorettype => 'bool', proargtypes => 'internal',
+ prosrc => 'bool_alltrue' },
+{ oid => '3499', descr => 'aggregate final function',
+ proname => 'bool_anytrue', prorettype => 'bool', proargtypes => 'internal',
+ prosrc => 'bool_anytrue' },
+{ oid => '2517', descr => 'boolean-and aggregate',
+ proname => 'bool_and', prokind => 'a', proisstrict => 'f',
+ prorettype => 'bool', proargtypes => 'bool', prosrc => 'aggregate_dummy' },
+
+# ANY, SOME? These names conflict with subquery operators. See doc.
+{ oid => '2518', descr => 'boolean-or aggregate',
+ proname => 'bool_or', prokind => 'a', proisstrict => 'f',
+ prorettype => 'bool', proargtypes => 'bool', prosrc => 'aggregate_dummy' },
+{ oid => '2519', descr => 'boolean-and aggregate',
+ proname => 'every', prokind => 'a', proisstrict => 'f', prorettype => 'bool',
+ proargtypes => 'bool', prosrc => 'aggregate_dummy' },
+
+# bitwise integer aggregates
+{ oid => '2236', descr => 'bitwise-and smallint aggregate',
+ proname => 'bit_and', prokind => 'a', proisstrict => 'f',
+ prorettype => 'int2', proargtypes => 'int2', prosrc => 'aggregate_dummy' },
+{ oid => '2237', descr => 'bitwise-or smallint aggregate',
+ proname => 'bit_or', prokind => 'a', proisstrict => 'f', prorettype => 'int2',
+ proargtypes => 'int2', prosrc => 'aggregate_dummy' },
+{ oid => '2238', descr => 'bitwise-and integer aggregate',
+ proname => 'bit_and', prokind => 'a', proisstrict => 'f',
+ prorettype => 'int4', proargtypes => 'int4', prosrc => 'aggregate_dummy' },
+{ oid => '2239', descr => 'bitwise-or integer aggregate',
+ proname => 'bit_or', prokind => 'a', proisstrict => 'f', prorettype => 'int4',
+ proargtypes => 'int4', prosrc => 'aggregate_dummy' },
+{ oid => '2240', descr => 'bitwise-and bigint aggregate',
+ proname => 'bit_and', prokind => 'a', proisstrict => 'f',
+ prorettype => 'int8', proargtypes => 'int8', prosrc => 'aggregate_dummy' },
+{ oid => '2241', descr => 'bitwise-or bigint aggregate',
+ proname => 'bit_or', prokind => 'a', proisstrict => 'f', prorettype => 'int8',
+ proargtypes => 'int8', prosrc => 'aggregate_dummy' },
+{ oid => '2242', descr => 'bitwise-and bit aggregate',
+ proname => 'bit_and', prokind => 'a', proisstrict => 'f', prorettype => 'bit',
+ proargtypes => 'bit', prosrc => 'aggregate_dummy' },
+{ oid => '2243', descr => 'bitwise-or bit aggregate',
+ proname => 'bit_or', prokind => 'a', proisstrict => 'f', prorettype => 'bit',
+ proargtypes => 'bit', prosrc => 'aggregate_dummy' },
+
+# formerly-missing interval + datetime operators
+{ oid => '2546',
+ proname => 'interval_pl_date', prolang => 'sql', prorettype => 'timestamp',
+ proargtypes => 'interval date', prosrc => 'select $2 + $1' },
+{ oid => '2547',
+ proname => 'interval_pl_timetz', prolang => 'sql', prorettype => 'timetz',
+ proargtypes => 'interval timetz', prosrc => 'select $2 + $1' },
+{ oid => '2548',
+ proname => 'interval_pl_timestamp', prolang => 'sql',
+ prorettype => 'timestamp', proargtypes => 'interval timestamp',
+ prosrc => 'select $2 + $1' },
+{ oid => '2549',
+ proname => 'interval_pl_timestamptz', prolang => 'sql', provolatile => 's',
+ prorettype => 'timestamptz', proargtypes => 'interval timestamptz',
+ prosrc => 'select $2 + $1' },
+{ oid => '2550',
+ proname => 'integer_pl_date', prolang => 'sql', prorettype => 'date',
+ proargtypes => 'int4 date', prosrc => 'select $2 + $1' },
+
+{ oid => '2556', descr => 'get OIDs of databases in a tablespace',
+ proname => 'pg_tablespace_databases', prorows => '1000', proretset => 't',
+ provolatile => 's', prorettype => 'oid', proargtypes => 'oid',
+ prosrc => 'pg_tablespace_databases' },
+
+{ oid => '2557', descr => 'convert int4 to boolean',
+ proname => 'bool', prorettype => 'bool', proargtypes => 'int4',
+ prosrc => 'int4_bool' },
+{ oid => '2558', descr => 'convert boolean to int4',
+ proname => 'int4', prorettype => 'int4', proargtypes => 'bool',
+ prosrc => 'bool_int4' },
+{ oid => '2559', descr => 'current value from last used sequence',
+ proname => 'lastval', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int8', proargtypes => '', prosrc => 'lastval' },
+
+# start time function
+{ oid => '2560', descr => 'postmaster start time',
+ proname => 'pg_postmaster_start_time', provolatile => 's',
+ prorettype => 'timestamptz', proargtypes => '',
+ prosrc => 'pg_postmaster_start_time' },
+
+# config reload time function
+{ oid => '2034', descr => 'configuration load time',
+ proname => 'pg_conf_load_time', provolatile => 's', proparallel => 'r',
+ prorettype => 'timestamptz', proargtypes => '',
+ prosrc => 'pg_conf_load_time' },
+
+# new functions for Y-direction rtree opclasses
+{ oid => '2562',
+ proname => 'box_below', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_below' },
+{ oid => '2563',
+ proname => 'box_overbelow', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_overbelow' },
+{ oid => '2564',
+ proname => 'box_overabove', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_overabove' },
+{ oid => '2565',
+ proname => 'box_above', prorettype => 'bool', proargtypes => 'box box',
+ prosrc => 'box_above' },
+{ oid => '2566',
+ proname => 'poly_below', prorettype => 'bool',
+ proargtypes => 'polygon polygon', prosrc => 'poly_below' },
+{ oid => '2567',
+ proname => 'poly_overbelow', prorettype => 'bool',
+ proargtypes => 'polygon polygon', prosrc => 'poly_overbelow' },
+{ oid => '2568',
+ proname => 'poly_overabove', prorettype => 'bool',
+ proargtypes => 'polygon polygon', prosrc => 'poly_overabove' },
+{ oid => '2569',
+ proname => 'poly_above', prorettype => 'bool',
+ proargtypes => 'polygon polygon', prosrc => 'poly_above' },
+{ oid => '2587',
+ proname => 'circle_overbelow', prorettype => 'bool',
+ proargtypes => 'circle circle', prosrc => 'circle_overbelow' },
+{ oid => '2588',
+ proname => 'circle_overabove', prorettype => 'bool',
+ proargtypes => 'circle circle', prosrc => 'circle_overabove' },
+
+# support functions for GiST r-tree emulation
+{ oid => '2578', descr => 'GiST support',
+ proname => 'gist_box_consistent', prorettype => 'bool',
+ proargtypes => 'internal box int2 oid internal',
+ prosrc => 'gist_box_consistent' },
+{ oid => '2581', descr => 'GiST support',
+ proname => 'gist_box_penalty', prorettype => 'internal',
+ proargtypes => 'internal internal internal', prosrc => 'gist_box_penalty' },
+{ oid => '2582', descr => 'GiST support',
+ proname => 'gist_box_picksplit', prorettype => 'internal',
+ proargtypes => 'internal internal', prosrc => 'gist_box_picksplit' },
+{ oid => '2583', descr => 'GiST support',
+ proname => 'gist_box_union', prorettype => 'box',
+ proargtypes => 'internal internal', prosrc => 'gist_box_union' },
+{ oid => '2584', descr => 'GiST support',
+ proname => 'gist_box_same', prorettype => 'internal',
+ proargtypes => 'box box internal', prosrc => 'gist_box_same' },
+{ oid => '3998', descr => 'GiST support',
+ proname => 'gist_box_distance', prorettype => 'float8',
+ proargtypes => 'internal box int2 oid internal',
+ prosrc => 'gist_box_distance' },
+{ oid => '2585', descr => 'GiST support',
+ proname => 'gist_poly_consistent', prorettype => 'bool',
+ proargtypes => 'internal polygon int2 oid internal',
+ prosrc => 'gist_poly_consistent' },
+{ oid => '2586', descr => 'GiST support',
+ proname => 'gist_poly_compress', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'gist_poly_compress' },
+{ oid => '2591', descr => 'GiST support',
+ proname => 'gist_circle_consistent', prorettype => 'bool',
+ proargtypes => 'internal circle int2 oid internal',
+ prosrc => 'gist_circle_consistent' },
+{ oid => '2592', descr => 'GiST support',
+ proname => 'gist_circle_compress', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'gist_circle_compress' },
+{ oid => '1030', descr => 'GiST support',
+ proname => 'gist_point_compress', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'gist_point_compress' },
+{ oid => '3282', descr => 'GiST support',
+ proname => 'gist_point_fetch', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'gist_point_fetch' },
+{ oid => '2179', descr => 'GiST support',
+ proname => 'gist_point_consistent', prorettype => 'bool',
+ proargtypes => 'internal point int2 oid internal',
+ prosrc => 'gist_point_consistent' },
+{ oid => '3064', descr => 'GiST support',
+ proname => 'gist_point_distance', prorettype => 'float8',
+ proargtypes => 'internal point int2 oid internal',
+ prosrc => 'gist_point_distance' },
+{ oid => '3280', descr => 'GiST support',
+ proname => 'gist_circle_distance', prorettype => 'float8',
+ proargtypes => 'internal circle int2 oid internal',
+ prosrc => 'gist_circle_distance' },
+{ oid => '3288', descr => 'GiST support',
+ proname => 'gist_poly_distance', prorettype => 'float8',
+ proargtypes => 'internal polygon int2 oid internal',
+ prosrc => 'gist_poly_distance' },
+
+# GIN array support
+{ oid => '2743', descr => 'GIN array support',
+ proname => 'ginarrayextract', prorettype => 'internal',
+ proargtypes => 'anyarray internal internal', prosrc => 'ginarrayextract' },
+{ oid => '2774', descr => 'GIN array support',
+ proname => 'ginqueryarrayextract', prorettype => 'internal',
+ proargtypes => 'anyarray internal int2 internal internal internal internal',
+ prosrc => 'ginqueryarrayextract' },
+{ oid => '2744', descr => 'GIN array support',
+ proname => 'ginarrayconsistent', prorettype => 'bool',
+ proargtypes => 'internal int2 anyarray int4 internal internal internal internal',
+ prosrc => 'ginarrayconsistent' },
+{ oid => '3920', descr => 'GIN array support',
+ proname => 'ginarraytriconsistent', prorettype => 'char',
+ proargtypes => 'internal int2 anyarray int4 internal internal internal',
+ prosrc => 'ginarraytriconsistent' },
+{ oid => '3076', descr => 'GIN array support (obsolete)',
+ proname => 'ginarrayextract', prorettype => 'internal',
+ proargtypes => 'anyarray internal', prosrc => 'ginarrayextract_2args' },
+
+# overlap/contains/contained
+{ oid => '2747',
+ proname => 'arrayoverlap', prorettype => 'bool',
+ proargtypes => 'anyarray anyarray', prosrc => 'arrayoverlap' },
+{ oid => '2748',
+ proname => 'arraycontains', prorettype => 'bool',
+ proargtypes => 'anyarray anyarray', prosrc => 'arraycontains' },
+{ oid => '2749',
+ proname => 'arraycontained', prorettype => 'bool',
+ proargtypes => 'anyarray anyarray', prosrc => 'arraycontained' },
+
+# BRIN minmax
+{ oid => '3383', descr => 'BRIN minmax support',
+ proname => 'brin_minmax_opcinfo', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'brin_minmax_opcinfo' },
+{ oid => '3384', descr => 'BRIN minmax support',
+ proname => 'brin_minmax_add_value', prorettype => 'bool',
+ proargtypes => 'internal internal internal internal',
+ prosrc => 'brin_minmax_add_value' },
+{ oid => '3385', descr => 'BRIN minmax support',
+ proname => 'brin_minmax_consistent', prorettype => 'bool',
+ proargtypes => 'internal internal internal',
+ prosrc => 'brin_minmax_consistent' },
+{ oid => '3386', descr => 'BRIN minmax support',
+ proname => 'brin_minmax_union', prorettype => 'bool',
+ proargtypes => 'internal internal internal', prosrc => 'brin_minmax_union' },
+
+# BRIN inclusion
+{ oid => '4105', descr => 'BRIN inclusion support',
+ proname => 'brin_inclusion_opcinfo', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'brin_inclusion_opcinfo' },
+{ oid => '4106', descr => 'BRIN inclusion support',
+ proname => 'brin_inclusion_add_value', prorettype => 'bool',
+ proargtypes => 'internal internal internal internal',
+ prosrc => 'brin_inclusion_add_value' },
+{ oid => '4107', descr => 'BRIN inclusion support',
+ proname => 'brin_inclusion_consistent', prorettype => 'bool',
+ proargtypes => 'internal internal internal',
+ prosrc => 'brin_inclusion_consistent' },
+{ oid => '4108', descr => 'BRIN inclusion support',
+ proname => 'brin_inclusion_union', prorettype => 'bool',
+ proargtypes => 'internal internal internal',
+ prosrc => 'brin_inclusion_union' },
+
+# userlock replacements
+{ oid => '2880', descr => 'obtain exclusive advisory lock',
+ proname => 'pg_advisory_lock', provolatile => 'v', proparallel => 'r',
+ prorettype => 'void', proargtypes => 'int8',
+ prosrc => 'pg_advisory_lock_int8' },
+{ oid => '3089', descr => 'obtain exclusive advisory lock',
+ proname => 'pg_advisory_xact_lock', provolatile => 'v', proparallel => 'r',
+ prorettype => 'void', proargtypes => 'int8',
+ prosrc => 'pg_advisory_xact_lock_int8' },
+{ oid => '2881', descr => 'obtain shared advisory lock',
+ proname => 'pg_advisory_lock_shared', provolatile => 'v', proparallel => 'r',
+ prorettype => 'void', proargtypes => 'int8',
+ prosrc => 'pg_advisory_lock_shared_int8' },
+{ oid => '3090', descr => 'obtain shared advisory lock',
+ proname => 'pg_advisory_xact_lock_shared', provolatile => 'v',
+ proparallel => 'r', prorettype => 'void', proargtypes => 'int8',
+ prosrc => 'pg_advisory_xact_lock_shared_int8' },
+{ oid => '2882', descr => 'obtain exclusive advisory lock if available',
+ proname => 'pg_try_advisory_lock', provolatile => 'v', proparallel => 'r',
+ prorettype => 'bool', proargtypes => 'int8',
+ prosrc => 'pg_try_advisory_lock_int8' },
+{ oid => '3091', descr => 'obtain exclusive advisory lock if available',
+ proname => 'pg_try_advisory_xact_lock', provolatile => 'v',
+ proparallel => 'r', prorettype => 'bool', proargtypes => 'int8',
+ prosrc => 'pg_try_advisory_xact_lock_int8' },
+{ oid => '2883', descr => 'obtain shared advisory lock if available',
+ proname => 'pg_try_advisory_lock_shared', provolatile => 'v',
+ proparallel => 'r', prorettype => 'bool', proargtypes => 'int8',
+ prosrc => 'pg_try_advisory_lock_shared_int8' },
+{ oid => '3092', descr => 'obtain shared advisory lock if available',
+ proname => 'pg_try_advisory_xact_lock_shared', provolatile => 'v',
+ proparallel => 'r', prorettype => 'bool', proargtypes => 'int8',
+ prosrc => 'pg_try_advisory_xact_lock_shared_int8' },
+{ oid => '2884', descr => 'release exclusive advisory lock',
+ proname => 'pg_advisory_unlock', provolatile => 'v', proparallel => 'r',
+ prorettype => 'bool', proargtypes => 'int8',
+ prosrc => 'pg_advisory_unlock_int8' },
+{ oid => '2885', descr => 'release shared advisory lock',
+ proname => 'pg_advisory_unlock_shared', provolatile => 'v',
+ proparallel => 'r', prorettype => 'bool', proargtypes => 'int8',
+ prosrc => 'pg_advisory_unlock_shared_int8' },
+{ oid => '2886', descr => 'obtain exclusive advisory lock',
+ proname => 'pg_advisory_lock', provolatile => 'v', proparallel => 'r',
+ prorettype => 'void', proargtypes => 'int4 int4',
+ prosrc => 'pg_advisory_lock_int4' },
+{ oid => '3093', descr => 'obtain exclusive advisory lock',
+ proname => 'pg_advisory_xact_lock', provolatile => 'v', proparallel => 'r',
+ prorettype => 'void', proargtypes => 'int4 int4',
+ prosrc => 'pg_advisory_xact_lock_int4' },
+{ oid => '2887', descr => 'obtain shared advisory lock',
+ proname => 'pg_advisory_lock_shared', provolatile => 'v', proparallel => 'r',
+ prorettype => 'void', proargtypes => 'int4 int4',
+ prosrc => 'pg_advisory_lock_shared_int4' },
+{ oid => '3094', descr => 'obtain shared advisory lock',
+ proname => 'pg_advisory_xact_lock_shared', provolatile => 'v',
+ proparallel => 'r', prorettype => 'void', proargtypes => 'int4 int4',
+ prosrc => 'pg_advisory_xact_lock_shared_int4' },
+{ oid => '2888', descr => 'obtain exclusive advisory lock if available',
+ proname => 'pg_try_advisory_lock', provolatile => 'v', proparallel => 'r',
+ prorettype => 'bool', proargtypes => 'int4 int4',
+ prosrc => 'pg_try_advisory_lock_int4' },
+{ oid => '3095', descr => 'obtain exclusive advisory lock if available',
+ proname => 'pg_try_advisory_xact_lock', provolatile => 'v',
+ proparallel => 'r', prorettype => 'bool', proargtypes => 'int4 int4',
+ prosrc => 'pg_try_advisory_xact_lock_int4' },
+{ oid => '2889', descr => 'obtain shared advisory lock if available',
+ proname => 'pg_try_advisory_lock_shared', provolatile => 'v',
+ proparallel => 'r', prorettype => 'bool', proargtypes => 'int4 int4',
+ prosrc => 'pg_try_advisory_lock_shared_int4' },
+{ oid => '3096', descr => 'obtain shared advisory lock if available',
+ proname => 'pg_try_advisory_xact_lock_shared', provolatile => 'v',
+ proparallel => 'r', prorettype => 'bool', proargtypes => 'int4 int4',
+ prosrc => 'pg_try_advisory_xact_lock_shared_int4' },
+{ oid => '2890', descr => 'release exclusive advisory lock',
+ proname => 'pg_advisory_unlock', provolatile => 'v', proparallel => 'r',
+ prorettype => 'bool', proargtypes => 'int4 int4',
+ prosrc => 'pg_advisory_unlock_int4' },
+{ oid => '2891', descr => 'release shared advisory lock',
+ proname => 'pg_advisory_unlock_shared', provolatile => 'v',
+ proparallel => 'r', prorettype => 'bool', proargtypes => 'int4 int4',
+ prosrc => 'pg_advisory_unlock_shared_int4' },
+{ oid => '2892', descr => 'release all advisory locks',
+ proname => 'pg_advisory_unlock_all', provolatile => 'v', proparallel => 'r',
+ prorettype => 'void', proargtypes => '', prosrc => 'pg_advisory_unlock_all' },
+
+# XML support
+{ oid => '2893', descr => 'I/O',
+ proname => 'xml_in', provolatile => 's', prorettype => 'xml',
+ proargtypes => 'cstring', prosrc => 'xml_in' },
+{ oid => '2894', descr => 'I/O',
+ proname => 'xml_out', prorettype => 'cstring', proargtypes => 'xml',
+ prosrc => 'xml_out' },
+{ oid => '2895', descr => 'generate XML comment',
+ proname => 'xmlcomment', prorettype => 'xml', proargtypes => 'text',
+ prosrc => 'xmlcomment' },
+{ oid => '2896',
+ descr => 'perform a non-validating parse of a character string to produce an XML value',
+ proname => 'xml', provolatile => 's', prorettype => 'xml',
+ proargtypes => 'text', prosrc => 'texttoxml' },
+{ oid => '2897', descr => 'validate an XML value',
+ proname => 'xmlvalidate', prorettype => 'bool', proargtypes => 'xml text',
+ prosrc => 'xmlvalidate' },
+{ oid => '2898', descr => 'I/O',
+ proname => 'xml_recv', provolatile => 's', prorettype => 'xml',
+ proargtypes => 'internal', prosrc => 'xml_recv' },
+{ oid => '2899', descr => 'I/O',
+ proname => 'xml_send', provolatile => 's', prorettype => 'bytea',
+ proargtypes => 'xml', prosrc => 'xml_send' },
+{ oid => '2900', descr => 'aggregate transition function',
+ proname => 'xmlconcat2', proisstrict => 'f', prorettype => 'xml',
+ proargtypes => 'xml xml', prosrc => 'xmlconcat2' },
+{ oid => '2901', descr => 'concatenate XML values',
+ proname => 'xmlagg', prokind => 'a', proisstrict => 'f', prorettype => 'xml',
+ proargtypes => 'xml', prosrc => 'aggregate_dummy' },
+{ oid => '2922', descr => 'serialize an XML value to a character string',
+ proname => 'text', prorettype => 'text', proargtypes => 'xml',
+ prosrc => 'xmltotext' },
+
+{ oid => '2923', descr => 'map table contents to XML',
+ proname => 'table_to_xml', procost => '100', provolatile => 's',
+ proparallel => 'r', prorettype => 'xml',
+ proargtypes => 'regclass bool bool text',
+ proargnames => '{tbl,nulls,tableforest,targetns}', prosrc => 'table_to_xml' },
+{ oid => '2924', descr => 'map query result to XML',
+ proname => 'query_to_xml', procost => '100', provolatile => 'v',
+ proparallel => 'u', prorettype => 'xml', proargtypes => 'text bool bool text',
+ proargnames => '{query,nulls,tableforest,targetns}',
+ prosrc => 'query_to_xml' },
+{ oid => '2925', descr => 'map rows from cursor to XML',
+ proname => 'cursor_to_xml', procost => '100', provolatile => 'v',
+ proparallel => 'u', prorettype => 'xml',
+ proargtypes => 'refcursor int4 bool bool text',
+ proargnames => '{cursor,count,nulls,tableforest,targetns}',
+ prosrc => 'cursor_to_xml' },
+{ oid => '2926', descr => 'map table structure to XML Schema',
+ proname => 'table_to_xmlschema', procost => '100', provolatile => 's',
+ proparallel => 'r', prorettype => 'xml',
+ proargtypes => 'regclass bool bool text',
+ proargnames => '{tbl,nulls,tableforest,targetns}',
+ prosrc => 'table_to_xmlschema' },
+{ oid => '2927', descr => 'map query result structure to XML Schema',
+ proname => 'query_to_xmlschema', procost => '100', provolatile => 'v',
+ proparallel => 'u', prorettype => 'xml', proargtypes => 'text bool bool text',
+ proargnames => '{query,nulls,tableforest,targetns}',
+ prosrc => 'query_to_xmlschema' },
+{ oid => '2928', descr => 'map cursor structure to XML Schema',
+ proname => 'cursor_to_xmlschema', procost => '100', provolatile => 'v',
+ proparallel => 'u', prorettype => 'xml',
+ proargtypes => 'refcursor bool bool text',
+ proargnames => '{cursor,nulls,tableforest,targetns}',
+ prosrc => 'cursor_to_xmlschema' },
+{ oid => '2929',
+ descr => 'map table contents and structure to XML and XML Schema',
+ proname => 'table_to_xml_and_xmlschema', procost => '100', provolatile => 's',
+ proparallel => 'r', prorettype => 'xml',
+ proargtypes => 'regclass bool bool text',
+ proargnames => '{tbl,nulls,tableforest,targetns}',
+ prosrc => 'table_to_xml_and_xmlschema' },
+{ oid => '2930',
+ descr => 'map query result and structure to XML and XML Schema',
+ proname => 'query_to_xml_and_xmlschema', procost => '100', provolatile => 'v',
+ proparallel => 'u', prorettype => 'xml', proargtypes => 'text bool bool text',
+ proargnames => '{query,nulls,tableforest,targetns}',
+ prosrc => 'query_to_xml_and_xmlschema' },
+
+{ oid => '2933', descr => 'map schema contents to XML',
+ proname => 'schema_to_xml', procost => '100', provolatile => 's',
+ proparallel => 'r', prorettype => 'xml', proargtypes => 'name bool bool text',
+ proargnames => '{schema,nulls,tableforest,targetns}',
+ prosrc => 'schema_to_xml' },
+{ oid => '2934', descr => 'map schema structure to XML Schema',
+ proname => 'schema_to_xmlschema', procost => '100', provolatile => 's',
+ proparallel => 'r', prorettype => 'xml', proargtypes => 'name bool bool text',
+ proargnames => '{schema,nulls,tableforest,targetns}',
+ prosrc => 'schema_to_xmlschema' },
+{ oid => '2935',
+ descr => 'map schema contents and structure to XML and XML Schema',
+ proname => 'schema_to_xml_and_xmlschema', procost => '100',
+ provolatile => 's', proparallel => 'r', prorettype => 'xml',
+ proargtypes => 'name bool bool text',
+ proargnames => '{schema,nulls,tableforest,targetns}',
+ prosrc => 'schema_to_xml_and_xmlschema' },
+
+{ oid => '2936', descr => 'map database contents to XML',
+ proname => 'database_to_xml', procost => '100', provolatile => 's',
+ proparallel => 'r', prorettype => 'xml', proargtypes => 'bool bool text',
+ proargnames => '{nulls,tableforest,targetns}', prosrc => 'database_to_xml' },
+{ oid => '2937', descr => 'map database structure to XML Schema',
+ proname => 'database_to_xmlschema', procost => '100', provolatile => 's',
+ proparallel => 'r', prorettype => 'xml', proargtypes => 'bool bool text',
+ proargnames => '{nulls,tableforest,targetns}',
+ prosrc => 'database_to_xmlschema' },
+{ oid => '2938',
+ descr => 'map database contents and structure to XML and XML Schema',
+ proname => 'database_to_xml_and_xmlschema', procost => '100',
+ provolatile => 's', proparallel => 'r', prorettype => 'xml',
+ proargtypes => 'bool bool text',
+ proargnames => '{nulls,tableforest,targetns}',
+ prosrc => 'database_to_xml_and_xmlschema' },
+
+{ oid => '2931',
+ descr => 'evaluate XPath expression, with namespaces support',
+ proname => 'xpath', prorettype => '_xml', proargtypes => 'text xml _text',
+ prosrc => 'xpath' },
+{ oid => '2932', descr => 'evaluate XPath expression',
+ proname => 'xpath', prolang => 'sql', prorettype => '_xml',
+ proargtypes => 'text xml',
+ prosrc => 'select pg_catalog.xpath($1, $2, \'{}\'::pg_catalog.text[])' },
+
+{ oid => '2614', descr => 'test XML value against XPath expression',
+ proname => 'xmlexists', prorettype => 'bool', proargtypes => 'text xml',
+ prosrc => 'xmlexists' },
+
+{ oid => '3049',
+ descr => 'test XML value against XPath expression, with namespace support',
+ proname => 'xpath_exists', prorettype => 'bool',
+ proargtypes => 'text xml _text', prosrc => 'xpath_exists' },
+{ oid => '3050', descr => 'test XML value against XPath expression',
+ proname => 'xpath_exists', prolang => 'sql', prorettype => 'bool',
+ proargtypes => 'text xml',
+ prosrc => 'select pg_catalog.xpath_exists($1, $2, \'{}\'::pg_catalog.text[])' },
+{ oid => '3051', descr => 'determine if a string is well formed XML',
+ proname => 'xml_is_well_formed', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'text', prosrc => 'xml_is_well_formed' },
+{ oid => '3052', descr => 'determine if a string is well formed XML document',
+ proname => 'xml_is_well_formed_document', prorettype => 'bool',
+ proargtypes => 'text', prosrc => 'xml_is_well_formed_document' },
+{ oid => '3053', descr => 'determine if a string is well formed XML content',
+ proname => 'xml_is_well_formed_content', prorettype => 'bool',
+ proargtypes => 'text', prosrc => 'xml_is_well_formed_content' },
+
+# json
+{ oid => '321', descr => 'I/O',
+ proname => 'json_in', prorettype => 'json', proargtypes => 'cstring',
+ prosrc => 'json_in' },
+{ oid => '322', descr => 'I/O',
+ proname => 'json_out', prorettype => 'cstring', proargtypes => 'json',
+ prosrc => 'json_out' },
+{ oid => '323', descr => 'I/O',
+ proname => 'json_recv', prorettype => 'json', proargtypes => 'internal',
+ prosrc => 'json_recv' },
+{ oid => '324', descr => 'I/O',
+ proname => 'json_send', prorettype => 'bytea', proargtypes => 'json',
+ prosrc => 'json_send' },
+{ oid => '3153', descr => 'map array to json',
+ proname => 'array_to_json', provolatile => 's', prorettype => 'json',
+ proargtypes => 'anyarray', prosrc => 'array_to_json' },
+{ oid => '3154', descr => 'map array to json with optional pretty printing',
+ proname => 'array_to_json', provolatile => 's', prorettype => 'json',
+ proargtypes => 'anyarray bool', prosrc => 'array_to_json_pretty' },
+{ oid => '3155', descr => 'map row to json',
+ proname => 'row_to_json', provolatile => 's', prorettype => 'json',
+ proargtypes => 'record', prosrc => 'row_to_json' },
+{ oid => '3156', descr => 'map row to json with optional pretty printing',
+ proname => 'row_to_json', provolatile => 's', prorettype => 'json',
+ proargtypes => 'record bool', prosrc => 'row_to_json_pretty' },
+{ oid => '3173', descr => 'json aggregate transition function',
+ proname => 'json_agg_transfn', proisstrict => 'f', provolatile => 's',
+ prorettype => 'internal', proargtypes => 'internal anyelement',
+ prosrc => 'json_agg_transfn' },
+{ oid => '3174', descr => 'json aggregate final function',
+ proname => 'json_agg_finalfn', proisstrict => 'f', prorettype => 'json',
+ proargtypes => 'internal', prosrc => 'json_agg_finalfn' },
+{ oid => '3175', descr => 'aggregate input into json',
+ proname => 'json_agg', prokind => 'a', proisstrict => 'f', provolatile => 's',
+ prorettype => 'json', proargtypes => 'anyelement',
+ prosrc => 'aggregate_dummy' },
+{ oid => '3180', descr => 'json object aggregate transition function',
+ proname => 'json_object_agg_transfn', proisstrict => 'f', provolatile => 's',
+ prorettype => 'internal', proargtypes => 'internal any any',
+ prosrc => 'json_object_agg_transfn' },
+{ oid => '3196', descr => 'json object aggregate final function',
+ proname => 'json_object_agg_finalfn', proisstrict => 'f',
+ prorettype => 'json', proargtypes => 'internal',
+ prosrc => 'json_object_agg_finalfn' },
+{ oid => '3197', descr => 'aggregate input into a json object',
+ proname => 'json_object_agg', prokind => 'a', proisstrict => 'f',
+ provolatile => 's', prorettype => 'json', proargtypes => 'any any',
+ prosrc => 'aggregate_dummy' },
+{ oid => '3198', descr => 'build a json array from any inputs',
+ proname => 'json_build_array', provariadic => 'any', proisstrict => 'f',
+ provolatile => 's', prorettype => 'json', proargtypes => 'any',
+ proallargtypes => '{any}', proargmodes => '{v}',
+ prosrc => 'json_build_array' },
+{ oid => '3199', descr => 'build an empty json array',
+ proname => 'json_build_array', proisstrict => 'f', provolatile => 's',
+ prorettype => 'json', proargtypes => '',
+ prosrc => 'json_build_array_noargs' },
+{ oid => '3200',
+ descr => 'build a json object from pairwise key/value inputs',
+ proname => 'json_build_object', provariadic => 'any', proisstrict => 'f',
+ provolatile => 's', prorettype => 'json', proargtypes => 'any',
+ proallargtypes => '{any}', proargmodes => '{v}',
+ prosrc => 'json_build_object' },
+{ oid => '3201', descr => 'build an empty json object',
+ proname => 'json_build_object', proisstrict => 'f', provolatile => 's',
+ prorettype => 'json', proargtypes => '',
+ prosrc => 'json_build_object_noargs' },
+{ oid => '3202', descr => 'map text array of key value pairs to json object',
+ proname => 'json_object', prorettype => 'json', proargtypes => '_text',
+ prosrc => 'json_object' },
+{ oid => '3203', descr => 'map text arrays of keys and values to json object',
+ proname => 'json_object', prorettype => 'json', proargtypes => '_text _text',
+ prosrc => 'json_object_two_arg' },
+{ oid => '3176', descr => 'map input to json',
+ proname => 'to_json', provolatile => 's', prorettype => 'json',
+ proargtypes => 'anyelement', prosrc => 'to_json' },
+{ oid => '3261', descr => 'remove object fields with null values from json',
+ proname => 'json_strip_nulls', prorettype => 'json', proargtypes => 'json',
+ prosrc => 'json_strip_nulls' },
+
+{ oid => '3947',
+ proname => 'json_object_field', prorettype => 'json',
+ proargtypes => 'json text', proargnames => '{from_json, field_name}',
+ prosrc => 'json_object_field' },
+{ oid => '3948',
+ proname => 'json_object_field_text', prorettype => 'text',
+ proargtypes => 'json text', proargnames => '{from_json, field_name}',
+ prosrc => 'json_object_field_text' },
+{ oid => '3949',
+ proname => 'json_array_element', prorettype => 'json',
+ proargtypes => 'json int4', proargnames => '{from_json, element_index}',
+ prosrc => 'json_array_element' },
+{ oid => '3950',
+ proname => 'json_array_element_text', prorettype => 'text',
+ proargtypes => 'json int4', proargnames => '{from_json, element_index}',
+ prosrc => 'json_array_element_text' },
+{ oid => '3951', descr => 'get value from json with path elements',
+ proname => 'json_extract_path', provariadic => 'text', prorettype => 'json',
+ proargtypes => 'json _text', proallargtypes => '{json,_text}',
+ proargmodes => '{i,v}', proargnames => '{from_json,path_elems}',
+ prosrc => 'json_extract_path' },
+{ oid => '3953', descr => 'get value from json as text with path elements',
+ proname => 'json_extract_path_text', provariadic => 'text',
+ prorettype => 'text', proargtypes => 'json _text',
+ proallargtypes => '{json,_text}', proargmodes => '{i,v}',
+ proargnames => '{from_json,path_elems}', prosrc => 'json_extract_path_text' },
+{ oid => '3955', descr => 'key value pairs of a json object',
+ proname => 'json_array_elements', prorows => '100', proretset => 't',
+ prorettype => 'json', proargtypes => 'json', proallargtypes => '{json,json}',
+ proargmodes => '{i,o}', proargnames => '{from_json,value}',
+ prosrc => 'json_array_elements' },
+{ oid => '3969', descr => 'elements of json array',
+ proname => 'json_array_elements_text', prorows => '100', proretset => 't',
+ prorettype => 'text', proargtypes => 'json', proallargtypes => '{json,text}',
+ proargmodes => '{i,o}', proargnames => '{from_json,value}',
+ prosrc => 'json_array_elements_text' },
+{ oid => '3956', descr => 'length of json array',
+ proname => 'json_array_length', prorettype => 'int4', proargtypes => 'json',
+ prosrc => 'json_array_length' },
+{ oid => '3957', descr => 'get json object keys',
+ proname => 'json_object_keys', prorows => '100', proretset => 't',
+ prorettype => 'text', proargtypes => 'json', prosrc => 'json_object_keys' },
+{ oid => '3958', descr => 'key value pairs of a json object',
+ proname => 'json_each', prorows => '100', proretset => 't',
+ prorettype => 'record', proargtypes => 'json',
+ proallargtypes => '{json,text,json}', proargmodes => '{i,o,o}',
+ proargnames => '{from_json,key,value}', prosrc => 'json_each' },
+{ oid => '3959', descr => 'key value pairs of a json object',
+ proname => 'json_each_text', prorows => '100', proretset => 't',
+ prorettype => 'record', proargtypes => 'json',
+ proallargtypes => '{json,text,text}', proargmodes => '{i,o,o}',
+ proargnames => '{from_json,key,value}', prosrc => 'json_each_text' },
+{ oid => '3960', descr => 'get record fields from a json object',
+ proname => 'json_populate_record', proisstrict => 'f', provolatile => 's',
+ prorettype => 'anyelement', proargtypes => 'anyelement json bool',
+ prosrc => 'json_populate_record' },
+{ oid => '3961',
+ descr => 'get set of records with fields from a json array of objects',
+ proname => 'json_populate_recordset', prorows => '100', proisstrict => 'f',
+ proretset => 't', provolatile => 's', prorettype => 'anyelement',
+ proargtypes => 'anyelement json bool', prosrc => 'json_populate_recordset' },
+{ oid => '3204', descr => 'get record fields from a json object',
+ proname => 'json_to_record', provolatile => 's', prorettype => 'record',
+ proargtypes => 'json', prosrc => 'json_to_record' },
+{ oid => '3205',
+ descr => 'get set of records with fields from a json array of objects',
+ proname => 'json_to_recordset', prorows => '100', proisstrict => 'f',
+ proretset => 't', provolatile => 's', prorettype => 'record',
+ proargtypes => 'json', prosrc => 'json_to_recordset' },
+{ oid => '3968', descr => 'get the type of a json value',
+ proname => 'json_typeof', prorettype => 'text', proargtypes => 'json',
+ prosrc => 'json_typeof' },
+
+# uuid
+{ oid => '2952', descr => 'I/O',
+ proname => 'uuid_in', prorettype => 'uuid', proargtypes => 'cstring',
+ prosrc => 'uuid_in' },
+{ oid => '2953', descr => 'I/O',
+ proname => 'uuid_out', prorettype => 'cstring', proargtypes => 'uuid',
+ prosrc => 'uuid_out' },
+{ oid => '2954',
+ proname => 'uuid_lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'uuid uuid', prosrc => 'uuid_lt' },
+{ oid => '2955',
+ proname => 'uuid_le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'uuid uuid', prosrc => 'uuid_le' },
+{ oid => '2956',
+ proname => 'uuid_eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'uuid uuid', prosrc => 'uuid_eq' },
+{ oid => '2957',
+ proname => 'uuid_ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'uuid uuid', prosrc => 'uuid_ge' },
+{ oid => '2958',
+ proname => 'uuid_gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'uuid uuid', prosrc => 'uuid_gt' },
+{ oid => '2959',
+ proname => 'uuid_ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'uuid uuid', prosrc => 'uuid_ne' },
+{ oid => '2960', descr => 'less-equal-greater',
+ proname => 'uuid_cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'uuid uuid', prosrc => 'uuid_cmp' },
+{ oid => '3300', descr => 'sort support',
+ proname => 'uuid_sortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'uuid_sortsupport' },
+{ oid => '2961', descr => 'I/O',
+ proname => 'uuid_recv', prorettype => 'uuid', proargtypes => 'internal',
+ prosrc => 'uuid_recv' },
+{ oid => '2962', descr => 'I/O',
+ proname => 'uuid_send', prorettype => 'bytea', proargtypes => 'uuid',
+ prosrc => 'uuid_send' },
+{ oid => '2963', descr => 'hash',
+ proname => 'uuid_hash', prorettype => 'int4', proargtypes => 'uuid',
+ prosrc => 'uuid_hash' },
+{ oid => '3412', descr => 'hash',
+ proname => 'uuid_hash_extended', prorettype => 'int8',
+ proargtypes => 'uuid int8', prosrc => 'uuid_hash_extended' },
+{ oid => '3432', descr => 'generate random UUID',
+ proname => 'gen_random_uuid', proleakproof => 't', provolatile => 'v',
+ prorettype => 'uuid', proargtypes => '', prosrc => 'gen_random_uuid' },
+
+# pg_lsn
+{ oid => '3229', descr => 'I/O',
+ proname => 'pg_lsn_in', prorettype => 'pg_lsn', proargtypes => 'cstring',
+ prosrc => 'pg_lsn_in' },
+{ oid => '3230', descr => 'I/O',
+ proname => 'pg_lsn_out', prorettype => 'cstring', proargtypes => 'pg_lsn',
+ prosrc => 'pg_lsn_out' },
+{ oid => '3231',
+ proname => 'pg_lsn_lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'pg_lsn pg_lsn', prosrc => 'pg_lsn_lt' },
+{ oid => '3232',
+ proname => 'pg_lsn_le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'pg_lsn pg_lsn', prosrc => 'pg_lsn_le' },
+{ oid => '3233',
+ proname => 'pg_lsn_eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'pg_lsn pg_lsn', prosrc => 'pg_lsn_eq' },
+{ oid => '3234',
+ proname => 'pg_lsn_ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'pg_lsn pg_lsn', prosrc => 'pg_lsn_ge' },
+{ oid => '3235',
+ proname => 'pg_lsn_gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'pg_lsn pg_lsn', prosrc => 'pg_lsn_gt' },
+{ oid => '3236',
+ proname => 'pg_lsn_ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'pg_lsn pg_lsn', prosrc => 'pg_lsn_ne' },
+{ oid => '3237',
+ proname => 'pg_lsn_mi', prorettype => 'numeric',
+ proargtypes => 'pg_lsn pg_lsn', prosrc => 'pg_lsn_mi' },
+{ oid => '3238', descr => 'I/O',
+ proname => 'pg_lsn_recv', prorettype => 'pg_lsn', proargtypes => 'internal',
+ prosrc => 'pg_lsn_recv' },
+{ oid => '3239', descr => 'I/O',
+ proname => 'pg_lsn_send', prorettype => 'bytea', proargtypes => 'pg_lsn',
+ prosrc => 'pg_lsn_send' },
+{ oid => '3251', descr => 'less-equal-greater',
+ proname => 'pg_lsn_cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'pg_lsn pg_lsn', prosrc => 'pg_lsn_cmp' },
+{ oid => '3252', descr => 'hash',
+ proname => 'pg_lsn_hash', prorettype => 'int4', proargtypes => 'pg_lsn',
+ prosrc => 'pg_lsn_hash' },
+{ oid => '3413', descr => 'hash',
+ proname => 'pg_lsn_hash_extended', prorettype => 'int8',
+ proargtypes => 'pg_lsn int8', prosrc => 'pg_lsn_hash_extended' },
+{ oid => '4187', descr => 'larger of two',
+ proname => 'pg_lsn_larger', prorettype => 'pg_lsn',
+ proargtypes => 'pg_lsn pg_lsn', prosrc => 'pg_lsn_larger' },
+{ oid => '4188', descr => 'smaller of two',
+ proname => 'pg_lsn_smaller', prorettype => 'pg_lsn',
+ proargtypes => 'pg_lsn pg_lsn', prosrc => 'pg_lsn_smaller' },
+
+# enum related procs
+{ oid => '3504', descr => 'I/O',
+ proname => 'anyenum_in', prorettype => 'anyenum', proargtypes => 'cstring',
+ prosrc => 'anyenum_in' },
+{ oid => '3505', descr => 'I/O',
+ proname => 'anyenum_out', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'anyenum', prosrc => 'anyenum_out' },
+{ oid => '3506', descr => 'I/O',
+ proname => 'enum_in', provolatile => 's', prorettype => 'anyenum',
+ proargtypes => 'cstring oid', prosrc => 'enum_in' },
+{ oid => '3507', descr => 'I/O',
+ proname => 'enum_out', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'anyenum', prosrc => 'enum_out' },
+{ oid => '3508',
+ proname => 'enum_eq', prorettype => 'bool', proargtypes => 'anyenum anyenum',
+ prosrc => 'enum_eq' },
+{ oid => '3509',
+ proname => 'enum_ne', prorettype => 'bool', proargtypes => 'anyenum anyenum',
+ prosrc => 'enum_ne' },
+{ oid => '3510',
+ proname => 'enum_lt', prorettype => 'bool', proargtypes => 'anyenum anyenum',
+ prosrc => 'enum_lt' },
+{ oid => '3511',
+ proname => 'enum_gt', prorettype => 'bool', proargtypes => 'anyenum anyenum',
+ prosrc => 'enum_gt' },
+{ oid => '3512',
+ proname => 'enum_le', prorettype => 'bool', proargtypes => 'anyenum anyenum',
+ prosrc => 'enum_le' },
+{ oid => '3513',
+ proname => 'enum_ge', prorettype => 'bool', proargtypes => 'anyenum anyenum',
+ prosrc => 'enum_ge' },
+{ oid => '3514', descr => 'less-equal-greater',
+ proname => 'enum_cmp', prorettype => 'int4', proargtypes => 'anyenum anyenum',
+ prosrc => 'enum_cmp' },
+{ oid => '3515', descr => 'hash',
+ proname => 'hashenum', prorettype => 'int4', proargtypes => 'anyenum',
+ prosrc => 'hashenum' },
+{ oid => '3414', descr => 'hash',
+ proname => 'hashenumextended', prorettype => 'int8',
+ proargtypes => 'anyenum int8', prosrc => 'hashenumextended' },
+{ oid => '3524', descr => 'smaller of two',
+ proname => 'enum_smaller', prorettype => 'anyenum',
+ proargtypes => 'anyenum anyenum', prosrc => 'enum_smaller' },
+{ oid => '3525', descr => 'larger of two',
+ proname => 'enum_larger', prorettype => 'anyenum',
+ proargtypes => 'anyenum anyenum', prosrc => 'enum_larger' },
+{ oid => '3526', descr => 'maximum value of all enum input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'anyenum',
+ proargtypes => 'anyenum', prosrc => 'aggregate_dummy' },
+{ oid => '3527', descr => 'minimum value of all enum input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'anyenum',
+ proargtypes => 'anyenum', prosrc => 'aggregate_dummy' },
+{ oid => '3528', descr => 'first value of the input enum type',
+ proname => 'enum_first', proisstrict => 'f', provolatile => 's',
+ prorettype => 'anyenum', proargtypes => 'anyenum', prosrc => 'enum_first' },
+{ oid => '3529', descr => 'last value of the input enum type',
+ proname => 'enum_last', proisstrict => 'f', provolatile => 's',
+ prorettype => 'anyenum', proargtypes => 'anyenum', prosrc => 'enum_last' },
+{ oid => '3530',
+ descr => 'range between the two given enum values, as an ordered array',
+ proname => 'enum_range', proisstrict => 'f', provolatile => 's',
+ prorettype => 'anyarray', proargtypes => 'anyenum anyenum',
+ prosrc => 'enum_range_bounds' },
+{ oid => '3531', descr => 'range of the given enum type, as an ordered array',
+ proname => 'enum_range', proisstrict => 'f', provolatile => 's',
+ prorettype => 'anyarray', proargtypes => 'anyenum',
+ prosrc => 'enum_range_all' },
+{ oid => '3532', descr => 'I/O',
+ proname => 'enum_recv', provolatile => 's', prorettype => 'anyenum',
+ proargtypes => 'internal oid', prosrc => 'enum_recv' },
+{ oid => '3533', descr => 'I/O',
+ proname => 'enum_send', provolatile => 's', prorettype => 'bytea',
+ proargtypes => 'anyenum', prosrc => 'enum_send' },
+
+# text search stuff
+{ oid => '3610', descr => 'I/O',
+ proname => 'tsvectorin', prorettype => 'tsvector', proargtypes => 'cstring',
+ prosrc => 'tsvectorin' },
+{ oid => '3639', descr => 'I/O',
+ proname => 'tsvectorrecv', prorettype => 'tsvector',
+ proargtypes => 'internal', prosrc => 'tsvectorrecv' },
+{ oid => '3611', descr => 'I/O',
+ proname => 'tsvectorout', prorettype => 'cstring', proargtypes => 'tsvector',
+ prosrc => 'tsvectorout' },
+{ oid => '3638', descr => 'I/O',
+ proname => 'tsvectorsend', prorettype => 'bytea', proargtypes => 'tsvector',
+ prosrc => 'tsvectorsend' },
+{ oid => '3612', descr => 'I/O',
+ proname => 'tsqueryin', prorettype => 'tsquery', proargtypes => 'cstring',
+ prosrc => 'tsqueryin' },
+{ oid => '3641', descr => 'I/O',
+ proname => 'tsqueryrecv', prorettype => 'tsquery', proargtypes => 'internal',
+ prosrc => 'tsqueryrecv' },
+{ oid => '3613', descr => 'I/O',
+ proname => 'tsqueryout', prorettype => 'cstring', proargtypes => 'tsquery',
+ prosrc => 'tsqueryout' },
+{ oid => '3640', descr => 'I/O',
+ proname => 'tsquerysend', prorettype => 'bytea', proargtypes => 'tsquery',
+ prosrc => 'tsquerysend' },
+{ oid => '3646', descr => 'I/O',
+ proname => 'gtsvectorin', prorettype => 'gtsvector', proargtypes => 'cstring',
+ prosrc => 'gtsvectorin' },
+{ oid => '3647', descr => 'I/O',
+ proname => 'gtsvectorout', prorettype => 'cstring',
+ proargtypes => 'gtsvector', prosrc => 'gtsvectorout' },
+
+{ oid => '3616',
+ proname => 'tsvector_lt', prorettype => 'bool',
+ proargtypes => 'tsvector tsvector', prosrc => 'tsvector_lt' },
+{ oid => '3617',
+ proname => 'tsvector_le', prorettype => 'bool',
+ proargtypes => 'tsvector tsvector', prosrc => 'tsvector_le' },
+{ oid => '3618',
+ proname => 'tsvector_eq', prorettype => 'bool',
+ proargtypes => 'tsvector tsvector', prosrc => 'tsvector_eq' },
+{ oid => '3619',
+ proname => 'tsvector_ne', prorettype => 'bool',
+ proargtypes => 'tsvector tsvector', prosrc => 'tsvector_ne' },
+{ oid => '3620',
+ proname => 'tsvector_ge', prorettype => 'bool',
+ proargtypes => 'tsvector tsvector', prosrc => 'tsvector_ge' },
+{ oid => '3621',
+ proname => 'tsvector_gt', prorettype => 'bool',
+ proargtypes => 'tsvector tsvector', prosrc => 'tsvector_gt' },
+{ oid => '3622', descr => 'less-equal-greater',
+ proname => 'tsvector_cmp', prorettype => 'int4',
+ proargtypes => 'tsvector tsvector', prosrc => 'tsvector_cmp' },
+
+{ oid => '3711', descr => 'number of lexemes',
+ proname => 'length', prorettype => 'int4', proargtypes => 'tsvector',
+ prosrc => 'tsvector_length' },
+{ oid => '3623', descr => 'strip position information',
+ proname => 'strip', prorettype => 'tsvector', proargtypes => 'tsvector',
+ prosrc => 'tsvector_strip' },
+{ oid => '3624', descr => 'set given weight for whole tsvector',
+ proname => 'setweight', prorettype => 'tsvector',
+ proargtypes => 'tsvector char', prosrc => 'tsvector_setweight' },
+{ oid => '3320', descr => 'set given weight for given lexemes',
+ proname => 'setweight', prorettype => 'tsvector',
+ proargtypes => 'tsvector char _text',
+ prosrc => 'tsvector_setweight_by_filter' },
+{ oid => '3625',
+ proname => 'tsvector_concat', prorettype => 'tsvector',
+ proargtypes => 'tsvector tsvector', prosrc => 'tsvector_concat' },
+{ oid => '3321', descr => 'delete lexeme',
+ proname => 'ts_delete', prorettype => 'tsvector',
+ proargtypes => 'tsvector text', prosrc => 'tsvector_delete_str' },
+{ oid => '3323', descr => 'delete given lexemes',
+ proname => 'ts_delete', prorettype => 'tsvector',
+ proargtypes => 'tsvector _text', prosrc => 'tsvector_delete_arr' },
+{ oid => '3322', descr => 'expand tsvector to set of rows',
+ proname => 'unnest', prorows => '10', proretset => 't',
+ prorettype => 'record', proargtypes => 'tsvector',
+ proallargtypes => '{tsvector,text,_int2,_text}', proargmodes => '{i,o,o,o}',
+ proargnames => '{tsvector,lexeme,positions,weights}',
+ prosrc => 'tsvector_unnest' },
+{ oid => '3326', descr => 'convert tsvector to array of lexemes',
+ proname => 'tsvector_to_array', prorettype => '_text',
+ proargtypes => 'tsvector', prosrc => 'tsvector_to_array' },
+{ oid => '3327', descr => 'build tsvector from array of lexemes',
+ proname => 'array_to_tsvector', prorettype => 'tsvector',
+ proargtypes => '_text', prosrc => 'array_to_tsvector' },
+{ oid => '3319',
+ descr => 'delete lexemes that do not have one of the given weights',
+ proname => 'ts_filter', prorettype => 'tsvector',
+ proargtypes => 'tsvector _char', prosrc => 'tsvector_filter' },
+
+{ oid => '3634',
+ proname => 'ts_match_vq', prorettype => 'bool',
+ proargtypes => 'tsvector tsquery', prosrc => 'ts_match_vq' },
+{ oid => '3635',
+ proname => 'ts_match_qv', prorettype => 'bool',
+ proargtypes => 'tsquery tsvector', prosrc => 'ts_match_qv' },
+{ oid => '3760',
+ proname => 'ts_match_tt', procost => '100', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'text text', prosrc => 'ts_match_tt' },
+{ oid => '3761',
+ proname => 'ts_match_tq', procost => '100', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'text tsquery',
+ prosrc => 'ts_match_tq' },
+
+{ oid => '3648', descr => 'GiST tsvector support',
+ proname => 'gtsvector_compress', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'gtsvector_compress' },
+{ oid => '3649', descr => 'GiST tsvector support',
+ proname => 'gtsvector_decompress', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'gtsvector_decompress' },
+{ oid => '3650', descr => 'GiST tsvector support',
+ proname => 'gtsvector_picksplit', prorettype => 'internal',
+ proargtypes => 'internal internal', prosrc => 'gtsvector_picksplit' },
+{ oid => '3651', descr => 'GiST tsvector support',
+ proname => 'gtsvector_union', prorettype => 'gtsvector',
+ proargtypes => 'internal internal', prosrc => 'gtsvector_union' },
+{ oid => '3652', descr => 'GiST tsvector support',
+ proname => 'gtsvector_same', prorettype => 'internal',
+ proargtypes => 'gtsvector gtsvector internal', prosrc => 'gtsvector_same' },
+{ oid => '3653', descr => 'GiST tsvector support',
+ proname => 'gtsvector_penalty', prorettype => 'internal',
+ proargtypes => 'internal internal internal', prosrc => 'gtsvector_penalty' },
+{ oid => '3654', descr => 'GiST tsvector support',
+ proname => 'gtsvector_consistent', prorettype => 'bool',
+ proargtypes => 'internal tsvector int2 oid internal',
+ prosrc => 'gtsvector_consistent' },
+{ oid => '3790', descr => 'GiST tsvector support (obsolete)',
+ proname => 'gtsvector_consistent', prorettype => 'bool',
+ proargtypes => 'internal gtsvector int4 oid internal',
+ prosrc => 'gtsvector_consistent_oldsig' },
+{ oid => '3434', descr => 'GiST tsvector support',
+ proname => 'gtsvector_options', proisstrict => 'f', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'gtsvector_options' },
+
+{ oid => '3656', descr => 'GIN tsvector support',
+ proname => 'gin_extract_tsvector', prorettype => 'internal',
+ proargtypes => 'tsvector internal internal',
+ prosrc => 'gin_extract_tsvector' },
+{ oid => '3657', descr => 'GIN tsvector support',
+ proname => 'gin_extract_tsquery', prorettype => 'internal',
+ proargtypes => 'tsvector internal int2 internal internal internal internal',
+ prosrc => 'gin_extract_tsquery' },
+{ oid => '3658', descr => 'GIN tsvector support',
+ proname => 'gin_tsquery_consistent', prorettype => 'bool',
+ proargtypes => 'internal int2 tsvector int4 internal internal internal internal',
+ prosrc => 'gin_tsquery_consistent' },
+{ oid => '3921', descr => 'GIN tsvector support',
+ proname => 'gin_tsquery_triconsistent', prorettype => 'char',
+ proargtypes => 'internal int2 tsvector int4 internal internal internal',
+ prosrc => 'gin_tsquery_triconsistent' },
+{ oid => '3724', descr => 'GIN tsvector support',
+ proname => 'gin_cmp_tslexeme', prorettype => 'int4',
+ proargtypes => 'text text', prosrc => 'gin_cmp_tslexeme' },
+{ oid => '2700', descr => 'GIN tsvector support',
+ proname => 'gin_cmp_prefix', prorettype => 'int4',
+ proargtypes => 'text text int2 internal', prosrc => 'gin_cmp_prefix' },
+{ oid => '3077', descr => 'GIN tsvector support (obsolete)',
+ proname => 'gin_extract_tsvector', prorettype => 'internal',
+ proargtypes => 'tsvector internal', prosrc => 'gin_extract_tsvector_2args' },
+{ oid => '3087', descr => 'GIN tsvector support (obsolete)',
+ proname => 'gin_extract_tsquery', prorettype => 'internal',
+ proargtypes => 'tsquery internal int2 internal internal',
+ prosrc => 'gin_extract_tsquery_5args' },
+{ oid => '3088', descr => 'GIN tsvector support (obsolete)',
+ proname => 'gin_tsquery_consistent', prorettype => 'bool',
+ proargtypes => 'internal int2 tsquery int4 internal internal',
+ prosrc => 'gin_tsquery_consistent_6args' },
+{ oid => '3791', descr => 'GIN tsvector support (obsolete)',
+ proname => 'gin_extract_tsquery', prorettype => 'internal',
+ proargtypes => 'tsquery internal int2 internal internal internal internal',
+ prosrc => 'gin_extract_tsquery_oldsig' },
+{ oid => '3792', descr => 'GIN tsvector support (obsolete)',
+ proname => 'gin_tsquery_consistent', prorettype => 'bool',
+ proargtypes => 'internal int2 tsquery int4 internal internal internal internal',
+ prosrc => 'gin_tsquery_consistent_oldsig' },
+
+{ oid => '3789', descr => 'clean up GIN pending list',
+ proname => 'gin_clean_pending_list', provolatile => 'v', proparallel => 'u',
+ prorettype => 'int8', proargtypes => 'regclass',
+ prosrc => 'gin_clean_pending_list' },
+
+{ oid => '3662',
+ proname => 'tsquery_lt', prorettype => 'bool',
+ proargtypes => 'tsquery tsquery', prosrc => 'tsquery_lt' },
+{ oid => '3663',
+ proname => 'tsquery_le', prorettype => 'bool',
+ proargtypes => 'tsquery tsquery', prosrc => 'tsquery_le' },
+{ oid => '3664',
+ proname => 'tsquery_eq', prorettype => 'bool',
+ proargtypes => 'tsquery tsquery', prosrc => 'tsquery_eq' },
+{ oid => '3665',
+ proname => 'tsquery_ne', prorettype => 'bool',
+ proargtypes => 'tsquery tsquery', prosrc => 'tsquery_ne' },
+{ oid => '3666',
+ proname => 'tsquery_ge', prorettype => 'bool',
+ proargtypes => 'tsquery tsquery', prosrc => 'tsquery_ge' },
+{ oid => '3667',
+ proname => 'tsquery_gt', prorettype => 'bool',
+ proargtypes => 'tsquery tsquery', prosrc => 'tsquery_gt' },
+{ oid => '3668', descr => 'less-equal-greater',
+ proname => 'tsquery_cmp', prorettype => 'int4',
+ proargtypes => 'tsquery tsquery', prosrc => 'tsquery_cmp' },
+
+{ oid => '3669',
+ proname => 'tsquery_and', prorettype => 'tsquery',
+ proargtypes => 'tsquery tsquery', prosrc => 'tsquery_and' },
+{ oid => '3670',
+ proname => 'tsquery_or', prorettype => 'tsquery',
+ proargtypes => 'tsquery tsquery', prosrc => 'tsquery_or' },
+{ oid => '5003',
+ proname => 'tsquery_phrase', prorettype => 'tsquery',
+ proargtypes => 'tsquery tsquery', prosrc => 'tsquery_phrase' },
+{ oid => '5004', descr => 'phrase-concatenate with distance',
+ proname => 'tsquery_phrase', prorettype => 'tsquery',
+ proargtypes => 'tsquery tsquery int4', prosrc => 'tsquery_phrase_distance' },
+{ oid => '3671',
+ proname => 'tsquery_not', prorettype => 'tsquery', proargtypes => 'tsquery',
+ prosrc => 'tsquery_not' },
+
+{ oid => '3691',
+ proname => 'tsq_mcontains', prorettype => 'bool',
+ proargtypes => 'tsquery tsquery', prosrc => 'tsq_mcontains' },
+{ oid => '3692',
+ proname => 'tsq_mcontained', prorettype => 'bool',
+ proargtypes => 'tsquery tsquery', prosrc => 'tsq_mcontained' },
+
+{ oid => '3672', descr => 'number of nodes',
+ proname => 'numnode', prorettype => 'int4', proargtypes => 'tsquery',
+ prosrc => 'tsquery_numnode' },
+{ oid => '3673', descr => 'show real useful query for GiST index',
+ proname => 'querytree', prorettype => 'text', proargtypes => 'tsquery',
+ prosrc => 'tsquerytree' },
+
+{ oid => '3684', descr => 'rewrite tsquery',
+ proname => 'ts_rewrite', prorettype => 'tsquery',
+ proargtypes => 'tsquery tsquery tsquery', prosrc => 'tsquery_rewrite' },
+{ oid => '3685', descr => 'rewrite tsquery',
+ proname => 'ts_rewrite', procost => '100', provolatile => 'v',
+ proparallel => 'u', prorettype => 'tsquery', proargtypes => 'tsquery text',
+ prosrc => 'tsquery_rewrite_query' },
+
+{ oid => '3695', descr => 'GiST tsquery support',
+ proname => 'gtsquery_compress', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'gtsquery_compress' },
+{ oid => '3697', descr => 'GiST tsquery support',
+ proname => 'gtsquery_picksplit', prorettype => 'internal',
+ proargtypes => 'internal internal', prosrc => 'gtsquery_picksplit' },
+{ oid => '3698', descr => 'GiST tsquery support',
+ proname => 'gtsquery_union', prorettype => 'int8',
+ proargtypes => 'internal internal', prosrc => 'gtsquery_union' },
+{ oid => '3699', descr => 'GiST tsquery support',
+ proname => 'gtsquery_same', prorettype => 'internal',
+ proargtypes => 'int8 int8 internal', prosrc => 'gtsquery_same' },
+{ oid => '3700', descr => 'GiST tsquery support',
+ proname => 'gtsquery_penalty', prorettype => 'internal',
+ proargtypes => 'internal internal internal', prosrc => 'gtsquery_penalty' },
+{ oid => '3701', descr => 'GiST tsquery support',
+ proname => 'gtsquery_consistent', prorettype => 'bool',
+ proargtypes => 'internal tsquery int2 oid internal',
+ prosrc => 'gtsquery_consistent' },
+{ oid => '3793', descr => 'GiST tsquery support (obsolete)',
+ proname => 'gtsquery_consistent', prorettype => 'bool',
+ proargtypes => 'internal internal int4 oid internal',
+ prosrc => 'gtsquery_consistent_oldsig' },
+
+{ oid => '3686', descr => 'restriction selectivity of tsvector @@ tsquery',
+ proname => 'tsmatchsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'tsmatchsel' },
+{ oid => '3687', descr => 'join selectivity of tsvector @@ tsquery',
+ proname => 'tsmatchjoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'tsmatchjoinsel' },
+{ oid => '3688', descr => 'tsvector typanalyze',
+ proname => 'ts_typanalyze', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'internal', prosrc => 'ts_typanalyze' },
+
+{ oid => '3689', descr => 'statistics of tsvector column',
+ proname => 'ts_stat', procost => '10', prorows => '10000', proretset => 't',
+ provolatile => 'v', proparallel => 'u', prorettype => 'record',
+ proargtypes => 'text', proallargtypes => '{text,text,int4,int4}',
+ proargmodes => '{i,o,o,o}', proargnames => '{query,word,ndoc,nentry}',
+ prosrc => 'ts_stat1' },
+{ oid => '3690', descr => 'statistics of tsvector column',
+ proname => 'ts_stat', procost => '10', prorows => '10000', proretset => 't',
+ provolatile => 'v', proparallel => 'u', prorettype => 'record',
+ proargtypes => 'text text', proallargtypes => '{text,text,text,int4,int4}',
+ proargmodes => '{i,i,o,o,o}',
+ proargnames => '{query,weights,word,ndoc,nentry}', prosrc => 'ts_stat2' },
+
+{ oid => '3703', descr => 'relevance',
+ proname => 'ts_rank', prorettype => 'float4',
+ proargtypes => '_float4 tsvector tsquery int4', prosrc => 'ts_rank_wttf' },
+{ oid => '3704', descr => 'relevance',
+ proname => 'ts_rank', prorettype => 'float4',
+ proargtypes => '_float4 tsvector tsquery', prosrc => 'ts_rank_wtt' },
+{ oid => '3705', descr => 'relevance',
+ proname => 'ts_rank', prorettype => 'float4',
+ proargtypes => 'tsvector tsquery int4', prosrc => 'ts_rank_ttf' },
+{ oid => '3706', descr => 'relevance',
+ proname => 'ts_rank', prorettype => 'float4',
+ proargtypes => 'tsvector tsquery', prosrc => 'ts_rank_tt' },
+{ oid => '3707', descr => 'relevance',
+ proname => 'ts_rank_cd', prorettype => 'float4',
+ proargtypes => '_float4 tsvector tsquery int4', prosrc => 'ts_rankcd_wttf' },
+{ oid => '3708', descr => 'relevance',
+ proname => 'ts_rank_cd', prorettype => 'float4',
+ proargtypes => '_float4 tsvector tsquery', prosrc => 'ts_rankcd_wtt' },
+{ oid => '3709', descr => 'relevance',
+ proname => 'ts_rank_cd', prorettype => 'float4',
+ proargtypes => 'tsvector tsquery int4', prosrc => 'ts_rankcd_ttf' },
+{ oid => '3710', descr => 'relevance',
+ proname => 'ts_rank_cd', prorettype => 'float4',
+ proargtypes => 'tsvector tsquery', prosrc => 'ts_rankcd_tt' },
+
+{ oid => '3713', descr => 'get parser\'s token types',
+ proname => 'ts_token_type', prorows => '16', proretset => 't',
+ prorettype => 'record', proargtypes => 'oid',
+ proallargtypes => '{oid,int4,text,text}', proargmodes => '{i,o,o,o}',
+ proargnames => '{parser_oid,tokid,alias,description}',
+ prosrc => 'ts_token_type_byid' },
+{ oid => '3714', descr => 'get parser\'s token types',
+ proname => 'ts_token_type', prorows => '16', proretset => 't',
+ provolatile => 's', prorettype => 'record', proargtypes => 'text',
+ proallargtypes => '{text,int4,text,text}', proargmodes => '{i,o,o,o}',
+ proargnames => '{parser_name,tokid,alias,description}',
+ prosrc => 'ts_token_type_byname' },
+{ oid => '3715', descr => 'parse text to tokens',
+ proname => 'ts_parse', prorows => '1000', proretset => 't',
+ prorettype => 'record', proargtypes => 'oid text',
+ proallargtypes => '{oid,text,int4,text}', proargmodes => '{i,i,o,o}',
+ proargnames => '{parser_oid,txt,tokid,token}', prosrc => 'ts_parse_byid' },
+{ oid => '3716', descr => 'parse text to tokens',
+ proname => 'ts_parse', prorows => '1000', proretset => 't',
+ provolatile => 's', prorettype => 'record', proargtypes => 'text text',
+ proallargtypes => '{text,text,int4,text}', proargmodes => '{i,i,o,o}',
+ proargnames => '{parser_name,txt,tokid,token}', prosrc => 'ts_parse_byname' },
+
+{ oid => '3717', descr => '(internal)',
+ proname => 'prsd_start', prorettype => 'internal',
+ proargtypes => 'internal int4', prosrc => 'prsd_start' },
+{ oid => '3718', descr => '(internal)',
+ proname => 'prsd_nexttoken', prorettype => 'internal',
+ proargtypes => 'internal internal internal', prosrc => 'prsd_nexttoken' },
+{ oid => '3719', descr => '(internal)',
+ proname => 'prsd_end', prorettype => 'void', proargtypes => 'internal',
+ prosrc => 'prsd_end' },
+{ oid => '3720', descr => '(internal)',
+ proname => 'prsd_headline', prorettype => 'internal',
+ proargtypes => 'internal internal tsquery', prosrc => 'prsd_headline' },
+{ oid => '3721', descr => '(internal)',
+ proname => 'prsd_lextype', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'prsd_lextype' },
+
+{ oid => '3723', descr => 'normalize one word by dictionary',
+ proname => 'ts_lexize', prorettype => '_text',
+ proargtypes => 'regdictionary text', prosrc => 'ts_lexize' },
+
+{ oid => '3725', descr => '(internal)',
+ proname => 'dsimple_init', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'dsimple_init' },
+{ oid => '3726', descr => '(internal)',
+ proname => 'dsimple_lexize', prorettype => 'internal',
+ proargtypes => 'internal internal internal internal',
+ prosrc => 'dsimple_lexize' },
+
+{ oid => '3728', descr => '(internal)',
+ proname => 'dsynonym_init', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'dsynonym_init' },
+{ oid => '3729', descr => '(internal)',
+ proname => 'dsynonym_lexize', prorettype => 'internal',
+ proargtypes => 'internal internal internal internal',
+ prosrc => 'dsynonym_lexize' },
+
+{ oid => '3731', descr => '(internal)',
+ proname => 'dispell_init', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'dispell_init' },
+{ oid => '3732', descr => '(internal)',
+ proname => 'dispell_lexize', prorettype => 'internal',
+ proargtypes => 'internal internal internal internal',
+ prosrc => 'dispell_lexize' },
+
+{ oid => '3740', descr => '(internal)',
+ proname => 'thesaurus_init', prorettype => 'internal',
+ proargtypes => 'internal', prosrc => 'thesaurus_init' },
+{ oid => '3741', descr => '(internal)',
+ proname => 'thesaurus_lexize', prorettype => 'internal',
+ proargtypes => 'internal internal internal internal',
+ prosrc => 'thesaurus_lexize' },
+
+{ oid => '3743', descr => 'generate headline',
+ proname => 'ts_headline', procost => '100', prorettype => 'text',
+ proargtypes => 'regconfig text tsquery text',
+ prosrc => 'ts_headline_byid_opt' },
+{ oid => '3744', descr => 'generate headline',
+ proname => 'ts_headline', procost => '100', prorettype => 'text',
+ proargtypes => 'regconfig text tsquery', prosrc => 'ts_headline_byid' },
+{ oid => '3754', descr => 'generate headline',
+ proname => 'ts_headline', procost => '100', provolatile => 's',
+ prorettype => 'text', proargtypes => 'text tsquery text',
+ prosrc => 'ts_headline_opt' },
+{ oid => '3755', descr => 'generate headline',
+ proname => 'ts_headline', procost => '100', provolatile => 's',
+ prorettype => 'text', proargtypes => 'text tsquery',
+ prosrc => 'ts_headline' },
+
+{ oid => '4201', descr => 'generate headline from jsonb',
+ proname => 'ts_headline', procost => '100', prorettype => 'jsonb',
+ proargtypes => 'regconfig jsonb tsquery text',
+ prosrc => 'ts_headline_jsonb_byid_opt' },
+{ oid => '4202', descr => 'generate headline from jsonb',
+ proname => 'ts_headline', procost => '100', prorettype => 'jsonb',
+ proargtypes => 'regconfig jsonb tsquery',
+ prosrc => 'ts_headline_jsonb_byid' },
+{ oid => '4203', descr => 'generate headline from jsonb',
+ proname => 'ts_headline', procost => '100', provolatile => 's',
+ prorettype => 'jsonb', proargtypes => 'jsonb tsquery text',
+ prosrc => 'ts_headline_jsonb_opt' },
+{ oid => '4204', descr => 'generate headline from jsonb',
+ proname => 'ts_headline', procost => '100', provolatile => 's',
+ prorettype => 'jsonb', proargtypes => 'jsonb tsquery',
+ prosrc => 'ts_headline_jsonb' },
+
+{ oid => '4205', descr => 'generate headline from json',
+ proname => 'ts_headline', procost => '100', prorettype => 'json',
+ proargtypes => 'regconfig json tsquery text',
+ prosrc => 'ts_headline_json_byid_opt' },
+{ oid => '4206', descr => 'generate headline from json',
+ proname => 'ts_headline', procost => '100', prorettype => 'json',
+ proargtypes => 'regconfig json tsquery', prosrc => 'ts_headline_json_byid' },
+{ oid => '4207', descr => 'generate headline from json',
+ proname => 'ts_headline', procost => '100', provolatile => 's',
+ prorettype => 'json', proargtypes => 'json tsquery text',
+ prosrc => 'ts_headline_json_opt' },
+{ oid => '4208', descr => 'generate headline from json',
+ proname => 'ts_headline', procost => '100', provolatile => 's',
+ prorettype => 'json', proargtypes => 'json tsquery',
+ prosrc => 'ts_headline_json' },
+
+{ oid => '3745', descr => 'transform to tsvector',
+ proname => 'to_tsvector', procost => '100', prorettype => 'tsvector',
+ proargtypes => 'regconfig text', prosrc => 'to_tsvector_byid' },
+{ oid => '3746', descr => 'make tsquery',
+ proname => 'to_tsquery', procost => '100', prorettype => 'tsquery',
+ proargtypes => 'regconfig text', prosrc => 'to_tsquery_byid' },
+{ oid => '3747', descr => 'transform to tsquery',
+ proname => 'plainto_tsquery', procost => '100', prorettype => 'tsquery',
+ proargtypes => 'regconfig text', prosrc => 'plainto_tsquery_byid' },
+{ oid => '5006', descr => 'transform to tsquery',
+ proname => 'phraseto_tsquery', procost => '100', prorettype => 'tsquery',
+ proargtypes => 'regconfig text', prosrc => 'phraseto_tsquery_byid' },
+{ oid => '5007', descr => 'transform to tsquery',
+ proname => 'websearch_to_tsquery', procost => '100', prorettype => 'tsquery',
+ proargtypes => 'regconfig text', prosrc => 'websearch_to_tsquery_byid' },
+{ oid => '3749', descr => 'transform to tsvector',
+ proname => 'to_tsvector', procost => '100', provolatile => 's',
+ prorettype => 'tsvector', proargtypes => 'text', prosrc => 'to_tsvector' },
+{ oid => '3750', descr => 'make tsquery',
+ proname => 'to_tsquery', procost => '100', provolatile => 's',
+ prorettype => 'tsquery', proargtypes => 'text', prosrc => 'to_tsquery' },
+{ oid => '3751', descr => 'transform to tsquery',
+ proname => 'plainto_tsquery', procost => '100', provolatile => 's',
+ prorettype => 'tsquery', proargtypes => 'text', prosrc => 'plainto_tsquery' },
+{ oid => '5001', descr => 'transform to tsquery',
+ proname => 'phraseto_tsquery', procost => '100', provolatile => 's',
+ prorettype => 'tsquery', proargtypes => 'text',
+ prosrc => 'phraseto_tsquery' },
+{ oid => '5009', descr => 'transform to tsquery',
+ proname => 'websearch_to_tsquery', procost => '100', provolatile => 's',
+ prorettype => 'tsquery', proargtypes => 'text',
+ prosrc => 'websearch_to_tsquery' },
+{ oid => '4209', descr => 'transform string values from jsonb to tsvector',
+ proname => 'to_tsvector', procost => '100', provolatile => 's',
+ prorettype => 'tsvector', proargtypes => 'jsonb',
+ prosrc => 'jsonb_string_to_tsvector' },
+{ oid => '4213', descr => 'transform specified values from jsonb to tsvector',
+ proname => 'jsonb_to_tsvector', procost => '100', provolatile => 's',
+ prorettype => 'tsvector', proargtypes => 'jsonb jsonb',
+ prosrc => 'jsonb_to_tsvector' },
+{ oid => '4210', descr => 'transform string values from json to tsvector',
+ proname => 'to_tsvector', procost => '100', provolatile => 's',
+ prorettype => 'tsvector', proargtypes => 'json',
+ prosrc => 'json_string_to_tsvector' },
+{ oid => '4215', descr => 'transform specified values from json to tsvector',
+ proname => 'json_to_tsvector', procost => '100', provolatile => 's',
+ prorettype => 'tsvector', proargtypes => 'json jsonb',
+ prosrc => 'json_to_tsvector' },
+{ oid => '4211', descr => 'transform string values from jsonb to tsvector',
+ proname => 'to_tsvector', procost => '100', prorettype => 'tsvector',
+ proargtypes => 'regconfig jsonb', prosrc => 'jsonb_string_to_tsvector_byid' },
+{ oid => '4214', descr => 'transform specified values from jsonb to tsvector',
+ proname => 'jsonb_to_tsvector', procost => '100', prorettype => 'tsvector',
+ proargtypes => 'regconfig jsonb jsonb', prosrc => 'jsonb_to_tsvector_byid' },
+{ oid => '4212', descr => 'transform string values from json to tsvector',
+ proname => 'to_tsvector', procost => '100', prorettype => 'tsvector',
+ proargtypes => 'regconfig json', prosrc => 'json_string_to_tsvector_byid' },
+{ oid => '4216', descr => 'transform specified values from json to tsvector',
+ proname => 'json_to_tsvector', procost => '100', prorettype => 'tsvector',
+ proargtypes => 'regconfig json jsonb', prosrc => 'json_to_tsvector_byid' },
+
+{ oid => '3752', descr => 'trigger for automatic update of tsvector column',
+ proname => 'tsvector_update_trigger', proisstrict => 'f', provolatile => 'v',
+ prorettype => 'trigger', proargtypes => '',
+ prosrc => 'tsvector_update_trigger_byid' },
+{ oid => '3753', descr => 'trigger for automatic update of tsvector column',
+ proname => 'tsvector_update_trigger_column', proisstrict => 'f',
+ provolatile => 'v', prorettype => 'trigger', proargtypes => '',
+ prosrc => 'tsvector_update_trigger_bycolumn' },
+
+{ oid => '3759', descr => 'get current tsearch configuration',
+ proname => 'get_current_ts_config', provolatile => 's',
+ prorettype => 'regconfig', proargtypes => '',
+ prosrc => 'get_current_ts_config' },
+
+{ oid => '3736', descr => 'I/O',
+ proname => 'regconfigin', provolatile => 's', prorettype => 'regconfig',
+ proargtypes => 'cstring', prosrc => 'regconfigin' },
+{ oid => '3737', descr => 'I/O',
+ proname => 'regconfigout', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'regconfig', prosrc => 'regconfigout' },
+{ oid => '3738', descr => 'I/O',
+ proname => 'regconfigrecv', prorettype => 'regconfig',
+ proargtypes => 'internal', prosrc => 'regconfigrecv' },
+{ oid => '3739', descr => 'I/O',
+ proname => 'regconfigsend', prorettype => 'bytea', proargtypes => 'regconfig',
+ prosrc => 'regconfigsend' },
+
+{ oid => '3771', descr => 'I/O',
+ proname => 'regdictionaryin', provolatile => 's',
+ prorettype => 'regdictionary', proargtypes => 'cstring',
+ prosrc => 'regdictionaryin' },
+{ oid => '3772', descr => 'I/O',
+ proname => 'regdictionaryout', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'regdictionary', prosrc => 'regdictionaryout' },
+{ oid => '3773', descr => 'I/O',
+ proname => 'regdictionaryrecv', prorettype => 'regdictionary',
+ proargtypes => 'internal', prosrc => 'regdictionaryrecv' },
+{ oid => '3774', descr => 'I/O',
+ proname => 'regdictionarysend', prorettype => 'bytea',
+ proargtypes => 'regdictionary', prosrc => 'regdictionarysend' },
+
+# jsonb
+{ oid => '3806', descr => 'I/O',
+ proname => 'jsonb_in', prorettype => 'jsonb', proargtypes => 'cstring',
+ prosrc => 'jsonb_in' },
+{ oid => '3805', descr => 'I/O',
+ proname => 'jsonb_recv', prorettype => 'jsonb', proargtypes => 'internal',
+ prosrc => 'jsonb_recv' },
+{ oid => '3804', descr => 'I/O',
+ proname => 'jsonb_out', prorettype => 'cstring', proargtypes => 'jsonb',
+ prosrc => 'jsonb_out' },
+{ oid => '3803', descr => 'I/O',
+ proname => 'jsonb_send', prorettype => 'bytea', proargtypes => 'jsonb',
+ prosrc => 'jsonb_send' },
+
+{ oid => '3263', descr => 'map text array of key value pairs to jsonb object',
+ proname => 'jsonb_object', prorettype => 'jsonb', proargtypes => '_text',
+ prosrc => 'jsonb_object' },
+{ oid => '3264', descr => 'map text array of key value pairs to jsonb object',
+ proname => 'jsonb_object', prorettype => 'jsonb',
+ proargtypes => '_text _text', prosrc => 'jsonb_object_two_arg' },
+{ oid => '3787', descr => 'map input to jsonb',
+ proname => 'to_jsonb', provolatile => 's', prorettype => 'jsonb',
+ proargtypes => 'anyelement', prosrc => 'to_jsonb' },
+{ oid => '3265', descr => 'jsonb aggregate transition function',
+ proname => 'jsonb_agg_transfn', proisstrict => 'f', provolatile => 's',
+ prorettype => 'internal', proargtypes => 'internal anyelement',
+ prosrc => 'jsonb_agg_transfn' },
+{ oid => '3266', descr => 'jsonb aggregate final function',
+ proname => 'jsonb_agg_finalfn', proisstrict => 'f', provolatile => 's',
+ prorettype => 'jsonb', proargtypes => 'internal',
+ prosrc => 'jsonb_agg_finalfn' },
+{ oid => '3267', descr => 'aggregate input into jsonb',
+ proname => 'jsonb_agg', prokind => 'a', proisstrict => 'f',
+ provolatile => 's', prorettype => 'jsonb', proargtypes => 'anyelement',
+ prosrc => 'aggregate_dummy' },
+{ oid => '3268', descr => 'jsonb object aggregate transition function',
+ proname => 'jsonb_object_agg_transfn', proisstrict => 'f', provolatile => 's',
+ prorettype => 'internal', proargtypes => 'internal any any',
+ prosrc => 'jsonb_object_agg_transfn' },
+{ oid => '3269', descr => 'jsonb object aggregate final function',
+ proname => 'jsonb_object_agg_finalfn', proisstrict => 'f', provolatile => 's',
+ prorettype => 'jsonb', proargtypes => 'internal',
+ prosrc => 'jsonb_object_agg_finalfn' },
+{ oid => '3270', descr => 'aggregate inputs into jsonb object',
+ proname => 'jsonb_object_agg', prokind => 'a', proisstrict => 'f',
+ prorettype => 'jsonb', proargtypes => 'any any',
+ prosrc => 'aggregate_dummy' },
+{ oid => '3271', descr => 'build a jsonb array from any inputs',
+ proname => 'jsonb_build_array', provariadic => 'any', proisstrict => 'f',
+ provolatile => 's', prorettype => 'jsonb', proargtypes => 'any',
+ proallargtypes => '{any}', proargmodes => '{v}',
+ prosrc => 'jsonb_build_array' },
+{ oid => '3272', descr => 'build an empty jsonb array',
+ proname => 'jsonb_build_array', proisstrict => 'f', provolatile => 's',
+ prorettype => 'jsonb', proargtypes => '',
+ prosrc => 'jsonb_build_array_noargs' },
+{ oid => '3273',
+ descr => 'build a jsonb object from pairwise key/value inputs',
+ proname => 'jsonb_build_object', provariadic => 'any', proisstrict => 'f',
+ provolatile => 's', prorettype => 'jsonb', proargtypes => 'any',
+ proallargtypes => '{any}', proargmodes => '{v}',
+ prosrc => 'jsonb_build_object' },
+{ oid => '3274', descr => 'build an empty jsonb object',
+ proname => 'jsonb_build_object', proisstrict => 'f', provolatile => 's',
+ prorettype => 'jsonb', proargtypes => '',
+ prosrc => 'jsonb_build_object_noargs' },
+{ oid => '3262', descr => 'remove object fields with null values from jsonb',
+ proname => 'jsonb_strip_nulls', prorettype => 'jsonb', proargtypes => 'jsonb',
+ prosrc => 'jsonb_strip_nulls' },
+
+{ oid => '3478',
+ proname => 'jsonb_object_field', prorettype => 'jsonb',
+ proargtypes => 'jsonb text', proargnames => '{from_json, field_name}',
+ prosrc => 'jsonb_object_field' },
+{ oid => '3214',
+ proname => 'jsonb_object_field_text', prorettype => 'text',
+ proargtypes => 'jsonb text', proargnames => '{from_json, field_name}',
+ prosrc => 'jsonb_object_field_text' },
+{ oid => '3215',
+ proname => 'jsonb_array_element', prorettype => 'jsonb',
+ proargtypes => 'jsonb int4', proargnames => '{from_json, element_index}',
+ prosrc => 'jsonb_array_element' },
+{ oid => '3216',
+ proname => 'jsonb_array_element_text', prorettype => 'text',
+ proargtypes => 'jsonb int4', proargnames => '{from_json, element_index}',
+ prosrc => 'jsonb_array_element_text' },
+{ oid => '3217', descr => 'get value from jsonb with path elements',
+ proname => 'jsonb_extract_path', provariadic => 'text', prorettype => 'jsonb',
+ proargtypes => 'jsonb _text', proallargtypes => '{jsonb,_text}',
+ proargmodes => '{i,v}', proargnames => '{from_json,path_elems}',
+ prosrc => 'jsonb_extract_path' },
+{ oid => '3940', descr => 'get value from jsonb as text with path elements',
+ proname => 'jsonb_extract_path_text', provariadic => 'text',
+ prorettype => 'text', proargtypes => 'jsonb _text',
+ proallargtypes => '{jsonb,_text}', proargmodes => '{i,v}',
+ proargnames => '{from_json,path_elems}',
+ prosrc => 'jsonb_extract_path_text' },
+{ oid => '3219', descr => 'elements of a jsonb array',
+ proname => 'jsonb_array_elements', prorows => '100', proretset => 't',
+ prorettype => 'jsonb', proargtypes => 'jsonb',
+ proallargtypes => '{jsonb,jsonb}', proargmodes => '{i,o}',
+ proargnames => '{from_json,value}', prosrc => 'jsonb_array_elements' },
+{ oid => '3465', descr => 'elements of jsonb array',
+ proname => 'jsonb_array_elements_text', prorows => '100', proretset => 't',
+ prorettype => 'text', proargtypes => 'jsonb',
+ proallargtypes => '{jsonb,text}', proargmodes => '{i,o}',
+ proargnames => '{from_json,value}', prosrc => 'jsonb_array_elements_text' },
+{ oid => '3207', descr => 'length of jsonb array',
+ proname => 'jsonb_array_length', prorettype => 'int4', proargtypes => 'jsonb',
+ prosrc => 'jsonb_array_length' },
+{ oid => '3931', descr => 'get jsonb object keys',
+ proname => 'jsonb_object_keys', prorows => '100', proretset => 't',
+ prorettype => 'text', proargtypes => 'jsonb', prosrc => 'jsonb_object_keys' },
+{ oid => '3208', descr => 'key value pairs of a jsonb object',
+ proname => 'jsonb_each', prorows => '100', proretset => 't',
+ prorettype => 'record', proargtypes => 'jsonb',
+ proallargtypes => '{jsonb,text,jsonb}', proargmodes => '{i,o,o}',
+ proargnames => '{from_json,key,value}', prosrc => 'jsonb_each' },
+{ oid => '3932', descr => 'key value pairs of a jsonb object',
+ proname => 'jsonb_each_text', prorows => '100', proretset => 't',
+ prorettype => 'record', proargtypes => 'jsonb',
+ proallargtypes => '{jsonb,text,text}', proargmodes => '{i,o,o}',
+ proargnames => '{from_json,key,value}', prosrc => 'jsonb_each_text' },
+{ oid => '3209', descr => 'get record fields from a jsonb object',
+ proname => 'jsonb_populate_record', proisstrict => 'f', provolatile => 's',
+ prorettype => 'anyelement', proargtypes => 'anyelement jsonb',
+ prosrc => 'jsonb_populate_record' },
+{ oid => '3475',
+ descr => 'get set of records with fields from a jsonb array of objects',
+ proname => 'jsonb_populate_recordset', prorows => '100', proisstrict => 'f',
+ proretset => 't', provolatile => 's', prorettype => 'anyelement',
+ proargtypes => 'anyelement jsonb', prosrc => 'jsonb_populate_recordset' },
+{ oid => '3490', descr => 'get record fields from a jsonb object',
+ proname => 'jsonb_to_record', provolatile => 's', prorettype => 'record',
+ proargtypes => 'jsonb', prosrc => 'jsonb_to_record' },
+{ oid => '3491',
+ descr => 'get set of records with fields from a jsonb array of objects',
+ proname => 'jsonb_to_recordset', prorows => '100', proisstrict => 'f',
+ proretset => 't', provolatile => 's', prorettype => 'record',
+ proargtypes => 'jsonb', prosrc => 'jsonb_to_recordset' },
+{ oid => '3210', descr => 'get the type of a jsonb value',
+ proname => 'jsonb_typeof', prorettype => 'text', proargtypes => 'jsonb',
+ prosrc => 'jsonb_typeof' },
+{ oid => '4038',
+ proname => 'jsonb_ne', prorettype => 'bool', proargtypes => 'jsonb jsonb',
+ prosrc => 'jsonb_ne' },
+{ oid => '4039',
+ proname => 'jsonb_lt', prorettype => 'bool', proargtypes => 'jsonb jsonb',
+ prosrc => 'jsonb_lt' },
+{ oid => '4040',
+ proname => 'jsonb_gt', prorettype => 'bool', proargtypes => 'jsonb jsonb',
+ prosrc => 'jsonb_gt' },
+{ oid => '4041',
+ proname => 'jsonb_le', prorettype => 'bool', proargtypes => 'jsonb jsonb',
+ prosrc => 'jsonb_le' },
+{ oid => '4042',
+ proname => 'jsonb_ge', prorettype => 'bool', proargtypes => 'jsonb jsonb',
+ prosrc => 'jsonb_ge' },
+{ oid => '4043',
+ proname => 'jsonb_eq', prorettype => 'bool', proargtypes => 'jsonb jsonb',
+ prosrc => 'jsonb_eq' },
+{ oid => '4044', descr => 'less-equal-greater',
+ proname => 'jsonb_cmp', prorettype => 'int4', proargtypes => 'jsonb jsonb',
+ prosrc => 'jsonb_cmp' },
+{ oid => '4045', descr => 'hash',
+ proname => 'jsonb_hash', prorettype => 'int4', proargtypes => 'jsonb',
+ prosrc => 'jsonb_hash' },
+{ oid => '3416', descr => 'hash',
+ proname => 'jsonb_hash_extended', prorettype => 'int8',
+ proargtypes => 'jsonb int8', prosrc => 'jsonb_hash_extended' },
+{ oid => '4046',
+ proname => 'jsonb_contains', prorettype => 'bool',
+ proargtypes => 'jsonb jsonb', prosrc => 'jsonb_contains' },
+{ oid => '4047',
+ proname => 'jsonb_exists', prorettype => 'bool', proargtypes => 'jsonb text',
+ prosrc => 'jsonb_exists' },
+{ oid => '4048',
+ proname => 'jsonb_exists_any', prorettype => 'bool',
+ proargtypes => 'jsonb _text', prosrc => 'jsonb_exists_any' },
+{ oid => '4049',
+ proname => 'jsonb_exists_all', prorettype => 'bool',
+ proargtypes => 'jsonb _text', prosrc => 'jsonb_exists_all' },
+{ oid => '4050',
+ proname => 'jsonb_contained', prorettype => 'bool',
+ proargtypes => 'jsonb jsonb', prosrc => 'jsonb_contained' },
+{ oid => '3480', descr => 'GIN support',
+ proname => 'gin_compare_jsonb', prorettype => 'int4',
+ proargtypes => 'text text', prosrc => 'gin_compare_jsonb' },
+{ oid => '3482', descr => 'GIN support',
+ proname => 'gin_extract_jsonb', prorettype => 'internal',
+ proargtypes => 'jsonb internal internal', prosrc => 'gin_extract_jsonb' },
+{ oid => '3483', descr => 'GIN support',
+ proname => 'gin_extract_jsonb_query', prorettype => 'internal',
+ proargtypes => 'jsonb internal int2 internal internal internal internal',
+ prosrc => 'gin_extract_jsonb_query' },
+{ oid => '3484', descr => 'GIN support',
+ proname => 'gin_consistent_jsonb', prorettype => 'bool',
+ proargtypes => 'internal int2 jsonb int4 internal internal internal internal',
+ prosrc => 'gin_consistent_jsonb' },
+{ oid => '3488', descr => 'GIN support',
+ proname => 'gin_triconsistent_jsonb', prorettype => 'char',
+ proargtypes => 'internal int2 jsonb int4 internal internal internal',
+ prosrc => 'gin_triconsistent_jsonb' },
+{ oid => '3485', descr => 'GIN support',
+ proname => 'gin_extract_jsonb_path', prorettype => 'internal',
+ proargtypes => 'jsonb internal internal',
+ prosrc => 'gin_extract_jsonb_path' },
+{ oid => '3486', descr => 'GIN support',
+ proname => 'gin_extract_jsonb_query_path', prorettype => 'internal',
+ proargtypes => 'jsonb internal int2 internal internal internal internal',
+ prosrc => 'gin_extract_jsonb_query_path' },
+{ oid => '3487', descr => 'GIN support',
+ proname => 'gin_consistent_jsonb_path', prorettype => 'bool',
+ proargtypes => 'internal int2 jsonb int4 internal internal internal internal',
+ prosrc => 'gin_consistent_jsonb_path' },
+{ oid => '3489', descr => 'GIN support',
+ proname => 'gin_triconsistent_jsonb_path', prorettype => 'char',
+ proargtypes => 'internal int2 jsonb int4 internal internal internal',
+ prosrc => 'gin_triconsistent_jsonb_path' },
+{ oid => '3301',
+ proname => 'jsonb_concat', prorettype => 'jsonb',
+ proargtypes => 'jsonb jsonb', prosrc => 'jsonb_concat' },
+{ oid => '3302',
+ proname => 'jsonb_delete', prorettype => 'jsonb', proargtypes => 'jsonb text',
+ prosrc => 'jsonb_delete' },
+{ oid => '3303',
+ proname => 'jsonb_delete', prorettype => 'jsonb', proargtypes => 'jsonb int4',
+ prosrc => 'jsonb_delete_idx' },
+{ oid => '3343',
+ proname => 'jsonb_delete', provariadic => 'text', prorettype => 'jsonb',
+ proargtypes => 'jsonb _text', proallargtypes => '{jsonb,_text}',
+ proargmodes => '{i,v}', proargnames => '{from_json,path_elems}',
+ prosrc => 'jsonb_delete_array' },
+{ oid => '3304',
+ proname => 'jsonb_delete_path', prorettype => 'jsonb',
+ proargtypes => 'jsonb _text', prosrc => 'jsonb_delete_path' },
+{ oid => '5054', descr => 'Set part of a jsonb, handle NULL value',
+ proname => 'jsonb_set_lax', proisstrict => 'f', prorettype => 'jsonb',
+ proargtypes => 'jsonb _text jsonb bool text', prosrc => 'jsonb_set_lax' },
+{ oid => '3305', descr => 'Set part of a jsonb',
+ proname => 'jsonb_set', prorettype => 'jsonb',
+ proargtypes => 'jsonb _text jsonb bool', prosrc => 'jsonb_set' },
+{ oid => '3306', descr => 'Indented text from jsonb',
+ proname => 'jsonb_pretty', prorettype => 'text', proargtypes => 'jsonb',
+ prosrc => 'jsonb_pretty' },
+{ oid => '3579', descr => 'Insert value into a jsonb',
+ proname => 'jsonb_insert', prorettype => 'jsonb',
+ proargtypes => 'jsonb _text jsonb bool', prosrc => 'jsonb_insert' },
+
+# jsonpath
+{ oid => '4001', descr => 'I/O',
+ proname => 'jsonpath_in', prorettype => 'jsonpath', proargtypes => 'cstring',
+ prosrc => 'jsonpath_in' },
+{ oid => '4002', descr => 'I/O',
+ proname => 'jsonpath_recv', prorettype => 'jsonpath',
+ proargtypes => 'internal', prosrc => 'jsonpath_recv' },
+{ oid => '4003', descr => 'I/O',
+ proname => 'jsonpath_out', prorettype => 'cstring', proargtypes => 'jsonpath',
+ prosrc => 'jsonpath_out' },
+{ oid => '4004', descr => 'I/O',
+ proname => 'jsonpath_send', prorettype => 'bytea', proargtypes => 'jsonpath',
+ prosrc => 'jsonpath_send' },
+
+{ oid => '4005', descr => 'jsonpath exists test',
+ proname => 'jsonb_path_exists', prorettype => 'bool',
+ proargtypes => 'jsonb jsonpath jsonb bool', prosrc => 'jsonb_path_exists' },
+{ oid => '4006', descr => 'jsonpath query',
+ proname => 'jsonb_path_query', prorows => '1000', proretset => 't',
+ prorettype => 'jsonb', proargtypes => 'jsonb jsonpath jsonb bool',
+ prosrc => 'jsonb_path_query' },
+{ oid => '4007', descr => 'jsonpath query wrapped into array',
+ proname => 'jsonb_path_query_array', prorettype => 'jsonb',
+ proargtypes => 'jsonb jsonpath jsonb bool',
+ prosrc => 'jsonb_path_query_array' },
+{ oid => '4008', descr => 'jsonpath query first item',
+ proname => 'jsonb_path_query_first', prorettype => 'jsonb',
+ proargtypes => 'jsonb jsonpath jsonb bool',
+ prosrc => 'jsonb_path_query_first' },
+{ oid => '4009', descr => 'jsonpath match',
+ proname => 'jsonb_path_match', prorettype => 'bool',
+ proargtypes => 'jsonb jsonpath jsonb bool', prosrc => 'jsonb_path_match' },
+
+{ oid => '1177', descr => 'jsonpath exists test with timezone',
+ proname => 'jsonb_path_exists_tz', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'jsonb jsonpath jsonb bool',
+ prosrc => 'jsonb_path_exists_tz' },
+{ oid => '1179', descr => 'jsonpath query with timezone',
+ proname => 'jsonb_path_query_tz', prorows => '1000', proretset => 't',
+ provolatile => 's', prorettype => 'jsonb',
+ proargtypes => 'jsonb jsonpath jsonb bool', prosrc => 'jsonb_path_query_tz' },
+{ oid => '1180', descr => 'jsonpath query wrapped into array with timezone',
+ proname => 'jsonb_path_query_array_tz', provolatile => 's',
+ prorettype => 'jsonb', proargtypes => 'jsonb jsonpath jsonb bool',
+ prosrc => 'jsonb_path_query_array_tz' },
+{ oid => '2023', descr => 'jsonpath query first item with timezone',
+ proname => 'jsonb_path_query_first_tz', provolatile => 's',
+ prorettype => 'jsonb', proargtypes => 'jsonb jsonpath jsonb bool',
+ prosrc => 'jsonb_path_query_first_tz' },
+{ oid => '2030', descr => 'jsonpath match with timezone',
+ proname => 'jsonb_path_match_tz', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'jsonb jsonpath jsonb bool', prosrc => 'jsonb_path_match_tz' },
+
+{ oid => '4010', descr => 'implementation of @? operator',
+ proname => 'jsonb_path_exists_opr', prorettype => 'bool',
+ proargtypes => 'jsonb jsonpath', prosrc => 'jsonb_path_exists_opr' },
+{ oid => '4011', descr => 'implementation of @@ operator',
+ proname => 'jsonb_path_match_opr', prorettype => 'bool',
+ proargtypes => 'jsonb jsonpath', prosrc => 'jsonb_path_match_opr' },
+
+# historical int8/txid_snapshot variants of xid8 functions
+{ oid => '2939', descr => 'I/O',
+ proname => 'txid_snapshot_in', prorettype => 'txid_snapshot',
+ proargtypes => 'cstring', prosrc => 'pg_snapshot_in' },
+{ oid => '2940', descr => 'I/O',
+ proname => 'txid_snapshot_out', prorettype => 'cstring',
+ proargtypes => 'txid_snapshot', prosrc => 'pg_snapshot_out' },
+{ oid => '2941', descr => 'I/O',
+ proname => 'txid_snapshot_recv', prorettype => 'txid_snapshot',
+ proargtypes => 'internal', prosrc => 'pg_snapshot_recv' },
+{ oid => '2942', descr => 'I/O',
+ proname => 'txid_snapshot_send', prorettype => 'bytea',
+ proargtypes => 'txid_snapshot', prosrc => 'pg_snapshot_send' },
+{ oid => '2943', descr => 'get current transaction ID',
+ proname => 'txid_current', provolatile => 's', proparallel => 'u',
+ prorettype => 'int8', proargtypes => '', prosrc => 'pg_current_xact_id' },
+{ oid => '3348', descr => 'get current transaction ID',
+ proname => 'txid_current_if_assigned', provolatile => 's', proparallel => 'u',
+ prorettype => 'int8', proargtypes => '',
+ prosrc => 'pg_current_xact_id_if_assigned' },
+{ oid => '2944', descr => 'get current snapshot',
+ proname => 'txid_current_snapshot', provolatile => 's',
+ prorettype => 'txid_snapshot', proargtypes => '',
+ prosrc => 'pg_current_snapshot' },
+{ oid => '2945', descr => 'get xmin of snapshot',
+ proname => 'txid_snapshot_xmin', prorettype => 'int8',
+ proargtypes => 'txid_snapshot', prosrc => 'pg_snapshot_xmin' },
+{ oid => '2946', descr => 'get xmax of snapshot',
+ proname => 'txid_snapshot_xmax', prorettype => 'int8',
+ proargtypes => 'txid_snapshot', prosrc => 'pg_snapshot_xmax' },
+{ oid => '2947', descr => 'get set of in-progress txids in snapshot',
+ proname => 'txid_snapshot_xip', prorows => '50', proretset => 't',
+ prorettype => 'int8', proargtypes => 'txid_snapshot',
+ prosrc => 'pg_snapshot_xip' },
+{ oid => '2948', descr => 'is txid visible in snapshot?',
+ proname => 'txid_visible_in_snapshot', prorettype => 'bool',
+ proargtypes => 'int8 txid_snapshot', prosrc => 'pg_visible_in_snapshot' },
+{ oid => '3360', descr => 'commit status of transaction',
+ proname => 'txid_status', provolatile => 'v', prorettype => 'text',
+ proargtypes => 'int8', prosrc => 'pg_xact_status' },
+
+# pg_snapshot functions
+{ oid => '5055', descr => 'I/O',
+ proname => 'pg_snapshot_in', prorettype => 'pg_snapshot',
+ proargtypes => 'cstring', prosrc => 'pg_snapshot_in' },
+{ oid => '5056', descr => 'I/O',
+ proname => 'pg_snapshot_out', prorettype => 'cstring',
+ proargtypes => 'pg_snapshot', prosrc => 'pg_snapshot_out' },
+{ oid => '5057', descr => 'I/O',
+ proname => 'pg_snapshot_recv', prorettype => 'pg_snapshot',
+ proargtypes => 'internal', prosrc => 'pg_snapshot_recv' },
+{ oid => '5058', descr => 'I/O',
+ proname => 'pg_snapshot_send', prorettype => 'bytea',
+ proargtypes => 'pg_snapshot', prosrc => 'pg_snapshot_send' },
+{ oid => '5061', descr => 'get current snapshot',
+ proname => 'pg_current_snapshot', provolatile => 's',
+ prorettype => 'pg_snapshot', proargtypes => '',
+ prosrc => 'pg_current_snapshot' },
+{ oid => '5062', descr => 'get xmin of snapshot',
+ proname => 'pg_snapshot_xmin', prorettype => 'xid8',
+ proargtypes => 'pg_snapshot', prosrc => 'pg_snapshot_xmin' },
+{ oid => '5063', descr => 'get xmax of snapshot',
+ proname => 'pg_snapshot_xmax', prorettype => 'xid8',
+ proargtypes => 'pg_snapshot', prosrc => 'pg_snapshot_xmax' },
+{ oid => '5064', descr => 'get set of in-progress transactions in snapshot',
+ proname => 'pg_snapshot_xip', prorows => '50', proretset => 't',
+ prorettype => 'xid8', proargtypes => 'pg_snapshot',
+ prosrc => 'pg_snapshot_xip' },
+{ oid => '5065', descr => 'is xid8 visible in snapshot?',
+ proname => 'pg_visible_in_snapshot', prorettype => 'bool',
+ proargtypes => 'xid8 pg_snapshot', prosrc => 'pg_visible_in_snapshot' },
+
+# transaction ID and status functions
+{ oid => '5059', descr => 'get current transaction ID',
+ proname => 'pg_current_xact_id', provolatile => 's', proparallel => 'u',
+ prorettype => 'xid8', proargtypes => '', prosrc => 'pg_current_xact_id' },
+{ oid => '5060', descr => 'get current transaction ID',
+ proname => 'pg_current_xact_id_if_assigned', provolatile => 's',
+ proparallel => 'u', prorettype => 'xid8', proargtypes => '',
+ prosrc => 'pg_current_xact_id_if_assigned' },
+{ oid => '5066', descr => 'commit status of transaction',
+ proname => 'pg_xact_status', provolatile => 'v', prorettype => 'text',
+ proargtypes => 'xid8', prosrc => 'pg_xact_status' },
+
+# record comparison using normal comparison rules
+{ oid => '2981',
+ proname => 'record_eq', prorettype => 'bool', proargtypes => 'record record',
+ prosrc => 'record_eq' },
+{ oid => '2982',
+ proname => 'record_ne', prorettype => 'bool', proargtypes => 'record record',
+ prosrc => 'record_ne' },
+{ oid => '2983',
+ proname => 'record_lt', prorettype => 'bool', proargtypes => 'record record',
+ prosrc => 'record_lt' },
+{ oid => '2984',
+ proname => 'record_gt', prorettype => 'bool', proargtypes => 'record record',
+ prosrc => 'record_gt' },
+{ oid => '2985',
+ proname => 'record_le', prorettype => 'bool', proargtypes => 'record record',
+ prosrc => 'record_le' },
+{ oid => '2986',
+ proname => 'record_ge', prorettype => 'bool', proargtypes => 'record record',
+ prosrc => 'record_ge' },
+{ oid => '2987', descr => 'less-equal-greater',
+ proname => 'btrecordcmp', prorettype => 'int4',
+ proargtypes => 'record record', prosrc => 'btrecordcmp' },
+
+# record comparison using raw byte images
+{ oid => '3181',
+ proname => 'record_image_eq', prorettype => 'bool',
+ proargtypes => 'record record', prosrc => 'record_image_eq' },
+{ oid => '3182',
+ proname => 'record_image_ne', prorettype => 'bool',
+ proargtypes => 'record record', prosrc => 'record_image_ne' },
+{ oid => '3183',
+ proname => 'record_image_lt', prorettype => 'bool',
+ proargtypes => 'record record', prosrc => 'record_image_lt' },
+{ oid => '3184',
+ proname => 'record_image_gt', prorettype => 'bool',
+ proargtypes => 'record record', prosrc => 'record_image_gt' },
+{ oid => '3185',
+ proname => 'record_image_le', prorettype => 'bool',
+ proargtypes => 'record record', prosrc => 'record_image_le' },
+{ oid => '3186',
+ proname => 'record_image_ge', prorettype => 'bool',
+ proargtypes => 'record record', prosrc => 'record_image_ge' },
+{ oid => '3187', descr => 'less-equal-greater based on byte images',
+ proname => 'btrecordimagecmp', prorettype => 'int4',
+ proargtypes => 'record record', prosrc => 'btrecordimagecmp' },
+{ oid => '5051', descr => 'equal image',
+ proname => 'btequalimage', prorettype => 'bool', proargtypes => 'oid',
+ prosrc => 'btequalimage' },
+
+# Extensions
+{ oid => '3082', descr => 'list available extensions',
+ proname => 'pg_available_extensions', procost => '10', prorows => '100',
+ proretset => 't', provolatile => 's', prorettype => 'record',
+ proargtypes => '', proallargtypes => '{name,text,text}',
+ proargmodes => '{o,o,o}', proargnames => '{name,default_version,comment}',
+ prosrc => 'pg_available_extensions' },
+{ oid => '3083', descr => 'list available extension versions',
+ proname => 'pg_available_extension_versions', procost => '10',
+ prorows => '100', proretset => 't', provolatile => 's',
+ prorettype => 'record', proargtypes => '',
+ proallargtypes => '{name,text,bool,bool,bool,name,_name,text}',
+ proargmodes => '{o,o,o,o,o,o,o,o}',
+ proargnames => '{name,version,superuser,trusted,relocatable,schema,requires,comment}',
+ prosrc => 'pg_available_extension_versions' },
+{ oid => '3084', descr => 'list an extension\'s version update paths',
+ proname => 'pg_extension_update_paths', procost => '10', prorows => '100',
+ proretset => 't', provolatile => 's', prorettype => 'record',
+ proargtypes => 'name', proallargtypes => '{name,text,text,text}',
+ proargmodes => '{i,o,o,o}', proargnames => '{name,source,target,path}',
+ prosrc => 'pg_extension_update_paths' },
+{ oid => '3086',
+ descr => 'flag an extension\'s table contents to be emitted by pg_dump',
+ proname => 'pg_extension_config_dump', provolatile => 'v', proparallel => 'u',
+ prorettype => 'void', proargtypes => 'regclass text',
+ prosrc => 'pg_extension_config_dump' },
+
+# SQL-spec window functions
+{ oid => '3100', descr => 'row number within partition',
+ proname => 'row_number', prokind => 'w', proisstrict => 'f',
+ prorettype => 'int8', proargtypes => '', prosrc => 'window_row_number' },
+{ oid => '3101', descr => 'integer rank with gaps',
+ proname => 'rank', prokind => 'w', proisstrict => 'f', prorettype => 'int8',
+ proargtypes => '', prosrc => 'window_rank' },
+{ oid => '3102', descr => 'integer rank without gaps',
+ proname => 'dense_rank', prokind => 'w', proisstrict => 'f',
+ prorettype => 'int8', proargtypes => '', prosrc => 'window_dense_rank' },
+{ oid => '3103', descr => 'fractional rank within partition',
+ proname => 'percent_rank', prokind => 'w', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => '', prosrc => 'window_percent_rank' },
+{ oid => '3104', descr => 'fractional row number within partition',
+ proname => 'cume_dist', prokind => 'w', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => '', prosrc => 'window_cume_dist' },
+{ oid => '3105', descr => 'split rows into N groups',
+ proname => 'ntile', prokind => 'w', prorettype => 'int4',
+ proargtypes => 'int4', prosrc => 'window_ntile' },
+{ oid => '3106', descr => 'fetch the preceding row value',
+ proname => 'lag', prokind => 'w', prorettype => 'anyelement',
+ proargtypes => 'anyelement', prosrc => 'window_lag' },
+{ oid => '3107', descr => 'fetch the Nth preceding row value',
+ proname => 'lag', prokind => 'w', prorettype => 'anyelement',
+ proargtypes => 'anyelement int4', prosrc => 'window_lag_with_offset' },
+{ oid => '3108', descr => 'fetch the Nth preceding row value with default',
+ proname => 'lag', prokind => 'w', prorettype => 'anyelement',
+ proargtypes => 'anyelement int4 anyelement',
+ prosrc => 'window_lag_with_offset_and_default' },
+{ oid => '3109', descr => 'fetch the following row value',
+ proname => 'lead', prokind => 'w', prorettype => 'anyelement',
+ proargtypes => 'anyelement', prosrc => 'window_lead' },
+{ oid => '3110', descr => 'fetch the Nth following row value',
+ proname => 'lead', prokind => 'w', prorettype => 'anyelement',
+ proargtypes => 'anyelement int4', prosrc => 'window_lead_with_offset' },
+{ oid => '3111', descr => 'fetch the Nth following row value with default',
+ proname => 'lead', prokind => 'w', prorettype => 'anyelement',
+ proargtypes => 'anyelement int4 anyelement',
+ prosrc => 'window_lead_with_offset_and_default' },
+{ oid => '3112', descr => 'fetch the first row value',
+ proname => 'first_value', prokind => 'w', prorettype => 'anyelement',
+ proargtypes => 'anyelement', prosrc => 'window_first_value' },
+{ oid => '3113', descr => 'fetch the last row value',
+ proname => 'last_value', prokind => 'w', prorettype => 'anyelement',
+ proargtypes => 'anyelement', prosrc => 'window_last_value' },
+{ oid => '3114', descr => 'fetch the Nth row value',
+ proname => 'nth_value', prokind => 'w', prorettype => 'anyelement',
+ proargtypes => 'anyelement int4', prosrc => 'window_nth_value' },
+
+# functions for range types
+{ oid => '3832', descr => 'I/O',
+ proname => 'anyrange_in', provolatile => 's', prorettype => 'anyrange',
+ proargtypes => 'cstring oid int4', prosrc => 'anyrange_in' },
+{ oid => '3833', descr => 'I/O',
+ proname => 'anyrange_out', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'anyrange', prosrc => 'anyrange_out' },
+{ oid => '3834', descr => 'I/O',
+ proname => 'range_in', provolatile => 's', prorettype => 'anyrange',
+ proargtypes => 'cstring oid int4', prosrc => 'range_in' },
+{ oid => '3835', descr => 'I/O',
+ proname => 'range_out', provolatile => 's', prorettype => 'cstring',
+ proargtypes => 'anyrange', prosrc => 'range_out' },
+{ oid => '3836', descr => 'I/O',
+ proname => 'range_recv', provolatile => 's', prorettype => 'anyrange',
+ proargtypes => 'internal oid int4', prosrc => 'range_recv' },
+{ oid => '3837', descr => 'I/O',
+ proname => 'range_send', provolatile => 's', prorettype => 'bytea',
+ proargtypes => 'anyrange', prosrc => 'range_send' },
+{ oid => '3848', descr => 'lower bound of range',
+ proname => 'lower', prorettype => 'anyelement', proargtypes => 'anyrange',
+ prosrc => 'range_lower' },
+{ oid => '3849', descr => 'upper bound of range',
+ proname => 'upper', prorettype => 'anyelement', proargtypes => 'anyrange',
+ prosrc => 'range_upper' },
+{ oid => '3850', descr => 'is the range empty?',
+ proname => 'isempty', prorettype => 'bool', proargtypes => 'anyrange',
+ prosrc => 'range_empty' },
+{ oid => '3851', descr => 'is the range\'s lower bound inclusive?',
+ proname => 'lower_inc', prorettype => 'bool', proargtypes => 'anyrange',
+ prosrc => 'range_lower_inc' },
+{ oid => '3852', descr => 'is the range\'s upper bound inclusive?',
+ proname => 'upper_inc', prorettype => 'bool', proargtypes => 'anyrange',
+ prosrc => 'range_upper_inc' },
+{ oid => '3853', descr => 'is the range\'s lower bound infinite?',
+ proname => 'lower_inf', prorettype => 'bool', proargtypes => 'anyrange',
+ prosrc => 'range_lower_inf' },
+{ oid => '3854', descr => 'is the range\'s upper bound infinite?',
+ proname => 'upper_inf', prorettype => 'bool', proargtypes => 'anyrange',
+ prosrc => 'range_upper_inf' },
+{ oid => '3855',
+ proname => 'range_eq', prorettype => 'bool',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_eq' },
+{ oid => '3856',
+ proname => 'range_ne', prorettype => 'bool',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_ne' },
+{ oid => '3857',
+ proname => 'range_overlaps', prorettype => 'bool',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_overlaps' },
+{ oid => '3858',
+ proname => 'range_contains_elem', prorettype => 'bool',
+ proargtypes => 'anyrange anyelement', prosrc => 'range_contains_elem' },
+{ oid => '3859',
+ proname => 'range_contains', prorettype => 'bool',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_contains' },
+{ oid => '3860',
+ proname => 'elem_contained_by_range', prorettype => 'bool',
+ proargtypes => 'anyelement anyrange', prosrc => 'elem_contained_by_range' },
+{ oid => '3861',
+ proname => 'range_contained_by', prorettype => 'bool',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_contained_by' },
+{ oid => '3862',
+ proname => 'range_adjacent', prorettype => 'bool',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_adjacent' },
+{ oid => '3863',
+ proname => 'range_before', prorettype => 'bool',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_before' },
+{ oid => '3864',
+ proname => 'range_after', prorettype => 'bool',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_after' },
+{ oid => '3865',
+ proname => 'range_overleft', prorettype => 'bool',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_overleft' },
+{ oid => '3866',
+ proname => 'range_overright', prorettype => 'bool',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_overright' },
+{ oid => '3867',
+ proname => 'range_union', prorettype => 'anyrange',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_union' },
+{ oid => '4057',
+ descr => 'the smallest range which includes both of the given ranges',
+ proname => 'range_merge', prorettype => 'anyrange',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_merge' },
+{ oid => '3868',
+ proname => 'range_intersect', prorettype => 'anyrange',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_intersect' },
+{ oid => '3869',
+ proname => 'range_minus', prorettype => 'anyrange',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_minus' },
+{ oid => '3870', descr => 'less-equal-greater',
+ proname => 'range_cmp', prorettype => 'int4',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_cmp' },
+{ oid => '3871',
+ proname => 'range_lt', prorettype => 'bool',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_lt' },
+{ oid => '3872',
+ proname => 'range_le', prorettype => 'bool',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_le' },
+{ oid => '3873',
+ proname => 'range_ge', prorettype => 'bool',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_ge' },
+{ oid => '3874',
+ proname => 'range_gt', prorettype => 'bool',
+ proargtypes => 'anyrange anyrange', prosrc => 'range_gt' },
+{ oid => '3875', descr => 'GiST support',
+ proname => 'range_gist_consistent', prorettype => 'bool',
+ proargtypes => 'internal anyrange int2 oid internal',
+ prosrc => 'range_gist_consistent' },
+{ oid => '3876', descr => 'GiST support',
+ proname => 'range_gist_union', prorettype => 'anyrange',
+ proargtypes => 'internal internal', prosrc => 'range_gist_union' },
+{ oid => '3879', descr => 'GiST support',
+ proname => 'range_gist_penalty', prorettype => 'internal',
+ proargtypes => 'internal internal internal', prosrc => 'range_gist_penalty' },
+{ oid => '3880', descr => 'GiST support',
+ proname => 'range_gist_picksplit', prorettype => 'internal',
+ proargtypes => 'internal internal', prosrc => 'range_gist_picksplit' },
+{ oid => '3881', descr => 'GiST support',
+ proname => 'range_gist_same', prorettype => 'internal',
+ proargtypes => 'anyrange anyrange internal', prosrc => 'range_gist_same' },
+{ oid => '3902', descr => 'hash a range',
+ proname => 'hash_range', prorettype => 'int4', proargtypes => 'anyrange',
+ prosrc => 'hash_range' },
+{ oid => '3417', descr => 'hash a range',
+ proname => 'hash_range_extended', prorettype => 'int8',
+ proargtypes => 'anyrange int8', prosrc => 'hash_range_extended' },
+{ oid => '3916', descr => 'range typanalyze',
+ proname => 'range_typanalyze', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'internal', prosrc => 'range_typanalyze' },
+{ oid => '3169', descr => 'restriction selectivity for range operators',
+ proname => 'rangesel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'rangesel' },
+
+{ oid => '3914', descr => 'convert an int4 range to canonical form',
+ proname => 'int4range_canonical', prorettype => 'int4range',
+ proargtypes => 'int4range', prosrc => 'int4range_canonical' },
+{ oid => '3928', descr => 'convert an int8 range to canonical form',
+ proname => 'int8range_canonical', prorettype => 'int8range',
+ proargtypes => 'int8range', prosrc => 'int8range_canonical' },
+{ oid => '3915', descr => 'convert a date range to canonical form',
+ proname => 'daterange_canonical', prorettype => 'daterange',
+ proargtypes => 'daterange', prosrc => 'daterange_canonical' },
+{ oid => '3922', descr => 'float8 difference of two int4 values',
+ proname => 'int4range_subdiff', prorettype => 'float8',
+ proargtypes => 'int4 int4', prosrc => 'int4range_subdiff' },
+{ oid => '3923', descr => 'float8 difference of two int8 values',
+ proname => 'int8range_subdiff', prorettype => 'float8',
+ proargtypes => 'int8 int8', prosrc => 'int8range_subdiff' },
+{ oid => '3924', descr => 'float8 difference of two numeric values',
+ proname => 'numrange_subdiff', prorettype => 'float8',
+ proargtypes => 'numeric numeric', prosrc => 'numrange_subdiff' },
+{ oid => '3925', descr => 'float8 difference of two date values',
+ proname => 'daterange_subdiff', prorettype => 'float8',
+ proargtypes => 'date date', prosrc => 'daterange_subdiff' },
+{ oid => '3929', descr => 'float8 difference of two timestamp values',
+ proname => 'tsrange_subdiff', prorettype => 'float8',
+ proargtypes => 'timestamp timestamp', prosrc => 'tsrange_subdiff' },
+{ oid => '3930',
+ descr => 'float8 difference of two timestamp with time zone values',
+ proname => 'tstzrange_subdiff', prorettype => 'float8',
+ proargtypes => 'timestamptz timestamptz', prosrc => 'tstzrange_subdiff' },
+
+{ oid => '3840', descr => 'int4range constructor',
+ proname => 'int4range', proisstrict => 'f', prorettype => 'int4range',
+ proargtypes => 'int4 int4', prosrc => 'range_constructor2' },
+{ oid => '3841', descr => 'int4range constructor',
+ proname => 'int4range', proisstrict => 'f', prorettype => 'int4range',
+ proargtypes => 'int4 int4 text', prosrc => 'range_constructor3' },
+{ oid => '3844', descr => 'numrange constructor',
+ proname => 'numrange', proisstrict => 'f', prorettype => 'numrange',
+ proargtypes => 'numeric numeric', prosrc => 'range_constructor2' },
+{ oid => '3845', descr => 'numrange constructor',
+ proname => 'numrange', proisstrict => 'f', prorettype => 'numrange',
+ proargtypes => 'numeric numeric text', prosrc => 'range_constructor3' },
+{ oid => '3933', descr => 'tsrange constructor',
+ proname => 'tsrange', proisstrict => 'f', prorettype => 'tsrange',
+ proargtypes => 'timestamp timestamp', prosrc => 'range_constructor2' },
+{ oid => '3934', descr => 'tsrange constructor',
+ proname => 'tsrange', proisstrict => 'f', prorettype => 'tsrange',
+ proargtypes => 'timestamp timestamp text', prosrc => 'range_constructor3' },
+{ oid => '3937', descr => 'tstzrange constructor',
+ proname => 'tstzrange', proisstrict => 'f', prorettype => 'tstzrange',
+ proargtypes => 'timestamptz timestamptz', prosrc => 'range_constructor2' },
+{ oid => '3938', descr => 'tstzrange constructor',
+ proname => 'tstzrange', proisstrict => 'f', prorettype => 'tstzrange',
+ proargtypes => 'timestamptz timestamptz text',
+ prosrc => 'range_constructor3' },
+{ oid => '3941', descr => 'daterange constructor',
+ proname => 'daterange', proisstrict => 'f', prorettype => 'daterange',
+ proargtypes => 'date date', prosrc => 'range_constructor2' },
+{ oid => '3942', descr => 'daterange constructor',
+ proname => 'daterange', proisstrict => 'f', prorettype => 'daterange',
+ proargtypes => 'date date text', prosrc => 'range_constructor3' },
+{ oid => '3945', descr => 'int8range constructor',
+ proname => 'int8range', proisstrict => 'f', prorettype => 'int8range',
+ proargtypes => 'int8 int8', prosrc => 'range_constructor2' },
+{ oid => '3946', descr => 'int8range constructor',
+ proname => 'int8range', proisstrict => 'f', prorettype => 'int8range',
+ proargtypes => 'int8 int8 text', prosrc => 'range_constructor3' },
+
+# date, time, timestamp constructors
+{ oid => '3846', descr => 'construct date',
+ proname => 'make_date', prorettype => 'date', proargtypes => 'int4 int4 int4',
+ proargnames => '{year,month,day}', prosrc => 'make_date' },
+{ oid => '3847', descr => 'construct time',
+ proname => 'make_time', prorettype => 'time',
+ proargtypes => 'int4 int4 float8', proargnames => '{hour,min,sec}',
+ prosrc => 'make_time' },
+{ oid => '3461', descr => 'construct timestamp',
+ proname => 'make_timestamp', prorettype => 'timestamp',
+ proargtypes => 'int4 int4 int4 int4 int4 float8',
+ proargnames => '{year,month,mday,hour,min,sec}', prosrc => 'make_timestamp' },
+{ oid => '3462', descr => 'construct timestamp with time zone',
+ proname => 'make_timestamptz', provolatile => 's',
+ prorettype => 'timestamptz', proargtypes => 'int4 int4 int4 int4 int4 float8',
+ proargnames => '{year,month,mday,hour,min,sec}',
+ prosrc => 'make_timestamptz' },
+{ oid => '3463', descr => 'construct timestamp with time zone',
+ proname => 'make_timestamptz', provolatile => 's',
+ prorettype => 'timestamptz',
+ proargtypes => 'int4 int4 int4 int4 int4 float8 text',
+ proargnames => '{year,month,mday,hour,min,sec,timezone}',
+ prosrc => 'make_timestamptz_at_timezone' },
+{ oid => '3464', descr => 'construct interval',
+ proname => 'make_interval', prorettype => 'interval',
+ proargtypes => 'int4 int4 int4 int4 int4 int4 float8',
+ proargnames => '{years,months,weeks,days,hours,mins,secs}',
+ prosrc => 'make_interval' },
+
+# spgist opclasses
+{ oid => '4018', descr => 'SP-GiST support for quad tree over point',
+ proname => 'spg_quad_config', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_quad_config' },
+{ oid => '4019', descr => 'SP-GiST support for quad tree over point',
+ proname => 'spg_quad_choose', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_quad_choose' },
+{ oid => '4020', descr => 'SP-GiST support for quad tree over point',
+ proname => 'spg_quad_picksplit', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_quad_picksplit' },
+{ oid => '4021', descr => 'SP-GiST support for quad tree over point',
+ proname => 'spg_quad_inner_consistent', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_quad_inner_consistent' },
+{ oid => '4022',
+ descr => 'SP-GiST support for quad tree and k-d tree over point',
+ proname => 'spg_quad_leaf_consistent', prorettype => 'bool',
+ proargtypes => 'internal internal', prosrc => 'spg_quad_leaf_consistent' },
+
+{ oid => '4023', descr => 'SP-GiST support for k-d tree over point',
+ proname => 'spg_kd_config', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_kd_config' },
+{ oid => '4024', descr => 'SP-GiST support for k-d tree over point',
+ proname => 'spg_kd_choose', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_kd_choose' },
+{ oid => '4025', descr => 'SP-GiST support for k-d tree over point',
+ proname => 'spg_kd_picksplit', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_kd_picksplit' },
+{ oid => '4026', descr => 'SP-GiST support for k-d tree over point',
+ proname => 'spg_kd_inner_consistent', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_kd_inner_consistent' },
+
+{ oid => '4027', descr => 'SP-GiST support for radix tree over text',
+ proname => 'spg_text_config', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_text_config' },
+{ oid => '4028', descr => 'SP-GiST support for radix tree over text',
+ proname => 'spg_text_choose', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_text_choose' },
+{ oid => '4029', descr => 'SP-GiST support for radix tree over text',
+ proname => 'spg_text_picksplit', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_text_picksplit' },
+{ oid => '4030', descr => 'SP-GiST support for radix tree over text',
+ proname => 'spg_text_inner_consistent', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_text_inner_consistent' },
+{ oid => '4031', descr => 'SP-GiST support for radix tree over text',
+ proname => 'spg_text_leaf_consistent', prorettype => 'bool',
+ proargtypes => 'internal internal', prosrc => 'spg_text_leaf_consistent' },
+
+{ oid => '3469', descr => 'SP-GiST support for quad tree over range',
+ proname => 'spg_range_quad_config', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_range_quad_config' },
+{ oid => '3470', descr => 'SP-GiST support for quad tree over range',
+ proname => 'spg_range_quad_choose', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_range_quad_choose' },
+{ oid => '3471', descr => 'SP-GiST support for quad tree over range',
+ proname => 'spg_range_quad_picksplit', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_range_quad_picksplit' },
+{ oid => '3472', descr => 'SP-GiST support for quad tree over range',
+ proname => 'spg_range_quad_inner_consistent', prorettype => 'void',
+ proargtypes => 'internal internal',
+ prosrc => 'spg_range_quad_inner_consistent' },
+{ oid => '3473', descr => 'SP-GiST support for quad tree over range',
+ proname => 'spg_range_quad_leaf_consistent', prorettype => 'bool',
+ proargtypes => 'internal internal',
+ prosrc => 'spg_range_quad_leaf_consistent' },
+
+{ oid => '5012', descr => 'SP-GiST support for quad tree over box',
+ proname => 'spg_box_quad_config', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_box_quad_config' },
+{ oid => '5013', descr => 'SP-GiST support for quad tree over box',
+ proname => 'spg_box_quad_choose', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_box_quad_choose' },
+{ oid => '5014', descr => 'SP-GiST support for quad tree over box',
+ proname => 'spg_box_quad_picksplit', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_box_quad_picksplit' },
+{ oid => '5015', descr => 'SP-GiST support for quad tree over box',
+ proname => 'spg_box_quad_inner_consistent', prorettype => 'void',
+ proargtypes => 'internal internal',
+ prosrc => 'spg_box_quad_inner_consistent' },
+{ oid => '5016', descr => 'SP-GiST support for quad tree over box',
+ proname => 'spg_box_quad_leaf_consistent', prorettype => 'bool',
+ proargtypes => 'internal internal',
+ prosrc => 'spg_box_quad_leaf_consistent' },
+
+{ oid => '5010',
+ descr => 'SP-GiST support for quad tree over 2-D types represented by their bounding boxes',
+ proname => 'spg_bbox_quad_config', prorettype => 'void',
+ proargtypes => 'internal internal', prosrc => 'spg_bbox_quad_config' },
+{ oid => '5011', descr => 'SP-GiST support for quad tree over polygons',
+ proname => 'spg_poly_quad_compress', prorettype => 'box',
+ proargtypes => 'polygon', prosrc => 'spg_poly_quad_compress' },
+
+# replication slots
+{ oid => '3779', descr => 'create a physical replication slot',
+ proname => 'pg_create_physical_replication_slot', provolatile => 'v',
+ proparallel => 'u', prorettype => 'record', proargtypes => 'name bool bool',
+ proallargtypes => '{name,bool,bool,name,pg_lsn}',
+ proargmodes => '{i,i,i,o,o}',
+ proargnames => '{slot_name,immediately_reserve,temporary,slot_name,lsn}',
+ prosrc => 'pg_create_physical_replication_slot' },
+{ oid => '4220',
+ descr => 'copy a physical replication slot, changing temporality',
+ proname => 'pg_copy_physical_replication_slot', provolatile => 'v',
+ proparallel => 'u', prorettype => 'record', proargtypes => 'name name bool',
+ proallargtypes => '{name,name,bool,name,pg_lsn}',
+ proargmodes => '{i,i,i,o,o}',
+ proargnames => '{src_slot_name,dst_slot_name,temporary,slot_name,lsn}',
+ prosrc => 'pg_copy_physical_replication_slot_a' },
+{ oid => '4221', descr => 'copy a physical replication slot',
+ proname => 'pg_copy_physical_replication_slot', provolatile => 'v',
+ proparallel => 'u', prorettype => 'record', proargtypes => 'name name',
+ proallargtypes => '{name,name,name,pg_lsn}', proargmodes => '{i,i,o,o}',
+ proargnames => '{src_slot_name,dst_slot_name,slot_name,lsn}',
+ prosrc => 'pg_copy_physical_replication_slot_b' },
+{ oid => '3780', descr => 'drop a replication slot',
+ proname => 'pg_drop_replication_slot', provolatile => 'v', proparallel => 'u',
+ prorettype => 'void', proargtypes => 'name',
+ prosrc => 'pg_drop_replication_slot' },
+{ oid => '3781',
+ descr => 'information about replication slots currently in use',
+ proname => 'pg_get_replication_slots', prorows => '10', proisstrict => 'f',
+ proretset => 't', provolatile => 's', prorettype => 'record',
+ proargtypes => '',
+ proallargtypes => '{name,name,text,oid,bool,bool,int4,xid,xid,pg_lsn,pg_lsn,text,int8}',
+ proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{slot_name,plugin,slot_type,datoid,temporary,active,active_pid,xmin,catalog_xmin,restart_lsn,confirmed_flush_lsn,wal_status,safe_wal_size}',
+ prosrc => 'pg_get_replication_slots' },
+{ oid => '3786', descr => 'set up a logical replication slot',
+ proname => 'pg_create_logical_replication_slot', provolatile => 'v',
+ proparallel => 'u', prorettype => 'record', proargtypes => 'name name bool',
+ proallargtypes => '{name,name,bool,name,pg_lsn}',
+ proargmodes => '{i,i,i,o,o}',
+ proargnames => '{slot_name,plugin,temporary,slot_name,lsn}',
+ prosrc => 'pg_create_logical_replication_slot' },
+{ oid => '4222',
+ descr => 'copy a logical replication slot, changing temporality and plugin',
+ proname => 'pg_copy_logical_replication_slot', provolatile => 'v',
+ proparallel => 'u', prorettype => 'record',
+ proargtypes => 'name name bool name',
+ proallargtypes => '{name,name,bool,name,name,pg_lsn}',
+ proargmodes => '{i,i,i,i,o,o}',
+ proargnames => '{src_slot_name,dst_slot_name,temporary,plugin,slot_name,lsn}',
+ prosrc => 'pg_copy_logical_replication_slot_a' },
+{ oid => '4223',
+ descr => 'copy a logical replication slot, changing temporality',
+ proname => 'pg_copy_logical_replication_slot', provolatile => 'v',
+ proparallel => 'u', prorettype => 'record', proargtypes => 'name name bool',
+ proallargtypes => '{name,name,bool,name,pg_lsn}',
+ proargmodes => '{i,i,i,o,o}',
+ proargnames => '{src_slot_name,dst_slot_name,temporary,slot_name,lsn}',
+ prosrc => 'pg_copy_logical_replication_slot_b' },
+{ oid => '4224', descr => 'copy a logical replication slot',
+ proname => 'pg_copy_logical_replication_slot', provolatile => 'v',
+ proparallel => 'u', prorettype => 'record', proargtypes => 'name name',
+ proallargtypes => '{name,name,name,pg_lsn}', proargmodes => '{i,i,o,o}',
+ proargnames => '{src_slot_name,dst_slot_name,slot_name,lsn}',
+ prosrc => 'pg_copy_logical_replication_slot_c' },
+{ oid => '3782', descr => 'get changes from replication slot',
+ proname => 'pg_logical_slot_get_changes', procost => '1000',
+ prorows => '1000', provariadic => 'text', proisstrict => 'f',
+ proretset => 't', provolatile => 'v', proparallel => 'u',
+ prorettype => 'record', proargtypes => 'name pg_lsn int4 _text',
+ proallargtypes => '{name,pg_lsn,int4,_text,pg_lsn,xid,text}',
+ proargmodes => '{i,i,i,v,o,o,o}',
+ proargnames => '{slot_name,upto_lsn,upto_nchanges,options,lsn,xid,data}',
+ prosrc => 'pg_logical_slot_get_changes' },
+{ oid => '3783', descr => 'get binary changes from replication slot',
+ proname => 'pg_logical_slot_get_binary_changes', procost => '1000',
+ prorows => '1000', provariadic => 'text', proisstrict => 'f',
+ proretset => 't', provolatile => 'v', proparallel => 'u',
+ prorettype => 'record', proargtypes => 'name pg_lsn int4 _text',
+ proallargtypes => '{name,pg_lsn,int4,_text,pg_lsn,xid,bytea}',
+ proargmodes => '{i,i,i,v,o,o,o}',
+ proargnames => '{slot_name,upto_lsn,upto_nchanges,options,lsn,xid,data}',
+ prosrc => 'pg_logical_slot_get_binary_changes' },
+{ oid => '3784', descr => 'peek at changes from replication slot',
+ proname => 'pg_logical_slot_peek_changes', procost => '1000',
+ prorows => '1000', provariadic => 'text', proisstrict => 'f',
+ proretset => 't', provolatile => 'v', proparallel => 'u',
+ prorettype => 'record', proargtypes => 'name pg_lsn int4 _text',
+ proallargtypes => '{name,pg_lsn,int4,_text,pg_lsn,xid,text}',
+ proargmodes => '{i,i,i,v,o,o,o}',
+ proargnames => '{slot_name,upto_lsn,upto_nchanges,options,lsn,xid,data}',
+ prosrc => 'pg_logical_slot_peek_changes' },
+{ oid => '3785', descr => 'peek at binary changes from replication slot',
+ proname => 'pg_logical_slot_peek_binary_changes', procost => '1000',
+ prorows => '1000', provariadic => 'text', proisstrict => 'f',
+ proretset => 't', provolatile => 'v', proparallel => 'u',
+ prorettype => 'record', proargtypes => 'name pg_lsn int4 _text',
+ proallargtypes => '{name,pg_lsn,int4,_text,pg_lsn,xid,bytea}',
+ proargmodes => '{i,i,i,v,o,o,o}',
+ proargnames => '{slot_name,upto_lsn,upto_nchanges,options,lsn,xid,data}',
+ prosrc => 'pg_logical_slot_peek_binary_changes' },
+{ oid => '3878', descr => 'advance logical replication slot',
+ proname => 'pg_replication_slot_advance', provolatile => 'v',
+ proparallel => 'u', prorettype => 'record', proargtypes => 'name pg_lsn',
+ proallargtypes => '{name,pg_lsn,name,pg_lsn}', proargmodes => '{i,i,o,o}',
+ proargnames => '{slot_name,upto_lsn,slot_name,end_lsn}',
+ prosrc => 'pg_replication_slot_advance' },
+{ oid => '3577', descr => 'emit a textual logical decoding message',
+ proname => 'pg_logical_emit_message', provolatile => 'v', proparallel => 'u',
+ prorettype => 'pg_lsn', proargtypes => 'bool text text',
+ prosrc => 'pg_logical_emit_message_text' },
+{ oid => '3578', descr => 'emit a binary logical decoding message',
+ proname => 'pg_logical_emit_message', provolatile => 'v', proparallel => 'u',
+ prorettype => 'pg_lsn', proargtypes => 'bool text bytea',
+ prosrc => 'pg_logical_emit_message_bytea' },
+
+# event triggers
+{ oid => '3566', descr => 'list objects dropped by the current command',
+ proname => 'pg_event_trigger_dropped_objects', procost => '10',
+ prorows => '100', proretset => 't', provolatile => 's', proparallel => 'r',
+ prorettype => 'record', proargtypes => '',
+ proallargtypes => '{oid,oid,int4,bool,bool,bool,text,text,text,text,_text,_text}',
+ proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{classid, objid, objsubid, original, normal, is_temporary, object_type, schema_name, object_name, object_identity, address_names, address_args}',
+ prosrc => 'pg_event_trigger_dropped_objects' },
+{ oid => '4566', descr => 'return Oid of the table getting rewritten',
+ proname => 'pg_event_trigger_table_rewrite_oid', provolatile => 's',
+ proparallel => 'r', prorettype => 'oid', proargtypes => '',
+ proallargtypes => '{oid}', proargmodes => '{o}', proargnames => '{oid}',
+ prosrc => 'pg_event_trigger_table_rewrite_oid' },
+{ oid => '4567', descr => 'return reason code for table getting rewritten',
+ proname => 'pg_event_trigger_table_rewrite_reason', provolatile => 's',
+ proparallel => 'r', prorettype => 'int4', proargtypes => '',
+ prosrc => 'pg_event_trigger_table_rewrite_reason' },
+{ oid => '4568',
+ descr => 'list DDL actions being executed by the current command',
+ proname => 'pg_event_trigger_ddl_commands', procost => '10', prorows => '100',
+ proretset => 't', provolatile => 's', proparallel => 'r',
+ prorettype => 'record', proargtypes => '',
+ proallargtypes => '{oid,oid,int4,text,text,text,text,bool,pg_ddl_command}',
+ proargmodes => '{o,o,o,o,o,o,o,o,o}',
+ proargnames => '{classid, objid, objsubid, command_tag, object_type, schema_name, object_identity, in_extension, command}',
+ prosrc => 'pg_event_trigger_ddl_commands' },
+
+# generic transition functions for ordered-set aggregates
+{ oid => '3970', descr => 'aggregate transition function',
+ proname => 'ordered_set_transition', proisstrict => 'f',
+ prorettype => 'internal', proargtypes => 'internal any',
+ prosrc => 'ordered_set_transition' },
+{ oid => '3971', descr => 'aggregate transition function',
+ proname => 'ordered_set_transition_multi', provariadic => 'any',
+ proisstrict => 'f', prorettype => 'internal', proargtypes => 'internal any',
+ proallargtypes => '{internal,any}', proargmodes => '{i,v}',
+ prosrc => 'ordered_set_transition_multi' },
+
+# inverse distribution aggregates (and their support functions)
+{ oid => '3972', descr => 'discrete percentile',
+ proname => 'percentile_disc', prokind => 'a', proisstrict => 'f',
+ prorettype => 'anyelement', proargtypes => 'float8 anyelement',
+ prosrc => 'aggregate_dummy' },
+{ oid => '3973', descr => 'aggregate final function',
+ proname => 'percentile_disc_final', proisstrict => 'f',
+ prorettype => 'anyelement', proargtypes => 'internal float8 anyelement',
+ prosrc => 'percentile_disc_final' },
+{ oid => '3974', descr => 'continuous distribution percentile',
+ proname => 'percentile_cont', prokind => 'a', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'float8 float8',
+ prosrc => 'aggregate_dummy' },
+{ oid => '3975', descr => 'aggregate final function',
+ proname => 'percentile_cont_float8_final', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'internal float8',
+ prosrc => 'percentile_cont_float8_final' },
+{ oid => '3976', descr => 'continuous distribution percentile',
+ proname => 'percentile_cont', prokind => 'a', proisstrict => 'f',
+ prorettype => 'interval', proargtypes => 'float8 interval',
+ prosrc => 'aggregate_dummy' },
+{ oid => '3977', descr => 'aggregate final function',
+ proname => 'percentile_cont_interval_final', proisstrict => 'f',
+ prorettype => 'interval', proargtypes => 'internal float8',
+ prosrc => 'percentile_cont_interval_final' },
+{ oid => '3978', descr => 'multiple discrete percentiles',
+ proname => 'percentile_disc', prokind => 'a', proisstrict => 'f',
+ prorettype => 'anyarray', proargtypes => '_float8 anyelement',
+ prosrc => 'aggregate_dummy' },
+{ oid => '3979', descr => 'aggregate final function',
+ proname => 'percentile_disc_multi_final', proisstrict => 'f',
+ prorettype => 'anyarray', proargtypes => 'internal _float8 anyelement',
+ prosrc => 'percentile_disc_multi_final' },
+{ oid => '3980', descr => 'multiple continuous percentiles',
+ proname => 'percentile_cont', prokind => 'a', proisstrict => 'f',
+ prorettype => '_float8', proargtypes => '_float8 float8',
+ prosrc => 'aggregate_dummy' },
+{ oid => '3981', descr => 'aggregate final function',
+ proname => 'percentile_cont_float8_multi_final', proisstrict => 'f',
+ prorettype => '_float8', proargtypes => 'internal _float8',
+ prosrc => 'percentile_cont_float8_multi_final' },
+{ oid => '3982', descr => 'multiple continuous percentiles',
+ proname => 'percentile_cont', prokind => 'a', proisstrict => 'f',
+ prorettype => '_interval', proargtypes => '_float8 interval',
+ prosrc => 'aggregate_dummy' },
+{ oid => '3983', descr => 'aggregate final function',
+ proname => 'percentile_cont_interval_multi_final', proisstrict => 'f',
+ prorettype => '_interval', proargtypes => 'internal _float8',
+ prosrc => 'percentile_cont_interval_multi_final' },
+{ oid => '3984', descr => 'most common value',
+ proname => 'mode', prokind => 'a', proisstrict => 'f',
+ prorettype => 'anyelement', proargtypes => 'anyelement',
+ prosrc => 'aggregate_dummy' },
+{ oid => '3985', descr => 'aggregate final function',
+ proname => 'mode_final', proisstrict => 'f', prorettype => 'anyelement',
+ proargtypes => 'internal anyelement', prosrc => 'mode_final' },
+
+# hypothetical-set aggregates (and their support functions)
+{ oid => '3986', descr => 'rank of hypothetical row',
+ proname => 'rank', provariadic => 'any', prokind => 'a', proisstrict => 'f',
+ prorettype => 'int8', proargtypes => 'any', proallargtypes => '{any}',
+ proargmodes => '{v}', prosrc => 'aggregate_dummy' },
+{ oid => '3987', descr => 'aggregate final function',
+ proname => 'rank_final', provariadic => 'any', proisstrict => 'f',
+ prorettype => 'int8', proargtypes => 'internal any',
+ proallargtypes => '{internal,any}', proargmodes => '{i,v}',
+ prosrc => 'hypothetical_rank_final' },
+{ oid => '3988', descr => 'fractional rank of hypothetical row',
+ proname => 'percent_rank', provariadic => 'any', prokind => 'a',
+ proisstrict => 'f', prorettype => 'float8', proargtypes => 'any',
+ proallargtypes => '{any}', proargmodes => '{v}',
+ prosrc => 'aggregate_dummy' },
+{ oid => '3989', descr => 'aggregate final function',
+ proname => 'percent_rank_final', provariadic => 'any', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'internal any',
+ proallargtypes => '{internal,any}', proargmodes => '{i,v}',
+ prosrc => 'hypothetical_percent_rank_final' },
+{ oid => '3990', descr => 'cumulative distribution of hypothetical row',
+ proname => 'cume_dist', provariadic => 'any', prokind => 'a',
+ proisstrict => 'f', prorettype => 'float8', proargtypes => 'any',
+ proallargtypes => '{any}', proargmodes => '{v}',
+ prosrc => 'aggregate_dummy' },
+{ oid => '3991', descr => 'aggregate final function',
+ proname => 'cume_dist_final', provariadic => 'any', proisstrict => 'f',
+ prorettype => 'float8', proargtypes => 'internal any',
+ proallargtypes => '{internal,any}', proargmodes => '{i,v}',
+ prosrc => 'hypothetical_cume_dist_final' },
+{ oid => '3992', descr => 'rank of hypothetical row without gaps',
+ proname => 'dense_rank', provariadic => 'any', prokind => 'a',
+ proisstrict => 'f', prorettype => 'int8', proargtypes => 'any',
+ proallargtypes => '{any}', proargmodes => '{v}',
+ prosrc => 'aggregate_dummy' },
+{ oid => '3993', descr => 'aggregate final function',
+ proname => 'dense_rank_final', provariadic => 'any', proisstrict => 'f',
+ prorettype => 'int8', proargtypes => 'internal any',
+ proallargtypes => '{internal,any}', proargmodes => '{i,v}',
+ prosrc => 'hypothetical_dense_rank_final' },
+
+# pg_upgrade support
+{ oid => '3582', descr => 'for use by pg_upgrade',
+ proname => 'binary_upgrade_set_next_pg_type_oid', provolatile => 'v',
+ proparallel => 'r', prorettype => 'void', proargtypes => 'oid',
+ prosrc => 'binary_upgrade_set_next_pg_type_oid' },
+{ oid => '3584', descr => 'for use by pg_upgrade',
+ proname => 'binary_upgrade_set_next_array_pg_type_oid', provolatile => 'v',
+ proparallel => 'r', prorettype => 'void', proargtypes => 'oid',
+ prosrc => 'binary_upgrade_set_next_array_pg_type_oid' },
+{ oid => '3585', descr => 'for use by pg_upgrade',
+ proname => 'binary_upgrade_set_next_toast_pg_type_oid', provolatile => 'v',
+ proparallel => 'r', prorettype => 'void', proargtypes => 'oid',
+ prosrc => 'binary_upgrade_set_next_toast_pg_type_oid' },
+{ oid => '3586', descr => 'for use by pg_upgrade',
+ proname => 'binary_upgrade_set_next_heap_pg_class_oid', provolatile => 'v',
+ proparallel => 'r', prorettype => 'void', proargtypes => 'oid',
+ prosrc => 'binary_upgrade_set_next_heap_pg_class_oid' },
+{ oid => '3587', descr => 'for use by pg_upgrade',
+ proname => 'binary_upgrade_set_next_index_pg_class_oid', provolatile => 'v',
+ proparallel => 'r', prorettype => 'void', proargtypes => 'oid',
+ prosrc => 'binary_upgrade_set_next_index_pg_class_oid' },
+{ oid => '3588', descr => 'for use by pg_upgrade',
+ proname => 'binary_upgrade_set_next_toast_pg_class_oid', provolatile => 'v',
+ proparallel => 'r', prorettype => 'void', proargtypes => 'oid',
+ prosrc => 'binary_upgrade_set_next_toast_pg_class_oid' },
+{ oid => '3589', descr => 'for use by pg_upgrade',
+ proname => 'binary_upgrade_set_next_pg_enum_oid', provolatile => 'v',
+ proparallel => 'r', prorettype => 'void', proargtypes => 'oid',
+ prosrc => 'binary_upgrade_set_next_pg_enum_oid' },
+{ oid => '3590', descr => 'for use by pg_upgrade',
+ proname => 'binary_upgrade_set_next_pg_authid_oid', provolatile => 'v',
+ proparallel => 'r', prorettype => 'void', proargtypes => 'oid',
+ prosrc => 'binary_upgrade_set_next_pg_authid_oid' },
+{ oid => '3591', descr => 'for use by pg_upgrade',
+ proname => 'binary_upgrade_create_empty_extension', proisstrict => 'f',
+ provolatile => 'v', proparallel => 'u', prorettype => 'void',
+ proargtypes => 'text text bool text _oid _text _text',
+ prosrc => 'binary_upgrade_create_empty_extension' },
+{ oid => '4083', descr => 'for use by pg_upgrade',
+ proname => 'binary_upgrade_set_record_init_privs', provolatile => 'v',
+ proparallel => 'r', prorettype => 'void', proargtypes => 'bool',
+ prosrc => 'binary_upgrade_set_record_init_privs' },
+{ oid => '4101', descr => 'for use by pg_upgrade',
+ proname => 'binary_upgrade_set_missing_value', provolatile => 'v',
+ proparallel => 'u', prorettype => 'void', proargtypes => 'oid text text',
+ prosrc => 'binary_upgrade_set_missing_value' },
+
+# conversion functions
+{ oid => '4302',
+ descr => 'internal conversion function for KOI8R to MULE_INTERNAL',
+ proname => 'koi8r_to_mic', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'koi8r_to_mic',
+ probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4303',
+ descr => 'internal conversion function for MULE_INTERNAL to KOI8R',
+ proname => 'mic_to_koi8r', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'mic_to_koi8r',
+ probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4304',
+ descr => 'internal conversion function for ISO-8859-5 to MULE_INTERNAL',
+ proname => 'iso_to_mic', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'iso_to_mic',
+ probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4305',
+ descr => 'internal conversion function for MULE_INTERNAL to ISO-8859-5',
+ proname => 'mic_to_iso', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'mic_to_iso',
+ probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4306',
+ descr => 'internal conversion function for WIN1251 to MULE_INTERNAL',
+ proname => 'win1251_to_mic', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'win1251_to_mic',
+ probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4307',
+ descr => 'internal conversion function for MULE_INTERNAL to WIN1251',
+ proname => 'mic_to_win1251', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'mic_to_win1251',
+ probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4308',
+ descr => 'internal conversion function for WIN866 to MULE_INTERNAL',
+ proname => 'win866_to_mic', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'win866_to_mic',
+ probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4309',
+ descr => 'internal conversion function for MULE_INTERNAL to WIN866',
+ proname => 'mic_to_win866', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'mic_to_win866',
+ probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4310', descr => 'internal conversion function for KOI8R to WIN1251',
+ proname => 'koi8r_to_win1251', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4',
+ prosrc => 'koi8r_to_win1251', probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4311', descr => 'internal conversion function for WIN1251 to KOI8R',
+ proname => 'win1251_to_koi8r', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4',
+ prosrc => 'win1251_to_koi8r', probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4312', descr => 'internal conversion function for KOI8R to WIN866',
+ proname => 'koi8r_to_win866', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'koi8r_to_win866',
+ probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4313', descr => 'internal conversion function for WIN866 to KOI8R',
+ proname => 'win866_to_koi8r', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'win866_to_koi8r',
+ probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4314',
+ descr => 'internal conversion function for WIN866 to WIN1251',
+ proname => 'win866_to_win1251', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4',
+ prosrc => 'win866_to_win1251', probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4315',
+ descr => 'internal conversion function for WIN1251 to WIN866',
+ proname => 'win1251_to_win866', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4',
+ prosrc => 'win1251_to_win866', probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4316',
+ descr => 'internal conversion function for ISO-8859-5 to KOI8R',
+ proname => 'iso_to_koi8r', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'iso_to_koi8r',
+ probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4317',
+ descr => 'internal conversion function for KOI8R to ISO-8859-5',
+ proname => 'koi8r_to_iso', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'koi8r_to_iso',
+ probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4318',
+ descr => 'internal conversion function for ISO-8859-5 to WIN1251',
+ proname => 'iso_to_win1251', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'iso_to_win1251',
+ probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4319',
+ descr => 'internal conversion function for WIN1251 to ISO-8859-5',
+ proname => 'win1251_to_iso', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'win1251_to_iso',
+ probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4320',
+ descr => 'internal conversion function for ISO-8859-5 to WIN866',
+ proname => 'iso_to_win866', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'iso_to_win866',
+ probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4321',
+ descr => 'internal conversion function for WIN866 to ISO-8859-5',
+ proname => 'win866_to_iso', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'win866_to_iso',
+ probin => '$libdir/cyrillic_and_mic' },
+{ oid => '4322',
+ descr => 'internal conversion function for EUC_CN to MULE_INTERNAL',
+ proname => 'euc_cn_to_mic', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'euc_cn_to_mic',
+ probin => '$libdir/euc_cn_and_mic' },
+{ oid => '4323',
+ descr => 'internal conversion function for MULE_INTERNAL to EUC_CN',
+ proname => 'mic_to_euc_cn', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'mic_to_euc_cn',
+ probin => '$libdir/euc_cn_and_mic' },
+{ oid => '4324', descr => 'internal conversion function for EUC_JP to SJIS',
+ proname => 'euc_jp_to_sjis', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'euc_jp_to_sjis',
+ probin => '$libdir/euc_jp_and_sjis' },
+{ oid => '4325', descr => 'internal conversion function for SJIS to EUC_JP',
+ proname => 'sjis_to_euc_jp', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'sjis_to_euc_jp',
+ probin => '$libdir/euc_jp_and_sjis' },
+{ oid => '4326',
+ descr => 'internal conversion function for EUC_JP to MULE_INTERNAL',
+ proname => 'euc_jp_to_mic', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'euc_jp_to_mic',
+ probin => '$libdir/euc_jp_and_sjis' },
+{ oid => '4327',
+ descr => 'internal conversion function for SJIS to MULE_INTERNAL',
+ proname => 'sjis_to_mic', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'sjis_to_mic',
+ probin => '$libdir/euc_jp_and_sjis' },
+{ oid => '4328',
+ descr => 'internal conversion function for MULE_INTERNAL to EUC_JP',
+ proname => 'mic_to_euc_jp', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'mic_to_euc_jp',
+ probin => '$libdir/euc_jp_and_sjis' },
+{ oid => '4329',
+ descr => 'internal conversion function for MULE_INTERNAL to SJIS',
+ proname => 'mic_to_sjis', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'mic_to_sjis',
+ probin => '$libdir/euc_jp_and_sjis' },
+{ oid => '4330',
+ descr => 'internal conversion function for EUC_KR to MULE_INTERNAL',
+ proname => 'euc_kr_to_mic', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'euc_kr_to_mic',
+ probin => '$libdir/euc_kr_and_mic' },
+{ oid => '4331',
+ descr => 'internal conversion function for MULE_INTERNAL to EUC_KR',
+ proname => 'mic_to_euc_kr', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'mic_to_euc_kr',
+ probin => '$libdir/euc_kr_and_mic' },
+{ oid => '4332', descr => 'internal conversion function for EUC_TW to BIG5',
+ proname => 'euc_tw_to_big5', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'euc_tw_to_big5',
+ probin => '$libdir/euc_tw_and_big5' },
+{ oid => '4333', descr => 'internal conversion function for BIG5 to EUC_TW',
+ proname => 'big5_to_euc_tw', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'big5_to_euc_tw',
+ probin => '$libdir/euc_tw_and_big5' },
+{ oid => '4334',
+ descr => 'internal conversion function for EUC_TW to MULE_INTERNAL',
+ proname => 'euc_tw_to_mic', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'euc_tw_to_mic',
+ probin => '$libdir/euc_tw_and_big5' },
+{ oid => '4335',
+ descr => 'internal conversion function for BIG5 to MULE_INTERNAL',
+ proname => 'big5_to_mic', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'big5_to_mic',
+ probin => '$libdir/euc_tw_and_big5' },
+{ oid => '4336',
+ descr => 'internal conversion function for MULE_INTERNAL to EUC_TW',
+ proname => 'mic_to_euc_tw', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'mic_to_euc_tw',
+ probin => '$libdir/euc_tw_and_big5' },
+{ oid => '4337',
+ descr => 'internal conversion function for MULE_INTERNAL to BIG5',
+ proname => 'mic_to_big5', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'mic_to_big5',
+ probin => '$libdir/euc_tw_and_big5' },
+{ oid => '4338',
+ descr => 'internal conversion function for LATIN2 to MULE_INTERNAL',
+ proname => 'latin2_to_mic', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'latin2_to_mic',
+ probin => '$libdir/latin2_and_win1250' },
+{ oid => '4339',
+ descr => 'internal conversion function for MULE_INTERNAL to LATIN2',
+ proname => 'mic_to_latin2', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'mic_to_latin2',
+ probin => '$libdir/latin2_and_win1250' },
+{ oid => '4340',
+ descr => 'internal conversion function for WIN1250 to MULE_INTERNAL',
+ proname => 'win1250_to_mic', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'win1250_to_mic',
+ probin => '$libdir/latin2_and_win1250' },
+{ oid => '4341',
+ descr => 'internal conversion function for MULE_INTERNAL to WIN1250',
+ proname => 'mic_to_win1250', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'mic_to_win1250',
+ probin => '$libdir/latin2_and_win1250' },
+{ oid => '4342',
+ descr => 'internal conversion function for LATIN2 to WIN1250',
+ proname => 'latin2_to_win1250', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4',
+ prosrc => 'latin2_to_win1250', probin => '$libdir/latin2_and_win1250' },
+{ oid => '4343',
+ descr => 'internal conversion function for WIN1250 to LATIN2',
+ proname => 'win1250_to_latin2', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4',
+ prosrc => 'win1250_to_latin2', probin => '$libdir/latin2_and_win1250' },
+{ oid => '4344',
+ descr => 'internal conversion function for LATIN1 to MULE_INTERNAL',
+ proname => 'latin1_to_mic', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'latin1_to_mic',
+ probin => '$libdir/latin_and_mic' },
+{ oid => '4345',
+ descr => 'internal conversion function for MULE_INTERNAL to LATIN1',
+ proname => 'mic_to_latin1', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'mic_to_latin1',
+ probin => '$libdir/latin_and_mic' },
+{ oid => '4346',
+ descr => 'internal conversion function for LATIN3 to MULE_INTERNAL',
+ proname => 'latin3_to_mic', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'latin3_to_mic',
+ probin => '$libdir/latin_and_mic' },
+{ oid => '4347',
+ descr => 'internal conversion function for MULE_INTERNAL to LATIN3',
+ proname => 'mic_to_latin3', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'mic_to_latin3',
+ probin => '$libdir/latin_and_mic' },
+{ oid => '4348',
+ descr => 'internal conversion function for LATIN4 to MULE_INTERNAL',
+ proname => 'latin4_to_mic', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'latin4_to_mic',
+ probin => '$libdir/latin_and_mic' },
+{ oid => '4349',
+ descr => 'internal conversion function for MULE_INTERNAL to LATIN4',
+ proname => 'mic_to_latin4', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'mic_to_latin4',
+ probin => '$libdir/latin_and_mic' },
+{ oid => '4352', descr => 'internal conversion function for BIG5 to UTF8',
+ proname => 'big5_to_utf8', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'big5_to_utf8',
+ probin => '$libdir/utf8_and_big5' },
+{ oid => '4353', descr => 'internal conversion function for UTF8 to BIG5',
+ proname => 'utf8_to_big5', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'utf8_to_big5',
+ probin => '$libdir/utf8_and_big5' },
+{ oid => '4354', descr => 'internal conversion function for UTF8 to KOI8R',
+ proname => 'utf8_to_koi8r', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'utf8_to_koi8r',
+ probin => '$libdir/utf8_and_cyrillic' },
+{ oid => '4355', descr => 'internal conversion function for KOI8R to UTF8',
+ proname => 'koi8r_to_utf8', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'koi8r_to_utf8',
+ probin => '$libdir/utf8_and_cyrillic' },
+{ oid => '4356', descr => 'internal conversion function for UTF8 to KOI8U',
+ proname => 'utf8_to_koi8u', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'utf8_to_koi8u',
+ probin => '$libdir/utf8_and_cyrillic' },
+{ oid => '4357', descr => 'internal conversion function for KOI8U to UTF8',
+ proname => 'koi8u_to_utf8', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'koi8u_to_utf8',
+ probin => '$libdir/utf8_and_cyrillic' },
+{ oid => '4358', descr => 'internal conversion function for UTF8 to WIN',
+ proname => 'utf8_to_win', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'utf8_to_win',
+ probin => '$libdir/utf8_and_win' },
+{ oid => '4359', descr => 'internal conversion function for WIN to UTF8',
+ proname => 'win_to_utf8', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'win_to_utf8',
+ probin => '$libdir/utf8_and_win' },
+{ oid => '4360', descr => 'internal conversion function for EUC_CN to UTF8',
+ proname => 'euc_cn_to_utf8', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'euc_cn_to_utf8',
+ probin => '$libdir/utf8_and_euc_cn' },
+{ oid => '4361', descr => 'internal conversion function for UTF8 to EUC_CN',
+ proname => 'utf8_to_euc_cn', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'utf8_to_euc_cn',
+ probin => '$libdir/utf8_and_euc_cn' },
+{ oid => '4362', descr => 'internal conversion function for EUC_JP to UTF8',
+ proname => 'euc_jp_to_utf8', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'euc_jp_to_utf8',
+ probin => '$libdir/utf8_and_euc_jp' },
+{ oid => '4363', descr => 'internal conversion function for UTF8 to EUC_JP',
+ proname => 'utf8_to_euc_jp', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'utf8_to_euc_jp',
+ probin => '$libdir/utf8_and_euc_jp' },
+{ oid => '4364', descr => 'internal conversion function for EUC_KR to UTF8',
+ proname => 'euc_kr_to_utf8', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'euc_kr_to_utf8',
+ probin => '$libdir/utf8_and_euc_kr' },
+{ oid => '4365', descr => 'internal conversion function for UTF8 to EUC_KR',
+ proname => 'utf8_to_euc_kr', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'utf8_to_euc_kr',
+ probin => '$libdir/utf8_and_euc_kr' },
+{ oid => '4366', descr => 'internal conversion function for EUC_TW to UTF8',
+ proname => 'euc_tw_to_utf8', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'euc_tw_to_utf8',
+ probin => '$libdir/utf8_and_euc_tw' },
+{ oid => '4367', descr => 'internal conversion function for UTF8 to EUC_TW',
+ proname => 'utf8_to_euc_tw', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'utf8_to_euc_tw',
+ probin => '$libdir/utf8_and_euc_tw' },
+{ oid => '4368', descr => 'internal conversion function for GB18030 to UTF8',
+ proname => 'gb18030_to_utf8', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'gb18030_to_utf8',
+ probin => '$libdir/utf8_and_gb18030' },
+{ oid => '4369', descr => 'internal conversion function for UTF8 to GB18030',
+ proname => 'utf8_to_gb18030', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'utf8_to_gb18030',
+ probin => '$libdir/utf8_and_gb18030' },
+{ oid => '4370', descr => 'internal conversion function for GBK to UTF8',
+ proname => 'gbk_to_utf8', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'gbk_to_utf8',
+ probin => '$libdir/utf8_and_gbk' },
+{ oid => '4371', descr => 'internal conversion function for UTF8 to GBK',
+ proname => 'utf8_to_gbk', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'utf8_to_gbk',
+ probin => '$libdir/utf8_and_gbk' },
+{ oid => '4372',
+ descr => 'internal conversion function for UTF8 to ISO-8859 2-16',
+ proname => 'utf8_to_iso8859', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'utf8_to_iso8859',
+ probin => '$libdir/utf8_and_iso8859' },
+{ oid => '4373',
+ descr => 'internal conversion function for ISO-8859 2-16 to UTF8',
+ proname => 'iso8859_to_utf8', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'iso8859_to_utf8',
+ probin => '$libdir/utf8_and_iso8859' },
+{ oid => '4374', descr => 'internal conversion function for LATIN1 to UTF8',
+ proname => 'iso8859_1_to_utf8', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4',
+ prosrc => 'iso8859_1_to_utf8', probin => '$libdir/utf8_and_iso8859_1' },
+{ oid => '4375', descr => 'internal conversion function for UTF8 to LATIN1',
+ proname => 'utf8_to_iso8859_1', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4',
+ prosrc => 'utf8_to_iso8859_1', probin => '$libdir/utf8_and_iso8859_1' },
+{ oid => '4376', descr => 'internal conversion function for JOHAB to UTF8',
+ proname => 'johab_to_utf8', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'johab_to_utf8',
+ probin => '$libdir/utf8_and_johab' },
+{ oid => '4377', descr => 'internal conversion function for UTF8 to JOHAB',
+ proname => 'utf8_to_johab', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'utf8_to_johab',
+ probin => '$libdir/utf8_and_johab' },
+{ oid => '4378', descr => 'internal conversion function for SJIS to UTF8',
+ proname => 'sjis_to_utf8', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'sjis_to_utf8',
+ probin => '$libdir/utf8_and_sjis' },
+{ oid => '4379', descr => 'internal conversion function for UTF8 to SJIS',
+ proname => 'utf8_to_sjis', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'utf8_to_sjis',
+ probin => '$libdir/utf8_and_sjis' },
+{ oid => '4380', descr => 'internal conversion function for UHC to UTF8',
+ proname => 'uhc_to_utf8', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'uhc_to_utf8',
+ probin => '$libdir/utf8_and_uhc' },
+{ oid => '4381', descr => 'internal conversion function for UTF8 to UHC',
+ proname => 'utf8_to_uhc', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4', prosrc => 'utf8_to_uhc',
+ probin => '$libdir/utf8_and_uhc' },
+{ oid => '4382',
+ descr => 'internal conversion function for EUC_JIS_2004 to UTF8',
+ proname => 'euc_jis_2004_to_utf8', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4',
+ prosrc => 'euc_jis_2004_to_utf8', probin => '$libdir/utf8_and_euc2004' },
+{ oid => '4383',
+ descr => 'internal conversion function for UTF8 to EUC_JIS_2004',
+ proname => 'utf8_to_euc_jis_2004', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4',
+ prosrc => 'utf8_to_euc_jis_2004', probin => '$libdir/utf8_and_euc2004' },
+{ oid => '4384',
+ descr => 'internal conversion function for SHIFT_JIS_2004 to UTF8',
+ proname => 'shift_jis_2004_to_utf8', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4',
+ prosrc => 'shift_jis_2004_to_utf8', probin => '$libdir/utf8_and_sjis2004' },
+{ oid => '4385',
+ descr => 'internal conversion function for UTF8 to SHIFT_JIS_2004',
+ proname => 'utf8_to_shift_jis_2004', prolang => 'c', prorettype => 'void',
+ proargtypes => 'int4 int4 cstring internal int4',
+ prosrc => 'utf8_to_shift_jis_2004', probin => '$libdir/utf8_and_sjis2004' },
+{ oid => '4386',
+ descr => 'internal conversion function for EUC_JIS_2004 to SHIFT_JIS_2004',
+ proname => 'euc_jis_2004_to_shift_jis_2004', prolang => 'c',
+ prorettype => 'void', proargtypes => 'int4 int4 cstring internal int4',
+ prosrc => 'euc_jis_2004_to_shift_jis_2004',
+ probin => '$libdir/euc2004_sjis2004' },
+{ oid => '4387',
+ descr => 'internal conversion function for SHIFT_JIS_2004 to EUC_JIS_2004',
+ proname => 'shift_jis_2004_to_euc_jis_2004', prolang => 'c',
+ prorettype => 'void', proargtypes => 'int4 int4 cstring internal int4',
+ prosrc => 'shift_jis_2004_to_euc_jis_2004',
+ probin => '$libdir/euc2004_sjis2004' },
+
+{ oid => '5040',
+ descr => 'restriction selectivity for generic matching operators',
+ proname => 'matchingsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int4', prosrc => 'matchingsel' },
+{ oid => '5041', descr => 'join selectivity for generic matching operators',
+ proname => 'matchingjoinsel', provolatile => 's', prorettype => 'float8',
+ proargtypes => 'internal oid internal int2 internal',
+ prosrc => 'matchingjoinsel' },
+
+# replication/origin.h
+{ oid => '6003', descr => 'create a replication origin',
+ proname => 'pg_replication_origin_create', provolatile => 'v',
+ proparallel => 'u', prorettype => 'oid', proargtypes => 'text',
+ prosrc => 'pg_replication_origin_create' },
+
+{ oid => '6004', descr => 'drop replication origin identified by its name',
+ proname => 'pg_replication_origin_drop', provolatile => 'v',
+ proparallel => 'u', prorettype => 'void', proargtypes => 'text',
+ prosrc => 'pg_replication_origin_drop' },
+
+{ oid => '6005',
+ descr => 'translate the replication origin\'s name to its id',
+ proname => 'pg_replication_origin_oid', provolatile => 's',
+ prorettype => 'oid', proargtypes => 'text',
+ prosrc => 'pg_replication_origin_oid' },
+
+{ oid => '6006',
+ descr => 'configure session to maintain replication progress tracking for the passed in origin',
+ proname => 'pg_replication_origin_session_setup', provolatile => 'v',
+ proparallel => 'u', prorettype => 'void', proargtypes => 'text',
+ prosrc => 'pg_replication_origin_session_setup' },
+
+{ oid => '6007', descr => 'teardown configured replication progress tracking',
+ proname => 'pg_replication_origin_session_reset', provolatile => 'v',
+ proparallel => 'u', prorettype => 'void', proargtypes => '',
+ prosrc => 'pg_replication_origin_session_reset' },
+
+{ oid => '6008',
+ descr => 'is a replication origin configured in this session',
+ proname => 'pg_replication_origin_session_is_setup', provolatile => 'v',
+ proparallel => 'r', prorettype => 'bool', proargtypes => '',
+ prosrc => 'pg_replication_origin_session_is_setup' },
+
+{ oid => '6009',
+ descr => 'get the replication progress of the current session',
+ proname => 'pg_replication_origin_session_progress', provolatile => 'v',
+ proparallel => 'u', prorettype => 'pg_lsn', proargtypes => 'bool',
+ prosrc => 'pg_replication_origin_session_progress' },
+
+{ oid => '6010', descr => 'setup the transaction\'s origin lsn and timestamp',
+ proname => 'pg_replication_origin_xact_setup', provolatile => 'v',
+ proparallel => 'r', prorettype => 'void', proargtypes => 'pg_lsn timestamptz',
+ prosrc => 'pg_replication_origin_xact_setup' },
+
+{ oid => '6011', descr => 'reset the transaction\'s origin lsn and timestamp',
+ proname => 'pg_replication_origin_xact_reset', provolatile => 'v',
+ proparallel => 'r', prorettype => 'void', proargtypes => '',
+ prosrc => 'pg_replication_origin_xact_reset' },
+
+{ oid => '6012', descr => 'advance replication origin to specific location',
+ proname => 'pg_replication_origin_advance', provolatile => 'v',
+ proparallel => 'u', prorettype => 'void', proargtypes => 'text pg_lsn',
+ prosrc => 'pg_replication_origin_advance' },
+
+{ oid => '6013',
+ descr => 'get an individual replication origin\'s replication progress',
+ proname => 'pg_replication_origin_progress', provolatile => 'v',
+ proparallel => 'u', prorettype => 'pg_lsn', proargtypes => 'text bool',
+ prosrc => 'pg_replication_origin_progress' },
+
+{ oid => '6014', descr => 'get progress for all replication origins',
+ proname => 'pg_show_replication_origin_status', prorows => '100',
+ proisstrict => 'f', proretset => 't', provolatile => 'v', proparallel => 'r',
+ prorettype => 'record', proargtypes => '',
+ proallargtypes => '{oid,text,pg_lsn,pg_lsn}', proargmodes => '{o,o,o,o}',
+ proargnames => '{local_id, external_id, remote_lsn, local_lsn}',
+ prosrc => 'pg_show_replication_origin_status' },
+
+# publications
+{ oid => '6119', descr => 'get OIDs of tables in a publication',
+ proname => 'pg_get_publication_tables', prorows => '1000', proretset => 't',
+ provolatile => 's', prorettype => 'oid', proargtypes => 'text',
+ proallargtypes => '{text,oid}', proargmodes => '{i,o}',
+ proargnames => '{pubname,relid}', prosrc => 'pg_get_publication_tables' },
+{ oid => '6121',
+ descr => 'returns whether a relation can be part of a publication',
+ proname => 'pg_relation_is_publishable', provolatile => 's',
+ prorettype => 'bool', proargtypes => 'regclass',
+ prosrc => 'pg_relation_is_publishable' },
+
+# rls
+{ oid => '3298',
+ descr => 'row security for current context active on table by table oid',
+ proname => 'row_security_active', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'oid', prosrc => 'row_security_active' },
+{ oid => '3299',
+ descr => 'row security for current context active on table by table name',
+ proname => 'row_security_active', provolatile => 's', prorettype => 'bool',
+ proargtypes => 'text', prosrc => 'row_security_active_name' },
+
+# pg_config
+{ oid => '3400', descr => 'pg_config binary as a function',
+ proname => 'pg_config', prorows => '23', proretset => 't', provolatile => 's',
+ proparallel => 'r', prorettype => 'record', proargtypes => '',
+ proallargtypes => '{text,text}', proargmodes => '{o,o}',
+ proargnames => '{name,setting}', prosrc => 'pg_config' },
+
+# pg_controldata related functions
+{ oid => '3441',
+ descr => 'pg_controldata general state information as a function',
+ proname => 'pg_control_system', provolatile => 'v', prorettype => 'record',
+ proargtypes => '', proallargtypes => '{int4,int4,int8,timestamptz}',
+ proargmodes => '{o,o,o,o}',
+ proargnames => '{pg_control_version,catalog_version_no,system_identifier,pg_control_last_modified}',
+ prosrc => 'pg_control_system' },
+
+{ oid => '3442',
+ descr => 'pg_controldata checkpoint state information as a function',
+ proname => 'pg_control_checkpoint', provolatile => 'v',
+ prorettype => 'record', proargtypes => '',
+ proallargtypes => '{pg_lsn,pg_lsn,text,int4,int4,bool,text,oid,xid,xid,xid,oid,xid,xid,oid,xid,xid,timestamptz}',
+ proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{checkpoint_lsn,redo_lsn,redo_wal_file,timeline_id,prev_timeline_id,full_page_writes,next_xid,next_oid,next_multixact_id,next_multi_offset,oldest_xid,oldest_xid_dbid,oldest_active_xid,oldest_multi_xid,oldest_multi_dbid,oldest_commit_ts_xid,newest_commit_ts_xid,checkpoint_time}',
+ prosrc => 'pg_control_checkpoint' },
+
+{ oid => '3443',
+ descr => 'pg_controldata recovery state information as a function',
+ proname => 'pg_control_recovery', provolatile => 'v', prorettype => 'record',
+ proargtypes => '', proallargtypes => '{pg_lsn,int4,pg_lsn,pg_lsn,bool}',
+ proargmodes => '{o,o,o,o,o}',
+ proargnames => '{min_recovery_end_lsn,min_recovery_end_timeline,backup_start_lsn,backup_end_lsn,end_of_backup_record_required}',
+ prosrc => 'pg_control_recovery' },
+
+{ oid => '3444',
+ descr => 'pg_controldata init state information as a function',
+ proname => 'pg_control_init', provolatile => 'v', prorettype => 'record',
+ proargtypes => '',
+ proallargtypes => '{int4,int4,int4,int4,int4,int4,int4,int4,int4,bool,int4}',
+ proargmodes => '{o,o,o,o,o,o,o,o,o,o,o}',
+ proargnames => '{max_data_alignment,database_block_size,blocks_per_segment,wal_block_size,bytes_per_wal_segment,max_identifier_length,max_index_columns,max_toast_chunk_size,large_object_chunk_size,float8_pass_by_value,data_page_checksum_version}',
+ prosrc => 'pg_control_init' },
+
+# collation management functions
+{ oid => '3445', descr => 'import collations from operating system',
+ proname => 'pg_import_system_collations', procost => '100',
+ provolatile => 'v', proparallel => 'u', prorettype => 'int4',
+ proargtypes => 'regnamespace', prosrc => 'pg_import_system_collations' },
+
+{ oid => '3448',
+ descr => 'get actual version of collation from operating system',
+ proname => 'pg_collation_actual_version', procost => '100',
+ provolatile => 'v', prorettype => 'text', proargtypes => 'oid',
+ prosrc => 'pg_collation_actual_version' },
+
+# system management/monitoring related functions
+{ oid => '3353', descr => 'list files in the log directory',
+ proname => 'pg_ls_logdir', procost => '10', prorows => '20', proretset => 't',
+ provolatile => 'v', prorettype => 'record', proargtypes => '',
+ proallargtypes => '{text,int8,timestamptz}', proargmodes => '{o,o,o}',
+ proargnames => '{name,size,modification}', prosrc => 'pg_ls_logdir' },
+{ oid => '3354', descr => 'list of files in the WAL directory',
+ proname => 'pg_ls_waldir', procost => '10', prorows => '20', proretset => 't',
+ provolatile => 'v', prorettype => 'record', proargtypes => '',
+ proallargtypes => '{text,int8,timestamptz}', proargmodes => '{o,o,o}',
+ proargnames => '{name,size,modification}', prosrc => 'pg_ls_waldir' },
+{ oid => '5031', descr => 'list of files in the archive_status directory',
+ proname => 'pg_ls_archive_statusdir', procost => '10', prorows => '20',
+ proretset => 't', provolatile => 'v', prorettype => 'record',
+ proargtypes => '', proallargtypes => '{text,int8,timestamptz}',
+ proargmodes => '{o,o,o}', proargnames => '{name,size,modification}',
+ prosrc => 'pg_ls_archive_statusdir' },
+{ oid => '5029', descr => 'list files in the pgsql_tmp directory',
+ proname => 'pg_ls_tmpdir', procost => '10', prorows => '20', proretset => 't',
+ provolatile => 'v', prorettype => 'record', proargtypes => '',
+ proallargtypes => '{text,int8,timestamptz}', proargmodes => '{o,o,o}',
+ proargnames => '{name,size,modification}', prosrc => 'pg_ls_tmpdir_noargs' },
+{ oid => '5030', descr => 'list files in the pgsql_tmp directory',
+ proname => 'pg_ls_tmpdir', procost => '10', prorows => '20', proretset => 't',
+ provolatile => 'v', prorettype => 'record', proargtypes => 'oid',
+ proallargtypes => '{oid,text,int8,timestamptz}', proargmodes => '{i,o,o,o}',
+ proargnames => '{tablespace,name,size,modification}',
+ prosrc => 'pg_ls_tmpdir_1arg' },
+
+# hash partitioning constraint function
+{ oid => '5028', descr => 'hash partition CHECK constraint',
+ proname => 'satisfies_hash_partition', provariadic => 'any',
+ proisstrict => 'f', prorettype => 'bool', proargtypes => 'oid int4 int4 any',
+ proargmodes => '{i,i,i,v}', prosrc => 'satisfies_hash_partition' },
+
+# information about a partition tree
+{ oid => '3423', descr => 'view partition tree tables',
+ proname => 'pg_partition_tree', prorows => '1000', proretset => 't',
+ provolatile => 'v', prorettype => 'record', proargtypes => 'regclass',
+ proallargtypes => '{regclass,regclass,regclass,bool,int4}',
+ proargmodes => '{i,o,o,o,o}',
+ proargnames => '{rootrelid,relid,parentrelid,isleaf,level}',
+ prosrc => 'pg_partition_tree' },
+{ oid => '3425', descr => 'view ancestors of the partition',
+ proname => 'pg_partition_ancestors', prorows => '10', proretset => 't',
+ provolatile => 'v', prorettype => 'regclass', proargtypes => 'regclass',
+ proallargtypes => '{regclass,regclass}', proargmodes => '{i,o}',
+ proargnames => '{partitionid,relid}', prosrc => 'pg_partition_ancestors' },
+
+# function to get the top-most partition root parent
+{ oid => '3424', descr => 'get top-most partition root parent',
+ proname => 'pg_partition_root', prorettype => 'regclass',
+ proargtypes => 'regclass', prosrc => 'pg_partition_root' },
+
+{ oid => '4350', descr => 'Unicode normalization',
+ proname => 'normalize', prorettype => 'text', proargtypes => 'text text',
+ prosrc => 'unicode_normalize_func' },
+
+{ oid => '4351', descr => 'check Unicode normalization',
+ proname => 'is_normalized', prorettype => 'bool', proargtypes => 'text text',
+ prosrc => 'unicode_is_normalized' },
+
+]
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
new file mode 100644
index 0000000..ee3959d
--- /dev/null
+++ b/src/include/catalog/pg_proc.h
@@ -0,0 +1,211 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_proc.h
+ * definition of the "procedure" system catalog (pg_proc)
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_proc.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_PROC_H
+#define PG_PROC_H
+
+#include "catalog/genbki.h"
+#include "catalog/objectaddress.h"
+#include "catalog/pg_proc_d.h"
+#include "nodes/pg_list.h"
+
+/* ----------------
+ * pg_proc definition. cpp turns this into
+ * typedef struct FormData_pg_proc
+ * ----------------
+ */
+CATALOG(pg_proc,1255,ProcedureRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(81,ProcedureRelation_Rowtype_Id) BKI_SCHEMA_MACRO
+{
+ Oid oid; /* oid */
+
+ /* procedure name */
+ NameData proname;
+
+ /* OID of namespace containing this proc */
+ Oid pronamespace BKI_DEFAULT(PGNSP);
+
+ /* procedure owner */
+ Oid proowner BKI_DEFAULT(PGUID);
+
+ /* OID of pg_language entry */
+ Oid prolang BKI_DEFAULT(internal) BKI_LOOKUP(pg_language);
+
+ /* estimated execution cost */
+ float4 procost BKI_DEFAULT(1);
+
+ /* estimated # of rows out (if proretset) */
+ float4 prorows BKI_DEFAULT(0);
+
+ /* element type of variadic array, or 0 */
+ Oid provariadic BKI_DEFAULT(0) BKI_LOOKUP(pg_type);
+
+ /* planner support function for this function, or 0 if none */
+ regproc prosupport BKI_DEFAULT(0) BKI_LOOKUP(pg_proc);
+
+ /* see PROKIND_ categories below */
+ char prokind BKI_DEFAULT(f);
+
+ /* security definer */
+ bool prosecdef BKI_DEFAULT(f);
+
+ /* is it a leak-proof function? */
+ bool proleakproof BKI_DEFAULT(f);
+
+ /* strict with respect to NULLs? */
+ bool proisstrict BKI_DEFAULT(t);
+
+ /* returns a set? */
+ bool proretset BKI_DEFAULT(f);
+
+ /* see PROVOLATILE_ categories below */
+ char provolatile BKI_DEFAULT(i);
+
+ /* see PROPARALLEL_ categories below */
+ char proparallel BKI_DEFAULT(s);
+
+ /* number of arguments */
+ /* Note: need not be given in pg_proc.dat; genbki.pl will compute it */
+ int16 pronargs;
+
+ /* number of arguments with defaults */
+ int16 pronargdefaults BKI_DEFAULT(0);
+
+ /* OID of result type */
+ Oid prorettype BKI_LOOKUP(pg_type);
+
+ /*
+ * variable-length fields start here, but we allow direct access to
+ * proargtypes
+ */
+
+ /* parameter types (excludes OUT params) */
+ oidvector proargtypes BKI_LOOKUP(pg_type);
+
+#ifdef CATALOG_VARLEN
+
+ /* all param types (NULL if IN only) */
+ Oid proallargtypes[1] BKI_DEFAULT(_null_) BKI_LOOKUP(pg_type);
+
+ /* parameter modes (NULL if IN only) */
+ char proargmodes[1] BKI_DEFAULT(_null_);
+
+ /* parameter names (NULL if no names) */
+ text proargnames[1] BKI_DEFAULT(_null_);
+
+ /* list of expression trees for argument defaults (NULL if none) */
+ pg_node_tree proargdefaults BKI_DEFAULT(_null_);
+
+ /* types for which to apply transforms */
+ Oid protrftypes[1] BKI_DEFAULT(_null_);
+
+ /* procedure source text */
+ text prosrc BKI_FORCE_NOT_NULL;
+
+ /* secondary procedure info (can be NULL) */
+ text probin BKI_DEFAULT(_null_);
+
+ /* procedure-local GUC settings */
+ text proconfig[1] BKI_DEFAULT(_null_);
+
+ /* access permissions */
+ aclitem proacl[1] BKI_DEFAULT(_null_);
+#endif
+} FormData_pg_proc;
+
+/* ----------------
+ * Form_pg_proc corresponds to a pointer to a tuple with
+ * the format of pg_proc relation.
+ * ----------------
+ */
+typedef FormData_pg_proc *Form_pg_proc;
+
+#ifdef EXPOSE_TO_CLIENT_CODE
+
+/*
+ * Symbolic values for prokind column
+ */
+#define PROKIND_FUNCTION 'f'
+#define PROKIND_AGGREGATE 'a'
+#define PROKIND_WINDOW 'w'
+#define PROKIND_PROCEDURE 'p'
+
+/*
+ * Symbolic values for provolatile column: these indicate whether the result
+ * of a function is dependent *only* on the values of its explicit arguments,
+ * or can change due to outside factors (such as parameter variables or
+ * table contents). NOTE: functions having side-effects, such as setval(),
+ * must be labeled volatile to ensure they will not get optimized away,
+ * even if the actual return value is not changeable.
+ */
+#define PROVOLATILE_IMMUTABLE 'i' /* never changes for given input */
+#define PROVOLATILE_STABLE 's' /* does not change within a scan */
+#define PROVOLATILE_VOLATILE 'v' /* can change even within a scan */
+
+/*
+ * Symbolic values for proparallel column: these indicate whether a function
+ * can be safely be run in a parallel backend, during parallelism but
+ * necessarily in the master, or only in non-parallel mode.
+ */
+#define PROPARALLEL_SAFE 's' /* can run in worker or master */
+#define PROPARALLEL_RESTRICTED 'r' /* can run in parallel master only */
+#define PROPARALLEL_UNSAFE 'u' /* banned while in parallel mode */
+
+/*
+ * Symbolic values for proargmodes column. Note that these must agree with
+ * the FunctionParameterMode enum in parsenodes.h; we declare them here to
+ * be accessible from either header.
+ */
+#define PROARGMODE_IN 'i'
+#define PROARGMODE_OUT 'o'
+#define PROARGMODE_INOUT 'b'
+#define PROARGMODE_VARIADIC 'v'
+#define PROARGMODE_TABLE 't'
+
+#endif /* EXPOSE_TO_CLIENT_CODE */
+
+
+extern ObjectAddress ProcedureCreate(const char *procedureName,
+ Oid procNamespace,
+ bool replace,
+ bool returnsSet,
+ Oid returnType,
+ Oid proowner,
+ Oid languageObjectId,
+ Oid languageValidator,
+ const char *prosrc,
+ const char *probin,
+ char prokind,
+ bool security_definer,
+ bool isLeakProof,
+ bool isStrict,
+ char volatility,
+ char parallel,
+ oidvector *parameterTypes,
+ Datum allParameterTypes,
+ Datum parameterModes,
+ Datum parameterNames,
+ List *parameterDefaults,
+ Datum trftypes,
+ Datum proconfig,
+ Oid prosupport,
+ float4 procost,
+ float4 prorows);
+
+extern bool function_parse_error_transpose(const char *prosrc);
+
+extern List *oid_array_to_list(Datum datum);
+
+#endif /* PG_PROC_H */
diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h
new file mode 100644
index 0000000..5955ba0
--- /dev/null
+++ b/src/include/catalog/pg_publication.h
@@ -0,0 +1,115 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_publication.h
+ * definition of the "publication" system catalog (pg_publication)
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_publication.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_PUBLICATION_H
+#define PG_PUBLICATION_H
+
+#include "catalog/genbki.h"
+#include "catalog/objectaddress.h"
+#include "catalog/pg_publication_d.h"
+
+/* ----------------
+ * pg_publication definition. cpp turns this into
+ * typedef struct FormData_pg_publication
+ * ----------------
+ */
+CATALOG(pg_publication,6104,PublicationRelationId)
+{
+ Oid oid; /* oid */
+
+ NameData pubname; /* name of the publication */
+
+ Oid pubowner; /* publication owner */
+
+ /*
+ * indicates that this is special publication which should encompass all
+ * tables in the database (except for the unlogged and temp ones)
+ */
+ bool puballtables;
+
+ /* true if inserts are published */
+ bool pubinsert;
+
+ /* true if updates are published */
+ bool pubupdate;
+
+ /* true if deletes are published */
+ bool pubdelete;
+
+ /* true if truncates are published */
+ bool pubtruncate;
+
+ /* true if partition changes are published using root schema */
+ bool pubviaroot;
+} FormData_pg_publication;
+
+/* ----------------
+ * Form_pg_publication corresponds to a pointer to a tuple with
+ * the format of pg_publication relation.
+ * ----------------
+ */
+typedef FormData_pg_publication *Form_pg_publication;
+
+typedef struct PublicationActions
+{
+ bool pubinsert;
+ bool pubupdate;
+ bool pubdelete;
+ bool pubtruncate;
+} PublicationActions;
+
+typedef struct Publication
+{
+ Oid oid;
+ char *name;
+ bool alltables;
+ bool pubviaroot;
+ PublicationActions pubactions;
+} Publication;
+
+extern Publication *GetPublication(Oid pubid);
+extern Publication *GetPublicationByName(const char *pubname, bool missing_ok);
+extern List *GetRelationPublications(Oid relid);
+
+/*---------
+ * Expected values for pub_partopt parameter of GetRelationPublications(),
+ * which allows callers to specify which partitions of partitioned tables
+ * mentioned in the publication they expect to see.
+ *
+ * ROOT: only the table explicitly mentioned in the publication
+ * LEAF: only leaf partitions in given tree
+ * ALL: all partitions in given tree
+ */
+typedef enum PublicationPartOpt
+{
+ PUBLICATION_PART_ROOT,
+ PUBLICATION_PART_LEAF,
+ PUBLICATION_PART_ALL,
+} PublicationPartOpt;
+
+extern List *GetPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt);
+extern List *GetAllTablesPublications(void);
+extern List *GetAllTablesPublicationRelations(bool pubviaroot);
+
+extern bool is_publishable_relation(Relation rel);
+extern ObjectAddress publication_add_relation(Oid pubid, Relation targetrel,
+ bool if_not_exists);
+
+extern Oid get_publication_oid(const char *pubname, bool missing_ok);
+extern char *get_publication_name(Oid pubid, bool missing_ok);
+
+
+#endif /* PG_PUBLICATION_H */
diff --git a/src/include/catalog/pg_publication_rel.h b/src/include/catalog/pg_publication_rel.h
new file mode 100644
index 0000000..8ab226e
--- /dev/null
+++ b/src/include/catalog/pg_publication_rel.h
@@ -0,0 +1,43 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_publication_rel.h
+ * definition of the system catalog for mappings between relations and
+ * publications (pg_publication_rel)
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_publication_rel.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_PUBLICATION_REL_H
+#define PG_PUBLICATION_REL_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_publication_rel_d.h"
+
+/* ----------------
+ * pg_publication_rel definition. cpp turns this into
+ * typedef struct FormData_pg_publication_rel
+ * ----------------
+ */
+CATALOG(pg_publication_rel,6106,PublicationRelRelationId)
+{
+ Oid oid; /* oid */
+ Oid prpubid; /* Oid of the publication */
+ Oid prrelid; /* Oid of the relation */
+} FormData_pg_publication_rel;
+
+/* ----------------
+ * Form_pg_publication_rel corresponds to a pointer to a tuple with
+ * the format of pg_publication_rel relation.
+ * ----------------
+ */
+typedef FormData_pg_publication_rel *Form_pg_publication_rel;
+
+#endif /* PG_PUBLICATION_REL_H */
diff --git a/src/include/catalog/pg_range.dat b/src/include/catalog/pg_range.dat
new file mode 100644
index 0000000..479754c
--- /dev/null
+++ b/src/include/catalog/pg_range.dat
@@ -0,0 +1,31 @@
+#----------------------------------------------------------------------
+#
+# pg_range.dat
+# Initial contents of the pg_range system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_range.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+{ rngtypid => 'int4range', rngsubtype => 'int4', rngsubopc => 'btree/int4_ops',
+ rngcanonical => 'int4range_canonical', rngsubdiff => 'int4range_subdiff' },
+{ rngtypid => 'numrange', rngsubtype => 'numeric',
+ rngsubopc => 'btree/numeric_ops', rngcanonical => '-',
+ rngsubdiff => 'numrange_subdiff' },
+{ rngtypid => 'tsrange', rngsubtype => 'timestamp',
+ rngsubopc => 'btree/timestamp_ops', rngcanonical => '-',
+ rngsubdiff => 'tsrange_subdiff' },
+{ rngtypid => 'tstzrange', rngsubtype => 'timestamptz',
+ rngsubopc => 'btree/timestamptz_ops', rngcanonical => '-',
+ rngsubdiff => 'tstzrange_subdiff' },
+{ rngtypid => 'daterange', rngsubtype => 'date', rngsubopc => 'btree/date_ops',
+ rngcanonical => 'daterange_canonical', rngsubdiff => 'daterange_subdiff' },
+{ rngtypid => 'int8range', rngsubtype => 'int8', rngsubopc => 'btree/int8_ops',
+ rngcanonical => 'int8range_canonical', rngsubdiff => 'int8range_subdiff' },
+
+]
diff --git a/src/include/catalog/pg_range.h b/src/include/catalog/pg_range.h
new file mode 100644
index 0000000..98172bb
--- /dev/null
+++ b/src/include/catalog/pg_range.h
@@ -0,0 +1,66 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_range.h
+ * definition of the "range type" system catalog (pg_range)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_range.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_RANGE_H
+#define PG_RANGE_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_range_d.h"
+
+/* ----------------
+ * pg_range definition. cpp turns this into
+ * typedef struct FormData_pg_range
+ * ----------------
+ */
+CATALOG(pg_range,3541,RangeRelationId)
+{
+ /* OID of owning range type */
+ Oid rngtypid BKI_LOOKUP(pg_type);
+
+ /* OID of range's element type (subtype) */
+ Oid rngsubtype BKI_LOOKUP(pg_type);
+
+ /* collation for this range type, or 0 */
+ Oid rngcollation BKI_DEFAULT(0);
+
+ /* subtype's btree opclass */
+ Oid rngsubopc BKI_LOOKUP(pg_opclass);
+
+ /* canonicalize range, or 0 */
+ regproc rngcanonical BKI_LOOKUP(pg_proc);
+
+ /* subtype difference as a float8, or 0 */
+ regproc rngsubdiff BKI_LOOKUP(pg_proc);
+} FormData_pg_range;
+
+/* ----------------
+ * Form_pg_range corresponds to a pointer to a tuple with
+ * the format of pg_range relation.
+ * ----------------
+ */
+typedef FormData_pg_range *Form_pg_range;
+
+/*
+ * prototypes for functions in pg_range.c
+ */
+
+extern void RangeCreate(Oid rangeTypeOid, Oid rangeSubType, Oid rangeCollation,
+ Oid rangeSubOpclass, RegProcedure rangeCanonical,
+ RegProcedure rangeSubDiff);
+extern void RangeDelete(Oid rangeTypeOid);
+
+#endif /* PG_RANGE_H */
diff --git a/src/include/catalog/pg_replication_origin.h b/src/include/catalog/pg_replication_origin.h
new file mode 100644
index 0000000..7477ce4
--- /dev/null
+++ b/src/include/catalog/pg_replication_origin.h
@@ -0,0 +1,57 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_replication_origin.h
+ * definition of the "replication origin" system catalog
+ * (pg_replication_origin)
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_replication_origin.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_REPLICATION_ORIGIN_H
+#define PG_REPLICATION_ORIGIN_H
+
+#include "access/xlogdefs.h"
+#include "catalog/genbki.h"
+#include "catalog/pg_replication_origin_d.h"
+
+/* ----------------
+ * pg_replication_origin. cpp turns this into
+ * typedef struct FormData_pg_replication_origin
+ * ----------------
+ */
+CATALOG(pg_replication_origin,6000,ReplicationOriginRelationId) BKI_SHARED_RELATION
+{
+ /*
+ * Locally known id that get included into WAL.
+ *
+ * This should never leave the system.
+ *
+ * Needs to fit into an uint16, so we don't waste too much space in WAL
+ * records. For this reason we don't use a normal Oid column here, since
+ * we need to handle allocation of new values manually.
+ */
+ Oid roident;
+
+ /*
+ * Variable-length fields start here, but we allow direct access to
+ * roname.
+ */
+
+ /* external, free-format, name */
+ text roname BKI_FORCE_NOT_NULL;
+
+#ifdef CATALOG_VARLEN /* further variable-length fields */
+#endif
+} FormData_pg_replication_origin;
+
+typedef FormData_pg_replication_origin *Form_pg_replication_origin;
+
+#endif /* PG_REPLICATION_ORIGIN_H */
diff --git a/src/include/catalog/pg_rewrite.h b/src/include/catalog/pg_rewrite.h
new file mode 100644
index 0000000..4369fc8
--- /dev/null
+++ b/src/include/catalog/pg_rewrite.h
@@ -0,0 +1,54 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_rewrite.h
+ * definition of the "rewrite rule" system catalog (pg_rewrite)
+ *
+ * As of Postgres 7.3, the primary key for this table is <ev_class, rulename>
+ * --- ie, rule names are only unique among the rules of a given table.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_rewrite.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_REWRITE_H
+#define PG_REWRITE_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_rewrite_d.h"
+
+/* ----------------
+ * pg_rewrite definition. cpp turns this into
+ * typedef struct FormData_pg_rewrite
+ * ----------------
+ */
+CATALOG(pg_rewrite,2618,RewriteRelationId)
+{
+ Oid oid; /* oid */
+ NameData rulename;
+ Oid ev_class;
+ char ev_type;
+ char ev_enabled;
+ bool is_instead;
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ pg_node_tree ev_qual BKI_FORCE_NOT_NULL;
+ pg_node_tree ev_action BKI_FORCE_NOT_NULL;
+#endif
+} FormData_pg_rewrite;
+
+/* ----------------
+ * Form_pg_rewrite corresponds to a pointer to a tuple with
+ * the format of pg_rewrite relation.
+ * ----------------
+ */
+typedef FormData_pg_rewrite *Form_pg_rewrite;
+
+#endif /* PG_REWRITE_H */
diff --git a/src/include/catalog/pg_seclabel.h b/src/include/catalog/pg_seclabel.h
new file mode 100644
index 0000000..07d4bff
--- /dev/null
+++ b/src/include/catalog/pg_seclabel.h
@@ -0,0 +1,40 @@
+/* -------------------------------------------------------------------------
+ *
+ * pg_seclabel.h
+ * definition of the "security label" system catalog (pg_seclabel)
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_seclabel.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ * -------------------------------------------------------------------------
+ */
+#ifndef PG_SECLABEL_H
+#define PG_SECLABEL_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_seclabel_d.h"
+
+/* ----------------
+ * pg_seclabel definition. cpp turns this into
+ * typedef struct FormData_pg_seclabel
+ * ----------------
+ */
+CATALOG(pg_seclabel,3596,SecLabelRelationId)
+{
+ Oid objoid; /* OID of the object itself */
+ Oid classoid; /* OID of table containing the object */
+ int32 objsubid; /* column number, or 0 if not used */
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ text provider BKI_FORCE_NOT_NULL; /* name of label provider */
+ text label BKI_FORCE_NOT_NULL; /* security label of the object */
+#endif
+} FormData_pg_seclabel;
+
+#endif /* PG_SECLABEL_H */
diff --git a/src/include/catalog/pg_sequence.h b/src/include/catalog/pg_sequence.h
new file mode 100644
index 0000000..9459edd
--- /dev/null
+++ b/src/include/catalog/pg_sequence.h
@@ -0,0 +1,42 @@
+/* -------------------------------------------------------------------------
+ *
+ * pg_sequence.h
+ * definition of the "sequence" system catalog (pg_sequence)
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_sequence.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ * -------------------------------------------------------------------------
+ */
+#ifndef PG_SEQUENCE_H
+#define PG_SEQUENCE_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_sequence_d.h"
+
+CATALOG(pg_sequence,2224,SequenceRelationId)
+{
+ Oid seqrelid;
+ Oid seqtypid;
+ int64 seqstart;
+ int64 seqincrement;
+ int64 seqmax;
+ int64 seqmin;
+ int64 seqcache;
+ bool seqcycle;
+} FormData_pg_sequence;
+
+/* ----------------
+ * Form_pg_sequence corresponds to a pointer to a tuple with
+ * the format of pg_sequence relation.
+ * ----------------
+ */
+typedef FormData_pg_sequence *Form_pg_sequence;
+
+#endif /* PG_SEQUENCE_H */
diff --git a/src/include/catalog/pg_shdepend.h b/src/include/catalog/pg_shdepend.h
new file mode 100644
index 0000000..7c3fd5b
--- /dev/null
+++ b/src/include/catalog/pg_shdepend.h
@@ -0,0 +1,72 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_shdepend.h
+ * definition of the "shared dependency" system catalog (pg_shdepend)
+ *
+ * pg_shdepend has no preloaded contents, so there is no pg_shdepend.dat
+ * file; system-defined dependencies are loaded into it during a late stage
+ * of the initdb process.
+ *
+ * NOTE: we do not represent all possible dependency pairs in pg_shdepend;
+ * for example, there's not much value in creating an explicit dependency
+ * from a relation to its database. Currently, only dependencies on roles
+ * are explicitly stored in pg_shdepend.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_shdepend.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_SHDEPEND_H
+#define PG_SHDEPEND_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_shdepend_d.h"
+
+/* ----------------
+ * pg_shdepend definition. cpp turns this into
+ * typedef struct FormData_pg_shdepend
+ * ----------------
+ */
+CATALOG(pg_shdepend,1214,SharedDependRelationId) BKI_SHARED_RELATION
+{
+ /*
+ * Identification of the dependent (referencing) object.
+ *
+ * These fields are all zeroes for a DEPENDENCY_PIN entry. Also, dbid can
+ * be zero to denote a shared object.
+ */
+ Oid dbid; /* OID of database containing object */
+ Oid classid; /* OID of table containing object */
+ Oid objid; /* OID of object itself */
+ int32 objsubid; /* column number, or 0 if not used */
+
+ /*
+ * Identification of the independent (referenced) object. This is always
+ * a shared object, so we need no database ID field. We don't bother with
+ * a sub-object ID either.
+ */
+ Oid refclassid; /* OID of table containing object */
+ Oid refobjid; /* OID of object itself */
+
+ /*
+ * Precise semantics of the relationship are specified by the deptype
+ * field. See SharedDependencyType in catalog/dependency.h.
+ */
+ char deptype; /* see codes in dependency.h */
+} FormData_pg_shdepend;
+
+/* ----------------
+ * Form_pg_shdepend corresponds to a pointer to a row with
+ * the format of pg_shdepend relation.
+ * ----------------
+ */
+typedef FormData_pg_shdepend *Form_pg_shdepend;
+
+#endif /* PG_SHDEPEND_H */
diff --git a/src/include/catalog/pg_shdescription.h b/src/include/catalog/pg_shdescription.h
new file mode 100644
index 0000000..a8238aa
--- /dev/null
+++ b/src/include/catalog/pg_shdescription.h
@@ -0,0 +1,58 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_shdescription.h
+ * definition of the "shared description" system catalog
+ * (pg_shdescription)
+ *
+ * Because the contents of this table are taken from the *.dat files
+ * of other catalogs, there is no pg_shdescription.dat file. The initial
+ * contents are assembled by genbki.pl and loaded during initdb.
+ *
+ * NOTE: an object is identified by the OID of the row that primarily
+ * defines the object, plus the OID of the table that that row appears in.
+ * For example, a database is identified by the OID of its pg_database row
+ * plus the pg_class OID of table pg_database. This allows unique
+ * identification of objects without assuming that OIDs are unique
+ * across tables.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_shdescription.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_SHDESCRIPTION_H
+#define PG_SHDESCRIPTION_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_shdescription_d.h"
+
+/* ----------------
+ * pg_shdescription definition. cpp turns this into
+ * typedef struct FormData_pg_shdescription
+ * ----------------
+ */
+CATALOG(pg_shdescription,2396,SharedDescriptionRelationId) BKI_SHARED_RELATION
+{
+ Oid objoid; /* OID of object itself */
+ Oid classoid; /* OID of table containing object */
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ text description BKI_FORCE_NOT_NULL; /* description of object */
+#endif
+} FormData_pg_shdescription;
+
+/* ----------------
+ * Form_pg_shdescription corresponds to a pointer to a tuple with
+ * the format of pg_shdescription relation.
+ * ----------------
+ */
+typedef FormData_pg_shdescription * Form_pg_shdescription;
+
+#endif /* PG_SHDESCRIPTION_H */
diff --git a/src/include/catalog/pg_shseclabel.h b/src/include/catalog/pg_shseclabel.h
new file mode 100644
index 0000000..331e066
--- /dev/null
+++ b/src/include/catalog/pg_shseclabel.h
@@ -0,0 +1,41 @@
+/* -------------------------------------------------------------------------
+ *
+ * pg_shseclabel.h
+ * definition of the "shared security label" system catalog (pg_shseclabel)
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_shseclabel.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ * -------------------------------------------------------------------------
+ */
+#ifndef PG_SHSECLABEL_H
+#define PG_SHSECLABEL_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_shseclabel_d.h"
+
+/* ----------------
+ * pg_shseclabel definition. cpp turns this into
+ * typedef struct FormData_pg_shseclabel
+ * ----------------
+ */
+CATALOG(pg_shseclabel,3592,SharedSecLabelRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_OID(4066,SharedSecLabelRelation_Rowtype_Id) BKI_SCHEMA_MACRO
+{
+ Oid objoid; /* OID of the shared object itself */
+ Oid classoid; /* OID of table containing the shared object */
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ text provider BKI_FORCE_NOT_NULL; /* name of label provider */
+ text label BKI_FORCE_NOT_NULL; /* security label of the object */
+#endif
+} FormData_pg_shseclabel;
+
+typedef FormData_pg_shseclabel * Form_pg_shseclabel;
+
+#endif /* PG_SHSECLABEL_H */
diff --git a/src/include/catalog/pg_statistic.h b/src/include/catalog/pg_statistic.h
new file mode 100644
index 0000000..40a7260
--- /dev/null
+++ b/src/include/catalog/pg_statistic.h
@@ -0,0 +1,275 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_statistic.h
+ * definition of the "statistics" system catalog (pg_statistic)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_statistic.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_STATISTIC_H
+#define PG_STATISTIC_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_statistic_d.h"
+
+/* ----------------
+ * pg_statistic definition. cpp turns this into
+ * typedef struct FormData_pg_statistic
+ * ----------------
+ */
+CATALOG(pg_statistic,2619,StatisticRelationId)
+{
+ /* These fields form the unique key for the entry: */
+ Oid starelid; /* relation containing attribute */
+ int16 staattnum; /* attribute (column) stats are for */
+ bool stainherit; /* true if inheritance children are included */
+
+ /* the fraction of the column's entries that are NULL: */
+ float4 stanullfrac;
+
+ /*
+ * stawidth is the average width in bytes of non-null entries. For
+ * fixed-width datatypes this is of course the same as the typlen, but for
+ * var-width types it is more useful. Note that this is the average width
+ * of the data as actually stored, post-TOASTing (eg, for a
+ * moved-out-of-line value, only the size of the pointer object is
+ * counted). This is the appropriate definition for the primary use of
+ * the statistic, which is to estimate sizes of in-memory hash tables of
+ * tuples.
+ */
+ int32 stawidth;
+
+ /* ----------------
+ * stadistinct indicates the (approximate) number of distinct non-null
+ * data values in the column. The interpretation is:
+ * 0 unknown or not computed
+ * > 0 actual number of distinct values
+ * < 0 negative of multiplier for number of rows
+ * The special negative case allows us to cope with columns that are
+ * unique (stadistinct = -1) or nearly so (for example, a column in which
+ * non-null values appear about twice on the average could be represented
+ * by stadistinct = -0.5 if there are no nulls, or -0.4 if 20% of the
+ * column is nulls). Because the number-of-rows statistic in pg_class may
+ * be updated more frequently than pg_statistic is, it's important to be
+ * able to describe such situations as a multiple of the number of rows,
+ * rather than a fixed number of distinct values. But in other cases a
+ * fixed number is correct (eg, a boolean column).
+ * ----------------
+ */
+ float4 stadistinct;
+
+ /* ----------------
+ * To allow keeping statistics on different kinds of datatypes,
+ * we do not hard-wire any particular meaning for the remaining
+ * statistical fields. Instead, we provide several "slots" in which
+ * statistical data can be placed. Each slot includes:
+ * kind integer code identifying kind of data (see below)
+ * op OID of associated operator, if needed
+ * coll OID of relevant collation, or 0 if none
+ * numbers float4 array (for statistical values)
+ * values anyarray (for representations of data values)
+ * The ID, operator, and collation fields are never NULL; they are zeroes
+ * in an unused slot. The numbers and values fields are NULL in an
+ * unused slot, and might also be NULL in a used slot if the slot kind
+ * has no need for one or the other.
+ * ----------------
+ */
+
+ int16 stakind1;
+ int16 stakind2;
+ int16 stakind3;
+ int16 stakind4;
+ int16 stakind5;
+
+ Oid staop1;
+ Oid staop2;
+ Oid staop3;
+ Oid staop4;
+ Oid staop5;
+
+ Oid stacoll1;
+ Oid stacoll2;
+ Oid stacoll3;
+ Oid stacoll4;
+ Oid stacoll5;
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ float4 stanumbers1[1];
+ float4 stanumbers2[1];
+ float4 stanumbers3[1];
+ float4 stanumbers4[1];
+ float4 stanumbers5[1];
+
+ /*
+ * Values in these arrays are values of the column's data type, or of some
+ * related type such as an array element type. We presently have to cheat
+ * quite a bit to allow polymorphic arrays of this kind, but perhaps
+ * someday it'll be a less bogus facility.
+ */
+ anyarray stavalues1;
+ anyarray stavalues2;
+ anyarray stavalues3;
+ anyarray stavalues4;
+ anyarray stavalues5;
+#endif
+} FormData_pg_statistic;
+
+#define STATISTIC_NUM_SLOTS 5
+
+
+/* ----------------
+ * Form_pg_statistic corresponds to a pointer to a tuple with
+ * the format of pg_statistic relation.
+ * ----------------
+ */
+typedef FormData_pg_statistic *Form_pg_statistic;
+
+#ifdef EXPOSE_TO_CLIENT_CODE
+
+/*
+ * Several statistical slot "kinds" are defined by core PostgreSQL, as
+ * documented below. Also, custom data types can define their own "kind"
+ * codes by mutual agreement between a custom typanalyze routine and the
+ * selectivity estimation functions of the type's operators.
+ *
+ * Code reading the pg_statistic relation should not assume that a particular
+ * data "kind" will appear in any particular slot. Instead, search the
+ * stakind fields to see if the desired data is available. (The standard
+ * function get_attstatsslot() may be used for this.)
+ */
+
+/*
+ * The present allocation of "kind" codes is:
+ *
+ * 1-99: reserved for assignment by the core PostgreSQL project
+ * (values in this range will be documented in this file)
+ * 100-199: reserved for assignment by the PostGIS project
+ * (values to be documented in PostGIS documentation)
+ * 200-299: reserved for assignment by the ESRI ST_Geometry project
+ * (values to be documented in ESRI ST_Geometry documentation)
+ * 300-9999: reserved for future public assignments
+ *
+ * For private use you may choose a "kind" code at random in the range
+ * 10000-30000. However, for code that is to be widely disseminated it is
+ * better to obtain a publicly defined "kind" code by request from the
+ * PostgreSQL Global Development Group.
+ */
+
+/*
+ * In a "most common values" slot, staop is the OID of the "=" operator
+ * used to decide whether values are the same or not, and stacoll is the
+ * collation used (same as column's collation). stavalues contains
+ * the K most common non-null values appearing in the column, and stanumbers
+ * contains their frequencies (fractions of total row count). The values
+ * shall be ordered in decreasing frequency. Note that since the arrays are
+ * variable-size, K may be chosen by the statistics collector. Values should
+ * not appear in MCV unless they have been observed to occur more than once;
+ * a unique column will have no MCV slot.
+ */
+#define STATISTIC_KIND_MCV 1
+
+/*
+ * A "histogram" slot describes the distribution of scalar data. staop is
+ * the OID of the "<" operator that describes the sort ordering, and stacoll
+ * is the relevant collation. (In theory more than one histogram could appear,
+ * if a datatype has more than one useful sort operator or we care about more
+ * than one collation. Currently the collation will always be that of the
+ * underlying column.) stavalues contains M (>=2) non-null values that
+ * divide the non-null column data values into M-1 bins of approximately equal
+ * population. The first stavalues item is the MIN and the last is the MAX.
+ * stanumbers is not used and should be NULL. IMPORTANT POINT: if an MCV
+ * slot is also provided, then the histogram describes the data distribution
+ * *after removing the values listed in MCV* (thus, it's a "compressed
+ * histogram" in the technical parlance). This allows a more accurate
+ * representation of the distribution of a column with some very-common
+ * values. In a column with only a few distinct values, it's possible that
+ * the MCV list describes the entire data population; in this case the
+ * histogram reduces to empty and should be omitted.
+ */
+#define STATISTIC_KIND_HISTOGRAM 2
+
+/*
+ * A "correlation" slot describes the correlation between the physical order
+ * of table tuples and the ordering of data values of this column, as seen
+ * by the "<" operator identified by staop with the collation identified by
+ * stacoll. (As with the histogram, more than one entry could theoretically
+ * appear.) stavalues is not used and should be NULL. stanumbers contains
+ * a single entry, the correlation coefficient between the sequence of data
+ * values and the sequence of their actual tuple positions. The coefficient
+ * ranges from +1 to -1.
+ */
+#define STATISTIC_KIND_CORRELATION 3
+
+/*
+ * A "most common elements" slot is similar to a "most common values" slot,
+ * except that it stores the most common non-null *elements* of the column
+ * values. This is useful when the column datatype is an array or some other
+ * type with identifiable elements (for instance, tsvector). staop contains
+ * the equality operator appropriate to the element type, and stacoll
+ * contains the collation to use with it. stavalues contains
+ * the most common element values, and stanumbers their frequencies. Unlike
+ * MCV slots, frequencies are measured as the fraction of non-null rows the
+ * element value appears in, not the frequency of all rows. Also unlike
+ * MCV slots, the values are sorted into the element type's default order
+ * (to support binary search for a particular value). Since this puts the
+ * minimum and maximum frequencies at unpredictable spots in stanumbers,
+ * there are two extra members of stanumbers, holding copies of the minimum
+ * and maximum frequencies. Optionally, there can be a third extra member,
+ * which holds the frequency of null elements (expressed in the same terms:
+ * the fraction of non-null rows that contain at least one null element). If
+ * this member is omitted, the column is presumed to contain no null elements.
+ *
+ * Note: in current usage for tsvector columns, the stavalues elements are of
+ * type text, even though their representation within tsvector is not
+ * exactly text.
+ */
+#define STATISTIC_KIND_MCELEM 4
+
+/*
+ * A "distinct elements count histogram" slot describes the distribution of
+ * the number of distinct element values present in each row of an array-type
+ * column. Only non-null rows are considered, and only non-null elements.
+ * staop contains the equality operator appropriate to the element type,
+ * and stacoll contains the collation to use with it.
+ * stavalues is not used and should be NULL. The last member of stanumbers is
+ * the average count of distinct element values over all non-null rows. The
+ * preceding M (>=2) members form a histogram that divides the population of
+ * distinct-elements counts into M-1 bins of approximately equal population.
+ * The first of these is the minimum observed count, and the last the maximum.
+ */
+#define STATISTIC_KIND_DECHIST 5
+
+/*
+ * A "length histogram" slot describes the distribution of range lengths in
+ * rows of a range-type column. stanumbers contains a single entry, the
+ * fraction of empty ranges. stavalues is a histogram of non-empty lengths, in
+ * a format similar to STATISTIC_KIND_HISTOGRAM: it contains M (>=2) range
+ * values that divide the column data values into M-1 bins of approximately
+ * equal population. The lengths are stored as float8s, as measured by the
+ * range type's subdiff function. Only non-null rows are considered.
+ */
+#define STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM 6
+
+/*
+ * A "bounds histogram" slot is similar to STATISTIC_KIND_HISTOGRAM, but for
+ * a range-type column. stavalues contains M (>=2) range values that divide
+ * the column data values into M-1 bins of approximately equal population.
+ * Unlike a regular scalar histogram, this is actually two histograms combined
+ * into a single array, with the lower bounds of each value forming a
+ * histogram of lower bounds, and the upper bounds a histogram of upper
+ * bounds. Only non-NULL, non-empty ranges are included.
+ */
+#define STATISTIC_KIND_BOUNDS_HISTOGRAM 7
+
+#endif /* EXPOSE_TO_CLIENT_CODE */
+
+#endif /* PG_STATISTIC_H */
diff --git a/src/include/catalog/pg_statistic_ext.h b/src/include/catalog/pg_statistic_ext.h
new file mode 100644
index 0000000..a8cb169
--- /dev/null
+++ b/src/include/catalog/pg_statistic_ext.h
@@ -0,0 +1,74 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_statistic_ext.h
+ * definition of the "extended statistics" system catalog
+ * (pg_statistic_ext)
+ *
+ * Note that pg_statistic_ext contains the definitions of extended statistics
+ * objects, created by CREATE STATISTICS, but not the actual statistical data,
+ * created by running ANALYZE.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_statistic_ext.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_STATISTIC_EXT_H
+#define PG_STATISTIC_EXT_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_statistic_ext_d.h"
+
+/* ----------------
+ * pg_statistic_ext definition. cpp turns this into
+ * typedef struct FormData_pg_statistic_ext
+ * ----------------
+ */
+CATALOG(pg_statistic_ext,3381,StatisticExtRelationId)
+{
+ Oid oid; /* oid */
+
+ Oid stxrelid; /* relation containing attributes */
+
+ /* These two fields form the unique key for the entry: */
+ NameData stxname; /* statistics object name */
+ Oid stxnamespace; /* OID of statistics object's namespace */
+
+ Oid stxowner; /* statistics object's owner */
+ int32 stxstattarget BKI_DEFAULT(-1); /* statistics target */
+
+ /*
+ * variable-length fields start here, but we allow direct access to
+ * stxkeys
+ */
+ int2vector stxkeys; /* array of column keys */
+
+#ifdef CATALOG_VARLEN
+ char stxkind[1] BKI_FORCE_NOT_NULL; /* statistics kinds requested
+ * to build */
+#endif
+
+} FormData_pg_statistic_ext;
+
+/* ----------------
+ * Form_pg_statistic_ext corresponds to a pointer to a tuple with
+ * the format of pg_statistic_ext relation.
+ * ----------------
+ */
+typedef FormData_pg_statistic_ext *Form_pg_statistic_ext;
+
+#ifdef EXPOSE_TO_CLIENT_CODE
+
+#define STATS_EXT_NDISTINCT 'd'
+#define STATS_EXT_DEPENDENCIES 'f'
+#define STATS_EXT_MCV 'm'
+
+#endif /* EXPOSE_TO_CLIENT_CODE */
+
+#endif /* PG_STATISTIC_EXT_H */
diff --git a/src/include/catalog/pg_statistic_ext_data.h b/src/include/catalog/pg_statistic_ext_data.h
new file mode 100644
index 0000000..0ef4ecb
--- /dev/null
+++ b/src/include/catalog/pg_statistic_ext_data.h
@@ -0,0 +1,52 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_statistic_ext_data.h
+ * definition of the "extended statistics data" system catalog
+ * (pg_statistic_ext_data)
+ *
+ * This catalog stores the statistical data for extended statistics objects.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_statistic_ext_data.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_STATISTIC_EXT_DATA_H
+#define PG_STATISTIC_EXT_DATA_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_statistic_ext_data_d.h"
+
+/* ----------------
+ * pg_statistic_ext_data definition. cpp turns this into
+ * typedef struct FormData_pg_statistic_ext_data
+ * ----------------
+ */
+CATALOG(pg_statistic_ext_data,3429,StatisticExtDataRelationId)
+{
+ Oid stxoid; /* statistics object this data is for */
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+
+ pg_ndistinct stxdndistinct; /* ndistinct coefficients (serialized) */
+ pg_dependencies stxddependencies; /* dependencies (serialized) */
+ pg_mcv_list stxdmcv; /* MCV (serialized) */
+
+#endif
+
+} FormData_pg_statistic_ext_data;
+
+/* ----------------
+ * Form_pg_statistic_ext_data corresponds to a pointer to a tuple with
+ * the format of pg_statistic_ext_data relation.
+ * ----------------
+ */
+typedef FormData_pg_statistic_ext_data * Form_pg_statistic_ext_data;
+
+#endif /* PG_STATISTIC_EXT_DATA_H */
diff --git a/src/include/catalog/pg_subscription.h b/src/include/catalog/pg_subscription.h
new file mode 100644
index 0000000..e3288ad
--- /dev/null
+++ b/src/include/catalog/pg_subscription.h
@@ -0,0 +1,89 @@
+/* -------------------------------------------------------------------------
+ *
+ * pg_subscription.h
+ * definition of the "subscription" system catalog (pg_subscription)
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_subscription.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ * -------------------------------------------------------------------------
+ */
+#ifndef PG_SUBSCRIPTION_H
+#define PG_SUBSCRIPTION_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_subscription_d.h"
+
+#include "nodes/pg_list.h"
+
+/* ----------------
+ * pg_subscription definition. cpp turns this into
+ * typedef struct FormData_pg_subscription
+ * ----------------
+ */
+
+/*
+ * Technically, the subscriptions live inside the database, so a shared catalog
+ * seems weird, but the replication launcher process needs to access all of
+ * them to be able to start the workers, so we have to put them in a shared,
+ * nailed catalog.
+ *
+ * NOTE: When adding a column, also update system_views.sql.
+ */
+CATALOG(pg_subscription,6100,SubscriptionRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_OID(6101,SubscriptionRelation_Rowtype_Id) BKI_SCHEMA_MACRO
+{
+ Oid oid; /* oid */
+
+ Oid subdbid; /* Database the subscription is in. */
+ NameData subname; /* Name of the subscription */
+
+ Oid subowner; /* Owner of the subscription */
+
+ bool subenabled; /* True if the subscription is enabled (the
+ * worker should be running) */
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ /* Connection string to the publisher */
+ text subconninfo BKI_FORCE_NOT_NULL;
+
+ /* Slot name on publisher */
+ NameData subslotname BKI_FORCE_NULL;
+
+ /* Synchronous commit setting for worker */
+ text subsynccommit BKI_FORCE_NOT_NULL;
+
+ /* List of publications subscribed to */
+ text subpublications[1] BKI_FORCE_NOT_NULL;
+#endif
+} FormData_pg_subscription;
+
+typedef FormData_pg_subscription *Form_pg_subscription;
+
+typedef struct Subscription
+{
+ Oid oid; /* Oid of the subscription */
+ Oid dbid; /* Oid of the database which subscription is
+ * in */
+ char *name; /* Name of the subscription */
+ Oid owner; /* Oid of the subscription owner */
+ bool enabled; /* Indicates if the subscription is enabled */
+ char *conninfo; /* Connection string to the publisher */
+ char *slotname; /* Name of the replication slot */
+ char *synccommit; /* Synchronous commit setting for worker */
+ List *publications; /* List of publication names to subscribe to */
+} Subscription;
+
+extern Subscription *GetSubscription(Oid subid, bool missing_ok);
+extern void FreeSubscription(Subscription *sub);
+extern Oid get_subscription_oid(const char *subname, bool missing_ok);
+extern char *get_subscription_name(Oid subid, bool missing_ok);
+
+extern int CountDBSubscriptions(Oid dbid);
+
+#endif /* PG_SUBSCRIPTION_H */
diff --git a/src/include/catalog/pg_subscription_rel.h b/src/include/catalog/pg_subscription_rel.h
new file mode 100644
index 0000000..f384f4e
--- /dev/null
+++ b/src/include/catalog/pg_subscription_rel.h
@@ -0,0 +1,90 @@
+/* -------------------------------------------------------------------------
+ *
+ * pg_subscription_rel.h
+ * definition of the system catalog containing the state for each
+ * replicated table in each subscription (pg_subscription_rel)
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_subscription_rel.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ * -------------------------------------------------------------------------
+ */
+#ifndef PG_SUBSCRIPTION_REL_H
+#define PG_SUBSCRIPTION_REL_H
+
+#include "access/xlogdefs.h"
+#include "catalog/genbki.h"
+#include "catalog/pg_subscription_rel_d.h"
+#include "nodes/pg_list.h"
+
+/* ----------------
+ * pg_subscription_rel definition. cpp turns this into
+ * typedef struct FormData_pg_subscription_rel
+ * ----------------
+ */
+CATALOG(pg_subscription_rel,6102,SubscriptionRelRelationId)
+{
+ Oid srsubid; /* Oid of subscription */
+ Oid srrelid; /* Oid of relation */
+ char srsubstate; /* state of the relation in subscription */
+
+ /*
+ * Although srsublsn is a fixed-width type, it is allowed to be NULL, so
+ * we prevent direct C code access to it just as for a varlena field.
+ */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+
+ XLogRecPtr srsublsn BKI_FORCE_NULL; /* remote LSN of the state change
+ * used for synchronization
+ * coordination, or NULL if not
+ * valid */
+#endif
+} FormData_pg_subscription_rel;
+
+typedef FormData_pg_subscription_rel *Form_pg_subscription_rel;
+
+#ifdef EXPOSE_TO_CLIENT_CODE
+
+/* ----------------
+ * substate constants
+ * ----------------
+ */
+#define SUBREL_STATE_INIT 'i' /* initializing (sublsn NULL) */
+#define SUBREL_STATE_DATASYNC 'd' /* data is being synchronized (sublsn
+ * NULL) */
+#define SUBREL_STATE_SYNCDONE 's' /* synchronization finished in front of
+ * apply (sublsn set) */
+#define SUBREL_STATE_READY 'r' /* ready (sublsn set) */
+
+/* These are never stored in the catalog, we only use them for IPC. */
+#define SUBREL_STATE_UNKNOWN '\0' /* unknown state */
+#define SUBREL_STATE_SYNCWAIT 'w' /* waiting for sync */
+#define SUBREL_STATE_CATCHUP 'c' /* catching up with apply */
+
+#endif /* EXPOSE_TO_CLIENT_CODE */
+
+typedef struct SubscriptionRelState
+{
+ Oid relid;
+ XLogRecPtr lsn;
+ char state;
+} SubscriptionRelState;
+
+extern void AddSubscriptionRelState(Oid subid, Oid relid, char state,
+ XLogRecPtr sublsn);
+extern void UpdateSubscriptionRelState(Oid subid, Oid relid, char state,
+ XLogRecPtr sublsn);
+extern char GetSubscriptionRelState(Oid subid, Oid relid,
+ XLogRecPtr *sublsn, bool missing_ok);
+extern void RemoveSubscriptionRel(Oid subid, Oid relid);
+
+extern List *GetSubscriptionRelations(Oid subid);
+extern List *GetSubscriptionNotReadyRelations(Oid subid);
+
+#endif /* PG_SUBSCRIPTION_REL_H */
diff --git a/src/include/catalog/pg_tablespace.dat b/src/include/catalog/pg_tablespace.dat
new file mode 100644
index 0000000..bb0dec0
--- /dev/null
+++ b/src/include/catalog/pg_tablespace.dat
@@ -0,0 +1,22 @@
+#----------------------------------------------------------------------
+#
+# pg_tablespace.dat
+# Initial contents of the pg_tablespace system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_tablespace.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+{ oid => '1663', oid_symbol => 'DEFAULTTABLESPACE_OID',
+ spcname => 'pg_default', spcowner => 'PGUID', spcacl => '_null_',
+ spcoptions => '_null_' },
+{ oid => '1664', oid_symbol => 'GLOBALTABLESPACE_OID',
+ spcname => 'pg_global', spcowner => 'PGUID', spcacl => '_null_',
+ spcoptions => '_null_' },
+
+]
diff --git a/src/include/catalog/pg_tablespace.h b/src/include/catalog/pg_tablespace.h
new file mode 100644
index 0000000..1daf2dd
--- /dev/null
+++ b/src/include/catalog/pg_tablespace.h
@@ -0,0 +1,48 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_tablespace.h
+ * definition of the "tablespace" system catalog (pg_tablespace)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_tablespace.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TABLESPACE_H
+#define PG_TABLESPACE_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_tablespace_d.h"
+
+/* ----------------
+ * pg_tablespace definition. cpp turns this into
+ * typedef struct FormData_pg_tablespace
+ * ----------------
+ */
+CATALOG(pg_tablespace,1213,TableSpaceRelationId) BKI_SHARED_RELATION
+{
+ Oid oid; /* oid */
+ NameData spcname; /* tablespace name */
+ Oid spcowner; /* owner of tablespace */
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ aclitem spcacl[1]; /* access permissions */
+ text spcoptions[1]; /* per-tablespace options */
+#endif
+} FormData_pg_tablespace;
+
+/* ----------------
+ * Form_pg_tablespace corresponds to a pointer to a tuple with
+ * the format of pg_tablespace relation.
+ * ----------------
+ */
+typedef FormData_pg_tablespace *Form_pg_tablespace;
+
+#endif /* PG_TABLESPACE_H */
diff --git a/src/include/catalog/pg_transform.h b/src/include/catalog/pg_transform.h
new file mode 100644
index 0000000..05f3e27
--- /dev/null
+++ b/src/include/catalog/pg_transform.h
@@ -0,0 +1,45 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_transform.h
+ * definition of the "transform" system catalog (pg_transform)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_transform.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TRANSFORM_H
+#define PG_TRANSFORM_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_transform_d.h"
+
+/* ----------------
+ * pg_transform definition. cpp turns this into
+ * typedef struct FormData_pg_transform
+ * ----------------
+ */
+CATALOG(pg_transform,3576,TransformRelationId)
+{
+ Oid oid; /* oid */
+ Oid trftype;
+ Oid trflang;
+ regproc trffromsql;
+ regproc trftosql;
+} FormData_pg_transform;
+
+/* ----------------
+ * Form_pg_transform corresponds to a pointer to a tuple with
+ * the format of pg_transform relation.
+ * ----------------
+ */
+typedef FormData_pg_transform *Form_pg_transform;
+
+#endif /* PG_TRANSFORM_H */
diff --git a/src/include/catalog/pg_trigger.h b/src/include/catalog/pg_trigger.h
new file mode 100644
index 0000000..9612b9b
--- /dev/null
+++ b/src/include/catalog/pg_trigger.h
@@ -0,0 +1,137 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_trigger.h
+ * definition of the "trigger" system catalog (pg_trigger)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_trigger.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TRIGGER_H
+#define PG_TRIGGER_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_trigger_d.h"
+
+/* ----------------
+ * pg_trigger definition. cpp turns this into
+ * typedef struct FormData_pg_trigger
+ *
+ * Note: when tgconstraint is nonzero, tgconstrrelid, tgconstrindid,
+ * tgdeferrable, and tginitdeferred are largely redundant with the referenced
+ * pg_constraint entry. However, it is possible for a non-deferrable trigger
+ * to be associated with a deferrable constraint.
+ * ----------------
+ */
+CATALOG(pg_trigger,2620,TriggerRelationId)
+{
+ Oid oid; /* oid */
+ Oid tgrelid; /* relation trigger is attached to */
+ Oid tgparentid; /* OID of parent trigger, if any */
+ NameData tgname; /* trigger's name */
+ Oid tgfoid; /* OID of function to be called */
+ int16 tgtype; /* BEFORE/AFTER/INSTEAD, UPDATE/DELETE/INSERT,
+ * ROW/STATEMENT; see below */
+ char tgenabled; /* trigger's firing configuration WRT
+ * session_replication_role */
+ bool tgisinternal; /* trigger is system-generated */
+ Oid tgconstrrelid; /* constraint's FROM table, if any */
+ Oid tgconstrindid; /* constraint's supporting index, if any */
+ Oid tgconstraint; /* associated pg_constraint entry, if any */
+ bool tgdeferrable; /* constraint trigger is deferrable */
+ bool tginitdeferred; /* constraint trigger is deferred initially */
+ int16 tgnargs; /* # of extra arguments in tgargs */
+
+ /*
+ * Variable-length fields start here, but we allow direct access to
+ * tgattr. Note: tgattr and tgargs must not be null.
+ */
+ int2vector tgattr; /* column numbers, if trigger is on columns */
+
+#ifdef CATALOG_VARLEN
+ bytea tgargs BKI_FORCE_NOT_NULL; /* first\000second\000tgnargs\000 */
+ pg_node_tree tgqual; /* WHEN expression, or NULL if none */
+ NameData tgoldtable; /* old transition table, or NULL if none */
+ NameData tgnewtable; /* new transition table, or NULL if none */
+#endif
+} FormData_pg_trigger;
+
+/* ----------------
+ * Form_pg_trigger corresponds to a pointer to a tuple with
+ * the format of pg_trigger relation.
+ * ----------------
+ */
+typedef FormData_pg_trigger *Form_pg_trigger;
+
+#ifdef EXPOSE_TO_CLIENT_CODE
+
+/* Bits within tgtype */
+#define TRIGGER_TYPE_ROW (1 << 0)
+#define TRIGGER_TYPE_BEFORE (1 << 1)
+#define TRIGGER_TYPE_INSERT (1 << 2)
+#define TRIGGER_TYPE_DELETE (1 << 3)
+#define TRIGGER_TYPE_UPDATE (1 << 4)
+#define TRIGGER_TYPE_TRUNCATE (1 << 5)
+#define TRIGGER_TYPE_INSTEAD (1 << 6)
+
+#define TRIGGER_TYPE_LEVEL_MASK (TRIGGER_TYPE_ROW)
+#define TRIGGER_TYPE_STATEMENT 0
+
+/* Note bits within TRIGGER_TYPE_TIMING_MASK aren't adjacent */
+#define TRIGGER_TYPE_TIMING_MASK \
+ (TRIGGER_TYPE_BEFORE | TRIGGER_TYPE_INSTEAD)
+#define TRIGGER_TYPE_AFTER 0
+
+#define TRIGGER_TYPE_EVENT_MASK \
+ (TRIGGER_TYPE_INSERT | TRIGGER_TYPE_DELETE | TRIGGER_TYPE_UPDATE | TRIGGER_TYPE_TRUNCATE)
+
+/* Macros for manipulating tgtype */
+#define TRIGGER_CLEAR_TYPE(type) ((type) = 0)
+
+#define TRIGGER_SETT_ROW(type) ((type) |= TRIGGER_TYPE_ROW)
+#define TRIGGER_SETT_STATEMENT(type) ((type) |= TRIGGER_TYPE_STATEMENT)
+#define TRIGGER_SETT_BEFORE(type) ((type) |= TRIGGER_TYPE_BEFORE)
+#define TRIGGER_SETT_AFTER(type) ((type) |= TRIGGER_TYPE_AFTER)
+#define TRIGGER_SETT_INSTEAD(type) ((type) |= TRIGGER_TYPE_INSTEAD)
+#define TRIGGER_SETT_INSERT(type) ((type) |= TRIGGER_TYPE_INSERT)
+#define TRIGGER_SETT_DELETE(type) ((type) |= TRIGGER_TYPE_DELETE)
+#define TRIGGER_SETT_UPDATE(type) ((type) |= TRIGGER_TYPE_UPDATE)
+#define TRIGGER_SETT_TRUNCATE(type) ((type) |= TRIGGER_TYPE_TRUNCATE)
+
+#define TRIGGER_FOR_ROW(type) ((type) & TRIGGER_TYPE_ROW)
+#define TRIGGER_FOR_BEFORE(type) (((type) & TRIGGER_TYPE_TIMING_MASK) == TRIGGER_TYPE_BEFORE)
+#define TRIGGER_FOR_AFTER(type) (((type) & TRIGGER_TYPE_TIMING_MASK) == TRIGGER_TYPE_AFTER)
+#define TRIGGER_FOR_INSTEAD(type) (((type) & TRIGGER_TYPE_TIMING_MASK) == TRIGGER_TYPE_INSTEAD)
+#define TRIGGER_FOR_INSERT(type) ((type) & TRIGGER_TYPE_INSERT)
+#define TRIGGER_FOR_DELETE(type) ((type) & TRIGGER_TYPE_DELETE)
+#define TRIGGER_FOR_UPDATE(type) ((type) & TRIGGER_TYPE_UPDATE)
+#define TRIGGER_FOR_TRUNCATE(type) ((type) & TRIGGER_TYPE_TRUNCATE)
+
+/*
+ * Efficient macro for checking if tgtype matches a particular level
+ * (TRIGGER_TYPE_ROW or TRIGGER_TYPE_STATEMENT), timing (TRIGGER_TYPE_BEFORE,
+ * TRIGGER_TYPE_AFTER or TRIGGER_TYPE_INSTEAD), and event (TRIGGER_TYPE_INSERT,
+ * TRIGGER_TYPE_DELETE, TRIGGER_TYPE_UPDATE, or TRIGGER_TYPE_TRUNCATE). Note
+ * that a tgtype can match more than one event, but only one level or timing.
+ */
+#define TRIGGER_TYPE_MATCHES(type, level, timing, event) \
+ (((type) & (TRIGGER_TYPE_LEVEL_MASK | TRIGGER_TYPE_TIMING_MASK | (event))) == ((level) | (timing) | (event)))
+
+/*
+ * Macro to determine whether tgnewtable or tgoldtable has been specified for
+ * a trigger.
+ */
+#define TRIGGER_USES_TRANSITION_TABLE(namepointer) \
+ ((namepointer) != (char *) NULL)
+
+#endif /* EXPOSE_TO_CLIENT_CODE */
+
+#endif /* PG_TRIGGER_H */
diff --git a/src/include/catalog/pg_ts_config.dat b/src/include/catalog/pg_ts_config.dat
new file mode 100644
index 0000000..4428167
--- /dev/null
+++ b/src/include/catalog/pg_ts_config.dat
@@ -0,0 +1,18 @@
+#----------------------------------------------------------------------
+#
+# pg_ts_config.dat
+# Initial contents of the pg_ts_config system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_ts_config.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+{ oid => '3748', descr => 'simple configuration',
+ cfgname => 'simple', cfgparser => 'default' },
+
+]
diff --git a/src/include/catalog/pg_ts_config.h b/src/include/catalog/pg_ts_config.h
new file mode 100644
index 0000000..0d9c5e3
--- /dev/null
+++ b/src/include/catalog/pg_ts_config.h
@@ -0,0 +1,50 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_ts_config.h
+ * definition of the "text search configuration" system catalog
+ * (pg_ts_config)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_ts_config.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TS_CONFIG_H
+#define PG_TS_CONFIG_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_ts_config_d.h"
+
+/* ----------------
+ * pg_ts_config definition. cpp turns this into
+ * typedef struct FormData_pg_ts_config
+ * ----------------
+ */
+CATALOG(pg_ts_config,3602,TSConfigRelationId)
+{
+ /* oid */
+ Oid oid;
+
+ /* name of configuration */
+ NameData cfgname;
+
+ /* name space */
+ Oid cfgnamespace BKI_DEFAULT(PGNSP);
+
+ /* owner */
+ Oid cfgowner BKI_DEFAULT(PGUID);
+
+ /* OID of parser */
+ Oid cfgparser BKI_LOOKUP(pg_ts_parser);
+} FormData_pg_ts_config;
+
+typedef FormData_pg_ts_config *Form_pg_ts_config;
+
+#endif /* PG_TS_CONFIG_H */
diff --git a/src/include/catalog/pg_ts_config_map.dat b/src/include/catalog/pg_ts_config_map.dat
new file mode 100644
index 0000000..f3a5933
--- /dev/null
+++ b/src/include/catalog/pg_ts_config_map.dat
@@ -0,0 +1,54 @@
+#----------------------------------------------------------------------
+#
+# pg_ts_config_map.dat
+# Initial contents of the pg_ts_config_map system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_ts_config_map.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+{ mapcfg => 'simple', maptokentype => '1', mapseqno => '1',
+ mapdict => 'simple' },
+{ mapcfg => 'simple', maptokentype => '2', mapseqno => '1',
+ mapdict => 'simple' },
+{ mapcfg => 'simple', maptokentype => '3', mapseqno => '1',
+ mapdict => 'simple' },
+{ mapcfg => 'simple', maptokentype => '4', mapseqno => '1',
+ mapdict => 'simple' },
+{ mapcfg => 'simple', maptokentype => '5', mapseqno => '1',
+ mapdict => 'simple' },
+{ mapcfg => 'simple', maptokentype => '6', mapseqno => '1',
+ mapdict => 'simple' },
+{ mapcfg => 'simple', maptokentype => '7', mapseqno => '1',
+ mapdict => 'simple' },
+{ mapcfg => 'simple', maptokentype => '8', mapseqno => '1',
+ mapdict => 'simple' },
+{ mapcfg => 'simple', maptokentype => '9', mapseqno => '1',
+ mapdict => 'simple' },
+{ mapcfg => 'simple', maptokentype => '10', mapseqno => '1',
+ mapdict => 'simple' },
+{ mapcfg => 'simple', maptokentype => '11', mapseqno => '1',
+ mapdict => 'simple' },
+{ mapcfg => 'simple', maptokentype => '15', mapseqno => '1',
+ mapdict => 'simple' },
+{ mapcfg => 'simple', maptokentype => '16', mapseqno => '1',
+ mapdict => 'simple' },
+{ mapcfg => 'simple', maptokentype => '17', mapseqno => '1',
+ mapdict => 'simple' },
+{ mapcfg => 'simple', maptokentype => '18', mapseqno => '1',
+ mapdict => 'simple' },
+{ mapcfg => 'simple', maptokentype => '19', mapseqno => '1',
+ mapdict => 'simple' },
+{ mapcfg => 'simple', maptokentype => '20', mapseqno => '1',
+ mapdict => 'simple' },
+{ mapcfg => 'simple', maptokentype => '21', mapseqno => '1',
+ mapdict => 'simple' },
+{ mapcfg => 'simple', maptokentype => '22', mapseqno => '1',
+ mapdict => 'simple' },
+
+]
diff --git a/src/include/catalog/pg_ts_config_map.h b/src/include/catalog/pg_ts_config_map.h
new file mode 100644
index 0000000..46aef63
--- /dev/null
+++ b/src/include/catalog/pg_ts_config_map.h
@@ -0,0 +1,47 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_ts_config_map.h
+ * definition of the system catalog for text search token mappings
+ * (pg_ts_config_map)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_ts_config_map.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TS_CONFIG_MAP_H
+#define PG_TS_CONFIG_MAP_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_ts_config_map_d.h"
+
+/* ----------------
+ * pg_ts_config_map definition. cpp turns this into
+ * typedef struct FormData_pg_ts_config_map
+ * ----------------
+ */
+CATALOG(pg_ts_config_map,3603,TSConfigMapRelationId)
+{
+ /* OID of configuration owning this entry */
+ Oid mapcfg BKI_LOOKUP(pg_ts_config);
+
+ /* token type from parser */
+ int32 maptokentype;
+
+ /* order in which to consult dictionaries */
+ int32 mapseqno;
+
+ /* dictionary to consult */
+ Oid mapdict BKI_LOOKUP(pg_ts_dict);
+} FormData_pg_ts_config_map;
+
+typedef FormData_pg_ts_config_map *Form_pg_ts_config_map;
+
+#endif /* PG_TS_CONFIG_MAP_H */
diff --git a/src/include/catalog/pg_ts_dict.dat b/src/include/catalog/pg_ts_dict.dat
new file mode 100644
index 0000000..abeec0c
--- /dev/null
+++ b/src/include/catalog/pg_ts_dict.dat
@@ -0,0 +1,19 @@
+#----------------------------------------------------------------------
+#
+# pg_ts_dict.dat
+# Initial contents of the pg_ts_dict system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_ts_dict.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+{ oid => '3765',
+ descr => 'simple dictionary: just lower case and check for stopword',
+ dictname => 'simple', dicttemplate => 'simple', dictinitoption => '_null_' },
+
+]
diff --git a/src/include/catalog/pg_ts_dict.h b/src/include/catalog/pg_ts_dict.h
new file mode 100644
index 0000000..38128a3
--- /dev/null
+++ b/src/include/catalog/pg_ts_dict.h
@@ -0,0 +1,54 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_ts_dict.h
+ * definition of the "text search dictionary" system catalog (pg_ts_dict)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_ts_dict.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TS_DICT_H
+#define PG_TS_DICT_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_ts_dict_d.h"
+
+/* ----------------
+ * pg_ts_dict definition. cpp turns this into
+ * typedef struct FormData_pg_ts_dict
+ * ----------------
+ */
+CATALOG(pg_ts_dict,3600,TSDictionaryRelationId)
+{
+ /* oid */
+ Oid oid;
+
+ /* dictionary name */
+ NameData dictname;
+
+ /* name space */
+ Oid dictnamespace BKI_DEFAULT(PGNSP);
+
+ /* owner */
+ Oid dictowner BKI_DEFAULT(PGUID);
+
+ /* dictionary's template */
+ Oid dicttemplate BKI_LOOKUP(pg_ts_template);
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ /* options passed to dict_init() */
+ text dictinitoption;
+#endif
+} FormData_pg_ts_dict;
+
+typedef FormData_pg_ts_dict *Form_pg_ts_dict;
+
+#endif /* PG_TS_DICT_H */
diff --git a/src/include/catalog/pg_ts_parser.dat b/src/include/catalog/pg_ts_parser.dat
new file mode 100644
index 0000000..f23aa8c
--- /dev/null
+++ b/src/include/catalog/pg_ts_parser.dat
@@ -0,0 +1,20 @@
+#----------------------------------------------------------------------
+#
+# pg_ts_parser.dat
+# Initial contents of the pg_ts_parser system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_ts_parser.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+{ oid => '3722', descr => 'default word parser',
+ prsname => 'default', prsstart => 'prsd_start', prstoken => 'prsd_nexttoken',
+ prsend => 'prsd_end', prsheadline => 'prsd_headline',
+ prslextype => 'prsd_lextype' },
+
+]
diff --git a/src/include/catalog/pg_ts_parser.h b/src/include/catalog/pg_ts_parser.h
new file mode 100644
index 0000000..641c6b6
--- /dev/null
+++ b/src/include/catalog/pg_ts_parser.h
@@ -0,0 +1,57 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_ts_parser.h
+ * definition of the "text search parser" system catalog (pg_ts_parser)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_ts_parser.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TS_PARSER_H
+#define PG_TS_PARSER_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_ts_parser_d.h"
+
+/* ----------------
+ * pg_ts_parser definition. cpp turns this into
+ * typedef struct FormData_pg_ts_parser
+ * ----------------
+ */
+CATALOG(pg_ts_parser,3601,TSParserRelationId)
+{
+ Oid oid; /* oid */
+
+ /* parser's name */
+ NameData prsname;
+
+ /* name space */
+ Oid prsnamespace BKI_DEFAULT(PGNSP);
+
+ /* init parsing session */
+ regproc prsstart BKI_LOOKUP(pg_proc);
+
+ /* return next token */
+ regproc prstoken BKI_LOOKUP(pg_proc);
+
+ /* finalize parsing session */
+ regproc prsend BKI_LOOKUP(pg_proc);
+
+ /* return data for headline creation */
+ regproc prsheadline BKI_LOOKUP(pg_proc);
+
+ /* return descriptions of lexeme's types */
+ regproc prslextype BKI_LOOKUP(pg_proc);
+} FormData_pg_ts_parser;
+
+typedef FormData_pg_ts_parser *Form_pg_ts_parser;
+
+#endif /* PG_TS_PARSER_H */
diff --git a/src/include/catalog/pg_ts_template.dat b/src/include/catalog/pg_ts_template.dat
new file mode 100644
index 0000000..297a8b3
--- /dev/null
+++ b/src/include/catalog/pg_ts_template.dat
@@ -0,0 +1,30 @@
+#----------------------------------------------------------------------
+#
+# pg_ts_template.dat
+# Initial contents of the pg_ts_template system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_ts_template.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+{ oid => '3727',
+ descr => 'simple dictionary: just lower case and check for stopword',
+ tmplname => 'simple', tmplinit => 'dsimple_init',
+ tmpllexize => 'dsimple_lexize' },
+{ oid => '3730', descr => 'synonym dictionary: replace word by its synonym',
+ tmplname => 'synonym', tmplinit => 'dsynonym_init',
+ tmpllexize => 'dsynonym_lexize' },
+{ oid => '3733', descr => 'ispell dictionary',
+ tmplname => 'ispell', tmplinit => 'dispell_init',
+ tmpllexize => 'dispell_lexize' },
+{ oid => '3742',
+ descr => 'thesaurus dictionary: phrase by phrase substitution',
+ tmplname => 'thesaurus', tmplinit => 'thesaurus_init',
+ tmpllexize => 'thesaurus_lexize' },
+
+]
diff --git a/src/include/catalog/pg_ts_template.h b/src/include/catalog/pg_ts_template.h
new file mode 100644
index 0000000..f610225
--- /dev/null
+++ b/src/include/catalog/pg_ts_template.h
@@ -0,0 +1,48 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_ts_template.h
+ * definition of the "text search template" system catalog (pg_ts_template)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_ts_template.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TS_TEMPLATE_H
+#define PG_TS_TEMPLATE_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_ts_template_d.h"
+
+/* ----------------
+ * pg_ts_template definition. cpp turns this into
+ * typedef struct FormData_pg_ts_template
+ * ----------------
+ */
+CATALOG(pg_ts_template,3764,TSTemplateRelationId)
+{
+ Oid oid; /* oid */
+
+ /* template name */
+ NameData tmplname;
+
+ /* name space */
+ Oid tmplnamespace BKI_DEFAULT(PGNSP);
+
+ /* initialization method of dict (may be 0) */
+ regproc tmplinit BKI_LOOKUP(pg_proc);
+
+ /* base method of dictionary */
+ regproc tmpllexize BKI_LOOKUP(pg_proc);
+} FormData_pg_ts_template;
+
+typedef FormData_pg_ts_template *Form_pg_ts_template;
+
+#endif /* PG_TS_TEMPLATE_H */
diff --git a/src/include/catalog/pg_type.dat b/src/include/catalog/pg_type.dat
new file mode 100644
index 0000000..e8be000
--- /dev/null
+++ b/src/include/catalog/pg_type.dat
@@ -0,0 +1,633 @@
+#----------------------------------------------------------------------
+#
+# pg_type.dat
+# Initial contents of the pg_type system catalog.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/pg_type.dat
+#
+#----------------------------------------------------------------------
+
+[
+
+# For types used in the system catalogs, make sure the values here match
+# TypInfo[] in bootstrap.c.
+
+# OID symbol macro names for pg_type OIDs are generated by genbki.pl
+# according to the following rule, so you don't need to specify them
+# here:
+# foo_bar -> FOO_BAROID
+# _foo_bar -> FOO_BARARRAYOID
+#
+# The only oid_symbol entries in this file are for names that don't match
+# this rule, and are grandfathered in.
+
+# To autogenerate an array type, add 'array_type_oid => 'nnnn' to the element
+# type, which will instruct genbki.pl to generate a BKI entry for it.
+# In a few cases, the array type's properties don't match the normal pattern
+# so it can't be autogenerated; in such cases do not write array_type_oid.
+
+# Once upon a time these entries were ordered by OID. Lately it's often
+# been the custom to insert new entries adjacent to related older entries.
+# Try to do one or the other though, don't just insert entries at random.
+
+# OIDS 1 - 99
+
+{ oid => '16', array_type_oid => '1000',
+ descr => 'boolean, \'true\'/\'false\'',
+ typname => 'bool', typlen => '1', typbyval => 't', typcategory => 'B',
+ typispreferred => 't', typinput => 'boolin', typoutput => 'boolout',
+ typreceive => 'boolrecv', typsend => 'boolsend', typalign => 'c' },
+{ oid => '17', array_type_oid => '1001',
+ descr => 'variable-length string, binary values escaped',
+ typname => 'bytea', typlen => '-1', typbyval => 'f', typcategory => 'U',
+ typinput => 'byteain', typoutput => 'byteaout', typreceive => 'bytearecv',
+ typsend => 'byteasend', typalign => 'i', typstorage => 'x' },
+{ oid => '18', array_type_oid => '1002', descr => 'single character',
+ typname => 'char', typlen => '1', typbyval => 't', typcategory => 'S',
+ typinput => 'charin', typoutput => 'charout', typreceive => 'charrecv',
+ typsend => 'charsend', typalign => 'c' },
+{ oid => '19', array_type_oid => '1003',
+ descr => '63-byte type for storing system identifiers',
+ typname => 'name', typlen => 'NAMEDATALEN', typbyval => 'f',
+ typcategory => 'S', typelem => 'char', typinput => 'namein',
+ typoutput => 'nameout', typreceive => 'namerecv', typsend => 'namesend',
+ typalign => 'c', typcollation => 'C' },
+{ oid => '20', array_type_oid => '1016',
+ descr => '~18 digit integer, 8-byte storage',
+ typname => 'int8', typlen => '8', typbyval => 'FLOAT8PASSBYVAL',
+ typcategory => 'N', typinput => 'int8in', typoutput => 'int8out',
+ typreceive => 'int8recv', typsend => 'int8send', typalign => 'd' },
+{ oid => '21', array_type_oid => '1005',
+ descr => '-32 thousand to 32 thousand, 2-byte storage',
+ typname => 'int2', typlen => '2', typbyval => 't', typcategory => 'N',
+ typinput => 'int2in', typoutput => 'int2out', typreceive => 'int2recv',
+ typsend => 'int2send', typalign => 's' },
+{ oid => '22', array_type_oid => '1006',
+ descr => 'array of int2, used in system tables',
+ typname => 'int2vector', typlen => '-1', typbyval => 'f', typcategory => 'A',
+ typelem => 'int2', typinput => 'int2vectorin', typoutput => 'int2vectorout',
+ typreceive => 'int2vectorrecv', typsend => 'int2vectorsend',
+ typalign => 'i' },
+{ oid => '23', array_type_oid => '1007',
+ descr => '-2 billion to 2 billion integer, 4-byte storage',
+ typname => 'int4', typlen => '4', typbyval => 't', typcategory => 'N',
+ typinput => 'int4in', typoutput => 'int4out', typreceive => 'int4recv',
+ typsend => 'int4send', typalign => 'i' },
+{ oid => '24', array_type_oid => '1008', descr => 'registered procedure',
+ typname => 'regproc', typlen => '4', typbyval => 't', typcategory => 'N',
+ typinput => 'regprocin', typoutput => 'regprocout',
+ typreceive => 'regprocrecv', typsend => 'regprocsend', typalign => 'i' },
+{ oid => '25', array_type_oid => '1009',
+ descr => 'variable-length string, no limit specified',
+ typname => 'text', typlen => '-1', typbyval => 'f', typcategory => 'S',
+ typispreferred => 't', typinput => 'textin', typoutput => 'textout',
+ typreceive => 'textrecv', typsend => 'textsend', typalign => 'i',
+ typstorage => 'x', typcollation => 'default' },
+{ oid => '26', array_type_oid => '1028',
+ descr => 'object identifier(oid), maximum 4 billion',
+ typname => 'oid', typlen => '4', typbyval => 't', typcategory => 'N',
+ typispreferred => 't', typinput => 'oidin', typoutput => 'oidout',
+ typreceive => 'oidrecv', typsend => 'oidsend', typalign => 'i' },
+{ oid => '27', array_type_oid => '1010',
+ descr => '(block, offset), physical location of tuple',
+ typname => 'tid', typlen => '6', typbyval => 'f', typcategory => 'U',
+ typinput => 'tidin', typoutput => 'tidout', typreceive => 'tidrecv',
+ typsend => 'tidsend', typalign => 's' },
+{ oid => '28', array_type_oid => '1011', descr => 'transaction id',
+ typname => 'xid', typlen => '4', typbyval => 't', typcategory => 'U',
+ typinput => 'xidin', typoutput => 'xidout', typreceive => 'xidrecv',
+ typsend => 'xidsend', typalign => 'i' },
+{ oid => '29', array_type_oid => '1012',
+ descr => 'command identifier type, sequence in transaction id',
+ typname => 'cid', typlen => '4', typbyval => 't', typcategory => 'U',
+ typinput => 'cidin', typoutput => 'cidout', typreceive => 'cidrecv',
+ typsend => 'cidsend', typalign => 'i' },
+{ oid => '30', array_type_oid => '1013',
+ descr => 'array of oids, used in system tables',
+ typname => 'oidvector', typlen => '-1', typbyval => 'f', typcategory => 'A',
+ typelem => 'oid', typinput => 'oidvectorin', typoutput => 'oidvectorout',
+ typreceive => 'oidvectorrecv', typsend => 'oidvectorsend', typalign => 'i' },
+
+# hand-built rowtype entries for bootstrapped catalogs
+# NB: OIDs assigned here must match the BKI_ROWTYPE_OID declarations
+{ oid => '71',
+ typname => 'pg_type', typlen => '-1', typbyval => 'f', typtype => 'c',
+ typcategory => 'C', typrelid => 'pg_type', typinput => 'record_in',
+ typoutput => 'record_out', typreceive => 'record_recv',
+ typsend => 'record_send', typalign => 'd', typstorage => 'x' },
+{ oid => '75',
+ typname => 'pg_attribute', typlen => '-1', typbyval => 'f', typtype => 'c',
+ typcategory => 'C', typrelid => 'pg_attribute', typinput => 'record_in',
+ typoutput => 'record_out', typreceive => 'record_recv',
+ typsend => 'record_send', typalign => 'd', typstorage => 'x' },
+{ oid => '81',
+ typname => 'pg_proc', typlen => '-1', typbyval => 'f', typtype => 'c',
+ typcategory => 'C', typrelid => 'pg_proc', typinput => 'record_in',
+ typoutput => 'record_out', typreceive => 'record_recv',
+ typsend => 'record_send', typalign => 'd', typstorage => 'x' },
+{ oid => '83',
+ typname => 'pg_class', typlen => '-1', typbyval => 'f', typtype => 'c',
+ typcategory => 'C', typrelid => 'pg_class', typinput => 'record_in',
+ typoutput => 'record_out', typreceive => 'record_recv',
+ typsend => 'record_send', typalign => 'd', typstorage => 'x' },
+
+# OIDS 100 - 199
+
+{ oid => '114', array_type_oid => '199', descr => 'JSON stored as text',
+ typname => 'json', typlen => '-1', typbyval => 'f', typcategory => 'U',
+ typinput => 'json_in', typoutput => 'json_out', typreceive => 'json_recv',
+ typsend => 'json_send', typalign => 'i', typstorage => 'x' },
+{ oid => '142', array_type_oid => '143', descr => 'XML content',
+ typname => 'xml', typlen => '-1', typbyval => 'f', typcategory => 'U',
+ typinput => 'xml_in', typoutput => 'xml_out', typreceive => 'xml_recv',
+ typsend => 'xml_send', typalign => 'i', typstorage => 'x' },
+{ oid => '194', oid_symbol => 'PGNODETREEOID',
+ descr => 'string representing an internal node tree',
+ typname => 'pg_node_tree', typlen => '-1', typbyval => 'f',
+ typcategory => 'S', typinput => 'pg_node_tree_in',
+ typoutput => 'pg_node_tree_out', typreceive => 'pg_node_tree_recv',
+ typsend => 'pg_node_tree_send', typalign => 'i', typstorage => 'x',
+ typcollation => 'default' },
+{ oid => '3361', oid_symbol => 'PGNDISTINCTOID',
+ descr => 'multivariate ndistinct coefficients',
+ typname => 'pg_ndistinct', typlen => '-1', typbyval => 'f',
+ typcategory => 'S', typinput => 'pg_ndistinct_in',
+ typoutput => 'pg_ndistinct_out', typreceive => 'pg_ndistinct_recv',
+ typsend => 'pg_ndistinct_send', typalign => 'i', typstorage => 'x',
+ typcollation => 'default' },
+{ oid => '3402', oid_symbol => 'PGDEPENDENCIESOID',
+ descr => 'multivariate dependencies',
+ typname => 'pg_dependencies', typlen => '-1', typbyval => 'f',
+ typcategory => 'S', typinput => 'pg_dependencies_in',
+ typoutput => 'pg_dependencies_out', typreceive => 'pg_dependencies_recv',
+ typsend => 'pg_dependencies_send', typalign => 'i', typstorage => 'x',
+ typcollation => 'default' },
+{ oid => '5017', oid_symbol => 'PGMCVLISTOID',
+ descr => 'multivariate MCV list',
+ typname => 'pg_mcv_list', typlen => '-1', typbyval => 'f', typcategory => 'S',
+ typinput => 'pg_mcv_list_in', typoutput => 'pg_mcv_list_out',
+ typreceive => 'pg_mcv_list_recv', typsend => 'pg_mcv_list_send',
+ typalign => 'i', typstorage => 'x', typcollation => 'default' },
+{ oid => '32', oid_symbol => 'PGDDLCOMMANDOID',
+ descr => 'internal type for passing CollectedCommand',
+ typname => 'pg_ddl_command', typlen => 'SIZEOF_POINTER', typbyval => 't',
+ typtype => 'p', typcategory => 'P', typinput => 'pg_ddl_command_in',
+ typoutput => 'pg_ddl_command_out', typreceive => 'pg_ddl_command_recv',
+ typsend => 'pg_ddl_command_send', typalign => 'ALIGNOF_POINTER' },
+{ oid => '5069', array_type_oid => '271', descr => 'full transaction id',
+ typname => 'xid8', typlen => '8', typbyval => 'FLOAT8PASSBYVAL',
+ typcategory => 'U', typinput => 'xid8in', typoutput => 'xid8out',
+ typreceive => 'xid8recv', typsend => 'xid8send', typalign => 'd' },
+
+# OIDS 600 - 699
+
+{ oid => '600', array_type_oid => '1017',
+ descr => 'geometric point \'(x, y)\'',
+ typname => 'point', typlen => '16', typbyval => 'f', typcategory => 'G',
+ typelem => 'float8', typinput => 'point_in', typoutput => 'point_out',
+ typreceive => 'point_recv', typsend => 'point_send', typalign => 'd' },
+{ oid => '601', array_type_oid => '1018',
+ descr => 'geometric line segment \'(pt1,pt2)\'',
+ typname => 'lseg', typlen => '32', typbyval => 'f', typcategory => 'G',
+ typelem => 'point', typinput => 'lseg_in', typoutput => 'lseg_out',
+ typreceive => 'lseg_recv', typsend => 'lseg_send', typalign => 'd' },
+{ oid => '602', array_type_oid => '1019',
+ descr => 'geometric path \'(pt1,...)\'',
+ typname => 'path', typlen => '-1', typbyval => 'f', typcategory => 'G',
+ typinput => 'path_in', typoutput => 'path_out', typreceive => 'path_recv',
+ typsend => 'path_send', typalign => 'd', typstorage => 'x' },
+{ oid => '603', array_type_oid => '1020',
+ descr => 'geometric box \'(lower left,upper right)\'',
+ typname => 'box', typlen => '32', typbyval => 'f', typcategory => 'G',
+ typdelim => ';', typelem => 'point', typinput => 'box_in',
+ typoutput => 'box_out', typreceive => 'box_recv', typsend => 'box_send',
+ typalign => 'd' },
+{ oid => '604', array_type_oid => '1027',
+ descr => 'geometric polygon \'(pt1,...)\'',
+ typname => 'polygon', typlen => '-1', typbyval => 'f', typcategory => 'G',
+ typinput => 'poly_in', typoutput => 'poly_out', typreceive => 'poly_recv',
+ typsend => 'poly_send', typalign => 'd', typstorage => 'x' },
+{ oid => '628', array_type_oid => '629', descr => 'geometric line',
+ typname => 'line', typlen => '24', typbyval => 'f', typcategory => 'G',
+ typelem => 'float8', typinput => 'line_in', typoutput => 'line_out',
+ typreceive => 'line_recv', typsend => 'line_send', typalign => 'd' },
+
+# OIDS 700 - 799
+
+{ oid => '700', array_type_oid => '1021',
+ descr => 'single-precision floating point number, 4-byte storage',
+ typname => 'float4', typlen => '4', typbyval => 't', typcategory => 'N',
+ typinput => 'float4in', typoutput => 'float4out', typreceive => 'float4recv',
+ typsend => 'float4send', typalign => 'i' },
+{ oid => '701', array_type_oid => '1022',
+ descr => 'double-precision floating point number, 8-byte storage',
+ typname => 'float8', typlen => '8', typbyval => 'FLOAT8PASSBYVAL',
+ typcategory => 'N', typispreferred => 't', typinput => 'float8in',
+ typoutput => 'float8out', typreceive => 'float8recv', typsend => 'float8send',
+ typalign => 'd' },
+{ oid => '705', descr => 'pseudo-type representing an undetermined type',
+ typname => 'unknown', typlen => '-2', typbyval => 'f', typtype => 'p',
+ typcategory => 'X', typinput => 'unknownin', typoutput => 'unknownout',
+ typreceive => 'unknownrecv', typsend => 'unknownsend', typalign => 'c' },
+{ oid => '718', array_type_oid => '719',
+ descr => 'geometric circle \'(center,radius)\'',
+ typname => 'circle', typlen => '24', typbyval => 'f', typcategory => 'G',
+ typinput => 'circle_in', typoutput => 'circle_out',
+ typreceive => 'circle_recv', typsend => 'circle_send', typalign => 'd' },
+{ oid => '790', oid_symbol => 'CASHOID', array_type_oid => '791',
+ descr => 'monetary amounts, $d,ddd.cc',
+ typname => 'money', typlen => '8', typbyval => 'FLOAT8PASSBYVAL',
+ typcategory => 'N', typinput => 'cash_in', typoutput => 'cash_out',
+ typreceive => 'cash_recv', typsend => 'cash_send', typalign => 'd' },
+
+# OIDS 800 - 899
+
+{ oid => '829', array_type_oid => '1040',
+ descr => 'XX:XX:XX:XX:XX:XX, MAC address',
+ typname => 'macaddr', typlen => '6', typbyval => 'f', typcategory => 'U',
+ typinput => 'macaddr_in', typoutput => 'macaddr_out',
+ typreceive => 'macaddr_recv', typsend => 'macaddr_send', typalign => 'i' },
+{ oid => '869', array_type_oid => '1041',
+ descr => 'IP address/netmask, host address, netmask optional',
+ typname => 'inet', typlen => '-1', typbyval => 'f', typcategory => 'I',
+ typispreferred => 't', typinput => 'inet_in', typoutput => 'inet_out',
+ typreceive => 'inet_recv', typsend => 'inet_send', typalign => 'i',
+ typstorage => 'm' },
+{ oid => '650', array_type_oid => '651',
+ descr => 'network IP address/netmask, network address',
+ typname => 'cidr', typlen => '-1', typbyval => 'f', typcategory => 'I',
+ typinput => 'cidr_in', typoutput => 'cidr_out', typreceive => 'cidr_recv',
+ typsend => 'cidr_send', typalign => 'i', typstorage => 'm' },
+{ oid => '774', array_type_oid => '775',
+ descr => 'XX:XX:XX:XX:XX:XX:XX:XX, MAC address',
+ typname => 'macaddr8', typlen => '8', typbyval => 'f', typcategory => 'U',
+ typinput => 'macaddr8_in', typoutput => 'macaddr8_out',
+ typreceive => 'macaddr8_recv', typsend => 'macaddr8_send', typalign => 'i' },
+
+# OIDS 1000 - 1099
+
+{ oid => '1033', array_type_oid => '1034', descr => 'access control list',
+ typname => 'aclitem', typlen => '12', typbyval => 'f', typcategory => 'U',
+ typinput => 'aclitemin', typoutput => 'aclitemout', typreceive => '-',
+ typsend => '-', typalign => 'i' },
+{ oid => '1042', array_type_oid => '1014',
+ descr => 'char(length), blank-padded string, fixed storage length',
+ typname => 'bpchar', typlen => '-1', typbyval => 'f', typcategory => 'S',
+ typinput => 'bpcharin', typoutput => 'bpcharout', typreceive => 'bpcharrecv',
+ typsend => 'bpcharsend', typmodin => 'bpchartypmodin',
+ typmodout => 'bpchartypmodout', typalign => 'i', typstorage => 'x',
+ typcollation => 'default' },
+{ oid => '1043', array_type_oid => '1015',
+ descr => 'varchar(length), non-blank-padded string, variable storage length',
+ typname => 'varchar', typlen => '-1', typbyval => 'f', typcategory => 'S',
+ typinput => 'varcharin', typoutput => 'varcharout',
+ typreceive => 'varcharrecv', typsend => 'varcharsend',
+ typmodin => 'varchartypmodin', typmodout => 'varchartypmodout',
+ typalign => 'i', typstorage => 'x', typcollation => 'default' },
+{ oid => '1082', array_type_oid => '1182', descr => 'date',
+ typname => 'date', typlen => '4', typbyval => 't', typcategory => 'D',
+ typinput => 'date_in', typoutput => 'date_out', typreceive => 'date_recv',
+ typsend => 'date_send', typalign => 'i' },
+{ oid => '1083', array_type_oid => '1183', descr => 'time of day',
+ typname => 'time', typlen => '8', typbyval => 'FLOAT8PASSBYVAL',
+ typcategory => 'D', typinput => 'time_in', typoutput => 'time_out',
+ typreceive => 'time_recv', typsend => 'time_send', typmodin => 'timetypmodin',
+ typmodout => 'timetypmodout', typalign => 'd' },
+
+# OIDS 1100 - 1199
+
+{ oid => '1114', array_type_oid => '1115', descr => 'date and time',
+ typname => 'timestamp', typlen => '8', typbyval => 'FLOAT8PASSBYVAL',
+ typcategory => 'D', typinput => 'timestamp_in', typoutput => 'timestamp_out',
+ typreceive => 'timestamp_recv', typsend => 'timestamp_send',
+ typmodin => 'timestamptypmodin', typmodout => 'timestamptypmodout',
+ typalign => 'd' },
+{ oid => '1184', array_type_oid => '1185',
+ descr => 'date and time with time zone',
+ typname => 'timestamptz', typlen => '8', typbyval => 'FLOAT8PASSBYVAL',
+ typcategory => 'D', typispreferred => 't', typinput => 'timestamptz_in',
+ typoutput => 'timestamptz_out', typreceive => 'timestamptz_recv',
+ typsend => 'timestamptz_send', typmodin => 'timestamptztypmodin',
+ typmodout => 'timestamptztypmodout', typalign => 'd' },
+{ oid => '1186', array_type_oid => '1187',
+ descr => '@ <number> <units>, time interval',
+ typname => 'interval', typlen => '16', typbyval => 'f', typcategory => 'T',
+ typispreferred => 't', typinput => 'interval_in', typoutput => 'interval_out',
+ typreceive => 'interval_recv', typsend => 'interval_send',
+ typmodin => 'intervaltypmodin', typmodout => 'intervaltypmodout',
+ typalign => 'd' },
+
+# OIDS 1200 - 1299
+
+{ oid => '1266', array_type_oid => '1270',
+ descr => 'time of day with time zone',
+ typname => 'timetz', typlen => '12', typbyval => 'f', typcategory => 'D',
+ typinput => 'timetz_in', typoutput => 'timetz_out',
+ typreceive => 'timetz_recv', typsend => 'timetz_send',
+ typmodin => 'timetztypmodin', typmodout => 'timetztypmodout',
+ typalign => 'd' },
+
+# OIDS 1500 - 1599
+
+{ oid => '1560', array_type_oid => '1561', descr => 'fixed-length bit string',
+ typname => 'bit', typlen => '-1', typbyval => 'f', typcategory => 'V',
+ typinput => 'bit_in', typoutput => 'bit_out', typreceive => 'bit_recv',
+ typsend => 'bit_send', typmodin => 'bittypmodin', typmodout => 'bittypmodout',
+ typalign => 'i', typstorage => 'x' },
+{ oid => '1562', array_type_oid => '1563',
+ descr => 'variable-length bit string',
+ typname => 'varbit', typlen => '-1', typbyval => 'f', typcategory => 'V',
+ typispreferred => 't', typinput => 'varbit_in', typoutput => 'varbit_out',
+ typreceive => 'varbit_recv', typsend => 'varbit_send',
+ typmodin => 'varbittypmodin', typmodout => 'varbittypmodout', typalign => 'i',
+ typstorage => 'x' },
+
+# OIDS 1700 - 1799
+
+{ oid => '1700', array_type_oid => '1231',
+ descr => 'numeric(precision, decimal), arbitrary precision number',
+ typname => 'numeric', typlen => '-1', typbyval => 'f', typcategory => 'N',
+ typinput => 'numeric_in', typoutput => 'numeric_out',
+ typreceive => 'numeric_recv', typsend => 'numeric_send',
+ typmodin => 'numerictypmodin', typmodout => 'numerictypmodout',
+ typalign => 'i', typstorage => 'm' },
+
+{ oid => '1790', array_type_oid => '2201',
+ descr => 'reference to cursor (portal name)',
+ typname => 'refcursor', typlen => '-1', typbyval => 'f', typcategory => 'U',
+ typinput => 'textin', typoutput => 'textout', typreceive => 'textrecv',
+ typsend => 'textsend', typalign => 'i', typstorage => 'x' },
+
+# OIDS 2200 - 2299
+
+{ oid => '2202', array_type_oid => '2207',
+ descr => 'registered procedure (with args)',
+ typname => 'regprocedure', typlen => '4', typbyval => 't', typcategory => 'N',
+ typinput => 'regprocedurein', typoutput => 'regprocedureout',
+ typreceive => 'regprocedurerecv', typsend => 'regproceduresend',
+ typalign => 'i' },
+{ oid => '2203', array_type_oid => '2208', descr => 'registered operator',
+ typname => 'regoper', typlen => '4', typbyval => 't', typcategory => 'N',
+ typinput => 'regoperin', typoutput => 'regoperout',
+ typreceive => 'regoperrecv', typsend => 'regopersend', typalign => 'i' },
+{ oid => '2204', array_type_oid => '2209',
+ descr => 'registered operator (with args)',
+ typname => 'regoperator', typlen => '4', typbyval => 't', typcategory => 'N',
+ typinput => 'regoperatorin', typoutput => 'regoperatorout',
+ typreceive => 'regoperatorrecv', typsend => 'regoperatorsend',
+ typalign => 'i' },
+{ oid => '2205', array_type_oid => '2210', descr => 'registered class',
+ typname => 'regclass', typlen => '4', typbyval => 't', typcategory => 'N',
+ typinput => 'regclassin', typoutput => 'regclassout',
+ typreceive => 'regclassrecv', typsend => 'regclasssend', typalign => 'i' },
+{ oid => '4191', array_type_oid => '4192', descr => 'registered collation',
+ typname => 'regcollation', typlen => '4', typbyval => 't', typcategory => 'N',
+ typinput => 'regcollationin', typoutput => 'regcollationout',
+ typreceive => 'regcollationrecv', typsend => 'regcollationsend',
+ typalign => 'i' },
+{ oid => '2206', array_type_oid => '2211', descr => 'registered type',
+ typname => 'regtype', typlen => '4', typbyval => 't', typcategory => 'N',
+ typinput => 'regtypein', typoutput => 'regtypeout',
+ typreceive => 'regtyperecv', typsend => 'regtypesend', typalign => 'i' },
+{ oid => '4096', array_type_oid => '4097', descr => 'registered role',
+ typname => 'regrole', typlen => '4', typbyval => 't', typcategory => 'N',
+ typinput => 'regrolein', typoutput => 'regroleout',
+ typreceive => 'regrolerecv', typsend => 'regrolesend', typalign => 'i' },
+{ oid => '4089', array_type_oid => '4090', descr => 'registered namespace',
+ typname => 'regnamespace', typlen => '4', typbyval => 't', typcategory => 'N',
+ typinput => 'regnamespacein', typoutput => 'regnamespaceout',
+ typreceive => 'regnamespacerecv', typsend => 'regnamespacesend',
+ typalign => 'i' },
+
+# uuid
+{ oid => '2950', array_type_oid => '2951', descr => 'UUID datatype',
+ typname => 'uuid', typlen => '16', typbyval => 'f', typcategory => 'U',
+ typinput => 'uuid_in', typoutput => 'uuid_out', typreceive => 'uuid_recv',
+ typsend => 'uuid_send', typalign => 'c' },
+
+# pg_lsn
+{ oid => '3220', oid_symbol => 'LSNOID', array_type_oid => '3221',
+ descr => 'PostgreSQL LSN datatype',
+ typname => 'pg_lsn', typlen => '8', typbyval => 'FLOAT8PASSBYVAL',
+ typcategory => 'U', typinput => 'pg_lsn_in', typoutput => 'pg_lsn_out',
+ typreceive => 'pg_lsn_recv', typsend => 'pg_lsn_send', typalign => 'd' },
+
+# text search
+{ oid => '3614', array_type_oid => '3643',
+ descr => 'text representation for text search',
+ typname => 'tsvector', typlen => '-1', typbyval => 'f', typcategory => 'U',
+ typinput => 'tsvectorin', typoutput => 'tsvectorout',
+ typreceive => 'tsvectorrecv', typsend => 'tsvectorsend',
+ typanalyze => 'ts_typanalyze', typalign => 'i', typstorage => 'x' },
+{ oid => '3642', array_type_oid => '3644',
+ descr => 'GiST index internal text representation for text search',
+ typname => 'gtsvector', typlen => '-1', typbyval => 'f', typcategory => 'U',
+ typinput => 'gtsvectorin', typoutput => 'gtsvectorout', typreceive => '-',
+ typsend => '-', typalign => 'i' },
+{ oid => '3615', array_type_oid => '3645',
+ descr => 'query representation for text search',
+ typname => 'tsquery', typlen => '-1', typbyval => 'f', typcategory => 'U',
+ typinput => 'tsqueryin', typoutput => 'tsqueryout',
+ typreceive => 'tsqueryrecv', typsend => 'tsquerysend', typalign => 'i' },
+{ oid => '3734', array_type_oid => '3735',
+ descr => 'registered text search configuration',
+ typname => 'regconfig', typlen => '4', typbyval => 't', typcategory => 'N',
+ typinput => 'regconfigin', typoutput => 'regconfigout',
+ typreceive => 'regconfigrecv', typsend => 'regconfigsend', typalign => 'i' },
+{ oid => '3769', array_type_oid => '3770',
+ descr => 'registered text search dictionary',
+ typname => 'regdictionary', typlen => '4', typbyval => 't',
+ typcategory => 'N', typinput => 'regdictionaryin',
+ typoutput => 'regdictionaryout', typreceive => 'regdictionaryrecv',
+ typsend => 'regdictionarysend', typalign => 'i' },
+
+# jsonb
+{ oid => '3802', array_type_oid => '3807', descr => 'Binary JSON',
+ typname => 'jsonb', typlen => '-1', typbyval => 'f', typcategory => 'U',
+ typinput => 'jsonb_in', typoutput => 'jsonb_out', typreceive => 'jsonb_recv',
+ typsend => 'jsonb_send', typalign => 'i', typstorage => 'x' },
+{ oid => '4072', array_type_oid => '4073', descr => 'JSON path',
+ typname => 'jsonpath', typlen => '-1', typbyval => 'f', typcategory => 'U',
+ typinput => 'jsonpath_in', typoutput => 'jsonpath_out',
+ typreceive => 'jsonpath_recv', typsend => 'jsonpath_send', typalign => 'i',
+ typstorage => 'x' },
+
+{ oid => '2970', array_type_oid => '2949', descr => 'txid snapshot',
+ typname => 'txid_snapshot', typlen => '-1', typbyval => 'f',
+ typcategory => 'U', typinput => 'txid_snapshot_in',
+ typoutput => 'txid_snapshot_out', typreceive => 'txid_snapshot_recv',
+ typsend => 'txid_snapshot_send', typalign => 'd', typstorage => 'x' },
+{ oid => '5038', array_type_oid => '5039', descr => 'snapshot',
+ typname => 'pg_snapshot', typlen => '-1', typbyval => 'f', typcategory => 'U',
+ typinput => 'pg_snapshot_in', typoutput => 'pg_snapshot_out',
+ typreceive => 'pg_snapshot_recv', typsend => 'pg_snapshot_send',
+ typalign => 'd', typstorage => 'x' },
+
+# range types
+{ oid => '3904', array_type_oid => '3905', descr => 'range of integers',
+ typname => 'int4range', typlen => '-1', typbyval => 'f', typtype => 'r',
+ typcategory => 'R', typinput => 'range_in', typoutput => 'range_out',
+ typreceive => 'range_recv', typsend => 'range_send',
+ typanalyze => 'range_typanalyze', typalign => 'i', typstorage => 'x' },
+{ oid => '3906', array_type_oid => '3907', descr => 'range of numerics',
+ typname => 'numrange', typlen => '-1', typbyval => 'f', typtype => 'r',
+ typcategory => 'R', typinput => 'range_in', typoutput => 'range_out',
+ typreceive => 'range_recv', typsend => 'range_send',
+ typanalyze => 'range_typanalyze', typalign => 'i', typstorage => 'x' },
+{ oid => '3908', array_type_oid => '3909',
+ descr => 'range of timestamps without time zone',
+ typname => 'tsrange', typlen => '-1', typbyval => 'f', typtype => 'r',
+ typcategory => 'R', typinput => 'range_in', typoutput => 'range_out',
+ typreceive => 'range_recv', typsend => 'range_send',
+ typanalyze => 'range_typanalyze', typalign => 'd', typstorage => 'x' },
+{ oid => '3910', array_type_oid => '3911',
+ descr => 'range of timestamps with time zone',
+ typname => 'tstzrange', typlen => '-1', typbyval => 'f', typtype => 'r',
+ typcategory => 'R', typinput => 'range_in', typoutput => 'range_out',
+ typreceive => 'range_recv', typsend => 'range_send',
+ typanalyze => 'range_typanalyze', typalign => 'd', typstorage => 'x' },
+{ oid => '3912', array_type_oid => '3913', descr => 'range of dates',
+ typname => 'daterange', typlen => '-1', typbyval => 'f', typtype => 'r',
+ typcategory => 'R', typinput => 'range_in', typoutput => 'range_out',
+ typreceive => 'range_recv', typsend => 'range_send',
+ typanalyze => 'range_typanalyze', typalign => 'i', typstorage => 'x' },
+{ oid => '3926', array_type_oid => '3927', descr => 'range of bigints',
+ typname => 'int8range', typlen => '-1', typbyval => 'f', typtype => 'r',
+ typcategory => 'R', typinput => 'range_in', typoutput => 'range_out',
+ typreceive => 'range_recv', typsend => 'range_send',
+ typanalyze => 'range_typanalyze', typalign => 'd', typstorage => 'x' },
+
+# pseudo-types
+# types with typtype='p' represent various special cases in the type system.
+# These cannot be used to define table columns, but are valid as function
+# argument and result types (if supported by the function's implementation
+# language).
+# Note: cstring is a borderline case; it is still considered a pseudo-type,
+# but there is now support for it in records and arrays. Perhaps we should
+# just treat it as a regular base type?
+
+{ oid => '2249', descr => 'pseudo-type representing any composite type',
+ typname => 'record', typlen => '-1', typbyval => 'f', typtype => 'p',
+ typcategory => 'P', typarray => '_record', typinput => 'record_in',
+ typoutput => 'record_out', typreceive => 'record_recv',
+ typsend => 'record_send', typalign => 'd', typstorage => 'x' },
+# Arrays of records have typcategory P, so they can't be autogenerated.
+{ oid => '2287',
+ typname => '_record', typlen => '-1', typbyval => 'f', typtype => 'p',
+ typcategory => 'P', typelem => 'record', typinput => 'array_in',
+ typoutput => 'array_out', typreceive => 'array_recv', typsend => 'array_send',
+ typanalyze => 'array_typanalyze', typalign => 'd', typstorage => 'x' },
+{ oid => '2275', array_type_oid => '1263', descr => 'C-style string',
+ typname => 'cstring', typlen => '-2', typbyval => 'f', typtype => 'p',
+ typcategory => 'P', typinput => 'cstring_in', typoutput => 'cstring_out',
+ typreceive => 'cstring_recv', typsend => 'cstring_send', typalign => 'c' },
+{ oid => '2276', descr => 'pseudo-type representing any type',
+ typname => 'any', typlen => '4', typbyval => 't', typtype => 'p',
+ typcategory => 'P', typinput => 'any_in', typoutput => 'any_out',
+ typreceive => '-', typsend => '-', typalign => 'i' },
+{ oid => '2277', descr => 'pseudo-type representing a polymorphic array type',
+ typname => 'anyarray', typlen => '-1', typbyval => 'f', typtype => 'p',
+ typcategory => 'P', typinput => 'anyarray_in', typoutput => 'anyarray_out',
+ typreceive => 'anyarray_recv', typsend => 'anyarray_send', typalign => 'd',
+ typstorage => 'x' },
+{ oid => '2278',
+ descr => 'pseudo-type for the result of a function with no real result',
+ typname => 'void', typlen => '4', typbyval => 't', typtype => 'p',
+ typcategory => 'P', typinput => 'void_in', typoutput => 'void_out',
+ typreceive => 'void_recv', typsend => 'void_send', typalign => 'i' },
+{ oid => '2279', descr => 'pseudo-type for the result of a trigger function',
+ typname => 'trigger', typlen => '4', typbyval => 't', typtype => 'p',
+ typcategory => 'P', typinput => 'trigger_in', typoutput => 'trigger_out',
+ typreceive => '-', typsend => '-', typalign => 'i' },
+{ oid => '3838', oid_symbol => 'EVTTRIGGEROID',
+ descr => 'pseudo-type for the result of an event trigger function',
+ typname => 'event_trigger', typlen => '4', typbyval => 't', typtype => 'p',
+ typcategory => 'P', typinput => 'event_trigger_in',
+ typoutput => 'event_trigger_out', typreceive => '-', typsend => '-',
+ typalign => 'i' },
+{ oid => '2280',
+ descr => 'pseudo-type for the result of a language handler function',
+ typname => 'language_handler', typlen => '4', typbyval => 't', typtype => 'p',
+ typcategory => 'P', typinput => 'language_handler_in',
+ typoutput => 'language_handler_out', typreceive => '-', typsend => '-',
+ typalign => 'i' },
+{ oid => '2281',
+ descr => 'pseudo-type representing an internal data structure',
+ typname => 'internal', typlen => 'SIZEOF_POINTER', typbyval => 't',
+ typtype => 'p', typcategory => 'P', typinput => 'internal_in',
+ typoutput => 'internal_out', typreceive => '-', typsend => '-',
+ typalign => 'ALIGNOF_POINTER' },
+{ oid => '2283', descr => 'pseudo-type representing a polymorphic base type',
+ typname => 'anyelement', typlen => '4', typbyval => 't', typtype => 'p',
+ typcategory => 'P', typinput => 'anyelement_in',
+ typoutput => 'anyelement_out', typreceive => '-', typsend => '-',
+ typalign => 'i' },
+{ oid => '2776',
+ descr => 'pseudo-type representing a polymorphic base type that is not an array',
+ typname => 'anynonarray', typlen => '4', typbyval => 't', typtype => 'p',
+ typcategory => 'P', typinput => 'anynonarray_in',
+ typoutput => 'anynonarray_out', typreceive => '-', typsend => '-',
+ typalign => 'i' },
+{ oid => '3500',
+ descr => 'pseudo-type representing a polymorphic base type that is an enum',
+ typname => 'anyenum', typlen => '4', typbyval => 't', typtype => 'p',
+ typcategory => 'P', typinput => 'anyenum_in', typoutput => 'anyenum_out',
+ typreceive => '-', typsend => '-', typalign => 'i' },
+{ oid => '3115',
+ descr => 'pseudo-type for the result of an FDW handler function',
+ typname => 'fdw_handler', typlen => '4', typbyval => 't', typtype => 'p',
+ typcategory => 'P', typinput => 'fdw_handler_in',
+ typoutput => 'fdw_handler_out', typreceive => '-', typsend => '-',
+ typalign => 'i' },
+{ oid => '325',
+ descr => 'pseudo-type for the result of an index AM handler function',
+ typname => 'index_am_handler', typlen => '4', typbyval => 't', typtype => 'p',
+ typcategory => 'P', typinput => 'index_am_handler_in',
+ typoutput => 'index_am_handler_out', typreceive => '-', typsend => '-',
+ typalign => 'i' },
+{ oid => '3310',
+ descr => 'pseudo-type for the result of a tablesample method function',
+ typname => 'tsm_handler', typlen => '4', typbyval => 't', typtype => 'p',
+ typcategory => 'P', typinput => 'tsm_handler_in',
+ typoutput => 'tsm_handler_out', typreceive => '-', typsend => '-',
+ typalign => 'i' },
+{ oid => '269',
+ typname => 'table_am_handler', typlen => '4', typbyval => 't', typtype => 'p',
+ typcategory => 'P', typinput => 'table_am_handler_in',
+ typoutput => 'table_am_handler_out', typreceive => '-', typsend => '-',
+ typalign => 'i' },
+{ oid => '3831',
+ descr => 'pseudo-type representing a range over a polymorphic base type',
+ typname => 'anyrange', typlen => '-1', typbyval => 'f', typtype => 'p',
+ typcategory => 'P', typinput => 'anyrange_in', typoutput => 'anyrange_out',
+ typreceive => '-', typsend => '-', typalign => 'd', typstorage => 'x' },
+{ oid => '5077',
+ descr => 'pseudo-type representing a polymorphic common type',
+ typname => 'anycompatible', typlen => '4', typbyval => 't', typtype => 'p',
+ typcategory => 'P', typinput => 'anycompatible_in',
+ typoutput => 'anycompatible_out', typreceive => '-', typsend => '-',
+ typalign => 'i' },
+{ oid => '5078',
+ descr => 'pseudo-type representing an array of polymorphic common type elements',
+ typname => 'anycompatiblearray', typlen => '-1', typbyval => 'f',
+ typtype => 'p', typcategory => 'P', typinput => 'anycompatiblearray_in',
+ typoutput => 'anycompatiblearray_out',
+ typreceive => 'anycompatiblearray_recv', typsend => 'anycompatiblearray_send',
+ typalign => 'd', typstorage => 'x' },
+{ oid => '5079',
+ descr => 'pseudo-type representing a polymorphic common type that is not an array',
+ typname => 'anycompatiblenonarray', typlen => '4', typbyval => 't',
+ typtype => 'p', typcategory => 'P', typinput => 'anycompatiblenonarray_in',
+ typoutput => 'anycompatiblenonarray_out', typreceive => '-', typsend => '-',
+ typalign => 'i' },
+{ oid => '5080',
+ descr => 'pseudo-type representing a range over a polymorphic common type',
+ typname => 'anycompatiblerange', typlen => '-1', typbyval => 'f',
+ typtype => 'p', typcategory => 'P', typinput => 'anycompatiblerange_in',
+ typoutput => 'anycompatiblerange_out', typreceive => '-', typsend => '-',
+ typalign => 'd', typstorage => 'x' },
+
+]
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
new file mode 100644
index 0000000..7b37562
--- /dev/null
+++ b/src/include/catalog/pg_type.h
@@ -0,0 +1,372 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_type.h
+ * definition of the "type" system catalog (pg_type)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_type.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TYPE_H
+#define PG_TYPE_H
+
+#include "catalog/genbki.h"
+#include "catalog/objectaddress.h"
+#include "catalog/pg_type_d.h"
+#include "nodes/nodes.h"
+
+/* ----------------
+ * pg_type definition. cpp turns this into
+ * typedef struct FormData_pg_type
+ *
+ * Some of the values in a pg_type instance are copied into
+ * pg_attribute instances. Some parts of Postgres use the pg_type copy,
+ * while others use the pg_attribute copy, so they must match.
+ * See struct FormData_pg_attribute for details.
+ * ----------------
+ */
+CATALOG(pg_type,1247,TypeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71,TypeRelation_Rowtype_Id) BKI_SCHEMA_MACRO
+{
+ Oid oid; /* oid */
+
+ /* type name */
+ NameData typname;
+
+ /* OID of namespace containing this type */
+ Oid typnamespace BKI_DEFAULT(PGNSP);
+
+ /* type owner */
+ Oid typowner BKI_DEFAULT(PGUID);
+
+ /*
+ * For a fixed-size type, typlen is the number of bytes we use to
+ * represent a value of this type, e.g. 4 for an int4. But for a
+ * variable-length type, typlen is negative. We use -1 to indicate a
+ * "varlena" type (one that has a length word), -2 to indicate a
+ * null-terminated C string.
+ */
+ int16 typlen BKI_ARRAY_DEFAULT(-1);
+
+ /*
+ * typbyval determines whether internal Postgres routines pass a value of
+ * this type by value or by reference. typbyval had better be false if
+ * the length is not 1, 2, or 4 (or 8 on 8-byte-Datum machines).
+ * Variable-length types are always passed by reference. Note that
+ * typbyval can be false even if the length would allow pass-by-value; for
+ * example, type macaddr8 is pass-by-ref even when Datum is 8 bytes.
+ */
+ bool typbyval BKI_ARRAY_DEFAULT(f);
+
+ /*
+ * typtype is 'b' for a base type, 'c' for a composite type (e.g., a
+ * table's rowtype), 'd' for a domain, 'e' for an enum type, 'p' for a
+ * pseudo-type, or 'r' for a range type. (Use the TYPTYPE macros below.)
+ *
+ * If typtype is 'c', typrelid is the OID of the class' entry in pg_class.
+ */
+ char typtype BKI_DEFAULT(b) BKI_ARRAY_DEFAULT(b);
+
+ /*
+ * typcategory and typispreferred help the parser distinguish preferred
+ * and non-preferred coercions. The category can be any single ASCII
+ * character (but not \0). The categories used for built-in types are
+ * identified by the TYPCATEGORY macros below.
+ */
+
+ /* arbitrary type classification */
+ char typcategory BKI_ARRAY_DEFAULT(A);
+
+ /* is type "preferred" within its category? */
+ bool typispreferred BKI_DEFAULT(f) BKI_ARRAY_DEFAULT(f);
+
+ /*
+ * If typisdefined is false, the entry is only a placeholder (forward
+ * reference). We know the type's name and owner, but not yet anything
+ * else about it.
+ */
+ bool typisdefined BKI_DEFAULT(t);
+
+ /* delimiter for arrays of this type */
+ char typdelim BKI_DEFAULT(',');
+
+ /* associated pg_class OID if a composite type, else 0 */
+ Oid typrelid BKI_DEFAULT(0) BKI_ARRAY_DEFAULT(0) BKI_LOOKUP(pg_class);
+
+ /*
+ * If typelem is not 0 then it identifies another row in pg_type. The
+ * current type can then be subscripted like an array yielding values of
+ * type typelem. A non-zero typelem does not guarantee this type to be a
+ * "real" array type; some ordinary fixed-length types can also be
+ * subscripted (e.g., name, point). Variable-length types can *not* be
+ * turned into pseudo-arrays like that. Hence, the way to determine
+ * whether a type is a "true" array type is if:
+ *
+ * typelem != 0 and typlen == -1.
+ */
+ Oid typelem BKI_DEFAULT(0) BKI_LOOKUP(pg_type);
+
+ /*
+ * If there is a "true" array type having this type as element type,
+ * typarray links to it. Zero if no associated "true" array type.
+ */
+ Oid typarray BKI_DEFAULT(0) BKI_ARRAY_DEFAULT(0) BKI_LOOKUP(pg_type);
+
+ /*
+ * I/O conversion procedures for the datatype.
+ */
+
+ /* text format (required) */
+ regproc typinput BKI_ARRAY_DEFAULT(array_in) BKI_LOOKUP(pg_proc);
+ regproc typoutput BKI_ARRAY_DEFAULT(array_out) BKI_LOOKUP(pg_proc);
+
+ /* binary format (optional) */
+ regproc typreceive BKI_ARRAY_DEFAULT(array_recv) BKI_LOOKUP(pg_proc);
+ regproc typsend BKI_ARRAY_DEFAULT(array_send) BKI_LOOKUP(pg_proc);
+
+ /*
+ * I/O functions for optional type modifiers.
+ */
+ regproc typmodin BKI_DEFAULT(-) BKI_LOOKUP(pg_proc);
+ regproc typmodout BKI_DEFAULT(-) BKI_LOOKUP(pg_proc);
+
+ /*
+ * Custom ANALYZE procedure for the datatype (0 selects the default).
+ */
+ regproc typanalyze BKI_DEFAULT(-) BKI_ARRAY_DEFAULT(array_typanalyze) BKI_LOOKUP(pg_proc);
+
+ /* ----------------
+ * typalign is the alignment required when storing a value of this
+ * type. It applies to storage on disk as well as most
+ * representations of the value inside Postgres. When multiple values
+ * are stored consecutively, such as in the representation of a
+ * complete row on disk, padding is inserted before a datum of this
+ * type so that it begins on the specified boundary. The alignment
+ * reference is the beginning of the first datum in the sequence.
+ *
+ * 'c' = CHAR alignment, ie no alignment needed.
+ * 's' = SHORT alignment (2 bytes on most machines).
+ * 'i' = INT alignment (4 bytes on most machines).
+ * 'd' = DOUBLE alignment (8 bytes on many machines, but by no means all).
+ * (Use the TYPALIGN macros below for these.)
+ *
+ * See include/access/tupmacs.h for the macros that compute these
+ * alignment requirements. Note also that we allow the nominal alignment
+ * to be violated when storing "packed" varlenas; the TOAST mechanism
+ * takes care of hiding that from most code.
+ *
+ * NOTE: for types used in system tables, it is critical that the
+ * size and alignment defined in pg_type agree with the way that the
+ * compiler will lay out the field in a struct representing a table row.
+ * ----------------
+ */
+ char typalign;
+
+ /* ----------------
+ * typstorage tells if the type is prepared for toasting and what
+ * the default strategy for attributes of this type should be.
+ *
+ * 'p' PLAIN type not prepared for toasting
+ * 'e' EXTERNAL external storage possible, don't try to compress
+ * 'x' EXTENDED try to compress and store external if required
+ * 'm' MAIN like 'x' but try to keep in main tuple
+ * (Use the TYPSTORAGE macros below for these.)
+ *
+ * Note that 'm' fields can also be moved out to secondary storage,
+ * but only as a last resort ('e' and 'x' fields are moved first).
+ * ----------------
+ */
+ char typstorage BKI_DEFAULT(p) BKI_ARRAY_DEFAULT(x);
+
+ /*
+ * This flag represents a "NOT NULL" constraint against this datatype.
+ *
+ * If true, the attnotnull column for a corresponding table column using
+ * this datatype will always enforce the NOT NULL constraint.
+ *
+ * Used primarily for domain types.
+ */
+ bool typnotnull BKI_DEFAULT(f);
+
+ /*
+ * Domains use typbasetype to show the base (or domain) type that the
+ * domain is based on. Zero if the type is not a domain.
+ */
+ Oid typbasetype BKI_DEFAULT(0);
+
+ /*
+ * Domains use typtypmod to record the typmod to be applied to their base
+ * type (-1 if base type does not use a typmod). -1 if this type is not a
+ * domain.
+ */
+ int32 typtypmod BKI_DEFAULT(-1);
+
+ /*
+ * typndims is the declared number of dimensions for an array domain type
+ * (i.e., typbasetype is an array type). Otherwise zero.
+ */
+ int32 typndims BKI_DEFAULT(0);
+
+ /*
+ * Collation: 0 if type cannot use collations, nonzero (typically
+ * DEFAULT_COLLATION_OID) for collatable base types, possibly some other
+ * OID for domains over collatable types
+ */
+ Oid typcollation BKI_DEFAULT(0) BKI_LOOKUP(pg_collation);
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+
+ /*
+ * If typdefaultbin is not NULL, it is the nodeToString representation of
+ * a default expression for the type. Currently this is only used for
+ * domains.
+ */
+ pg_node_tree typdefaultbin BKI_DEFAULT(_null_) BKI_ARRAY_DEFAULT(_null_);
+
+ /*
+ * typdefault is NULL if the type has no associated default value. If
+ * typdefaultbin is not NULL, typdefault must contain a human-readable
+ * version of the default expression represented by typdefaultbin. If
+ * typdefaultbin is NULL and typdefault is not, then typdefault is the
+ * external representation of the type's default value, which may be fed
+ * to the type's input converter to produce a constant.
+ */
+ text typdefault BKI_DEFAULT(_null_) BKI_ARRAY_DEFAULT(_null_);
+
+ /*
+ * Access permissions
+ */
+ aclitem typacl[1] BKI_DEFAULT(_null_);
+#endif
+} FormData_pg_type;
+
+/* ----------------
+ * Form_pg_type corresponds to a pointer to a row with
+ * the format of pg_type relation.
+ * ----------------
+ */
+typedef FormData_pg_type *Form_pg_type;
+
+#ifdef EXPOSE_TO_CLIENT_CODE
+
+/*
+ * macros for values of poor-mans-enumerated-type columns
+ */
+#define TYPTYPE_BASE 'b' /* base type (ordinary scalar type) */
+#define TYPTYPE_COMPOSITE 'c' /* composite (e.g., table's rowtype) */
+#define TYPTYPE_DOMAIN 'd' /* domain over another type */
+#define TYPTYPE_ENUM 'e' /* enumerated type */
+#define TYPTYPE_PSEUDO 'p' /* pseudo-type */
+#define TYPTYPE_RANGE 'r' /* range type */
+
+#define TYPCATEGORY_INVALID '\0' /* not an allowed category */
+#define TYPCATEGORY_ARRAY 'A'
+#define TYPCATEGORY_BOOLEAN 'B'
+#define TYPCATEGORY_COMPOSITE 'C'
+#define TYPCATEGORY_DATETIME 'D'
+#define TYPCATEGORY_ENUM 'E'
+#define TYPCATEGORY_GEOMETRIC 'G'
+#define TYPCATEGORY_NETWORK 'I' /* think INET */
+#define TYPCATEGORY_NUMERIC 'N'
+#define TYPCATEGORY_PSEUDOTYPE 'P'
+#define TYPCATEGORY_RANGE 'R'
+#define TYPCATEGORY_STRING 'S'
+#define TYPCATEGORY_TIMESPAN 'T'
+#define TYPCATEGORY_USER 'U'
+#define TYPCATEGORY_BITSTRING 'V' /* er ... "varbit"? */
+#define TYPCATEGORY_UNKNOWN 'X'
+
+#define TYPALIGN_CHAR 'c' /* char alignment (i.e. unaligned) */
+#define TYPALIGN_SHORT 's' /* short alignment (typically 2 bytes) */
+#define TYPALIGN_INT 'i' /* int alignment (typically 4 bytes) */
+#define TYPALIGN_DOUBLE 'd' /* double alignment (often 8 bytes) */
+
+#define TYPSTORAGE_PLAIN 'p' /* type not prepared for toasting */
+#define TYPSTORAGE_EXTERNAL 'e' /* toastable, don't try to compress */
+#define TYPSTORAGE_EXTENDED 'x' /* fully toastable */
+#define TYPSTORAGE_MAIN 'm' /* like 'x' but try to store inline */
+
+/* Is a type OID a polymorphic pseudotype? (Beware of multiple evaluation) */
+#define IsPolymorphicType(typid) \
+ (IsPolymorphicTypeFamily1(typid) || \
+ IsPolymorphicTypeFamily2(typid))
+
+/* Code not part of polymorphic type resolution should not use these macros: */
+#define IsPolymorphicTypeFamily1(typid) \
+ ((typid) == ANYELEMENTOID || \
+ (typid) == ANYARRAYOID || \
+ (typid) == ANYNONARRAYOID || \
+ (typid) == ANYENUMOID || \
+ (typid) == ANYRANGEOID)
+
+#define IsPolymorphicTypeFamily2(typid) \
+ ((typid) == ANYCOMPATIBLEOID || \
+ (typid) == ANYCOMPATIBLEARRAYOID || \
+ (typid) == ANYCOMPATIBLENONARRAYOID || \
+ (typid) == ANYCOMPATIBLERANGEOID)
+
+#endif /* EXPOSE_TO_CLIENT_CODE */
+
+
+extern ObjectAddress TypeShellMake(const char *typeName,
+ Oid typeNamespace,
+ Oid ownerId);
+
+extern ObjectAddress TypeCreate(Oid newTypeOid,
+ const char *typeName,
+ Oid typeNamespace,
+ Oid relationOid,
+ char relationKind,
+ Oid ownerId,
+ int16 internalSize,
+ char typeType,
+ char typeCategory,
+ bool typePreferred,
+ char typDelim,
+ Oid inputProcedure,
+ Oid outputProcedure,
+ Oid receiveProcedure,
+ Oid sendProcedure,
+ Oid typmodinProcedure,
+ Oid typmodoutProcedure,
+ Oid analyzeProcedure,
+ Oid elementType,
+ bool isImplicitArray,
+ Oid arrayType,
+ Oid baseType,
+ const char *defaultTypeValue,
+ char *defaultTypeBin,
+ bool passedByValue,
+ char alignment,
+ char storage,
+ int32 typeMod,
+ int32 typNDims,
+ bool typeNotNull,
+ Oid typeCollation);
+
+extern void GenerateTypeDependencies(HeapTuple typeTuple,
+ Relation typeCatalog,
+ Node *defaultExpr,
+ void *typacl,
+ char relationKind, /* only for relation
+ * rowtypes */
+ bool isImplicitArray,
+ bool isDependentType,
+ bool rebuild);
+
+extern void RenameTypeInternal(Oid typeOid, const char *newTypeName,
+ Oid typeNamespace);
+
+extern char *makeArrayTypeName(const char *typeName, Oid typeNamespace);
+
+extern bool moveArrayTypeName(Oid typeOid, const char *typeName,
+ Oid typeNamespace);
+
+#endif /* PG_TYPE_H */
diff --git a/src/include/catalog/pg_user_mapping.h b/src/include/catalog/pg_user_mapping.h
new file mode 100644
index 0000000..f5ccdb8
--- /dev/null
+++ b/src/include/catalog/pg_user_mapping.h
@@ -0,0 +1,48 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_user_mapping.h
+ * definition of the "user mapping" system catalog (pg_user_mapping)
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/pg_user_mapping.h
+ *
+ * NOTES
+ * The Catalog.pm module reads this file and derives schema
+ * information.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_USER_MAPPING_H
+#define PG_USER_MAPPING_H
+
+#include "catalog/genbki.h"
+#include "catalog/pg_user_mapping_d.h"
+
+/* ----------------
+ * pg_user_mapping definition. cpp turns this into
+ * typedef struct FormData_pg_user_mapping
+ * ----------------
+ */
+CATALOG(pg_user_mapping,1418,UserMappingRelationId)
+{
+ Oid oid; /* oid */
+
+ Oid umuser; /* Id of the user, InvalidOid if PUBLIC is
+ * wanted */
+ Oid umserver; /* server of this mapping */
+
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ text umoptions[1]; /* user mapping options */
+#endif
+} FormData_pg_user_mapping;
+
+/* ----------------
+ * Form_pg_user_mapping corresponds to a pointer to a tuple with
+ * the format of pg_user_mapping relation.
+ * ----------------
+ */
+typedef FormData_pg_user_mapping *Form_pg_user_mapping;
+
+#endif /* PG_USER_MAPPING_H */
diff --git a/src/include/catalog/reformat_dat_file.pl b/src/include/catalog/reformat_dat_file.pl
new file mode 100755
index 0000000..1cadbfd
--- /dev/null
+++ b/src/include/catalog/reformat_dat_file.pl
@@ -0,0 +1,312 @@
+#!/usr/bin/perl
+#----------------------------------------------------------------------
+#
+# reformat_dat_file.pl
+# Perl script that reads in catalog data file(s) and writes out
+# functionally equivalent file(s) in a standard format.
+#
+# In each entry of a reformatted file, metadata fields (if present)
+# come first, with normal attributes starting on the following line,
+# in the same order as the columns of the corresponding catalog.
+# Comments and blank lines are preserved.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/reformat_dat_file.pl
+#
+#----------------------------------------------------------------------
+
+use strict;
+use warnings;
+
+use FindBin;
+use Getopt::Long;
+
+# If you copy this script to somewhere other than src/include/catalog,
+# you'll need to modify this "use lib" or provide a suitable -I switch.
+use lib "$FindBin::RealBin/../../backend/catalog/";
+use Catalog;
+
+# Names of the metadata fields of a catalog entry.
+# Note: oid is a normal column from a storage perspective, but it's more
+# important than the rest, so it's listed first among the metadata fields.
+# Note: line_number is also a metadata field, but we never write it out,
+# so it's not listed here.
+my @METADATA =
+ ('oid', 'oid_symbol', 'array_type_oid', 'descr', 'autogenerated');
+
+# Process command line switches.
+my $output_path = '';
+my $full_tuples = 0;
+
+GetOptions(
+ 'output=s' => \$output_path,
+ 'full-tuples' => \$full_tuples) || usage();
+
+# Sanity check arguments.
+die "No input files.\n" unless @ARGV;
+
+# Make sure output_path ends in a slash.
+if ($output_path ne '' && substr($output_path, -1) ne '/')
+{
+ $output_path .= '/';
+}
+
+# Read all the input files into internal data structures.
+# We pass data file names as arguments and then look for matching
+# headers to parse the schema from.
+my %catalogs;
+my %catalog_data;
+my @catnames;
+foreach my $datfile (@ARGV)
+{
+ $datfile =~ /(.+)\.dat$/
+ or die "Input files need to be data (.dat) files.\n";
+
+ my $header = "$1.h";
+ die "There in no header file corresponding to $datfile"
+ if !-e $header;
+
+ my $catalog = Catalog::ParseHeader($header);
+ my $catname = $catalog->{catname};
+ my $schema = $catalog->{columns};
+
+ push @catnames, $catname;
+ $catalogs{$catname} = $catalog;
+
+ $catalog_data{$catname} = Catalog::ParseData($datfile, $schema, 1);
+}
+
+########################################################################
+# At this point, we have read all the data. If you are modifying this
+# script for bulk editing, this is a good place to build lookup tables,
+# if you need to. In the following example, the "next if !ref $row"
+# check below is a hack to filter out non-hash objects. This is because
+# we build the lookup tables from data that we read using the
+# "preserve_formatting" parameter.
+#
+##Index access method lookup.
+#my %amnames;
+#foreach my $row (@{ $catalog_data{pg_am} })
+#{
+# next if !ref $row;
+# $amnames{$row->{oid}} = $row->{amname};
+#}
+########################################################################
+
+# Write the data.
+foreach my $catname (@catnames)
+{
+ my $catalog = $catalogs{$catname};
+ my @attnames;
+ my $schema = $catalog->{columns};
+
+ foreach my $column (@$schema)
+ {
+ my $attname = $column->{name};
+
+ # We may have ordinary columns at the storage level that we still
+ # want to format as a special value. Exclude these from the column
+ # list so they are not written twice.
+ push @attnames, $attname
+ if !(grep { $_ eq $attname } @METADATA);
+ }
+
+ # Write output files to specified directory.
+ my $datfile = "$output_path$catname.dat";
+ open my $dat, '>', $datfile
+ or die "can't open $datfile: $!";
+
+ foreach my $data (@{ $catalog_data{$catname} })
+ {
+
+ # Hash ref representing a data entry.
+ if (ref $data eq 'HASH')
+ {
+ my %values = %$data;
+
+ ############################################################
+ # At this point we have the full tuple in memory as a hash
+ # and can do any operations we want. As written, it only
+ # removes default values, but this script can be adapted to
+ # do one-off bulk-editing.
+ ############################################################
+
+ if (!$full_tuples)
+ {
+ # If it's an autogenerated entry, drop it completely.
+ next if $values{autogenerated};
+ # Else, just drop any default/computed fields.
+ strip_default_values(\%values, $schema, $catname);
+ }
+
+ print $dat "{";
+
+ # Separate out metadata fields for readability.
+ my $metadata_str = format_hash(\%values, @METADATA);
+ if ($metadata_str)
+ {
+ print $dat $metadata_str;
+
+ # User attributes start on next line.
+ print $dat ",\n ";
+ }
+
+ my $data_str = format_hash(\%values, @attnames);
+ print $dat $data_str;
+ print $dat " },\n";
+ }
+
+ # Preserve blank lines.
+ elsif ($data =~ /^\s*$/)
+ {
+ print $dat "\n";
+ }
+
+ # Preserve comments or brackets that are on their own line.
+ elsif ($data =~ /^\s*(\[|\]|#.*?)\s*$/)
+ {
+ print $dat "$1\n";
+ }
+ }
+ close $dat;
+}
+
+# Remove column values for which there is a matching default,
+# or if the value can be computed from other columns.
+sub strip_default_values
+{
+ my ($row, $schema, $catname) = @_;
+
+ # Delete values that match defaults.
+ foreach my $column (@$schema)
+ {
+ my $attname = $column->{name};
+
+ # It's okay if we have no oid value, since it will be assigned
+ # automatically before bootstrap.
+ die "strip_default_values: $catname.$attname undefined\n"
+ if !defined $row->{$attname} and $attname ne 'oid';
+
+ if (defined $column->{default}
+ and ($row->{$attname} eq $column->{default}))
+ {
+ delete $row->{$attname};
+ }
+ }
+
+ # Delete computed values. See AddDefaultValues() in Catalog.pm.
+ # Note: This must be done after deleting values matching defaults.
+ if ($catname eq 'pg_proc')
+ {
+ delete $row->{pronargs} if defined $row->{proargtypes};
+ }
+
+ # If a pg_type entry has an auto-generated array type, then its
+ # typarray field is a computed value too (see GenerateArrayTypes).
+ if ($catname eq 'pg_type')
+ {
+ delete $row->{typarray} if defined $row->{array_type_oid};
+ }
+
+ return;
+}
+
+# Format the individual elements of a Perl hash into a valid string
+# representation. We do this ourselves, rather than use native Perl
+# facilities, so we can keep control over the exact formatting of the
+# data files.
+sub format_hash
+{
+ my $data = shift;
+ my @orig_attnames = @_;
+
+ # Copy attname to new array if it has a value, so we can determine
+ # the last populated element. We do this because we may have default
+ # values or empty metadata fields.
+ my @attnames;
+ foreach my $orig_attname (@orig_attnames)
+ {
+ push @attnames, $orig_attname
+ if defined $data->{$orig_attname};
+ }
+
+ # When calling this function, we ether have an open-bracket or a
+ # leading space already.
+ my $char_count = 1;
+
+ my $threshold;
+ my $hash_str = '';
+ my $element_count = 0;
+
+ foreach my $attname (@attnames)
+ {
+ $element_count++;
+
+ # To limit the line to 80 chars, we need to account for the
+ # trailing characters.
+ if ($element_count == $#attnames + 1)
+ {
+ # Last element, so allow space for ' },'
+ $threshold = 77;
+ }
+ else
+ {
+ # Just need space for trailing comma
+ $threshold = 79;
+ }
+
+ if ($element_count > 1)
+ {
+ $hash_str .= ',';
+ $char_count++;
+ }
+
+ my $value = $data->{$attname};
+
+ # Escape single quotes.
+ $value =~ s/'/\\'/g;
+
+ # Include a leading space in the key-value pair, since this will
+ # always go after either a comma or an additional padding space on
+ # the next line.
+ my $element = " $attname => '$value'";
+ my $element_length = length($element);
+
+ # If adding the element to the current line would expand the line
+ # beyond 80 chars, put it on the next line. We don't do this for
+ # the first element, since that would create a blank line.
+ if ($element_count > 1 and $char_count + $element_length > $threshold)
+ {
+
+ # Put on next line with an additional space preceding. There
+ # are now two spaces in front of the key-value pair, lining
+ # it up with the line above it.
+ $hash_str .= "\n $element";
+ $char_count = $element_length + 1;
+ }
+ else
+ {
+ $hash_str .= $element;
+ $char_count += $element_length;
+ }
+ }
+ return $hash_str;
+}
+
+sub usage
+{
+ die <<EOM;
+Usage: reformat_dat_file.pl [options] datafile...
+
+Options:
+ --output PATH output directory (default '.')
+ --full-tuples write out full tuples, including default values
+
+Non-option arguments are the names of input .dat files.
+Updated files are written to the output directory,
+possibly overwriting the input files.
+
+EOM
+}
diff --git a/src/include/catalog/renumber_oids.pl b/src/include/catalog/renumber_oids.pl
new file mode 100755
index 0000000..690869d
--- /dev/null
+++ b/src/include/catalog/renumber_oids.pl
@@ -0,0 +1,291 @@
+#!/usr/bin/perl
+#----------------------------------------------------------------------
+#
+# renumber_oids.pl
+# Perl script that shifts a range of OIDs in the Postgres catalog data
+# to a different range, skipping any OIDs that are already in use.
+#
+# Note: This does not reformat the .dat files, so you may want
+# to run reformat_dat_file.pl afterwards.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/renumber_oids.pl
+#
+#----------------------------------------------------------------------
+
+use strict;
+use warnings;
+
+use FindBin;
+use Getopt::Long;
+
+# Must run in src/include/catalog
+chdir $FindBin::RealBin or die "could not cd to $FindBin::RealBin: $!\n";
+
+use lib "$FindBin::RealBin/../../backend/catalog/";
+use Catalog;
+
+# We'll need this number.
+my $FirstGenbkiObjectId =
+ Catalog::FindDefinedSymbol('access/transam.h', '..', 'FirstGenbkiObjectId');
+
+# Process command line switches.
+my $output_path = '';
+my $first_mapped_oid = 0;
+my $last_mapped_oid = $FirstGenbkiObjectId - 1;
+my $target_oid = 0;
+
+GetOptions(
+ 'output=s' => \$output_path,
+ 'first-mapped-oid=i' => \$first_mapped_oid,
+ 'last-mapped-oid=i' => \$last_mapped_oid,
+ 'target-oid=i' => \$target_oid) || usage();
+
+# Sanity check arguments.
+die "Unexpected non-switch arguments.\n" if @ARGV;
+die "--first-mapped-oid must be specified.\n"
+ if $first_mapped_oid <= 0;
+die "Empty mapped OID range.\n"
+ if $last_mapped_oid < $first_mapped_oid;
+die "--target-oid must be specified.\n"
+ if $target_oid <= 0;
+die "--target-oid must not be within mapped OID range.\n"
+ if $target_oid >= $first_mapped_oid && $target_oid <= $last_mapped_oid;
+
+# Make sure output_path ends in a slash.
+if ($output_path ne '' && substr($output_path, -1) ne '/')
+{
+ $output_path .= '/';
+}
+
+# Collect all the existing assigned OIDs (including those to be remapped).
+my @header_files = (glob("pg_*.h"), qw(indexing.h toasting.h));
+my $oids = Catalog::FindAllOidsFromHeaders(@header_files);
+
+# Hash-ify the existing OIDs for convenient lookup.
+my %oidhash;
+@oidhash{@$oids} = undef;
+
+# Select new OIDs for existing OIDs in the mapped range.
+# We do this first so that we preserve the ordering of the mapped OIDs
+# (for reproducibility's sake), and so that if we fail due to running out
+# of OID room, that happens before we've overwritten any files.
+my %maphash;
+my $next_oid = $target_oid;
+
+for (
+ my $mapped_oid = $first_mapped_oid;
+ $mapped_oid <= $last_mapped_oid;
+ $mapped_oid++)
+{
+ next if !exists $oidhash{$mapped_oid};
+ $next_oid++
+ while (
+ exists $oidhash{$next_oid}
+ || ( $next_oid >= $first_mapped_oid
+ && $next_oid <= $last_mapped_oid));
+ die "Reached FirstGenbkiObjectId before assigning all OIDs.\n"
+ if $next_oid >= $FirstGenbkiObjectId;
+ $maphash{$mapped_oid} = $next_oid;
+ $next_oid++;
+}
+
+die "There are no OIDs in the mapped range.\n" if $next_oid == $target_oid;
+
+# Read each .h file and write out modified data.
+foreach my $input_file (@header_files)
+{
+ $input_file =~ /(\w+)\.h$/
+ or die "Input file $input_file needs to be a .h file.\n";
+ my $catname = $1;
+
+ # Ignore generated *_d.h files.
+ next if $catname =~ /_d$/;
+
+ open(my $ifd, '<', $input_file) || die "$input_file: $!";
+
+ # Write output files to specified directory.
+ # Use a .tmp suffix, then rename into place, in case we're overwriting.
+ my $output_file = "$output_path$catname.h";
+ my $tmp_output_file = "$output_file.tmp";
+ open my $ofd, '>', $tmp_output_file
+ or die "can't open $tmp_output_file: $!";
+ my $changed = 0;
+
+ # Scan the input file.
+ while (<$ifd>)
+ {
+ my $line = $_;
+
+ # Check for OID-defining macros that Catalog::ParseHeader knows about,
+ # and update OIDs as needed.
+ if ($line =~ m/^(DECLARE_TOAST\(\s*\w+,\s*)(\d+)(,\s*)(\d+)\)/)
+ {
+ my $oid2 = $2;
+ my $oid4 = $4;
+ if (exists $maphash{$oid2})
+ {
+ $oid2 = $maphash{$oid2};
+ my $repl = $1 . $oid2 . $3 . $oid4 . ")";
+ $line =~ s/^DECLARE_TOAST\(\s*\w+,\s*\d+,\s*\d+\)/$repl/;
+ $changed = 1;
+ }
+ if (exists $maphash{$oid4})
+ {
+ $oid4 = $maphash{$oid4};
+ my $repl = $1 . $oid2 . $3 . $oid4 . ")";
+ $line =~ s/^DECLARE_TOAST\(\s*\w+,\s*\d+,\s*\d+\)/$repl/;
+ $changed = 1;
+ }
+ }
+ elsif (
+ $line =~ m/^(DECLARE_(UNIQUE_)?INDEX\(\s*\w+,\s*)(\d+)(,\s*.+)\)/)
+ {
+ if (exists $maphash{$3})
+ {
+ my $repl = $1 . $maphash{$3} . $4 . ")";
+ $line =~
+ s/^DECLARE_(UNIQUE_)?INDEX\(\s*\w+,\s*\d+,\s*.+\)/$repl/;
+ $changed = 1;
+ }
+ }
+ elsif ($line =~ m/^CATALOG\((\w+),(\d+),(\w+)\)/)
+ {
+ if (exists $maphash{$2})
+ {
+ my $repl =
+ "CATALOG(" . $1 . "," . $maphash{$2} . "," . $3 . ")";
+ $line =~ s/^CATALOG\(\w+,\d+,\w+\)/$repl/;
+ $changed = 1;
+ }
+
+ if ($line =~ m/BKI_ROWTYPE_OID\((\d+),(\w+)\)/)
+ {
+ if (exists $maphash{$1})
+ {
+ my $repl =
+ "BKI_ROWTYPE_OID(" . $maphash{$1} . "," . $2 . ")";
+ $line =~ s/BKI_ROWTYPE_OID\(\d+,\w+\)/$repl/;
+ $changed = 1;
+ }
+ }
+ }
+
+ # In indexing.h and toasting.h only, check for #define SYM nnnn,
+ # and replace if within mapped range.
+ elsif ($line =~ m/^(\s*#\s*define\s+\w+\s+)(\d+)\b/)
+ {
+ if (($catname eq 'indexing' || $catname eq 'toasting')
+ && exists $maphash{$2})
+ {
+ my $repl = $1 . $maphash{$2};
+ $line =~ s/^\s*#\s*define\s+\w+\s+\d+\b/$repl/;
+ $changed = 1;
+ }
+ }
+
+ print $ofd $line;
+ }
+
+ close $ifd;
+ close $ofd;
+
+ # Avoid updating files if we didn't change them.
+ if ($changed || $output_path ne '')
+ {
+ rename $tmp_output_file, $output_file
+ or die "can't rename $tmp_output_file to $output_file: $!";
+ }
+ else
+ {
+ unlink $tmp_output_file
+ or die "can't unlink $tmp_output_file: $!";
+ }
+}
+
+# Likewise, read each .dat file and write out modified data.
+foreach my $input_file (glob("pg_*.dat"))
+{
+ $input_file =~ /(\w+)\.dat$/
+ or die "Input file $input_file needs to be a .dat file.\n";
+ my $catname = $1;
+
+ open(my $ifd, '<', $input_file) || die "$input_file: $!";
+
+ # Write output files to specified directory.
+ # Use a .tmp suffix, then rename into place, in case we're overwriting.
+ my $output_file = "$output_path$catname.dat";
+ my $tmp_output_file = "$output_file.tmp";
+ open my $ofd, '>', $tmp_output_file
+ or die "can't open $tmp_output_file: $!";
+ my $changed = 0;
+
+ # Scan the input file.
+ while (<$ifd>)
+ {
+ my $line = $_;
+
+ # Check for oid => 'nnnn', and replace if within mapped range.
+ if ($line =~ m/\b(oid\s*=>\s*)'(\d+)'/)
+ {
+ if (exists $maphash{$2})
+ {
+ my $repl = $1 . "'" . $maphash{$2} . "'";
+ $line =~ s/\boid\s*=>\s*'\d+'/$repl/;
+ $changed = 1;
+ }
+ }
+
+ # Likewise for array_type_oid.
+ if ($line =~ m/\b(array_type_oid\s*=>\s*)'(\d+)'/)
+ {
+ if (exists $maphash{$2})
+ {
+ my $repl = $1 . "'" . $maphash{$2} . "'";
+ $line =~ s/\barray_type_oid\s*=>\s*'\d+'/$repl/;
+ $changed = 1;
+ }
+ }
+
+ print $ofd $line;
+ }
+
+ close $ifd;
+ close $ofd;
+
+ # Avoid updating files if we didn't change them.
+ if ($changed || $output_path ne '')
+ {
+ rename $tmp_output_file, $output_file
+ or die "can't rename $tmp_output_file to $output_file: $!";
+ }
+ else
+ {
+ unlink $tmp_output_file
+ or die "can't unlink $tmp_output_file: $!";
+ }
+}
+
+sub usage
+{
+ my $last = $FirstGenbkiObjectId - 1;
+ die <<EOM;
+Usage: renumber_oids.pl [--output PATH] --first-mapped-oid X [--last-mapped-oid Y] --target-oid Z
+
+Options:
+ --output PATH output directory (default '.')
+ --first-mapped-oid X first OID to be moved
+ --last-mapped-oid Y last OID to be moved (default $last)
+ --target-oid Z first OID to move to
+
+Catalog *.h and *.dat files are updated and written to the
+output directory; by default, this overwrites the input files.
+
+Caution: the output PATH will be interpreted relative to
+src/include/catalog, even if you start the script
+in some other directory.
+
+EOM
+}
diff --git a/src/include/catalog/storage.h b/src/include/catalog/storage.h
new file mode 100644
index 0000000..30c38e0
--- /dev/null
+++ b/src/include/catalog/storage.h
@@ -0,0 +1,48 @@
+/*-------------------------------------------------------------------------
+ *
+ * storage.h
+ * prototypes for functions in backend/catalog/storage.c
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/storage.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef STORAGE_H
+#define STORAGE_H
+
+#include "storage/block.h"
+#include "storage/relfilenode.h"
+#include "storage/smgr.h"
+#include "utils/relcache.h"
+
+/* GUC variables */
+extern int wal_skip_threshold;
+
+extern SMgrRelation RelationCreateStorage(RelFileNode rnode, char relpersistence);
+extern void RelationDropStorage(Relation rel);
+extern void RelationPreserveStorage(RelFileNode rnode, bool atCommit);
+extern void RelationPreTruncate(Relation rel);
+extern void RelationTruncate(Relation rel, BlockNumber nblocks);
+extern void RelationCopyStorage(SMgrRelation src, SMgrRelation dst,
+ ForkNumber forkNum, char relpersistence);
+extern bool RelFileNodeSkippingWAL(RelFileNode rnode);
+extern Size EstimatePendingSyncsSpace(void);
+extern void SerializePendingSyncs(Size maxSize, char *startAddress);
+extern void RestorePendingSyncs(char *startAddress);
+
+/*
+ * These functions used to be in storage/smgr/smgr.c, which explains the
+ * naming
+ */
+extern void smgrDoPendingDeletes(bool isCommit);
+extern void smgrDoPendingSyncs(bool isCommit, bool isParallelWorker);
+extern int smgrGetPendingDeletes(bool forCommit, RelFileNode **ptr);
+extern void AtSubCommit_smgr(void);
+extern void AtSubAbort_smgr(void);
+extern void PostPrepare_smgr(void);
+
+#endif /* STORAGE_H */
diff --git a/src/include/catalog/storage_xlog.h b/src/include/catalog/storage_xlog.h
new file mode 100644
index 0000000..7b21cab
--- /dev/null
+++ b/src/include/catalog/storage_xlog.h
@@ -0,0 +1,59 @@
+/*-------------------------------------------------------------------------
+ *
+ * storage_xlog.h
+ * prototypes for XLog support for backend/catalog/storage.c
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/storage_xlog.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef STORAGE_XLOG_H
+#define STORAGE_XLOG_H
+
+#include "access/xlogreader.h"
+#include "lib/stringinfo.h"
+#include "storage/block.h"
+#include "storage/relfilenode.h"
+
+/*
+ * Declarations for smgr-related XLOG records
+ *
+ * Note: we log file creation and truncation here, but logging of deletion
+ * actions is handled by xact.c, because it is part of transaction commit.
+ */
+
+/* XLOG gives us high 4 bits */
+#define XLOG_SMGR_CREATE 0x10
+#define XLOG_SMGR_TRUNCATE 0x20
+
+typedef struct xl_smgr_create
+{
+ RelFileNode rnode;
+ ForkNumber forkNum;
+} xl_smgr_create;
+
+/* flags for xl_smgr_truncate */
+#define SMGR_TRUNCATE_HEAP 0x0001
+#define SMGR_TRUNCATE_VM 0x0002
+#define SMGR_TRUNCATE_FSM 0x0004
+#define SMGR_TRUNCATE_ALL \
+ (SMGR_TRUNCATE_HEAP|SMGR_TRUNCATE_VM|SMGR_TRUNCATE_FSM)
+
+typedef struct xl_smgr_truncate
+{
+ BlockNumber blkno;
+ RelFileNode rnode;
+ int flags;
+} xl_smgr_truncate;
+
+extern void log_smgrcreate(const RelFileNode *rnode, ForkNumber forkNum);
+
+extern void smgr_redo(XLogReaderState *record);
+extern void smgr_desc(StringInfo buf, XLogReaderState *record);
+extern const char *smgr_identify(uint8 info);
+
+#endif /* STORAGE_XLOG_H */
diff --git a/src/include/catalog/toasting.h b/src/include/catalog/toasting.h
new file mode 100644
index 0000000..51491c4
--- /dev/null
+++ b/src/include/catalog/toasting.h
@@ -0,0 +1,105 @@
+/*-------------------------------------------------------------------------
+ *
+ * toasting.h
+ * This file provides some definitions to support creation of toast tables
+ *
+ * Caution: all #define's with numeric values in this file had better be
+ * object OIDs, else renumber_oids.pl might change them inappropriately.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/catalog/toasting.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TOASTING_H
+#define TOASTING_H
+
+#include "storage/lock.h"
+
+/*
+ * toasting.c prototypes
+ */
+extern void NewRelationCreateToastTable(Oid relOid, Datum reloptions);
+extern void NewHeapCreateToastTable(Oid relOid, Datum reloptions,
+ LOCKMODE lockmode);
+extern void AlterTableCreateToastTable(Oid relOid, Datum reloptions,
+ LOCKMODE lockmode);
+extern void BootstrapToastTable(char *relName,
+ Oid toastOid, Oid toastIndexOid);
+
+
+/*
+ * This macro is just to keep the C compiler from spitting up on the
+ * upcoming commands for Catalog.pm.
+ */
+#define DECLARE_TOAST(name,toastoid,indexoid) extern int no_such_variable
+
+
+/*
+ * What follows are lines processed by genbki.pl to create the statements
+ * the bootstrap parser will turn into BootstrapToastTable commands.
+ * Each line specifies the system catalog that needs a toast table,
+ * the OID to assign to the toast table, and the OID to assign to the
+ * toast table's index. The reason we hard-wire these OIDs is that we
+ * need stable OIDs for shared relations, and that includes toast tables
+ * of shared relations.
+ */
+
+/* normal catalogs */
+DECLARE_TOAST(pg_aggregate, 4159, 4160);
+DECLARE_TOAST(pg_attrdef, 2830, 2831);
+DECLARE_TOAST(pg_collation, 4161, 4162);
+DECLARE_TOAST(pg_constraint, 2832, 2833);
+DECLARE_TOAST(pg_default_acl, 4143, 4144);
+DECLARE_TOAST(pg_description, 2834, 2835);
+DECLARE_TOAST(pg_event_trigger, 4145, 4146);
+DECLARE_TOAST(pg_extension, 4147, 4148);
+DECLARE_TOAST(pg_foreign_data_wrapper, 4149, 4150);
+DECLARE_TOAST(pg_foreign_server, 4151, 4152);
+DECLARE_TOAST(pg_foreign_table, 4153, 4154);
+DECLARE_TOAST(pg_init_privs, 4155, 4156);
+DECLARE_TOAST(pg_language, 4157, 4158);
+DECLARE_TOAST(pg_namespace, 4163, 4164);
+DECLARE_TOAST(pg_partitioned_table, 4165, 4166);
+DECLARE_TOAST(pg_policy, 4167, 4168);
+DECLARE_TOAST(pg_proc, 2836, 2837);
+DECLARE_TOAST(pg_rewrite, 2838, 2839);
+DECLARE_TOAST(pg_seclabel, 3598, 3599);
+DECLARE_TOAST(pg_statistic, 2840, 2841);
+DECLARE_TOAST(pg_statistic_ext, 3439, 3440);
+DECLARE_TOAST(pg_statistic_ext_data, 3430, 3431);
+DECLARE_TOAST(pg_trigger, 2336, 2337);
+DECLARE_TOAST(pg_ts_dict, 4169, 4170);
+DECLARE_TOAST(pg_type, 4171, 4172);
+DECLARE_TOAST(pg_user_mapping, 4173, 4174);
+
+/* shared catalogs */
+DECLARE_TOAST(pg_authid, 4175, 4176);
+#define PgAuthidToastTable 4175
+#define PgAuthidToastIndex 4176
+DECLARE_TOAST(pg_database, 4177, 4178);
+#define PgDatabaseToastTable 4177
+#define PgDatabaseToastIndex 4178
+DECLARE_TOAST(pg_db_role_setting, 2966, 2967);
+#define PgDbRoleSettingToastTable 2966
+#define PgDbRoleSettingToastIndex 2967
+DECLARE_TOAST(pg_replication_origin, 4181, 4182);
+#define PgReplicationOriginToastTable 4181
+#define PgReplicationOriginToastIndex 4182
+DECLARE_TOAST(pg_shdescription, 2846, 2847);
+#define PgShdescriptionToastTable 2846
+#define PgShdescriptionToastIndex 2847
+DECLARE_TOAST(pg_shseclabel, 4060, 4061);
+#define PgShseclabelToastTable 4060
+#define PgShseclabelToastIndex 4061
+DECLARE_TOAST(pg_subscription, 4183, 4184);
+#define PgSubscriptionToastTable 4183
+#define PgSubscriptionToastIndex 4184
+DECLARE_TOAST(pg_tablespace, 4185, 4186);
+#define PgTablespaceToastTable 4185
+#define PgTablespaceToastIndex 4186
+
+#endif /* TOASTING_H */
diff --git a/src/include/catalog/unused_oids b/src/include/catalog/unused_oids
new file mode 100755
index 0000000..83adbd5
--- /dev/null
+++ b/src/include/catalog/unused_oids
@@ -0,0 +1,78 @@
+#!/usr/bin/perl
+#----------------------------------------------------------------------
+#
+# unused_oids
+# Finds blocks of manually-assignable OIDs that have not already been
+# claimed by previous hackers. The main use is for finding available
+# OIDs for new internal functions. The numbers printed are inclusive
+# ranges of unused OIDs.
+#
+# Before using a large empty block, make sure you aren't about
+# to take over what was intended as expansion space for something
+# else.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/include/catalog/unused_oids
+#
+#----------------------------------------------------------------------
+
+use strict;
+use warnings;
+
+# Must run in src/include/catalog
+use FindBin;
+chdir $FindBin::RealBin or die "could not cd to $FindBin::RealBin: $!\n";
+
+use lib "$FindBin::RealBin/../../backend/catalog/";
+use Catalog;
+
+my @input_files = (glob("pg_*.h"), qw(indexing.h toasting.h));
+
+my $oids = Catalog::FindAllOidsFromHeaders(@input_files);
+
+# Also push FirstGenbkiObjectId to serve as a terminator for the last gap.
+my $FirstGenbkiObjectId =
+ Catalog::FindDefinedSymbol('access/transam.h', '..', 'FirstGenbkiObjectId');
+push @{$oids}, $FirstGenbkiObjectId;
+
+my $prev_oid = 0;
+my @sortedoids = sort { $a <=> $b } @{$oids};
+foreach my $oid (@sortedoids)
+{
+ if ($oid > $prev_oid + 1)
+ {
+ if ($oid > $prev_oid + 2)
+ {
+ printf "%d - %d\n", $prev_oid + 1, $oid - 1;
+ }
+ else
+ {
+ printf "%d\n", $prev_oid + 1;
+ }
+ }
+ $prev_oid = $oid;
+}
+
+my $suggestion;
+do
+{
+ $suggestion = int(8000 + rand(2000));
+} while (grep(/^$suggestion$/, @{$oids}));
+
+my $navailable = 0;
+foreach my $oid (@sortedoids)
+{
+ if ($oid > $suggestion)
+ {
+ $navailable = $oid - $suggestion;
+ last;
+ }
+}
+
+printf "Patches should use a more-or-less consecutive range of OIDs.\n";
+printf
+ "Best practice is to start with a random choice in the range 8000-9999.\n";
+printf
+ "Suggested random unused OID: $suggestion ($navailable consecutive OID(s) available starting here)\n";
diff --git a/src/include/commands/alter.h b/src/include/commands/alter.h
new file mode 100644
index 0000000..f9d6ba1
--- /dev/null
+++ b/src/include/commands/alter.h
@@ -0,0 +1,35 @@
+/*-------------------------------------------------------------------------
+ *
+ * alter.h
+ * prototypes for commands/alter.c
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/alter.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ALTER_H
+#define ALTER_H
+
+#include "catalog/dependency.h"
+#include "catalog/objectaddress.h"
+#include "nodes/parsenodes.h"
+#include "utils/relcache.h"
+
+extern ObjectAddress ExecRenameStmt(RenameStmt *stmt);
+
+extern ObjectAddress ExecAlterObjectDependsStmt(AlterObjectDependsStmt *stmt,
+ ObjectAddress *refAddress);
+extern ObjectAddress ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt,
+ ObjectAddress *oldSchemaAddr);
+extern Oid AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid,
+ ObjectAddresses *objsMoved);
+
+extern ObjectAddress ExecAlterOwnerStmt(AlterOwnerStmt *stmt);
+extern void AlterObjectOwner_internal(Relation catalog, Oid objectId,
+ Oid new_ownerId);
+
+#endif /* ALTER_H */
diff --git a/src/include/commands/async.h b/src/include/commands/async.h
new file mode 100644
index 0000000..4c35394
--- /dev/null
+++ b/src/include/commands/async.h
@@ -0,0 +1,54 @@
+/*-------------------------------------------------------------------------
+ *
+ * async.h
+ * Asynchronous notification: NOTIFY, LISTEN, UNLISTEN
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/async.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ASYNC_H
+#define ASYNC_H
+
+#include <signal.h>
+
+/*
+ * The number of SLRU page buffers we use for the notification queue.
+ */
+#define NUM_NOTIFY_BUFFERS 8
+
+extern bool Trace_notify;
+extern volatile sig_atomic_t notifyInterruptPending;
+
+extern Size AsyncShmemSize(void);
+extern void AsyncShmemInit(void);
+
+extern void NotifyMyFrontEnd(const char *channel,
+ const char *payload,
+ int32 srcPid);
+
+/* notify-related SQL statements */
+extern void Async_Notify(const char *channel, const char *payload);
+extern void Async_Listen(const char *channel);
+extern void Async_Unlisten(const char *channel);
+extern void Async_UnlistenAll(void);
+
+/* perform (or cancel) outbound notify processing at transaction commit */
+extern void PreCommit_Notify(void);
+extern void AtCommit_Notify(void);
+extern void AtAbort_Notify(void);
+extern void AtSubCommit_Notify(void);
+extern void AtSubAbort_Notify(void);
+extern void AtPrepare_Notify(void);
+extern void ProcessCompletedNotifies(void);
+
+/* signal handler for inbound notifies (PROCSIG_NOTIFY_INTERRUPT) */
+extern void HandleNotifyInterrupt(void);
+
+/* process interrupts */
+extern void ProcessNotifyInterrupt(void);
+
+#endif /* ASYNC_H */
diff --git a/src/include/commands/cluster.h b/src/include/commands/cluster.h
new file mode 100644
index 0000000..e058847
--- /dev/null
+++ b/src/include/commands/cluster.h
@@ -0,0 +1,38 @@
+/*-------------------------------------------------------------------------
+ *
+ * cluster.h
+ * header file for postgres cluster command stuff
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994-5, Regents of the University of California
+ *
+ * src/include/commands/cluster.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef CLUSTER_H
+#define CLUSTER_H
+
+#include "nodes/parsenodes.h"
+#include "storage/lock.h"
+#include "utils/relcache.h"
+
+
+extern void cluster(ClusterStmt *stmt, bool isTopLevel);
+extern void cluster_rel(Oid tableOid, Oid indexOid, int options);
+extern void check_index_is_clusterable(Relation OldHeap, Oid indexOid,
+ bool recheck, LOCKMODE lockmode);
+extern void mark_index_clustered(Relation rel, Oid indexOid, bool is_internal);
+
+extern Oid make_new_heap(Oid OIDOldHeap, Oid NewTableSpace, char relpersistence,
+ LOCKMODE lockmode);
+extern void finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
+ bool is_system_catalog,
+ bool swap_toast_by_content,
+ bool check_constraints,
+ bool is_internal,
+ TransactionId frozenXid,
+ MultiXactId minMulti,
+ char newrelpersistence);
+
+#endif /* CLUSTER_H */
diff --git a/src/include/commands/collationcmds.h b/src/include/commands/collationcmds.h
new file mode 100644
index 0000000..373b853
--- /dev/null
+++ b/src/include/commands/collationcmds.h
@@ -0,0 +1,25 @@
+/*-------------------------------------------------------------------------
+ *
+ * collationcmds.h
+ * prototypes for collationcmds.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/collationcmds.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef COLLATIONCMDS_H
+#define COLLATIONCMDS_H
+
+#include "catalog/objectaddress.h"
+#include "parser/parse_node.h"
+
+extern ObjectAddress DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_exists);
+extern void IsThereCollationInNamespace(const char *collname, Oid nspOid);
+extern ObjectAddress AlterCollation(AlterCollationStmt *stmt);
+
+#endif /* COLLATIONCMDS_H */
diff --git a/src/include/commands/comment.h b/src/include/commands/comment.h
new file mode 100644
index 0000000..840936e
--- /dev/null
+++ b/src/include/commands/comment.h
@@ -0,0 +1,45 @@
+/*
+ * src/include/commands/comment.h
+ *
+ *-------------------------------------------------------------------------
+ *
+ * comment.h
+ *
+ * Prototypes for functions in commands/comment.c
+ *
+ * Copyright (c) 1999-2020, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef COMMENT_H
+#define COMMENT_H
+
+#include "catalog/objectaddress.h"
+#include "nodes/parsenodes.h"
+
+/*------------------------------------------------------------------
+ * Function Prototypes --
+ *
+ * The following prototypes define the public functions of the comment
+ * related routines. CommentObject() implements the SQL "COMMENT ON"
+ * command. DeleteComments() deletes all comments for an object.
+ * CreateComments creates (or deletes, if comment is NULL) a comment
+ * for a specific key. There are versions of these two methods for
+ * both normal and shared objects.
+ *------------------------------------------------------------------
+ */
+
+extern ObjectAddress CommentObject(CommentStmt *stmt);
+
+extern void DeleteComments(Oid oid, Oid classoid, int32 subid);
+
+extern void CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment);
+
+extern void DeleteSharedComments(Oid oid, Oid classoid);
+
+extern void CreateSharedComments(Oid oid, Oid classoid, const char *comment);
+
+extern char *GetComment(Oid oid, Oid classoid, int32 subid);
+
+#endif /* COMMENT_H */
diff --git a/src/include/commands/conversioncmds.h b/src/include/commands/conversioncmds.h
new file mode 100644
index 0000000..543d874
--- /dev/null
+++ b/src/include/commands/conversioncmds.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * conversioncmds.h
+ * prototypes for conversioncmds.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/conversioncmds.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef CONVERSIONCMDS_H
+#define CONVERSIONCMDS_H
+
+#include "catalog/objectaddress.h"
+#include "nodes/parsenodes.h"
+
+extern ObjectAddress CreateConversionCommand(CreateConversionStmt *parsetree);
+
+#endif /* CONVERSIONCMDS_H */
diff --git a/src/include/commands/copy.h b/src/include/commands/copy.h
new file mode 100644
index 0000000..c639833
--- /dev/null
+++ b/src/include/commands/copy.h
@@ -0,0 +1,44 @@
+/*-------------------------------------------------------------------------
+ *
+ * copy.h
+ * Definitions for using the POSTGRES copy command.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/copy.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef COPY_H
+#define COPY_H
+
+#include "nodes/execnodes.h"
+#include "nodes/parsenodes.h"
+#include "parser/parse_node.h"
+#include "tcop/dest.h"
+
+/* CopyStateData is private in commands/copy.c */
+typedef struct CopyStateData *CopyState;
+typedef int (*copy_data_source_cb) (void *outbuf, int minread, int maxread);
+
+extern void DoCopy(ParseState *state, const CopyStmt *stmt,
+ int stmt_location, int stmt_len,
+ uint64 *processed);
+
+extern void ProcessCopyOptions(ParseState *pstate, CopyState cstate, bool is_from, List *options);
+extern CopyState BeginCopyFrom(ParseState *pstate, Relation rel, const char *filename,
+ bool is_program, copy_data_source_cb data_source_cb, List *attnamelist, List *options);
+extern void EndCopyFrom(CopyState cstate);
+extern bool NextCopyFrom(CopyState cstate, ExprContext *econtext,
+ Datum *values, bool *nulls);
+extern bool NextCopyFromRawFields(CopyState cstate,
+ char ***fields, int *nfields);
+extern void CopyFromErrorCallback(void *arg);
+
+extern uint64 CopyFrom(CopyState cstate);
+
+extern DestReceiver *CreateCopyDestReceiver(void);
+
+#endif /* COPY_H */
diff --git a/src/include/commands/createas.h b/src/include/commands/createas.h
new file mode 100644
index 0000000..7629230
--- /dev/null
+++ b/src/include/commands/createas.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * createas.h
+ * prototypes for createas.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/createas.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef CREATEAS_H
+#define CREATEAS_H
+
+#include "catalog/objectaddress.h"
+#include "nodes/params.h"
+#include "parser/parse_node.h"
+#include "tcop/dest.h"
+#include "utils/queryenvironment.h"
+
+
+extern ObjectAddress ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt,
+ ParamListInfo params, QueryEnvironment *queryEnv,
+ QueryCompletion *qc);
+
+extern int GetIntoRelEFlags(IntoClause *intoClause);
+
+extern DestReceiver *CreateIntoRelDestReceiver(IntoClause *intoClause);
+
+#endif /* CREATEAS_H */
diff --git a/src/include/commands/dbcommands.h b/src/include/commands/dbcommands.h
new file mode 100644
index 0000000..fb8ccfd
--- /dev/null
+++ b/src/include/commands/dbcommands.h
@@ -0,0 +1,35 @@
+/*-------------------------------------------------------------------------
+ *
+ * dbcommands.h
+ * Database management commands (create/drop database).
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/dbcommands.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DBCOMMANDS_H
+#define DBCOMMANDS_H
+
+#include "access/xlogreader.h"
+#include "catalog/objectaddress.h"
+#include "lib/stringinfo.h"
+#include "parser/parse_node.h"
+
+extern Oid createdb(ParseState *pstate, const CreatedbStmt *stmt);
+extern void dropdb(const char *dbname, bool missing_ok, bool force);
+extern void DropDatabase(ParseState *pstate, DropdbStmt *stmt);
+extern ObjectAddress RenameDatabase(const char *oldname, const char *newname);
+extern Oid AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel);
+extern Oid AlterDatabaseSet(AlterDatabaseSetStmt *stmt);
+extern ObjectAddress AlterDatabaseOwner(const char *dbname, Oid newOwnerId);
+
+extern Oid get_database_oid(const char *dbname, bool missing_ok);
+extern char *get_database_name(Oid dbid);
+
+extern void check_encoding_locale_matches(int encoding, const char *collate, const char *ctype);
+
+#endif /* DBCOMMANDS_H */
diff --git a/src/include/commands/dbcommands_xlog.h b/src/include/commands/dbcommands_xlog.h
new file mode 100644
index 0000000..7438d55
--- /dev/null
+++ b/src/include/commands/dbcommands_xlog.h
@@ -0,0 +1,45 @@
+/*-------------------------------------------------------------------------
+ *
+ * dbcommands_xlog.h
+ * Database resource manager XLOG definitions (create/drop database).
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/dbcommands_xlog.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DBCOMMANDS_XLOG_H
+#define DBCOMMANDS_XLOG_H
+
+#include "access/xlogreader.h"
+#include "lib/stringinfo.h"
+
+/* record types */
+#define XLOG_DBASE_CREATE 0x00
+#define XLOG_DBASE_DROP 0x10
+
+typedef struct xl_dbase_create_rec
+{
+ /* Records copying of a single subdirectory incl. contents */
+ Oid db_id;
+ Oid tablespace_id;
+ Oid src_db_id;
+ Oid src_tablespace_id;
+} xl_dbase_create_rec;
+
+typedef struct xl_dbase_drop_rec
+{
+ Oid db_id;
+ int ntablespaces; /* number of tablespace IDs */
+ Oid tablespace_ids[FLEXIBLE_ARRAY_MEMBER];
+} xl_dbase_drop_rec;
+#define MinSizeOfDbaseDropRec offsetof(xl_dbase_drop_rec, tablespace_ids)
+
+extern void dbase_redo(XLogReaderState *rptr);
+extern void dbase_desc(StringInfo buf, XLogReaderState *rptr);
+extern const char *dbase_identify(uint8 info);
+
+#endif /* DBCOMMANDS_XLOG_H */
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
new file mode 100644
index 0000000..c77c9a6
--- /dev/null
+++ b/src/include/commands/defrem.h
@@ -0,0 +1,173 @@
+/*-------------------------------------------------------------------------
+ *
+ * defrem.h
+ * POSTGRES define and remove utility definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/defrem.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DEFREM_H
+#define DEFREM_H
+
+#include "catalog/objectaddress.h"
+#include "nodes/params.h"
+#include "parser/parse_node.h"
+#include "tcop/dest.h"
+#include "utils/array.h"
+
+/* commands/dropcmds.c */
+extern void RemoveObjects(DropStmt *stmt);
+
+/* commands/indexcmds.c */
+extern ObjectAddress DefineIndex(Oid relationId,
+ IndexStmt *stmt,
+ Oid indexRelationId,
+ Oid parentIndexId,
+ Oid parentConstraintId,
+ bool is_alter_table,
+ bool check_rights,
+ bool check_not_in_use,
+ bool skip_build,
+ bool quiet);
+extern void ReindexIndex(RangeVar *indexRelation, int options, bool concurrent);
+extern Oid ReindexTable(RangeVar *relation, int options, bool concurrent);
+extern void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind,
+ int options, bool concurrent);
+extern char *makeObjectName(const char *name1, const char *name2,
+ const char *label);
+extern char *ChooseRelationName(const char *name1, const char *name2,
+ const char *label, Oid namespaceid,
+ bool isconstraint);
+extern bool CheckIndexCompatible(Oid oldId,
+ const char *accessMethodName,
+ List *attributeList,
+ List *exclusionOpNames);
+extern Oid GetDefaultOpClass(Oid type_id, Oid am_id);
+extern Oid ResolveOpClass(List *opclass, Oid attrType,
+ const char *accessMethodName, Oid accessMethodId);
+
+/* commands/functioncmds.c */
+extern ObjectAddress CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt);
+extern void RemoveFunctionById(Oid funcOid);
+extern ObjectAddress AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt);
+extern ObjectAddress CreateCast(CreateCastStmt *stmt);
+extern void DropCastById(Oid castOid);
+extern ObjectAddress CreateTransform(CreateTransformStmt *stmt);
+extern void DropTransformById(Oid transformOid);
+extern void IsThereFunctionInNamespace(const char *proname, int pronargs,
+ oidvector *proargtypes, Oid nspOid);
+extern void ExecuteDoStmt(DoStmt *stmt, bool atomic);
+extern void ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest);
+extern TupleDesc CallStmtResultDesc(CallStmt *stmt);
+extern Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok);
+extern void interpret_function_parameter_list(ParseState *pstate,
+ List *parameters,
+ Oid languageOid,
+ ObjectType objtype,
+ oidvector **parameterTypes,
+ ArrayType **allParameterTypes,
+ ArrayType **parameterModes,
+ ArrayType **parameterNames,
+ List **parameterDefaults,
+ Oid *variadicArgType,
+ Oid *requiredResultType);
+
+/* commands/operatorcmds.c */
+extern ObjectAddress DefineOperator(List *names, List *parameters);
+extern void RemoveOperatorById(Oid operOid);
+extern ObjectAddress AlterOperator(AlterOperatorStmt *stmt);
+
+/* commands/statscmds.c */
+extern ObjectAddress CreateStatistics(CreateStatsStmt *stmt);
+extern ObjectAddress AlterStatistics(AlterStatsStmt *stmt);
+extern void RemoveStatisticsById(Oid statsOid);
+extern void UpdateStatisticsForTypeChange(Oid statsOid,
+ Oid relationOid, int attnum,
+ Oid oldColumnType, Oid newColumnType);
+
+/* commands/aggregatecmds.c */
+extern ObjectAddress DefineAggregate(ParseState *pstate, List *name, List *args, bool oldstyle,
+ List *parameters, bool replace);
+
+/* commands/opclasscmds.c */
+extern ObjectAddress DefineOpClass(CreateOpClassStmt *stmt);
+extern ObjectAddress DefineOpFamily(CreateOpFamilyStmt *stmt);
+extern Oid AlterOpFamily(AlterOpFamilyStmt *stmt);
+extern void RemoveOpClassById(Oid opclassOid);
+extern void RemoveOpFamilyById(Oid opfamilyOid);
+extern void RemoveAmOpEntryById(Oid entryOid);
+extern void RemoveAmProcEntryById(Oid entryOid);
+extern void IsThereOpClassInNamespace(const char *opcname, Oid opcmethod,
+ Oid opcnamespace);
+extern void IsThereOpFamilyInNamespace(const char *opfname, Oid opfmethod,
+ Oid opfnamespace);
+extern Oid get_opclass_oid(Oid amID, List *opclassname, bool missing_ok);
+extern Oid get_opfamily_oid(Oid amID, List *opfamilyname, bool missing_ok);
+
+/* commands/tsearchcmds.c */
+extern ObjectAddress DefineTSParser(List *names, List *parameters);
+extern void RemoveTSParserById(Oid prsId);
+
+extern ObjectAddress DefineTSDictionary(List *names, List *parameters);
+extern void RemoveTSDictionaryById(Oid dictId);
+extern ObjectAddress AlterTSDictionary(AlterTSDictionaryStmt *stmt);
+
+extern ObjectAddress DefineTSTemplate(List *names, List *parameters);
+extern void RemoveTSTemplateById(Oid tmplId);
+
+extern ObjectAddress DefineTSConfiguration(List *names, List *parameters,
+ ObjectAddress *copied);
+extern void RemoveTSConfigurationById(Oid cfgId);
+extern ObjectAddress AlterTSConfiguration(AlterTSConfigurationStmt *stmt);
+
+extern text *serialize_deflist(List *deflist);
+extern List *deserialize_deflist(Datum txt);
+
+/* commands/foreigncmds.c */
+extern ObjectAddress AlterForeignServerOwner(const char *name, Oid newOwnerId);
+extern void AlterForeignServerOwner_oid(Oid, Oid newOwnerId);
+extern ObjectAddress AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId);
+extern void AlterForeignDataWrapperOwner_oid(Oid fwdId, Oid newOwnerId);
+extern ObjectAddress CreateForeignDataWrapper(CreateFdwStmt *stmt);
+extern ObjectAddress AlterForeignDataWrapper(AlterFdwStmt *stmt);
+extern void RemoveForeignDataWrapperById(Oid fdwId);
+extern ObjectAddress CreateForeignServer(CreateForeignServerStmt *stmt);
+extern ObjectAddress AlterForeignServer(AlterForeignServerStmt *stmt);
+extern void RemoveForeignServerById(Oid srvId);
+extern ObjectAddress CreateUserMapping(CreateUserMappingStmt *stmt);
+extern ObjectAddress AlterUserMapping(AlterUserMappingStmt *stmt);
+extern Oid RemoveUserMapping(DropUserMappingStmt *stmt);
+extern void RemoveUserMappingById(Oid umId);
+extern void CreateForeignTable(CreateForeignTableStmt *stmt, Oid relid);
+extern void ImportForeignSchema(ImportForeignSchemaStmt *stmt);
+extern Datum transformGenericOptions(Oid catalogId,
+ Datum oldOptions,
+ List *options,
+ Oid fdwvalidator);
+
+/* commands/amcmds.c */
+extern ObjectAddress CreateAccessMethod(CreateAmStmt *stmt);
+extern void RemoveAccessMethodById(Oid amOid);
+extern Oid get_index_am_oid(const char *amname, bool missing_ok);
+extern Oid get_table_am_oid(const char *amname, bool missing_ok);
+extern Oid get_am_oid(const char *amname, bool missing_ok);
+extern char *get_am_name(Oid amOid);
+
+/* support routines in commands/define.c */
+
+extern char *defGetString(DefElem *def);
+extern double defGetNumeric(DefElem *def);
+extern bool defGetBoolean(DefElem *def);
+extern int32 defGetInt32(DefElem *def);
+extern int64 defGetInt64(DefElem *def);
+extern List *defGetQualifiedName(DefElem *def);
+extern TypeName *defGetTypeName(DefElem *def);
+extern int defGetTypeLength(DefElem *def);
+extern List *defGetStringList(DefElem *def);
+
+#endif /* DEFREM_H */
diff --git a/src/include/commands/discard.h b/src/include/commands/discard.h
new file mode 100644
index 0000000..a4b0c64
--- /dev/null
+++ b/src/include/commands/discard.h
@@ -0,0 +1,20 @@
+/*-------------------------------------------------------------------------
+ *
+ * discard.h
+ * prototypes for discard.c.
+ *
+ *
+ * Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ *
+ * src/include/commands/discard.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DISCARD_H
+#define DISCARD_H
+
+#include "nodes/parsenodes.h"
+
+extern void DiscardCommand(DiscardStmt *stmt, bool isTopLevel);
+
+#endif /* DISCARD_H */
diff --git a/src/include/commands/event_trigger.h b/src/include/commands/event_trigger.h
new file mode 100644
index 0000000..28b3520
--- /dev/null
+++ b/src/include/commands/event_trigger.h
@@ -0,0 +1,88 @@
+/*-------------------------------------------------------------------------
+ *
+ * event_trigger.h
+ * Declarations for command trigger handling.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/event_trigger.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EVENT_TRIGGER_H
+#define EVENT_TRIGGER_H
+
+#include "catalog/dependency.h"
+#include "catalog/objectaddress.h"
+#include "catalog/pg_event_trigger.h"
+#include "nodes/parsenodes.h"
+#include "tcop/cmdtag.h"
+#include "tcop/deparse_utility.h"
+#include "utils/aclchk_internal.h"
+
+typedef struct EventTriggerData
+{
+ NodeTag type;
+ const char *event; /* event name */
+ Node *parsetree; /* parse tree */
+ CommandTag tag;
+} EventTriggerData;
+
+#define AT_REWRITE_ALTER_PERSISTENCE 0x01
+#define AT_REWRITE_DEFAULT_VAL 0x02
+#define AT_REWRITE_COLUMN_REWRITE 0x04
+
+/*
+ * EventTriggerData is the node type that is passed as fmgr "context" info
+ * when a function is called by the event trigger manager.
+ */
+#define CALLED_AS_EVENT_TRIGGER(fcinfo) \
+ ((fcinfo)->context != NULL && IsA((fcinfo)->context, EventTriggerData))
+
+extern Oid CreateEventTrigger(CreateEventTrigStmt *stmt);
+extern void RemoveEventTriggerById(Oid trigOid);
+extern Oid get_event_trigger_oid(const char *trigname, bool missing_ok);
+
+extern Oid AlterEventTrigger(AlterEventTrigStmt *stmt);
+extern ObjectAddress AlterEventTriggerOwner(const char *name, Oid newOwnerId);
+extern void AlterEventTriggerOwner_oid(Oid, Oid newOwnerId);
+
+extern bool EventTriggerSupportsObjectType(ObjectType obtype);
+extern bool EventTriggerSupportsObjectClass(ObjectClass objclass);
+extern void EventTriggerDDLCommandStart(Node *parsetree);
+extern void EventTriggerDDLCommandEnd(Node *parsetree);
+extern void EventTriggerSQLDrop(Node *parsetree);
+extern void EventTriggerTableRewrite(Node *parsetree, Oid tableOid, int reason);
+
+extern bool EventTriggerBeginCompleteQuery(void);
+extern void EventTriggerEndCompleteQuery(void);
+extern bool trackDroppedObjectsNeeded(void);
+extern void EventTriggerSQLDropAddObject(const ObjectAddress *object,
+ bool original, bool normal);
+
+extern void EventTriggerInhibitCommandCollection(void);
+extern void EventTriggerUndoInhibitCommandCollection(void);
+
+extern void EventTriggerCollectSimpleCommand(ObjectAddress address,
+ ObjectAddress secondaryObject,
+ Node *parsetree);
+
+extern void EventTriggerAlterTableStart(Node *parsetree);
+extern void EventTriggerAlterTableRelid(Oid objectId);
+extern void EventTriggerCollectAlterTableSubcmd(Node *subcmd,
+ ObjectAddress address);
+extern void EventTriggerAlterTableEnd(void);
+
+extern void EventTriggerCollectGrant(InternalGrant *istmt);
+extern void EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt,
+ Oid opfamoid, List *operators,
+ List *procedures);
+extern void EventTriggerCollectCreateOpClass(CreateOpClassStmt *stmt,
+ Oid opcoid, List *operators,
+ List *procedures);
+extern void EventTriggerCollectAlterTSConfig(AlterTSConfigurationStmt *stmt,
+ Oid cfgId, Oid *dictIds, int ndicts);
+extern void EventTriggerCollectAlterDefPrivs(AlterDefaultPrivilegesStmt *stmt);
+
+#endif /* EVENT_TRIGGER_H */
diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h
new file mode 100644
index 0000000..ba661d3
--- /dev/null
+++ b/src/include/commands/explain.h
@@ -0,0 +1,127 @@
+/*-------------------------------------------------------------------------
+ *
+ * explain.h
+ * prototypes for explain.c
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994-5, Regents of the University of California
+ *
+ * src/include/commands/explain.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXPLAIN_H
+#define EXPLAIN_H
+
+#include "executor/executor.h"
+#include "lib/stringinfo.h"
+#include "parser/parse_node.h"
+
+typedef enum ExplainFormat
+{
+ EXPLAIN_FORMAT_TEXT,
+ EXPLAIN_FORMAT_XML,
+ EXPLAIN_FORMAT_JSON,
+ EXPLAIN_FORMAT_YAML
+} ExplainFormat;
+
+typedef struct ExplainWorkersState
+{
+ int num_workers; /* # of worker processes the plan used */
+ bool *worker_inited; /* per-worker state-initialized flags */
+ StringInfoData *worker_str; /* per-worker transient output buffers */
+ int *worker_state_save; /* per-worker grouping state save areas */
+ StringInfo prev_str; /* saved output buffer while redirecting */
+} ExplainWorkersState;
+
+typedef struct ExplainState
+{
+ StringInfo str; /* output buffer */
+ /* options */
+ bool verbose; /* be verbose */
+ bool analyze; /* print actual times */
+ bool costs; /* print estimated costs */
+ bool buffers; /* print buffer usage */
+ bool wal; /* print WAL usage */
+ bool timing; /* print detailed node timing */
+ bool summary; /* print total planning and execution timing */
+ bool settings; /* print modified settings */
+ ExplainFormat format; /* output format */
+ /* state for output formatting --- not reset for each new plan tree */
+ int indent; /* current indentation level */
+ List *grouping_stack; /* format-specific grouping state */
+ /* state related to the current plan tree (filled by ExplainPrintPlan) */
+ PlannedStmt *pstmt; /* top of plan */
+ List *rtable; /* range table */
+ List *rtable_names; /* alias names for RTEs */
+ List *deparse_cxt; /* context list for deparsing expressions */
+ Bitmapset *printed_subplans; /* ids of SubPlans we've printed */
+ bool hide_workers; /* set if we find an invisible Gather */
+ /* state related to the current plan node */
+ ExplainWorkersState *workers_state; /* needed if parallel plan */
+} ExplainState;
+
+/* Hook for plugins to get control in ExplainOneQuery() */
+typedef void (*ExplainOneQuery_hook_type) (Query *query,
+ int cursorOptions,
+ IntoClause *into,
+ ExplainState *es,
+ const char *queryString,
+ ParamListInfo params,
+ QueryEnvironment *queryEnv);
+extern PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook;
+
+/* Hook for plugins to get control in explain_get_index_name() */
+typedef const char *(*explain_get_index_name_hook_type) (Oid indexId);
+extern PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook;
+
+
+extern void ExplainQuery(ParseState *pstate, ExplainStmt *stmt,
+ ParamListInfo params, DestReceiver *dest);
+
+extern ExplainState *NewExplainState(void);
+
+extern TupleDesc ExplainResultDesc(ExplainStmt *stmt);
+
+extern void ExplainOneUtility(Node *utilityStmt, IntoClause *into,
+ ExplainState *es, const char *queryString,
+ ParamListInfo params, QueryEnvironment *queryEnv);
+
+extern void ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into,
+ ExplainState *es, const char *queryString,
+ ParamListInfo params, QueryEnvironment *queryEnv,
+ const instr_time *planduration,
+ const BufferUsage *bufusage);
+
+extern void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc);
+extern void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc);
+
+extern void ExplainPrintJITSummary(ExplainState *es, QueryDesc *queryDesc);
+
+extern void ExplainQueryText(ExplainState *es, QueryDesc *queryDesc);
+
+extern void ExplainBeginOutput(ExplainState *es);
+extern void ExplainEndOutput(ExplainState *es);
+extern void ExplainSeparatePlans(ExplainState *es);
+
+extern void ExplainPropertyList(const char *qlabel, List *data,
+ ExplainState *es);
+extern void ExplainPropertyListNested(const char *qlabel, List *data,
+ ExplainState *es);
+extern void ExplainPropertyText(const char *qlabel, const char *value,
+ ExplainState *es);
+extern void ExplainPropertyInteger(const char *qlabel, const char *unit,
+ int64 value, ExplainState *es);
+extern void ExplainPropertyUInteger(const char *qlabel, const char *unit,
+ uint64 value, ExplainState *es);
+extern void ExplainPropertyFloat(const char *qlabel, const char *unit,
+ double value, int ndigits, ExplainState *es);
+extern void ExplainPropertyBool(const char *qlabel, bool value,
+ ExplainState *es);
+
+extern void ExplainOpenGroup(const char *objtype, const char *labelname,
+ bool labeled, ExplainState *es);
+extern void ExplainCloseGroup(const char *objtype, const char *labelname,
+ bool labeled, ExplainState *es);
+
+#endif /* EXPLAIN_H */
diff --git a/src/include/commands/extension.h b/src/include/commands/extension.h
new file mode 100644
index 0000000..8b06df0
--- /dev/null
+++ b/src/include/commands/extension.h
@@ -0,0 +1,55 @@
+/*-------------------------------------------------------------------------
+ *
+ * extension.h
+ * Extension management commands (create/drop extension).
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/extension.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXTENSION_H
+#define EXTENSION_H
+
+#include "catalog/objectaddress.h"
+#include "parser/parse_node.h"
+
+
+/*
+ * creating_extension is only true while running a CREATE EXTENSION or ALTER
+ * EXTENSION UPDATE command. It instructs recordDependencyOnCurrentExtension()
+ * to register a dependency on the current pg_extension object for each SQL
+ * object created by an extension script. It also instructs performDeletion()
+ * to remove such dependencies without following them, so that extension
+ * scripts can drop member objects without having to explicitly dissociate
+ * them from the extension first.
+ */
+extern PGDLLIMPORT bool creating_extension;
+extern PGDLLIMPORT Oid CurrentExtensionObject;
+
+
+extern ObjectAddress CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt);
+
+extern void RemoveExtensionById(Oid extId);
+
+extern ObjectAddress InsertExtensionTuple(const char *extName, Oid extOwner,
+ Oid schemaOid, bool relocatable, const char *extVersion,
+ Datum extConfig, Datum extCondition,
+ List *requiredExtensions);
+
+extern ObjectAddress ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt);
+
+extern ObjectAddress ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt,
+ ObjectAddress *objAddr);
+
+extern Oid get_extension_oid(const char *extname, bool missing_ok);
+extern char *get_extension_name(Oid ext_oid);
+extern bool extension_file_exists(const char *extensionName);
+
+extern ObjectAddress AlterExtensionNamespace(const char *extensionName, const char *newschema,
+ Oid *oldschema);
+
+#endif /* EXTENSION_H */
diff --git a/src/include/commands/lockcmds.h b/src/include/commands/lockcmds.h
new file mode 100644
index 0000000..552ff78
--- /dev/null
+++ b/src/include/commands/lockcmds.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * lockcmds.h
+ * prototypes for lockcmds.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/lockcmds.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LOCKCMDS_H
+#define LOCKCMDS_H
+
+#include "nodes/parsenodes.h"
+
+/*
+ * LOCK
+ */
+extern void LockTableCommand(LockStmt *lockstmt);
+
+#endif /* LOCKCMDS_H */
diff --git a/src/include/commands/matview.h b/src/include/commands/matview.h
new file mode 100644
index 0000000..3ea4f5c
--- /dev/null
+++ b/src/include/commands/matview.h
@@ -0,0 +1,33 @@
+/*-------------------------------------------------------------------------
+ *
+ * matview.h
+ * prototypes for matview.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/matview.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef MATVIEW_H
+#define MATVIEW_H
+
+#include "catalog/objectaddress.h"
+#include "nodes/params.h"
+#include "nodes/parsenodes.h"
+#include "tcop/dest.h"
+#include "utils/relcache.h"
+
+
+extern void SetMatViewPopulatedState(Relation relation, bool newstate);
+
+extern ObjectAddress ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
+ ParamListInfo params, QueryCompletion *qc);
+
+extern DestReceiver *CreateTransientRelDestReceiver(Oid oid);
+
+extern bool MatViewIncrementalMaintenanceIsEnabled(void);
+
+#endif /* MATVIEW_H */
diff --git a/src/include/commands/policy.h b/src/include/commands/policy.h
new file mode 100644
index 0000000..946ce80
--- /dev/null
+++ b/src/include/commands/policy.h
@@ -0,0 +1,38 @@
+/*-------------------------------------------------------------------------
+ *
+ * policy.h
+ * prototypes for policy.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/policy.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef POLICY_H
+#define POLICY_H
+
+#include "catalog/objectaddress.h"
+#include "nodes/parsenodes.h"
+#include "utils/relcache.h"
+
+extern void RelationBuildRowSecurity(Relation relation);
+
+extern void RemovePolicyById(Oid policy_id);
+
+extern bool RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid objid);
+
+extern ObjectAddress CreatePolicy(CreatePolicyStmt *stmt);
+extern ObjectAddress AlterPolicy(AlterPolicyStmt *stmt);
+
+extern Oid get_relation_policy_oid(Oid relid, const char *policy_name,
+ bool missing_ok);
+
+extern ObjectAddress rename_policy(RenameStmt *stmt);
+
+extern bool relation_has_policies(Relation rel);
+
+#endif /* POLICY_H */
diff --git a/src/include/commands/portalcmds.h b/src/include/commands/portalcmds.h
new file mode 100644
index 0000000..5f64b0a
--- /dev/null
+++ b/src/include/commands/portalcmds.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * portalcmds.h
+ * prototypes for portalcmds.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/portalcmds.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PORTALCMDS_H
+#define PORTALCMDS_H
+
+#include "nodes/parsenodes.h"
+#include "parser/parse_node.h"
+#include "utils/portal.h"
+
+
+extern void PerformCursorOpen(ParseState *pstate, DeclareCursorStmt *cstmt, ParamListInfo params,
+ bool isTopLevel);
+
+extern void PerformPortalFetch(FetchStmt *stmt, DestReceiver *dest,
+ QueryCompletion *qc);
+
+extern void PerformPortalClose(const char *name);
+
+extern void PortalCleanup(Portal portal);
+
+extern void PersistHoldablePortal(Portal portal);
+
+#endif /* PORTALCMDS_H */
diff --git a/src/include/commands/prepare.h b/src/include/commands/prepare.h
new file mode 100644
index 0000000..4fcf240
--- /dev/null
+++ b/src/include/commands/prepare.h
@@ -0,0 +1,61 @@
+/*-------------------------------------------------------------------------
+ *
+ * prepare.h
+ * PREPARE, EXECUTE and DEALLOCATE commands, and prepared-stmt storage
+ *
+ *
+ * Copyright (c) 2002-2020, PostgreSQL Global Development Group
+ *
+ * src/include/commands/prepare.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PREPARE_H
+#define PREPARE_H
+
+#include "commands/explain.h"
+#include "datatype/timestamp.h"
+#include "utils/plancache.h"
+
+/*
+ * The data structure representing a prepared statement. This is now just
+ * a thin veneer over a plancache entry --- the main addition is that of
+ * a name.
+ *
+ * Note: all subsidiary storage lives in the referenced plancache entry.
+ */
+typedef struct
+{
+ /* dynahash.c requires key to be first field */
+ char stmt_name[NAMEDATALEN];
+ CachedPlanSource *plansource; /* the actual cached plan */
+ bool from_sql; /* prepared via SQL, not FE/BE protocol? */
+ TimestampTz prepare_time; /* the time when the stmt was prepared */
+} PreparedStatement;
+
+
+/* Utility statements PREPARE, EXECUTE, DEALLOCATE, EXPLAIN EXECUTE */
+extern void PrepareQuery(ParseState *pstate, PrepareStmt *stmt,
+ int stmt_location, int stmt_len);
+extern void ExecuteQuery(ParseState *pstate,
+ ExecuteStmt *stmt, IntoClause *intoClause,
+ ParamListInfo params,
+ DestReceiver *dest, QueryCompletion *qc);
+extern void DeallocateQuery(DeallocateStmt *stmt);
+extern void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into,
+ ExplainState *es, const char *queryString,
+ ParamListInfo params, QueryEnvironment *queryEnv);
+
+/* Low-level access to stored prepared statements */
+extern void StorePreparedStatement(const char *stmt_name,
+ CachedPlanSource *plansource,
+ bool from_sql);
+extern PreparedStatement *FetchPreparedStatement(const char *stmt_name,
+ bool throwError);
+extern void DropPreparedStatement(const char *stmt_name, bool showError);
+extern TupleDesc FetchPreparedStatementResultDesc(PreparedStatement *stmt);
+extern List *FetchPreparedStatementTargetList(PreparedStatement *stmt);
+
+extern void DropAllPreparedStatements(void);
+
+#endif /* PREPARE_H */
diff --git a/src/include/commands/proclang.h b/src/include/commands/proclang.h
new file mode 100644
index 0000000..c70f8ec
--- /dev/null
+++ b/src/include/commands/proclang.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * proclang.h
+ * prototypes for proclang.c.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/proclang.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PROCLANG_H
+#define PROCLANG_H
+
+#include "catalog/objectaddress.h"
+#include "nodes/parsenodes.h"
+
+extern ObjectAddress CreateProceduralLanguage(CreatePLangStmt *stmt);
+extern void DropProceduralLanguageById(Oid langOid);
+
+extern Oid get_language_oid(const char *langname, bool missing_ok);
+
+#endif /* PROCLANG_H */
diff --git a/src/include/commands/progress.h b/src/include/commands/progress.h
new file mode 100644
index 0000000..36b073e
--- /dev/null
+++ b/src/include/commands/progress.h
@@ -0,0 +1,136 @@
+/*-------------------------------------------------------------------------
+ *
+ * progress.h
+ * Constants used with the progress reporting facilities defined in
+ * pgstat.h. These are possibly interesting to extensions, so we
+ * expose them via this header file. Note that if you update these
+ * constants, you probably also need to update the views based on them
+ * in system_views.sql.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/progress.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PROGRESS_H
+#define PROGRESS_H
+
+/* Progress parameters for (lazy) vacuum */
+#define PROGRESS_VACUUM_PHASE 0
+#define PROGRESS_VACUUM_TOTAL_HEAP_BLKS 1
+#define PROGRESS_VACUUM_HEAP_BLKS_SCANNED 2
+#define PROGRESS_VACUUM_HEAP_BLKS_VACUUMED 3
+#define PROGRESS_VACUUM_NUM_INDEX_VACUUMS 4
+#define PROGRESS_VACUUM_MAX_DEAD_TUPLES 5
+#define PROGRESS_VACUUM_NUM_DEAD_TUPLES 6
+
+/* Phases of vacuum (as advertised via PROGRESS_VACUUM_PHASE) */
+#define PROGRESS_VACUUM_PHASE_SCAN_HEAP 1
+#define PROGRESS_VACUUM_PHASE_VACUUM_INDEX 2
+#define PROGRESS_VACUUM_PHASE_VACUUM_HEAP 3
+#define PROGRESS_VACUUM_PHASE_INDEX_CLEANUP 4
+#define PROGRESS_VACUUM_PHASE_TRUNCATE 5
+#define PROGRESS_VACUUM_PHASE_FINAL_CLEANUP 6
+
+/* Progress parameters for analyze */
+#define PROGRESS_ANALYZE_PHASE 0
+#define PROGRESS_ANALYZE_BLOCKS_TOTAL 1
+#define PROGRESS_ANALYZE_BLOCKS_DONE 2
+#define PROGRESS_ANALYZE_EXT_STATS_TOTAL 3
+#define PROGRESS_ANALYZE_EXT_STATS_COMPUTED 4
+#define PROGRESS_ANALYZE_CHILD_TABLES_TOTAL 5
+#define PROGRESS_ANALYZE_CHILD_TABLES_DONE 6
+#define PROGRESS_ANALYZE_CURRENT_CHILD_TABLE_RELID 7
+
+/* Phases of analyze (as advertised via PROGRESS_ANALYZE_PHASE) */
+#define PROGRESS_ANALYZE_PHASE_ACQUIRE_SAMPLE_ROWS 1
+#define PROGRESS_ANALYZE_PHASE_ACQUIRE_SAMPLE_ROWS_INH 2
+#define PROGRESS_ANALYZE_PHASE_COMPUTE_STATS 3
+#define PROGRESS_ANALYZE_PHASE_COMPUTE_EXT_STATS 4
+#define PROGRESS_ANALYZE_PHASE_FINALIZE_ANALYZE 5
+
+/* Progress parameters for cluster */
+#define PROGRESS_CLUSTER_COMMAND 0
+#define PROGRESS_CLUSTER_PHASE 1
+#define PROGRESS_CLUSTER_INDEX_RELID 2
+#define PROGRESS_CLUSTER_HEAP_TUPLES_SCANNED 3
+#define PROGRESS_CLUSTER_HEAP_TUPLES_WRITTEN 4
+#define PROGRESS_CLUSTER_TOTAL_HEAP_BLKS 5
+#define PROGRESS_CLUSTER_HEAP_BLKS_SCANNED 6
+#define PROGRESS_CLUSTER_INDEX_REBUILD_COUNT 7
+
+/* Phases of cluster (as advertised via PROGRESS_CLUSTER_PHASE) */
+#define PROGRESS_CLUSTER_PHASE_SEQ_SCAN_HEAP 1
+#define PROGRESS_CLUSTER_PHASE_INDEX_SCAN_HEAP 2
+#define PROGRESS_CLUSTER_PHASE_SORT_TUPLES 3
+#define PROGRESS_CLUSTER_PHASE_WRITE_NEW_HEAP 4
+#define PROGRESS_CLUSTER_PHASE_SWAP_REL_FILES 5
+#define PROGRESS_CLUSTER_PHASE_REBUILD_INDEX 6
+#define PROGRESS_CLUSTER_PHASE_FINAL_CLEANUP 7
+
+/* Commands of PROGRESS_CLUSTER */
+#define PROGRESS_CLUSTER_COMMAND_CLUSTER 1
+#define PROGRESS_CLUSTER_COMMAND_VACUUM_FULL 2
+
+/* Progress parameters for CREATE INDEX */
+/* 3, 4 and 5 reserved for "waitfor" metrics */
+#define PROGRESS_CREATEIDX_COMMAND 0
+#define PROGRESS_CREATEIDX_INDEX_OID 6
+#define PROGRESS_CREATEIDX_ACCESS_METHOD_OID 8
+#define PROGRESS_CREATEIDX_PHASE 9 /* AM-agnostic phase # */
+#define PROGRESS_CREATEIDX_SUBPHASE 10 /* phase # filled by AM */
+#define PROGRESS_CREATEIDX_TUPLES_TOTAL 11
+#define PROGRESS_CREATEIDX_TUPLES_DONE 12
+#define PROGRESS_CREATEIDX_PARTITIONS_TOTAL 13
+#define PROGRESS_CREATEIDX_PARTITIONS_DONE 14
+/* 15 and 16 reserved for "block number" metrics */
+
+/* Phases of CREATE INDEX (as advertised via PROGRESS_CREATEIDX_PHASE) */
+#define PROGRESS_CREATEIDX_PHASE_WAIT_1 1
+#define PROGRESS_CREATEIDX_PHASE_BUILD 2
+#define PROGRESS_CREATEIDX_PHASE_WAIT_2 3
+#define PROGRESS_CREATEIDX_PHASE_VALIDATE_IDXSCAN 4
+#define PROGRESS_CREATEIDX_PHASE_VALIDATE_SORT 5
+#define PROGRESS_CREATEIDX_PHASE_VALIDATE_TABLESCAN 6
+#define PROGRESS_CREATEIDX_PHASE_WAIT_3 7
+#define PROGRESS_CREATEIDX_PHASE_WAIT_4 8
+#define PROGRESS_CREATEIDX_PHASE_WAIT_5 9
+
+/*
+ * Subphases of CREATE INDEX, for index_build.
+ */
+#define PROGRESS_CREATEIDX_SUBPHASE_INITIALIZE 1
+/* Additional phases are defined by each AM */
+
+/* Commands of PROGRESS_CREATEIDX */
+#define PROGRESS_CREATEIDX_COMMAND_CREATE 1
+#define PROGRESS_CREATEIDX_COMMAND_CREATE_CONCURRENTLY 2
+#define PROGRESS_CREATEIDX_COMMAND_REINDEX 3
+#define PROGRESS_CREATEIDX_COMMAND_REINDEX_CONCURRENTLY 4
+
+/* Lock holder wait counts */
+#define PROGRESS_WAITFOR_TOTAL 3
+#define PROGRESS_WAITFOR_DONE 4
+#define PROGRESS_WAITFOR_CURRENT_PID 5
+
+/* Block numbers in a generic relation scan */
+#define PROGRESS_SCAN_BLOCKS_TOTAL 15
+#define PROGRESS_SCAN_BLOCKS_DONE 16
+
+/* Progress parameters for pg_basebackup */
+#define PROGRESS_BASEBACKUP_PHASE 0
+#define PROGRESS_BASEBACKUP_BACKUP_TOTAL 1
+#define PROGRESS_BASEBACKUP_BACKUP_STREAMED 2
+#define PROGRESS_BASEBACKUP_TBLSPC_TOTAL 3
+#define PROGRESS_BASEBACKUP_TBLSPC_STREAMED 4
+
+/* Phases of pg_basebackup (as advertised via PROGRESS_BASEBACKUP_PHASE) */
+#define PROGRESS_BASEBACKUP_PHASE_WAIT_CHECKPOINT 1
+#define PROGRESS_BASEBACKUP_PHASE_ESTIMATE_BACKUP_SIZE 2
+#define PROGRESS_BASEBACKUP_PHASE_STREAM_BACKUP 3
+#define PROGRESS_BASEBACKUP_PHASE_WAIT_WAL_ARCHIVE 4
+#define PROGRESS_BASEBACKUP_PHASE_TRANSFER_WAL 5
+
+#endif
diff --git a/src/include/commands/publicationcmds.h b/src/include/commands/publicationcmds.h
new file mode 100644
index 0000000..e713df0
--- /dev/null
+++ b/src/include/commands/publicationcmds.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ *
+ * publicationcmds.h
+ * prototypes for publicationcmds.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/publicationcmds.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef PUBLICATIONCMDS_H
+#define PUBLICATIONCMDS_H
+
+#include "catalog/objectaddress.h"
+#include "nodes/parsenodes.h"
+
+extern ObjectAddress CreatePublication(CreatePublicationStmt *stmt);
+extern void AlterPublication(AlterPublicationStmt *stmt);
+extern void RemovePublicationById(Oid pubid);
+extern void RemovePublicationRelById(Oid proid);
+
+extern ObjectAddress AlterPublicationOwner(const char *name, Oid newOwnerId);
+extern void AlterPublicationOwner_oid(Oid pubid, Oid newOwnerId);
+
+#endif /* PUBLICATIONCMDS_H */
diff --git a/src/include/commands/schemacmds.h b/src/include/commands/schemacmds.h
new file mode 100644
index 0000000..ac88a35
--- /dev/null
+++ b/src/include/commands/schemacmds.h
@@ -0,0 +1,31 @@
+/*-------------------------------------------------------------------------
+ *
+ * schemacmds.h
+ * prototypes for schemacmds.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/schemacmds.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef SCHEMACMDS_H
+#define SCHEMACMDS_H
+
+#include "catalog/objectaddress.h"
+#include "nodes/parsenodes.h"
+
+extern Oid CreateSchemaCommand(CreateSchemaStmt *parsetree,
+ const char *queryString,
+ int stmt_location, int stmt_len);
+
+extern void RemoveSchemaById(Oid schemaOid);
+
+extern ObjectAddress RenameSchema(const char *oldname, const char *newname);
+extern ObjectAddress AlterSchemaOwner(const char *name, Oid newOwnerId);
+extern void AlterSchemaOwner_oid(Oid schemaOid, Oid newOwnerId);
+
+#endif /* SCHEMACMDS_H */
diff --git a/src/include/commands/seclabel.h b/src/include/commands/seclabel.h
new file mode 100644
index 0000000..42fe4c0
--- /dev/null
+++ b/src/include/commands/seclabel.h
@@ -0,0 +1,34 @@
+/*
+ * seclabel.h
+ *
+ * Prototypes for functions in commands/seclabel.c
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ */
+#ifndef SECLABEL_H
+#define SECLABEL_H
+
+#include "catalog/objectaddress.h"
+
+/*
+ * Internal APIs
+ */
+extern char *GetSecurityLabel(const ObjectAddress *object,
+ const char *provider);
+extern void SetSecurityLabel(const ObjectAddress *object,
+ const char *provider, const char *label);
+extern void DeleteSecurityLabel(const ObjectAddress *object);
+extern void DeleteSharedSecurityLabel(Oid objectId, Oid classId);
+
+/*
+ * Statement and ESP hook support
+ */
+extern ObjectAddress ExecSecLabelStmt(SecLabelStmt *stmt);
+
+typedef void (*check_object_relabel_type) (const ObjectAddress *object,
+ const char *seclabel);
+extern void register_label_provider(const char *provider,
+ check_object_relabel_type hook);
+
+#endif /* SECLABEL_H */
diff --git a/src/include/commands/sequence.h b/src/include/commands/sequence.h
new file mode 100644
index 0000000..e2638ab
--- /dev/null
+++ b/src/include/commands/sequence.h
@@ -0,0 +1,69 @@
+/*-------------------------------------------------------------------------
+ *
+ * sequence.h
+ * prototypes for sequence.c.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/sequence.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SEQUENCE_H
+#define SEQUENCE_H
+
+#include "access/xlogreader.h"
+#include "catalog/objectaddress.h"
+#include "fmgr.h"
+#include "lib/stringinfo.h"
+#include "nodes/parsenodes.h"
+#include "parser/parse_node.h"
+#include "storage/relfilenode.h"
+
+
+typedef struct FormData_pg_sequence_data
+{
+ int64 last_value;
+ int64 log_cnt;
+ bool is_called;
+} FormData_pg_sequence_data;
+
+typedef FormData_pg_sequence_data *Form_pg_sequence_data;
+
+/*
+ * Columns of a sequence relation
+ */
+
+#define SEQ_COL_LASTVAL 1
+#define SEQ_COL_LOG 2
+#define SEQ_COL_CALLED 3
+
+#define SEQ_COL_FIRSTCOL SEQ_COL_LASTVAL
+#define SEQ_COL_LASTCOL SEQ_COL_CALLED
+
+/* XLOG stuff */
+#define XLOG_SEQ_LOG 0x00
+
+typedef struct xl_seq_rec
+{
+ RelFileNode node;
+ /* SEQUENCE TUPLE DATA FOLLOWS AT THE END */
+} xl_seq_rec;
+
+extern int64 nextval_internal(Oid relid, bool check_permissions);
+extern Datum nextval(PG_FUNCTION_ARGS);
+extern List *sequence_options(Oid relid);
+
+extern ObjectAddress DefineSequence(ParseState *pstate, CreateSeqStmt *stmt);
+extern ObjectAddress AlterSequence(ParseState *pstate, AlterSeqStmt *stmt);
+extern void DeleteSequenceTuple(Oid relid);
+extern void ResetSequence(Oid seq_relid);
+extern void ResetSequenceCaches(void);
+
+extern void seq_redo(XLogReaderState *rptr);
+extern void seq_desc(StringInfo buf, XLogReaderState *rptr);
+extern const char *seq_identify(uint8 info);
+extern void seq_mask(char *pagedata, BlockNumber blkno);
+
+#endif /* SEQUENCE_H */
diff --git a/src/include/commands/subscriptioncmds.h b/src/include/commands/subscriptioncmds.h
new file mode 100644
index 0000000..804e47b
--- /dev/null
+++ b/src/include/commands/subscriptioncmds.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ *
+ * subscriptioncmds.h
+ * prototypes for subscriptioncmds.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/subscriptioncmds.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef SUBSCRIPTIONCMDS_H
+#define SUBSCRIPTIONCMDS_H
+
+#include "catalog/objectaddress.h"
+#include "nodes/parsenodes.h"
+
+extern ObjectAddress CreateSubscription(CreateSubscriptionStmt *stmt,
+ bool isTopLevel);
+extern ObjectAddress AlterSubscription(AlterSubscriptionStmt *stmt);
+extern void DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel);
+
+extern ObjectAddress AlterSubscriptionOwner(const char *name, Oid newOwnerId);
+extern void AlterSubscriptionOwner_oid(Oid subid, Oid newOwnerId);
+
+#endif /* SUBSCRIPTIONCMDS_H */
diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h
new file mode 100644
index 0000000..c1581ad
--- /dev/null
+++ b/src/include/commands/tablecmds.h
@@ -0,0 +1,97 @@
+/*-------------------------------------------------------------------------
+ *
+ * tablecmds.h
+ * prototypes for tablecmds.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/tablecmds.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TABLECMDS_H
+#define TABLECMDS_H
+
+#include "access/htup.h"
+#include "catalog/dependency.h"
+#include "catalog/objectaddress.h"
+#include "nodes/parsenodes.h"
+#include "storage/lock.h"
+#include "utils/relcache.h"
+
+struct AlterTableUtilityContext; /* avoid including tcop/utility.h here */
+
+
+extern ObjectAddress DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
+ ObjectAddress *typaddress, const char *queryString);
+
+extern void RemoveRelations(DropStmt *drop);
+
+extern Oid AlterTableLookupRelation(AlterTableStmt *stmt, LOCKMODE lockmode);
+
+extern void AlterTable(AlterTableStmt *stmt, LOCKMODE lockmode,
+ struct AlterTableUtilityContext *context);
+
+extern LOCKMODE AlterTableGetLockLevel(List *cmds);
+
+extern void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lockmode);
+
+extern void AlterTableInternal(Oid relid, List *cmds, bool recurse);
+
+extern Oid AlterTableMoveAll(AlterTableMoveAllStmt *stmt);
+
+extern ObjectAddress AlterTableNamespace(AlterObjectSchemaStmt *stmt,
+ Oid *oldschema);
+
+extern void AlterTableNamespaceInternal(Relation rel, Oid oldNspOid,
+ Oid nspOid, ObjectAddresses *objsMoved);
+
+extern void AlterRelationNamespaceInternal(Relation classRel, Oid relOid,
+ Oid oldNspOid, Oid newNspOid,
+ bool hasDependEntry,
+ ObjectAddresses *objsMoved);
+
+extern void CheckTableNotInUse(Relation rel, const char *stmt);
+
+extern void ExecuteTruncate(TruncateStmt *stmt);
+extern void ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged,
+ DropBehavior behavior, bool restart_seqs);
+
+extern void SetRelationHasSubclass(Oid relationId, bool relhassubclass);
+
+extern ObjectAddress renameatt(RenameStmt *stmt);
+
+extern ObjectAddress RenameConstraint(RenameStmt *stmt);
+
+extern ObjectAddress RenameRelation(RenameStmt *stmt);
+
+extern void RenameRelationInternal(Oid myrelid,
+ const char *newrelname, bool is_internal,
+ bool is_index);
+
+extern void find_composite_type_dependencies(Oid typeOid,
+ Relation origRelation,
+ const char *origTypeName);
+
+extern void check_of_type(HeapTuple typetuple);
+
+extern void register_on_commit_action(Oid relid, OnCommitAction action);
+extern void remove_on_commit_action(Oid relid);
+
+extern void PreCommit_on_commit_actions(void);
+extern void AtEOXact_on_commit_actions(bool isCommit);
+extern void AtEOSubXact_on_commit_actions(bool isCommit,
+ SubTransactionId mySubid,
+ SubTransactionId parentSubid);
+
+extern void RangeVarCallbackOwnsTable(const RangeVar *relation,
+ Oid relId, Oid oldRelId, void *arg);
+
+extern void RangeVarCallbackOwnsRelation(const RangeVar *relation,
+ Oid relId, Oid oldRelId, void *arg);
+extern bool PartConstraintImpliedByRelConstraint(Relation scanrel,
+ List *partConstraint);
+
+#endif /* TABLECMDS_H */
diff --git a/src/include/commands/tablespace.h b/src/include/commands/tablespace.h
new file mode 100644
index 0000000..fd1b28f
--- /dev/null
+++ b/src/include/commands/tablespace.h
@@ -0,0 +1,67 @@
+/*-------------------------------------------------------------------------
+ *
+ * tablespace.h
+ * Tablespace management commands (create/drop tablespace).
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/tablespace.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TABLESPACE_H
+#define TABLESPACE_H
+
+#include "access/xlogreader.h"
+#include "catalog/objectaddress.h"
+#include "lib/stringinfo.h"
+#include "nodes/parsenodes.h"
+
+/* XLOG stuff */
+#define XLOG_TBLSPC_CREATE 0x00
+#define XLOG_TBLSPC_DROP 0x10
+
+typedef struct xl_tblspc_create_rec
+{
+ Oid ts_id;
+ char ts_path[FLEXIBLE_ARRAY_MEMBER]; /* null-terminated string */
+} xl_tblspc_create_rec;
+
+typedef struct xl_tblspc_drop_rec
+{
+ Oid ts_id;
+} xl_tblspc_drop_rec;
+
+typedef struct TableSpaceOpts
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ float8 random_page_cost;
+ float8 seq_page_cost;
+ int effective_io_concurrency;
+ int maintenance_io_concurrency;
+} TableSpaceOpts;
+
+extern Oid CreateTableSpace(CreateTableSpaceStmt *stmt);
+extern void DropTableSpace(DropTableSpaceStmt *stmt);
+extern ObjectAddress RenameTableSpace(const char *oldname, const char *newname);
+extern Oid AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt);
+
+extern void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo);
+
+extern Oid GetDefaultTablespace(char relpersistence, bool partitioned);
+
+extern void PrepareTempTablespaces(void);
+
+extern Oid get_tablespace_oid(const char *tablespacename, bool missing_ok);
+extern char *get_tablespace_name(Oid spc_oid);
+
+extern bool directory_is_empty(const char *path);
+extern void remove_tablespace_symlink(const char *linkloc);
+
+extern void tblspc_redo(XLogReaderState *rptr);
+extern void tblspc_desc(StringInfo buf, XLogReaderState *rptr);
+extern const char *tblspc_identify(uint8 info);
+
+#endif /* TABLESPACE_H */
diff --git a/src/include/commands/trigger.h b/src/include/commands/trigger.h
new file mode 100644
index 0000000..40b8154
--- /dev/null
+++ b/src/include/commands/trigger.h
@@ -0,0 +1,282 @@
+/*-------------------------------------------------------------------------
+ *
+ * trigger.h
+ * Declarations for trigger handling.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/trigger.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TRIGGER_H
+#define TRIGGER_H
+
+#include "catalog/objectaddress.h"
+#include "nodes/execnodes.h"
+#include "nodes/parsenodes.h"
+
+/*
+ * TriggerData is the node type that is passed as fmgr "context" info
+ * when a function is called by the trigger manager.
+ */
+
+#define CALLED_AS_TRIGGER(fcinfo) \
+ ((fcinfo)->context != NULL && IsA((fcinfo)->context, TriggerData))
+
+typedef uint32 TriggerEvent;
+
+typedef struct TriggerData
+{
+ NodeTag type;
+ TriggerEvent tg_event;
+ Relation tg_relation;
+ HeapTuple tg_trigtuple;
+ HeapTuple tg_newtuple;
+ Trigger *tg_trigger;
+ TupleTableSlot *tg_trigslot;
+ TupleTableSlot *tg_newslot;
+ Tuplestorestate *tg_oldtable;
+ Tuplestorestate *tg_newtable;
+ const Bitmapset *tg_updatedcols;
+} TriggerData;
+
+/*
+ * The state for capturing old and new tuples into transition tables for a
+ * single ModifyTable node (or other operation source, e.g. copy.c).
+ *
+ * This is per-caller to avoid conflicts in setting tcs_map or
+ * tcs_original_insert_tuple. Note, however, that the pointed-to
+ * private data may be shared across multiple callers.
+ */
+struct AfterTriggersTableData; /* private in trigger.c */
+
+typedef struct TransitionCaptureState
+{
+ /*
+ * Is there at least one trigger specifying each transition relation on
+ * the relation explicitly named in the DML statement or COPY command?
+ * Note: in current usage, these flags could be part of the private state,
+ * but it seems possibly useful to let callers see them.
+ */
+ bool tcs_delete_old_table;
+ bool tcs_update_old_table;
+ bool tcs_update_new_table;
+ bool tcs_insert_new_table;
+
+ /*
+ * For UPDATE and DELETE, AfterTriggerSaveEvent may need to convert the
+ * new and old tuples from a child table's format to the format of the
+ * relation named in a query so that it is compatible with the transition
+ * tuplestores. The caller must store the conversion map here if so.
+ */
+ TupleConversionMap *tcs_map;
+
+ /*
+ * For INSERT and COPY, it would be wasteful to convert tuples from child
+ * format to parent format after they have already been converted in the
+ * opposite direction during routing. In that case we bypass conversion
+ * and allow the inserting code (copy.c and nodeModifyTable.c) to provide
+ * a slot containing the original tuple directly.
+ */
+ TupleTableSlot *tcs_original_insert_tuple;
+
+ /*
+ * Private data including the tuplestore(s) into which to insert tuples.
+ */
+ struct AfterTriggersTableData *tcs_private;
+} TransitionCaptureState;
+
+/*
+ * TriggerEvent bit flags
+ *
+ * Note that we assume different event types (INSERT/DELETE/UPDATE/TRUNCATE)
+ * can't be OR'd together in a single TriggerEvent. This is unlike the
+ * situation for pg_trigger rows, so pg_trigger.tgtype uses a different
+ * representation!
+ */
+#define TRIGGER_EVENT_INSERT 0x00000000
+#define TRIGGER_EVENT_DELETE 0x00000001
+#define TRIGGER_EVENT_UPDATE 0x00000002
+#define TRIGGER_EVENT_TRUNCATE 0x00000003
+#define TRIGGER_EVENT_OPMASK 0x00000003
+
+#define TRIGGER_EVENT_ROW 0x00000004
+
+#define TRIGGER_EVENT_BEFORE 0x00000008
+#define TRIGGER_EVENT_AFTER 0x00000000
+#define TRIGGER_EVENT_INSTEAD 0x00000010
+#define TRIGGER_EVENT_TIMINGMASK 0x00000018
+
+/* More TriggerEvent flags, used only within trigger.c */
+
+#define AFTER_TRIGGER_DEFERRABLE 0x00000020
+#define AFTER_TRIGGER_INITDEFERRED 0x00000040
+
+#define TRIGGER_FIRED_BY_INSERT(event) \
+ (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_INSERT)
+
+#define TRIGGER_FIRED_BY_DELETE(event) \
+ (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_DELETE)
+
+#define TRIGGER_FIRED_BY_UPDATE(event) \
+ (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_UPDATE)
+
+#define TRIGGER_FIRED_BY_TRUNCATE(event) \
+ (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_TRUNCATE)
+
+#define TRIGGER_FIRED_FOR_ROW(event) \
+ ((event) & TRIGGER_EVENT_ROW)
+
+#define TRIGGER_FIRED_FOR_STATEMENT(event) \
+ (!TRIGGER_FIRED_FOR_ROW(event))
+
+#define TRIGGER_FIRED_BEFORE(event) \
+ (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_BEFORE)
+
+#define TRIGGER_FIRED_AFTER(event) \
+ (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_AFTER)
+
+#define TRIGGER_FIRED_INSTEAD(event) \
+ (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_INSTEAD)
+
+/*
+ * Definitions for replication role based firing.
+ */
+#define SESSION_REPLICATION_ROLE_ORIGIN 0
+#define SESSION_REPLICATION_ROLE_REPLICA 1
+#define SESSION_REPLICATION_ROLE_LOCAL 2
+extern PGDLLIMPORT int SessionReplicationRole;
+
+/*
+ * States at which a trigger can be fired. These are the
+ * possible values for pg_trigger.tgenabled.
+ */
+#define TRIGGER_FIRES_ON_ORIGIN 'O'
+#define TRIGGER_FIRES_ALWAYS 'A'
+#define TRIGGER_FIRES_ON_REPLICA 'R'
+#define TRIGGER_DISABLED 'D'
+
+extern ObjectAddress CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
+ Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid,
+ Oid funcoid, Oid parentTriggerOid, Node *whenClause,
+ bool isInternal, bool in_partition);
+extern ObjectAddress CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString,
+ Oid relOid, Oid refRelOid, Oid constraintOid,
+ Oid indexOid, Oid funcoid, Oid parentTriggerOid,
+ Node *whenClause, bool isInternal, bool in_partition,
+ char trigger_fires_when);
+
+extern void RemoveTriggerById(Oid trigOid);
+extern Oid get_trigger_oid(Oid relid, const char *name, bool missing_ok);
+
+extern ObjectAddress renametrig(RenameStmt *stmt);
+
+extern void EnableDisableTrigger(Relation rel, const char *tgname,
+ char fires_when, bool skip_system, LOCKMODE lockmode);
+
+extern void RelationBuildTriggers(Relation relation);
+
+extern TriggerDesc *CopyTriggerDesc(TriggerDesc *trigdesc);
+
+extern const char *FindTriggerIncompatibleWithInheritance(TriggerDesc *trigdesc);
+
+extern TransitionCaptureState *MakeTransitionCaptureState(TriggerDesc *trigdesc,
+ Oid relid, CmdType cmdType);
+
+extern void FreeTriggerDesc(TriggerDesc *trigdesc);
+
+extern void ExecBSInsertTriggers(EState *estate,
+ ResultRelInfo *relinfo);
+extern void ExecASInsertTriggers(EState *estate,
+ ResultRelInfo *relinfo,
+ TransitionCaptureState *transition_capture);
+extern bool ExecBRInsertTriggers(EState *estate,
+ ResultRelInfo *relinfo,
+ TupleTableSlot *slot);
+extern void ExecARInsertTriggers(EState *estate,
+ ResultRelInfo *relinfo,
+ TupleTableSlot *slot,
+ List *recheckIndexes,
+ TransitionCaptureState *transition_capture);
+extern bool ExecIRInsertTriggers(EState *estate,
+ ResultRelInfo *relinfo,
+ TupleTableSlot *slot);
+extern void ExecBSDeleteTriggers(EState *estate,
+ ResultRelInfo *relinfo);
+extern void ExecASDeleteTriggers(EState *estate,
+ ResultRelInfo *relinfo,
+ TransitionCaptureState *transition_capture);
+extern bool ExecBRDeleteTriggers(EState *estate,
+ EPQState *epqstate,
+ ResultRelInfo *relinfo,
+ ItemPointer tupleid,
+ HeapTuple fdw_trigtuple,
+ TupleTableSlot **epqslot);
+extern void ExecARDeleteTriggers(EState *estate,
+ ResultRelInfo *relinfo,
+ ItemPointer tupleid,
+ HeapTuple fdw_trigtuple,
+ TransitionCaptureState *transition_capture);
+extern bool ExecIRDeleteTriggers(EState *estate,
+ ResultRelInfo *relinfo,
+ HeapTuple trigtuple);
+extern void ExecBSUpdateTriggers(EState *estate,
+ ResultRelInfo *relinfo);
+extern void ExecASUpdateTriggers(EState *estate,
+ ResultRelInfo *relinfo,
+ TransitionCaptureState *transition_capture);
+extern bool ExecBRUpdateTriggers(EState *estate,
+ EPQState *epqstate,
+ ResultRelInfo *relinfo,
+ ItemPointer tupleid,
+ HeapTuple fdw_trigtuple,
+ TupleTableSlot *slot);
+extern void ExecARUpdateTriggers(EState *estate,
+ ResultRelInfo *relinfo,
+ ItemPointer tupleid,
+ HeapTuple fdw_trigtuple,
+ TupleTableSlot *slot,
+ List *recheckIndexes,
+ TransitionCaptureState *transition_capture);
+extern bool ExecIRUpdateTriggers(EState *estate,
+ ResultRelInfo *relinfo,
+ HeapTuple trigtuple,
+ TupleTableSlot *slot);
+extern void ExecBSTruncateTriggers(EState *estate,
+ ResultRelInfo *relinfo);
+extern void ExecASTruncateTriggers(EState *estate,
+ ResultRelInfo *relinfo);
+
+extern void AfterTriggerBeginXact(void);
+extern void AfterTriggerBeginQuery(void);
+extern void AfterTriggerEndQuery(EState *estate);
+extern void AfterTriggerFireDeferred(void);
+extern void AfterTriggerEndXact(bool isCommit);
+extern void AfterTriggerBeginSubXact(void);
+extern void AfterTriggerEndSubXact(bool isCommit);
+extern void AfterTriggerSetState(ConstraintsSetStmt *stmt);
+extern bool AfterTriggerPendingOnRel(Oid relid);
+
+
+/*
+ * in utils/adt/ri_triggers.c
+ */
+extern bool RI_FKey_pk_upd_check_required(Trigger *trigger, Relation pk_rel,
+ TupleTableSlot *old_slot, TupleTableSlot *new_slot);
+extern bool RI_FKey_fk_upd_check_required(Trigger *trigger, Relation fk_rel,
+ TupleTableSlot *old_slot, TupleTableSlot *new_slot);
+extern bool RI_Initial_Check(Trigger *trigger,
+ Relation fk_rel, Relation pk_rel);
+extern void RI_PartitionRemove_Check(Trigger *trigger, Relation fk_rel,
+ Relation pk_rel);
+
+/* result values for RI_FKey_trigger_type: */
+#define RI_TRIGGER_PK 1 /* is a trigger on the PK relation */
+#define RI_TRIGGER_FK 2 /* is a trigger on the FK relation */
+#define RI_TRIGGER_NONE 0 /* is not an RI trigger function */
+
+extern int RI_FKey_trigger_type(Oid tgfoid);
+
+#endif /* TRIGGER_H */
diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h
new file mode 100644
index 0000000..2313089
--- /dev/null
+++ b/src/include/commands/typecmds.h
@@ -0,0 +1,59 @@
+/*-------------------------------------------------------------------------
+ *
+ * typecmds.h
+ * prototypes for typecmds.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/typecmds.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TYPECMDS_H
+#define TYPECMDS_H
+
+#include "access/htup.h"
+#include "catalog/dependency.h"
+#include "parser/parse_node.h"
+
+
+#define DEFAULT_TYPDELIM ','
+
+extern ObjectAddress DefineType(ParseState *pstate, List *names, List *parameters);
+extern void RemoveTypeById(Oid typeOid);
+extern ObjectAddress DefineDomain(CreateDomainStmt *stmt);
+extern ObjectAddress DefineEnum(CreateEnumStmt *stmt);
+extern ObjectAddress DefineRange(CreateRangeStmt *stmt);
+extern ObjectAddress AlterEnum(AlterEnumStmt *stmt);
+extern ObjectAddress DefineCompositeType(RangeVar *typevar, List *coldeflist);
+extern Oid AssignTypeArrayOid(void);
+
+extern ObjectAddress AlterDomainDefault(List *names, Node *defaultRaw);
+extern ObjectAddress AlterDomainNotNull(List *names, bool notNull);
+extern ObjectAddress AlterDomainAddConstraint(List *names, Node *constr,
+ ObjectAddress *constrAddr);
+extern ObjectAddress AlterDomainValidateConstraint(List *names, const char *constrName);
+extern ObjectAddress AlterDomainDropConstraint(List *names, const char *constrName,
+ DropBehavior behavior, bool missing_ok);
+
+extern void checkDomainOwner(HeapTuple tup);
+
+extern ObjectAddress RenameType(RenameStmt *stmt);
+
+extern ObjectAddress AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype);
+extern void AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry);
+extern void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId);
+
+extern ObjectAddress AlterTypeNamespace(List *names, const char *newschema,
+ ObjectType objecttype, Oid *oldschema);
+extern Oid AlterTypeNamespace_oid(Oid typeOid, Oid nspOid, ObjectAddresses *objsMoved);
+extern Oid AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid,
+ bool isImplicitArray,
+ bool errorOnTableType,
+ ObjectAddresses *objsMoved);
+
+extern ObjectAddress AlterType(AlterTypeStmt *stmt);
+
+#endif /* TYPECMDS_H */
diff --git a/src/include/commands/user.h b/src/include/commands/user.h
new file mode 100644
index 0000000..028e0dd
--- /dev/null
+++ b/src/include/commands/user.h
@@ -0,0 +1,37 @@
+/*-------------------------------------------------------------------------
+ *
+ * user.h
+ * Commands for manipulating roles (formerly called users).
+ *
+ *
+ * src/include/commands/user.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef USER_H
+#define USER_H
+
+#include "catalog/objectaddress.h"
+#include "libpq/crypt.h"
+#include "nodes/parsenodes.h"
+#include "parser/parse_node.h"
+
+/* GUC. Is actually of type PasswordType. */
+extern int Password_encryption;
+
+/* Hook to check passwords in CreateRole() and AlterRole() */
+typedef void (*check_password_hook_type) (const char *username, const char *shadow_pass, PasswordType password_type, Datum validuntil_time, bool validuntil_null);
+
+extern PGDLLIMPORT check_password_hook_type check_password_hook;
+
+extern Oid CreateRole(ParseState *pstate, CreateRoleStmt *stmt);
+extern Oid AlterRole(AlterRoleStmt *stmt);
+extern Oid AlterRoleSet(AlterRoleSetStmt *stmt);
+extern void DropRole(DropRoleStmt *stmt);
+extern void GrantRole(GrantRoleStmt *stmt);
+extern ObjectAddress RenameRole(const char *oldname, const char *newname);
+extern void DropOwnedObjects(DropOwnedStmt *stmt);
+extern void ReassignOwnedObjects(ReassignOwnedStmt *stmt);
+extern List *roleSpecsToIds(List *memberNames);
+
+#endif /* USER_H */
diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h
new file mode 100644
index 0000000..a4cd721
--- /dev/null
+++ b/src/include/commands/vacuum.h
@@ -0,0 +1,293 @@
+/*-------------------------------------------------------------------------
+ *
+ * vacuum.h
+ * header file for postgres vacuum cleaner and statistics analyzer
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/vacuum.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef VACUUM_H
+#define VACUUM_H
+
+#include "access/htup.h"
+#include "catalog/pg_class.h"
+#include "catalog/pg_statistic.h"
+#include "catalog/pg_type.h"
+#include "parser/parse_node.h"
+#include "storage/buf.h"
+#include "storage/lock.h"
+#include "utils/relcache.h"
+
+/*
+ * Flags for amparallelvacuumoptions to control the participation of bulkdelete
+ * and vacuumcleanup in parallel vacuum.
+ */
+
+/*
+ * Both bulkdelete and vacuumcleanup are disabled by default. This will be
+ * used by IndexAM's that don't want to or cannot participate in parallel
+ * vacuum. For example, if an index AM doesn't have a way to communicate the
+ * index statistics allocated by the first ambulkdelete call to the subsequent
+ * ones until amvacuumcleanup, the index AM cannot participate in parallel
+ * vacuum.
+ */
+#define VACUUM_OPTION_NO_PARALLEL 0
+
+/*
+ * bulkdelete can be performed in parallel. This option can be used by
+ * IndexAm's that need to scan the index to delete the tuples.
+ */
+#define VACUUM_OPTION_PARALLEL_BULKDEL (1 << 0)
+
+/*
+ * vacuumcleanup can be performed in parallel if bulkdelete is not performed
+ * yet. This will be used by IndexAM's that can scan the index if the
+ * bulkdelete is not performed.
+ */
+#define VACUUM_OPTION_PARALLEL_COND_CLEANUP (1 << 1)
+
+/*
+ * vacuumcleanup can be performed in parallel even if bulkdelete has already
+ * processed the index. This will be used by IndexAM's that scan the index
+ * during the cleanup phase of index irrespective of whether the index is
+ * already scanned or not during bulkdelete phase.
+ */
+#define VACUUM_OPTION_PARALLEL_CLEANUP (1 << 2)
+
+/* value for checking vacuum flags */
+#define VACUUM_OPTION_MAX_VALID_VALUE ((1 << 3) - 1)
+
+/*----------
+ * ANALYZE builds one of these structs for each attribute (column) that is
+ * to be analyzed. The struct and subsidiary data are in anl_context,
+ * so they live until the end of the ANALYZE operation.
+ *
+ * The type-specific typanalyze function is passed a pointer to this struct
+ * and must return true to continue analysis, false to skip analysis of this
+ * column. In the true case it must set the compute_stats and minrows fields,
+ * and can optionally set extra_data to pass additional info to compute_stats.
+ * minrows is its request for the minimum number of sample rows to be gathered
+ * (but note this request might not be honored, eg if there are fewer rows
+ * than that in the table).
+ *
+ * The compute_stats routine will be called after sample rows have been
+ * gathered. Aside from this struct, it is passed:
+ * fetchfunc: a function for accessing the column values from the
+ * sample rows
+ * samplerows: the number of sample tuples
+ * totalrows: estimated total number of rows in relation
+ * The fetchfunc may be called with rownum running from 0 to samplerows-1.
+ * It returns a Datum and an isNull flag.
+ *
+ * compute_stats should set stats_valid true if it is able to compute
+ * any useful statistics. If it does, the remainder of the struct holds
+ * the information to be stored in a pg_statistic row for the column. Be
+ * careful to allocate any pointed-to data in anl_context, which will NOT
+ * be CurrentMemoryContext when compute_stats is called.
+ *
+ * Note: all comparisons done for statistical purposes should use the
+ * underlying column's collation (attcollation), except in situations
+ * where a noncollatable container type contains a collatable type;
+ * in that case use the type's default collation. Be sure to record
+ * the appropriate collation in stacoll.
+ *----------
+ */
+typedef struct VacAttrStats *VacAttrStatsP;
+
+typedef Datum (*AnalyzeAttrFetchFunc) (VacAttrStatsP stats, int rownum,
+ bool *isNull);
+
+typedef void (*AnalyzeAttrComputeStatsFunc) (VacAttrStatsP stats,
+ AnalyzeAttrFetchFunc fetchfunc,
+ int samplerows,
+ double totalrows);
+
+typedef struct VacAttrStats
+{
+ /*
+ * These fields are set up by the main ANALYZE code before invoking the
+ * type-specific typanalyze function.
+ *
+ * Note: do not assume that the data being analyzed has the same datatype
+ * shown in attr, ie do not trust attr->atttypid, attlen, etc. This is
+ * because some index opclasses store a different type than the underlying
+ * column/expression. Instead use attrtypid, attrtypmod, and attrtype for
+ * information about the datatype being fed to the typanalyze function.
+ * Likewise, use attrcollid not attr->attcollation.
+ */
+ Form_pg_attribute attr; /* copy of pg_attribute row for column */
+ Oid attrtypid; /* type of data being analyzed */
+ int32 attrtypmod; /* typmod of data being analyzed */
+ Form_pg_type attrtype; /* copy of pg_type row for attrtypid */
+ Oid attrcollid; /* collation of data being analyzed */
+ MemoryContext anl_context; /* where to save long-lived data */
+
+ /*
+ * These fields must be filled in by the typanalyze routine, unless it
+ * returns false.
+ */
+ AnalyzeAttrComputeStatsFunc compute_stats; /* function pointer */
+ int minrows; /* Minimum # of rows wanted for stats */
+ void *extra_data; /* for extra type-specific data */
+
+ /*
+ * These fields are to be filled in by the compute_stats routine. (They
+ * are initialized to zero when the struct is created.)
+ */
+ bool stats_valid;
+ float4 stanullfrac; /* fraction of entries that are NULL */
+ int32 stawidth; /* average width of column values */
+ float4 stadistinct; /* # distinct values */
+ int16 stakind[STATISTIC_NUM_SLOTS];
+ Oid staop[STATISTIC_NUM_SLOTS];
+ Oid stacoll[STATISTIC_NUM_SLOTS];
+ int numnumbers[STATISTIC_NUM_SLOTS];
+ float4 *stanumbers[STATISTIC_NUM_SLOTS];
+ int numvalues[STATISTIC_NUM_SLOTS];
+ Datum *stavalues[STATISTIC_NUM_SLOTS];
+
+ /*
+ * These fields describe the stavalues[n] element types. They will be
+ * initialized to match attrtypid, but a custom typanalyze function might
+ * want to store an array of something other than the analyzed column's
+ * elements. It should then overwrite these fields.
+ */
+ Oid statypid[STATISTIC_NUM_SLOTS];
+ int16 statyplen[STATISTIC_NUM_SLOTS];
+ bool statypbyval[STATISTIC_NUM_SLOTS];
+ char statypalign[STATISTIC_NUM_SLOTS];
+
+ /*
+ * These fields are private to the main ANALYZE code and should not be
+ * looked at by type-specific functions.
+ */
+ int tupattnum; /* attribute number within tuples */
+ HeapTuple *rows; /* access info for std fetch function */
+ TupleDesc tupDesc;
+ Datum *exprvals; /* access info for index fetch function */
+ bool *exprnulls;
+ int rowstride;
+} VacAttrStats;
+
+typedef enum VacuumOption
+{
+ VACOPT_VACUUM = 1 << 0, /* do VACUUM */
+ VACOPT_ANALYZE = 1 << 1, /* do ANALYZE */
+ VACOPT_VERBOSE = 1 << 2, /* print progress info */
+ VACOPT_FREEZE = 1 << 3, /* FREEZE option */
+ VACOPT_FULL = 1 << 4, /* FULL (non-concurrent) vacuum */
+ VACOPT_SKIP_LOCKED = 1 << 5, /* skip if cannot get lock */
+ VACOPT_SKIPTOAST = 1 << 6, /* don't process the TOAST table, if any */
+ VACOPT_DISABLE_PAGE_SKIPPING = 1 << 7 /* don't skip any pages */
+} VacuumOption;
+
+/*
+ * A ternary value used by vacuum parameters.
+ *
+ * DEFAULT value is used to determine the value based on other
+ * configurations, e.g. reloptions.
+ */
+typedef enum VacOptTernaryValue
+{
+ VACOPT_TERNARY_DEFAULT = 0,
+ VACOPT_TERNARY_DISABLED,
+ VACOPT_TERNARY_ENABLED,
+} VacOptTernaryValue;
+
+/*
+ * Parameters customizing behavior of VACUUM and ANALYZE.
+ *
+ * Note that at least one of VACOPT_VACUUM and VACOPT_ANALYZE must be set
+ * in options.
+ */
+typedef struct VacuumParams
+{
+ int options; /* bitmask of VacuumOption */
+ int freeze_min_age; /* min freeze age, -1 to use default */
+ int freeze_table_age; /* age at which to scan whole table */
+ int multixact_freeze_min_age; /* min multixact freeze age, -1 to
+ * use default */
+ int multixact_freeze_table_age; /* multixact age at which to scan
+ * whole table */
+ bool is_wraparound; /* force a for-wraparound vacuum */
+ int log_min_duration; /* minimum execution threshold in ms at
+ * which verbose logs are activated, -1
+ * to use default */
+ VacOptTernaryValue index_cleanup; /* Do index vacuum and cleanup,
+ * default value depends on reloptions */
+ VacOptTernaryValue truncate; /* Truncate empty pages at the end,
+ * default value depends on reloptions */
+
+ /*
+ * The number of parallel vacuum workers. 0 by default which means choose
+ * based on the number of indexes. -1 indicates parallel vacuum is
+ * disabled.
+ */
+ int nworkers;
+} VacuumParams;
+
+/* GUC parameters */
+extern PGDLLIMPORT int default_statistics_target; /* PGDLLIMPORT for PostGIS */
+extern int vacuum_freeze_min_age;
+extern int vacuum_freeze_table_age;
+extern int vacuum_multixact_freeze_min_age;
+extern int vacuum_multixact_freeze_table_age;
+
+/* Variables for cost-based parallel vacuum */
+extern pg_atomic_uint32 *VacuumSharedCostBalance;
+extern pg_atomic_uint32 *VacuumActiveNWorkers;
+extern int VacuumCostBalanceLocal;
+
+
+/* in commands/vacuum.c */
+extern void ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel);
+extern void vacuum(List *relations, VacuumParams *params,
+ BufferAccessStrategy bstrategy, bool isTopLevel);
+extern void vac_open_indexes(Relation relation, LOCKMODE lockmode,
+ int *nindexes, Relation **Irel);
+extern void vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode);
+extern double vac_estimate_reltuples(Relation relation,
+ BlockNumber total_pages,
+ BlockNumber scanned_pages,
+ double scanned_tuples);
+extern void vac_update_relstats(Relation relation,
+ BlockNumber num_pages,
+ double num_tuples,
+ BlockNumber num_all_visible_pages,
+ bool hasindex,
+ TransactionId frozenxid,
+ MultiXactId minmulti,
+ bool in_outer_xact);
+extern void vacuum_set_xid_limits(Relation rel,
+ int freeze_min_age, int freeze_table_age,
+ int multixact_freeze_min_age,
+ int multixact_freeze_table_age,
+ TransactionId *oldestXmin,
+ TransactionId *freezeLimit,
+ TransactionId *xidFullScanLimit,
+ MultiXactId *multiXactCutoff,
+ MultiXactId *mxactFullScanLimit);
+extern void vac_update_datfrozenxid(void);
+extern void vacuum_delay_point(void);
+extern bool vacuum_is_relation_owner(Oid relid, Form_pg_class reltuple,
+ int options);
+extern Relation vacuum_open_relation(Oid relid, RangeVar *relation,
+ int options, bool verbose, LOCKMODE lmode);
+
+/* in commands/analyze.c */
+extern void analyze_rel(Oid relid, RangeVar *relation,
+ VacuumParams *params, List *va_cols, bool in_outer_xact,
+ BufferAccessStrategy bstrategy);
+extern bool std_typanalyze(VacAttrStats *stats);
+
+/* in utils/misc/sampling.c --- duplicate of declarations in utils/sampling.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 /* VACUUM_H */
diff --git a/src/include/commands/variable.h b/src/include/commands/variable.h
new file mode 100644
index 0000000..2749ff1
--- /dev/null
+++ b/src/include/commands/variable.h
@@ -0,0 +1,38 @@
+/*
+ * variable.h
+ * Routines for handling specialized SET variables.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/variable.h
+ */
+#ifndef VARIABLE_H
+#define VARIABLE_H
+
+#include "utils/guc.h"
+
+
+extern bool check_datestyle(char **newval, void **extra, GucSource source);
+extern void assign_datestyle(const char *newval, void *extra);
+extern bool check_timezone(char **newval, void **extra, GucSource source);
+extern void assign_timezone(const char *newval, void *extra);
+extern const char *show_timezone(void);
+extern bool check_log_timezone(char **newval, void **extra, GucSource source);
+extern void assign_log_timezone(const char *newval, void *extra);
+extern const char *show_log_timezone(void);
+extern bool check_transaction_read_only(bool *newval, void **extra, GucSource source);
+extern bool check_XactIsoLevel(int *newval, void **extra, GucSource source);
+extern bool check_transaction_deferrable(bool *newval, void **extra, GucSource source);
+extern bool check_random_seed(double *newval, void **extra, GucSource source);
+extern void assign_random_seed(double newval, void *extra);
+extern const char *show_random_seed(void);
+extern bool check_client_encoding(char **newval, void **extra, GucSource source);
+extern void assign_client_encoding(const char *newval, void *extra);
+extern bool check_session_authorization(char **newval, void **extra, GucSource source);
+extern void assign_session_authorization(const char *newval, void *extra);
+extern bool check_role(char **newval, void **extra, GucSource source);
+extern void assign_role(const char *newval, void *extra);
+extern const char *show_role(void);
+
+#endif /* VARIABLE_H */
diff --git a/src/include/commands/view.h b/src/include/commands/view.h
new file mode 100644
index 0000000..44a16d8
--- /dev/null
+++ b/src/include/commands/view.h
@@ -0,0 +1,25 @@
+/*-------------------------------------------------------------------------
+ *
+ * view.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/commands/view.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef VIEW_H
+#define VIEW_H
+
+#include "catalog/objectaddress.h"
+#include "nodes/parsenodes.h"
+
+extern ObjectAddress DefineView(ViewStmt *stmt, const char *queryString,
+ int stmt_location, int stmt_len);
+
+extern void StoreViewQuery(Oid viewOid, Query *viewParse, bool replace);
+
+#endif /* VIEW_H */
diff --git a/src/include/common/archive.h b/src/include/common/archive.h
new file mode 100644
index 0000000..b269910
--- /dev/null
+++ b/src/include/common/archive.h
@@ -0,0 +1,21 @@
+/*-------------------------------------------------------------------------
+ *
+ * archive.h
+ * Common WAL archive routines
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/archive.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ARCHIVE_H
+#define ARCHIVE_H
+
+extern char *BuildRestoreCommand(const char *restoreCommand,
+ const char *xlogpath, /* %p */
+ const char *xlogfname, /* %f */
+ const char *lastRestartPointFname); /* %r */
+
+#endif /* ARCHIVE_H */
diff --git a/src/include/common/base64.h b/src/include/common/base64.h
new file mode 100644
index 0000000..5de4499
--- /dev/null
+++ b/src/include/common/base64.h
@@ -0,0 +1,19 @@
+/*
+ * base64.h
+ * Encoding and decoding routines for base64 without whitespace
+ * support.
+ *
+ * Portions Copyright (c) 2001-2020, PostgreSQL Global Development Group
+ *
+ * src/include/common/base64.h
+ */
+#ifndef BASE64_H
+#define BASE64_H
+
+/* base 64 */
+extern int pg_b64_encode(const char *src, int len, char *dst, int dstlen);
+extern int pg_b64_decode(const char *src, int len, char *dst, int dstlen);
+extern int pg_b64_enc_len(int srclen);
+extern int pg_b64_dec_len(int srclen);
+
+#endif /* BASE64_H */
diff --git a/src/include/common/checksum_helper.h b/src/include/common/checksum_helper.h
new file mode 100644
index 0000000..48b0745
--- /dev/null
+++ b/src/include/common/checksum_helper.h
@@ -0,0 +1,74 @@
+/*-------------------------------------------------------------------------
+ *
+ * checksum_helper.h
+ * Compute a checksum of any of various types using common routines
+ *
+ * Portions Copyright (c) 2016-2020, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/common/checksum_helper.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef CHECKSUM_HELPER_H
+#define CHECKSUM_HELPER_H
+
+#include "common/sha2.h"
+#include "port/pg_crc32c.h"
+
+/*
+ * Supported checksum types. It's not necessarily the case that code using
+ * these functions needs a cryptographically strong checksum; it may only
+ * need to detect accidental modification. That's why we include CRC-32C: it's
+ * much faster than any of the other algorithms. On the other hand, we omit
+ * MD5 here because any new that does need a cryptographically strong checksum
+ * should use something better.
+ */
+typedef enum pg_checksum_type
+{
+ CHECKSUM_TYPE_NONE,
+ CHECKSUM_TYPE_CRC32C,
+ CHECKSUM_TYPE_SHA224,
+ CHECKSUM_TYPE_SHA256,
+ CHECKSUM_TYPE_SHA384,
+ CHECKSUM_TYPE_SHA512
+} pg_checksum_type;
+
+/*
+ * This is just a union of all applicable context types.
+ */
+typedef union pg_checksum_raw_context
+{
+ pg_crc32c c_crc32c;
+ pg_sha224_ctx c_sha224;
+ pg_sha256_ctx c_sha256;
+ pg_sha384_ctx c_sha384;
+ pg_sha512_ctx c_sha512;
+} pg_checksum_raw_context;
+
+/*
+ * This structure provides a convenient way to pass the checksum type and the
+ * checksum context around together.
+ */
+typedef struct pg_checksum_context
+{
+ pg_checksum_type type;
+ pg_checksum_raw_context raw_context;
+} pg_checksum_context;
+
+/*
+ * This is the longest possible output for any checksum algorithm supported
+ * by this file.
+ */
+#define PG_CHECKSUM_MAX_LENGTH PG_SHA512_DIGEST_LENGTH
+
+extern bool pg_checksum_parse_type(char *name, pg_checksum_type *);
+extern char *pg_checksum_type_name(pg_checksum_type);
+
+extern void pg_checksum_init(pg_checksum_context *, pg_checksum_type);
+extern void pg_checksum_update(pg_checksum_context *, const uint8 *input,
+ size_t len);
+extern int pg_checksum_final(pg_checksum_context *, uint8 *output);
+
+#endif
diff --git a/src/include/common/config_info.h b/src/include/common/config_info.h
new file mode 100644
index 0000000..f36b783
--- /dev/null
+++ b/src/include/common/config_info.h
@@ -0,0 +1,21 @@
+/*
+ * config_info.h
+ * Common code for pg_config output
+ *
+ * Copyright (c) 2016-2020, PostgreSQL Global Development Group
+ *
+ * src/include/common/config_info.h
+ */
+#ifndef COMMON_CONFIG_INFO_H
+#define COMMON_CONFIG_INFO_H
+
+typedef struct ConfigData
+{
+ char *name;
+ char *setting;
+} ConfigData;
+
+extern ConfigData *get_configdata(const char *my_exec_path,
+ size_t *configdata_len);
+
+#endif /* COMMON_CONFIG_INFO_H */
diff --git a/src/include/common/connect.h b/src/include/common/connect.h
new file mode 100644
index 0000000..2cc5d7d
--- /dev/null
+++ b/src/include/common/connect.h
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+ *
+ * Interfaces in support of FE/BE connections.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/connect.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef CONNECT_H
+#define CONNECT_H
+
+/*
+ * This SQL statement installs an always-secure search path, so malicious
+ * users can't take control. CREATE of an unqualified name will fail, because
+ * this selects no creation schema. This does not demote pg_temp, so it is
+ * suitable where we control the entire FE/BE connection but not suitable in
+ * SECURITY DEFINER functions. This is portable to PostgreSQL 7.3, which
+ * introduced schemas. When connected to an older version from code that
+ * might work with the old server, skip this.
+ */
+#define ALWAYS_SECURE_SEARCH_PATH_SQL \
+ "SELECT pg_catalog.set_config('search_path', '', false);"
+
+#endif /* CONNECT_H */
diff --git a/src/include/common/controldata_utils.h b/src/include/common/controldata_utils.h
new file mode 100644
index 0000000..bf3c1f8
--- /dev/null
+++ b/src/include/common/controldata_utils.h
@@ -0,0 +1,19 @@
+/*
+ * controldata_utils.h
+ * Common code for pg_controldata output
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/controldata_utils.h
+ */
+#ifndef COMMON_CONTROLDATA_UTILS_H
+#define COMMON_CONTROLDATA_UTILS_H
+
+#include "catalog/pg_control.h"
+
+extern ControlFileData *get_controlfile(const char *DataDir, bool *crc_ok_p);
+extern void update_controlfile(const char *DataDir,
+ ControlFileData *ControlFile, bool do_sync);
+
+#endif /* COMMON_CONTROLDATA_UTILS_H */
diff --git a/src/include/common/fe_memutils.h b/src/include/common/fe_memutils.h
new file mode 100644
index 0000000..b2badd3
--- /dev/null
+++ b/src/include/common/fe_memutils.h
@@ -0,0 +1,45 @@
+/*
+ * fe_memutils.h
+ * memory management support for frontend code
+ *
+ * Copyright (c) 2003-2020, PostgreSQL Global Development Group
+ *
+ * src/include/common/fe_memutils.h
+ */
+#ifndef FE_MEMUTILS_H
+#define FE_MEMUTILS_H
+
+/*
+ * Flags for pg_malloc_extended and palloc_extended, deliberately named
+ * the same as the backend flags.
+ */
+#define MCXT_ALLOC_HUGE 0x01 /* allow huge allocation (> 1 GB) not
+ * actually used for frontends */
+#define MCXT_ALLOC_NO_OOM 0x02 /* no failure if out-of-memory */
+#define MCXT_ALLOC_ZERO 0x04 /* zero allocated memory */
+
+/*
+ * "Safe" memory allocation functions --- these exit(1) on failure
+ * (except pg_malloc_extended with MCXT_ALLOC_NO_OOM)
+ */
+extern char *pg_strdup(const char *in);
+extern void *pg_malloc(size_t size);
+extern void *pg_malloc0(size_t size);
+extern void *pg_malloc_extended(size_t size, int flags);
+extern void *pg_realloc(void *pointer, size_t size);
+extern void pg_free(void *pointer);
+
+/* Equivalent functions, deliberately named the same as backend functions */
+extern char *pstrdup(const char *in);
+extern char *pnstrdup(const char *in, Size size);
+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);
+
+/* 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 /* FE_MEMUTILS_H */
diff --git a/src/include/common/file_perm.h b/src/include/common/file_perm.h
new file mode 100644
index 0000000..d878816
--- /dev/null
+++ b/src/include/common/file_perm.h
@@ -0,0 +1,56 @@
+/*-------------------------------------------------------------------------
+ *
+ * File and directory permission definitions
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/file_perm.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FILE_PERM_H
+#define FILE_PERM_H
+
+#include <sys/stat.h>
+
+/*
+ * Mode mask for data directory permissions that only allows the owner to
+ * read/write directories and files.
+ *
+ * This is the default.
+ */
+#define PG_MODE_MASK_OWNER (S_IRWXG | S_IRWXO)
+
+/*
+ * Mode mask for data directory permissions that also allows group read/execute.
+ */
+#define PG_MODE_MASK_GROUP (S_IWGRP | S_IRWXO)
+
+/* Default mode for creating directories */
+#define PG_DIR_MODE_OWNER S_IRWXU
+
+/* Mode for creating directories that allows group read/execute */
+#define PG_DIR_MODE_GROUP (S_IRWXU | S_IRGRP | S_IXGRP)
+
+/* Default mode for creating files */
+#define PG_FILE_MODE_OWNER (S_IRUSR | S_IWUSR)
+
+/* Mode for creating files that allows group read */
+#define PG_FILE_MODE_GROUP (S_IRUSR | S_IWUSR | S_IRGRP)
+
+/* Modes for creating directories and files in the data directory */
+extern int pg_dir_create_mode;
+extern int pg_file_create_mode;
+
+/* Mode mask to pass to umask() */
+extern int pg_mode_mask;
+
+/* Set permissions and mask based on the provided mode */
+extern void SetDataDirectoryCreatePerm(int dataDirMode);
+
+/* Set permissions and mask based on the mode of the data directory */
+extern bool GetDataDirectoryCreatePerm(const char *dataDir);
+
+#endif /* FILE_PERM_H */
diff --git a/src/include/common/file_utils.h b/src/include/common/file_utils.h
new file mode 100644
index 0000000..a7add75
--- /dev/null
+++ b/src/include/common/file_utils.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * File-processing utility routines for frontend code
+ *
+ * Assorted utility functions to work on files.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/file_utils.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FILE_UTILS_H
+#define FILE_UTILS_H
+
+extern int fsync_fname(const char *fname, bool isdir);
+extern void fsync_pgdata(const char *pg_data, int serverVersion);
+extern void fsync_dir_recurse(const char *dir);
+extern int durable_rename(const char *oldfile, const char *newfile);
+extern int fsync_parent_path(const char *fname);
+
+#endif /* FILE_UTILS_H */
diff --git a/src/include/common/hashfn.h b/src/include/common/hashfn.h
new file mode 100644
index 0000000..6ecc864
--- /dev/null
+++ b/src/include/common/hashfn.h
@@ -0,0 +1,104 @@
+/*
+ * Utilities for working with hash values.
+ *
+ * Portions Copyright (c) 2017-2020, PostgreSQL Global Development Group
+ */
+
+#ifndef HASHFN_H
+#define HASHFN_H
+
+
+/*
+ * Rotate the high 32 bits and the low 32 bits separately. The standard
+ * hash function sometimes rotates the low 32 bits by one bit when
+ * combining elements. We want extended hash functions to be compatible with
+ * that algorithm when the seed is 0, so we can't just do a normal rotation.
+ * This works, though.
+ */
+#define ROTATE_HIGH_AND_LOW_32BITS(v) \
+ ((((v) << 1) & UINT64CONST(0xfffffffefffffffe)) | \
+ (((v) >> 31) & UINT64CONST(0x100000001)))
+
+
+extern uint32 hash_bytes(const unsigned char *k, int keylen);
+extern uint64 hash_bytes_extended(const unsigned char *k,
+ int keylen, uint64 seed);
+extern uint32 hash_bytes_uint32(uint32 k);
+extern uint64 hash_bytes_uint32_extended(uint32 k, uint64 seed);
+
+#ifndef FRONTEND
+static inline Datum
+hash_any(const unsigned char *k, int keylen)
+{
+ return UInt32GetDatum(hash_bytes(k, keylen));
+}
+
+static inline Datum
+hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
+{
+ return UInt64GetDatum(hash_bytes_extended(k, keylen, seed));
+}
+
+static inline Datum
+hash_uint32(uint32 k)
+{
+ return UInt32GetDatum(hash_bytes_uint32(k));
+}
+
+static inline Datum
+hash_uint32_extended(uint32 k, uint64 seed)
+{
+ return UInt64GetDatum(hash_bytes_uint32_extended(k, seed));
+}
+#endif
+
+extern uint32 string_hash(const void *key, Size keysize);
+extern uint32 tag_hash(const void *key, Size keysize);
+extern uint32 uint32_hash(const void *key, Size keysize);
+
+#define oid_hash uint32_hash /* Remove me eventually */
+
+/*
+ * Combine two 32-bit hash values, resulting in another hash value, with
+ * decent bit mixing.
+ *
+ * Similar to boost's hash_combine().
+ */
+static inline uint32
+hash_combine(uint32 a, uint32 b)
+{
+ a ^= b + 0x9e3779b9 + (a << 6) + (a >> 2);
+ return a;
+}
+
+/*
+ * Combine two 64-bit hash values, resulting in another hash value, using the
+ * same kind of technique as hash_combine(). Testing shows that this also
+ * produces good bit mixing.
+ */
+static inline uint64
+hash_combine64(uint64 a, uint64 b)
+{
+ /* 0x49a0f4dd15e5a8e3 is 64bit random data */
+ a ^= b + UINT64CONST(0x49a0f4dd15e5a8e3) + (a << 54) + (a >> 7);
+ return a;
+}
+
+/*
+ * Simple inline murmur hash implementation hashing a 32 bit integer, for
+ * performance.
+ */
+static inline uint32
+murmurhash32(uint32 data)
+{
+ uint32 h = data;
+
+ h ^= h >> 16;
+ h *= 0x85ebca6b;
+ h ^= h >> 13;
+ h *= 0xc2b2ae35;
+ h ^= h >> 16;
+ return h;
+}
+
+#endif /* HASHFN_H */
diff --git a/src/include/common/int.h b/src/include/common/int.h
new file mode 100644
index 0000000..a297221
--- /dev/null
+++ b/src/include/common/int.h
@@ -0,0 +1,437 @@
+/*-------------------------------------------------------------------------
+ *
+ * int.h
+ * Routines to perform integer math, while checking for overflows.
+ *
+ * The routines in this file are intended to be well defined C, without
+ * relying on compiler flags like -fwrapv.
+ *
+ * To reduce the overhead of these routines try to use compiler intrinsics
+ * where available. That's not that important for the 16, 32 bit cases, but
+ * the 64 bit cases can be considerably faster with intrinsics. In case no
+ * intrinsics are available 128 bit math is used where available.
+ *
+ * Copyright (c) 2017-2020, PostgreSQL Global Development Group
+ *
+ * src/include/common/int.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef COMMON_INT_H
+#define COMMON_INT_H
+
+
+/*---------
+ * The following guidelines apply to all the routines:
+ * - If a + b overflows, return true, otherwise store the result of a + b
+ * into *result. The content of *result is implementation defined in case of
+ * overflow.
+ * - If a - b overflows, return true, otherwise store the result of a - b
+ * into *result. The content of *result is implementation defined in case of
+ * overflow.
+ * - If a * b overflows, return true, otherwise store the result of a * b
+ * into *result. The content of *result is implementation defined in case of
+ * overflow.
+ *---------
+ */
+
+/*------------------------------------------------------------------------
+ * Overflow routines for signed integers
+ *------------------------------------------------------------------------
+ */
+
+/*
+ * INT16
+ */
+static inline bool
+pg_add_s16_overflow(int16 a, int16 b, int16 *result)
+{
+#if defined(HAVE__BUILTIN_OP_OVERFLOW)
+ return __builtin_add_overflow(a, b, result);
+#else
+ int32 res = (int32) a + (int32) b;
+
+ if (res > PG_INT16_MAX || res < PG_INT16_MIN)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = (int16) res;
+ return false;
+#endif
+}
+
+static inline bool
+pg_sub_s16_overflow(int16 a, int16 b, int16 *result)
+{
+#if defined(HAVE__BUILTIN_OP_OVERFLOW)
+ return __builtin_sub_overflow(a, b, result);
+#else
+ int32 res = (int32) a - (int32) b;
+
+ if (res > PG_INT16_MAX || res < PG_INT16_MIN)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = (int16) res;
+ return false;
+#endif
+}
+
+static inline bool
+pg_mul_s16_overflow(int16 a, int16 b, int16 *result)
+{
+#if defined(HAVE__BUILTIN_OP_OVERFLOW)
+ return __builtin_mul_overflow(a, b, result);
+#else
+ int32 res = (int32) a * (int32) b;
+
+ if (res > PG_INT16_MAX || res < PG_INT16_MIN)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = (int16) res;
+ return false;
+#endif
+}
+
+/*
+ * INT32
+ */
+static inline bool
+pg_add_s32_overflow(int32 a, int32 b, int32 *result)
+{
+#if defined(HAVE__BUILTIN_OP_OVERFLOW)
+ return __builtin_add_overflow(a, b, result);
+#else
+ int64 res = (int64) a + (int64) b;
+
+ if (res > PG_INT32_MAX || res < PG_INT32_MIN)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = (int32) res;
+ return false;
+#endif
+}
+
+static inline bool
+pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
+{
+#if defined(HAVE__BUILTIN_OP_OVERFLOW)
+ return __builtin_sub_overflow(a, b, result);
+#else
+ int64 res = (int64) a - (int64) b;
+
+ if (res > PG_INT32_MAX || res < PG_INT32_MIN)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = (int32) res;
+ return false;
+#endif
+}
+
+static inline bool
+pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
+{
+#if defined(HAVE__BUILTIN_OP_OVERFLOW)
+ return __builtin_mul_overflow(a, b, result);
+#else
+ int64 res = (int64) a * (int64) b;
+
+ if (res > PG_INT32_MAX || res < PG_INT32_MIN)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = (int32) res;
+ return false;
+#endif
+}
+
+/*
+ * INT64
+ */
+static inline bool
+pg_add_s64_overflow(int64 a, int64 b, int64 *result)
+{
+#if defined(HAVE__BUILTIN_OP_OVERFLOW)
+ return __builtin_add_overflow(a, b, result);
+#elif defined(HAVE_INT128)
+ int128 res = (int128) a + (int128) b;
+
+ if (res > PG_INT64_MAX || res < PG_INT64_MIN)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = (int64) res;
+ return false;
+#else
+ if ((a > 0 && b > 0 && a > PG_INT64_MAX - b) ||
+ (a < 0 && b < 0 && a < PG_INT64_MIN - b))
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = a + b;
+ return false;
+#endif
+}
+
+static inline bool
+pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
+{
+#if defined(HAVE__BUILTIN_OP_OVERFLOW)
+ return __builtin_sub_overflow(a, b, result);
+#elif defined(HAVE_INT128)
+ int128 res = (int128) a - (int128) b;
+
+ if (res > PG_INT64_MAX || res < PG_INT64_MIN)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = (int64) res;
+ return false;
+#else
+ if ((a < 0 && b > 0 && a < PG_INT64_MIN + b) ||
+ (a > 0 && b < 0 && a > PG_INT64_MAX + b))
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = a - b;
+ return false;
+#endif
+}
+
+static inline bool
+pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
+{
+#if defined(HAVE__BUILTIN_OP_OVERFLOW)
+ return __builtin_mul_overflow(a, b, result);
+#elif defined(HAVE_INT128)
+ int128 res = (int128) a * (int128) b;
+
+ if (res > PG_INT64_MAX || res < PG_INT64_MIN)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = (int64) res;
+ return false;
+#else
+ /*
+ * Overflow can only happen if at least one value is outside the range
+ * sqrt(min)..sqrt(max) so check that first as the division can be quite a
+ * bit more expensive than the multiplication.
+ *
+ * Multiplying by 0 or 1 can't overflow of course and checking for 0
+ * separately avoids any risk of dividing by 0. Be careful about dividing
+ * INT_MIN by -1 also, note reversing the a and b to ensure we're always
+ * dividing it by a positive value.
+ *
+ */
+ if ((a > PG_INT32_MAX || a < PG_INT32_MIN ||
+ b > PG_INT32_MAX || b < PG_INT32_MIN) &&
+ a != 0 && a != 1 && b != 0 && b != 1 &&
+ ((a > 0 && b > 0 && a > PG_INT64_MAX / b) ||
+ (a > 0 && b < 0 && b < PG_INT64_MIN / a) ||
+ (a < 0 && b > 0 && a < PG_INT64_MIN / b) ||
+ (a < 0 && b < 0 && a < PG_INT64_MAX / b)))
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = a * b;
+ return false;
+#endif
+}
+
+/*------------------------------------------------------------------------
+ * Overflow routines for unsigned integers
+ *------------------------------------------------------------------------
+ */
+
+/*
+ * UINT16
+ */
+static inline bool
+pg_add_u16_overflow(uint16 a, uint16 b, uint16 *result)
+{
+#if defined(HAVE__BUILTIN_OP_OVERFLOW)
+ return __builtin_add_overflow(a, b, result);
+#else
+ uint16 res = a + b;
+
+ if (res < a)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = res;
+ return false;
+#endif
+}
+
+static inline bool
+pg_sub_u16_overflow(uint16 a, uint16 b, uint16 *result)
+{
+#if defined(HAVE__BUILTIN_OP_OVERFLOW)
+ return __builtin_sub_overflow(a, b, result);
+#else
+ if (b > a)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = a - b;
+ return false;
+#endif
+}
+
+static inline bool
+pg_mul_u16_overflow(uint16 a, uint16 b, uint16 *result)
+{
+#if defined(HAVE__BUILTIN_OP_OVERFLOW)
+ return __builtin_mul_overflow(a, b, result);
+#else
+ uint32 res = (uint32) a * (uint32) b;
+
+ if (res > PG_UINT16_MAX)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = (uint16) res;
+ return false;
+#endif
+}
+
+/*
+ * INT32
+ */
+static inline bool
+pg_add_u32_overflow(uint32 a, uint32 b, uint32 *result)
+{
+#if defined(HAVE__BUILTIN_OP_OVERFLOW)
+ return __builtin_add_overflow(a, b, result);
+#else
+ uint32 res = a + b;
+
+ if (res < a)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = res;
+ return false;
+#endif
+}
+
+static inline bool
+pg_sub_u32_overflow(uint32 a, uint32 b, uint32 *result)
+{
+#if defined(HAVE__BUILTIN_OP_OVERFLOW)
+ return __builtin_sub_overflow(a, b, result);
+#else
+ if (b > a)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = a - b;
+ return false;
+#endif
+}
+
+static inline bool
+pg_mul_u32_overflow(uint32 a, uint32 b, uint32 *result)
+{
+#if defined(HAVE__BUILTIN_OP_OVERFLOW)
+ return __builtin_mul_overflow(a, b, result);
+#else
+ uint64 res = (uint64) a * (uint64) b;
+
+ if (res > PG_UINT32_MAX)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = (uint32) res;
+ return false;
+#endif
+}
+
+/*
+ * UINT64
+ */
+static inline bool
+pg_add_u64_overflow(uint64 a, uint64 b, uint64 *result)
+{
+#if defined(HAVE__BUILTIN_OP_OVERFLOW)
+ return __builtin_add_overflow(a, b, result);
+#else
+ uint64 res = a + b;
+
+ if (res < a)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = res;
+ return false;
+#endif
+}
+
+static inline bool
+pg_sub_u64_overflow(uint64 a, uint64 b, uint64 *result)
+{
+#if defined(HAVE__BUILTIN_OP_OVERFLOW)
+ return __builtin_sub_overflow(a, b, result);
+#else
+ if (b > a)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = a - b;
+ return false;
+#endif
+}
+
+static inline bool
+pg_mul_u64_overflow(uint64 a, uint64 b, uint64 *result)
+{
+#if defined(HAVE__BUILTIN_OP_OVERFLOW)
+ return __builtin_mul_overflow(a, b, result);
+#elif defined(HAVE_INT128)
+ uint128 res = (uint128) a * (uint128) b;
+
+ if (res > PG_UINT64_MAX)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = (uint64) res;
+ return false;
+#else
+ uint64 res = a * b;
+
+ if (a != 0 && b != res / a)
+ {
+ *result = 0x5EED; /* to avoid spurious warnings */
+ return true;
+ }
+ *result = res;
+ return false;
+#endif
+}
+
+#endif /* COMMON_INT_H */
diff --git a/src/include/common/int128.h b/src/include/common/int128.h
new file mode 100644
index 0000000..a83edc7
--- /dev/null
+++ b/src/include/common/int128.h
@@ -0,0 +1,276 @@
+/*-------------------------------------------------------------------------
+ *
+ * int128.h
+ * Roll-our-own 128-bit integer arithmetic.
+ *
+ * We make use of the native int128 type if there is one, otherwise
+ * implement things the hard way based on two int64 halves.
+ *
+ * See src/tools/testint128.c for a simple test harness for this file.
+ *
+ * Copyright (c) 2017-2020, PostgreSQL Global Development Group
+ *
+ * src/include/common/int128.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef INT128_H
+#define INT128_H
+
+/*
+ * For testing purposes, use of native int128 can be switched on/off by
+ * predefining USE_NATIVE_INT128.
+ */
+#ifndef USE_NATIVE_INT128
+#ifdef HAVE_INT128
+#define USE_NATIVE_INT128 1
+#else
+#define USE_NATIVE_INT128 0
+#endif
+#endif
+
+
+#if USE_NATIVE_INT128
+
+typedef int128 INT128;
+
+/*
+ * Add an unsigned int64 value into an INT128 variable.
+ */
+static inline void
+int128_add_uint64(INT128 *i128, uint64 v)
+{
+ *i128 += v;
+}
+
+/*
+ * Add a signed int64 value into an INT128 variable.
+ */
+static inline void
+int128_add_int64(INT128 *i128, int64 v)
+{
+ *i128 += v;
+}
+
+/*
+ * Add the 128-bit product of two int64 values into an INT128 variable.
+ *
+ * XXX with a stupid compiler, this could actually be less efficient than
+ * the other implementation; maybe we should do it by hand always?
+ */
+static inline void
+int128_add_int64_mul_int64(INT128 *i128, int64 x, int64 y)
+{
+ *i128 += (int128) x * (int128) y;
+}
+
+/*
+ * Compare two INT128 values, return -1, 0, or +1.
+ */
+static inline int
+int128_compare(INT128 x, INT128 y)
+{
+ if (x < y)
+ return -1;
+ if (x > y)
+ return 1;
+ return 0;
+}
+
+/*
+ * Widen int64 to INT128.
+ */
+static inline INT128
+int64_to_int128(int64 v)
+{
+ return (INT128) v;
+}
+
+/*
+ * Convert INT128 to int64 (losing any high-order bits).
+ * This also works fine for casting down to uint64.
+ */
+static inline int64
+int128_to_int64(INT128 val)
+{
+ return (int64) val;
+}
+
+#else /* !USE_NATIVE_INT128 */
+
+/*
+ * We lay out the INT128 structure with the same content and byte ordering
+ * that a native int128 type would (probably) have. This makes no difference
+ * for ordinary use of INT128, but allows union'ing INT128 with int128 for
+ * testing purposes.
+ */
+typedef struct
+{
+#ifdef WORDS_BIGENDIAN
+ int64 hi; /* most significant 64 bits, including sign */
+ uint64 lo; /* least significant 64 bits, without sign */
+#else
+ uint64 lo; /* least significant 64 bits, without sign */
+ int64 hi; /* most significant 64 bits, including sign */
+#endif
+} INT128;
+
+/*
+ * Add an unsigned int64 value into an INT128 variable.
+ */
+static inline void
+int128_add_uint64(INT128 *i128, uint64 v)
+{
+ /*
+ * First add the value to the .lo part, then check to see if a carry needs
+ * to be propagated into the .hi part. A carry is needed if both inputs
+ * have high bits set, or if just one input has high bit set while the new
+ * .lo part doesn't. Remember that .lo part is unsigned; we cast to
+ * signed here just as a cheap way to check the high bit.
+ */
+ uint64 oldlo = i128->lo;
+
+ i128->lo += v;
+ if (((int64) v < 0 && (int64) oldlo < 0) ||
+ (((int64) v < 0 || (int64) oldlo < 0) && (int64) i128->lo >= 0))
+ i128->hi++;
+}
+
+/*
+ * Add a signed int64 value into an INT128 variable.
+ */
+static inline void
+int128_add_int64(INT128 *i128, int64 v)
+{
+ /*
+ * This is much like the above except that the carry logic differs for
+ * negative v. Ordinarily we'd need to subtract 1 from the .hi part
+ * (corresponding to adding the sign-extended bits of v to it); but if
+ * there is a carry out of the .lo part, that cancels and we do nothing.
+ */
+ uint64 oldlo = i128->lo;
+
+ i128->lo += v;
+ if (v >= 0)
+ {
+ if ((int64) oldlo < 0 && (int64) i128->lo >= 0)
+ i128->hi++;
+ }
+ else
+ {
+ if (!((int64) oldlo < 0 || (int64) i128->lo >= 0))
+ i128->hi--;
+ }
+}
+
+/*
+ * INT64_AU32 extracts the most significant 32 bits of int64 as int64, while
+ * INT64_AL32 extracts the least significant 32 bits as uint64.
+ */
+#define INT64_AU32(i64) ((i64) >> 32)
+#define INT64_AL32(i64) ((i64) & UINT64CONST(0xFFFFFFFF))
+
+/*
+ * Add the 128-bit product of two int64 values into an INT128 variable.
+ */
+static inline void
+int128_add_int64_mul_int64(INT128 *i128, int64 x, int64 y)
+{
+ /* INT64_AU32 must use arithmetic right shift */
+ StaticAssertStmt(((int64) -1 >> 1) == (int64) -1,
+ "arithmetic right shift is needed");
+
+ /*----------
+ * Form the 128-bit product x * y using 64-bit arithmetic.
+ * Considering each 64-bit input as having 32-bit high and low parts,
+ * we can compute
+ *
+ * x * y = ((x.hi << 32) + x.lo) * (((y.hi << 32) + y.lo)
+ * = (x.hi * y.hi) << 64 +
+ * (x.hi * y.lo) << 32 +
+ * (x.lo * y.hi) << 32 +
+ * x.lo * y.lo
+ *
+ * Each individual product is of 32-bit terms so it won't overflow when
+ * computed in 64-bit arithmetic. Then we just have to shift it to the
+ * correct position while adding into the 128-bit result. We must also
+ * keep in mind that the "lo" parts must be treated as unsigned.
+ *----------
+ */
+
+ /* No need to work hard if product must be zero */
+ if (x != 0 && y != 0)
+ {
+ int64 x_u32 = INT64_AU32(x);
+ uint64 x_l32 = INT64_AL32(x);
+ int64 y_u32 = INT64_AU32(y);
+ uint64 y_l32 = INT64_AL32(y);
+ int64 tmp;
+
+ /* the first term */
+ i128->hi += x_u32 * y_u32;
+
+ /* the second term: sign-extend it only if x is negative */
+ tmp = x_u32 * y_l32;
+ if (x < 0)
+ i128->hi += INT64_AU32(tmp);
+ else
+ i128->hi += ((uint64) tmp) >> 32;
+ int128_add_uint64(i128, ((uint64) INT64_AL32(tmp)) << 32);
+
+ /* the third term: sign-extend it only if y is negative */
+ tmp = x_l32 * y_u32;
+ if (y < 0)
+ i128->hi += INT64_AU32(tmp);
+ else
+ i128->hi += ((uint64) tmp) >> 32;
+ int128_add_uint64(i128, ((uint64) INT64_AL32(tmp)) << 32);
+
+ /* the fourth term: always unsigned */
+ int128_add_uint64(i128, x_l32 * y_l32);
+ }
+}
+
+/*
+ * Compare two INT128 values, return -1, 0, or +1.
+ */
+static inline int
+int128_compare(INT128 x, INT128 y)
+{
+ if (x.hi < y.hi)
+ return -1;
+ if (x.hi > y.hi)
+ return 1;
+ if (x.lo < y.lo)
+ return -1;
+ if (x.lo > y.lo)
+ return 1;
+ return 0;
+}
+
+/*
+ * Widen int64 to INT128.
+ */
+static inline INT128
+int64_to_int128(int64 v)
+{
+ INT128 val;
+
+ val.lo = (uint64) v;
+ val.hi = (v < 0) ? -INT64CONST(1) : INT64CONST(0);
+ return val;
+}
+
+/*
+ * Convert INT128 to int64 (losing any high-order bits).
+ * This also works fine for casting down to uint64.
+ */
+static inline int64
+int128_to_int64(INT128 val)
+{
+ return (int64) val.lo;
+}
+
+#endif /* USE_NATIVE_INT128 */
+
+#endif /* INT128_H */
diff --git a/src/include/common/ip.h b/src/include/common/ip.h
new file mode 100644
index 0000000..34c78eb
--- /dev/null
+++ b/src/include/common/ip.h
@@ -0,0 +1,37 @@
+/*-------------------------------------------------------------------------
+ *
+ * ip.h
+ * Definitions for IPv6-aware network access.
+ *
+ * These definitions are used by both frontend and backend code.
+ *
+ * Copyright (c) 2003-2020, PostgreSQL Global Development Group
+ *
+ * src/include/common/ip.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef IP_H
+#define IP_H
+
+#include "getaddrinfo.h" /* pgrminclude ignore */
+#include "libpq/pqcomm.h" /* pgrminclude ignore */
+
+
+#ifdef HAVE_UNIX_SOCKETS
+#define IS_AF_UNIX(fam) ((fam) == AF_UNIX)
+#else
+#define IS_AF_UNIX(fam) (0)
+#endif
+
+extern int pg_getaddrinfo_all(const char *hostname, const char *servname,
+ const struct addrinfo *hintp,
+ struct addrinfo **result);
+extern void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai);
+
+extern int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen,
+ char *node, int nodelen,
+ char *service, int servicelen,
+ int flags);
+
+#endif /* IP_H */
diff --git a/src/include/common/jsonapi.h b/src/include/common/jsonapi.h
new file mode 100644
index 0000000..bcfd57c
--- /dev/null
+++ b/src/include/common/jsonapi.h
@@ -0,0 +1,169 @@
+/*-------------------------------------------------------------------------
+ *
+ * jsonapi.h
+ * Declarations for JSON API support.
+ *
+ * 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 JSONAPI_H
+#define JSONAPI_H
+
+#include "lib/stringinfo.h"
+
+typedef enum
+{
+ JSON_TOKEN_INVALID,
+ JSON_TOKEN_STRING,
+ JSON_TOKEN_NUMBER,
+ JSON_TOKEN_OBJECT_START,
+ JSON_TOKEN_OBJECT_END,
+ JSON_TOKEN_ARRAY_START,
+ JSON_TOKEN_ARRAY_END,
+ JSON_TOKEN_COMMA,
+ JSON_TOKEN_COLON,
+ JSON_TOKEN_TRUE,
+ JSON_TOKEN_FALSE,
+ JSON_TOKEN_NULL,
+ JSON_TOKEN_END
+} JsonTokenType;
+
+typedef enum
+{
+ JSON_SUCCESS,
+ JSON_ESCAPING_INVALID,
+ JSON_ESCAPING_REQUIRED,
+ JSON_EXPECTED_ARRAY_FIRST,
+ JSON_EXPECTED_ARRAY_NEXT,
+ JSON_EXPECTED_COLON,
+ JSON_EXPECTED_END,
+ JSON_EXPECTED_JSON,
+ JSON_EXPECTED_MORE,
+ JSON_EXPECTED_OBJECT_FIRST,
+ JSON_EXPECTED_OBJECT_NEXT,
+ JSON_EXPECTED_STRING,
+ JSON_INVALID_TOKEN,
+ JSON_UNICODE_CODE_POINT_ZERO,
+ JSON_UNICODE_ESCAPE_FORMAT,
+ JSON_UNICODE_HIGH_ESCAPE,
+ JSON_UNICODE_HIGH_SURROGATE,
+ JSON_UNICODE_LOW_SURROGATE
+} JsonParseErrorType;
+
+
+/*
+ * All the fields in this structure should be treated as read-only.
+ *
+ * If strval is not null, then it should contain the de-escaped value
+ * of the lexeme if it's a string. Otherwise most of these field names
+ * should be self-explanatory.
+ *
+ * line_number and line_start are principally for use by the parser's
+ * error reporting routines.
+ * token_terminator and prev_token_terminator point to the character
+ * AFTER the end of the token, i.e. where there would be a nul byte
+ * if we were using nul-terminated strings.
+ */
+typedef struct JsonLexContext
+{
+ char *input;
+ int input_length;
+ int input_encoding;
+ char *token_start;
+ char *token_terminator;
+ char *prev_token_terminator;
+ JsonTokenType token_type;
+ int lex_level;
+ int line_number;
+ char *line_start;
+ StringInfo strval;
+} JsonLexContext;
+
+typedef void (*json_struct_action) (void *state);
+typedef void (*json_ofield_action) (void *state, char *fname, bool isnull);
+typedef void (*json_aelem_action) (void *state, bool isnull);
+typedef void (*json_scalar_action) (void *state, char *token, JsonTokenType tokentype);
+
+
+/*
+ * Semantic Action structure for use in parsing json.
+ * Any of these actions can be NULL, in which case nothing is done at that
+ * point, Likewise, semstate can be NULL. Using an all-NULL structure amounts
+ * to doing a pure parse with no side-effects, and is therefore exactly
+ * what the json input routines do.
+ *
+ * The 'fname' and 'token' strings passed to these actions are palloc'd.
+ * They are not free'd or used further by the parser, so the action function
+ * is free to do what it wishes with them.
+ */
+typedef struct JsonSemAction
+{
+ void *semstate;
+ json_struct_action object_start;
+ json_struct_action object_end;
+ json_struct_action array_start;
+ json_struct_action array_end;
+ json_ofield_action object_field_start;
+ json_ofield_action object_field_end;
+ json_aelem_action array_element_start;
+ json_aelem_action array_element_end;
+ json_scalar_action scalar;
+} JsonSemAction;
+
+/*
+ * pg_parse_json will parse the string in the lex calling the
+ * action functions in sem at the appropriate points. It is
+ * up to them to keep what state they need in semstate. If they
+ * need access to the state of the lexer, then its pointer
+ * should be passed to them as a member of whatever semstate
+ * points to. If the action pointers are NULL the parser
+ * does nothing and just continues.
+ */
+extern JsonParseErrorType pg_parse_json(JsonLexContext *lex,
+ JsonSemAction *sem);
+
+/* the null action object used for pure validation */
+extern JsonSemAction nullSemAction;
+
+/*
+ * json_count_array_elements performs a fast secondary parse to determine the
+ * number of elements in passed array lex context. It should be called from an
+ * array_start action.
+ *
+ * The return value indicates whether any error occurred, while the number
+ * of elements is stored into *elements (but only if the return value is
+ * JSON_SUCCESS).
+ */
+extern JsonParseErrorType json_count_array_elements(JsonLexContext *lex,
+ int *elements);
+
+/*
+ * constructor for JsonLexContext, with or without strval element.
+ * If supplied, the strval element will contain a de-escaped version of
+ * the lexeme. However, doing this imposes a performance penalty, so
+ * it should be avoided if the de-escaped lexeme is not required.
+ */
+extern JsonLexContext *makeJsonLexContextCstringLen(char *json,
+ int len,
+ int encoding,
+ bool need_escapes);
+
+/* lex one token */
+extern JsonParseErrorType json_lex(JsonLexContext *lex);
+
+/* construct an error detail string for a json error */
+extern char *json_errdetail(JsonParseErrorType error, JsonLexContext *lex);
+
+/*
+ * Utility function to check if a string is a valid JSON number.
+ *
+ * str argument does not need to be nul-terminated.
+ */
+extern bool IsValidJsonNumber(const char *str, int len);
+
+#endif /* JSONAPI_H */
diff --git a/src/include/common/keywords.h b/src/include/common/keywords.h
new file mode 100644
index 0000000..257c050
--- /dev/null
+++ b/src/include/common/keywords.h
@@ -0,0 +1,33 @@
+/*-------------------------------------------------------------------------
+ *
+ * keywords.h
+ * PostgreSQL's list of SQL keywords
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/keywords.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef KEYWORDS_H
+#define KEYWORDS_H
+
+#include "common/kwlookup.h"
+
+/* Keyword categories --- should match lists in gram.y */
+#define UNRESERVED_KEYWORD 0
+#define COL_NAME_KEYWORD 1
+#define TYPE_FUNC_NAME_KEYWORD 2
+#define RESERVED_KEYWORD 3
+
+#ifndef FRONTEND
+extern PGDLLIMPORT const ScanKeywordList ScanKeywords;
+extern PGDLLIMPORT const uint8 ScanKeywordCategories[];
+#else
+extern const ScanKeywordList ScanKeywords;
+extern const uint8 ScanKeywordCategories[];
+#endif
+
+#endif /* KEYWORDS_H */
diff --git a/src/include/common/kwlookup.h b/src/include/common/kwlookup.h
new file mode 100644
index 0000000..9c0c7f8
--- /dev/null
+++ b/src/include/common/kwlookup.h
@@ -0,0 +1,44 @@
+/*-------------------------------------------------------------------------
+ *
+ * kwlookup.h
+ * Key word lookup for PostgreSQL
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/kwlookup.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef KWLOOKUP_H
+#define KWLOOKUP_H
+
+/* Hash function used by ScanKeywordLookup */
+typedef int (*ScanKeywordHashFunc) (const void *key, size_t keylen);
+
+/*
+ * This struct contains the data needed by ScanKeywordLookup to perform a
+ * search within a set of keywords. The contents are typically generated by
+ * src/tools/gen_keywordlist.pl from a header containing PG_KEYWORD macros.
+ */
+typedef struct ScanKeywordList
+{
+ const char *kw_string; /* all keywords in order, separated by \0 */
+ const uint16 *kw_offsets; /* offsets to the start of each keyword */
+ ScanKeywordHashFunc hash; /* perfect hash function for keywords */
+ int num_keywords; /* number of keywords */
+ int max_kw_len; /* length of longest keyword */
+} ScanKeywordList;
+
+
+extern int ScanKeywordLookup(const char *text, const ScanKeywordList *keywords);
+
+/* Code that wants to retrieve the text of the N'th keyword should use this. */
+static inline const char *
+GetScanKeyword(int n, const ScanKeywordList *keywords)
+{
+ return keywords->kw_string + keywords->kw_offsets[n];
+}
+
+#endif /* KWLOOKUP_H */
diff --git a/src/include/common/link-canary.h b/src/include/common/link-canary.h
new file mode 100644
index 0000000..e8665dc
--- /dev/null
+++ b/src/include/common/link-canary.h
@@ -0,0 +1,17 @@
+/*-------------------------------------------------------------------------
+ *
+ * link-canary.h
+ * Detect whether src/common functions came from frontend or backend.
+ *
+ * Copyright (c) 2018-2020, PostgreSQL Global Development Group
+ *
+ * src/include/common/link-canary.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LINK_CANARY_H
+#define LINK_CANARY_H
+
+extern bool pg_link_canary_is_frontend(void);
+
+#endif /* LINK_CANARY_H */
diff --git a/src/include/common/logging.h b/src/include/common/logging.h
new file mode 100644
index 0000000..028149c
--- /dev/null
+++ b/src/include/common/logging.h
@@ -0,0 +1,95 @@
+/*-------------------------------------------------------------------------
+ * Logging framework for frontend programs
+ *
+ * Copyright (c) 2018-2020, PostgreSQL Global Development Group
+ *
+ * src/include/common/logging.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef COMMON_LOGGING_H
+#define COMMON_LOGGING_H
+
+/*
+ * Log levels are informational only. They do not affect program flow.
+ */
+enum pg_log_level
+{
+ /*
+ * Not initialized yet
+ */
+ PG_LOG_NOTSET = 0,
+
+ /*
+ * Low level messages that are normally off by default.
+ */
+ PG_LOG_DEBUG,
+
+ /*
+ * Any program messages that go to stderr, shown by default. (The
+ * program's normal output should go to stdout and not use the logging
+ * system.)
+ */
+ PG_LOG_INFO,
+
+ /*
+ * Warnings and "almost" errors, depends on the program
+ */
+ PG_LOG_WARNING,
+
+ /*
+ * Errors
+ */
+ PG_LOG_ERROR,
+
+ /*
+ * Severe errors that cause program termination. (One-shot programs may
+ * chose to label even fatal errors as merely "errors". The distinction
+ * is up to the program.)
+ */
+ PG_LOG_FATAL,
+
+ /*
+ * Turn all logging off.
+ */
+ PG_LOG_OFF,
+};
+
+extern enum pg_log_level __pg_log_level;
+
+/*
+ * Kind of a hack to be able to produce the psql output exactly as required by
+ * the regression tests.
+ */
+#define PG_LOG_FLAG_TERSE 1
+
+void pg_logging_init(const char *argv0);
+void pg_logging_config(int new_flags);
+void pg_logging_set_level(enum pg_log_level new_level);
+void pg_logging_set_pre_callback(void (*cb) (void));
+void pg_logging_set_locus_callback(void (*cb) (const char **filename, uint64 *lineno));
+
+void pg_log_generic(enum pg_log_level level, const char *pg_restrict fmt,...) pg_attribute_printf(2, 3);
+void pg_log_generic_v(enum pg_log_level level, const char *pg_restrict fmt, va_list ap) pg_attribute_printf(2, 0);
+
+#define pg_log_fatal(...) do { \
+ if (likely(__pg_log_level <= PG_LOG_FATAL)) pg_log_generic(PG_LOG_FATAL, __VA_ARGS__); \
+ } while(0)
+
+#define pg_log_error(...) do { \
+ if (likely(__pg_log_level <= PG_LOG_ERROR)) pg_log_generic(PG_LOG_ERROR, __VA_ARGS__); \
+ } while(0)
+
+#define pg_log_warning(...) do { \
+ if (likely(__pg_log_level <= PG_LOG_WARNING)) pg_log_generic(PG_LOG_WARNING, __VA_ARGS__); \
+ } while(0)
+
+#define pg_log_info(...) do { \
+ if (likely(__pg_log_level <= PG_LOG_INFO)) pg_log_generic(PG_LOG_INFO, __VA_ARGS__); \
+ } while(0)
+
+#define pg_log_debug(...) do { \
+ if (unlikely(__pg_log_level <= PG_LOG_DEBUG)) pg_log_generic(PG_LOG_DEBUG, __VA_ARGS__); \
+ } while(0)
+
+#endif /* COMMON_LOGGING_H */
diff --git a/src/include/common/md5.h b/src/include/common/md5.h
new file mode 100644
index 0000000..8695f10
--- /dev/null
+++ b/src/include/common/md5.h
@@ -0,0 +1,27 @@
+/*-------------------------------------------------------------------------
+ *
+ * md5.h
+ * Interface to libpq/md5.c
+ *
+ * These definitions are needed by both frontend and backend code to work
+ * with MD5-encrypted passwords.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/md5.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_MD5_H
+#define PG_MD5_H
+
+#define MD5_PASSWD_CHARSET "0123456789abcdef"
+#define MD5_PASSWD_LEN 35
+
+extern bool pg_md5_hash(const void *buff, size_t len, char *hexsum);
+extern bool pg_md5_binary(const void *buff, size_t len, void *outbuf);
+extern bool pg_md5_encrypt(const char *passwd, const char *salt,
+ size_t salt_len, char *buf);
+
+#endif
diff --git a/src/include/common/openssl.h b/src/include/common/openssl.h
new file mode 100644
index 0000000..9d1c681
--- /dev/null
+++ b/src/include/common/openssl.h
@@ -0,0 +1,49 @@
+/*-------------------------------------------------------------------------
+ *
+ * openssl.h
+ * OpenSSL supporting functionality shared between frontend and backend
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/common/openssl.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef COMMON_OPENSSL_H
+#define COMMON_OPENSSL_H
+
+#ifdef USE_OPENSSL
+#include <openssl/ssl.h>
+
+/*
+ * OpenSSL doesn't provide any very nice way to identify the min/max
+ * protocol versions the library supports, so we fake it as best we can.
+ * Note in particular that this doesn't account for restrictions that
+ * might be specified in the installation's openssl.cnf.
+ *
+ * We disable SSLv3 and older in library setup, so TLSv1 is the oldest
+ * protocol version of interest.
+ */
+#define MIN_OPENSSL_TLS_VERSION "TLSv1"
+
+#if defined(TLS1_3_VERSION)
+#define MAX_OPENSSL_TLS_VERSION "TLSv1.3"
+#elif defined(TLS1_2_VERSION)
+#define MAX_OPENSSL_TLS_VERSION "TLSv1.2"
+#elif defined(TLS1_1_VERSION)
+#define MAX_OPENSSL_TLS_VERSION "TLSv1.1"
+#else
+#define MAX_OPENSSL_TLS_VERSION "TLSv1"
+#endif
+
+/* src/common/protocol_openssl.c */
+#ifndef SSL_CTX_set_min_proto_version
+extern int SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version);
+extern int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version);
+#endif
+
+#endif /* USE_OPENSSL */
+
+#endif /* COMMON_OPENSSL_H */
diff --git a/src/include/common/pg_lzcompress.h b/src/include/common/pg_lzcompress.h
new file mode 100644
index 0000000..3e53fbe
--- /dev/null
+++ b/src/include/common/pg_lzcompress.h
@@ -0,0 +1,93 @@
+/* ----------
+ * pg_lzcompress.h -
+ *
+ * Definitions for the builtin LZ compressor
+ *
+ * src/include/common/pg_lzcompress.h
+ * ----------
+ */
+
+#ifndef _PG_LZCOMPRESS_H_
+#define _PG_LZCOMPRESS_H_
+
+
+/* ----------
+ * PGLZ_MAX_OUTPUT -
+ *
+ * Macro to compute the buffer size required by pglz_compress().
+ * We allow 4 bytes for overrun before detecting compression failure.
+ * ----------
+ */
+#define PGLZ_MAX_OUTPUT(_dlen) ((_dlen) + 4)
+
+
+/* ----------
+ * PGLZ_Strategy -
+ *
+ * Some values that control the compression algorithm.
+ *
+ * min_input_size Minimum input data size to consider compression.
+ *
+ * max_input_size Maximum input data size to consider compression.
+ *
+ * min_comp_rate Minimum compression rate (0-99%) to require.
+ * Regardless of min_comp_rate, the output must be
+ * smaller than the input, else we don't store
+ * compressed.
+ *
+ * first_success_by Abandon compression if we find no compressible
+ * data within the first this-many bytes.
+ *
+ * match_size_good The initial GOOD match size when starting history
+ * lookup. When looking up the history to find a
+ * match that could be expressed as a tag, the
+ * algorithm does not always walk back entirely.
+ * A good match fast is usually better than the
+ * best possible one very late. For each iteration
+ * in the lookup, this value is lowered so the
+ * longer the lookup takes, the smaller matches
+ * are considered good.
+ *
+ * match_size_drop The percentage by which match_size_good is lowered
+ * after each history check. Allowed values are
+ * 0 (no change until end) to 100 (only check
+ * latest history entry at all).
+ * ----------
+ */
+typedef struct PGLZ_Strategy
+{
+ int32 min_input_size;
+ int32 max_input_size;
+ int32 min_comp_rate;
+ int32 first_success_by;
+ int32 match_size_good;
+ int32 match_size_drop;
+} PGLZ_Strategy;
+
+
+/* ----------
+ * The standard strategies
+ *
+ * PGLZ_strategy_default Recommended default strategy for TOAST.
+ *
+ * PGLZ_strategy_always Try to compress inputs of any length.
+ * Fallback to uncompressed storage only if
+ * output would be larger than input.
+ * ----------
+ */
+extern const PGLZ_Strategy *const PGLZ_strategy_default;
+extern const PGLZ_Strategy *const PGLZ_strategy_always;
+
+
+/* ----------
+ * Global function declarations
+ * ----------
+ */
+extern int32 pglz_compress(const char *source, int32 slen, char *dest,
+ const PGLZ_Strategy *strategy);
+extern int32 pglz_decompress(const char *source, int32 slen, char *dest,
+ int32 rawsize, bool check_complete);
+extern int32 pglz_maximum_compressed_size(int32 rawsize,
+ int32 total_compressed_size);
+
+#endif /* _PG_LZCOMPRESS_H_ */
diff --git a/src/include/common/relpath.h b/src/include/common/relpath.h
new file mode 100644
index 0000000..869cabc
--- /dev/null
+++ b/src/include/common/relpath.h
@@ -0,0 +1,90 @@
+/*-------------------------------------------------------------------------
+ *
+ * relpath.h
+ * Declarations for GetRelationPath() and friends
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/relpath.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RELPATH_H
+#define RELPATH_H
+
+/*
+ * 'pgrminclude ignore' needed here because CppAsString2() does not throw
+ * an error if the symbol is not defined.
+ */
+#include "catalog/catversion.h" /* pgrminclude ignore */
+
+
+/*
+ * Name of major-version-specific tablespace subdirectories
+ */
+#define TABLESPACE_VERSION_DIRECTORY "PG_" PG_MAJORVERSION "_" \
+ CppAsString2(CATALOG_VERSION_NO)
+
+/* Characters to allow for an OID in a relation path */
+#define OIDCHARS 10 /* max chars printed by %u */
+
+/*
+ * Stuff for fork names.
+ *
+ * The physical storage of a relation consists of one or more forks.
+ * The main fork is always created, but in addition to that there can be
+ * additional forks for storing various metadata. ForkNumber is used when
+ * we need to refer to a specific fork in a relation.
+ */
+typedef enum ForkNumber
+{
+ InvalidForkNumber = -1,
+ MAIN_FORKNUM = 0,
+ FSM_FORKNUM,
+ VISIBILITYMAP_FORKNUM,
+ INIT_FORKNUM
+
+ /*
+ * NOTE: if you add a new fork, change MAX_FORKNUM and possibly
+ * FORKNAMECHARS below, and update the forkNames array in
+ * src/common/relpath.c
+ */
+} ForkNumber;
+
+#define MAX_FORKNUM INIT_FORKNUM
+
+#define FORKNAMECHARS 4 /* max chars for a fork name */
+
+extern const char *const forkNames[];
+
+extern ForkNumber forkname_to_number(const char *forkName);
+extern int forkname_chars(const char *str, ForkNumber *fork);
+
+/*
+ * Stuff for computing filesystem pathnames for relations.
+ */
+extern char *GetDatabasePath(Oid dbNode, Oid spcNode);
+
+extern char *GetRelationPath(Oid dbNode, Oid spcNode, Oid relNode,
+ int backendId, ForkNumber forkNumber);
+
+/*
+ * Wrapper macros for GetRelationPath. Beware of multiple
+ * evaluation of the RelFileNode or RelFileNodeBackend argument!
+ */
+
+/* First argument is a RelFileNode */
+#define relpathbackend(rnode, backend, forknum) \
+ GetRelationPath((rnode).dbNode, (rnode).spcNode, (rnode).relNode, \
+ backend, forknum)
+
+/* First argument is a RelFileNode */
+#define relpathperm(rnode, forknum) \
+ relpathbackend(rnode, InvalidBackendId, forknum)
+
+/* First argument is a RelFileNodeBackend */
+#define relpath(rnode, forknum) \
+ relpathbackend((rnode).node, (rnode).backend, forknum)
+
+#endif /* RELPATH_H */
diff --git a/src/include/common/restricted_token.h b/src/include/common/restricted_token.h
new file mode 100644
index 0000000..4a93808
--- /dev/null
+++ b/src/include/common/restricted_token.h
@@ -0,0 +1,24 @@
+/*
+ * restricted_token.h
+ * helper routine to ensure restricted token on Windows
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/restricted_token.h
+ */
+#ifndef COMMON_RESTRICTED_TOKEN_H
+#define COMMON_RESTRICTED_TOKEN_H
+
+/*
+ * On Windows make sure that we are running with a restricted token,
+ * On other platforms do nothing.
+ */
+void get_restricted_token(void);
+
+#ifdef WIN32
+/* Create a restricted token and execute the specified process with it. */
+HANDLE CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo);
+#endif
+
+#endif /* COMMON_RESTRICTED_TOKEN_H */
diff --git a/src/include/common/saslprep.h b/src/include/common/saslprep.h
new file mode 100644
index 0000000..3abf2ac
--- /dev/null
+++ b/src/include/common/saslprep.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * saslprep.h
+ * SASLprep normalization, for SCRAM authentication
+ *
+ * These definitions are used by both frontend and backend code.
+ *
+ * Copyright (c) 2017-2020, PostgreSQL Global Development Group
+ *
+ * src/include/common/saslprep.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SASLPREP_H
+#define SASLPREP_H
+
+/*
+ * Return codes for pg_saslprep() function.
+ */
+typedef enum
+{
+ SASLPREP_SUCCESS = 0,
+ SASLPREP_OOM = -1, /* out of memory (only in frontend) */
+ SASLPREP_INVALID_UTF8 = -2, /* input is not a valid UTF-8 string */
+ SASLPREP_PROHIBITED = -3 /* output would contain prohibited characters */
+} pg_saslprep_rc;
+
+extern pg_saslprep_rc pg_saslprep(const char *input, char **output);
+
+#endif /* SASLPREP_H */
diff --git a/src/include/common/scram-common.h b/src/include/common/scram-common.h
new file mode 100644
index 0000000..2edae2d
--- /dev/null
+++ b/src/include/common/scram-common.h
@@ -0,0 +1,70 @@
+/*-------------------------------------------------------------------------
+ *
+ * scram-common.h
+ * Declarations for helper functions used for SCRAM authentication
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/scram-common.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SCRAM_COMMON_H
+#define SCRAM_COMMON_H
+
+#include "common/sha2.h"
+
+/* Name of SCRAM mechanisms per IANA */
+#define SCRAM_SHA_256_NAME "SCRAM-SHA-256"
+#define SCRAM_SHA_256_PLUS_NAME "SCRAM-SHA-256-PLUS" /* with channel binding */
+
+/* Length of SCRAM keys (client and server) */
+#define SCRAM_KEY_LEN PG_SHA256_DIGEST_LENGTH
+
+/* length of HMAC */
+#define SHA256_HMAC_B PG_SHA256_BLOCK_LENGTH
+
+/*
+ * Size of random nonce generated in the authentication exchange. This
+ * is in "raw" number of bytes, the actual nonces sent over the wire are
+ * encoded using only ASCII-printable characters.
+ */
+#define SCRAM_RAW_NONCE_LEN 18
+
+/*
+ * Length of salt when generating new secrets, in bytes. (It will be stored
+ * and sent over the wire encoded in Base64.) 16 bytes is what the example in
+ * RFC 7677 uses.
+ */
+#define SCRAM_DEFAULT_SALT_LEN 16
+
+/*
+ * Default number of iterations when generating secret. Should be at least
+ * 4096 per RFC 7677.
+ */
+#define SCRAM_DEFAULT_ITERATIONS 4096
+
+/*
+ * Context data for HMAC used in SCRAM authentication.
+ */
+typedef struct
+{
+ pg_sha256_ctx sha256ctx;
+ uint8 k_opad[SHA256_HMAC_B];
+} scram_HMAC_ctx;
+
+extern void scram_HMAC_init(scram_HMAC_ctx *ctx, const uint8 *key, int keylen);
+extern void scram_HMAC_update(scram_HMAC_ctx *ctx, const char *str, int slen);
+extern void scram_HMAC_final(uint8 *result, scram_HMAC_ctx *ctx);
+
+extern void scram_SaltedPassword(const char *password, const char *salt,
+ int saltlen, int iterations, uint8 *result);
+extern void scram_H(const uint8 *str, int len, uint8 *result);
+extern void scram_ClientKey(const uint8 *salted_password, uint8 *result);
+extern void scram_ServerKey(const uint8 *salted_password, uint8 *result);
+
+extern char *scram_build_secret(const char *salt, int saltlen, int iterations,
+ const char *password);
+
+#endif /* SCRAM_COMMON_H */
diff --git a/src/include/common/sha2.h b/src/include/common/sha2.h
new file mode 100644
index 0000000..673e75b
--- /dev/null
+++ b/src/include/common/sha2.h
@@ -0,0 +1,115 @@
+/*-------------------------------------------------------------------------
+ *
+ * sha2.h
+ * Generic headers for SHA224, 256, 384 AND 512 functions of PostgreSQL.
+ *
+ * Portions Copyright (c) 2016-2020, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/common/sha2.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* $OpenBSD: sha2.h,v 1.2 2004/04/28 23:11:57 millert Exp $ */
+
+/*
+ * FILE: sha2.h
+ * AUTHOR: Aaron D. Gifford <me@aarongifford.com>
+ *
+ * Copyright (c) 2000-2001, Aaron D. Gifford
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $From: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $
+ */
+
+#ifndef _PG_SHA2_H_
+#define _PG_SHA2_H_
+
+#ifdef USE_OPENSSL
+#include <openssl/sha.h>
+#endif
+
+/*** SHA224/256/384/512 Various Length Definitions ***********************/
+#define PG_SHA224_BLOCK_LENGTH 64
+#define PG_SHA224_DIGEST_LENGTH 28
+#define PG_SHA224_DIGEST_STRING_LENGTH (PG_SHA224_DIGEST_LENGTH * 2 + 1)
+#define PG_SHA256_BLOCK_LENGTH 64
+#define PG_SHA256_DIGEST_LENGTH 32
+#define PG_SHA256_DIGEST_STRING_LENGTH (PG_SHA256_DIGEST_LENGTH * 2 + 1)
+#define PG_SHA384_BLOCK_LENGTH 128
+#define PG_SHA384_DIGEST_LENGTH 48
+#define PG_SHA384_DIGEST_STRING_LENGTH (PG_SHA384_DIGEST_LENGTH * 2 + 1)
+#define PG_SHA512_BLOCK_LENGTH 128
+#define PG_SHA512_DIGEST_LENGTH 64
+#define PG_SHA512_DIGEST_STRING_LENGTH (PG_SHA512_DIGEST_LENGTH * 2 + 1)
+
+/* Context Structures for SHA-1/224/256/384/512 */
+#ifdef USE_OPENSSL
+typedef SHA256_CTX pg_sha256_ctx;
+typedef SHA512_CTX pg_sha512_ctx;
+typedef SHA256_CTX pg_sha224_ctx;
+typedef SHA512_CTX pg_sha384_ctx;
+#else
+typedef struct pg_sha256_ctx
+{
+ uint32 state[8];
+ uint64 bitcount;
+ uint8 buffer[PG_SHA256_BLOCK_LENGTH];
+} pg_sha256_ctx;
+typedef struct pg_sha512_ctx
+{
+ uint64 state[8];
+ uint64 bitcount[2];
+ uint8 buffer[PG_SHA512_BLOCK_LENGTH];
+} pg_sha512_ctx;
+typedef struct pg_sha256_ctx pg_sha224_ctx;
+typedef struct pg_sha512_ctx pg_sha384_ctx;
+#endif /* USE_OPENSSL */
+
+/* Interface routines for SHA224/256/384/512 */
+extern void pg_sha224_init(pg_sha224_ctx *ctx);
+extern void pg_sha224_update(pg_sha224_ctx *ctx, const uint8 *input0,
+ size_t len);
+extern void pg_sha224_final(pg_sha224_ctx *ctx, uint8 *dest);
+
+extern void pg_sha256_init(pg_sha256_ctx *ctx);
+extern void pg_sha256_update(pg_sha256_ctx *ctx, const uint8 *input0,
+ size_t len);
+extern void pg_sha256_final(pg_sha256_ctx *ctx, uint8 *dest);
+
+extern void pg_sha384_init(pg_sha384_ctx *ctx);
+extern void pg_sha384_update(pg_sha384_ctx *ctx,
+ const uint8 *, size_t len);
+extern void pg_sha384_final(pg_sha384_ctx *ctx, uint8 *dest);
+
+extern void pg_sha512_init(pg_sha512_ctx *ctx);
+extern void pg_sha512_update(pg_sha512_ctx *ctx, const uint8 *input0,
+ size_t len);
+extern void pg_sha512_final(pg_sha512_ctx *ctx, uint8 *dest);
+
+#endif /* _PG_SHA2_H_ */
diff --git a/src/include/common/shortest_dec.h b/src/include/common/shortest_dec.h
new file mode 100644
index 0000000..a028231
--- /dev/null
+++ b/src/include/common/shortest_dec.h
@@ -0,0 +1,63 @@
+/*---------------------------------------------------------------------------
+ *
+ * Ryu floating-point output.
+ *
+ * Portions Copyright (c) 2018-2020, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/common/shortest_dec.h
+ *
+ * This is a modification of code taken from github.com/ulfjack/ryu under the
+ * terms of the Boost license (not the Apache license). The original copyright
+ * notice follows:
+ *
+ * Copyright 2018 Ulf Adams
+ *
+ * The contents of this file may be used under the terms of the Apache
+ * License, Version 2.0.
+ *
+ * (See accompanying file LICENSE-Apache or copy at
+ * http://www.apache.org/licenses/LICENSE-2.0)
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * Boost Software License, Version 1.0.
+ *
+ * (See accompanying file LICENSE-Boost or copy at
+ * https://www.boost.org/LICENSE_1_0.txt)
+ *
+ * Unless required by applicable law or agreed to in writing, this software is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.
+ *
+ *---------------------------------------------------------------------------
+ */
+#ifndef SHORTEST_DEC_H
+#define SHORTEST_DEC_H
+
+/*----
+ * The length of 25 comes from:
+ *
+ * Case 1: -9.9999999999999999e-299 = 24 bytes, plus 1 for null
+ *
+ * Case 2: -0.00099999999999999999 = 23 bytes, plus 1 for null
+ */
+#define DOUBLE_SHORTEST_DECIMAL_LEN 25
+
+int double_to_shortest_decimal_bufn(double f, char *result);
+int double_to_shortest_decimal_buf(double f, char *result);
+char *double_to_shortest_decimal(double f);
+
+/*
+ * The length of 16 comes from:
+ *
+ * Case 1: -9.99999999e+29 = 15 bytes, plus 1 for null
+ *
+ * Case 2: -0.000999999999 = 15 bytes, plus 1 for null
+ */
+#define FLOAT_SHORTEST_DECIMAL_LEN 16
+
+int float_to_shortest_decimal_bufn(float f, char *result);
+int float_to_shortest_decimal_buf(float f, char *result);
+char *float_to_shortest_decimal(float f);
+
+#endif /* SHORTEST_DEC_H */
diff --git a/src/include/common/string.h b/src/include/common/string.h
new file mode 100644
index 0000000..5113c04
--- /dev/null
+++ b/src/include/common/string.h
@@ -0,0 +1,19 @@
+/*
+ * string.h
+ * string handling helpers
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/string.h
+ */
+#ifndef COMMON_STRING_H
+#define COMMON_STRING_H
+
+extern bool pg_str_endswith(const char *str, const char *end);
+extern int strtoint(const char *pg_restrict str, char **pg_restrict endptr,
+ int base);
+extern void pg_clean_ascii(char *str);
+extern int pg_strip_crlf(char *str);
+
+#endif /* COMMON_STRING_H */
diff --git a/src/include/common/unicode_combining_table.h b/src/include/common/unicode_combining_table.h
new file mode 100644
index 0000000..a9f10c3
--- /dev/null
+++ b/src/include/common/unicode_combining_table.h
@@ -0,0 +1,196 @@
+/* generated by src/common/unicode/generate-unicode_combining_table.pl, do not edit */
+
+static const struct mbinterval combining[] = {
+ {0x0300, 0x036F},
+ {0x0483, 0x0489},
+ {0x0591, 0x05BD},
+ {0x05BF, 0x05BF},
+ {0x05C1, 0x05C2},
+ {0x05C4, 0x05C5},
+ {0x05C7, 0x05C7},
+ {0x0610, 0x061A},
+ {0x064B, 0x065F},
+ {0x0670, 0x0670},
+ {0x06D6, 0x06DC},
+ {0x06DF, 0x06E4},
+ {0x06E7, 0x06E8},
+ {0x06EA, 0x06ED},
+ {0x0711, 0x0711},
+ {0x0730, 0x074A},
+ {0x07A6, 0x07B0},
+ {0x07EB, 0x07F3},
+ {0x07FD, 0x07FD},
+ {0x0816, 0x0819},
+ {0x081B, 0x0823},
+ {0x0825, 0x0827},
+ {0x0829, 0x082D},
+ {0x0859, 0x085B},
+ {0x08D3, 0x08E1},
+ {0x08E3, 0x0902},
+ {0x093A, 0x093A},
+ {0x093C, 0x093C},
+ {0x0941, 0x0948},
+ {0x094D, 0x094D},
+ {0x0951, 0x0957},
+ {0x0962, 0x0963},
+ {0x0981, 0x0981},
+ {0x09BC, 0x09BC},
+ {0x09C1, 0x09C4},
+ {0x09CD, 0x09CD},
+ {0x09E2, 0x09E3},
+ {0x09FE, 0x0A02},
+ {0x0A3C, 0x0A3C},
+ {0x0A41, 0x0A51},
+ {0x0A70, 0x0A71},
+ {0x0A75, 0x0A75},
+ {0x0A81, 0x0A82},
+ {0x0ABC, 0x0ABC},
+ {0x0AC1, 0x0AC8},
+ {0x0ACD, 0x0ACD},
+ {0x0AE2, 0x0AE3},
+ {0x0AFA, 0x0B01},
+ {0x0B3C, 0x0B3C},
+ {0x0B3F, 0x0B3F},
+ {0x0B41, 0x0B44},
+ {0x0B4D, 0x0B56},
+ {0x0B62, 0x0B63},
+ {0x0B82, 0x0B82},
+ {0x0BC0, 0x0BC0},
+ {0x0BCD, 0x0BCD},
+ {0x0C00, 0x0C00},
+ {0x0C04, 0x0C04},
+ {0x0C3E, 0x0C40},
+ {0x0C46, 0x0C56},
+ {0x0C62, 0x0C63},
+ {0x0C81, 0x0C81},
+ {0x0CBC, 0x0CBC},
+ {0x0CBF, 0x0CBF},
+ {0x0CC6, 0x0CC6},
+ {0x0CCC, 0x0CCD},
+ {0x0CE2, 0x0CE3},
+ {0x0D00, 0x0D01},
+ {0x0D3B, 0x0D3C},
+ {0x0D41, 0x0D44},
+ {0x0D4D, 0x0D4D},
+ {0x0D62, 0x0D63},
+ {0x0D81, 0x0D81},
+ {0x0DCA, 0x0DCA},
+ {0x0DD2, 0x0DD6},
+ {0x0E31, 0x0E31},
+ {0x0E34, 0x0E3A},
+ {0x0E47, 0x0E4E},
+ {0x0EB1, 0x0EB1},
+ {0x0EB4, 0x0EBC},
+ {0x0EC8, 0x0ECD},
+ {0x0F18, 0x0F19},
+ {0x0F35, 0x0F35},
+ {0x0F37, 0x0F37},
+ {0x0F39, 0x0F39},
+ {0x0F71, 0x0F7E},
+ {0x0F80, 0x0F84},
+ {0x0F86, 0x0F87},
+ {0x0F8D, 0x0FBC},
+ {0x0FC6, 0x0FC6},
+ {0x102D, 0x1030},
+ {0x1032, 0x1037},
+ {0x1039, 0x103A},
+ {0x103D, 0x103E},
+ {0x1058, 0x1059},
+ {0x105E, 0x1060},
+ {0x1071, 0x1074},
+ {0x1082, 0x1082},
+ {0x1085, 0x1086},
+ {0x108D, 0x108D},
+ {0x109D, 0x109D},
+ {0x135D, 0x135F},
+ {0x1712, 0x1714},
+ {0x1732, 0x1734},
+ {0x1752, 0x1753},
+ {0x1772, 0x1773},
+ {0x17B4, 0x17B5},
+ {0x17B7, 0x17BD},
+ {0x17C6, 0x17C6},
+ {0x17C9, 0x17D3},
+ {0x17DD, 0x17DD},
+ {0x180B, 0x180D},
+ {0x1885, 0x1886},
+ {0x18A9, 0x18A9},
+ {0x1920, 0x1922},
+ {0x1927, 0x1928},
+ {0x1932, 0x1932},
+ {0x1939, 0x193B},
+ {0x1A17, 0x1A18},
+ {0x1A1B, 0x1A1B},
+ {0x1A56, 0x1A56},
+ {0x1A58, 0x1A60},
+ {0x1A62, 0x1A62},
+ {0x1A65, 0x1A6C},
+ {0x1A73, 0x1A7F},
+ {0x1AB0, 0x1B03},
+ {0x1B34, 0x1B34},
+ {0x1B36, 0x1B3A},
+ {0x1B3C, 0x1B3C},
+ {0x1B42, 0x1B42},
+ {0x1B6B, 0x1B73},
+ {0x1B80, 0x1B81},
+ {0x1BA2, 0x1BA5},
+ {0x1BA8, 0x1BA9},
+ {0x1BAB, 0x1BAD},
+ {0x1BE6, 0x1BE6},
+ {0x1BE8, 0x1BE9},
+ {0x1BED, 0x1BED},
+ {0x1BEF, 0x1BF1},
+ {0x1C2C, 0x1C33},
+ {0x1C36, 0x1C37},
+ {0x1CD0, 0x1CD2},
+ {0x1CD4, 0x1CE0},
+ {0x1CE2, 0x1CE8},
+ {0x1CED, 0x1CED},
+ {0x1CF4, 0x1CF4},
+ {0x1CF8, 0x1CF9},
+ {0x1DC0, 0x1DFF},
+ {0x20D0, 0x20F0},
+ {0x2CEF, 0x2CF1},
+ {0x2D7F, 0x2D7F},
+ {0x2DE0, 0x2DFF},
+ {0x302A, 0x302D},
+ {0x3099, 0x309A},
+ {0xA66F, 0xA672},
+ {0xA674, 0xA67D},
+ {0xA69E, 0xA69F},
+ {0xA6F0, 0xA6F1},
+ {0xA802, 0xA802},
+ {0xA806, 0xA806},
+ {0xA80B, 0xA80B},
+ {0xA825, 0xA826},
+ {0xA82C, 0xA82C},
+ {0xA8C4, 0xA8C5},
+ {0xA8E0, 0xA8F1},
+ {0xA8FF, 0xA8FF},
+ {0xA926, 0xA92D},
+ {0xA947, 0xA951},
+ {0xA980, 0xA982},
+ {0xA9B3, 0xA9B3},
+ {0xA9B6, 0xA9B9},
+ {0xA9BC, 0xA9BD},
+ {0xA9E5, 0xA9E5},
+ {0xAA29, 0xAA2E},
+ {0xAA31, 0xAA32},
+ {0xAA35, 0xAA36},
+ {0xAA43, 0xAA43},
+ {0xAA4C, 0xAA4C},
+ {0xAA7C, 0xAA7C},
+ {0xAAB0, 0xAAB0},
+ {0xAAB2, 0xAAB4},
+ {0xAAB7, 0xAAB8},
+ {0xAABE, 0xAABF},
+ {0xAAC1, 0xAAC1},
+ {0xAAEC, 0xAAED},
+ {0xAAF6, 0xAAF6},
+ {0xABE5, 0xABE5},
+ {0xABE8, 0xABE8},
+ {0xABED, 0xABED},
+ {0xFB1E, 0xFB1E},
+ {0xFE00, 0xFE0F},
+ {0xFE20, 0xFE2F},
+};
diff --git a/src/include/common/unicode_norm.h b/src/include/common/unicode_norm.h
new file mode 100644
index 0000000..731e05b
--- /dev/null
+++ b/src/include/common/unicode_norm.h
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * unicode_norm.h
+ * Routines for normalizing Unicode strings
+ *
+ * These definitions are used by both frontend and backend code.
+ *
+ * Copyright (c) 2017-2020, PostgreSQL Global Development Group
+ *
+ * src/include/common/unicode_norm.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef UNICODE_NORM_H
+#define UNICODE_NORM_H
+
+#include "mb/pg_wchar.h"
+
+typedef enum
+{
+ UNICODE_NFC = 0,
+ UNICODE_NFD = 1,
+ UNICODE_NFKC = 2,
+ UNICODE_NFKD = 3,
+} UnicodeNormalizationForm;
+
+/* see UAX #15 */
+typedef enum
+{
+ UNICODE_NORM_QC_NO = 0,
+ UNICODE_NORM_QC_YES = 1,
+ UNICODE_NORM_QC_MAYBE = -1,
+} UnicodeNormalizationQC;
+
+extern pg_wchar *unicode_normalize(UnicodeNormalizationForm form, const pg_wchar *input);
+
+extern UnicodeNormalizationQC unicode_is_normalized_quickcheck(UnicodeNormalizationForm form, const pg_wchar *input);
+
+#endif /* UNICODE_NORM_H */
diff --git a/src/include/common/unicode_norm_table.h b/src/include/common/unicode_norm_table.h
new file mode 100644
index 0000000..96d43b8
--- /dev/null
+++ b/src/include/common/unicode_norm_table.h
@@ -0,0 +1,8937 @@
+/*-------------------------------------------------------------------------
+ *
+ * unicode_norm_table.h
+ * Composition table used for Unicode normalization
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/unicode_norm_table.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/*
+ * File auto-generated by src/common/unicode/generate-unicode_norm_table.pl,
+ * do not edit. There is deliberately not an #ifndef PG_UNICODE_NORM_TABLE_H
+ * here.
+ */
+typedef struct
+{
+ uint32 codepoint; /* Unicode codepoint */
+ uint8 comb_class; /* combining class of character */
+ uint8 dec_size_flags; /* size and flags of decomposition code list */
+ uint16 dec_index; /* index into UnicodeDecomp_codepoints, or the
+ * decomposition itself if DECOMP_INLINE */
+} pg_unicode_decomposition;
+
+#define DECOMP_NO_COMPOSE 0x80 /* don't use for re-composition */
+#define DECOMP_INLINE 0x40 /* decomposition is stored inline in
+ * dec_index */
+#define DECOMP_COMPAT 0x20 /* compatibility mapping */
+
+#define DECOMPOSITION_SIZE(x) ((x)->dec_size_flags & 0x1F)
+#define DECOMPOSITION_NO_COMPOSE(x) (((x)->dec_size_flags & (DECOMP_NO_COMPOSE | DECOMP_COMPAT)) != 0)
+#define DECOMPOSITION_IS_INLINE(x) (((x)->dec_size_flags & DECOMP_INLINE) != 0)
+#define DECOMPOSITION_IS_COMPAT(x) (((x)->dec_size_flags & DECOMP_COMPAT) != 0)
+
+/* Table of Unicode codepoints and their decompositions */
+static const pg_unicode_decomposition UnicodeDecompMain[6604] =
+{
+ {0x00A0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x00A8, 0, 2 | DECOMP_COMPAT, 0},
+ {0x00AA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x00AF, 0, 2 | DECOMP_COMPAT, 2},
+ {0x00B2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0x00B3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0x00B4, 0, 2 | DECOMP_COMPAT, 4},
+ {0x00B5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BC},
+ {0x00B8, 0, 2 | DECOMP_COMPAT, 6},
+ {0x00B9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0x00BA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x00BC, 0, 3 | DECOMP_COMPAT, 8},
+ {0x00BD, 0, 3 | DECOMP_COMPAT, 11},
+ {0x00BE, 0, 3 | DECOMP_COMPAT, 14},
+ {0x00C0, 0, 2, 17},
+ {0x00C1, 0, 2, 19},
+ {0x00C2, 0, 2, 21},
+ {0x00C3, 0, 2, 23},
+ {0x00C4, 0, 2, 25},
+ {0x00C5, 0, 2, 27},
+ {0x00C7, 0, 2, 29},
+ {0x00C8, 0, 2, 31},
+ {0x00C9, 0, 2, 33},
+ {0x00CA, 0, 2, 35},
+ {0x00CB, 0, 2, 37},
+ {0x00CC, 0, 2, 39},
+ {0x00CD, 0, 2, 41},
+ {0x00CE, 0, 2, 43},
+ {0x00CF, 0, 2, 45},
+ {0x00D1, 0, 2, 47},
+ {0x00D2, 0, 2, 49},
+ {0x00D3, 0, 2, 51},
+ {0x00D4, 0, 2, 53},
+ {0x00D5, 0, 2, 55},
+ {0x00D6, 0, 2, 57},
+ {0x00D9, 0, 2, 59},
+ {0x00DA, 0, 2, 61},
+ {0x00DB, 0, 2, 63},
+ {0x00DC, 0, 2, 65},
+ {0x00DD, 0, 2, 67},
+ {0x00E0, 0, 2, 69},
+ {0x00E1, 0, 2, 71},
+ {0x00E2, 0, 2, 73},
+ {0x00E3, 0, 2, 75},
+ {0x00E4, 0, 2, 77},
+ {0x00E5, 0, 2, 79},
+ {0x00E7, 0, 2, 81},
+ {0x00E8, 0, 2, 83},
+ {0x00E9, 0, 2, 85},
+ {0x00EA, 0, 2, 87},
+ {0x00EB, 0, 2, 89},
+ {0x00EC, 0, 2, 91},
+ {0x00ED, 0, 2, 93},
+ {0x00EE, 0, 2, 95},
+ {0x00EF, 0, 2, 97},
+ {0x00F1, 0, 2, 99},
+ {0x00F2, 0, 2, 101},
+ {0x00F3, 0, 2, 103},
+ {0x00F4, 0, 2, 105},
+ {0x00F5, 0, 2, 107},
+ {0x00F6, 0, 2, 109},
+ {0x00F9, 0, 2, 111},
+ {0x00FA, 0, 2, 113},
+ {0x00FB, 0, 2, 115},
+ {0x00FC, 0, 2, 117},
+ {0x00FD, 0, 2, 119},
+ {0x00FF, 0, 2, 121},
+ {0x0100, 0, 2, 123},
+ {0x0101, 0, 2, 125},
+ {0x0102, 0, 2, 127},
+ {0x0103, 0, 2, 129},
+ {0x0104, 0, 2, 131},
+ {0x0105, 0, 2, 133},
+ {0x0106, 0, 2, 135},
+ {0x0107, 0, 2, 137},
+ {0x0108, 0, 2, 139},
+ {0x0109, 0, 2, 141},
+ {0x010A, 0, 2, 143},
+ {0x010B, 0, 2, 145},
+ {0x010C, 0, 2, 147},
+ {0x010D, 0, 2, 149},
+ {0x010E, 0, 2, 151},
+ {0x010F, 0, 2, 153},
+ {0x0112, 0, 2, 155},
+ {0x0113, 0, 2, 157},
+ {0x0114, 0, 2, 159},
+ {0x0115, 0, 2, 161},
+ {0x0116, 0, 2, 163},
+ {0x0117, 0, 2, 165},
+ {0x0118, 0, 2, 167},
+ {0x0119, 0, 2, 169},
+ {0x011A, 0, 2, 171},
+ {0x011B, 0, 2, 173},
+ {0x011C, 0, 2, 175},
+ {0x011D, 0, 2, 177},
+ {0x011E, 0, 2, 179},
+ {0x011F, 0, 2, 181},
+ {0x0120, 0, 2, 183},
+ {0x0121, 0, 2, 185},
+ {0x0122, 0, 2, 187},
+ {0x0123, 0, 2, 189},
+ {0x0124, 0, 2, 191},
+ {0x0125, 0, 2, 193},
+ {0x0128, 0, 2, 195},
+ {0x0129, 0, 2, 197},
+ {0x012A, 0, 2, 199},
+ {0x012B, 0, 2, 201},
+ {0x012C, 0, 2, 203},
+ {0x012D, 0, 2, 205},
+ {0x012E, 0, 2, 207},
+ {0x012F, 0, 2, 209},
+ {0x0130, 0, 2, 211},
+ {0x0132, 0, 2 | DECOMP_COMPAT, 213},
+ {0x0133, 0, 2 | DECOMP_COMPAT, 215},
+ {0x0134, 0, 2, 217},
+ {0x0135, 0, 2, 219},
+ {0x0136, 0, 2, 221},
+ {0x0137, 0, 2, 223},
+ {0x0139, 0, 2, 225},
+ {0x013A, 0, 2, 227},
+ {0x013B, 0, 2, 229},
+ {0x013C, 0, 2, 231},
+ {0x013D, 0, 2, 233},
+ {0x013E, 0, 2, 235},
+ {0x013F, 0, 2 | DECOMP_COMPAT, 237},
+ {0x0140, 0, 2 | DECOMP_COMPAT, 239},
+ {0x0143, 0, 2, 241},
+ {0x0144, 0, 2, 243},
+ {0x0145, 0, 2, 245},
+ {0x0146, 0, 2, 247},
+ {0x0147, 0, 2, 249},
+ {0x0148, 0, 2, 251},
+ {0x0149, 0, 2 | DECOMP_COMPAT, 253},
+ {0x014C, 0, 2, 255},
+ {0x014D, 0, 2, 257},
+ {0x014E, 0, 2, 259},
+ {0x014F, 0, 2, 261},
+ {0x0150, 0, 2, 263},
+ {0x0151, 0, 2, 265},
+ {0x0154, 0, 2, 267},
+ {0x0155, 0, 2, 269},
+ {0x0156, 0, 2, 271},
+ {0x0157, 0, 2, 273},
+ {0x0158, 0, 2, 275},
+ {0x0159, 0, 2, 277},
+ {0x015A, 0, 2, 279},
+ {0x015B, 0, 2, 281},
+ {0x015C, 0, 2, 283},
+ {0x015D, 0, 2, 285},
+ {0x015E, 0, 2, 287},
+ {0x015F, 0, 2, 289},
+ {0x0160, 0, 2, 291},
+ {0x0161, 0, 2, 293},
+ {0x0162, 0, 2, 295},
+ {0x0163, 0, 2, 297},
+ {0x0164, 0, 2, 299},
+ {0x0165, 0, 2, 301},
+ {0x0168, 0, 2, 303},
+ {0x0169, 0, 2, 305},
+ {0x016A, 0, 2, 307},
+ {0x016B, 0, 2, 309},
+ {0x016C, 0, 2, 311},
+ {0x016D, 0, 2, 313},
+ {0x016E, 0, 2, 315},
+ {0x016F, 0, 2, 317},
+ {0x0170, 0, 2, 319},
+ {0x0171, 0, 2, 321},
+ {0x0172, 0, 2, 323},
+ {0x0173, 0, 2, 325},
+ {0x0174, 0, 2, 327},
+ {0x0175, 0, 2, 329},
+ {0x0176, 0, 2, 331},
+ {0x0177, 0, 2, 333},
+ {0x0178, 0, 2, 335},
+ {0x0179, 0, 2, 337},
+ {0x017A, 0, 2, 339},
+ {0x017B, 0, 2, 341},
+ {0x017C, 0, 2, 343},
+ {0x017D, 0, 2, 345},
+ {0x017E, 0, 2, 347},
+ {0x017F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x01A0, 0, 2, 349},
+ {0x01A1, 0, 2, 351},
+ {0x01AF, 0, 2, 353},
+ {0x01B0, 0, 2, 355},
+ {0x01C4, 0, 2 | DECOMP_COMPAT, 357},
+ {0x01C5, 0, 2 | DECOMP_COMPAT, 359},
+ {0x01C6, 0, 2 | DECOMP_COMPAT, 361},
+ {0x01C7, 0, 2 | DECOMP_COMPAT, 363},
+ {0x01C8, 0, 2 | DECOMP_COMPAT, 365},
+ {0x01C9, 0, 2 | DECOMP_COMPAT, 367},
+ {0x01CA, 0, 2 | DECOMP_COMPAT, 369},
+ {0x01CB, 0, 2 | DECOMP_COMPAT, 371},
+ {0x01CC, 0, 2 | DECOMP_COMPAT, 373},
+ {0x01CD, 0, 2, 375},
+ {0x01CE, 0, 2, 377},
+ {0x01CF, 0, 2, 379},
+ {0x01D0, 0, 2, 381},
+ {0x01D1, 0, 2, 383},
+ {0x01D2, 0, 2, 385},
+ {0x01D3, 0, 2, 387},
+ {0x01D4, 0, 2, 389},
+ {0x01D5, 0, 2, 391},
+ {0x01D6, 0, 2, 393},
+ {0x01D7, 0, 2, 395},
+ {0x01D8, 0, 2, 397},
+ {0x01D9, 0, 2, 399},
+ {0x01DA, 0, 2, 401},
+ {0x01DB, 0, 2, 403},
+ {0x01DC, 0, 2, 405},
+ {0x01DE, 0, 2, 407},
+ {0x01DF, 0, 2, 409},
+ {0x01E0, 0, 2, 411},
+ {0x01E1, 0, 2, 413},
+ {0x01E2, 0, 2, 415},
+ {0x01E3, 0, 2, 417},
+ {0x01E6, 0, 2, 419},
+ {0x01E7, 0, 2, 421},
+ {0x01E8, 0, 2, 423},
+ {0x01E9, 0, 2, 425},
+ {0x01EA, 0, 2, 427},
+ {0x01EB, 0, 2, 429},
+ {0x01EC, 0, 2, 431},
+ {0x01ED, 0, 2, 433},
+ {0x01EE, 0, 2, 435},
+ {0x01EF, 0, 2, 437},
+ {0x01F0, 0, 2, 439},
+ {0x01F1, 0, 2 | DECOMP_COMPAT, 441},
+ {0x01F2, 0, 2 | DECOMP_COMPAT, 443},
+ {0x01F3, 0, 2 | DECOMP_COMPAT, 445},
+ {0x01F4, 0, 2, 447},
+ {0x01F5, 0, 2, 449},
+ {0x01F8, 0, 2, 451},
+ {0x01F9, 0, 2, 453},
+ {0x01FA, 0, 2, 455},
+ {0x01FB, 0, 2, 457},
+ {0x01FC, 0, 2, 459},
+ {0x01FD, 0, 2, 461},
+ {0x01FE, 0, 2, 463},
+ {0x01FF, 0, 2, 465},
+ {0x0200, 0, 2, 467},
+ {0x0201, 0, 2, 469},
+ {0x0202, 0, 2, 471},
+ {0x0203, 0, 2, 473},
+ {0x0204, 0, 2, 475},
+ {0x0205, 0, 2, 477},
+ {0x0206, 0, 2, 479},
+ {0x0207, 0, 2, 481},
+ {0x0208, 0, 2, 483},
+ {0x0209, 0, 2, 485},
+ {0x020A, 0, 2, 487},
+ {0x020B, 0, 2, 489},
+ {0x020C, 0, 2, 491},
+ {0x020D, 0, 2, 493},
+ {0x020E, 0, 2, 495},
+ {0x020F, 0, 2, 497},
+ {0x0210, 0, 2, 499},
+ {0x0211, 0, 2, 501},
+ {0x0212, 0, 2, 503},
+ {0x0213, 0, 2, 505},
+ {0x0214, 0, 2, 507},
+ {0x0215, 0, 2, 509},
+ {0x0216, 0, 2, 511},
+ {0x0217, 0, 2, 513},
+ {0x0218, 0, 2, 515},
+ {0x0219, 0, 2, 517},
+ {0x021A, 0, 2, 519},
+ {0x021B, 0, 2, 521},
+ {0x021E, 0, 2, 523},
+ {0x021F, 0, 2, 525},
+ {0x0226, 0, 2, 527},
+ {0x0227, 0, 2, 529},
+ {0x0228, 0, 2, 531},
+ {0x0229, 0, 2, 533},
+ {0x022A, 0, 2, 535},
+ {0x022B, 0, 2, 537},
+ {0x022C, 0, 2, 539},
+ {0x022D, 0, 2, 541},
+ {0x022E, 0, 2, 543},
+ {0x022F, 0, 2, 545},
+ {0x0230, 0, 2, 547},
+ {0x0231, 0, 2, 549},
+ {0x0232, 0, 2, 551},
+ {0x0233, 0, 2, 553},
+ {0x02B0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x02B1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0266},
+ {0x02B2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x02B3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x02B4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0279},
+ {0x02B5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x027B},
+ {0x02B6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0281},
+ {0x02B7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x02B8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x02D8, 0, 2 | DECOMP_COMPAT, 555},
+ {0x02D9, 0, 2 | DECOMP_COMPAT, 557},
+ {0x02DA, 0, 2 | DECOMP_COMPAT, 559},
+ {0x02DB, 0, 2 | DECOMP_COMPAT, 561},
+ {0x02DC, 0, 2 | DECOMP_COMPAT, 563},
+ {0x02DD, 0, 2 | DECOMP_COMPAT, 565},
+ {0x02E0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0263},
+ {0x02E1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x02E2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x02E3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x02E4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0295},
+ {0x0300, 230, 0, 0},
+ {0x0301, 230, 0, 0},
+ {0x0302, 230, 0, 0},
+ {0x0303, 230, 0, 0},
+ {0x0304, 230, 0, 0},
+ {0x0305, 230, 0, 0},
+ {0x0306, 230, 0, 0},
+ {0x0307, 230, 0, 0},
+ {0x0308, 230, 0, 0},
+ {0x0309, 230, 0, 0},
+ {0x030A, 230, 0, 0},
+ {0x030B, 230, 0, 0},
+ {0x030C, 230, 0, 0},
+ {0x030D, 230, 0, 0},
+ {0x030E, 230, 0, 0},
+ {0x030F, 230, 0, 0},
+ {0x0310, 230, 0, 0},
+ {0x0311, 230, 0, 0},
+ {0x0312, 230, 0, 0},
+ {0x0313, 230, 0, 0},
+ {0x0314, 230, 0, 0},
+ {0x0315, 232, 0, 0},
+ {0x0316, 220, 0, 0},
+ {0x0317, 220, 0, 0},
+ {0x0318, 220, 0, 0},
+ {0x0319, 220, 0, 0},
+ {0x031A, 232, 0, 0},
+ {0x031B, 216, 0, 0},
+ {0x031C, 220, 0, 0},
+ {0x031D, 220, 0, 0},
+ {0x031E, 220, 0, 0},
+ {0x031F, 220, 0, 0},
+ {0x0320, 220, 0, 0},
+ {0x0321, 202, 0, 0},
+ {0x0322, 202, 0, 0},
+ {0x0323, 220, 0, 0},
+ {0x0324, 220, 0, 0},
+ {0x0325, 220, 0, 0},
+ {0x0326, 220, 0, 0},
+ {0x0327, 202, 0, 0},
+ {0x0328, 202, 0, 0},
+ {0x0329, 220, 0, 0},
+ {0x032A, 220, 0, 0},
+ {0x032B, 220, 0, 0},
+ {0x032C, 220, 0, 0},
+ {0x032D, 220, 0, 0},
+ {0x032E, 220, 0, 0},
+ {0x032F, 220, 0, 0},
+ {0x0330, 220, 0, 0},
+ {0x0331, 220, 0, 0},
+ {0x0332, 220, 0, 0},
+ {0x0333, 220, 0, 0},
+ {0x0334, 1, 0, 0},
+ {0x0335, 1, 0, 0},
+ {0x0336, 1, 0, 0},
+ {0x0337, 1, 0, 0},
+ {0x0338, 1, 0, 0},
+ {0x0339, 220, 0, 0},
+ {0x033A, 220, 0, 0},
+ {0x033B, 220, 0, 0},
+ {0x033C, 220, 0, 0},
+ {0x033D, 230, 0, 0},
+ {0x033E, 230, 0, 0},
+ {0x033F, 230, 0, 0},
+ {0x0340, 230, 1 | DECOMP_INLINE, 0x0300},
+ {0x0341, 230, 1 | DECOMP_INLINE, 0x0301},
+ {0x0342, 230, 0, 0},
+ {0x0343, 230, 1 | DECOMP_INLINE, 0x0313},
+ {0x0344, 230, 2 | DECOMP_NO_COMPOSE, 567}, /* non-starter decomposition */
+ {0x0345, 240, 0, 0},
+ {0x0346, 230, 0, 0},
+ {0x0347, 220, 0, 0},
+ {0x0348, 220, 0, 0},
+ {0x0349, 220, 0, 0},
+ {0x034A, 230, 0, 0},
+ {0x034B, 230, 0, 0},
+ {0x034C, 230, 0, 0},
+ {0x034D, 220, 0, 0},
+ {0x034E, 220, 0, 0},
+ {0x0350, 230, 0, 0},
+ {0x0351, 230, 0, 0},
+ {0x0352, 230, 0, 0},
+ {0x0353, 220, 0, 0},
+ {0x0354, 220, 0, 0},
+ {0x0355, 220, 0, 0},
+ {0x0356, 220, 0, 0},
+ {0x0357, 230, 0, 0},
+ {0x0358, 232, 0, 0},
+ {0x0359, 220, 0, 0},
+ {0x035A, 220, 0, 0},
+ {0x035B, 230, 0, 0},
+ {0x035C, 233, 0, 0},
+ {0x035D, 234, 0, 0},
+ {0x035E, 234, 0, 0},
+ {0x035F, 233, 0, 0},
+ {0x0360, 234, 0, 0},
+ {0x0361, 234, 0, 0},
+ {0x0362, 233, 0, 0},
+ {0x0363, 230, 0, 0},
+ {0x0364, 230, 0, 0},
+ {0x0365, 230, 0, 0},
+ {0x0366, 230, 0, 0},
+ {0x0367, 230, 0, 0},
+ {0x0368, 230, 0, 0},
+ {0x0369, 230, 0, 0},
+ {0x036A, 230, 0, 0},
+ {0x036B, 230, 0, 0},
+ {0x036C, 230, 0, 0},
+ {0x036D, 230, 0, 0},
+ {0x036E, 230, 0, 0},
+ {0x036F, 230, 0, 0},
+ {0x0374, 0, 1 | DECOMP_INLINE, 0x02B9},
+ {0x037A, 0, 2 | DECOMP_COMPAT, 569},
+ {0x037E, 0, 1 | DECOMP_INLINE, 0x003B},
+ {0x0384, 0, 2 | DECOMP_COMPAT, 571},
+ {0x0385, 0, 2, 573},
+ {0x0386, 0, 2, 575},
+ {0x0387, 0, 1 | DECOMP_INLINE, 0x00B7},
+ {0x0388, 0, 2, 577},
+ {0x0389, 0, 2, 579},
+ {0x038A, 0, 2, 581},
+ {0x038C, 0, 2, 583},
+ {0x038E, 0, 2, 585},
+ {0x038F, 0, 2, 587},
+ {0x0390, 0, 2, 589},
+ {0x03AA, 0, 2, 591},
+ {0x03AB, 0, 2, 593},
+ {0x03AC, 0, 2, 595},
+ {0x03AD, 0, 2, 597},
+ {0x03AE, 0, 2, 599},
+ {0x03AF, 0, 2, 601},
+ {0x03B0, 0, 2, 603},
+ {0x03CA, 0, 2, 605},
+ {0x03CB, 0, 2, 607},
+ {0x03CC, 0, 2, 609},
+ {0x03CD, 0, 2, 611},
+ {0x03CE, 0, 2, 613},
+ {0x03D0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B2},
+ {0x03D1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B8},
+ {0x03D2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A5},
+ {0x03D3, 0, 2, 615},
+ {0x03D4, 0, 2, 617},
+ {0x03D5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C6},
+ {0x03D6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C0},
+ {0x03F0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BA},
+ {0x03F1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C1},
+ {0x03F2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C2},
+ {0x03F4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0398},
+ {0x03F5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B5},
+ {0x03F9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A3},
+ {0x0400, 0, 2, 619},
+ {0x0401, 0, 2, 621},
+ {0x0403, 0, 2, 623},
+ {0x0407, 0, 2, 625},
+ {0x040C, 0, 2, 627},
+ {0x040D, 0, 2, 629},
+ {0x040E, 0, 2, 631},
+ {0x0419, 0, 2, 633},
+ {0x0439, 0, 2, 635},
+ {0x0450, 0, 2, 637},
+ {0x0451, 0, 2, 639},
+ {0x0453, 0, 2, 641},
+ {0x0457, 0, 2, 643},
+ {0x045C, 0, 2, 645},
+ {0x045D, 0, 2, 647},
+ {0x045E, 0, 2, 649},
+ {0x0476, 0, 2, 651},
+ {0x0477, 0, 2, 653},
+ {0x0483, 230, 0, 0},
+ {0x0484, 230, 0, 0},
+ {0x0485, 230, 0, 0},
+ {0x0486, 230, 0, 0},
+ {0x0487, 230, 0, 0},
+ {0x04C1, 0, 2, 655},
+ {0x04C2, 0, 2, 657},
+ {0x04D0, 0, 2, 659},
+ {0x04D1, 0, 2, 661},
+ {0x04D2, 0, 2, 663},
+ {0x04D3, 0, 2, 665},
+ {0x04D6, 0, 2, 667},
+ {0x04D7, 0, 2, 669},
+ {0x04DA, 0, 2, 671},
+ {0x04DB, 0, 2, 673},
+ {0x04DC, 0, 2, 675},
+ {0x04DD, 0, 2, 677},
+ {0x04DE, 0, 2, 679},
+ {0x04DF, 0, 2, 681},
+ {0x04E2, 0, 2, 683},
+ {0x04E3, 0, 2, 685},
+ {0x04E4, 0, 2, 687},
+ {0x04E5, 0, 2, 689},
+ {0x04E6, 0, 2, 691},
+ {0x04E7, 0, 2, 693},
+ {0x04EA, 0, 2, 695},
+ {0x04EB, 0, 2, 697},
+ {0x04EC, 0, 2, 699},
+ {0x04ED, 0, 2, 701},
+ {0x04EE, 0, 2, 703},
+ {0x04EF, 0, 2, 705},
+ {0x04F0, 0, 2, 707},
+ {0x04F1, 0, 2, 709},
+ {0x04F2, 0, 2, 711},
+ {0x04F3, 0, 2, 713},
+ {0x04F4, 0, 2, 715},
+ {0x04F5, 0, 2, 717},
+ {0x04F8, 0, 2, 719},
+ {0x04F9, 0, 2, 721},
+ {0x0587, 0, 2 | DECOMP_COMPAT, 723},
+ {0x0591, 220, 0, 0},
+ {0x0592, 230, 0, 0},
+ {0x0593, 230, 0, 0},
+ {0x0594, 230, 0, 0},
+ {0x0595, 230, 0, 0},
+ {0x0596, 220, 0, 0},
+ {0x0597, 230, 0, 0},
+ {0x0598, 230, 0, 0},
+ {0x0599, 230, 0, 0},
+ {0x059A, 222, 0, 0},
+ {0x059B, 220, 0, 0},
+ {0x059C, 230, 0, 0},
+ {0x059D, 230, 0, 0},
+ {0x059E, 230, 0, 0},
+ {0x059F, 230, 0, 0},
+ {0x05A0, 230, 0, 0},
+ {0x05A1, 230, 0, 0},
+ {0x05A2, 220, 0, 0},
+ {0x05A3, 220, 0, 0},
+ {0x05A4, 220, 0, 0},
+ {0x05A5, 220, 0, 0},
+ {0x05A6, 220, 0, 0},
+ {0x05A7, 220, 0, 0},
+ {0x05A8, 230, 0, 0},
+ {0x05A9, 230, 0, 0},
+ {0x05AA, 220, 0, 0},
+ {0x05AB, 230, 0, 0},
+ {0x05AC, 230, 0, 0},
+ {0x05AD, 222, 0, 0},
+ {0x05AE, 228, 0, 0},
+ {0x05AF, 230, 0, 0},
+ {0x05B0, 10, 0, 0},
+ {0x05B1, 11, 0, 0},
+ {0x05B2, 12, 0, 0},
+ {0x05B3, 13, 0, 0},
+ {0x05B4, 14, 0, 0},
+ {0x05B5, 15, 0, 0},
+ {0x05B6, 16, 0, 0},
+ {0x05B7, 17, 0, 0},
+ {0x05B8, 18, 0, 0},
+ {0x05B9, 19, 0, 0},
+ {0x05BA, 19, 0, 0},
+ {0x05BB, 20, 0, 0},
+ {0x05BC, 21, 0, 0},
+ {0x05BD, 22, 0, 0},
+ {0x05BF, 23, 0, 0},
+ {0x05C1, 24, 0, 0},
+ {0x05C2, 25, 0, 0},
+ {0x05C4, 230, 0, 0},
+ {0x05C5, 220, 0, 0},
+ {0x05C7, 18, 0, 0},
+ {0x0610, 230, 0, 0},
+ {0x0611, 230, 0, 0},
+ {0x0612, 230, 0, 0},
+ {0x0613, 230, 0, 0},
+ {0x0614, 230, 0, 0},
+ {0x0615, 230, 0, 0},
+ {0x0616, 230, 0, 0},
+ {0x0617, 230, 0, 0},
+ {0x0618, 30, 0, 0},
+ {0x0619, 31, 0, 0},
+ {0x061A, 32, 0, 0},
+ {0x0622, 0, 2, 725},
+ {0x0623, 0, 2, 727},
+ {0x0624, 0, 2, 729},
+ {0x0625, 0, 2, 731},
+ {0x0626, 0, 2, 733},
+ {0x064B, 27, 0, 0},
+ {0x064C, 28, 0, 0},
+ {0x064D, 29, 0, 0},
+ {0x064E, 30, 0, 0},
+ {0x064F, 31, 0, 0},
+ {0x0650, 32, 0, 0},
+ {0x0651, 33, 0, 0},
+ {0x0652, 34, 0, 0},
+ {0x0653, 230, 0, 0},
+ {0x0654, 230, 0, 0},
+ {0x0655, 220, 0, 0},
+ {0x0656, 220, 0, 0},
+ {0x0657, 230, 0, 0},
+ {0x0658, 230, 0, 0},
+ {0x0659, 230, 0, 0},
+ {0x065A, 230, 0, 0},
+ {0x065B, 230, 0, 0},
+ {0x065C, 220, 0, 0},
+ {0x065D, 230, 0, 0},
+ {0x065E, 230, 0, 0},
+ {0x065F, 220, 0, 0},
+ {0x0670, 35, 0, 0},
+ {0x0675, 0, 2 | DECOMP_COMPAT, 735},
+ {0x0676, 0, 2 | DECOMP_COMPAT, 737},
+ {0x0677, 0, 2 | DECOMP_COMPAT, 739},
+ {0x0678, 0, 2 | DECOMP_COMPAT, 741},
+ {0x06C0, 0, 2, 743},
+ {0x06C2, 0, 2, 745},
+ {0x06D3, 0, 2, 747},
+ {0x06D6, 230, 0, 0},
+ {0x06D7, 230, 0, 0},
+ {0x06D8, 230, 0, 0},
+ {0x06D9, 230, 0, 0},
+ {0x06DA, 230, 0, 0},
+ {0x06DB, 230, 0, 0},
+ {0x06DC, 230, 0, 0},
+ {0x06DF, 230, 0, 0},
+ {0x06E0, 230, 0, 0},
+ {0x06E1, 230, 0, 0},
+ {0x06E2, 230, 0, 0},
+ {0x06E3, 220, 0, 0},
+ {0x06E4, 230, 0, 0},
+ {0x06E7, 230, 0, 0},
+ {0x06E8, 230, 0, 0},
+ {0x06EA, 220, 0, 0},
+ {0x06EB, 230, 0, 0},
+ {0x06EC, 230, 0, 0},
+ {0x06ED, 220, 0, 0},
+ {0x0711, 36, 0, 0},
+ {0x0730, 230, 0, 0},
+ {0x0731, 220, 0, 0},
+ {0x0732, 230, 0, 0},
+ {0x0733, 230, 0, 0},
+ {0x0734, 220, 0, 0},
+ {0x0735, 230, 0, 0},
+ {0x0736, 230, 0, 0},
+ {0x0737, 220, 0, 0},
+ {0x0738, 220, 0, 0},
+ {0x0739, 220, 0, 0},
+ {0x073A, 230, 0, 0},
+ {0x073B, 220, 0, 0},
+ {0x073C, 220, 0, 0},
+ {0x073D, 230, 0, 0},
+ {0x073E, 220, 0, 0},
+ {0x073F, 230, 0, 0},
+ {0x0740, 230, 0, 0},
+ {0x0741, 230, 0, 0},
+ {0x0742, 220, 0, 0},
+ {0x0743, 230, 0, 0},
+ {0x0744, 220, 0, 0},
+ {0x0745, 230, 0, 0},
+ {0x0746, 220, 0, 0},
+ {0x0747, 230, 0, 0},
+ {0x0748, 220, 0, 0},
+ {0x0749, 230, 0, 0},
+ {0x074A, 230, 0, 0},
+ {0x07EB, 230, 0, 0},
+ {0x07EC, 230, 0, 0},
+ {0x07ED, 230, 0, 0},
+ {0x07EE, 230, 0, 0},
+ {0x07EF, 230, 0, 0},
+ {0x07F0, 230, 0, 0},
+ {0x07F1, 230, 0, 0},
+ {0x07F2, 220, 0, 0},
+ {0x07F3, 230, 0, 0},
+ {0x07FD, 220, 0, 0},
+ {0x0816, 230, 0, 0},
+ {0x0817, 230, 0, 0},
+ {0x0818, 230, 0, 0},
+ {0x0819, 230, 0, 0},
+ {0x081B, 230, 0, 0},
+ {0x081C, 230, 0, 0},
+ {0x081D, 230, 0, 0},
+ {0x081E, 230, 0, 0},
+ {0x081F, 230, 0, 0},
+ {0x0820, 230, 0, 0},
+ {0x0821, 230, 0, 0},
+ {0x0822, 230, 0, 0},
+ {0x0823, 230, 0, 0},
+ {0x0825, 230, 0, 0},
+ {0x0826, 230, 0, 0},
+ {0x0827, 230, 0, 0},
+ {0x0829, 230, 0, 0},
+ {0x082A, 230, 0, 0},
+ {0x082B, 230, 0, 0},
+ {0x082C, 230, 0, 0},
+ {0x082D, 230, 0, 0},
+ {0x0859, 220, 0, 0},
+ {0x085A, 220, 0, 0},
+ {0x085B, 220, 0, 0},
+ {0x08D3, 220, 0, 0},
+ {0x08D4, 230, 0, 0},
+ {0x08D5, 230, 0, 0},
+ {0x08D6, 230, 0, 0},
+ {0x08D7, 230, 0, 0},
+ {0x08D8, 230, 0, 0},
+ {0x08D9, 230, 0, 0},
+ {0x08DA, 230, 0, 0},
+ {0x08DB, 230, 0, 0},
+ {0x08DC, 230, 0, 0},
+ {0x08DD, 230, 0, 0},
+ {0x08DE, 230, 0, 0},
+ {0x08DF, 230, 0, 0},
+ {0x08E0, 230, 0, 0},
+ {0x08E1, 230, 0, 0},
+ {0x08E3, 220, 0, 0},
+ {0x08E4, 230, 0, 0},
+ {0x08E5, 230, 0, 0},
+ {0x08E6, 220, 0, 0},
+ {0x08E7, 230, 0, 0},
+ {0x08E8, 230, 0, 0},
+ {0x08E9, 220, 0, 0},
+ {0x08EA, 230, 0, 0},
+ {0x08EB, 230, 0, 0},
+ {0x08EC, 230, 0, 0},
+ {0x08ED, 220, 0, 0},
+ {0x08EE, 220, 0, 0},
+ {0x08EF, 220, 0, 0},
+ {0x08F0, 27, 0, 0},
+ {0x08F1, 28, 0, 0},
+ {0x08F2, 29, 0, 0},
+ {0x08F3, 230, 0, 0},
+ {0x08F4, 230, 0, 0},
+ {0x08F5, 230, 0, 0},
+ {0x08F6, 220, 0, 0},
+ {0x08F7, 230, 0, 0},
+ {0x08F8, 230, 0, 0},
+ {0x08F9, 220, 0, 0},
+ {0x08FA, 220, 0, 0},
+ {0x08FB, 230, 0, 0},
+ {0x08FC, 230, 0, 0},
+ {0x08FD, 230, 0, 0},
+ {0x08FE, 230, 0, 0},
+ {0x08FF, 230, 0, 0},
+ {0x0929, 0, 2, 749},
+ {0x0931, 0, 2, 751},
+ {0x0934, 0, 2, 753},
+ {0x093C, 7, 0, 0},
+ {0x094D, 9, 0, 0},
+ {0x0951, 230, 0, 0},
+ {0x0952, 220, 0, 0},
+ {0x0953, 230, 0, 0},
+ {0x0954, 230, 0, 0},
+ {0x0958, 0, 2 | DECOMP_NO_COMPOSE, 755}, /* in exclusion list */
+ {0x0959, 0, 2 | DECOMP_NO_COMPOSE, 757}, /* in exclusion list */
+ {0x095A, 0, 2 | DECOMP_NO_COMPOSE, 759}, /* in exclusion list */
+ {0x095B, 0, 2 | DECOMP_NO_COMPOSE, 761}, /* in exclusion list */
+ {0x095C, 0, 2 | DECOMP_NO_COMPOSE, 763}, /* in exclusion list */
+ {0x095D, 0, 2 | DECOMP_NO_COMPOSE, 765}, /* in exclusion list */
+ {0x095E, 0, 2 | DECOMP_NO_COMPOSE, 767}, /* in exclusion list */
+ {0x095F, 0, 2 | DECOMP_NO_COMPOSE, 769}, /* in exclusion list */
+ {0x09BC, 7, 0, 0},
+ {0x09CB, 0, 2, 771},
+ {0x09CC, 0, 2, 773},
+ {0x09CD, 9, 0, 0},
+ {0x09DC, 0, 2 | DECOMP_NO_COMPOSE, 775}, /* in exclusion list */
+ {0x09DD, 0, 2 | DECOMP_NO_COMPOSE, 777}, /* in exclusion list */
+ {0x09DF, 0, 2 | DECOMP_NO_COMPOSE, 779}, /* in exclusion list */
+ {0x09FE, 230, 0, 0},
+ {0x0A33, 0, 2 | DECOMP_NO_COMPOSE, 781}, /* in exclusion list */
+ {0x0A36, 0, 2 | DECOMP_NO_COMPOSE, 783}, /* in exclusion list */
+ {0x0A3C, 7, 0, 0},
+ {0x0A4D, 9, 0, 0},
+ {0x0A59, 0, 2 | DECOMP_NO_COMPOSE, 785}, /* in exclusion list */
+ {0x0A5A, 0, 2 | DECOMP_NO_COMPOSE, 787}, /* in exclusion list */
+ {0x0A5B, 0, 2 | DECOMP_NO_COMPOSE, 789}, /* in exclusion list */
+ {0x0A5E, 0, 2 | DECOMP_NO_COMPOSE, 791}, /* in exclusion list */
+ {0x0ABC, 7, 0, 0},
+ {0x0ACD, 9, 0, 0},
+ {0x0B3C, 7, 0, 0},
+ {0x0B48, 0, 2, 793},
+ {0x0B4B, 0, 2, 795},
+ {0x0B4C, 0, 2, 797},
+ {0x0B4D, 9, 0, 0},
+ {0x0B5C, 0, 2 | DECOMP_NO_COMPOSE, 799}, /* in exclusion list */
+ {0x0B5D, 0, 2 | DECOMP_NO_COMPOSE, 801}, /* in exclusion list */
+ {0x0B94, 0, 2, 803},
+ {0x0BCA, 0, 2, 805},
+ {0x0BCB, 0, 2, 807},
+ {0x0BCC, 0, 2, 809},
+ {0x0BCD, 9, 0, 0},
+ {0x0C48, 0, 2, 811},
+ {0x0C4D, 9, 0, 0},
+ {0x0C55, 84, 0, 0},
+ {0x0C56, 91, 0, 0},
+ {0x0CBC, 7, 0, 0},
+ {0x0CC0, 0, 2, 813},
+ {0x0CC7, 0, 2, 815},
+ {0x0CC8, 0, 2, 817},
+ {0x0CCA, 0, 2, 819},
+ {0x0CCB, 0, 2, 821},
+ {0x0CCD, 9, 0, 0},
+ {0x0D3B, 9, 0, 0},
+ {0x0D3C, 9, 0, 0},
+ {0x0D4A, 0, 2, 823},
+ {0x0D4B, 0, 2, 825},
+ {0x0D4C, 0, 2, 827},
+ {0x0D4D, 9, 0, 0},
+ {0x0DCA, 9, 0, 0},
+ {0x0DDA, 0, 2, 829},
+ {0x0DDC, 0, 2, 831},
+ {0x0DDD, 0, 2, 833},
+ {0x0DDE, 0, 2, 835},
+ {0x0E33, 0, 2 | DECOMP_COMPAT, 837},
+ {0x0E38, 103, 0, 0},
+ {0x0E39, 103, 0, 0},
+ {0x0E3A, 9, 0, 0},
+ {0x0E48, 107, 0, 0},
+ {0x0E49, 107, 0, 0},
+ {0x0E4A, 107, 0, 0},
+ {0x0E4B, 107, 0, 0},
+ {0x0EB3, 0, 2 | DECOMP_COMPAT, 839},
+ {0x0EB8, 118, 0, 0},
+ {0x0EB9, 118, 0, 0},
+ {0x0EBA, 9, 0, 0},
+ {0x0EC8, 122, 0, 0},
+ {0x0EC9, 122, 0, 0},
+ {0x0ECA, 122, 0, 0},
+ {0x0ECB, 122, 0, 0},
+ {0x0EDC, 0, 2 | DECOMP_COMPAT, 841},
+ {0x0EDD, 0, 2 | DECOMP_COMPAT, 843},
+ {0x0F0C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0F0B},
+ {0x0F18, 220, 0, 0},
+ {0x0F19, 220, 0, 0},
+ {0x0F35, 220, 0, 0},
+ {0x0F37, 220, 0, 0},
+ {0x0F39, 216, 0, 0},
+ {0x0F43, 0, 2 | DECOMP_NO_COMPOSE, 845}, /* in exclusion list */
+ {0x0F4D, 0, 2 | DECOMP_NO_COMPOSE, 847}, /* in exclusion list */
+ {0x0F52, 0, 2 | DECOMP_NO_COMPOSE, 849}, /* in exclusion list */
+ {0x0F57, 0, 2 | DECOMP_NO_COMPOSE, 851}, /* in exclusion list */
+ {0x0F5C, 0, 2 | DECOMP_NO_COMPOSE, 853}, /* in exclusion list */
+ {0x0F69, 0, 2 | DECOMP_NO_COMPOSE, 855}, /* in exclusion list */
+ {0x0F71, 129, 0, 0},
+ {0x0F72, 130, 0, 0},
+ {0x0F73, 0, 2 | DECOMP_NO_COMPOSE, 857}, /* non-starter decomposition */
+ {0x0F74, 132, 0, 0},
+ {0x0F75, 0, 2 | DECOMP_NO_COMPOSE, 859}, /* non-starter decomposition */
+ {0x0F76, 0, 2 | DECOMP_NO_COMPOSE, 861}, /* in exclusion list */
+ {0x0F77, 0, 2 | DECOMP_COMPAT, 863},
+ {0x0F78, 0, 2 | DECOMP_NO_COMPOSE, 865}, /* in exclusion list */
+ {0x0F79, 0, 2 | DECOMP_COMPAT, 867},
+ {0x0F7A, 130, 0, 0},
+ {0x0F7B, 130, 0, 0},
+ {0x0F7C, 130, 0, 0},
+ {0x0F7D, 130, 0, 0},
+ {0x0F80, 130, 0, 0},
+ {0x0F81, 0, 2 | DECOMP_NO_COMPOSE, 869}, /* non-starter decomposition */
+ {0x0F82, 230, 0, 0},
+ {0x0F83, 230, 0, 0},
+ {0x0F84, 9, 0, 0},
+ {0x0F86, 230, 0, 0},
+ {0x0F87, 230, 0, 0},
+ {0x0F93, 0, 2 | DECOMP_NO_COMPOSE, 871}, /* in exclusion list */
+ {0x0F9D, 0, 2 | DECOMP_NO_COMPOSE, 873}, /* in exclusion list */
+ {0x0FA2, 0, 2 | DECOMP_NO_COMPOSE, 875}, /* in exclusion list */
+ {0x0FA7, 0, 2 | DECOMP_NO_COMPOSE, 877}, /* in exclusion list */
+ {0x0FAC, 0, 2 | DECOMP_NO_COMPOSE, 879}, /* in exclusion list */
+ {0x0FB9, 0, 2 | DECOMP_NO_COMPOSE, 881}, /* in exclusion list */
+ {0x0FC6, 220, 0, 0},
+ {0x1026, 0, 2, 883},
+ {0x1037, 7, 0, 0},
+ {0x1039, 9, 0, 0},
+ {0x103A, 9, 0, 0},
+ {0x108D, 220, 0, 0},
+ {0x10FC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x10DC},
+ {0x135D, 230, 0, 0},
+ {0x135E, 230, 0, 0},
+ {0x135F, 230, 0, 0},
+ {0x1714, 9, 0, 0},
+ {0x1734, 9, 0, 0},
+ {0x17D2, 9, 0, 0},
+ {0x17DD, 230, 0, 0},
+ {0x18A9, 228, 0, 0},
+ {0x1939, 222, 0, 0},
+ {0x193A, 230, 0, 0},
+ {0x193B, 220, 0, 0},
+ {0x1A17, 230, 0, 0},
+ {0x1A18, 220, 0, 0},
+ {0x1A60, 9, 0, 0},
+ {0x1A75, 230, 0, 0},
+ {0x1A76, 230, 0, 0},
+ {0x1A77, 230, 0, 0},
+ {0x1A78, 230, 0, 0},
+ {0x1A79, 230, 0, 0},
+ {0x1A7A, 230, 0, 0},
+ {0x1A7B, 230, 0, 0},
+ {0x1A7C, 230, 0, 0},
+ {0x1A7F, 220, 0, 0},
+ {0x1AB0, 230, 0, 0},
+ {0x1AB1, 230, 0, 0},
+ {0x1AB2, 230, 0, 0},
+ {0x1AB3, 230, 0, 0},
+ {0x1AB4, 230, 0, 0},
+ {0x1AB5, 220, 0, 0},
+ {0x1AB6, 220, 0, 0},
+ {0x1AB7, 220, 0, 0},
+ {0x1AB8, 220, 0, 0},
+ {0x1AB9, 220, 0, 0},
+ {0x1ABA, 220, 0, 0},
+ {0x1ABB, 230, 0, 0},
+ {0x1ABC, 230, 0, 0},
+ {0x1ABD, 220, 0, 0},
+ {0x1ABF, 220, 0, 0},
+ {0x1AC0, 220, 0, 0},
+ {0x1B06, 0, 2, 885},
+ {0x1B08, 0, 2, 887},
+ {0x1B0A, 0, 2, 889},
+ {0x1B0C, 0, 2, 891},
+ {0x1B0E, 0, 2, 893},
+ {0x1B12, 0, 2, 895},
+ {0x1B34, 7, 0, 0},
+ {0x1B3B, 0, 2, 897},
+ {0x1B3D, 0, 2, 899},
+ {0x1B40, 0, 2, 901},
+ {0x1B41, 0, 2, 903},
+ {0x1B43, 0, 2, 905},
+ {0x1B44, 9, 0, 0},
+ {0x1B6B, 230, 0, 0},
+ {0x1B6C, 220, 0, 0},
+ {0x1B6D, 230, 0, 0},
+ {0x1B6E, 230, 0, 0},
+ {0x1B6F, 230, 0, 0},
+ {0x1B70, 230, 0, 0},
+ {0x1B71, 230, 0, 0},
+ {0x1B72, 230, 0, 0},
+ {0x1B73, 230, 0, 0},
+ {0x1BAA, 9, 0, 0},
+ {0x1BAB, 9, 0, 0},
+ {0x1BE6, 7, 0, 0},
+ {0x1BF2, 9, 0, 0},
+ {0x1BF3, 9, 0, 0},
+ {0x1C37, 7, 0, 0},
+ {0x1CD0, 230, 0, 0},
+ {0x1CD1, 230, 0, 0},
+ {0x1CD2, 230, 0, 0},
+ {0x1CD4, 1, 0, 0},
+ {0x1CD5, 220, 0, 0},
+ {0x1CD6, 220, 0, 0},
+ {0x1CD7, 220, 0, 0},
+ {0x1CD8, 220, 0, 0},
+ {0x1CD9, 220, 0, 0},
+ {0x1CDA, 230, 0, 0},
+ {0x1CDB, 230, 0, 0},
+ {0x1CDC, 220, 0, 0},
+ {0x1CDD, 220, 0, 0},
+ {0x1CDE, 220, 0, 0},
+ {0x1CDF, 220, 0, 0},
+ {0x1CE0, 230, 0, 0},
+ {0x1CE2, 1, 0, 0},
+ {0x1CE3, 1, 0, 0},
+ {0x1CE4, 1, 0, 0},
+ {0x1CE5, 1, 0, 0},
+ {0x1CE6, 1, 0, 0},
+ {0x1CE7, 1, 0, 0},
+ {0x1CE8, 1, 0, 0},
+ {0x1CED, 220, 0, 0},
+ {0x1CF4, 230, 0, 0},
+ {0x1CF8, 230, 0, 0},
+ {0x1CF9, 230, 0, 0},
+ {0x1D2C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D2D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00C6},
+ {0x1D2E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D30, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D31, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D32, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x018E},
+ {0x1D33, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D34, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D35, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D36, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D37, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D38, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D39, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D3A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D3C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D3D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0222},
+ {0x1D3E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D3F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D40, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D41, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D42, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D43, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D44, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0250},
+ {0x1D45, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0251},
+ {0x1D46, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1D02},
+ {0x1D47, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D48, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D49, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D4A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0259},
+ {0x1D4B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x025B},
+ {0x1D4C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x025C},
+ {0x1D4D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D4F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D50, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D51, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x014B},
+ {0x1D52, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D53, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0254},
+ {0x1D54, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1D16},
+ {0x1D55, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1D17},
+ {0x1D56, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D57, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D58, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D59, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1D1D},
+ {0x1D5A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x026F},
+ {0x1D5B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D5C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1D25},
+ {0x1D5D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B2},
+ {0x1D5E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B3},
+ {0x1D5F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B4},
+ {0x1D60, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C6},
+ {0x1D61, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C7},
+ {0x1D62, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D63, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D64, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D65, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D66, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B2},
+ {0x1D67, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B3},
+ {0x1D68, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C1},
+ {0x1D69, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C6},
+ {0x1D6A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C7},
+ {0x1D78, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x043D},
+ {0x1D9B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0252},
+ {0x1D9C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D9D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0255},
+ {0x1D9E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00F0},
+ {0x1D9F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x025C},
+ {0x1DA0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1DA1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x025F},
+ {0x1DA2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0261},
+ {0x1DA3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0265},
+ {0x1DA4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0268},
+ {0x1DA5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0269},
+ {0x1DA6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x026A},
+ {0x1DA7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1D7B},
+ {0x1DA8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x029D},
+ {0x1DA9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x026D},
+ {0x1DAA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1D85},
+ {0x1DAB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x029F},
+ {0x1DAC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0271},
+ {0x1DAD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0270},
+ {0x1DAE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0272},
+ {0x1DAF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0273},
+ {0x1DB0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0274},
+ {0x1DB1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0275},
+ {0x1DB2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0278},
+ {0x1DB3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0282},
+ {0x1DB4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0283},
+ {0x1DB5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x01AB},
+ {0x1DB6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0289},
+ {0x1DB7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x028A},
+ {0x1DB8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1D1C},
+ {0x1DB9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x028B},
+ {0x1DBA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x028C},
+ {0x1DBB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1DBC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0290},
+ {0x1DBD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0291},
+ {0x1DBE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0292},
+ {0x1DBF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B8},
+ {0x1DC0, 230, 0, 0},
+ {0x1DC1, 230, 0, 0},
+ {0x1DC2, 220, 0, 0},
+ {0x1DC3, 230, 0, 0},
+ {0x1DC4, 230, 0, 0},
+ {0x1DC5, 230, 0, 0},
+ {0x1DC6, 230, 0, 0},
+ {0x1DC7, 230, 0, 0},
+ {0x1DC8, 230, 0, 0},
+ {0x1DC9, 230, 0, 0},
+ {0x1DCA, 220, 0, 0},
+ {0x1DCB, 230, 0, 0},
+ {0x1DCC, 230, 0, 0},
+ {0x1DCD, 234, 0, 0},
+ {0x1DCE, 214, 0, 0},
+ {0x1DCF, 220, 0, 0},
+ {0x1DD0, 202, 0, 0},
+ {0x1DD1, 230, 0, 0},
+ {0x1DD2, 230, 0, 0},
+ {0x1DD3, 230, 0, 0},
+ {0x1DD4, 230, 0, 0},
+ {0x1DD5, 230, 0, 0},
+ {0x1DD6, 230, 0, 0},
+ {0x1DD7, 230, 0, 0},
+ {0x1DD8, 230, 0, 0},
+ {0x1DD9, 230, 0, 0},
+ {0x1DDA, 230, 0, 0},
+ {0x1DDB, 230, 0, 0},
+ {0x1DDC, 230, 0, 0},
+ {0x1DDD, 230, 0, 0},
+ {0x1DDE, 230, 0, 0},
+ {0x1DDF, 230, 0, 0},
+ {0x1DE0, 230, 0, 0},
+ {0x1DE1, 230, 0, 0},
+ {0x1DE2, 230, 0, 0},
+ {0x1DE3, 230, 0, 0},
+ {0x1DE4, 230, 0, 0},
+ {0x1DE5, 230, 0, 0},
+ {0x1DE6, 230, 0, 0},
+ {0x1DE7, 230, 0, 0},
+ {0x1DE8, 230, 0, 0},
+ {0x1DE9, 230, 0, 0},
+ {0x1DEA, 230, 0, 0},
+ {0x1DEB, 230, 0, 0},
+ {0x1DEC, 230, 0, 0},
+ {0x1DED, 230, 0, 0},
+ {0x1DEE, 230, 0, 0},
+ {0x1DEF, 230, 0, 0},
+ {0x1DF0, 230, 0, 0},
+ {0x1DF1, 230, 0, 0},
+ {0x1DF2, 230, 0, 0},
+ {0x1DF3, 230, 0, 0},
+ {0x1DF4, 230, 0, 0},
+ {0x1DF5, 230, 0, 0},
+ {0x1DF6, 232, 0, 0},
+ {0x1DF7, 228, 0, 0},
+ {0x1DF8, 228, 0, 0},
+ {0x1DF9, 220, 0, 0},
+ {0x1DFB, 230, 0, 0},
+ {0x1DFC, 233, 0, 0},
+ {0x1DFD, 220, 0, 0},
+ {0x1DFE, 230, 0, 0},
+ {0x1DFF, 220, 0, 0},
+ {0x1E00, 0, 2, 907},
+ {0x1E01, 0, 2, 909},
+ {0x1E02, 0, 2, 911},
+ {0x1E03, 0, 2, 913},
+ {0x1E04, 0, 2, 915},
+ {0x1E05, 0, 2, 917},
+ {0x1E06, 0, 2, 919},
+ {0x1E07, 0, 2, 921},
+ {0x1E08, 0, 2, 923},
+ {0x1E09, 0, 2, 925},
+ {0x1E0A, 0, 2, 927},
+ {0x1E0B, 0, 2, 929},
+ {0x1E0C, 0, 2, 931},
+ {0x1E0D, 0, 2, 933},
+ {0x1E0E, 0, 2, 935},
+ {0x1E0F, 0, 2, 937},
+ {0x1E10, 0, 2, 939},
+ {0x1E11, 0, 2, 941},
+ {0x1E12, 0, 2, 943},
+ {0x1E13, 0, 2, 945},
+ {0x1E14, 0, 2, 947},
+ {0x1E15, 0, 2, 949},
+ {0x1E16, 0, 2, 951},
+ {0x1E17, 0, 2, 953},
+ {0x1E18, 0, 2, 955},
+ {0x1E19, 0, 2, 957},
+ {0x1E1A, 0, 2, 959},
+ {0x1E1B, 0, 2, 961},
+ {0x1E1C, 0, 2, 963},
+ {0x1E1D, 0, 2, 965},
+ {0x1E1E, 0, 2, 967},
+ {0x1E1F, 0, 2, 969},
+ {0x1E20, 0, 2, 971},
+ {0x1E21, 0, 2, 973},
+ {0x1E22, 0, 2, 975},
+ {0x1E23, 0, 2, 977},
+ {0x1E24, 0, 2, 979},
+ {0x1E25, 0, 2, 981},
+ {0x1E26, 0, 2, 983},
+ {0x1E27, 0, 2, 985},
+ {0x1E28, 0, 2, 987},
+ {0x1E29, 0, 2, 989},
+ {0x1E2A, 0, 2, 991},
+ {0x1E2B, 0, 2, 993},
+ {0x1E2C, 0, 2, 995},
+ {0x1E2D, 0, 2, 997},
+ {0x1E2E, 0, 2, 999},
+ {0x1E2F, 0, 2, 1001},
+ {0x1E30, 0, 2, 1003},
+ {0x1E31, 0, 2, 1005},
+ {0x1E32, 0, 2, 1007},
+ {0x1E33, 0, 2, 1009},
+ {0x1E34, 0, 2, 1011},
+ {0x1E35, 0, 2, 1013},
+ {0x1E36, 0, 2, 1015},
+ {0x1E37, 0, 2, 1017},
+ {0x1E38, 0, 2, 1019},
+ {0x1E39, 0, 2, 1021},
+ {0x1E3A, 0, 2, 1023},
+ {0x1E3B, 0, 2, 1025},
+ {0x1E3C, 0, 2, 1027},
+ {0x1E3D, 0, 2, 1029},
+ {0x1E3E, 0, 2, 1031},
+ {0x1E3F, 0, 2, 1033},
+ {0x1E40, 0, 2, 1035},
+ {0x1E41, 0, 2, 1037},
+ {0x1E42, 0, 2, 1039},
+ {0x1E43, 0, 2, 1041},
+ {0x1E44, 0, 2, 1043},
+ {0x1E45, 0, 2, 1045},
+ {0x1E46, 0, 2, 1047},
+ {0x1E47, 0, 2, 1049},
+ {0x1E48, 0, 2, 1051},
+ {0x1E49, 0, 2, 1053},
+ {0x1E4A, 0, 2, 1055},
+ {0x1E4B, 0, 2, 1057},
+ {0x1E4C, 0, 2, 1059},
+ {0x1E4D, 0, 2, 1061},
+ {0x1E4E, 0, 2, 1063},
+ {0x1E4F, 0, 2, 1065},
+ {0x1E50, 0, 2, 1067},
+ {0x1E51, 0, 2, 1069},
+ {0x1E52, 0, 2, 1071},
+ {0x1E53, 0, 2, 1073},
+ {0x1E54, 0, 2, 1075},
+ {0x1E55, 0, 2, 1077},
+ {0x1E56, 0, 2, 1079},
+ {0x1E57, 0, 2, 1081},
+ {0x1E58, 0, 2, 1083},
+ {0x1E59, 0, 2, 1085},
+ {0x1E5A, 0, 2, 1087},
+ {0x1E5B, 0, 2, 1089},
+ {0x1E5C, 0, 2, 1091},
+ {0x1E5D, 0, 2, 1093},
+ {0x1E5E, 0, 2, 1095},
+ {0x1E5F, 0, 2, 1097},
+ {0x1E60, 0, 2, 1099},
+ {0x1E61, 0, 2, 1101},
+ {0x1E62, 0, 2, 1103},
+ {0x1E63, 0, 2, 1105},
+ {0x1E64, 0, 2, 1107},
+ {0x1E65, 0, 2, 1109},
+ {0x1E66, 0, 2, 1111},
+ {0x1E67, 0, 2, 1113},
+ {0x1E68, 0, 2, 1115},
+ {0x1E69, 0, 2, 1117},
+ {0x1E6A, 0, 2, 1119},
+ {0x1E6B, 0, 2, 1121},
+ {0x1E6C, 0, 2, 1123},
+ {0x1E6D, 0, 2, 1125},
+ {0x1E6E, 0, 2, 1127},
+ {0x1E6F, 0, 2, 1129},
+ {0x1E70, 0, 2, 1131},
+ {0x1E71, 0, 2, 1133},
+ {0x1E72, 0, 2, 1135},
+ {0x1E73, 0, 2, 1137},
+ {0x1E74, 0, 2, 1139},
+ {0x1E75, 0, 2, 1141},
+ {0x1E76, 0, 2, 1143},
+ {0x1E77, 0, 2, 1145},
+ {0x1E78, 0, 2, 1147},
+ {0x1E79, 0, 2, 1149},
+ {0x1E7A, 0, 2, 1151},
+ {0x1E7B, 0, 2, 1153},
+ {0x1E7C, 0, 2, 1155},
+ {0x1E7D, 0, 2, 1157},
+ {0x1E7E, 0, 2, 1159},
+ {0x1E7F, 0, 2, 1161},
+ {0x1E80, 0, 2, 1163},
+ {0x1E81, 0, 2, 1165},
+ {0x1E82, 0, 2, 1167},
+ {0x1E83, 0, 2, 1169},
+ {0x1E84, 0, 2, 1171},
+ {0x1E85, 0, 2, 1173},
+ {0x1E86, 0, 2, 1175},
+ {0x1E87, 0, 2, 1177},
+ {0x1E88, 0, 2, 1179},
+ {0x1E89, 0, 2, 1181},
+ {0x1E8A, 0, 2, 1183},
+ {0x1E8B, 0, 2, 1185},
+ {0x1E8C, 0, 2, 1187},
+ {0x1E8D, 0, 2, 1189},
+ {0x1E8E, 0, 2, 1191},
+ {0x1E8F, 0, 2, 1193},
+ {0x1E90, 0, 2, 1195},
+ {0x1E91, 0, 2, 1197},
+ {0x1E92, 0, 2, 1199},
+ {0x1E93, 0, 2, 1201},
+ {0x1E94, 0, 2, 1203},
+ {0x1E95, 0, 2, 1205},
+ {0x1E96, 0, 2, 1207},
+ {0x1E97, 0, 2, 1209},
+ {0x1E98, 0, 2, 1211},
+ {0x1E99, 0, 2, 1213},
+ {0x1E9A, 0, 2 | DECOMP_COMPAT, 1215},
+ {0x1E9B, 0, 2, 1217},
+ {0x1EA0, 0, 2, 1219},
+ {0x1EA1, 0, 2, 1221},
+ {0x1EA2, 0, 2, 1223},
+ {0x1EA3, 0, 2, 1225},
+ {0x1EA4, 0, 2, 1227},
+ {0x1EA5, 0, 2, 1229},
+ {0x1EA6, 0, 2, 1231},
+ {0x1EA7, 0, 2, 1233},
+ {0x1EA8, 0, 2, 1235},
+ {0x1EA9, 0, 2, 1237},
+ {0x1EAA, 0, 2, 1239},
+ {0x1EAB, 0, 2, 1241},
+ {0x1EAC, 0, 2, 1243},
+ {0x1EAD, 0, 2, 1245},
+ {0x1EAE, 0, 2, 1247},
+ {0x1EAF, 0, 2, 1249},
+ {0x1EB0, 0, 2, 1251},
+ {0x1EB1, 0, 2, 1253},
+ {0x1EB2, 0, 2, 1255},
+ {0x1EB3, 0, 2, 1257},
+ {0x1EB4, 0, 2, 1259},
+ {0x1EB5, 0, 2, 1261},
+ {0x1EB6, 0, 2, 1263},
+ {0x1EB7, 0, 2, 1265},
+ {0x1EB8, 0, 2, 1267},
+ {0x1EB9, 0, 2, 1269},
+ {0x1EBA, 0, 2, 1271},
+ {0x1EBB, 0, 2, 1273},
+ {0x1EBC, 0, 2, 1275},
+ {0x1EBD, 0, 2, 1277},
+ {0x1EBE, 0, 2, 1279},
+ {0x1EBF, 0, 2, 1281},
+ {0x1EC0, 0, 2, 1283},
+ {0x1EC1, 0, 2, 1285},
+ {0x1EC2, 0, 2, 1287},
+ {0x1EC3, 0, 2, 1289},
+ {0x1EC4, 0, 2, 1291},
+ {0x1EC5, 0, 2, 1293},
+ {0x1EC6, 0, 2, 1295},
+ {0x1EC7, 0, 2, 1297},
+ {0x1EC8, 0, 2, 1299},
+ {0x1EC9, 0, 2, 1301},
+ {0x1ECA, 0, 2, 1303},
+ {0x1ECB, 0, 2, 1305},
+ {0x1ECC, 0, 2, 1307},
+ {0x1ECD, 0, 2, 1309},
+ {0x1ECE, 0, 2, 1311},
+ {0x1ECF, 0, 2, 1313},
+ {0x1ED0, 0, 2, 1315},
+ {0x1ED1, 0, 2, 1317},
+ {0x1ED2, 0, 2, 1319},
+ {0x1ED3, 0, 2, 1321},
+ {0x1ED4, 0, 2, 1323},
+ {0x1ED5, 0, 2, 1325},
+ {0x1ED6, 0, 2, 1327},
+ {0x1ED7, 0, 2, 1329},
+ {0x1ED8, 0, 2, 1331},
+ {0x1ED9, 0, 2, 1333},
+ {0x1EDA, 0, 2, 1335},
+ {0x1EDB, 0, 2, 1337},
+ {0x1EDC, 0, 2, 1339},
+ {0x1EDD, 0, 2, 1341},
+ {0x1EDE, 0, 2, 1343},
+ {0x1EDF, 0, 2, 1345},
+ {0x1EE0, 0, 2, 1347},
+ {0x1EE1, 0, 2, 1349},
+ {0x1EE2, 0, 2, 1351},
+ {0x1EE3, 0, 2, 1353},
+ {0x1EE4, 0, 2, 1355},
+ {0x1EE5, 0, 2, 1357},
+ {0x1EE6, 0, 2, 1359},
+ {0x1EE7, 0, 2, 1361},
+ {0x1EE8, 0, 2, 1363},
+ {0x1EE9, 0, 2, 1365},
+ {0x1EEA, 0, 2, 1367},
+ {0x1EEB, 0, 2, 1369},
+ {0x1EEC, 0, 2, 1371},
+ {0x1EED, 0, 2, 1373},
+ {0x1EEE, 0, 2, 1375},
+ {0x1EEF, 0, 2, 1377},
+ {0x1EF0, 0, 2, 1379},
+ {0x1EF1, 0, 2, 1381},
+ {0x1EF2, 0, 2, 1383},
+ {0x1EF3, 0, 2, 1385},
+ {0x1EF4, 0, 2, 1387},
+ {0x1EF5, 0, 2, 1389},
+ {0x1EF6, 0, 2, 1391},
+ {0x1EF7, 0, 2, 1393},
+ {0x1EF8, 0, 2, 1395},
+ {0x1EF9, 0, 2, 1397},
+ {0x1F00, 0, 2, 1399},
+ {0x1F01, 0, 2, 1401},
+ {0x1F02, 0, 2, 1403},
+ {0x1F03, 0, 2, 1405},
+ {0x1F04, 0, 2, 1407},
+ {0x1F05, 0, 2, 1409},
+ {0x1F06, 0, 2, 1411},
+ {0x1F07, 0, 2, 1413},
+ {0x1F08, 0, 2, 1415},
+ {0x1F09, 0, 2, 1417},
+ {0x1F0A, 0, 2, 1419},
+ {0x1F0B, 0, 2, 1421},
+ {0x1F0C, 0, 2, 1423},
+ {0x1F0D, 0, 2, 1425},
+ {0x1F0E, 0, 2, 1427},
+ {0x1F0F, 0, 2, 1429},
+ {0x1F10, 0, 2, 1431},
+ {0x1F11, 0, 2, 1433},
+ {0x1F12, 0, 2, 1435},
+ {0x1F13, 0, 2, 1437},
+ {0x1F14, 0, 2, 1439},
+ {0x1F15, 0, 2, 1441},
+ {0x1F18, 0, 2, 1443},
+ {0x1F19, 0, 2, 1445},
+ {0x1F1A, 0, 2, 1447},
+ {0x1F1B, 0, 2, 1449},
+ {0x1F1C, 0, 2, 1451},
+ {0x1F1D, 0, 2, 1453},
+ {0x1F20, 0, 2, 1455},
+ {0x1F21, 0, 2, 1457},
+ {0x1F22, 0, 2, 1459},
+ {0x1F23, 0, 2, 1461},
+ {0x1F24, 0, 2, 1463},
+ {0x1F25, 0, 2, 1465},
+ {0x1F26, 0, 2, 1467},
+ {0x1F27, 0, 2, 1469},
+ {0x1F28, 0, 2, 1471},
+ {0x1F29, 0, 2, 1473},
+ {0x1F2A, 0, 2, 1475},
+ {0x1F2B, 0, 2, 1477},
+ {0x1F2C, 0, 2, 1479},
+ {0x1F2D, 0, 2, 1481},
+ {0x1F2E, 0, 2, 1483},
+ {0x1F2F, 0, 2, 1485},
+ {0x1F30, 0, 2, 1487},
+ {0x1F31, 0, 2, 1489},
+ {0x1F32, 0, 2, 1491},
+ {0x1F33, 0, 2, 1493},
+ {0x1F34, 0, 2, 1495},
+ {0x1F35, 0, 2, 1497},
+ {0x1F36, 0, 2, 1499},
+ {0x1F37, 0, 2, 1501},
+ {0x1F38, 0, 2, 1503},
+ {0x1F39, 0, 2, 1505},
+ {0x1F3A, 0, 2, 1507},
+ {0x1F3B, 0, 2, 1509},
+ {0x1F3C, 0, 2, 1511},
+ {0x1F3D, 0, 2, 1513},
+ {0x1F3E, 0, 2, 1515},
+ {0x1F3F, 0, 2, 1517},
+ {0x1F40, 0, 2, 1519},
+ {0x1F41, 0, 2, 1521},
+ {0x1F42, 0, 2, 1523},
+ {0x1F43, 0, 2, 1525},
+ {0x1F44, 0, 2, 1527},
+ {0x1F45, 0, 2, 1529},
+ {0x1F48, 0, 2, 1531},
+ {0x1F49, 0, 2, 1533},
+ {0x1F4A, 0, 2, 1535},
+ {0x1F4B, 0, 2, 1537},
+ {0x1F4C, 0, 2, 1539},
+ {0x1F4D, 0, 2, 1541},
+ {0x1F50, 0, 2, 1543},
+ {0x1F51, 0, 2, 1545},
+ {0x1F52, 0, 2, 1547},
+ {0x1F53, 0, 2, 1549},
+ {0x1F54, 0, 2, 1551},
+ {0x1F55, 0, 2, 1553},
+ {0x1F56, 0, 2, 1555},
+ {0x1F57, 0, 2, 1557},
+ {0x1F59, 0, 2, 1559},
+ {0x1F5B, 0, 2, 1561},
+ {0x1F5D, 0, 2, 1563},
+ {0x1F5F, 0, 2, 1565},
+ {0x1F60, 0, 2, 1567},
+ {0x1F61, 0, 2, 1569},
+ {0x1F62, 0, 2, 1571},
+ {0x1F63, 0, 2, 1573},
+ {0x1F64, 0, 2, 1575},
+ {0x1F65, 0, 2, 1577},
+ {0x1F66, 0, 2, 1579},
+ {0x1F67, 0, 2, 1581},
+ {0x1F68, 0, 2, 1583},
+ {0x1F69, 0, 2, 1585},
+ {0x1F6A, 0, 2, 1587},
+ {0x1F6B, 0, 2, 1589},
+ {0x1F6C, 0, 2, 1591},
+ {0x1F6D, 0, 2, 1593},
+ {0x1F6E, 0, 2, 1595},
+ {0x1F6F, 0, 2, 1597},
+ {0x1F70, 0, 2, 1599},
+ {0x1F71, 0, 1 | DECOMP_INLINE, 0x03AC},
+ {0x1F72, 0, 2, 1601},
+ {0x1F73, 0, 1 | DECOMP_INLINE, 0x03AD},
+ {0x1F74, 0, 2, 1603},
+ {0x1F75, 0, 1 | DECOMP_INLINE, 0x03AE},
+ {0x1F76, 0, 2, 1605},
+ {0x1F77, 0, 1 | DECOMP_INLINE, 0x03AF},
+ {0x1F78, 0, 2, 1607},
+ {0x1F79, 0, 1 | DECOMP_INLINE, 0x03CC},
+ {0x1F7A, 0, 2, 1609},
+ {0x1F7B, 0, 1 | DECOMP_INLINE, 0x03CD},
+ {0x1F7C, 0, 2, 1611},
+ {0x1F7D, 0, 1 | DECOMP_INLINE, 0x03CE},
+ {0x1F80, 0, 2, 1613},
+ {0x1F81, 0, 2, 1615},
+ {0x1F82, 0, 2, 1617},
+ {0x1F83, 0, 2, 1619},
+ {0x1F84, 0, 2, 1621},
+ {0x1F85, 0, 2, 1623},
+ {0x1F86, 0, 2, 1625},
+ {0x1F87, 0, 2, 1627},
+ {0x1F88, 0, 2, 1629},
+ {0x1F89, 0, 2, 1631},
+ {0x1F8A, 0, 2, 1633},
+ {0x1F8B, 0, 2, 1635},
+ {0x1F8C, 0, 2, 1637},
+ {0x1F8D, 0, 2, 1639},
+ {0x1F8E, 0, 2, 1641},
+ {0x1F8F, 0, 2, 1643},
+ {0x1F90, 0, 2, 1645},
+ {0x1F91, 0, 2, 1647},
+ {0x1F92, 0, 2, 1649},
+ {0x1F93, 0, 2, 1651},
+ {0x1F94, 0, 2, 1653},
+ {0x1F95, 0, 2, 1655},
+ {0x1F96, 0, 2, 1657},
+ {0x1F97, 0, 2, 1659},
+ {0x1F98, 0, 2, 1661},
+ {0x1F99, 0, 2, 1663},
+ {0x1F9A, 0, 2, 1665},
+ {0x1F9B, 0, 2, 1667},
+ {0x1F9C, 0, 2, 1669},
+ {0x1F9D, 0, 2, 1671},
+ {0x1F9E, 0, 2, 1673},
+ {0x1F9F, 0, 2, 1675},
+ {0x1FA0, 0, 2, 1677},
+ {0x1FA1, 0, 2, 1679},
+ {0x1FA2, 0, 2, 1681},
+ {0x1FA3, 0, 2, 1683},
+ {0x1FA4, 0, 2, 1685},
+ {0x1FA5, 0, 2, 1687},
+ {0x1FA6, 0, 2, 1689},
+ {0x1FA7, 0, 2, 1691},
+ {0x1FA8, 0, 2, 1693},
+ {0x1FA9, 0, 2, 1695},
+ {0x1FAA, 0, 2, 1697},
+ {0x1FAB, 0, 2, 1699},
+ {0x1FAC, 0, 2, 1701},
+ {0x1FAD, 0, 2, 1703},
+ {0x1FAE, 0, 2, 1705},
+ {0x1FAF, 0, 2, 1707},
+ {0x1FB0, 0, 2, 1709},
+ {0x1FB1, 0, 2, 1711},
+ {0x1FB2, 0, 2, 1713},
+ {0x1FB3, 0, 2, 1715},
+ {0x1FB4, 0, 2, 1717},
+ {0x1FB6, 0, 2, 1719},
+ {0x1FB7, 0, 2, 1721},
+ {0x1FB8, 0, 2, 1723},
+ {0x1FB9, 0, 2, 1725},
+ {0x1FBA, 0, 2, 1727},
+ {0x1FBB, 0, 1 | DECOMP_INLINE, 0x0386},
+ {0x1FBC, 0, 2, 1729},
+ {0x1FBD, 0, 2 | DECOMP_COMPAT, 1731},
+ {0x1FBE, 0, 1 | DECOMP_INLINE, 0x03B9},
+ {0x1FBF, 0, 2 | DECOMP_COMPAT, 1733},
+ {0x1FC0, 0, 2 | DECOMP_COMPAT, 1735},
+ {0x1FC1, 0, 2, 1737},
+ {0x1FC2, 0, 2, 1739},
+ {0x1FC3, 0, 2, 1741},
+ {0x1FC4, 0, 2, 1743},
+ {0x1FC6, 0, 2, 1745},
+ {0x1FC7, 0, 2, 1747},
+ {0x1FC8, 0, 2, 1749},
+ {0x1FC9, 0, 1 | DECOMP_INLINE, 0x0388},
+ {0x1FCA, 0, 2, 1751},
+ {0x1FCB, 0, 1 | DECOMP_INLINE, 0x0389},
+ {0x1FCC, 0, 2, 1753},
+ {0x1FCD, 0, 2, 1755},
+ {0x1FCE, 0, 2, 1757},
+ {0x1FCF, 0, 2, 1759},
+ {0x1FD0, 0, 2, 1761},
+ {0x1FD1, 0, 2, 1763},
+ {0x1FD2, 0, 2, 1765},
+ {0x1FD3, 0, 1 | DECOMP_INLINE, 0x0390},
+ {0x1FD6, 0, 2, 1767},
+ {0x1FD7, 0, 2, 1769},
+ {0x1FD8, 0, 2, 1771},
+ {0x1FD9, 0, 2, 1773},
+ {0x1FDA, 0, 2, 1775},
+ {0x1FDB, 0, 1 | DECOMP_INLINE, 0x038A},
+ {0x1FDD, 0, 2, 1777},
+ {0x1FDE, 0, 2, 1779},
+ {0x1FDF, 0, 2, 1781},
+ {0x1FE0, 0, 2, 1783},
+ {0x1FE1, 0, 2, 1785},
+ {0x1FE2, 0, 2, 1787},
+ {0x1FE3, 0, 1 | DECOMP_INLINE, 0x03B0},
+ {0x1FE4, 0, 2, 1789},
+ {0x1FE5, 0, 2, 1791},
+ {0x1FE6, 0, 2, 1793},
+ {0x1FE7, 0, 2, 1795},
+ {0x1FE8, 0, 2, 1797},
+ {0x1FE9, 0, 2, 1799},
+ {0x1FEA, 0, 2, 1801},
+ {0x1FEB, 0, 1 | DECOMP_INLINE, 0x038E},
+ {0x1FEC, 0, 2, 1803},
+ {0x1FED, 0, 2, 1805},
+ {0x1FEE, 0, 1 | DECOMP_INLINE, 0x0385},
+ {0x1FEF, 0, 1 | DECOMP_INLINE, 0x0060},
+ {0x1FF2, 0, 2, 1807},
+ {0x1FF3, 0, 2, 1809},
+ {0x1FF4, 0, 2, 1811},
+ {0x1FF6, 0, 2, 1813},
+ {0x1FF7, 0, 2, 1815},
+ {0x1FF8, 0, 2, 1817},
+ {0x1FF9, 0, 1 | DECOMP_INLINE, 0x038C},
+ {0x1FFA, 0, 2, 1819},
+ {0x1FFB, 0, 1 | DECOMP_INLINE, 0x038F},
+ {0x1FFC, 0, 2, 1821},
+ {0x1FFD, 0, 1 | DECOMP_INLINE, 0x00B4},
+ {0x1FFE, 0, 2 | DECOMP_COMPAT, 1823},
+ {0x2000, 0, 1 | DECOMP_INLINE, 0x2002},
+ {0x2001, 0, 1 | DECOMP_INLINE, 0x2003},
+ {0x2002, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2003, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2004, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2005, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2006, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2007, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2008, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2009, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x200A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2011, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2010},
+ {0x2017, 0, 2 | DECOMP_COMPAT, 1825},
+ {0x2024, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002E},
+ {0x2025, 0, 2 | DECOMP_COMPAT, 1827},
+ {0x2026, 0, 3 | DECOMP_COMPAT, 1829},
+ {0x202F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2033, 0, 2 | DECOMP_COMPAT, 1832},
+ {0x2034, 0, 3 | DECOMP_COMPAT, 1834},
+ {0x2036, 0, 2 | DECOMP_COMPAT, 1837},
+ {0x2037, 0, 3 | DECOMP_COMPAT, 1839},
+ {0x203C, 0, 2 | DECOMP_COMPAT, 1842},
+ {0x203E, 0, 2 | DECOMP_COMPAT, 1844},
+ {0x2047, 0, 2 | DECOMP_COMPAT, 1846},
+ {0x2048, 0, 2 | DECOMP_COMPAT, 1848},
+ {0x2049, 0, 2 | DECOMP_COMPAT, 1850},
+ {0x2057, 0, 4 | DECOMP_COMPAT, 1852},
+ {0x205F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x2070, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0x2071, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x2074, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0x2075, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0x2076, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0x2077, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0x2078, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0x2079, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0x207A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002B},
+ {0x207B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2212},
+ {0x207C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003D},
+ {0x207D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0028},
+ {0x207E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0029},
+ {0x207F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x2080, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0x2081, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0x2082, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0x2083, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0x2084, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0x2085, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0x2086, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0x2087, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0x2088, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0x2089, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0x208A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002B},
+ {0x208B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2212},
+ {0x208C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003D},
+ {0x208D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0028},
+ {0x208E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0029},
+ {0x2090, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x2091, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x2092, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x2093, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x2094, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0259},
+ {0x2095, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x2096, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x2097, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x2098, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x2099, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x209A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x209B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x209C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x20A8, 0, 2 | DECOMP_COMPAT, 1856},
+ {0x20D0, 230, 0, 0},
+ {0x20D1, 230, 0, 0},
+ {0x20D2, 1, 0, 0},
+ {0x20D3, 1, 0, 0},
+ {0x20D4, 230, 0, 0},
+ {0x20D5, 230, 0, 0},
+ {0x20D6, 230, 0, 0},
+ {0x20D7, 230, 0, 0},
+ {0x20D8, 1, 0, 0},
+ {0x20D9, 1, 0, 0},
+ {0x20DA, 1, 0, 0},
+ {0x20DB, 230, 0, 0},
+ {0x20DC, 230, 0, 0},
+ {0x20E1, 230, 0, 0},
+ {0x20E5, 1, 0, 0},
+ {0x20E6, 1, 0, 0},
+ {0x20E7, 230, 0, 0},
+ {0x20E8, 220, 0, 0},
+ {0x20E9, 230, 0, 0},
+ {0x20EA, 1, 0, 0},
+ {0x20EB, 1, 0, 0},
+ {0x20EC, 220, 0, 0},
+ {0x20ED, 220, 0, 0},
+ {0x20EE, 220, 0, 0},
+ {0x20EF, 220, 0, 0},
+ {0x20F0, 230, 0, 0},
+ {0x2100, 0, 3 | DECOMP_COMPAT, 1858},
+ {0x2101, 0, 3 | DECOMP_COMPAT, 1861},
+ {0x2102, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x2103, 0, 2 | DECOMP_COMPAT, 1864},
+ {0x2105, 0, 3 | DECOMP_COMPAT, 1866},
+ {0x2106, 0, 3 | DECOMP_COMPAT, 1869},
+ {0x2107, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0190},
+ {0x2109, 0, 2 | DECOMP_COMPAT, 1872},
+ {0x210A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x210B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x210C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x210D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x210E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x210F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0127},
+ {0x2110, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x2111, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x2112, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x2113, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x2115, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x2116, 0, 2 | DECOMP_COMPAT, 1874},
+ {0x2119, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x211A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x211B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x211C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x211D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x2120, 0, 2 | DECOMP_COMPAT, 1876},
+ {0x2121, 0, 3 | DECOMP_COMPAT, 1878},
+ {0x2122, 0, 2 | DECOMP_COMPAT, 1881},
+ {0x2124, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x2126, 0, 1 | DECOMP_INLINE, 0x03A9},
+ {0x2128, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x212A, 0, 1 | DECOMP_INLINE, 0x004B},
+ {0x212B, 0, 1 | DECOMP_INLINE, 0x00C5},
+ {0x212C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x212D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x212F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x2130, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x2131, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x2133, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x2134, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x2135, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05D0},
+ {0x2136, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05D1},
+ {0x2137, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05D2},
+ {0x2138, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05D3},
+ {0x2139, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x213B, 0, 3 | DECOMP_COMPAT, 1883},
+ {0x213C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C0},
+ {0x213D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B3},
+ {0x213E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0393},
+ {0x213F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A0},
+ {0x2140, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2211},
+ {0x2145, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x2146, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x2147, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x2148, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x2149, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x2150, 0, 3 | DECOMP_COMPAT, 1886},
+ {0x2151, 0, 3 | DECOMP_COMPAT, 1889},
+ {0x2152, 0, 4 | DECOMP_COMPAT, 1892},
+ {0x2153, 0, 3 | DECOMP_COMPAT, 1896},
+ {0x2154, 0, 3 | DECOMP_COMPAT, 1899},
+ {0x2155, 0, 3 | DECOMP_COMPAT, 1902},
+ {0x2156, 0, 3 | DECOMP_COMPAT, 1905},
+ {0x2157, 0, 3 | DECOMP_COMPAT, 1908},
+ {0x2158, 0, 3 | DECOMP_COMPAT, 1911},
+ {0x2159, 0, 3 | DECOMP_COMPAT, 1914},
+ {0x215A, 0, 3 | DECOMP_COMPAT, 1917},
+ {0x215B, 0, 3 | DECOMP_COMPAT, 1920},
+ {0x215C, 0, 3 | DECOMP_COMPAT, 1923},
+ {0x215D, 0, 3 | DECOMP_COMPAT, 1926},
+ {0x215E, 0, 3 | DECOMP_COMPAT, 1929},
+ {0x215F, 0, 2 | DECOMP_COMPAT, 1932},
+ {0x2160, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x2161, 0, 2 | DECOMP_COMPAT, 1934},
+ {0x2162, 0, 3 | DECOMP_COMPAT, 1936},
+ {0x2163, 0, 2 | DECOMP_COMPAT, 1939},
+ {0x2164, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x2165, 0, 2 | DECOMP_COMPAT, 1941},
+ {0x2166, 0, 3 | DECOMP_COMPAT, 1943},
+ {0x2167, 0, 4 | DECOMP_COMPAT, 1946},
+ {0x2168, 0, 2 | DECOMP_COMPAT, 1950},
+ {0x2169, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x216A, 0, 2 | DECOMP_COMPAT, 1952},
+ {0x216B, 0, 3 | DECOMP_COMPAT, 1954},
+ {0x216C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x216D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x216E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x216F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x2170, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x2171, 0, 2 | DECOMP_COMPAT, 1957},
+ {0x2172, 0, 3 | DECOMP_COMPAT, 1959},
+ {0x2173, 0, 2 | DECOMP_COMPAT, 1962},
+ {0x2174, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x2175, 0, 2 | DECOMP_COMPAT, 1964},
+ {0x2176, 0, 3 | DECOMP_COMPAT, 1966},
+ {0x2177, 0, 4 | DECOMP_COMPAT, 1969},
+ {0x2178, 0, 2 | DECOMP_COMPAT, 1973},
+ {0x2179, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x217A, 0, 2 | DECOMP_COMPAT, 1975},
+ {0x217B, 0, 3 | DECOMP_COMPAT, 1977},
+ {0x217C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x217D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x217E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x217F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x2189, 0, 3 | DECOMP_COMPAT, 1980},
+ {0x219A, 0, 2, 1983},
+ {0x219B, 0, 2, 1985},
+ {0x21AE, 0, 2, 1987},
+ {0x21CD, 0, 2, 1989},
+ {0x21CE, 0, 2, 1991},
+ {0x21CF, 0, 2, 1993},
+ {0x2204, 0, 2, 1995},
+ {0x2209, 0, 2, 1997},
+ {0x220C, 0, 2, 1999},
+ {0x2224, 0, 2, 2001},
+ {0x2226, 0, 2, 2003},
+ {0x222C, 0, 2 | DECOMP_COMPAT, 2005},
+ {0x222D, 0, 3 | DECOMP_COMPAT, 2007},
+ {0x222F, 0, 2 | DECOMP_COMPAT, 2010},
+ {0x2230, 0, 3 | DECOMP_COMPAT, 2012},
+ {0x2241, 0, 2, 2015},
+ {0x2244, 0, 2, 2017},
+ {0x2247, 0, 2, 2019},
+ {0x2249, 0, 2, 2021},
+ {0x2260, 0, 2, 2023},
+ {0x2262, 0, 2, 2025},
+ {0x226D, 0, 2, 2027},
+ {0x226E, 0, 2, 2029},
+ {0x226F, 0, 2, 2031},
+ {0x2270, 0, 2, 2033},
+ {0x2271, 0, 2, 2035},
+ {0x2274, 0, 2, 2037},
+ {0x2275, 0, 2, 2039},
+ {0x2278, 0, 2, 2041},
+ {0x2279, 0, 2, 2043},
+ {0x2280, 0, 2, 2045},
+ {0x2281, 0, 2, 2047},
+ {0x2284, 0, 2, 2049},
+ {0x2285, 0, 2, 2051},
+ {0x2288, 0, 2, 2053},
+ {0x2289, 0, 2, 2055},
+ {0x22AC, 0, 2, 2057},
+ {0x22AD, 0, 2, 2059},
+ {0x22AE, 0, 2, 2061},
+ {0x22AF, 0, 2, 2063},
+ {0x22E0, 0, 2, 2065},
+ {0x22E1, 0, 2, 2067},
+ {0x22E2, 0, 2, 2069},
+ {0x22E3, 0, 2, 2071},
+ {0x22EA, 0, 2, 2073},
+ {0x22EB, 0, 2, 2075},
+ {0x22EC, 0, 2, 2077},
+ {0x22ED, 0, 2, 2079},
+ {0x2329, 0, 1 | DECOMP_INLINE, 0x3008},
+ {0x232A, 0, 1 | DECOMP_INLINE, 0x3009},
+ {0x2460, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0x2461, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0x2462, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0x2463, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0x2464, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0x2465, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0x2466, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0x2467, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0x2468, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0x2469, 0, 2 | DECOMP_COMPAT, 2081},
+ {0x246A, 0, 2 | DECOMP_COMPAT, 2083},
+ {0x246B, 0, 2 | DECOMP_COMPAT, 2085},
+ {0x246C, 0, 2 | DECOMP_COMPAT, 2087},
+ {0x246D, 0, 2 | DECOMP_COMPAT, 2089},
+ {0x246E, 0, 2 | DECOMP_COMPAT, 2091},
+ {0x246F, 0, 2 | DECOMP_COMPAT, 2093},
+ {0x2470, 0, 2 | DECOMP_COMPAT, 2095},
+ {0x2471, 0, 2 | DECOMP_COMPAT, 2097},
+ {0x2472, 0, 2 | DECOMP_COMPAT, 2099},
+ {0x2473, 0, 2 | DECOMP_COMPAT, 2101},
+ {0x2474, 0, 3 | DECOMP_COMPAT, 2103},
+ {0x2475, 0, 3 | DECOMP_COMPAT, 2106},
+ {0x2476, 0, 3 | DECOMP_COMPAT, 2109},
+ {0x2477, 0, 3 | DECOMP_COMPAT, 2112},
+ {0x2478, 0, 3 | DECOMP_COMPAT, 2115},
+ {0x2479, 0, 3 | DECOMP_COMPAT, 2118},
+ {0x247A, 0, 3 | DECOMP_COMPAT, 2121},
+ {0x247B, 0, 3 | DECOMP_COMPAT, 2124},
+ {0x247C, 0, 3 | DECOMP_COMPAT, 2127},
+ {0x247D, 0, 4 | DECOMP_COMPAT, 2130},
+ {0x247E, 0, 4 | DECOMP_COMPAT, 2134},
+ {0x247F, 0, 4 | DECOMP_COMPAT, 2138},
+ {0x2480, 0, 4 | DECOMP_COMPAT, 2142},
+ {0x2481, 0, 4 | DECOMP_COMPAT, 2146},
+ {0x2482, 0, 4 | DECOMP_COMPAT, 2150},
+ {0x2483, 0, 4 | DECOMP_COMPAT, 2154},
+ {0x2484, 0, 4 | DECOMP_COMPAT, 2158},
+ {0x2485, 0, 4 | DECOMP_COMPAT, 2162},
+ {0x2486, 0, 4 | DECOMP_COMPAT, 2166},
+ {0x2487, 0, 4 | DECOMP_COMPAT, 2170},
+ {0x2488, 0, 2 | DECOMP_COMPAT, 2174},
+ {0x2489, 0, 2 | DECOMP_COMPAT, 2176},
+ {0x248A, 0, 2 | DECOMP_COMPAT, 2178},
+ {0x248B, 0, 2 | DECOMP_COMPAT, 2180},
+ {0x248C, 0, 2 | DECOMP_COMPAT, 2182},
+ {0x248D, 0, 2 | DECOMP_COMPAT, 2184},
+ {0x248E, 0, 2 | DECOMP_COMPAT, 2186},
+ {0x248F, 0, 2 | DECOMP_COMPAT, 2188},
+ {0x2490, 0, 2 | DECOMP_COMPAT, 2190},
+ {0x2491, 0, 3 | DECOMP_COMPAT, 2192},
+ {0x2492, 0, 3 | DECOMP_COMPAT, 2195},
+ {0x2493, 0, 3 | DECOMP_COMPAT, 2198},
+ {0x2494, 0, 3 | DECOMP_COMPAT, 2201},
+ {0x2495, 0, 3 | DECOMP_COMPAT, 2204},
+ {0x2496, 0, 3 | DECOMP_COMPAT, 2207},
+ {0x2497, 0, 3 | DECOMP_COMPAT, 2210},
+ {0x2498, 0, 3 | DECOMP_COMPAT, 2213},
+ {0x2499, 0, 3 | DECOMP_COMPAT, 2216},
+ {0x249A, 0, 3 | DECOMP_COMPAT, 2219},
+ {0x249B, 0, 3 | DECOMP_COMPAT, 2222},
+ {0x249C, 0, 3 | DECOMP_COMPAT, 2225},
+ {0x249D, 0, 3 | DECOMP_COMPAT, 2228},
+ {0x249E, 0, 3 | DECOMP_COMPAT, 2231},
+ {0x249F, 0, 3 | DECOMP_COMPAT, 2234},
+ {0x24A0, 0, 3 | DECOMP_COMPAT, 2237},
+ {0x24A1, 0, 3 | DECOMP_COMPAT, 2240},
+ {0x24A2, 0, 3 | DECOMP_COMPAT, 2243},
+ {0x24A3, 0, 3 | DECOMP_COMPAT, 2246},
+ {0x24A4, 0, 3 | DECOMP_COMPAT, 2249},
+ {0x24A5, 0, 3 | DECOMP_COMPAT, 2252},
+ {0x24A6, 0, 3 | DECOMP_COMPAT, 2255},
+ {0x24A7, 0, 3 | DECOMP_COMPAT, 2258},
+ {0x24A8, 0, 3 | DECOMP_COMPAT, 2261},
+ {0x24A9, 0, 3 | DECOMP_COMPAT, 2264},
+ {0x24AA, 0, 3 | DECOMP_COMPAT, 2267},
+ {0x24AB, 0, 3 | DECOMP_COMPAT, 2270},
+ {0x24AC, 0, 3 | DECOMP_COMPAT, 2273},
+ {0x24AD, 0, 3 | DECOMP_COMPAT, 2276},
+ {0x24AE, 0, 3 | DECOMP_COMPAT, 2279},
+ {0x24AF, 0, 3 | DECOMP_COMPAT, 2282},
+ {0x24B0, 0, 3 | DECOMP_COMPAT, 2285},
+ {0x24B1, 0, 3 | DECOMP_COMPAT, 2288},
+ {0x24B2, 0, 3 | DECOMP_COMPAT, 2291},
+ {0x24B3, 0, 3 | DECOMP_COMPAT, 2294},
+ {0x24B4, 0, 3 | DECOMP_COMPAT, 2297},
+ {0x24B5, 0, 3 | DECOMP_COMPAT, 2300},
+ {0x24B6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x24B7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x24B8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x24B9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x24BA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x24BB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x24BC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x24BD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x24BE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x24BF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x24C0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x24C1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x24C2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x24C3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x24C4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x24C5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x24C6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x24C7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x24C8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x24C9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x24CA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x24CB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x24CC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x24CD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x24CE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x24CF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x24D0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x24D1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x24D2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x24D3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x24D4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x24D5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x24D6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x24D7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x24D8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x24D9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x24DA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x24DB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x24DC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x24DD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x24DE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x24DF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x24E0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x24E1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x24E2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x24E3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x24E4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x24E5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x24E6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x24E7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x24E8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x24E9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x24EA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0x2A0C, 0, 4 | DECOMP_COMPAT, 2303},
+ {0x2A74, 0, 3 | DECOMP_COMPAT, 2307},
+ {0x2A75, 0, 2 | DECOMP_COMPAT, 2310},
+ {0x2A76, 0, 3 | DECOMP_COMPAT, 2312},
+ {0x2ADC, 0, 2 | DECOMP_NO_COMPOSE, 2315}, /* in exclusion list */
+ {0x2C7C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x2C7D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x2CEF, 230, 0, 0},
+ {0x2CF0, 230, 0, 0},
+ {0x2CF1, 230, 0, 0},
+ {0x2D6F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2D61},
+ {0x2D7F, 9, 0, 0},
+ {0x2DE0, 230, 0, 0},
+ {0x2DE1, 230, 0, 0},
+ {0x2DE2, 230, 0, 0},
+ {0x2DE3, 230, 0, 0},
+ {0x2DE4, 230, 0, 0},
+ {0x2DE5, 230, 0, 0},
+ {0x2DE6, 230, 0, 0},
+ {0x2DE7, 230, 0, 0},
+ {0x2DE8, 230, 0, 0},
+ {0x2DE9, 230, 0, 0},
+ {0x2DEA, 230, 0, 0},
+ {0x2DEB, 230, 0, 0},
+ {0x2DEC, 230, 0, 0},
+ {0x2DED, 230, 0, 0},
+ {0x2DEE, 230, 0, 0},
+ {0x2DEF, 230, 0, 0},
+ {0x2DF0, 230, 0, 0},
+ {0x2DF1, 230, 0, 0},
+ {0x2DF2, 230, 0, 0},
+ {0x2DF3, 230, 0, 0},
+ {0x2DF4, 230, 0, 0},
+ {0x2DF5, 230, 0, 0},
+ {0x2DF6, 230, 0, 0},
+ {0x2DF7, 230, 0, 0},
+ {0x2DF8, 230, 0, 0},
+ {0x2DF9, 230, 0, 0},
+ {0x2DFA, 230, 0, 0},
+ {0x2DFB, 230, 0, 0},
+ {0x2DFC, 230, 0, 0},
+ {0x2DFD, 230, 0, 0},
+ {0x2DFE, 230, 0, 0},
+ {0x2DFF, 230, 0, 0},
+ {0x2E9F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6BCD},
+ {0x2EF3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9F9F},
+ {0x2F00, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E00},
+ {0x2F01, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E28},
+ {0x2F02, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E36},
+ {0x2F03, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E3F},
+ {0x2F04, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E59},
+ {0x2F05, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E85},
+ {0x2F06, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E8C},
+ {0x2F07, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4EA0},
+ {0x2F08, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4EBA},
+ {0x2F09, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x513F},
+ {0x2F0A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5165},
+ {0x2F0B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x516B},
+ {0x2F0C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5182},
+ {0x2F0D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5196},
+ {0x2F0E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x51AB},
+ {0x2F0F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x51E0},
+ {0x2F10, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x51F5},
+ {0x2F11, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5200},
+ {0x2F12, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x529B},
+ {0x2F13, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x52F9},
+ {0x2F14, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5315},
+ {0x2F15, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x531A},
+ {0x2F16, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5338},
+ {0x2F17, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5341},
+ {0x2F18, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x535C},
+ {0x2F19, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5369},
+ {0x2F1A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5382},
+ {0x2F1B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x53B6},
+ {0x2F1C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x53C8},
+ {0x2F1D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x53E3},
+ {0x2F1E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x56D7},
+ {0x2F1F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x571F},
+ {0x2F20, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x58EB},
+ {0x2F21, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5902},
+ {0x2F22, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x590A},
+ {0x2F23, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5915},
+ {0x2F24, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5927},
+ {0x2F25, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5973},
+ {0x2F26, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5B50},
+ {0x2F27, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5B80},
+ {0x2F28, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5BF8},
+ {0x2F29, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5C0F},
+ {0x2F2A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5C22},
+ {0x2F2B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5C38},
+ {0x2F2C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5C6E},
+ {0x2F2D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5C71},
+ {0x2F2E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5DDB},
+ {0x2F2F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5DE5},
+ {0x2F30, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5DF1},
+ {0x2F31, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5DFE},
+ {0x2F32, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5E72},
+ {0x2F33, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5E7A},
+ {0x2F34, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5E7F},
+ {0x2F35, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5EF4},
+ {0x2F36, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5EFE},
+ {0x2F37, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5F0B},
+ {0x2F38, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5F13},
+ {0x2F39, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5F50},
+ {0x2F3A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5F61},
+ {0x2F3B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5F73},
+ {0x2F3C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5FC3},
+ {0x2F3D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6208},
+ {0x2F3E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6236},
+ {0x2F3F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x624B},
+ {0x2F40, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x652F},
+ {0x2F41, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6534},
+ {0x2F42, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6587},
+ {0x2F43, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6597},
+ {0x2F44, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x65A4},
+ {0x2F45, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x65B9},
+ {0x2F46, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x65E0},
+ {0x2F47, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x65E5},
+ {0x2F48, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x66F0},
+ {0x2F49, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6708},
+ {0x2F4A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6728},
+ {0x2F4B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6B20},
+ {0x2F4C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6B62},
+ {0x2F4D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6B79},
+ {0x2F4E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6BB3},
+ {0x2F4F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6BCB},
+ {0x2F50, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6BD4},
+ {0x2F51, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6BDB},
+ {0x2F52, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6C0F},
+ {0x2F53, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6C14},
+ {0x2F54, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6C34},
+ {0x2F55, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x706B},
+ {0x2F56, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x722A},
+ {0x2F57, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7236},
+ {0x2F58, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x723B},
+ {0x2F59, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x723F},
+ {0x2F5A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7247},
+ {0x2F5B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7259},
+ {0x2F5C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x725B},
+ {0x2F5D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x72AC},
+ {0x2F5E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7384},
+ {0x2F5F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7389},
+ {0x2F60, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x74DC},
+ {0x2F61, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x74E6},
+ {0x2F62, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7518},
+ {0x2F63, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x751F},
+ {0x2F64, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7528},
+ {0x2F65, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7530},
+ {0x2F66, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x758B},
+ {0x2F67, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7592},
+ {0x2F68, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7676},
+ {0x2F69, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x767D},
+ {0x2F6A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x76AE},
+ {0x2F6B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x76BF},
+ {0x2F6C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x76EE},
+ {0x2F6D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x77DB},
+ {0x2F6E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x77E2},
+ {0x2F6F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x77F3},
+ {0x2F70, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x793A},
+ {0x2F71, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x79B8},
+ {0x2F72, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x79BE},
+ {0x2F73, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7A74},
+ {0x2F74, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7ACB},
+ {0x2F75, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7AF9},
+ {0x2F76, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7C73},
+ {0x2F77, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7CF8},
+ {0x2F78, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7F36},
+ {0x2F79, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7F51},
+ {0x2F7A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7F8A},
+ {0x2F7B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7FBD},
+ {0x2F7C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8001},
+ {0x2F7D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x800C},
+ {0x2F7E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8012},
+ {0x2F7F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8033},
+ {0x2F80, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x807F},
+ {0x2F81, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8089},
+ {0x2F82, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x81E3},
+ {0x2F83, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x81EA},
+ {0x2F84, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x81F3},
+ {0x2F85, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x81FC},
+ {0x2F86, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x820C},
+ {0x2F87, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x821B},
+ {0x2F88, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x821F},
+ {0x2F89, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x826E},
+ {0x2F8A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8272},
+ {0x2F8B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8278},
+ {0x2F8C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x864D},
+ {0x2F8D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x866B},
+ {0x2F8E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8840},
+ {0x2F8F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x884C},
+ {0x2F90, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8863},
+ {0x2F91, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x897E},
+ {0x2F92, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x898B},
+ {0x2F93, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x89D2},
+ {0x2F94, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8A00},
+ {0x2F95, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8C37},
+ {0x2F96, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8C46},
+ {0x2F97, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8C55},
+ {0x2F98, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8C78},
+ {0x2F99, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8C9D},
+ {0x2F9A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8D64},
+ {0x2F9B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8D70},
+ {0x2F9C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8DB3},
+ {0x2F9D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8EAB},
+ {0x2F9E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8ECA},
+ {0x2F9F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8F9B},
+ {0x2FA0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8FB0},
+ {0x2FA1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8FB5},
+ {0x2FA2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9091},
+ {0x2FA3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9149},
+ {0x2FA4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x91C6},
+ {0x2FA5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x91CC},
+ {0x2FA6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x91D1},
+ {0x2FA7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9577},
+ {0x2FA8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9580},
+ {0x2FA9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x961C},
+ {0x2FAA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x96B6},
+ {0x2FAB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x96B9},
+ {0x2FAC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x96E8},
+ {0x2FAD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9751},
+ {0x2FAE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x975E},
+ {0x2FAF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9762},
+ {0x2FB0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9769},
+ {0x2FB1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x97CB},
+ {0x2FB2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x97ED},
+ {0x2FB3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x97F3},
+ {0x2FB4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9801},
+ {0x2FB5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x98A8},
+ {0x2FB6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x98DB},
+ {0x2FB7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x98DF},
+ {0x2FB8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9996},
+ {0x2FB9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9999},
+ {0x2FBA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x99AC},
+ {0x2FBB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9AA8},
+ {0x2FBC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9AD8},
+ {0x2FBD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9ADF},
+ {0x2FBE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9B25},
+ {0x2FBF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9B2F},
+ {0x2FC0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9B32},
+ {0x2FC1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9B3C},
+ {0x2FC2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9B5A},
+ {0x2FC3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9CE5},
+ {0x2FC4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9E75},
+ {0x2FC5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9E7F},
+ {0x2FC6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9EA5},
+ {0x2FC7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9EBB},
+ {0x2FC8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9EC3},
+ {0x2FC9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9ECD},
+ {0x2FCA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9ED1},
+ {0x2FCB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9EF9},
+ {0x2FCC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9EFD},
+ {0x2FCD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9F0E},
+ {0x2FCE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9F13},
+ {0x2FCF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9F20},
+ {0x2FD0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9F3B},
+ {0x2FD1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9F4A},
+ {0x2FD2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9F52},
+ {0x2FD3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9F8D},
+ {0x2FD4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9F9C},
+ {0x2FD5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9FA0},
+ {0x3000, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0020},
+ {0x302A, 218, 0, 0},
+ {0x302B, 228, 0, 0},
+ {0x302C, 232, 0, 0},
+ {0x302D, 222, 0, 0},
+ {0x302E, 224, 0, 0},
+ {0x302F, 224, 0, 0},
+ {0x3036, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3012},
+ {0x3038, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5341},
+ {0x3039, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5344},
+ {0x303A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5345},
+ {0x304C, 0, 2, 2317},
+ {0x304E, 0, 2, 2319},
+ {0x3050, 0, 2, 2321},
+ {0x3052, 0, 2, 2323},
+ {0x3054, 0, 2, 2325},
+ {0x3056, 0, 2, 2327},
+ {0x3058, 0, 2, 2329},
+ {0x305A, 0, 2, 2331},
+ {0x305C, 0, 2, 2333},
+ {0x305E, 0, 2, 2335},
+ {0x3060, 0, 2, 2337},
+ {0x3062, 0, 2, 2339},
+ {0x3065, 0, 2, 2341},
+ {0x3067, 0, 2, 2343},
+ {0x3069, 0, 2, 2345},
+ {0x3070, 0, 2, 2347},
+ {0x3071, 0, 2, 2349},
+ {0x3073, 0, 2, 2351},
+ {0x3074, 0, 2, 2353},
+ {0x3076, 0, 2, 2355},
+ {0x3077, 0, 2, 2357},
+ {0x3079, 0, 2, 2359},
+ {0x307A, 0, 2, 2361},
+ {0x307C, 0, 2, 2363},
+ {0x307D, 0, 2, 2365},
+ {0x3094, 0, 2, 2367},
+ {0x3099, 8, 0, 0},
+ {0x309A, 8, 0, 0},
+ {0x309B, 0, 2 | DECOMP_COMPAT, 2369},
+ {0x309C, 0, 2 | DECOMP_COMPAT, 2371},
+ {0x309E, 0, 2, 2373},
+ {0x309F, 0, 2 | DECOMP_COMPAT, 2375},
+ {0x30AC, 0, 2, 2377},
+ {0x30AE, 0, 2, 2379},
+ {0x30B0, 0, 2, 2381},
+ {0x30B2, 0, 2, 2383},
+ {0x30B4, 0, 2, 2385},
+ {0x30B6, 0, 2, 2387},
+ {0x30B8, 0, 2, 2389},
+ {0x30BA, 0, 2, 2391},
+ {0x30BC, 0, 2, 2393},
+ {0x30BE, 0, 2, 2395},
+ {0x30C0, 0, 2, 2397},
+ {0x30C2, 0, 2, 2399},
+ {0x30C5, 0, 2, 2401},
+ {0x30C7, 0, 2, 2403},
+ {0x30C9, 0, 2, 2405},
+ {0x30D0, 0, 2, 2407},
+ {0x30D1, 0, 2, 2409},
+ {0x30D3, 0, 2, 2411},
+ {0x30D4, 0, 2, 2413},
+ {0x30D6, 0, 2, 2415},
+ {0x30D7, 0, 2, 2417},
+ {0x30D9, 0, 2, 2419},
+ {0x30DA, 0, 2, 2421},
+ {0x30DC, 0, 2, 2423},
+ {0x30DD, 0, 2, 2425},
+ {0x30F4, 0, 2, 2427},
+ {0x30F7, 0, 2, 2429},
+ {0x30F8, 0, 2, 2431},
+ {0x30F9, 0, 2, 2433},
+ {0x30FA, 0, 2, 2435},
+ {0x30FE, 0, 2, 2437},
+ {0x30FF, 0, 2 | DECOMP_COMPAT, 2439},
+ {0x3131, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1100},
+ {0x3132, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1101},
+ {0x3133, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11AA},
+ {0x3134, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1102},
+ {0x3135, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11AC},
+ {0x3136, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11AD},
+ {0x3137, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1103},
+ {0x3138, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1104},
+ {0x3139, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1105},
+ {0x313A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11B0},
+ {0x313B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11B1},
+ {0x313C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11B2},
+ {0x313D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11B3},
+ {0x313E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11B4},
+ {0x313F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11B5},
+ {0x3140, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x111A},
+ {0x3141, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1106},
+ {0x3142, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1107},
+ {0x3143, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1108},
+ {0x3144, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1121},
+ {0x3145, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1109},
+ {0x3146, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110A},
+ {0x3147, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110B},
+ {0x3148, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110C},
+ {0x3149, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110D},
+ {0x314A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110E},
+ {0x314B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110F},
+ {0x314C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1110},
+ {0x314D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1111},
+ {0x314E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1112},
+ {0x314F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1161},
+ {0x3150, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1162},
+ {0x3151, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1163},
+ {0x3152, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1164},
+ {0x3153, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1165},
+ {0x3154, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1166},
+ {0x3155, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1167},
+ {0x3156, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1168},
+ {0x3157, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1169},
+ {0x3158, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x116A},
+ {0x3159, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x116B},
+ {0x315A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x116C},
+ {0x315B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x116D},
+ {0x315C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x116E},
+ {0x315D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x116F},
+ {0x315E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1170},
+ {0x315F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1171},
+ {0x3160, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1172},
+ {0x3161, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1173},
+ {0x3162, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1174},
+ {0x3163, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1175},
+ {0x3164, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1160},
+ {0x3165, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1114},
+ {0x3166, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1115},
+ {0x3167, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11C7},
+ {0x3168, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11C8},
+ {0x3169, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11CC},
+ {0x316A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11CE},
+ {0x316B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11D3},
+ {0x316C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11D7},
+ {0x316D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11D9},
+ {0x316E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x111C},
+ {0x316F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11DD},
+ {0x3170, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11DF},
+ {0x3171, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x111D},
+ {0x3172, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x111E},
+ {0x3173, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1120},
+ {0x3174, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1122},
+ {0x3175, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1123},
+ {0x3176, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1127},
+ {0x3177, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1129},
+ {0x3178, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x112B},
+ {0x3179, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x112C},
+ {0x317A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x112D},
+ {0x317B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x112E},
+ {0x317C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x112F},
+ {0x317D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1132},
+ {0x317E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1136},
+ {0x317F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1140},
+ {0x3180, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1147},
+ {0x3181, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x114C},
+ {0x3182, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11F1},
+ {0x3183, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11F2},
+ {0x3184, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1157},
+ {0x3185, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1158},
+ {0x3186, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1159},
+ {0x3187, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1184},
+ {0x3188, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1185},
+ {0x3189, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1188},
+ {0x318A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1191},
+ {0x318B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1192},
+ {0x318C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1194},
+ {0x318D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x119E},
+ {0x318E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x11A1},
+ {0x3192, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E00},
+ {0x3193, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E8C},
+ {0x3194, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E09},
+ {0x3195, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x56DB},
+ {0x3196, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E0A},
+ {0x3197, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E2D},
+ {0x3198, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E0B},
+ {0x3199, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7532},
+ {0x319A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E59},
+ {0x319B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E19},
+ {0x319C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E01},
+ {0x319D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5929},
+ {0x319E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5730},
+ {0x319F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4EBA},
+ {0x3200, 0, 3 | DECOMP_COMPAT, 2441},
+ {0x3201, 0, 3 | DECOMP_COMPAT, 2444},
+ {0x3202, 0, 3 | DECOMP_COMPAT, 2447},
+ {0x3203, 0, 3 | DECOMP_COMPAT, 2450},
+ {0x3204, 0, 3 | DECOMP_COMPAT, 2453},
+ {0x3205, 0, 3 | DECOMP_COMPAT, 2456},
+ {0x3206, 0, 3 | DECOMP_COMPAT, 2459},
+ {0x3207, 0, 3 | DECOMP_COMPAT, 2462},
+ {0x3208, 0, 3 | DECOMP_COMPAT, 2465},
+ {0x3209, 0, 3 | DECOMP_COMPAT, 2468},
+ {0x320A, 0, 3 | DECOMP_COMPAT, 2471},
+ {0x320B, 0, 3 | DECOMP_COMPAT, 2474},
+ {0x320C, 0, 3 | DECOMP_COMPAT, 2477},
+ {0x320D, 0, 3 | DECOMP_COMPAT, 2480},
+ {0x320E, 0, 4 | DECOMP_COMPAT, 2483},
+ {0x320F, 0, 4 | DECOMP_COMPAT, 2487},
+ {0x3210, 0, 4 | DECOMP_COMPAT, 2491},
+ {0x3211, 0, 4 | DECOMP_COMPAT, 2495},
+ {0x3212, 0, 4 | DECOMP_COMPAT, 2499},
+ {0x3213, 0, 4 | DECOMP_COMPAT, 2503},
+ {0x3214, 0, 4 | DECOMP_COMPAT, 2507},
+ {0x3215, 0, 4 | DECOMP_COMPAT, 2511},
+ {0x3216, 0, 4 | DECOMP_COMPAT, 2515},
+ {0x3217, 0, 4 | DECOMP_COMPAT, 2519},
+ {0x3218, 0, 4 | DECOMP_COMPAT, 2523},
+ {0x3219, 0, 4 | DECOMP_COMPAT, 2527},
+ {0x321A, 0, 4 | DECOMP_COMPAT, 2531},
+ {0x321B, 0, 4 | DECOMP_COMPAT, 2535},
+ {0x321C, 0, 4 | DECOMP_COMPAT, 2539},
+ {0x321D, 0, 7 | DECOMP_COMPAT, 2543},
+ {0x321E, 0, 6 | DECOMP_COMPAT, 2550},
+ {0x3220, 0, 3 | DECOMP_COMPAT, 2556},
+ {0x3221, 0, 3 | DECOMP_COMPAT, 2559},
+ {0x3222, 0, 3 | DECOMP_COMPAT, 2562},
+ {0x3223, 0, 3 | DECOMP_COMPAT, 2565},
+ {0x3224, 0, 3 | DECOMP_COMPAT, 2568},
+ {0x3225, 0, 3 | DECOMP_COMPAT, 2571},
+ {0x3226, 0, 3 | DECOMP_COMPAT, 2574},
+ {0x3227, 0, 3 | DECOMP_COMPAT, 2577},
+ {0x3228, 0, 3 | DECOMP_COMPAT, 2580},
+ {0x3229, 0, 3 | DECOMP_COMPAT, 2583},
+ {0x322A, 0, 3 | DECOMP_COMPAT, 2586},
+ {0x322B, 0, 3 | DECOMP_COMPAT, 2589},
+ {0x322C, 0, 3 | DECOMP_COMPAT, 2592},
+ {0x322D, 0, 3 | DECOMP_COMPAT, 2595},
+ {0x322E, 0, 3 | DECOMP_COMPAT, 2598},
+ {0x322F, 0, 3 | DECOMP_COMPAT, 2601},
+ {0x3230, 0, 3 | DECOMP_COMPAT, 2604},
+ {0x3231, 0, 3 | DECOMP_COMPAT, 2607},
+ {0x3232, 0, 3 | DECOMP_COMPAT, 2610},
+ {0x3233, 0, 3 | DECOMP_COMPAT, 2613},
+ {0x3234, 0, 3 | DECOMP_COMPAT, 2616},
+ {0x3235, 0, 3 | DECOMP_COMPAT, 2619},
+ {0x3236, 0, 3 | DECOMP_COMPAT, 2622},
+ {0x3237, 0, 3 | DECOMP_COMPAT, 2625},
+ {0x3238, 0, 3 | DECOMP_COMPAT, 2628},
+ {0x3239, 0, 3 | DECOMP_COMPAT, 2631},
+ {0x323A, 0, 3 | DECOMP_COMPAT, 2634},
+ {0x323B, 0, 3 | DECOMP_COMPAT, 2637},
+ {0x323C, 0, 3 | DECOMP_COMPAT, 2640},
+ {0x323D, 0, 3 | DECOMP_COMPAT, 2643},
+ {0x323E, 0, 3 | DECOMP_COMPAT, 2646},
+ {0x323F, 0, 3 | DECOMP_COMPAT, 2649},
+ {0x3240, 0, 3 | DECOMP_COMPAT, 2652},
+ {0x3241, 0, 3 | DECOMP_COMPAT, 2655},
+ {0x3242, 0, 3 | DECOMP_COMPAT, 2658},
+ {0x3243, 0, 3 | DECOMP_COMPAT, 2661},
+ {0x3244, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x554F},
+ {0x3245, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5E7C},
+ {0x3246, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6587},
+ {0x3247, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7B8F},
+ {0x3250, 0, 3 | DECOMP_COMPAT, 2664},
+ {0x3251, 0, 2 | DECOMP_COMPAT, 2667},
+ {0x3252, 0, 2 | DECOMP_COMPAT, 2669},
+ {0x3253, 0, 2 | DECOMP_COMPAT, 2671},
+ {0x3254, 0, 2 | DECOMP_COMPAT, 2673},
+ {0x3255, 0, 2 | DECOMP_COMPAT, 2675},
+ {0x3256, 0, 2 | DECOMP_COMPAT, 2677},
+ {0x3257, 0, 2 | DECOMP_COMPAT, 2679},
+ {0x3258, 0, 2 | DECOMP_COMPAT, 2681},
+ {0x3259, 0, 2 | DECOMP_COMPAT, 2683},
+ {0x325A, 0, 2 | DECOMP_COMPAT, 2685},
+ {0x325B, 0, 2 | DECOMP_COMPAT, 2687},
+ {0x325C, 0, 2 | DECOMP_COMPAT, 2689},
+ {0x325D, 0, 2 | DECOMP_COMPAT, 2691},
+ {0x325E, 0, 2 | DECOMP_COMPAT, 2693},
+ {0x325F, 0, 2 | DECOMP_COMPAT, 2695},
+ {0x3260, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1100},
+ {0x3261, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1102},
+ {0x3262, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1103},
+ {0x3263, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1105},
+ {0x3264, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1106},
+ {0x3265, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1107},
+ {0x3266, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1109},
+ {0x3267, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110B},
+ {0x3268, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110C},
+ {0x3269, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110E},
+ {0x326A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x110F},
+ {0x326B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1110},
+ {0x326C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1111},
+ {0x326D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x1112},
+ {0x326E, 0, 2 | DECOMP_COMPAT, 2697},
+ {0x326F, 0, 2 | DECOMP_COMPAT, 2699},
+ {0x3270, 0, 2 | DECOMP_COMPAT, 2701},
+ {0x3271, 0, 2 | DECOMP_COMPAT, 2703},
+ {0x3272, 0, 2 | DECOMP_COMPAT, 2705},
+ {0x3273, 0, 2 | DECOMP_COMPAT, 2707},
+ {0x3274, 0, 2 | DECOMP_COMPAT, 2709},
+ {0x3275, 0, 2 | DECOMP_COMPAT, 2711},
+ {0x3276, 0, 2 | DECOMP_COMPAT, 2713},
+ {0x3277, 0, 2 | DECOMP_COMPAT, 2715},
+ {0x3278, 0, 2 | DECOMP_COMPAT, 2717},
+ {0x3279, 0, 2 | DECOMP_COMPAT, 2719},
+ {0x327A, 0, 2 | DECOMP_COMPAT, 2721},
+ {0x327B, 0, 2 | DECOMP_COMPAT, 2723},
+ {0x327C, 0, 5 | DECOMP_COMPAT, 2725},
+ {0x327D, 0, 4 | DECOMP_COMPAT, 2730},
+ {0x327E, 0, 2 | DECOMP_COMPAT, 2734},
+ {0x3280, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E00},
+ {0x3281, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E8C},
+ {0x3282, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E09},
+ {0x3283, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x56DB},
+ {0x3284, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E94},
+ {0x3285, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x516D},
+ {0x3286, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E03},
+ {0x3287, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x516B},
+ {0x3288, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E5D},
+ {0x3289, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5341},
+ {0x328A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6708},
+ {0x328B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x706B},
+ {0x328C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6C34},
+ {0x328D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6728},
+ {0x328E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x91D1},
+ {0x328F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x571F},
+ {0x3290, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x65E5},
+ {0x3291, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x682A},
+ {0x3292, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6709},
+ {0x3293, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x793E},
+ {0x3294, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x540D},
+ {0x3295, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7279},
+ {0x3296, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8CA1},
+ {0x3297, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x795D},
+ {0x3298, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x52B4},
+ {0x3299, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x79D8},
+ {0x329A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7537},
+ {0x329B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5973},
+ {0x329C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9069},
+ {0x329D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x512A},
+ {0x329E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5370},
+ {0x329F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6CE8},
+ {0x32A0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x9805},
+ {0x32A1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4F11},
+ {0x32A2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5199},
+ {0x32A3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6B63},
+ {0x32A4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E0A},
+ {0x32A5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E2D},
+ {0x32A6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E0B},
+ {0x32A7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5DE6},
+ {0x32A8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x53F3},
+ {0x32A9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x533B},
+ {0x32AA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5B97},
+ {0x32AB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5B66},
+ {0x32AC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x76E3},
+ {0x32AD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4F01},
+ {0x32AE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8CC7},
+ {0x32AF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5354},
+ {0x32B0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x591C},
+ {0x32B1, 0, 2 | DECOMP_COMPAT, 2736},
+ {0x32B2, 0, 2 | DECOMP_COMPAT, 2738},
+ {0x32B3, 0, 2 | DECOMP_COMPAT, 2740},
+ {0x32B4, 0, 2 | DECOMP_COMPAT, 2742},
+ {0x32B5, 0, 2 | DECOMP_COMPAT, 2744},
+ {0x32B6, 0, 2 | DECOMP_COMPAT, 2746},
+ {0x32B7, 0, 2 | DECOMP_COMPAT, 2748},
+ {0x32B8, 0, 2 | DECOMP_COMPAT, 2750},
+ {0x32B9, 0, 2 | DECOMP_COMPAT, 2752},
+ {0x32BA, 0, 2 | DECOMP_COMPAT, 2754},
+ {0x32BB, 0, 2 | DECOMP_COMPAT, 2756},
+ {0x32BC, 0, 2 | DECOMP_COMPAT, 2758},
+ {0x32BD, 0, 2 | DECOMP_COMPAT, 2760},
+ {0x32BE, 0, 2 | DECOMP_COMPAT, 2762},
+ {0x32BF, 0, 2 | DECOMP_COMPAT, 2764},
+ {0x32C0, 0, 2 | DECOMP_COMPAT, 2766},
+ {0x32C1, 0, 2 | DECOMP_COMPAT, 2768},
+ {0x32C2, 0, 2 | DECOMP_COMPAT, 2770},
+ {0x32C3, 0, 2 | DECOMP_COMPAT, 2772},
+ {0x32C4, 0, 2 | DECOMP_COMPAT, 2774},
+ {0x32C5, 0, 2 | DECOMP_COMPAT, 2776},
+ {0x32C6, 0, 2 | DECOMP_COMPAT, 2778},
+ {0x32C7, 0, 2 | DECOMP_COMPAT, 2780},
+ {0x32C8, 0, 2 | DECOMP_COMPAT, 2782},
+ {0x32C9, 0, 3 | DECOMP_COMPAT, 2784},
+ {0x32CA, 0, 3 | DECOMP_COMPAT, 2787},
+ {0x32CB, 0, 3 | DECOMP_COMPAT, 2790},
+ {0x32CC, 0, 2 | DECOMP_COMPAT, 2793},
+ {0x32CD, 0, 3 | DECOMP_COMPAT, 2795},
+ {0x32CE, 0, 2 | DECOMP_COMPAT, 2798},
+ {0x32CF, 0, 3 | DECOMP_COMPAT, 2800},
+ {0x32D0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A2},
+ {0x32D1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A4},
+ {0x32D2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A6},
+ {0x32D3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A8},
+ {0x32D4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30AA},
+ {0x32D5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30AB},
+ {0x32D6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30AD},
+ {0x32D7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30AF},
+ {0x32D8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B1},
+ {0x32D9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B3},
+ {0x32DA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B5},
+ {0x32DB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B7},
+ {0x32DC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B9},
+ {0x32DD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30BB},
+ {0x32DE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30BD},
+ {0x32DF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30BF},
+ {0x32E0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C1},
+ {0x32E1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C4},
+ {0x32E2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C6},
+ {0x32E3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C8},
+ {0x32E4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CA},
+ {0x32E5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CB},
+ {0x32E6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CC},
+ {0x32E7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CD},
+ {0x32E8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CE},
+ {0x32E9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CF},
+ {0x32EA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30D2},
+ {0x32EB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30D5},
+ {0x32EC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30D8},
+ {0x32ED, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30DB},
+ {0x32EE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30DE},
+ {0x32EF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30DF},
+ {0x32F0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E0},
+ {0x32F1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E1},
+ {0x32F2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E2},
+ {0x32F3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E4},
+ {0x32F4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E6},
+ {0x32F5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E8},
+ {0x32F6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E9},
+ {0x32F7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30EA},
+ {0x32F8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30EB},
+ {0x32F9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30EC},
+ {0x32FA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30ED},
+ {0x32FB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30EF},
+ {0x32FC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30F0},
+ {0x32FD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30F1},
+ {0x32FE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30F2},
+ {0x32FF, 0, 2 | DECOMP_COMPAT, 2803},
+ {0x3300, 0, 4 | DECOMP_COMPAT, 2805},
+ {0x3301, 0, 4 | DECOMP_COMPAT, 2809},
+ {0x3302, 0, 4 | DECOMP_COMPAT, 2813},
+ {0x3303, 0, 3 | DECOMP_COMPAT, 2817},
+ {0x3304, 0, 4 | DECOMP_COMPAT, 2820},
+ {0x3305, 0, 3 | DECOMP_COMPAT, 2824},
+ {0x3306, 0, 3 | DECOMP_COMPAT, 2827},
+ {0x3307, 0, 5 | DECOMP_COMPAT, 2830},
+ {0x3308, 0, 4 | DECOMP_COMPAT, 2835},
+ {0x3309, 0, 3 | DECOMP_COMPAT, 2839},
+ {0x330A, 0, 3 | DECOMP_COMPAT, 2842},
+ {0x330B, 0, 3 | DECOMP_COMPAT, 2845},
+ {0x330C, 0, 4 | DECOMP_COMPAT, 2848},
+ {0x330D, 0, 4 | DECOMP_COMPAT, 2852},
+ {0x330E, 0, 3 | DECOMP_COMPAT, 2856},
+ {0x330F, 0, 3 | DECOMP_COMPAT, 2859},
+ {0x3310, 0, 2 | DECOMP_COMPAT, 2862},
+ {0x3311, 0, 3 | DECOMP_COMPAT, 2864},
+ {0x3312, 0, 4 | DECOMP_COMPAT, 2867},
+ {0x3313, 0, 4 | DECOMP_COMPAT, 2871},
+ {0x3314, 0, 2 | DECOMP_COMPAT, 2875},
+ {0x3315, 0, 5 | DECOMP_COMPAT, 2877},
+ {0x3316, 0, 6 | DECOMP_COMPAT, 2882},
+ {0x3317, 0, 5 | DECOMP_COMPAT, 2888},
+ {0x3318, 0, 3 | DECOMP_COMPAT, 2893},
+ {0x3319, 0, 5 | DECOMP_COMPAT, 2896},
+ {0x331A, 0, 5 | DECOMP_COMPAT, 2901},
+ {0x331B, 0, 4 | DECOMP_COMPAT, 2906},
+ {0x331C, 0, 3 | DECOMP_COMPAT, 2910},
+ {0x331D, 0, 3 | DECOMP_COMPAT, 2913},
+ {0x331E, 0, 3 | DECOMP_COMPAT, 2916},
+ {0x331F, 0, 4 | DECOMP_COMPAT, 2919},
+ {0x3320, 0, 5 | DECOMP_COMPAT, 2923},
+ {0x3321, 0, 4 | DECOMP_COMPAT, 2928},
+ {0x3322, 0, 3 | DECOMP_COMPAT, 2932},
+ {0x3323, 0, 3 | DECOMP_COMPAT, 2935},
+ {0x3324, 0, 3 | DECOMP_COMPAT, 2938},
+ {0x3325, 0, 2 | DECOMP_COMPAT, 2941},
+ {0x3326, 0, 2 | DECOMP_COMPAT, 2943},
+ {0x3327, 0, 2 | DECOMP_COMPAT, 2945},
+ {0x3328, 0, 2 | DECOMP_COMPAT, 2947},
+ {0x3329, 0, 3 | DECOMP_COMPAT, 2949},
+ {0x332A, 0, 3 | DECOMP_COMPAT, 2952},
+ {0x332B, 0, 5 | DECOMP_COMPAT, 2955},
+ {0x332C, 0, 3 | DECOMP_COMPAT, 2960},
+ {0x332D, 0, 4 | DECOMP_COMPAT, 2963},
+ {0x332E, 0, 5 | DECOMP_COMPAT, 2967},
+ {0x332F, 0, 3 | DECOMP_COMPAT, 2972},
+ {0x3330, 0, 2 | DECOMP_COMPAT, 2975},
+ {0x3331, 0, 2 | DECOMP_COMPAT, 2977},
+ {0x3332, 0, 5 | DECOMP_COMPAT, 2979},
+ {0x3333, 0, 4 | DECOMP_COMPAT, 2984},
+ {0x3334, 0, 5 | DECOMP_COMPAT, 2988},
+ {0x3335, 0, 3 | DECOMP_COMPAT, 2993},
+ {0x3336, 0, 5 | DECOMP_COMPAT, 2996},
+ {0x3337, 0, 2 | DECOMP_COMPAT, 3001},
+ {0x3338, 0, 3 | DECOMP_COMPAT, 3003},
+ {0x3339, 0, 3 | DECOMP_COMPAT, 3006},
+ {0x333A, 0, 3 | DECOMP_COMPAT, 3009},
+ {0x333B, 0, 3 | DECOMP_COMPAT, 3012},
+ {0x333C, 0, 3 | DECOMP_COMPAT, 3015},
+ {0x333D, 0, 4 | DECOMP_COMPAT, 3018},
+ {0x333E, 0, 3 | DECOMP_COMPAT, 3022},
+ {0x333F, 0, 2 | DECOMP_COMPAT, 3025},
+ {0x3340, 0, 3 | DECOMP_COMPAT, 3027},
+ {0x3341, 0, 3 | DECOMP_COMPAT, 3030},
+ {0x3342, 0, 3 | DECOMP_COMPAT, 3033},
+ {0x3343, 0, 4 | DECOMP_COMPAT, 3036},
+ {0x3344, 0, 3 | DECOMP_COMPAT, 3040},
+ {0x3345, 0, 3 | DECOMP_COMPAT, 3043},
+ {0x3346, 0, 3 | DECOMP_COMPAT, 3046},
+ {0x3347, 0, 5 | DECOMP_COMPAT, 3049},
+ {0x3348, 0, 4 | DECOMP_COMPAT, 3054},
+ {0x3349, 0, 2 | DECOMP_COMPAT, 3058},
+ {0x334A, 0, 5 | DECOMP_COMPAT, 3060},
+ {0x334B, 0, 2 | DECOMP_COMPAT, 3065},
+ {0x334C, 0, 4 | DECOMP_COMPAT, 3067},
+ {0x334D, 0, 4 | DECOMP_COMPAT, 3071},
+ {0x334E, 0, 3 | DECOMP_COMPAT, 3075},
+ {0x334F, 0, 3 | DECOMP_COMPAT, 3078},
+ {0x3350, 0, 3 | DECOMP_COMPAT, 3081},
+ {0x3351, 0, 4 | DECOMP_COMPAT, 3084},
+ {0x3352, 0, 2 | DECOMP_COMPAT, 3088},
+ {0x3353, 0, 3 | DECOMP_COMPAT, 3090},
+ {0x3354, 0, 4 | DECOMP_COMPAT, 3093},
+ {0x3355, 0, 2 | DECOMP_COMPAT, 3097},
+ {0x3356, 0, 5 | DECOMP_COMPAT, 3099},
+ {0x3357, 0, 3 | DECOMP_COMPAT, 3104},
+ {0x3358, 0, 2 | DECOMP_COMPAT, 3107},
+ {0x3359, 0, 2 | DECOMP_COMPAT, 3109},
+ {0x335A, 0, 2 | DECOMP_COMPAT, 3111},
+ {0x335B, 0, 2 | DECOMP_COMPAT, 3113},
+ {0x335C, 0, 2 | DECOMP_COMPAT, 3115},
+ {0x335D, 0, 2 | DECOMP_COMPAT, 3117},
+ {0x335E, 0, 2 | DECOMP_COMPAT, 3119},
+ {0x335F, 0, 2 | DECOMP_COMPAT, 3121},
+ {0x3360, 0, 2 | DECOMP_COMPAT, 3123},
+ {0x3361, 0, 2 | DECOMP_COMPAT, 3125},
+ {0x3362, 0, 3 | DECOMP_COMPAT, 3127},
+ {0x3363, 0, 3 | DECOMP_COMPAT, 3130},
+ {0x3364, 0, 3 | DECOMP_COMPAT, 3133},
+ {0x3365, 0, 3 | DECOMP_COMPAT, 3136},
+ {0x3366, 0, 3 | DECOMP_COMPAT, 3139},
+ {0x3367, 0, 3 | DECOMP_COMPAT, 3142},
+ {0x3368, 0, 3 | DECOMP_COMPAT, 3145},
+ {0x3369, 0, 3 | DECOMP_COMPAT, 3148},
+ {0x336A, 0, 3 | DECOMP_COMPAT, 3151},
+ {0x336B, 0, 3 | DECOMP_COMPAT, 3154},
+ {0x336C, 0, 3 | DECOMP_COMPAT, 3157},
+ {0x336D, 0, 3 | DECOMP_COMPAT, 3160},
+ {0x336E, 0, 3 | DECOMP_COMPAT, 3163},
+ {0x336F, 0, 3 | DECOMP_COMPAT, 3166},
+ {0x3370, 0, 3 | DECOMP_COMPAT, 3169},
+ {0x3371, 0, 3 | DECOMP_COMPAT, 3172},
+ {0x3372, 0, 2 | DECOMP_COMPAT, 3175},
+ {0x3373, 0, 2 | DECOMP_COMPAT, 3177},
+ {0x3374, 0, 3 | DECOMP_COMPAT, 3179},
+ {0x3375, 0, 2 | DECOMP_COMPAT, 3182},
+ {0x3376, 0, 2 | DECOMP_COMPAT, 3184},
+ {0x3377, 0, 2 | DECOMP_COMPAT, 3186},
+ {0x3378, 0, 3 | DECOMP_COMPAT, 3188},
+ {0x3379, 0, 3 | DECOMP_COMPAT, 3191},
+ {0x337A, 0, 2 | DECOMP_COMPAT, 3194},
+ {0x337B, 0, 2 | DECOMP_COMPAT, 3196},
+ {0x337C, 0, 2 | DECOMP_COMPAT, 3198},
+ {0x337D, 0, 2 | DECOMP_COMPAT, 3200},
+ {0x337E, 0, 2 | DECOMP_COMPAT, 3202},
+ {0x337F, 0, 4 | DECOMP_COMPAT, 3204},
+ {0x3380, 0, 2 | DECOMP_COMPAT, 3208},
+ {0x3381, 0, 2 | DECOMP_COMPAT, 3210},
+ {0x3382, 0, 2 | DECOMP_COMPAT, 3212},
+ {0x3383, 0, 2 | DECOMP_COMPAT, 3214},
+ {0x3384, 0, 2 | DECOMP_COMPAT, 3216},
+ {0x3385, 0, 2 | DECOMP_COMPAT, 3218},
+ {0x3386, 0, 2 | DECOMP_COMPAT, 3220},
+ {0x3387, 0, 2 | DECOMP_COMPAT, 3222},
+ {0x3388, 0, 3 | DECOMP_COMPAT, 3224},
+ {0x3389, 0, 4 | DECOMP_COMPAT, 3227},
+ {0x338A, 0, 2 | DECOMP_COMPAT, 3231},
+ {0x338B, 0, 2 | DECOMP_COMPAT, 3233},
+ {0x338C, 0, 2 | DECOMP_COMPAT, 3235},
+ {0x338D, 0, 2 | DECOMP_COMPAT, 3237},
+ {0x338E, 0, 2 | DECOMP_COMPAT, 3239},
+ {0x338F, 0, 2 | DECOMP_COMPAT, 3241},
+ {0x3390, 0, 2 | DECOMP_COMPAT, 3243},
+ {0x3391, 0, 3 | DECOMP_COMPAT, 3245},
+ {0x3392, 0, 3 | DECOMP_COMPAT, 3248},
+ {0x3393, 0, 3 | DECOMP_COMPAT, 3251},
+ {0x3394, 0, 3 | DECOMP_COMPAT, 3254},
+ {0x3395, 0, 2 | DECOMP_COMPAT, 3257},
+ {0x3396, 0, 2 | DECOMP_COMPAT, 3259},
+ {0x3397, 0, 2 | DECOMP_COMPAT, 3261},
+ {0x3398, 0, 2 | DECOMP_COMPAT, 3263},
+ {0x3399, 0, 2 | DECOMP_COMPAT, 3265},
+ {0x339A, 0, 2 | DECOMP_COMPAT, 3267},
+ {0x339B, 0, 2 | DECOMP_COMPAT, 3269},
+ {0x339C, 0, 2 | DECOMP_COMPAT, 3271},
+ {0x339D, 0, 2 | DECOMP_COMPAT, 3273},
+ {0x339E, 0, 2 | DECOMP_COMPAT, 3275},
+ {0x339F, 0, 3 | DECOMP_COMPAT, 3277},
+ {0x33A0, 0, 3 | DECOMP_COMPAT, 3280},
+ {0x33A1, 0, 2 | DECOMP_COMPAT, 3283},
+ {0x33A2, 0, 3 | DECOMP_COMPAT, 3285},
+ {0x33A3, 0, 3 | DECOMP_COMPAT, 3288},
+ {0x33A4, 0, 3 | DECOMP_COMPAT, 3291},
+ {0x33A5, 0, 2 | DECOMP_COMPAT, 3294},
+ {0x33A6, 0, 3 | DECOMP_COMPAT, 3296},
+ {0x33A7, 0, 3 | DECOMP_COMPAT, 3299},
+ {0x33A8, 0, 4 | DECOMP_COMPAT, 3302},
+ {0x33A9, 0, 2 | DECOMP_COMPAT, 3306},
+ {0x33AA, 0, 3 | DECOMP_COMPAT, 3308},
+ {0x33AB, 0, 3 | DECOMP_COMPAT, 3311},
+ {0x33AC, 0, 3 | DECOMP_COMPAT, 3314},
+ {0x33AD, 0, 3 | DECOMP_COMPAT, 3317},
+ {0x33AE, 0, 5 | DECOMP_COMPAT, 3320},
+ {0x33AF, 0, 6 | DECOMP_COMPAT, 3325},
+ {0x33B0, 0, 2 | DECOMP_COMPAT, 3331},
+ {0x33B1, 0, 2 | DECOMP_COMPAT, 3333},
+ {0x33B2, 0, 2 | DECOMP_COMPAT, 3335},
+ {0x33B3, 0, 2 | DECOMP_COMPAT, 3337},
+ {0x33B4, 0, 2 | DECOMP_COMPAT, 3339},
+ {0x33B5, 0, 2 | DECOMP_COMPAT, 3341},
+ {0x33B6, 0, 2 | DECOMP_COMPAT, 3343},
+ {0x33B7, 0, 2 | DECOMP_COMPAT, 3345},
+ {0x33B8, 0, 2 | DECOMP_COMPAT, 3347},
+ {0x33B9, 0, 2 | DECOMP_COMPAT, 3349},
+ {0x33BA, 0, 2 | DECOMP_COMPAT, 3351},
+ {0x33BB, 0, 2 | DECOMP_COMPAT, 3353},
+ {0x33BC, 0, 2 | DECOMP_COMPAT, 3355},
+ {0x33BD, 0, 2 | DECOMP_COMPAT, 3357},
+ {0x33BE, 0, 2 | DECOMP_COMPAT, 3359},
+ {0x33BF, 0, 2 | DECOMP_COMPAT, 3361},
+ {0x33C0, 0, 2 | DECOMP_COMPAT, 3363},
+ {0x33C1, 0, 2 | DECOMP_COMPAT, 3365},
+ {0x33C2, 0, 4 | DECOMP_COMPAT, 3367},
+ {0x33C3, 0, 2 | DECOMP_COMPAT, 3371},
+ {0x33C4, 0, 2 | DECOMP_COMPAT, 3373},
+ {0x33C5, 0, 2 | DECOMP_COMPAT, 3375},
+ {0x33C6, 0, 4 | DECOMP_COMPAT, 3377},
+ {0x33C7, 0, 3 | DECOMP_COMPAT, 3381},
+ {0x33C8, 0, 2 | DECOMP_COMPAT, 3384},
+ {0x33C9, 0, 2 | DECOMP_COMPAT, 3386},
+ {0x33CA, 0, 2 | DECOMP_COMPAT, 3388},
+ {0x33CB, 0, 2 | DECOMP_COMPAT, 3390},
+ {0x33CC, 0, 2 | DECOMP_COMPAT, 3392},
+ {0x33CD, 0, 2 | DECOMP_COMPAT, 3394},
+ {0x33CE, 0, 2 | DECOMP_COMPAT, 3396},
+ {0x33CF, 0, 2 | DECOMP_COMPAT, 3398},
+ {0x33D0, 0, 2 | DECOMP_COMPAT, 3400},
+ {0x33D1, 0, 2 | DECOMP_COMPAT, 3402},
+ {0x33D2, 0, 3 | DECOMP_COMPAT, 3404},
+ {0x33D3, 0, 2 | DECOMP_COMPAT, 3407},
+ {0x33D4, 0, 2 | DECOMP_COMPAT, 3409},
+ {0x33D5, 0, 3 | DECOMP_COMPAT, 3411},
+ {0x33D6, 0, 3 | DECOMP_COMPAT, 3414},
+ {0x33D7, 0, 2 | DECOMP_COMPAT, 3417},
+ {0x33D8, 0, 4 | DECOMP_COMPAT, 3419},
+ {0x33D9, 0, 3 | DECOMP_COMPAT, 3423},
+ {0x33DA, 0, 2 | DECOMP_COMPAT, 3426},
+ {0x33DB, 0, 2 | DECOMP_COMPAT, 3428},
+ {0x33DC, 0, 2 | DECOMP_COMPAT, 3430},
+ {0x33DD, 0, 2 | DECOMP_COMPAT, 3432},
+ {0x33DE, 0, 3 | DECOMP_COMPAT, 3434},
+ {0x33DF, 0, 3 | DECOMP_COMPAT, 3437},
+ {0x33E0, 0, 2 | DECOMP_COMPAT, 3440},
+ {0x33E1, 0, 2 | DECOMP_COMPAT, 3442},
+ {0x33E2, 0, 2 | DECOMP_COMPAT, 3444},
+ {0x33E3, 0, 2 | DECOMP_COMPAT, 3446},
+ {0x33E4, 0, 2 | DECOMP_COMPAT, 3448},
+ {0x33E5, 0, 2 | DECOMP_COMPAT, 3450},
+ {0x33E6, 0, 2 | DECOMP_COMPAT, 3452},
+ {0x33E7, 0, 2 | DECOMP_COMPAT, 3454},
+ {0x33E8, 0, 2 | DECOMP_COMPAT, 3456},
+ {0x33E9, 0, 3 | DECOMP_COMPAT, 3458},
+ {0x33EA, 0, 3 | DECOMP_COMPAT, 3461},
+ {0x33EB, 0, 3 | DECOMP_COMPAT, 3464},
+ {0x33EC, 0, 3 | DECOMP_COMPAT, 3467},
+ {0x33ED, 0, 3 | DECOMP_COMPAT, 3470},
+ {0x33EE, 0, 3 | DECOMP_COMPAT, 3473},
+ {0x33EF, 0, 3 | DECOMP_COMPAT, 3476},
+ {0x33F0, 0, 3 | DECOMP_COMPAT, 3479},
+ {0x33F1, 0, 3 | DECOMP_COMPAT, 3482},
+ {0x33F2, 0, 3 | DECOMP_COMPAT, 3485},
+ {0x33F3, 0, 3 | DECOMP_COMPAT, 3488},
+ {0x33F4, 0, 3 | DECOMP_COMPAT, 3491},
+ {0x33F5, 0, 3 | DECOMP_COMPAT, 3494},
+ {0x33F6, 0, 3 | DECOMP_COMPAT, 3497},
+ {0x33F7, 0, 3 | DECOMP_COMPAT, 3500},
+ {0x33F8, 0, 3 | DECOMP_COMPAT, 3503},
+ {0x33F9, 0, 3 | DECOMP_COMPAT, 3506},
+ {0x33FA, 0, 3 | DECOMP_COMPAT, 3509},
+ {0x33FB, 0, 3 | DECOMP_COMPAT, 3512},
+ {0x33FC, 0, 3 | DECOMP_COMPAT, 3515},
+ {0x33FD, 0, 3 | DECOMP_COMPAT, 3518},
+ {0x33FE, 0, 3 | DECOMP_COMPAT, 3521},
+ {0x33FF, 0, 3 | DECOMP_COMPAT, 3524},
+ {0xA66F, 230, 0, 0},
+ {0xA674, 230, 0, 0},
+ {0xA675, 230, 0, 0},
+ {0xA676, 230, 0, 0},
+ {0xA677, 230, 0, 0},
+ {0xA678, 230, 0, 0},
+ {0xA679, 230, 0, 0},
+ {0xA67A, 230, 0, 0},
+ {0xA67B, 230, 0, 0},
+ {0xA67C, 230, 0, 0},
+ {0xA67D, 230, 0, 0},
+ {0xA69C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x044A},
+ {0xA69D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x044C},
+ {0xA69E, 230, 0, 0},
+ {0xA69F, 230, 0, 0},
+ {0xA6F0, 230, 0, 0},
+ {0xA6F1, 230, 0, 0},
+ {0xA770, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0xA76F},
+ {0xA7F8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0126},
+ {0xA7F9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0153},
+ {0xA806, 9, 0, 0},
+ {0xA82C, 9, 0, 0},
+ {0xA8C4, 9, 0, 0},
+ {0xA8E0, 230, 0, 0},
+ {0xA8E1, 230, 0, 0},
+ {0xA8E2, 230, 0, 0},
+ {0xA8E3, 230, 0, 0},
+ {0xA8E4, 230, 0, 0},
+ {0xA8E5, 230, 0, 0},
+ {0xA8E6, 230, 0, 0},
+ {0xA8E7, 230, 0, 0},
+ {0xA8E8, 230, 0, 0},
+ {0xA8E9, 230, 0, 0},
+ {0xA8EA, 230, 0, 0},
+ {0xA8EB, 230, 0, 0},
+ {0xA8EC, 230, 0, 0},
+ {0xA8ED, 230, 0, 0},
+ {0xA8EE, 230, 0, 0},
+ {0xA8EF, 230, 0, 0},
+ {0xA8F0, 230, 0, 0},
+ {0xA8F1, 230, 0, 0},
+ {0xA92B, 220, 0, 0},
+ {0xA92C, 220, 0, 0},
+ {0xA92D, 220, 0, 0},
+ {0xA953, 9, 0, 0},
+ {0xA9B3, 7, 0, 0},
+ {0xA9C0, 9, 0, 0},
+ {0xAAB0, 230, 0, 0},
+ {0xAAB2, 230, 0, 0},
+ {0xAAB3, 230, 0, 0},
+ {0xAAB4, 220, 0, 0},
+ {0xAAB7, 230, 0, 0},
+ {0xAAB8, 230, 0, 0},
+ {0xAABE, 230, 0, 0},
+ {0xAABF, 230, 0, 0},
+ {0xAAC1, 230, 0, 0},
+ {0xAAF6, 9, 0, 0},
+ {0xAB5C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0xA727},
+ {0xAB5D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0xAB37},
+ {0xAB5E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x026B},
+ {0xAB5F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0xAB52},
+ {0xAB69, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x028D},
+ {0xABED, 9, 0, 0},
+ {0xF900, 0, 1 | DECOMP_INLINE, 0x8C48},
+ {0xF901, 0, 1 | DECOMP_INLINE, 0x66F4},
+ {0xF902, 0, 1 | DECOMP_INLINE, 0x8ECA},
+ {0xF903, 0, 1 | DECOMP_INLINE, 0x8CC8},
+ {0xF904, 0, 1 | DECOMP_INLINE, 0x6ED1},
+ {0xF905, 0, 1 | DECOMP_INLINE, 0x4E32},
+ {0xF906, 0, 1 | DECOMP_INLINE, 0x53E5},
+ {0xF907, 0, 1 | DECOMP_INLINE, 0x9F9C},
+ {0xF908, 0, 1 | DECOMP_INLINE, 0x9F9C},
+ {0xF909, 0, 1 | DECOMP_INLINE, 0x5951},
+ {0xF90A, 0, 1 | DECOMP_INLINE, 0x91D1},
+ {0xF90B, 0, 1 | DECOMP_INLINE, 0x5587},
+ {0xF90C, 0, 1 | DECOMP_INLINE, 0x5948},
+ {0xF90D, 0, 1 | DECOMP_INLINE, 0x61F6},
+ {0xF90E, 0, 1 | DECOMP_INLINE, 0x7669},
+ {0xF90F, 0, 1 | DECOMP_INLINE, 0x7F85},
+ {0xF910, 0, 1 | DECOMP_INLINE, 0x863F},
+ {0xF911, 0, 1 | DECOMP_INLINE, 0x87BA},
+ {0xF912, 0, 1 | DECOMP_INLINE, 0x88F8},
+ {0xF913, 0, 1 | DECOMP_INLINE, 0x908F},
+ {0xF914, 0, 1 | DECOMP_INLINE, 0x6A02},
+ {0xF915, 0, 1 | DECOMP_INLINE, 0x6D1B},
+ {0xF916, 0, 1 | DECOMP_INLINE, 0x70D9},
+ {0xF917, 0, 1 | DECOMP_INLINE, 0x73DE},
+ {0xF918, 0, 1 | DECOMP_INLINE, 0x843D},
+ {0xF919, 0, 1 | DECOMP_INLINE, 0x916A},
+ {0xF91A, 0, 1 | DECOMP_INLINE, 0x99F1},
+ {0xF91B, 0, 1 | DECOMP_INLINE, 0x4E82},
+ {0xF91C, 0, 1 | DECOMP_INLINE, 0x5375},
+ {0xF91D, 0, 1 | DECOMP_INLINE, 0x6B04},
+ {0xF91E, 0, 1 | DECOMP_INLINE, 0x721B},
+ {0xF91F, 0, 1 | DECOMP_INLINE, 0x862D},
+ {0xF920, 0, 1 | DECOMP_INLINE, 0x9E1E},
+ {0xF921, 0, 1 | DECOMP_INLINE, 0x5D50},
+ {0xF922, 0, 1 | DECOMP_INLINE, 0x6FEB},
+ {0xF923, 0, 1 | DECOMP_INLINE, 0x85CD},
+ {0xF924, 0, 1 | DECOMP_INLINE, 0x8964},
+ {0xF925, 0, 1 | DECOMP_INLINE, 0x62C9},
+ {0xF926, 0, 1 | DECOMP_INLINE, 0x81D8},
+ {0xF927, 0, 1 | DECOMP_INLINE, 0x881F},
+ {0xF928, 0, 1 | DECOMP_INLINE, 0x5ECA},
+ {0xF929, 0, 1 | DECOMP_INLINE, 0x6717},
+ {0xF92A, 0, 1 | DECOMP_INLINE, 0x6D6A},
+ {0xF92B, 0, 1 | DECOMP_INLINE, 0x72FC},
+ {0xF92C, 0, 1 | DECOMP_INLINE, 0x90CE},
+ {0xF92D, 0, 1 | DECOMP_INLINE, 0x4F86},
+ {0xF92E, 0, 1 | DECOMP_INLINE, 0x51B7},
+ {0xF92F, 0, 1 | DECOMP_INLINE, 0x52DE},
+ {0xF930, 0, 1 | DECOMP_INLINE, 0x64C4},
+ {0xF931, 0, 1 | DECOMP_INLINE, 0x6AD3},
+ {0xF932, 0, 1 | DECOMP_INLINE, 0x7210},
+ {0xF933, 0, 1 | DECOMP_INLINE, 0x76E7},
+ {0xF934, 0, 1 | DECOMP_INLINE, 0x8001},
+ {0xF935, 0, 1 | DECOMP_INLINE, 0x8606},
+ {0xF936, 0, 1 | DECOMP_INLINE, 0x865C},
+ {0xF937, 0, 1 | DECOMP_INLINE, 0x8DEF},
+ {0xF938, 0, 1 | DECOMP_INLINE, 0x9732},
+ {0xF939, 0, 1 | DECOMP_INLINE, 0x9B6F},
+ {0xF93A, 0, 1 | DECOMP_INLINE, 0x9DFA},
+ {0xF93B, 0, 1 | DECOMP_INLINE, 0x788C},
+ {0xF93C, 0, 1 | DECOMP_INLINE, 0x797F},
+ {0xF93D, 0, 1 | DECOMP_INLINE, 0x7DA0},
+ {0xF93E, 0, 1 | DECOMP_INLINE, 0x83C9},
+ {0xF93F, 0, 1 | DECOMP_INLINE, 0x9304},
+ {0xF940, 0, 1 | DECOMP_INLINE, 0x9E7F},
+ {0xF941, 0, 1 | DECOMP_INLINE, 0x8AD6},
+ {0xF942, 0, 1 | DECOMP_INLINE, 0x58DF},
+ {0xF943, 0, 1 | DECOMP_INLINE, 0x5F04},
+ {0xF944, 0, 1 | DECOMP_INLINE, 0x7C60},
+ {0xF945, 0, 1 | DECOMP_INLINE, 0x807E},
+ {0xF946, 0, 1 | DECOMP_INLINE, 0x7262},
+ {0xF947, 0, 1 | DECOMP_INLINE, 0x78CA},
+ {0xF948, 0, 1 | DECOMP_INLINE, 0x8CC2},
+ {0xF949, 0, 1 | DECOMP_INLINE, 0x96F7},
+ {0xF94A, 0, 1 | DECOMP_INLINE, 0x58D8},
+ {0xF94B, 0, 1 | DECOMP_INLINE, 0x5C62},
+ {0xF94C, 0, 1 | DECOMP_INLINE, 0x6A13},
+ {0xF94D, 0, 1 | DECOMP_INLINE, 0x6DDA},
+ {0xF94E, 0, 1 | DECOMP_INLINE, 0x6F0F},
+ {0xF94F, 0, 1 | DECOMP_INLINE, 0x7D2F},
+ {0xF950, 0, 1 | DECOMP_INLINE, 0x7E37},
+ {0xF951, 0, 1 | DECOMP_INLINE, 0x964B},
+ {0xF952, 0, 1 | DECOMP_INLINE, 0x52D2},
+ {0xF953, 0, 1 | DECOMP_INLINE, 0x808B},
+ {0xF954, 0, 1 | DECOMP_INLINE, 0x51DC},
+ {0xF955, 0, 1 | DECOMP_INLINE, 0x51CC},
+ {0xF956, 0, 1 | DECOMP_INLINE, 0x7A1C},
+ {0xF957, 0, 1 | DECOMP_INLINE, 0x7DBE},
+ {0xF958, 0, 1 | DECOMP_INLINE, 0x83F1},
+ {0xF959, 0, 1 | DECOMP_INLINE, 0x9675},
+ {0xF95A, 0, 1 | DECOMP_INLINE, 0x8B80},
+ {0xF95B, 0, 1 | DECOMP_INLINE, 0x62CF},
+ {0xF95C, 0, 1 | DECOMP_INLINE, 0x6A02},
+ {0xF95D, 0, 1 | DECOMP_INLINE, 0x8AFE},
+ {0xF95E, 0, 1 | DECOMP_INLINE, 0x4E39},
+ {0xF95F, 0, 1 | DECOMP_INLINE, 0x5BE7},
+ {0xF960, 0, 1 | DECOMP_INLINE, 0x6012},
+ {0xF961, 0, 1 | DECOMP_INLINE, 0x7387},
+ {0xF962, 0, 1 | DECOMP_INLINE, 0x7570},
+ {0xF963, 0, 1 | DECOMP_INLINE, 0x5317},
+ {0xF964, 0, 1 | DECOMP_INLINE, 0x78FB},
+ {0xF965, 0, 1 | DECOMP_INLINE, 0x4FBF},
+ {0xF966, 0, 1 | DECOMP_INLINE, 0x5FA9},
+ {0xF967, 0, 1 | DECOMP_INLINE, 0x4E0D},
+ {0xF968, 0, 1 | DECOMP_INLINE, 0x6CCC},
+ {0xF969, 0, 1 | DECOMP_INLINE, 0x6578},
+ {0xF96A, 0, 1 | DECOMP_INLINE, 0x7D22},
+ {0xF96B, 0, 1 | DECOMP_INLINE, 0x53C3},
+ {0xF96C, 0, 1 | DECOMP_INLINE, 0x585E},
+ {0xF96D, 0, 1 | DECOMP_INLINE, 0x7701},
+ {0xF96E, 0, 1 | DECOMP_INLINE, 0x8449},
+ {0xF96F, 0, 1 | DECOMP_INLINE, 0x8AAA},
+ {0xF970, 0, 1 | DECOMP_INLINE, 0x6BBA},
+ {0xF971, 0, 1 | DECOMP_INLINE, 0x8FB0},
+ {0xF972, 0, 1 | DECOMP_INLINE, 0x6C88},
+ {0xF973, 0, 1 | DECOMP_INLINE, 0x62FE},
+ {0xF974, 0, 1 | DECOMP_INLINE, 0x82E5},
+ {0xF975, 0, 1 | DECOMP_INLINE, 0x63A0},
+ {0xF976, 0, 1 | DECOMP_INLINE, 0x7565},
+ {0xF977, 0, 1 | DECOMP_INLINE, 0x4EAE},
+ {0xF978, 0, 1 | DECOMP_INLINE, 0x5169},
+ {0xF979, 0, 1 | DECOMP_INLINE, 0x51C9},
+ {0xF97A, 0, 1 | DECOMP_INLINE, 0x6881},
+ {0xF97B, 0, 1 | DECOMP_INLINE, 0x7CE7},
+ {0xF97C, 0, 1 | DECOMP_INLINE, 0x826F},
+ {0xF97D, 0, 1 | DECOMP_INLINE, 0x8AD2},
+ {0xF97E, 0, 1 | DECOMP_INLINE, 0x91CF},
+ {0xF97F, 0, 1 | DECOMP_INLINE, 0x52F5},
+ {0xF980, 0, 1 | DECOMP_INLINE, 0x5442},
+ {0xF981, 0, 1 | DECOMP_INLINE, 0x5973},
+ {0xF982, 0, 1 | DECOMP_INLINE, 0x5EEC},
+ {0xF983, 0, 1 | DECOMP_INLINE, 0x65C5},
+ {0xF984, 0, 1 | DECOMP_INLINE, 0x6FFE},
+ {0xF985, 0, 1 | DECOMP_INLINE, 0x792A},
+ {0xF986, 0, 1 | DECOMP_INLINE, 0x95AD},
+ {0xF987, 0, 1 | DECOMP_INLINE, 0x9A6A},
+ {0xF988, 0, 1 | DECOMP_INLINE, 0x9E97},
+ {0xF989, 0, 1 | DECOMP_INLINE, 0x9ECE},
+ {0xF98A, 0, 1 | DECOMP_INLINE, 0x529B},
+ {0xF98B, 0, 1 | DECOMP_INLINE, 0x66C6},
+ {0xF98C, 0, 1 | DECOMP_INLINE, 0x6B77},
+ {0xF98D, 0, 1 | DECOMP_INLINE, 0x8F62},
+ {0xF98E, 0, 1 | DECOMP_INLINE, 0x5E74},
+ {0xF98F, 0, 1 | DECOMP_INLINE, 0x6190},
+ {0xF990, 0, 1 | DECOMP_INLINE, 0x6200},
+ {0xF991, 0, 1 | DECOMP_INLINE, 0x649A},
+ {0xF992, 0, 1 | DECOMP_INLINE, 0x6F23},
+ {0xF993, 0, 1 | DECOMP_INLINE, 0x7149},
+ {0xF994, 0, 1 | DECOMP_INLINE, 0x7489},
+ {0xF995, 0, 1 | DECOMP_INLINE, 0x79CA},
+ {0xF996, 0, 1 | DECOMP_INLINE, 0x7DF4},
+ {0xF997, 0, 1 | DECOMP_INLINE, 0x806F},
+ {0xF998, 0, 1 | DECOMP_INLINE, 0x8F26},
+ {0xF999, 0, 1 | DECOMP_INLINE, 0x84EE},
+ {0xF99A, 0, 1 | DECOMP_INLINE, 0x9023},
+ {0xF99B, 0, 1 | DECOMP_INLINE, 0x934A},
+ {0xF99C, 0, 1 | DECOMP_INLINE, 0x5217},
+ {0xF99D, 0, 1 | DECOMP_INLINE, 0x52A3},
+ {0xF99E, 0, 1 | DECOMP_INLINE, 0x54BD},
+ {0xF99F, 0, 1 | DECOMP_INLINE, 0x70C8},
+ {0xF9A0, 0, 1 | DECOMP_INLINE, 0x88C2},
+ {0xF9A1, 0, 1 | DECOMP_INLINE, 0x8AAA},
+ {0xF9A2, 0, 1 | DECOMP_INLINE, 0x5EC9},
+ {0xF9A3, 0, 1 | DECOMP_INLINE, 0x5FF5},
+ {0xF9A4, 0, 1 | DECOMP_INLINE, 0x637B},
+ {0xF9A5, 0, 1 | DECOMP_INLINE, 0x6BAE},
+ {0xF9A6, 0, 1 | DECOMP_INLINE, 0x7C3E},
+ {0xF9A7, 0, 1 | DECOMP_INLINE, 0x7375},
+ {0xF9A8, 0, 1 | DECOMP_INLINE, 0x4EE4},
+ {0xF9A9, 0, 1 | DECOMP_INLINE, 0x56F9},
+ {0xF9AA, 0, 1 | DECOMP_INLINE, 0x5BE7},
+ {0xF9AB, 0, 1 | DECOMP_INLINE, 0x5DBA},
+ {0xF9AC, 0, 1 | DECOMP_INLINE, 0x601C},
+ {0xF9AD, 0, 1 | DECOMP_INLINE, 0x73B2},
+ {0xF9AE, 0, 1 | DECOMP_INLINE, 0x7469},
+ {0xF9AF, 0, 1 | DECOMP_INLINE, 0x7F9A},
+ {0xF9B0, 0, 1 | DECOMP_INLINE, 0x8046},
+ {0xF9B1, 0, 1 | DECOMP_INLINE, 0x9234},
+ {0xF9B2, 0, 1 | DECOMP_INLINE, 0x96F6},
+ {0xF9B3, 0, 1 | DECOMP_INLINE, 0x9748},
+ {0xF9B4, 0, 1 | DECOMP_INLINE, 0x9818},
+ {0xF9B5, 0, 1 | DECOMP_INLINE, 0x4F8B},
+ {0xF9B6, 0, 1 | DECOMP_INLINE, 0x79AE},
+ {0xF9B7, 0, 1 | DECOMP_INLINE, 0x91B4},
+ {0xF9B8, 0, 1 | DECOMP_INLINE, 0x96B8},
+ {0xF9B9, 0, 1 | DECOMP_INLINE, 0x60E1},
+ {0xF9BA, 0, 1 | DECOMP_INLINE, 0x4E86},
+ {0xF9BB, 0, 1 | DECOMP_INLINE, 0x50DA},
+ {0xF9BC, 0, 1 | DECOMP_INLINE, 0x5BEE},
+ {0xF9BD, 0, 1 | DECOMP_INLINE, 0x5C3F},
+ {0xF9BE, 0, 1 | DECOMP_INLINE, 0x6599},
+ {0xF9BF, 0, 1 | DECOMP_INLINE, 0x6A02},
+ {0xF9C0, 0, 1 | DECOMP_INLINE, 0x71CE},
+ {0xF9C1, 0, 1 | DECOMP_INLINE, 0x7642},
+ {0xF9C2, 0, 1 | DECOMP_INLINE, 0x84FC},
+ {0xF9C3, 0, 1 | DECOMP_INLINE, 0x907C},
+ {0xF9C4, 0, 1 | DECOMP_INLINE, 0x9F8D},
+ {0xF9C5, 0, 1 | DECOMP_INLINE, 0x6688},
+ {0xF9C6, 0, 1 | DECOMP_INLINE, 0x962E},
+ {0xF9C7, 0, 1 | DECOMP_INLINE, 0x5289},
+ {0xF9C8, 0, 1 | DECOMP_INLINE, 0x677B},
+ {0xF9C9, 0, 1 | DECOMP_INLINE, 0x67F3},
+ {0xF9CA, 0, 1 | DECOMP_INLINE, 0x6D41},
+ {0xF9CB, 0, 1 | DECOMP_INLINE, 0x6E9C},
+ {0xF9CC, 0, 1 | DECOMP_INLINE, 0x7409},
+ {0xF9CD, 0, 1 | DECOMP_INLINE, 0x7559},
+ {0xF9CE, 0, 1 | DECOMP_INLINE, 0x786B},
+ {0xF9CF, 0, 1 | DECOMP_INLINE, 0x7D10},
+ {0xF9D0, 0, 1 | DECOMP_INLINE, 0x985E},
+ {0xF9D1, 0, 1 | DECOMP_INLINE, 0x516D},
+ {0xF9D2, 0, 1 | DECOMP_INLINE, 0x622E},
+ {0xF9D3, 0, 1 | DECOMP_INLINE, 0x9678},
+ {0xF9D4, 0, 1 | DECOMP_INLINE, 0x502B},
+ {0xF9D5, 0, 1 | DECOMP_INLINE, 0x5D19},
+ {0xF9D6, 0, 1 | DECOMP_INLINE, 0x6DEA},
+ {0xF9D7, 0, 1 | DECOMP_INLINE, 0x8F2A},
+ {0xF9D8, 0, 1 | DECOMP_INLINE, 0x5F8B},
+ {0xF9D9, 0, 1 | DECOMP_INLINE, 0x6144},
+ {0xF9DA, 0, 1 | DECOMP_INLINE, 0x6817},
+ {0xF9DB, 0, 1 | DECOMP_INLINE, 0x7387},
+ {0xF9DC, 0, 1 | DECOMP_INLINE, 0x9686},
+ {0xF9DD, 0, 1 | DECOMP_INLINE, 0x5229},
+ {0xF9DE, 0, 1 | DECOMP_INLINE, 0x540F},
+ {0xF9DF, 0, 1 | DECOMP_INLINE, 0x5C65},
+ {0xF9E0, 0, 1 | DECOMP_INLINE, 0x6613},
+ {0xF9E1, 0, 1 | DECOMP_INLINE, 0x674E},
+ {0xF9E2, 0, 1 | DECOMP_INLINE, 0x68A8},
+ {0xF9E3, 0, 1 | DECOMP_INLINE, 0x6CE5},
+ {0xF9E4, 0, 1 | DECOMP_INLINE, 0x7406},
+ {0xF9E5, 0, 1 | DECOMP_INLINE, 0x75E2},
+ {0xF9E6, 0, 1 | DECOMP_INLINE, 0x7F79},
+ {0xF9E7, 0, 1 | DECOMP_INLINE, 0x88CF},
+ {0xF9E8, 0, 1 | DECOMP_INLINE, 0x88E1},
+ {0xF9E9, 0, 1 | DECOMP_INLINE, 0x91CC},
+ {0xF9EA, 0, 1 | DECOMP_INLINE, 0x96E2},
+ {0xF9EB, 0, 1 | DECOMP_INLINE, 0x533F},
+ {0xF9EC, 0, 1 | DECOMP_INLINE, 0x6EBA},
+ {0xF9ED, 0, 1 | DECOMP_INLINE, 0x541D},
+ {0xF9EE, 0, 1 | DECOMP_INLINE, 0x71D0},
+ {0xF9EF, 0, 1 | DECOMP_INLINE, 0x7498},
+ {0xF9F0, 0, 1 | DECOMP_INLINE, 0x85FA},
+ {0xF9F1, 0, 1 | DECOMP_INLINE, 0x96A3},
+ {0xF9F2, 0, 1 | DECOMP_INLINE, 0x9C57},
+ {0xF9F3, 0, 1 | DECOMP_INLINE, 0x9E9F},
+ {0xF9F4, 0, 1 | DECOMP_INLINE, 0x6797},
+ {0xF9F5, 0, 1 | DECOMP_INLINE, 0x6DCB},
+ {0xF9F6, 0, 1 | DECOMP_INLINE, 0x81E8},
+ {0xF9F7, 0, 1 | DECOMP_INLINE, 0x7ACB},
+ {0xF9F8, 0, 1 | DECOMP_INLINE, 0x7B20},
+ {0xF9F9, 0, 1 | DECOMP_INLINE, 0x7C92},
+ {0xF9FA, 0, 1 | DECOMP_INLINE, 0x72C0},
+ {0xF9FB, 0, 1 | DECOMP_INLINE, 0x7099},
+ {0xF9FC, 0, 1 | DECOMP_INLINE, 0x8B58},
+ {0xF9FD, 0, 1 | DECOMP_INLINE, 0x4EC0},
+ {0xF9FE, 0, 1 | DECOMP_INLINE, 0x8336},
+ {0xF9FF, 0, 1 | DECOMP_INLINE, 0x523A},
+ {0xFA00, 0, 1 | DECOMP_INLINE, 0x5207},
+ {0xFA01, 0, 1 | DECOMP_INLINE, 0x5EA6},
+ {0xFA02, 0, 1 | DECOMP_INLINE, 0x62D3},
+ {0xFA03, 0, 1 | DECOMP_INLINE, 0x7CD6},
+ {0xFA04, 0, 1 | DECOMP_INLINE, 0x5B85},
+ {0xFA05, 0, 1 | DECOMP_INLINE, 0x6D1E},
+ {0xFA06, 0, 1 | DECOMP_INLINE, 0x66B4},
+ {0xFA07, 0, 1 | DECOMP_INLINE, 0x8F3B},
+ {0xFA08, 0, 1 | DECOMP_INLINE, 0x884C},
+ {0xFA09, 0, 1 | DECOMP_INLINE, 0x964D},
+ {0xFA0A, 0, 1 | DECOMP_INLINE, 0x898B},
+ {0xFA0B, 0, 1 | DECOMP_INLINE, 0x5ED3},
+ {0xFA0C, 0, 1 | DECOMP_INLINE, 0x5140},
+ {0xFA0D, 0, 1 | DECOMP_INLINE, 0x55C0},
+ {0xFA10, 0, 1 | DECOMP_INLINE, 0x585A},
+ {0xFA12, 0, 1 | DECOMP_INLINE, 0x6674},
+ {0xFA15, 0, 1 | DECOMP_INLINE, 0x51DE},
+ {0xFA16, 0, 1 | DECOMP_INLINE, 0x732A},
+ {0xFA17, 0, 1 | DECOMP_INLINE, 0x76CA},
+ {0xFA18, 0, 1 | DECOMP_INLINE, 0x793C},
+ {0xFA19, 0, 1 | DECOMP_INLINE, 0x795E},
+ {0xFA1A, 0, 1 | DECOMP_INLINE, 0x7965},
+ {0xFA1B, 0, 1 | DECOMP_INLINE, 0x798F},
+ {0xFA1C, 0, 1 | DECOMP_INLINE, 0x9756},
+ {0xFA1D, 0, 1 | DECOMP_INLINE, 0x7CBE},
+ {0xFA1E, 0, 1 | DECOMP_INLINE, 0x7FBD},
+ {0xFA20, 0, 1 | DECOMP_INLINE, 0x8612},
+ {0xFA22, 0, 1 | DECOMP_INLINE, 0x8AF8},
+ {0xFA25, 0, 1 | DECOMP_INLINE, 0x9038},
+ {0xFA26, 0, 1 | DECOMP_INLINE, 0x90FD},
+ {0xFA2A, 0, 1 | DECOMP_INLINE, 0x98EF},
+ {0xFA2B, 0, 1 | DECOMP_INLINE, 0x98FC},
+ {0xFA2C, 0, 1 | DECOMP_INLINE, 0x9928},
+ {0xFA2D, 0, 1 | DECOMP_INLINE, 0x9DB4},
+ {0xFA2E, 0, 1 | DECOMP_INLINE, 0x90DE},
+ {0xFA2F, 0, 1 | DECOMP_INLINE, 0x96B7},
+ {0xFA30, 0, 1 | DECOMP_INLINE, 0x4FAE},
+ {0xFA31, 0, 1 | DECOMP_INLINE, 0x50E7},
+ {0xFA32, 0, 1 | DECOMP_INLINE, 0x514D},
+ {0xFA33, 0, 1 | DECOMP_INLINE, 0x52C9},
+ {0xFA34, 0, 1 | DECOMP_INLINE, 0x52E4},
+ {0xFA35, 0, 1 | DECOMP_INLINE, 0x5351},
+ {0xFA36, 0, 1 | DECOMP_INLINE, 0x559D},
+ {0xFA37, 0, 1 | DECOMP_INLINE, 0x5606},
+ {0xFA38, 0, 1 | DECOMP_INLINE, 0x5668},
+ {0xFA39, 0, 1 | DECOMP_INLINE, 0x5840},
+ {0xFA3A, 0, 1 | DECOMP_INLINE, 0x58A8},
+ {0xFA3B, 0, 1 | DECOMP_INLINE, 0x5C64},
+ {0xFA3C, 0, 1 | DECOMP_INLINE, 0x5C6E},
+ {0xFA3D, 0, 1 | DECOMP_INLINE, 0x6094},
+ {0xFA3E, 0, 1 | DECOMP_INLINE, 0x6168},
+ {0xFA3F, 0, 1 | DECOMP_INLINE, 0x618E},
+ {0xFA40, 0, 1 | DECOMP_INLINE, 0x61F2},
+ {0xFA41, 0, 1 | DECOMP_INLINE, 0x654F},
+ {0xFA42, 0, 1 | DECOMP_INLINE, 0x65E2},
+ {0xFA43, 0, 1 | DECOMP_INLINE, 0x6691},
+ {0xFA44, 0, 1 | DECOMP_INLINE, 0x6885},
+ {0xFA45, 0, 1 | DECOMP_INLINE, 0x6D77},
+ {0xFA46, 0, 1 | DECOMP_INLINE, 0x6E1A},
+ {0xFA47, 0, 1 | DECOMP_INLINE, 0x6F22},
+ {0xFA48, 0, 1 | DECOMP_INLINE, 0x716E},
+ {0xFA49, 0, 1 | DECOMP_INLINE, 0x722B},
+ {0xFA4A, 0, 1 | DECOMP_INLINE, 0x7422},
+ {0xFA4B, 0, 1 | DECOMP_INLINE, 0x7891},
+ {0xFA4C, 0, 1 | DECOMP_INLINE, 0x793E},
+ {0xFA4D, 0, 1 | DECOMP_INLINE, 0x7949},
+ {0xFA4E, 0, 1 | DECOMP_INLINE, 0x7948},
+ {0xFA4F, 0, 1 | DECOMP_INLINE, 0x7950},
+ {0xFA50, 0, 1 | DECOMP_INLINE, 0x7956},
+ {0xFA51, 0, 1 | DECOMP_INLINE, 0x795D},
+ {0xFA52, 0, 1 | DECOMP_INLINE, 0x798D},
+ {0xFA53, 0, 1 | DECOMP_INLINE, 0x798E},
+ {0xFA54, 0, 1 | DECOMP_INLINE, 0x7A40},
+ {0xFA55, 0, 1 | DECOMP_INLINE, 0x7A81},
+ {0xFA56, 0, 1 | DECOMP_INLINE, 0x7BC0},
+ {0xFA57, 0, 1 | DECOMP_INLINE, 0x7DF4},
+ {0xFA58, 0, 1 | DECOMP_INLINE, 0x7E09},
+ {0xFA59, 0, 1 | DECOMP_INLINE, 0x7E41},
+ {0xFA5A, 0, 1 | DECOMP_INLINE, 0x7F72},
+ {0xFA5B, 0, 1 | DECOMP_INLINE, 0x8005},
+ {0xFA5C, 0, 1 | DECOMP_INLINE, 0x81ED},
+ {0xFA5D, 0, 1 | DECOMP_INLINE, 0x8279},
+ {0xFA5E, 0, 1 | DECOMP_INLINE, 0x8279},
+ {0xFA5F, 0, 1 | DECOMP_INLINE, 0x8457},
+ {0xFA60, 0, 1 | DECOMP_INLINE, 0x8910},
+ {0xFA61, 0, 1 | DECOMP_INLINE, 0x8996},
+ {0xFA62, 0, 1 | DECOMP_INLINE, 0x8B01},
+ {0xFA63, 0, 1 | DECOMP_INLINE, 0x8B39},
+ {0xFA64, 0, 1 | DECOMP_INLINE, 0x8CD3},
+ {0xFA65, 0, 1 | DECOMP_INLINE, 0x8D08},
+ {0xFA66, 0, 1 | DECOMP_INLINE, 0x8FB6},
+ {0xFA67, 0, 1 | DECOMP_INLINE, 0x9038},
+ {0xFA68, 0, 1 | DECOMP_INLINE, 0x96E3},
+ {0xFA69, 0, 1 | DECOMP_INLINE, 0x97FF},
+ {0xFA6A, 0, 1 | DECOMP_INLINE, 0x983B},
+ {0xFA6B, 0, 1 | DECOMP_INLINE, 0x6075},
+ {0xFA6C, 0, 1, 3527},
+ {0xFA6D, 0, 1 | DECOMP_INLINE, 0x8218},
+ {0xFA70, 0, 1 | DECOMP_INLINE, 0x4E26},
+ {0xFA71, 0, 1 | DECOMP_INLINE, 0x51B5},
+ {0xFA72, 0, 1 | DECOMP_INLINE, 0x5168},
+ {0xFA73, 0, 1 | DECOMP_INLINE, 0x4F80},
+ {0xFA74, 0, 1 | DECOMP_INLINE, 0x5145},
+ {0xFA75, 0, 1 | DECOMP_INLINE, 0x5180},
+ {0xFA76, 0, 1 | DECOMP_INLINE, 0x52C7},
+ {0xFA77, 0, 1 | DECOMP_INLINE, 0x52FA},
+ {0xFA78, 0, 1 | DECOMP_INLINE, 0x559D},
+ {0xFA79, 0, 1 | DECOMP_INLINE, 0x5555},
+ {0xFA7A, 0, 1 | DECOMP_INLINE, 0x5599},
+ {0xFA7B, 0, 1 | DECOMP_INLINE, 0x55E2},
+ {0xFA7C, 0, 1 | DECOMP_INLINE, 0x585A},
+ {0xFA7D, 0, 1 | DECOMP_INLINE, 0x58B3},
+ {0xFA7E, 0, 1 | DECOMP_INLINE, 0x5944},
+ {0xFA7F, 0, 1 | DECOMP_INLINE, 0x5954},
+ {0xFA80, 0, 1 | DECOMP_INLINE, 0x5A62},
+ {0xFA81, 0, 1 | DECOMP_INLINE, 0x5B28},
+ {0xFA82, 0, 1 | DECOMP_INLINE, 0x5ED2},
+ {0xFA83, 0, 1 | DECOMP_INLINE, 0x5ED9},
+ {0xFA84, 0, 1 | DECOMP_INLINE, 0x5F69},
+ {0xFA85, 0, 1 | DECOMP_INLINE, 0x5FAD},
+ {0xFA86, 0, 1 | DECOMP_INLINE, 0x60D8},
+ {0xFA87, 0, 1 | DECOMP_INLINE, 0x614E},
+ {0xFA88, 0, 1 | DECOMP_INLINE, 0x6108},
+ {0xFA89, 0, 1 | DECOMP_INLINE, 0x618E},
+ {0xFA8A, 0, 1 | DECOMP_INLINE, 0x6160},
+ {0xFA8B, 0, 1 | DECOMP_INLINE, 0x61F2},
+ {0xFA8C, 0, 1 | DECOMP_INLINE, 0x6234},
+ {0xFA8D, 0, 1 | DECOMP_INLINE, 0x63C4},
+ {0xFA8E, 0, 1 | DECOMP_INLINE, 0x641C},
+ {0xFA8F, 0, 1 | DECOMP_INLINE, 0x6452},
+ {0xFA90, 0, 1 | DECOMP_INLINE, 0x6556},
+ {0xFA91, 0, 1 | DECOMP_INLINE, 0x6674},
+ {0xFA92, 0, 1 | DECOMP_INLINE, 0x6717},
+ {0xFA93, 0, 1 | DECOMP_INLINE, 0x671B},
+ {0xFA94, 0, 1 | DECOMP_INLINE, 0x6756},
+ {0xFA95, 0, 1 | DECOMP_INLINE, 0x6B79},
+ {0xFA96, 0, 1 | DECOMP_INLINE, 0x6BBA},
+ {0xFA97, 0, 1 | DECOMP_INLINE, 0x6D41},
+ {0xFA98, 0, 1 | DECOMP_INLINE, 0x6EDB},
+ {0xFA99, 0, 1 | DECOMP_INLINE, 0x6ECB},
+ {0xFA9A, 0, 1 | DECOMP_INLINE, 0x6F22},
+ {0xFA9B, 0, 1 | DECOMP_INLINE, 0x701E},
+ {0xFA9C, 0, 1 | DECOMP_INLINE, 0x716E},
+ {0xFA9D, 0, 1 | DECOMP_INLINE, 0x77A7},
+ {0xFA9E, 0, 1 | DECOMP_INLINE, 0x7235},
+ {0xFA9F, 0, 1 | DECOMP_INLINE, 0x72AF},
+ {0xFAA0, 0, 1 | DECOMP_INLINE, 0x732A},
+ {0xFAA1, 0, 1 | DECOMP_INLINE, 0x7471},
+ {0xFAA2, 0, 1 | DECOMP_INLINE, 0x7506},
+ {0xFAA3, 0, 1 | DECOMP_INLINE, 0x753B},
+ {0xFAA4, 0, 1 | DECOMP_INLINE, 0x761D},
+ {0xFAA5, 0, 1 | DECOMP_INLINE, 0x761F},
+ {0xFAA6, 0, 1 | DECOMP_INLINE, 0x76CA},
+ {0xFAA7, 0, 1 | DECOMP_INLINE, 0x76DB},
+ {0xFAA8, 0, 1 | DECOMP_INLINE, 0x76F4},
+ {0xFAA9, 0, 1 | DECOMP_INLINE, 0x774A},
+ {0xFAAA, 0, 1 | DECOMP_INLINE, 0x7740},
+ {0xFAAB, 0, 1 | DECOMP_INLINE, 0x78CC},
+ {0xFAAC, 0, 1 | DECOMP_INLINE, 0x7AB1},
+ {0xFAAD, 0, 1 | DECOMP_INLINE, 0x7BC0},
+ {0xFAAE, 0, 1 | DECOMP_INLINE, 0x7C7B},
+ {0xFAAF, 0, 1 | DECOMP_INLINE, 0x7D5B},
+ {0xFAB0, 0, 1 | DECOMP_INLINE, 0x7DF4},
+ {0xFAB1, 0, 1 | DECOMP_INLINE, 0x7F3E},
+ {0xFAB2, 0, 1 | DECOMP_INLINE, 0x8005},
+ {0xFAB3, 0, 1 | DECOMP_INLINE, 0x8352},
+ {0xFAB4, 0, 1 | DECOMP_INLINE, 0x83EF},
+ {0xFAB5, 0, 1 | DECOMP_INLINE, 0x8779},
+ {0xFAB6, 0, 1 | DECOMP_INLINE, 0x8941},
+ {0xFAB7, 0, 1 | DECOMP_INLINE, 0x8986},
+ {0xFAB8, 0, 1 | DECOMP_INLINE, 0x8996},
+ {0xFAB9, 0, 1 | DECOMP_INLINE, 0x8ABF},
+ {0xFABA, 0, 1 | DECOMP_INLINE, 0x8AF8},
+ {0xFABB, 0, 1 | DECOMP_INLINE, 0x8ACB},
+ {0xFABC, 0, 1 | DECOMP_INLINE, 0x8B01},
+ {0xFABD, 0, 1 | DECOMP_INLINE, 0x8AFE},
+ {0xFABE, 0, 1 | DECOMP_INLINE, 0x8AED},
+ {0xFABF, 0, 1 | DECOMP_INLINE, 0x8B39},
+ {0xFAC0, 0, 1 | DECOMP_INLINE, 0x8B8A},
+ {0xFAC1, 0, 1 | DECOMP_INLINE, 0x8D08},
+ {0xFAC2, 0, 1 | DECOMP_INLINE, 0x8F38},
+ {0xFAC3, 0, 1 | DECOMP_INLINE, 0x9072},
+ {0xFAC4, 0, 1 | DECOMP_INLINE, 0x9199},
+ {0xFAC5, 0, 1 | DECOMP_INLINE, 0x9276},
+ {0xFAC6, 0, 1 | DECOMP_INLINE, 0x967C},
+ {0xFAC7, 0, 1 | DECOMP_INLINE, 0x96E3},
+ {0xFAC8, 0, 1 | DECOMP_INLINE, 0x9756},
+ {0xFAC9, 0, 1 | DECOMP_INLINE, 0x97DB},
+ {0xFACA, 0, 1 | DECOMP_INLINE, 0x97FF},
+ {0xFACB, 0, 1 | DECOMP_INLINE, 0x980B},
+ {0xFACC, 0, 1 | DECOMP_INLINE, 0x983B},
+ {0xFACD, 0, 1 | DECOMP_INLINE, 0x9B12},
+ {0xFACE, 0, 1 | DECOMP_INLINE, 0x9F9C},
+ {0xFACF, 0, 1, 3528},
+ {0xFAD0, 0, 1, 3529},
+ {0xFAD1, 0, 1, 3530},
+ {0xFAD2, 0, 1 | DECOMP_INLINE, 0x3B9D},
+ {0xFAD3, 0, 1 | DECOMP_INLINE, 0x4018},
+ {0xFAD4, 0, 1 | DECOMP_INLINE, 0x4039},
+ {0xFAD5, 0, 1, 3531},
+ {0xFAD6, 0, 1, 3532},
+ {0xFAD7, 0, 1, 3533},
+ {0xFAD8, 0, 1 | DECOMP_INLINE, 0x9F43},
+ {0xFAD9, 0, 1 | DECOMP_INLINE, 0x9F8E},
+ {0xFB00, 0, 2 | DECOMP_COMPAT, 3534},
+ {0xFB01, 0, 2 | DECOMP_COMPAT, 3536},
+ {0xFB02, 0, 2 | DECOMP_COMPAT, 3538},
+ {0xFB03, 0, 3 | DECOMP_COMPAT, 3540},
+ {0xFB04, 0, 3 | DECOMP_COMPAT, 3543},
+ {0xFB05, 0, 2 | DECOMP_COMPAT, 3546},
+ {0xFB06, 0, 2 | DECOMP_COMPAT, 3548},
+ {0xFB13, 0, 2 | DECOMP_COMPAT, 3550},
+ {0xFB14, 0, 2 | DECOMP_COMPAT, 3552},
+ {0xFB15, 0, 2 | DECOMP_COMPAT, 3554},
+ {0xFB16, 0, 2 | DECOMP_COMPAT, 3556},
+ {0xFB17, 0, 2 | DECOMP_COMPAT, 3558},
+ {0xFB1D, 0, 2 | DECOMP_NO_COMPOSE, 3560}, /* in exclusion list */
+ {0xFB1E, 26, 0, 0},
+ {0xFB1F, 0, 2 | DECOMP_NO_COMPOSE, 3562}, /* in exclusion list */
+ {0xFB20, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05E2},
+ {0xFB21, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05D0},
+ {0xFB22, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05D3},
+ {0xFB23, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05D4},
+ {0xFB24, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05DB},
+ {0xFB25, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05DC},
+ {0xFB26, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05DD},
+ {0xFB27, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05E8},
+ {0xFB28, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x05EA},
+ {0xFB29, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002B},
+ {0xFB2A, 0, 2 | DECOMP_NO_COMPOSE, 3564}, /* in exclusion list */
+ {0xFB2B, 0, 2 | DECOMP_NO_COMPOSE, 3566}, /* in exclusion list */
+ {0xFB2C, 0, 2 | DECOMP_NO_COMPOSE, 3568}, /* in exclusion list */
+ {0xFB2D, 0, 2 | DECOMP_NO_COMPOSE, 3570}, /* in exclusion list */
+ {0xFB2E, 0, 2 | DECOMP_NO_COMPOSE, 3572}, /* in exclusion list */
+ {0xFB2F, 0, 2 | DECOMP_NO_COMPOSE, 3574}, /* in exclusion list */
+ {0xFB30, 0, 2 | DECOMP_NO_COMPOSE, 3576}, /* in exclusion list */
+ {0xFB31, 0, 2 | DECOMP_NO_COMPOSE, 3578}, /* in exclusion list */
+ {0xFB32, 0, 2 | DECOMP_NO_COMPOSE, 3580}, /* in exclusion list */
+ {0xFB33, 0, 2 | DECOMP_NO_COMPOSE, 3582}, /* in exclusion list */
+ {0xFB34, 0, 2 | DECOMP_NO_COMPOSE, 3584}, /* in exclusion list */
+ {0xFB35, 0, 2 | DECOMP_NO_COMPOSE, 3586}, /* in exclusion list */
+ {0xFB36, 0, 2 | DECOMP_NO_COMPOSE, 3588}, /* in exclusion list */
+ {0xFB38, 0, 2 | DECOMP_NO_COMPOSE, 3590}, /* in exclusion list */
+ {0xFB39, 0, 2 | DECOMP_NO_COMPOSE, 3592}, /* in exclusion list */
+ {0xFB3A, 0, 2 | DECOMP_NO_COMPOSE, 3594}, /* in exclusion list */
+ {0xFB3B, 0, 2 | DECOMP_NO_COMPOSE, 3596}, /* in exclusion list */
+ {0xFB3C, 0, 2 | DECOMP_NO_COMPOSE, 3598}, /* in exclusion list */
+ {0xFB3E, 0, 2 | DECOMP_NO_COMPOSE, 3600}, /* in exclusion list */
+ {0xFB40, 0, 2 | DECOMP_NO_COMPOSE, 3602}, /* in exclusion list */
+ {0xFB41, 0, 2 | DECOMP_NO_COMPOSE, 3604}, /* in exclusion list */
+ {0xFB43, 0, 2 | DECOMP_NO_COMPOSE, 3606}, /* in exclusion list */
+ {0xFB44, 0, 2 | DECOMP_NO_COMPOSE, 3608}, /* in exclusion list */
+ {0xFB46, 0, 2 | DECOMP_NO_COMPOSE, 3610}, /* in exclusion list */
+ {0xFB47, 0, 2 | DECOMP_NO_COMPOSE, 3612}, /* in exclusion list */
+ {0xFB48, 0, 2 | DECOMP_NO_COMPOSE, 3614}, /* in exclusion list */
+ {0xFB49, 0, 2 | DECOMP_NO_COMPOSE, 3616}, /* in exclusion list */
+ {0xFB4A, 0, 2 | DECOMP_NO_COMPOSE, 3618}, /* in exclusion list */
+ {0xFB4B, 0, 2 | DECOMP_NO_COMPOSE, 3620}, /* in exclusion list */
+ {0xFB4C, 0, 2 | DECOMP_NO_COMPOSE, 3622}, /* in exclusion list */
+ {0xFB4D, 0, 2 | DECOMP_NO_COMPOSE, 3624}, /* in exclusion list */
+ {0xFB4E, 0, 2 | DECOMP_NO_COMPOSE, 3626}, /* in exclusion list */
+ {0xFB4F, 0, 2 | DECOMP_COMPAT, 3628},
+ {0xFB50, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0671},
+ {0xFB51, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0671},
+ {0xFB52, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067B},
+ {0xFB53, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067B},
+ {0xFB54, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067B},
+ {0xFB55, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067B},
+ {0xFB56, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067E},
+ {0xFB57, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067E},
+ {0xFB58, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067E},
+ {0xFB59, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067E},
+ {0xFB5A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0680},
+ {0xFB5B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0680},
+ {0xFB5C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0680},
+ {0xFB5D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0680},
+ {0xFB5E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067A},
+ {0xFB5F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067A},
+ {0xFB60, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067A},
+ {0xFB61, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067A},
+ {0xFB62, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067F},
+ {0xFB63, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067F},
+ {0xFB64, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067F},
+ {0xFB65, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x067F},
+ {0xFB66, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0679},
+ {0xFB67, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0679},
+ {0xFB68, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0679},
+ {0xFB69, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0679},
+ {0xFB6A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A4},
+ {0xFB6B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A4},
+ {0xFB6C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A4},
+ {0xFB6D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A4},
+ {0xFB6E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A6},
+ {0xFB6F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A6},
+ {0xFB70, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A6},
+ {0xFB71, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A6},
+ {0xFB72, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0684},
+ {0xFB73, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0684},
+ {0xFB74, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0684},
+ {0xFB75, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0684},
+ {0xFB76, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0683},
+ {0xFB77, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0683},
+ {0xFB78, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0683},
+ {0xFB79, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0683},
+ {0xFB7A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0686},
+ {0xFB7B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0686},
+ {0xFB7C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0686},
+ {0xFB7D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0686},
+ {0xFB7E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0687},
+ {0xFB7F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0687},
+ {0xFB80, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0687},
+ {0xFB81, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0687},
+ {0xFB82, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x068D},
+ {0xFB83, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x068D},
+ {0xFB84, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x068C},
+ {0xFB85, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x068C},
+ {0xFB86, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x068E},
+ {0xFB87, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x068E},
+ {0xFB88, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0688},
+ {0xFB89, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0688},
+ {0xFB8A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0698},
+ {0xFB8B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0698},
+ {0xFB8C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0691},
+ {0xFB8D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0691},
+ {0xFB8E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A9},
+ {0xFB8F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A9},
+ {0xFB90, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A9},
+ {0xFB91, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A9},
+ {0xFB92, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06AF},
+ {0xFB93, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06AF},
+ {0xFB94, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06AF},
+ {0xFB95, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06AF},
+ {0xFB96, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06B3},
+ {0xFB97, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06B3},
+ {0xFB98, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06B3},
+ {0xFB99, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06B3},
+ {0xFB9A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06B1},
+ {0xFB9B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06B1},
+ {0xFB9C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06B1},
+ {0xFB9D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06B1},
+ {0xFB9E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BA},
+ {0xFB9F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BA},
+ {0xFBA0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BB},
+ {0xFBA1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BB},
+ {0xFBA2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BB},
+ {0xFBA3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BB},
+ {0xFBA4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C0},
+ {0xFBA5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C0},
+ {0xFBA6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C1},
+ {0xFBA7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C1},
+ {0xFBA8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C1},
+ {0xFBA9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C1},
+ {0xFBAA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BE},
+ {0xFBAB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BE},
+ {0xFBAC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BE},
+ {0xFBAD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BE},
+ {0xFBAE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06D2},
+ {0xFBAF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06D2},
+ {0xFBB0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06D3},
+ {0xFBB1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06D3},
+ {0xFBD3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06AD},
+ {0xFBD4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06AD},
+ {0xFBD5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06AD},
+ {0xFBD6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06AD},
+ {0xFBD7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C7},
+ {0xFBD8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C7},
+ {0xFBD9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C6},
+ {0xFBDA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C6},
+ {0xFBDB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C8},
+ {0xFBDC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C8},
+ {0xFBDD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0677},
+ {0xFBDE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06CB},
+ {0xFBDF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06CB},
+ {0xFBE0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C5},
+ {0xFBE1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C5},
+ {0xFBE2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C9},
+ {0xFBE3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06C9},
+ {0xFBE4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06D0},
+ {0xFBE5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06D0},
+ {0xFBE6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06D0},
+ {0xFBE7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06D0},
+ {0xFBE8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0649},
+ {0xFBE9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0649},
+ {0xFBEA, 0, 2 | DECOMP_COMPAT, 3630},
+ {0xFBEB, 0, 2 | DECOMP_COMPAT, 3632},
+ {0xFBEC, 0, 2 | DECOMP_COMPAT, 3634},
+ {0xFBED, 0, 2 | DECOMP_COMPAT, 3636},
+ {0xFBEE, 0, 2 | DECOMP_COMPAT, 3638},
+ {0xFBEF, 0, 2 | DECOMP_COMPAT, 3640},
+ {0xFBF0, 0, 2 | DECOMP_COMPAT, 3642},
+ {0xFBF1, 0, 2 | DECOMP_COMPAT, 3644},
+ {0xFBF2, 0, 2 | DECOMP_COMPAT, 3646},
+ {0xFBF3, 0, 2 | DECOMP_COMPAT, 3648},
+ {0xFBF4, 0, 2 | DECOMP_COMPAT, 3650},
+ {0xFBF5, 0, 2 | DECOMP_COMPAT, 3652},
+ {0xFBF6, 0, 2 | DECOMP_COMPAT, 3654},
+ {0xFBF7, 0, 2 | DECOMP_COMPAT, 3656},
+ {0xFBF8, 0, 2 | DECOMP_COMPAT, 3658},
+ {0xFBF9, 0, 2 | DECOMP_COMPAT, 3660},
+ {0xFBFA, 0, 2 | DECOMP_COMPAT, 3662},
+ {0xFBFB, 0, 2 | DECOMP_COMPAT, 3664},
+ {0xFBFC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06CC},
+ {0xFBFD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06CC},
+ {0xFBFE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06CC},
+ {0xFBFF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06CC},
+ {0xFC00, 0, 2 | DECOMP_COMPAT, 3666},
+ {0xFC01, 0, 2 | DECOMP_COMPAT, 3668},
+ {0xFC02, 0, 2 | DECOMP_COMPAT, 3670},
+ {0xFC03, 0, 2 | DECOMP_COMPAT, 3672},
+ {0xFC04, 0, 2 | DECOMP_COMPAT, 3674},
+ {0xFC05, 0, 2 | DECOMP_COMPAT, 3676},
+ {0xFC06, 0, 2 | DECOMP_COMPAT, 3678},
+ {0xFC07, 0, 2 | DECOMP_COMPAT, 3680},
+ {0xFC08, 0, 2 | DECOMP_COMPAT, 3682},
+ {0xFC09, 0, 2 | DECOMP_COMPAT, 3684},
+ {0xFC0A, 0, 2 | DECOMP_COMPAT, 3686},
+ {0xFC0B, 0, 2 | DECOMP_COMPAT, 3688},
+ {0xFC0C, 0, 2 | DECOMP_COMPAT, 3690},
+ {0xFC0D, 0, 2 | DECOMP_COMPAT, 3692},
+ {0xFC0E, 0, 2 | DECOMP_COMPAT, 3694},
+ {0xFC0F, 0, 2 | DECOMP_COMPAT, 3696},
+ {0xFC10, 0, 2 | DECOMP_COMPAT, 3698},
+ {0xFC11, 0, 2 | DECOMP_COMPAT, 3700},
+ {0xFC12, 0, 2 | DECOMP_COMPAT, 3702},
+ {0xFC13, 0, 2 | DECOMP_COMPAT, 3704},
+ {0xFC14, 0, 2 | DECOMP_COMPAT, 3706},
+ {0xFC15, 0, 2 | DECOMP_COMPAT, 3708},
+ {0xFC16, 0, 2 | DECOMP_COMPAT, 3710},
+ {0xFC17, 0, 2 | DECOMP_COMPAT, 3712},
+ {0xFC18, 0, 2 | DECOMP_COMPAT, 3714},
+ {0xFC19, 0, 2 | DECOMP_COMPAT, 3716},
+ {0xFC1A, 0, 2 | DECOMP_COMPAT, 3718},
+ {0xFC1B, 0, 2 | DECOMP_COMPAT, 3720},
+ {0xFC1C, 0, 2 | DECOMP_COMPAT, 3722},
+ {0xFC1D, 0, 2 | DECOMP_COMPAT, 3724},
+ {0xFC1E, 0, 2 | DECOMP_COMPAT, 3726},
+ {0xFC1F, 0, 2 | DECOMP_COMPAT, 3728},
+ {0xFC20, 0, 2 | DECOMP_COMPAT, 3730},
+ {0xFC21, 0, 2 | DECOMP_COMPAT, 3732},
+ {0xFC22, 0, 2 | DECOMP_COMPAT, 3734},
+ {0xFC23, 0, 2 | DECOMP_COMPAT, 3736},
+ {0xFC24, 0, 2 | DECOMP_COMPAT, 3738},
+ {0xFC25, 0, 2 | DECOMP_COMPAT, 3740},
+ {0xFC26, 0, 2 | DECOMP_COMPAT, 3742},
+ {0xFC27, 0, 2 | DECOMP_COMPAT, 3744},
+ {0xFC28, 0, 2 | DECOMP_COMPAT, 3746},
+ {0xFC29, 0, 2 | DECOMP_COMPAT, 3748},
+ {0xFC2A, 0, 2 | DECOMP_COMPAT, 3750},
+ {0xFC2B, 0, 2 | DECOMP_COMPAT, 3752},
+ {0xFC2C, 0, 2 | DECOMP_COMPAT, 3754},
+ {0xFC2D, 0, 2 | DECOMP_COMPAT, 3756},
+ {0xFC2E, 0, 2 | DECOMP_COMPAT, 3758},
+ {0xFC2F, 0, 2 | DECOMP_COMPAT, 3760},
+ {0xFC30, 0, 2 | DECOMP_COMPAT, 3762},
+ {0xFC31, 0, 2 | DECOMP_COMPAT, 3764},
+ {0xFC32, 0, 2 | DECOMP_COMPAT, 3766},
+ {0xFC33, 0, 2 | DECOMP_COMPAT, 3768},
+ {0xFC34, 0, 2 | DECOMP_COMPAT, 3770},
+ {0xFC35, 0, 2 | DECOMP_COMPAT, 3772},
+ {0xFC36, 0, 2 | DECOMP_COMPAT, 3774},
+ {0xFC37, 0, 2 | DECOMP_COMPAT, 3776},
+ {0xFC38, 0, 2 | DECOMP_COMPAT, 3778},
+ {0xFC39, 0, 2 | DECOMP_COMPAT, 3780},
+ {0xFC3A, 0, 2 | DECOMP_COMPAT, 3782},
+ {0xFC3B, 0, 2 | DECOMP_COMPAT, 3784},
+ {0xFC3C, 0, 2 | DECOMP_COMPAT, 3786},
+ {0xFC3D, 0, 2 | DECOMP_COMPAT, 3788},
+ {0xFC3E, 0, 2 | DECOMP_COMPAT, 3790},
+ {0xFC3F, 0, 2 | DECOMP_COMPAT, 3792},
+ {0xFC40, 0, 2 | DECOMP_COMPAT, 3794},
+ {0xFC41, 0, 2 | DECOMP_COMPAT, 3796},
+ {0xFC42, 0, 2 | DECOMP_COMPAT, 3798},
+ {0xFC43, 0, 2 | DECOMP_COMPAT, 3800},
+ {0xFC44, 0, 2 | DECOMP_COMPAT, 3802},
+ {0xFC45, 0, 2 | DECOMP_COMPAT, 3804},
+ {0xFC46, 0, 2 | DECOMP_COMPAT, 3806},
+ {0xFC47, 0, 2 | DECOMP_COMPAT, 3808},
+ {0xFC48, 0, 2 | DECOMP_COMPAT, 3810},
+ {0xFC49, 0, 2 | DECOMP_COMPAT, 3812},
+ {0xFC4A, 0, 2 | DECOMP_COMPAT, 3814},
+ {0xFC4B, 0, 2 | DECOMP_COMPAT, 3816},
+ {0xFC4C, 0, 2 | DECOMP_COMPAT, 3818},
+ {0xFC4D, 0, 2 | DECOMP_COMPAT, 3820},
+ {0xFC4E, 0, 2 | DECOMP_COMPAT, 3822},
+ {0xFC4F, 0, 2 | DECOMP_COMPAT, 3824},
+ {0xFC50, 0, 2 | DECOMP_COMPAT, 3826},
+ {0xFC51, 0, 2 | DECOMP_COMPAT, 3828},
+ {0xFC52, 0, 2 | DECOMP_COMPAT, 3830},
+ {0xFC53, 0, 2 | DECOMP_COMPAT, 3832},
+ {0xFC54, 0, 2 | DECOMP_COMPAT, 3834},
+ {0xFC55, 0, 2 | DECOMP_COMPAT, 3836},
+ {0xFC56, 0, 2 | DECOMP_COMPAT, 3838},
+ {0xFC57, 0, 2 | DECOMP_COMPAT, 3840},
+ {0xFC58, 0, 2 | DECOMP_COMPAT, 3842},
+ {0xFC59, 0, 2 | DECOMP_COMPAT, 3844},
+ {0xFC5A, 0, 2 | DECOMP_COMPAT, 3846},
+ {0xFC5B, 0, 2 | DECOMP_COMPAT, 3848},
+ {0xFC5C, 0, 2 | DECOMP_COMPAT, 3850},
+ {0xFC5D, 0, 2 | DECOMP_COMPAT, 3852},
+ {0xFC5E, 0, 3 | DECOMP_COMPAT, 3854},
+ {0xFC5F, 0, 3 | DECOMP_COMPAT, 3857},
+ {0xFC60, 0, 3 | DECOMP_COMPAT, 3860},
+ {0xFC61, 0, 3 | DECOMP_COMPAT, 3863},
+ {0xFC62, 0, 3 | DECOMP_COMPAT, 3866},
+ {0xFC63, 0, 3 | DECOMP_COMPAT, 3869},
+ {0xFC64, 0, 2 | DECOMP_COMPAT, 3872},
+ {0xFC65, 0, 2 | DECOMP_COMPAT, 3874},
+ {0xFC66, 0, 2 | DECOMP_COMPAT, 3876},
+ {0xFC67, 0, 2 | DECOMP_COMPAT, 3878},
+ {0xFC68, 0, 2 | DECOMP_COMPAT, 3880},
+ {0xFC69, 0, 2 | DECOMP_COMPAT, 3882},
+ {0xFC6A, 0, 2 | DECOMP_COMPAT, 3884},
+ {0xFC6B, 0, 2 | DECOMP_COMPAT, 3886},
+ {0xFC6C, 0, 2 | DECOMP_COMPAT, 3888},
+ {0xFC6D, 0, 2 | DECOMP_COMPAT, 3890},
+ {0xFC6E, 0, 2 | DECOMP_COMPAT, 3892},
+ {0xFC6F, 0, 2 | DECOMP_COMPAT, 3894},
+ {0xFC70, 0, 2 | DECOMP_COMPAT, 3896},
+ {0xFC71, 0, 2 | DECOMP_COMPAT, 3898},
+ {0xFC72, 0, 2 | DECOMP_COMPAT, 3900},
+ {0xFC73, 0, 2 | DECOMP_COMPAT, 3902},
+ {0xFC74, 0, 2 | DECOMP_COMPAT, 3904},
+ {0xFC75, 0, 2 | DECOMP_COMPAT, 3906},
+ {0xFC76, 0, 2 | DECOMP_COMPAT, 3908},
+ {0xFC77, 0, 2 | DECOMP_COMPAT, 3910},
+ {0xFC78, 0, 2 | DECOMP_COMPAT, 3912},
+ {0xFC79, 0, 2 | DECOMP_COMPAT, 3914},
+ {0xFC7A, 0, 2 | DECOMP_COMPAT, 3916},
+ {0xFC7B, 0, 2 | DECOMP_COMPAT, 3918},
+ {0xFC7C, 0, 2 | DECOMP_COMPAT, 3920},
+ {0xFC7D, 0, 2 | DECOMP_COMPAT, 3922},
+ {0xFC7E, 0, 2 | DECOMP_COMPAT, 3924},
+ {0xFC7F, 0, 2 | DECOMP_COMPAT, 3926},
+ {0xFC80, 0, 2 | DECOMP_COMPAT, 3928},
+ {0xFC81, 0, 2 | DECOMP_COMPAT, 3930},
+ {0xFC82, 0, 2 | DECOMP_COMPAT, 3932},
+ {0xFC83, 0, 2 | DECOMP_COMPAT, 3934},
+ {0xFC84, 0, 2 | DECOMP_COMPAT, 3936},
+ {0xFC85, 0, 2 | DECOMP_COMPAT, 3938},
+ {0xFC86, 0, 2 | DECOMP_COMPAT, 3940},
+ {0xFC87, 0, 2 | DECOMP_COMPAT, 3942},
+ {0xFC88, 0, 2 | DECOMP_COMPAT, 3944},
+ {0xFC89, 0, 2 | DECOMP_COMPAT, 3946},
+ {0xFC8A, 0, 2 | DECOMP_COMPAT, 3948},
+ {0xFC8B, 0, 2 | DECOMP_COMPAT, 3950},
+ {0xFC8C, 0, 2 | DECOMP_COMPAT, 3952},
+ {0xFC8D, 0, 2 | DECOMP_COMPAT, 3954},
+ {0xFC8E, 0, 2 | DECOMP_COMPAT, 3956},
+ {0xFC8F, 0, 2 | DECOMP_COMPAT, 3958},
+ {0xFC90, 0, 2 | DECOMP_COMPAT, 3960},
+ {0xFC91, 0, 2 | DECOMP_COMPAT, 3962},
+ {0xFC92, 0, 2 | DECOMP_COMPAT, 3964},
+ {0xFC93, 0, 2 | DECOMP_COMPAT, 3966},
+ {0xFC94, 0, 2 | DECOMP_COMPAT, 3968},
+ {0xFC95, 0, 2 | DECOMP_COMPAT, 3970},
+ {0xFC96, 0, 2 | DECOMP_COMPAT, 3972},
+ {0xFC97, 0, 2 | DECOMP_COMPAT, 3974},
+ {0xFC98, 0, 2 | DECOMP_COMPAT, 3976},
+ {0xFC99, 0, 2 | DECOMP_COMPAT, 3978},
+ {0xFC9A, 0, 2 | DECOMP_COMPAT, 3980},
+ {0xFC9B, 0, 2 | DECOMP_COMPAT, 3982},
+ {0xFC9C, 0, 2 | DECOMP_COMPAT, 3984},
+ {0xFC9D, 0, 2 | DECOMP_COMPAT, 3986},
+ {0xFC9E, 0, 2 | DECOMP_COMPAT, 3988},
+ {0xFC9F, 0, 2 | DECOMP_COMPAT, 3990},
+ {0xFCA0, 0, 2 | DECOMP_COMPAT, 3992},
+ {0xFCA1, 0, 2 | DECOMP_COMPAT, 3994},
+ {0xFCA2, 0, 2 | DECOMP_COMPAT, 3996},
+ {0xFCA3, 0, 2 | DECOMP_COMPAT, 3998},
+ {0xFCA4, 0, 2 | DECOMP_COMPAT, 4000},
+ {0xFCA5, 0, 2 | DECOMP_COMPAT, 4002},
+ {0xFCA6, 0, 2 | DECOMP_COMPAT, 4004},
+ {0xFCA7, 0, 2 | DECOMP_COMPAT, 4006},
+ {0xFCA8, 0, 2 | DECOMP_COMPAT, 4008},
+ {0xFCA9, 0, 2 | DECOMP_COMPAT, 4010},
+ {0xFCAA, 0, 2 | DECOMP_COMPAT, 4012},
+ {0xFCAB, 0, 2 | DECOMP_COMPAT, 4014},
+ {0xFCAC, 0, 2 | DECOMP_COMPAT, 4016},
+ {0xFCAD, 0, 2 | DECOMP_COMPAT, 4018},
+ {0xFCAE, 0, 2 | DECOMP_COMPAT, 4020},
+ {0xFCAF, 0, 2 | DECOMP_COMPAT, 4022},
+ {0xFCB0, 0, 2 | DECOMP_COMPAT, 4024},
+ {0xFCB1, 0, 2 | DECOMP_COMPAT, 4026},
+ {0xFCB2, 0, 2 | DECOMP_COMPAT, 4028},
+ {0xFCB3, 0, 2 | DECOMP_COMPAT, 4030},
+ {0xFCB4, 0, 2 | DECOMP_COMPAT, 4032},
+ {0xFCB5, 0, 2 | DECOMP_COMPAT, 4034},
+ {0xFCB6, 0, 2 | DECOMP_COMPAT, 4036},
+ {0xFCB7, 0, 2 | DECOMP_COMPAT, 4038},
+ {0xFCB8, 0, 2 | DECOMP_COMPAT, 4040},
+ {0xFCB9, 0, 2 | DECOMP_COMPAT, 4042},
+ {0xFCBA, 0, 2 | DECOMP_COMPAT, 4044},
+ {0xFCBB, 0, 2 | DECOMP_COMPAT, 4046},
+ {0xFCBC, 0, 2 | DECOMP_COMPAT, 4048},
+ {0xFCBD, 0, 2 | DECOMP_COMPAT, 4050},
+ {0xFCBE, 0, 2 | DECOMP_COMPAT, 4052},
+ {0xFCBF, 0, 2 | DECOMP_COMPAT, 4054},
+ {0xFCC0, 0, 2 | DECOMP_COMPAT, 4056},
+ {0xFCC1, 0, 2 | DECOMP_COMPAT, 4058},
+ {0xFCC2, 0, 2 | DECOMP_COMPAT, 4060},
+ {0xFCC3, 0, 2 | DECOMP_COMPAT, 4062},
+ {0xFCC4, 0, 2 | DECOMP_COMPAT, 4064},
+ {0xFCC5, 0, 2 | DECOMP_COMPAT, 4066},
+ {0xFCC6, 0, 2 | DECOMP_COMPAT, 4068},
+ {0xFCC7, 0, 2 | DECOMP_COMPAT, 4070},
+ {0xFCC8, 0, 2 | DECOMP_COMPAT, 4072},
+ {0xFCC9, 0, 2 | DECOMP_COMPAT, 4074},
+ {0xFCCA, 0, 2 | DECOMP_COMPAT, 4076},
+ {0xFCCB, 0, 2 | DECOMP_COMPAT, 4078},
+ {0xFCCC, 0, 2 | DECOMP_COMPAT, 4080},
+ {0xFCCD, 0, 2 | DECOMP_COMPAT, 4082},
+ {0xFCCE, 0, 2 | DECOMP_COMPAT, 4084},
+ {0xFCCF, 0, 2 | DECOMP_COMPAT, 4086},
+ {0xFCD0, 0, 2 | DECOMP_COMPAT, 4088},
+ {0xFCD1, 0, 2 | DECOMP_COMPAT, 4090},
+ {0xFCD2, 0, 2 | DECOMP_COMPAT, 4092},
+ {0xFCD3, 0, 2 | DECOMP_COMPAT, 4094},
+ {0xFCD4, 0, 2 | DECOMP_COMPAT, 4096},
+ {0xFCD5, 0, 2 | DECOMP_COMPAT, 4098},
+ {0xFCD6, 0, 2 | DECOMP_COMPAT, 4100},
+ {0xFCD7, 0, 2 | DECOMP_COMPAT, 4102},
+ {0xFCD8, 0, 2 | DECOMP_COMPAT, 4104},
+ {0xFCD9, 0, 2 | DECOMP_COMPAT, 4106},
+ {0xFCDA, 0, 2 | DECOMP_COMPAT, 4108},
+ {0xFCDB, 0, 2 | DECOMP_COMPAT, 4110},
+ {0xFCDC, 0, 2 | DECOMP_COMPAT, 4112},
+ {0xFCDD, 0, 2 | DECOMP_COMPAT, 4114},
+ {0xFCDE, 0, 2 | DECOMP_COMPAT, 4116},
+ {0xFCDF, 0, 2 | DECOMP_COMPAT, 4118},
+ {0xFCE0, 0, 2 | DECOMP_COMPAT, 4120},
+ {0xFCE1, 0, 2 | DECOMP_COMPAT, 4122},
+ {0xFCE2, 0, 2 | DECOMP_COMPAT, 4124},
+ {0xFCE3, 0, 2 | DECOMP_COMPAT, 4126},
+ {0xFCE4, 0, 2 | DECOMP_COMPAT, 4128},
+ {0xFCE5, 0, 2 | DECOMP_COMPAT, 4130},
+ {0xFCE6, 0, 2 | DECOMP_COMPAT, 4132},
+ {0xFCE7, 0, 2 | DECOMP_COMPAT, 4134},
+ {0xFCE8, 0, 2 | DECOMP_COMPAT, 4136},
+ {0xFCE9, 0, 2 | DECOMP_COMPAT, 4138},
+ {0xFCEA, 0, 2 | DECOMP_COMPAT, 4140},
+ {0xFCEB, 0, 2 | DECOMP_COMPAT, 4142},
+ {0xFCEC, 0, 2 | DECOMP_COMPAT, 4144},
+ {0xFCED, 0, 2 | DECOMP_COMPAT, 4146},
+ {0xFCEE, 0, 2 | DECOMP_COMPAT, 4148},
+ {0xFCEF, 0, 2 | DECOMP_COMPAT, 4150},
+ {0xFCF0, 0, 2 | DECOMP_COMPAT, 4152},
+ {0xFCF1, 0, 2 | DECOMP_COMPAT, 4154},
+ {0xFCF2, 0, 3 | DECOMP_COMPAT, 4156},
+ {0xFCF3, 0, 3 | DECOMP_COMPAT, 4159},
+ {0xFCF4, 0, 3 | DECOMP_COMPAT, 4162},
+ {0xFCF5, 0, 2 | DECOMP_COMPAT, 4165},
+ {0xFCF6, 0, 2 | DECOMP_COMPAT, 4167},
+ {0xFCF7, 0, 2 | DECOMP_COMPAT, 4169},
+ {0xFCF8, 0, 2 | DECOMP_COMPAT, 4171},
+ {0xFCF9, 0, 2 | DECOMP_COMPAT, 4173},
+ {0xFCFA, 0, 2 | DECOMP_COMPAT, 4175},
+ {0xFCFB, 0, 2 | DECOMP_COMPAT, 4177},
+ {0xFCFC, 0, 2 | DECOMP_COMPAT, 4179},
+ {0xFCFD, 0, 2 | DECOMP_COMPAT, 4181},
+ {0xFCFE, 0, 2 | DECOMP_COMPAT, 4183},
+ {0xFCFF, 0, 2 | DECOMP_COMPAT, 4185},
+ {0xFD00, 0, 2 | DECOMP_COMPAT, 4187},
+ {0xFD01, 0, 2 | DECOMP_COMPAT, 4189},
+ {0xFD02, 0, 2 | DECOMP_COMPAT, 4191},
+ {0xFD03, 0, 2 | DECOMP_COMPAT, 4193},
+ {0xFD04, 0, 2 | DECOMP_COMPAT, 4195},
+ {0xFD05, 0, 2 | DECOMP_COMPAT, 4197},
+ {0xFD06, 0, 2 | DECOMP_COMPAT, 4199},
+ {0xFD07, 0, 2 | DECOMP_COMPAT, 4201},
+ {0xFD08, 0, 2 | DECOMP_COMPAT, 4203},
+ {0xFD09, 0, 2 | DECOMP_COMPAT, 4205},
+ {0xFD0A, 0, 2 | DECOMP_COMPAT, 4207},
+ {0xFD0B, 0, 2 | DECOMP_COMPAT, 4209},
+ {0xFD0C, 0, 2 | DECOMP_COMPAT, 4211},
+ {0xFD0D, 0, 2 | DECOMP_COMPAT, 4213},
+ {0xFD0E, 0, 2 | DECOMP_COMPAT, 4215},
+ {0xFD0F, 0, 2 | DECOMP_COMPAT, 4217},
+ {0xFD10, 0, 2 | DECOMP_COMPAT, 4219},
+ {0xFD11, 0, 2 | DECOMP_COMPAT, 4221},
+ {0xFD12, 0, 2 | DECOMP_COMPAT, 4223},
+ {0xFD13, 0, 2 | DECOMP_COMPAT, 4225},
+ {0xFD14, 0, 2 | DECOMP_COMPAT, 4227},
+ {0xFD15, 0, 2 | DECOMP_COMPAT, 4229},
+ {0xFD16, 0, 2 | DECOMP_COMPAT, 4231},
+ {0xFD17, 0, 2 | DECOMP_COMPAT, 4233},
+ {0xFD18, 0, 2 | DECOMP_COMPAT, 4235},
+ {0xFD19, 0, 2 | DECOMP_COMPAT, 4237},
+ {0xFD1A, 0, 2 | DECOMP_COMPAT, 4239},
+ {0xFD1B, 0, 2 | DECOMP_COMPAT, 4241},
+ {0xFD1C, 0, 2 | DECOMP_COMPAT, 4243},
+ {0xFD1D, 0, 2 | DECOMP_COMPAT, 4245},
+ {0xFD1E, 0, 2 | DECOMP_COMPAT, 4247},
+ {0xFD1F, 0, 2 | DECOMP_COMPAT, 4249},
+ {0xFD20, 0, 2 | DECOMP_COMPAT, 4251},
+ {0xFD21, 0, 2 | DECOMP_COMPAT, 4253},
+ {0xFD22, 0, 2 | DECOMP_COMPAT, 4255},
+ {0xFD23, 0, 2 | DECOMP_COMPAT, 4257},
+ {0xFD24, 0, 2 | DECOMP_COMPAT, 4259},
+ {0xFD25, 0, 2 | DECOMP_COMPAT, 4261},
+ {0xFD26, 0, 2 | DECOMP_COMPAT, 4263},
+ {0xFD27, 0, 2 | DECOMP_COMPAT, 4265},
+ {0xFD28, 0, 2 | DECOMP_COMPAT, 4267},
+ {0xFD29, 0, 2 | DECOMP_COMPAT, 4269},
+ {0xFD2A, 0, 2 | DECOMP_COMPAT, 4271},
+ {0xFD2B, 0, 2 | DECOMP_COMPAT, 4273},
+ {0xFD2C, 0, 2 | DECOMP_COMPAT, 4275},
+ {0xFD2D, 0, 2 | DECOMP_COMPAT, 4277},
+ {0xFD2E, 0, 2 | DECOMP_COMPAT, 4279},
+ {0xFD2F, 0, 2 | DECOMP_COMPAT, 4281},
+ {0xFD30, 0, 2 | DECOMP_COMPAT, 4283},
+ {0xFD31, 0, 2 | DECOMP_COMPAT, 4285},
+ {0xFD32, 0, 2 | DECOMP_COMPAT, 4287},
+ {0xFD33, 0, 2 | DECOMP_COMPAT, 4289},
+ {0xFD34, 0, 2 | DECOMP_COMPAT, 4291},
+ {0xFD35, 0, 2 | DECOMP_COMPAT, 4293},
+ {0xFD36, 0, 2 | DECOMP_COMPAT, 4295},
+ {0xFD37, 0, 2 | DECOMP_COMPAT, 4297},
+ {0xFD38, 0, 2 | DECOMP_COMPAT, 4299},
+ {0xFD39, 0, 2 | DECOMP_COMPAT, 4301},
+ {0xFD3A, 0, 2 | DECOMP_COMPAT, 4303},
+ {0xFD3B, 0, 2 | DECOMP_COMPAT, 4305},
+ {0xFD3C, 0, 2 | DECOMP_COMPAT, 4307},
+ {0xFD3D, 0, 2 | DECOMP_COMPAT, 4309},
+ {0xFD50, 0, 3 | DECOMP_COMPAT, 4311},
+ {0xFD51, 0, 3 | DECOMP_COMPAT, 4314},
+ {0xFD52, 0, 3 | DECOMP_COMPAT, 4317},
+ {0xFD53, 0, 3 | DECOMP_COMPAT, 4320},
+ {0xFD54, 0, 3 | DECOMP_COMPAT, 4323},
+ {0xFD55, 0, 3 | DECOMP_COMPAT, 4326},
+ {0xFD56, 0, 3 | DECOMP_COMPAT, 4329},
+ {0xFD57, 0, 3 | DECOMP_COMPAT, 4332},
+ {0xFD58, 0, 3 | DECOMP_COMPAT, 4335},
+ {0xFD59, 0, 3 | DECOMP_COMPAT, 4338},
+ {0xFD5A, 0, 3 | DECOMP_COMPAT, 4341},
+ {0xFD5B, 0, 3 | DECOMP_COMPAT, 4344},
+ {0xFD5C, 0, 3 | DECOMP_COMPAT, 4347},
+ {0xFD5D, 0, 3 | DECOMP_COMPAT, 4350},
+ {0xFD5E, 0, 3 | DECOMP_COMPAT, 4353},
+ {0xFD5F, 0, 3 | DECOMP_COMPAT, 4356},
+ {0xFD60, 0, 3 | DECOMP_COMPAT, 4359},
+ {0xFD61, 0, 3 | DECOMP_COMPAT, 4362},
+ {0xFD62, 0, 3 | DECOMP_COMPAT, 4365},
+ {0xFD63, 0, 3 | DECOMP_COMPAT, 4368},
+ {0xFD64, 0, 3 | DECOMP_COMPAT, 4371},
+ {0xFD65, 0, 3 | DECOMP_COMPAT, 4374},
+ {0xFD66, 0, 3 | DECOMP_COMPAT, 4377},
+ {0xFD67, 0, 3 | DECOMP_COMPAT, 4380},
+ {0xFD68, 0, 3 | DECOMP_COMPAT, 4383},
+ {0xFD69, 0, 3 | DECOMP_COMPAT, 4386},
+ {0xFD6A, 0, 3 | DECOMP_COMPAT, 4389},
+ {0xFD6B, 0, 3 | DECOMP_COMPAT, 4392},
+ {0xFD6C, 0, 3 | DECOMP_COMPAT, 4395},
+ {0xFD6D, 0, 3 | DECOMP_COMPAT, 4398},
+ {0xFD6E, 0, 3 | DECOMP_COMPAT, 4401},
+ {0xFD6F, 0, 3 | DECOMP_COMPAT, 4404},
+ {0xFD70, 0, 3 | DECOMP_COMPAT, 4407},
+ {0xFD71, 0, 3 | DECOMP_COMPAT, 4410},
+ {0xFD72, 0, 3 | DECOMP_COMPAT, 4413},
+ {0xFD73, 0, 3 | DECOMP_COMPAT, 4416},
+ {0xFD74, 0, 3 | DECOMP_COMPAT, 4419},
+ {0xFD75, 0, 3 | DECOMP_COMPAT, 4422},
+ {0xFD76, 0, 3 | DECOMP_COMPAT, 4425},
+ {0xFD77, 0, 3 | DECOMP_COMPAT, 4428},
+ {0xFD78, 0, 3 | DECOMP_COMPAT, 4431},
+ {0xFD79, 0, 3 | DECOMP_COMPAT, 4434},
+ {0xFD7A, 0, 3 | DECOMP_COMPAT, 4437},
+ {0xFD7B, 0, 3 | DECOMP_COMPAT, 4440},
+ {0xFD7C, 0, 3 | DECOMP_COMPAT, 4443},
+ {0xFD7D, 0, 3 | DECOMP_COMPAT, 4446},
+ {0xFD7E, 0, 3 | DECOMP_COMPAT, 4449},
+ {0xFD7F, 0, 3 | DECOMP_COMPAT, 4452},
+ {0xFD80, 0, 3 | DECOMP_COMPAT, 4455},
+ {0xFD81, 0, 3 | DECOMP_COMPAT, 4458},
+ {0xFD82, 0, 3 | DECOMP_COMPAT, 4461},
+ {0xFD83, 0, 3 | DECOMP_COMPAT, 4464},
+ {0xFD84, 0, 3 | DECOMP_COMPAT, 4467},
+ {0xFD85, 0, 3 | DECOMP_COMPAT, 4470},
+ {0xFD86, 0, 3 | DECOMP_COMPAT, 4473},
+ {0xFD87, 0, 3 | DECOMP_COMPAT, 4476},
+ {0xFD88, 0, 3 | DECOMP_COMPAT, 4479},
+ {0xFD89, 0, 3 | DECOMP_COMPAT, 4482},
+ {0xFD8A, 0, 3 | DECOMP_COMPAT, 4485},
+ {0xFD8B, 0, 3 | DECOMP_COMPAT, 4488},
+ {0xFD8C, 0, 3 | DECOMP_COMPAT, 4491},
+ {0xFD8D, 0, 3 | DECOMP_COMPAT, 4494},
+ {0xFD8E, 0, 3 | DECOMP_COMPAT, 4497},
+ {0xFD8F, 0, 3 | DECOMP_COMPAT, 4500},
+ {0xFD92, 0, 3 | DECOMP_COMPAT, 4503},
+ {0xFD93, 0, 3 | DECOMP_COMPAT, 4506},
+ {0xFD94, 0, 3 | DECOMP_COMPAT, 4509},
+ {0xFD95, 0, 3 | DECOMP_COMPAT, 4512},
+ {0xFD96, 0, 3 | DECOMP_COMPAT, 4515},
+ {0xFD97, 0, 3 | DECOMP_COMPAT, 4518},
+ {0xFD98, 0, 3 | DECOMP_COMPAT, 4521},
+ {0xFD99, 0, 3 | DECOMP_COMPAT, 4524},
+ {0xFD9A, 0, 3 | DECOMP_COMPAT, 4527},
+ {0xFD9B, 0, 3 | DECOMP_COMPAT, 4530},
+ {0xFD9C, 0, 3 | DECOMP_COMPAT, 4533},
+ {0xFD9D, 0, 3 | DECOMP_COMPAT, 4536},
+ {0xFD9E, 0, 3 | DECOMP_COMPAT, 4539},
+ {0xFD9F, 0, 3 | DECOMP_COMPAT, 4542},
+ {0xFDA0, 0, 3 | DECOMP_COMPAT, 4545},
+ {0xFDA1, 0, 3 | DECOMP_COMPAT, 4548},
+ {0xFDA2, 0, 3 | DECOMP_COMPAT, 4551},
+ {0xFDA3, 0, 3 | DECOMP_COMPAT, 4554},
+ {0xFDA4, 0, 3 | DECOMP_COMPAT, 4557},
+ {0xFDA5, 0, 3 | DECOMP_COMPAT, 4560},
+ {0xFDA6, 0, 3 | DECOMP_COMPAT, 4563},
+ {0xFDA7, 0, 3 | DECOMP_COMPAT, 4566},
+ {0xFDA8, 0, 3 | DECOMP_COMPAT, 4569},
+ {0xFDA9, 0, 3 | DECOMP_COMPAT, 4572},
+ {0xFDAA, 0, 3 | DECOMP_COMPAT, 4575},
+ {0xFDAB, 0, 3 | DECOMP_COMPAT, 4578},
+ {0xFDAC, 0, 3 | DECOMP_COMPAT, 4581},
+ {0xFDAD, 0, 3 | DECOMP_COMPAT, 4584},
+ {0xFDAE, 0, 3 | DECOMP_COMPAT, 4587},
+ {0xFDAF, 0, 3 | DECOMP_COMPAT, 4590},
+ {0xFDB0, 0, 3 | DECOMP_COMPAT, 4593},
+ {0xFDB1, 0, 3 | DECOMP_COMPAT, 4596},
+ {0xFDB2, 0, 3 | DECOMP_COMPAT, 4599},
+ {0xFDB3, 0, 3 | DECOMP_COMPAT, 4602},
+ {0xFDB4, 0, 3 | DECOMP_COMPAT, 4605},
+ {0xFDB5, 0, 3 | DECOMP_COMPAT, 4608},
+ {0xFDB6, 0, 3 | DECOMP_COMPAT, 4611},
+ {0xFDB7, 0, 3 | DECOMP_COMPAT, 4614},
+ {0xFDB8, 0, 3 | DECOMP_COMPAT, 4617},
+ {0xFDB9, 0, 3 | DECOMP_COMPAT, 4620},
+ {0xFDBA, 0, 3 | DECOMP_COMPAT, 4623},
+ {0xFDBB, 0, 3 | DECOMP_COMPAT, 4626},
+ {0xFDBC, 0, 3 | DECOMP_COMPAT, 4629},
+ {0xFDBD, 0, 3 | DECOMP_COMPAT, 4632},
+ {0xFDBE, 0, 3 | DECOMP_COMPAT, 4635},
+ {0xFDBF, 0, 3 | DECOMP_COMPAT, 4638},
+ {0xFDC0, 0, 3 | DECOMP_COMPAT, 4641},
+ {0xFDC1, 0, 3 | DECOMP_COMPAT, 4644},
+ {0xFDC2, 0, 3 | DECOMP_COMPAT, 4647},
+ {0xFDC3, 0, 3 | DECOMP_COMPAT, 4650},
+ {0xFDC4, 0, 3 | DECOMP_COMPAT, 4653},
+ {0xFDC5, 0, 3 | DECOMP_COMPAT, 4656},
+ {0xFDC6, 0, 3 | DECOMP_COMPAT, 4659},
+ {0xFDC7, 0, 3 | DECOMP_COMPAT, 4662},
+ {0xFDF0, 0, 3 | DECOMP_COMPAT, 4665},
+ {0xFDF1, 0, 3 | DECOMP_COMPAT, 4668},
+ {0xFDF2, 0, 4 | DECOMP_COMPAT, 4671},
+ {0xFDF3, 0, 4 | DECOMP_COMPAT, 4675},
+ {0xFDF4, 0, 4 | DECOMP_COMPAT, 4679},
+ {0xFDF5, 0, 4 | DECOMP_COMPAT, 4683},
+ {0xFDF6, 0, 4 | DECOMP_COMPAT, 4687},
+ {0xFDF7, 0, 4 | DECOMP_COMPAT, 4691},
+ {0xFDF8, 0, 4 | DECOMP_COMPAT, 4695},
+ {0xFDF9, 0, 3 | DECOMP_COMPAT, 4699},
+ {0xFDFA, 0, 18 | DECOMP_COMPAT, 4702},
+ {0xFDFB, 0, 8 | DECOMP_COMPAT, 4720},
+ {0xFDFC, 0, 4 | DECOMP_COMPAT, 4728},
+ {0xFE10, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002C},
+ {0xFE11, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3001},
+ {0xFE12, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3002},
+ {0xFE13, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003A},
+ {0xFE14, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003B},
+ {0xFE15, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0021},
+ {0xFE16, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003F},
+ {0xFE17, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3016},
+ {0xFE18, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3017},
+ {0xFE19, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2026},
+ {0xFE20, 230, 0, 0},
+ {0xFE21, 230, 0, 0},
+ {0xFE22, 230, 0, 0},
+ {0xFE23, 230, 0, 0},
+ {0xFE24, 230, 0, 0},
+ {0xFE25, 230, 0, 0},
+ {0xFE26, 230, 0, 0},
+ {0xFE27, 220, 0, 0},
+ {0xFE28, 220, 0, 0},
+ {0xFE29, 220, 0, 0},
+ {0xFE2A, 220, 0, 0},
+ {0xFE2B, 220, 0, 0},
+ {0xFE2C, 220, 0, 0},
+ {0xFE2D, 220, 0, 0},
+ {0xFE2E, 230, 0, 0},
+ {0xFE2F, 230, 0, 0},
+ {0xFE30, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2025},
+ {0xFE31, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2014},
+ {0xFE32, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2013},
+ {0xFE33, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005F},
+ {0xFE34, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005F},
+ {0xFE35, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0028},
+ {0xFE36, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0029},
+ {0xFE37, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007B},
+ {0xFE38, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007D},
+ {0xFE39, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3014},
+ {0xFE3A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3015},
+ {0xFE3B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3010},
+ {0xFE3C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3011},
+ {0xFE3D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x300A},
+ {0xFE3E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x300B},
+ {0xFE3F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3008},
+ {0xFE40, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3009},
+ {0xFE41, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x300C},
+ {0xFE42, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x300D},
+ {0xFE43, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x300E},
+ {0xFE44, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x300F},
+ {0xFE47, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005B},
+ {0xFE48, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005D},
+ {0xFE49, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x203E},
+ {0xFE4A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x203E},
+ {0xFE4B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x203E},
+ {0xFE4C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x203E},
+ {0xFE4D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005F},
+ {0xFE4E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005F},
+ {0xFE4F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005F},
+ {0xFE50, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002C},
+ {0xFE51, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3001},
+ {0xFE52, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002E},
+ {0xFE54, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003B},
+ {0xFE55, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003A},
+ {0xFE56, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003F},
+ {0xFE57, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0021},
+ {0xFE58, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2014},
+ {0xFE59, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0028},
+ {0xFE5A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0029},
+ {0xFE5B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007B},
+ {0xFE5C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007D},
+ {0xFE5D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3014},
+ {0xFE5E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3015},
+ {0xFE5F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0023},
+ {0xFE60, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0026},
+ {0xFE61, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002A},
+ {0xFE62, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002B},
+ {0xFE63, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002D},
+ {0xFE64, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003C},
+ {0xFE65, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003E},
+ {0xFE66, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003D},
+ {0xFE68, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005C},
+ {0xFE69, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0024},
+ {0xFE6A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0025},
+ {0xFE6B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0040},
+ {0xFE70, 0, 2 | DECOMP_COMPAT, 4732},
+ {0xFE71, 0, 2 | DECOMP_COMPAT, 4734},
+ {0xFE72, 0, 2 | DECOMP_COMPAT, 4736},
+ {0xFE74, 0, 2 | DECOMP_COMPAT, 4738},
+ {0xFE76, 0, 2 | DECOMP_COMPAT, 4740},
+ {0xFE77, 0, 2 | DECOMP_COMPAT, 4742},
+ {0xFE78, 0, 2 | DECOMP_COMPAT, 4744},
+ {0xFE79, 0, 2 | DECOMP_COMPAT, 4746},
+ {0xFE7A, 0, 2 | DECOMP_COMPAT, 4748},
+ {0xFE7B, 0, 2 | DECOMP_COMPAT, 4750},
+ {0xFE7C, 0, 2 | DECOMP_COMPAT, 4752},
+ {0xFE7D, 0, 2 | DECOMP_COMPAT, 4754},
+ {0xFE7E, 0, 2 | DECOMP_COMPAT, 4756},
+ {0xFE7F, 0, 2 | DECOMP_COMPAT, 4758},
+ {0xFE80, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0621},
+ {0xFE81, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0622},
+ {0xFE82, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0622},
+ {0xFE83, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0623},
+ {0xFE84, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0623},
+ {0xFE85, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0624},
+ {0xFE86, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0624},
+ {0xFE87, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0625},
+ {0xFE88, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0625},
+ {0xFE89, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0626},
+ {0xFE8A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0626},
+ {0xFE8B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0626},
+ {0xFE8C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0626},
+ {0xFE8D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0627},
+ {0xFE8E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0627},
+ {0xFE8F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0628},
+ {0xFE90, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0628},
+ {0xFE91, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0628},
+ {0xFE92, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0628},
+ {0xFE93, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0629},
+ {0xFE94, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0629},
+ {0xFE95, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062A},
+ {0xFE96, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062A},
+ {0xFE97, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062A},
+ {0xFE98, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062A},
+ {0xFE99, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062B},
+ {0xFE9A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062B},
+ {0xFE9B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062B},
+ {0xFE9C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062B},
+ {0xFE9D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0xFE9E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0xFE9F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0xFEA0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0xFEA1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0xFEA2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0xFEA3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0xFEA4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0xFEA5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0xFEA6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0xFEA7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0xFEA8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0xFEA9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062F},
+ {0xFEAA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062F},
+ {0xFEAB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0630},
+ {0xFEAC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0630},
+ {0xFEAD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0631},
+ {0xFEAE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0631},
+ {0xFEAF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0632},
+ {0xFEB0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0632},
+ {0xFEB1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0xFEB2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0xFEB3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0xFEB4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0xFEB5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0xFEB6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0xFEB7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0xFEB8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0xFEB9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0xFEBA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0xFEBB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0xFEBC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0xFEBD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0xFEBE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0xFEBF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0xFEC0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0xFEC1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0637},
+ {0xFEC2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0637},
+ {0xFEC3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0637},
+ {0xFEC4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0637},
+ {0xFEC5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0638},
+ {0xFEC6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0638},
+ {0xFEC7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0638},
+ {0xFEC8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0638},
+ {0xFEC9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0xFECA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0xFECB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0xFECC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0xFECD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0xFECE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0xFECF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0xFED0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0xFED1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0641},
+ {0xFED2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0641},
+ {0xFED3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0641},
+ {0xFED4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0641},
+ {0xFED5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0xFED6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0xFED7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0xFED8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0xFED9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0643},
+ {0xFEDA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0643},
+ {0xFEDB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0643},
+ {0xFEDC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0643},
+ {0xFEDD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0644},
+ {0xFEDE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0644},
+ {0xFEDF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0644},
+ {0xFEE0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0644},
+ {0xFEE1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0645},
+ {0xFEE2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0645},
+ {0xFEE3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0645},
+ {0xFEE4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0645},
+ {0xFEE5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0xFEE6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0xFEE7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0xFEE8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0xFEE9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0647},
+ {0xFEEA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0647},
+ {0xFEEB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0647},
+ {0xFEEC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0647},
+ {0xFEED, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0648},
+ {0xFEEE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0648},
+ {0xFEEF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0649},
+ {0xFEF0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0649},
+ {0xFEF1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0xFEF2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0xFEF3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0xFEF4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0xFEF5, 0, 2 | DECOMP_COMPAT, 4760},
+ {0xFEF6, 0, 2 | DECOMP_COMPAT, 4762},
+ {0xFEF7, 0, 2 | DECOMP_COMPAT, 4764},
+ {0xFEF8, 0, 2 | DECOMP_COMPAT, 4766},
+ {0xFEF9, 0, 2 | DECOMP_COMPAT, 4768},
+ {0xFEFA, 0, 2 | DECOMP_COMPAT, 4770},
+ {0xFEFB, 0, 2 | DECOMP_COMPAT, 4772},
+ {0xFEFC, 0, 2 | DECOMP_COMPAT, 4774},
+ {0xFF01, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0021},
+ {0xFF02, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0022},
+ {0xFF03, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0023},
+ {0xFF04, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0024},
+ {0xFF05, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0025},
+ {0xFF06, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0026},
+ {0xFF07, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0027},
+ {0xFF08, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0028},
+ {0xFF09, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0029},
+ {0xFF0A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002A},
+ {0xFF0B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002B},
+ {0xFF0C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002C},
+ {0xFF0D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002D},
+ {0xFF0E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002E},
+ {0xFF0F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x002F},
+ {0xFF10, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0xFF11, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0xFF12, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0xFF13, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0xFF14, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0xFF15, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0xFF16, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0xFF17, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0xFF18, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0xFF19, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0xFF1A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003A},
+ {0xFF1B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003B},
+ {0xFF1C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003C},
+ {0xFF1D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003D},
+ {0xFF1E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003E},
+ {0xFF1F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x003F},
+ {0xFF20, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0040},
+ {0xFF21, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0xFF22, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0xFF23, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0xFF24, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0xFF25, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0xFF26, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0xFF27, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0xFF28, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0xFF29, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0xFF2A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0xFF2B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0xFF2C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0xFF2D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0xFF2E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0xFF2F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0xFF30, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0xFF31, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0xFF32, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0xFF33, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0xFF34, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0xFF35, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0xFF36, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0xFF37, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0xFF38, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0xFF39, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0xFF3A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0xFF3B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005B},
+ {0xFF3C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005C},
+ {0xFF3D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005D},
+ {0xFF3E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005E},
+ {0xFF3F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005F},
+ {0xFF40, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0060},
+ {0xFF41, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0xFF42, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0xFF43, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0xFF44, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0xFF45, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0xFF46, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0xFF47, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0xFF48, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0xFF49, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0xFF4A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0xFF4B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0xFF4C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0xFF4D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0xFF4E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0xFF4F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0xFF50, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0xFF51, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0xFF52, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0xFF53, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0xFF54, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0xFF55, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0xFF56, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0xFF57, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0xFF58, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0xFF59, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0xFF5A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0xFF5B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007B},
+ {0xFF5C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007C},
+ {0xFF5D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007D},
+ {0xFF5E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007E},
+ {0xFF5F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2985},
+ {0xFF60, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2986},
+ {0xFF61, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3002},
+ {0xFF62, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x300C},
+ {0xFF63, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x300D},
+ {0xFF64, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3001},
+ {0xFF65, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30FB},
+ {0xFF66, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30F2},
+ {0xFF67, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A1},
+ {0xFF68, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A3},
+ {0xFF69, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A5},
+ {0xFF6A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A7},
+ {0xFF6B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A9},
+ {0xFF6C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E3},
+ {0xFF6D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E5},
+ {0xFF6E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E7},
+ {0xFF6F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C3},
+ {0xFF70, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30FC},
+ {0xFF71, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A2},
+ {0xFF72, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A4},
+ {0xFF73, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A6},
+ {0xFF74, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30A8},
+ {0xFF75, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30AA},
+ {0xFF76, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30AB},
+ {0xFF77, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30AD},
+ {0xFF78, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30AF},
+ {0xFF79, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B1},
+ {0xFF7A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B3},
+ {0xFF7B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B5},
+ {0xFF7C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B7},
+ {0xFF7D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B9},
+ {0xFF7E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30BB},
+ {0xFF7F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30BD},
+ {0xFF80, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30BF},
+ {0xFF81, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C1},
+ {0xFF82, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C4},
+ {0xFF83, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C6},
+ {0xFF84, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C8},
+ {0xFF85, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CA},
+ {0xFF86, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CB},
+ {0xFF87, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CC},
+ {0xFF88, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CD},
+ {0xFF89, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CE},
+ {0xFF8A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30CF},
+ {0xFF8B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30D2},
+ {0xFF8C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30D5},
+ {0xFF8D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30D8},
+ {0xFF8E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30DB},
+ {0xFF8F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30DE},
+ {0xFF90, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30DF},
+ {0xFF91, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E0},
+ {0xFF92, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E1},
+ {0xFF93, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E2},
+ {0xFF94, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E4},
+ {0xFF95, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E6},
+ {0xFF96, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E8},
+ {0xFF97, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30E9},
+ {0xFF98, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30EA},
+ {0xFF99, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30EB},
+ {0xFF9A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30EC},
+ {0xFF9B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30ED},
+ {0xFF9C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30EF},
+ {0xFF9D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30F3},
+ {0xFF9E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3099},
+ {0xFF9F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x309A},
+ {0xFFA0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3164},
+ {0xFFA1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3131},
+ {0xFFA2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3132},
+ {0xFFA3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3133},
+ {0xFFA4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3134},
+ {0xFFA5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3135},
+ {0xFFA6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3136},
+ {0xFFA7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3137},
+ {0xFFA8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3138},
+ {0xFFA9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3139},
+ {0xFFAA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x313A},
+ {0xFFAB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x313B},
+ {0xFFAC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x313C},
+ {0xFFAD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x313D},
+ {0xFFAE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x313E},
+ {0xFFAF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x313F},
+ {0xFFB0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3140},
+ {0xFFB1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3141},
+ {0xFFB2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3142},
+ {0xFFB3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3143},
+ {0xFFB4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3144},
+ {0xFFB5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3145},
+ {0xFFB6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3146},
+ {0xFFB7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3147},
+ {0xFFB8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3148},
+ {0xFFB9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3149},
+ {0xFFBA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x314A},
+ {0xFFBB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x314B},
+ {0xFFBC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x314C},
+ {0xFFBD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x314D},
+ {0xFFBE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x314E},
+ {0xFFC2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x314F},
+ {0xFFC3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3150},
+ {0xFFC4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3151},
+ {0xFFC5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3152},
+ {0xFFC6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3153},
+ {0xFFC7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3154},
+ {0xFFCA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3155},
+ {0xFFCB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3156},
+ {0xFFCC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3157},
+ {0xFFCD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3158},
+ {0xFFCE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3159},
+ {0xFFCF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x315A},
+ {0xFFD2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x315B},
+ {0xFFD3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x315C},
+ {0xFFD4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x315D},
+ {0xFFD5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x315E},
+ {0xFFD6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x315F},
+ {0xFFD7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3160},
+ {0xFFDA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3161},
+ {0xFFDB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3162},
+ {0xFFDC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x3163},
+ {0xFFE0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00A2},
+ {0xFFE1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00A3},
+ {0xFFE2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00AC},
+ {0xFFE3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00AF},
+ {0xFFE4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00A6},
+ {0xFFE5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x00A5},
+ {0xFFE6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x20A9},
+ {0xFFE8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2502},
+ {0xFFE9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2190},
+ {0xFFEA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2191},
+ {0xFFEB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2192},
+ {0xFFEC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2193},
+ {0xFFED, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x25A0},
+ {0xFFEE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x25CB},
+ {0x101FD, 220, 0, 0},
+ {0x102E0, 220, 0, 0},
+ {0x10376, 230, 0, 0},
+ {0x10377, 230, 0, 0},
+ {0x10378, 230, 0, 0},
+ {0x10379, 230, 0, 0},
+ {0x1037A, 230, 0, 0},
+ {0x10A0D, 220, 0, 0},
+ {0x10A0F, 230, 0, 0},
+ {0x10A38, 230, 0, 0},
+ {0x10A39, 1, 0, 0},
+ {0x10A3A, 220, 0, 0},
+ {0x10A3F, 9, 0, 0},
+ {0x10AE5, 230, 0, 0},
+ {0x10AE6, 220, 0, 0},
+ {0x10D24, 230, 0, 0},
+ {0x10D25, 230, 0, 0},
+ {0x10D26, 230, 0, 0},
+ {0x10D27, 230, 0, 0},
+ {0x10EAB, 230, 0, 0},
+ {0x10EAC, 230, 0, 0},
+ {0x10F46, 220, 0, 0},
+ {0x10F47, 220, 0, 0},
+ {0x10F48, 230, 0, 0},
+ {0x10F49, 230, 0, 0},
+ {0x10F4A, 230, 0, 0},
+ {0x10F4B, 220, 0, 0},
+ {0x10F4C, 230, 0, 0},
+ {0x10F4D, 220, 0, 0},
+ {0x10F4E, 220, 0, 0},
+ {0x10F4F, 220, 0, 0},
+ {0x10F50, 220, 0, 0},
+ {0x11046, 9, 0, 0},
+ {0x1107F, 9, 0, 0},
+ {0x1109A, 0, 2, 4776},
+ {0x1109C, 0, 2, 4778},
+ {0x110AB, 0, 2, 4780},
+ {0x110B9, 9, 0, 0},
+ {0x110BA, 7, 0, 0},
+ {0x11100, 230, 0, 0},
+ {0x11101, 230, 0, 0},
+ {0x11102, 230, 0, 0},
+ {0x1112E, 0, 2, 4782},
+ {0x1112F, 0, 2, 4784},
+ {0x11133, 9, 0, 0},
+ {0x11134, 9, 0, 0},
+ {0x11173, 7, 0, 0},
+ {0x111C0, 9, 0, 0},
+ {0x111CA, 7, 0, 0},
+ {0x11235, 9, 0, 0},
+ {0x11236, 7, 0, 0},
+ {0x112E9, 7, 0, 0},
+ {0x112EA, 9, 0, 0},
+ {0x1133B, 7, 0, 0},
+ {0x1133C, 7, 0, 0},
+ {0x1134B, 0, 2, 4786},
+ {0x1134C, 0, 2, 4788},
+ {0x1134D, 9, 0, 0},
+ {0x11366, 230, 0, 0},
+ {0x11367, 230, 0, 0},
+ {0x11368, 230, 0, 0},
+ {0x11369, 230, 0, 0},
+ {0x1136A, 230, 0, 0},
+ {0x1136B, 230, 0, 0},
+ {0x1136C, 230, 0, 0},
+ {0x11370, 230, 0, 0},
+ {0x11371, 230, 0, 0},
+ {0x11372, 230, 0, 0},
+ {0x11373, 230, 0, 0},
+ {0x11374, 230, 0, 0},
+ {0x11442, 9, 0, 0},
+ {0x11446, 7, 0, 0},
+ {0x1145E, 230, 0, 0},
+ {0x114BB, 0, 2, 4790},
+ {0x114BC, 0, 2, 4792},
+ {0x114BE, 0, 2, 4794},
+ {0x114C2, 9, 0, 0},
+ {0x114C3, 7, 0, 0},
+ {0x115BA, 0, 2, 4796},
+ {0x115BB, 0, 2, 4798},
+ {0x115BF, 9, 0, 0},
+ {0x115C0, 7, 0, 0},
+ {0x1163F, 9, 0, 0},
+ {0x116B6, 9, 0, 0},
+ {0x116B7, 7, 0, 0},
+ {0x1172B, 9, 0, 0},
+ {0x11839, 9, 0, 0},
+ {0x1183A, 7, 0, 0},
+ {0x11938, 0, 2, 4800},
+ {0x1193D, 9, 0, 0},
+ {0x1193E, 9, 0, 0},
+ {0x11943, 7, 0, 0},
+ {0x119E0, 9, 0, 0},
+ {0x11A34, 9, 0, 0},
+ {0x11A47, 9, 0, 0},
+ {0x11A99, 9, 0, 0},
+ {0x11C3F, 9, 0, 0},
+ {0x11D42, 7, 0, 0},
+ {0x11D44, 9, 0, 0},
+ {0x11D45, 9, 0, 0},
+ {0x11D97, 9, 0, 0},
+ {0x16AF0, 1, 0, 0},
+ {0x16AF1, 1, 0, 0},
+ {0x16AF2, 1, 0, 0},
+ {0x16AF3, 1, 0, 0},
+ {0x16AF4, 1, 0, 0},
+ {0x16B30, 230, 0, 0},
+ {0x16B31, 230, 0, 0},
+ {0x16B32, 230, 0, 0},
+ {0x16B33, 230, 0, 0},
+ {0x16B34, 230, 0, 0},
+ {0x16B35, 230, 0, 0},
+ {0x16B36, 230, 0, 0},
+ {0x16FF0, 6, 0, 0},
+ {0x16FF1, 6, 0, 0},
+ {0x1BC9E, 1, 0, 0},
+ {0x1D15E, 0, 2 | DECOMP_NO_COMPOSE, 4802}, /* in exclusion list */
+ {0x1D15F, 0, 2 | DECOMP_NO_COMPOSE, 4804}, /* in exclusion list */
+ {0x1D160, 0, 2 | DECOMP_NO_COMPOSE, 4806}, /* in exclusion list */
+ {0x1D161, 0, 2 | DECOMP_NO_COMPOSE, 4808}, /* in exclusion list */
+ {0x1D162, 0, 2 | DECOMP_NO_COMPOSE, 4810}, /* in exclusion list */
+ {0x1D163, 0, 2 | DECOMP_NO_COMPOSE, 4812}, /* in exclusion list */
+ {0x1D164, 0, 2 | DECOMP_NO_COMPOSE, 4814}, /* in exclusion list */
+ {0x1D165, 216, 0, 0},
+ {0x1D166, 216, 0, 0},
+ {0x1D167, 1, 0, 0},
+ {0x1D168, 1, 0, 0},
+ {0x1D169, 1, 0, 0},
+ {0x1D16D, 226, 0, 0},
+ {0x1D16E, 216, 0, 0},
+ {0x1D16F, 216, 0, 0},
+ {0x1D170, 216, 0, 0},
+ {0x1D171, 216, 0, 0},
+ {0x1D172, 216, 0, 0},
+ {0x1D17B, 220, 0, 0},
+ {0x1D17C, 220, 0, 0},
+ {0x1D17D, 220, 0, 0},
+ {0x1D17E, 220, 0, 0},
+ {0x1D17F, 220, 0, 0},
+ {0x1D180, 220, 0, 0},
+ {0x1D181, 220, 0, 0},
+ {0x1D182, 220, 0, 0},
+ {0x1D185, 230, 0, 0},
+ {0x1D186, 230, 0, 0},
+ {0x1D187, 230, 0, 0},
+ {0x1D188, 230, 0, 0},
+ {0x1D189, 230, 0, 0},
+ {0x1D18A, 220, 0, 0},
+ {0x1D18B, 220, 0, 0},
+ {0x1D1AA, 230, 0, 0},
+ {0x1D1AB, 230, 0, 0},
+ {0x1D1AC, 230, 0, 0},
+ {0x1D1AD, 230, 0, 0},
+ {0x1D1BB, 0, 2 | DECOMP_NO_COMPOSE, 4816}, /* in exclusion list */
+ {0x1D1BC, 0, 2 | DECOMP_NO_COMPOSE, 4818}, /* in exclusion list */
+ {0x1D1BD, 0, 2 | DECOMP_NO_COMPOSE, 4820}, /* in exclusion list */
+ {0x1D1BE, 0, 2 | DECOMP_NO_COMPOSE, 4822}, /* in exclusion list */
+ {0x1D1BF, 0, 2 | DECOMP_NO_COMPOSE, 4824}, /* in exclusion list */
+ {0x1D1C0, 0, 2 | DECOMP_NO_COMPOSE, 4826}, /* in exclusion list */
+ {0x1D242, 230, 0, 0},
+ {0x1D243, 230, 0, 0},
+ {0x1D244, 230, 0, 0},
+ {0x1D400, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D401, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D402, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D403, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D404, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D405, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D406, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D407, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D408, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D409, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D40A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D40B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D40C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D40D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D40E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D40F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D410, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D411, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D412, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D413, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D414, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D415, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D416, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D417, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D418, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D419, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D41A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D41B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D41C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D41D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D41E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D41F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D420, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D421, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D422, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D423, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D424, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D425, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D426, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D427, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D428, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D429, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D42A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D42B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D42C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D42D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D42E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D42F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D430, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D431, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D432, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D433, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D434, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D435, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D436, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D437, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D438, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D439, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D43A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D43B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D43C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D43D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D43E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D43F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D440, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D441, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D442, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D443, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D444, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D445, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D446, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D447, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D448, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D449, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D44A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D44B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D44C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D44D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D44E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D44F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D450, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D451, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D452, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D453, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D454, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D456, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D457, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D458, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D459, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D45A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D45B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D45C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D45D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D45E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D45F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D460, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D461, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D462, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D463, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D464, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D465, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D466, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D467, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D468, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D469, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D46A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D46B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D46C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D46D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D46E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D46F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D470, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D471, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D472, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D473, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D474, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D475, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D476, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D477, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D478, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D479, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D47A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D47B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D47C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D47D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D47E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D47F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D480, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D481, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D482, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D483, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D484, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D485, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D486, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D487, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D488, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D489, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D48A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D48B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D48C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D48D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D48E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D48F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D490, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D491, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D492, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D493, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D494, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D495, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D496, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D497, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D498, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D499, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D49A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D49B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D49C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D49E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D49F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D4A2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D4A5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D4A6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D4A9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D4AA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D4AB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D4AC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D4AE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D4AF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D4B0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D4B1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D4B2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D4B3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D4B4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D4B5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D4B6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D4B7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D4B8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D4B9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D4BB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D4BD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D4BE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D4BF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D4C0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D4C1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D4C2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D4C3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D4C5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D4C6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D4C7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D4C8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D4C9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D4CA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D4CB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D4CC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D4CD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D4CE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D4CF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D4D0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D4D1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D4D2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D4D3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D4D4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D4D5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D4D6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D4D7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D4D8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D4D9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D4DA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D4DB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D4DC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D4DD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D4DE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D4DF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D4E0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D4E1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D4E2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D4E3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D4E4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D4E5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D4E6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D4E7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D4E8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D4E9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D4EA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D4EB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D4EC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D4ED, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D4EE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D4EF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D4F0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D4F1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D4F2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D4F3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D4F4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D4F5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D4F6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D4F7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D4F8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D4F9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D4FA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D4FB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D4FC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D4FD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D4FE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D4FF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D500, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D501, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D502, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D503, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D504, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D505, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D507, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D508, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D509, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D50A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D50D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D50E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D50F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D510, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D511, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D512, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D513, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D514, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D516, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D517, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D518, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D519, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D51A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D51B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D51C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D51E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D51F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D520, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D521, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D522, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D523, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D524, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D525, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D526, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D527, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D528, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D529, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D52A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D52B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D52C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D52D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D52E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D52F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D530, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D531, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D532, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D533, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D534, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D535, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D536, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D537, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D538, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D539, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D53B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D53C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D53D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D53E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D540, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D541, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D542, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D543, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D544, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D546, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D54A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D54B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D54C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D54D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D54E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D54F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D550, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D552, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D553, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D554, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D555, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D556, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D557, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D558, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D559, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D55A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D55B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D55C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D55D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D55E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D55F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D560, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D561, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D562, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D563, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D564, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D565, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D566, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D567, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D568, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D569, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D56A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D56B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D56C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D56D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D56E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D56F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D570, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D571, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D572, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D573, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D574, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D575, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D576, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D577, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D578, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D579, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D57A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D57B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D57C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D57D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D57E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D57F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D580, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D581, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D582, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D583, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D584, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D585, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D586, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D587, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D588, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D589, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D58A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D58B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D58C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D58D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D58E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D58F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D590, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D591, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D592, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D593, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D594, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D595, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D596, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D597, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D598, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D599, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D59A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D59B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D59C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D59D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D59E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D59F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D5A0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D5A1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D5A2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D5A3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D5A4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D5A5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D5A6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D5A7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D5A8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D5A9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D5AA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D5AB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D5AC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D5AD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D5AE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D5AF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D5B0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D5B1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D5B2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D5B3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D5B4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D5B5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D5B6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D5B7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D5B8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D5B9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D5BA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D5BB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D5BC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D5BD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D5BE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D5BF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D5C0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D5C1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D5C2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D5C3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D5C4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D5C5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D5C6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D5C7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D5C8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D5C9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D5CA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D5CB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D5CC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D5CD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D5CE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D5CF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D5D0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D5D1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D5D2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D5D3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D5D4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D5D5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D5D6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D5D7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D5D8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D5D9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D5DA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D5DB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D5DC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D5DD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D5DE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D5DF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D5E0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D5E1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D5E2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D5E3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D5E4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D5E5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D5E6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D5E7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D5E8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D5E9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D5EA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D5EB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D5EC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D5ED, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D5EE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D5EF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D5F0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D5F1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D5F2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D5F3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D5F4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D5F5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D5F6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D5F7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D5F8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D5F9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D5FA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D5FB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D5FC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D5FD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D5FE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D5FF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D600, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D601, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D602, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D603, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D604, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D605, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D606, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D607, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D608, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D609, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D60A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D60B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D60C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D60D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D60E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D60F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D610, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D611, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D612, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D613, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D614, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D615, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D616, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D617, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D618, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D619, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D61A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D61B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D61C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D61D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D61E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D61F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D620, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D621, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D622, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D623, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D624, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D625, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D626, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D627, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D628, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D629, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D62A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D62B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D62C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D62D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D62E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D62F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D630, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D631, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D632, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D633, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D634, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D635, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D636, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D637, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D638, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D639, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D63A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D63B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D63C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D63D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D63E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D63F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D640, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D641, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D642, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D643, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D644, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D645, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D646, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D647, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D648, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D649, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D64A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D64B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D64C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D64D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D64E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D64F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D650, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D651, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D652, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D653, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D654, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D655, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D656, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D657, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D658, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D659, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D65A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D65B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D65C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D65D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D65E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D65F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D660, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D661, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D662, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D663, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D664, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D665, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D666, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D667, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D668, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D669, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D66A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D66B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D66C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D66D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D66E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D66F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D670, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1D671, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1D672, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1D673, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1D674, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1D675, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1D676, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1D677, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1D678, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1D679, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1D67A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1D67B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1D67C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1D67D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1D67E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1D67F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1D680, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1D681, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1D682, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1D683, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1D684, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1D685, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1D686, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1D687, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1D688, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1D689, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1D68A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0061},
+ {0x1D68B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0062},
+ {0x1D68C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0063},
+ {0x1D68D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0064},
+ {0x1D68E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0065},
+ {0x1D68F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0066},
+ {0x1D690, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0067},
+ {0x1D691, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0068},
+ {0x1D692, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0069},
+ {0x1D693, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006A},
+ {0x1D694, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006B},
+ {0x1D695, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006C},
+ {0x1D696, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006D},
+ {0x1D697, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006E},
+ {0x1D698, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x006F},
+ {0x1D699, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0070},
+ {0x1D69A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0071},
+ {0x1D69B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0072},
+ {0x1D69C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0073},
+ {0x1D69D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0074},
+ {0x1D69E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0075},
+ {0x1D69F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0076},
+ {0x1D6A0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0077},
+ {0x1D6A1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0078},
+ {0x1D6A2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0079},
+ {0x1D6A3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x007A},
+ {0x1D6A4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0131},
+ {0x1D6A5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0237},
+ {0x1D6A8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0391},
+ {0x1D6A9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0392},
+ {0x1D6AA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0393},
+ {0x1D6AB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0394},
+ {0x1D6AC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0395},
+ {0x1D6AD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0396},
+ {0x1D6AE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0397},
+ {0x1D6AF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0398},
+ {0x1D6B0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0399},
+ {0x1D6B1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039A},
+ {0x1D6B2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039B},
+ {0x1D6B3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039C},
+ {0x1D6B4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039D},
+ {0x1D6B5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039E},
+ {0x1D6B6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039F},
+ {0x1D6B7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A0},
+ {0x1D6B8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A1},
+ {0x1D6B9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F4},
+ {0x1D6BA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A3},
+ {0x1D6BB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A4},
+ {0x1D6BC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A5},
+ {0x1D6BD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A6},
+ {0x1D6BE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A7},
+ {0x1D6BF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A8},
+ {0x1D6C0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A9},
+ {0x1D6C1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2207},
+ {0x1D6C2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B1},
+ {0x1D6C3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B2},
+ {0x1D6C4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B3},
+ {0x1D6C5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B4},
+ {0x1D6C6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B5},
+ {0x1D6C7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B6},
+ {0x1D6C8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B7},
+ {0x1D6C9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B8},
+ {0x1D6CA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B9},
+ {0x1D6CB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BA},
+ {0x1D6CC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BB},
+ {0x1D6CD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BC},
+ {0x1D6CE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BD},
+ {0x1D6CF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BE},
+ {0x1D6D0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BF},
+ {0x1D6D1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C0},
+ {0x1D6D2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C1},
+ {0x1D6D3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C2},
+ {0x1D6D4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C3},
+ {0x1D6D5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C4},
+ {0x1D6D6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C5},
+ {0x1D6D7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C6},
+ {0x1D6D8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C7},
+ {0x1D6D9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C8},
+ {0x1D6DA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C9},
+ {0x1D6DB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2202},
+ {0x1D6DC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F5},
+ {0x1D6DD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D1},
+ {0x1D6DE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F0},
+ {0x1D6DF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D5},
+ {0x1D6E0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F1},
+ {0x1D6E1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D6},
+ {0x1D6E2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0391},
+ {0x1D6E3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0392},
+ {0x1D6E4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0393},
+ {0x1D6E5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0394},
+ {0x1D6E6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0395},
+ {0x1D6E7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0396},
+ {0x1D6E8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0397},
+ {0x1D6E9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0398},
+ {0x1D6EA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0399},
+ {0x1D6EB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039A},
+ {0x1D6EC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039B},
+ {0x1D6ED, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039C},
+ {0x1D6EE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039D},
+ {0x1D6EF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039E},
+ {0x1D6F0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039F},
+ {0x1D6F1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A0},
+ {0x1D6F2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A1},
+ {0x1D6F3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F4},
+ {0x1D6F4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A3},
+ {0x1D6F5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A4},
+ {0x1D6F6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A5},
+ {0x1D6F7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A6},
+ {0x1D6F8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A7},
+ {0x1D6F9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A8},
+ {0x1D6FA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A9},
+ {0x1D6FB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2207},
+ {0x1D6FC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B1},
+ {0x1D6FD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B2},
+ {0x1D6FE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B3},
+ {0x1D6FF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B4},
+ {0x1D700, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B5},
+ {0x1D701, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B6},
+ {0x1D702, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B7},
+ {0x1D703, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B8},
+ {0x1D704, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B9},
+ {0x1D705, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BA},
+ {0x1D706, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BB},
+ {0x1D707, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BC},
+ {0x1D708, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BD},
+ {0x1D709, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BE},
+ {0x1D70A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BF},
+ {0x1D70B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C0},
+ {0x1D70C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C1},
+ {0x1D70D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C2},
+ {0x1D70E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C3},
+ {0x1D70F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C4},
+ {0x1D710, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C5},
+ {0x1D711, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C6},
+ {0x1D712, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C7},
+ {0x1D713, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C8},
+ {0x1D714, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C9},
+ {0x1D715, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2202},
+ {0x1D716, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F5},
+ {0x1D717, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D1},
+ {0x1D718, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F0},
+ {0x1D719, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D5},
+ {0x1D71A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F1},
+ {0x1D71B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D6},
+ {0x1D71C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0391},
+ {0x1D71D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0392},
+ {0x1D71E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0393},
+ {0x1D71F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0394},
+ {0x1D720, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0395},
+ {0x1D721, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0396},
+ {0x1D722, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0397},
+ {0x1D723, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0398},
+ {0x1D724, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0399},
+ {0x1D725, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039A},
+ {0x1D726, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039B},
+ {0x1D727, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039C},
+ {0x1D728, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039D},
+ {0x1D729, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039E},
+ {0x1D72A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039F},
+ {0x1D72B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A0},
+ {0x1D72C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A1},
+ {0x1D72D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F4},
+ {0x1D72E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A3},
+ {0x1D72F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A4},
+ {0x1D730, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A5},
+ {0x1D731, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A6},
+ {0x1D732, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A7},
+ {0x1D733, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A8},
+ {0x1D734, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A9},
+ {0x1D735, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2207},
+ {0x1D736, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B1},
+ {0x1D737, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B2},
+ {0x1D738, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B3},
+ {0x1D739, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B4},
+ {0x1D73A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B5},
+ {0x1D73B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B6},
+ {0x1D73C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B7},
+ {0x1D73D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B8},
+ {0x1D73E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B9},
+ {0x1D73F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BA},
+ {0x1D740, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BB},
+ {0x1D741, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BC},
+ {0x1D742, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BD},
+ {0x1D743, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BE},
+ {0x1D744, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BF},
+ {0x1D745, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C0},
+ {0x1D746, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C1},
+ {0x1D747, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C2},
+ {0x1D748, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C3},
+ {0x1D749, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C4},
+ {0x1D74A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C5},
+ {0x1D74B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C6},
+ {0x1D74C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C7},
+ {0x1D74D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C8},
+ {0x1D74E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C9},
+ {0x1D74F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2202},
+ {0x1D750, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F5},
+ {0x1D751, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D1},
+ {0x1D752, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F0},
+ {0x1D753, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D5},
+ {0x1D754, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F1},
+ {0x1D755, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D6},
+ {0x1D756, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0391},
+ {0x1D757, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0392},
+ {0x1D758, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0393},
+ {0x1D759, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0394},
+ {0x1D75A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0395},
+ {0x1D75B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0396},
+ {0x1D75C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0397},
+ {0x1D75D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0398},
+ {0x1D75E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0399},
+ {0x1D75F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039A},
+ {0x1D760, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039B},
+ {0x1D761, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039C},
+ {0x1D762, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039D},
+ {0x1D763, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039E},
+ {0x1D764, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039F},
+ {0x1D765, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A0},
+ {0x1D766, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A1},
+ {0x1D767, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F4},
+ {0x1D768, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A3},
+ {0x1D769, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A4},
+ {0x1D76A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A5},
+ {0x1D76B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A6},
+ {0x1D76C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A7},
+ {0x1D76D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A8},
+ {0x1D76E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A9},
+ {0x1D76F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2207},
+ {0x1D770, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B1},
+ {0x1D771, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B2},
+ {0x1D772, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B3},
+ {0x1D773, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B4},
+ {0x1D774, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B5},
+ {0x1D775, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B6},
+ {0x1D776, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B7},
+ {0x1D777, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B8},
+ {0x1D778, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B9},
+ {0x1D779, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BA},
+ {0x1D77A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BB},
+ {0x1D77B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BC},
+ {0x1D77C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BD},
+ {0x1D77D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BE},
+ {0x1D77E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BF},
+ {0x1D77F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C0},
+ {0x1D780, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C1},
+ {0x1D781, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C2},
+ {0x1D782, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C3},
+ {0x1D783, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C4},
+ {0x1D784, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C5},
+ {0x1D785, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C6},
+ {0x1D786, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C7},
+ {0x1D787, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C8},
+ {0x1D788, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C9},
+ {0x1D789, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2202},
+ {0x1D78A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F5},
+ {0x1D78B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D1},
+ {0x1D78C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F0},
+ {0x1D78D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D5},
+ {0x1D78E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F1},
+ {0x1D78F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D6},
+ {0x1D790, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0391},
+ {0x1D791, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0392},
+ {0x1D792, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0393},
+ {0x1D793, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0394},
+ {0x1D794, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0395},
+ {0x1D795, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0396},
+ {0x1D796, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0397},
+ {0x1D797, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0398},
+ {0x1D798, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0399},
+ {0x1D799, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039A},
+ {0x1D79A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039B},
+ {0x1D79B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039C},
+ {0x1D79C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039D},
+ {0x1D79D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039E},
+ {0x1D79E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x039F},
+ {0x1D79F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A0},
+ {0x1D7A0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A1},
+ {0x1D7A1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F4},
+ {0x1D7A2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A3},
+ {0x1D7A3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A4},
+ {0x1D7A4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A5},
+ {0x1D7A5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A6},
+ {0x1D7A6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A7},
+ {0x1D7A7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A8},
+ {0x1D7A8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03A9},
+ {0x1D7A9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2207},
+ {0x1D7AA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B1},
+ {0x1D7AB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B2},
+ {0x1D7AC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B3},
+ {0x1D7AD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B4},
+ {0x1D7AE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B5},
+ {0x1D7AF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B6},
+ {0x1D7B0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B7},
+ {0x1D7B1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B8},
+ {0x1D7B2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03B9},
+ {0x1D7B3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BA},
+ {0x1D7B4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BB},
+ {0x1D7B5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BC},
+ {0x1D7B6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BD},
+ {0x1D7B7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BE},
+ {0x1D7B8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03BF},
+ {0x1D7B9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C0},
+ {0x1D7BA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C1},
+ {0x1D7BB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C2},
+ {0x1D7BC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C3},
+ {0x1D7BD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C4},
+ {0x1D7BE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C5},
+ {0x1D7BF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C6},
+ {0x1D7C0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C7},
+ {0x1D7C1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C8},
+ {0x1D7C2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03C9},
+ {0x1D7C3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x2202},
+ {0x1D7C4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F5},
+ {0x1D7C5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D1},
+ {0x1D7C6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F0},
+ {0x1D7C7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D5},
+ {0x1D7C8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03F1},
+ {0x1D7C9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03D6},
+ {0x1D7CA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03DC},
+ {0x1D7CB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x03DD},
+ {0x1D7CE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0x1D7CF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0x1D7D0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0x1D7D1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0x1D7D2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0x1D7D3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0x1D7D4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0x1D7D5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0x1D7D6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0x1D7D7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0x1D7D8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0x1D7D9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0x1D7DA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0x1D7DB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0x1D7DC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0x1D7DD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0x1D7DE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0x1D7DF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0x1D7E0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0x1D7E1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0x1D7E2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0x1D7E3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0x1D7E4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0x1D7E5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0x1D7E6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0x1D7E7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0x1D7E8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0x1D7E9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0x1D7EA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0x1D7EB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0x1D7EC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0x1D7ED, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0x1D7EE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0x1D7EF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0x1D7F0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0x1D7F1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0x1D7F2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0x1D7F3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0x1D7F4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0x1D7F5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0x1D7F6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0x1D7F7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0x1D7F8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0x1D7F9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0x1D7FA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0x1D7FB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0x1D7FC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0x1D7FD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0x1D7FE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0x1D7FF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0x1E000, 230, 0, 0},
+ {0x1E001, 230, 0, 0},
+ {0x1E002, 230, 0, 0},
+ {0x1E003, 230, 0, 0},
+ {0x1E004, 230, 0, 0},
+ {0x1E005, 230, 0, 0},
+ {0x1E006, 230, 0, 0},
+ {0x1E008, 230, 0, 0},
+ {0x1E009, 230, 0, 0},
+ {0x1E00A, 230, 0, 0},
+ {0x1E00B, 230, 0, 0},
+ {0x1E00C, 230, 0, 0},
+ {0x1E00D, 230, 0, 0},
+ {0x1E00E, 230, 0, 0},
+ {0x1E00F, 230, 0, 0},
+ {0x1E010, 230, 0, 0},
+ {0x1E011, 230, 0, 0},
+ {0x1E012, 230, 0, 0},
+ {0x1E013, 230, 0, 0},
+ {0x1E014, 230, 0, 0},
+ {0x1E015, 230, 0, 0},
+ {0x1E016, 230, 0, 0},
+ {0x1E017, 230, 0, 0},
+ {0x1E018, 230, 0, 0},
+ {0x1E01B, 230, 0, 0},
+ {0x1E01C, 230, 0, 0},
+ {0x1E01D, 230, 0, 0},
+ {0x1E01E, 230, 0, 0},
+ {0x1E01F, 230, 0, 0},
+ {0x1E020, 230, 0, 0},
+ {0x1E021, 230, 0, 0},
+ {0x1E023, 230, 0, 0},
+ {0x1E024, 230, 0, 0},
+ {0x1E026, 230, 0, 0},
+ {0x1E027, 230, 0, 0},
+ {0x1E028, 230, 0, 0},
+ {0x1E029, 230, 0, 0},
+ {0x1E02A, 230, 0, 0},
+ {0x1E130, 230, 0, 0},
+ {0x1E131, 230, 0, 0},
+ {0x1E132, 230, 0, 0},
+ {0x1E133, 230, 0, 0},
+ {0x1E134, 230, 0, 0},
+ {0x1E135, 230, 0, 0},
+ {0x1E136, 230, 0, 0},
+ {0x1E2EC, 230, 0, 0},
+ {0x1E2ED, 230, 0, 0},
+ {0x1E2EE, 230, 0, 0},
+ {0x1E2EF, 230, 0, 0},
+ {0x1E8D0, 220, 0, 0},
+ {0x1E8D1, 220, 0, 0},
+ {0x1E8D2, 220, 0, 0},
+ {0x1E8D3, 220, 0, 0},
+ {0x1E8D4, 220, 0, 0},
+ {0x1E8D5, 220, 0, 0},
+ {0x1E8D6, 220, 0, 0},
+ {0x1E944, 230, 0, 0},
+ {0x1E945, 230, 0, 0},
+ {0x1E946, 230, 0, 0},
+ {0x1E947, 230, 0, 0},
+ {0x1E948, 230, 0, 0},
+ {0x1E949, 230, 0, 0},
+ {0x1E94A, 7, 0, 0},
+ {0x1EE00, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0627},
+ {0x1EE01, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0628},
+ {0x1EE02, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0x1EE03, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062F},
+ {0x1EE05, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0648},
+ {0x1EE06, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0632},
+ {0x1EE07, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0x1EE08, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0637},
+ {0x1EE09, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0x1EE0A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0643},
+ {0x1EE0B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0644},
+ {0x1EE0C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0645},
+ {0x1EE0D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0x1EE0E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0x1EE0F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0x1EE10, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0641},
+ {0x1EE11, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0x1EE12, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0x1EE13, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0631},
+ {0x1EE14, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0x1EE15, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062A},
+ {0x1EE16, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062B},
+ {0x1EE17, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0x1EE18, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0630},
+ {0x1EE19, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0x1EE1A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0638},
+ {0x1EE1B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0x1EE1C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x066E},
+ {0x1EE1D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BA},
+ {0x1EE1E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A1},
+ {0x1EE1F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x066F},
+ {0x1EE21, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0628},
+ {0x1EE22, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0x1EE24, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0647},
+ {0x1EE27, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0x1EE29, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0x1EE2A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0643},
+ {0x1EE2B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0644},
+ {0x1EE2C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0645},
+ {0x1EE2D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0x1EE2E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0x1EE2F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0x1EE30, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0641},
+ {0x1EE31, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0x1EE32, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0x1EE34, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0x1EE35, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062A},
+ {0x1EE36, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062B},
+ {0x1EE37, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0x1EE39, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0x1EE3B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0x1EE42, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0x1EE47, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0x1EE49, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0x1EE4B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0644},
+ {0x1EE4D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0x1EE4E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0x1EE4F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0x1EE51, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0x1EE52, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0x1EE54, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0x1EE57, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0x1EE59, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0x1EE5B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0x1EE5D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06BA},
+ {0x1EE5F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x066F},
+ {0x1EE61, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0628},
+ {0x1EE62, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0x1EE64, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0647},
+ {0x1EE67, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0x1EE68, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0637},
+ {0x1EE69, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0x1EE6A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0643},
+ {0x1EE6C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0645},
+ {0x1EE6D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0x1EE6E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0x1EE6F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0x1EE70, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0641},
+ {0x1EE71, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0x1EE72, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0x1EE74, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0x1EE75, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062A},
+ {0x1EE76, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062B},
+ {0x1EE77, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0x1EE79, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0x1EE7A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0638},
+ {0x1EE7B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0x1EE7C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x066E},
+ {0x1EE7E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x06A1},
+ {0x1EE80, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0627},
+ {0x1EE81, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0628},
+ {0x1EE82, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0x1EE83, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062F},
+ {0x1EE84, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0647},
+ {0x1EE85, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0648},
+ {0x1EE86, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0632},
+ {0x1EE87, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0x1EE88, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0637},
+ {0x1EE89, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0x1EE8B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0644},
+ {0x1EE8C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0645},
+ {0x1EE8D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0x1EE8E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0x1EE8F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0x1EE90, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0641},
+ {0x1EE91, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0x1EE92, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0x1EE93, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0631},
+ {0x1EE94, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0x1EE95, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062A},
+ {0x1EE96, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062B},
+ {0x1EE97, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0x1EE98, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0630},
+ {0x1EE99, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0x1EE9A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0638},
+ {0x1EE9B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0x1EEA1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0628},
+ {0x1EEA2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062C},
+ {0x1EEA3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062F},
+ {0x1EEA5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0648},
+ {0x1EEA6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0632},
+ {0x1EEA7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062D},
+ {0x1EEA8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0637},
+ {0x1EEA9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x064A},
+ {0x1EEAB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0644},
+ {0x1EEAC, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0645},
+ {0x1EEAD, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0646},
+ {0x1EEAE, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0633},
+ {0x1EEAF, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0639},
+ {0x1EEB0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0641},
+ {0x1EEB1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0635},
+ {0x1EEB2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0642},
+ {0x1EEB3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0631},
+ {0x1EEB4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0634},
+ {0x1EEB5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062A},
+ {0x1EEB6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062B},
+ {0x1EEB7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x062E},
+ {0x1EEB8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0630},
+ {0x1EEB9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0636},
+ {0x1EEBA, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0638},
+ {0x1EEBB, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x063A},
+ {0x1F100, 0, 2 | DECOMP_COMPAT, 4828},
+ {0x1F101, 0, 2 | DECOMP_COMPAT, 4830},
+ {0x1F102, 0, 2 | DECOMP_COMPAT, 4832},
+ {0x1F103, 0, 2 | DECOMP_COMPAT, 4834},
+ {0x1F104, 0, 2 | DECOMP_COMPAT, 4836},
+ {0x1F105, 0, 2 | DECOMP_COMPAT, 4838},
+ {0x1F106, 0, 2 | DECOMP_COMPAT, 4840},
+ {0x1F107, 0, 2 | DECOMP_COMPAT, 4842},
+ {0x1F108, 0, 2 | DECOMP_COMPAT, 4844},
+ {0x1F109, 0, 2 | DECOMP_COMPAT, 4846},
+ {0x1F10A, 0, 2 | DECOMP_COMPAT, 4848},
+ {0x1F110, 0, 3 | DECOMP_COMPAT, 4850},
+ {0x1F111, 0, 3 | DECOMP_COMPAT, 4853},
+ {0x1F112, 0, 3 | DECOMP_COMPAT, 4856},
+ {0x1F113, 0, 3 | DECOMP_COMPAT, 4859},
+ {0x1F114, 0, 3 | DECOMP_COMPAT, 4862},
+ {0x1F115, 0, 3 | DECOMP_COMPAT, 4865},
+ {0x1F116, 0, 3 | DECOMP_COMPAT, 4868},
+ {0x1F117, 0, 3 | DECOMP_COMPAT, 4871},
+ {0x1F118, 0, 3 | DECOMP_COMPAT, 4874},
+ {0x1F119, 0, 3 | DECOMP_COMPAT, 4877},
+ {0x1F11A, 0, 3 | DECOMP_COMPAT, 4880},
+ {0x1F11B, 0, 3 | DECOMP_COMPAT, 4883},
+ {0x1F11C, 0, 3 | DECOMP_COMPAT, 4886},
+ {0x1F11D, 0, 3 | DECOMP_COMPAT, 4889},
+ {0x1F11E, 0, 3 | DECOMP_COMPAT, 4892},
+ {0x1F11F, 0, 3 | DECOMP_COMPAT, 4895},
+ {0x1F120, 0, 3 | DECOMP_COMPAT, 4898},
+ {0x1F121, 0, 3 | DECOMP_COMPAT, 4901},
+ {0x1F122, 0, 3 | DECOMP_COMPAT, 4904},
+ {0x1F123, 0, 3 | DECOMP_COMPAT, 4907},
+ {0x1F124, 0, 3 | DECOMP_COMPAT, 4910},
+ {0x1F125, 0, 3 | DECOMP_COMPAT, 4913},
+ {0x1F126, 0, 3 | DECOMP_COMPAT, 4916},
+ {0x1F127, 0, 3 | DECOMP_COMPAT, 4919},
+ {0x1F128, 0, 3 | DECOMP_COMPAT, 4922},
+ {0x1F129, 0, 3 | DECOMP_COMPAT, 4925},
+ {0x1F12A, 0, 3 | DECOMP_COMPAT, 4928},
+ {0x1F12B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1F12C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1F12D, 0, 2 | DECOMP_COMPAT, 4931},
+ {0x1F12E, 0, 2 | DECOMP_COMPAT, 4933},
+ {0x1F130, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0041},
+ {0x1F131, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0042},
+ {0x1F132, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0043},
+ {0x1F133, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0044},
+ {0x1F134, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0045},
+ {0x1F135, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0046},
+ {0x1F136, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0047},
+ {0x1F137, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0048},
+ {0x1F138, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0049},
+ {0x1F139, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004A},
+ {0x1F13A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004B},
+ {0x1F13B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004C},
+ {0x1F13C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004D},
+ {0x1F13D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004E},
+ {0x1F13E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x004F},
+ {0x1F13F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0050},
+ {0x1F140, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0051},
+ {0x1F141, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0052},
+ {0x1F142, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0053},
+ {0x1F143, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0054},
+ {0x1F144, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0055},
+ {0x1F145, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0056},
+ {0x1F146, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0057},
+ {0x1F147, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0058},
+ {0x1F148, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0059},
+ {0x1F149, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x005A},
+ {0x1F14A, 0, 2 | DECOMP_COMPAT, 4935},
+ {0x1F14B, 0, 2 | DECOMP_COMPAT, 4937},
+ {0x1F14C, 0, 2 | DECOMP_COMPAT, 4939},
+ {0x1F14D, 0, 2 | DECOMP_COMPAT, 4941},
+ {0x1F14E, 0, 3 | DECOMP_COMPAT, 4943},
+ {0x1F14F, 0, 2 | DECOMP_COMPAT, 4946},
+ {0x1F16A, 0, 2 | DECOMP_COMPAT, 4948},
+ {0x1F16B, 0, 2 | DECOMP_COMPAT, 4950},
+ {0x1F16C, 0, 2 | DECOMP_COMPAT, 4952},
+ {0x1F190, 0, 2 | DECOMP_COMPAT, 4954},
+ {0x1F200, 0, 2 | DECOMP_COMPAT, 4956},
+ {0x1F201, 0, 2 | DECOMP_COMPAT, 4958},
+ {0x1F202, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30B5},
+ {0x1F210, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x624B},
+ {0x1F211, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5B57},
+ {0x1F212, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x53CC},
+ {0x1F213, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x30C7},
+ {0x1F214, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E8C},
+ {0x1F215, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x591A},
+ {0x1F216, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x89E3},
+ {0x1F217, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5929},
+ {0x1F218, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4EA4},
+ {0x1F219, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6620},
+ {0x1F21A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7121},
+ {0x1F21B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6599},
+ {0x1F21C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x524D},
+ {0x1F21D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5F8C},
+ {0x1F21E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x518D},
+ {0x1F21F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x65B0},
+ {0x1F220, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x521D},
+ {0x1F221, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7D42},
+ {0x1F222, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x751F},
+ {0x1F223, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8CA9},
+ {0x1F224, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x58F0},
+ {0x1F225, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5439},
+ {0x1F226, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6F14},
+ {0x1F227, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6295},
+ {0x1F228, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6355},
+ {0x1F229, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E00},
+ {0x1F22A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E09},
+ {0x1F22B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x904A},
+ {0x1F22C, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5DE6},
+ {0x1F22D, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x4E2D},
+ {0x1F22E, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x53F3},
+ {0x1F22F, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6307},
+ {0x1F230, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x8D70},
+ {0x1F231, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6253},
+ {0x1F232, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7981},
+ {0x1F233, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7A7A},
+ {0x1F234, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5408},
+ {0x1F235, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6E80},
+ {0x1F236, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6709},
+ {0x1F237, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x6708},
+ {0x1F238, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x7533},
+ {0x1F239, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5272},
+ {0x1F23A, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x55B6},
+ {0x1F23B, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x914D},
+ {0x1F240, 0, 3 | DECOMP_COMPAT, 4960},
+ {0x1F241, 0, 3 | DECOMP_COMPAT, 4963},
+ {0x1F242, 0, 3 | DECOMP_COMPAT, 4966},
+ {0x1F243, 0, 3 | DECOMP_COMPAT, 4969},
+ {0x1F244, 0, 3 | DECOMP_COMPAT, 4972},
+ {0x1F245, 0, 3 | DECOMP_COMPAT, 4975},
+ {0x1F246, 0, 3 | DECOMP_COMPAT, 4978},
+ {0x1F247, 0, 3 | DECOMP_COMPAT, 4981},
+ {0x1F248, 0, 3 | DECOMP_COMPAT, 4984},
+ {0x1F250, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x5F97},
+ {0x1F251, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x53EF},
+ {0x1FBF0, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0030},
+ {0x1FBF1, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0031},
+ {0x1FBF2, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0032},
+ {0x1FBF3, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0033},
+ {0x1FBF4, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0034},
+ {0x1FBF5, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0035},
+ {0x1FBF6, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0036},
+ {0x1FBF7, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0037},
+ {0x1FBF8, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0038},
+ {0x1FBF9, 0, 1 | DECOMP_COMPAT | DECOMP_INLINE, 0x0039},
+ {0x2F800, 0, 1 | DECOMP_INLINE, 0x4E3D},
+ {0x2F801, 0, 1 | DECOMP_INLINE, 0x4E38},
+ {0x2F802, 0, 1 | DECOMP_INLINE, 0x4E41},
+ {0x2F803, 0, 1, 4987},
+ {0x2F804, 0, 1 | DECOMP_INLINE, 0x4F60},
+ {0x2F805, 0, 1 | DECOMP_INLINE, 0x4FAE},
+ {0x2F806, 0, 1 | DECOMP_INLINE, 0x4FBB},
+ {0x2F807, 0, 1 | DECOMP_INLINE, 0x5002},
+ {0x2F808, 0, 1 | DECOMP_INLINE, 0x507A},
+ {0x2F809, 0, 1 | DECOMP_INLINE, 0x5099},
+ {0x2F80A, 0, 1 | DECOMP_INLINE, 0x50E7},
+ {0x2F80B, 0, 1 | DECOMP_INLINE, 0x50CF},
+ {0x2F80C, 0, 1 | DECOMP_INLINE, 0x349E},
+ {0x2F80D, 0, 1, 4988},
+ {0x2F80E, 0, 1 | DECOMP_INLINE, 0x514D},
+ {0x2F80F, 0, 1 | DECOMP_INLINE, 0x5154},
+ {0x2F810, 0, 1 | DECOMP_INLINE, 0x5164},
+ {0x2F811, 0, 1 | DECOMP_INLINE, 0x5177},
+ {0x2F812, 0, 1, 4989},
+ {0x2F813, 0, 1 | DECOMP_INLINE, 0x34B9},
+ {0x2F814, 0, 1 | DECOMP_INLINE, 0x5167},
+ {0x2F815, 0, 1 | DECOMP_INLINE, 0x518D},
+ {0x2F816, 0, 1, 4990},
+ {0x2F817, 0, 1 | DECOMP_INLINE, 0x5197},
+ {0x2F818, 0, 1 | DECOMP_INLINE, 0x51A4},
+ {0x2F819, 0, 1 | DECOMP_INLINE, 0x4ECC},
+ {0x2F81A, 0, 1 | DECOMP_INLINE, 0x51AC},
+ {0x2F81B, 0, 1 | DECOMP_INLINE, 0x51B5},
+ {0x2F81C, 0, 1, 4991},
+ {0x2F81D, 0, 1 | DECOMP_INLINE, 0x51F5},
+ {0x2F81E, 0, 1 | DECOMP_INLINE, 0x5203},
+ {0x2F81F, 0, 1 | DECOMP_INLINE, 0x34DF},
+ {0x2F820, 0, 1 | DECOMP_INLINE, 0x523B},
+ {0x2F821, 0, 1 | DECOMP_INLINE, 0x5246},
+ {0x2F822, 0, 1 | DECOMP_INLINE, 0x5272},
+ {0x2F823, 0, 1 | DECOMP_INLINE, 0x5277},
+ {0x2F824, 0, 1 | DECOMP_INLINE, 0x3515},
+ {0x2F825, 0, 1 | DECOMP_INLINE, 0x52C7},
+ {0x2F826, 0, 1 | DECOMP_INLINE, 0x52C9},
+ {0x2F827, 0, 1 | DECOMP_INLINE, 0x52E4},
+ {0x2F828, 0, 1 | DECOMP_INLINE, 0x52FA},
+ {0x2F829, 0, 1 | DECOMP_INLINE, 0x5305},
+ {0x2F82A, 0, 1 | DECOMP_INLINE, 0x5306},
+ {0x2F82B, 0, 1 | DECOMP_INLINE, 0x5317},
+ {0x2F82C, 0, 1 | DECOMP_INLINE, 0x5349},
+ {0x2F82D, 0, 1 | DECOMP_INLINE, 0x5351},
+ {0x2F82E, 0, 1 | DECOMP_INLINE, 0x535A},
+ {0x2F82F, 0, 1 | DECOMP_INLINE, 0x5373},
+ {0x2F830, 0, 1 | DECOMP_INLINE, 0x537D},
+ {0x2F831, 0, 1 | DECOMP_INLINE, 0x537F},
+ {0x2F832, 0, 1 | DECOMP_INLINE, 0x537F},
+ {0x2F833, 0, 1 | DECOMP_INLINE, 0x537F},
+ {0x2F834, 0, 1, 4992},
+ {0x2F835, 0, 1 | DECOMP_INLINE, 0x7070},
+ {0x2F836, 0, 1 | DECOMP_INLINE, 0x53CA},
+ {0x2F837, 0, 1 | DECOMP_INLINE, 0x53DF},
+ {0x2F838, 0, 1, 4993},
+ {0x2F839, 0, 1 | DECOMP_INLINE, 0x53EB},
+ {0x2F83A, 0, 1 | DECOMP_INLINE, 0x53F1},
+ {0x2F83B, 0, 1 | DECOMP_INLINE, 0x5406},
+ {0x2F83C, 0, 1 | DECOMP_INLINE, 0x549E},
+ {0x2F83D, 0, 1 | DECOMP_INLINE, 0x5438},
+ {0x2F83E, 0, 1 | DECOMP_INLINE, 0x5448},
+ {0x2F83F, 0, 1 | DECOMP_INLINE, 0x5468},
+ {0x2F840, 0, 1 | DECOMP_INLINE, 0x54A2},
+ {0x2F841, 0, 1 | DECOMP_INLINE, 0x54F6},
+ {0x2F842, 0, 1 | DECOMP_INLINE, 0x5510},
+ {0x2F843, 0, 1 | DECOMP_INLINE, 0x5553},
+ {0x2F844, 0, 1 | DECOMP_INLINE, 0x5563},
+ {0x2F845, 0, 1 | DECOMP_INLINE, 0x5584},
+ {0x2F846, 0, 1 | DECOMP_INLINE, 0x5584},
+ {0x2F847, 0, 1 | DECOMP_INLINE, 0x5599},
+ {0x2F848, 0, 1 | DECOMP_INLINE, 0x55AB},
+ {0x2F849, 0, 1 | DECOMP_INLINE, 0x55B3},
+ {0x2F84A, 0, 1 | DECOMP_INLINE, 0x55C2},
+ {0x2F84B, 0, 1 | DECOMP_INLINE, 0x5716},
+ {0x2F84C, 0, 1 | DECOMP_INLINE, 0x5606},
+ {0x2F84D, 0, 1 | DECOMP_INLINE, 0x5717},
+ {0x2F84E, 0, 1 | DECOMP_INLINE, 0x5651},
+ {0x2F84F, 0, 1 | DECOMP_INLINE, 0x5674},
+ {0x2F850, 0, 1 | DECOMP_INLINE, 0x5207},
+ {0x2F851, 0, 1 | DECOMP_INLINE, 0x58EE},
+ {0x2F852, 0, 1 | DECOMP_INLINE, 0x57CE},
+ {0x2F853, 0, 1 | DECOMP_INLINE, 0x57F4},
+ {0x2F854, 0, 1 | DECOMP_INLINE, 0x580D},
+ {0x2F855, 0, 1 | DECOMP_INLINE, 0x578B},
+ {0x2F856, 0, 1 | DECOMP_INLINE, 0x5832},
+ {0x2F857, 0, 1 | DECOMP_INLINE, 0x5831},
+ {0x2F858, 0, 1 | DECOMP_INLINE, 0x58AC},
+ {0x2F859, 0, 1, 4994},
+ {0x2F85A, 0, 1 | DECOMP_INLINE, 0x58F2},
+ {0x2F85B, 0, 1 | DECOMP_INLINE, 0x58F7},
+ {0x2F85C, 0, 1 | DECOMP_INLINE, 0x5906},
+ {0x2F85D, 0, 1 | DECOMP_INLINE, 0x591A},
+ {0x2F85E, 0, 1 | DECOMP_INLINE, 0x5922},
+ {0x2F85F, 0, 1 | DECOMP_INLINE, 0x5962},
+ {0x2F860, 0, 1, 4995},
+ {0x2F861, 0, 1, 4996},
+ {0x2F862, 0, 1 | DECOMP_INLINE, 0x59EC},
+ {0x2F863, 0, 1 | DECOMP_INLINE, 0x5A1B},
+ {0x2F864, 0, 1 | DECOMP_INLINE, 0x5A27},
+ {0x2F865, 0, 1 | DECOMP_INLINE, 0x59D8},
+ {0x2F866, 0, 1 | DECOMP_INLINE, 0x5A66},
+ {0x2F867, 0, 1 | DECOMP_INLINE, 0x36EE},
+ {0x2F868, 0, 1 | DECOMP_INLINE, 0x36FC},
+ {0x2F869, 0, 1 | DECOMP_INLINE, 0x5B08},
+ {0x2F86A, 0, 1 | DECOMP_INLINE, 0x5B3E},
+ {0x2F86B, 0, 1 | DECOMP_INLINE, 0x5B3E},
+ {0x2F86C, 0, 1, 4997},
+ {0x2F86D, 0, 1 | DECOMP_INLINE, 0x5BC3},
+ {0x2F86E, 0, 1 | DECOMP_INLINE, 0x5BD8},
+ {0x2F86F, 0, 1 | DECOMP_INLINE, 0x5BE7},
+ {0x2F870, 0, 1 | DECOMP_INLINE, 0x5BF3},
+ {0x2F871, 0, 1, 4998},
+ {0x2F872, 0, 1 | DECOMP_INLINE, 0x5BFF},
+ {0x2F873, 0, 1 | DECOMP_INLINE, 0x5C06},
+ {0x2F874, 0, 1 | DECOMP_INLINE, 0x5F53},
+ {0x2F875, 0, 1 | DECOMP_INLINE, 0x5C22},
+ {0x2F876, 0, 1 | DECOMP_INLINE, 0x3781},
+ {0x2F877, 0, 1 | DECOMP_INLINE, 0x5C60},
+ {0x2F878, 0, 1 | DECOMP_INLINE, 0x5C6E},
+ {0x2F879, 0, 1 | DECOMP_INLINE, 0x5CC0},
+ {0x2F87A, 0, 1 | DECOMP_INLINE, 0x5C8D},
+ {0x2F87B, 0, 1, 4999},
+ {0x2F87C, 0, 1 | DECOMP_INLINE, 0x5D43},
+ {0x2F87D, 0, 1, 5000},
+ {0x2F87E, 0, 1 | DECOMP_INLINE, 0x5D6E},
+ {0x2F87F, 0, 1 | DECOMP_INLINE, 0x5D6B},
+ {0x2F880, 0, 1 | DECOMP_INLINE, 0x5D7C},
+ {0x2F881, 0, 1 | DECOMP_INLINE, 0x5DE1},
+ {0x2F882, 0, 1 | DECOMP_INLINE, 0x5DE2},
+ {0x2F883, 0, 1 | DECOMP_INLINE, 0x382F},
+ {0x2F884, 0, 1 | DECOMP_INLINE, 0x5DFD},
+ {0x2F885, 0, 1 | DECOMP_INLINE, 0x5E28},
+ {0x2F886, 0, 1 | DECOMP_INLINE, 0x5E3D},
+ {0x2F887, 0, 1 | DECOMP_INLINE, 0x5E69},
+ {0x2F888, 0, 1 | DECOMP_INLINE, 0x3862},
+ {0x2F889, 0, 1, 5001},
+ {0x2F88A, 0, 1 | DECOMP_INLINE, 0x387C},
+ {0x2F88B, 0, 1 | DECOMP_INLINE, 0x5EB0},
+ {0x2F88C, 0, 1 | DECOMP_INLINE, 0x5EB3},
+ {0x2F88D, 0, 1 | DECOMP_INLINE, 0x5EB6},
+ {0x2F88E, 0, 1 | DECOMP_INLINE, 0x5ECA},
+ {0x2F88F, 0, 1, 5002},
+ {0x2F890, 0, 1 | DECOMP_INLINE, 0x5EFE},
+ {0x2F891, 0, 1, 5003},
+ {0x2F892, 0, 1, 5004},
+ {0x2F893, 0, 1 | DECOMP_INLINE, 0x8201},
+ {0x2F894, 0, 1 | DECOMP_INLINE, 0x5F22},
+ {0x2F895, 0, 1 | DECOMP_INLINE, 0x5F22},
+ {0x2F896, 0, 1 | DECOMP_INLINE, 0x38C7},
+ {0x2F897, 0, 1, 5005},
+ {0x2F898, 0, 1, 5006},
+ {0x2F899, 0, 1 | DECOMP_INLINE, 0x5F62},
+ {0x2F89A, 0, 1 | DECOMP_INLINE, 0x5F6B},
+ {0x2F89B, 0, 1 | DECOMP_INLINE, 0x38E3},
+ {0x2F89C, 0, 1 | DECOMP_INLINE, 0x5F9A},
+ {0x2F89D, 0, 1 | DECOMP_INLINE, 0x5FCD},
+ {0x2F89E, 0, 1 | DECOMP_INLINE, 0x5FD7},
+ {0x2F89F, 0, 1 | DECOMP_INLINE, 0x5FF9},
+ {0x2F8A0, 0, 1 | DECOMP_INLINE, 0x6081},
+ {0x2F8A1, 0, 1 | DECOMP_INLINE, 0x393A},
+ {0x2F8A2, 0, 1 | DECOMP_INLINE, 0x391C},
+ {0x2F8A3, 0, 1 | DECOMP_INLINE, 0x6094},
+ {0x2F8A4, 0, 1, 5007},
+ {0x2F8A5, 0, 1 | DECOMP_INLINE, 0x60C7},
+ {0x2F8A6, 0, 1 | DECOMP_INLINE, 0x6148},
+ {0x2F8A7, 0, 1 | DECOMP_INLINE, 0x614C},
+ {0x2F8A8, 0, 1 | DECOMP_INLINE, 0x614E},
+ {0x2F8A9, 0, 1 | DECOMP_INLINE, 0x614C},
+ {0x2F8AA, 0, 1 | DECOMP_INLINE, 0x617A},
+ {0x2F8AB, 0, 1 | DECOMP_INLINE, 0x618E},
+ {0x2F8AC, 0, 1 | DECOMP_INLINE, 0x61B2},
+ {0x2F8AD, 0, 1 | DECOMP_INLINE, 0x61A4},
+ {0x2F8AE, 0, 1 | DECOMP_INLINE, 0x61AF},
+ {0x2F8AF, 0, 1 | DECOMP_INLINE, 0x61DE},
+ {0x2F8B0, 0, 1 | DECOMP_INLINE, 0x61F2},
+ {0x2F8B1, 0, 1 | DECOMP_INLINE, 0x61F6},
+ {0x2F8B2, 0, 1 | DECOMP_INLINE, 0x6210},
+ {0x2F8B3, 0, 1 | DECOMP_INLINE, 0x621B},
+ {0x2F8B4, 0, 1 | DECOMP_INLINE, 0x625D},
+ {0x2F8B5, 0, 1 | DECOMP_INLINE, 0x62B1},
+ {0x2F8B6, 0, 1 | DECOMP_INLINE, 0x62D4},
+ {0x2F8B7, 0, 1 | DECOMP_INLINE, 0x6350},
+ {0x2F8B8, 0, 1, 5008},
+ {0x2F8B9, 0, 1 | DECOMP_INLINE, 0x633D},
+ {0x2F8BA, 0, 1 | DECOMP_INLINE, 0x62FC},
+ {0x2F8BB, 0, 1 | DECOMP_INLINE, 0x6368},
+ {0x2F8BC, 0, 1 | DECOMP_INLINE, 0x6383},
+ {0x2F8BD, 0, 1 | DECOMP_INLINE, 0x63E4},
+ {0x2F8BE, 0, 1, 5009},
+ {0x2F8BF, 0, 1 | DECOMP_INLINE, 0x6422},
+ {0x2F8C0, 0, 1 | DECOMP_INLINE, 0x63C5},
+ {0x2F8C1, 0, 1 | DECOMP_INLINE, 0x63A9},
+ {0x2F8C2, 0, 1 | DECOMP_INLINE, 0x3A2E},
+ {0x2F8C3, 0, 1 | DECOMP_INLINE, 0x6469},
+ {0x2F8C4, 0, 1 | DECOMP_INLINE, 0x647E},
+ {0x2F8C5, 0, 1 | DECOMP_INLINE, 0x649D},
+ {0x2F8C6, 0, 1 | DECOMP_INLINE, 0x6477},
+ {0x2F8C7, 0, 1 | DECOMP_INLINE, 0x3A6C},
+ {0x2F8C8, 0, 1 | DECOMP_INLINE, 0x654F},
+ {0x2F8C9, 0, 1 | DECOMP_INLINE, 0x656C},
+ {0x2F8CA, 0, 1, 5010},
+ {0x2F8CB, 0, 1 | DECOMP_INLINE, 0x65E3},
+ {0x2F8CC, 0, 1 | DECOMP_INLINE, 0x66F8},
+ {0x2F8CD, 0, 1 | DECOMP_INLINE, 0x6649},
+ {0x2F8CE, 0, 1 | DECOMP_INLINE, 0x3B19},
+ {0x2F8CF, 0, 1 | DECOMP_INLINE, 0x6691},
+ {0x2F8D0, 0, 1 | DECOMP_INLINE, 0x3B08},
+ {0x2F8D1, 0, 1 | DECOMP_INLINE, 0x3AE4},
+ {0x2F8D2, 0, 1 | DECOMP_INLINE, 0x5192},
+ {0x2F8D3, 0, 1 | DECOMP_INLINE, 0x5195},
+ {0x2F8D4, 0, 1 | DECOMP_INLINE, 0x6700},
+ {0x2F8D5, 0, 1 | DECOMP_INLINE, 0x669C},
+ {0x2F8D6, 0, 1 | DECOMP_INLINE, 0x80AD},
+ {0x2F8D7, 0, 1 | DECOMP_INLINE, 0x43D9},
+ {0x2F8D8, 0, 1 | DECOMP_INLINE, 0x6717},
+ {0x2F8D9, 0, 1 | DECOMP_INLINE, 0x671B},
+ {0x2F8DA, 0, 1 | DECOMP_INLINE, 0x6721},
+ {0x2F8DB, 0, 1 | DECOMP_INLINE, 0x675E},
+ {0x2F8DC, 0, 1 | DECOMP_INLINE, 0x6753},
+ {0x2F8DD, 0, 1, 5011},
+ {0x2F8DE, 0, 1 | DECOMP_INLINE, 0x3B49},
+ {0x2F8DF, 0, 1 | DECOMP_INLINE, 0x67FA},
+ {0x2F8E0, 0, 1 | DECOMP_INLINE, 0x6785},
+ {0x2F8E1, 0, 1 | DECOMP_INLINE, 0x6852},
+ {0x2F8E2, 0, 1 | DECOMP_INLINE, 0x6885},
+ {0x2F8E3, 0, 1, 5012},
+ {0x2F8E4, 0, 1 | DECOMP_INLINE, 0x688E},
+ {0x2F8E5, 0, 1 | DECOMP_INLINE, 0x681F},
+ {0x2F8E6, 0, 1 | DECOMP_INLINE, 0x6914},
+ {0x2F8E7, 0, 1 | DECOMP_INLINE, 0x3B9D},
+ {0x2F8E8, 0, 1 | DECOMP_INLINE, 0x6942},
+ {0x2F8E9, 0, 1 | DECOMP_INLINE, 0x69A3},
+ {0x2F8EA, 0, 1 | DECOMP_INLINE, 0x69EA},
+ {0x2F8EB, 0, 1 | DECOMP_INLINE, 0x6AA8},
+ {0x2F8EC, 0, 1, 5013},
+ {0x2F8ED, 0, 1 | DECOMP_INLINE, 0x6ADB},
+ {0x2F8EE, 0, 1 | DECOMP_INLINE, 0x3C18},
+ {0x2F8EF, 0, 1 | DECOMP_INLINE, 0x6B21},
+ {0x2F8F0, 0, 1, 5014},
+ {0x2F8F1, 0, 1 | DECOMP_INLINE, 0x6B54},
+ {0x2F8F2, 0, 1 | DECOMP_INLINE, 0x3C4E},
+ {0x2F8F3, 0, 1 | DECOMP_INLINE, 0x6B72},
+ {0x2F8F4, 0, 1 | DECOMP_INLINE, 0x6B9F},
+ {0x2F8F5, 0, 1 | DECOMP_INLINE, 0x6BBA},
+ {0x2F8F6, 0, 1 | DECOMP_INLINE, 0x6BBB},
+ {0x2F8F7, 0, 1, 5015},
+ {0x2F8F8, 0, 1, 5016},
+ {0x2F8F9, 0, 1, 5017},
+ {0x2F8FA, 0, 1 | DECOMP_INLINE, 0x6C4E},
+ {0x2F8FB, 0, 1, 5018},
+ {0x2F8FC, 0, 1 | DECOMP_INLINE, 0x6CBF},
+ {0x2F8FD, 0, 1 | DECOMP_INLINE, 0x6CCD},
+ {0x2F8FE, 0, 1 | DECOMP_INLINE, 0x6C67},
+ {0x2F8FF, 0, 1 | DECOMP_INLINE, 0x6D16},
+ {0x2F900, 0, 1 | DECOMP_INLINE, 0x6D3E},
+ {0x2F901, 0, 1 | DECOMP_INLINE, 0x6D77},
+ {0x2F902, 0, 1 | DECOMP_INLINE, 0x6D41},
+ {0x2F903, 0, 1 | DECOMP_INLINE, 0x6D69},
+ {0x2F904, 0, 1 | DECOMP_INLINE, 0x6D78},
+ {0x2F905, 0, 1 | DECOMP_INLINE, 0x6D85},
+ {0x2F906, 0, 1, 5019},
+ {0x2F907, 0, 1 | DECOMP_INLINE, 0x6D34},
+ {0x2F908, 0, 1 | DECOMP_INLINE, 0x6E2F},
+ {0x2F909, 0, 1 | DECOMP_INLINE, 0x6E6E},
+ {0x2F90A, 0, 1 | DECOMP_INLINE, 0x3D33},
+ {0x2F90B, 0, 1 | DECOMP_INLINE, 0x6ECB},
+ {0x2F90C, 0, 1 | DECOMP_INLINE, 0x6EC7},
+ {0x2F90D, 0, 1, 5020},
+ {0x2F90E, 0, 1 | DECOMP_INLINE, 0x6DF9},
+ {0x2F90F, 0, 1 | DECOMP_INLINE, 0x6F6E},
+ {0x2F910, 0, 1, 5021},
+ {0x2F911, 0, 1, 5022},
+ {0x2F912, 0, 1 | DECOMP_INLINE, 0x6FC6},
+ {0x2F913, 0, 1 | DECOMP_INLINE, 0x7039},
+ {0x2F914, 0, 1 | DECOMP_INLINE, 0x701E},
+ {0x2F915, 0, 1 | DECOMP_INLINE, 0x701B},
+ {0x2F916, 0, 1 | DECOMP_INLINE, 0x3D96},
+ {0x2F917, 0, 1 | DECOMP_INLINE, 0x704A},
+ {0x2F918, 0, 1 | DECOMP_INLINE, 0x707D},
+ {0x2F919, 0, 1 | DECOMP_INLINE, 0x7077},
+ {0x2F91A, 0, 1 | DECOMP_INLINE, 0x70AD},
+ {0x2F91B, 0, 1, 5023},
+ {0x2F91C, 0, 1 | DECOMP_INLINE, 0x7145},
+ {0x2F91D, 0, 1, 5024},
+ {0x2F91E, 0, 1 | DECOMP_INLINE, 0x719C},
+ {0x2F91F, 0, 1, 5025},
+ {0x2F920, 0, 1 | DECOMP_INLINE, 0x7228},
+ {0x2F921, 0, 1 | DECOMP_INLINE, 0x7235},
+ {0x2F922, 0, 1 | DECOMP_INLINE, 0x7250},
+ {0x2F923, 0, 1, 5026},
+ {0x2F924, 0, 1 | DECOMP_INLINE, 0x7280},
+ {0x2F925, 0, 1 | DECOMP_INLINE, 0x7295},
+ {0x2F926, 0, 1, 5027},
+ {0x2F927, 0, 1, 5028},
+ {0x2F928, 0, 1 | DECOMP_INLINE, 0x737A},
+ {0x2F929, 0, 1 | DECOMP_INLINE, 0x738B},
+ {0x2F92A, 0, 1 | DECOMP_INLINE, 0x3EAC},
+ {0x2F92B, 0, 1 | DECOMP_INLINE, 0x73A5},
+ {0x2F92C, 0, 1 | DECOMP_INLINE, 0x3EB8},
+ {0x2F92D, 0, 1 | DECOMP_INLINE, 0x3EB8},
+ {0x2F92E, 0, 1 | DECOMP_INLINE, 0x7447},
+ {0x2F92F, 0, 1 | DECOMP_INLINE, 0x745C},
+ {0x2F930, 0, 1 | DECOMP_INLINE, 0x7471},
+ {0x2F931, 0, 1 | DECOMP_INLINE, 0x7485},
+ {0x2F932, 0, 1 | DECOMP_INLINE, 0x74CA},
+ {0x2F933, 0, 1 | DECOMP_INLINE, 0x3F1B},
+ {0x2F934, 0, 1 | DECOMP_INLINE, 0x7524},
+ {0x2F935, 0, 1, 5029},
+ {0x2F936, 0, 1 | DECOMP_INLINE, 0x753E},
+ {0x2F937, 0, 1, 5030},
+ {0x2F938, 0, 1 | DECOMP_INLINE, 0x7570},
+ {0x2F939, 0, 1, 5031},
+ {0x2F93A, 0, 1 | DECOMP_INLINE, 0x7610},
+ {0x2F93B, 0, 1, 5032},
+ {0x2F93C, 0, 1, 5033},
+ {0x2F93D, 0, 1, 5034},
+ {0x2F93E, 0, 1 | DECOMP_INLINE, 0x3FFC},
+ {0x2F93F, 0, 1 | DECOMP_INLINE, 0x4008},
+ {0x2F940, 0, 1 | DECOMP_INLINE, 0x76F4},
+ {0x2F941, 0, 1, 5035},
+ {0x2F942, 0, 1, 5036},
+ {0x2F943, 0, 1, 5037},
+ {0x2F944, 0, 1, 5038},
+ {0x2F945, 0, 1 | DECOMP_INLINE, 0x771E},
+ {0x2F946, 0, 1 | DECOMP_INLINE, 0x771F},
+ {0x2F947, 0, 1 | DECOMP_INLINE, 0x771F},
+ {0x2F948, 0, 1 | DECOMP_INLINE, 0x774A},
+ {0x2F949, 0, 1 | DECOMP_INLINE, 0x4039},
+ {0x2F94A, 0, 1 | DECOMP_INLINE, 0x778B},
+ {0x2F94B, 0, 1 | DECOMP_INLINE, 0x4046},
+ {0x2F94C, 0, 1 | DECOMP_INLINE, 0x4096},
+ {0x2F94D, 0, 1, 5039},
+ {0x2F94E, 0, 1 | DECOMP_INLINE, 0x784E},
+ {0x2F94F, 0, 1 | DECOMP_INLINE, 0x788C},
+ {0x2F950, 0, 1 | DECOMP_INLINE, 0x78CC},
+ {0x2F951, 0, 1 | DECOMP_INLINE, 0x40E3},
+ {0x2F952, 0, 1, 5040},
+ {0x2F953, 0, 1 | DECOMP_INLINE, 0x7956},
+ {0x2F954, 0, 1, 5041},
+ {0x2F955, 0, 1, 5042},
+ {0x2F956, 0, 1 | DECOMP_INLINE, 0x798F},
+ {0x2F957, 0, 1 | DECOMP_INLINE, 0x79EB},
+ {0x2F958, 0, 1 | DECOMP_INLINE, 0x412F},
+ {0x2F959, 0, 1 | DECOMP_INLINE, 0x7A40},
+ {0x2F95A, 0, 1 | DECOMP_INLINE, 0x7A4A},
+ {0x2F95B, 0, 1 | DECOMP_INLINE, 0x7A4F},
+ {0x2F95C, 0, 1, 5043},
+ {0x2F95D, 0, 1, 5044},
+ {0x2F95E, 0, 1, 5045},
+ {0x2F95F, 0, 1 | DECOMP_INLINE, 0x7AEE},
+ {0x2F960, 0, 1 | DECOMP_INLINE, 0x4202},
+ {0x2F961, 0, 1, 5046},
+ {0x2F962, 0, 1 | DECOMP_INLINE, 0x7BC6},
+ {0x2F963, 0, 1 | DECOMP_INLINE, 0x7BC9},
+ {0x2F964, 0, 1 | DECOMP_INLINE, 0x4227},
+ {0x2F965, 0, 1, 5047},
+ {0x2F966, 0, 1 | DECOMP_INLINE, 0x7CD2},
+ {0x2F967, 0, 1 | DECOMP_INLINE, 0x42A0},
+ {0x2F968, 0, 1 | DECOMP_INLINE, 0x7CE8},
+ {0x2F969, 0, 1 | DECOMP_INLINE, 0x7CE3},
+ {0x2F96A, 0, 1 | DECOMP_INLINE, 0x7D00},
+ {0x2F96B, 0, 1, 5048},
+ {0x2F96C, 0, 1 | DECOMP_INLINE, 0x7D63},
+ {0x2F96D, 0, 1 | DECOMP_INLINE, 0x4301},
+ {0x2F96E, 0, 1 | DECOMP_INLINE, 0x7DC7},
+ {0x2F96F, 0, 1 | DECOMP_INLINE, 0x7E02},
+ {0x2F970, 0, 1 | DECOMP_INLINE, 0x7E45},
+ {0x2F971, 0, 1 | DECOMP_INLINE, 0x4334},
+ {0x2F972, 0, 1, 5049},
+ {0x2F973, 0, 1, 5050},
+ {0x2F974, 0, 1 | DECOMP_INLINE, 0x4359},
+ {0x2F975, 0, 1, 5051},
+ {0x2F976, 0, 1 | DECOMP_INLINE, 0x7F7A},
+ {0x2F977, 0, 1, 5052},
+ {0x2F978, 0, 1 | DECOMP_INLINE, 0x7F95},
+ {0x2F979, 0, 1 | DECOMP_INLINE, 0x7FFA},
+ {0x2F97A, 0, 1 | DECOMP_INLINE, 0x8005},
+ {0x2F97B, 0, 1, 5053},
+ {0x2F97C, 0, 1, 5054},
+ {0x2F97D, 0, 1 | DECOMP_INLINE, 0x8060},
+ {0x2F97E, 0, 1, 5055},
+ {0x2F97F, 0, 1 | DECOMP_INLINE, 0x8070},
+ {0x2F980, 0, 1, 5056},
+ {0x2F981, 0, 1 | DECOMP_INLINE, 0x43D5},
+ {0x2F982, 0, 1 | DECOMP_INLINE, 0x80B2},
+ {0x2F983, 0, 1 | DECOMP_INLINE, 0x8103},
+ {0x2F984, 0, 1 | DECOMP_INLINE, 0x440B},
+ {0x2F985, 0, 1 | DECOMP_INLINE, 0x813E},
+ {0x2F986, 0, 1 | DECOMP_INLINE, 0x5AB5},
+ {0x2F987, 0, 1, 5057},
+ {0x2F988, 0, 1, 5058},
+ {0x2F989, 0, 1, 5059},
+ {0x2F98A, 0, 1, 5060},
+ {0x2F98B, 0, 1 | DECOMP_INLINE, 0x8201},
+ {0x2F98C, 0, 1 | DECOMP_INLINE, 0x8204},
+ {0x2F98D, 0, 1 | DECOMP_INLINE, 0x8F9E},
+ {0x2F98E, 0, 1 | DECOMP_INLINE, 0x446B},
+ {0x2F98F, 0, 1 | DECOMP_INLINE, 0x8291},
+ {0x2F990, 0, 1 | DECOMP_INLINE, 0x828B},
+ {0x2F991, 0, 1 | DECOMP_INLINE, 0x829D},
+ {0x2F992, 0, 1 | DECOMP_INLINE, 0x52B3},
+ {0x2F993, 0, 1 | DECOMP_INLINE, 0x82B1},
+ {0x2F994, 0, 1 | DECOMP_INLINE, 0x82B3},
+ {0x2F995, 0, 1 | DECOMP_INLINE, 0x82BD},
+ {0x2F996, 0, 1 | DECOMP_INLINE, 0x82E6},
+ {0x2F997, 0, 1, 5061},
+ {0x2F998, 0, 1 | DECOMP_INLINE, 0x82E5},
+ {0x2F999, 0, 1 | DECOMP_INLINE, 0x831D},
+ {0x2F99A, 0, 1 | DECOMP_INLINE, 0x8363},
+ {0x2F99B, 0, 1 | DECOMP_INLINE, 0x83AD},
+ {0x2F99C, 0, 1 | DECOMP_INLINE, 0x8323},
+ {0x2F99D, 0, 1 | DECOMP_INLINE, 0x83BD},
+ {0x2F99E, 0, 1 | DECOMP_INLINE, 0x83E7},
+ {0x2F99F, 0, 1 | DECOMP_INLINE, 0x8457},
+ {0x2F9A0, 0, 1 | DECOMP_INLINE, 0x8353},
+ {0x2F9A1, 0, 1 | DECOMP_INLINE, 0x83CA},
+ {0x2F9A2, 0, 1 | DECOMP_INLINE, 0x83CC},
+ {0x2F9A3, 0, 1 | DECOMP_INLINE, 0x83DC},
+ {0x2F9A4, 0, 1, 5062},
+ {0x2F9A5, 0, 1, 5063},
+ {0x2F9A6, 0, 1, 5064},
+ {0x2F9A7, 0, 1 | DECOMP_INLINE, 0x452B},
+ {0x2F9A8, 0, 1 | DECOMP_INLINE, 0x84F1},
+ {0x2F9A9, 0, 1 | DECOMP_INLINE, 0x84F3},
+ {0x2F9AA, 0, 1 | DECOMP_INLINE, 0x8516},
+ {0x2F9AB, 0, 1, 5065},
+ {0x2F9AC, 0, 1 | DECOMP_INLINE, 0x8564},
+ {0x2F9AD, 0, 1, 5066},
+ {0x2F9AE, 0, 1 | DECOMP_INLINE, 0x455D},
+ {0x2F9AF, 0, 1 | DECOMP_INLINE, 0x4561},
+ {0x2F9B0, 0, 1, 5067},
+ {0x2F9B1, 0, 1, 5068},
+ {0x2F9B2, 0, 1 | DECOMP_INLINE, 0x456B},
+ {0x2F9B3, 0, 1 | DECOMP_INLINE, 0x8650},
+ {0x2F9B4, 0, 1 | DECOMP_INLINE, 0x865C},
+ {0x2F9B5, 0, 1 | DECOMP_INLINE, 0x8667},
+ {0x2F9B6, 0, 1 | DECOMP_INLINE, 0x8669},
+ {0x2F9B7, 0, 1 | DECOMP_INLINE, 0x86A9},
+ {0x2F9B8, 0, 1 | DECOMP_INLINE, 0x8688},
+ {0x2F9B9, 0, 1 | DECOMP_INLINE, 0x870E},
+ {0x2F9BA, 0, 1 | DECOMP_INLINE, 0x86E2},
+ {0x2F9BB, 0, 1 | DECOMP_INLINE, 0x8779},
+ {0x2F9BC, 0, 1 | DECOMP_INLINE, 0x8728},
+ {0x2F9BD, 0, 1 | DECOMP_INLINE, 0x876B},
+ {0x2F9BE, 0, 1 | DECOMP_INLINE, 0x8786},
+ {0x2F9BF, 0, 1 | DECOMP_INLINE, 0x45D7},
+ {0x2F9C0, 0, 1 | DECOMP_INLINE, 0x87E1},
+ {0x2F9C1, 0, 1 | DECOMP_INLINE, 0x8801},
+ {0x2F9C2, 0, 1 | DECOMP_INLINE, 0x45F9},
+ {0x2F9C3, 0, 1 | DECOMP_INLINE, 0x8860},
+ {0x2F9C4, 0, 1 | DECOMP_INLINE, 0x8863},
+ {0x2F9C5, 0, 1, 5069},
+ {0x2F9C6, 0, 1 | DECOMP_INLINE, 0x88D7},
+ {0x2F9C7, 0, 1 | DECOMP_INLINE, 0x88DE},
+ {0x2F9C8, 0, 1 | DECOMP_INLINE, 0x4635},
+ {0x2F9C9, 0, 1 | DECOMP_INLINE, 0x88FA},
+ {0x2F9CA, 0, 1 | DECOMP_INLINE, 0x34BB},
+ {0x2F9CB, 0, 1, 5070},
+ {0x2F9CC, 0, 1, 5071},
+ {0x2F9CD, 0, 1 | DECOMP_INLINE, 0x46BE},
+ {0x2F9CE, 0, 1 | DECOMP_INLINE, 0x46C7},
+ {0x2F9CF, 0, 1 | DECOMP_INLINE, 0x8AA0},
+ {0x2F9D0, 0, 1 | DECOMP_INLINE, 0x8AED},
+ {0x2F9D1, 0, 1 | DECOMP_INLINE, 0x8B8A},
+ {0x2F9D2, 0, 1 | DECOMP_INLINE, 0x8C55},
+ {0x2F9D3, 0, 1, 5072},
+ {0x2F9D4, 0, 1 | DECOMP_INLINE, 0x8CAB},
+ {0x2F9D5, 0, 1 | DECOMP_INLINE, 0x8CC1},
+ {0x2F9D6, 0, 1 | DECOMP_INLINE, 0x8D1B},
+ {0x2F9D7, 0, 1 | DECOMP_INLINE, 0x8D77},
+ {0x2F9D8, 0, 1, 5073},
+ {0x2F9D9, 0, 1, 5074},
+ {0x2F9DA, 0, 1 | DECOMP_INLINE, 0x8DCB},
+ {0x2F9DB, 0, 1 | DECOMP_INLINE, 0x8DBC},
+ {0x2F9DC, 0, 1 | DECOMP_INLINE, 0x8DF0},
+ {0x2F9DD, 0, 1, 5075},
+ {0x2F9DE, 0, 1 | DECOMP_INLINE, 0x8ED4},
+ {0x2F9DF, 0, 1 | DECOMP_INLINE, 0x8F38},
+ {0x2F9E0, 0, 1, 5076},
+ {0x2F9E1, 0, 1, 5077},
+ {0x2F9E2, 0, 1 | DECOMP_INLINE, 0x9094},
+ {0x2F9E3, 0, 1 | DECOMP_INLINE, 0x90F1},
+ {0x2F9E4, 0, 1 | DECOMP_INLINE, 0x9111},
+ {0x2F9E5, 0, 1, 5078},
+ {0x2F9E6, 0, 1 | DECOMP_INLINE, 0x911B},
+ {0x2F9E7, 0, 1 | DECOMP_INLINE, 0x9238},
+ {0x2F9E8, 0, 1 | DECOMP_INLINE, 0x92D7},
+ {0x2F9E9, 0, 1 | DECOMP_INLINE, 0x92D8},
+ {0x2F9EA, 0, 1 | DECOMP_INLINE, 0x927C},
+ {0x2F9EB, 0, 1 | DECOMP_INLINE, 0x93F9},
+ {0x2F9EC, 0, 1 | DECOMP_INLINE, 0x9415},
+ {0x2F9ED, 0, 1, 5079},
+ {0x2F9EE, 0, 1 | DECOMP_INLINE, 0x958B},
+ {0x2F9EF, 0, 1 | DECOMP_INLINE, 0x4995},
+ {0x2F9F0, 0, 1 | DECOMP_INLINE, 0x95B7},
+ {0x2F9F1, 0, 1, 5080},
+ {0x2F9F2, 0, 1 | DECOMP_INLINE, 0x49E6},
+ {0x2F9F3, 0, 1 | DECOMP_INLINE, 0x96C3},
+ {0x2F9F4, 0, 1 | DECOMP_INLINE, 0x5DB2},
+ {0x2F9F5, 0, 1 | DECOMP_INLINE, 0x9723},
+ {0x2F9F6, 0, 1, 5081},
+ {0x2F9F7, 0, 1, 5082},
+ {0x2F9F8, 0, 1 | DECOMP_INLINE, 0x4A6E},
+ {0x2F9F9, 0, 1 | DECOMP_INLINE, 0x4A76},
+ {0x2F9FA, 0, 1 | DECOMP_INLINE, 0x97E0},
+ {0x2F9FB, 0, 1, 5083},
+ {0x2F9FC, 0, 1 | DECOMP_INLINE, 0x4AB2},
+ {0x2F9FD, 0, 1, 5084},
+ {0x2F9FE, 0, 1 | DECOMP_INLINE, 0x980B},
+ {0x2F9FF, 0, 1 | DECOMP_INLINE, 0x980B},
+ {0x2FA00, 0, 1 | DECOMP_INLINE, 0x9829},
+ {0x2FA01, 0, 1, 5085},
+ {0x2FA02, 0, 1 | DECOMP_INLINE, 0x98E2},
+ {0x2FA03, 0, 1 | DECOMP_INLINE, 0x4B33},
+ {0x2FA04, 0, 1 | DECOMP_INLINE, 0x9929},
+ {0x2FA05, 0, 1 | DECOMP_INLINE, 0x99A7},
+ {0x2FA06, 0, 1 | DECOMP_INLINE, 0x99C2},
+ {0x2FA07, 0, 1 | DECOMP_INLINE, 0x99FE},
+ {0x2FA08, 0, 1 | DECOMP_INLINE, 0x4BCE},
+ {0x2FA09, 0, 1, 5086},
+ {0x2FA0A, 0, 1 | DECOMP_INLINE, 0x9B12},
+ {0x2FA0B, 0, 1 | DECOMP_INLINE, 0x9C40},
+ {0x2FA0C, 0, 1 | DECOMP_INLINE, 0x9CFD},
+ {0x2FA0D, 0, 1 | DECOMP_INLINE, 0x4CCE},
+ {0x2FA0E, 0, 1 | DECOMP_INLINE, 0x4CED},
+ {0x2FA0F, 0, 1 | DECOMP_INLINE, 0x9D67},
+ {0x2FA10, 0, 1, 5087},
+ {0x2FA11, 0, 1 | DECOMP_INLINE, 0x4CF8},
+ {0x2FA12, 0, 1, 5088},
+ {0x2FA13, 0, 1, 5089},
+ {0x2FA14, 0, 1, 5090},
+ {0x2FA15, 0, 1 | DECOMP_INLINE, 0x9EBB},
+ {0x2FA16, 0, 1 | DECOMP_INLINE, 0x4D56},
+ {0x2FA17, 0, 1 | DECOMP_INLINE, 0x9EF9},
+ {0x2FA18, 0, 1 | DECOMP_INLINE, 0x9EFE},
+ {0x2FA19, 0, 1 | DECOMP_INLINE, 0x9F05},
+ {0x2FA1A, 0, 1 | DECOMP_INLINE, 0x9F0F},
+ {0x2FA1B, 0, 1 | DECOMP_INLINE, 0x9F16},
+ {0x2FA1C, 0, 1 | DECOMP_INLINE, 0x9F3B},
+ {0x2FA1D, 0, 1, 5091}
+
+};
+
+/* codepoints array */
+static const uint32 UnicodeDecomp_codepoints[5092] =
+{
+ /* 0 */ 0x0020, 0x0308,
+ /* 2 */ 0x0020, 0x0304,
+ /* 4 */ 0x0020, 0x0301,
+ /* 6 */ 0x0020, 0x0327,
+ /* 8 */ 0x0031, 0x2044, 0x0034,
+ /* 11 */ 0x0031, 0x2044, 0x0032,
+ /* 14 */ 0x0033, 0x2044, 0x0034,
+ /* 17 */ 0x0041, 0x0300,
+ /* 19 */ 0x0041, 0x0301,
+ /* 21 */ 0x0041, 0x0302,
+ /* 23 */ 0x0041, 0x0303,
+ /* 25 */ 0x0041, 0x0308,
+ /* 27 */ 0x0041, 0x030A,
+ /* 29 */ 0x0043, 0x0327,
+ /* 31 */ 0x0045, 0x0300,
+ /* 33 */ 0x0045, 0x0301,
+ /* 35 */ 0x0045, 0x0302,
+ /* 37 */ 0x0045, 0x0308,
+ /* 39 */ 0x0049, 0x0300,
+ /* 41 */ 0x0049, 0x0301,
+ /* 43 */ 0x0049, 0x0302,
+ /* 45 */ 0x0049, 0x0308,
+ /* 47 */ 0x004E, 0x0303,
+ /* 49 */ 0x004F, 0x0300,
+ /* 51 */ 0x004F, 0x0301,
+ /* 53 */ 0x004F, 0x0302,
+ /* 55 */ 0x004F, 0x0303,
+ /* 57 */ 0x004F, 0x0308,
+ /* 59 */ 0x0055, 0x0300,
+ /* 61 */ 0x0055, 0x0301,
+ /* 63 */ 0x0055, 0x0302,
+ /* 65 */ 0x0055, 0x0308,
+ /* 67 */ 0x0059, 0x0301,
+ /* 69 */ 0x0061, 0x0300,
+ /* 71 */ 0x0061, 0x0301,
+ /* 73 */ 0x0061, 0x0302,
+ /* 75 */ 0x0061, 0x0303,
+ /* 77 */ 0x0061, 0x0308,
+ /* 79 */ 0x0061, 0x030A,
+ /* 81 */ 0x0063, 0x0327,
+ /* 83 */ 0x0065, 0x0300,
+ /* 85 */ 0x0065, 0x0301,
+ /* 87 */ 0x0065, 0x0302,
+ /* 89 */ 0x0065, 0x0308,
+ /* 91 */ 0x0069, 0x0300,
+ /* 93 */ 0x0069, 0x0301,
+ /* 95 */ 0x0069, 0x0302,
+ /* 97 */ 0x0069, 0x0308,
+ /* 99 */ 0x006E, 0x0303,
+ /* 101 */ 0x006F, 0x0300,
+ /* 103 */ 0x006F, 0x0301,
+ /* 105 */ 0x006F, 0x0302,
+ /* 107 */ 0x006F, 0x0303,
+ /* 109 */ 0x006F, 0x0308,
+ /* 111 */ 0x0075, 0x0300,
+ /* 113 */ 0x0075, 0x0301,
+ /* 115 */ 0x0075, 0x0302,
+ /* 117 */ 0x0075, 0x0308,
+ /* 119 */ 0x0079, 0x0301,
+ /* 121 */ 0x0079, 0x0308,
+ /* 123 */ 0x0041, 0x0304,
+ /* 125 */ 0x0061, 0x0304,
+ /* 127 */ 0x0041, 0x0306,
+ /* 129 */ 0x0061, 0x0306,
+ /* 131 */ 0x0041, 0x0328,
+ /* 133 */ 0x0061, 0x0328,
+ /* 135 */ 0x0043, 0x0301,
+ /* 137 */ 0x0063, 0x0301,
+ /* 139 */ 0x0043, 0x0302,
+ /* 141 */ 0x0063, 0x0302,
+ /* 143 */ 0x0043, 0x0307,
+ /* 145 */ 0x0063, 0x0307,
+ /* 147 */ 0x0043, 0x030C,
+ /* 149 */ 0x0063, 0x030C,
+ /* 151 */ 0x0044, 0x030C,
+ /* 153 */ 0x0064, 0x030C,
+ /* 155 */ 0x0045, 0x0304,
+ /* 157 */ 0x0065, 0x0304,
+ /* 159 */ 0x0045, 0x0306,
+ /* 161 */ 0x0065, 0x0306,
+ /* 163 */ 0x0045, 0x0307,
+ /* 165 */ 0x0065, 0x0307,
+ /* 167 */ 0x0045, 0x0328,
+ /* 169 */ 0x0065, 0x0328,
+ /* 171 */ 0x0045, 0x030C,
+ /* 173 */ 0x0065, 0x030C,
+ /* 175 */ 0x0047, 0x0302,
+ /* 177 */ 0x0067, 0x0302,
+ /* 179 */ 0x0047, 0x0306,
+ /* 181 */ 0x0067, 0x0306,
+ /* 183 */ 0x0047, 0x0307,
+ /* 185 */ 0x0067, 0x0307,
+ /* 187 */ 0x0047, 0x0327,
+ /* 189 */ 0x0067, 0x0327,
+ /* 191 */ 0x0048, 0x0302,
+ /* 193 */ 0x0068, 0x0302,
+ /* 195 */ 0x0049, 0x0303,
+ /* 197 */ 0x0069, 0x0303,
+ /* 199 */ 0x0049, 0x0304,
+ /* 201 */ 0x0069, 0x0304,
+ /* 203 */ 0x0049, 0x0306,
+ /* 205 */ 0x0069, 0x0306,
+ /* 207 */ 0x0049, 0x0328,
+ /* 209 */ 0x0069, 0x0328,
+ /* 211 */ 0x0049, 0x0307,
+ /* 213 */ 0x0049, 0x004A,
+ /* 215 */ 0x0069, 0x006A,
+ /* 217 */ 0x004A, 0x0302,
+ /* 219 */ 0x006A, 0x0302,
+ /* 221 */ 0x004B, 0x0327,
+ /* 223 */ 0x006B, 0x0327,
+ /* 225 */ 0x004C, 0x0301,
+ /* 227 */ 0x006C, 0x0301,
+ /* 229 */ 0x004C, 0x0327,
+ /* 231 */ 0x006C, 0x0327,
+ /* 233 */ 0x004C, 0x030C,
+ /* 235 */ 0x006C, 0x030C,
+ /* 237 */ 0x004C, 0x00B7,
+ /* 239 */ 0x006C, 0x00B7,
+ /* 241 */ 0x004E, 0x0301,
+ /* 243 */ 0x006E, 0x0301,
+ /* 245 */ 0x004E, 0x0327,
+ /* 247 */ 0x006E, 0x0327,
+ /* 249 */ 0x004E, 0x030C,
+ /* 251 */ 0x006E, 0x030C,
+ /* 253 */ 0x02BC, 0x006E,
+ /* 255 */ 0x004F, 0x0304,
+ /* 257 */ 0x006F, 0x0304,
+ /* 259 */ 0x004F, 0x0306,
+ /* 261 */ 0x006F, 0x0306,
+ /* 263 */ 0x004F, 0x030B,
+ /* 265 */ 0x006F, 0x030B,
+ /* 267 */ 0x0052, 0x0301,
+ /* 269 */ 0x0072, 0x0301,
+ /* 271 */ 0x0052, 0x0327,
+ /* 273 */ 0x0072, 0x0327,
+ /* 275 */ 0x0052, 0x030C,
+ /* 277 */ 0x0072, 0x030C,
+ /* 279 */ 0x0053, 0x0301,
+ /* 281 */ 0x0073, 0x0301,
+ /* 283 */ 0x0053, 0x0302,
+ /* 285 */ 0x0073, 0x0302,
+ /* 287 */ 0x0053, 0x0327,
+ /* 289 */ 0x0073, 0x0327,
+ /* 291 */ 0x0053, 0x030C,
+ /* 293 */ 0x0073, 0x030C,
+ /* 295 */ 0x0054, 0x0327,
+ /* 297 */ 0x0074, 0x0327,
+ /* 299 */ 0x0054, 0x030C,
+ /* 301 */ 0x0074, 0x030C,
+ /* 303 */ 0x0055, 0x0303,
+ /* 305 */ 0x0075, 0x0303,
+ /* 307 */ 0x0055, 0x0304,
+ /* 309 */ 0x0075, 0x0304,
+ /* 311 */ 0x0055, 0x0306,
+ /* 313 */ 0x0075, 0x0306,
+ /* 315 */ 0x0055, 0x030A,
+ /* 317 */ 0x0075, 0x030A,
+ /* 319 */ 0x0055, 0x030B,
+ /* 321 */ 0x0075, 0x030B,
+ /* 323 */ 0x0055, 0x0328,
+ /* 325 */ 0x0075, 0x0328,
+ /* 327 */ 0x0057, 0x0302,
+ /* 329 */ 0x0077, 0x0302,
+ /* 331 */ 0x0059, 0x0302,
+ /* 333 */ 0x0079, 0x0302,
+ /* 335 */ 0x0059, 0x0308,
+ /* 337 */ 0x005A, 0x0301,
+ /* 339 */ 0x007A, 0x0301,
+ /* 341 */ 0x005A, 0x0307,
+ /* 343 */ 0x007A, 0x0307,
+ /* 345 */ 0x005A, 0x030C,
+ /* 347 */ 0x007A, 0x030C,
+ /* 349 */ 0x004F, 0x031B,
+ /* 351 */ 0x006F, 0x031B,
+ /* 353 */ 0x0055, 0x031B,
+ /* 355 */ 0x0075, 0x031B,
+ /* 357 */ 0x0044, 0x017D,
+ /* 359 */ 0x0044, 0x017E,
+ /* 361 */ 0x0064, 0x017E,
+ /* 363 */ 0x004C, 0x004A,
+ /* 365 */ 0x004C, 0x006A,
+ /* 367 */ 0x006C, 0x006A,
+ /* 369 */ 0x004E, 0x004A,
+ /* 371 */ 0x004E, 0x006A,
+ /* 373 */ 0x006E, 0x006A,
+ /* 375 */ 0x0041, 0x030C,
+ /* 377 */ 0x0061, 0x030C,
+ /* 379 */ 0x0049, 0x030C,
+ /* 381 */ 0x0069, 0x030C,
+ /* 383 */ 0x004F, 0x030C,
+ /* 385 */ 0x006F, 0x030C,
+ /* 387 */ 0x0055, 0x030C,
+ /* 389 */ 0x0075, 0x030C,
+ /* 391 */ 0x00DC, 0x0304,
+ /* 393 */ 0x00FC, 0x0304,
+ /* 395 */ 0x00DC, 0x0301,
+ /* 397 */ 0x00FC, 0x0301,
+ /* 399 */ 0x00DC, 0x030C,
+ /* 401 */ 0x00FC, 0x030C,
+ /* 403 */ 0x00DC, 0x0300,
+ /* 405 */ 0x00FC, 0x0300,
+ /* 407 */ 0x00C4, 0x0304,
+ /* 409 */ 0x00E4, 0x0304,
+ /* 411 */ 0x0226, 0x0304,
+ /* 413 */ 0x0227, 0x0304,
+ /* 415 */ 0x00C6, 0x0304,
+ /* 417 */ 0x00E6, 0x0304,
+ /* 419 */ 0x0047, 0x030C,
+ /* 421 */ 0x0067, 0x030C,
+ /* 423 */ 0x004B, 0x030C,
+ /* 425 */ 0x006B, 0x030C,
+ /* 427 */ 0x004F, 0x0328,
+ /* 429 */ 0x006F, 0x0328,
+ /* 431 */ 0x01EA, 0x0304,
+ /* 433 */ 0x01EB, 0x0304,
+ /* 435 */ 0x01B7, 0x030C,
+ /* 437 */ 0x0292, 0x030C,
+ /* 439 */ 0x006A, 0x030C,
+ /* 441 */ 0x0044, 0x005A,
+ /* 443 */ 0x0044, 0x007A,
+ /* 445 */ 0x0064, 0x007A,
+ /* 447 */ 0x0047, 0x0301,
+ /* 449 */ 0x0067, 0x0301,
+ /* 451 */ 0x004E, 0x0300,
+ /* 453 */ 0x006E, 0x0300,
+ /* 455 */ 0x00C5, 0x0301,
+ /* 457 */ 0x00E5, 0x0301,
+ /* 459 */ 0x00C6, 0x0301,
+ /* 461 */ 0x00E6, 0x0301,
+ /* 463 */ 0x00D8, 0x0301,
+ /* 465 */ 0x00F8, 0x0301,
+ /* 467 */ 0x0041, 0x030F,
+ /* 469 */ 0x0061, 0x030F,
+ /* 471 */ 0x0041, 0x0311,
+ /* 473 */ 0x0061, 0x0311,
+ /* 475 */ 0x0045, 0x030F,
+ /* 477 */ 0x0065, 0x030F,
+ /* 479 */ 0x0045, 0x0311,
+ /* 481 */ 0x0065, 0x0311,
+ /* 483 */ 0x0049, 0x030F,
+ /* 485 */ 0x0069, 0x030F,
+ /* 487 */ 0x0049, 0x0311,
+ /* 489 */ 0x0069, 0x0311,
+ /* 491 */ 0x004F, 0x030F,
+ /* 493 */ 0x006F, 0x030F,
+ /* 495 */ 0x004F, 0x0311,
+ /* 497 */ 0x006F, 0x0311,
+ /* 499 */ 0x0052, 0x030F,
+ /* 501 */ 0x0072, 0x030F,
+ /* 503 */ 0x0052, 0x0311,
+ /* 505 */ 0x0072, 0x0311,
+ /* 507 */ 0x0055, 0x030F,
+ /* 509 */ 0x0075, 0x030F,
+ /* 511 */ 0x0055, 0x0311,
+ /* 513 */ 0x0075, 0x0311,
+ /* 515 */ 0x0053, 0x0326,
+ /* 517 */ 0x0073, 0x0326,
+ /* 519 */ 0x0054, 0x0326,
+ /* 521 */ 0x0074, 0x0326,
+ /* 523 */ 0x0048, 0x030C,
+ /* 525 */ 0x0068, 0x030C,
+ /* 527 */ 0x0041, 0x0307,
+ /* 529 */ 0x0061, 0x0307,
+ /* 531 */ 0x0045, 0x0327,
+ /* 533 */ 0x0065, 0x0327,
+ /* 535 */ 0x00D6, 0x0304,
+ /* 537 */ 0x00F6, 0x0304,
+ /* 539 */ 0x00D5, 0x0304,
+ /* 541 */ 0x00F5, 0x0304,
+ /* 543 */ 0x004F, 0x0307,
+ /* 545 */ 0x006F, 0x0307,
+ /* 547 */ 0x022E, 0x0304,
+ /* 549 */ 0x022F, 0x0304,
+ /* 551 */ 0x0059, 0x0304,
+ /* 553 */ 0x0079, 0x0304,
+ /* 555 */ 0x0020, 0x0306,
+ /* 557 */ 0x0020, 0x0307,
+ /* 559 */ 0x0020, 0x030A,
+ /* 561 */ 0x0020, 0x0328,
+ /* 563 */ 0x0020, 0x0303,
+ /* 565 */ 0x0020, 0x030B,
+ /* 567 */ 0x0308, 0x0301,
+ /* 569 */ 0x0020, 0x0345,
+ /* 571 */ 0x0020, 0x0301,
+ /* 573 */ 0x00A8, 0x0301,
+ /* 575 */ 0x0391, 0x0301,
+ /* 577 */ 0x0395, 0x0301,
+ /* 579 */ 0x0397, 0x0301,
+ /* 581 */ 0x0399, 0x0301,
+ /* 583 */ 0x039F, 0x0301,
+ /* 585 */ 0x03A5, 0x0301,
+ /* 587 */ 0x03A9, 0x0301,
+ /* 589 */ 0x03CA, 0x0301,
+ /* 591 */ 0x0399, 0x0308,
+ /* 593 */ 0x03A5, 0x0308,
+ /* 595 */ 0x03B1, 0x0301,
+ /* 597 */ 0x03B5, 0x0301,
+ /* 599 */ 0x03B7, 0x0301,
+ /* 601 */ 0x03B9, 0x0301,
+ /* 603 */ 0x03CB, 0x0301,
+ /* 605 */ 0x03B9, 0x0308,
+ /* 607 */ 0x03C5, 0x0308,
+ /* 609 */ 0x03BF, 0x0301,
+ /* 611 */ 0x03C5, 0x0301,
+ /* 613 */ 0x03C9, 0x0301,
+ /* 615 */ 0x03D2, 0x0301,
+ /* 617 */ 0x03D2, 0x0308,
+ /* 619 */ 0x0415, 0x0300,
+ /* 621 */ 0x0415, 0x0308,
+ /* 623 */ 0x0413, 0x0301,
+ /* 625 */ 0x0406, 0x0308,
+ /* 627 */ 0x041A, 0x0301,
+ /* 629 */ 0x0418, 0x0300,
+ /* 631 */ 0x0423, 0x0306,
+ /* 633 */ 0x0418, 0x0306,
+ /* 635 */ 0x0438, 0x0306,
+ /* 637 */ 0x0435, 0x0300,
+ /* 639 */ 0x0435, 0x0308,
+ /* 641 */ 0x0433, 0x0301,
+ /* 643 */ 0x0456, 0x0308,
+ /* 645 */ 0x043A, 0x0301,
+ /* 647 */ 0x0438, 0x0300,
+ /* 649 */ 0x0443, 0x0306,
+ /* 651 */ 0x0474, 0x030F,
+ /* 653 */ 0x0475, 0x030F,
+ /* 655 */ 0x0416, 0x0306,
+ /* 657 */ 0x0436, 0x0306,
+ /* 659 */ 0x0410, 0x0306,
+ /* 661 */ 0x0430, 0x0306,
+ /* 663 */ 0x0410, 0x0308,
+ /* 665 */ 0x0430, 0x0308,
+ /* 667 */ 0x0415, 0x0306,
+ /* 669 */ 0x0435, 0x0306,
+ /* 671 */ 0x04D8, 0x0308,
+ /* 673 */ 0x04D9, 0x0308,
+ /* 675 */ 0x0416, 0x0308,
+ /* 677 */ 0x0436, 0x0308,
+ /* 679 */ 0x0417, 0x0308,
+ /* 681 */ 0x0437, 0x0308,
+ /* 683 */ 0x0418, 0x0304,
+ /* 685 */ 0x0438, 0x0304,
+ /* 687 */ 0x0418, 0x0308,
+ /* 689 */ 0x0438, 0x0308,
+ /* 691 */ 0x041E, 0x0308,
+ /* 693 */ 0x043E, 0x0308,
+ /* 695 */ 0x04E8, 0x0308,
+ /* 697 */ 0x04E9, 0x0308,
+ /* 699 */ 0x042D, 0x0308,
+ /* 701 */ 0x044D, 0x0308,
+ /* 703 */ 0x0423, 0x0304,
+ /* 705 */ 0x0443, 0x0304,
+ /* 707 */ 0x0423, 0x0308,
+ /* 709 */ 0x0443, 0x0308,
+ /* 711 */ 0x0423, 0x030B,
+ /* 713 */ 0x0443, 0x030B,
+ /* 715 */ 0x0427, 0x0308,
+ /* 717 */ 0x0447, 0x0308,
+ /* 719 */ 0x042B, 0x0308,
+ /* 721 */ 0x044B, 0x0308,
+ /* 723 */ 0x0565, 0x0582,
+ /* 725 */ 0x0627, 0x0653,
+ /* 727 */ 0x0627, 0x0654,
+ /* 729 */ 0x0648, 0x0654,
+ /* 731 */ 0x0627, 0x0655,
+ /* 733 */ 0x064A, 0x0654,
+ /* 735 */ 0x0627, 0x0674,
+ /* 737 */ 0x0648, 0x0674,
+ /* 739 */ 0x06C7, 0x0674,
+ /* 741 */ 0x064A, 0x0674,
+ /* 743 */ 0x06D5, 0x0654,
+ /* 745 */ 0x06C1, 0x0654,
+ /* 747 */ 0x06D2, 0x0654,
+ /* 749 */ 0x0928, 0x093C,
+ /* 751 */ 0x0930, 0x093C,
+ /* 753 */ 0x0933, 0x093C,
+ /* 755 */ 0x0915, 0x093C,
+ /* 757 */ 0x0916, 0x093C,
+ /* 759 */ 0x0917, 0x093C,
+ /* 761 */ 0x091C, 0x093C,
+ /* 763 */ 0x0921, 0x093C,
+ /* 765 */ 0x0922, 0x093C,
+ /* 767 */ 0x092B, 0x093C,
+ /* 769 */ 0x092F, 0x093C,
+ /* 771 */ 0x09C7, 0x09BE,
+ /* 773 */ 0x09C7, 0x09D7,
+ /* 775 */ 0x09A1, 0x09BC,
+ /* 777 */ 0x09A2, 0x09BC,
+ /* 779 */ 0x09AF, 0x09BC,
+ /* 781 */ 0x0A32, 0x0A3C,
+ /* 783 */ 0x0A38, 0x0A3C,
+ /* 785 */ 0x0A16, 0x0A3C,
+ /* 787 */ 0x0A17, 0x0A3C,
+ /* 789 */ 0x0A1C, 0x0A3C,
+ /* 791 */ 0x0A2B, 0x0A3C,
+ /* 793 */ 0x0B47, 0x0B56,
+ /* 795 */ 0x0B47, 0x0B3E,
+ /* 797 */ 0x0B47, 0x0B57,
+ /* 799 */ 0x0B21, 0x0B3C,
+ /* 801 */ 0x0B22, 0x0B3C,
+ /* 803 */ 0x0B92, 0x0BD7,
+ /* 805 */ 0x0BC6, 0x0BBE,
+ /* 807 */ 0x0BC7, 0x0BBE,
+ /* 809 */ 0x0BC6, 0x0BD7,
+ /* 811 */ 0x0C46, 0x0C56,
+ /* 813 */ 0x0CBF, 0x0CD5,
+ /* 815 */ 0x0CC6, 0x0CD5,
+ /* 817 */ 0x0CC6, 0x0CD6,
+ /* 819 */ 0x0CC6, 0x0CC2,
+ /* 821 */ 0x0CCA, 0x0CD5,
+ /* 823 */ 0x0D46, 0x0D3E,
+ /* 825 */ 0x0D47, 0x0D3E,
+ /* 827 */ 0x0D46, 0x0D57,
+ /* 829 */ 0x0DD9, 0x0DCA,
+ /* 831 */ 0x0DD9, 0x0DCF,
+ /* 833 */ 0x0DDC, 0x0DCA,
+ /* 835 */ 0x0DD9, 0x0DDF,
+ /* 837 */ 0x0E4D, 0x0E32,
+ /* 839 */ 0x0ECD, 0x0EB2,
+ /* 841 */ 0x0EAB, 0x0E99,
+ /* 843 */ 0x0EAB, 0x0EA1,
+ /* 845 */ 0x0F42, 0x0FB7,
+ /* 847 */ 0x0F4C, 0x0FB7,
+ /* 849 */ 0x0F51, 0x0FB7,
+ /* 851 */ 0x0F56, 0x0FB7,
+ /* 853 */ 0x0F5B, 0x0FB7,
+ /* 855 */ 0x0F40, 0x0FB5,
+ /* 857 */ 0x0F71, 0x0F72,
+ /* 859 */ 0x0F71, 0x0F74,
+ /* 861 */ 0x0FB2, 0x0F80,
+ /* 863 */ 0x0FB2, 0x0F81,
+ /* 865 */ 0x0FB3, 0x0F80,
+ /* 867 */ 0x0FB3, 0x0F81,
+ /* 869 */ 0x0F71, 0x0F80,
+ /* 871 */ 0x0F92, 0x0FB7,
+ /* 873 */ 0x0F9C, 0x0FB7,
+ /* 875 */ 0x0FA1, 0x0FB7,
+ /* 877 */ 0x0FA6, 0x0FB7,
+ /* 879 */ 0x0FAB, 0x0FB7,
+ /* 881 */ 0x0F90, 0x0FB5,
+ /* 883 */ 0x1025, 0x102E,
+ /* 885 */ 0x1B05, 0x1B35,
+ /* 887 */ 0x1B07, 0x1B35,
+ /* 889 */ 0x1B09, 0x1B35,
+ /* 891 */ 0x1B0B, 0x1B35,
+ /* 893 */ 0x1B0D, 0x1B35,
+ /* 895 */ 0x1B11, 0x1B35,
+ /* 897 */ 0x1B3A, 0x1B35,
+ /* 899 */ 0x1B3C, 0x1B35,
+ /* 901 */ 0x1B3E, 0x1B35,
+ /* 903 */ 0x1B3F, 0x1B35,
+ /* 905 */ 0x1B42, 0x1B35,
+ /* 907 */ 0x0041, 0x0325,
+ /* 909 */ 0x0061, 0x0325,
+ /* 911 */ 0x0042, 0x0307,
+ /* 913 */ 0x0062, 0x0307,
+ /* 915 */ 0x0042, 0x0323,
+ /* 917 */ 0x0062, 0x0323,
+ /* 919 */ 0x0042, 0x0331,
+ /* 921 */ 0x0062, 0x0331,
+ /* 923 */ 0x00C7, 0x0301,
+ /* 925 */ 0x00E7, 0x0301,
+ /* 927 */ 0x0044, 0x0307,
+ /* 929 */ 0x0064, 0x0307,
+ /* 931 */ 0x0044, 0x0323,
+ /* 933 */ 0x0064, 0x0323,
+ /* 935 */ 0x0044, 0x0331,
+ /* 937 */ 0x0064, 0x0331,
+ /* 939 */ 0x0044, 0x0327,
+ /* 941 */ 0x0064, 0x0327,
+ /* 943 */ 0x0044, 0x032D,
+ /* 945 */ 0x0064, 0x032D,
+ /* 947 */ 0x0112, 0x0300,
+ /* 949 */ 0x0113, 0x0300,
+ /* 951 */ 0x0112, 0x0301,
+ /* 953 */ 0x0113, 0x0301,
+ /* 955 */ 0x0045, 0x032D,
+ /* 957 */ 0x0065, 0x032D,
+ /* 959 */ 0x0045, 0x0330,
+ /* 961 */ 0x0065, 0x0330,
+ /* 963 */ 0x0228, 0x0306,
+ /* 965 */ 0x0229, 0x0306,
+ /* 967 */ 0x0046, 0x0307,
+ /* 969 */ 0x0066, 0x0307,
+ /* 971 */ 0x0047, 0x0304,
+ /* 973 */ 0x0067, 0x0304,
+ /* 975 */ 0x0048, 0x0307,
+ /* 977 */ 0x0068, 0x0307,
+ /* 979 */ 0x0048, 0x0323,
+ /* 981 */ 0x0068, 0x0323,
+ /* 983 */ 0x0048, 0x0308,
+ /* 985 */ 0x0068, 0x0308,
+ /* 987 */ 0x0048, 0x0327,
+ /* 989 */ 0x0068, 0x0327,
+ /* 991 */ 0x0048, 0x032E,
+ /* 993 */ 0x0068, 0x032E,
+ /* 995 */ 0x0049, 0x0330,
+ /* 997 */ 0x0069, 0x0330,
+ /* 999 */ 0x00CF, 0x0301,
+ /* 1001 */ 0x00EF, 0x0301,
+ /* 1003 */ 0x004B, 0x0301,
+ /* 1005 */ 0x006B, 0x0301,
+ /* 1007 */ 0x004B, 0x0323,
+ /* 1009 */ 0x006B, 0x0323,
+ /* 1011 */ 0x004B, 0x0331,
+ /* 1013 */ 0x006B, 0x0331,
+ /* 1015 */ 0x004C, 0x0323,
+ /* 1017 */ 0x006C, 0x0323,
+ /* 1019 */ 0x1E36, 0x0304,
+ /* 1021 */ 0x1E37, 0x0304,
+ /* 1023 */ 0x004C, 0x0331,
+ /* 1025 */ 0x006C, 0x0331,
+ /* 1027 */ 0x004C, 0x032D,
+ /* 1029 */ 0x006C, 0x032D,
+ /* 1031 */ 0x004D, 0x0301,
+ /* 1033 */ 0x006D, 0x0301,
+ /* 1035 */ 0x004D, 0x0307,
+ /* 1037 */ 0x006D, 0x0307,
+ /* 1039 */ 0x004D, 0x0323,
+ /* 1041 */ 0x006D, 0x0323,
+ /* 1043 */ 0x004E, 0x0307,
+ /* 1045 */ 0x006E, 0x0307,
+ /* 1047 */ 0x004E, 0x0323,
+ /* 1049 */ 0x006E, 0x0323,
+ /* 1051 */ 0x004E, 0x0331,
+ /* 1053 */ 0x006E, 0x0331,
+ /* 1055 */ 0x004E, 0x032D,
+ /* 1057 */ 0x006E, 0x032D,
+ /* 1059 */ 0x00D5, 0x0301,
+ /* 1061 */ 0x00F5, 0x0301,
+ /* 1063 */ 0x00D5, 0x0308,
+ /* 1065 */ 0x00F5, 0x0308,
+ /* 1067 */ 0x014C, 0x0300,
+ /* 1069 */ 0x014D, 0x0300,
+ /* 1071 */ 0x014C, 0x0301,
+ /* 1073 */ 0x014D, 0x0301,
+ /* 1075 */ 0x0050, 0x0301,
+ /* 1077 */ 0x0070, 0x0301,
+ /* 1079 */ 0x0050, 0x0307,
+ /* 1081 */ 0x0070, 0x0307,
+ /* 1083 */ 0x0052, 0x0307,
+ /* 1085 */ 0x0072, 0x0307,
+ /* 1087 */ 0x0052, 0x0323,
+ /* 1089 */ 0x0072, 0x0323,
+ /* 1091 */ 0x1E5A, 0x0304,
+ /* 1093 */ 0x1E5B, 0x0304,
+ /* 1095 */ 0x0052, 0x0331,
+ /* 1097 */ 0x0072, 0x0331,
+ /* 1099 */ 0x0053, 0x0307,
+ /* 1101 */ 0x0073, 0x0307,
+ /* 1103 */ 0x0053, 0x0323,
+ /* 1105 */ 0x0073, 0x0323,
+ /* 1107 */ 0x015A, 0x0307,
+ /* 1109 */ 0x015B, 0x0307,
+ /* 1111 */ 0x0160, 0x0307,
+ /* 1113 */ 0x0161, 0x0307,
+ /* 1115 */ 0x1E62, 0x0307,
+ /* 1117 */ 0x1E63, 0x0307,
+ /* 1119 */ 0x0054, 0x0307,
+ /* 1121 */ 0x0074, 0x0307,
+ /* 1123 */ 0x0054, 0x0323,
+ /* 1125 */ 0x0074, 0x0323,
+ /* 1127 */ 0x0054, 0x0331,
+ /* 1129 */ 0x0074, 0x0331,
+ /* 1131 */ 0x0054, 0x032D,
+ /* 1133 */ 0x0074, 0x032D,
+ /* 1135 */ 0x0055, 0x0324,
+ /* 1137 */ 0x0075, 0x0324,
+ /* 1139 */ 0x0055, 0x0330,
+ /* 1141 */ 0x0075, 0x0330,
+ /* 1143 */ 0x0055, 0x032D,
+ /* 1145 */ 0x0075, 0x032D,
+ /* 1147 */ 0x0168, 0x0301,
+ /* 1149 */ 0x0169, 0x0301,
+ /* 1151 */ 0x016A, 0x0308,
+ /* 1153 */ 0x016B, 0x0308,
+ /* 1155 */ 0x0056, 0x0303,
+ /* 1157 */ 0x0076, 0x0303,
+ /* 1159 */ 0x0056, 0x0323,
+ /* 1161 */ 0x0076, 0x0323,
+ /* 1163 */ 0x0057, 0x0300,
+ /* 1165 */ 0x0077, 0x0300,
+ /* 1167 */ 0x0057, 0x0301,
+ /* 1169 */ 0x0077, 0x0301,
+ /* 1171 */ 0x0057, 0x0308,
+ /* 1173 */ 0x0077, 0x0308,
+ /* 1175 */ 0x0057, 0x0307,
+ /* 1177 */ 0x0077, 0x0307,
+ /* 1179 */ 0x0057, 0x0323,
+ /* 1181 */ 0x0077, 0x0323,
+ /* 1183 */ 0x0058, 0x0307,
+ /* 1185 */ 0x0078, 0x0307,
+ /* 1187 */ 0x0058, 0x0308,
+ /* 1189 */ 0x0078, 0x0308,
+ /* 1191 */ 0x0059, 0x0307,
+ /* 1193 */ 0x0079, 0x0307,
+ /* 1195 */ 0x005A, 0x0302,
+ /* 1197 */ 0x007A, 0x0302,
+ /* 1199 */ 0x005A, 0x0323,
+ /* 1201 */ 0x007A, 0x0323,
+ /* 1203 */ 0x005A, 0x0331,
+ /* 1205 */ 0x007A, 0x0331,
+ /* 1207 */ 0x0068, 0x0331,
+ /* 1209 */ 0x0074, 0x0308,
+ /* 1211 */ 0x0077, 0x030A,
+ /* 1213 */ 0x0079, 0x030A,
+ /* 1215 */ 0x0061, 0x02BE,
+ /* 1217 */ 0x017F, 0x0307,
+ /* 1219 */ 0x0041, 0x0323,
+ /* 1221 */ 0x0061, 0x0323,
+ /* 1223 */ 0x0041, 0x0309,
+ /* 1225 */ 0x0061, 0x0309,
+ /* 1227 */ 0x00C2, 0x0301,
+ /* 1229 */ 0x00E2, 0x0301,
+ /* 1231 */ 0x00C2, 0x0300,
+ /* 1233 */ 0x00E2, 0x0300,
+ /* 1235 */ 0x00C2, 0x0309,
+ /* 1237 */ 0x00E2, 0x0309,
+ /* 1239 */ 0x00C2, 0x0303,
+ /* 1241 */ 0x00E2, 0x0303,
+ /* 1243 */ 0x1EA0, 0x0302,
+ /* 1245 */ 0x1EA1, 0x0302,
+ /* 1247 */ 0x0102, 0x0301,
+ /* 1249 */ 0x0103, 0x0301,
+ /* 1251 */ 0x0102, 0x0300,
+ /* 1253 */ 0x0103, 0x0300,
+ /* 1255 */ 0x0102, 0x0309,
+ /* 1257 */ 0x0103, 0x0309,
+ /* 1259 */ 0x0102, 0x0303,
+ /* 1261 */ 0x0103, 0x0303,
+ /* 1263 */ 0x1EA0, 0x0306,
+ /* 1265 */ 0x1EA1, 0x0306,
+ /* 1267 */ 0x0045, 0x0323,
+ /* 1269 */ 0x0065, 0x0323,
+ /* 1271 */ 0x0045, 0x0309,
+ /* 1273 */ 0x0065, 0x0309,
+ /* 1275 */ 0x0045, 0x0303,
+ /* 1277 */ 0x0065, 0x0303,
+ /* 1279 */ 0x00CA, 0x0301,
+ /* 1281 */ 0x00EA, 0x0301,
+ /* 1283 */ 0x00CA, 0x0300,
+ /* 1285 */ 0x00EA, 0x0300,
+ /* 1287 */ 0x00CA, 0x0309,
+ /* 1289 */ 0x00EA, 0x0309,
+ /* 1291 */ 0x00CA, 0x0303,
+ /* 1293 */ 0x00EA, 0x0303,
+ /* 1295 */ 0x1EB8, 0x0302,
+ /* 1297 */ 0x1EB9, 0x0302,
+ /* 1299 */ 0x0049, 0x0309,
+ /* 1301 */ 0x0069, 0x0309,
+ /* 1303 */ 0x0049, 0x0323,
+ /* 1305 */ 0x0069, 0x0323,
+ /* 1307 */ 0x004F, 0x0323,
+ /* 1309 */ 0x006F, 0x0323,
+ /* 1311 */ 0x004F, 0x0309,
+ /* 1313 */ 0x006F, 0x0309,
+ /* 1315 */ 0x00D4, 0x0301,
+ /* 1317 */ 0x00F4, 0x0301,
+ /* 1319 */ 0x00D4, 0x0300,
+ /* 1321 */ 0x00F4, 0x0300,
+ /* 1323 */ 0x00D4, 0x0309,
+ /* 1325 */ 0x00F4, 0x0309,
+ /* 1327 */ 0x00D4, 0x0303,
+ /* 1329 */ 0x00F4, 0x0303,
+ /* 1331 */ 0x1ECC, 0x0302,
+ /* 1333 */ 0x1ECD, 0x0302,
+ /* 1335 */ 0x01A0, 0x0301,
+ /* 1337 */ 0x01A1, 0x0301,
+ /* 1339 */ 0x01A0, 0x0300,
+ /* 1341 */ 0x01A1, 0x0300,
+ /* 1343 */ 0x01A0, 0x0309,
+ /* 1345 */ 0x01A1, 0x0309,
+ /* 1347 */ 0x01A0, 0x0303,
+ /* 1349 */ 0x01A1, 0x0303,
+ /* 1351 */ 0x01A0, 0x0323,
+ /* 1353 */ 0x01A1, 0x0323,
+ /* 1355 */ 0x0055, 0x0323,
+ /* 1357 */ 0x0075, 0x0323,
+ /* 1359 */ 0x0055, 0x0309,
+ /* 1361 */ 0x0075, 0x0309,
+ /* 1363 */ 0x01AF, 0x0301,
+ /* 1365 */ 0x01B0, 0x0301,
+ /* 1367 */ 0x01AF, 0x0300,
+ /* 1369 */ 0x01B0, 0x0300,
+ /* 1371 */ 0x01AF, 0x0309,
+ /* 1373 */ 0x01B0, 0x0309,
+ /* 1375 */ 0x01AF, 0x0303,
+ /* 1377 */ 0x01B0, 0x0303,
+ /* 1379 */ 0x01AF, 0x0323,
+ /* 1381 */ 0x01B0, 0x0323,
+ /* 1383 */ 0x0059, 0x0300,
+ /* 1385 */ 0x0079, 0x0300,
+ /* 1387 */ 0x0059, 0x0323,
+ /* 1389 */ 0x0079, 0x0323,
+ /* 1391 */ 0x0059, 0x0309,
+ /* 1393 */ 0x0079, 0x0309,
+ /* 1395 */ 0x0059, 0x0303,
+ /* 1397 */ 0x0079, 0x0303,
+ /* 1399 */ 0x03B1, 0x0313,
+ /* 1401 */ 0x03B1, 0x0314,
+ /* 1403 */ 0x1F00, 0x0300,
+ /* 1405 */ 0x1F01, 0x0300,
+ /* 1407 */ 0x1F00, 0x0301,
+ /* 1409 */ 0x1F01, 0x0301,
+ /* 1411 */ 0x1F00, 0x0342,
+ /* 1413 */ 0x1F01, 0x0342,
+ /* 1415 */ 0x0391, 0x0313,
+ /* 1417 */ 0x0391, 0x0314,
+ /* 1419 */ 0x1F08, 0x0300,
+ /* 1421 */ 0x1F09, 0x0300,
+ /* 1423 */ 0x1F08, 0x0301,
+ /* 1425 */ 0x1F09, 0x0301,
+ /* 1427 */ 0x1F08, 0x0342,
+ /* 1429 */ 0x1F09, 0x0342,
+ /* 1431 */ 0x03B5, 0x0313,
+ /* 1433 */ 0x03B5, 0x0314,
+ /* 1435 */ 0x1F10, 0x0300,
+ /* 1437 */ 0x1F11, 0x0300,
+ /* 1439 */ 0x1F10, 0x0301,
+ /* 1441 */ 0x1F11, 0x0301,
+ /* 1443 */ 0x0395, 0x0313,
+ /* 1445 */ 0x0395, 0x0314,
+ /* 1447 */ 0x1F18, 0x0300,
+ /* 1449 */ 0x1F19, 0x0300,
+ /* 1451 */ 0x1F18, 0x0301,
+ /* 1453 */ 0x1F19, 0x0301,
+ /* 1455 */ 0x03B7, 0x0313,
+ /* 1457 */ 0x03B7, 0x0314,
+ /* 1459 */ 0x1F20, 0x0300,
+ /* 1461 */ 0x1F21, 0x0300,
+ /* 1463 */ 0x1F20, 0x0301,
+ /* 1465 */ 0x1F21, 0x0301,
+ /* 1467 */ 0x1F20, 0x0342,
+ /* 1469 */ 0x1F21, 0x0342,
+ /* 1471 */ 0x0397, 0x0313,
+ /* 1473 */ 0x0397, 0x0314,
+ /* 1475 */ 0x1F28, 0x0300,
+ /* 1477 */ 0x1F29, 0x0300,
+ /* 1479 */ 0x1F28, 0x0301,
+ /* 1481 */ 0x1F29, 0x0301,
+ /* 1483 */ 0x1F28, 0x0342,
+ /* 1485 */ 0x1F29, 0x0342,
+ /* 1487 */ 0x03B9, 0x0313,
+ /* 1489 */ 0x03B9, 0x0314,
+ /* 1491 */ 0x1F30, 0x0300,
+ /* 1493 */ 0x1F31, 0x0300,
+ /* 1495 */ 0x1F30, 0x0301,
+ /* 1497 */ 0x1F31, 0x0301,
+ /* 1499 */ 0x1F30, 0x0342,
+ /* 1501 */ 0x1F31, 0x0342,
+ /* 1503 */ 0x0399, 0x0313,
+ /* 1505 */ 0x0399, 0x0314,
+ /* 1507 */ 0x1F38, 0x0300,
+ /* 1509 */ 0x1F39, 0x0300,
+ /* 1511 */ 0x1F38, 0x0301,
+ /* 1513 */ 0x1F39, 0x0301,
+ /* 1515 */ 0x1F38, 0x0342,
+ /* 1517 */ 0x1F39, 0x0342,
+ /* 1519 */ 0x03BF, 0x0313,
+ /* 1521 */ 0x03BF, 0x0314,
+ /* 1523 */ 0x1F40, 0x0300,
+ /* 1525 */ 0x1F41, 0x0300,
+ /* 1527 */ 0x1F40, 0x0301,
+ /* 1529 */ 0x1F41, 0x0301,
+ /* 1531 */ 0x039F, 0x0313,
+ /* 1533 */ 0x039F, 0x0314,
+ /* 1535 */ 0x1F48, 0x0300,
+ /* 1537 */ 0x1F49, 0x0300,
+ /* 1539 */ 0x1F48, 0x0301,
+ /* 1541 */ 0x1F49, 0x0301,
+ /* 1543 */ 0x03C5, 0x0313,
+ /* 1545 */ 0x03C5, 0x0314,
+ /* 1547 */ 0x1F50, 0x0300,
+ /* 1549 */ 0x1F51, 0x0300,
+ /* 1551 */ 0x1F50, 0x0301,
+ /* 1553 */ 0x1F51, 0x0301,
+ /* 1555 */ 0x1F50, 0x0342,
+ /* 1557 */ 0x1F51, 0x0342,
+ /* 1559 */ 0x03A5, 0x0314,
+ /* 1561 */ 0x1F59, 0x0300,
+ /* 1563 */ 0x1F59, 0x0301,
+ /* 1565 */ 0x1F59, 0x0342,
+ /* 1567 */ 0x03C9, 0x0313,
+ /* 1569 */ 0x03C9, 0x0314,
+ /* 1571 */ 0x1F60, 0x0300,
+ /* 1573 */ 0x1F61, 0x0300,
+ /* 1575 */ 0x1F60, 0x0301,
+ /* 1577 */ 0x1F61, 0x0301,
+ /* 1579 */ 0x1F60, 0x0342,
+ /* 1581 */ 0x1F61, 0x0342,
+ /* 1583 */ 0x03A9, 0x0313,
+ /* 1585 */ 0x03A9, 0x0314,
+ /* 1587 */ 0x1F68, 0x0300,
+ /* 1589 */ 0x1F69, 0x0300,
+ /* 1591 */ 0x1F68, 0x0301,
+ /* 1593 */ 0x1F69, 0x0301,
+ /* 1595 */ 0x1F68, 0x0342,
+ /* 1597 */ 0x1F69, 0x0342,
+ /* 1599 */ 0x03B1, 0x0300,
+ /* 1601 */ 0x03B5, 0x0300,
+ /* 1603 */ 0x03B7, 0x0300,
+ /* 1605 */ 0x03B9, 0x0300,
+ /* 1607 */ 0x03BF, 0x0300,
+ /* 1609 */ 0x03C5, 0x0300,
+ /* 1611 */ 0x03C9, 0x0300,
+ /* 1613 */ 0x1F00, 0x0345,
+ /* 1615 */ 0x1F01, 0x0345,
+ /* 1617 */ 0x1F02, 0x0345,
+ /* 1619 */ 0x1F03, 0x0345,
+ /* 1621 */ 0x1F04, 0x0345,
+ /* 1623 */ 0x1F05, 0x0345,
+ /* 1625 */ 0x1F06, 0x0345,
+ /* 1627 */ 0x1F07, 0x0345,
+ /* 1629 */ 0x1F08, 0x0345,
+ /* 1631 */ 0x1F09, 0x0345,
+ /* 1633 */ 0x1F0A, 0x0345,
+ /* 1635 */ 0x1F0B, 0x0345,
+ /* 1637 */ 0x1F0C, 0x0345,
+ /* 1639 */ 0x1F0D, 0x0345,
+ /* 1641 */ 0x1F0E, 0x0345,
+ /* 1643 */ 0x1F0F, 0x0345,
+ /* 1645 */ 0x1F20, 0x0345,
+ /* 1647 */ 0x1F21, 0x0345,
+ /* 1649 */ 0x1F22, 0x0345,
+ /* 1651 */ 0x1F23, 0x0345,
+ /* 1653 */ 0x1F24, 0x0345,
+ /* 1655 */ 0x1F25, 0x0345,
+ /* 1657 */ 0x1F26, 0x0345,
+ /* 1659 */ 0x1F27, 0x0345,
+ /* 1661 */ 0x1F28, 0x0345,
+ /* 1663 */ 0x1F29, 0x0345,
+ /* 1665 */ 0x1F2A, 0x0345,
+ /* 1667 */ 0x1F2B, 0x0345,
+ /* 1669 */ 0x1F2C, 0x0345,
+ /* 1671 */ 0x1F2D, 0x0345,
+ /* 1673 */ 0x1F2E, 0x0345,
+ /* 1675 */ 0x1F2F, 0x0345,
+ /* 1677 */ 0x1F60, 0x0345,
+ /* 1679 */ 0x1F61, 0x0345,
+ /* 1681 */ 0x1F62, 0x0345,
+ /* 1683 */ 0x1F63, 0x0345,
+ /* 1685 */ 0x1F64, 0x0345,
+ /* 1687 */ 0x1F65, 0x0345,
+ /* 1689 */ 0x1F66, 0x0345,
+ /* 1691 */ 0x1F67, 0x0345,
+ /* 1693 */ 0x1F68, 0x0345,
+ /* 1695 */ 0x1F69, 0x0345,
+ /* 1697 */ 0x1F6A, 0x0345,
+ /* 1699 */ 0x1F6B, 0x0345,
+ /* 1701 */ 0x1F6C, 0x0345,
+ /* 1703 */ 0x1F6D, 0x0345,
+ /* 1705 */ 0x1F6E, 0x0345,
+ /* 1707 */ 0x1F6F, 0x0345,
+ /* 1709 */ 0x03B1, 0x0306,
+ /* 1711 */ 0x03B1, 0x0304,
+ /* 1713 */ 0x1F70, 0x0345,
+ /* 1715 */ 0x03B1, 0x0345,
+ /* 1717 */ 0x03AC, 0x0345,
+ /* 1719 */ 0x03B1, 0x0342,
+ /* 1721 */ 0x1FB6, 0x0345,
+ /* 1723 */ 0x0391, 0x0306,
+ /* 1725 */ 0x0391, 0x0304,
+ /* 1727 */ 0x0391, 0x0300,
+ /* 1729 */ 0x0391, 0x0345,
+ /* 1731 */ 0x0020, 0x0313,
+ /* 1733 */ 0x0020, 0x0313,
+ /* 1735 */ 0x0020, 0x0342,
+ /* 1737 */ 0x00A8, 0x0342,
+ /* 1739 */ 0x1F74, 0x0345,
+ /* 1741 */ 0x03B7, 0x0345,
+ /* 1743 */ 0x03AE, 0x0345,
+ /* 1745 */ 0x03B7, 0x0342,
+ /* 1747 */ 0x1FC6, 0x0345,
+ /* 1749 */ 0x0395, 0x0300,
+ /* 1751 */ 0x0397, 0x0300,
+ /* 1753 */ 0x0397, 0x0345,
+ /* 1755 */ 0x1FBF, 0x0300,
+ /* 1757 */ 0x1FBF, 0x0301,
+ /* 1759 */ 0x1FBF, 0x0342,
+ /* 1761 */ 0x03B9, 0x0306,
+ /* 1763 */ 0x03B9, 0x0304,
+ /* 1765 */ 0x03CA, 0x0300,
+ /* 1767 */ 0x03B9, 0x0342,
+ /* 1769 */ 0x03CA, 0x0342,
+ /* 1771 */ 0x0399, 0x0306,
+ /* 1773 */ 0x0399, 0x0304,
+ /* 1775 */ 0x0399, 0x0300,
+ /* 1777 */ 0x1FFE, 0x0300,
+ /* 1779 */ 0x1FFE, 0x0301,
+ /* 1781 */ 0x1FFE, 0x0342,
+ /* 1783 */ 0x03C5, 0x0306,
+ /* 1785 */ 0x03C5, 0x0304,
+ /* 1787 */ 0x03CB, 0x0300,
+ /* 1789 */ 0x03C1, 0x0313,
+ /* 1791 */ 0x03C1, 0x0314,
+ /* 1793 */ 0x03C5, 0x0342,
+ /* 1795 */ 0x03CB, 0x0342,
+ /* 1797 */ 0x03A5, 0x0306,
+ /* 1799 */ 0x03A5, 0x0304,
+ /* 1801 */ 0x03A5, 0x0300,
+ /* 1803 */ 0x03A1, 0x0314,
+ /* 1805 */ 0x00A8, 0x0300,
+ /* 1807 */ 0x1F7C, 0x0345,
+ /* 1809 */ 0x03C9, 0x0345,
+ /* 1811 */ 0x03CE, 0x0345,
+ /* 1813 */ 0x03C9, 0x0342,
+ /* 1815 */ 0x1FF6, 0x0345,
+ /* 1817 */ 0x039F, 0x0300,
+ /* 1819 */ 0x03A9, 0x0300,
+ /* 1821 */ 0x03A9, 0x0345,
+ /* 1823 */ 0x0020, 0x0314,
+ /* 1825 */ 0x0020, 0x0333,
+ /* 1827 */ 0x002E, 0x002E,
+ /* 1829 */ 0x002E, 0x002E, 0x002E,
+ /* 1832 */ 0x2032, 0x2032,
+ /* 1834 */ 0x2032, 0x2032, 0x2032,
+ /* 1837 */ 0x2035, 0x2035,
+ /* 1839 */ 0x2035, 0x2035, 0x2035,
+ /* 1842 */ 0x0021, 0x0021,
+ /* 1844 */ 0x0020, 0x0305,
+ /* 1846 */ 0x003F, 0x003F,
+ /* 1848 */ 0x003F, 0x0021,
+ /* 1850 */ 0x0021, 0x003F,
+ /* 1852 */ 0x2032, 0x2032, 0x2032, 0x2032,
+ /* 1856 */ 0x0052, 0x0073,
+ /* 1858 */ 0x0061, 0x002F, 0x0063,
+ /* 1861 */ 0x0061, 0x002F, 0x0073,
+ /* 1864 */ 0x00B0, 0x0043,
+ /* 1866 */ 0x0063, 0x002F, 0x006F,
+ /* 1869 */ 0x0063, 0x002F, 0x0075,
+ /* 1872 */ 0x00B0, 0x0046,
+ /* 1874 */ 0x004E, 0x006F,
+ /* 1876 */ 0x0053, 0x004D,
+ /* 1878 */ 0x0054, 0x0045, 0x004C,
+ /* 1881 */ 0x0054, 0x004D,
+ /* 1883 */ 0x0046, 0x0041, 0x0058,
+ /* 1886 */ 0x0031, 0x2044, 0x0037,
+ /* 1889 */ 0x0031, 0x2044, 0x0039,
+ /* 1892 */ 0x0031, 0x2044, 0x0031, 0x0030,
+ /* 1896 */ 0x0031, 0x2044, 0x0033,
+ /* 1899 */ 0x0032, 0x2044, 0x0033,
+ /* 1902 */ 0x0031, 0x2044, 0x0035,
+ /* 1905 */ 0x0032, 0x2044, 0x0035,
+ /* 1908 */ 0x0033, 0x2044, 0x0035,
+ /* 1911 */ 0x0034, 0x2044, 0x0035,
+ /* 1914 */ 0x0031, 0x2044, 0x0036,
+ /* 1917 */ 0x0035, 0x2044, 0x0036,
+ /* 1920 */ 0x0031, 0x2044, 0x0038,
+ /* 1923 */ 0x0033, 0x2044, 0x0038,
+ /* 1926 */ 0x0035, 0x2044, 0x0038,
+ /* 1929 */ 0x0037, 0x2044, 0x0038,
+ /* 1932 */ 0x0031, 0x2044,
+ /* 1934 */ 0x0049, 0x0049,
+ /* 1936 */ 0x0049, 0x0049, 0x0049,
+ /* 1939 */ 0x0049, 0x0056,
+ /* 1941 */ 0x0056, 0x0049,
+ /* 1943 */ 0x0056, 0x0049, 0x0049,
+ /* 1946 */ 0x0056, 0x0049, 0x0049, 0x0049,
+ /* 1950 */ 0x0049, 0x0058,
+ /* 1952 */ 0x0058, 0x0049,
+ /* 1954 */ 0x0058, 0x0049, 0x0049,
+ /* 1957 */ 0x0069, 0x0069,
+ /* 1959 */ 0x0069, 0x0069, 0x0069,
+ /* 1962 */ 0x0069, 0x0076,
+ /* 1964 */ 0x0076, 0x0069,
+ /* 1966 */ 0x0076, 0x0069, 0x0069,
+ /* 1969 */ 0x0076, 0x0069, 0x0069, 0x0069,
+ /* 1973 */ 0x0069, 0x0078,
+ /* 1975 */ 0x0078, 0x0069,
+ /* 1977 */ 0x0078, 0x0069, 0x0069,
+ /* 1980 */ 0x0030, 0x2044, 0x0033,
+ /* 1983 */ 0x2190, 0x0338,
+ /* 1985 */ 0x2192, 0x0338,
+ /* 1987 */ 0x2194, 0x0338,
+ /* 1989 */ 0x21D0, 0x0338,
+ /* 1991 */ 0x21D4, 0x0338,
+ /* 1993 */ 0x21D2, 0x0338,
+ /* 1995 */ 0x2203, 0x0338,
+ /* 1997 */ 0x2208, 0x0338,
+ /* 1999 */ 0x220B, 0x0338,
+ /* 2001 */ 0x2223, 0x0338,
+ /* 2003 */ 0x2225, 0x0338,
+ /* 2005 */ 0x222B, 0x222B,
+ /* 2007 */ 0x222B, 0x222B, 0x222B,
+ /* 2010 */ 0x222E, 0x222E,
+ /* 2012 */ 0x222E, 0x222E, 0x222E,
+ /* 2015 */ 0x223C, 0x0338,
+ /* 2017 */ 0x2243, 0x0338,
+ /* 2019 */ 0x2245, 0x0338,
+ /* 2021 */ 0x2248, 0x0338,
+ /* 2023 */ 0x003D, 0x0338,
+ /* 2025 */ 0x2261, 0x0338,
+ /* 2027 */ 0x224D, 0x0338,
+ /* 2029 */ 0x003C, 0x0338,
+ /* 2031 */ 0x003E, 0x0338,
+ /* 2033 */ 0x2264, 0x0338,
+ /* 2035 */ 0x2265, 0x0338,
+ /* 2037 */ 0x2272, 0x0338,
+ /* 2039 */ 0x2273, 0x0338,
+ /* 2041 */ 0x2276, 0x0338,
+ /* 2043 */ 0x2277, 0x0338,
+ /* 2045 */ 0x227A, 0x0338,
+ /* 2047 */ 0x227B, 0x0338,
+ /* 2049 */ 0x2282, 0x0338,
+ /* 2051 */ 0x2283, 0x0338,
+ /* 2053 */ 0x2286, 0x0338,
+ /* 2055 */ 0x2287, 0x0338,
+ /* 2057 */ 0x22A2, 0x0338,
+ /* 2059 */ 0x22A8, 0x0338,
+ /* 2061 */ 0x22A9, 0x0338,
+ /* 2063 */ 0x22AB, 0x0338,
+ /* 2065 */ 0x227C, 0x0338,
+ /* 2067 */ 0x227D, 0x0338,
+ /* 2069 */ 0x2291, 0x0338,
+ /* 2071 */ 0x2292, 0x0338,
+ /* 2073 */ 0x22B2, 0x0338,
+ /* 2075 */ 0x22B3, 0x0338,
+ /* 2077 */ 0x22B4, 0x0338,
+ /* 2079 */ 0x22B5, 0x0338,
+ /* 2081 */ 0x0031, 0x0030,
+ /* 2083 */ 0x0031, 0x0031,
+ /* 2085 */ 0x0031, 0x0032,
+ /* 2087 */ 0x0031, 0x0033,
+ /* 2089 */ 0x0031, 0x0034,
+ /* 2091 */ 0x0031, 0x0035,
+ /* 2093 */ 0x0031, 0x0036,
+ /* 2095 */ 0x0031, 0x0037,
+ /* 2097 */ 0x0031, 0x0038,
+ /* 2099 */ 0x0031, 0x0039,
+ /* 2101 */ 0x0032, 0x0030,
+ /* 2103 */ 0x0028, 0x0031, 0x0029,
+ /* 2106 */ 0x0028, 0x0032, 0x0029,
+ /* 2109 */ 0x0028, 0x0033, 0x0029,
+ /* 2112 */ 0x0028, 0x0034, 0x0029,
+ /* 2115 */ 0x0028, 0x0035, 0x0029,
+ /* 2118 */ 0x0028, 0x0036, 0x0029,
+ /* 2121 */ 0x0028, 0x0037, 0x0029,
+ /* 2124 */ 0x0028, 0x0038, 0x0029,
+ /* 2127 */ 0x0028, 0x0039, 0x0029,
+ /* 2130 */ 0x0028, 0x0031, 0x0030, 0x0029,
+ /* 2134 */ 0x0028, 0x0031, 0x0031, 0x0029,
+ /* 2138 */ 0x0028, 0x0031, 0x0032, 0x0029,
+ /* 2142 */ 0x0028, 0x0031, 0x0033, 0x0029,
+ /* 2146 */ 0x0028, 0x0031, 0x0034, 0x0029,
+ /* 2150 */ 0x0028, 0x0031, 0x0035, 0x0029,
+ /* 2154 */ 0x0028, 0x0031, 0x0036, 0x0029,
+ /* 2158 */ 0x0028, 0x0031, 0x0037, 0x0029,
+ /* 2162 */ 0x0028, 0x0031, 0x0038, 0x0029,
+ /* 2166 */ 0x0028, 0x0031, 0x0039, 0x0029,
+ /* 2170 */ 0x0028, 0x0032, 0x0030, 0x0029,
+ /* 2174 */ 0x0031, 0x002E,
+ /* 2176 */ 0x0032, 0x002E,
+ /* 2178 */ 0x0033, 0x002E,
+ /* 2180 */ 0x0034, 0x002E,
+ /* 2182 */ 0x0035, 0x002E,
+ /* 2184 */ 0x0036, 0x002E,
+ /* 2186 */ 0x0037, 0x002E,
+ /* 2188 */ 0x0038, 0x002E,
+ /* 2190 */ 0x0039, 0x002E,
+ /* 2192 */ 0x0031, 0x0030, 0x002E,
+ /* 2195 */ 0x0031, 0x0031, 0x002E,
+ /* 2198 */ 0x0031, 0x0032, 0x002E,
+ /* 2201 */ 0x0031, 0x0033, 0x002E,
+ /* 2204 */ 0x0031, 0x0034, 0x002E,
+ /* 2207 */ 0x0031, 0x0035, 0x002E,
+ /* 2210 */ 0x0031, 0x0036, 0x002E,
+ /* 2213 */ 0x0031, 0x0037, 0x002E,
+ /* 2216 */ 0x0031, 0x0038, 0x002E,
+ /* 2219 */ 0x0031, 0x0039, 0x002E,
+ /* 2222 */ 0x0032, 0x0030, 0x002E,
+ /* 2225 */ 0x0028, 0x0061, 0x0029,
+ /* 2228 */ 0x0028, 0x0062, 0x0029,
+ /* 2231 */ 0x0028, 0x0063, 0x0029,
+ /* 2234 */ 0x0028, 0x0064, 0x0029,
+ /* 2237 */ 0x0028, 0x0065, 0x0029,
+ /* 2240 */ 0x0028, 0x0066, 0x0029,
+ /* 2243 */ 0x0028, 0x0067, 0x0029,
+ /* 2246 */ 0x0028, 0x0068, 0x0029,
+ /* 2249 */ 0x0028, 0x0069, 0x0029,
+ /* 2252 */ 0x0028, 0x006A, 0x0029,
+ /* 2255 */ 0x0028, 0x006B, 0x0029,
+ /* 2258 */ 0x0028, 0x006C, 0x0029,
+ /* 2261 */ 0x0028, 0x006D, 0x0029,
+ /* 2264 */ 0x0028, 0x006E, 0x0029,
+ /* 2267 */ 0x0028, 0x006F, 0x0029,
+ /* 2270 */ 0x0028, 0x0070, 0x0029,
+ /* 2273 */ 0x0028, 0x0071, 0x0029,
+ /* 2276 */ 0x0028, 0x0072, 0x0029,
+ /* 2279 */ 0x0028, 0x0073, 0x0029,
+ /* 2282 */ 0x0028, 0x0074, 0x0029,
+ /* 2285 */ 0x0028, 0x0075, 0x0029,
+ /* 2288 */ 0x0028, 0x0076, 0x0029,
+ /* 2291 */ 0x0028, 0x0077, 0x0029,
+ /* 2294 */ 0x0028, 0x0078, 0x0029,
+ /* 2297 */ 0x0028, 0x0079, 0x0029,
+ /* 2300 */ 0x0028, 0x007A, 0x0029,
+ /* 2303 */ 0x222B, 0x222B, 0x222B, 0x222B,
+ /* 2307 */ 0x003A, 0x003A, 0x003D,
+ /* 2310 */ 0x003D, 0x003D,
+ /* 2312 */ 0x003D, 0x003D, 0x003D,
+ /* 2315 */ 0x2ADD, 0x0338,
+ /* 2317 */ 0x304B, 0x3099,
+ /* 2319 */ 0x304D, 0x3099,
+ /* 2321 */ 0x304F, 0x3099,
+ /* 2323 */ 0x3051, 0x3099,
+ /* 2325 */ 0x3053, 0x3099,
+ /* 2327 */ 0x3055, 0x3099,
+ /* 2329 */ 0x3057, 0x3099,
+ /* 2331 */ 0x3059, 0x3099,
+ /* 2333 */ 0x305B, 0x3099,
+ /* 2335 */ 0x305D, 0x3099,
+ /* 2337 */ 0x305F, 0x3099,
+ /* 2339 */ 0x3061, 0x3099,
+ /* 2341 */ 0x3064, 0x3099,
+ /* 2343 */ 0x3066, 0x3099,
+ /* 2345 */ 0x3068, 0x3099,
+ /* 2347 */ 0x306F, 0x3099,
+ /* 2349 */ 0x306F, 0x309A,
+ /* 2351 */ 0x3072, 0x3099,
+ /* 2353 */ 0x3072, 0x309A,
+ /* 2355 */ 0x3075, 0x3099,
+ /* 2357 */ 0x3075, 0x309A,
+ /* 2359 */ 0x3078, 0x3099,
+ /* 2361 */ 0x3078, 0x309A,
+ /* 2363 */ 0x307B, 0x3099,
+ /* 2365 */ 0x307B, 0x309A,
+ /* 2367 */ 0x3046, 0x3099,
+ /* 2369 */ 0x0020, 0x3099,
+ /* 2371 */ 0x0020, 0x309A,
+ /* 2373 */ 0x309D, 0x3099,
+ /* 2375 */ 0x3088, 0x308A,
+ /* 2377 */ 0x30AB, 0x3099,
+ /* 2379 */ 0x30AD, 0x3099,
+ /* 2381 */ 0x30AF, 0x3099,
+ /* 2383 */ 0x30B1, 0x3099,
+ /* 2385 */ 0x30B3, 0x3099,
+ /* 2387 */ 0x30B5, 0x3099,
+ /* 2389 */ 0x30B7, 0x3099,
+ /* 2391 */ 0x30B9, 0x3099,
+ /* 2393 */ 0x30BB, 0x3099,
+ /* 2395 */ 0x30BD, 0x3099,
+ /* 2397 */ 0x30BF, 0x3099,
+ /* 2399 */ 0x30C1, 0x3099,
+ /* 2401 */ 0x30C4, 0x3099,
+ /* 2403 */ 0x30C6, 0x3099,
+ /* 2405 */ 0x30C8, 0x3099,
+ /* 2407 */ 0x30CF, 0x3099,
+ /* 2409 */ 0x30CF, 0x309A,
+ /* 2411 */ 0x30D2, 0x3099,
+ /* 2413 */ 0x30D2, 0x309A,
+ /* 2415 */ 0x30D5, 0x3099,
+ /* 2417 */ 0x30D5, 0x309A,
+ /* 2419 */ 0x30D8, 0x3099,
+ /* 2421 */ 0x30D8, 0x309A,
+ /* 2423 */ 0x30DB, 0x3099,
+ /* 2425 */ 0x30DB, 0x309A,
+ /* 2427 */ 0x30A6, 0x3099,
+ /* 2429 */ 0x30EF, 0x3099,
+ /* 2431 */ 0x30F0, 0x3099,
+ /* 2433 */ 0x30F1, 0x3099,
+ /* 2435 */ 0x30F2, 0x3099,
+ /* 2437 */ 0x30FD, 0x3099,
+ /* 2439 */ 0x30B3, 0x30C8,
+ /* 2441 */ 0x0028, 0x1100, 0x0029,
+ /* 2444 */ 0x0028, 0x1102, 0x0029,
+ /* 2447 */ 0x0028, 0x1103, 0x0029,
+ /* 2450 */ 0x0028, 0x1105, 0x0029,
+ /* 2453 */ 0x0028, 0x1106, 0x0029,
+ /* 2456 */ 0x0028, 0x1107, 0x0029,
+ /* 2459 */ 0x0028, 0x1109, 0x0029,
+ /* 2462 */ 0x0028, 0x110B, 0x0029,
+ /* 2465 */ 0x0028, 0x110C, 0x0029,
+ /* 2468 */ 0x0028, 0x110E, 0x0029,
+ /* 2471 */ 0x0028, 0x110F, 0x0029,
+ /* 2474 */ 0x0028, 0x1110, 0x0029,
+ /* 2477 */ 0x0028, 0x1111, 0x0029,
+ /* 2480 */ 0x0028, 0x1112, 0x0029,
+ /* 2483 */ 0x0028, 0x1100, 0x1161, 0x0029,
+ /* 2487 */ 0x0028, 0x1102, 0x1161, 0x0029,
+ /* 2491 */ 0x0028, 0x1103, 0x1161, 0x0029,
+ /* 2495 */ 0x0028, 0x1105, 0x1161, 0x0029,
+ /* 2499 */ 0x0028, 0x1106, 0x1161, 0x0029,
+ /* 2503 */ 0x0028, 0x1107, 0x1161, 0x0029,
+ /* 2507 */ 0x0028, 0x1109, 0x1161, 0x0029,
+ /* 2511 */ 0x0028, 0x110B, 0x1161, 0x0029,
+ /* 2515 */ 0x0028, 0x110C, 0x1161, 0x0029,
+ /* 2519 */ 0x0028, 0x110E, 0x1161, 0x0029,
+ /* 2523 */ 0x0028, 0x110F, 0x1161, 0x0029,
+ /* 2527 */ 0x0028, 0x1110, 0x1161, 0x0029,
+ /* 2531 */ 0x0028, 0x1111, 0x1161, 0x0029,
+ /* 2535 */ 0x0028, 0x1112, 0x1161, 0x0029,
+ /* 2539 */ 0x0028, 0x110C, 0x116E, 0x0029,
+ /* 2543 */ 0x0028, 0x110B, 0x1169, 0x110C, 0x1165, 0x11AB, 0x0029,
+ /* 2550 */ 0x0028, 0x110B, 0x1169, 0x1112, 0x116E, 0x0029,
+ /* 2556 */ 0x0028, 0x4E00, 0x0029,
+ /* 2559 */ 0x0028, 0x4E8C, 0x0029,
+ /* 2562 */ 0x0028, 0x4E09, 0x0029,
+ /* 2565 */ 0x0028, 0x56DB, 0x0029,
+ /* 2568 */ 0x0028, 0x4E94, 0x0029,
+ /* 2571 */ 0x0028, 0x516D, 0x0029,
+ /* 2574 */ 0x0028, 0x4E03, 0x0029,
+ /* 2577 */ 0x0028, 0x516B, 0x0029,
+ /* 2580 */ 0x0028, 0x4E5D, 0x0029,
+ /* 2583 */ 0x0028, 0x5341, 0x0029,
+ /* 2586 */ 0x0028, 0x6708, 0x0029,
+ /* 2589 */ 0x0028, 0x706B, 0x0029,
+ /* 2592 */ 0x0028, 0x6C34, 0x0029,
+ /* 2595 */ 0x0028, 0x6728, 0x0029,
+ /* 2598 */ 0x0028, 0x91D1, 0x0029,
+ /* 2601 */ 0x0028, 0x571F, 0x0029,
+ /* 2604 */ 0x0028, 0x65E5, 0x0029,
+ /* 2607 */ 0x0028, 0x682A, 0x0029,
+ /* 2610 */ 0x0028, 0x6709, 0x0029,
+ /* 2613 */ 0x0028, 0x793E, 0x0029,
+ /* 2616 */ 0x0028, 0x540D, 0x0029,
+ /* 2619 */ 0x0028, 0x7279, 0x0029,
+ /* 2622 */ 0x0028, 0x8CA1, 0x0029,
+ /* 2625 */ 0x0028, 0x795D, 0x0029,
+ /* 2628 */ 0x0028, 0x52B4, 0x0029,
+ /* 2631 */ 0x0028, 0x4EE3, 0x0029,
+ /* 2634 */ 0x0028, 0x547C, 0x0029,
+ /* 2637 */ 0x0028, 0x5B66, 0x0029,
+ /* 2640 */ 0x0028, 0x76E3, 0x0029,
+ /* 2643 */ 0x0028, 0x4F01, 0x0029,
+ /* 2646 */ 0x0028, 0x8CC7, 0x0029,
+ /* 2649 */ 0x0028, 0x5354, 0x0029,
+ /* 2652 */ 0x0028, 0x796D, 0x0029,
+ /* 2655 */ 0x0028, 0x4F11, 0x0029,
+ /* 2658 */ 0x0028, 0x81EA, 0x0029,
+ /* 2661 */ 0x0028, 0x81F3, 0x0029,
+ /* 2664 */ 0x0050, 0x0054, 0x0045,
+ /* 2667 */ 0x0032, 0x0031,
+ /* 2669 */ 0x0032, 0x0032,
+ /* 2671 */ 0x0032, 0x0033,
+ /* 2673 */ 0x0032, 0x0034,
+ /* 2675 */ 0x0032, 0x0035,
+ /* 2677 */ 0x0032, 0x0036,
+ /* 2679 */ 0x0032, 0x0037,
+ /* 2681 */ 0x0032, 0x0038,
+ /* 2683 */ 0x0032, 0x0039,
+ /* 2685 */ 0x0033, 0x0030,
+ /* 2687 */ 0x0033, 0x0031,
+ /* 2689 */ 0x0033, 0x0032,
+ /* 2691 */ 0x0033, 0x0033,
+ /* 2693 */ 0x0033, 0x0034,
+ /* 2695 */ 0x0033, 0x0035,
+ /* 2697 */ 0x1100, 0x1161,
+ /* 2699 */ 0x1102, 0x1161,
+ /* 2701 */ 0x1103, 0x1161,
+ /* 2703 */ 0x1105, 0x1161,
+ /* 2705 */ 0x1106, 0x1161,
+ /* 2707 */ 0x1107, 0x1161,
+ /* 2709 */ 0x1109, 0x1161,
+ /* 2711 */ 0x110B, 0x1161,
+ /* 2713 */ 0x110C, 0x1161,
+ /* 2715 */ 0x110E, 0x1161,
+ /* 2717 */ 0x110F, 0x1161,
+ /* 2719 */ 0x1110, 0x1161,
+ /* 2721 */ 0x1111, 0x1161,
+ /* 2723 */ 0x1112, 0x1161,
+ /* 2725 */ 0x110E, 0x1161, 0x11B7, 0x1100, 0x1169,
+ /* 2730 */ 0x110C, 0x116E, 0x110B, 0x1174,
+ /* 2734 */ 0x110B, 0x116E,
+ /* 2736 */ 0x0033, 0x0036,
+ /* 2738 */ 0x0033, 0x0037,
+ /* 2740 */ 0x0033, 0x0038,
+ /* 2742 */ 0x0033, 0x0039,
+ /* 2744 */ 0x0034, 0x0030,
+ /* 2746 */ 0x0034, 0x0031,
+ /* 2748 */ 0x0034, 0x0032,
+ /* 2750 */ 0x0034, 0x0033,
+ /* 2752 */ 0x0034, 0x0034,
+ /* 2754 */ 0x0034, 0x0035,
+ /* 2756 */ 0x0034, 0x0036,
+ /* 2758 */ 0x0034, 0x0037,
+ /* 2760 */ 0x0034, 0x0038,
+ /* 2762 */ 0x0034, 0x0039,
+ /* 2764 */ 0x0035, 0x0030,
+ /* 2766 */ 0x0031, 0x6708,
+ /* 2768 */ 0x0032, 0x6708,
+ /* 2770 */ 0x0033, 0x6708,
+ /* 2772 */ 0x0034, 0x6708,
+ /* 2774 */ 0x0035, 0x6708,
+ /* 2776 */ 0x0036, 0x6708,
+ /* 2778 */ 0x0037, 0x6708,
+ /* 2780 */ 0x0038, 0x6708,
+ /* 2782 */ 0x0039, 0x6708,
+ /* 2784 */ 0x0031, 0x0030, 0x6708,
+ /* 2787 */ 0x0031, 0x0031, 0x6708,
+ /* 2790 */ 0x0031, 0x0032, 0x6708,
+ /* 2793 */ 0x0048, 0x0067,
+ /* 2795 */ 0x0065, 0x0072, 0x0067,
+ /* 2798 */ 0x0065, 0x0056,
+ /* 2800 */ 0x004C, 0x0054, 0x0044,
+ /* 2803 */ 0x4EE4, 0x548C,
+ /* 2805 */ 0x30A2, 0x30D1, 0x30FC, 0x30C8,
+ /* 2809 */ 0x30A2, 0x30EB, 0x30D5, 0x30A1,
+ /* 2813 */ 0x30A2, 0x30F3, 0x30DA, 0x30A2,
+ /* 2817 */ 0x30A2, 0x30FC, 0x30EB,
+ /* 2820 */ 0x30A4, 0x30CB, 0x30F3, 0x30B0,
+ /* 2824 */ 0x30A4, 0x30F3, 0x30C1,
+ /* 2827 */ 0x30A6, 0x30A9, 0x30F3,
+ /* 2830 */ 0x30A8, 0x30B9, 0x30AF, 0x30FC, 0x30C9,
+ /* 2835 */ 0x30A8, 0x30FC, 0x30AB, 0x30FC,
+ /* 2839 */ 0x30AA, 0x30F3, 0x30B9,
+ /* 2842 */ 0x30AA, 0x30FC, 0x30E0,
+ /* 2845 */ 0x30AB, 0x30A4, 0x30EA,
+ /* 2848 */ 0x30AB, 0x30E9, 0x30C3, 0x30C8,
+ /* 2852 */ 0x30AB, 0x30ED, 0x30EA, 0x30FC,
+ /* 2856 */ 0x30AC, 0x30ED, 0x30F3,
+ /* 2859 */ 0x30AC, 0x30F3, 0x30DE,
+ /* 2862 */ 0x30AE, 0x30AC,
+ /* 2864 */ 0x30AE, 0x30CB, 0x30FC,
+ /* 2867 */ 0x30AD, 0x30E5, 0x30EA, 0x30FC,
+ /* 2871 */ 0x30AE, 0x30EB, 0x30C0, 0x30FC,
+ /* 2875 */ 0x30AD, 0x30ED,
+ /* 2877 */ 0x30AD, 0x30ED, 0x30B0, 0x30E9, 0x30E0,
+ /* 2882 */ 0x30AD, 0x30ED, 0x30E1, 0x30FC, 0x30C8, 0x30EB,
+ /* 2888 */ 0x30AD, 0x30ED, 0x30EF, 0x30C3, 0x30C8,
+ /* 2893 */ 0x30B0, 0x30E9, 0x30E0,
+ /* 2896 */ 0x30B0, 0x30E9, 0x30E0, 0x30C8, 0x30F3,
+ /* 2901 */ 0x30AF, 0x30EB, 0x30BC, 0x30A4, 0x30ED,
+ /* 2906 */ 0x30AF, 0x30ED, 0x30FC, 0x30CD,
+ /* 2910 */ 0x30B1, 0x30FC, 0x30B9,
+ /* 2913 */ 0x30B3, 0x30EB, 0x30CA,
+ /* 2916 */ 0x30B3, 0x30FC, 0x30DD,
+ /* 2919 */ 0x30B5, 0x30A4, 0x30AF, 0x30EB,
+ /* 2923 */ 0x30B5, 0x30F3, 0x30C1, 0x30FC, 0x30E0,
+ /* 2928 */ 0x30B7, 0x30EA, 0x30F3, 0x30B0,
+ /* 2932 */ 0x30BB, 0x30F3, 0x30C1,
+ /* 2935 */ 0x30BB, 0x30F3, 0x30C8,
+ /* 2938 */ 0x30C0, 0x30FC, 0x30B9,
+ /* 2941 */ 0x30C7, 0x30B7,
+ /* 2943 */ 0x30C9, 0x30EB,
+ /* 2945 */ 0x30C8, 0x30F3,
+ /* 2947 */ 0x30CA, 0x30CE,
+ /* 2949 */ 0x30CE, 0x30C3, 0x30C8,
+ /* 2952 */ 0x30CF, 0x30A4, 0x30C4,
+ /* 2955 */ 0x30D1, 0x30FC, 0x30BB, 0x30F3, 0x30C8,
+ /* 2960 */ 0x30D1, 0x30FC, 0x30C4,
+ /* 2963 */ 0x30D0, 0x30FC, 0x30EC, 0x30EB,
+ /* 2967 */ 0x30D4, 0x30A2, 0x30B9, 0x30C8, 0x30EB,
+ /* 2972 */ 0x30D4, 0x30AF, 0x30EB,
+ /* 2975 */ 0x30D4, 0x30B3,
+ /* 2977 */ 0x30D3, 0x30EB,
+ /* 2979 */ 0x30D5, 0x30A1, 0x30E9, 0x30C3, 0x30C9,
+ /* 2984 */ 0x30D5, 0x30A3, 0x30FC, 0x30C8,
+ /* 2988 */ 0x30D6, 0x30C3, 0x30B7, 0x30A7, 0x30EB,
+ /* 2993 */ 0x30D5, 0x30E9, 0x30F3,
+ /* 2996 */ 0x30D8, 0x30AF, 0x30BF, 0x30FC, 0x30EB,
+ /* 3001 */ 0x30DA, 0x30BD,
+ /* 3003 */ 0x30DA, 0x30CB, 0x30D2,
+ /* 3006 */ 0x30D8, 0x30EB, 0x30C4,
+ /* 3009 */ 0x30DA, 0x30F3, 0x30B9,
+ /* 3012 */ 0x30DA, 0x30FC, 0x30B8,
+ /* 3015 */ 0x30D9, 0x30FC, 0x30BF,
+ /* 3018 */ 0x30DD, 0x30A4, 0x30F3, 0x30C8,
+ /* 3022 */ 0x30DC, 0x30EB, 0x30C8,
+ /* 3025 */ 0x30DB, 0x30F3,
+ /* 3027 */ 0x30DD, 0x30F3, 0x30C9,
+ /* 3030 */ 0x30DB, 0x30FC, 0x30EB,
+ /* 3033 */ 0x30DB, 0x30FC, 0x30F3,
+ /* 3036 */ 0x30DE, 0x30A4, 0x30AF, 0x30ED,
+ /* 3040 */ 0x30DE, 0x30A4, 0x30EB,
+ /* 3043 */ 0x30DE, 0x30C3, 0x30CF,
+ /* 3046 */ 0x30DE, 0x30EB, 0x30AF,
+ /* 3049 */ 0x30DE, 0x30F3, 0x30B7, 0x30E7, 0x30F3,
+ /* 3054 */ 0x30DF, 0x30AF, 0x30ED, 0x30F3,
+ /* 3058 */ 0x30DF, 0x30EA,
+ /* 3060 */ 0x30DF, 0x30EA, 0x30D0, 0x30FC, 0x30EB,
+ /* 3065 */ 0x30E1, 0x30AC,
+ /* 3067 */ 0x30E1, 0x30AC, 0x30C8, 0x30F3,
+ /* 3071 */ 0x30E1, 0x30FC, 0x30C8, 0x30EB,
+ /* 3075 */ 0x30E4, 0x30FC, 0x30C9,
+ /* 3078 */ 0x30E4, 0x30FC, 0x30EB,
+ /* 3081 */ 0x30E6, 0x30A2, 0x30F3,
+ /* 3084 */ 0x30EA, 0x30C3, 0x30C8, 0x30EB,
+ /* 3088 */ 0x30EA, 0x30E9,
+ /* 3090 */ 0x30EB, 0x30D4, 0x30FC,
+ /* 3093 */ 0x30EB, 0x30FC, 0x30D6, 0x30EB,
+ /* 3097 */ 0x30EC, 0x30E0,
+ /* 3099 */ 0x30EC, 0x30F3, 0x30C8, 0x30B2, 0x30F3,
+ /* 3104 */ 0x30EF, 0x30C3, 0x30C8,
+ /* 3107 */ 0x0030, 0x70B9,
+ /* 3109 */ 0x0031, 0x70B9,
+ /* 3111 */ 0x0032, 0x70B9,
+ /* 3113 */ 0x0033, 0x70B9,
+ /* 3115 */ 0x0034, 0x70B9,
+ /* 3117 */ 0x0035, 0x70B9,
+ /* 3119 */ 0x0036, 0x70B9,
+ /* 3121 */ 0x0037, 0x70B9,
+ /* 3123 */ 0x0038, 0x70B9,
+ /* 3125 */ 0x0039, 0x70B9,
+ /* 3127 */ 0x0031, 0x0030, 0x70B9,
+ /* 3130 */ 0x0031, 0x0031, 0x70B9,
+ /* 3133 */ 0x0031, 0x0032, 0x70B9,
+ /* 3136 */ 0x0031, 0x0033, 0x70B9,
+ /* 3139 */ 0x0031, 0x0034, 0x70B9,
+ /* 3142 */ 0x0031, 0x0035, 0x70B9,
+ /* 3145 */ 0x0031, 0x0036, 0x70B9,
+ /* 3148 */ 0x0031, 0x0037, 0x70B9,
+ /* 3151 */ 0x0031, 0x0038, 0x70B9,
+ /* 3154 */ 0x0031, 0x0039, 0x70B9,
+ /* 3157 */ 0x0032, 0x0030, 0x70B9,
+ /* 3160 */ 0x0032, 0x0031, 0x70B9,
+ /* 3163 */ 0x0032, 0x0032, 0x70B9,
+ /* 3166 */ 0x0032, 0x0033, 0x70B9,
+ /* 3169 */ 0x0032, 0x0034, 0x70B9,
+ /* 3172 */ 0x0068, 0x0050, 0x0061,
+ /* 3175 */ 0x0064, 0x0061,
+ /* 3177 */ 0x0041, 0x0055,
+ /* 3179 */ 0x0062, 0x0061, 0x0072,
+ /* 3182 */ 0x006F, 0x0056,
+ /* 3184 */ 0x0070, 0x0063,
+ /* 3186 */ 0x0064, 0x006D,
+ /* 3188 */ 0x0064, 0x006D, 0x00B2,
+ /* 3191 */ 0x0064, 0x006D, 0x00B3,
+ /* 3194 */ 0x0049, 0x0055,
+ /* 3196 */ 0x5E73, 0x6210,
+ /* 3198 */ 0x662D, 0x548C,
+ /* 3200 */ 0x5927, 0x6B63,
+ /* 3202 */ 0x660E, 0x6CBB,
+ /* 3204 */ 0x682A, 0x5F0F, 0x4F1A, 0x793E,
+ /* 3208 */ 0x0070, 0x0041,
+ /* 3210 */ 0x006E, 0x0041,
+ /* 3212 */ 0x03BC, 0x0041,
+ /* 3214 */ 0x006D, 0x0041,
+ /* 3216 */ 0x006B, 0x0041,
+ /* 3218 */ 0x004B, 0x0042,
+ /* 3220 */ 0x004D, 0x0042,
+ /* 3222 */ 0x0047, 0x0042,
+ /* 3224 */ 0x0063, 0x0061, 0x006C,
+ /* 3227 */ 0x006B, 0x0063, 0x0061, 0x006C,
+ /* 3231 */ 0x0070, 0x0046,
+ /* 3233 */ 0x006E, 0x0046,
+ /* 3235 */ 0x03BC, 0x0046,
+ /* 3237 */ 0x03BC, 0x0067,
+ /* 3239 */ 0x006D, 0x0067,
+ /* 3241 */ 0x006B, 0x0067,
+ /* 3243 */ 0x0048, 0x007A,
+ /* 3245 */ 0x006B, 0x0048, 0x007A,
+ /* 3248 */ 0x004D, 0x0048, 0x007A,
+ /* 3251 */ 0x0047, 0x0048, 0x007A,
+ /* 3254 */ 0x0054, 0x0048, 0x007A,
+ /* 3257 */ 0x03BC, 0x2113,
+ /* 3259 */ 0x006D, 0x2113,
+ /* 3261 */ 0x0064, 0x2113,
+ /* 3263 */ 0x006B, 0x2113,
+ /* 3265 */ 0x0066, 0x006D,
+ /* 3267 */ 0x006E, 0x006D,
+ /* 3269 */ 0x03BC, 0x006D,
+ /* 3271 */ 0x006D, 0x006D,
+ /* 3273 */ 0x0063, 0x006D,
+ /* 3275 */ 0x006B, 0x006D,
+ /* 3277 */ 0x006D, 0x006D, 0x00B2,
+ /* 3280 */ 0x0063, 0x006D, 0x00B2,
+ /* 3283 */ 0x006D, 0x00B2,
+ /* 3285 */ 0x006B, 0x006D, 0x00B2,
+ /* 3288 */ 0x006D, 0x006D, 0x00B3,
+ /* 3291 */ 0x0063, 0x006D, 0x00B3,
+ /* 3294 */ 0x006D, 0x00B3,
+ /* 3296 */ 0x006B, 0x006D, 0x00B3,
+ /* 3299 */ 0x006D, 0x2215, 0x0073,
+ /* 3302 */ 0x006D, 0x2215, 0x0073, 0x00B2,
+ /* 3306 */ 0x0050, 0x0061,
+ /* 3308 */ 0x006B, 0x0050, 0x0061,
+ /* 3311 */ 0x004D, 0x0050, 0x0061,
+ /* 3314 */ 0x0047, 0x0050, 0x0061,
+ /* 3317 */ 0x0072, 0x0061, 0x0064,
+ /* 3320 */ 0x0072, 0x0061, 0x0064, 0x2215, 0x0073,
+ /* 3325 */ 0x0072, 0x0061, 0x0064, 0x2215, 0x0073, 0x00B2,
+ /* 3331 */ 0x0070, 0x0073,
+ /* 3333 */ 0x006E, 0x0073,
+ /* 3335 */ 0x03BC, 0x0073,
+ /* 3337 */ 0x006D, 0x0073,
+ /* 3339 */ 0x0070, 0x0056,
+ /* 3341 */ 0x006E, 0x0056,
+ /* 3343 */ 0x03BC, 0x0056,
+ /* 3345 */ 0x006D, 0x0056,
+ /* 3347 */ 0x006B, 0x0056,
+ /* 3349 */ 0x004D, 0x0056,
+ /* 3351 */ 0x0070, 0x0057,
+ /* 3353 */ 0x006E, 0x0057,
+ /* 3355 */ 0x03BC, 0x0057,
+ /* 3357 */ 0x006D, 0x0057,
+ /* 3359 */ 0x006B, 0x0057,
+ /* 3361 */ 0x004D, 0x0057,
+ /* 3363 */ 0x006B, 0x03A9,
+ /* 3365 */ 0x004D, 0x03A9,
+ /* 3367 */ 0x0061, 0x002E, 0x006D, 0x002E,
+ /* 3371 */ 0x0042, 0x0071,
+ /* 3373 */ 0x0063, 0x0063,
+ /* 3375 */ 0x0063, 0x0064,
+ /* 3377 */ 0x0043, 0x2215, 0x006B, 0x0067,
+ /* 3381 */ 0x0043, 0x006F, 0x002E,
+ /* 3384 */ 0x0064, 0x0042,
+ /* 3386 */ 0x0047, 0x0079,
+ /* 3388 */ 0x0068, 0x0061,
+ /* 3390 */ 0x0048, 0x0050,
+ /* 3392 */ 0x0069, 0x006E,
+ /* 3394 */ 0x004B, 0x004B,
+ /* 3396 */ 0x004B, 0x004D,
+ /* 3398 */ 0x006B, 0x0074,
+ /* 3400 */ 0x006C, 0x006D,
+ /* 3402 */ 0x006C, 0x006E,
+ /* 3404 */ 0x006C, 0x006F, 0x0067,
+ /* 3407 */ 0x006C, 0x0078,
+ /* 3409 */ 0x006D, 0x0062,
+ /* 3411 */ 0x006D, 0x0069, 0x006C,
+ /* 3414 */ 0x006D, 0x006F, 0x006C,
+ /* 3417 */ 0x0050, 0x0048,
+ /* 3419 */ 0x0070, 0x002E, 0x006D, 0x002E,
+ /* 3423 */ 0x0050, 0x0050, 0x004D,
+ /* 3426 */ 0x0050, 0x0052,
+ /* 3428 */ 0x0073, 0x0072,
+ /* 3430 */ 0x0053, 0x0076,
+ /* 3432 */ 0x0057, 0x0062,
+ /* 3434 */ 0x0056, 0x2215, 0x006D,
+ /* 3437 */ 0x0041, 0x2215, 0x006D,
+ /* 3440 */ 0x0031, 0x65E5,
+ /* 3442 */ 0x0032, 0x65E5,
+ /* 3444 */ 0x0033, 0x65E5,
+ /* 3446 */ 0x0034, 0x65E5,
+ /* 3448 */ 0x0035, 0x65E5,
+ /* 3450 */ 0x0036, 0x65E5,
+ /* 3452 */ 0x0037, 0x65E5,
+ /* 3454 */ 0x0038, 0x65E5,
+ /* 3456 */ 0x0039, 0x65E5,
+ /* 3458 */ 0x0031, 0x0030, 0x65E5,
+ /* 3461 */ 0x0031, 0x0031, 0x65E5,
+ /* 3464 */ 0x0031, 0x0032, 0x65E5,
+ /* 3467 */ 0x0031, 0x0033, 0x65E5,
+ /* 3470 */ 0x0031, 0x0034, 0x65E5,
+ /* 3473 */ 0x0031, 0x0035, 0x65E5,
+ /* 3476 */ 0x0031, 0x0036, 0x65E5,
+ /* 3479 */ 0x0031, 0x0037, 0x65E5,
+ /* 3482 */ 0x0031, 0x0038, 0x65E5,
+ /* 3485 */ 0x0031, 0x0039, 0x65E5,
+ /* 3488 */ 0x0032, 0x0030, 0x65E5,
+ /* 3491 */ 0x0032, 0x0031, 0x65E5,
+ /* 3494 */ 0x0032, 0x0032, 0x65E5,
+ /* 3497 */ 0x0032, 0x0033, 0x65E5,
+ /* 3500 */ 0x0032, 0x0034, 0x65E5,
+ /* 3503 */ 0x0032, 0x0035, 0x65E5,
+ /* 3506 */ 0x0032, 0x0036, 0x65E5,
+ /* 3509 */ 0x0032, 0x0037, 0x65E5,
+ /* 3512 */ 0x0032, 0x0038, 0x65E5,
+ /* 3515 */ 0x0032, 0x0039, 0x65E5,
+ /* 3518 */ 0x0033, 0x0030, 0x65E5,
+ /* 3521 */ 0x0033, 0x0031, 0x65E5,
+ /* 3524 */ 0x0067, 0x0061, 0x006C,
+ /* 3527 */ 0x242EE,
+ /* 3528 */ 0x2284A,
+ /* 3529 */ 0x22844,
+ /* 3530 */ 0x233D5,
+ /* 3531 */ 0x25249,
+ /* 3532 */ 0x25CD0,
+ /* 3533 */ 0x27ED3,
+ /* 3534 */ 0x0066, 0x0066,
+ /* 3536 */ 0x0066, 0x0069,
+ /* 3538 */ 0x0066, 0x006C,
+ /* 3540 */ 0x0066, 0x0066, 0x0069,
+ /* 3543 */ 0x0066, 0x0066, 0x006C,
+ /* 3546 */ 0x017F, 0x0074,
+ /* 3548 */ 0x0073, 0x0074,
+ /* 3550 */ 0x0574, 0x0576,
+ /* 3552 */ 0x0574, 0x0565,
+ /* 3554 */ 0x0574, 0x056B,
+ /* 3556 */ 0x057E, 0x0576,
+ /* 3558 */ 0x0574, 0x056D,
+ /* 3560 */ 0x05D9, 0x05B4,
+ /* 3562 */ 0x05F2, 0x05B7,
+ /* 3564 */ 0x05E9, 0x05C1,
+ /* 3566 */ 0x05E9, 0x05C2,
+ /* 3568 */ 0xFB49, 0x05C1,
+ /* 3570 */ 0xFB49, 0x05C2,
+ /* 3572 */ 0x05D0, 0x05B7,
+ /* 3574 */ 0x05D0, 0x05B8,
+ /* 3576 */ 0x05D0, 0x05BC,
+ /* 3578 */ 0x05D1, 0x05BC,
+ /* 3580 */ 0x05D2, 0x05BC,
+ /* 3582 */ 0x05D3, 0x05BC,
+ /* 3584 */ 0x05D4, 0x05BC,
+ /* 3586 */ 0x05D5, 0x05BC,
+ /* 3588 */ 0x05D6, 0x05BC,
+ /* 3590 */ 0x05D8, 0x05BC,
+ /* 3592 */ 0x05D9, 0x05BC,
+ /* 3594 */ 0x05DA, 0x05BC,
+ /* 3596 */ 0x05DB, 0x05BC,
+ /* 3598 */ 0x05DC, 0x05BC,
+ /* 3600 */ 0x05DE, 0x05BC,
+ /* 3602 */ 0x05E0, 0x05BC,
+ /* 3604 */ 0x05E1, 0x05BC,
+ /* 3606 */ 0x05E3, 0x05BC,
+ /* 3608 */ 0x05E4, 0x05BC,
+ /* 3610 */ 0x05E6, 0x05BC,
+ /* 3612 */ 0x05E7, 0x05BC,
+ /* 3614 */ 0x05E8, 0x05BC,
+ /* 3616 */ 0x05E9, 0x05BC,
+ /* 3618 */ 0x05EA, 0x05BC,
+ /* 3620 */ 0x05D5, 0x05B9,
+ /* 3622 */ 0x05D1, 0x05BF,
+ /* 3624 */ 0x05DB, 0x05BF,
+ /* 3626 */ 0x05E4, 0x05BF,
+ /* 3628 */ 0x05D0, 0x05DC,
+ /* 3630 */ 0x0626, 0x0627,
+ /* 3632 */ 0x0626, 0x0627,
+ /* 3634 */ 0x0626, 0x06D5,
+ /* 3636 */ 0x0626, 0x06D5,
+ /* 3638 */ 0x0626, 0x0648,
+ /* 3640 */ 0x0626, 0x0648,
+ /* 3642 */ 0x0626, 0x06C7,
+ /* 3644 */ 0x0626, 0x06C7,
+ /* 3646 */ 0x0626, 0x06C6,
+ /* 3648 */ 0x0626, 0x06C6,
+ /* 3650 */ 0x0626, 0x06C8,
+ /* 3652 */ 0x0626, 0x06C8,
+ /* 3654 */ 0x0626, 0x06D0,
+ /* 3656 */ 0x0626, 0x06D0,
+ /* 3658 */ 0x0626, 0x06D0,
+ /* 3660 */ 0x0626, 0x0649,
+ /* 3662 */ 0x0626, 0x0649,
+ /* 3664 */ 0x0626, 0x0649,
+ /* 3666 */ 0x0626, 0x062C,
+ /* 3668 */ 0x0626, 0x062D,
+ /* 3670 */ 0x0626, 0x0645,
+ /* 3672 */ 0x0626, 0x0649,
+ /* 3674 */ 0x0626, 0x064A,
+ /* 3676 */ 0x0628, 0x062C,
+ /* 3678 */ 0x0628, 0x062D,
+ /* 3680 */ 0x0628, 0x062E,
+ /* 3682 */ 0x0628, 0x0645,
+ /* 3684 */ 0x0628, 0x0649,
+ /* 3686 */ 0x0628, 0x064A,
+ /* 3688 */ 0x062A, 0x062C,
+ /* 3690 */ 0x062A, 0x062D,
+ /* 3692 */ 0x062A, 0x062E,
+ /* 3694 */ 0x062A, 0x0645,
+ /* 3696 */ 0x062A, 0x0649,
+ /* 3698 */ 0x062A, 0x064A,
+ /* 3700 */ 0x062B, 0x062C,
+ /* 3702 */ 0x062B, 0x0645,
+ /* 3704 */ 0x062B, 0x0649,
+ /* 3706 */ 0x062B, 0x064A,
+ /* 3708 */ 0x062C, 0x062D,
+ /* 3710 */ 0x062C, 0x0645,
+ /* 3712 */ 0x062D, 0x062C,
+ /* 3714 */ 0x062D, 0x0645,
+ /* 3716 */ 0x062E, 0x062C,
+ /* 3718 */ 0x062E, 0x062D,
+ /* 3720 */ 0x062E, 0x0645,
+ /* 3722 */ 0x0633, 0x062C,
+ /* 3724 */ 0x0633, 0x062D,
+ /* 3726 */ 0x0633, 0x062E,
+ /* 3728 */ 0x0633, 0x0645,
+ /* 3730 */ 0x0635, 0x062D,
+ /* 3732 */ 0x0635, 0x0645,
+ /* 3734 */ 0x0636, 0x062C,
+ /* 3736 */ 0x0636, 0x062D,
+ /* 3738 */ 0x0636, 0x062E,
+ /* 3740 */ 0x0636, 0x0645,
+ /* 3742 */ 0x0637, 0x062D,
+ /* 3744 */ 0x0637, 0x0645,
+ /* 3746 */ 0x0638, 0x0645,
+ /* 3748 */ 0x0639, 0x062C,
+ /* 3750 */ 0x0639, 0x0645,
+ /* 3752 */ 0x063A, 0x062C,
+ /* 3754 */ 0x063A, 0x0645,
+ /* 3756 */ 0x0641, 0x062C,
+ /* 3758 */ 0x0641, 0x062D,
+ /* 3760 */ 0x0641, 0x062E,
+ /* 3762 */ 0x0641, 0x0645,
+ /* 3764 */ 0x0641, 0x0649,
+ /* 3766 */ 0x0641, 0x064A,
+ /* 3768 */ 0x0642, 0x062D,
+ /* 3770 */ 0x0642, 0x0645,
+ /* 3772 */ 0x0642, 0x0649,
+ /* 3774 */ 0x0642, 0x064A,
+ /* 3776 */ 0x0643, 0x0627,
+ /* 3778 */ 0x0643, 0x062C,
+ /* 3780 */ 0x0643, 0x062D,
+ /* 3782 */ 0x0643, 0x062E,
+ /* 3784 */ 0x0643, 0x0644,
+ /* 3786 */ 0x0643, 0x0645,
+ /* 3788 */ 0x0643, 0x0649,
+ /* 3790 */ 0x0643, 0x064A,
+ /* 3792 */ 0x0644, 0x062C,
+ /* 3794 */ 0x0644, 0x062D,
+ /* 3796 */ 0x0644, 0x062E,
+ /* 3798 */ 0x0644, 0x0645,
+ /* 3800 */ 0x0644, 0x0649,
+ /* 3802 */ 0x0644, 0x064A,
+ /* 3804 */ 0x0645, 0x062C,
+ /* 3806 */ 0x0645, 0x062D,
+ /* 3808 */ 0x0645, 0x062E,
+ /* 3810 */ 0x0645, 0x0645,
+ /* 3812 */ 0x0645, 0x0649,
+ /* 3814 */ 0x0645, 0x064A,
+ /* 3816 */ 0x0646, 0x062C,
+ /* 3818 */ 0x0646, 0x062D,
+ /* 3820 */ 0x0646, 0x062E,
+ /* 3822 */ 0x0646, 0x0645,
+ /* 3824 */ 0x0646, 0x0649,
+ /* 3826 */ 0x0646, 0x064A,
+ /* 3828 */ 0x0647, 0x062C,
+ /* 3830 */ 0x0647, 0x0645,
+ /* 3832 */ 0x0647, 0x0649,
+ /* 3834 */ 0x0647, 0x064A,
+ /* 3836 */ 0x064A, 0x062C,
+ /* 3838 */ 0x064A, 0x062D,
+ /* 3840 */ 0x064A, 0x062E,
+ /* 3842 */ 0x064A, 0x0645,
+ /* 3844 */ 0x064A, 0x0649,
+ /* 3846 */ 0x064A, 0x064A,
+ /* 3848 */ 0x0630, 0x0670,
+ /* 3850 */ 0x0631, 0x0670,
+ /* 3852 */ 0x0649, 0x0670,
+ /* 3854 */ 0x0020, 0x064C, 0x0651,
+ /* 3857 */ 0x0020, 0x064D, 0x0651,
+ /* 3860 */ 0x0020, 0x064E, 0x0651,
+ /* 3863 */ 0x0020, 0x064F, 0x0651,
+ /* 3866 */ 0x0020, 0x0650, 0x0651,
+ /* 3869 */ 0x0020, 0x0651, 0x0670,
+ /* 3872 */ 0x0626, 0x0631,
+ /* 3874 */ 0x0626, 0x0632,
+ /* 3876 */ 0x0626, 0x0645,
+ /* 3878 */ 0x0626, 0x0646,
+ /* 3880 */ 0x0626, 0x0649,
+ /* 3882 */ 0x0626, 0x064A,
+ /* 3884 */ 0x0628, 0x0631,
+ /* 3886 */ 0x0628, 0x0632,
+ /* 3888 */ 0x0628, 0x0645,
+ /* 3890 */ 0x0628, 0x0646,
+ /* 3892 */ 0x0628, 0x0649,
+ /* 3894 */ 0x0628, 0x064A,
+ /* 3896 */ 0x062A, 0x0631,
+ /* 3898 */ 0x062A, 0x0632,
+ /* 3900 */ 0x062A, 0x0645,
+ /* 3902 */ 0x062A, 0x0646,
+ /* 3904 */ 0x062A, 0x0649,
+ /* 3906 */ 0x062A, 0x064A,
+ /* 3908 */ 0x062B, 0x0631,
+ /* 3910 */ 0x062B, 0x0632,
+ /* 3912 */ 0x062B, 0x0645,
+ /* 3914 */ 0x062B, 0x0646,
+ /* 3916 */ 0x062B, 0x0649,
+ /* 3918 */ 0x062B, 0x064A,
+ /* 3920 */ 0x0641, 0x0649,
+ /* 3922 */ 0x0641, 0x064A,
+ /* 3924 */ 0x0642, 0x0649,
+ /* 3926 */ 0x0642, 0x064A,
+ /* 3928 */ 0x0643, 0x0627,
+ /* 3930 */ 0x0643, 0x0644,
+ /* 3932 */ 0x0643, 0x0645,
+ /* 3934 */ 0x0643, 0x0649,
+ /* 3936 */ 0x0643, 0x064A,
+ /* 3938 */ 0x0644, 0x0645,
+ /* 3940 */ 0x0644, 0x0649,
+ /* 3942 */ 0x0644, 0x064A,
+ /* 3944 */ 0x0645, 0x0627,
+ /* 3946 */ 0x0645, 0x0645,
+ /* 3948 */ 0x0646, 0x0631,
+ /* 3950 */ 0x0646, 0x0632,
+ /* 3952 */ 0x0646, 0x0645,
+ /* 3954 */ 0x0646, 0x0646,
+ /* 3956 */ 0x0646, 0x0649,
+ /* 3958 */ 0x0646, 0x064A,
+ /* 3960 */ 0x0649, 0x0670,
+ /* 3962 */ 0x064A, 0x0631,
+ /* 3964 */ 0x064A, 0x0632,
+ /* 3966 */ 0x064A, 0x0645,
+ /* 3968 */ 0x064A, 0x0646,
+ /* 3970 */ 0x064A, 0x0649,
+ /* 3972 */ 0x064A, 0x064A,
+ /* 3974 */ 0x0626, 0x062C,
+ /* 3976 */ 0x0626, 0x062D,
+ /* 3978 */ 0x0626, 0x062E,
+ /* 3980 */ 0x0626, 0x0645,
+ /* 3982 */ 0x0626, 0x0647,
+ /* 3984 */ 0x0628, 0x062C,
+ /* 3986 */ 0x0628, 0x062D,
+ /* 3988 */ 0x0628, 0x062E,
+ /* 3990 */ 0x0628, 0x0645,
+ /* 3992 */ 0x0628, 0x0647,
+ /* 3994 */ 0x062A, 0x062C,
+ /* 3996 */ 0x062A, 0x062D,
+ /* 3998 */ 0x062A, 0x062E,
+ /* 4000 */ 0x062A, 0x0645,
+ /* 4002 */ 0x062A, 0x0647,
+ /* 4004 */ 0x062B, 0x0645,
+ /* 4006 */ 0x062C, 0x062D,
+ /* 4008 */ 0x062C, 0x0645,
+ /* 4010 */ 0x062D, 0x062C,
+ /* 4012 */ 0x062D, 0x0645,
+ /* 4014 */ 0x062E, 0x062C,
+ /* 4016 */ 0x062E, 0x0645,
+ /* 4018 */ 0x0633, 0x062C,
+ /* 4020 */ 0x0633, 0x062D,
+ /* 4022 */ 0x0633, 0x062E,
+ /* 4024 */ 0x0633, 0x0645,
+ /* 4026 */ 0x0635, 0x062D,
+ /* 4028 */ 0x0635, 0x062E,
+ /* 4030 */ 0x0635, 0x0645,
+ /* 4032 */ 0x0636, 0x062C,
+ /* 4034 */ 0x0636, 0x062D,
+ /* 4036 */ 0x0636, 0x062E,
+ /* 4038 */ 0x0636, 0x0645,
+ /* 4040 */ 0x0637, 0x062D,
+ /* 4042 */ 0x0638, 0x0645,
+ /* 4044 */ 0x0639, 0x062C,
+ /* 4046 */ 0x0639, 0x0645,
+ /* 4048 */ 0x063A, 0x062C,
+ /* 4050 */ 0x063A, 0x0645,
+ /* 4052 */ 0x0641, 0x062C,
+ /* 4054 */ 0x0641, 0x062D,
+ /* 4056 */ 0x0641, 0x062E,
+ /* 4058 */ 0x0641, 0x0645,
+ /* 4060 */ 0x0642, 0x062D,
+ /* 4062 */ 0x0642, 0x0645,
+ /* 4064 */ 0x0643, 0x062C,
+ /* 4066 */ 0x0643, 0x062D,
+ /* 4068 */ 0x0643, 0x062E,
+ /* 4070 */ 0x0643, 0x0644,
+ /* 4072 */ 0x0643, 0x0645,
+ /* 4074 */ 0x0644, 0x062C,
+ /* 4076 */ 0x0644, 0x062D,
+ /* 4078 */ 0x0644, 0x062E,
+ /* 4080 */ 0x0644, 0x0645,
+ /* 4082 */ 0x0644, 0x0647,
+ /* 4084 */ 0x0645, 0x062C,
+ /* 4086 */ 0x0645, 0x062D,
+ /* 4088 */ 0x0645, 0x062E,
+ /* 4090 */ 0x0645, 0x0645,
+ /* 4092 */ 0x0646, 0x062C,
+ /* 4094 */ 0x0646, 0x062D,
+ /* 4096 */ 0x0646, 0x062E,
+ /* 4098 */ 0x0646, 0x0645,
+ /* 4100 */ 0x0646, 0x0647,
+ /* 4102 */ 0x0647, 0x062C,
+ /* 4104 */ 0x0647, 0x0645,
+ /* 4106 */ 0x0647, 0x0670,
+ /* 4108 */ 0x064A, 0x062C,
+ /* 4110 */ 0x064A, 0x062D,
+ /* 4112 */ 0x064A, 0x062E,
+ /* 4114 */ 0x064A, 0x0645,
+ /* 4116 */ 0x064A, 0x0647,
+ /* 4118 */ 0x0626, 0x0645,
+ /* 4120 */ 0x0626, 0x0647,
+ /* 4122 */ 0x0628, 0x0645,
+ /* 4124 */ 0x0628, 0x0647,
+ /* 4126 */ 0x062A, 0x0645,
+ /* 4128 */ 0x062A, 0x0647,
+ /* 4130 */ 0x062B, 0x0645,
+ /* 4132 */ 0x062B, 0x0647,
+ /* 4134 */ 0x0633, 0x0645,
+ /* 4136 */ 0x0633, 0x0647,
+ /* 4138 */ 0x0634, 0x0645,
+ /* 4140 */ 0x0634, 0x0647,
+ /* 4142 */ 0x0643, 0x0644,
+ /* 4144 */ 0x0643, 0x0645,
+ /* 4146 */ 0x0644, 0x0645,
+ /* 4148 */ 0x0646, 0x0645,
+ /* 4150 */ 0x0646, 0x0647,
+ /* 4152 */ 0x064A, 0x0645,
+ /* 4154 */ 0x064A, 0x0647,
+ /* 4156 */ 0x0640, 0x064E, 0x0651,
+ /* 4159 */ 0x0640, 0x064F, 0x0651,
+ /* 4162 */ 0x0640, 0x0650, 0x0651,
+ /* 4165 */ 0x0637, 0x0649,
+ /* 4167 */ 0x0637, 0x064A,
+ /* 4169 */ 0x0639, 0x0649,
+ /* 4171 */ 0x0639, 0x064A,
+ /* 4173 */ 0x063A, 0x0649,
+ /* 4175 */ 0x063A, 0x064A,
+ /* 4177 */ 0x0633, 0x0649,
+ /* 4179 */ 0x0633, 0x064A,
+ /* 4181 */ 0x0634, 0x0649,
+ /* 4183 */ 0x0634, 0x064A,
+ /* 4185 */ 0x062D, 0x0649,
+ /* 4187 */ 0x062D, 0x064A,
+ /* 4189 */ 0x062C, 0x0649,
+ /* 4191 */ 0x062C, 0x064A,
+ /* 4193 */ 0x062E, 0x0649,
+ /* 4195 */ 0x062E, 0x064A,
+ /* 4197 */ 0x0635, 0x0649,
+ /* 4199 */ 0x0635, 0x064A,
+ /* 4201 */ 0x0636, 0x0649,
+ /* 4203 */ 0x0636, 0x064A,
+ /* 4205 */ 0x0634, 0x062C,
+ /* 4207 */ 0x0634, 0x062D,
+ /* 4209 */ 0x0634, 0x062E,
+ /* 4211 */ 0x0634, 0x0645,
+ /* 4213 */ 0x0634, 0x0631,
+ /* 4215 */ 0x0633, 0x0631,
+ /* 4217 */ 0x0635, 0x0631,
+ /* 4219 */ 0x0636, 0x0631,
+ /* 4221 */ 0x0637, 0x0649,
+ /* 4223 */ 0x0637, 0x064A,
+ /* 4225 */ 0x0639, 0x0649,
+ /* 4227 */ 0x0639, 0x064A,
+ /* 4229 */ 0x063A, 0x0649,
+ /* 4231 */ 0x063A, 0x064A,
+ /* 4233 */ 0x0633, 0x0649,
+ /* 4235 */ 0x0633, 0x064A,
+ /* 4237 */ 0x0634, 0x0649,
+ /* 4239 */ 0x0634, 0x064A,
+ /* 4241 */ 0x062D, 0x0649,
+ /* 4243 */ 0x062D, 0x064A,
+ /* 4245 */ 0x062C, 0x0649,
+ /* 4247 */ 0x062C, 0x064A,
+ /* 4249 */ 0x062E, 0x0649,
+ /* 4251 */ 0x062E, 0x064A,
+ /* 4253 */ 0x0635, 0x0649,
+ /* 4255 */ 0x0635, 0x064A,
+ /* 4257 */ 0x0636, 0x0649,
+ /* 4259 */ 0x0636, 0x064A,
+ /* 4261 */ 0x0634, 0x062C,
+ /* 4263 */ 0x0634, 0x062D,
+ /* 4265 */ 0x0634, 0x062E,
+ /* 4267 */ 0x0634, 0x0645,
+ /* 4269 */ 0x0634, 0x0631,
+ /* 4271 */ 0x0633, 0x0631,
+ /* 4273 */ 0x0635, 0x0631,
+ /* 4275 */ 0x0636, 0x0631,
+ /* 4277 */ 0x0634, 0x062C,
+ /* 4279 */ 0x0634, 0x062D,
+ /* 4281 */ 0x0634, 0x062E,
+ /* 4283 */ 0x0634, 0x0645,
+ /* 4285 */ 0x0633, 0x0647,
+ /* 4287 */ 0x0634, 0x0647,
+ /* 4289 */ 0x0637, 0x0645,
+ /* 4291 */ 0x0633, 0x062C,
+ /* 4293 */ 0x0633, 0x062D,
+ /* 4295 */ 0x0633, 0x062E,
+ /* 4297 */ 0x0634, 0x062C,
+ /* 4299 */ 0x0634, 0x062D,
+ /* 4301 */ 0x0634, 0x062E,
+ /* 4303 */ 0x0637, 0x0645,
+ /* 4305 */ 0x0638, 0x0645,
+ /* 4307 */ 0x0627, 0x064B,
+ /* 4309 */ 0x0627, 0x064B,
+ /* 4311 */ 0x062A, 0x062C, 0x0645,
+ /* 4314 */ 0x062A, 0x062D, 0x062C,
+ /* 4317 */ 0x062A, 0x062D, 0x062C,
+ /* 4320 */ 0x062A, 0x062D, 0x0645,
+ /* 4323 */ 0x062A, 0x062E, 0x0645,
+ /* 4326 */ 0x062A, 0x0645, 0x062C,
+ /* 4329 */ 0x062A, 0x0645, 0x062D,
+ /* 4332 */ 0x062A, 0x0645, 0x062E,
+ /* 4335 */ 0x062C, 0x0645, 0x062D,
+ /* 4338 */ 0x062C, 0x0645, 0x062D,
+ /* 4341 */ 0x062D, 0x0645, 0x064A,
+ /* 4344 */ 0x062D, 0x0645, 0x0649,
+ /* 4347 */ 0x0633, 0x062D, 0x062C,
+ /* 4350 */ 0x0633, 0x062C, 0x062D,
+ /* 4353 */ 0x0633, 0x062C, 0x0649,
+ /* 4356 */ 0x0633, 0x0645, 0x062D,
+ /* 4359 */ 0x0633, 0x0645, 0x062D,
+ /* 4362 */ 0x0633, 0x0645, 0x062C,
+ /* 4365 */ 0x0633, 0x0645, 0x0645,
+ /* 4368 */ 0x0633, 0x0645, 0x0645,
+ /* 4371 */ 0x0635, 0x062D, 0x062D,
+ /* 4374 */ 0x0635, 0x062D, 0x062D,
+ /* 4377 */ 0x0635, 0x0645, 0x0645,
+ /* 4380 */ 0x0634, 0x062D, 0x0645,
+ /* 4383 */ 0x0634, 0x062D, 0x0645,
+ /* 4386 */ 0x0634, 0x062C, 0x064A,
+ /* 4389 */ 0x0634, 0x0645, 0x062E,
+ /* 4392 */ 0x0634, 0x0645, 0x062E,
+ /* 4395 */ 0x0634, 0x0645, 0x0645,
+ /* 4398 */ 0x0634, 0x0645, 0x0645,
+ /* 4401 */ 0x0636, 0x062D, 0x0649,
+ /* 4404 */ 0x0636, 0x062E, 0x0645,
+ /* 4407 */ 0x0636, 0x062E, 0x0645,
+ /* 4410 */ 0x0637, 0x0645, 0x062D,
+ /* 4413 */ 0x0637, 0x0645, 0x062D,
+ /* 4416 */ 0x0637, 0x0645, 0x0645,
+ /* 4419 */ 0x0637, 0x0645, 0x064A,
+ /* 4422 */ 0x0639, 0x062C, 0x0645,
+ /* 4425 */ 0x0639, 0x0645, 0x0645,
+ /* 4428 */ 0x0639, 0x0645, 0x0645,
+ /* 4431 */ 0x0639, 0x0645, 0x0649,
+ /* 4434 */ 0x063A, 0x0645, 0x0645,
+ /* 4437 */ 0x063A, 0x0645, 0x064A,
+ /* 4440 */ 0x063A, 0x0645, 0x0649,
+ /* 4443 */ 0x0641, 0x062E, 0x0645,
+ /* 4446 */ 0x0641, 0x062E, 0x0645,
+ /* 4449 */ 0x0642, 0x0645, 0x062D,
+ /* 4452 */ 0x0642, 0x0645, 0x0645,
+ /* 4455 */ 0x0644, 0x062D, 0x0645,
+ /* 4458 */ 0x0644, 0x062D, 0x064A,
+ /* 4461 */ 0x0644, 0x062D, 0x0649,
+ /* 4464 */ 0x0644, 0x062C, 0x062C,
+ /* 4467 */ 0x0644, 0x062C, 0x062C,
+ /* 4470 */ 0x0644, 0x062E, 0x0645,
+ /* 4473 */ 0x0644, 0x062E, 0x0645,
+ /* 4476 */ 0x0644, 0x0645, 0x062D,
+ /* 4479 */ 0x0644, 0x0645, 0x062D,
+ /* 4482 */ 0x0645, 0x062D, 0x062C,
+ /* 4485 */ 0x0645, 0x062D, 0x0645,
+ /* 4488 */ 0x0645, 0x062D, 0x064A,
+ /* 4491 */ 0x0645, 0x062C, 0x062D,
+ /* 4494 */ 0x0645, 0x062C, 0x0645,
+ /* 4497 */ 0x0645, 0x062E, 0x062C,
+ /* 4500 */ 0x0645, 0x062E, 0x0645,
+ /* 4503 */ 0x0645, 0x062C, 0x062E,
+ /* 4506 */ 0x0647, 0x0645, 0x062C,
+ /* 4509 */ 0x0647, 0x0645, 0x0645,
+ /* 4512 */ 0x0646, 0x062D, 0x0645,
+ /* 4515 */ 0x0646, 0x062D, 0x0649,
+ /* 4518 */ 0x0646, 0x062C, 0x0645,
+ /* 4521 */ 0x0646, 0x062C, 0x0645,
+ /* 4524 */ 0x0646, 0x062C, 0x0649,
+ /* 4527 */ 0x0646, 0x0645, 0x064A,
+ /* 4530 */ 0x0646, 0x0645, 0x0649,
+ /* 4533 */ 0x064A, 0x0645, 0x0645,
+ /* 4536 */ 0x064A, 0x0645, 0x0645,
+ /* 4539 */ 0x0628, 0x062E, 0x064A,
+ /* 4542 */ 0x062A, 0x062C, 0x064A,
+ /* 4545 */ 0x062A, 0x062C, 0x0649,
+ /* 4548 */ 0x062A, 0x062E, 0x064A,
+ /* 4551 */ 0x062A, 0x062E, 0x0649,
+ /* 4554 */ 0x062A, 0x0645, 0x064A,
+ /* 4557 */ 0x062A, 0x0645, 0x0649,
+ /* 4560 */ 0x062C, 0x0645, 0x064A,
+ /* 4563 */ 0x062C, 0x062D, 0x0649,
+ /* 4566 */ 0x062C, 0x0645, 0x0649,
+ /* 4569 */ 0x0633, 0x062E, 0x0649,
+ /* 4572 */ 0x0635, 0x062D, 0x064A,
+ /* 4575 */ 0x0634, 0x062D, 0x064A,
+ /* 4578 */ 0x0636, 0x062D, 0x064A,
+ /* 4581 */ 0x0644, 0x062C, 0x064A,
+ /* 4584 */ 0x0644, 0x0645, 0x064A,
+ /* 4587 */ 0x064A, 0x062D, 0x064A,
+ /* 4590 */ 0x064A, 0x062C, 0x064A,
+ /* 4593 */ 0x064A, 0x0645, 0x064A,
+ /* 4596 */ 0x0645, 0x0645, 0x064A,
+ /* 4599 */ 0x0642, 0x0645, 0x064A,
+ /* 4602 */ 0x0646, 0x062D, 0x064A,
+ /* 4605 */ 0x0642, 0x0645, 0x062D,
+ /* 4608 */ 0x0644, 0x062D, 0x0645,
+ /* 4611 */ 0x0639, 0x0645, 0x064A,
+ /* 4614 */ 0x0643, 0x0645, 0x064A,
+ /* 4617 */ 0x0646, 0x062C, 0x062D,
+ /* 4620 */ 0x0645, 0x062E, 0x064A,
+ /* 4623 */ 0x0644, 0x062C, 0x0645,
+ /* 4626 */ 0x0643, 0x0645, 0x0645,
+ /* 4629 */ 0x0644, 0x062C, 0x0645,
+ /* 4632 */ 0x0646, 0x062C, 0x062D,
+ /* 4635 */ 0x062C, 0x062D, 0x064A,
+ /* 4638 */ 0x062D, 0x062C, 0x064A,
+ /* 4641 */ 0x0645, 0x062C, 0x064A,
+ /* 4644 */ 0x0641, 0x0645, 0x064A,
+ /* 4647 */ 0x0628, 0x062D, 0x064A,
+ /* 4650 */ 0x0643, 0x0645, 0x0645,
+ /* 4653 */ 0x0639, 0x062C, 0x0645,
+ /* 4656 */ 0x0635, 0x0645, 0x0645,
+ /* 4659 */ 0x0633, 0x062E, 0x064A,
+ /* 4662 */ 0x0646, 0x062C, 0x064A,
+ /* 4665 */ 0x0635, 0x0644, 0x06D2,
+ /* 4668 */ 0x0642, 0x0644, 0x06D2,
+ /* 4671 */ 0x0627, 0x0644, 0x0644, 0x0647,
+ /* 4675 */ 0x0627, 0x0643, 0x0628, 0x0631,
+ /* 4679 */ 0x0645, 0x062D, 0x0645, 0x062F,
+ /* 4683 */ 0x0635, 0x0644, 0x0639, 0x0645,
+ /* 4687 */ 0x0631, 0x0633, 0x0648, 0x0644,
+ /* 4691 */ 0x0639, 0x0644, 0x064A, 0x0647,
+ /* 4695 */ 0x0648, 0x0633, 0x0644, 0x0645,
+ /* 4699 */ 0x0635, 0x0644, 0x0649,
+ /* 4702 */ 0x0635, 0x0644, 0x0649, 0x0020, 0x0627, 0x0644, 0x0644, 0x0647, 0x0020, 0x0639, 0x0644, 0x064A, 0x0647, 0x0020, 0x0648, 0x0633, 0x0644, 0x0645,
+ /* 4720 */ 0x062C, 0x0644, 0x0020, 0x062C, 0x0644, 0x0627, 0x0644, 0x0647,
+ /* 4728 */ 0x0631, 0x06CC, 0x0627, 0x0644,
+ /* 4732 */ 0x0020, 0x064B,
+ /* 4734 */ 0x0640, 0x064B,
+ /* 4736 */ 0x0020, 0x064C,
+ /* 4738 */ 0x0020, 0x064D,
+ /* 4740 */ 0x0020, 0x064E,
+ /* 4742 */ 0x0640, 0x064E,
+ /* 4744 */ 0x0020, 0x064F,
+ /* 4746 */ 0x0640, 0x064F,
+ /* 4748 */ 0x0020, 0x0650,
+ /* 4750 */ 0x0640, 0x0650,
+ /* 4752 */ 0x0020, 0x0651,
+ /* 4754 */ 0x0640, 0x0651,
+ /* 4756 */ 0x0020, 0x0652,
+ /* 4758 */ 0x0640, 0x0652,
+ /* 4760 */ 0x0644, 0x0622,
+ /* 4762 */ 0x0644, 0x0622,
+ /* 4764 */ 0x0644, 0x0623,
+ /* 4766 */ 0x0644, 0x0623,
+ /* 4768 */ 0x0644, 0x0625,
+ /* 4770 */ 0x0644, 0x0625,
+ /* 4772 */ 0x0644, 0x0627,
+ /* 4774 */ 0x0644, 0x0627,
+ /* 4776 */ 0x11099, 0x110BA,
+ /* 4778 */ 0x1109B, 0x110BA,
+ /* 4780 */ 0x110A5, 0x110BA,
+ /* 4782 */ 0x11131, 0x11127,
+ /* 4784 */ 0x11132, 0x11127,
+ /* 4786 */ 0x11347, 0x1133E,
+ /* 4788 */ 0x11347, 0x11357,
+ /* 4790 */ 0x114B9, 0x114BA,
+ /* 4792 */ 0x114B9, 0x114B0,
+ /* 4794 */ 0x114B9, 0x114BD,
+ /* 4796 */ 0x115B8, 0x115AF,
+ /* 4798 */ 0x115B9, 0x115AF,
+ /* 4800 */ 0x11935, 0x11930,
+ /* 4802 */ 0x1D157, 0x1D165,
+ /* 4804 */ 0x1D158, 0x1D165,
+ /* 4806 */ 0x1D15F, 0x1D16E,
+ /* 4808 */ 0x1D15F, 0x1D16F,
+ /* 4810 */ 0x1D15F, 0x1D170,
+ /* 4812 */ 0x1D15F, 0x1D171,
+ /* 4814 */ 0x1D15F, 0x1D172,
+ /* 4816 */ 0x1D1B9, 0x1D165,
+ /* 4818 */ 0x1D1BA, 0x1D165,
+ /* 4820 */ 0x1D1BB, 0x1D16E,
+ /* 4822 */ 0x1D1BC, 0x1D16E,
+ /* 4824 */ 0x1D1BB, 0x1D16F,
+ /* 4826 */ 0x1D1BC, 0x1D16F,
+ /* 4828 */ 0x0030, 0x002E,
+ /* 4830 */ 0x0030, 0x002C,
+ /* 4832 */ 0x0031, 0x002C,
+ /* 4834 */ 0x0032, 0x002C,
+ /* 4836 */ 0x0033, 0x002C,
+ /* 4838 */ 0x0034, 0x002C,
+ /* 4840 */ 0x0035, 0x002C,
+ /* 4842 */ 0x0036, 0x002C,
+ /* 4844 */ 0x0037, 0x002C,
+ /* 4846 */ 0x0038, 0x002C,
+ /* 4848 */ 0x0039, 0x002C,
+ /* 4850 */ 0x0028, 0x0041, 0x0029,
+ /* 4853 */ 0x0028, 0x0042, 0x0029,
+ /* 4856 */ 0x0028, 0x0043, 0x0029,
+ /* 4859 */ 0x0028, 0x0044, 0x0029,
+ /* 4862 */ 0x0028, 0x0045, 0x0029,
+ /* 4865 */ 0x0028, 0x0046, 0x0029,
+ /* 4868 */ 0x0028, 0x0047, 0x0029,
+ /* 4871 */ 0x0028, 0x0048, 0x0029,
+ /* 4874 */ 0x0028, 0x0049, 0x0029,
+ /* 4877 */ 0x0028, 0x004A, 0x0029,
+ /* 4880 */ 0x0028, 0x004B, 0x0029,
+ /* 4883 */ 0x0028, 0x004C, 0x0029,
+ /* 4886 */ 0x0028, 0x004D, 0x0029,
+ /* 4889 */ 0x0028, 0x004E, 0x0029,
+ /* 4892 */ 0x0028, 0x004F, 0x0029,
+ /* 4895 */ 0x0028, 0x0050, 0x0029,
+ /* 4898 */ 0x0028, 0x0051, 0x0029,
+ /* 4901 */ 0x0028, 0x0052, 0x0029,
+ /* 4904 */ 0x0028, 0x0053, 0x0029,
+ /* 4907 */ 0x0028, 0x0054, 0x0029,
+ /* 4910 */ 0x0028, 0x0055, 0x0029,
+ /* 4913 */ 0x0028, 0x0056, 0x0029,
+ /* 4916 */ 0x0028, 0x0057, 0x0029,
+ /* 4919 */ 0x0028, 0x0058, 0x0029,
+ /* 4922 */ 0x0028, 0x0059, 0x0029,
+ /* 4925 */ 0x0028, 0x005A, 0x0029,
+ /* 4928 */ 0x3014, 0x0053, 0x3015,
+ /* 4931 */ 0x0043, 0x0044,
+ /* 4933 */ 0x0057, 0x005A,
+ /* 4935 */ 0x0048, 0x0056,
+ /* 4937 */ 0x004D, 0x0056,
+ /* 4939 */ 0x0053, 0x0044,
+ /* 4941 */ 0x0053, 0x0053,
+ /* 4943 */ 0x0050, 0x0050, 0x0056,
+ /* 4946 */ 0x0057, 0x0043,
+ /* 4948 */ 0x004D, 0x0043,
+ /* 4950 */ 0x004D, 0x0044,
+ /* 4952 */ 0x004D, 0x0052,
+ /* 4954 */ 0x0044, 0x004A,
+ /* 4956 */ 0x307B, 0x304B,
+ /* 4958 */ 0x30B3, 0x30B3,
+ /* 4960 */ 0x3014, 0x672C, 0x3015,
+ /* 4963 */ 0x3014, 0x4E09, 0x3015,
+ /* 4966 */ 0x3014, 0x4E8C, 0x3015,
+ /* 4969 */ 0x3014, 0x5B89, 0x3015,
+ /* 4972 */ 0x3014, 0x70B9, 0x3015,
+ /* 4975 */ 0x3014, 0x6253, 0x3015,
+ /* 4978 */ 0x3014, 0x76D7, 0x3015,
+ /* 4981 */ 0x3014, 0x52DD, 0x3015,
+ /* 4984 */ 0x3014, 0x6557, 0x3015,
+ /* 4987 */ 0x20122,
+ /* 4988 */ 0x2063A,
+ /* 4989 */ 0x2051C,
+ /* 4990 */ 0x2054B,
+ /* 4991 */ 0x291DF,
+ /* 4992 */ 0x20A2C,
+ /* 4993 */ 0x20B63,
+ /* 4994 */ 0x214E4,
+ /* 4995 */ 0x216A8,
+ /* 4996 */ 0x216EA,
+ /* 4997 */ 0x219C8,
+ /* 4998 */ 0x21B18,
+ /* 4999 */ 0x21DE4,
+ /* 5000 */ 0x21DE6,
+ /* 5001 */ 0x22183,
+ /* 5002 */ 0x2A392,
+ /* 5003 */ 0x22331,
+ /* 5004 */ 0x22331,
+ /* 5005 */ 0x232B8,
+ /* 5006 */ 0x261DA,
+ /* 5007 */ 0x226D4,
+ /* 5008 */ 0x22B0C,
+ /* 5009 */ 0x22BF1,
+ /* 5010 */ 0x2300A,
+ /* 5011 */ 0x233C3,
+ /* 5012 */ 0x2346D,
+ /* 5013 */ 0x236A3,
+ /* 5014 */ 0x238A7,
+ /* 5015 */ 0x23A8D,
+ /* 5016 */ 0x21D0B,
+ /* 5017 */ 0x23AFA,
+ /* 5018 */ 0x23CBC,
+ /* 5019 */ 0x23D1E,
+ /* 5020 */ 0x23ED1,
+ /* 5021 */ 0x23F5E,
+ /* 5022 */ 0x23F8E,
+ /* 5023 */ 0x20525,
+ /* 5024 */ 0x24263,
+ /* 5025 */ 0x243AB,
+ /* 5026 */ 0x24608,
+ /* 5027 */ 0x24735,
+ /* 5028 */ 0x24814,
+ /* 5029 */ 0x24C36,
+ /* 5030 */ 0x24C92,
+ /* 5031 */ 0x2219F,
+ /* 5032 */ 0x24FA1,
+ /* 5033 */ 0x24FB8,
+ /* 5034 */ 0x25044,
+ /* 5035 */ 0x250F3,
+ /* 5036 */ 0x250F2,
+ /* 5037 */ 0x25119,
+ /* 5038 */ 0x25133,
+ /* 5039 */ 0x2541D,
+ /* 5040 */ 0x25626,
+ /* 5041 */ 0x2569A,
+ /* 5042 */ 0x256C5,
+ /* 5043 */ 0x2597C,
+ /* 5044 */ 0x25AA7,
+ /* 5045 */ 0x25AA7,
+ /* 5046 */ 0x25BAB,
+ /* 5047 */ 0x25C80,
+ /* 5048 */ 0x25F86,
+ /* 5049 */ 0x26228,
+ /* 5050 */ 0x26247,
+ /* 5051 */ 0x262D9,
+ /* 5052 */ 0x2633E,
+ /* 5053 */ 0x264DA,
+ /* 5054 */ 0x26523,
+ /* 5055 */ 0x265A8,
+ /* 5056 */ 0x2335F,
+ /* 5057 */ 0x267A7,
+ /* 5058 */ 0x267B5,
+ /* 5059 */ 0x23393,
+ /* 5060 */ 0x2339C,
+ /* 5061 */ 0x26B3C,
+ /* 5062 */ 0x26C36,
+ /* 5063 */ 0x26D6B,
+ /* 5064 */ 0x26CD5,
+ /* 5065 */ 0x273CA,
+ /* 5066 */ 0x26F2C,
+ /* 5067 */ 0x26FB1,
+ /* 5068 */ 0x270D2,
+ /* 5069 */ 0x27667,
+ /* 5070 */ 0x278AE,
+ /* 5071 */ 0x27966,
+ /* 5072 */ 0x27CA8,
+ /* 5073 */ 0x27F2F,
+ /* 5074 */ 0x20804,
+ /* 5075 */ 0x208DE,
+ /* 5076 */ 0x285D2,
+ /* 5077 */ 0x285ED,
+ /* 5078 */ 0x2872E,
+ /* 5079 */ 0x28BFA,
+ /* 5080 */ 0x28D77,
+ /* 5081 */ 0x29145,
+ /* 5082 */ 0x2921A,
+ /* 5083 */ 0x2940A,
+ /* 5084 */ 0x29496,
+ /* 5085 */ 0x295B6,
+ /* 5086 */ 0x29B30,
+ /* 5087 */ 0x2A0CE,
+ /* 5088 */ 0x2A105,
+ /* 5089 */ 0x2A20E,
+ /* 5090 */ 0x2A291,
+ /* 5091 */ 0x2A600
+};
diff --git a/src/include/common/unicode_normprops_table.h b/src/include/common/unicode_normprops_table.h
new file mode 100644
index 0000000..93a2e55
--- /dev/null
+++ b/src/include/common/unicode_normprops_table.h
@@ -0,0 +1,6167 @@
+/* generated by src/common/unicode/generate-unicode_normprops_table.pl, do not edit */
+
+#include "common/unicode_norm.h"
+
+/*
+ * We use a bit field here to save space.
+ */
+typedef struct
+{
+ unsigned int codepoint:21;
+ signed int quickcheck:4; /* really UnicodeNormalizationQC */
+} pg_unicode_normprops;
+
+static const pg_unicode_normprops UnicodeNormProps_NFC_QC[] = {
+ {0x0300, UNICODE_NORM_QC_MAYBE},
+ {0x0301, UNICODE_NORM_QC_MAYBE},
+ {0x0302, UNICODE_NORM_QC_MAYBE},
+ {0x0303, UNICODE_NORM_QC_MAYBE},
+ {0x0304, UNICODE_NORM_QC_MAYBE},
+ {0x0306, UNICODE_NORM_QC_MAYBE},
+ {0x0307, UNICODE_NORM_QC_MAYBE},
+ {0x0308, UNICODE_NORM_QC_MAYBE},
+ {0x0309, UNICODE_NORM_QC_MAYBE},
+ {0x030A, UNICODE_NORM_QC_MAYBE},
+ {0x030B, UNICODE_NORM_QC_MAYBE},
+ {0x030C, UNICODE_NORM_QC_MAYBE},
+ {0x030F, UNICODE_NORM_QC_MAYBE},
+ {0x0311, UNICODE_NORM_QC_MAYBE},
+ {0x0313, UNICODE_NORM_QC_MAYBE},
+ {0x0314, UNICODE_NORM_QC_MAYBE},
+ {0x031B, UNICODE_NORM_QC_MAYBE},
+ {0x0323, UNICODE_NORM_QC_MAYBE},
+ {0x0324, UNICODE_NORM_QC_MAYBE},
+ {0x0325, UNICODE_NORM_QC_MAYBE},
+ {0x0326, UNICODE_NORM_QC_MAYBE},
+ {0x0327, UNICODE_NORM_QC_MAYBE},
+ {0x0328, UNICODE_NORM_QC_MAYBE},
+ {0x032D, UNICODE_NORM_QC_MAYBE},
+ {0x032E, UNICODE_NORM_QC_MAYBE},
+ {0x0330, UNICODE_NORM_QC_MAYBE},
+ {0x0331, UNICODE_NORM_QC_MAYBE},
+ {0x0338, UNICODE_NORM_QC_MAYBE},
+ {0x0340, UNICODE_NORM_QC_NO},
+ {0x0341, UNICODE_NORM_QC_NO},
+ {0x0342, UNICODE_NORM_QC_MAYBE},
+ {0x0343, UNICODE_NORM_QC_NO},
+ {0x0344, UNICODE_NORM_QC_NO},
+ {0x0345, UNICODE_NORM_QC_MAYBE},
+ {0x0374, UNICODE_NORM_QC_NO},
+ {0x037E, UNICODE_NORM_QC_NO},
+ {0x0387, UNICODE_NORM_QC_NO},
+ {0x0653, UNICODE_NORM_QC_MAYBE},
+ {0x0654, UNICODE_NORM_QC_MAYBE},
+ {0x0655, UNICODE_NORM_QC_MAYBE},
+ {0x093C, UNICODE_NORM_QC_MAYBE},
+ {0x0958, UNICODE_NORM_QC_NO},
+ {0x0959, UNICODE_NORM_QC_NO},
+ {0x095A, UNICODE_NORM_QC_NO},
+ {0x095B, UNICODE_NORM_QC_NO},
+ {0x095C, UNICODE_NORM_QC_NO},
+ {0x095D, UNICODE_NORM_QC_NO},
+ {0x095E, UNICODE_NORM_QC_NO},
+ {0x095F, UNICODE_NORM_QC_NO},
+ {0x09BE, UNICODE_NORM_QC_MAYBE},
+ {0x09D7, UNICODE_NORM_QC_MAYBE},
+ {0x09DC, UNICODE_NORM_QC_NO},
+ {0x09DD, UNICODE_NORM_QC_NO},
+ {0x09DF, UNICODE_NORM_QC_NO},
+ {0x0A33, UNICODE_NORM_QC_NO},
+ {0x0A36, UNICODE_NORM_QC_NO},
+ {0x0A59, UNICODE_NORM_QC_NO},
+ {0x0A5A, UNICODE_NORM_QC_NO},
+ {0x0A5B, UNICODE_NORM_QC_NO},
+ {0x0A5E, UNICODE_NORM_QC_NO},
+ {0x0B3E, UNICODE_NORM_QC_MAYBE},
+ {0x0B56, UNICODE_NORM_QC_MAYBE},
+ {0x0B57, UNICODE_NORM_QC_MAYBE},
+ {0x0B5C, UNICODE_NORM_QC_NO},
+ {0x0B5D, UNICODE_NORM_QC_NO},
+ {0x0BBE, UNICODE_NORM_QC_MAYBE},
+ {0x0BD7, UNICODE_NORM_QC_MAYBE},
+ {0x0C56, UNICODE_NORM_QC_MAYBE},
+ {0x0CC2, UNICODE_NORM_QC_MAYBE},
+ {0x0CD5, UNICODE_NORM_QC_MAYBE},
+ {0x0CD6, UNICODE_NORM_QC_MAYBE},
+ {0x0D3E, UNICODE_NORM_QC_MAYBE},
+ {0x0D57, UNICODE_NORM_QC_MAYBE},
+ {0x0DCA, UNICODE_NORM_QC_MAYBE},
+ {0x0DCF, UNICODE_NORM_QC_MAYBE},
+ {0x0DDF, UNICODE_NORM_QC_MAYBE},
+ {0x0F43, UNICODE_NORM_QC_NO},
+ {0x0F4D, UNICODE_NORM_QC_NO},
+ {0x0F52, UNICODE_NORM_QC_NO},
+ {0x0F57, UNICODE_NORM_QC_NO},
+ {0x0F5C, UNICODE_NORM_QC_NO},
+ {0x0F69, UNICODE_NORM_QC_NO},
+ {0x0F73, UNICODE_NORM_QC_NO},
+ {0x0F75, UNICODE_NORM_QC_NO},
+ {0x0F76, UNICODE_NORM_QC_NO},
+ {0x0F78, UNICODE_NORM_QC_NO},
+ {0x0F81, UNICODE_NORM_QC_NO},
+ {0x0F93, UNICODE_NORM_QC_NO},
+ {0x0F9D, UNICODE_NORM_QC_NO},
+ {0x0FA2, UNICODE_NORM_QC_NO},
+ {0x0FA7, UNICODE_NORM_QC_NO},
+ {0x0FAC, UNICODE_NORM_QC_NO},
+ {0x0FB9, UNICODE_NORM_QC_NO},
+ {0x102E, UNICODE_NORM_QC_MAYBE},
+ {0x1161, UNICODE_NORM_QC_MAYBE},
+ {0x1162, UNICODE_NORM_QC_MAYBE},
+ {0x1163, UNICODE_NORM_QC_MAYBE},
+ {0x1164, UNICODE_NORM_QC_MAYBE},
+ {0x1165, UNICODE_NORM_QC_MAYBE},
+ {0x1166, UNICODE_NORM_QC_MAYBE},
+ {0x1167, UNICODE_NORM_QC_MAYBE},
+ {0x1168, UNICODE_NORM_QC_MAYBE},
+ {0x1169, UNICODE_NORM_QC_MAYBE},
+ {0x116A, UNICODE_NORM_QC_MAYBE},
+ {0x116B, UNICODE_NORM_QC_MAYBE},
+ {0x116C, UNICODE_NORM_QC_MAYBE},
+ {0x116D, UNICODE_NORM_QC_MAYBE},
+ {0x116E, UNICODE_NORM_QC_MAYBE},
+ {0x116F, UNICODE_NORM_QC_MAYBE},
+ {0x1170, UNICODE_NORM_QC_MAYBE},
+ {0x1171, UNICODE_NORM_QC_MAYBE},
+ {0x1172, UNICODE_NORM_QC_MAYBE},
+ {0x1173, UNICODE_NORM_QC_MAYBE},
+ {0x1174, UNICODE_NORM_QC_MAYBE},
+ {0x1175, UNICODE_NORM_QC_MAYBE},
+ {0x11A8, UNICODE_NORM_QC_MAYBE},
+ {0x11A9, UNICODE_NORM_QC_MAYBE},
+ {0x11AA, UNICODE_NORM_QC_MAYBE},
+ {0x11AB, UNICODE_NORM_QC_MAYBE},
+ {0x11AC, UNICODE_NORM_QC_MAYBE},
+ {0x11AD, UNICODE_NORM_QC_MAYBE},
+ {0x11AE, UNICODE_NORM_QC_MAYBE},
+ {0x11AF, UNICODE_NORM_QC_MAYBE},
+ {0x11B0, UNICODE_NORM_QC_MAYBE},
+ {0x11B1, UNICODE_NORM_QC_MAYBE},
+ {0x11B2, UNICODE_NORM_QC_MAYBE},
+ {0x11B3, UNICODE_NORM_QC_MAYBE},
+ {0x11B4, UNICODE_NORM_QC_MAYBE},
+ {0x11B5, UNICODE_NORM_QC_MAYBE},
+ {0x11B6, UNICODE_NORM_QC_MAYBE},
+ {0x11B7, UNICODE_NORM_QC_MAYBE},
+ {0x11B8, UNICODE_NORM_QC_MAYBE},
+ {0x11B9, UNICODE_NORM_QC_MAYBE},
+ {0x11BA, UNICODE_NORM_QC_MAYBE},
+ {0x11BB, UNICODE_NORM_QC_MAYBE},
+ {0x11BC, UNICODE_NORM_QC_MAYBE},
+ {0x11BD, UNICODE_NORM_QC_MAYBE},
+ {0x11BE, UNICODE_NORM_QC_MAYBE},
+ {0x11BF, UNICODE_NORM_QC_MAYBE},
+ {0x11C0, UNICODE_NORM_QC_MAYBE},
+ {0x11C1, UNICODE_NORM_QC_MAYBE},
+ {0x11C2, UNICODE_NORM_QC_MAYBE},
+ {0x1B35, UNICODE_NORM_QC_MAYBE},
+ {0x1F71, UNICODE_NORM_QC_NO},
+ {0x1F73, UNICODE_NORM_QC_NO},
+ {0x1F75, UNICODE_NORM_QC_NO},
+ {0x1F77, UNICODE_NORM_QC_NO},
+ {0x1F79, UNICODE_NORM_QC_NO},
+ {0x1F7B, UNICODE_NORM_QC_NO},
+ {0x1F7D, UNICODE_NORM_QC_NO},
+ {0x1FBB, UNICODE_NORM_QC_NO},
+ {0x1FBE, UNICODE_NORM_QC_NO},
+ {0x1FC9, UNICODE_NORM_QC_NO},
+ {0x1FCB, UNICODE_NORM_QC_NO},
+ {0x1FD3, UNICODE_NORM_QC_NO},
+ {0x1FDB, UNICODE_NORM_QC_NO},
+ {0x1FE3, UNICODE_NORM_QC_NO},
+ {0x1FEB, UNICODE_NORM_QC_NO},
+ {0x1FEE, UNICODE_NORM_QC_NO},
+ {0x1FEF, UNICODE_NORM_QC_NO},
+ {0x1FF9, UNICODE_NORM_QC_NO},
+ {0x1FFB, UNICODE_NORM_QC_NO},
+ {0x1FFD, UNICODE_NORM_QC_NO},
+ {0x2000, UNICODE_NORM_QC_NO},
+ {0x2001, UNICODE_NORM_QC_NO},
+ {0x2126, UNICODE_NORM_QC_NO},
+ {0x212A, UNICODE_NORM_QC_NO},
+ {0x212B, UNICODE_NORM_QC_NO},
+ {0x2329, UNICODE_NORM_QC_NO},
+ {0x232A, UNICODE_NORM_QC_NO},
+ {0x2ADC, UNICODE_NORM_QC_NO},
+ {0x3099, UNICODE_NORM_QC_MAYBE},
+ {0x309A, UNICODE_NORM_QC_MAYBE},
+ {0xF900, UNICODE_NORM_QC_NO},
+ {0xF901, UNICODE_NORM_QC_NO},
+ {0xF902, UNICODE_NORM_QC_NO},
+ {0xF903, UNICODE_NORM_QC_NO},
+ {0xF904, UNICODE_NORM_QC_NO},
+ {0xF905, UNICODE_NORM_QC_NO},
+ {0xF906, UNICODE_NORM_QC_NO},
+ {0xF907, UNICODE_NORM_QC_NO},
+ {0xF908, UNICODE_NORM_QC_NO},
+ {0xF909, UNICODE_NORM_QC_NO},
+ {0xF90A, UNICODE_NORM_QC_NO},
+ {0xF90B, UNICODE_NORM_QC_NO},
+ {0xF90C, UNICODE_NORM_QC_NO},
+ {0xF90D, UNICODE_NORM_QC_NO},
+ {0xF90E, UNICODE_NORM_QC_NO},
+ {0xF90F, UNICODE_NORM_QC_NO},
+ {0xF910, UNICODE_NORM_QC_NO},
+ {0xF911, UNICODE_NORM_QC_NO},
+ {0xF912, UNICODE_NORM_QC_NO},
+ {0xF913, UNICODE_NORM_QC_NO},
+ {0xF914, UNICODE_NORM_QC_NO},
+ {0xF915, UNICODE_NORM_QC_NO},
+ {0xF916, UNICODE_NORM_QC_NO},
+ {0xF917, UNICODE_NORM_QC_NO},
+ {0xF918, UNICODE_NORM_QC_NO},
+ {0xF919, UNICODE_NORM_QC_NO},
+ {0xF91A, UNICODE_NORM_QC_NO},
+ {0xF91B, UNICODE_NORM_QC_NO},
+ {0xF91C, UNICODE_NORM_QC_NO},
+ {0xF91D, UNICODE_NORM_QC_NO},
+ {0xF91E, UNICODE_NORM_QC_NO},
+ {0xF91F, UNICODE_NORM_QC_NO},
+ {0xF920, UNICODE_NORM_QC_NO},
+ {0xF921, UNICODE_NORM_QC_NO},
+ {0xF922, UNICODE_NORM_QC_NO},
+ {0xF923, UNICODE_NORM_QC_NO},
+ {0xF924, UNICODE_NORM_QC_NO},
+ {0xF925, UNICODE_NORM_QC_NO},
+ {0xF926, UNICODE_NORM_QC_NO},
+ {0xF927, UNICODE_NORM_QC_NO},
+ {0xF928, UNICODE_NORM_QC_NO},
+ {0xF929, UNICODE_NORM_QC_NO},
+ {0xF92A, UNICODE_NORM_QC_NO},
+ {0xF92B, UNICODE_NORM_QC_NO},
+ {0xF92C, UNICODE_NORM_QC_NO},
+ {0xF92D, UNICODE_NORM_QC_NO},
+ {0xF92E, UNICODE_NORM_QC_NO},
+ {0xF92F, UNICODE_NORM_QC_NO},
+ {0xF930, UNICODE_NORM_QC_NO},
+ {0xF931, UNICODE_NORM_QC_NO},
+ {0xF932, UNICODE_NORM_QC_NO},
+ {0xF933, UNICODE_NORM_QC_NO},
+ {0xF934, UNICODE_NORM_QC_NO},
+ {0xF935, UNICODE_NORM_QC_NO},
+ {0xF936, UNICODE_NORM_QC_NO},
+ {0xF937, UNICODE_NORM_QC_NO},
+ {0xF938, UNICODE_NORM_QC_NO},
+ {0xF939, UNICODE_NORM_QC_NO},
+ {0xF93A, UNICODE_NORM_QC_NO},
+ {0xF93B, UNICODE_NORM_QC_NO},
+ {0xF93C, UNICODE_NORM_QC_NO},
+ {0xF93D, UNICODE_NORM_QC_NO},
+ {0xF93E, UNICODE_NORM_QC_NO},
+ {0xF93F, UNICODE_NORM_QC_NO},
+ {0xF940, UNICODE_NORM_QC_NO},
+ {0xF941, UNICODE_NORM_QC_NO},
+ {0xF942, UNICODE_NORM_QC_NO},
+ {0xF943, UNICODE_NORM_QC_NO},
+ {0xF944, UNICODE_NORM_QC_NO},
+ {0xF945, UNICODE_NORM_QC_NO},
+ {0xF946, UNICODE_NORM_QC_NO},
+ {0xF947, UNICODE_NORM_QC_NO},
+ {0xF948, UNICODE_NORM_QC_NO},
+ {0xF949, UNICODE_NORM_QC_NO},
+ {0xF94A, UNICODE_NORM_QC_NO},
+ {0xF94B, UNICODE_NORM_QC_NO},
+ {0xF94C, UNICODE_NORM_QC_NO},
+ {0xF94D, UNICODE_NORM_QC_NO},
+ {0xF94E, UNICODE_NORM_QC_NO},
+ {0xF94F, UNICODE_NORM_QC_NO},
+ {0xF950, UNICODE_NORM_QC_NO},
+ {0xF951, UNICODE_NORM_QC_NO},
+ {0xF952, UNICODE_NORM_QC_NO},
+ {0xF953, UNICODE_NORM_QC_NO},
+ {0xF954, UNICODE_NORM_QC_NO},
+ {0xF955, UNICODE_NORM_QC_NO},
+ {0xF956, UNICODE_NORM_QC_NO},
+ {0xF957, UNICODE_NORM_QC_NO},
+ {0xF958, UNICODE_NORM_QC_NO},
+ {0xF959, UNICODE_NORM_QC_NO},
+ {0xF95A, UNICODE_NORM_QC_NO},
+ {0xF95B, UNICODE_NORM_QC_NO},
+ {0xF95C, UNICODE_NORM_QC_NO},
+ {0xF95D, UNICODE_NORM_QC_NO},
+ {0xF95E, UNICODE_NORM_QC_NO},
+ {0xF95F, UNICODE_NORM_QC_NO},
+ {0xF960, UNICODE_NORM_QC_NO},
+ {0xF961, UNICODE_NORM_QC_NO},
+ {0xF962, UNICODE_NORM_QC_NO},
+ {0xF963, UNICODE_NORM_QC_NO},
+ {0xF964, UNICODE_NORM_QC_NO},
+ {0xF965, UNICODE_NORM_QC_NO},
+ {0xF966, UNICODE_NORM_QC_NO},
+ {0xF967, UNICODE_NORM_QC_NO},
+ {0xF968, UNICODE_NORM_QC_NO},
+ {0xF969, UNICODE_NORM_QC_NO},
+ {0xF96A, UNICODE_NORM_QC_NO},
+ {0xF96B, UNICODE_NORM_QC_NO},
+ {0xF96C, UNICODE_NORM_QC_NO},
+ {0xF96D, UNICODE_NORM_QC_NO},
+ {0xF96E, UNICODE_NORM_QC_NO},
+ {0xF96F, UNICODE_NORM_QC_NO},
+ {0xF970, UNICODE_NORM_QC_NO},
+ {0xF971, UNICODE_NORM_QC_NO},
+ {0xF972, UNICODE_NORM_QC_NO},
+ {0xF973, UNICODE_NORM_QC_NO},
+ {0xF974, UNICODE_NORM_QC_NO},
+ {0xF975, UNICODE_NORM_QC_NO},
+ {0xF976, UNICODE_NORM_QC_NO},
+ {0xF977, UNICODE_NORM_QC_NO},
+ {0xF978, UNICODE_NORM_QC_NO},
+ {0xF979, UNICODE_NORM_QC_NO},
+ {0xF97A, UNICODE_NORM_QC_NO},
+ {0xF97B, UNICODE_NORM_QC_NO},
+ {0xF97C, UNICODE_NORM_QC_NO},
+ {0xF97D, UNICODE_NORM_QC_NO},
+ {0xF97E, UNICODE_NORM_QC_NO},
+ {0xF97F, UNICODE_NORM_QC_NO},
+ {0xF980, UNICODE_NORM_QC_NO},
+ {0xF981, UNICODE_NORM_QC_NO},
+ {0xF982, UNICODE_NORM_QC_NO},
+ {0xF983, UNICODE_NORM_QC_NO},
+ {0xF984, UNICODE_NORM_QC_NO},
+ {0xF985, UNICODE_NORM_QC_NO},
+ {0xF986, UNICODE_NORM_QC_NO},
+ {0xF987, UNICODE_NORM_QC_NO},
+ {0xF988, UNICODE_NORM_QC_NO},
+ {0xF989, UNICODE_NORM_QC_NO},
+ {0xF98A, UNICODE_NORM_QC_NO},
+ {0xF98B, UNICODE_NORM_QC_NO},
+ {0xF98C, UNICODE_NORM_QC_NO},
+ {0xF98D, UNICODE_NORM_QC_NO},
+ {0xF98E, UNICODE_NORM_QC_NO},
+ {0xF98F, UNICODE_NORM_QC_NO},
+ {0xF990, UNICODE_NORM_QC_NO},
+ {0xF991, UNICODE_NORM_QC_NO},
+ {0xF992, UNICODE_NORM_QC_NO},
+ {0xF993, UNICODE_NORM_QC_NO},
+ {0xF994, UNICODE_NORM_QC_NO},
+ {0xF995, UNICODE_NORM_QC_NO},
+ {0xF996, UNICODE_NORM_QC_NO},
+ {0xF997, UNICODE_NORM_QC_NO},
+ {0xF998, UNICODE_NORM_QC_NO},
+ {0xF999, UNICODE_NORM_QC_NO},
+ {0xF99A, UNICODE_NORM_QC_NO},
+ {0xF99B, UNICODE_NORM_QC_NO},
+ {0xF99C, UNICODE_NORM_QC_NO},
+ {0xF99D, UNICODE_NORM_QC_NO},
+ {0xF99E, UNICODE_NORM_QC_NO},
+ {0xF99F, UNICODE_NORM_QC_NO},
+ {0xF9A0, UNICODE_NORM_QC_NO},
+ {0xF9A1, UNICODE_NORM_QC_NO},
+ {0xF9A2, UNICODE_NORM_QC_NO},
+ {0xF9A3, UNICODE_NORM_QC_NO},
+ {0xF9A4, UNICODE_NORM_QC_NO},
+ {0xF9A5, UNICODE_NORM_QC_NO},
+ {0xF9A6, UNICODE_NORM_QC_NO},
+ {0xF9A7, UNICODE_NORM_QC_NO},
+ {0xF9A8, UNICODE_NORM_QC_NO},
+ {0xF9A9, UNICODE_NORM_QC_NO},
+ {0xF9AA, UNICODE_NORM_QC_NO},
+ {0xF9AB, UNICODE_NORM_QC_NO},
+ {0xF9AC, UNICODE_NORM_QC_NO},
+ {0xF9AD, UNICODE_NORM_QC_NO},
+ {0xF9AE, UNICODE_NORM_QC_NO},
+ {0xF9AF, UNICODE_NORM_QC_NO},
+ {0xF9B0, UNICODE_NORM_QC_NO},
+ {0xF9B1, UNICODE_NORM_QC_NO},
+ {0xF9B2, UNICODE_NORM_QC_NO},
+ {0xF9B3, UNICODE_NORM_QC_NO},
+ {0xF9B4, UNICODE_NORM_QC_NO},
+ {0xF9B5, UNICODE_NORM_QC_NO},
+ {0xF9B6, UNICODE_NORM_QC_NO},
+ {0xF9B7, UNICODE_NORM_QC_NO},
+ {0xF9B8, UNICODE_NORM_QC_NO},
+ {0xF9B9, UNICODE_NORM_QC_NO},
+ {0xF9BA, UNICODE_NORM_QC_NO},
+ {0xF9BB, UNICODE_NORM_QC_NO},
+ {0xF9BC, UNICODE_NORM_QC_NO},
+ {0xF9BD, UNICODE_NORM_QC_NO},
+ {0xF9BE, UNICODE_NORM_QC_NO},
+ {0xF9BF, UNICODE_NORM_QC_NO},
+ {0xF9C0, UNICODE_NORM_QC_NO},
+ {0xF9C1, UNICODE_NORM_QC_NO},
+ {0xF9C2, UNICODE_NORM_QC_NO},
+ {0xF9C3, UNICODE_NORM_QC_NO},
+ {0xF9C4, UNICODE_NORM_QC_NO},
+ {0xF9C5, UNICODE_NORM_QC_NO},
+ {0xF9C6, UNICODE_NORM_QC_NO},
+ {0xF9C7, UNICODE_NORM_QC_NO},
+ {0xF9C8, UNICODE_NORM_QC_NO},
+ {0xF9C9, UNICODE_NORM_QC_NO},
+ {0xF9CA, UNICODE_NORM_QC_NO},
+ {0xF9CB, UNICODE_NORM_QC_NO},
+ {0xF9CC, UNICODE_NORM_QC_NO},
+ {0xF9CD, UNICODE_NORM_QC_NO},
+ {0xF9CE, UNICODE_NORM_QC_NO},
+ {0xF9CF, UNICODE_NORM_QC_NO},
+ {0xF9D0, UNICODE_NORM_QC_NO},
+ {0xF9D1, UNICODE_NORM_QC_NO},
+ {0xF9D2, UNICODE_NORM_QC_NO},
+ {0xF9D3, UNICODE_NORM_QC_NO},
+ {0xF9D4, UNICODE_NORM_QC_NO},
+ {0xF9D5, UNICODE_NORM_QC_NO},
+ {0xF9D6, UNICODE_NORM_QC_NO},
+ {0xF9D7, UNICODE_NORM_QC_NO},
+ {0xF9D8, UNICODE_NORM_QC_NO},
+ {0xF9D9, UNICODE_NORM_QC_NO},
+ {0xF9DA, UNICODE_NORM_QC_NO},
+ {0xF9DB, UNICODE_NORM_QC_NO},
+ {0xF9DC, UNICODE_NORM_QC_NO},
+ {0xF9DD, UNICODE_NORM_QC_NO},
+ {0xF9DE, UNICODE_NORM_QC_NO},
+ {0xF9DF, UNICODE_NORM_QC_NO},
+ {0xF9E0, UNICODE_NORM_QC_NO},
+ {0xF9E1, UNICODE_NORM_QC_NO},
+ {0xF9E2, UNICODE_NORM_QC_NO},
+ {0xF9E3, UNICODE_NORM_QC_NO},
+ {0xF9E4, UNICODE_NORM_QC_NO},
+ {0xF9E5, UNICODE_NORM_QC_NO},
+ {0xF9E6, UNICODE_NORM_QC_NO},
+ {0xF9E7, UNICODE_NORM_QC_NO},
+ {0xF9E8, UNICODE_NORM_QC_NO},
+ {0xF9E9, UNICODE_NORM_QC_NO},
+ {0xF9EA, UNICODE_NORM_QC_NO},
+ {0xF9EB, UNICODE_NORM_QC_NO},
+ {0xF9EC, UNICODE_NORM_QC_NO},
+ {0xF9ED, UNICODE_NORM_QC_NO},
+ {0xF9EE, UNICODE_NORM_QC_NO},
+ {0xF9EF, UNICODE_NORM_QC_NO},
+ {0xF9F0, UNICODE_NORM_QC_NO},
+ {0xF9F1, UNICODE_NORM_QC_NO},
+ {0xF9F2, UNICODE_NORM_QC_NO},
+ {0xF9F3, UNICODE_NORM_QC_NO},
+ {0xF9F4, UNICODE_NORM_QC_NO},
+ {0xF9F5, UNICODE_NORM_QC_NO},
+ {0xF9F6, UNICODE_NORM_QC_NO},
+ {0xF9F7, UNICODE_NORM_QC_NO},
+ {0xF9F8, UNICODE_NORM_QC_NO},
+ {0xF9F9, UNICODE_NORM_QC_NO},
+ {0xF9FA, UNICODE_NORM_QC_NO},
+ {0xF9FB, UNICODE_NORM_QC_NO},
+ {0xF9FC, UNICODE_NORM_QC_NO},
+ {0xF9FD, UNICODE_NORM_QC_NO},
+ {0xF9FE, UNICODE_NORM_QC_NO},
+ {0xF9FF, UNICODE_NORM_QC_NO},
+ {0xFA00, UNICODE_NORM_QC_NO},
+ {0xFA01, UNICODE_NORM_QC_NO},
+ {0xFA02, UNICODE_NORM_QC_NO},
+ {0xFA03, UNICODE_NORM_QC_NO},
+ {0xFA04, UNICODE_NORM_QC_NO},
+ {0xFA05, UNICODE_NORM_QC_NO},
+ {0xFA06, UNICODE_NORM_QC_NO},
+ {0xFA07, UNICODE_NORM_QC_NO},
+ {0xFA08, UNICODE_NORM_QC_NO},
+ {0xFA09, UNICODE_NORM_QC_NO},
+ {0xFA0A, UNICODE_NORM_QC_NO},
+ {0xFA0B, UNICODE_NORM_QC_NO},
+ {0xFA0C, UNICODE_NORM_QC_NO},
+ {0xFA0D, UNICODE_NORM_QC_NO},
+ {0xFA10, UNICODE_NORM_QC_NO},
+ {0xFA12, UNICODE_NORM_QC_NO},
+ {0xFA15, UNICODE_NORM_QC_NO},
+ {0xFA16, UNICODE_NORM_QC_NO},
+ {0xFA17, UNICODE_NORM_QC_NO},
+ {0xFA18, UNICODE_NORM_QC_NO},
+ {0xFA19, UNICODE_NORM_QC_NO},
+ {0xFA1A, UNICODE_NORM_QC_NO},
+ {0xFA1B, UNICODE_NORM_QC_NO},
+ {0xFA1C, UNICODE_NORM_QC_NO},
+ {0xFA1D, UNICODE_NORM_QC_NO},
+ {0xFA1E, UNICODE_NORM_QC_NO},
+ {0xFA20, UNICODE_NORM_QC_NO},
+ {0xFA22, UNICODE_NORM_QC_NO},
+ {0xFA25, UNICODE_NORM_QC_NO},
+ {0xFA26, UNICODE_NORM_QC_NO},
+ {0xFA2A, UNICODE_NORM_QC_NO},
+ {0xFA2B, UNICODE_NORM_QC_NO},
+ {0xFA2C, UNICODE_NORM_QC_NO},
+ {0xFA2D, UNICODE_NORM_QC_NO},
+ {0xFA2E, UNICODE_NORM_QC_NO},
+ {0xFA2F, UNICODE_NORM_QC_NO},
+ {0xFA30, UNICODE_NORM_QC_NO},
+ {0xFA31, UNICODE_NORM_QC_NO},
+ {0xFA32, UNICODE_NORM_QC_NO},
+ {0xFA33, UNICODE_NORM_QC_NO},
+ {0xFA34, UNICODE_NORM_QC_NO},
+ {0xFA35, UNICODE_NORM_QC_NO},
+ {0xFA36, UNICODE_NORM_QC_NO},
+ {0xFA37, UNICODE_NORM_QC_NO},
+ {0xFA38, UNICODE_NORM_QC_NO},
+ {0xFA39, UNICODE_NORM_QC_NO},
+ {0xFA3A, UNICODE_NORM_QC_NO},
+ {0xFA3B, UNICODE_NORM_QC_NO},
+ {0xFA3C, UNICODE_NORM_QC_NO},
+ {0xFA3D, UNICODE_NORM_QC_NO},
+ {0xFA3E, UNICODE_NORM_QC_NO},
+ {0xFA3F, UNICODE_NORM_QC_NO},
+ {0xFA40, UNICODE_NORM_QC_NO},
+ {0xFA41, UNICODE_NORM_QC_NO},
+ {0xFA42, UNICODE_NORM_QC_NO},
+ {0xFA43, UNICODE_NORM_QC_NO},
+ {0xFA44, UNICODE_NORM_QC_NO},
+ {0xFA45, UNICODE_NORM_QC_NO},
+ {0xFA46, UNICODE_NORM_QC_NO},
+ {0xFA47, UNICODE_NORM_QC_NO},
+ {0xFA48, UNICODE_NORM_QC_NO},
+ {0xFA49, UNICODE_NORM_QC_NO},
+ {0xFA4A, UNICODE_NORM_QC_NO},
+ {0xFA4B, UNICODE_NORM_QC_NO},
+ {0xFA4C, UNICODE_NORM_QC_NO},
+ {0xFA4D, UNICODE_NORM_QC_NO},
+ {0xFA4E, UNICODE_NORM_QC_NO},
+ {0xFA4F, UNICODE_NORM_QC_NO},
+ {0xFA50, UNICODE_NORM_QC_NO},
+ {0xFA51, UNICODE_NORM_QC_NO},
+ {0xFA52, UNICODE_NORM_QC_NO},
+ {0xFA53, UNICODE_NORM_QC_NO},
+ {0xFA54, UNICODE_NORM_QC_NO},
+ {0xFA55, UNICODE_NORM_QC_NO},
+ {0xFA56, UNICODE_NORM_QC_NO},
+ {0xFA57, UNICODE_NORM_QC_NO},
+ {0xFA58, UNICODE_NORM_QC_NO},
+ {0xFA59, UNICODE_NORM_QC_NO},
+ {0xFA5A, UNICODE_NORM_QC_NO},
+ {0xFA5B, UNICODE_NORM_QC_NO},
+ {0xFA5C, UNICODE_NORM_QC_NO},
+ {0xFA5D, UNICODE_NORM_QC_NO},
+ {0xFA5E, UNICODE_NORM_QC_NO},
+ {0xFA5F, UNICODE_NORM_QC_NO},
+ {0xFA60, UNICODE_NORM_QC_NO},
+ {0xFA61, UNICODE_NORM_QC_NO},
+ {0xFA62, UNICODE_NORM_QC_NO},
+ {0xFA63, UNICODE_NORM_QC_NO},
+ {0xFA64, UNICODE_NORM_QC_NO},
+ {0xFA65, UNICODE_NORM_QC_NO},
+ {0xFA66, UNICODE_NORM_QC_NO},
+ {0xFA67, UNICODE_NORM_QC_NO},
+ {0xFA68, UNICODE_NORM_QC_NO},
+ {0xFA69, UNICODE_NORM_QC_NO},
+ {0xFA6A, UNICODE_NORM_QC_NO},
+ {0xFA6B, UNICODE_NORM_QC_NO},
+ {0xFA6C, UNICODE_NORM_QC_NO},
+ {0xFA6D, UNICODE_NORM_QC_NO},
+ {0xFA70, UNICODE_NORM_QC_NO},
+ {0xFA71, UNICODE_NORM_QC_NO},
+ {0xFA72, UNICODE_NORM_QC_NO},
+ {0xFA73, UNICODE_NORM_QC_NO},
+ {0xFA74, UNICODE_NORM_QC_NO},
+ {0xFA75, UNICODE_NORM_QC_NO},
+ {0xFA76, UNICODE_NORM_QC_NO},
+ {0xFA77, UNICODE_NORM_QC_NO},
+ {0xFA78, UNICODE_NORM_QC_NO},
+ {0xFA79, UNICODE_NORM_QC_NO},
+ {0xFA7A, UNICODE_NORM_QC_NO},
+ {0xFA7B, UNICODE_NORM_QC_NO},
+ {0xFA7C, UNICODE_NORM_QC_NO},
+ {0xFA7D, UNICODE_NORM_QC_NO},
+ {0xFA7E, UNICODE_NORM_QC_NO},
+ {0xFA7F, UNICODE_NORM_QC_NO},
+ {0xFA80, UNICODE_NORM_QC_NO},
+ {0xFA81, UNICODE_NORM_QC_NO},
+ {0xFA82, UNICODE_NORM_QC_NO},
+ {0xFA83, UNICODE_NORM_QC_NO},
+ {0xFA84, UNICODE_NORM_QC_NO},
+ {0xFA85, UNICODE_NORM_QC_NO},
+ {0xFA86, UNICODE_NORM_QC_NO},
+ {0xFA87, UNICODE_NORM_QC_NO},
+ {0xFA88, UNICODE_NORM_QC_NO},
+ {0xFA89, UNICODE_NORM_QC_NO},
+ {0xFA8A, UNICODE_NORM_QC_NO},
+ {0xFA8B, UNICODE_NORM_QC_NO},
+ {0xFA8C, UNICODE_NORM_QC_NO},
+ {0xFA8D, UNICODE_NORM_QC_NO},
+ {0xFA8E, UNICODE_NORM_QC_NO},
+ {0xFA8F, UNICODE_NORM_QC_NO},
+ {0xFA90, UNICODE_NORM_QC_NO},
+ {0xFA91, UNICODE_NORM_QC_NO},
+ {0xFA92, UNICODE_NORM_QC_NO},
+ {0xFA93, UNICODE_NORM_QC_NO},
+ {0xFA94, UNICODE_NORM_QC_NO},
+ {0xFA95, UNICODE_NORM_QC_NO},
+ {0xFA96, UNICODE_NORM_QC_NO},
+ {0xFA97, UNICODE_NORM_QC_NO},
+ {0xFA98, UNICODE_NORM_QC_NO},
+ {0xFA99, UNICODE_NORM_QC_NO},
+ {0xFA9A, UNICODE_NORM_QC_NO},
+ {0xFA9B, UNICODE_NORM_QC_NO},
+ {0xFA9C, UNICODE_NORM_QC_NO},
+ {0xFA9D, UNICODE_NORM_QC_NO},
+ {0xFA9E, UNICODE_NORM_QC_NO},
+ {0xFA9F, UNICODE_NORM_QC_NO},
+ {0xFAA0, UNICODE_NORM_QC_NO},
+ {0xFAA1, UNICODE_NORM_QC_NO},
+ {0xFAA2, UNICODE_NORM_QC_NO},
+ {0xFAA3, UNICODE_NORM_QC_NO},
+ {0xFAA4, UNICODE_NORM_QC_NO},
+ {0xFAA5, UNICODE_NORM_QC_NO},
+ {0xFAA6, UNICODE_NORM_QC_NO},
+ {0xFAA7, UNICODE_NORM_QC_NO},
+ {0xFAA8, UNICODE_NORM_QC_NO},
+ {0xFAA9, UNICODE_NORM_QC_NO},
+ {0xFAAA, UNICODE_NORM_QC_NO},
+ {0xFAAB, UNICODE_NORM_QC_NO},
+ {0xFAAC, UNICODE_NORM_QC_NO},
+ {0xFAAD, UNICODE_NORM_QC_NO},
+ {0xFAAE, UNICODE_NORM_QC_NO},
+ {0xFAAF, UNICODE_NORM_QC_NO},
+ {0xFAB0, UNICODE_NORM_QC_NO},
+ {0xFAB1, UNICODE_NORM_QC_NO},
+ {0xFAB2, UNICODE_NORM_QC_NO},
+ {0xFAB3, UNICODE_NORM_QC_NO},
+ {0xFAB4, UNICODE_NORM_QC_NO},
+ {0xFAB5, UNICODE_NORM_QC_NO},
+ {0xFAB6, UNICODE_NORM_QC_NO},
+ {0xFAB7, UNICODE_NORM_QC_NO},
+ {0xFAB8, UNICODE_NORM_QC_NO},
+ {0xFAB9, UNICODE_NORM_QC_NO},
+ {0xFABA, UNICODE_NORM_QC_NO},
+ {0xFABB, UNICODE_NORM_QC_NO},
+ {0xFABC, UNICODE_NORM_QC_NO},
+ {0xFABD, UNICODE_NORM_QC_NO},
+ {0xFABE, UNICODE_NORM_QC_NO},
+ {0xFABF, UNICODE_NORM_QC_NO},
+ {0xFAC0, UNICODE_NORM_QC_NO},
+ {0xFAC1, UNICODE_NORM_QC_NO},
+ {0xFAC2, UNICODE_NORM_QC_NO},
+ {0xFAC3, UNICODE_NORM_QC_NO},
+ {0xFAC4, UNICODE_NORM_QC_NO},
+ {0xFAC5, UNICODE_NORM_QC_NO},
+ {0xFAC6, UNICODE_NORM_QC_NO},
+ {0xFAC7, UNICODE_NORM_QC_NO},
+ {0xFAC8, UNICODE_NORM_QC_NO},
+ {0xFAC9, UNICODE_NORM_QC_NO},
+ {0xFACA, UNICODE_NORM_QC_NO},
+ {0xFACB, UNICODE_NORM_QC_NO},
+ {0xFACC, UNICODE_NORM_QC_NO},
+ {0xFACD, UNICODE_NORM_QC_NO},
+ {0xFACE, UNICODE_NORM_QC_NO},
+ {0xFACF, UNICODE_NORM_QC_NO},
+ {0xFAD0, UNICODE_NORM_QC_NO},
+ {0xFAD1, UNICODE_NORM_QC_NO},
+ {0xFAD2, UNICODE_NORM_QC_NO},
+ {0xFAD3, UNICODE_NORM_QC_NO},
+ {0xFAD4, UNICODE_NORM_QC_NO},
+ {0xFAD5, UNICODE_NORM_QC_NO},
+ {0xFAD6, UNICODE_NORM_QC_NO},
+ {0xFAD7, UNICODE_NORM_QC_NO},
+ {0xFAD8, UNICODE_NORM_QC_NO},
+ {0xFAD9, UNICODE_NORM_QC_NO},
+ {0xFB1D, UNICODE_NORM_QC_NO},
+ {0xFB1F, UNICODE_NORM_QC_NO},
+ {0xFB2A, UNICODE_NORM_QC_NO},
+ {0xFB2B, UNICODE_NORM_QC_NO},
+ {0xFB2C, UNICODE_NORM_QC_NO},
+ {0xFB2D, UNICODE_NORM_QC_NO},
+ {0xFB2E, UNICODE_NORM_QC_NO},
+ {0xFB2F, UNICODE_NORM_QC_NO},
+ {0xFB30, UNICODE_NORM_QC_NO},
+ {0xFB31, UNICODE_NORM_QC_NO},
+ {0xFB32, UNICODE_NORM_QC_NO},
+ {0xFB33, UNICODE_NORM_QC_NO},
+ {0xFB34, UNICODE_NORM_QC_NO},
+ {0xFB35, UNICODE_NORM_QC_NO},
+ {0xFB36, UNICODE_NORM_QC_NO},
+ {0xFB38, UNICODE_NORM_QC_NO},
+ {0xFB39, UNICODE_NORM_QC_NO},
+ {0xFB3A, UNICODE_NORM_QC_NO},
+ {0xFB3B, UNICODE_NORM_QC_NO},
+ {0xFB3C, UNICODE_NORM_QC_NO},
+ {0xFB3E, UNICODE_NORM_QC_NO},
+ {0xFB40, UNICODE_NORM_QC_NO},
+ {0xFB41, UNICODE_NORM_QC_NO},
+ {0xFB43, UNICODE_NORM_QC_NO},
+ {0xFB44, UNICODE_NORM_QC_NO},
+ {0xFB46, UNICODE_NORM_QC_NO},
+ {0xFB47, UNICODE_NORM_QC_NO},
+ {0xFB48, UNICODE_NORM_QC_NO},
+ {0xFB49, UNICODE_NORM_QC_NO},
+ {0xFB4A, UNICODE_NORM_QC_NO},
+ {0xFB4B, UNICODE_NORM_QC_NO},
+ {0xFB4C, UNICODE_NORM_QC_NO},
+ {0xFB4D, UNICODE_NORM_QC_NO},
+ {0xFB4E, UNICODE_NORM_QC_NO},
+ {0x110BA, UNICODE_NORM_QC_MAYBE},
+ {0x11127, UNICODE_NORM_QC_MAYBE},
+ {0x1133E, UNICODE_NORM_QC_MAYBE},
+ {0x11357, UNICODE_NORM_QC_MAYBE},
+ {0x114B0, UNICODE_NORM_QC_MAYBE},
+ {0x114BA, UNICODE_NORM_QC_MAYBE},
+ {0x114BD, UNICODE_NORM_QC_MAYBE},
+ {0x115AF, UNICODE_NORM_QC_MAYBE},
+ {0x11930, UNICODE_NORM_QC_MAYBE},
+ {0x1D15E, UNICODE_NORM_QC_NO},
+ {0x1D15F, UNICODE_NORM_QC_NO},
+ {0x1D160, UNICODE_NORM_QC_NO},
+ {0x1D161, UNICODE_NORM_QC_NO},
+ {0x1D162, UNICODE_NORM_QC_NO},
+ {0x1D163, UNICODE_NORM_QC_NO},
+ {0x1D164, UNICODE_NORM_QC_NO},
+ {0x1D1BB, UNICODE_NORM_QC_NO},
+ {0x1D1BC, UNICODE_NORM_QC_NO},
+ {0x1D1BD, UNICODE_NORM_QC_NO},
+ {0x1D1BE, UNICODE_NORM_QC_NO},
+ {0x1D1BF, UNICODE_NORM_QC_NO},
+ {0x1D1C0, UNICODE_NORM_QC_NO},
+ {0x2F800, UNICODE_NORM_QC_NO},
+ {0x2F801, UNICODE_NORM_QC_NO},
+ {0x2F802, UNICODE_NORM_QC_NO},
+ {0x2F803, UNICODE_NORM_QC_NO},
+ {0x2F804, UNICODE_NORM_QC_NO},
+ {0x2F805, UNICODE_NORM_QC_NO},
+ {0x2F806, UNICODE_NORM_QC_NO},
+ {0x2F807, UNICODE_NORM_QC_NO},
+ {0x2F808, UNICODE_NORM_QC_NO},
+ {0x2F809, UNICODE_NORM_QC_NO},
+ {0x2F80A, UNICODE_NORM_QC_NO},
+ {0x2F80B, UNICODE_NORM_QC_NO},
+ {0x2F80C, UNICODE_NORM_QC_NO},
+ {0x2F80D, UNICODE_NORM_QC_NO},
+ {0x2F80E, UNICODE_NORM_QC_NO},
+ {0x2F80F, UNICODE_NORM_QC_NO},
+ {0x2F810, UNICODE_NORM_QC_NO},
+ {0x2F811, UNICODE_NORM_QC_NO},
+ {0x2F812, UNICODE_NORM_QC_NO},
+ {0x2F813, UNICODE_NORM_QC_NO},
+ {0x2F814, UNICODE_NORM_QC_NO},
+ {0x2F815, UNICODE_NORM_QC_NO},
+ {0x2F816, UNICODE_NORM_QC_NO},
+ {0x2F817, UNICODE_NORM_QC_NO},
+ {0x2F818, UNICODE_NORM_QC_NO},
+ {0x2F819, UNICODE_NORM_QC_NO},
+ {0x2F81A, UNICODE_NORM_QC_NO},
+ {0x2F81B, UNICODE_NORM_QC_NO},
+ {0x2F81C, UNICODE_NORM_QC_NO},
+ {0x2F81D, UNICODE_NORM_QC_NO},
+ {0x2F81E, UNICODE_NORM_QC_NO},
+ {0x2F81F, UNICODE_NORM_QC_NO},
+ {0x2F820, UNICODE_NORM_QC_NO},
+ {0x2F821, UNICODE_NORM_QC_NO},
+ {0x2F822, UNICODE_NORM_QC_NO},
+ {0x2F823, UNICODE_NORM_QC_NO},
+ {0x2F824, UNICODE_NORM_QC_NO},
+ {0x2F825, UNICODE_NORM_QC_NO},
+ {0x2F826, UNICODE_NORM_QC_NO},
+ {0x2F827, UNICODE_NORM_QC_NO},
+ {0x2F828, UNICODE_NORM_QC_NO},
+ {0x2F829, UNICODE_NORM_QC_NO},
+ {0x2F82A, UNICODE_NORM_QC_NO},
+ {0x2F82B, UNICODE_NORM_QC_NO},
+ {0x2F82C, UNICODE_NORM_QC_NO},
+ {0x2F82D, UNICODE_NORM_QC_NO},
+ {0x2F82E, UNICODE_NORM_QC_NO},
+ {0x2F82F, UNICODE_NORM_QC_NO},
+ {0x2F830, UNICODE_NORM_QC_NO},
+ {0x2F831, UNICODE_NORM_QC_NO},
+ {0x2F832, UNICODE_NORM_QC_NO},
+ {0x2F833, UNICODE_NORM_QC_NO},
+ {0x2F834, UNICODE_NORM_QC_NO},
+ {0x2F835, UNICODE_NORM_QC_NO},
+ {0x2F836, UNICODE_NORM_QC_NO},
+ {0x2F837, UNICODE_NORM_QC_NO},
+ {0x2F838, UNICODE_NORM_QC_NO},
+ {0x2F839, UNICODE_NORM_QC_NO},
+ {0x2F83A, UNICODE_NORM_QC_NO},
+ {0x2F83B, UNICODE_NORM_QC_NO},
+ {0x2F83C, UNICODE_NORM_QC_NO},
+ {0x2F83D, UNICODE_NORM_QC_NO},
+ {0x2F83E, UNICODE_NORM_QC_NO},
+ {0x2F83F, UNICODE_NORM_QC_NO},
+ {0x2F840, UNICODE_NORM_QC_NO},
+ {0x2F841, UNICODE_NORM_QC_NO},
+ {0x2F842, UNICODE_NORM_QC_NO},
+ {0x2F843, UNICODE_NORM_QC_NO},
+ {0x2F844, UNICODE_NORM_QC_NO},
+ {0x2F845, UNICODE_NORM_QC_NO},
+ {0x2F846, UNICODE_NORM_QC_NO},
+ {0x2F847, UNICODE_NORM_QC_NO},
+ {0x2F848, UNICODE_NORM_QC_NO},
+ {0x2F849, UNICODE_NORM_QC_NO},
+ {0x2F84A, UNICODE_NORM_QC_NO},
+ {0x2F84B, UNICODE_NORM_QC_NO},
+ {0x2F84C, UNICODE_NORM_QC_NO},
+ {0x2F84D, UNICODE_NORM_QC_NO},
+ {0x2F84E, UNICODE_NORM_QC_NO},
+ {0x2F84F, UNICODE_NORM_QC_NO},
+ {0x2F850, UNICODE_NORM_QC_NO},
+ {0x2F851, UNICODE_NORM_QC_NO},
+ {0x2F852, UNICODE_NORM_QC_NO},
+ {0x2F853, UNICODE_NORM_QC_NO},
+ {0x2F854, UNICODE_NORM_QC_NO},
+ {0x2F855, UNICODE_NORM_QC_NO},
+ {0x2F856, UNICODE_NORM_QC_NO},
+ {0x2F857, UNICODE_NORM_QC_NO},
+ {0x2F858, UNICODE_NORM_QC_NO},
+ {0x2F859, UNICODE_NORM_QC_NO},
+ {0x2F85A, UNICODE_NORM_QC_NO},
+ {0x2F85B, UNICODE_NORM_QC_NO},
+ {0x2F85C, UNICODE_NORM_QC_NO},
+ {0x2F85D, UNICODE_NORM_QC_NO},
+ {0x2F85E, UNICODE_NORM_QC_NO},
+ {0x2F85F, UNICODE_NORM_QC_NO},
+ {0x2F860, UNICODE_NORM_QC_NO},
+ {0x2F861, UNICODE_NORM_QC_NO},
+ {0x2F862, UNICODE_NORM_QC_NO},
+ {0x2F863, UNICODE_NORM_QC_NO},
+ {0x2F864, UNICODE_NORM_QC_NO},
+ {0x2F865, UNICODE_NORM_QC_NO},
+ {0x2F866, UNICODE_NORM_QC_NO},
+ {0x2F867, UNICODE_NORM_QC_NO},
+ {0x2F868, UNICODE_NORM_QC_NO},
+ {0x2F869, UNICODE_NORM_QC_NO},
+ {0x2F86A, UNICODE_NORM_QC_NO},
+ {0x2F86B, UNICODE_NORM_QC_NO},
+ {0x2F86C, UNICODE_NORM_QC_NO},
+ {0x2F86D, UNICODE_NORM_QC_NO},
+ {0x2F86E, UNICODE_NORM_QC_NO},
+ {0x2F86F, UNICODE_NORM_QC_NO},
+ {0x2F870, UNICODE_NORM_QC_NO},
+ {0x2F871, UNICODE_NORM_QC_NO},
+ {0x2F872, UNICODE_NORM_QC_NO},
+ {0x2F873, UNICODE_NORM_QC_NO},
+ {0x2F874, UNICODE_NORM_QC_NO},
+ {0x2F875, UNICODE_NORM_QC_NO},
+ {0x2F876, UNICODE_NORM_QC_NO},
+ {0x2F877, UNICODE_NORM_QC_NO},
+ {0x2F878, UNICODE_NORM_QC_NO},
+ {0x2F879, UNICODE_NORM_QC_NO},
+ {0x2F87A, UNICODE_NORM_QC_NO},
+ {0x2F87B, UNICODE_NORM_QC_NO},
+ {0x2F87C, UNICODE_NORM_QC_NO},
+ {0x2F87D, UNICODE_NORM_QC_NO},
+ {0x2F87E, UNICODE_NORM_QC_NO},
+ {0x2F87F, UNICODE_NORM_QC_NO},
+ {0x2F880, UNICODE_NORM_QC_NO},
+ {0x2F881, UNICODE_NORM_QC_NO},
+ {0x2F882, UNICODE_NORM_QC_NO},
+ {0x2F883, UNICODE_NORM_QC_NO},
+ {0x2F884, UNICODE_NORM_QC_NO},
+ {0x2F885, UNICODE_NORM_QC_NO},
+ {0x2F886, UNICODE_NORM_QC_NO},
+ {0x2F887, UNICODE_NORM_QC_NO},
+ {0x2F888, UNICODE_NORM_QC_NO},
+ {0x2F889, UNICODE_NORM_QC_NO},
+ {0x2F88A, UNICODE_NORM_QC_NO},
+ {0x2F88B, UNICODE_NORM_QC_NO},
+ {0x2F88C, UNICODE_NORM_QC_NO},
+ {0x2F88D, UNICODE_NORM_QC_NO},
+ {0x2F88E, UNICODE_NORM_QC_NO},
+ {0x2F88F, UNICODE_NORM_QC_NO},
+ {0x2F890, UNICODE_NORM_QC_NO},
+ {0x2F891, UNICODE_NORM_QC_NO},
+ {0x2F892, UNICODE_NORM_QC_NO},
+ {0x2F893, UNICODE_NORM_QC_NO},
+ {0x2F894, UNICODE_NORM_QC_NO},
+ {0x2F895, UNICODE_NORM_QC_NO},
+ {0x2F896, UNICODE_NORM_QC_NO},
+ {0x2F897, UNICODE_NORM_QC_NO},
+ {0x2F898, UNICODE_NORM_QC_NO},
+ {0x2F899, UNICODE_NORM_QC_NO},
+ {0x2F89A, UNICODE_NORM_QC_NO},
+ {0x2F89B, UNICODE_NORM_QC_NO},
+ {0x2F89C, UNICODE_NORM_QC_NO},
+ {0x2F89D, UNICODE_NORM_QC_NO},
+ {0x2F89E, UNICODE_NORM_QC_NO},
+ {0x2F89F, UNICODE_NORM_QC_NO},
+ {0x2F8A0, UNICODE_NORM_QC_NO},
+ {0x2F8A1, UNICODE_NORM_QC_NO},
+ {0x2F8A2, UNICODE_NORM_QC_NO},
+ {0x2F8A3, UNICODE_NORM_QC_NO},
+ {0x2F8A4, UNICODE_NORM_QC_NO},
+ {0x2F8A5, UNICODE_NORM_QC_NO},
+ {0x2F8A6, UNICODE_NORM_QC_NO},
+ {0x2F8A7, UNICODE_NORM_QC_NO},
+ {0x2F8A8, UNICODE_NORM_QC_NO},
+ {0x2F8A9, UNICODE_NORM_QC_NO},
+ {0x2F8AA, UNICODE_NORM_QC_NO},
+ {0x2F8AB, UNICODE_NORM_QC_NO},
+ {0x2F8AC, UNICODE_NORM_QC_NO},
+ {0x2F8AD, UNICODE_NORM_QC_NO},
+ {0x2F8AE, UNICODE_NORM_QC_NO},
+ {0x2F8AF, UNICODE_NORM_QC_NO},
+ {0x2F8B0, UNICODE_NORM_QC_NO},
+ {0x2F8B1, UNICODE_NORM_QC_NO},
+ {0x2F8B2, UNICODE_NORM_QC_NO},
+ {0x2F8B3, UNICODE_NORM_QC_NO},
+ {0x2F8B4, UNICODE_NORM_QC_NO},
+ {0x2F8B5, UNICODE_NORM_QC_NO},
+ {0x2F8B6, UNICODE_NORM_QC_NO},
+ {0x2F8B7, UNICODE_NORM_QC_NO},
+ {0x2F8B8, UNICODE_NORM_QC_NO},
+ {0x2F8B9, UNICODE_NORM_QC_NO},
+ {0x2F8BA, UNICODE_NORM_QC_NO},
+ {0x2F8BB, UNICODE_NORM_QC_NO},
+ {0x2F8BC, UNICODE_NORM_QC_NO},
+ {0x2F8BD, UNICODE_NORM_QC_NO},
+ {0x2F8BE, UNICODE_NORM_QC_NO},
+ {0x2F8BF, UNICODE_NORM_QC_NO},
+ {0x2F8C0, UNICODE_NORM_QC_NO},
+ {0x2F8C1, UNICODE_NORM_QC_NO},
+ {0x2F8C2, UNICODE_NORM_QC_NO},
+ {0x2F8C3, UNICODE_NORM_QC_NO},
+ {0x2F8C4, UNICODE_NORM_QC_NO},
+ {0x2F8C5, UNICODE_NORM_QC_NO},
+ {0x2F8C6, UNICODE_NORM_QC_NO},
+ {0x2F8C7, UNICODE_NORM_QC_NO},
+ {0x2F8C8, UNICODE_NORM_QC_NO},
+ {0x2F8C9, UNICODE_NORM_QC_NO},
+ {0x2F8CA, UNICODE_NORM_QC_NO},
+ {0x2F8CB, UNICODE_NORM_QC_NO},
+ {0x2F8CC, UNICODE_NORM_QC_NO},
+ {0x2F8CD, UNICODE_NORM_QC_NO},
+ {0x2F8CE, UNICODE_NORM_QC_NO},
+ {0x2F8CF, UNICODE_NORM_QC_NO},
+ {0x2F8D0, UNICODE_NORM_QC_NO},
+ {0x2F8D1, UNICODE_NORM_QC_NO},
+ {0x2F8D2, UNICODE_NORM_QC_NO},
+ {0x2F8D3, UNICODE_NORM_QC_NO},
+ {0x2F8D4, UNICODE_NORM_QC_NO},
+ {0x2F8D5, UNICODE_NORM_QC_NO},
+ {0x2F8D6, UNICODE_NORM_QC_NO},
+ {0x2F8D7, UNICODE_NORM_QC_NO},
+ {0x2F8D8, UNICODE_NORM_QC_NO},
+ {0x2F8D9, UNICODE_NORM_QC_NO},
+ {0x2F8DA, UNICODE_NORM_QC_NO},
+ {0x2F8DB, UNICODE_NORM_QC_NO},
+ {0x2F8DC, UNICODE_NORM_QC_NO},
+ {0x2F8DD, UNICODE_NORM_QC_NO},
+ {0x2F8DE, UNICODE_NORM_QC_NO},
+ {0x2F8DF, UNICODE_NORM_QC_NO},
+ {0x2F8E0, UNICODE_NORM_QC_NO},
+ {0x2F8E1, UNICODE_NORM_QC_NO},
+ {0x2F8E2, UNICODE_NORM_QC_NO},
+ {0x2F8E3, UNICODE_NORM_QC_NO},
+ {0x2F8E4, UNICODE_NORM_QC_NO},
+ {0x2F8E5, UNICODE_NORM_QC_NO},
+ {0x2F8E6, UNICODE_NORM_QC_NO},
+ {0x2F8E7, UNICODE_NORM_QC_NO},
+ {0x2F8E8, UNICODE_NORM_QC_NO},
+ {0x2F8E9, UNICODE_NORM_QC_NO},
+ {0x2F8EA, UNICODE_NORM_QC_NO},
+ {0x2F8EB, UNICODE_NORM_QC_NO},
+ {0x2F8EC, UNICODE_NORM_QC_NO},
+ {0x2F8ED, UNICODE_NORM_QC_NO},
+ {0x2F8EE, UNICODE_NORM_QC_NO},
+ {0x2F8EF, UNICODE_NORM_QC_NO},
+ {0x2F8F0, UNICODE_NORM_QC_NO},
+ {0x2F8F1, UNICODE_NORM_QC_NO},
+ {0x2F8F2, UNICODE_NORM_QC_NO},
+ {0x2F8F3, UNICODE_NORM_QC_NO},
+ {0x2F8F4, UNICODE_NORM_QC_NO},
+ {0x2F8F5, UNICODE_NORM_QC_NO},
+ {0x2F8F6, UNICODE_NORM_QC_NO},
+ {0x2F8F7, UNICODE_NORM_QC_NO},
+ {0x2F8F8, UNICODE_NORM_QC_NO},
+ {0x2F8F9, UNICODE_NORM_QC_NO},
+ {0x2F8FA, UNICODE_NORM_QC_NO},
+ {0x2F8FB, UNICODE_NORM_QC_NO},
+ {0x2F8FC, UNICODE_NORM_QC_NO},
+ {0x2F8FD, UNICODE_NORM_QC_NO},
+ {0x2F8FE, UNICODE_NORM_QC_NO},
+ {0x2F8FF, UNICODE_NORM_QC_NO},
+ {0x2F900, UNICODE_NORM_QC_NO},
+ {0x2F901, UNICODE_NORM_QC_NO},
+ {0x2F902, UNICODE_NORM_QC_NO},
+ {0x2F903, UNICODE_NORM_QC_NO},
+ {0x2F904, UNICODE_NORM_QC_NO},
+ {0x2F905, UNICODE_NORM_QC_NO},
+ {0x2F906, UNICODE_NORM_QC_NO},
+ {0x2F907, UNICODE_NORM_QC_NO},
+ {0x2F908, UNICODE_NORM_QC_NO},
+ {0x2F909, UNICODE_NORM_QC_NO},
+ {0x2F90A, UNICODE_NORM_QC_NO},
+ {0x2F90B, UNICODE_NORM_QC_NO},
+ {0x2F90C, UNICODE_NORM_QC_NO},
+ {0x2F90D, UNICODE_NORM_QC_NO},
+ {0x2F90E, UNICODE_NORM_QC_NO},
+ {0x2F90F, UNICODE_NORM_QC_NO},
+ {0x2F910, UNICODE_NORM_QC_NO},
+ {0x2F911, UNICODE_NORM_QC_NO},
+ {0x2F912, UNICODE_NORM_QC_NO},
+ {0x2F913, UNICODE_NORM_QC_NO},
+ {0x2F914, UNICODE_NORM_QC_NO},
+ {0x2F915, UNICODE_NORM_QC_NO},
+ {0x2F916, UNICODE_NORM_QC_NO},
+ {0x2F917, UNICODE_NORM_QC_NO},
+ {0x2F918, UNICODE_NORM_QC_NO},
+ {0x2F919, UNICODE_NORM_QC_NO},
+ {0x2F91A, UNICODE_NORM_QC_NO},
+ {0x2F91B, UNICODE_NORM_QC_NO},
+ {0x2F91C, UNICODE_NORM_QC_NO},
+ {0x2F91D, UNICODE_NORM_QC_NO},
+ {0x2F91E, UNICODE_NORM_QC_NO},
+ {0x2F91F, UNICODE_NORM_QC_NO},
+ {0x2F920, UNICODE_NORM_QC_NO},
+ {0x2F921, UNICODE_NORM_QC_NO},
+ {0x2F922, UNICODE_NORM_QC_NO},
+ {0x2F923, UNICODE_NORM_QC_NO},
+ {0x2F924, UNICODE_NORM_QC_NO},
+ {0x2F925, UNICODE_NORM_QC_NO},
+ {0x2F926, UNICODE_NORM_QC_NO},
+ {0x2F927, UNICODE_NORM_QC_NO},
+ {0x2F928, UNICODE_NORM_QC_NO},
+ {0x2F929, UNICODE_NORM_QC_NO},
+ {0x2F92A, UNICODE_NORM_QC_NO},
+ {0x2F92B, UNICODE_NORM_QC_NO},
+ {0x2F92C, UNICODE_NORM_QC_NO},
+ {0x2F92D, UNICODE_NORM_QC_NO},
+ {0x2F92E, UNICODE_NORM_QC_NO},
+ {0x2F92F, UNICODE_NORM_QC_NO},
+ {0x2F930, UNICODE_NORM_QC_NO},
+ {0x2F931, UNICODE_NORM_QC_NO},
+ {0x2F932, UNICODE_NORM_QC_NO},
+ {0x2F933, UNICODE_NORM_QC_NO},
+ {0x2F934, UNICODE_NORM_QC_NO},
+ {0x2F935, UNICODE_NORM_QC_NO},
+ {0x2F936, UNICODE_NORM_QC_NO},
+ {0x2F937, UNICODE_NORM_QC_NO},
+ {0x2F938, UNICODE_NORM_QC_NO},
+ {0x2F939, UNICODE_NORM_QC_NO},
+ {0x2F93A, UNICODE_NORM_QC_NO},
+ {0x2F93B, UNICODE_NORM_QC_NO},
+ {0x2F93C, UNICODE_NORM_QC_NO},
+ {0x2F93D, UNICODE_NORM_QC_NO},
+ {0x2F93E, UNICODE_NORM_QC_NO},
+ {0x2F93F, UNICODE_NORM_QC_NO},
+ {0x2F940, UNICODE_NORM_QC_NO},
+ {0x2F941, UNICODE_NORM_QC_NO},
+ {0x2F942, UNICODE_NORM_QC_NO},
+ {0x2F943, UNICODE_NORM_QC_NO},
+ {0x2F944, UNICODE_NORM_QC_NO},
+ {0x2F945, UNICODE_NORM_QC_NO},
+ {0x2F946, UNICODE_NORM_QC_NO},
+ {0x2F947, UNICODE_NORM_QC_NO},
+ {0x2F948, UNICODE_NORM_QC_NO},
+ {0x2F949, UNICODE_NORM_QC_NO},
+ {0x2F94A, UNICODE_NORM_QC_NO},
+ {0x2F94B, UNICODE_NORM_QC_NO},
+ {0x2F94C, UNICODE_NORM_QC_NO},
+ {0x2F94D, UNICODE_NORM_QC_NO},
+ {0x2F94E, UNICODE_NORM_QC_NO},
+ {0x2F94F, UNICODE_NORM_QC_NO},
+ {0x2F950, UNICODE_NORM_QC_NO},
+ {0x2F951, UNICODE_NORM_QC_NO},
+ {0x2F952, UNICODE_NORM_QC_NO},
+ {0x2F953, UNICODE_NORM_QC_NO},
+ {0x2F954, UNICODE_NORM_QC_NO},
+ {0x2F955, UNICODE_NORM_QC_NO},
+ {0x2F956, UNICODE_NORM_QC_NO},
+ {0x2F957, UNICODE_NORM_QC_NO},
+ {0x2F958, UNICODE_NORM_QC_NO},
+ {0x2F959, UNICODE_NORM_QC_NO},
+ {0x2F95A, UNICODE_NORM_QC_NO},
+ {0x2F95B, UNICODE_NORM_QC_NO},
+ {0x2F95C, UNICODE_NORM_QC_NO},
+ {0x2F95D, UNICODE_NORM_QC_NO},
+ {0x2F95E, UNICODE_NORM_QC_NO},
+ {0x2F95F, UNICODE_NORM_QC_NO},
+ {0x2F960, UNICODE_NORM_QC_NO},
+ {0x2F961, UNICODE_NORM_QC_NO},
+ {0x2F962, UNICODE_NORM_QC_NO},
+ {0x2F963, UNICODE_NORM_QC_NO},
+ {0x2F964, UNICODE_NORM_QC_NO},
+ {0x2F965, UNICODE_NORM_QC_NO},
+ {0x2F966, UNICODE_NORM_QC_NO},
+ {0x2F967, UNICODE_NORM_QC_NO},
+ {0x2F968, UNICODE_NORM_QC_NO},
+ {0x2F969, UNICODE_NORM_QC_NO},
+ {0x2F96A, UNICODE_NORM_QC_NO},
+ {0x2F96B, UNICODE_NORM_QC_NO},
+ {0x2F96C, UNICODE_NORM_QC_NO},
+ {0x2F96D, UNICODE_NORM_QC_NO},
+ {0x2F96E, UNICODE_NORM_QC_NO},
+ {0x2F96F, UNICODE_NORM_QC_NO},
+ {0x2F970, UNICODE_NORM_QC_NO},
+ {0x2F971, UNICODE_NORM_QC_NO},
+ {0x2F972, UNICODE_NORM_QC_NO},
+ {0x2F973, UNICODE_NORM_QC_NO},
+ {0x2F974, UNICODE_NORM_QC_NO},
+ {0x2F975, UNICODE_NORM_QC_NO},
+ {0x2F976, UNICODE_NORM_QC_NO},
+ {0x2F977, UNICODE_NORM_QC_NO},
+ {0x2F978, UNICODE_NORM_QC_NO},
+ {0x2F979, UNICODE_NORM_QC_NO},
+ {0x2F97A, UNICODE_NORM_QC_NO},
+ {0x2F97B, UNICODE_NORM_QC_NO},
+ {0x2F97C, UNICODE_NORM_QC_NO},
+ {0x2F97D, UNICODE_NORM_QC_NO},
+ {0x2F97E, UNICODE_NORM_QC_NO},
+ {0x2F97F, UNICODE_NORM_QC_NO},
+ {0x2F980, UNICODE_NORM_QC_NO},
+ {0x2F981, UNICODE_NORM_QC_NO},
+ {0x2F982, UNICODE_NORM_QC_NO},
+ {0x2F983, UNICODE_NORM_QC_NO},
+ {0x2F984, UNICODE_NORM_QC_NO},
+ {0x2F985, UNICODE_NORM_QC_NO},
+ {0x2F986, UNICODE_NORM_QC_NO},
+ {0x2F987, UNICODE_NORM_QC_NO},
+ {0x2F988, UNICODE_NORM_QC_NO},
+ {0x2F989, UNICODE_NORM_QC_NO},
+ {0x2F98A, UNICODE_NORM_QC_NO},
+ {0x2F98B, UNICODE_NORM_QC_NO},
+ {0x2F98C, UNICODE_NORM_QC_NO},
+ {0x2F98D, UNICODE_NORM_QC_NO},
+ {0x2F98E, UNICODE_NORM_QC_NO},
+ {0x2F98F, UNICODE_NORM_QC_NO},
+ {0x2F990, UNICODE_NORM_QC_NO},
+ {0x2F991, UNICODE_NORM_QC_NO},
+ {0x2F992, UNICODE_NORM_QC_NO},
+ {0x2F993, UNICODE_NORM_QC_NO},
+ {0x2F994, UNICODE_NORM_QC_NO},
+ {0x2F995, UNICODE_NORM_QC_NO},
+ {0x2F996, UNICODE_NORM_QC_NO},
+ {0x2F997, UNICODE_NORM_QC_NO},
+ {0x2F998, UNICODE_NORM_QC_NO},
+ {0x2F999, UNICODE_NORM_QC_NO},
+ {0x2F99A, UNICODE_NORM_QC_NO},
+ {0x2F99B, UNICODE_NORM_QC_NO},
+ {0x2F99C, UNICODE_NORM_QC_NO},
+ {0x2F99D, UNICODE_NORM_QC_NO},
+ {0x2F99E, UNICODE_NORM_QC_NO},
+ {0x2F99F, UNICODE_NORM_QC_NO},
+ {0x2F9A0, UNICODE_NORM_QC_NO},
+ {0x2F9A1, UNICODE_NORM_QC_NO},
+ {0x2F9A2, UNICODE_NORM_QC_NO},
+ {0x2F9A3, UNICODE_NORM_QC_NO},
+ {0x2F9A4, UNICODE_NORM_QC_NO},
+ {0x2F9A5, UNICODE_NORM_QC_NO},
+ {0x2F9A6, UNICODE_NORM_QC_NO},
+ {0x2F9A7, UNICODE_NORM_QC_NO},
+ {0x2F9A8, UNICODE_NORM_QC_NO},
+ {0x2F9A9, UNICODE_NORM_QC_NO},
+ {0x2F9AA, UNICODE_NORM_QC_NO},
+ {0x2F9AB, UNICODE_NORM_QC_NO},
+ {0x2F9AC, UNICODE_NORM_QC_NO},
+ {0x2F9AD, UNICODE_NORM_QC_NO},
+ {0x2F9AE, UNICODE_NORM_QC_NO},
+ {0x2F9AF, UNICODE_NORM_QC_NO},
+ {0x2F9B0, UNICODE_NORM_QC_NO},
+ {0x2F9B1, UNICODE_NORM_QC_NO},
+ {0x2F9B2, UNICODE_NORM_QC_NO},
+ {0x2F9B3, UNICODE_NORM_QC_NO},
+ {0x2F9B4, UNICODE_NORM_QC_NO},
+ {0x2F9B5, UNICODE_NORM_QC_NO},
+ {0x2F9B6, UNICODE_NORM_QC_NO},
+ {0x2F9B7, UNICODE_NORM_QC_NO},
+ {0x2F9B8, UNICODE_NORM_QC_NO},
+ {0x2F9B9, UNICODE_NORM_QC_NO},
+ {0x2F9BA, UNICODE_NORM_QC_NO},
+ {0x2F9BB, UNICODE_NORM_QC_NO},
+ {0x2F9BC, UNICODE_NORM_QC_NO},
+ {0x2F9BD, UNICODE_NORM_QC_NO},
+ {0x2F9BE, UNICODE_NORM_QC_NO},
+ {0x2F9BF, UNICODE_NORM_QC_NO},
+ {0x2F9C0, UNICODE_NORM_QC_NO},
+ {0x2F9C1, UNICODE_NORM_QC_NO},
+ {0x2F9C2, UNICODE_NORM_QC_NO},
+ {0x2F9C3, UNICODE_NORM_QC_NO},
+ {0x2F9C4, UNICODE_NORM_QC_NO},
+ {0x2F9C5, UNICODE_NORM_QC_NO},
+ {0x2F9C6, UNICODE_NORM_QC_NO},
+ {0x2F9C7, UNICODE_NORM_QC_NO},
+ {0x2F9C8, UNICODE_NORM_QC_NO},
+ {0x2F9C9, UNICODE_NORM_QC_NO},
+ {0x2F9CA, UNICODE_NORM_QC_NO},
+ {0x2F9CB, UNICODE_NORM_QC_NO},
+ {0x2F9CC, UNICODE_NORM_QC_NO},
+ {0x2F9CD, UNICODE_NORM_QC_NO},
+ {0x2F9CE, UNICODE_NORM_QC_NO},
+ {0x2F9CF, UNICODE_NORM_QC_NO},
+ {0x2F9D0, UNICODE_NORM_QC_NO},
+ {0x2F9D1, UNICODE_NORM_QC_NO},
+ {0x2F9D2, UNICODE_NORM_QC_NO},
+ {0x2F9D3, UNICODE_NORM_QC_NO},
+ {0x2F9D4, UNICODE_NORM_QC_NO},
+ {0x2F9D5, UNICODE_NORM_QC_NO},
+ {0x2F9D6, UNICODE_NORM_QC_NO},
+ {0x2F9D7, UNICODE_NORM_QC_NO},
+ {0x2F9D8, UNICODE_NORM_QC_NO},
+ {0x2F9D9, UNICODE_NORM_QC_NO},
+ {0x2F9DA, UNICODE_NORM_QC_NO},
+ {0x2F9DB, UNICODE_NORM_QC_NO},
+ {0x2F9DC, UNICODE_NORM_QC_NO},
+ {0x2F9DD, UNICODE_NORM_QC_NO},
+ {0x2F9DE, UNICODE_NORM_QC_NO},
+ {0x2F9DF, UNICODE_NORM_QC_NO},
+ {0x2F9E0, UNICODE_NORM_QC_NO},
+ {0x2F9E1, UNICODE_NORM_QC_NO},
+ {0x2F9E2, UNICODE_NORM_QC_NO},
+ {0x2F9E3, UNICODE_NORM_QC_NO},
+ {0x2F9E4, UNICODE_NORM_QC_NO},
+ {0x2F9E5, UNICODE_NORM_QC_NO},
+ {0x2F9E6, UNICODE_NORM_QC_NO},
+ {0x2F9E7, UNICODE_NORM_QC_NO},
+ {0x2F9E8, UNICODE_NORM_QC_NO},
+ {0x2F9E9, UNICODE_NORM_QC_NO},
+ {0x2F9EA, UNICODE_NORM_QC_NO},
+ {0x2F9EB, UNICODE_NORM_QC_NO},
+ {0x2F9EC, UNICODE_NORM_QC_NO},
+ {0x2F9ED, UNICODE_NORM_QC_NO},
+ {0x2F9EE, UNICODE_NORM_QC_NO},
+ {0x2F9EF, UNICODE_NORM_QC_NO},
+ {0x2F9F0, UNICODE_NORM_QC_NO},
+ {0x2F9F1, UNICODE_NORM_QC_NO},
+ {0x2F9F2, UNICODE_NORM_QC_NO},
+ {0x2F9F3, UNICODE_NORM_QC_NO},
+ {0x2F9F4, UNICODE_NORM_QC_NO},
+ {0x2F9F5, UNICODE_NORM_QC_NO},
+ {0x2F9F6, UNICODE_NORM_QC_NO},
+ {0x2F9F7, UNICODE_NORM_QC_NO},
+ {0x2F9F8, UNICODE_NORM_QC_NO},
+ {0x2F9F9, UNICODE_NORM_QC_NO},
+ {0x2F9FA, UNICODE_NORM_QC_NO},
+ {0x2F9FB, UNICODE_NORM_QC_NO},
+ {0x2F9FC, UNICODE_NORM_QC_NO},
+ {0x2F9FD, UNICODE_NORM_QC_NO},
+ {0x2F9FE, UNICODE_NORM_QC_NO},
+ {0x2F9FF, UNICODE_NORM_QC_NO},
+ {0x2FA00, UNICODE_NORM_QC_NO},
+ {0x2FA01, UNICODE_NORM_QC_NO},
+ {0x2FA02, UNICODE_NORM_QC_NO},
+ {0x2FA03, UNICODE_NORM_QC_NO},
+ {0x2FA04, UNICODE_NORM_QC_NO},
+ {0x2FA05, UNICODE_NORM_QC_NO},
+ {0x2FA06, UNICODE_NORM_QC_NO},
+ {0x2FA07, UNICODE_NORM_QC_NO},
+ {0x2FA08, UNICODE_NORM_QC_NO},
+ {0x2FA09, UNICODE_NORM_QC_NO},
+ {0x2FA0A, UNICODE_NORM_QC_NO},
+ {0x2FA0B, UNICODE_NORM_QC_NO},
+ {0x2FA0C, UNICODE_NORM_QC_NO},
+ {0x2FA0D, UNICODE_NORM_QC_NO},
+ {0x2FA0E, UNICODE_NORM_QC_NO},
+ {0x2FA0F, UNICODE_NORM_QC_NO},
+ {0x2FA10, UNICODE_NORM_QC_NO},
+ {0x2FA11, UNICODE_NORM_QC_NO},
+ {0x2FA12, UNICODE_NORM_QC_NO},
+ {0x2FA13, UNICODE_NORM_QC_NO},
+ {0x2FA14, UNICODE_NORM_QC_NO},
+ {0x2FA15, UNICODE_NORM_QC_NO},
+ {0x2FA16, UNICODE_NORM_QC_NO},
+ {0x2FA17, UNICODE_NORM_QC_NO},
+ {0x2FA18, UNICODE_NORM_QC_NO},
+ {0x2FA19, UNICODE_NORM_QC_NO},
+ {0x2FA1A, UNICODE_NORM_QC_NO},
+ {0x2FA1B, UNICODE_NORM_QC_NO},
+ {0x2FA1C, UNICODE_NORM_QC_NO},
+ {0x2FA1D, UNICODE_NORM_QC_NO},
+};
+
+static const pg_unicode_normprops UnicodeNormProps_NFKC_QC[] = {
+ {0x00A0, UNICODE_NORM_QC_NO},
+ {0x00A8, UNICODE_NORM_QC_NO},
+ {0x00AA, UNICODE_NORM_QC_NO},
+ {0x00AF, UNICODE_NORM_QC_NO},
+ {0x00B2, UNICODE_NORM_QC_NO},
+ {0x00B3, UNICODE_NORM_QC_NO},
+ {0x00B4, UNICODE_NORM_QC_NO},
+ {0x00B5, UNICODE_NORM_QC_NO},
+ {0x00B8, UNICODE_NORM_QC_NO},
+ {0x00B9, UNICODE_NORM_QC_NO},
+ {0x00BA, UNICODE_NORM_QC_NO},
+ {0x00BC, UNICODE_NORM_QC_NO},
+ {0x00BD, UNICODE_NORM_QC_NO},
+ {0x00BE, UNICODE_NORM_QC_NO},
+ {0x0132, UNICODE_NORM_QC_NO},
+ {0x0133, UNICODE_NORM_QC_NO},
+ {0x013F, UNICODE_NORM_QC_NO},
+ {0x0140, UNICODE_NORM_QC_NO},
+ {0x0149, UNICODE_NORM_QC_NO},
+ {0x017F, UNICODE_NORM_QC_NO},
+ {0x01C4, UNICODE_NORM_QC_NO},
+ {0x01C5, UNICODE_NORM_QC_NO},
+ {0x01C6, UNICODE_NORM_QC_NO},
+ {0x01C7, UNICODE_NORM_QC_NO},
+ {0x01C8, UNICODE_NORM_QC_NO},
+ {0x01C9, UNICODE_NORM_QC_NO},
+ {0x01CA, UNICODE_NORM_QC_NO},
+ {0x01CB, UNICODE_NORM_QC_NO},
+ {0x01CC, UNICODE_NORM_QC_NO},
+ {0x01F1, UNICODE_NORM_QC_NO},
+ {0x01F2, UNICODE_NORM_QC_NO},
+ {0x01F3, UNICODE_NORM_QC_NO},
+ {0x02B0, UNICODE_NORM_QC_NO},
+ {0x02B1, UNICODE_NORM_QC_NO},
+ {0x02B2, UNICODE_NORM_QC_NO},
+ {0x02B3, UNICODE_NORM_QC_NO},
+ {0x02B4, UNICODE_NORM_QC_NO},
+ {0x02B5, UNICODE_NORM_QC_NO},
+ {0x02B6, UNICODE_NORM_QC_NO},
+ {0x02B7, UNICODE_NORM_QC_NO},
+ {0x02B8, UNICODE_NORM_QC_NO},
+ {0x02D8, UNICODE_NORM_QC_NO},
+ {0x02D9, UNICODE_NORM_QC_NO},
+ {0x02DA, UNICODE_NORM_QC_NO},
+ {0x02DB, UNICODE_NORM_QC_NO},
+ {0x02DC, UNICODE_NORM_QC_NO},
+ {0x02DD, UNICODE_NORM_QC_NO},
+ {0x02E0, UNICODE_NORM_QC_NO},
+ {0x02E1, UNICODE_NORM_QC_NO},
+ {0x02E2, UNICODE_NORM_QC_NO},
+ {0x02E3, UNICODE_NORM_QC_NO},
+ {0x02E4, UNICODE_NORM_QC_NO},
+ {0x0300, UNICODE_NORM_QC_MAYBE},
+ {0x0301, UNICODE_NORM_QC_MAYBE},
+ {0x0302, UNICODE_NORM_QC_MAYBE},
+ {0x0303, UNICODE_NORM_QC_MAYBE},
+ {0x0304, UNICODE_NORM_QC_MAYBE},
+ {0x0306, UNICODE_NORM_QC_MAYBE},
+ {0x0307, UNICODE_NORM_QC_MAYBE},
+ {0x0308, UNICODE_NORM_QC_MAYBE},
+ {0x0309, UNICODE_NORM_QC_MAYBE},
+ {0x030A, UNICODE_NORM_QC_MAYBE},
+ {0x030B, UNICODE_NORM_QC_MAYBE},
+ {0x030C, UNICODE_NORM_QC_MAYBE},
+ {0x030F, UNICODE_NORM_QC_MAYBE},
+ {0x0311, UNICODE_NORM_QC_MAYBE},
+ {0x0313, UNICODE_NORM_QC_MAYBE},
+ {0x0314, UNICODE_NORM_QC_MAYBE},
+ {0x031B, UNICODE_NORM_QC_MAYBE},
+ {0x0323, UNICODE_NORM_QC_MAYBE},
+ {0x0324, UNICODE_NORM_QC_MAYBE},
+ {0x0325, UNICODE_NORM_QC_MAYBE},
+ {0x0326, UNICODE_NORM_QC_MAYBE},
+ {0x0327, UNICODE_NORM_QC_MAYBE},
+ {0x0328, UNICODE_NORM_QC_MAYBE},
+ {0x032D, UNICODE_NORM_QC_MAYBE},
+ {0x032E, UNICODE_NORM_QC_MAYBE},
+ {0x0330, UNICODE_NORM_QC_MAYBE},
+ {0x0331, UNICODE_NORM_QC_MAYBE},
+ {0x0338, UNICODE_NORM_QC_MAYBE},
+ {0x0340, UNICODE_NORM_QC_NO},
+ {0x0341, UNICODE_NORM_QC_NO},
+ {0x0342, UNICODE_NORM_QC_MAYBE},
+ {0x0343, UNICODE_NORM_QC_NO},
+ {0x0344, UNICODE_NORM_QC_NO},
+ {0x0345, UNICODE_NORM_QC_MAYBE},
+ {0x0374, UNICODE_NORM_QC_NO},
+ {0x037A, UNICODE_NORM_QC_NO},
+ {0x037E, UNICODE_NORM_QC_NO},
+ {0x0384, UNICODE_NORM_QC_NO},
+ {0x0385, UNICODE_NORM_QC_NO},
+ {0x0387, UNICODE_NORM_QC_NO},
+ {0x03D0, UNICODE_NORM_QC_NO},
+ {0x03D1, UNICODE_NORM_QC_NO},
+ {0x03D2, UNICODE_NORM_QC_NO},
+ {0x03D3, UNICODE_NORM_QC_NO},
+ {0x03D4, UNICODE_NORM_QC_NO},
+ {0x03D5, UNICODE_NORM_QC_NO},
+ {0x03D6, UNICODE_NORM_QC_NO},
+ {0x03F0, UNICODE_NORM_QC_NO},
+ {0x03F1, UNICODE_NORM_QC_NO},
+ {0x03F2, UNICODE_NORM_QC_NO},
+ {0x03F4, UNICODE_NORM_QC_NO},
+ {0x03F5, UNICODE_NORM_QC_NO},
+ {0x03F9, UNICODE_NORM_QC_NO},
+ {0x0587, UNICODE_NORM_QC_NO},
+ {0x0653, UNICODE_NORM_QC_MAYBE},
+ {0x0654, UNICODE_NORM_QC_MAYBE},
+ {0x0655, UNICODE_NORM_QC_MAYBE},
+ {0x0675, UNICODE_NORM_QC_NO},
+ {0x0676, UNICODE_NORM_QC_NO},
+ {0x0677, UNICODE_NORM_QC_NO},
+ {0x0678, UNICODE_NORM_QC_NO},
+ {0x093C, UNICODE_NORM_QC_MAYBE},
+ {0x0958, UNICODE_NORM_QC_NO},
+ {0x0959, UNICODE_NORM_QC_NO},
+ {0x095A, UNICODE_NORM_QC_NO},
+ {0x095B, UNICODE_NORM_QC_NO},
+ {0x095C, UNICODE_NORM_QC_NO},
+ {0x095D, UNICODE_NORM_QC_NO},
+ {0x095E, UNICODE_NORM_QC_NO},
+ {0x095F, UNICODE_NORM_QC_NO},
+ {0x09BE, UNICODE_NORM_QC_MAYBE},
+ {0x09D7, UNICODE_NORM_QC_MAYBE},
+ {0x09DC, UNICODE_NORM_QC_NO},
+ {0x09DD, UNICODE_NORM_QC_NO},
+ {0x09DF, UNICODE_NORM_QC_NO},
+ {0x0A33, UNICODE_NORM_QC_NO},
+ {0x0A36, UNICODE_NORM_QC_NO},
+ {0x0A59, UNICODE_NORM_QC_NO},
+ {0x0A5A, UNICODE_NORM_QC_NO},
+ {0x0A5B, UNICODE_NORM_QC_NO},
+ {0x0A5E, UNICODE_NORM_QC_NO},
+ {0x0B3E, UNICODE_NORM_QC_MAYBE},
+ {0x0B56, UNICODE_NORM_QC_MAYBE},
+ {0x0B57, UNICODE_NORM_QC_MAYBE},
+ {0x0B5C, UNICODE_NORM_QC_NO},
+ {0x0B5D, UNICODE_NORM_QC_NO},
+ {0x0BBE, UNICODE_NORM_QC_MAYBE},
+ {0x0BD7, UNICODE_NORM_QC_MAYBE},
+ {0x0C56, UNICODE_NORM_QC_MAYBE},
+ {0x0CC2, UNICODE_NORM_QC_MAYBE},
+ {0x0CD5, UNICODE_NORM_QC_MAYBE},
+ {0x0CD6, UNICODE_NORM_QC_MAYBE},
+ {0x0D3E, UNICODE_NORM_QC_MAYBE},
+ {0x0D57, UNICODE_NORM_QC_MAYBE},
+ {0x0DCA, UNICODE_NORM_QC_MAYBE},
+ {0x0DCF, UNICODE_NORM_QC_MAYBE},
+ {0x0DDF, UNICODE_NORM_QC_MAYBE},
+ {0x0E33, UNICODE_NORM_QC_NO},
+ {0x0EB3, UNICODE_NORM_QC_NO},
+ {0x0EDC, UNICODE_NORM_QC_NO},
+ {0x0EDD, UNICODE_NORM_QC_NO},
+ {0x0F0C, UNICODE_NORM_QC_NO},
+ {0x0F43, UNICODE_NORM_QC_NO},
+ {0x0F4D, UNICODE_NORM_QC_NO},
+ {0x0F52, UNICODE_NORM_QC_NO},
+ {0x0F57, UNICODE_NORM_QC_NO},
+ {0x0F5C, UNICODE_NORM_QC_NO},
+ {0x0F69, UNICODE_NORM_QC_NO},
+ {0x0F73, UNICODE_NORM_QC_NO},
+ {0x0F75, UNICODE_NORM_QC_NO},
+ {0x0F76, UNICODE_NORM_QC_NO},
+ {0x0F77, UNICODE_NORM_QC_NO},
+ {0x0F78, UNICODE_NORM_QC_NO},
+ {0x0F79, UNICODE_NORM_QC_NO},
+ {0x0F81, UNICODE_NORM_QC_NO},
+ {0x0F93, UNICODE_NORM_QC_NO},
+ {0x0F9D, UNICODE_NORM_QC_NO},
+ {0x0FA2, UNICODE_NORM_QC_NO},
+ {0x0FA7, UNICODE_NORM_QC_NO},
+ {0x0FAC, UNICODE_NORM_QC_NO},
+ {0x0FB9, UNICODE_NORM_QC_NO},
+ {0x102E, UNICODE_NORM_QC_MAYBE},
+ {0x10FC, UNICODE_NORM_QC_NO},
+ {0x1161, UNICODE_NORM_QC_MAYBE},
+ {0x1162, UNICODE_NORM_QC_MAYBE},
+ {0x1163, UNICODE_NORM_QC_MAYBE},
+ {0x1164, UNICODE_NORM_QC_MAYBE},
+ {0x1165, UNICODE_NORM_QC_MAYBE},
+ {0x1166, UNICODE_NORM_QC_MAYBE},
+ {0x1167, UNICODE_NORM_QC_MAYBE},
+ {0x1168, UNICODE_NORM_QC_MAYBE},
+ {0x1169, UNICODE_NORM_QC_MAYBE},
+ {0x116A, UNICODE_NORM_QC_MAYBE},
+ {0x116B, UNICODE_NORM_QC_MAYBE},
+ {0x116C, UNICODE_NORM_QC_MAYBE},
+ {0x116D, UNICODE_NORM_QC_MAYBE},
+ {0x116E, UNICODE_NORM_QC_MAYBE},
+ {0x116F, UNICODE_NORM_QC_MAYBE},
+ {0x1170, UNICODE_NORM_QC_MAYBE},
+ {0x1171, UNICODE_NORM_QC_MAYBE},
+ {0x1172, UNICODE_NORM_QC_MAYBE},
+ {0x1173, UNICODE_NORM_QC_MAYBE},
+ {0x1174, UNICODE_NORM_QC_MAYBE},
+ {0x1175, UNICODE_NORM_QC_MAYBE},
+ {0x11A8, UNICODE_NORM_QC_MAYBE},
+ {0x11A9, UNICODE_NORM_QC_MAYBE},
+ {0x11AA, UNICODE_NORM_QC_MAYBE},
+ {0x11AB, UNICODE_NORM_QC_MAYBE},
+ {0x11AC, UNICODE_NORM_QC_MAYBE},
+ {0x11AD, UNICODE_NORM_QC_MAYBE},
+ {0x11AE, UNICODE_NORM_QC_MAYBE},
+ {0x11AF, UNICODE_NORM_QC_MAYBE},
+ {0x11B0, UNICODE_NORM_QC_MAYBE},
+ {0x11B1, UNICODE_NORM_QC_MAYBE},
+ {0x11B2, UNICODE_NORM_QC_MAYBE},
+ {0x11B3, UNICODE_NORM_QC_MAYBE},
+ {0x11B4, UNICODE_NORM_QC_MAYBE},
+ {0x11B5, UNICODE_NORM_QC_MAYBE},
+ {0x11B6, UNICODE_NORM_QC_MAYBE},
+ {0x11B7, UNICODE_NORM_QC_MAYBE},
+ {0x11B8, UNICODE_NORM_QC_MAYBE},
+ {0x11B9, UNICODE_NORM_QC_MAYBE},
+ {0x11BA, UNICODE_NORM_QC_MAYBE},
+ {0x11BB, UNICODE_NORM_QC_MAYBE},
+ {0x11BC, UNICODE_NORM_QC_MAYBE},
+ {0x11BD, UNICODE_NORM_QC_MAYBE},
+ {0x11BE, UNICODE_NORM_QC_MAYBE},
+ {0x11BF, UNICODE_NORM_QC_MAYBE},
+ {0x11C0, UNICODE_NORM_QC_MAYBE},
+ {0x11C1, UNICODE_NORM_QC_MAYBE},
+ {0x11C2, UNICODE_NORM_QC_MAYBE},
+ {0x1B35, UNICODE_NORM_QC_MAYBE},
+ {0x1D2C, UNICODE_NORM_QC_NO},
+ {0x1D2D, UNICODE_NORM_QC_NO},
+ {0x1D2E, UNICODE_NORM_QC_NO},
+ {0x1D30, UNICODE_NORM_QC_NO},
+ {0x1D31, UNICODE_NORM_QC_NO},
+ {0x1D32, UNICODE_NORM_QC_NO},
+ {0x1D33, UNICODE_NORM_QC_NO},
+ {0x1D34, UNICODE_NORM_QC_NO},
+ {0x1D35, UNICODE_NORM_QC_NO},
+ {0x1D36, UNICODE_NORM_QC_NO},
+ {0x1D37, UNICODE_NORM_QC_NO},
+ {0x1D38, UNICODE_NORM_QC_NO},
+ {0x1D39, UNICODE_NORM_QC_NO},
+ {0x1D3A, UNICODE_NORM_QC_NO},
+ {0x1D3C, UNICODE_NORM_QC_NO},
+ {0x1D3D, UNICODE_NORM_QC_NO},
+ {0x1D3E, UNICODE_NORM_QC_NO},
+ {0x1D3F, UNICODE_NORM_QC_NO},
+ {0x1D40, UNICODE_NORM_QC_NO},
+ {0x1D41, UNICODE_NORM_QC_NO},
+ {0x1D42, UNICODE_NORM_QC_NO},
+ {0x1D43, UNICODE_NORM_QC_NO},
+ {0x1D44, UNICODE_NORM_QC_NO},
+ {0x1D45, UNICODE_NORM_QC_NO},
+ {0x1D46, UNICODE_NORM_QC_NO},
+ {0x1D47, UNICODE_NORM_QC_NO},
+ {0x1D48, UNICODE_NORM_QC_NO},
+ {0x1D49, UNICODE_NORM_QC_NO},
+ {0x1D4A, UNICODE_NORM_QC_NO},
+ {0x1D4B, UNICODE_NORM_QC_NO},
+ {0x1D4C, UNICODE_NORM_QC_NO},
+ {0x1D4D, UNICODE_NORM_QC_NO},
+ {0x1D4F, UNICODE_NORM_QC_NO},
+ {0x1D50, UNICODE_NORM_QC_NO},
+ {0x1D51, UNICODE_NORM_QC_NO},
+ {0x1D52, UNICODE_NORM_QC_NO},
+ {0x1D53, UNICODE_NORM_QC_NO},
+ {0x1D54, UNICODE_NORM_QC_NO},
+ {0x1D55, UNICODE_NORM_QC_NO},
+ {0x1D56, UNICODE_NORM_QC_NO},
+ {0x1D57, UNICODE_NORM_QC_NO},
+ {0x1D58, UNICODE_NORM_QC_NO},
+ {0x1D59, UNICODE_NORM_QC_NO},
+ {0x1D5A, UNICODE_NORM_QC_NO},
+ {0x1D5B, UNICODE_NORM_QC_NO},
+ {0x1D5C, UNICODE_NORM_QC_NO},
+ {0x1D5D, UNICODE_NORM_QC_NO},
+ {0x1D5E, UNICODE_NORM_QC_NO},
+ {0x1D5F, UNICODE_NORM_QC_NO},
+ {0x1D60, UNICODE_NORM_QC_NO},
+ {0x1D61, UNICODE_NORM_QC_NO},
+ {0x1D62, UNICODE_NORM_QC_NO},
+ {0x1D63, UNICODE_NORM_QC_NO},
+ {0x1D64, UNICODE_NORM_QC_NO},
+ {0x1D65, UNICODE_NORM_QC_NO},
+ {0x1D66, UNICODE_NORM_QC_NO},
+ {0x1D67, UNICODE_NORM_QC_NO},
+ {0x1D68, UNICODE_NORM_QC_NO},
+ {0x1D69, UNICODE_NORM_QC_NO},
+ {0x1D6A, UNICODE_NORM_QC_NO},
+ {0x1D78, UNICODE_NORM_QC_NO},
+ {0x1D9B, UNICODE_NORM_QC_NO},
+ {0x1D9C, UNICODE_NORM_QC_NO},
+ {0x1D9D, UNICODE_NORM_QC_NO},
+ {0x1D9E, UNICODE_NORM_QC_NO},
+ {0x1D9F, UNICODE_NORM_QC_NO},
+ {0x1DA0, UNICODE_NORM_QC_NO},
+ {0x1DA1, UNICODE_NORM_QC_NO},
+ {0x1DA2, UNICODE_NORM_QC_NO},
+ {0x1DA3, UNICODE_NORM_QC_NO},
+ {0x1DA4, UNICODE_NORM_QC_NO},
+ {0x1DA5, UNICODE_NORM_QC_NO},
+ {0x1DA6, UNICODE_NORM_QC_NO},
+ {0x1DA7, UNICODE_NORM_QC_NO},
+ {0x1DA8, UNICODE_NORM_QC_NO},
+ {0x1DA9, UNICODE_NORM_QC_NO},
+ {0x1DAA, UNICODE_NORM_QC_NO},
+ {0x1DAB, UNICODE_NORM_QC_NO},
+ {0x1DAC, UNICODE_NORM_QC_NO},
+ {0x1DAD, UNICODE_NORM_QC_NO},
+ {0x1DAE, UNICODE_NORM_QC_NO},
+ {0x1DAF, UNICODE_NORM_QC_NO},
+ {0x1DB0, UNICODE_NORM_QC_NO},
+ {0x1DB1, UNICODE_NORM_QC_NO},
+ {0x1DB2, UNICODE_NORM_QC_NO},
+ {0x1DB3, UNICODE_NORM_QC_NO},
+ {0x1DB4, UNICODE_NORM_QC_NO},
+ {0x1DB5, UNICODE_NORM_QC_NO},
+ {0x1DB6, UNICODE_NORM_QC_NO},
+ {0x1DB7, UNICODE_NORM_QC_NO},
+ {0x1DB8, UNICODE_NORM_QC_NO},
+ {0x1DB9, UNICODE_NORM_QC_NO},
+ {0x1DBA, UNICODE_NORM_QC_NO},
+ {0x1DBB, UNICODE_NORM_QC_NO},
+ {0x1DBC, UNICODE_NORM_QC_NO},
+ {0x1DBD, UNICODE_NORM_QC_NO},
+ {0x1DBE, UNICODE_NORM_QC_NO},
+ {0x1DBF, UNICODE_NORM_QC_NO},
+ {0x1E9A, UNICODE_NORM_QC_NO},
+ {0x1E9B, UNICODE_NORM_QC_NO},
+ {0x1F71, UNICODE_NORM_QC_NO},
+ {0x1F73, UNICODE_NORM_QC_NO},
+ {0x1F75, UNICODE_NORM_QC_NO},
+ {0x1F77, UNICODE_NORM_QC_NO},
+ {0x1F79, UNICODE_NORM_QC_NO},
+ {0x1F7B, UNICODE_NORM_QC_NO},
+ {0x1F7D, UNICODE_NORM_QC_NO},
+ {0x1FBB, UNICODE_NORM_QC_NO},
+ {0x1FBD, UNICODE_NORM_QC_NO},
+ {0x1FBE, UNICODE_NORM_QC_NO},
+ {0x1FBF, UNICODE_NORM_QC_NO},
+ {0x1FC0, UNICODE_NORM_QC_NO},
+ {0x1FC1, UNICODE_NORM_QC_NO},
+ {0x1FC9, UNICODE_NORM_QC_NO},
+ {0x1FCB, UNICODE_NORM_QC_NO},
+ {0x1FCD, UNICODE_NORM_QC_NO},
+ {0x1FCE, UNICODE_NORM_QC_NO},
+ {0x1FCF, UNICODE_NORM_QC_NO},
+ {0x1FD3, UNICODE_NORM_QC_NO},
+ {0x1FDB, UNICODE_NORM_QC_NO},
+ {0x1FDD, UNICODE_NORM_QC_NO},
+ {0x1FDE, UNICODE_NORM_QC_NO},
+ {0x1FDF, UNICODE_NORM_QC_NO},
+ {0x1FE3, UNICODE_NORM_QC_NO},
+ {0x1FEB, UNICODE_NORM_QC_NO},
+ {0x1FED, UNICODE_NORM_QC_NO},
+ {0x1FEE, UNICODE_NORM_QC_NO},
+ {0x1FEF, UNICODE_NORM_QC_NO},
+ {0x1FF9, UNICODE_NORM_QC_NO},
+ {0x1FFB, UNICODE_NORM_QC_NO},
+ {0x1FFD, UNICODE_NORM_QC_NO},
+ {0x1FFE, UNICODE_NORM_QC_NO},
+ {0x2000, UNICODE_NORM_QC_NO},
+ {0x2001, UNICODE_NORM_QC_NO},
+ {0x2002, UNICODE_NORM_QC_NO},
+ {0x2003, UNICODE_NORM_QC_NO},
+ {0x2004, UNICODE_NORM_QC_NO},
+ {0x2005, UNICODE_NORM_QC_NO},
+ {0x2006, UNICODE_NORM_QC_NO},
+ {0x2007, UNICODE_NORM_QC_NO},
+ {0x2008, UNICODE_NORM_QC_NO},
+ {0x2009, UNICODE_NORM_QC_NO},
+ {0x200A, UNICODE_NORM_QC_NO},
+ {0x2011, UNICODE_NORM_QC_NO},
+ {0x2017, UNICODE_NORM_QC_NO},
+ {0x2024, UNICODE_NORM_QC_NO},
+ {0x2025, UNICODE_NORM_QC_NO},
+ {0x2026, UNICODE_NORM_QC_NO},
+ {0x202F, UNICODE_NORM_QC_NO},
+ {0x2033, UNICODE_NORM_QC_NO},
+ {0x2034, UNICODE_NORM_QC_NO},
+ {0x2036, UNICODE_NORM_QC_NO},
+ {0x2037, UNICODE_NORM_QC_NO},
+ {0x203C, UNICODE_NORM_QC_NO},
+ {0x203E, UNICODE_NORM_QC_NO},
+ {0x2047, UNICODE_NORM_QC_NO},
+ {0x2048, UNICODE_NORM_QC_NO},
+ {0x2049, UNICODE_NORM_QC_NO},
+ {0x2057, UNICODE_NORM_QC_NO},
+ {0x205F, UNICODE_NORM_QC_NO},
+ {0x2070, UNICODE_NORM_QC_NO},
+ {0x2071, UNICODE_NORM_QC_NO},
+ {0x2074, UNICODE_NORM_QC_NO},
+ {0x2075, UNICODE_NORM_QC_NO},
+ {0x2076, UNICODE_NORM_QC_NO},
+ {0x2077, UNICODE_NORM_QC_NO},
+ {0x2078, UNICODE_NORM_QC_NO},
+ {0x2079, UNICODE_NORM_QC_NO},
+ {0x207A, UNICODE_NORM_QC_NO},
+ {0x207B, UNICODE_NORM_QC_NO},
+ {0x207C, UNICODE_NORM_QC_NO},
+ {0x207D, UNICODE_NORM_QC_NO},
+ {0x207E, UNICODE_NORM_QC_NO},
+ {0x207F, UNICODE_NORM_QC_NO},
+ {0x2080, UNICODE_NORM_QC_NO},
+ {0x2081, UNICODE_NORM_QC_NO},
+ {0x2082, UNICODE_NORM_QC_NO},
+ {0x2083, UNICODE_NORM_QC_NO},
+ {0x2084, UNICODE_NORM_QC_NO},
+ {0x2085, UNICODE_NORM_QC_NO},
+ {0x2086, UNICODE_NORM_QC_NO},
+ {0x2087, UNICODE_NORM_QC_NO},
+ {0x2088, UNICODE_NORM_QC_NO},
+ {0x2089, UNICODE_NORM_QC_NO},
+ {0x208A, UNICODE_NORM_QC_NO},
+ {0x208B, UNICODE_NORM_QC_NO},
+ {0x208C, UNICODE_NORM_QC_NO},
+ {0x208D, UNICODE_NORM_QC_NO},
+ {0x208E, UNICODE_NORM_QC_NO},
+ {0x2090, UNICODE_NORM_QC_NO},
+ {0x2091, UNICODE_NORM_QC_NO},
+ {0x2092, UNICODE_NORM_QC_NO},
+ {0x2093, UNICODE_NORM_QC_NO},
+ {0x2094, UNICODE_NORM_QC_NO},
+ {0x2095, UNICODE_NORM_QC_NO},
+ {0x2096, UNICODE_NORM_QC_NO},
+ {0x2097, UNICODE_NORM_QC_NO},
+ {0x2098, UNICODE_NORM_QC_NO},
+ {0x2099, UNICODE_NORM_QC_NO},
+ {0x209A, UNICODE_NORM_QC_NO},
+ {0x209B, UNICODE_NORM_QC_NO},
+ {0x209C, UNICODE_NORM_QC_NO},
+ {0x20A8, UNICODE_NORM_QC_NO},
+ {0x2100, UNICODE_NORM_QC_NO},
+ {0x2101, UNICODE_NORM_QC_NO},
+ {0x2102, UNICODE_NORM_QC_NO},
+ {0x2103, UNICODE_NORM_QC_NO},
+ {0x2105, UNICODE_NORM_QC_NO},
+ {0x2106, UNICODE_NORM_QC_NO},
+ {0x2107, UNICODE_NORM_QC_NO},
+ {0x2109, UNICODE_NORM_QC_NO},
+ {0x210A, UNICODE_NORM_QC_NO},
+ {0x210B, UNICODE_NORM_QC_NO},
+ {0x210C, UNICODE_NORM_QC_NO},
+ {0x210D, UNICODE_NORM_QC_NO},
+ {0x210E, UNICODE_NORM_QC_NO},
+ {0x210F, UNICODE_NORM_QC_NO},
+ {0x2110, UNICODE_NORM_QC_NO},
+ {0x2111, UNICODE_NORM_QC_NO},
+ {0x2112, UNICODE_NORM_QC_NO},
+ {0x2113, UNICODE_NORM_QC_NO},
+ {0x2115, UNICODE_NORM_QC_NO},
+ {0x2116, UNICODE_NORM_QC_NO},
+ {0x2119, UNICODE_NORM_QC_NO},
+ {0x211A, UNICODE_NORM_QC_NO},
+ {0x211B, UNICODE_NORM_QC_NO},
+ {0x211C, UNICODE_NORM_QC_NO},
+ {0x211D, UNICODE_NORM_QC_NO},
+ {0x2120, UNICODE_NORM_QC_NO},
+ {0x2121, UNICODE_NORM_QC_NO},
+ {0x2122, UNICODE_NORM_QC_NO},
+ {0x2124, UNICODE_NORM_QC_NO},
+ {0x2126, UNICODE_NORM_QC_NO},
+ {0x2128, UNICODE_NORM_QC_NO},
+ {0x212A, UNICODE_NORM_QC_NO},
+ {0x212B, UNICODE_NORM_QC_NO},
+ {0x212C, UNICODE_NORM_QC_NO},
+ {0x212D, UNICODE_NORM_QC_NO},
+ {0x212F, UNICODE_NORM_QC_NO},
+ {0x2130, UNICODE_NORM_QC_NO},
+ {0x2131, UNICODE_NORM_QC_NO},
+ {0x2133, UNICODE_NORM_QC_NO},
+ {0x2134, UNICODE_NORM_QC_NO},
+ {0x2135, UNICODE_NORM_QC_NO},
+ {0x2136, UNICODE_NORM_QC_NO},
+ {0x2137, UNICODE_NORM_QC_NO},
+ {0x2138, UNICODE_NORM_QC_NO},
+ {0x2139, UNICODE_NORM_QC_NO},
+ {0x213B, UNICODE_NORM_QC_NO},
+ {0x213C, UNICODE_NORM_QC_NO},
+ {0x213D, UNICODE_NORM_QC_NO},
+ {0x213E, UNICODE_NORM_QC_NO},
+ {0x213F, UNICODE_NORM_QC_NO},
+ {0x2140, UNICODE_NORM_QC_NO},
+ {0x2145, UNICODE_NORM_QC_NO},
+ {0x2146, UNICODE_NORM_QC_NO},
+ {0x2147, UNICODE_NORM_QC_NO},
+ {0x2148, UNICODE_NORM_QC_NO},
+ {0x2149, UNICODE_NORM_QC_NO},
+ {0x2150, UNICODE_NORM_QC_NO},
+ {0x2151, UNICODE_NORM_QC_NO},
+ {0x2152, UNICODE_NORM_QC_NO},
+ {0x2153, UNICODE_NORM_QC_NO},
+ {0x2154, UNICODE_NORM_QC_NO},
+ {0x2155, UNICODE_NORM_QC_NO},
+ {0x2156, UNICODE_NORM_QC_NO},
+ {0x2157, UNICODE_NORM_QC_NO},
+ {0x2158, UNICODE_NORM_QC_NO},
+ {0x2159, UNICODE_NORM_QC_NO},
+ {0x215A, UNICODE_NORM_QC_NO},
+ {0x215B, UNICODE_NORM_QC_NO},
+ {0x215C, UNICODE_NORM_QC_NO},
+ {0x215D, UNICODE_NORM_QC_NO},
+ {0x215E, UNICODE_NORM_QC_NO},
+ {0x215F, UNICODE_NORM_QC_NO},
+ {0x2160, UNICODE_NORM_QC_NO},
+ {0x2161, UNICODE_NORM_QC_NO},
+ {0x2162, UNICODE_NORM_QC_NO},
+ {0x2163, UNICODE_NORM_QC_NO},
+ {0x2164, UNICODE_NORM_QC_NO},
+ {0x2165, UNICODE_NORM_QC_NO},
+ {0x2166, UNICODE_NORM_QC_NO},
+ {0x2167, UNICODE_NORM_QC_NO},
+ {0x2168, UNICODE_NORM_QC_NO},
+ {0x2169, UNICODE_NORM_QC_NO},
+ {0x216A, UNICODE_NORM_QC_NO},
+ {0x216B, UNICODE_NORM_QC_NO},
+ {0x216C, UNICODE_NORM_QC_NO},
+ {0x216D, UNICODE_NORM_QC_NO},
+ {0x216E, UNICODE_NORM_QC_NO},
+ {0x216F, UNICODE_NORM_QC_NO},
+ {0x2170, UNICODE_NORM_QC_NO},
+ {0x2171, UNICODE_NORM_QC_NO},
+ {0x2172, UNICODE_NORM_QC_NO},
+ {0x2173, UNICODE_NORM_QC_NO},
+ {0x2174, UNICODE_NORM_QC_NO},
+ {0x2175, UNICODE_NORM_QC_NO},
+ {0x2176, UNICODE_NORM_QC_NO},
+ {0x2177, UNICODE_NORM_QC_NO},
+ {0x2178, UNICODE_NORM_QC_NO},
+ {0x2179, UNICODE_NORM_QC_NO},
+ {0x217A, UNICODE_NORM_QC_NO},
+ {0x217B, UNICODE_NORM_QC_NO},
+ {0x217C, UNICODE_NORM_QC_NO},
+ {0x217D, UNICODE_NORM_QC_NO},
+ {0x217E, UNICODE_NORM_QC_NO},
+ {0x217F, UNICODE_NORM_QC_NO},
+ {0x2189, UNICODE_NORM_QC_NO},
+ {0x222C, UNICODE_NORM_QC_NO},
+ {0x222D, UNICODE_NORM_QC_NO},
+ {0x222F, UNICODE_NORM_QC_NO},
+ {0x2230, UNICODE_NORM_QC_NO},
+ {0x2329, UNICODE_NORM_QC_NO},
+ {0x232A, UNICODE_NORM_QC_NO},
+ {0x2460, UNICODE_NORM_QC_NO},
+ {0x2461, UNICODE_NORM_QC_NO},
+ {0x2462, UNICODE_NORM_QC_NO},
+ {0x2463, UNICODE_NORM_QC_NO},
+ {0x2464, UNICODE_NORM_QC_NO},
+ {0x2465, UNICODE_NORM_QC_NO},
+ {0x2466, UNICODE_NORM_QC_NO},
+ {0x2467, UNICODE_NORM_QC_NO},
+ {0x2468, UNICODE_NORM_QC_NO},
+ {0x2469, UNICODE_NORM_QC_NO},
+ {0x246A, UNICODE_NORM_QC_NO},
+ {0x246B, UNICODE_NORM_QC_NO},
+ {0x246C, UNICODE_NORM_QC_NO},
+ {0x246D, UNICODE_NORM_QC_NO},
+ {0x246E, UNICODE_NORM_QC_NO},
+ {0x246F, UNICODE_NORM_QC_NO},
+ {0x2470, UNICODE_NORM_QC_NO},
+ {0x2471, UNICODE_NORM_QC_NO},
+ {0x2472, UNICODE_NORM_QC_NO},
+ {0x2473, UNICODE_NORM_QC_NO},
+ {0x2474, UNICODE_NORM_QC_NO},
+ {0x2475, UNICODE_NORM_QC_NO},
+ {0x2476, UNICODE_NORM_QC_NO},
+ {0x2477, UNICODE_NORM_QC_NO},
+ {0x2478, UNICODE_NORM_QC_NO},
+ {0x2479, UNICODE_NORM_QC_NO},
+ {0x247A, UNICODE_NORM_QC_NO},
+ {0x247B, UNICODE_NORM_QC_NO},
+ {0x247C, UNICODE_NORM_QC_NO},
+ {0x247D, UNICODE_NORM_QC_NO},
+ {0x247E, UNICODE_NORM_QC_NO},
+ {0x247F, UNICODE_NORM_QC_NO},
+ {0x2480, UNICODE_NORM_QC_NO},
+ {0x2481, UNICODE_NORM_QC_NO},
+ {0x2482, UNICODE_NORM_QC_NO},
+ {0x2483, UNICODE_NORM_QC_NO},
+ {0x2484, UNICODE_NORM_QC_NO},
+ {0x2485, UNICODE_NORM_QC_NO},
+ {0x2486, UNICODE_NORM_QC_NO},
+ {0x2487, UNICODE_NORM_QC_NO},
+ {0x2488, UNICODE_NORM_QC_NO},
+ {0x2489, UNICODE_NORM_QC_NO},
+ {0x248A, UNICODE_NORM_QC_NO},
+ {0x248B, UNICODE_NORM_QC_NO},
+ {0x248C, UNICODE_NORM_QC_NO},
+ {0x248D, UNICODE_NORM_QC_NO},
+ {0x248E, UNICODE_NORM_QC_NO},
+ {0x248F, UNICODE_NORM_QC_NO},
+ {0x2490, UNICODE_NORM_QC_NO},
+ {0x2491, UNICODE_NORM_QC_NO},
+ {0x2492, UNICODE_NORM_QC_NO},
+ {0x2493, UNICODE_NORM_QC_NO},
+ {0x2494, UNICODE_NORM_QC_NO},
+ {0x2495, UNICODE_NORM_QC_NO},
+ {0x2496, UNICODE_NORM_QC_NO},
+ {0x2497, UNICODE_NORM_QC_NO},
+ {0x2498, UNICODE_NORM_QC_NO},
+ {0x2499, UNICODE_NORM_QC_NO},
+ {0x249A, UNICODE_NORM_QC_NO},
+ {0x249B, UNICODE_NORM_QC_NO},
+ {0x249C, UNICODE_NORM_QC_NO},
+ {0x249D, UNICODE_NORM_QC_NO},
+ {0x249E, UNICODE_NORM_QC_NO},
+ {0x249F, UNICODE_NORM_QC_NO},
+ {0x24A0, UNICODE_NORM_QC_NO},
+ {0x24A1, UNICODE_NORM_QC_NO},
+ {0x24A2, UNICODE_NORM_QC_NO},
+ {0x24A3, UNICODE_NORM_QC_NO},
+ {0x24A4, UNICODE_NORM_QC_NO},
+ {0x24A5, UNICODE_NORM_QC_NO},
+ {0x24A6, UNICODE_NORM_QC_NO},
+ {0x24A7, UNICODE_NORM_QC_NO},
+ {0x24A8, UNICODE_NORM_QC_NO},
+ {0x24A9, UNICODE_NORM_QC_NO},
+ {0x24AA, UNICODE_NORM_QC_NO},
+ {0x24AB, UNICODE_NORM_QC_NO},
+ {0x24AC, UNICODE_NORM_QC_NO},
+ {0x24AD, UNICODE_NORM_QC_NO},
+ {0x24AE, UNICODE_NORM_QC_NO},
+ {0x24AF, UNICODE_NORM_QC_NO},
+ {0x24B0, UNICODE_NORM_QC_NO},
+ {0x24B1, UNICODE_NORM_QC_NO},
+ {0x24B2, UNICODE_NORM_QC_NO},
+ {0x24B3, UNICODE_NORM_QC_NO},
+ {0x24B4, UNICODE_NORM_QC_NO},
+ {0x24B5, UNICODE_NORM_QC_NO},
+ {0x24B6, UNICODE_NORM_QC_NO},
+ {0x24B7, UNICODE_NORM_QC_NO},
+ {0x24B8, UNICODE_NORM_QC_NO},
+ {0x24B9, UNICODE_NORM_QC_NO},
+ {0x24BA, UNICODE_NORM_QC_NO},
+ {0x24BB, UNICODE_NORM_QC_NO},
+ {0x24BC, UNICODE_NORM_QC_NO},
+ {0x24BD, UNICODE_NORM_QC_NO},
+ {0x24BE, UNICODE_NORM_QC_NO},
+ {0x24BF, UNICODE_NORM_QC_NO},
+ {0x24C0, UNICODE_NORM_QC_NO},
+ {0x24C1, UNICODE_NORM_QC_NO},
+ {0x24C2, UNICODE_NORM_QC_NO},
+ {0x24C3, UNICODE_NORM_QC_NO},
+ {0x24C4, UNICODE_NORM_QC_NO},
+ {0x24C5, UNICODE_NORM_QC_NO},
+ {0x24C6, UNICODE_NORM_QC_NO},
+ {0x24C7, UNICODE_NORM_QC_NO},
+ {0x24C8, UNICODE_NORM_QC_NO},
+ {0x24C9, UNICODE_NORM_QC_NO},
+ {0x24CA, UNICODE_NORM_QC_NO},
+ {0x24CB, UNICODE_NORM_QC_NO},
+ {0x24CC, UNICODE_NORM_QC_NO},
+ {0x24CD, UNICODE_NORM_QC_NO},
+ {0x24CE, UNICODE_NORM_QC_NO},
+ {0x24CF, UNICODE_NORM_QC_NO},
+ {0x24D0, UNICODE_NORM_QC_NO},
+ {0x24D1, UNICODE_NORM_QC_NO},
+ {0x24D2, UNICODE_NORM_QC_NO},
+ {0x24D3, UNICODE_NORM_QC_NO},
+ {0x24D4, UNICODE_NORM_QC_NO},
+ {0x24D5, UNICODE_NORM_QC_NO},
+ {0x24D6, UNICODE_NORM_QC_NO},
+ {0x24D7, UNICODE_NORM_QC_NO},
+ {0x24D8, UNICODE_NORM_QC_NO},
+ {0x24D9, UNICODE_NORM_QC_NO},
+ {0x24DA, UNICODE_NORM_QC_NO},
+ {0x24DB, UNICODE_NORM_QC_NO},
+ {0x24DC, UNICODE_NORM_QC_NO},
+ {0x24DD, UNICODE_NORM_QC_NO},
+ {0x24DE, UNICODE_NORM_QC_NO},
+ {0x24DF, UNICODE_NORM_QC_NO},
+ {0x24E0, UNICODE_NORM_QC_NO},
+ {0x24E1, UNICODE_NORM_QC_NO},
+ {0x24E2, UNICODE_NORM_QC_NO},
+ {0x24E3, UNICODE_NORM_QC_NO},
+ {0x24E4, UNICODE_NORM_QC_NO},
+ {0x24E5, UNICODE_NORM_QC_NO},
+ {0x24E6, UNICODE_NORM_QC_NO},
+ {0x24E7, UNICODE_NORM_QC_NO},
+ {0x24E8, UNICODE_NORM_QC_NO},
+ {0x24E9, UNICODE_NORM_QC_NO},
+ {0x24EA, UNICODE_NORM_QC_NO},
+ {0x2A0C, UNICODE_NORM_QC_NO},
+ {0x2A74, UNICODE_NORM_QC_NO},
+ {0x2A75, UNICODE_NORM_QC_NO},
+ {0x2A76, UNICODE_NORM_QC_NO},
+ {0x2ADC, UNICODE_NORM_QC_NO},
+ {0x2C7C, UNICODE_NORM_QC_NO},
+ {0x2C7D, UNICODE_NORM_QC_NO},
+ {0x2D6F, UNICODE_NORM_QC_NO},
+ {0x2E9F, UNICODE_NORM_QC_NO},
+ {0x2EF3, UNICODE_NORM_QC_NO},
+ {0x2F00, UNICODE_NORM_QC_NO},
+ {0x2F01, UNICODE_NORM_QC_NO},
+ {0x2F02, UNICODE_NORM_QC_NO},
+ {0x2F03, UNICODE_NORM_QC_NO},
+ {0x2F04, UNICODE_NORM_QC_NO},
+ {0x2F05, UNICODE_NORM_QC_NO},
+ {0x2F06, UNICODE_NORM_QC_NO},
+ {0x2F07, UNICODE_NORM_QC_NO},
+ {0x2F08, UNICODE_NORM_QC_NO},
+ {0x2F09, UNICODE_NORM_QC_NO},
+ {0x2F0A, UNICODE_NORM_QC_NO},
+ {0x2F0B, UNICODE_NORM_QC_NO},
+ {0x2F0C, UNICODE_NORM_QC_NO},
+ {0x2F0D, UNICODE_NORM_QC_NO},
+ {0x2F0E, UNICODE_NORM_QC_NO},
+ {0x2F0F, UNICODE_NORM_QC_NO},
+ {0x2F10, UNICODE_NORM_QC_NO},
+ {0x2F11, UNICODE_NORM_QC_NO},
+ {0x2F12, UNICODE_NORM_QC_NO},
+ {0x2F13, UNICODE_NORM_QC_NO},
+ {0x2F14, UNICODE_NORM_QC_NO},
+ {0x2F15, UNICODE_NORM_QC_NO},
+ {0x2F16, UNICODE_NORM_QC_NO},
+ {0x2F17, UNICODE_NORM_QC_NO},
+ {0x2F18, UNICODE_NORM_QC_NO},
+ {0x2F19, UNICODE_NORM_QC_NO},
+ {0x2F1A, UNICODE_NORM_QC_NO},
+ {0x2F1B, UNICODE_NORM_QC_NO},
+ {0x2F1C, UNICODE_NORM_QC_NO},
+ {0x2F1D, UNICODE_NORM_QC_NO},
+ {0x2F1E, UNICODE_NORM_QC_NO},
+ {0x2F1F, UNICODE_NORM_QC_NO},
+ {0x2F20, UNICODE_NORM_QC_NO},
+ {0x2F21, UNICODE_NORM_QC_NO},
+ {0x2F22, UNICODE_NORM_QC_NO},
+ {0x2F23, UNICODE_NORM_QC_NO},
+ {0x2F24, UNICODE_NORM_QC_NO},
+ {0x2F25, UNICODE_NORM_QC_NO},
+ {0x2F26, UNICODE_NORM_QC_NO},
+ {0x2F27, UNICODE_NORM_QC_NO},
+ {0x2F28, UNICODE_NORM_QC_NO},
+ {0x2F29, UNICODE_NORM_QC_NO},
+ {0x2F2A, UNICODE_NORM_QC_NO},
+ {0x2F2B, UNICODE_NORM_QC_NO},
+ {0x2F2C, UNICODE_NORM_QC_NO},
+ {0x2F2D, UNICODE_NORM_QC_NO},
+ {0x2F2E, UNICODE_NORM_QC_NO},
+ {0x2F2F, UNICODE_NORM_QC_NO},
+ {0x2F30, UNICODE_NORM_QC_NO},
+ {0x2F31, UNICODE_NORM_QC_NO},
+ {0x2F32, UNICODE_NORM_QC_NO},
+ {0x2F33, UNICODE_NORM_QC_NO},
+ {0x2F34, UNICODE_NORM_QC_NO},
+ {0x2F35, UNICODE_NORM_QC_NO},
+ {0x2F36, UNICODE_NORM_QC_NO},
+ {0x2F37, UNICODE_NORM_QC_NO},
+ {0x2F38, UNICODE_NORM_QC_NO},
+ {0x2F39, UNICODE_NORM_QC_NO},
+ {0x2F3A, UNICODE_NORM_QC_NO},
+ {0x2F3B, UNICODE_NORM_QC_NO},
+ {0x2F3C, UNICODE_NORM_QC_NO},
+ {0x2F3D, UNICODE_NORM_QC_NO},
+ {0x2F3E, UNICODE_NORM_QC_NO},
+ {0x2F3F, UNICODE_NORM_QC_NO},
+ {0x2F40, UNICODE_NORM_QC_NO},
+ {0x2F41, UNICODE_NORM_QC_NO},
+ {0x2F42, UNICODE_NORM_QC_NO},
+ {0x2F43, UNICODE_NORM_QC_NO},
+ {0x2F44, UNICODE_NORM_QC_NO},
+ {0x2F45, UNICODE_NORM_QC_NO},
+ {0x2F46, UNICODE_NORM_QC_NO},
+ {0x2F47, UNICODE_NORM_QC_NO},
+ {0x2F48, UNICODE_NORM_QC_NO},
+ {0x2F49, UNICODE_NORM_QC_NO},
+ {0x2F4A, UNICODE_NORM_QC_NO},
+ {0x2F4B, UNICODE_NORM_QC_NO},
+ {0x2F4C, UNICODE_NORM_QC_NO},
+ {0x2F4D, UNICODE_NORM_QC_NO},
+ {0x2F4E, UNICODE_NORM_QC_NO},
+ {0x2F4F, UNICODE_NORM_QC_NO},
+ {0x2F50, UNICODE_NORM_QC_NO},
+ {0x2F51, UNICODE_NORM_QC_NO},
+ {0x2F52, UNICODE_NORM_QC_NO},
+ {0x2F53, UNICODE_NORM_QC_NO},
+ {0x2F54, UNICODE_NORM_QC_NO},
+ {0x2F55, UNICODE_NORM_QC_NO},
+ {0x2F56, UNICODE_NORM_QC_NO},
+ {0x2F57, UNICODE_NORM_QC_NO},
+ {0x2F58, UNICODE_NORM_QC_NO},
+ {0x2F59, UNICODE_NORM_QC_NO},
+ {0x2F5A, UNICODE_NORM_QC_NO},
+ {0x2F5B, UNICODE_NORM_QC_NO},
+ {0x2F5C, UNICODE_NORM_QC_NO},
+ {0x2F5D, UNICODE_NORM_QC_NO},
+ {0x2F5E, UNICODE_NORM_QC_NO},
+ {0x2F5F, UNICODE_NORM_QC_NO},
+ {0x2F60, UNICODE_NORM_QC_NO},
+ {0x2F61, UNICODE_NORM_QC_NO},
+ {0x2F62, UNICODE_NORM_QC_NO},
+ {0x2F63, UNICODE_NORM_QC_NO},
+ {0x2F64, UNICODE_NORM_QC_NO},
+ {0x2F65, UNICODE_NORM_QC_NO},
+ {0x2F66, UNICODE_NORM_QC_NO},
+ {0x2F67, UNICODE_NORM_QC_NO},
+ {0x2F68, UNICODE_NORM_QC_NO},
+ {0x2F69, UNICODE_NORM_QC_NO},
+ {0x2F6A, UNICODE_NORM_QC_NO},
+ {0x2F6B, UNICODE_NORM_QC_NO},
+ {0x2F6C, UNICODE_NORM_QC_NO},
+ {0x2F6D, UNICODE_NORM_QC_NO},
+ {0x2F6E, UNICODE_NORM_QC_NO},
+ {0x2F6F, UNICODE_NORM_QC_NO},
+ {0x2F70, UNICODE_NORM_QC_NO},
+ {0x2F71, UNICODE_NORM_QC_NO},
+ {0x2F72, UNICODE_NORM_QC_NO},
+ {0x2F73, UNICODE_NORM_QC_NO},
+ {0x2F74, UNICODE_NORM_QC_NO},
+ {0x2F75, UNICODE_NORM_QC_NO},
+ {0x2F76, UNICODE_NORM_QC_NO},
+ {0x2F77, UNICODE_NORM_QC_NO},
+ {0x2F78, UNICODE_NORM_QC_NO},
+ {0x2F79, UNICODE_NORM_QC_NO},
+ {0x2F7A, UNICODE_NORM_QC_NO},
+ {0x2F7B, UNICODE_NORM_QC_NO},
+ {0x2F7C, UNICODE_NORM_QC_NO},
+ {0x2F7D, UNICODE_NORM_QC_NO},
+ {0x2F7E, UNICODE_NORM_QC_NO},
+ {0x2F7F, UNICODE_NORM_QC_NO},
+ {0x2F80, UNICODE_NORM_QC_NO},
+ {0x2F81, UNICODE_NORM_QC_NO},
+ {0x2F82, UNICODE_NORM_QC_NO},
+ {0x2F83, UNICODE_NORM_QC_NO},
+ {0x2F84, UNICODE_NORM_QC_NO},
+ {0x2F85, UNICODE_NORM_QC_NO},
+ {0x2F86, UNICODE_NORM_QC_NO},
+ {0x2F87, UNICODE_NORM_QC_NO},
+ {0x2F88, UNICODE_NORM_QC_NO},
+ {0x2F89, UNICODE_NORM_QC_NO},
+ {0x2F8A, UNICODE_NORM_QC_NO},
+ {0x2F8B, UNICODE_NORM_QC_NO},
+ {0x2F8C, UNICODE_NORM_QC_NO},
+ {0x2F8D, UNICODE_NORM_QC_NO},
+ {0x2F8E, UNICODE_NORM_QC_NO},
+ {0x2F8F, UNICODE_NORM_QC_NO},
+ {0x2F90, UNICODE_NORM_QC_NO},
+ {0x2F91, UNICODE_NORM_QC_NO},
+ {0x2F92, UNICODE_NORM_QC_NO},
+ {0x2F93, UNICODE_NORM_QC_NO},
+ {0x2F94, UNICODE_NORM_QC_NO},
+ {0x2F95, UNICODE_NORM_QC_NO},
+ {0x2F96, UNICODE_NORM_QC_NO},
+ {0x2F97, UNICODE_NORM_QC_NO},
+ {0x2F98, UNICODE_NORM_QC_NO},
+ {0x2F99, UNICODE_NORM_QC_NO},
+ {0x2F9A, UNICODE_NORM_QC_NO},
+ {0x2F9B, UNICODE_NORM_QC_NO},
+ {0x2F9C, UNICODE_NORM_QC_NO},
+ {0x2F9D, UNICODE_NORM_QC_NO},
+ {0x2F9E, UNICODE_NORM_QC_NO},
+ {0x2F9F, UNICODE_NORM_QC_NO},
+ {0x2FA0, UNICODE_NORM_QC_NO},
+ {0x2FA1, UNICODE_NORM_QC_NO},
+ {0x2FA2, UNICODE_NORM_QC_NO},
+ {0x2FA3, UNICODE_NORM_QC_NO},
+ {0x2FA4, UNICODE_NORM_QC_NO},
+ {0x2FA5, UNICODE_NORM_QC_NO},
+ {0x2FA6, UNICODE_NORM_QC_NO},
+ {0x2FA7, UNICODE_NORM_QC_NO},
+ {0x2FA8, UNICODE_NORM_QC_NO},
+ {0x2FA9, UNICODE_NORM_QC_NO},
+ {0x2FAA, UNICODE_NORM_QC_NO},
+ {0x2FAB, UNICODE_NORM_QC_NO},
+ {0x2FAC, UNICODE_NORM_QC_NO},
+ {0x2FAD, UNICODE_NORM_QC_NO},
+ {0x2FAE, UNICODE_NORM_QC_NO},
+ {0x2FAF, UNICODE_NORM_QC_NO},
+ {0x2FB0, UNICODE_NORM_QC_NO},
+ {0x2FB1, UNICODE_NORM_QC_NO},
+ {0x2FB2, UNICODE_NORM_QC_NO},
+ {0x2FB3, UNICODE_NORM_QC_NO},
+ {0x2FB4, UNICODE_NORM_QC_NO},
+ {0x2FB5, UNICODE_NORM_QC_NO},
+ {0x2FB6, UNICODE_NORM_QC_NO},
+ {0x2FB7, UNICODE_NORM_QC_NO},
+ {0x2FB8, UNICODE_NORM_QC_NO},
+ {0x2FB9, UNICODE_NORM_QC_NO},
+ {0x2FBA, UNICODE_NORM_QC_NO},
+ {0x2FBB, UNICODE_NORM_QC_NO},
+ {0x2FBC, UNICODE_NORM_QC_NO},
+ {0x2FBD, UNICODE_NORM_QC_NO},
+ {0x2FBE, UNICODE_NORM_QC_NO},
+ {0x2FBF, UNICODE_NORM_QC_NO},
+ {0x2FC0, UNICODE_NORM_QC_NO},
+ {0x2FC1, UNICODE_NORM_QC_NO},
+ {0x2FC2, UNICODE_NORM_QC_NO},
+ {0x2FC3, UNICODE_NORM_QC_NO},
+ {0x2FC4, UNICODE_NORM_QC_NO},
+ {0x2FC5, UNICODE_NORM_QC_NO},
+ {0x2FC6, UNICODE_NORM_QC_NO},
+ {0x2FC7, UNICODE_NORM_QC_NO},
+ {0x2FC8, UNICODE_NORM_QC_NO},
+ {0x2FC9, UNICODE_NORM_QC_NO},
+ {0x2FCA, UNICODE_NORM_QC_NO},
+ {0x2FCB, UNICODE_NORM_QC_NO},
+ {0x2FCC, UNICODE_NORM_QC_NO},
+ {0x2FCD, UNICODE_NORM_QC_NO},
+ {0x2FCE, UNICODE_NORM_QC_NO},
+ {0x2FCF, UNICODE_NORM_QC_NO},
+ {0x2FD0, UNICODE_NORM_QC_NO},
+ {0x2FD1, UNICODE_NORM_QC_NO},
+ {0x2FD2, UNICODE_NORM_QC_NO},
+ {0x2FD3, UNICODE_NORM_QC_NO},
+ {0x2FD4, UNICODE_NORM_QC_NO},
+ {0x2FD5, UNICODE_NORM_QC_NO},
+ {0x3000, UNICODE_NORM_QC_NO},
+ {0x3036, UNICODE_NORM_QC_NO},
+ {0x3038, UNICODE_NORM_QC_NO},
+ {0x3039, UNICODE_NORM_QC_NO},
+ {0x303A, UNICODE_NORM_QC_NO},
+ {0x3099, UNICODE_NORM_QC_MAYBE},
+ {0x309A, UNICODE_NORM_QC_MAYBE},
+ {0x309B, UNICODE_NORM_QC_NO},
+ {0x309C, UNICODE_NORM_QC_NO},
+ {0x309F, UNICODE_NORM_QC_NO},
+ {0x30FF, UNICODE_NORM_QC_NO},
+ {0x3131, UNICODE_NORM_QC_NO},
+ {0x3132, UNICODE_NORM_QC_NO},
+ {0x3133, UNICODE_NORM_QC_NO},
+ {0x3134, UNICODE_NORM_QC_NO},
+ {0x3135, UNICODE_NORM_QC_NO},
+ {0x3136, UNICODE_NORM_QC_NO},
+ {0x3137, UNICODE_NORM_QC_NO},
+ {0x3138, UNICODE_NORM_QC_NO},
+ {0x3139, UNICODE_NORM_QC_NO},
+ {0x313A, UNICODE_NORM_QC_NO},
+ {0x313B, UNICODE_NORM_QC_NO},
+ {0x313C, UNICODE_NORM_QC_NO},
+ {0x313D, UNICODE_NORM_QC_NO},
+ {0x313E, UNICODE_NORM_QC_NO},
+ {0x313F, UNICODE_NORM_QC_NO},
+ {0x3140, UNICODE_NORM_QC_NO},
+ {0x3141, UNICODE_NORM_QC_NO},
+ {0x3142, UNICODE_NORM_QC_NO},
+ {0x3143, UNICODE_NORM_QC_NO},
+ {0x3144, UNICODE_NORM_QC_NO},
+ {0x3145, UNICODE_NORM_QC_NO},
+ {0x3146, UNICODE_NORM_QC_NO},
+ {0x3147, UNICODE_NORM_QC_NO},
+ {0x3148, UNICODE_NORM_QC_NO},
+ {0x3149, UNICODE_NORM_QC_NO},
+ {0x314A, UNICODE_NORM_QC_NO},
+ {0x314B, UNICODE_NORM_QC_NO},
+ {0x314C, UNICODE_NORM_QC_NO},
+ {0x314D, UNICODE_NORM_QC_NO},
+ {0x314E, UNICODE_NORM_QC_NO},
+ {0x314F, UNICODE_NORM_QC_NO},
+ {0x3150, UNICODE_NORM_QC_NO},
+ {0x3151, UNICODE_NORM_QC_NO},
+ {0x3152, UNICODE_NORM_QC_NO},
+ {0x3153, UNICODE_NORM_QC_NO},
+ {0x3154, UNICODE_NORM_QC_NO},
+ {0x3155, UNICODE_NORM_QC_NO},
+ {0x3156, UNICODE_NORM_QC_NO},
+ {0x3157, UNICODE_NORM_QC_NO},
+ {0x3158, UNICODE_NORM_QC_NO},
+ {0x3159, UNICODE_NORM_QC_NO},
+ {0x315A, UNICODE_NORM_QC_NO},
+ {0x315B, UNICODE_NORM_QC_NO},
+ {0x315C, UNICODE_NORM_QC_NO},
+ {0x315D, UNICODE_NORM_QC_NO},
+ {0x315E, UNICODE_NORM_QC_NO},
+ {0x315F, UNICODE_NORM_QC_NO},
+ {0x3160, UNICODE_NORM_QC_NO},
+ {0x3161, UNICODE_NORM_QC_NO},
+ {0x3162, UNICODE_NORM_QC_NO},
+ {0x3163, UNICODE_NORM_QC_NO},
+ {0x3164, UNICODE_NORM_QC_NO},
+ {0x3165, UNICODE_NORM_QC_NO},
+ {0x3166, UNICODE_NORM_QC_NO},
+ {0x3167, UNICODE_NORM_QC_NO},
+ {0x3168, UNICODE_NORM_QC_NO},
+ {0x3169, UNICODE_NORM_QC_NO},
+ {0x316A, UNICODE_NORM_QC_NO},
+ {0x316B, UNICODE_NORM_QC_NO},
+ {0x316C, UNICODE_NORM_QC_NO},
+ {0x316D, UNICODE_NORM_QC_NO},
+ {0x316E, UNICODE_NORM_QC_NO},
+ {0x316F, UNICODE_NORM_QC_NO},
+ {0x3170, UNICODE_NORM_QC_NO},
+ {0x3171, UNICODE_NORM_QC_NO},
+ {0x3172, UNICODE_NORM_QC_NO},
+ {0x3173, UNICODE_NORM_QC_NO},
+ {0x3174, UNICODE_NORM_QC_NO},
+ {0x3175, UNICODE_NORM_QC_NO},
+ {0x3176, UNICODE_NORM_QC_NO},
+ {0x3177, UNICODE_NORM_QC_NO},
+ {0x3178, UNICODE_NORM_QC_NO},
+ {0x3179, UNICODE_NORM_QC_NO},
+ {0x317A, UNICODE_NORM_QC_NO},
+ {0x317B, UNICODE_NORM_QC_NO},
+ {0x317C, UNICODE_NORM_QC_NO},
+ {0x317D, UNICODE_NORM_QC_NO},
+ {0x317E, UNICODE_NORM_QC_NO},
+ {0x317F, UNICODE_NORM_QC_NO},
+ {0x3180, UNICODE_NORM_QC_NO},
+ {0x3181, UNICODE_NORM_QC_NO},
+ {0x3182, UNICODE_NORM_QC_NO},
+ {0x3183, UNICODE_NORM_QC_NO},
+ {0x3184, UNICODE_NORM_QC_NO},
+ {0x3185, UNICODE_NORM_QC_NO},
+ {0x3186, UNICODE_NORM_QC_NO},
+ {0x3187, UNICODE_NORM_QC_NO},
+ {0x3188, UNICODE_NORM_QC_NO},
+ {0x3189, UNICODE_NORM_QC_NO},
+ {0x318A, UNICODE_NORM_QC_NO},
+ {0x318B, UNICODE_NORM_QC_NO},
+ {0x318C, UNICODE_NORM_QC_NO},
+ {0x318D, UNICODE_NORM_QC_NO},
+ {0x318E, UNICODE_NORM_QC_NO},
+ {0x3192, UNICODE_NORM_QC_NO},
+ {0x3193, UNICODE_NORM_QC_NO},
+ {0x3194, UNICODE_NORM_QC_NO},
+ {0x3195, UNICODE_NORM_QC_NO},
+ {0x3196, UNICODE_NORM_QC_NO},
+ {0x3197, UNICODE_NORM_QC_NO},
+ {0x3198, UNICODE_NORM_QC_NO},
+ {0x3199, UNICODE_NORM_QC_NO},
+ {0x319A, UNICODE_NORM_QC_NO},
+ {0x319B, UNICODE_NORM_QC_NO},
+ {0x319C, UNICODE_NORM_QC_NO},
+ {0x319D, UNICODE_NORM_QC_NO},
+ {0x319E, UNICODE_NORM_QC_NO},
+ {0x319F, UNICODE_NORM_QC_NO},
+ {0x3200, UNICODE_NORM_QC_NO},
+ {0x3201, UNICODE_NORM_QC_NO},
+ {0x3202, UNICODE_NORM_QC_NO},
+ {0x3203, UNICODE_NORM_QC_NO},
+ {0x3204, UNICODE_NORM_QC_NO},
+ {0x3205, UNICODE_NORM_QC_NO},
+ {0x3206, UNICODE_NORM_QC_NO},
+ {0x3207, UNICODE_NORM_QC_NO},
+ {0x3208, UNICODE_NORM_QC_NO},
+ {0x3209, UNICODE_NORM_QC_NO},
+ {0x320A, UNICODE_NORM_QC_NO},
+ {0x320B, UNICODE_NORM_QC_NO},
+ {0x320C, UNICODE_NORM_QC_NO},
+ {0x320D, UNICODE_NORM_QC_NO},
+ {0x320E, UNICODE_NORM_QC_NO},
+ {0x320F, UNICODE_NORM_QC_NO},
+ {0x3210, UNICODE_NORM_QC_NO},
+ {0x3211, UNICODE_NORM_QC_NO},
+ {0x3212, UNICODE_NORM_QC_NO},
+ {0x3213, UNICODE_NORM_QC_NO},
+ {0x3214, UNICODE_NORM_QC_NO},
+ {0x3215, UNICODE_NORM_QC_NO},
+ {0x3216, UNICODE_NORM_QC_NO},
+ {0x3217, UNICODE_NORM_QC_NO},
+ {0x3218, UNICODE_NORM_QC_NO},
+ {0x3219, UNICODE_NORM_QC_NO},
+ {0x321A, UNICODE_NORM_QC_NO},
+ {0x321B, UNICODE_NORM_QC_NO},
+ {0x321C, UNICODE_NORM_QC_NO},
+ {0x321D, UNICODE_NORM_QC_NO},
+ {0x321E, UNICODE_NORM_QC_NO},
+ {0x3220, UNICODE_NORM_QC_NO},
+ {0x3221, UNICODE_NORM_QC_NO},
+ {0x3222, UNICODE_NORM_QC_NO},
+ {0x3223, UNICODE_NORM_QC_NO},
+ {0x3224, UNICODE_NORM_QC_NO},
+ {0x3225, UNICODE_NORM_QC_NO},
+ {0x3226, UNICODE_NORM_QC_NO},
+ {0x3227, UNICODE_NORM_QC_NO},
+ {0x3228, UNICODE_NORM_QC_NO},
+ {0x3229, UNICODE_NORM_QC_NO},
+ {0x322A, UNICODE_NORM_QC_NO},
+ {0x322B, UNICODE_NORM_QC_NO},
+ {0x322C, UNICODE_NORM_QC_NO},
+ {0x322D, UNICODE_NORM_QC_NO},
+ {0x322E, UNICODE_NORM_QC_NO},
+ {0x322F, UNICODE_NORM_QC_NO},
+ {0x3230, UNICODE_NORM_QC_NO},
+ {0x3231, UNICODE_NORM_QC_NO},
+ {0x3232, UNICODE_NORM_QC_NO},
+ {0x3233, UNICODE_NORM_QC_NO},
+ {0x3234, UNICODE_NORM_QC_NO},
+ {0x3235, UNICODE_NORM_QC_NO},
+ {0x3236, UNICODE_NORM_QC_NO},
+ {0x3237, UNICODE_NORM_QC_NO},
+ {0x3238, UNICODE_NORM_QC_NO},
+ {0x3239, UNICODE_NORM_QC_NO},
+ {0x323A, UNICODE_NORM_QC_NO},
+ {0x323B, UNICODE_NORM_QC_NO},
+ {0x323C, UNICODE_NORM_QC_NO},
+ {0x323D, UNICODE_NORM_QC_NO},
+ {0x323E, UNICODE_NORM_QC_NO},
+ {0x323F, UNICODE_NORM_QC_NO},
+ {0x3240, UNICODE_NORM_QC_NO},
+ {0x3241, UNICODE_NORM_QC_NO},
+ {0x3242, UNICODE_NORM_QC_NO},
+ {0x3243, UNICODE_NORM_QC_NO},
+ {0x3244, UNICODE_NORM_QC_NO},
+ {0x3245, UNICODE_NORM_QC_NO},
+ {0x3246, UNICODE_NORM_QC_NO},
+ {0x3247, UNICODE_NORM_QC_NO},
+ {0x3250, UNICODE_NORM_QC_NO},
+ {0x3251, UNICODE_NORM_QC_NO},
+ {0x3252, UNICODE_NORM_QC_NO},
+ {0x3253, UNICODE_NORM_QC_NO},
+ {0x3254, UNICODE_NORM_QC_NO},
+ {0x3255, UNICODE_NORM_QC_NO},
+ {0x3256, UNICODE_NORM_QC_NO},
+ {0x3257, UNICODE_NORM_QC_NO},
+ {0x3258, UNICODE_NORM_QC_NO},
+ {0x3259, UNICODE_NORM_QC_NO},
+ {0x325A, UNICODE_NORM_QC_NO},
+ {0x325B, UNICODE_NORM_QC_NO},
+ {0x325C, UNICODE_NORM_QC_NO},
+ {0x325D, UNICODE_NORM_QC_NO},
+ {0x325E, UNICODE_NORM_QC_NO},
+ {0x325F, UNICODE_NORM_QC_NO},
+ {0x3260, UNICODE_NORM_QC_NO},
+ {0x3261, UNICODE_NORM_QC_NO},
+ {0x3262, UNICODE_NORM_QC_NO},
+ {0x3263, UNICODE_NORM_QC_NO},
+ {0x3264, UNICODE_NORM_QC_NO},
+ {0x3265, UNICODE_NORM_QC_NO},
+ {0x3266, UNICODE_NORM_QC_NO},
+ {0x3267, UNICODE_NORM_QC_NO},
+ {0x3268, UNICODE_NORM_QC_NO},
+ {0x3269, UNICODE_NORM_QC_NO},
+ {0x326A, UNICODE_NORM_QC_NO},
+ {0x326B, UNICODE_NORM_QC_NO},
+ {0x326C, UNICODE_NORM_QC_NO},
+ {0x326D, UNICODE_NORM_QC_NO},
+ {0x326E, UNICODE_NORM_QC_NO},
+ {0x326F, UNICODE_NORM_QC_NO},
+ {0x3270, UNICODE_NORM_QC_NO},
+ {0x3271, UNICODE_NORM_QC_NO},
+ {0x3272, UNICODE_NORM_QC_NO},
+ {0x3273, UNICODE_NORM_QC_NO},
+ {0x3274, UNICODE_NORM_QC_NO},
+ {0x3275, UNICODE_NORM_QC_NO},
+ {0x3276, UNICODE_NORM_QC_NO},
+ {0x3277, UNICODE_NORM_QC_NO},
+ {0x3278, UNICODE_NORM_QC_NO},
+ {0x3279, UNICODE_NORM_QC_NO},
+ {0x327A, UNICODE_NORM_QC_NO},
+ {0x327B, UNICODE_NORM_QC_NO},
+ {0x327C, UNICODE_NORM_QC_NO},
+ {0x327D, UNICODE_NORM_QC_NO},
+ {0x327E, UNICODE_NORM_QC_NO},
+ {0x3280, UNICODE_NORM_QC_NO},
+ {0x3281, UNICODE_NORM_QC_NO},
+ {0x3282, UNICODE_NORM_QC_NO},
+ {0x3283, UNICODE_NORM_QC_NO},
+ {0x3284, UNICODE_NORM_QC_NO},
+ {0x3285, UNICODE_NORM_QC_NO},
+ {0x3286, UNICODE_NORM_QC_NO},
+ {0x3287, UNICODE_NORM_QC_NO},
+ {0x3288, UNICODE_NORM_QC_NO},
+ {0x3289, UNICODE_NORM_QC_NO},
+ {0x328A, UNICODE_NORM_QC_NO},
+ {0x328B, UNICODE_NORM_QC_NO},
+ {0x328C, UNICODE_NORM_QC_NO},
+ {0x328D, UNICODE_NORM_QC_NO},
+ {0x328E, UNICODE_NORM_QC_NO},
+ {0x328F, UNICODE_NORM_QC_NO},
+ {0x3290, UNICODE_NORM_QC_NO},
+ {0x3291, UNICODE_NORM_QC_NO},
+ {0x3292, UNICODE_NORM_QC_NO},
+ {0x3293, UNICODE_NORM_QC_NO},
+ {0x3294, UNICODE_NORM_QC_NO},
+ {0x3295, UNICODE_NORM_QC_NO},
+ {0x3296, UNICODE_NORM_QC_NO},
+ {0x3297, UNICODE_NORM_QC_NO},
+ {0x3298, UNICODE_NORM_QC_NO},
+ {0x3299, UNICODE_NORM_QC_NO},
+ {0x329A, UNICODE_NORM_QC_NO},
+ {0x329B, UNICODE_NORM_QC_NO},
+ {0x329C, UNICODE_NORM_QC_NO},
+ {0x329D, UNICODE_NORM_QC_NO},
+ {0x329E, UNICODE_NORM_QC_NO},
+ {0x329F, UNICODE_NORM_QC_NO},
+ {0x32A0, UNICODE_NORM_QC_NO},
+ {0x32A1, UNICODE_NORM_QC_NO},
+ {0x32A2, UNICODE_NORM_QC_NO},
+ {0x32A3, UNICODE_NORM_QC_NO},
+ {0x32A4, UNICODE_NORM_QC_NO},
+ {0x32A5, UNICODE_NORM_QC_NO},
+ {0x32A6, UNICODE_NORM_QC_NO},
+ {0x32A7, UNICODE_NORM_QC_NO},
+ {0x32A8, UNICODE_NORM_QC_NO},
+ {0x32A9, UNICODE_NORM_QC_NO},
+ {0x32AA, UNICODE_NORM_QC_NO},
+ {0x32AB, UNICODE_NORM_QC_NO},
+ {0x32AC, UNICODE_NORM_QC_NO},
+ {0x32AD, UNICODE_NORM_QC_NO},
+ {0x32AE, UNICODE_NORM_QC_NO},
+ {0x32AF, UNICODE_NORM_QC_NO},
+ {0x32B0, UNICODE_NORM_QC_NO},
+ {0x32B1, UNICODE_NORM_QC_NO},
+ {0x32B2, UNICODE_NORM_QC_NO},
+ {0x32B3, UNICODE_NORM_QC_NO},
+ {0x32B4, UNICODE_NORM_QC_NO},
+ {0x32B5, UNICODE_NORM_QC_NO},
+ {0x32B6, UNICODE_NORM_QC_NO},
+ {0x32B7, UNICODE_NORM_QC_NO},
+ {0x32B8, UNICODE_NORM_QC_NO},
+ {0x32B9, UNICODE_NORM_QC_NO},
+ {0x32BA, UNICODE_NORM_QC_NO},
+ {0x32BB, UNICODE_NORM_QC_NO},
+ {0x32BC, UNICODE_NORM_QC_NO},
+ {0x32BD, UNICODE_NORM_QC_NO},
+ {0x32BE, UNICODE_NORM_QC_NO},
+ {0x32BF, UNICODE_NORM_QC_NO},
+ {0x32C0, UNICODE_NORM_QC_NO},
+ {0x32C1, UNICODE_NORM_QC_NO},
+ {0x32C2, UNICODE_NORM_QC_NO},
+ {0x32C3, UNICODE_NORM_QC_NO},
+ {0x32C4, UNICODE_NORM_QC_NO},
+ {0x32C5, UNICODE_NORM_QC_NO},
+ {0x32C6, UNICODE_NORM_QC_NO},
+ {0x32C7, UNICODE_NORM_QC_NO},
+ {0x32C8, UNICODE_NORM_QC_NO},
+ {0x32C9, UNICODE_NORM_QC_NO},
+ {0x32CA, UNICODE_NORM_QC_NO},
+ {0x32CB, UNICODE_NORM_QC_NO},
+ {0x32CC, UNICODE_NORM_QC_NO},
+ {0x32CD, UNICODE_NORM_QC_NO},
+ {0x32CE, UNICODE_NORM_QC_NO},
+ {0x32CF, UNICODE_NORM_QC_NO},
+ {0x32D0, UNICODE_NORM_QC_NO},
+ {0x32D1, UNICODE_NORM_QC_NO},
+ {0x32D2, UNICODE_NORM_QC_NO},
+ {0x32D3, UNICODE_NORM_QC_NO},
+ {0x32D4, UNICODE_NORM_QC_NO},
+ {0x32D5, UNICODE_NORM_QC_NO},
+ {0x32D6, UNICODE_NORM_QC_NO},
+ {0x32D7, UNICODE_NORM_QC_NO},
+ {0x32D8, UNICODE_NORM_QC_NO},
+ {0x32D9, UNICODE_NORM_QC_NO},
+ {0x32DA, UNICODE_NORM_QC_NO},
+ {0x32DB, UNICODE_NORM_QC_NO},
+ {0x32DC, UNICODE_NORM_QC_NO},
+ {0x32DD, UNICODE_NORM_QC_NO},
+ {0x32DE, UNICODE_NORM_QC_NO},
+ {0x32DF, UNICODE_NORM_QC_NO},
+ {0x32E0, UNICODE_NORM_QC_NO},
+ {0x32E1, UNICODE_NORM_QC_NO},
+ {0x32E2, UNICODE_NORM_QC_NO},
+ {0x32E3, UNICODE_NORM_QC_NO},
+ {0x32E4, UNICODE_NORM_QC_NO},
+ {0x32E5, UNICODE_NORM_QC_NO},
+ {0x32E6, UNICODE_NORM_QC_NO},
+ {0x32E7, UNICODE_NORM_QC_NO},
+ {0x32E8, UNICODE_NORM_QC_NO},
+ {0x32E9, UNICODE_NORM_QC_NO},
+ {0x32EA, UNICODE_NORM_QC_NO},
+ {0x32EB, UNICODE_NORM_QC_NO},
+ {0x32EC, UNICODE_NORM_QC_NO},
+ {0x32ED, UNICODE_NORM_QC_NO},
+ {0x32EE, UNICODE_NORM_QC_NO},
+ {0x32EF, UNICODE_NORM_QC_NO},
+ {0x32F0, UNICODE_NORM_QC_NO},
+ {0x32F1, UNICODE_NORM_QC_NO},
+ {0x32F2, UNICODE_NORM_QC_NO},
+ {0x32F3, UNICODE_NORM_QC_NO},
+ {0x32F4, UNICODE_NORM_QC_NO},
+ {0x32F5, UNICODE_NORM_QC_NO},
+ {0x32F6, UNICODE_NORM_QC_NO},
+ {0x32F7, UNICODE_NORM_QC_NO},
+ {0x32F8, UNICODE_NORM_QC_NO},
+ {0x32F9, UNICODE_NORM_QC_NO},
+ {0x32FA, UNICODE_NORM_QC_NO},
+ {0x32FB, UNICODE_NORM_QC_NO},
+ {0x32FC, UNICODE_NORM_QC_NO},
+ {0x32FD, UNICODE_NORM_QC_NO},
+ {0x32FE, UNICODE_NORM_QC_NO},
+ {0x32FF, UNICODE_NORM_QC_NO},
+ {0x3300, UNICODE_NORM_QC_NO},
+ {0x3301, UNICODE_NORM_QC_NO},
+ {0x3302, UNICODE_NORM_QC_NO},
+ {0x3303, UNICODE_NORM_QC_NO},
+ {0x3304, UNICODE_NORM_QC_NO},
+ {0x3305, UNICODE_NORM_QC_NO},
+ {0x3306, UNICODE_NORM_QC_NO},
+ {0x3307, UNICODE_NORM_QC_NO},
+ {0x3308, UNICODE_NORM_QC_NO},
+ {0x3309, UNICODE_NORM_QC_NO},
+ {0x330A, UNICODE_NORM_QC_NO},
+ {0x330B, UNICODE_NORM_QC_NO},
+ {0x330C, UNICODE_NORM_QC_NO},
+ {0x330D, UNICODE_NORM_QC_NO},
+ {0x330E, UNICODE_NORM_QC_NO},
+ {0x330F, UNICODE_NORM_QC_NO},
+ {0x3310, UNICODE_NORM_QC_NO},
+ {0x3311, UNICODE_NORM_QC_NO},
+ {0x3312, UNICODE_NORM_QC_NO},
+ {0x3313, UNICODE_NORM_QC_NO},
+ {0x3314, UNICODE_NORM_QC_NO},
+ {0x3315, UNICODE_NORM_QC_NO},
+ {0x3316, UNICODE_NORM_QC_NO},
+ {0x3317, UNICODE_NORM_QC_NO},
+ {0x3318, UNICODE_NORM_QC_NO},
+ {0x3319, UNICODE_NORM_QC_NO},
+ {0x331A, UNICODE_NORM_QC_NO},
+ {0x331B, UNICODE_NORM_QC_NO},
+ {0x331C, UNICODE_NORM_QC_NO},
+ {0x331D, UNICODE_NORM_QC_NO},
+ {0x331E, UNICODE_NORM_QC_NO},
+ {0x331F, UNICODE_NORM_QC_NO},
+ {0x3320, UNICODE_NORM_QC_NO},
+ {0x3321, UNICODE_NORM_QC_NO},
+ {0x3322, UNICODE_NORM_QC_NO},
+ {0x3323, UNICODE_NORM_QC_NO},
+ {0x3324, UNICODE_NORM_QC_NO},
+ {0x3325, UNICODE_NORM_QC_NO},
+ {0x3326, UNICODE_NORM_QC_NO},
+ {0x3327, UNICODE_NORM_QC_NO},
+ {0x3328, UNICODE_NORM_QC_NO},
+ {0x3329, UNICODE_NORM_QC_NO},
+ {0x332A, UNICODE_NORM_QC_NO},
+ {0x332B, UNICODE_NORM_QC_NO},
+ {0x332C, UNICODE_NORM_QC_NO},
+ {0x332D, UNICODE_NORM_QC_NO},
+ {0x332E, UNICODE_NORM_QC_NO},
+ {0x332F, UNICODE_NORM_QC_NO},
+ {0x3330, UNICODE_NORM_QC_NO},
+ {0x3331, UNICODE_NORM_QC_NO},
+ {0x3332, UNICODE_NORM_QC_NO},
+ {0x3333, UNICODE_NORM_QC_NO},
+ {0x3334, UNICODE_NORM_QC_NO},
+ {0x3335, UNICODE_NORM_QC_NO},
+ {0x3336, UNICODE_NORM_QC_NO},
+ {0x3337, UNICODE_NORM_QC_NO},
+ {0x3338, UNICODE_NORM_QC_NO},
+ {0x3339, UNICODE_NORM_QC_NO},
+ {0x333A, UNICODE_NORM_QC_NO},
+ {0x333B, UNICODE_NORM_QC_NO},
+ {0x333C, UNICODE_NORM_QC_NO},
+ {0x333D, UNICODE_NORM_QC_NO},
+ {0x333E, UNICODE_NORM_QC_NO},
+ {0x333F, UNICODE_NORM_QC_NO},
+ {0x3340, UNICODE_NORM_QC_NO},
+ {0x3341, UNICODE_NORM_QC_NO},
+ {0x3342, UNICODE_NORM_QC_NO},
+ {0x3343, UNICODE_NORM_QC_NO},
+ {0x3344, UNICODE_NORM_QC_NO},
+ {0x3345, UNICODE_NORM_QC_NO},
+ {0x3346, UNICODE_NORM_QC_NO},
+ {0x3347, UNICODE_NORM_QC_NO},
+ {0x3348, UNICODE_NORM_QC_NO},
+ {0x3349, UNICODE_NORM_QC_NO},
+ {0x334A, UNICODE_NORM_QC_NO},
+ {0x334B, UNICODE_NORM_QC_NO},
+ {0x334C, UNICODE_NORM_QC_NO},
+ {0x334D, UNICODE_NORM_QC_NO},
+ {0x334E, UNICODE_NORM_QC_NO},
+ {0x334F, UNICODE_NORM_QC_NO},
+ {0x3350, UNICODE_NORM_QC_NO},
+ {0x3351, UNICODE_NORM_QC_NO},
+ {0x3352, UNICODE_NORM_QC_NO},
+ {0x3353, UNICODE_NORM_QC_NO},
+ {0x3354, UNICODE_NORM_QC_NO},
+ {0x3355, UNICODE_NORM_QC_NO},
+ {0x3356, UNICODE_NORM_QC_NO},
+ {0x3357, UNICODE_NORM_QC_NO},
+ {0x3358, UNICODE_NORM_QC_NO},
+ {0x3359, UNICODE_NORM_QC_NO},
+ {0x335A, UNICODE_NORM_QC_NO},
+ {0x335B, UNICODE_NORM_QC_NO},
+ {0x335C, UNICODE_NORM_QC_NO},
+ {0x335D, UNICODE_NORM_QC_NO},
+ {0x335E, UNICODE_NORM_QC_NO},
+ {0x335F, UNICODE_NORM_QC_NO},
+ {0x3360, UNICODE_NORM_QC_NO},
+ {0x3361, UNICODE_NORM_QC_NO},
+ {0x3362, UNICODE_NORM_QC_NO},
+ {0x3363, UNICODE_NORM_QC_NO},
+ {0x3364, UNICODE_NORM_QC_NO},
+ {0x3365, UNICODE_NORM_QC_NO},
+ {0x3366, UNICODE_NORM_QC_NO},
+ {0x3367, UNICODE_NORM_QC_NO},
+ {0x3368, UNICODE_NORM_QC_NO},
+ {0x3369, UNICODE_NORM_QC_NO},
+ {0x336A, UNICODE_NORM_QC_NO},
+ {0x336B, UNICODE_NORM_QC_NO},
+ {0x336C, UNICODE_NORM_QC_NO},
+ {0x336D, UNICODE_NORM_QC_NO},
+ {0x336E, UNICODE_NORM_QC_NO},
+ {0x336F, UNICODE_NORM_QC_NO},
+ {0x3370, UNICODE_NORM_QC_NO},
+ {0x3371, UNICODE_NORM_QC_NO},
+ {0x3372, UNICODE_NORM_QC_NO},
+ {0x3373, UNICODE_NORM_QC_NO},
+ {0x3374, UNICODE_NORM_QC_NO},
+ {0x3375, UNICODE_NORM_QC_NO},
+ {0x3376, UNICODE_NORM_QC_NO},
+ {0x3377, UNICODE_NORM_QC_NO},
+ {0x3378, UNICODE_NORM_QC_NO},
+ {0x3379, UNICODE_NORM_QC_NO},
+ {0x337A, UNICODE_NORM_QC_NO},
+ {0x337B, UNICODE_NORM_QC_NO},
+ {0x337C, UNICODE_NORM_QC_NO},
+ {0x337D, UNICODE_NORM_QC_NO},
+ {0x337E, UNICODE_NORM_QC_NO},
+ {0x337F, UNICODE_NORM_QC_NO},
+ {0x3380, UNICODE_NORM_QC_NO},
+ {0x3381, UNICODE_NORM_QC_NO},
+ {0x3382, UNICODE_NORM_QC_NO},
+ {0x3383, UNICODE_NORM_QC_NO},
+ {0x3384, UNICODE_NORM_QC_NO},
+ {0x3385, UNICODE_NORM_QC_NO},
+ {0x3386, UNICODE_NORM_QC_NO},
+ {0x3387, UNICODE_NORM_QC_NO},
+ {0x3388, UNICODE_NORM_QC_NO},
+ {0x3389, UNICODE_NORM_QC_NO},
+ {0x338A, UNICODE_NORM_QC_NO},
+ {0x338B, UNICODE_NORM_QC_NO},
+ {0x338C, UNICODE_NORM_QC_NO},
+ {0x338D, UNICODE_NORM_QC_NO},
+ {0x338E, UNICODE_NORM_QC_NO},
+ {0x338F, UNICODE_NORM_QC_NO},
+ {0x3390, UNICODE_NORM_QC_NO},
+ {0x3391, UNICODE_NORM_QC_NO},
+ {0x3392, UNICODE_NORM_QC_NO},
+ {0x3393, UNICODE_NORM_QC_NO},
+ {0x3394, UNICODE_NORM_QC_NO},
+ {0x3395, UNICODE_NORM_QC_NO},
+ {0x3396, UNICODE_NORM_QC_NO},
+ {0x3397, UNICODE_NORM_QC_NO},
+ {0x3398, UNICODE_NORM_QC_NO},
+ {0x3399, UNICODE_NORM_QC_NO},
+ {0x339A, UNICODE_NORM_QC_NO},
+ {0x339B, UNICODE_NORM_QC_NO},
+ {0x339C, UNICODE_NORM_QC_NO},
+ {0x339D, UNICODE_NORM_QC_NO},
+ {0x339E, UNICODE_NORM_QC_NO},
+ {0x339F, UNICODE_NORM_QC_NO},
+ {0x33A0, UNICODE_NORM_QC_NO},
+ {0x33A1, UNICODE_NORM_QC_NO},
+ {0x33A2, UNICODE_NORM_QC_NO},
+ {0x33A3, UNICODE_NORM_QC_NO},
+ {0x33A4, UNICODE_NORM_QC_NO},
+ {0x33A5, UNICODE_NORM_QC_NO},
+ {0x33A6, UNICODE_NORM_QC_NO},
+ {0x33A7, UNICODE_NORM_QC_NO},
+ {0x33A8, UNICODE_NORM_QC_NO},
+ {0x33A9, UNICODE_NORM_QC_NO},
+ {0x33AA, UNICODE_NORM_QC_NO},
+ {0x33AB, UNICODE_NORM_QC_NO},
+ {0x33AC, UNICODE_NORM_QC_NO},
+ {0x33AD, UNICODE_NORM_QC_NO},
+ {0x33AE, UNICODE_NORM_QC_NO},
+ {0x33AF, UNICODE_NORM_QC_NO},
+ {0x33B0, UNICODE_NORM_QC_NO},
+ {0x33B1, UNICODE_NORM_QC_NO},
+ {0x33B2, UNICODE_NORM_QC_NO},
+ {0x33B3, UNICODE_NORM_QC_NO},
+ {0x33B4, UNICODE_NORM_QC_NO},
+ {0x33B5, UNICODE_NORM_QC_NO},
+ {0x33B6, UNICODE_NORM_QC_NO},
+ {0x33B7, UNICODE_NORM_QC_NO},
+ {0x33B8, UNICODE_NORM_QC_NO},
+ {0x33B9, UNICODE_NORM_QC_NO},
+ {0x33BA, UNICODE_NORM_QC_NO},
+ {0x33BB, UNICODE_NORM_QC_NO},
+ {0x33BC, UNICODE_NORM_QC_NO},
+ {0x33BD, UNICODE_NORM_QC_NO},
+ {0x33BE, UNICODE_NORM_QC_NO},
+ {0x33BF, UNICODE_NORM_QC_NO},
+ {0x33C0, UNICODE_NORM_QC_NO},
+ {0x33C1, UNICODE_NORM_QC_NO},
+ {0x33C2, UNICODE_NORM_QC_NO},
+ {0x33C3, UNICODE_NORM_QC_NO},
+ {0x33C4, UNICODE_NORM_QC_NO},
+ {0x33C5, UNICODE_NORM_QC_NO},
+ {0x33C6, UNICODE_NORM_QC_NO},
+ {0x33C7, UNICODE_NORM_QC_NO},
+ {0x33C8, UNICODE_NORM_QC_NO},
+ {0x33C9, UNICODE_NORM_QC_NO},
+ {0x33CA, UNICODE_NORM_QC_NO},
+ {0x33CB, UNICODE_NORM_QC_NO},
+ {0x33CC, UNICODE_NORM_QC_NO},
+ {0x33CD, UNICODE_NORM_QC_NO},
+ {0x33CE, UNICODE_NORM_QC_NO},
+ {0x33CF, UNICODE_NORM_QC_NO},
+ {0x33D0, UNICODE_NORM_QC_NO},
+ {0x33D1, UNICODE_NORM_QC_NO},
+ {0x33D2, UNICODE_NORM_QC_NO},
+ {0x33D3, UNICODE_NORM_QC_NO},
+ {0x33D4, UNICODE_NORM_QC_NO},
+ {0x33D5, UNICODE_NORM_QC_NO},
+ {0x33D6, UNICODE_NORM_QC_NO},
+ {0x33D7, UNICODE_NORM_QC_NO},
+ {0x33D8, UNICODE_NORM_QC_NO},
+ {0x33D9, UNICODE_NORM_QC_NO},
+ {0x33DA, UNICODE_NORM_QC_NO},
+ {0x33DB, UNICODE_NORM_QC_NO},
+ {0x33DC, UNICODE_NORM_QC_NO},
+ {0x33DD, UNICODE_NORM_QC_NO},
+ {0x33DE, UNICODE_NORM_QC_NO},
+ {0x33DF, UNICODE_NORM_QC_NO},
+ {0x33E0, UNICODE_NORM_QC_NO},
+ {0x33E1, UNICODE_NORM_QC_NO},
+ {0x33E2, UNICODE_NORM_QC_NO},
+ {0x33E3, UNICODE_NORM_QC_NO},
+ {0x33E4, UNICODE_NORM_QC_NO},
+ {0x33E5, UNICODE_NORM_QC_NO},
+ {0x33E6, UNICODE_NORM_QC_NO},
+ {0x33E7, UNICODE_NORM_QC_NO},
+ {0x33E8, UNICODE_NORM_QC_NO},
+ {0x33E9, UNICODE_NORM_QC_NO},
+ {0x33EA, UNICODE_NORM_QC_NO},
+ {0x33EB, UNICODE_NORM_QC_NO},
+ {0x33EC, UNICODE_NORM_QC_NO},
+ {0x33ED, UNICODE_NORM_QC_NO},
+ {0x33EE, UNICODE_NORM_QC_NO},
+ {0x33EF, UNICODE_NORM_QC_NO},
+ {0x33F0, UNICODE_NORM_QC_NO},
+ {0x33F1, UNICODE_NORM_QC_NO},
+ {0x33F2, UNICODE_NORM_QC_NO},
+ {0x33F3, UNICODE_NORM_QC_NO},
+ {0x33F4, UNICODE_NORM_QC_NO},
+ {0x33F5, UNICODE_NORM_QC_NO},
+ {0x33F6, UNICODE_NORM_QC_NO},
+ {0x33F7, UNICODE_NORM_QC_NO},
+ {0x33F8, UNICODE_NORM_QC_NO},
+ {0x33F9, UNICODE_NORM_QC_NO},
+ {0x33FA, UNICODE_NORM_QC_NO},
+ {0x33FB, UNICODE_NORM_QC_NO},
+ {0x33FC, UNICODE_NORM_QC_NO},
+ {0x33FD, UNICODE_NORM_QC_NO},
+ {0x33FE, UNICODE_NORM_QC_NO},
+ {0x33FF, UNICODE_NORM_QC_NO},
+ {0xA69C, UNICODE_NORM_QC_NO},
+ {0xA69D, UNICODE_NORM_QC_NO},
+ {0xA770, UNICODE_NORM_QC_NO},
+ {0xA7F8, UNICODE_NORM_QC_NO},
+ {0xA7F9, UNICODE_NORM_QC_NO},
+ {0xAB5C, UNICODE_NORM_QC_NO},
+ {0xAB5D, UNICODE_NORM_QC_NO},
+ {0xAB5E, UNICODE_NORM_QC_NO},
+ {0xAB5F, UNICODE_NORM_QC_NO},
+ {0xAB69, UNICODE_NORM_QC_NO},
+ {0xF900, UNICODE_NORM_QC_NO},
+ {0xF901, UNICODE_NORM_QC_NO},
+ {0xF902, UNICODE_NORM_QC_NO},
+ {0xF903, UNICODE_NORM_QC_NO},
+ {0xF904, UNICODE_NORM_QC_NO},
+ {0xF905, UNICODE_NORM_QC_NO},
+ {0xF906, UNICODE_NORM_QC_NO},
+ {0xF907, UNICODE_NORM_QC_NO},
+ {0xF908, UNICODE_NORM_QC_NO},
+ {0xF909, UNICODE_NORM_QC_NO},
+ {0xF90A, UNICODE_NORM_QC_NO},
+ {0xF90B, UNICODE_NORM_QC_NO},
+ {0xF90C, UNICODE_NORM_QC_NO},
+ {0xF90D, UNICODE_NORM_QC_NO},
+ {0xF90E, UNICODE_NORM_QC_NO},
+ {0xF90F, UNICODE_NORM_QC_NO},
+ {0xF910, UNICODE_NORM_QC_NO},
+ {0xF911, UNICODE_NORM_QC_NO},
+ {0xF912, UNICODE_NORM_QC_NO},
+ {0xF913, UNICODE_NORM_QC_NO},
+ {0xF914, UNICODE_NORM_QC_NO},
+ {0xF915, UNICODE_NORM_QC_NO},
+ {0xF916, UNICODE_NORM_QC_NO},
+ {0xF917, UNICODE_NORM_QC_NO},
+ {0xF918, UNICODE_NORM_QC_NO},
+ {0xF919, UNICODE_NORM_QC_NO},
+ {0xF91A, UNICODE_NORM_QC_NO},
+ {0xF91B, UNICODE_NORM_QC_NO},
+ {0xF91C, UNICODE_NORM_QC_NO},
+ {0xF91D, UNICODE_NORM_QC_NO},
+ {0xF91E, UNICODE_NORM_QC_NO},
+ {0xF91F, UNICODE_NORM_QC_NO},
+ {0xF920, UNICODE_NORM_QC_NO},
+ {0xF921, UNICODE_NORM_QC_NO},
+ {0xF922, UNICODE_NORM_QC_NO},
+ {0xF923, UNICODE_NORM_QC_NO},
+ {0xF924, UNICODE_NORM_QC_NO},
+ {0xF925, UNICODE_NORM_QC_NO},
+ {0xF926, UNICODE_NORM_QC_NO},
+ {0xF927, UNICODE_NORM_QC_NO},
+ {0xF928, UNICODE_NORM_QC_NO},
+ {0xF929, UNICODE_NORM_QC_NO},
+ {0xF92A, UNICODE_NORM_QC_NO},
+ {0xF92B, UNICODE_NORM_QC_NO},
+ {0xF92C, UNICODE_NORM_QC_NO},
+ {0xF92D, UNICODE_NORM_QC_NO},
+ {0xF92E, UNICODE_NORM_QC_NO},
+ {0xF92F, UNICODE_NORM_QC_NO},
+ {0xF930, UNICODE_NORM_QC_NO},
+ {0xF931, UNICODE_NORM_QC_NO},
+ {0xF932, UNICODE_NORM_QC_NO},
+ {0xF933, UNICODE_NORM_QC_NO},
+ {0xF934, UNICODE_NORM_QC_NO},
+ {0xF935, UNICODE_NORM_QC_NO},
+ {0xF936, UNICODE_NORM_QC_NO},
+ {0xF937, UNICODE_NORM_QC_NO},
+ {0xF938, UNICODE_NORM_QC_NO},
+ {0xF939, UNICODE_NORM_QC_NO},
+ {0xF93A, UNICODE_NORM_QC_NO},
+ {0xF93B, UNICODE_NORM_QC_NO},
+ {0xF93C, UNICODE_NORM_QC_NO},
+ {0xF93D, UNICODE_NORM_QC_NO},
+ {0xF93E, UNICODE_NORM_QC_NO},
+ {0xF93F, UNICODE_NORM_QC_NO},
+ {0xF940, UNICODE_NORM_QC_NO},
+ {0xF941, UNICODE_NORM_QC_NO},
+ {0xF942, UNICODE_NORM_QC_NO},
+ {0xF943, UNICODE_NORM_QC_NO},
+ {0xF944, UNICODE_NORM_QC_NO},
+ {0xF945, UNICODE_NORM_QC_NO},
+ {0xF946, UNICODE_NORM_QC_NO},
+ {0xF947, UNICODE_NORM_QC_NO},
+ {0xF948, UNICODE_NORM_QC_NO},
+ {0xF949, UNICODE_NORM_QC_NO},
+ {0xF94A, UNICODE_NORM_QC_NO},
+ {0xF94B, UNICODE_NORM_QC_NO},
+ {0xF94C, UNICODE_NORM_QC_NO},
+ {0xF94D, UNICODE_NORM_QC_NO},
+ {0xF94E, UNICODE_NORM_QC_NO},
+ {0xF94F, UNICODE_NORM_QC_NO},
+ {0xF950, UNICODE_NORM_QC_NO},
+ {0xF951, UNICODE_NORM_QC_NO},
+ {0xF952, UNICODE_NORM_QC_NO},
+ {0xF953, UNICODE_NORM_QC_NO},
+ {0xF954, UNICODE_NORM_QC_NO},
+ {0xF955, UNICODE_NORM_QC_NO},
+ {0xF956, UNICODE_NORM_QC_NO},
+ {0xF957, UNICODE_NORM_QC_NO},
+ {0xF958, UNICODE_NORM_QC_NO},
+ {0xF959, UNICODE_NORM_QC_NO},
+ {0xF95A, UNICODE_NORM_QC_NO},
+ {0xF95B, UNICODE_NORM_QC_NO},
+ {0xF95C, UNICODE_NORM_QC_NO},
+ {0xF95D, UNICODE_NORM_QC_NO},
+ {0xF95E, UNICODE_NORM_QC_NO},
+ {0xF95F, UNICODE_NORM_QC_NO},
+ {0xF960, UNICODE_NORM_QC_NO},
+ {0xF961, UNICODE_NORM_QC_NO},
+ {0xF962, UNICODE_NORM_QC_NO},
+ {0xF963, UNICODE_NORM_QC_NO},
+ {0xF964, UNICODE_NORM_QC_NO},
+ {0xF965, UNICODE_NORM_QC_NO},
+ {0xF966, UNICODE_NORM_QC_NO},
+ {0xF967, UNICODE_NORM_QC_NO},
+ {0xF968, UNICODE_NORM_QC_NO},
+ {0xF969, UNICODE_NORM_QC_NO},
+ {0xF96A, UNICODE_NORM_QC_NO},
+ {0xF96B, UNICODE_NORM_QC_NO},
+ {0xF96C, UNICODE_NORM_QC_NO},
+ {0xF96D, UNICODE_NORM_QC_NO},
+ {0xF96E, UNICODE_NORM_QC_NO},
+ {0xF96F, UNICODE_NORM_QC_NO},
+ {0xF970, UNICODE_NORM_QC_NO},
+ {0xF971, UNICODE_NORM_QC_NO},
+ {0xF972, UNICODE_NORM_QC_NO},
+ {0xF973, UNICODE_NORM_QC_NO},
+ {0xF974, UNICODE_NORM_QC_NO},
+ {0xF975, UNICODE_NORM_QC_NO},
+ {0xF976, UNICODE_NORM_QC_NO},
+ {0xF977, UNICODE_NORM_QC_NO},
+ {0xF978, UNICODE_NORM_QC_NO},
+ {0xF979, UNICODE_NORM_QC_NO},
+ {0xF97A, UNICODE_NORM_QC_NO},
+ {0xF97B, UNICODE_NORM_QC_NO},
+ {0xF97C, UNICODE_NORM_QC_NO},
+ {0xF97D, UNICODE_NORM_QC_NO},
+ {0xF97E, UNICODE_NORM_QC_NO},
+ {0xF97F, UNICODE_NORM_QC_NO},
+ {0xF980, UNICODE_NORM_QC_NO},
+ {0xF981, UNICODE_NORM_QC_NO},
+ {0xF982, UNICODE_NORM_QC_NO},
+ {0xF983, UNICODE_NORM_QC_NO},
+ {0xF984, UNICODE_NORM_QC_NO},
+ {0xF985, UNICODE_NORM_QC_NO},
+ {0xF986, UNICODE_NORM_QC_NO},
+ {0xF987, UNICODE_NORM_QC_NO},
+ {0xF988, UNICODE_NORM_QC_NO},
+ {0xF989, UNICODE_NORM_QC_NO},
+ {0xF98A, UNICODE_NORM_QC_NO},
+ {0xF98B, UNICODE_NORM_QC_NO},
+ {0xF98C, UNICODE_NORM_QC_NO},
+ {0xF98D, UNICODE_NORM_QC_NO},
+ {0xF98E, UNICODE_NORM_QC_NO},
+ {0xF98F, UNICODE_NORM_QC_NO},
+ {0xF990, UNICODE_NORM_QC_NO},
+ {0xF991, UNICODE_NORM_QC_NO},
+ {0xF992, UNICODE_NORM_QC_NO},
+ {0xF993, UNICODE_NORM_QC_NO},
+ {0xF994, UNICODE_NORM_QC_NO},
+ {0xF995, UNICODE_NORM_QC_NO},
+ {0xF996, UNICODE_NORM_QC_NO},
+ {0xF997, UNICODE_NORM_QC_NO},
+ {0xF998, UNICODE_NORM_QC_NO},
+ {0xF999, UNICODE_NORM_QC_NO},
+ {0xF99A, UNICODE_NORM_QC_NO},
+ {0xF99B, UNICODE_NORM_QC_NO},
+ {0xF99C, UNICODE_NORM_QC_NO},
+ {0xF99D, UNICODE_NORM_QC_NO},
+ {0xF99E, UNICODE_NORM_QC_NO},
+ {0xF99F, UNICODE_NORM_QC_NO},
+ {0xF9A0, UNICODE_NORM_QC_NO},
+ {0xF9A1, UNICODE_NORM_QC_NO},
+ {0xF9A2, UNICODE_NORM_QC_NO},
+ {0xF9A3, UNICODE_NORM_QC_NO},
+ {0xF9A4, UNICODE_NORM_QC_NO},
+ {0xF9A5, UNICODE_NORM_QC_NO},
+ {0xF9A6, UNICODE_NORM_QC_NO},
+ {0xF9A7, UNICODE_NORM_QC_NO},
+ {0xF9A8, UNICODE_NORM_QC_NO},
+ {0xF9A9, UNICODE_NORM_QC_NO},
+ {0xF9AA, UNICODE_NORM_QC_NO},
+ {0xF9AB, UNICODE_NORM_QC_NO},
+ {0xF9AC, UNICODE_NORM_QC_NO},
+ {0xF9AD, UNICODE_NORM_QC_NO},
+ {0xF9AE, UNICODE_NORM_QC_NO},
+ {0xF9AF, UNICODE_NORM_QC_NO},
+ {0xF9B0, UNICODE_NORM_QC_NO},
+ {0xF9B1, UNICODE_NORM_QC_NO},
+ {0xF9B2, UNICODE_NORM_QC_NO},
+ {0xF9B3, UNICODE_NORM_QC_NO},
+ {0xF9B4, UNICODE_NORM_QC_NO},
+ {0xF9B5, UNICODE_NORM_QC_NO},
+ {0xF9B6, UNICODE_NORM_QC_NO},
+ {0xF9B7, UNICODE_NORM_QC_NO},
+ {0xF9B8, UNICODE_NORM_QC_NO},
+ {0xF9B9, UNICODE_NORM_QC_NO},
+ {0xF9BA, UNICODE_NORM_QC_NO},
+ {0xF9BB, UNICODE_NORM_QC_NO},
+ {0xF9BC, UNICODE_NORM_QC_NO},
+ {0xF9BD, UNICODE_NORM_QC_NO},
+ {0xF9BE, UNICODE_NORM_QC_NO},
+ {0xF9BF, UNICODE_NORM_QC_NO},
+ {0xF9C0, UNICODE_NORM_QC_NO},
+ {0xF9C1, UNICODE_NORM_QC_NO},
+ {0xF9C2, UNICODE_NORM_QC_NO},
+ {0xF9C3, UNICODE_NORM_QC_NO},
+ {0xF9C4, UNICODE_NORM_QC_NO},
+ {0xF9C5, UNICODE_NORM_QC_NO},
+ {0xF9C6, UNICODE_NORM_QC_NO},
+ {0xF9C7, UNICODE_NORM_QC_NO},
+ {0xF9C8, UNICODE_NORM_QC_NO},
+ {0xF9C9, UNICODE_NORM_QC_NO},
+ {0xF9CA, UNICODE_NORM_QC_NO},
+ {0xF9CB, UNICODE_NORM_QC_NO},
+ {0xF9CC, UNICODE_NORM_QC_NO},
+ {0xF9CD, UNICODE_NORM_QC_NO},
+ {0xF9CE, UNICODE_NORM_QC_NO},
+ {0xF9CF, UNICODE_NORM_QC_NO},
+ {0xF9D0, UNICODE_NORM_QC_NO},
+ {0xF9D1, UNICODE_NORM_QC_NO},
+ {0xF9D2, UNICODE_NORM_QC_NO},
+ {0xF9D3, UNICODE_NORM_QC_NO},
+ {0xF9D4, UNICODE_NORM_QC_NO},
+ {0xF9D5, UNICODE_NORM_QC_NO},
+ {0xF9D6, UNICODE_NORM_QC_NO},
+ {0xF9D7, UNICODE_NORM_QC_NO},
+ {0xF9D8, UNICODE_NORM_QC_NO},
+ {0xF9D9, UNICODE_NORM_QC_NO},
+ {0xF9DA, UNICODE_NORM_QC_NO},
+ {0xF9DB, UNICODE_NORM_QC_NO},
+ {0xF9DC, UNICODE_NORM_QC_NO},
+ {0xF9DD, UNICODE_NORM_QC_NO},
+ {0xF9DE, UNICODE_NORM_QC_NO},
+ {0xF9DF, UNICODE_NORM_QC_NO},
+ {0xF9E0, UNICODE_NORM_QC_NO},
+ {0xF9E1, UNICODE_NORM_QC_NO},
+ {0xF9E2, UNICODE_NORM_QC_NO},
+ {0xF9E3, UNICODE_NORM_QC_NO},
+ {0xF9E4, UNICODE_NORM_QC_NO},
+ {0xF9E5, UNICODE_NORM_QC_NO},
+ {0xF9E6, UNICODE_NORM_QC_NO},
+ {0xF9E7, UNICODE_NORM_QC_NO},
+ {0xF9E8, UNICODE_NORM_QC_NO},
+ {0xF9E9, UNICODE_NORM_QC_NO},
+ {0xF9EA, UNICODE_NORM_QC_NO},
+ {0xF9EB, UNICODE_NORM_QC_NO},
+ {0xF9EC, UNICODE_NORM_QC_NO},
+ {0xF9ED, UNICODE_NORM_QC_NO},
+ {0xF9EE, UNICODE_NORM_QC_NO},
+ {0xF9EF, UNICODE_NORM_QC_NO},
+ {0xF9F0, UNICODE_NORM_QC_NO},
+ {0xF9F1, UNICODE_NORM_QC_NO},
+ {0xF9F2, UNICODE_NORM_QC_NO},
+ {0xF9F3, UNICODE_NORM_QC_NO},
+ {0xF9F4, UNICODE_NORM_QC_NO},
+ {0xF9F5, UNICODE_NORM_QC_NO},
+ {0xF9F6, UNICODE_NORM_QC_NO},
+ {0xF9F7, UNICODE_NORM_QC_NO},
+ {0xF9F8, UNICODE_NORM_QC_NO},
+ {0xF9F9, UNICODE_NORM_QC_NO},
+ {0xF9FA, UNICODE_NORM_QC_NO},
+ {0xF9FB, UNICODE_NORM_QC_NO},
+ {0xF9FC, UNICODE_NORM_QC_NO},
+ {0xF9FD, UNICODE_NORM_QC_NO},
+ {0xF9FE, UNICODE_NORM_QC_NO},
+ {0xF9FF, UNICODE_NORM_QC_NO},
+ {0xFA00, UNICODE_NORM_QC_NO},
+ {0xFA01, UNICODE_NORM_QC_NO},
+ {0xFA02, UNICODE_NORM_QC_NO},
+ {0xFA03, UNICODE_NORM_QC_NO},
+ {0xFA04, UNICODE_NORM_QC_NO},
+ {0xFA05, UNICODE_NORM_QC_NO},
+ {0xFA06, UNICODE_NORM_QC_NO},
+ {0xFA07, UNICODE_NORM_QC_NO},
+ {0xFA08, UNICODE_NORM_QC_NO},
+ {0xFA09, UNICODE_NORM_QC_NO},
+ {0xFA0A, UNICODE_NORM_QC_NO},
+ {0xFA0B, UNICODE_NORM_QC_NO},
+ {0xFA0C, UNICODE_NORM_QC_NO},
+ {0xFA0D, UNICODE_NORM_QC_NO},
+ {0xFA10, UNICODE_NORM_QC_NO},
+ {0xFA12, UNICODE_NORM_QC_NO},
+ {0xFA15, UNICODE_NORM_QC_NO},
+ {0xFA16, UNICODE_NORM_QC_NO},
+ {0xFA17, UNICODE_NORM_QC_NO},
+ {0xFA18, UNICODE_NORM_QC_NO},
+ {0xFA19, UNICODE_NORM_QC_NO},
+ {0xFA1A, UNICODE_NORM_QC_NO},
+ {0xFA1B, UNICODE_NORM_QC_NO},
+ {0xFA1C, UNICODE_NORM_QC_NO},
+ {0xFA1D, UNICODE_NORM_QC_NO},
+ {0xFA1E, UNICODE_NORM_QC_NO},
+ {0xFA20, UNICODE_NORM_QC_NO},
+ {0xFA22, UNICODE_NORM_QC_NO},
+ {0xFA25, UNICODE_NORM_QC_NO},
+ {0xFA26, UNICODE_NORM_QC_NO},
+ {0xFA2A, UNICODE_NORM_QC_NO},
+ {0xFA2B, UNICODE_NORM_QC_NO},
+ {0xFA2C, UNICODE_NORM_QC_NO},
+ {0xFA2D, UNICODE_NORM_QC_NO},
+ {0xFA2E, UNICODE_NORM_QC_NO},
+ {0xFA2F, UNICODE_NORM_QC_NO},
+ {0xFA30, UNICODE_NORM_QC_NO},
+ {0xFA31, UNICODE_NORM_QC_NO},
+ {0xFA32, UNICODE_NORM_QC_NO},
+ {0xFA33, UNICODE_NORM_QC_NO},
+ {0xFA34, UNICODE_NORM_QC_NO},
+ {0xFA35, UNICODE_NORM_QC_NO},
+ {0xFA36, UNICODE_NORM_QC_NO},
+ {0xFA37, UNICODE_NORM_QC_NO},
+ {0xFA38, UNICODE_NORM_QC_NO},
+ {0xFA39, UNICODE_NORM_QC_NO},
+ {0xFA3A, UNICODE_NORM_QC_NO},
+ {0xFA3B, UNICODE_NORM_QC_NO},
+ {0xFA3C, UNICODE_NORM_QC_NO},
+ {0xFA3D, UNICODE_NORM_QC_NO},
+ {0xFA3E, UNICODE_NORM_QC_NO},
+ {0xFA3F, UNICODE_NORM_QC_NO},
+ {0xFA40, UNICODE_NORM_QC_NO},
+ {0xFA41, UNICODE_NORM_QC_NO},
+ {0xFA42, UNICODE_NORM_QC_NO},
+ {0xFA43, UNICODE_NORM_QC_NO},
+ {0xFA44, UNICODE_NORM_QC_NO},
+ {0xFA45, UNICODE_NORM_QC_NO},
+ {0xFA46, UNICODE_NORM_QC_NO},
+ {0xFA47, UNICODE_NORM_QC_NO},
+ {0xFA48, UNICODE_NORM_QC_NO},
+ {0xFA49, UNICODE_NORM_QC_NO},
+ {0xFA4A, UNICODE_NORM_QC_NO},
+ {0xFA4B, UNICODE_NORM_QC_NO},
+ {0xFA4C, UNICODE_NORM_QC_NO},
+ {0xFA4D, UNICODE_NORM_QC_NO},
+ {0xFA4E, UNICODE_NORM_QC_NO},
+ {0xFA4F, UNICODE_NORM_QC_NO},
+ {0xFA50, UNICODE_NORM_QC_NO},
+ {0xFA51, UNICODE_NORM_QC_NO},
+ {0xFA52, UNICODE_NORM_QC_NO},
+ {0xFA53, UNICODE_NORM_QC_NO},
+ {0xFA54, UNICODE_NORM_QC_NO},
+ {0xFA55, UNICODE_NORM_QC_NO},
+ {0xFA56, UNICODE_NORM_QC_NO},
+ {0xFA57, UNICODE_NORM_QC_NO},
+ {0xFA58, UNICODE_NORM_QC_NO},
+ {0xFA59, UNICODE_NORM_QC_NO},
+ {0xFA5A, UNICODE_NORM_QC_NO},
+ {0xFA5B, UNICODE_NORM_QC_NO},
+ {0xFA5C, UNICODE_NORM_QC_NO},
+ {0xFA5D, UNICODE_NORM_QC_NO},
+ {0xFA5E, UNICODE_NORM_QC_NO},
+ {0xFA5F, UNICODE_NORM_QC_NO},
+ {0xFA60, UNICODE_NORM_QC_NO},
+ {0xFA61, UNICODE_NORM_QC_NO},
+ {0xFA62, UNICODE_NORM_QC_NO},
+ {0xFA63, UNICODE_NORM_QC_NO},
+ {0xFA64, UNICODE_NORM_QC_NO},
+ {0xFA65, UNICODE_NORM_QC_NO},
+ {0xFA66, UNICODE_NORM_QC_NO},
+ {0xFA67, UNICODE_NORM_QC_NO},
+ {0xFA68, UNICODE_NORM_QC_NO},
+ {0xFA69, UNICODE_NORM_QC_NO},
+ {0xFA6A, UNICODE_NORM_QC_NO},
+ {0xFA6B, UNICODE_NORM_QC_NO},
+ {0xFA6C, UNICODE_NORM_QC_NO},
+ {0xFA6D, UNICODE_NORM_QC_NO},
+ {0xFA70, UNICODE_NORM_QC_NO},
+ {0xFA71, UNICODE_NORM_QC_NO},
+ {0xFA72, UNICODE_NORM_QC_NO},
+ {0xFA73, UNICODE_NORM_QC_NO},
+ {0xFA74, UNICODE_NORM_QC_NO},
+ {0xFA75, UNICODE_NORM_QC_NO},
+ {0xFA76, UNICODE_NORM_QC_NO},
+ {0xFA77, UNICODE_NORM_QC_NO},
+ {0xFA78, UNICODE_NORM_QC_NO},
+ {0xFA79, UNICODE_NORM_QC_NO},
+ {0xFA7A, UNICODE_NORM_QC_NO},
+ {0xFA7B, UNICODE_NORM_QC_NO},
+ {0xFA7C, UNICODE_NORM_QC_NO},
+ {0xFA7D, UNICODE_NORM_QC_NO},
+ {0xFA7E, UNICODE_NORM_QC_NO},
+ {0xFA7F, UNICODE_NORM_QC_NO},
+ {0xFA80, UNICODE_NORM_QC_NO},
+ {0xFA81, UNICODE_NORM_QC_NO},
+ {0xFA82, UNICODE_NORM_QC_NO},
+ {0xFA83, UNICODE_NORM_QC_NO},
+ {0xFA84, UNICODE_NORM_QC_NO},
+ {0xFA85, UNICODE_NORM_QC_NO},
+ {0xFA86, UNICODE_NORM_QC_NO},
+ {0xFA87, UNICODE_NORM_QC_NO},
+ {0xFA88, UNICODE_NORM_QC_NO},
+ {0xFA89, UNICODE_NORM_QC_NO},
+ {0xFA8A, UNICODE_NORM_QC_NO},
+ {0xFA8B, UNICODE_NORM_QC_NO},
+ {0xFA8C, UNICODE_NORM_QC_NO},
+ {0xFA8D, UNICODE_NORM_QC_NO},
+ {0xFA8E, UNICODE_NORM_QC_NO},
+ {0xFA8F, UNICODE_NORM_QC_NO},
+ {0xFA90, UNICODE_NORM_QC_NO},
+ {0xFA91, UNICODE_NORM_QC_NO},
+ {0xFA92, UNICODE_NORM_QC_NO},
+ {0xFA93, UNICODE_NORM_QC_NO},
+ {0xFA94, UNICODE_NORM_QC_NO},
+ {0xFA95, UNICODE_NORM_QC_NO},
+ {0xFA96, UNICODE_NORM_QC_NO},
+ {0xFA97, UNICODE_NORM_QC_NO},
+ {0xFA98, UNICODE_NORM_QC_NO},
+ {0xFA99, UNICODE_NORM_QC_NO},
+ {0xFA9A, UNICODE_NORM_QC_NO},
+ {0xFA9B, UNICODE_NORM_QC_NO},
+ {0xFA9C, UNICODE_NORM_QC_NO},
+ {0xFA9D, UNICODE_NORM_QC_NO},
+ {0xFA9E, UNICODE_NORM_QC_NO},
+ {0xFA9F, UNICODE_NORM_QC_NO},
+ {0xFAA0, UNICODE_NORM_QC_NO},
+ {0xFAA1, UNICODE_NORM_QC_NO},
+ {0xFAA2, UNICODE_NORM_QC_NO},
+ {0xFAA3, UNICODE_NORM_QC_NO},
+ {0xFAA4, UNICODE_NORM_QC_NO},
+ {0xFAA5, UNICODE_NORM_QC_NO},
+ {0xFAA6, UNICODE_NORM_QC_NO},
+ {0xFAA7, UNICODE_NORM_QC_NO},
+ {0xFAA8, UNICODE_NORM_QC_NO},
+ {0xFAA9, UNICODE_NORM_QC_NO},
+ {0xFAAA, UNICODE_NORM_QC_NO},
+ {0xFAAB, UNICODE_NORM_QC_NO},
+ {0xFAAC, UNICODE_NORM_QC_NO},
+ {0xFAAD, UNICODE_NORM_QC_NO},
+ {0xFAAE, UNICODE_NORM_QC_NO},
+ {0xFAAF, UNICODE_NORM_QC_NO},
+ {0xFAB0, UNICODE_NORM_QC_NO},
+ {0xFAB1, UNICODE_NORM_QC_NO},
+ {0xFAB2, UNICODE_NORM_QC_NO},
+ {0xFAB3, UNICODE_NORM_QC_NO},
+ {0xFAB4, UNICODE_NORM_QC_NO},
+ {0xFAB5, UNICODE_NORM_QC_NO},
+ {0xFAB6, UNICODE_NORM_QC_NO},
+ {0xFAB7, UNICODE_NORM_QC_NO},
+ {0xFAB8, UNICODE_NORM_QC_NO},
+ {0xFAB9, UNICODE_NORM_QC_NO},
+ {0xFABA, UNICODE_NORM_QC_NO},
+ {0xFABB, UNICODE_NORM_QC_NO},
+ {0xFABC, UNICODE_NORM_QC_NO},
+ {0xFABD, UNICODE_NORM_QC_NO},
+ {0xFABE, UNICODE_NORM_QC_NO},
+ {0xFABF, UNICODE_NORM_QC_NO},
+ {0xFAC0, UNICODE_NORM_QC_NO},
+ {0xFAC1, UNICODE_NORM_QC_NO},
+ {0xFAC2, UNICODE_NORM_QC_NO},
+ {0xFAC3, UNICODE_NORM_QC_NO},
+ {0xFAC4, UNICODE_NORM_QC_NO},
+ {0xFAC5, UNICODE_NORM_QC_NO},
+ {0xFAC6, UNICODE_NORM_QC_NO},
+ {0xFAC7, UNICODE_NORM_QC_NO},
+ {0xFAC8, UNICODE_NORM_QC_NO},
+ {0xFAC9, UNICODE_NORM_QC_NO},
+ {0xFACA, UNICODE_NORM_QC_NO},
+ {0xFACB, UNICODE_NORM_QC_NO},
+ {0xFACC, UNICODE_NORM_QC_NO},
+ {0xFACD, UNICODE_NORM_QC_NO},
+ {0xFACE, UNICODE_NORM_QC_NO},
+ {0xFACF, UNICODE_NORM_QC_NO},
+ {0xFAD0, UNICODE_NORM_QC_NO},
+ {0xFAD1, UNICODE_NORM_QC_NO},
+ {0xFAD2, UNICODE_NORM_QC_NO},
+ {0xFAD3, UNICODE_NORM_QC_NO},
+ {0xFAD4, UNICODE_NORM_QC_NO},
+ {0xFAD5, UNICODE_NORM_QC_NO},
+ {0xFAD6, UNICODE_NORM_QC_NO},
+ {0xFAD7, UNICODE_NORM_QC_NO},
+ {0xFAD8, UNICODE_NORM_QC_NO},
+ {0xFAD9, UNICODE_NORM_QC_NO},
+ {0xFB00, UNICODE_NORM_QC_NO},
+ {0xFB01, UNICODE_NORM_QC_NO},
+ {0xFB02, UNICODE_NORM_QC_NO},
+ {0xFB03, UNICODE_NORM_QC_NO},
+ {0xFB04, UNICODE_NORM_QC_NO},
+ {0xFB05, UNICODE_NORM_QC_NO},
+ {0xFB06, UNICODE_NORM_QC_NO},
+ {0xFB13, UNICODE_NORM_QC_NO},
+ {0xFB14, UNICODE_NORM_QC_NO},
+ {0xFB15, UNICODE_NORM_QC_NO},
+ {0xFB16, UNICODE_NORM_QC_NO},
+ {0xFB17, UNICODE_NORM_QC_NO},
+ {0xFB1D, UNICODE_NORM_QC_NO},
+ {0xFB1F, UNICODE_NORM_QC_NO},
+ {0xFB20, UNICODE_NORM_QC_NO},
+ {0xFB21, UNICODE_NORM_QC_NO},
+ {0xFB22, UNICODE_NORM_QC_NO},
+ {0xFB23, UNICODE_NORM_QC_NO},
+ {0xFB24, UNICODE_NORM_QC_NO},
+ {0xFB25, UNICODE_NORM_QC_NO},
+ {0xFB26, UNICODE_NORM_QC_NO},
+ {0xFB27, UNICODE_NORM_QC_NO},
+ {0xFB28, UNICODE_NORM_QC_NO},
+ {0xFB29, UNICODE_NORM_QC_NO},
+ {0xFB2A, UNICODE_NORM_QC_NO},
+ {0xFB2B, UNICODE_NORM_QC_NO},
+ {0xFB2C, UNICODE_NORM_QC_NO},
+ {0xFB2D, UNICODE_NORM_QC_NO},
+ {0xFB2E, UNICODE_NORM_QC_NO},
+ {0xFB2F, UNICODE_NORM_QC_NO},
+ {0xFB30, UNICODE_NORM_QC_NO},
+ {0xFB31, UNICODE_NORM_QC_NO},
+ {0xFB32, UNICODE_NORM_QC_NO},
+ {0xFB33, UNICODE_NORM_QC_NO},
+ {0xFB34, UNICODE_NORM_QC_NO},
+ {0xFB35, UNICODE_NORM_QC_NO},
+ {0xFB36, UNICODE_NORM_QC_NO},
+ {0xFB38, UNICODE_NORM_QC_NO},
+ {0xFB39, UNICODE_NORM_QC_NO},
+ {0xFB3A, UNICODE_NORM_QC_NO},
+ {0xFB3B, UNICODE_NORM_QC_NO},
+ {0xFB3C, UNICODE_NORM_QC_NO},
+ {0xFB3E, UNICODE_NORM_QC_NO},
+ {0xFB40, UNICODE_NORM_QC_NO},
+ {0xFB41, UNICODE_NORM_QC_NO},
+ {0xFB43, UNICODE_NORM_QC_NO},
+ {0xFB44, UNICODE_NORM_QC_NO},
+ {0xFB46, UNICODE_NORM_QC_NO},
+ {0xFB47, UNICODE_NORM_QC_NO},
+ {0xFB48, UNICODE_NORM_QC_NO},
+ {0xFB49, UNICODE_NORM_QC_NO},
+ {0xFB4A, UNICODE_NORM_QC_NO},
+ {0xFB4B, UNICODE_NORM_QC_NO},
+ {0xFB4C, UNICODE_NORM_QC_NO},
+ {0xFB4D, UNICODE_NORM_QC_NO},
+ {0xFB4E, UNICODE_NORM_QC_NO},
+ {0xFB4F, UNICODE_NORM_QC_NO},
+ {0xFB50, UNICODE_NORM_QC_NO},
+ {0xFB51, UNICODE_NORM_QC_NO},
+ {0xFB52, UNICODE_NORM_QC_NO},
+ {0xFB53, UNICODE_NORM_QC_NO},
+ {0xFB54, UNICODE_NORM_QC_NO},
+ {0xFB55, UNICODE_NORM_QC_NO},
+ {0xFB56, UNICODE_NORM_QC_NO},
+ {0xFB57, UNICODE_NORM_QC_NO},
+ {0xFB58, UNICODE_NORM_QC_NO},
+ {0xFB59, UNICODE_NORM_QC_NO},
+ {0xFB5A, UNICODE_NORM_QC_NO},
+ {0xFB5B, UNICODE_NORM_QC_NO},
+ {0xFB5C, UNICODE_NORM_QC_NO},
+ {0xFB5D, UNICODE_NORM_QC_NO},
+ {0xFB5E, UNICODE_NORM_QC_NO},
+ {0xFB5F, UNICODE_NORM_QC_NO},
+ {0xFB60, UNICODE_NORM_QC_NO},
+ {0xFB61, UNICODE_NORM_QC_NO},
+ {0xFB62, UNICODE_NORM_QC_NO},
+ {0xFB63, UNICODE_NORM_QC_NO},
+ {0xFB64, UNICODE_NORM_QC_NO},
+ {0xFB65, UNICODE_NORM_QC_NO},
+ {0xFB66, UNICODE_NORM_QC_NO},
+ {0xFB67, UNICODE_NORM_QC_NO},
+ {0xFB68, UNICODE_NORM_QC_NO},
+ {0xFB69, UNICODE_NORM_QC_NO},
+ {0xFB6A, UNICODE_NORM_QC_NO},
+ {0xFB6B, UNICODE_NORM_QC_NO},
+ {0xFB6C, UNICODE_NORM_QC_NO},
+ {0xFB6D, UNICODE_NORM_QC_NO},
+ {0xFB6E, UNICODE_NORM_QC_NO},
+ {0xFB6F, UNICODE_NORM_QC_NO},
+ {0xFB70, UNICODE_NORM_QC_NO},
+ {0xFB71, UNICODE_NORM_QC_NO},
+ {0xFB72, UNICODE_NORM_QC_NO},
+ {0xFB73, UNICODE_NORM_QC_NO},
+ {0xFB74, UNICODE_NORM_QC_NO},
+ {0xFB75, UNICODE_NORM_QC_NO},
+ {0xFB76, UNICODE_NORM_QC_NO},
+ {0xFB77, UNICODE_NORM_QC_NO},
+ {0xFB78, UNICODE_NORM_QC_NO},
+ {0xFB79, UNICODE_NORM_QC_NO},
+ {0xFB7A, UNICODE_NORM_QC_NO},
+ {0xFB7B, UNICODE_NORM_QC_NO},
+ {0xFB7C, UNICODE_NORM_QC_NO},
+ {0xFB7D, UNICODE_NORM_QC_NO},
+ {0xFB7E, UNICODE_NORM_QC_NO},
+ {0xFB7F, UNICODE_NORM_QC_NO},
+ {0xFB80, UNICODE_NORM_QC_NO},
+ {0xFB81, UNICODE_NORM_QC_NO},
+ {0xFB82, UNICODE_NORM_QC_NO},
+ {0xFB83, UNICODE_NORM_QC_NO},
+ {0xFB84, UNICODE_NORM_QC_NO},
+ {0xFB85, UNICODE_NORM_QC_NO},
+ {0xFB86, UNICODE_NORM_QC_NO},
+ {0xFB87, UNICODE_NORM_QC_NO},
+ {0xFB88, UNICODE_NORM_QC_NO},
+ {0xFB89, UNICODE_NORM_QC_NO},
+ {0xFB8A, UNICODE_NORM_QC_NO},
+ {0xFB8B, UNICODE_NORM_QC_NO},
+ {0xFB8C, UNICODE_NORM_QC_NO},
+ {0xFB8D, UNICODE_NORM_QC_NO},
+ {0xFB8E, UNICODE_NORM_QC_NO},
+ {0xFB8F, UNICODE_NORM_QC_NO},
+ {0xFB90, UNICODE_NORM_QC_NO},
+ {0xFB91, UNICODE_NORM_QC_NO},
+ {0xFB92, UNICODE_NORM_QC_NO},
+ {0xFB93, UNICODE_NORM_QC_NO},
+ {0xFB94, UNICODE_NORM_QC_NO},
+ {0xFB95, UNICODE_NORM_QC_NO},
+ {0xFB96, UNICODE_NORM_QC_NO},
+ {0xFB97, UNICODE_NORM_QC_NO},
+ {0xFB98, UNICODE_NORM_QC_NO},
+ {0xFB99, UNICODE_NORM_QC_NO},
+ {0xFB9A, UNICODE_NORM_QC_NO},
+ {0xFB9B, UNICODE_NORM_QC_NO},
+ {0xFB9C, UNICODE_NORM_QC_NO},
+ {0xFB9D, UNICODE_NORM_QC_NO},
+ {0xFB9E, UNICODE_NORM_QC_NO},
+ {0xFB9F, UNICODE_NORM_QC_NO},
+ {0xFBA0, UNICODE_NORM_QC_NO},
+ {0xFBA1, UNICODE_NORM_QC_NO},
+ {0xFBA2, UNICODE_NORM_QC_NO},
+ {0xFBA3, UNICODE_NORM_QC_NO},
+ {0xFBA4, UNICODE_NORM_QC_NO},
+ {0xFBA5, UNICODE_NORM_QC_NO},
+ {0xFBA6, UNICODE_NORM_QC_NO},
+ {0xFBA7, UNICODE_NORM_QC_NO},
+ {0xFBA8, UNICODE_NORM_QC_NO},
+ {0xFBA9, UNICODE_NORM_QC_NO},
+ {0xFBAA, UNICODE_NORM_QC_NO},
+ {0xFBAB, UNICODE_NORM_QC_NO},
+ {0xFBAC, UNICODE_NORM_QC_NO},
+ {0xFBAD, UNICODE_NORM_QC_NO},
+ {0xFBAE, UNICODE_NORM_QC_NO},
+ {0xFBAF, UNICODE_NORM_QC_NO},
+ {0xFBB0, UNICODE_NORM_QC_NO},
+ {0xFBB1, UNICODE_NORM_QC_NO},
+ {0xFBD3, UNICODE_NORM_QC_NO},
+ {0xFBD4, UNICODE_NORM_QC_NO},
+ {0xFBD5, UNICODE_NORM_QC_NO},
+ {0xFBD6, UNICODE_NORM_QC_NO},
+ {0xFBD7, UNICODE_NORM_QC_NO},
+ {0xFBD8, UNICODE_NORM_QC_NO},
+ {0xFBD9, UNICODE_NORM_QC_NO},
+ {0xFBDA, UNICODE_NORM_QC_NO},
+ {0xFBDB, UNICODE_NORM_QC_NO},
+ {0xFBDC, UNICODE_NORM_QC_NO},
+ {0xFBDD, UNICODE_NORM_QC_NO},
+ {0xFBDE, UNICODE_NORM_QC_NO},
+ {0xFBDF, UNICODE_NORM_QC_NO},
+ {0xFBE0, UNICODE_NORM_QC_NO},
+ {0xFBE1, UNICODE_NORM_QC_NO},
+ {0xFBE2, UNICODE_NORM_QC_NO},
+ {0xFBE3, UNICODE_NORM_QC_NO},
+ {0xFBE4, UNICODE_NORM_QC_NO},
+ {0xFBE5, UNICODE_NORM_QC_NO},
+ {0xFBE6, UNICODE_NORM_QC_NO},
+ {0xFBE7, UNICODE_NORM_QC_NO},
+ {0xFBE8, UNICODE_NORM_QC_NO},
+ {0xFBE9, UNICODE_NORM_QC_NO},
+ {0xFBEA, UNICODE_NORM_QC_NO},
+ {0xFBEB, UNICODE_NORM_QC_NO},
+ {0xFBEC, UNICODE_NORM_QC_NO},
+ {0xFBED, UNICODE_NORM_QC_NO},
+ {0xFBEE, UNICODE_NORM_QC_NO},
+ {0xFBEF, UNICODE_NORM_QC_NO},
+ {0xFBF0, UNICODE_NORM_QC_NO},
+ {0xFBF1, UNICODE_NORM_QC_NO},
+ {0xFBF2, UNICODE_NORM_QC_NO},
+ {0xFBF3, UNICODE_NORM_QC_NO},
+ {0xFBF4, UNICODE_NORM_QC_NO},
+ {0xFBF5, UNICODE_NORM_QC_NO},
+ {0xFBF6, UNICODE_NORM_QC_NO},
+ {0xFBF7, UNICODE_NORM_QC_NO},
+ {0xFBF8, UNICODE_NORM_QC_NO},
+ {0xFBF9, UNICODE_NORM_QC_NO},
+ {0xFBFA, UNICODE_NORM_QC_NO},
+ {0xFBFB, UNICODE_NORM_QC_NO},
+ {0xFBFC, UNICODE_NORM_QC_NO},
+ {0xFBFD, UNICODE_NORM_QC_NO},
+ {0xFBFE, UNICODE_NORM_QC_NO},
+ {0xFBFF, UNICODE_NORM_QC_NO},
+ {0xFC00, UNICODE_NORM_QC_NO},
+ {0xFC01, UNICODE_NORM_QC_NO},
+ {0xFC02, UNICODE_NORM_QC_NO},
+ {0xFC03, UNICODE_NORM_QC_NO},
+ {0xFC04, UNICODE_NORM_QC_NO},
+ {0xFC05, UNICODE_NORM_QC_NO},
+ {0xFC06, UNICODE_NORM_QC_NO},
+ {0xFC07, UNICODE_NORM_QC_NO},
+ {0xFC08, UNICODE_NORM_QC_NO},
+ {0xFC09, UNICODE_NORM_QC_NO},
+ {0xFC0A, UNICODE_NORM_QC_NO},
+ {0xFC0B, UNICODE_NORM_QC_NO},
+ {0xFC0C, UNICODE_NORM_QC_NO},
+ {0xFC0D, UNICODE_NORM_QC_NO},
+ {0xFC0E, UNICODE_NORM_QC_NO},
+ {0xFC0F, UNICODE_NORM_QC_NO},
+ {0xFC10, UNICODE_NORM_QC_NO},
+ {0xFC11, UNICODE_NORM_QC_NO},
+ {0xFC12, UNICODE_NORM_QC_NO},
+ {0xFC13, UNICODE_NORM_QC_NO},
+ {0xFC14, UNICODE_NORM_QC_NO},
+ {0xFC15, UNICODE_NORM_QC_NO},
+ {0xFC16, UNICODE_NORM_QC_NO},
+ {0xFC17, UNICODE_NORM_QC_NO},
+ {0xFC18, UNICODE_NORM_QC_NO},
+ {0xFC19, UNICODE_NORM_QC_NO},
+ {0xFC1A, UNICODE_NORM_QC_NO},
+ {0xFC1B, UNICODE_NORM_QC_NO},
+ {0xFC1C, UNICODE_NORM_QC_NO},
+ {0xFC1D, UNICODE_NORM_QC_NO},
+ {0xFC1E, UNICODE_NORM_QC_NO},
+ {0xFC1F, UNICODE_NORM_QC_NO},
+ {0xFC20, UNICODE_NORM_QC_NO},
+ {0xFC21, UNICODE_NORM_QC_NO},
+ {0xFC22, UNICODE_NORM_QC_NO},
+ {0xFC23, UNICODE_NORM_QC_NO},
+ {0xFC24, UNICODE_NORM_QC_NO},
+ {0xFC25, UNICODE_NORM_QC_NO},
+ {0xFC26, UNICODE_NORM_QC_NO},
+ {0xFC27, UNICODE_NORM_QC_NO},
+ {0xFC28, UNICODE_NORM_QC_NO},
+ {0xFC29, UNICODE_NORM_QC_NO},
+ {0xFC2A, UNICODE_NORM_QC_NO},
+ {0xFC2B, UNICODE_NORM_QC_NO},
+ {0xFC2C, UNICODE_NORM_QC_NO},
+ {0xFC2D, UNICODE_NORM_QC_NO},
+ {0xFC2E, UNICODE_NORM_QC_NO},
+ {0xFC2F, UNICODE_NORM_QC_NO},
+ {0xFC30, UNICODE_NORM_QC_NO},
+ {0xFC31, UNICODE_NORM_QC_NO},
+ {0xFC32, UNICODE_NORM_QC_NO},
+ {0xFC33, UNICODE_NORM_QC_NO},
+ {0xFC34, UNICODE_NORM_QC_NO},
+ {0xFC35, UNICODE_NORM_QC_NO},
+ {0xFC36, UNICODE_NORM_QC_NO},
+ {0xFC37, UNICODE_NORM_QC_NO},
+ {0xFC38, UNICODE_NORM_QC_NO},
+ {0xFC39, UNICODE_NORM_QC_NO},
+ {0xFC3A, UNICODE_NORM_QC_NO},
+ {0xFC3B, UNICODE_NORM_QC_NO},
+ {0xFC3C, UNICODE_NORM_QC_NO},
+ {0xFC3D, UNICODE_NORM_QC_NO},
+ {0xFC3E, UNICODE_NORM_QC_NO},
+ {0xFC3F, UNICODE_NORM_QC_NO},
+ {0xFC40, UNICODE_NORM_QC_NO},
+ {0xFC41, UNICODE_NORM_QC_NO},
+ {0xFC42, UNICODE_NORM_QC_NO},
+ {0xFC43, UNICODE_NORM_QC_NO},
+ {0xFC44, UNICODE_NORM_QC_NO},
+ {0xFC45, UNICODE_NORM_QC_NO},
+ {0xFC46, UNICODE_NORM_QC_NO},
+ {0xFC47, UNICODE_NORM_QC_NO},
+ {0xFC48, UNICODE_NORM_QC_NO},
+ {0xFC49, UNICODE_NORM_QC_NO},
+ {0xFC4A, UNICODE_NORM_QC_NO},
+ {0xFC4B, UNICODE_NORM_QC_NO},
+ {0xFC4C, UNICODE_NORM_QC_NO},
+ {0xFC4D, UNICODE_NORM_QC_NO},
+ {0xFC4E, UNICODE_NORM_QC_NO},
+ {0xFC4F, UNICODE_NORM_QC_NO},
+ {0xFC50, UNICODE_NORM_QC_NO},
+ {0xFC51, UNICODE_NORM_QC_NO},
+ {0xFC52, UNICODE_NORM_QC_NO},
+ {0xFC53, UNICODE_NORM_QC_NO},
+ {0xFC54, UNICODE_NORM_QC_NO},
+ {0xFC55, UNICODE_NORM_QC_NO},
+ {0xFC56, UNICODE_NORM_QC_NO},
+ {0xFC57, UNICODE_NORM_QC_NO},
+ {0xFC58, UNICODE_NORM_QC_NO},
+ {0xFC59, UNICODE_NORM_QC_NO},
+ {0xFC5A, UNICODE_NORM_QC_NO},
+ {0xFC5B, UNICODE_NORM_QC_NO},
+ {0xFC5C, UNICODE_NORM_QC_NO},
+ {0xFC5D, UNICODE_NORM_QC_NO},
+ {0xFC5E, UNICODE_NORM_QC_NO},
+ {0xFC5F, UNICODE_NORM_QC_NO},
+ {0xFC60, UNICODE_NORM_QC_NO},
+ {0xFC61, UNICODE_NORM_QC_NO},
+ {0xFC62, UNICODE_NORM_QC_NO},
+ {0xFC63, UNICODE_NORM_QC_NO},
+ {0xFC64, UNICODE_NORM_QC_NO},
+ {0xFC65, UNICODE_NORM_QC_NO},
+ {0xFC66, UNICODE_NORM_QC_NO},
+ {0xFC67, UNICODE_NORM_QC_NO},
+ {0xFC68, UNICODE_NORM_QC_NO},
+ {0xFC69, UNICODE_NORM_QC_NO},
+ {0xFC6A, UNICODE_NORM_QC_NO},
+ {0xFC6B, UNICODE_NORM_QC_NO},
+ {0xFC6C, UNICODE_NORM_QC_NO},
+ {0xFC6D, UNICODE_NORM_QC_NO},
+ {0xFC6E, UNICODE_NORM_QC_NO},
+ {0xFC6F, UNICODE_NORM_QC_NO},
+ {0xFC70, UNICODE_NORM_QC_NO},
+ {0xFC71, UNICODE_NORM_QC_NO},
+ {0xFC72, UNICODE_NORM_QC_NO},
+ {0xFC73, UNICODE_NORM_QC_NO},
+ {0xFC74, UNICODE_NORM_QC_NO},
+ {0xFC75, UNICODE_NORM_QC_NO},
+ {0xFC76, UNICODE_NORM_QC_NO},
+ {0xFC77, UNICODE_NORM_QC_NO},
+ {0xFC78, UNICODE_NORM_QC_NO},
+ {0xFC79, UNICODE_NORM_QC_NO},
+ {0xFC7A, UNICODE_NORM_QC_NO},
+ {0xFC7B, UNICODE_NORM_QC_NO},
+ {0xFC7C, UNICODE_NORM_QC_NO},
+ {0xFC7D, UNICODE_NORM_QC_NO},
+ {0xFC7E, UNICODE_NORM_QC_NO},
+ {0xFC7F, UNICODE_NORM_QC_NO},
+ {0xFC80, UNICODE_NORM_QC_NO},
+ {0xFC81, UNICODE_NORM_QC_NO},
+ {0xFC82, UNICODE_NORM_QC_NO},
+ {0xFC83, UNICODE_NORM_QC_NO},
+ {0xFC84, UNICODE_NORM_QC_NO},
+ {0xFC85, UNICODE_NORM_QC_NO},
+ {0xFC86, UNICODE_NORM_QC_NO},
+ {0xFC87, UNICODE_NORM_QC_NO},
+ {0xFC88, UNICODE_NORM_QC_NO},
+ {0xFC89, UNICODE_NORM_QC_NO},
+ {0xFC8A, UNICODE_NORM_QC_NO},
+ {0xFC8B, UNICODE_NORM_QC_NO},
+ {0xFC8C, UNICODE_NORM_QC_NO},
+ {0xFC8D, UNICODE_NORM_QC_NO},
+ {0xFC8E, UNICODE_NORM_QC_NO},
+ {0xFC8F, UNICODE_NORM_QC_NO},
+ {0xFC90, UNICODE_NORM_QC_NO},
+ {0xFC91, UNICODE_NORM_QC_NO},
+ {0xFC92, UNICODE_NORM_QC_NO},
+ {0xFC93, UNICODE_NORM_QC_NO},
+ {0xFC94, UNICODE_NORM_QC_NO},
+ {0xFC95, UNICODE_NORM_QC_NO},
+ {0xFC96, UNICODE_NORM_QC_NO},
+ {0xFC97, UNICODE_NORM_QC_NO},
+ {0xFC98, UNICODE_NORM_QC_NO},
+ {0xFC99, UNICODE_NORM_QC_NO},
+ {0xFC9A, UNICODE_NORM_QC_NO},
+ {0xFC9B, UNICODE_NORM_QC_NO},
+ {0xFC9C, UNICODE_NORM_QC_NO},
+ {0xFC9D, UNICODE_NORM_QC_NO},
+ {0xFC9E, UNICODE_NORM_QC_NO},
+ {0xFC9F, UNICODE_NORM_QC_NO},
+ {0xFCA0, UNICODE_NORM_QC_NO},
+ {0xFCA1, UNICODE_NORM_QC_NO},
+ {0xFCA2, UNICODE_NORM_QC_NO},
+ {0xFCA3, UNICODE_NORM_QC_NO},
+ {0xFCA4, UNICODE_NORM_QC_NO},
+ {0xFCA5, UNICODE_NORM_QC_NO},
+ {0xFCA6, UNICODE_NORM_QC_NO},
+ {0xFCA7, UNICODE_NORM_QC_NO},
+ {0xFCA8, UNICODE_NORM_QC_NO},
+ {0xFCA9, UNICODE_NORM_QC_NO},
+ {0xFCAA, UNICODE_NORM_QC_NO},
+ {0xFCAB, UNICODE_NORM_QC_NO},
+ {0xFCAC, UNICODE_NORM_QC_NO},
+ {0xFCAD, UNICODE_NORM_QC_NO},
+ {0xFCAE, UNICODE_NORM_QC_NO},
+ {0xFCAF, UNICODE_NORM_QC_NO},
+ {0xFCB0, UNICODE_NORM_QC_NO},
+ {0xFCB1, UNICODE_NORM_QC_NO},
+ {0xFCB2, UNICODE_NORM_QC_NO},
+ {0xFCB3, UNICODE_NORM_QC_NO},
+ {0xFCB4, UNICODE_NORM_QC_NO},
+ {0xFCB5, UNICODE_NORM_QC_NO},
+ {0xFCB6, UNICODE_NORM_QC_NO},
+ {0xFCB7, UNICODE_NORM_QC_NO},
+ {0xFCB8, UNICODE_NORM_QC_NO},
+ {0xFCB9, UNICODE_NORM_QC_NO},
+ {0xFCBA, UNICODE_NORM_QC_NO},
+ {0xFCBB, UNICODE_NORM_QC_NO},
+ {0xFCBC, UNICODE_NORM_QC_NO},
+ {0xFCBD, UNICODE_NORM_QC_NO},
+ {0xFCBE, UNICODE_NORM_QC_NO},
+ {0xFCBF, UNICODE_NORM_QC_NO},
+ {0xFCC0, UNICODE_NORM_QC_NO},
+ {0xFCC1, UNICODE_NORM_QC_NO},
+ {0xFCC2, UNICODE_NORM_QC_NO},
+ {0xFCC3, UNICODE_NORM_QC_NO},
+ {0xFCC4, UNICODE_NORM_QC_NO},
+ {0xFCC5, UNICODE_NORM_QC_NO},
+ {0xFCC6, UNICODE_NORM_QC_NO},
+ {0xFCC7, UNICODE_NORM_QC_NO},
+ {0xFCC8, UNICODE_NORM_QC_NO},
+ {0xFCC9, UNICODE_NORM_QC_NO},
+ {0xFCCA, UNICODE_NORM_QC_NO},
+ {0xFCCB, UNICODE_NORM_QC_NO},
+ {0xFCCC, UNICODE_NORM_QC_NO},
+ {0xFCCD, UNICODE_NORM_QC_NO},
+ {0xFCCE, UNICODE_NORM_QC_NO},
+ {0xFCCF, UNICODE_NORM_QC_NO},
+ {0xFCD0, UNICODE_NORM_QC_NO},
+ {0xFCD1, UNICODE_NORM_QC_NO},
+ {0xFCD2, UNICODE_NORM_QC_NO},
+ {0xFCD3, UNICODE_NORM_QC_NO},
+ {0xFCD4, UNICODE_NORM_QC_NO},
+ {0xFCD5, UNICODE_NORM_QC_NO},
+ {0xFCD6, UNICODE_NORM_QC_NO},
+ {0xFCD7, UNICODE_NORM_QC_NO},
+ {0xFCD8, UNICODE_NORM_QC_NO},
+ {0xFCD9, UNICODE_NORM_QC_NO},
+ {0xFCDA, UNICODE_NORM_QC_NO},
+ {0xFCDB, UNICODE_NORM_QC_NO},
+ {0xFCDC, UNICODE_NORM_QC_NO},
+ {0xFCDD, UNICODE_NORM_QC_NO},
+ {0xFCDE, UNICODE_NORM_QC_NO},
+ {0xFCDF, UNICODE_NORM_QC_NO},
+ {0xFCE0, UNICODE_NORM_QC_NO},
+ {0xFCE1, UNICODE_NORM_QC_NO},
+ {0xFCE2, UNICODE_NORM_QC_NO},
+ {0xFCE3, UNICODE_NORM_QC_NO},
+ {0xFCE4, UNICODE_NORM_QC_NO},
+ {0xFCE5, UNICODE_NORM_QC_NO},
+ {0xFCE6, UNICODE_NORM_QC_NO},
+ {0xFCE7, UNICODE_NORM_QC_NO},
+ {0xFCE8, UNICODE_NORM_QC_NO},
+ {0xFCE9, UNICODE_NORM_QC_NO},
+ {0xFCEA, UNICODE_NORM_QC_NO},
+ {0xFCEB, UNICODE_NORM_QC_NO},
+ {0xFCEC, UNICODE_NORM_QC_NO},
+ {0xFCED, UNICODE_NORM_QC_NO},
+ {0xFCEE, UNICODE_NORM_QC_NO},
+ {0xFCEF, UNICODE_NORM_QC_NO},
+ {0xFCF0, UNICODE_NORM_QC_NO},
+ {0xFCF1, UNICODE_NORM_QC_NO},
+ {0xFCF2, UNICODE_NORM_QC_NO},
+ {0xFCF3, UNICODE_NORM_QC_NO},
+ {0xFCF4, UNICODE_NORM_QC_NO},
+ {0xFCF5, UNICODE_NORM_QC_NO},
+ {0xFCF6, UNICODE_NORM_QC_NO},
+ {0xFCF7, UNICODE_NORM_QC_NO},
+ {0xFCF8, UNICODE_NORM_QC_NO},
+ {0xFCF9, UNICODE_NORM_QC_NO},
+ {0xFCFA, UNICODE_NORM_QC_NO},
+ {0xFCFB, UNICODE_NORM_QC_NO},
+ {0xFCFC, UNICODE_NORM_QC_NO},
+ {0xFCFD, UNICODE_NORM_QC_NO},
+ {0xFCFE, UNICODE_NORM_QC_NO},
+ {0xFCFF, UNICODE_NORM_QC_NO},
+ {0xFD00, UNICODE_NORM_QC_NO},
+ {0xFD01, UNICODE_NORM_QC_NO},
+ {0xFD02, UNICODE_NORM_QC_NO},
+ {0xFD03, UNICODE_NORM_QC_NO},
+ {0xFD04, UNICODE_NORM_QC_NO},
+ {0xFD05, UNICODE_NORM_QC_NO},
+ {0xFD06, UNICODE_NORM_QC_NO},
+ {0xFD07, UNICODE_NORM_QC_NO},
+ {0xFD08, UNICODE_NORM_QC_NO},
+ {0xFD09, UNICODE_NORM_QC_NO},
+ {0xFD0A, UNICODE_NORM_QC_NO},
+ {0xFD0B, UNICODE_NORM_QC_NO},
+ {0xFD0C, UNICODE_NORM_QC_NO},
+ {0xFD0D, UNICODE_NORM_QC_NO},
+ {0xFD0E, UNICODE_NORM_QC_NO},
+ {0xFD0F, UNICODE_NORM_QC_NO},
+ {0xFD10, UNICODE_NORM_QC_NO},
+ {0xFD11, UNICODE_NORM_QC_NO},
+ {0xFD12, UNICODE_NORM_QC_NO},
+ {0xFD13, UNICODE_NORM_QC_NO},
+ {0xFD14, UNICODE_NORM_QC_NO},
+ {0xFD15, UNICODE_NORM_QC_NO},
+ {0xFD16, UNICODE_NORM_QC_NO},
+ {0xFD17, UNICODE_NORM_QC_NO},
+ {0xFD18, UNICODE_NORM_QC_NO},
+ {0xFD19, UNICODE_NORM_QC_NO},
+ {0xFD1A, UNICODE_NORM_QC_NO},
+ {0xFD1B, UNICODE_NORM_QC_NO},
+ {0xFD1C, UNICODE_NORM_QC_NO},
+ {0xFD1D, UNICODE_NORM_QC_NO},
+ {0xFD1E, UNICODE_NORM_QC_NO},
+ {0xFD1F, UNICODE_NORM_QC_NO},
+ {0xFD20, UNICODE_NORM_QC_NO},
+ {0xFD21, UNICODE_NORM_QC_NO},
+ {0xFD22, UNICODE_NORM_QC_NO},
+ {0xFD23, UNICODE_NORM_QC_NO},
+ {0xFD24, UNICODE_NORM_QC_NO},
+ {0xFD25, UNICODE_NORM_QC_NO},
+ {0xFD26, UNICODE_NORM_QC_NO},
+ {0xFD27, UNICODE_NORM_QC_NO},
+ {0xFD28, UNICODE_NORM_QC_NO},
+ {0xFD29, UNICODE_NORM_QC_NO},
+ {0xFD2A, UNICODE_NORM_QC_NO},
+ {0xFD2B, UNICODE_NORM_QC_NO},
+ {0xFD2C, UNICODE_NORM_QC_NO},
+ {0xFD2D, UNICODE_NORM_QC_NO},
+ {0xFD2E, UNICODE_NORM_QC_NO},
+ {0xFD2F, UNICODE_NORM_QC_NO},
+ {0xFD30, UNICODE_NORM_QC_NO},
+ {0xFD31, UNICODE_NORM_QC_NO},
+ {0xFD32, UNICODE_NORM_QC_NO},
+ {0xFD33, UNICODE_NORM_QC_NO},
+ {0xFD34, UNICODE_NORM_QC_NO},
+ {0xFD35, UNICODE_NORM_QC_NO},
+ {0xFD36, UNICODE_NORM_QC_NO},
+ {0xFD37, UNICODE_NORM_QC_NO},
+ {0xFD38, UNICODE_NORM_QC_NO},
+ {0xFD39, UNICODE_NORM_QC_NO},
+ {0xFD3A, UNICODE_NORM_QC_NO},
+ {0xFD3B, UNICODE_NORM_QC_NO},
+ {0xFD3C, UNICODE_NORM_QC_NO},
+ {0xFD3D, UNICODE_NORM_QC_NO},
+ {0xFD50, UNICODE_NORM_QC_NO},
+ {0xFD51, UNICODE_NORM_QC_NO},
+ {0xFD52, UNICODE_NORM_QC_NO},
+ {0xFD53, UNICODE_NORM_QC_NO},
+ {0xFD54, UNICODE_NORM_QC_NO},
+ {0xFD55, UNICODE_NORM_QC_NO},
+ {0xFD56, UNICODE_NORM_QC_NO},
+ {0xFD57, UNICODE_NORM_QC_NO},
+ {0xFD58, UNICODE_NORM_QC_NO},
+ {0xFD59, UNICODE_NORM_QC_NO},
+ {0xFD5A, UNICODE_NORM_QC_NO},
+ {0xFD5B, UNICODE_NORM_QC_NO},
+ {0xFD5C, UNICODE_NORM_QC_NO},
+ {0xFD5D, UNICODE_NORM_QC_NO},
+ {0xFD5E, UNICODE_NORM_QC_NO},
+ {0xFD5F, UNICODE_NORM_QC_NO},
+ {0xFD60, UNICODE_NORM_QC_NO},
+ {0xFD61, UNICODE_NORM_QC_NO},
+ {0xFD62, UNICODE_NORM_QC_NO},
+ {0xFD63, UNICODE_NORM_QC_NO},
+ {0xFD64, UNICODE_NORM_QC_NO},
+ {0xFD65, UNICODE_NORM_QC_NO},
+ {0xFD66, UNICODE_NORM_QC_NO},
+ {0xFD67, UNICODE_NORM_QC_NO},
+ {0xFD68, UNICODE_NORM_QC_NO},
+ {0xFD69, UNICODE_NORM_QC_NO},
+ {0xFD6A, UNICODE_NORM_QC_NO},
+ {0xFD6B, UNICODE_NORM_QC_NO},
+ {0xFD6C, UNICODE_NORM_QC_NO},
+ {0xFD6D, UNICODE_NORM_QC_NO},
+ {0xFD6E, UNICODE_NORM_QC_NO},
+ {0xFD6F, UNICODE_NORM_QC_NO},
+ {0xFD70, UNICODE_NORM_QC_NO},
+ {0xFD71, UNICODE_NORM_QC_NO},
+ {0xFD72, UNICODE_NORM_QC_NO},
+ {0xFD73, UNICODE_NORM_QC_NO},
+ {0xFD74, UNICODE_NORM_QC_NO},
+ {0xFD75, UNICODE_NORM_QC_NO},
+ {0xFD76, UNICODE_NORM_QC_NO},
+ {0xFD77, UNICODE_NORM_QC_NO},
+ {0xFD78, UNICODE_NORM_QC_NO},
+ {0xFD79, UNICODE_NORM_QC_NO},
+ {0xFD7A, UNICODE_NORM_QC_NO},
+ {0xFD7B, UNICODE_NORM_QC_NO},
+ {0xFD7C, UNICODE_NORM_QC_NO},
+ {0xFD7D, UNICODE_NORM_QC_NO},
+ {0xFD7E, UNICODE_NORM_QC_NO},
+ {0xFD7F, UNICODE_NORM_QC_NO},
+ {0xFD80, UNICODE_NORM_QC_NO},
+ {0xFD81, UNICODE_NORM_QC_NO},
+ {0xFD82, UNICODE_NORM_QC_NO},
+ {0xFD83, UNICODE_NORM_QC_NO},
+ {0xFD84, UNICODE_NORM_QC_NO},
+ {0xFD85, UNICODE_NORM_QC_NO},
+ {0xFD86, UNICODE_NORM_QC_NO},
+ {0xFD87, UNICODE_NORM_QC_NO},
+ {0xFD88, UNICODE_NORM_QC_NO},
+ {0xFD89, UNICODE_NORM_QC_NO},
+ {0xFD8A, UNICODE_NORM_QC_NO},
+ {0xFD8B, UNICODE_NORM_QC_NO},
+ {0xFD8C, UNICODE_NORM_QC_NO},
+ {0xFD8D, UNICODE_NORM_QC_NO},
+ {0xFD8E, UNICODE_NORM_QC_NO},
+ {0xFD8F, UNICODE_NORM_QC_NO},
+ {0xFD92, UNICODE_NORM_QC_NO},
+ {0xFD93, UNICODE_NORM_QC_NO},
+ {0xFD94, UNICODE_NORM_QC_NO},
+ {0xFD95, UNICODE_NORM_QC_NO},
+ {0xFD96, UNICODE_NORM_QC_NO},
+ {0xFD97, UNICODE_NORM_QC_NO},
+ {0xFD98, UNICODE_NORM_QC_NO},
+ {0xFD99, UNICODE_NORM_QC_NO},
+ {0xFD9A, UNICODE_NORM_QC_NO},
+ {0xFD9B, UNICODE_NORM_QC_NO},
+ {0xFD9C, UNICODE_NORM_QC_NO},
+ {0xFD9D, UNICODE_NORM_QC_NO},
+ {0xFD9E, UNICODE_NORM_QC_NO},
+ {0xFD9F, UNICODE_NORM_QC_NO},
+ {0xFDA0, UNICODE_NORM_QC_NO},
+ {0xFDA1, UNICODE_NORM_QC_NO},
+ {0xFDA2, UNICODE_NORM_QC_NO},
+ {0xFDA3, UNICODE_NORM_QC_NO},
+ {0xFDA4, UNICODE_NORM_QC_NO},
+ {0xFDA5, UNICODE_NORM_QC_NO},
+ {0xFDA6, UNICODE_NORM_QC_NO},
+ {0xFDA7, UNICODE_NORM_QC_NO},
+ {0xFDA8, UNICODE_NORM_QC_NO},
+ {0xFDA9, UNICODE_NORM_QC_NO},
+ {0xFDAA, UNICODE_NORM_QC_NO},
+ {0xFDAB, UNICODE_NORM_QC_NO},
+ {0xFDAC, UNICODE_NORM_QC_NO},
+ {0xFDAD, UNICODE_NORM_QC_NO},
+ {0xFDAE, UNICODE_NORM_QC_NO},
+ {0xFDAF, UNICODE_NORM_QC_NO},
+ {0xFDB0, UNICODE_NORM_QC_NO},
+ {0xFDB1, UNICODE_NORM_QC_NO},
+ {0xFDB2, UNICODE_NORM_QC_NO},
+ {0xFDB3, UNICODE_NORM_QC_NO},
+ {0xFDB4, UNICODE_NORM_QC_NO},
+ {0xFDB5, UNICODE_NORM_QC_NO},
+ {0xFDB6, UNICODE_NORM_QC_NO},
+ {0xFDB7, UNICODE_NORM_QC_NO},
+ {0xFDB8, UNICODE_NORM_QC_NO},
+ {0xFDB9, UNICODE_NORM_QC_NO},
+ {0xFDBA, UNICODE_NORM_QC_NO},
+ {0xFDBB, UNICODE_NORM_QC_NO},
+ {0xFDBC, UNICODE_NORM_QC_NO},
+ {0xFDBD, UNICODE_NORM_QC_NO},
+ {0xFDBE, UNICODE_NORM_QC_NO},
+ {0xFDBF, UNICODE_NORM_QC_NO},
+ {0xFDC0, UNICODE_NORM_QC_NO},
+ {0xFDC1, UNICODE_NORM_QC_NO},
+ {0xFDC2, UNICODE_NORM_QC_NO},
+ {0xFDC3, UNICODE_NORM_QC_NO},
+ {0xFDC4, UNICODE_NORM_QC_NO},
+ {0xFDC5, UNICODE_NORM_QC_NO},
+ {0xFDC6, UNICODE_NORM_QC_NO},
+ {0xFDC7, UNICODE_NORM_QC_NO},
+ {0xFDF0, UNICODE_NORM_QC_NO},
+ {0xFDF1, UNICODE_NORM_QC_NO},
+ {0xFDF2, UNICODE_NORM_QC_NO},
+ {0xFDF3, UNICODE_NORM_QC_NO},
+ {0xFDF4, UNICODE_NORM_QC_NO},
+ {0xFDF5, UNICODE_NORM_QC_NO},
+ {0xFDF6, UNICODE_NORM_QC_NO},
+ {0xFDF7, UNICODE_NORM_QC_NO},
+ {0xFDF8, UNICODE_NORM_QC_NO},
+ {0xFDF9, UNICODE_NORM_QC_NO},
+ {0xFDFA, UNICODE_NORM_QC_NO},
+ {0xFDFB, UNICODE_NORM_QC_NO},
+ {0xFDFC, UNICODE_NORM_QC_NO},
+ {0xFE10, UNICODE_NORM_QC_NO},
+ {0xFE11, UNICODE_NORM_QC_NO},
+ {0xFE12, UNICODE_NORM_QC_NO},
+ {0xFE13, UNICODE_NORM_QC_NO},
+ {0xFE14, UNICODE_NORM_QC_NO},
+ {0xFE15, UNICODE_NORM_QC_NO},
+ {0xFE16, UNICODE_NORM_QC_NO},
+ {0xFE17, UNICODE_NORM_QC_NO},
+ {0xFE18, UNICODE_NORM_QC_NO},
+ {0xFE19, UNICODE_NORM_QC_NO},
+ {0xFE30, UNICODE_NORM_QC_NO},
+ {0xFE31, UNICODE_NORM_QC_NO},
+ {0xFE32, UNICODE_NORM_QC_NO},
+ {0xFE33, UNICODE_NORM_QC_NO},
+ {0xFE34, UNICODE_NORM_QC_NO},
+ {0xFE35, UNICODE_NORM_QC_NO},
+ {0xFE36, UNICODE_NORM_QC_NO},
+ {0xFE37, UNICODE_NORM_QC_NO},
+ {0xFE38, UNICODE_NORM_QC_NO},
+ {0xFE39, UNICODE_NORM_QC_NO},
+ {0xFE3A, UNICODE_NORM_QC_NO},
+ {0xFE3B, UNICODE_NORM_QC_NO},
+ {0xFE3C, UNICODE_NORM_QC_NO},
+ {0xFE3D, UNICODE_NORM_QC_NO},
+ {0xFE3E, UNICODE_NORM_QC_NO},
+ {0xFE3F, UNICODE_NORM_QC_NO},
+ {0xFE40, UNICODE_NORM_QC_NO},
+ {0xFE41, UNICODE_NORM_QC_NO},
+ {0xFE42, UNICODE_NORM_QC_NO},
+ {0xFE43, UNICODE_NORM_QC_NO},
+ {0xFE44, UNICODE_NORM_QC_NO},
+ {0xFE47, UNICODE_NORM_QC_NO},
+ {0xFE48, UNICODE_NORM_QC_NO},
+ {0xFE49, UNICODE_NORM_QC_NO},
+ {0xFE4A, UNICODE_NORM_QC_NO},
+ {0xFE4B, UNICODE_NORM_QC_NO},
+ {0xFE4C, UNICODE_NORM_QC_NO},
+ {0xFE4D, UNICODE_NORM_QC_NO},
+ {0xFE4E, UNICODE_NORM_QC_NO},
+ {0xFE4F, UNICODE_NORM_QC_NO},
+ {0xFE50, UNICODE_NORM_QC_NO},
+ {0xFE51, UNICODE_NORM_QC_NO},
+ {0xFE52, UNICODE_NORM_QC_NO},
+ {0xFE54, UNICODE_NORM_QC_NO},
+ {0xFE55, UNICODE_NORM_QC_NO},
+ {0xFE56, UNICODE_NORM_QC_NO},
+ {0xFE57, UNICODE_NORM_QC_NO},
+ {0xFE58, UNICODE_NORM_QC_NO},
+ {0xFE59, UNICODE_NORM_QC_NO},
+ {0xFE5A, UNICODE_NORM_QC_NO},
+ {0xFE5B, UNICODE_NORM_QC_NO},
+ {0xFE5C, UNICODE_NORM_QC_NO},
+ {0xFE5D, UNICODE_NORM_QC_NO},
+ {0xFE5E, UNICODE_NORM_QC_NO},
+ {0xFE5F, UNICODE_NORM_QC_NO},
+ {0xFE60, UNICODE_NORM_QC_NO},
+ {0xFE61, UNICODE_NORM_QC_NO},
+ {0xFE62, UNICODE_NORM_QC_NO},
+ {0xFE63, UNICODE_NORM_QC_NO},
+ {0xFE64, UNICODE_NORM_QC_NO},
+ {0xFE65, UNICODE_NORM_QC_NO},
+ {0xFE66, UNICODE_NORM_QC_NO},
+ {0xFE68, UNICODE_NORM_QC_NO},
+ {0xFE69, UNICODE_NORM_QC_NO},
+ {0xFE6A, UNICODE_NORM_QC_NO},
+ {0xFE6B, UNICODE_NORM_QC_NO},
+ {0xFE70, UNICODE_NORM_QC_NO},
+ {0xFE71, UNICODE_NORM_QC_NO},
+ {0xFE72, UNICODE_NORM_QC_NO},
+ {0xFE74, UNICODE_NORM_QC_NO},
+ {0xFE76, UNICODE_NORM_QC_NO},
+ {0xFE77, UNICODE_NORM_QC_NO},
+ {0xFE78, UNICODE_NORM_QC_NO},
+ {0xFE79, UNICODE_NORM_QC_NO},
+ {0xFE7A, UNICODE_NORM_QC_NO},
+ {0xFE7B, UNICODE_NORM_QC_NO},
+ {0xFE7C, UNICODE_NORM_QC_NO},
+ {0xFE7D, UNICODE_NORM_QC_NO},
+ {0xFE7E, UNICODE_NORM_QC_NO},
+ {0xFE7F, UNICODE_NORM_QC_NO},
+ {0xFE80, UNICODE_NORM_QC_NO},
+ {0xFE81, UNICODE_NORM_QC_NO},
+ {0xFE82, UNICODE_NORM_QC_NO},
+ {0xFE83, UNICODE_NORM_QC_NO},
+ {0xFE84, UNICODE_NORM_QC_NO},
+ {0xFE85, UNICODE_NORM_QC_NO},
+ {0xFE86, UNICODE_NORM_QC_NO},
+ {0xFE87, UNICODE_NORM_QC_NO},
+ {0xFE88, UNICODE_NORM_QC_NO},
+ {0xFE89, UNICODE_NORM_QC_NO},
+ {0xFE8A, UNICODE_NORM_QC_NO},
+ {0xFE8B, UNICODE_NORM_QC_NO},
+ {0xFE8C, UNICODE_NORM_QC_NO},
+ {0xFE8D, UNICODE_NORM_QC_NO},
+ {0xFE8E, UNICODE_NORM_QC_NO},
+ {0xFE8F, UNICODE_NORM_QC_NO},
+ {0xFE90, UNICODE_NORM_QC_NO},
+ {0xFE91, UNICODE_NORM_QC_NO},
+ {0xFE92, UNICODE_NORM_QC_NO},
+ {0xFE93, UNICODE_NORM_QC_NO},
+ {0xFE94, UNICODE_NORM_QC_NO},
+ {0xFE95, UNICODE_NORM_QC_NO},
+ {0xFE96, UNICODE_NORM_QC_NO},
+ {0xFE97, UNICODE_NORM_QC_NO},
+ {0xFE98, UNICODE_NORM_QC_NO},
+ {0xFE99, UNICODE_NORM_QC_NO},
+ {0xFE9A, UNICODE_NORM_QC_NO},
+ {0xFE9B, UNICODE_NORM_QC_NO},
+ {0xFE9C, UNICODE_NORM_QC_NO},
+ {0xFE9D, UNICODE_NORM_QC_NO},
+ {0xFE9E, UNICODE_NORM_QC_NO},
+ {0xFE9F, UNICODE_NORM_QC_NO},
+ {0xFEA0, UNICODE_NORM_QC_NO},
+ {0xFEA1, UNICODE_NORM_QC_NO},
+ {0xFEA2, UNICODE_NORM_QC_NO},
+ {0xFEA3, UNICODE_NORM_QC_NO},
+ {0xFEA4, UNICODE_NORM_QC_NO},
+ {0xFEA5, UNICODE_NORM_QC_NO},
+ {0xFEA6, UNICODE_NORM_QC_NO},
+ {0xFEA7, UNICODE_NORM_QC_NO},
+ {0xFEA8, UNICODE_NORM_QC_NO},
+ {0xFEA9, UNICODE_NORM_QC_NO},
+ {0xFEAA, UNICODE_NORM_QC_NO},
+ {0xFEAB, UNICODE_NORM_QC_NO},
+ {0xFEAC, UNICODE_NORM_QC_NO},
+ {0xFEAD, UNICODE_NORM_QC_NO},
+ {0xFEAE, UNICODE_NORM_QC_NO},
+ {0xFEAF, UNICODE_NORM_QC_NO},
+ {0xFEB0, UNICODE_NORM_QC_NO},
+ {0xFEB1, UNICODE_NORM_QC_NO},
+ {0xFEB2, UNICODE_NORM_QC_NO},
+ {0xFEB3, UNICODE_NORM_QC_NO},
+ {0xFEB4, UNICODE_NORM_QC_NO},
+ {0xFEB5, UNICODE_NORM_QC_NO},
+ {0xFEB6, UNICODE_NORM_QC_NO},
+ {0xFEB7, UNICODE_NORM_QC_NO},
+ {0xFEB8, UNICODE_NORM_QC_NO},
+ {0xFEB9, UNICODE_NORM_QC_NO},
+ {0xFEBA, UNICODE_NORM_QC_NO},
+ {0xFEBB, UNICODE_NORM_QC_NO},
+ {0xFEBC, UNICODE_NORM_QC_NO},
+ {0xFEBD, UNICODE_NORM_QC_NO},
+ {0xFEBE, UNICODE_NORM_QC_NO},
+ {0xFEBF, UNICODE_NORM_QC_NO},
+ {0xFEC0, UNICODE_NORM_QC_NO},
+ {0xFEC1, UNICODE_NORM_QC_NO},
+ {0xFEC2, UNICODE_NORM_QC_NO},
+ {0xFEC3, UNICODE_NORM_QC_NO},
+ {0xFEC4, UNICODE_NORM_QC_NO},
+ {0xFEC5, UNICODE_NORM_QC_NO},
+ {0xFEC6, UNICODE_NORM_QC_NO},
+ {0xFEC7, UNICODE_NORM_QC_NO},
+ {0xFEC8, UNICODE_NORM_QC_NO},
+ {0xFEC9, UNICODE_NORM_QC_NO},
+ {0xFECA, UNICODE_NORM_QC_NO},
+ {0xFECB, UNICODE_NORM_QC_NO},
+ {0xFECC, UNICODE_NORM_QC_NO},
+ {0xFECD, UNICODE_NORM_QC_NO},
+ {0xFECE, UNICODE_NORM_QC_NO},
+ {0xFECF, UNICODE_NORM_QC_NO},
+ {0xFED0, UNICODE_NORM_QC_NO},
+ {0xFED1, UNICODE_NORM_QC_NO},
+ {0xFED2, UNICODE_NORM_QC_NO},
+ {0xFED3, UNICODE_NORM_QC_NO},
+ {0xFED4, UNICODE_NORM_QC_NO},
+ {0xFED5, UNICODE_NORM_QC_NO},
+ {0xFED6, UNICODE_NORM_QC_NO},
+ {0xFED7, UNICODE_NORM_QC_NO},
+ {0xFED8, UNICODE_NORM_QC_NO},
+ {0xFED9, UNICODE_NORM_QC_NO},
+ {0xFEDA, UNICODE_NORM_QC_NO},
+ {0xFEDB, UNICODE_NORM_QC_NO},
+ {0xFEDC, UNICODE_NORM_QC_NO},
+ {0xFEDD, UNICODE_NORM_QC_NO},
+ {0xFEDE, UNICODE_NORM_QC_NO},
+ {0xFEDF, UNICODE_NORM_QC_NO},
+ {0xFEE0, UNICODE_NORM_QC_NO},
+ {0xFEE1, UNICODE_NORM_QC_NO},
+ {0xFEE2, UNICODE_NORM_QC_NO},
+ {0xFEE3, UNICODE_NORM_QC_NO},
+ {0xFEE4, UNICODE_NORM_QC_NO},
+ {0xFEE5, UNICODE_NORM_QC_NO},
+ {0xFEE6, UNICODE_NORM_QC_NO},
+ {0xFEE7, UNICODE_NORM_QC_NO},
+ {0xFEE8, UNICODE_NORM_QC_NO},
+ {0xFEE9, UNICODE_NORM_QC_NO},
+ {0xFEEA, UNICODE_NORM_QC_NO},
+ {0xFEEB, UNICODE_NORM_QC_NO},
+ {0xFEEC, UNICODE_NORM_QC_NO},
+ {0xFEED, UNICODE_NORM_QC_NO},
+ {0xFEEE, UNICODE_NORM_QC_NO},
+ {0xFEEF, UNICODE_NORM_QC_NO},
+ {0xFEF0, UNICODE_NORM_QC_NO},
+ {0xFEF1, UNICODE_NORM_QC_NO},
+ {0xFEF2, UNICODE_NORM_QC_NO},
+ {0xFEF3, UNICODE_NORM_QC_NO},
+ {0xFEF4, UNICODE_NORM_QC_NO},
+ {0xFEF5, UNICODE_NORM_QC_NO},
+ {0xFEF6, UNICODE_NORM_QC_NO},
+ {0xFEF7, UNICODE_NORM_QC_NO},
+ {0xFEF8, UNICODE_NORM_QC_NO},
+ {0xFEF9, UNICODE_NORM_QC_NO},
+ {0xFEFA, UNICODE_NORM_QC_NO},
+ {0xFEFB, UNICODE_NORM_QC_NO},
+ {0xFEFC, UNICODE_NORM_QC_NO},
+ {0xFF01, UNICODE_NORM_QC_NO},
+ {0xFF02, UNICODE_NORM_QC_NO},
+ {0xFF03, UNICODE_NORM_QC_NO},
+ {0xFF04, UNICODE_NORM_QC_NO},
+ {0xFF05, UNICODE_NORM_QC_NO},
+ {0xFF06, UNICODE_NORM_QC_NO},
+ {0xFF07, UNICODE_NORM_QC_NO},
+ {0xFF08, UNICODE_NORM_QC_NO},
+ {0xFF09, UNICODE_NORM_QC_NO},
+ {0xFF0A, UNICODE_NORM_QC_NO},
+ {0xFF0B, UNICODE_NORM_QC_NO},
+ {0xFF0C, UNICODE_NORM_QC_NO},
+ {0xFF0D, UNICODE_NORM_QC_NO},
+ {0xFF0E, UNICODE_NORM_QC_NO},
+ {0xFF0F, UNICODE_NORM_QC_NO},
+ {0xFF10, UNICODE_NORM_QC_NO},
+ {0xFF11, UNICODE_NORM_QC_NO},
+ {0xFF12, UNICODE_NORM_QC_NO},
+ {0xFF13, UNICODE_NORM_QC_NO},
+ {0xFF14, UNICODE_NORM_QC_NO},
+ {0xFF15, UNICODE_NORM_QC_NO},
+ {0xFF16, UNICODE_NORM_QC_NO},
+ {0xFF17, UNICODE_NORM_QC_NO},
+ {0xFF18, UNICODE_NORM_QC_NO},
+ {0xFF19, UNICODE_NORM_QC_NO},
+ {0xFF1A, UNICODE_NORM_QC_NO},
+ {0xFF1B, UNICODE_NORM_QC_NO},
+ {0xFF1C, UNICODE_NORM_QC_NO},
+ {0xFF1D, UNICODE_NORM_QC_NO},
+ {0xFF1E, UNICODE_NORM_QC_NO},
+ {0xFF1F, UNICODE_NORM_QC_NO},
+ {0xFF20, UNICODE_NORM_QC_NO},
+ {0xFF21, UNICODE_NORM_QC_NO},
+ {0xFF22, UNICODE_NORM_QC_NO},
+ {0xFF23, UNICODE_NORM_QC_NO},
+ {0xFF24, UNICODE_NORM_QC_NO},
+ {0xFF25, UNICODE_NORM_QC_NO},
+ {0xFF26, UNICODE_NORM_QC_NO},
+ {0xFF27, UNICODE_NORM_QC_NO},
+ {0xFF28, UNICODE_NORM_QC_NO},
+ {0xFF29, UNICODE_NORM_QC_NO},
+ {0xFF2A, UNICODE_NORM_QC_NO},
+ {0xFF2B, UNICODE_NORM_QC_NO},
+ {0xFF2C, UNICODE_NORM_QC_NO},
+ {0xFF2D, UNICODE_NORM_QC_NO},
+ {0xFF2E, UNICODE_NORM_QC_NO},
+ {0xFF2F, UNICODE_NORM_QC_NO},
+ {0xFF30, UNICODE_NORM_QC_NO},
+ {0xFF31, UNICODE_NORM_QC_NO},
+ {0xFF32, UNICODE_NORM_QC_NO},
+ {0xFF33, UNICODE_NORM_QC_NO},
+ {0xFF34, UNICODE_NORM_QC_NO},
+ {0xFF35, UNICODE_NORM_QC_NO},
+ {0xFF36, UNICODE_NORM_QC_NO},
+ {0xFF37, UNICODE_NORM_QC_NO},
+ {0xFF38, UNICODE_NORM_QC_NO},
+ {0xFF39, UNICODE_NORM_QC_NO},
+ {0xFF3A, UNICODE_NORM_QC_NO},
+ {0xFF3B, UNICODE_NORM_QC_NO},
+ {0xFF3C, UNICODE_NORM_QC_NO},
+ {0xFF3D, UNICODE_NORM_QC_NO},
+ {0xFF3E, UNICODE_NORM_QC_NO},
+ {0xFF3F, UNICODE_NORM_QC_NO},
+ {0xFF40, UNICODE_NORM_QC_NO},
+ {0xFF41, UNICODE_NORM_QC_NO},
+ {0xFF42, UNICODE_NORM_QC_NO},
+ {0xFF43, UNICODE_NORM_QC_NO},
+ {0xFF44, UNICODE_NORM_QC_NO},
+ {0xFF45, UNICODE_NORM_QC_NO},
+ {0xFF46, UNICODE_NORM_QC_NO},
+ {0xFF47, UNICODE_NORM_QC_NO},
+ {0xFF48, UNICODE_NORM_QC_NO},
+ {0xFF49, UNICODE_NORM_QC_NO},
+ {0xFF4A, UNICODE_NORM_QC_NO},
+ {0xFF4B, UNICODE_NORM_QC_NO},
+ {0xFF4C, UNICODE_NORM_QC_NO},
+ {0xFF4D, UNICODE_NORM_QC_NO},
+ {0xFF4E, UNICODE_NORM_QC_NO},
+ {0xFF4F, UNICODE_NORM_QC_NO},
+ {0xFF50, UNICODE_NORM_QC_NO},
+ {0xFF51, UNICODE_NORM_QC_NO},
+ {0xFF52, UNICODE_NORM_QC_NO},
+ {0xFF53, UNICODE_NORM_QC_NO},
+ {0xFF54, UNICODE_NORM_QC_NO},
+ {0xFF55, UNICODE_NORM_QC_NO},
+ {0xFF56, UNICODE_NORM_QC_NO},
+ {0xFF57, UNICODE_NORM_QC_NO},
+ {0xFF58, UNICODE_NORM_QC_NO},
+ {0xFF59, UNICODE_NORM_QC_NO},
+ {0xFF5A, UNICODE_NORM_QC_NO},
+ {0xFF5B, UNICODE_NORM_QC_NO},
+ {0xFF5C, UNICODE_NORM_QC_NO},
+ {0xFF5D, UNICODE_NORM_QC_NO},
+ {0xFF5E, UNICODE_NORM_QC_NO},
+ {0xFF5F, UNICODE_NORM_QC_NO},
+ {0xFF60, UNICODE_NORM_QC_NO},
+ {0xFF61, UNICODE_NORM_QC_NO},
+ {0xFF62, UNICODE_NORM_QC_NO},
+ {0xFF63, UNICODE_NORM_QC_NO},
+ {0xFF64, UNICODE_NORM_QC_NO},
+ {0xFF65, UNICODE_NORM_QC_NO},
+ {0xFF66, UNICODE_NORM_QC_NO},
+ {0xFF67, UNICODE_NORM_QC_NO},
+ {0xFF68, UNICODE_NORM_QC_NO},
+ {0xFF69, UNICODE_NORM_QC_NO},
+ {0xFF6A, UNICODE_NORM_QC_NO},
+ {0xFF6B, UNICODE_NORM_QC_NO},
+ {0xFF6C, UNICODE_NORM_QC_NO},
+ {0xFF6D, UNICODE_NORM_QC_NO},
+ {0xFF6E, UNICODE_NORM_QC_NO},
+ {0xFF6F, UNICODE_NORM_QC_NO},
+ {0xFF70, UNICODE_NORM_QC_NO},
+ {0xFF71, UNICODE_NORM_QC_NO},
+ {0xFF72, UNICODE_NORM_QC_NO},
+ {0xFF73, UNICODE_NORM_QC_NO},
+ {0xFF74, UNICODE_NORM_QC_NO},
+ {0xFF75, UNICODE_NORM_QC_NO},
+ {0xFF76, UNICODE_NORM_QC_NO},
+ {0xFF77, UNICODE_NORM_QC_NO},
+ {0xFF78, UNICODE_NORM_QC_NO},
+ {0xFF79, UNICODE_NORM_QC_NO},
+ {0xFF7A, UNICODE_NORM_QC_NO},
+ {0xFF7B, UNICODE_NORM_QC_NO},
+ {0xFF7C, UNICODE_NORM_QC_NO},
+ {0xFF7D, UNICODE_NORM_QC_NO},
+ {0xFF7E, UNICODE_NORM_QC_NO},
+ {0xFF7F, UNICODE_NORM_QC_NO},
+ {0xFF80, UNICODE_NORM_QC_NO},
+ {0xFF81, UNICODE_NORM_QC_NO},
+ {0xFF82, UNICODE_NORM_QC_NO},
+ {0xFF83, UNICODE_NORM_QC_NO},
+ {0xFF84, UNICODE_NORM_QC_NO},
+ {0xFF85, UNICODE_NORM_QC_NO},
+ {0xFF86, UNICODE_NORM_QC_NO},
+ {0xFF87, UNICODE_NORM_QC_NO},
+ {0xFF88, UNICODE_NORM_QC_NO},
+ {0xFF89, UNICODE_NORM_QC_NO},
+ {0xFF8A, UNICODE_NORM_QC_NO},
+ {0xFF8B, UNICODE_NORM_QC_NO},
+ {0xFF8C, UNICODE_NORM_QC_NO},
+ {0xFF8D, UNICODE_NORM_QC_NO},
+ {0xFF8E, UNICODE_NORM_QC_NO},
+ {0xFF8F, UNICODE_NORM_QC_NO},
+ {0xFF90, UNICODE_NORM_QC_NO},
+ {0xFF91, UNICODE_NORM_QC_NO},
+ {0xFF92, UNICODE_NORM_QC_NO},
+ {0xFF93, UNICODE_NORM_QC_NO},
+ {0xFF94, UNICODE_NORM_QC_NO},
+ {0xFF95, UNICODE_NORM_QC_NO},
+ {0xFF96, UNICODE_NORM_QC_NO},
+ {0xFF97, UNICODE_NORM_QC_NO},
+ {0xFF98, UNICODE_NORM_QC_NO},
+ {0xFF99, UNICODE_NORM_QC_NO},
+ {0xFF9A, UNICODE_NORM_QC_NO},
+ {0xFF9B, UNICODE_NORM_QC_NO},
+ {0xFF9C, UNICODE_NORM_QC_NO},
+ {0xFF9D, UNICODE_NORM_QC_NO},
+ {0xFF9E, UNICODE_NORM_QC_NO},
+ {0xFF9F, UNICODE_NORM_QC_NO},
+ {0xFFA0, UNICODE_NORM_QC_NO},
+ {0xFFA1, UNICODE_NORM_QC_NO},
+ {0xFFA2, UNICODE_NORM_QC_NO},
+ {0xFFA3, UNICODE_NORM_QC_NO},
+ {0xFFA4, UNICODE_NORM_QC_NO},
+ {0xFFA5, UNICODE_NORM_QC_NO},
+ {0xFFA6, UNICODE_NORM_QC_NO},
+ {0xFFA7, UNICODE_NORM_QC_NO},
+ {0xFFA8, UNICODE_NORM_QC_NO},
+ {0xFFA9, UNICODE_NORM_QC_NO},
+ {0xFFAA, UNICODE_NORM_QC_NO},
+ {0xFFAB, UNICODE_NORM_QC_NO},
+ {0xFFAC, UNICODE_NORM_QC_NO},
+ {0xFFAD, UNICODE_NORM_QC_NO},
+ {0xFFAE, UNICODE_NORM_QC_NO},
+ {0xFFAF, UNICODE_NORM_QC_NO},
+ {0xFFB0, UNICODE_NORM_QC_NO},
+ {0xFFB1, UNICODE_NORM_QC_NO},
+ {0xFFB2, UNICODE_NORM_QC_NO},
+ {0xFFB3, UNICODE_NORM_QC_NO},
+ {0xFFB4, UNICODE_NORM_QC_NO},
+ {0xFFB5, UNICODE_NORM_QC_NO},
+ {0xFFB6, UNICODE_NORM_QC_NO},
+ {0xFFB7, UNICODE_NORM_QC_NO},
+ {0xFFB8, UNICODE_NORM_QC_NO},
+ {0xFFB9, UNICODE_NORM_QC_NO},
+ {0xFFBA, UNICODE_NORM_QC_NO},
+ {0xFFBB, UNICODE_NORM_QC_NO},
+ {0xFFBC, UNICODE_NORM_QC_NO},
+ {0xFFBD, UNICODE_NORM_QC_NO},
+ {0xFFBE, UNICODE_NORM_QC_NO},
+ {0xFFC2, UNICODE_NORM_QC_NO},
+ {0xFFC3, UNICODE_NORM_QC_NO},
+ {0xFFC4, UNICODE_NORM_QC_NO},
+ {0xFFC5, UNICODE_NORM_QC_NO},
+ {0xFFC6, UNICODE_NORM_QC_NO},
+ {0xFFC7, UNICODE_NORM_QC_NO},
+ {0xFFCA, UNICODE_NORM_QC_NO},
+ {0xFFCB, UNICODE_NORM_QC_NO},
+ {0xFFCC, UNICODE_NORM_QC_NO},
+ {0xFFCD, UNICODE_NORM_QC_NO},
+ {0xFFCE, UNICODE_NORM_QC_NO},
+ {0xFFCF, UNICODE_NORM_QC_NO},
+ {0xFFD2, UNICODE_NORM_QC_NO},
+ {0xFFD3, UNICODE_NORM_QC_NO},
+ {0xFFD4, UNICODE_NORM_QC_NO},
+ {0xFFD5, UNICODE_NORM_QC_NO},
+ {0xFFD6, UNICODE_NORM_QC_NO},
+ {0xFFD7, UNICODE_NORM_QC_NO},
+ {0xFFDA, UNICODE_NORM_QC_NO},
+ {0xFFDB, UNICODE_NORM_QC_NO},
+ {0xFFDC, UNICODE_NORM_QC_NO},
+ {0xFFE0, UNICODE_NORM_QC_NO},
+ {0xFFE1, UNICODE_NORM_QC_NO},
+ {0xFFE2, UNICODE_NORM_QC_NO},
+ {0xFFE3, UNICODE_NORM_QC_NO},
+ {0xFFE4, UNICODE_NORM_QC_NO},
+ {0xFFE5, UNICODE_NORM_QC_NO},
+ {0xFFE6, UNICODE_NORM_QC_NO},
+ {0xFFE8, UNICODE_NORM_QC_NO},
+ {0xFFE9, UNICODE_NORM_QC_NO},
+ {0xFFEA, UNICODE_NORM_QC_NO},
+ {0xFFEB, UNICODE_NORM_QC_NO},
+ {0xFFEC, UNICODE_NORM_QC_NO},
+ {0xFFED, UNICODE_NORM_QC_NO},
+ {0xFFEE, UNICODE_NORM_QC_NO},
+ {0x110BA, UNICODE_NORM_QC_MAYBE},
+ {0x11127, UNICODE_NORM_QC_MAYBE},
+ {0x1133E, UNICODE_NORM_QC_MAYBE},
+ {0x11357, UNICODE_NORM_QC_MAYBE},
+ {0x114B0, UNICODE_NORM_QC_MAYBE},
+ {0x114BA, UNICODE_NORM_QC_MAYBE},
+ {0x114BD, UNICODE_NORM_QC_MAYBE},
+ {0x115AF, UNICODE_NORM_QC_MAYBE},
+ {0x11930, UNICODE_NORM_QC_MAYBE},
+ {0x1D15E, UNICODE_NORM_QC_NO},
+ {0x1D15F, UNICODE_NORM_QC_NO},
+ {0x1D160, UNICODE_NORM_QC_NO},
+ {0x1D161, UNICODE_NORM_QC_NO},
+ {0x1D162, UNICODE_NORM_QC_NO},
+ {0x1D163, UNICODE_NORM_QC_NO},
+ {0x1D164, UNICODE_NORM_QC_NO},
+ {0x1D1BB, UNICODE_NORM_QC_NO},
+ {0x1D1BC, UNICODE_NORM_QC_NO},
+ {0x1D1BD, UNICODE_NORM_QC_NO},
+ {0x1D1BE, UNICODE_NORM_QC_NO},
+ {0x1D1BF, UNICODE_NORM_QC_NO},
+ {0x1D1C0, UNICODE_NORM_QC_NO},
+ {0x1D400, UNICODE_NORM_QC_NO},
+ {0x1D401, UNICODE_NORM_QC_NO},
+ {0x1D402, UNICODE_NORM_QC_NO},
+ {0x1D403, UNICODE_NORM_QC_NO},
+ {0x1D404, UNICODE_NORM_QC_NO},
+ {0x1D405, UNICODE_NORM_QC_NO},
+ {0x1D406, UNICODE_NORM_QC_NO},
+ {0x1D407, UNICODE_NORM_QC_NO},
+ {0x1D408, UNICODE_NORM_QC_NO},
+ {0x1D409, UNICODE_NORM_QC_NO},
+ {0x1D40A, UNICODE_NORM_QC_NO},
+ {0x1D40B, UNICODE_NORM_QC_NO},
+ {0x1D40C, UNICODE_NORM_QC_NO},
+ {0x1D40D, UNICODE_NORM_QC_NO},
+ {0x1D40E, UNICODE_NORM_QC_NO},
+ {0x1D40F, UNICODE_NORM_QC_NO},
+ {0x1D410, UNICODE_NORM_QC_NO},
+ {0x1D411, UNICODE_NORM_QC_NO},
+ {0x1D412, UNICODE_NORM_QC_NO},
+ {0x1D413, UNICODE_NORM_QC_NO},
+ {0x1D414, UNICODE_NORM_QC_NO},
+ {0x1D415, UNICODE_NORM_QC_NO},
+ {0x1D416, UNICODE_NORM_QC_NO},
+ {0x1D417, UNICODE_NORM_QC_NO},
+ {0x1D418, UNICODE_NORM_QC_NO},
+ {0x1D419, UNICODE_NORM_QC_NO},
+ {0x1D41A, UNICODE_NORM_QC_NO},
+ {0x1D41B, UNICODE_NORM_QC_NO},
+ {0x1D41C, UNICODE_NORM_QC_NO},
+ {0x1D41D, UNICODE_NORM_QC_NO},
+ {0x1D41E, UNICODE_NORM_QC_NO},
+ {0x1D41F, UNICODE_NORM_QC_NO},
+ {0x1D420, UNICODE_NORM_QC_NO},
+ {0x1D421, UNICODE_NORM_QC_NO},
+ {0x1D422, UNICODE_NORM_QC_NO},
+ {0x1D423, UNICODE_NORM_QC_NO},
+ {0x1D424, UNICODE_NORM_QC_NO},
+ {0x1D425, UNICODE_NORM_QC_NO},
+ {0x1D426, UNICODE_NORM_QC_NO},
+ {0x1D427, UNICODE_NORM_QC_NO},
+ {0x1D428, UNICODE_NORM_QC_NO},
+ {0x1D429, UNICODE_NORM_QC_NO},
+ {0x1D42A, UNICODE_NORM_QC_NO},
+ {0x1D42B, UNICODE_NORM_QC_NO},
+ {0x1D42C, UNICODE_NORM_QC_NO},
+ {0x1D42D, UNICODE_NORM_QC_NO},
+ {0x1D42E, UNICODE_NORM_QC_NO},
+ {0x1D42F, UNICODE_NORM_QC_NO},
+ {0x1D430, UNICODE_NORM_QC_NO},
+ {0x1D431, UNICODE_NORM_QC_NO},
+ {0x1D432, UNICODE_NORM_QC_NO},
+ {0x1D433, UNICODE_NORM_QC_NO},
+ {0x1D434, UNICODE_NORM_QC_NO},
+ {0x1D435, UNICODE_NORM_QC_NO},
+ {0x1D436, UNICODE_NORM_QC_NO},
+ {0x1D437, UNICODE_NORM_QC_NO},
+ {0x1D438, UNICODE_NORM_QC_NO},
+ {0x1D439, UNICODE_NORM_QC_NO},
+ {0x1D43A, UNICODE_NORM_QC_NO},
+ {0x1D43B, UNICODE_NORM_QC_NO},
+ {0x1D43C, UNICODE_NORM_QC_NO},
+ {0x1D43D, UNICODE_NORM_QC_NO},
+ {0x1D43E, UNICODE_NORM_QC_NO},
+ {0x1D43F, UNICODE_NORM_QC_NO},
+ {0x1D440, UNICODE_NORM_QC_NO},
+ {0x1D441, UNICODE_NORM_QC_NO},
+ {0x1D442, UNICODE_NORM_QC_NO},
+ {0x1D443, UNICODE_NORM_QC_NO},
+ {0x1D444, UNICODE_NORM_QC_NO},
+ {0x1D445, UNICODE_NORM_QC_NO},
+ {0x1D446, UNICODE_NORM_QC_NO},
+ {0x1D447, UNICODE_NORM_QC_NO},
+ {0x1D448, UNICODE_NORM_QC_NO},
+ {0x1D449, UNICODE_NORM_QC_NO},
+ {0x1D44A, UNICODE_NORM_QC_NO},
+ {0x1D44B, UNICODE_NORM_QC_NO},
+ {0x1D44C, UNICODE_NORM_QC_NO},
+ {0x1D44D, UNICODE_NORM_QC_NO},
+ {0x1D44E, UNICODE_NORM_QC_NO},
+ {0x1D44F, UNICODE_NORM_QC_NO},
+ {0x1D450, UNICODE_NORM_QC_NO},
+ {0x1D451, UNICODE_NORM_QC_NO},
+ {0x1D452, UNICODE_NORM_QC_NO},
+ {0x1D453, UNICODE_NORM_QC_NO},
+ {0x1D454, UNICODE_NORM_QC_NO},
+ {0x1D456, UNICODE_NORM_QC_NO},
+ {0x1D457, UNICODE_NORM_QC_NO},
+ {0x1D458, UNICODE_NORM_QC_NO},
+ {0x1D459, UNICODE_NORM_QC_NO},
+ {0x1D45A, UNICODE_NORM_QC_NO},
+ {0x1D45B, UNICODE_NORM_QC_NO},
+ {0x1D45C, UNICODE_NORM_QC_NO},
+ {0x1D45D, UNICODE_NORM_QC_NO},
+ {0x1D45E, UNICODE_NORM_QC_NO},
+ {0x1D45F, UNICODE_NORM_QC_NO},
+ {0x1D460, UNICODE_NORM_QC_NO},
+ {0x1D461, UNICODE_NORM_QC_NO},
+ {0x1D462, UNICODE_NORM_QC_NO},
+ {0x1D463, UNICODE_NORM_QC_NO},
+ {0x1D464, UNICODE_NORM_QC_NO},
+ {0x1D465, UNICODE_NORM_QC_NO},
+ {0x1D466, UNICODE_NORM_QC_NO},
+ {0x1D467, UNICODE_NORM_QC_NO},
+ {0x1D468, UNICODE_NORM_QC_NO},
+ {0x1D469, UNICODE_NORM_QC_NO},
+ {0x1D46A, UNICODE_NORM_QC_NO},
+ {0x1D46B, UNICODE_NORM_QC_NO},
+ {0x1D46C, UNICODE_NORM_QC_NO},
+ {0x1D46D, UNICODE_NORM_QC_NO},
+ {0x1D46E, UNICODE_NORM_QC_NO},
+ {0x1D46F, UNICODE_NORM_QC_NO},
+ {0x1D470, UNICODE_NORM_QC_NO},
+ {0x1D471, UNICODE_NORM_QC_NO},
+ {0x1D472, UNICODE_NORM_QC_NO},
+ {0x1D473, UNICODE_NORM_QC_NO},
+ {0x1D474, UNICODE_NORM_QC_NO},
+ {0x1D475, UNICODE_NORM_QC_NO},
+ {0x1D476, UNICODE_NORM_QC_NO},
+ {0x1D477, UNICODE_NORM_QC_NO},
+ {0x1D478, UNICODE_NORM_QC_NO},
+ {0x1D479, UNICODE_NORM_QC_NO},
+ {0x1D47A, UNICODE_NORM_QC_NO},
+ {0x1D47B, UNICODE_NORM_QC_NO},
+ {0x1D47C, UNICODE_NORM_QC_NO},
+ {0x1D47D, UNICODE_NORM_QC_NO},
+ {0x1D47E, UNICODE_NORM_QC_NO},
+ {0x1D47F, UNICODE_NORM_QC_NO},
+ {0x1D480, UNICODE_NORM_QC_NO},
+ {0x1D481, UNICODE_NORM_QC_NO},
+ {0x1D482, UNICODE_NORM_QC_NO},
+ {0x1D483, UNICODE_NORM_QC_NO},
+ {0x1D484, UNICODE_NORM_QC_NO},
+ {0x1D485, UNICODE_NORM_QC_NO},
+ {0x1D486, UNICODE_NORM_QC_NO},
+ {0x1D487, UNICODE_NORM_QC_NO},
+ {0x1D488, UNICODE_NORM_QC_NO},
+ {0x1D489, UNICODE_NORM_QC_NO},
+ {0x1D48A, UNICODE_NORM_QC_NO},
+ {0x1D48B, UNICODE_NORM_QC_NO},
+ {0x1D48C, UNICODE_NORM_QC_NO},
+ {0x1D48D, UNICODE_NORM_QC_NO},
+ {0x1D48E, UNICODE_NORM_QC_NO},
+ {0x1D48F, UNICODE_NORM_QC_NO},
+ {0x1D490, UNICODE_NORM_QC_NO},
+ {0x1D491, UNICODE_NORM_QC_NO},
+ {0x1D492, UNICODE_NORM_QC_NO},
+ {0x1D493, UNICODE_NORM_QC_NO},
+ {0x1D494, UNICODE_NORM_QC_NO},
+ {0x1D495, UNICODE_NORM_QC_NO},
+ {0x1D496, UNICODE_NORM_QC_NO},
+ {0x1D497, UNICODE_NORM_QC_NO},
+ {0x1D498, UNICODE_NORM_QC_NO},
+ {0x1D499, UNICODE_NORM_QC_NO},
+ {0x1D49A, UNICODE_NORM_QC_NO},
+ {0x1D49B, UNICODE_NORM_QC_NO},
+ {0x1D49C, UNICODE_NORM_QC_NO},
+ {0x1D49E, UNICODE_NORM_QC_NO},
+ {0x1D49F, UNICODE_NORM_QC_NO},
+ {0x1D4A2, UNICODE_NORM_QC_NO},
+ {0x1D4A5, UNICODE_NORM_QC_NO},
+ {0x1D4A6, UNICODE_NORM_QC_NO},
+ {0x1D4A9, UNICODE_NORM_QC_NO},
+ {0x1D4AA, UNICODE_NORM_QC_NO},
+ {0x1D4AB, UNICODE_NORM_QC_NO},
+ {0x1D4AC, UNICODE_NORM_QC_NO},
+ {0x1D4AE, UNICODE_NORM_QC_NO},
+ {0x1D4AF, UNICODE_NORM_QC_NO},
+ {0x1D4B0, UNICODE_NORM_QC_NO},
+ {0x1D4B1, UNICODE_NORM_QC_NO},
+ {0x1D4B2, UNICODE_NORM_QC_NO},
+ {0x1D4B3, UNICODE_NORM_QC_NO},
+ {0x1D4B4, UNICODE_NORM_QC_NO},
+ {0x1D4B5, UNICODE_NORM_QC_NO},
+ {0x1D4B6, UNICODE_NORM_QC_NO},
+ {0x1D4B7, UNICODE_NORM_QC_NO},
+ {0x1D4B8, UNICODE_NORM_QC_NO},
+ {0x1D4B9, UNICODE_NORM_QC_NO},
+ {0x1D4BB, UNICODE_NORM_QC_NO},
+ {0x1D4BD, UNICODE_NORM_QC_NO},
+ {0x1D4BE, UNICODE_NORM_QC_NO},
+ {0x1D4BF, UNICODE_NORM_QC_NO},
+ {0x1D4C0, UNICODE_NORM_QC_NO},
+ {0x1D4C1, UNICODE_NORM_QC_NO},
+ {0x1D4C2, UNICODE_NORM_QC_NO},
+ {0x1D4C3, UNICODE_NORM_QC_NO},
+ {0x1D4C5, UNICODE_NORM_QC_NO},
+ {0x1D4C6, UNICODE_NORM_QC_NO},
+ {0x1D4C7, UNICODE_NORM_QC_NO},
+ {0x1D4C8, UNICODE_NORM_QC_NO},
+ {0x1D4C9, UNICODE_NORM_QC_NO},
+ {0x1D4CA, UNICODE_NORM_QC_NO},
+ {0x1D4CB, UNICODE_NORM_QC_NO},
+ {0x1D4CC, UNICODE_NORM_QC_NO},
+ {0x1D4CD, UNICODE_NORM_QC_NO},
+ {0x1D4CE, UNICODE_NORM_QC_NO},
+ {0x1D4CF, UNICODE_NORM_QC_NO},
+ {0x1D4D0, UNICODE_NORM_QC_NO},
+ {0x1D4D1, UNICODE_NORM_QC_NO},
+ {0x1D4D2, UNICODE_NORM_QC_NO},
+ {0x1D4D3, UNICODE_NORM_QC_NO},
+ {0x1D4D4, UNICODE_NORM_QC_NO},
+ {0x1D4D5, UNICODE_NORM_QC_NO},
+ {0x1D4D6, UNICODE_NORM_QC_NO},
+ {0x1D4D7, UNICODE_NORM_QC_NO},
+ {0x1D4D8, UNICODE_NORM_QC_NO},
+ {0x1D4D9, UNICODE_NORM_QC_NO},
+ {0x1D4DA, UNICODE_NORM_QC_NO},
+ {0x1D4DB, UNICODE_NORM_QC_NO},
+ {0x1D4DC, UNICODE_NORM_QC_NO},
+ {0x1D4DD, UNICODE_NORM_QC_NO},
+ {0x1D4DE, UNICODE_NORM_QC_NO},
+ {0x1D4DF, UNICODE_NORM_QC_NO},
+ {0x1D4E0, UNICODE_NORM_QC_NO},
+ {0x1D4E1, UNICODE_NORM_QC_NO},
+ {0x1D4E2, UNICODE_NORM_QC_NO},
+ {0x1D4E3, UNICODE_NORM_QC_NO},
+ {0x1D4E4, UNICODE_NORM_QC_NO},
+ {0x1D4E5, UNICODE_NORM_QC_NO},
+ {0x1D4E6, UNICODE_NORM_QC_NO},
+ {0x1D4E7, UNICODE_NORM_QC_NO},
+ {0x1D4E8, UNICODE_NORM_QC_NO},
+ {0x1D4E9, UNICODE_NORM_QC_NO},
+ {0x1D4EA, UNICODE_NORM_QC_NO},
+ {0x1D4EB, UNICODE_NORM_QC_NO},
+ {0x1D4EC, UNICODE_NORM_QC_NO},
+ {0x1D4ED, UNICODE_NORM_QC_NO},
+ {0x1D4EE, UNICODE_NORM_QC_NO},
+ {0x1D4EF, UNICODE_NORM_QC_NO},
+ {0x1D4F0, UNICODE_NORM_QC_NO},
+ {0x1D4F1, UNICODE_NORM_QC_NO},
+ {0x1D4F2, UNICODE_NORM_QC_NO},
+ {0x1D4F3, UNICODE_NORM_QC_NO},
+ {0x1D4F4, UNICODE_NORM_QC_NO},
+ {0x1D4F5, UNICODE_NORM_QC_NO},
+ {0x1D4F6, UNICODE_NORM_QC_NO},
+ {0x1D4F7, UNICODE_NORM_QC_NO},
+ {0x1D4F8, UNICODE_NORM_QC_NO},
+ {0x1D4F9, UNICODE_NORM_QC_NO},
+ {0x1D4FA, UNICODE_NORM_QC_NO},
+ {0x1D4FB, UNICODE_NORM_QC_NO},
+ {0x1D4FC, UNICODE_NORM_QC_NO},
+ {0x1D4FD, UNICODE_NORM_QC_NO},
+ {0x1D4FE, UNICODE_NORM_QC_NO},
+ {0x1D4FF, UNICODE_NORM_QC_NO},
+ {0x1D500, UNICODE_NORM_QC_NO},
+ {0x1D501, UNICODE_NORM_QC_NO},
+ {0x1D502, UNICODE_NORM_QC_NO},
+ {0x1D503, UNICODE_NORM_QC_NO},
+ {0x1D504, UNICODE_NORM_QC_NO},
+ {0x1D505, UNICODE_NORM_QC_NO},
+ {0x1D507, UNICODE_NORM_QC_NO},
+ {0x1D508, UNICODE_NORM_QC_NO},
+ {0x1D509, UNICODE_NORM_QC_NO},
+ {0x1D50A, UNICODE_NORM_QC_NO},
+ {0x1D50D, UNICODE_NORM_QC_NO},
+ {0x1D50E, UNICODE_NORM_QC_NO},
+ {0x1D50F, UNICODE_NORM_QC_NO},
+ {0x1D510, UNICODE_NORM_QC_NO},
+ {0x1D511, UNICODE_NORM_QC_NO},
+ {0x1D512, UNICODE_NORM_QC_NO},
+ {0x1D513, UNICODE_NORM_QC_NO},
+ {0x1D514, UNICODE_NORM_QC_NO},
+ {0x1D516, UNICODE_NORM_QC_NO},
+ {0x1D517, UNICODE_NORM_QC_NO},
+ {0x1D518, UNICODE_NORM_QC_NO},
+ {0x1D519, UNICODE_NORM_QC_NO},
+ {0x1D51A, UNICODE_NORM_QC_NO},
+ {0x1D51B, UNICODE_NORM_QC_NO},
+ {0x1D51C, UNICODE_NORM_QC_NO},
+ {0x1D51E, UNICODE_NORM_QC_NO},
+ {0x1D51F, UNICODE_NORM_QC_NO},
+ {0x1D520, UNICODE_NORM_QC_NO},
+ {0x1D521, UNICODE_NORM_QC_NO},
+ {0x1D522, UNICODE_NORM_QC_NO},
+ {0x1D523, UNICODE_NORM_QC_NO},
+ {0x1D524, UNICODE_NORM_QC_NO},
+ {0x1D525, UNICODE_NORM_QC_NO},
+ {0x1D526, UNICODE_NORM_QC_NO},
+ {0x1D527, UNICODE_NORM_QC_NO},
+ {0x1D528, UNICODE_NORM_QC_NO},
+ {0x1D529, UNICODE_NORM_QC_NO},
+ {0x1D52A, UNICODE_NORM_QC_NO},
+ {0x1D52B, UNICODE_NORM_QC_NO},
+ {0x1D52C, UNICODE_NORM_QC_NO},
+ {0x1D52D, UNICODE_NORM_QC_NO},
+ {0x1D52E, UNICODE_NORM_QC_NO},
+ {0x1D52F, UNICODE_NORM_QC_NO},
+ {0x1D530, UNICODE_NORM_QC_NO},
+ {0x1D531, UNICODE_NORM_QC_NO},
+ {0x1D532, UNICODE_NORM_QC_NO},
+ {0x1D533, UNICODE_NORM_QC_NO},
+ {0x1D534, UNICODE_NORM_QC_NO},
+ {0x1D535, UNICODE_NORM_QC_NO},
+ {0x1D536, UNICODE_NORM_QC_NO},
+ {0x1D537, UNICODE_NORM_QC_NO},
+ {0x1D538, UNICODE_NORM_QC_NO},
+ {0x1D539, UNICODE_NORM_QC_NO},
+ {0x1D53B, UNICODE_NORM_QC_NO},
+ {0x1D53C, UNICODE_NORM_QC_NO},
+ {0x1D53D, UNICODE_NORM_QC_NO},
+ {0x1D53E, UNICODE_NORM_QC_NO},
+ {0x1D540, UNICODE_NORM_QC_NO},
+ {0x1D541, UNICODE_NORM_QC_NO},
+ {0x1D542, UNICODE_NORM_QC_NO},
+ {0x1D543, UNICODE_NORM_QC_NO},
+ {0x1D544, UNICODE_NORM_QC_NO},
+ {0x1D546, UNICODE_NORM_QC_NO},
+ {0x1D54A, UNICODE_NORM_QC_NO},
+ {0x1D54B, UNICODE_NORM_QC_NO},
+ {0x1D54C, UNICODE_NORM_QC_NO},
+ {0x1D54D, UNICODE_NORM_QC_NO},
+ {0x1D54E, UNICODE_NORM_QC_NO},
+ {0x1D54F, UNICODE_NORM_QC_NO},
+ {0x1D550, UNICODE_NORM_QC_NO},
+ {0x1D552, UNICODE_NORM_QC_NO},
+ {0x1D553, UNICODE_NORM_QC_NO},
+ {0x1D554, UNICODE_NORM_QC_NO},
+ {0x1D555, UNICODE_NORM_QC_NO},
+ {0x1D556, UNICODE_NORM_QC_NO},
+ {0x1D557, UNICODE_NORM_QC_NO},
+ {0x1D558, UNICODE_NORM_QC_NO},
+ {0x1D559, UNICODE_NORM_QC_NO},
+ {0x1D55A, UNICODE_NORM_QC_NO},
+ {0x1D55B, UNICODE_NORM_QC_NO},
+ {0x1D55C, UNICODE_NORM_QC_NO},
+ {0x1D55D, UNICODE_NORM_QC_NO},
+ {0x1D55E, UNICODE_NORM_QC_NO},
+ {0x1D55F, UNICODE_NORM_QC_NO},
+ {0x1D560, UNICODE_NORM_QC_NO},
+ {0x1D561, UNICODE_NORM_QC_NO},
+ {0x1D562, UNICODE_NORM_QC_NO},
+ {0x1D563, UNICODE_NORM_QC_NO},
+ {0x1D564, UNICODE_NORM_QC_NO},
+ {0x1D565, UNICODE_NORM_QC_NO},
+ {0x1D566, UNICODE_NORM_QC_NO},
+ {0x1D567, UNICODE_NORM_QC_NO},
+ {0x1D568, UNICODE_NORM_QC_NO},
+ {0x1D569, UNICODE_NORM_QC_NO},
+ {0x1D56A, UNICODE_NORM_QC_NO},
+ {0x1D56B, UNICODE_NORM_QC_NO},
+ {0x1D56C, UNICODE_NORM_QC_NO},
+ {0x1D56D, UNICODE_NORM_QC_NO},
+ {0x1D56E, UNICODE_NORM_QC_NO},
+ {0x1D56F, UNICODE_NORM_QC_NO},
+ {0x1D570, UNICODE_NORM_QC_NO},
+ {0x1D571, UNICODE_NORM_QC_NO},
+ {0x1D572, UNICODE_NORM_QC_NO},
+ {0x1D573, UNICODE_NORM_QC_NO},
+ {0x1D574, UNICODE_NORM_QC_NO},
+ {0x1D575, UNICODE_NORM_QC_NO},
+ {0x1D576, UNICODE_NORM_QC_NO},
+ {0x1D577, UNICODE_NORM_QC_NO},
+ {0x1D578, UNICODE_NORM_QC_NO},
+ {0x1D579, UNICODE_NORM_QC_NO},
+ {0x1D57A, UNICODE_NORM_QC_NO},
+ {0x1D57B, UNICODE_NORM_QC_NO},
+ {0x1D57C, UNICODE_NORM_QC_NO},
+ {0x1D57D, UNICODE_NORM_QC_NO},
+ {0x1D57E, UNICODE_NORM_QC_NO},
+ {0x1D57F, UNICODE_NORM_QC_NO},
+ {0x1D580, UNICODE_NORM_QC_NO},
+ {0x1D581, UNICODE_NORM_QC_NO},
+ {0x1D582, UNICODE_NORM_QC_NO},
+ {0x1D583, UNICODE_NORM_QC_NO},
+ {0x1D584, UNICODE_NORM_QC_NO},
+ {0x1D585, UNICODE_NORM_QC_NO},
+ {0x1D586, UNICODE_NORM_QC_NO},
+ {0x1D587, UNICODE_NORM_QC_NO},
+ {0x1D588, UNICODE_NORM_QC_NO},
+ {0x1D589, UNICODE_NORM_QC_NO},
+ {0x1D58A, UNICODE_NORM_QC_NO},
+ {0x1D58B, UNICODE_NORM_QC_NO},
+ {0x1D58C, UNICODE_NORM_QC_NO},
+ {0x1D58D, UNICODE_NORM_QC_NO},
+ {0x1D58E, UNICODE_NORM_QC_NO},
+ {0x1D58F, UNICODE_NORM_QC_NO},
+ {0x1D590, UNICODE_NORM_QC_NO},
+ {0x1D591, UNICODE_NORM_QC_NO},
+ {0x1D592, UNICODE_NORM_QC_NO},
+ {0x1D593, UNICODE_NORM_QC_NO},
+ {0x1D594, UNICODE_NORM_QC_NO},
+ {0x1D595, UNICODE_NORM_QC_NO},
+ {0x1D596, UNICODE_NORM_QC_NO},
+ {0x1D597, UNICODE_NORM_QC_NO},
+ {0x1D598, UNICODE_NORM_QC_NO},
+ {0x1D599, UNICODE_NORM_QC_NO},
+ {0x1D59A, UNICODE_NORM_QC_NO},
+ {0x1D59B, UNICODE_NORM_QC_NO},
+ {0x1D59C, UNICODE_NORM_QC_NO},
+ {0x1D59D, UNICODE_NORM_QC_NO},
+ {0x1D59E, UNICODE_NORM_QC_NO},
+ {0x1D59F, UNICODE_NORM_QC_NO},
+ {0x1D5A0, UNICODE_NORM_QC_NO},
+ {0x1D5A1, UNICODE_NORM_QC_NO},
+ {0x1D5A2, UNICODE_NORM_QC_NO},
+ {0x1D5A3, UNICODE_NORM_QC_NO},
+ {0x1D5A4, UNICODE_NORM_QC_NO},
+ {0x1D5A5, UNICODE_NORM_QC_NO},
+ {0x1D5A6, UNICODE_NORM_QC_NO},
+ {0x1D5A7, UNICODE_NORM_QC_NO},
+ {0x1D5A8, UNICODE_NORM_QC_NO},
+ {0x1D5A9, UNICODE_NORM_QC_NO},
+ {0x1D5AA, UNICODE_NORM_QC_NO},
+ {0x1D5AB, UNICODE_NORM_QC_NO},
+ {0x1D5AC, UNICODE_NORM_QC_NO},
+ {0x1D5AD, UNICODE_NORM_QC_NO},
+ {0x1D5AE, UNICODE_NORM_QC_NO},
+ {0x1D5AF, UNICODE_NORM_QC_NO},
+ {0x1D5B0, UNICODE_NORM_QC_NO},
+ {0x1D5B1, UNICODE_NORM_QC_NO},
+ {0x1D5B2, UNICODE_NORM_QC_NO},
+ {0x1D5B3, UNICODE_NORM_QC_NO},
+ {0x1D5B4, UNICODE_NORM_QC_NO},
+ {0x1D5B5, UNICODE_NORM_QC_NO},
+ {0x1D5B6, UNICODE_NORM_QC_NO},
+ {0x1D5B7, UNICODE_NORM_QC_NO},
+ {0x1D5B8, UNICODE_NORM_QC_NO},
+ {0x1D5B9, UNICODE_NORM_QC_NO},
+ {0x1D5BA, UNICODE_NORM_QC_NO},
+ {0x1D5BB, UNICODE_NORM_QC_NO},
+ {0x1D5BC, UNICODE_NORM_QC_NO},
+ {0x1D5BD, UNICODE_NORM_QC_NO},
+ {0x1D5BE, UNICODE_NORM_QC_NO},
+ {0x1D5BF, UNICODE_NORM_QC_NO},
+ {0x1D5C0, UNICODE_NORM_QC_NO},
+ {0x1D5C1, UNICODE_NORM_QC_NO},
+ {0x1D5C2, UNICODE_NORM_QC_NO},
+ {0x1D5C3, UNICODE_NORM_QC_NO},
+ {0x1D5C4, UNICODE_NORM_QC_NO},
+ {0x1D5C5, UNICODE_NORM_QC_NO},
+ {0x1D5C6, UNICODE_NORM_QC_NO},
+ {0x1D5C7, UNICODE_NORM_QC_NO},
+ {0x1D5C8, UNICODE_NORM_QC_NO},
+ {0x1D5C9, UNICODE_NORM_QC_NO},
+ {0x1D5CA, UNICODE_NORM_QC_NO},
+ {0x1D5CB, UNICODE_NORM_QC_NO},
+ {0x1D5CC, UNICODE_NORM_QC_NO},
+ {0x1D5CD, UNICODE_NORM_QC_NO},
+ {0x1D5CE, UNICODE_NORM_QC_NO},
+ {0x1D5CF, UNICODE_NORM_QC_NO},
+ {0x1D5D0, UNICODE_NORM_QC_NO},
+ {0x1D5D1, UNICODE_NORM_QC_NO},
+ {0x1D5D2, UNICODE_NORM_QC_NO},
+ {0x1D5D3, UNICODE_NORM_QC_NO},
+ {0x1D5D4, UNICODE_NORM_QC_NO},
+ {0x1D5D5, UNICODE_NORM_QC_NO},
+ {0x1D5D6, UNICODE_NORM_QC_NO},
+ {0x1D5D7, UNICODE_NORM_QC_NO},
+ {0x1D5D8, UNICODE_NORM_QC_NO},
+ {0x1D5D9, UNICODE_NORM_QC_NO},
+ {0x1D5DA, UNICODE_NORM_QC_NO},
+ {0x1D5DB, UNICODE_NORM_QC_NO},
+ {0x1D5DC, UNICODE_NORM_QC_NO},
+ {0x1D5DD, UNICODE_NORM_QC_NO},
+ {0x1D5DE, UNICODE_NORM_QC_NO},
+ {0x1D5DF, UNICODE_NORM_QC_NO},
+ {0x1D5E0, UNICODE_NORM_QC_NO},
+ {0x1D5E1, UNICODE_NORM_QC_NO},
+ {0x1D5E2, UNICODE_NORM_QC_NO},
+ {0x1D5E3, UNICODE_NORM_QC_NO},
+ {0x1D5E4, UNICODE_NORM_QC_NO},
+ {0x1D5E5, UNICODE_NORM_QC_NO},
+ {0x1D5E6, UNICODE_NORM_QC_NO},
+ {0x1D5E7, UNICODE_NORM_QC_NO},
+ {0x1D5E8, UNICODE_NORM_QC_NO},
+ {0x1D5E9, UNICODE_NORM_QC_NO},
+ {0x1D5EA, UNICODE_NORM_QC_NO},
+ {0x1D5EB, UNICODE_NORM_QC_NO},
+ {0x1D5EC, UNICODE_NORM_QC_NO},
+ {0x1D5ED, UNICODE_NORM_QC_NO},
+ {0x1D5EE, UNICODE_NORM_QC_NO},
+ {0x1D5EF, UNICODE_NORM_QC_NO},
+ {0x1D5F0, UNICODE_NORM_QC_NO},
+ {0x1D5F1, UNICODE_NORM_QC_NO},
+ {0x1D5F2, UNICODE_NORM_QC_NO},
+ {0x1D5F3, UNICODE_NORM_QC_NO},
+ {0x1D5F4, UNICODE_NORM_QC_NO},
+ {0x1D5F5, UNICODE_NORM_QC_NO},
+ {0x1D5F6, UNICODE_NORM_QC_NO},
+ {0x1D5F7, UNICODE_NORM_QC_NO},
+ {0x1D5F8, UNICODE_NORM_QC_NO},
+ {0x1D5F9, UNICODE_NORM_QC_NO},
+ {0x1D5FA, UNICODE_NORM_QC_NO},
+ {0x1D5FB, UNICODE_NORM_QC_NO},
+ {0x1D5FC, UNICODE_NORM_QC_NO},
+ {0x1D5FD, UNICODE_NORM_QC_NO},
+ {0x1D5FE, UNICODE_NORM_QC_NO},
+ {0x1D5FF, UNICODE_NORM_QC_NO},
+ {0x1D600, UNICODE_NORM_QC_NO},
+ {0x1D601, UNICODE_NORM_QC_NO},
+ {0x1D602, UNICODE_NORM_QC_NO},
+ {0x1D603, UNICODE_NORM_QC_NO},
+ {0x1D604, UNICODE_NORM_QC_NO},
+ {0x1D605, UNICODE_NORM_QC_NO},
+ {0x1D606, UNICODE_NORM_QC_NO},
+ {0x1D607, UNICODE_NORM_QC_NO},
+ {0x1D608, UNICODE_NORM_QC_NO},
+ {0x1D609, UNICODE_NORM_QC_NO},
+ {0x1D60A, UNICODE_NORM_QC_NO},
+ {0x1D60B, UNICODE_NORM_QC_NO},
+ {0x1D60C, UNICODE_NORM_QC_NO},
+ {0x1D60D, UNICODE_NORM_QC_NO},
+ {0x1D60E, UNICODE_NORM_QC_NO},
+ {0x1D60F, UNICODE_NORM_QC_NO},
+ {0x1D610, UNICODE_NORM_QC_NO},
+ {0x1D611, UNICODE_NORM_QC_NO},
+ {0x1D612, UNICODE_NORM_QC_NO},
+ {0x1D613, UNICODE_NORM_QC_NO},
+ {0x1D614, UNICODE_NORM_QC_NO},
+ {0x1D615, UNICODE_NORM_QC_NO},
+ {0x1D616, UNICODE_NORM_QC_NO},
+ {0x1D617, UNICODE_NORM_QC_NO},
+ {0x1D618, UNICODE_NORM_QC_NO},
+ {0x1D619, UNICODE_NORM_QC_NO},
+ {0x1D61A, UNICODE_NORM_QC_NO},
+ {0x1D61B, UNICODE_NORM_QC_NO},
+ {0x1D61C, UNICODE_NORM_QC_NO},
+ {0x1D61D, UNICODE_NORM_QC_NO},
+ {0x1D61E, UNICODE_NORM_QC_NO},
+ {0x1D61F, UNICODE_NORM_QC_NO},
+ {0x1D620, UNICODE_NORM_QC_NO},
+ {0x1D621, UNICODE_NORM_QC_NO},
+ {0x1D622, UNICODE_NORM_QC_NO},
+ {0x1D623, UNICODE_NORM_QC_NO},
+ {0x1D624, UNICODE_NORM_QC_NO},
+ {0x1D625, UNICODE_NORM_QC_NO},
+ {0x1D626, UNICODE_NORM_QC_NO},
+ {0x1D627, UNICODE_NORM_QC_NO},
+ {0x1D628, UNICODE_NORM_QC_NO},
+ {0x1D629, UNICODE_NORM_QC_NO},
+ {0x1D62A, UNICODE_NORM_QC_NO},
+ {0x1D62B, UNICODE_NORM_QC_NO},
+ {0x1D62C, UNICODE_NORM_QC_NO},
+ {0x1D62D, UNICODE_NORM_QC_NO},
+ {0x1D62E, UNICODE_NORM_QC_NO},
+ {0x1D62F, UNICODE_NORM_QC_NO},
+ {0x1D630, UNICODE_NORM_QC_NO},
+ {0x1D631, UNICODE_NORM_QC_NO},
+ {0x1D632, UNICODE_NORM_QC_NO},
+ {0x1D633, UNICODE_NORM_QC_NO},
+ {0x1D634, UNICODE_NORM_QC_NO},
+ {0x1D635, UNICODE_NORM_QC_NO},
+ {0x1D636, UNICODE_NORM_QC_NO},
+ {0x1D637, UNICODE_NORM_QC_NO},
+ {0x1D638, UNICODE_NORM_QC_NO},
+ {0x1D639, UNICODE_NORM_QC_NO},
+ {0x1D63A, UNICODE_NORM_QC_NO},
+ {0x1D63B, UNICODE_NORM_QC_NO},
+ {0x1D63C, UNICODE_NORM_QC_NO},
+ {0x1D63D, UNICODE_NORM_QC_NO},
+ {0x1D63E, UNICODE_NORM_QC_NO},
+ {0x1D63F, UNICODE_NORM_QC_NO},
+ {0x1D640, UNICODE_NORM_QC_NO},
+ {0x1D641, UNICODE_NORM_QC_NO},
+ {0x1D642, UNICODE_NORM_QC_NO},
+ {0x1D643, UNICODE_NORM_QC_NO},
+ {0x1D644, UNICODE_NORM_QC_NO},
+ {0x1D645, UNICODE_NORM_QC_NO},
+ {0x1D646, UNICODE_NORM_QC_NO},
+ {0x1D647, UNICODE_NORM_QC_NO},
+ {0x1D648, UNICODE_NORM_QC_NO},
+ {0x1D649, UNICODE_NORM_QC_NO},
+ {0x1D64A, UNICODE_NORM_QC_NO},
+ {0x1D64B, UNICODE_NORM_QC_NO},
+ {0x1D64C, UNICODE_NORM_QC_NO},
+ {0x1D64D, UNICODE_NORM_QC_NO},
+ {0x1D64E, UNICODE_NORM_QC_NO},
+ {0x1D64F, UNICODE_NORM_QC_NO},
+ {0x1D650, UNICODE_NORM_QC_NO},
+ {0x1D651, UNICODE_NORM_QC_NO},
+ {0x1D652, UNICODE_NORM_QC_NO},
+ {0x1D653, UNICODE_NORM_QC_NO},
+ {0x1D654, UNICODE_NORM_QC_NO},
+ {0x1D655, UNICODE_NORM_QC_NO},
+ {0x1D656, UNICODE_NORM_QC_NO},
+ {0x1D657, UNICODE_NORM_QC_NO},
+ {0x1D658, UNICODE_NORM_QC_NO},
+ {0x1D659, UNICODE_NORM_QC_NO},
+ {0x1D65A, UNICODE_NORM_QC_NO},
+ {0x1D65B, UNICODE_NORM_QC_NO},
+ {0x1D65C, UNICODE_NORM_QC_NO},
+ {0x1D65D, UNICODE_NORM_QC_NO},
+ {0x1D65E, UNICODE_NORM_QC_NO},
+ {0x1D65F, UNICODE_NORM_QC_NO},
+ {0x1D660, UNICODE_NORM_QC_NO},
+ {0x1D661, UNICODE_NORM_QC_NO},
+ {0x1D662, UNICODE_NORM_QC_NO},
+ {0x1D663, UNICODE_NORM_QC_NO},
+ {0x1D664, UNICODE_NORM_QC_NO},
+ {0x1D665, UNICODE_NORM_QC_NO},
+ {0x1D666, UNICODE_NORM_QC_NO},
+ {0x1D667, UNICODE_NORM_QC_NO},
+ {0x1D668, UNICODE_NORM_QC_NO},
+ {0x1D669, UNICODE_NORM_QC_NO},
+ {0x1D66A, UNICODE_NORM_QC_NO},
+ {0x1D66B, UNICODE_NORM_QC_NO},
+ {0x1D66C, UNICODE_NORM_QC_NO},
+ {0x1D66D, UNICODE_NORM_QC_NO},
+ {0x1D66E, UNICODE_NORM_QC_NO},
+ {0x1D66F, UNICODE_NORM_QC_NO},
+ {0x1D670, UNICODE_NORM_QC_NO},
+ {0x1D671, UNICODE_NORM_QC_NO},
+ {0x1D672, UNICODE_NORM_QC_NO},
+ {0x1D673, UNICODE_NORM_QC_NO},
+ {0x1D674, UNICODE_NORM_QC_NO},
+ {0x1D675, UNICODE_NORM_QC_NO},
+ {0x1D676, UNICODE_NORM_QC_NO},
+ {0x1D677, UNICODE_NORM_QC_NO},
+ {0x1D678, UNICODE_NORM_QC_NO},
+ {0x1D679, UNICODE_NORM_QC_NO},
+ {0x1D67A, UNICODE_NORM_QC_NO},
+ {0x1D67B, UNICODE_NORM_QC_NO},
+ {0x1D67C, UNICODE_NORM_QC_NO},
+ {0x1D67D, UNICODE_NORM_QC_NO},
+ {0x1D67E, UNICODE_NORM_QC_NO},
+ {0x1D67F, UNICODE_NORM_QC_NO},
+ {0x1D680, UNICODE_NORM_QC_NO},
+ {0x1D681, UNICODE_NORM_QC_NO},
+ {0x1D682, UNICODE_NORM_QC_NO},
+ {0x1D683, UNICODE_NORM_QC_NO},
+ {0x1D684, UNICODE_NORM_QC_NO},
+ {0x1D685, UNICODE_NORM_QC_NO},
+ {0x1D686, UNICODE_NORM_QC_NO},
+ {0x1D687, UNICODE_NORM_QC_NO},
+ {0x1D688, UNICODE_NORM_QC_NO},
+ {0x1D689, UNICODE_NORM_QC_NO},
+ {0x1D68A, UNICODE_NORM_QC_NO},
+ {0x1D68B, UNICODE_NORM_QC_NO},
+ {0x1D68C, UNICODE_NORM_QC_NO},
+ {0x1D68D, UNICODE_NORM_QC_NO},
+ {0x1D68E, UNICODE_NORM_QC_NO},
+ {0x1D68F, UNICODE_NORM_QC_NO},
+ {0x1D690, UNICODE_NORM_QC_NO},
+ {0x1D691, UNICODE_NORM_QC_NO},
+ {0x1D692, UNICODE_NORM_QC_NO},
+ {0x1D693, UNICODE_NORM_QC_NO},
+ {0x1D694, UNICODE_NORM_QC_NO},
+ {0x1D695, UNICODE_NORM_QC_NO},
+ {0x1D696, UNICODE_NORM_QC_NO},
+ {0x1D697, UNICODE_NORM_QC_NO},
+ {0x1D698, UNICODE_NORM_QC_NO},
+ {0x1D699, UNICODE_NORM_QC_NO},
+ {0x1D69A, UNICODE_NORM_QC_NO},
+ {0x1D69B, UNICODE_NORM_QC_NO},
+ {0x1D69C, UNICODE_NORM_QC_NO},
+ {0x1D69D, UNICODE_NORM_QC_NO},
+ {0x1D69E, UNICODE_NORM_QC_NO},
+ {0x1D69F, UNICODE_NORM_QC_NO},
+ {0x1D6A0, UNICODE_NORM_QC_NO},
+ {0x1D6A1, UNICODE_NORM_QC_NO},
+ {0x1D6A2, UNICODE_NORM_QC_NO},
+ {0x1D6A3, UNICODE_NORM_QC_NO},
+ {0x1D6A4, UNICODE_NORM_QC_NO},
+ {0x1D6A5, UNICODE_NORM_QC_NO},
+ {0x1D6A8, UNICODE_NORM_QC_NO},
+ {0x1D6A9, UNICODE_NORM_QC_NO},
+ {0x1D6AA, UNICODE_NORM_QC_NO},
+ {0x1D6AB, UNICODE_NORM_QC_NO},
+ {0x1D6AC, UNICODE_NORM_QC_NO},
+ {0x1D6AD, UNICODE_NORM_QC_NO},
+ {0x1D6AE, UNICODE_NORM_QC_NO},
+ {0x1D6AF, UNICODE_NORM_QC_NO},
+ {0x1D6B0, UNICODE_NORM_QC_NO},
+ {0x1D6B1, UNICODE_NORM_QC_NO},
+ {0x1D6B2, UNICODE_NORM_QC_NO},
+ {0x1D6B3, UNICODE_NORM_QC_NO},
+ {0x1D6B4, UNICODE_NORM_QC_NO},
+ {0x1D6B5, UNICODE_NORM_QC_NO},
+ {0x1D6B6, UNICODE_NORM_QC_NO},
+ {0x1D6B7, UNICODE_NORM_QC_NO},
+ {0x1D6B8, UNICODE_NORM_QC_NO},
+ {0x1D6B9, UNICODE_NORM_QC_NO},
+ {0x1D6BA, UNICODE_NORM_QC_NO},
+ {0x1D6BB, UNICODE_NORM_QC_NO},
+ {0x1D6BC, UNICODE_NORM_QC_NO},
+ {0x1D6BD, UNICODE_NORM_QC_NO},
+ {0x1D6BE, UNICODE_NORM_QC_NO},
+ {0x1D6BF, UNICODE_NORM_QC_NO},
+ {0x1D6C0, UNICODE_NORM_QC_NO},
+ {0x1D6C1, UNICODE_NORM_QC_NO},
+ {0x1D6C2, UNICODE_NORM_QC_NO},
+ {0x1D6C3, UNICODE_NORM_QC_NO},
+ {0x1D6C4, UNICODE_NORM_QC_NO},
+ {0x1D6C5, UNICODE_NORM_QC_NO},
+ {0x1D6C6, UNICODE_NORM_QC_NO},
+ {0x1D6C7, UNICODE_NORM_QC_NO},
+ {0x1D6C8, UNICODE_NORM_QC_NO},
+ {0x1D6C9, UNICODE_NORM_QC_NO},
+ {0x1D6CA, UNICODE_NORM_QC_NO},
+ {0x1D6CB, UNICODE_NORM_QC_NO},
+ {0x1D6CC, UNICODE_NORM_QC_NO},
+ {0x1D6CD, UNICODE_NORM_QC_NO},
+ {0x1D6CE, UNICODE_NORM_QC_NO},
+ {0x1D6CF, UNICODE_NORM_QC_NO},
+ {0x1D6D0, UNICODE_NORM_QC_NO},
+ {0x1D6D1, UNICODE_NORM_QC_NO},
+ {0x1D6D2, UNICODE_NORM_QC_NO},
+ {0x1D6D3, UNICODE_NORM_QC_NO},
+ {0x1D6D4, UNICODE_NORM_QC_NO},
+ {0x1D6D5, UNICODE_NORM_QC_NO},
+ {0x1D6D6, UNICODE_NORM_QC_NO},
+ {0x1D6D7, UNICODE_NORM_QC_NO},
+ {0x1D6D8, UNICODE_NORM_QC_NO},
+ {0x1D6D9, UNICODE_NORM_QC_NO},
+ {0x1D6DA, UNICODE_NORM_QC_NO},
+ {0x1D6DB, UNICODE_NORM_QC_NO},
+ {0x1D6DC, UNICODE_NORM_QC_NO},
+ {0x1D6DD, UNICODE_NORM_QC_NO},
+ {0x1D6DE, UNICODE_NORM_QC_NO},
+ {0x1D6DF, UNICODE_NORM_QC_NO},
+ {0x1D6E0, UNICODE_NORM_QC_NO},
+ {0x1D6E1, UNICODE_NORM_QC_NO},
+ {0x1D6E2, UNICODE_NORM_QC_NO},
+ {0x1D6E3, UNICODE_NORM_QC_NO},
+ {0x1D6E4, UNICODE_NORM_QC_NO},
+ {0x1D6E5, UNICODE_NORM_QC_NO},
+ {0x1D6E6, UNICODE_NORM_QC_NO},
+ {0x1D6E7, UNICODE_NORM_QC_NO},
+ {0x1D6E8, UNICODE_NORM_QC_NO},
+ {0x1D6E9, UNICODE_NORM_QC_NO},
+ {0x1D6EA, UNICODE_NORM_QC_NO},
+ {0x1D6EB, UNICODE_NORM_QC_NO},
+ {0x1D6EC, UNICODE_NORM_QC_NO},
+ {0x1D6ED, UNICODE_NORM_QC_NO},
+ {0x1D6EE, UNICODE_NORM_QC_NO},
+ {0x1D6EF, UNICODE_NORM_QC_NO},
+ {0x1D6F0, UNICODE_NORM_QC_NO},
+ {0x1D6F1, UNICODE_NORM_QC_NO},
+ {0x1D6F2, UNICODE_NORM_QC_NO},
+ {0x1D6F3, UNICODE_NORM_QC_NO},
+ {0x1D6F4, UNICODE_NORM_QC_NO},
+ {0x1D6F5, UNICODE_NORM_QC_NO},
+ {0x1D6F6, UNICODE_NORM_QC_NO},
+ {0x1D6F7, UNICODE_NORM_QC_NO},
+ {0x1D6F8, UNICODE_NORM_QC_NO},
+ {0x1D6F9, UNICODE_NORM_QC_NO},
+ {0x1D6FA, UNICODE_NORM_QC_NO},
+ {0x1D6FB, UNICODE_NORM_QC_NO},
+ {0x1D6FC, UNICODE_NORM_QC_NO},
+ {0x1D6FD, UNICODE_NORM_QC_NO},
+ {0x1D6FE, UNICODE_NORM_QC_NO},
+ {0x1D6FF, UNICODE_NORM_QC_NO},
+ {0x1D700, UNICODE_NORM_QC_NO},
+ {0x1D701, UNICODE_NORM_QC_NO},
+ {0x1D702, UNICODE_NORM_QC_NO},
+ {0x1D703, UNICODE_NORM_QC_NO},
+ {0x1D704, UNICODE_NORM_QC_NO},
+ {0x1D705, UNICODE_NORM_QC_NO},
+ {0x1D706, UNICODE_NORM_QC_NO},
+ {0x1D707, UNICODE_NORM_QC_NO},
+ {0x1D708, UNICODE_NORM_QC_NO},
+ {0x1D709, UNICODE_NORM_QC_NO},
+ {0x1D70A, UNICODE_NORM_QC_NO},
+ {0x1D70B, UNICODE_NORM_QC_NO},
+ {0x1D70C, UNICODE_NORM_QC_NO},
+ {0x1D70D, UNICODE_NORM_QC_NO},
+ {0x1D70E, UNICODE_NORM_QC_NO},
+ {0x1D70F, UNICODE_NORM_QC_NO},
+ {0x1D710, UNICODE_NORM_QC_NO},
+ {0x1D711, UNICODE_NORM_QC_NO},
+ {0x1D712, UNICODE_NORM_QC_NO},
+ {0x1D713, UNICODE_NORM_QC_NO},
+ {0x1D714, UNICODE_NORM_QC_NO},
+ {0x1D715, UNICODE_NORM_QC_NO},
+ {0x1D716, UNICODE_NORM_QC_NO},
+ {0x1D717, UNICODE_NORM_QC_NO},
+ {0x1D718, UNICODE_NORM_QC_NO},
+ {0x1D719, UNICODE_NORM_QC_NO},
+ {0x1D71A, UNICODE_NORM_QC_NO},
+ {0x1D71B, UNICODE_NORM_QC_NO},
+ {0x1D71C, UNICODE_NORM_QC_NO},
+ {0x1D71D, UNICODE_NORM_QC_NO},
+ {0x1D71E, UNICODE_NORM_QC_NO},
+ {0x1D71F, UNICODE_NORM_QC_NO},
+ {0x1D720, UNICODE_NORM_QC_NO},
+ {0x1D721, UNICODE_NORM_QC_NO},
+ {0x1D722, UNICODE_NORM_QC_NO},
+ {0x1D723, UNICODE_NORM_QC_NO},
+ {0x1D724, UNICODE_NORM_QC_NO},
+ {0x1D725, UNICODE_NORM_QC_NO},
+ {0x1D726, UNICODE_NORM_QC_NO},
+ {0x1D727, UNICODE_NORM_QC_NO},
+ {0x1D728, UNICODE_NORM_QC_NO},
+ {0x1D729, UNICODE_NORM_QC_NO},
+ {0x1D72A, UNICODE_NORM_QC_NO},
+ {0x1D72B, UNICODE_NORM_QC_NO},
+ {0x1D72C, UNICODE_NORM_QC_NO},
+ {0x1D72D, UNICODE_NORM_QC_NO},
+ {0x1D72E, UNICODE_NORM_QC_NO},
+ {0x1D72F, UNICODE_NORM_QC_NO},
+ {0x1D730, UNICODE_NORM_QC_NO},
+ {0x1D731, UNICODE_NORM_QC_NO},
+ {0x1D732, UNICODE_NORM_QC_NO},
+ {0x1D733, UNICODE_NORM_QC_NO},
+ {0x1D734, UNICODE_NORM_QC_NO},
+ {0x1D735, UNICODE_NORM_QC_NO},
+ {0x1D736, UNICODE_NORM_QC_NO},
+ {0x1D737, UNICODE_NORM_QC_NO},
+ {0x1D738, UNICODE_NORM_QC_NO},
+ {0x1D739, UNICODE_NORM_QC_NO},
+ {0x1D73A, UNICODE_NORM_QC_NO},
+ {0x1D73B, UNICODE_NORM_QC_NO},
+ {0x1D73C, UNICODE_NORM_QC_NO},
+ {0x1D73D, UNICODE_NORM_QC_NO},
+ {0x1D73E, UNICODE_NORM_QC_NO},
+ {0x1D73F, UNICODE_NORM_QC_NO},
+ {0x1D740, UNICODE_NORM_QC_NO},
+ {0x1D741, UNICODE_NORM_QC_NO},
+ {0x1D742, UNICODE_NORM_QC_NO},
+ {0x1D743, UNICODE_NORM_QC_NO},
+ {0x1D744, UNICODE_NORM_QC_NO},
+ {0x1D745, UNICODE_NORM_QC_NO},
+ {0x1D746, UNICODE_NORM_QC_NO},
+ {0x1D747, UNICODE_NORM_QC_NO},
+ {0x1D748, UNICODE_NORM_QC_NO},
+ {0x1D749, UNICODE_NORM_QC_NO},
+ {0x1D74A, UNICODE_NORM_QC_NO},
+ {0x1D74B, UNICODE_NORM_QC_NO},
+ {0x1D74C, UNICODE_NORM_QC_NO},
+ {0x1D74D, UNICODE_NORM_QC_NO},
+ {0x1D74E, UNICODE_NORM_QC_NO},
+ {0x1D74F, UNICODE_NORM_QC_NO},
+ {0x1D750, UNICODE_NORM_QC_NO},
+ {0x1D751, UNICODE_NORM_QC_NO},
+ {0x1D752, UNICODE_NORM_QC_NO},
+ {0x1D753, UNICODE_NORM_QC_NO},
+ {0x1D754, UNICODE_NORM_QC_NO},
+ {0x1D755, UNICODE_NORM_QC_NO},
+ {0x1D756, UNICODE_NORM_QC_NO},
+ {0x1D757, UNICODE_NORM_QC_NO},
+ {0x1D758, UNICODE_NORM_QC_NO},
+ {0x1D759, UNICODE_NORM_QC_NO},
+ {0x1D75A, UNICODE_NORM_QC_NO},
+ {0x1D75B, UNICODE_NORM_QC_NO},
+ {0x1D75C, UNICODE_NORM_QC_NO},
+ {0x1D75D, UNICODE_NORM_QC_NO},
+ {0x1D75E, UNICODE_NORM_QC_NO},
+ {0x1D75F, UNICODE_NORM_QC_NO},
+ {0x1D760, UNICODE_NORM_QC_NO},
+ {0x1D761, UNICODE_NORM_QC_NO},
+ {0x1D762, UNICODE_NORM_QC_NO},
+ {0x1D763, UNICODE_NORM_QC_NO},
+ {0x1D764, UNICODE_NORM_QC_NO},
+ {0x1D765, UNICODE_NORM_QC_NO},
+ {0x1D766, UNICODE_NORM_QC_NO},
+ {0x1D767, UNICODE_NORM_QC_NO},
+ {0x1D768, UNICODE_NORM_QC_NO},
+ {0x1D769, UNICODE_NORM_QC_NO},
+ {0x1D76A, UNICODE_NORM_QC_NO},
+ {0x1D76B, UNICODE_NORM_QC_NO},
+ {0x1D76C, UNICODE_NORM_QC_NO},
+ {0x1D76D, UNICODE_NORM_QC_NO},
+ {0x1D76E, UNICODE_NORM_QC_NO},
+ {0x1D76F, UNICODE_NORM_QC_NO},
+ {0x1D770, UNICODE_NORM_QC_NO},
+ {0x1D771, UNICODE_NORM_QC_NO},
+ {0x1D772, UNICODE_NORM_QC_NO},
+ {0x1D773, UNICODE_NORM_QC_NO},
+ {0x1D774, UNICODE_NORM_QC_NO},
+ {0x1D775, UNICODE_NORM_QC_NO},
+ {0x1D776, UNICODE_NORM_QC_NO},
+ {0x1D777, UNICODE_NORM_QC_NO},
+ {0x1D778, UNICODE_NORM_QC_NO},
+ {0x1D779, UNICODE_NORM_QC_NO},
+ {0x1D77A, UNICODE_NORM_QC_NO},
+ {0x1D77B, UNICODE_NORM_QC_NO},
+ {0x1D77C, UNICODE_NORM_QC_NO},
+ {0x1D77D, UNICODE_NORM_QC_NO},
+ {0x1D77E, UNICODE_NORM_QC_NO},
+ {0x1D77F, UNICODE_NORM_QC_NO},
+ {0x1D780, UNICODE_NORM_QC_NO},
+ {0x1D781, UNICODE_NORM_QC_NO},
+ {0x1D782, UNICODE_NORM_QC_NO},
+ {0x1D783, UNICODE_NORM_QC_NO},
+ {0x1D784, UNICODE_NORM_QC_NO},
+ {0x1D785, UNICODE_NORM_QC_NO},
+ {0x1D786, UNICODE_NORM_QC_NO},
+ {0x1D787, UNICODE_NORM_QC_NO},
+ {0x1D788, UNICODE_NORM_QC_NO},
+ {0x1D789, UNICODE_NORM_QC_NO},
+ {0x1D78A, UNICODE_NORM_QC_NO},
+ {0x1D78B, UNICODE_NORM_QC_NO},
+ {0x1D78C, UNICODE_NORM_QC_NO},
+ {0x1D78D, UNICODE_NORM_QC_NO},
+ {0x1D78E, UNICODE_NORM_QC_NO},
+ {0x1D78F, UNICODE_NORM_QC_NO},
+ {0x1D790, UNICODE_NORM_QC_NO},
+ {0x1D791, UNICODE_NORM_QC_NO},
+ {0x1D792, UNICODE_NORM_QC_NO},
+ {0x1D793, UNICODE_NORM_QC_NO},
+ {0x1D794, UNICODE_NORM_QC_NO},
+ {0x1D795, UNICODE_NORM_QC_NO},
+ {0x1D796, UNICODE_NORM_QC_NO},
+ {0x1D797, UNICODE_NORM_QC_NO},
+ {0x1D798, UNICODE_NORM_QC_NO},
+ {0x1D799, UNICODE_NORM_QC_NO},
+ {0x1D79A, UNICODE_NORM_QC_NO},
+ {0x1D79B, UNICODE_NORM_QC_NO},
+ {0x1D79C, UNICODE_NORM_QC_NO},
+ {0x1D79D, UNICODE_NORM_QC_NO},
+ {0x1D79E, UNICODE_NORM_QC_NO},
+ {0x1D79F, UNICODE_NORM_QC_NO},
+ {0x1D7A0, UNICODE_NORM_QC_NO},
+ {0x1D7A1, UNICODE_NORM_QC_NO},
+ {0x1D7A2, UNICODE_NORM_QC_NO},
+ {0x1D7A3, UNICODE_NORM_QC_NO},
+ {0x1D7A4, UNICODE_NORM_QC_NO},
+ {0x1D7A5, UNICODE_NORM_QC_NO},
+ {0x1D7A6, UNICODE_NORM_QC_NO},
+ {0x1D7A7, UNICODE_NORM_QC_NO},
+ {0x1D7A8, UNICODE_NORM_QC_NO},
+ {0x1D7A9, UNICODE_NORM_QC_NO},
+ {0x1D7AA, UNICODE_NORM_QC_NO},
+ {0x1D7AB, UNICODE_NORM_QC_NO},
+ {0x1D7AC, UNICODE_NORM_QC_NO},
+ {0x1D7AD, UNICODE_NORM_QC_NO},
+ {0x1D7AE, UNICODE_NORM_QC_NO},
+ {0x1D7AF, UNICODE_NORM_QC_NO},
+ {0x1D7B0, UNICODE_NORM_QC_NO},
+ {0x1D7B1, UNICODE_NORM_QC_NO},
+ {0x1D7B2, UNICODE_NORM_QC_NO},
+ {0x1D7B3, UNICODE_NORM_QC_NO},
+ {0x1D7B4, UNICODE_NORM_QC_NO},
+ {0x1D7B5, UNICODE_NORM_QC_NO},
+ {0x1D7B6, UNICODE_NORM_QC_NO},
+ {0x1D7B7, UNICODE_NORM_QC_NO},
+ {0x1D7B8, UNICODE_NORM_QC_NO},
+ {0x1D7B9, UNICODE_NORM_QC_NO},
+ {0x1D7BA, UNICODE_NORM_QC_NO},
+ {0x1D7BB, UNICODE_NORM_QC_NO},
+ {0x1D7BC, UNICODE_NORM_QC_NO},
+ {0x1D7BD, UNICODE_NORM_QC_NO},
+ {0x1D7BE, UNICODE_NORM_QC_NO},
+ {0x1D7BF, UNICODE_NORM_QC_NO},
+ {0x1D7C0, UNICODE_NORM_QC_NO},
+ {0x1D7C1, UNICODE_NORM_QC_NO},
+ {0x1D7C2, UNICODE_NORM_QC_NO},
+ {0x1D7C3, UNICODE_NORM_QC_NO},
+ {0x1D7C4, UNICODE_NORM_QC_NO},
+ {0x1D7C5, UNICODE_NORM_QC_NO},
+ {0x1D7C6, UNICODE_NORM_QC_NO},
+ {0x1D7C7, UNICODE_NORM_QC_NO},
+ {0x1D7C8, UNICODE_NORM_QC_NO},
+ {0x1D7C9, UNICODE_NORM_QC_NO},
+ {0x1D7CA, UNICODE_NORM_QC_NO},
+ {0x1D7CB, UNICODE_NORM_QC_NO},
+ {0x1D7CE, UNICODE_NORM_QC_NO},
+ {0x1D7CF, UNICODE_NORM_QC_NO},
+ {0x1D7D0, UNICODE_NORM_QC_NO},
+ {0x1D7D1, UNICODE_NORM_QC_NO},
+ {0x1D7D2, UNICODE_NORM_QC_NO},
+ {0x1D7D3, UNICODE_NORM_QC_NO},
+ {0x1D7D4, UNICODE_NORM_QC_NO},
+ {0x1D7D5, UNICODE_NORM_QC_NO},
+ {0x1D7D6, UNICODE_NORM_QC_NO},
+ {0x1D7D7, UNICODE_NORM_QC_NO},
+ {0x1D7D8, UNICODE_NORM_QC_NO},
+ {0x1D7D9, UNICODE_NORM_QC_NO},
+ {0x1D7DA, UNICODE_NORM_QC_NO},
+ {0x1D7DB, UNICODE_NORM_QC_NO},
+ {0x1D7DC, UNICODE_NORM_QC_NO},
+ {0x1D7DD, UNICODE_NORM_QC_NO},
+ {0x1D7DE, UNICODE_NORM_QC_NO},
+ {0x1D7DF, UNICODE_NORM_QC_NO},
+ {0x1D7E0, UNICODE_NORM_QC_NO},
+ {0x1D7E1, UNICODE_NORM_QC_NO},
+ {0x1D7E2, UNICODE_NORM_QC_NO},
+ {0x1D7E3, UNICODE_NORM_QC_NO},
+ {0x1D7E4, UNICODE_NORM_QC_NO},
+ {0x1D7E5, UNICODE_NORM_QC_NO},
+ {0x1D7E6, UNICODE_NORM_QC_NO},
+ {0x1D7E7, UNICODE_NORM_QC_NO},
+ {0x1D7E8, UNICODE_NORM_QC_NO},
+ {0x1D7E9, UNICODE_NORM_QC_NO},
+ {0x1D7EA, UNICODE_NORM_QC_NO},
+ {0x1D7EB, UNICODE_NORM_QC_NO},
+ {0x1D7EC, UNICODE_NORM_QC_NO},
+ {0x1D7ED, UNICODE_NORM_QC_NO},
+ {0x1D7EE, UNICODE_NORM_QC_NO},
+ {0x1D7EF, UNICODE_NORM_QC_NO},
+ {0x1D7F0, UNICODE_NORM_QC_NO},
+ {0x1D7F1, UNICODE_NORM_QC_NO},
+ {0x1D7F2, UNICODE_NORM_QC_NO},
+ {0x1D7F3, UNICODE_NORM_QC_NO},
+ {0x1D7F4, UNICODE_NORM_QC_NO},
+ {0x1D7F5, UNICODE_NORM_QC_NO},
+ {0x1D7F6, UNICODE_NORM_QC_NO},
+ {0x1D7F7, UNICODE_NORM_QC_NO},
+ {0x1D7F8, UNICODE_NORM_QC_NO},
+ {0x1D7F9, UNICODE_NORM_QC_NO},
+ {0x1D7FA, UNICODE_NORM_QC_NO},
+ {0x1D7FB, UNICODE_NORM_QC_NO},
+ {0x1D7FC, UNICODE_NORM_QC_NO},
+ {0x1D7FD, UNICODE_NORM_QC_NO},
+ {0x1D7FE, UNICODE_NORM_QC_NO},
+ {0x1D7FF, UNICODE_NORM_QC_NO},
+ {0x1EE00, UNICODE_NORM_QC_NO},
+ {0x1EE01, UNICODE_NORM_QC_NO},
+ {0x1EE02, UNICODE_NORM_QC_NO},
+ {0x1EE03, UNICODE_NORM_QC_NO},
+ {0x1EE05, UNICODE_NORM_QC_NO},
+ {0x1EE06, UNICODE_NORM_QC_NO},
+ {0x1EE07, UNICODE_NORM_QC_NO},
+ {0x1EE08, UNICODE_NORM_QC_NO},
+ {0x1EE09, UNICODE_NORM_QC_NO},
+ {0x1EE0A, UNICODE_NORM_QC_NO},
+ {0x1EE0B, UNICODE_NORM_QC_NO},
+ {0x1EE0C, UNICODE_NORM_QC_NO},
+ {0x1EE0D, UNICODE_NORM_QC_NO},
+ {0x1EE0E, UNICODE_NORM_QC_NO},
+ {0x1EE0F, UNICODE_NORM_QC_NO},
+ {0x1EE10, UNICODE_NORM_QC_NO},
+ {0x1EE11, UNICODE_NORM_QC_NO},
+ {0x1EE12, UNICODE_NORM_QC_NO},
+ {0x1EE13, UNICODE_NORM_QC_NO},
+ {0x1EE14, UNICODE_NORM_QC_NO},
+ {0x1EE15, UNICODE_NORM_QC_NO},
+ {0x1EE16, UNICODE_NORM_QC_NO},
+ {0x1EE17, UNICODE_NORM_QC_NO},
+ {0x1EE18, UNICODE_NORM_QC_NO},
+ {0x1EE19, UNICODE_NORM_QC_NO},
+ {0x1EE1A, UNICODE_NORM_QC_NO},
+ {0x1EE1B, UNICODE_NORM_QC_NO},
+ {0x1EE1C, UNICODE_NORM_QC_NO},
+ {0x1EE1D, UNICODE_NORM_QC_NO},
+ {0x1EE1E, UNICODE_NORM_QC_NO},
+ {0x1EE1F, UNICODE_NORM_QC_NO},
+ {0x1EE21, UNICODE_NORM_QC_NO},
+ {0x1EE22, UNICODE_NORM_QC_NO},
+ {0x1EE24, UNICODE_NORM_QC_NO},
+ {0x1EE27, UNICODE_NORM_QC_NO},
+ {0x1EE29, UNICODE_NORM_QC_NO},
+ {0x1EE2A, UNICODE_NORM_QC_NO},
+ {0x1EE2B, UNICODE_NORM_QC_NO},
+ {0x1EE2C, UNICODE_NORM_QC_NO},
+ {0x1EE2D, UNICODE_NORM_QC_NO},
+ {0x1EE2E, UNICODE_NORM_QC_NO},
+ {0x1EE2F, UNICODE_NORM_QC_NO},
+ {0x1EE30, UNICODE_NORM_QC_NO},
+ {0x1EE31, UNICODE_NORM_QC_NO},
+ {0x1EE32, UNICODE_NORM_QC_NO},
+ {0x1EE34, UNICODE_NORM_QC_NO},
+ {0x1EE35, UNICODE_NORM_QC_NO},
+ {0x1EE36, UNICODE_NORM_QC_NO},
+ {0x1EE37, UNICODE_NORM_QC_NO},
+ {0x1EE39, UNICODE_NORM_QC_NO},
+ {0x1EE3B, UNICODE_NORM_QC_NO},
+ {0x1EE42, UNICODE_NORM_QC_NO},
+ {0x1EE47, UNICODE_NORM_QC_NO},
+ {0x1EE49, UNICODE_NORM_QC_NO},
+ {0x1EE4B, UNICODE_NORM_QC_NO},
+ {0x1EE4D, UNICODE_NORM_QC_NO},
+ {0x1EE4E, UNICODE_NORM_QC_NO},
+ {0x1EE4F, UNICODE_NORM_QC_NO},
+ {0x1EE51, UNICODE_NORM_QC_NO},
+ {0x1EE52, UNICODE_NORM_QC_NO},
+ {0x1EE54, UNICODE_NORM_QC_NO},
+ {0x1EE57, UNICODE_NORM_QC_NO},
+ {0x1EE59, UNICODE_NORM_QC_NO},
+ {0x1EE5B, UNICODE_NORM_QC_NO},
+ {0x1EE5D, UNICODE_NORM_QC_NO},
+ {0x1EE5F, UNICODE_NORM_QC_NO},
+ {0x1EE61, UNICODE_NORM_QC_NO},
+ {0x1EE62, UNICODE_NORM_QC_NO},
+ {0x1EE64, UNICODE_NORM_QC_NO},
+ {0x1EE67, UNICODE_NORM_QC_NO},
+ {0x1EE68, UNICODE_NORM_QC_NO},
+ {0x1EE69, UNICODE_NORM_QC_NO},
+ {0x1EE6A, UNICODE_NORM_QC_NO},
+ {0x1EE6C, UNICODE_NORM_QC_NO},
+ {0x1EE6D, UNICODE_NORM_QC_NO},
+ {0x1EE6E, UNICODE_NORM_QC_NO},
+ {0x1EE6F, UNICODE_NORM_QC_NO},
+ {0x1EE70, UNICODE_NORM_QC_NO},
+ {0x1EE71, UNICODE_NORM_QC_NO},
+ {0x1EE72, UNICODE_NORM_QC_NO},
+ {0x1EE74, UNICODE_NORM_QC_NO},
+ {0x1EE75, UNICODE_NORM_QC_NO},
+ {0x1EE76, UNICODE_NORM_QC_NO},
+ {0x1EE77, UNICODE_NORM_QC_NO},
+ {0x1EE79, UNICODE_NORM_QC_NO},
+ {0x1EE7A, UNICODE_NORM_QC_NO},
+ {0x1EE7B, UNICODE_NORM_QC_NO},
+ {0x1EE7C, UNICODE_NORM_QC_NO},
+ {0x1EE7E, UNICODE_NORM_QC_NO},
+ {0x1EE80, UNICODE_NORM_QC_NO},
+ {0x1EE81, UNICODE_NORM_QC_NO},
+ {0x1EE82, UNICODE_NORM_QC_NO},
+ {0x1EE83, UNICODE_NORM_QC_NO},
+ {0x1EE84, UNICODE_NORM_QC_NO},
+ {0x1EE85, UNICODE_NORM_QC_NO},
+ {0x1EE86, UNICODE_NORM_QC_NO},
+ {0x1EE87, UNICODE_NORM_QC_NO},
+ {0x1EE88, UNICODE_NORM_QC_NO},
+ {0x1EE89, UNICODE_NORM_QC_NO},
+ {0x1EE8B, UNICODE_NORM_QC_NO},
+ {0x1EE8C, UNICODE_NORM_QC_NO},
+ {0x1EE8D, UNICODE_NORM_QC_NO},
+ {0x1EE8E, UNICODE_NORM_QC_NO},
+ {0x1EE8F, UNICODE_NORM_QC_NO},
+ {0x1EE90, UNICODE_NORM_QC_NO},
+ {0x1EE91, UNICODE_NORM_QC_NO},
+ {0x1EE92, UNICODE_NORM_QC_NO},
+ {0x1EE93, UNICODE_NORM_QC_NO},
+ {0x1EE94, UNICODE_NORM_QC_NO},
+ {0x1EE95, UNICODE_NORM_QC_NO},
+ {0x1EE96, UNICODE_NORM_QC_NO},
+ {0x1EE97, UNICODE_NORM_QC_NO},
+ {0x1EE98, UNICODE_NORM_QC_NO},
+ {0x1EE99, UNICODE_NORM_QC_NO},
+ {0x1EE9A, UNICODE_NORM_QC_NO},
+ {0x1EE9B, UNICODE_NORM_QC_NO},
+ {0x1EEA1, UNICODE_NORM_QC_NO},
+ {0x1EEA2, UNICODE_NORM_QC_NO},
+ {0x1EEA3, UNICODE_NORM_QC_NO},
+ {0x1EEA5, UNICODE_NORM_QC_NO},
+ {0x1EEA6, UNICODE_NORM_QC_NO},
+ {0x1EEA7, UNICODE_NORM_QC_NO},
+ {0x1EEA8, UNICODE_NORM_QC_NO},
+ {0x1EEA9, UNICODE_NORM_QC_NO},
+ {0x1EEAB, UNICODE_NORM_QC_NO},
+ {0x1EEAC, UNICODE_NORM_QC_NO},
+ {0x1EEAD, UNICODE_NORM_QC_NO},
+ {0x1EEAE, UNICODE_NORM_QC_NO},
+ {0x1EEAF, UNICODE_NORM_QC_NO},
+ {0x1EEB0, UNICODE_NORM_QC_NO},
+ {0x1EEB1, UNICODE_NORM_QC_NO},
+ {0x1EEB2, UNICODE_NORM_QC_NO},
+ {0x1EEB3, UNICODE_NORM_QC_NO},
+ {0x1EEB4, UNICODE_NORM_QC_NO},
+ {0x1EEB5, UNICODE_NORM_QC_NO},
+ {0x1EEB6, UNICODE_NORM_QC_NO},
+ {0x1EEB7, UNICODE_NORM_QC_NO},
+ {0x1EEB8, UNICODE_NORM_QC_NO},
+ {0x1EEB9, UNICODE_NORM_QC_NO},
+ {0x1EEBA, UNICODE_NORM_QC_NO},
+ {0x1EEBB, UNICODE_NORM_QC_NO},
+ {0x1F100, UNICODE_NORM_QC_NO},
+ {0x1F101, UNICODE_NORM_QC_NO},
+ {0x1F102, UNICODE_NORM_QC_NO},
+ {0x1F103, UNICODE_NORM_QC_NO},
+ {0x1F104, UNICODE_NORM_QC_NO},
+ {0x1F105, UNICODE_NORM_QC_NO},
+ {0x1F106, UNICODE_NORM_QC_NO},
+ {0x1F107, UNICODE_NORM_QC_NO},
+ {0x1F108, UNICODE_NORM_QC_NO},
+ {0x1F109, UNICODE_NORM_QC_NO},
+ {0x1F10A, UNICODE_NORM_QC_NO},
+ {0x1F110, UNICODE_NORM_QC_NO},
+ {0x1F111, UNICODE_NORM_QC_NO},
+ {0x1F112, UNICODE_NORM_QC_NO},
+ {0x1F113, UNICODE_NORM_QC_NO},
+ {0x1F114, UNICODE_NORM_QC_NO},
+ {0x1F115, UNICODE_NORM_QC_NO},
+ {0x1F116, UNICODE_NORM_QC_NO},
+ {0x1F117, UNICODE_NORM_QC_NO},
+ {0x1F118, UNICODE_NORM_QC_NO},
+ {0x1F119, UNICODE_NORM_QC_NO},
+ {0x1F11A, UNICODE_NORM_QC_NO},
+ {0x1F11B, UNICODE_NORM_QC_NO},
+ {0x1F11C, UNICODE_NORM_QC_NO},
+ {0x1F11D, UNICODE_NORM_QC_NO},
+ {0x1F11E, UNICODE_NORM_QC_NO},
+ {0x1F11F, UNICODE_NORM_QC_NO},
+ {0x1F120, UNICODE_NORM_QC_NO},
+ {0x1F121, UNICODE_NORM_QC_NO},
+ {0x1F122, UNICODE_NORM_QC_NO},
+ {0x1F123, UNICODE_NORM_QC_NO},
+ {0x1F124, UNICODE_NORM_QC_NO},
+ {0x1F125, UNICODE_NORM_QC_NO},
+ {0x1F126, UNICODE_NORM_QC_NO},
+ {0x1F127, UNICODE_NORM_QC_NO},
+ {0x1F128, UNICODE_NORM_QC_NO},
+ {0x1F129, UNICODE_NORM_QC_NO},
+ {0x1F12A, UNICODE_NORM_QC_NO},
+ {0x1F12B, UNICODE_NORM_QC_NO},
+ {0x1F12C, UNICODE_NORM_QC_NO},
+ {0x1F12D, UNICODE_NORM_QC_NO},
+ {0x1F12E, UNICODE_NORM_QC_NO},
+ {0x1F130, UNICODE_NORM_QC_NO},
+ {0x1F131, UNICODE_NORM_QC_NO},
+ {0x1F132, UNICODE_NORM_QC_NO},
+ {0x1F133, UNICODE_NORM_QC_NO},
+ {0x1F134, UNICODE_NORM_QC_NO},
+ {0x1F135, UNICODE_NORM_QC_NO},
+ {0x1F136, UNICODE_NORM_QC_NO},
+ {0x1F137, UNICODE_NORM_QC_NO},
+ {0x1F138, UNICODE_NORM_QC_NO},
+ {0x1F139, UNICODE_NORM_QC_NO},
+ {0x1F13A, UNICODE_NORM_QC_NO},
+ {0x1F13B, UNICODE_NORM_QC_NO},
+ {0x1F13C, UNICODE_NORM_QC_NO},
+ {0x1F13D, UNICODE_NORM_QC_NO},
+ {0x1F13E, UNICODE_NORM_QC_NO},
+ {0x1F13F, UNICODE_NORM_QC_NO},
+ {0x1F140, UNICODE_NORM_QC_NO},
+ {0x1F141, UNICODE_NORM_QC_NO},
+ {0x1F142, UNICODE_NORM_QC_NO},
+ {0x1F143, UNICODE_NORM_QC_NO},
+ {0x1F144, UNICODE_NORM_QC_NO},
+ {0x1F145, UNICODE_NORM_QC_NO},
+ {0x1F146, UNICODE_NORM_QC_NO},
+ {0x1F147, UNICODE_NORM_QC_NO},
+ {0x1F148, UNICODE_NORM_QC_NO},
+ {0x1F149, UNICODE_NORM_QC_NO},
+ {0x1F14A, UNICODE_NORM_QC_NO},
+ {0x1F14B, UNICODE_NORM_QC_NO},
+ {0x1F14C, UNICODE_NORM_QC_NO},
+ {0x1F14D, UNICODE_NORM_QC_NO},
+ {0x1F14E, UNICODE_NORM_QC_NO},
+ {0x1F14F, UNICODE_NORM_QC_NO},
+ {0x1F16A, UNICODE_NORM_QC_NO},
+ {0x1F16B, UNICODE_NORM_QC_NO},
+ {0x1F16C, UNICODE_NORM_QC_NO},
+ {0x1F190, UNICODE_NORM_QC_NO},
+ {0x1F200, UNICODE_NORM_QC_NO},
+ {0x1F201, UNICODE_NORM_QC_NO},
+ {0x1F202, UNICODE_NORM_QC_NO},
+ {0x1F210, UNICODE_NORM_QC_NO},
+ {0x1F211, UNICODE_NORM_QC_NO},
+ {0x1F212, UNICODE_NORM_QC_NO},
+ {0x1F213, UNICODE_NORM_QC_NO},
+ {0x1F214, UNICODE_NORM_QC_NO},
+ {0x1F215, UNICODE_NORM_QC_NO},
+ {0x1F216, UNICODE_NORM_QC_NO},
+ {0x1F217, UNICODE_NORM_QC_NO},
+ {0x1F218, UNICODE_NORM_QC_NO},
+ {0x1F219, UNICODE_NORM_QC_NO},
+ {0x1F21A, UNICODE_NORM_QC_NO},
+ {0x1F21B, UNICODE_NORM_QC_NO},
+ {0x1F21C, UNICODE_NORM_QC_NO},
+ {0x1F21D, UNICODE_NORM_QC_NO},
+ {0x1F21E, UNICODE_NORM_QC_NO},
+ {0x1F21F, UNICODE_NORM_QC_NO},
+ {0x1F220, UNICODE_NORM_QC_NO},
+ {0x1F221, UNICODE_NORM_QC_NO},
+ {0x1F222, UNICODE_NORM_QC_NO},
+ {0x1F223, UNICODE_NORM_QC_NO},
+ {0x1F224, UNICODE_NORM_QC_NO},
+ {0x1F225, UNICODE_NORM_QC_NO},
+ {0x1F226, UNICODE_NORM_QC_NO},
+ {0x1F227, UNICODE_NORM_QC_NO},
+ {0x1F228, UNICODE_NORM_QC_NO},
+ {0x1F229, UNICODE_NORM_QC_NO},
+ {0x1F22A, UNICODE_NORM_QC_NO},
+ {0x1F22B, UNICODE_NORM_QC_NO},
+ {0x1F22C, UNICODE_NORM_QC_NO},
+ {0x1F22D, UNICODE_NORM_QC_NO},
+ {0x1F22E, UNICODE_NORM_QC_NO},
+ {0x1F22F, UNICODE_NORM_QC_NO},
+ {0x1F230, UNICODE_NORM_QC_NO},
+ {0x1F231, UNICODE_NORM_QC_NO},
+ {0x1F232, UNICODE_NORM_QC_NO},
+ {0x1F233, UNICODE_NORM_QC_NO},
+ {0x1F234, UNICODE_NORM_QC_NO},
+ {0x1F235, UNICODE_NORM_QC_NO},
+ {0x1F236, UNICODE_NORM_QC_NO},
+ {0x1F237, UNICODE_NORM_QC_NO},
+ {0x1F238, UNICODE_NORM_QC_NO},
+ {0x1F239, UNICODE_NORM_QC_NO},
+ {0x1F23A, UNICODE_NORM_QC_NO},
+ {0x1F23B, UNICODE_NORM_QC_NO},
+ {0x1F240, UNICODE_NORM_QC_NO},
+ {0x1F241, UNICODE_NORM_QC_NO},
+ {0x1F242, UNICODE_NORM_QC_NO},
+ {0x1F243, UNICODE_NORM_QC_NO},
+ {0x1F244, UNICODE_NORM_QC_NO},
+ {0x1F245, UNICODE_NORM_QC_NO},
+ {0x1F246, UNICODE_NORM_QC_NO},
+ {0x1F247, UNICODE_NORM_QC_NO},
+ {0x1F248, UNICODE_NORM_QC_NO},
+ {0x1F250, UNICODE_NORM_QC_NO},
+ {0x1F251, UNICODE_NORM_QC_NO},
+ {0x1FBF0, UNICODE_NORM_QC_NO},
+ {0x1FBF1, UNICODE_NORM_QC_NO},
+ {0x1FBF2, UNICODE_NORM_QC_NO},
+ {0x1FBF3, UNICODE_NORM_QC_NO},
+ {0x1FBF4, UNICODE_NORM_QC_NO},
+ {0x1FBF5, UNICODE_NORM_QC_NO},
+ {0x1FBF6, UNICODE_NORM_QC_NO},
+ {0x1FBF7, UNICODE_NORM_QC_NO},
+ {0x1FBF8, UNICODE_NORM_QC_NO},
+ {0x1FBF9, UNICODE_NORM_QC_NO},
+ {0x2F800, UNICODE_NORM_QC_NO},
+ {0x2F801, UNICODE_NORM_QC_NO},
+ {0x2F802, UNICODE_NORM_QC_NO},
+ {0x2F803, UNICODE_NORM_QC_NO},
+ {0x2F804, UNICODE_NORM_QC_NO},
+ {0x2F805, UNICODE_NORM_QC_NO},
+ {0x2F806, UNICODE_NORM_QC_NO},
+ {0x2F807, UNICODE_NORM_QC_NO},
+ {0x2F808, UNICODE_NORM_QC_NO},
+ {0x2F809, UNICODE_NORM_QC_NO},
+ {0x2F80A, UNICODE_NORM_QC_NO},
+ {0x2F80B, UNICODE_NORM_QC_NO},
+ {0x2F80C, UNICODE_NORM_QC_NO},
+ {0x2F80D, UNICODE_NORM_QC_NO},
+ {0x2F80E, UNICODE_NORM_QC_NO},
+ {0x2F80F, UNICODE_NORM_QC_NO},
+ {0x2F810, UNICODE_NORM_QC_NO},
+ {0x2F811, UNICODE_NORM_QC_NO},
+ {0x2F812, UNICODE_NORM_QC_NO},
+ {0x2F813, UNICODE_NORM_QC_NO},
+ {0x2F814, UNICODE_NORM_QC_NO},
+ {0x2F815, UNICODE_NORM_QC_NO},
+ {0x2F816, UNICODE_NORM_QC_NO},
+ {0x2F817, UNICODE_NORM_QC_NO},
+ {0x2F818, UNICODE_NORM_QC_NO},
+ {0x2F819, UNICODE_NORM_QC_NO},
+ {0x2F81A, UNICODE_NORM_QC_NO},
+ {0x2F81B, UNICODE_NORM_QC_NO},
+ {0x2F81C, UNICODE_NORM_QC_NO},
+ {0x2F81D, UNICODE_NORM_QC_NO},
+ {0x2F81E, UNICODE_NORM_QC_NO},
+ {0x2F81F, UNICODE_NORM_QC_NO},
+ {0x2F820, UNICODE_NORM_QC_NO},
+ {0x2F821, UNICODE_NORM_QC_NO},
+ {0x2F822, UNICODE_NORM_QC_NO},
+ {0x2F823, UNICODE_NORM_QC_NO},
+ {0x2F824, UNICODE_NORM_QC_NO},
+ {0x2F825, UNICODE_NORM_QC_NO},
+ {0x2F826, UNICODE_NORM_QC_NO},
+ {0x2F827, UNICODE_NORM_QC_NO},
+ {0x2F828, UNICODE_NORM_QC_NO},
+ {0x2F829, UNICODE_NORM_QC_NO},
+ {0x2F82A, UNICODE_NORM_QC_NO},
+ {0x2F82B, UNICODE_NORM_QC_NO},
+ {0x2F82C, UNICODE_NORM_QC_NO},
+ {0x2F82D, UNICODE_NORM_QC_NO},
+ {0x2F82E, UNICODE_NORM_QC_NO},
+ {0x2F82F, UNICODE_NORM_QC_NO},
+ {0x2F830, UNICODE_NORM_QC_NO},
+ {0x2F831, UNICODE_NORM_QC_NO},
+ {0x2F832, UNICODE_NORM_QC_NO},
+ {0x2F833, UNICODE_NORM_QC_NO},
+ {0x2F834, UNICODE_NORM_QC_NO},
+ {0x2F835, UNICODE_NORM_QC_NO},
+ {0x2F836, UNICODE_NORM_QC_NO},
+ {0x2F837, UNICODE_NORM_QC_NO},
+ {0x2F838, UNICODE_NORM_QC_NO},
+ {0x2F839, UNICODE_NORM_QC_NO},
+ {0x2F83A, UNICODE_NORM_QC_NO},
+ {0x2F83B, UNICODE_NORM_QC_NO},
+ {0x2F83C, UNICODE_NORM_QC_NO},
+ {0x2F83D, UNICODE_NORM_QC_NO},
+ {0x2F83E, UNICODE_NORM_QC_NO},
+ {0x2F83F, UNICODE_NORM_QC_NO},
+ {0x2F840, UNICODE_NORM_QC_NO},
+ {0x2F841, UNICODE_NORM_QC_NO},
+ {0x2F842, UNICODE_NORM_QC_NO},
+ {0x2F843, UNICODE_NORM_QC_NO},
+ {0x2F844, UNICODE_NORM_QC_NO},
+ {0x2F845, UNICODE_NORM_QC_NO},
+ {0x2F846, UNICODE_NORM_QC_NO},
+ {0x2F847, UNICODE_NORM_QC_NO},
+ {0x2F848, UNICODE_NORM_QC_NO},
+ {0x2F849, UNICODE_NORM_QC_NO},
+ {0x2F84A, UNICODE_NORM_QC_NO},
+ {0x2F84B, UNICODE_NORM_QC_NO},
+ {0x2F84C, UNICODE_NORM_QC_NO},
+ {0x2F84D, UNICODE_NORM_QC_NO},
+ {0x2F84E, UNICODE_NORM_QC_NO},
+ {0x2F84F, UNICODE_NORM_QC_NO},
+ {0x2F850, UNICODE_NORM_QC_NO},
+ {0x2F851, UNICODE_NORM_QC_NO},
+ {0x2F852, UNICODE_NORM_QC_NO},
+ {0x2F853, UNICODE_NORM_QC_NO},
+ {0x2F854, UNICODE_NORM_QC_NO},
+ {0x2F855, UNICODE_NORM_QC_NO},
+ {0x2F856, UNICODE_NORM_QC_NO},
+ {0x2F857, UNICODE_NORM_QC_NO},
+ {0x2F858, UNICODE_NORM_QC_NO},
+ {0x2F859, UNICODE_NORM_QC_NO},
+ {0x2F85A, UNICODE_NORM_QC_NO},
+ {0x2F85B, UNICODE_NORM_QC_NO},
+ {0x2F85C, UNICODE_NORM_QC_NO},
+ {0x2F85D, UNICODE_NORM_QC_NO},
+ {0x2F85E, UNICODE_NORM_QC_NO},
+ {0x2F85F, UNICODE_NORM_QC_NO},
+ {0x2F860, UNICODE_NORM_QC_NO},
+ {0x2F861, UNICODE_NORM_QC_NO},
+ {0x2F862, UNICODE_NORM_QC_NO},
+ {0x2F863, UNICODE_NORM_QC_NO},
+ {0x2F864, UNICODE_NORM_QC_NO},
+ {0x2F865, UNICODE_NORM_QC_NO},
+ {0x2F866, UNICODE_NORM_QC_NO},
+ {0x2F867, UNICODE_NORM_QC_NO},
+ {0x2F868, UNICODE_NORM_QC_NO},
+ {0x2F869, UNICODE_NORM_QC_NO},
+ {0x2F86A, UNICODE_NORM_QC_NO},
+ {0x2F86B, UNICODE_NORM_QC_NO},
+ {0x2F86C, UNICODE_NORM_QC_NO},
+ {0x2F86D, UNICODE_NORM_QC_NO},
+ {0x2F86E, UNICODE_NORM_QC_NO},
+ {0x2F86F, UNICODE_NORM_QC_NO},
+ {0x2F870, UNICODE_NORM_QC_NO},
+ {0x2F871, UNICODE_NORM_QC_NO},
+ {0x2F872, UNICODE_NORM_QC_NO},
+ {0x2F873, UNICODE_NORM_QC_NO},
+ {0x2F874, UNICODE_NORM_QC_NO},
+ {0x2F875, UNICODE_NORM_QC_NO},
+ {0x2F876, UNICODE_NORM_QC_NO},
+ {0x2F877, UNICODE_NORM_QC_NO},
+ {0x2F878, UNICODE_NORM_QC_NO},
+ {0x2F879, UNICODE_NORM_QC_NO},
+ {0x2F87A, UNICODE_NORM_QC_NO},
+ {0x2F87B, UNICODE_NORM_QC_NO},
+ {0x2F87C, UNICODE_NORM_QC_NO},
+ {0x2F87D, UNICODE_NORM_QC_NO},
+ {0x2F87E, UNICODE_NORM_QC_NO},
+ {0x2F87F, UNICODE_NORM_QC_NO},
+ {0x2F880, UNICODE_NORM_QC_NO},
+ {0x2F881, UNICODE_NORM_QC_NO},
+ {0x2F882, UNICODE_NORM_QC_NO},
+ {0x2F883, UNICODE_NORM_QC_NO},
+ {0x2F884, UNICODE_NORM_QC_NO},
+ {0x2F885, UNICODE_NORM_QC_NO},
+ {0x2F886, UNICODE_NORM_QC_NO},
+ {0x2F887, UNICODE_NORM_QC_NO},
+ {0x2F888, UNICODE_NORM_QC_NO},
+ {0x2F889, UNICODE_NORM_QC_NO},
+ {0x2F88A, UNICODE_NORM_QC_NO},
+ {0x2F88B, UNICODE_NORM_QC_NO},
+ {0x2F88C, UNICODE_NORM_QC_NO},
+ {0x2F88D, UNICODE_NORM_QC_NO},
+ {0x2F88E, UNICODE_NORM_QC_NO},
+ {0x2F88F, UNICODE_NORM_QC_NO},
+ {0x2F890, UNICODE_NORM_QC_NO},
+ {0x2F891, UNICODE_NORM_QC_NO},
+ {0x2F892, UNICODE_NORM_QC_NO},
+ {0x2F893, UNICODE_NORM_QC_NO},
+ {0x2F894, UNICODE_NORM_QC_NO},
+ {0x2F895, UNICODE_NORM_QC_NO},
+ {0x2F896, UNICODE_NORM_QC_NO},
+ {0x2F897, UNICODE_NORM_QC_NO},
+ {0x2F898, UNICODE_NORM_QC_NO},
+ {0x2F899, UNICODE_NORM_QC_NO},
+ {0x2F89A, UNICODE_NORM_QC_NO},
+ {0x2F89B, UNICODE_NORM_QC_NO},
+ {0x2F89C, UNICODE_NORM_QC_NO},
+ {0x2F89D, UNICODE_NORM_QC_NO},
+ {0x2F89E, UNICODE_NORM_QC_NO},
+ {0x2F89F, UNICODE_NORM_QC_NO},
+ {0x2F8A0, UNICODE_NORM_QC_NO},
+ {0x2F8A1, UNICODE_NORM_QC_NO},
+ {0x2F8A2, UNICODE_NORM_QC_NO},
+ {0x2F8A3, UNICODE_NORM_QC_NO},
+ {0x2F8A4, UNICODE_NORM_QC_NO},
+ {0x2F8A5, UNICODE_NORM_QC_NO},
+ {0x2F8A6, UNICODE_NORM_QC_NO},
+ {0x2F8A7, UNICODE_NORM_QC_NO},
+ {0x2F8A8, UNICODE_NORM_QC_NO},
+ {0x2F8A9, UNICODE_NORM_QC_NO},
+ {0x2F8AA, UNICODE_NORM_QC_NO},
+ {0x2F8AB, UNICODE_NORM_QC_NO},
+ {0x2F8AC, UNICODE_NORM_QC_NO},
+ {0x2F8AD, UNICODE_NORM_QC_NO},
+ {0x2F8AE, UNICODE_NORM_QC_NO},
+ {0x2F8AF, UNICODE_NORM_QC_NO},
+ {0x2F8B0, UNICODE_NORM_QC_NO},
+ {0x2F8B1, UNICODE_NORM_QC_NO},
+ {0x2F8B2, UNICODE_NORM_QC_NO},
+ {0x2F8B3, UNICODE_NORM_QC_NO},
+ {0x2F8B4, UNICODE_NORM_QC_NO},
+ {0x2F8B5, UNICODE_NORM_QC_NO},
+ {0x2F8B6, UNICODE_NORM_QC_NO},
+ {0x2F8B7, UNICODE_NORM_QC_NO},
+ {0x2F8B8, UNICODE_NORM_QC_NO},
+ {0x2F8B9, UNICODE_NORM_QC_NO},
+ {0x2F8BA, UNICODE_NORM_QC_NO},
+ {0x2F8BB, UNICODE_NORM_QC_NO},
+ {0x2F8BC, UNICODE_NORM_QC_NO},
+ {0x2F8BD, UNICODE_NORM_QC_NO},
+ {0x2F8BE, UNICODE_NORM_QC_NO},
+ {0x2F8BF, UNICODE_NORM_QC_NO},
+ {0x2F8C0, UNICODE_NORM_QC_NO},
+ {0x2F8C1, UNICODE_NORM_QC_NO},
+ {0x2F8C2, UNICODE_NORM_QC_NO},
+ {0x2F8C3, UNICODE_NORM_QC_NO},
+ {0x2F8C4, UNICODE_NORM_QC_NO},
+ {0x2F8C5, UNICODE_NORM_QC_NO},
+ {0x2F8C6, UNICODE_NORM_QC_NO},
+ {0x2F8C7, UNICODE_NORM_QC_NO},
+ {0x2F8C8, UNICODE_NORM_QC_NO},
+ {0x2F8C9, UNICODE_NORM_QC_NO},
+ {0x2F8CA, UNICODE_NORM_QC_NO},
+ {0x2F8CB, UNICODE_NORM_QC_NO},
+ {0x2F8CC, UNICODE_NORM_QC_NO},
+ {0x2F8CD, UNICODE_NORM_QC_NO},
+ {0x2F8CE, UNICODE_NORM_QC_NO},
+ {0x2F8CF, UNICODE_NORM_QC_NO},
+ {0x2F8D0, UNICODE_NORM_QC_NO},
+ {0x2F8D1, UNICODE_NORM_QC_NO},
+ {0x2F8D2, UNICODE_NORM_QC_NO},
+ {0x2F8D3, UNICODE_NORM_QC_NO},
+ {0x2F8D4, UNICODE_NORM_QC_NO},
+ {0x2F8D5, UNICODE_NORM_QC_NO},
+ {0x2F8D6, UNICODE_NORM_QC_NO},
+ {0x2F8D7, UNICODE_NORM_QC_NO},
+ {0x2F8D8, UNICODE_NORM_QC_NO},
+ {0x2F8D9, UNICODE_NORM_QC_NO},
+ {0x2F8DA, UNICODE_NORM_QC_NO},
+ {0x2F8DB, UNICODE_NORM_QC_NO},
+ {0x2F8DC, UNICODE_NORM_QC_NO},
+ {0x2F8DD, UNICODE_NORM_QC_NO},
+ {0x2F8DE, UNICODE_NORM_QC_NO},
+ {0x2F8DF, UNICODE_NORM_QC_NO},
+ {0x2F8E0, UNICODE_NORM_QC_NO},
+ {0x2F8E1, UNICODE_NORM_QC_NO},
+ {0x2F8E2, UNICODE_NORM_QC_NO},
+ {0x2F8E3, UNICODE_NORM_QC_NO},
+ {0x2F8E4, UNICODE_NORM_QC_NO},
+ {0x2F8E5, UNICODE_NORM_QC_NO},
+ {0x2F8E6, UNICODE_NORM_QC_NO},
+ {0x2F8E7, UNICODE_NORM_QC_NO},
+ {0x2F8E8, UNICODE_NORM_QC_NO},
+ {0x2F8E9, UNICODE_NORM_QC_NO},
+ {0x2F8EA, UNICODE_NORM_QC_NO},
+ {0x2F8EB, UNICODE_NORM_QC_NO},
+ {0x2F8EC, UNICODE_NORM_QC_NO},
+ {0x2F8ED, UNICODE_NORM_QC_NO},
+ {0x2F8EE, UNICODE_NORM_QC_NO},
+ {0x2F8EF, UNICODE_NORM_QC_NO},
+ {0x2F8F0, UNICODE_NORM_QC_NO},
+ {0x2F8F1, UNICODE_NORM_QC_NO},
+ {0x2F8F2, UNICODE_NORM_QC_NO},
+ {0x2F8F3, UNICODE_NORM_QC_NO},
+ {0x2F8F4, UNICODE_NORM_QC_NO},
+ {0x2F8F5, UNICODE_NORM_QC_NO},
+ {0x2F8F6, UNICODE_NORM_QC_NO},
+ {0x2F8F7, UNICODE_NORM_QC_NO},
+ {0x2F8F8, UNICODE_NORM_QC_NO},
+ {0x2F8F9, UNICODE_NORM_QC_NO},
+ {0x2F8FA, UNICODE_NORM_QC_NO},
+ {0x2F8FB, UNICODE_NORM_QC_NO},
+ {0x2F8FC, UNICODE_NORM_QC_NO},
+ {0x2F8FD, UNICODE_NORM_QC_NO},
+ {0x2F8FE, UNICODE_NORM_QC_NO},
+ {0x2F8FF, UNICODE_NORM_QC_NO},
+ {0x2F900, UNICODE_NORM_QC_NO},
+ {0x2F901, UNICODE_NORM_QC_NO},
+ {0x2F902, UNICODE_NORM_QC_NO},
+ {0x2F903, UNICODE_NORM_QC_NO},
+ {0x2F904, UNICODE_NORM_QC_NO},
+ {0x2F905, UNICODE_NORM_QC_NO},
+ {0x2F906, UNICODE_NORM_QC_NO},
+ {0x2F907, UNICODE_NORM_QC_NO},
+ {0x2F908, UNICODE_NORM_QC_NO},
+ {0x2F909, UNICODE_NORM_QC_NO},
+ {0x2F90A, UNICODE_NORM_QC_NO},
+ {0x2F90B, UNICODE_NORM_QC_NO},
+ {0x2F90C, UNICODE_NORM_QC_NO},
+ {0x2F90D, UNICODE_NORM_QC_NO},
+ {0x2F90E, UNICODE_NORM_QC_NO},
+ {0x2F90F, UNICODE_NORM_QC_NO},
+ {0x2F910, UNICODE_NORM_QC_NO},
+ {0x2F911, UNICODE_NORM_QC_NO},
+ {0x2F912, UNICODE_NORM_QC_NO},
+ {0x2F913, UNICODE_NORM_QC_NO},
+ {0x2F914, UNICODE_NORM_QC_NO},
+ {0x2F915, UNICODE_NORM_QC_NO},
+ {0x2F916, UNICODE_NORM_QC_NO},
+ {0x2F917, UNICODE_NORM_QC_NO},
+ {0x2F918, UNICODE_NORM_QC_NO},
+ {0x2F919, UNICODE_NORM_QC_NO},
+ {0x2F91A, UNICODE_NORM_QC_NO},
+ {0x2F91B, UNICODE_NORM_QC_NO},
+ {0x2F91C, UNICODE_NORM_QC_NO},
+ {0x2F91D, UNICODE_NORM_QC_NO},
+ {0x2F91E, UNICODE_NORM_QC_NO},
+ {0x2F91F, UNICODE_NORM_QC_NO},
+ {0x2F920, UNICODE_NORM_QC_NO},
+ {0x2F921, UNICODE_NORM_QC_NO},
+ {0x2F922, UNICODE_NORM_QC_NO},
+ {0x2F923, UNICODE_NORM_QC_NO},
+ {0x2F924, UNICODE_NORM_QC_NO},
+ {0x2F925, UNICODE_NORM_QC_NO},
+ {0x2F926, UNICODE_NORM_QC_NO},
+ {0x2F927, UNICODE_NORM_QC_NO},
+ {0x2F928, UNICODE_NORM_QC_NO},
+ {0x2F929, UNICODE_NORM_QC_NO},
+ {0x2F92A, UNICODE_NORM_QC_NO},
+ {0x2F92B, UNICODE_NORM_QC_NO},
+ {0x2F92C, UNICODE_NORM_QC_NO},
+ {0x2F92D, UNICODE_NORM_QC_NO},
+ {0x2F92E, UNICODE_NORM_QC_NO},
+ {0x2F92F, UNICODE_NORM_QC_NO},
+ {0x2F930, UNICODE_NORM_QC_NO},
+ {0x2F931, UNICODE_NORM_QC_NO},
+ {0x2F932, UNICODE_NORM_QC_NO},
+ {0x2F933, UNICODE_NORM_QC_NO},
+ {0x2F934, UNICODE_NORM_QC_NO},
+ {0x2F935, UNICODE_NORM_QC_NO},
+ {0x2F936, UNICODE_NORM_QC_NO},
+ {0x2F937, UNICODE_NORM_QC_NO},
+ {0x2F938, UNICODE_NORM_QC_NO},
+ {0x2F939, UNICODE_NORM_QC_NO},
+ {0x2F93A, UNICODE_NORM_QC_NO},
+ {0x2F93B, UNICODE_NORM_QC_NO},
+ {0x2F93C, UNICODE_NORM_QC_NO},
+ {0x2F93D, UNICODE_NORM_QC_NO},
+ {0x2F93E, UNICODE_NORM_QC_NO},
+ {0x2F93F, UNICODE_NORM_QC_NO},
+ {0x2F940, UNICODE_NORM_QC_NO},
+ {0x2F941, UNICODE_NORM_QC_NO},
+ {0x2F942, UNICODE_NORM_QC_NO},
+ {0x2F943, UNICODE_NORM_QC_NO},
+ {0x2F944, UNICODE_NORM_QC_NO},
+ {0x2F945, UNICODE_NORM_QC_NO},
+ {0x2F946, UNICODE_NORM_QC_NO},
+ {0x2F947, UNICODE_NORM_QC_NO},
+ {0x2F948, UNICODE_NORM_QC_NO},
+ {0x2F949, UNICODE_NORM_QC_NO},
+ {0x2F94A, UNICODE_NORM_QC_NO},
+ {0x2F94B, UNICODE_NORM_QC_NO},
+ {0x2F94C, UNICODE_NORM_QC_NO},
+ {0x2F94D, UNICODE_NORM_QC_NO},
+ {0x2F94E, UNICODE_NORM_QC_NO},
+ {0x2F94F, UNICODE_NORM_QC_NO},
+ {0x2F950, UNICODE_NORM_QC_NO},
+ {0x2F951, UNICODE_NORM_QC_NO},
+ {0x2F952, UNICODE_NORM_QC_NO},
+ {0x2F953, UNICODE_NORM_QC_NO},
+ {0x2F954, UNICODE_NORM_QC_NO},
+ {0x2F955, UNICODE_NORM_QC_NO},
+ {0x2F956, UNICODE_NORM_QC_NO},
+ {0x2F957, UNICODE_NORM_QC_NO},
+ {0x2F958, UNICODE_NORM_QC_NO},
+ {0x2F959, UNICODE_NORM_QC_NO},
+ {0x2F95A, UNICODE_NORM_QC_NO},
+ {0x2F95B, UNICODE_NORM_QC_NO},
+ {0x2F95C, UNICODE_NORM_QC_NO},
+ {0x2F95D, UNICODE_NORM_QC_NO},
+ {0x2F95E, UNICODE_NORM_QC_NO},
+ {0x2F95F, UNICODE_NORM_QC_NO},
+ {0x2F960, UNICODE_NORM_QC_NO},
+ {0x2F961, UNICODE_NORM_QC_NO},
+ {0x2F962, UNICODE_NORM_QC_NO},
+ {0x2F963, UNICODE_NORM_QC_NO},
+ {0x2F964, UNICODE_NORM_QC_NO},
+ {0x2F965, UNICODE_NORM_QC_NO},
+ {0x2F966, UNICODE_NORM_QC_NO},
+ {0x2F967, UNICODE_NORM_QC_NO},
+ {0x2F968, UNICODE_NORM_QC_NO},
+ {0x2F969, UNICODE_NORM_QC_NO},
+ {0x2F96A, UNICODE_NORM_QC_NO},
+ {0x2F96B, UNICODE_NORM_QC_NO},
+ {0x2F96C, UNICODE_NORM_QC_NO},
+ {0x2F96D, UNICODE_NORM_QC_NO},
+ {0x2F96E, UNICODE_NORM_QC_NO},
+ {0x2F96F, UNICODE_NORM_QC_NO},
+ {0x2F970, UNICODE_NORM_QC_NO},
+ {0x2F971, UNICODE_NORM_QC_NO},
+ {0x2F972, UNICODE_NORM_QC_NO},
+ {0x2F973, UNICODE_NORM_QC_NO},
+ {0x2F974, UNICODE_NORM_QC_NO},
+ {0x2F975, UNICODE_NORM_QC_NO},
+ {0x2F976, UNICODE_NORM_QC_NO},
+ {0x2F977, UNICODE_NORM_QC_NO},
+ {0x2F978, UNICODE_NORM_QC_NO},
+ {0x2F979, UNICODE_NORM_QC_NO},
+ {0x2F97A, UNICODE_NORM_QC_NO},
+ {0x2F97B, UNICODE_NORM_QC_NO},
+ {0x2F97C, UNICODE_NORM_QC_NO},
+ {0x2F97D, UNICODE_NORM_QC_NO},
+ {0x2F97E, UNICODE_NORM_QC_NO},
+ {0x2F97F, UNICODE_NORM_QC_NO},
+ {0x2F980, UNICODE_NORM_QC_NO},
+ {0x2F981, UNICODE_NORM_QC_NO},
+ {0x2F982, UNICODE_NORM_QC_NO},
+ {0x2F983, UNICODE_NORM_QC_NO},
+ {0x2F984, UNICODE_NORM_QC_NO},
+ {0x2F985, UNICODE_NORM_QC_NO},
+ {0x2F986, UNICODE_NORM_QC_NO},
+ {0x2F987, UNICODE_NORM_QC_NO},
+ {0x2F988, UNICODE_NORM_QC_NO},
+ {0x2F989, UNICODE_NORM_QC_NO},
+ {0x2F98A, UNICODE_NORM_QC_NO},
+ {0x2F98B, UNICODE_NORM_QC_NO},
+ {0x2F98C, UNICODE_NORM_QC_NO},
+ {0x2F98D, UNICODE_NORM_QC_NO},
+ {0x2F98E, UNICODE_NORM_QC_NO},
+ {0x2F98F, UNICODE_NORM_QC_NO},
+ {0x2F990, UNICODE_NORM_QC_NO},
+ {0x2F991, UNICODE_NORM_QC_NO},
+ {0x2F992, UNICODE_NORM_QC_NO},
+ {0x2F993, UNICODE_NORM_QC_NO},
+ {0x2F994, UNICODE_NORM_QC_NO},
+ {0x2F995, UNICODE_NORM_QC_NO},
+ {0x2F996, UNICODE_NORM_QC_NO},
+ {0x2F997, UNICODE_NORM_QC_NO},
+ {0x2F998, UNICODE_NORM_QC_NO},
+ {0x2F999, UNICODE_NORM_QC_NO},
+ {0x2F99A, UNICODE_NORM_QC_NO},
+ {0x2F99B, UNICODE_NORM_QC_NO},
+ {0x2F99C, UNICODE_NORM_QC_NO},
+ {0x2F99D, UNICODE_NORM_QC_NO},
+ {0x2F99E, UNICODE_NORM_QC_NO},
+ {0x2F99F, UNICODE_NORM_QC_NO},
+ {0x2F9A0, UNICODE_NORM_QC_NO},
+ {0x2F9A1, UNICODE_NORM_QC_NO},
+ {0x2F9A2, UNICODE_NORM_QC_NO},
+ {0x2F9A3, UNICODE_NORM_QC_NO},
+ {0x2F9A4, UNICODE_NORM_QC_NO},
+ {0x2F9A5, UNICODE_NORM_QC_NO},
+ {0x2F9A6, UNICODE_NORM_QC_NO},
+ {0x2F9A7, UNICODE_NORM_QC_NO},
+ {0x2F9A8, UNICODE_NORM_QC_NO},
+ {0x2F9A9, UNICODE_NORM_QC_NO},
+ {0x2F9AA, UNICODE_NORM_QC_NO},
+ {0x2F9AB, UNICODE_NORM_QC_NO},
+ {0x2F9AC, UNICODE_NORM_QC_NO},
+ {0x2F9AD, UNICODE_NORM_QC_NO},
+ {0x2F9AE, UNICODE_NORM_QC_NO},
+ {0x2F9AF, UNICODE_NORM_QC_NO},
+ {0x2F9B0, UNICODE_NORM_QC_NO},
+ {0x2F9B1, UNICODE_NORM_QC_NO},
+ {0x2F9B2, UNICODE_NORM_QC_NO},
+ {0x2F9B3, UNICODE_NORM_QC_NO},
+ {0x2F9B4, UNICODE_NORM_QC_NO},
+ {0x2F9B5, UNICODE_NORM_QC_NO},
+ {0x2F9B6, UNICODE_NORM_QC_NO},
+ {0x2F9B7, UNICODE_NORM_QC_NO},
+ {0x2F9B8, UNICODE_NORM_QC_NO},
+ {0x2F9B9, UNICODE_NORM_QC_NO},
+ {0x2F9BA, UNICODE_NORM_QC_NO},
+ {0x2F9BB, UNICODE_NORM_QC_NO},
+ {0x2F9BC, UNICODE_NORM_QC_NO},
+ {0x2F9BD, UNICODE_NORM_QC_NO},
+ {0x2F9BE, UNICODE_NORM_QC_NO},
+ {0x2F9BF, UNICODE_NORM_QC_NO},
+ {0x2F9C0, UNICODE_NORM_QC_NO},
+ {0x2F9C1, UNICODE_NORM_QC_NO},
+ {0x2F9C2, UNICODE_NORM_QC_NO},
+ {0x2F9C3, UNICODE_NORM_QC_NO},
+ {0x2F9C4, UNICODE_NORM_QC_NO},
+ {0x2F9C5, UNICODE_NORM_QC_NO},
+ {0x2F9C6, UNICODE_NORM_QC_NO},
+ {0x2F9C7, UNICODE_NORM_QC_NO},
+ {0x2F9C8, UNICODE_NORM_QC_NO},
+ {0x2F9C9, UNICODE_NORM_QC_NO},
+ {0x2F9CA, UNICODE_NORM_QC_NO},
+ {0x2F9CB, UNICODE_NORM_QC_NO},
+ {0x2F9CC, UNICODE_NORM_QC_NO},
+ {0x2F9CD, UNICODE_NORM_QC_NO},
+ {0x2F9CE, UNICODE_NORM_QC_NO},
+ {0x2F9CF, UNICODE_NORM_QC_NO},
+ {0x2F9D0, UNICODE_NORM_QC_NO},
+ {0x2F9D1, UNICODE_NORM_QC_NO},
+ {0x2F9D2, UNICODE_NORM_QC_NO},
+ {0x2F9D3, UNICODE_NORM_QC_NO},
+ {0x2F9D4, UNICODE_NORM_QC_NO},
+ {0x2F9D5, UNICODE_NORM_QC_NO},
+ {0x2F9D6, UNICODE_NORM_QC_NO},
+ {0x2F9D7, UNICODE_NORM_QC_NO},
+ {0x2F9D8, UNICODE_NORM_QC_NO},
+ {0x2F9D9, UNICODE_NORM_QC_NO},
+ {0x2F9DA, UNICODE_NORM_QC_NO},
+ {0x2F9DB, UNICODE_NORM_QC_NO},
+ {0x2F9DC, UNICODE_NORM_QC_NO},
+ {0x2F9DD, UNICODE_NORM_QC_NO},
+ {0x2F9DE, UNICODE_NORM_QC_NO},
+ {0x2F9DF, UNICODE_NORM_QC_NO},
+ {0x2F9E0, UNICODE_NORM_QC_NO},
+ {0x2F9E1, UNICODE_NORM_QC_NO},
+ {0x2F9E2, UNICODE_NORM_QC_NO},
+ {0x2F9E3, UNICODE_NORM_QC_NO},
+ {0x2F9E4, UNICODE_NORM_QC_NO},
+ {0x2F9E5, UNICODE_NORM_QC_NO},
+ {0x2F9E6, UNICODE_NORM_QC_NO},
+ {0x2F9E7, UNICODE_NORM_QC_NO},
+ {0x2F9E8, UNICODE_NORM_QC_NO},
+ {0x2F9E9, UNICODE_NORM_QC_NO},
+ {0x2F9EA, UNICODE_NORM_QC_NO},
+ {0x2F9EB, UNICODE_NORM_QC_NO},
+ {0x2F9EC, UNICODE_NORM_QC_NO},
+ {0x2F9ED, UNICODE_NORM_QC_NO},
+ {0x2F9EE, UNICODE_NORM_QC_NO},
+ {0x2F9EF, UNICODE_NORM_QC_NO},
+ {0x2F9F0, UNICODE_NORM_QC_NO},
+ {0x2F9F1, UNICODE_NORM_QC_NO},
+ {0x2F9F2, UNICODE_NORM_QC_NO},
+ {0x2F9F3, UNICODE_NORM_QC_NO},
+ {0x2F9F4, UNICODE_NORM_QC_NO},
+ {0x2F9F5, UNICODE_NORM_QC_NO},
+ {0x2F9F6, UNICODE_NORM_QC_NO},
+ {0x2F9F7, UNICODE_NORM_QC_NO},
+ {0x2F9F8, UNICODE_NORM_QC_NO},
+ {0x2F9F9, UNICODE_NORM_QC_NO},
+ {0x2F9FA, UNICODE_NORM_QC_NO},
+ {0x2F9FB, UNICODE_NORM_QC_NO},
+ {0x2F9FC, UNICODE_NORM_QC_NO},
+ {0x2F9FD, UNICODE_NORM_QC_NO},
+ {0x2F9FE, UNICODE_NORM_QC_NO},
+ {0x2F9FF, UNICODE_NORM_QC_NO},
+ {0x2FA00, UNICODE_NORM_QC_NO},
+ {0x2FA01, UNICODE_NORM_QC_NO},
+ {0x2FA02, UNICODE_NORM_QC_NO},
+ {0x2FA03, UNICODE_NORM_QC_NO},
+ {0x2FA04, UNICODE_NORM_QC_NO},
+ {0x2FA05, UNICODE_NORM_QC_NO},
+ {0x2FA06, UNICODE_NORM_QC_NO},
+ {0x2FA07, UNICODE_NORM_QC_NO},
+ {0x2FA08, UNICODE_NORM_QC_NO},
+ {0x2FA09, UNICODE_NORM_QC_NO},
+ {0x2FA0A, UNICODE_NORM_QC_NO},
+ {0x2FA0B, UNICODE_NORM_QC_NO},
+ {0x2FA0C, UNICODE_NORM_QC_NO},
+ {0x2FA0D, UNICODE_NORM_QC_NO},
+ {0x2FA0E, UNICODE_NORM_QC_NO},
+ {0x2FA0F, UNICODE_NORM_QC_NO},
+ {0x2FA10, UNICODE_NORM_QC_NO},
+ {0x2FA11, UNICODE_NORM_QC_NO},
+ {0x2FA12, UNICODE_NORM_QC_NO},
+ {0x2FA13, UNICODE_NORM_QC_NO},
+ {0x2FA14, UNICODE_NORM_QC_NO},
+ {0x2FA15, UNICODE_NORM_QC_NO},
+ {0x2FA16, UNICODE_NORM_QC_NO},
+ {0x2FA17, UNICODE_NORM_QC_NO},
+ {0x2FA18, UNICODE_NORM_QC_NO},
+ {0x2FA19, UNICODE_NORM_QC_NO},
+ {0x2FA1A, UNICODE_NORM_QC_NO},
+ {0x2FA1B, UNICODE_NORM_QC_NO},
+ {0x2FA1C, UNICODE_NORM_QC_NO},
+ {0x2FA1D, UNICODE_NORM_QC_NO},
+};
diff --git a/src/include/common/username.h b/src/include/common/username.h
new file mode 100644
index 0000000..2a7c6c4
--- /dev/null
+++ b/src/include/common/username.h
@@ -0,0 +1,15 @@
+/*
+ * username.h
+ * lookup effective username
+ *
+ * Copyright (c) 2003-2020, PostgreSQL Global Development Group
+ *
+ * src/include/common/username.h
+ */
+#ifndef USERNAME_H
+#define USERNAME_H
+
+extern const char *get_user_name(char **errstr);
+extern const char *get_user_name_or_exit(const char *progname);
+
+#endif /* USERNAME_H */
diff --git a/src/include/datatype/timestamp.h b/src/include/datatype/timestamp.h
new file mode 100644
index 0000000..6be6d35
--- /dev/null
+++ b/src/include/datatype/timestamp.h
@@ -0,0 +1,197 @@
+/*-------------------------------------------------------------------------
+ *
+ * timestamp.h
+ * Timestamp and Interval typedefs and related macros.
+ *
+ * Note: this file must be includable in both frontend and backend contexts.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/datatype/timestamp.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DATATYPE_TIMESTAMP_H
+#define DATATYPE_TIMESTAMP_H
+
+/*
+ * Timestamp represents absolute time.
+ *
+ * Interval represents delta time. Keep track of months (and years), days,
+ * and hours/minutes/seconds separately since the elapsed time spanned is
+ * unknown until instantiated relative to an absolute time.
+ *
+ * Note that Postgres uses "time interval" to mean a bounded interval,
+ * consisting of a beginning and ending time, not a time span - thomas 97/03/20
+ *
+ * Timestamps, as well as the h/m/s fields of intervals, are stored as
+ * int64 values with units of microseconds. (Once upon a time they were
+ * double values with units of seconds.)
+ *
+ * TimeOffset and fsec_t are convenience typedefs for temporary variables.
+ * Do not use fsec_t in values stored on-disk.
+ * Also, fsec_t is only meant for *fractional* seconds; beware of overflow
+ * if the value you need to store could be many seconds.
+ */
+
+typedef int64 Timestamp;
+typedef int64 TimestampTz;
+typedef int64 TimeOffset;
+typedef int32 fsec_t; /* fractional seconds (in microseconds) */
+
+typedef struct
+{
+ TimeOffset time; /* all time units other than days, months and
+ * years */
+ int32 day; /* days, after time for alignment */
+ int32 month; /* months and years, after time for alignment */
+} Interval;
+
+
+/* Limits on the "precision" option (typmod) for these data types */
+#define MAX_TIMESTAMP_PRECISION 6
+#define MAX_INTERVAL_PRECISION 6
+
+/*
+ * Round off to MAX_TIMESTAMP_PRECISION decimal places.
+ * Note: this is also used for rounding off intervals.
+ */
+#define TS_PREC_INV 1000000.0
+#define TSROUND(j) (rint(((double) (j)) * TS_PREC_INV) / TS_PREC_INV)
+
+
+/*
+ * Assorted constants for datetime-related calculations
+ */
+
+#define DAYS_PER_YEAR 365.25 /* assumes leap year every four years */
+#define MONTHS_PER_YEAR 12
+/*
+ * DAYS_PER_MONTH is very imprecise. The more accurate value is
+ * 365.2425/12 = 30.436875, or '30 days 10:29:06'. Right now we only
+ * return an integral number of days, but someday perhaps we should
+ * also return a 'time' value to be used as well. ISO 8601 suggests
+ * 30 days.
+ */
+#define DAYS_PER_MONTH 30 /* assumes exactly 30 days per month */
+#define HOURS_PER_DAY 24 /* assume no daylight savings time changes */
+
+/*
+ * This doesn't adjust for uneven daylight savings time intervals or leap
+ * seconds, and it crudely estimates leap years. A more accurate value
+ * for days per years is 365.2422.
+ */
+#define SECS_PER_YEAR (36525 * 864) /* avoid floating-point computation */
+#define SECS_PER_DAY 86400
+#define SECS_PER_HOUR 3600
+#define SECS_PER_MINUTE 60
+#define MINS_PER_HOUR 60
+
+#define USECS_PER_DAY INT64CONST(86400000000)
+#define USECS_PER_HOUR INT64CONST(3600000000)
+#define USECS_PER_MINUTE INT64CONST(60000000)
+#define USECS_PER_SEC INT64CONST(1000000)
+
+/*
+ * We allow numeric timezone offsets up to 15:59:59 either way from Greenwich.
+ * Currently, the record holders for wackiest offsets in actual use are zones
+ * Asia/Manila, at -15:56:00 until 1844, and America/Metlakatla, at +15:13:42
+ * until 1867. If we were to reject such values we would fail to dump and
+ * restore old timestamptz values with these zone settings.
+ */
+#define MAX_TZDISP_HOUR 15 /* maximum allowed hour part */
+#define TZDISP_LIMIT ((MAX_TZDISP_HOUR + 1) * SECS_PER_HOUR)
+
+/*
+ * DT_NOBEGIN represents timestamp -infinity; DT_NOEND represents +infinity
+ */
+#define DT_NOBEGIN PG_INT64_MIN
+#define DT_NOEND PG_INT64_MAX
+
+#define TIMESTAMP_NOBEGIN(j) \
+ do {(j) = DT_NOBEGIN;} while (0)
+
+#define TIMESTAMP_IS_NOBEGIN(j) ((j) == DT_NOBEGIN)
+
+#define TIMESTAMP_NOEND(j) \
+ do {(j) = DT_NOEND;} while (0)
+
+#define TIMESTAMP_IS_NOEND(j) ((j) == DT_NOEND)
+
+#define TIMESTAMP_NOT_FINITE(j) (TIMESTAMP_IS_NOBEGIN(j) || TIMESTAMP_IS_NOEND(j))
+
+
+/*
+ * Julian date support.
+ *
+ * date2j() and j2date() nominally handle the Julian date range 0..INT_MAX,
+ * or 4714-11-24 BC to 5874898-06-03 AD. In practice, date2j() will work and
+ * give correct negative Julian dates for dates before 4714-11-24 BC as well.
+ * We rely on it to do so back to 4714-11-01 BC. Allowing at least one day's
+ * slop is necessary so that timestamp rotation doesn't produce dates that
+ * would be rejected on input. For example, '4714-11-24 00:00 GMT BC' is a
+ * legal timestamptz value, but in zones east of Greenwich it would print as
+ * sometime in the afternoon of 4714-11-23 BC; if we couldn't process such a
+ * date we'd have a dump/reload failure. So the idea is for IS_VALID_JULIAN
+ * to accept a slightly wider range of dates than we really support, and
+ * then we apply the exact checks in IS_VALID_DATE or IS_VALID_TIMESTAMP,
+ * after timezone rotation if any. To save a few cycles, we can make
+ * IS_VALID_JULIAN check only to the month boundary, since its exact cutoffs
+ * are not very critical in this scheme.
+ *
+ * It is correct that JULIAN_MINYEAR is -4713, not -4714; it is defined to
+ * allow easy comparison to tm_year values, in which we follow the convention
+ * that tm_year <= 0 represents abs(tm_year)+1 BC.
+ */
+
+#define JULIAN_MINYEAR (-4713)
+#define JULIAN_MINMONTH (11)
+#define JULIAN_MINDAY (24)
+#define JULIAN_MAXYEAR (5874898)
+#define JULIAN_MAXMONTH (6)
+#define JULIAN_MAXDAY (3)
+
+#define IS_VALID_JULIAN(y,m,d) \
+ (((y) > JULIAN_MINYEAR || \
+ ((y) == JULIAN_MINYEAR && ((m) >= JULIAN_MINMONTH))) && \
+ ((y) < JULIAN_MAXYEAR || \
+ ((y) == JULIAN_MAXYEAR && ((m) < JULIAN_MAXMONTH))))
+
+/* Julian-date equivalents of Day 0 in Unix and Postgres reckoning */
+#define UNIX_EPOCH_JDATE 2440588 /* == date2j(1970, 1, 1) */
+#define POSTGRES_EPOCH_JDATE 2451545 /* == date2j(2000, 1, 1) */
+
+/*
+ * Range limits for dates and timestamps.
+ *
+ * We have traditionally allowed Julian day zero as a valid datetime value,
+ * so that is the lower bound for both dates and timestamps.
+ *
+ * The upper limit for dates is 5874897-12-31, which is a bit less than what
+ * the Julian-date code can allow. For timestamps, the upper limit is
+ * 294276-12-31. The int64 overflow limit would be a few days later; again,
+ * leaving some slop avoids worries about corner-case overflow, and provides
+ * a simpler user-visible definition.
+ */
+
+/* First allowed date, and first disallowed date, in Julian-date form */
+#define DATETIME_MIN_JULIAN (0)
+#define DATE_END_JULIAN (2147483494) /* == date2j(JULIAN_MAXYEAR, 1, 1) */
+#define TIMESTAMP_END_JULIAN (109203528) /* == date2j(294277, 1, 1) */
+
+/* Timestamp limits */
+#define MIN_TIMESTAMP INT64CONST(-211813488000000000)
+/* == (DATETIME_MIN_JULIAN - POSTGRES_EPOCH_JDATE) * USECS_PER_DAY */
+#define END_TIMESTAMP INT64CONST(9223371331200000000)
+/* == (TIMESTAMP_END_JULIAN - POSTGRES_EPOCH_JDATE) * USECS_PER_DAY */
+
+/* Range-check a date (given in Postgres, not Julian, numbering) */
+#define IS_VALID_DATE(d) \
+ ((DATETIME_MIN_JULIAN - POSTGRES_EPOCH_JDATE) <= (d) && \
+ (d) < (DATE_END_JULIAN - POSTGRES_EPOCH_JDATE))
+
+/* Range-check a timestamp */
+#define IS_VALID_TIMESTAMP(t) (MIN_TIMESTAMP <= (t) && (t) < END_TIMESTAMP)
+
+#endif /* DATATYPE_TIMESTAMP_H */
diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h
new file mode 100644
index 0000000..afbab95
--- /dev/null
+++ b/src/include/executor/execExpr.h
@@ -0,0 +1,768 @@
+/*-------------------------------------------------------------------------
+ *
+ * execExpr.h
+ * Low level infrastructure related to expression evaluation
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/execExpr.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXEC_EXPR_H
+#define EXEC_EXPR_H
+
+#include "executor/nodeAgg.h"
+#include "nodes/execnodes.h"
+
+/* forward references to avoid circularity */
+struct ExprEvalStep;
+struct SubscriptingRefState;
+
+/* Bits in ExprState->flags (see also execnodes.h for public flag bits): */
+/* expression's interpreter has been initialized */
+#define EEO_FLAG_INTERPRETER_INITIALIZED (1 << 1)
+/* jump-threading is in use */
+#define EEO_FLAG_DIRECT_THREADED (1 << 2)
+
+/* Typical API for out-of-line evaluation subroutines */
+typedef void (*ExecEvalSubroutine) (ExprState *state,
+ struct ExprEvalStep *op,
+ ExprContext *econtext);
+
+/* ExprEvalSteps that cache a composite type's tupdesc need one of these */
+/* (it fits in-line in some step types, otherwise allocate out-of-line) */
+typedef struct ExprEvalRowtypeCache
+{
+ /*
+ * cacheptr points to composite type's TypeCacheEntry if tupdesc_id is not
+ * 0; or for an anonymous RECORD type, it points directly at the cached
+ * tupdesc for the type, and tupdesc_id is 0. (We'd use separate fields
+ * if space were not at a premium.) Initial state is cacheptr == NULL.
+ */
+ void *cacheptr;
+ uint64 tupdesc_id; /* last-seen tupdesc identifier, or 0 */
+} ExprEvalRowtypeCache;
+
+/*
+ * Discriminator for ExprEvalSteps.
+ *
+ * Identifies the operation to be executed and which member in the
+ * ExprEvalStep->d union is valid.
+ *
+ * The order of entries needs to be kept in sync with the dispatch_table[]
+ * array in execExprInterp.c:ExecInterpExpr().
+ */
+typedef enum ExprEvalOp
+{
+ /* entire expression has been evaluated completely, return */
+ EEOP_DONE,
+
+ /* apply slot_getsomeattrs on corresponding tuple slot */
+ EEOP_INNER_FETCHSOME,
+ EEOP_OUTER_FETCHSOME,
+ EEOP_SCAN_FETCHSOME,
+
+ /* compute non-system Var value */
+ EEOP_INNER_VAR,
+ EEOP_OUTER_VAR,
+ EEOP_SCAN_VAR,
+
+ /* compute system Var value */
+ EEOP_INNER_SYSVAR,
+ EEOP_OUTER_SYSVAR,
+ EEOP_SCAN_SYSVAR,
+
+ /* compute wholerow Var */
+ EEOP_WHOLEROW,
+
+ /*
+ * Compute non-system Var value, assign it into ExprState's resultslot.
+ * These are not used if a CheckVarSlotCompatibility() check would be
+ * needed.
+ */
+ EEOP_ASSIGN_INNER_VAR,
+ EEOP_ASSIGN_OUTER_VAR,
+ EEOP_ASSIGN_SCAN_VAR,
+
+ /* assign ExprState's resvalue/resnull to a column of its resultslot */
+ EEOP_ASSIGN_TMP,
+ /* ditto, applying MakeExpandedObjectReadOnly() */
+ EEOP_ASSIGN_TMP_MAKE_RO,
+
+ /* evaluate Const value */
+ EEOP_CONST,
+
+ /*
+ * Evaluate function call (including OpExprs etc). For speed, we
+ * distinguish in the opcode whether the function is strict and/or
+ * requires usage stats tracking.
+ */
+ EEOP_FUNCEXPR,
+ EEOP_FUNCEXPR_STRICT,
+ EEOP_FUNCEXPR_FUSAGE,
+ EEOP_FUNCEXPR_STRICT_FUSAGE,
+
+ /*
+ * Evaluate boolean AND expression, one step per subexpression. FIRST/LAST
+ * subexpressions are special-cased for performance. Since AND always has
+ * at least two subexpressions, FIRST and LAST never apply to the same
+ * subexpression.
+ */
+ EEOP_BOOL_AND_STEP_FIRST,
+ EEOP_BOOL_AND_STEP,
+ EEOP_BOOL_AND_STEP_LAST,
+
+ /* similarly for boolean OR expression */
+ EEOP_BOOL_OR_STEP_FIRST,
+ EEOP_BOOL_OR_STEP,
+ EEOP_BOOL_OR_STEP_LAST,
+
+ /* evaluate boolean NOT expression */
+ EEOP_BOOL_NOT_STEP,
+
+ /* simplified version of BOOL_AND_STEP for use by ExecQual() */
+ EEOP_QUAL,
+
+ /* unconditional jump to another step */
+ EEOP_JUMP,
+
+ /* conditional jumps based on current result value */
+ EEOP_JUMP_IF_NULL,
+ EEOP_JUMP_IF_NOT_NULL,
+ EEOP_JUMP_IF_NOT_TRUE,
+
+ /* perform NULL tests for scalar values */
+ EEOP_NULLTEST_ISNULL,
+ EEOP_NULLTEST_ISNOTNULL,
+
+ /* perform NULL tests for row values */
+ EEOP_NULLTEST_ROWISNULL,
+ EEOP_NULLTEST_ROWISNOTNULL,
+
+ /* evaluate a BooleanTest expression */
+ EEOP_BOOLTEST_IS_TRUE,
+ EEOP_BOOLTEST_IS_NOT_TRUE,
+ EEOP_BOOLTEST_IS_FALSE,
+ EEOP_BOOLTEST_IS_NOT_FALSE,
+
+ /* evaluate PARAM_EXEC/EXTERN parameters */
+ EEOP_PARAM_EXEC,
+ EEOP_PARAM_EXTERN,
+ EEOP_PARAM_CALLBACK,
+
+ /* return CaseTestExpr value */
+ EEOP_CASE_TESTVAL,
+
+ /* apply MakeExpandedObjectReadOnly() to target value */
+ EEOP_MAKE_READONLY,
+
+ /* evaluate assorted special-purpose expression types */
+ EEOP_IOCOERCE,
+ EEOP_DISTINCT,
+ EEOP_NOT_DISTINCT,
+ EEOP_NULLIF,
+ EEOP_SQLVALUEFUNCTION,
+ EEOP_CURRENTOFEXPR,
+ EEOP_NEXTVALUEEXPR,
+ EEOP_ARRAYEXPR,
+ EEOP_ARRAYCOERCE,
+ EEOP_ROW,
+
+ /*
+ * Compare two individual elements of each of two compared ROW()
+ * expressions. Skip to ROWCOMPARE_FINAL if elements are not equal.
+ */
+ EEOP_ROWCOMPARE_STEP,
+
+ /* evaluate boolean value based on previous ROWCOMPARE_STEP operations */
+ EEOP_ROWCOMPARE_FINAL,
+
+ /* evaluate GREATEST() or LEAST() */
+ EEOP_MINMAX,
+
+ /* evaluate FieldSelect expression */
+ EEOP_FIELDSELECT,
+
+ /*
+ * Deform tuple before evaluating new values for individual fields in a
+ * FieldStore expression.
+ */
+ EEOP_FIELDSTORE_DEFORM,
+
+ /*
+ * Form the new tuple for a FieldStore expression. Individual fields will
+ * have been evaluated into columns of the tuple deformed by the preceding
+ * DEFORM step.
+ */
+ EEOP_FIELDSTORE_FORM,
+
+ /* Process a container subscript; short-circuit expression to NULL if NULL */
+ EEOP_SBSREF_SUBSCRIPT,
+
+ /*
+ * Compute old container element/slice when a SubscriptingRef assignment
+ * expression contains SubscriptingRef/FieldStore subexpressions. Value is
+ * accessed using the CaseTest mechanism.
+ */
+ EEOP_SBSREF_OLD,
+
+ /* compute new value for SubscriptingRef assignment expression */
+ EEOP_SBSREF_ASSIGN,
+
+ /* compute element/slice for SubscriptingRef fetch expression */
+ EEOP_SBSREF_FETCH,
+
+ /* evaluate value for CoerceToDomainValue */
+ EEOP_DOMAIN_TESTVAL,
+
+ /* evaluate a domain's NOT NULL constraint */
+ EEOP_DOMAIN_NOTNULL,
+
+ /* evaluate a single domain CHECK constraint */
+ EEOP_DOMAIN_CHECK,
+
+ /* evaluate assorted special-purpose expression types */
+ EEOP_CONVERT_ROWTYPE,
+ EEOP_SCALARARRAYOP,
+ EEOP_XMLEXPR,
+ EEOP_AGGREF,
+ EEOP_GROUPING_FUNC,
+ EEOP_WINDOW_FUNC,
+ EEOP_SUBPLAN,
+ EEOP_ALTERNATIVE_SUBPLAN,
+
+ /* aggregation related nodes */
+ EEOP_AGG_STRICT_DESERIALIZE,
+ EEOP_AGG_DESERIALIZE,
+ EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
+ EEOP_AGG_STRICT_INPUT_CHECK_NULLS,
+ EEOP_AGG_PLAIN_PERGROUP_NULLCHECK,
+ EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL,
+ EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL,
+ EEOP_AGG_PLAIN_TRANS_BYVAL,
+ EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF,
+ EEOP_AGG_PLAIN_TRANS_STRICT_BYREF,
+ EEOP_AGG_PLAIN_TRANS_BYREF,
+ EEOP_AGG_ORDERED_TRANS_DATUM,
+ EEOP_AGG_ORDERED_TRANS_TUPLE,
+
+ /* non-existent operation, used e.g. to check array lengths */
+ EEOP_LAST
+} ExprEvalOp;
+
+
+typedef struct ExprEvalStep
+{
+ /*
+ * Instruction to be executed. During instruction preparation this is an
+ * enum ExprEvalOp, but later it can be changed to some other type, e.g. a
+ * pointer for computed goto (that's why it's an intptr_t).
+ */
+ intptr_t opcode;
+
+ /* where to store the result of this step */
+ Datum *resvalue;
+ bool *resnull;
+
+ /*
+ * Inline data for the operation. Inline data is faster to access, but
+ * also bloats the size of all instructions. The union should be kept to
+ * no more than 40 bytes on 64-bit systems (so that the entire struct is
+ * no more than 64 bytes, a single cacheline on common systems).
+ */
+ union
+ {
+ /* for EEOP_INNER/OUTER/SCAN_FETCHSOME */
+ struct
+ {
+ /* attribute number up to which to fetch (inclusive) */
+ int last_var;
+ /* will the type of slot be the same for every invocation */
+ bool fixed;
+ /* tuple descriptor, if known */
+ TupleDesc known_desc;
+ /* type of slot, can only be relied upon if fixed is set */
+ const TupleTableSlotOps *kind;
+ } fetch;
+
+ /* for EEOP_INNER/OUTER/SCAN_[SYS]VAR[_FIRST] */
+ struct
+ {
+ /* attnum is attr number - 1 for regular VAR ... */
+ /* but it's just the normal (negative) attr number for SYSVAR */
+ int attnum;
+ Oid vartype; /* type OID of variable */
+ } var;
+
+ /* for EEOP_WHOLEROW */
+ struct
+ {
+ Var *var; /* original Var node in plan tree */
+ bool first; /* first time through, need to initialize? */
+ bool slow; /* need runtime check for nulls? */
+ TupleDesc tupdesc; /* descriptor for resulting tuples */
+ JunkFilter *junkFilter; /* JunkFilter to remove resjunk cols */
+ } wholerow;
+
+ /* for EEOP_ASSIGN_*_VAR */
+ struct
+ {
+ /* target index in ExprState->resultslot->tts_values/nulls */
+ int resultnum;
+ /* source attribute number - 1 */
+ int attnum;
+ } assign_var;
+
+ /* for EEOP_ASSIGN_TMP[_MAKE_RO] */
+ struct
+ {
+ /* target index in ExprState->resultslot->tts_values/nulls */
+ int resultnum;
+ } assign_tmp;
+
+ /* for EEOP_CONST */
+ struct
+ {
+ /* constant's value */
+ Datum value;
+ bool isnull;
+ } constval;
+
+ /* for EEOP_FUNCEXPR_* / NULLIF / DISTINCT */
+ struct
+ {
+ FmgrInfo *finfo; /* function's lookup data */
+ FunctionCallInfo fcinfo_data; /* arguments etc */
+ /* faster to access without additional indirection: */
+ PGFunction fn_addr; /* actual call address */
+ int nargs; /* number of arguments */
+ } func;
+
+ /* for EEOP_BOOL_*_STEP */
+ struct
+ {
+ bool *anynull; /* track if any input was NULL */
+ int jumpdone; /* jump here if result determined */
+ } boolexpr;
+
+ /* for EEOP_QUAL */
+ struct
+ {
+ int jumpdone; /* jump here on false or null */
+ } qualexpr;
+
+ /* for EEOP_JUMP[_CONDITION] */
+ struct
+ {
+ int jumpdone; /* target instruction's index */
+ } jump;
+
+ /* for EEOP_NULLTEST_ROWIS[NOT]NULL */
+ struct
+ {
+ /* cached descriptor for composite type - filled at runtime */
+ ExprEvalRowtypeCache rowcache;
+ } nulltest_row;
+
+ /* for EEOP_PARAM_EXEC/EXTERN */
+ struct
+ {
+ int paramid; /* numeric ID for parameter */
+ Oid paramtype; /* OID of parameter's datatype */
+ } param;
+
+ /* for EEOP_PARAM_CALLBACK */
+ struct
+ {
+ ExecEvalSubroutine paramfunc; /* add-on evaluation subroutine */
+ void *paramarg; /* private data for same */
+ int paramid; /* numeric ID for parameter */
+ Oid paramtype; /* OID of parameter's datatype */
+ } cparam;
+
+ /* for EEOP_CASE_TESTVAL/DOMAIN_TESTVAL */
+ struct
+ {
+ Datum *value; /* value to return */
+ bool *isnull;
+ } casetest;
+
+ /* for EEOP_MAKE_READONLY */
+ struct
+ {
+ Datum *value; /* value to coerce to read-only */
+ bool *isnull;
+ } make_readonly;
+
+ /* for EEOP_IOCOERCE */
+ struct
+ {
+ /* lookup and call info for source type's output function */
+ FmgrInfo *finfo_out;
+ FunctionCallInfo fcinfo_data_out;
+ /* lookup and call info for result type's input function */
+ FmgrInfo *finfo_in;
+ FunctionCallInfo fcinfo_data_in;
+ } iocoerce;
+
+ /* for EEOP_SQLVALUEFUNCTION */
+ struct
+ {
+ SQLValueFunction *svf;
+ } sqlvaluefunction;
+
+ /* for EEOP_NEXTVALUEEXPR */
+ struct
+ {
+ Oid seqid;
+ Oid seqtypid;
+ } nextvalueexpr;
+
+ /* for EEOP_ARRAYEXPR */
+ struct
+ {
+ Datum *elemvalues; /* element values get stored here */
+ bool *elemnulls;
+ int nelems; /* length of the above arrays */
+ Oid elemtype; /* array element type */
+ int16 elemlength; /* typlen of the array element type */
+ bool elembyval; /* is the element type pass-by-value? */
+ char elemalign; /* typalign of the element type */
+ bool multidims; /* is array expression multi-D? */
+ } arrayexpr;
+
+ /* for EEOP_ARRAYCOERCE */
+ struct
+ {
+ ExprState *elemexprstate; /* null if no per-element work */
+ Oid resultelemtype; /* element type of result array */
+ struct ArrayMapState *amstate; /* workspace for array_map */
+ } arraycoerce;
+
+ /* for EEOP_ROW */
+ struct
+ {
+ TupleDesc tupdesc; /* descriptor for result tuples */
+ /* workspace for the values constituting the row: */
+ Datum *elemvalues;
+ bool *elemnulls;
+ } row;
+
+ /* for EEOP_ROWCOMPARE_STEP */
+ struct
+ {
+ /* lookup and call data for column comparison function */
+ FmgrInfo *finfo;
+ FunctionCallInfo fcinfo_data;
+ PGFunction fn_addr;
+ /* target for comparison resulting in NULL */
+ int jumpnull;
+ /* target for comparison yielding inequality */
+ int jumpdone;
+ } rowcompare_step;
+
+ /* for EEOP_ROWCOMPARE_FINAL */
+ struct
+ {
+ RowCompareType rctype;
+ } rowcompare_final;
+
+ /* for EEOP_MINMAX */
+ struct
+ {
+ /* workspace for argument values */
+ Datum *values;
+ bool *nulls;
+ int nelems;
+ /* is it GREATEST or LEAST? */
+ MinMaxOp op;
+ /* lookup and call data for comparison function */
+ FmgrInfo *finfo;
+ FunctionCallInfo fcinfo_data;
+ } minmax;
+
+ /* for EEOP_FIELDSELECT */
+ struct
+ {
+ AttrNumber fieldnum; /* field number to extract */
+ Oid resulttype; /* field's type */
+ /* cached descriptor for composite type - filled at runtime */
+ ExprEvalRowtypeCache rowcache;
+ } fieldselect;
+
+ /* for EEOP_FIELDSTORE_DEFORM / FIELDSTORE_FORM */
+ struct
+ {
+ /* original expression node */
+ FieldStore *fstore;
+
+ /* cached descriptor for composite type - filled at runtime */
+ /* note that a DEFORM and FORM pair share the same cache */
+ ExprEvalRowtypeCache *rowcache;
+
+ /* workspace for column values */
+ Datum *values;
+ bool *nulls;
+ int ncolumns;
+ } fieldstore;
+
+ /* for EEOP_SBSREF_SUBSCRIPT */
+ struct
+ {
+ /* too big to have inline */
+ struct SubscriptingRefState *state;
+ int off; /* 0-based index of this subscript */
+ bool isupper; /* is it upper or lower subscript? */
+ int jumpdone; /* jump here on null */
+ } sbsref_subscript;
+
+ /* for EEOP_SBSREF_OLD / ASSIGN / FETCH */
+ struct
+ {
+ /* too big to have inline */
+ struct SubscriptingRefState *state;
+ } sbsref;
+
+ /* for EEOP_DOMAIN_NOTNULL / DOMAIN_CHECK */
+ struct
+ {
+ /* name of constraint */
+ char *constraintname;
+ /* where the result of a CHECK constraint will be stored */
+ Datum *checkvalue;
+ bool *checknull;
+ /* OID of domain type */
+ Oid resulttype;
+ } domaincheck;
+
+ /* for EEOP_CONVERT_ROWTYPE */
+ struct
+ {
+ Oid inputtype; /* input composite type */
+ Oid outputtype; /* output composite type */
+ /* these three fields are filled at runtime: */
+ ExprEvalRowtypeCache *incache; /* cache for input type */
+ ExprEvalRowtypeCache *outcache; /* cache for output type */
+ TupleConversionMap *map; /* column mapping */
+ } convert_rowtype;
+
+ /* for EEOP_SCALARARRAYOP */
+ struct
+ {
+ /* element_type/typlen/typbyval/typalign are filled at runtime */
+ Oid element_type; /* InvalidOid if not yet filled */
+ bool useOr; /* use OR or AND semantics? */
+ int16 typlen; /* array element type storage info */
+ bool typbyval;
+ char typalign;
+ FmgrInfo *finfo; /* function's lookup data */
+ FunctionCallInfo fcinfo_data; /* arguments etc */
+ /* faster to access without additional indirection: */
+ PGFunction fn_addr; /* actual call address */
+ } scalararrayop;
+
+ /* for EEOP_XMLEXPR */
+ struct
+ {
+ XmlExpr *xexpr; /* original expression node */
+ /* workspace for evaluating named args, if any */
+ Datum *named_argvalue;
+ bool *named_argnull;
+ /* workspace for evaluating unnamed args, if any */
+ Datum *argvalue;
+ bool *argnull;
+ } xmlexpr;
+
+ /* for EEOP_AGGREF */
+ struct
+ {
+ /* out-of-line state, modified by nodeAgg.c */
+ AggrefExprState *astate;
+ } aggref;
+
+ /* for EEOP_GROUPING_FUNC */
+ struct
+ {
+ List *clauses; /* integer list of column numbers */
+ } grouping_func;
+
+ /* for EEOP_WINDOW_FUNC */
+ struct
+ {
+ /* out-of-line state, modified by nodeWindowAgg.c */
+ WindowFuncExprState *wfstate;
+ } window_func;
+
+ /* for EEOP_SUBPLAN */
+ struct
+ {
+ /* out-of-line state, created by nodeSubplan.c */
+ SubPlanState *sstate;
+ } subplan;
+
+ /* for EEOP_ALTERNATIVE_SUBPLAN */
+ struct
+ {
+ /* out-of-line state, created by nodeSubplan.c */
+ AlternativeSubPlanState *asstate;
+ } alternative_subplan;
+
+ /* for EEOP_AGG_*DESERIALIZE */
+ struct
+ {
+ FunctionCallInfo fcinfo_data;
+ int jumpnull;
+ } agg_deserialize;
+
+ /* for EEOP_AGG_STRICT_INPUT_CHECK_NULLS / STRICT_INPUT_CHECK_ARGS */
+ struct
+ {
+ /*
+ * For EEOP_AGG_STRICT_INPUT_CHECK_ARGS args contains pointers to
+ * the NullableDatums that need to be checked for NULLs.
+ *
+ * For EEOP_AGG_STRICT_INPUT_CHECK_NULLS nulls contains pointers
+ * to booleans that need to be checked for NULLs.
+ *
+ * Both cases currently need to exist because sometimes the
+ * to-be-checked nulls are in TupleTableSlot.isnull array, and
+ * sometimes in FunctionCallInfoBaseData.args[i].isnull.
+ */
+ NullableDatum *args;
+ bool *nulls;
+ int nargs;
+ int jumpnull;
+ } agg_strict_input_check;
+
+ /* for EEOP_AGG_PLAIN_PERGROUP_NULLCHECK */
+ struct
+ {
+ int setoff;
+ int jumpnull;
+ } agg_plain_pergroup_nullcheck;
+
+ /* for EEOP_AGG_PLAIN_TRANS_[INIT_][STRICT_]{BYVAL,BYREF} */
+ /* for EEOP_AGG_ORDERED_TRANS_{DATUM,TUPLE} */
+ struct
+ {
+ AggStatePerTrans pertrans;
+ ExprContext *aggcontext;
+ int setno;
+ int transno;
+ int setoff;
+ } agg_trans;
+ } d;
+} ExprEvalStep;
+
+
+/* Non-inline data for container operations */
+typedef struct SubscriptingRefState
+{
+ bool isassignment; /* is it assignment, or just fetch? */
+
+ Oid refelemtype; /* OID of the container element type */
+ int16 refattrlength; /* typlen of container type */
+ int16 refelemlength; /* typlen of the container element type */
+ bool refelembyval; /* is the element type pass-by-value? */
+ char refelemalign; /* typalign of the element type */
+
+ /* numupper and upperprovided[] are filled at compile time */
+ /* at runtime, extracted subscript datums get stored in upperindex[] */
+ int numupper;
+ bool upperprovided[MAXDIM];
+ int upperindex[MAXDIM];
+
+ /* similarly for lower indexes, if any */
+ int numlower;
+ bool lowerprovided[MAXDIM];
+ int lowerindex[MAXDIM];
+
+ /* subscript expressions get evaluated into here */
+ Datum subscriptvalue;
+ bool subscriptnull;
+
+ /* for assignment, new value to assign is evaluated into here */
+ Datum replacevalue;
+ bool replacenull;
+
+ /* if we have a nested assignment, SBSREF_OLD puts old value here */
+ Datum prevvalue;
+ bool prevnull;
+} SubscriptingRefState;
+
+
+/* functions in execExpr.c */
+extern void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s);
+
+/* functions in execExprInterp.c */
+extern void ExecReadyInterpretedExpr(ExprState *state);
+extern ExprEvalOp ExecEvalStepOp(ExprState *state, ExprEvalStep *op);
+
+extern Datum ExecInterpExprStillValid(ExprState *state, ExprContext *econtext, bool *isNull);
+extern void CheckExprStillValid(ExprState *state, ExprContext *econtext);
+
+/*
+ * Non fast-path execution functions. These are externs instead of statics in
+ * execExprInterp.c, because that allows them to be used by other methods of
+ * expression evaluation, reducing code duplication.
+ */
+extern void ExecEvalFuncExprFusage(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalFuncExprStrictFusage(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalParamExec(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalParamExtern(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalCurrentOfExpr(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalNextValueExpr(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalRowNull(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalRowNotNull(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalArrayExpr(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalArrayCoerce(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalRow(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalMinMax(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalFieldSelect(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalFieldStoreDeForm(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern bool ExecEvalSubscriptingRef(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalSubscriptingRefFetch(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalSubscriptingRefOld(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalSubscriptingRefAssign(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalConvertRowtype(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalConstraintNotNull(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalConstraintCheck(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalGroupingFunc(ExprState *state, ExprEvalStep *op);
+extern void ExecEvalSubPlan(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalAlternativeSubPlan(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalSysVar(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext, TupleTableSlot *slot);
+
+extern void ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup,
+ ExprContext *aggcontext);
+extern Datum ExecAggTransReparent(AggState *aggstate, AggStatePerTrans pertrans,
+ Datum newValue, bool newValueIsNull,
+ Datum oldValue, bool oldValueIsNull);
+extern void ExecEvalAggOrderedTransDatum(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+extern void ExecEvalAggOrderedTransTuple(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext);
+
+#endif /* EXEC_EXPR_H */
diff --git a/src/include/executor/execParallel.h b/src/include/executor/execParallel.h
new file mode 100644
index 0000000..5a39a5b
--- /dev/null
+++ b/src/include/executor/execParallel.h
@@ -0,0 +1,51 @@
+/*--------------------------------------------------------------------
+ * execParallel.h
+ * POSTGRES parallel execution interface
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/executor/execParallel.h
+ *--------------------------------------------------------------------
+ */
+
+#ifndef EXECPARALLEL_H
+#define EXECPARALLEL_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+#include "nodes/parsenodes.h"
+#include "nodes/plannodes.h"
+#include "utils/dsa.h"
+
+typedef struct SharedExecutorInstrumentation SharedExecutorInstrumentation;
+
+typedef struct ParallelExecutorInfo
+{
+ PlanState *planstate; /* plan subtree we're running in parallel */
+ ParallelContext *pcxt; /* parallel context we're using */
+ BufferUsage *buffer_usage; /* points to bufusage area in DSM */
+ WalUsage *wal_usage; /* walusage area in DSM */
+ SharedExecutorInstrumentation *instrumentation; /* optional */
+ struct SharedJitInstrumentation *jit_instrumentation; /* optional */
+ dsa_area *area; /* points to DSA area in DSM */
+ dsa_pointer param_exec; /* serialized PARAM_EXEC parameters */
+ bool finished; /* set true by ExecParallelFinish */
+ /* These two arrays have pcxt->nworkers_launched entries: */
+ shm_mq_handle **tqueue; /* tuple queues for worker output */
+ struct TupleQueueReader **reader; /* tuple reader/writer support */
+} ParallelExecutorInfo;
+
+extern ParallelExecutorInfo *ExecInitParallelPlan(PlanState *planstate,
+ EState *estate, Bitmapset *sendParam, int nworkers,
+ int64 tuples_needed);
+extern void ExecParallelCreateReaders(ParallelExecutorInfo *pei);
+extern void ExecParallelFinish(ParallelExecutorInfo *pei);
+extern void ExecParallelCleanup(ParallelExecutorInfo *pei);
+extern void ExecParallelReinitialize(PlanState *planstate,
+ ParallelExecutorInfo *pei, Bitmapset *sendParam);
+
+extern void ParallelQueryMain(dsm_segment *seg, shm_toc *toc);
+
+#endif /* EXECPARALLEL_H */
diff --git a/src/include/executor/execPartition.h b/src/include/executor/execPartition.h
new file mode 100644
index 0000000..6d1b722
--- /dev/null
+++ b/src/include/executor/execPartition.h
@@ -0,0 +1,156 @@
+/*--------------------------------------------------------------------
+ * execPartition.h
+ * POSTGRES partitioning executor interface
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/executor/execPartition.h
+ *--------------------------------------------------------------------
+ */
+
+#ifndef EXECPARTITION_H
+#define EXECPARTITION_H
+
+#include "nodes/execnodes.h"
+#include "nodes/parsenodes.h"
+#include "nodes/plannodes.h"
+#include "partitioning/partprune.h"
+
+/* See execPartition.c for the definitions. */
+typedef struct PartitionDispatchData *PartitionDispatch;
+typedef struct PartitionTupleRouting PartitionTupleRouting;
+
+/*
+ * PartitionRoutingInfo
+ *
+ * Additional result relation information specific to routing tuples to a
+ * table partition.
+ */
+typedef struct PartitionRoutingInfo
+{
+ /*
+ * Map for converting tuples in root partitioned table format into
+ * partition format, or NULL if no conversion is required.
+ */
+ TupleConversionMap *pi_RootToPartitionMap;
+
+ /*
+ * Map for converting tuples in partition format into the root partitioned
+ * table format, or NULL if no conversion is required.
+ */
+ TupleConversionMap *pi_PartitionToRootMap;
+
+ /*
+ * Slot to store tuples in partition format, or NULL when no translation
+ * is required between root and partition.
+ */
+ TupleTableSlot *pi_PartitionTupleSlot;
+} PartitionRoutingInfo;
+
+/*
+ * PartitionedRelPruningData - Per-partitioned-table data for run-time pruning
+ * of partitions. For a multilevel partitioned table, we have one of these
+ * for the topmost partition plus one for each non-leaf child partition.
+ *
+ * subplan_map[] and subpart_map[] have the same definitions as in
+ * PartitionedRelPruneInfo (see plannodes.h); though note that here,
+ * subpart_map contains indexes into PartitionPruningData.partrelprunedata[].
+ *
+ * nparts Length of subplan_map[] and subpart_map[].
+ * subplan_map Subplan index by partition index, or -1.
+ * subpart_map Subpart index by partition index, or -1.
+ * present_parts A Bitmapset of the partition indexes that we
+ * have subplans or subparts for.
+ * initial_pruning_steps List of PartitionPruneSteps used to
+ * perform executor startup pruning.
+ * exec_pruning_steps List of PartitionPruneSteps used to
+ * perform per-scan pruning.
+ * initial_context If initial_pruning_steps isn't NIL, contains
+ * the details needed to execute those steps.
+ * exec_context If exec_pruning_steps isn't NIL, contains
+ * the details needed to execute those steps.
+ */
+typedef struct PartitionedRelPruningData
+{
+ int nparts;
+ int *subplan_map;
+ int *subpart_map;
+ Bitmapset *present_parts;
+ List *initial_pruning_steps;
+ List *exec_pruning_steps;
+ PartitionPruneContext initial_context;
+ PartitionPruneContext exec_context;
+} PartitionedRelPruningData;
+
+/*
+ * PartitionPruningData - Holds all the run-time pruning information for
+ * a single partitioning hierarchy containing one or more partitions.
+ * partrelprunedata[] is an array ordered such that parents appear before
+ * their children; in particular, the first entry is the topmost partition,
+ * which was actually named in the SQL query.
+ */
+typedef struct PartitionPruningData
+{
+ int num_partrelprunedata; /* number of array entries */
+ PartitionedRelPruningData partrelprunedata[FLEXIBLE_ARRAY_MEMBER];
+} PartitionPruningData;
+
+/*
+ * PartitionPruneState - State object required for plan nodes to perform
+ * run-time partition pruning.
+ *
+ * This struct can be attached to plan types which support arbitrary Lists of
+ * subplans containing partitions, to allow subplans to be eliminated due to
+ * the clauses being unable to match to any tuple that the subplan could
+ * possibly produce.
+ *
+ * execparamids Contains paramids of PARAM_EXEC Params found within
+ * any of the partprunedata structs. Pruning must be
+ * done again each time the value of one of these
+ * parameters changes.
+ * other_subplans Contains indexes of subplans that don't belong to any
+ * "partprunedata", e.g UNION ALL children that are not
+ * partitioned tables, or a partitioned table that the
+ * planner deemed run-time pruning to be useless for.
+ * These must not be pruned.
+ * prune_context A short-lived memory context in which to execute the
+ * partition pruning functions.
+ * do_initial_prune true if pruning should be performed during executor
+ * startup (at any hierarchy level).
+ * do_exec_prune true if pruning should be performed during
+ * executor run (at any hierarchy level).
+ * num_partprunedata Number of items in "partprunedata" array.
+ * partprunedata Array of PartitionPruningData pointers for the plan's
+ * partitioned relation(s), one for each partitioning
+ * hierarchy that requires run-time pruning.
+ */
+typedef struct PartitionPruneState
+{
+ Bitmapset *execparamids;
+ Bitmapset *other_subplans;
+ MemoryContext prune_context;
+ bool do_initial_prune;
+ bool do_exec_prune;
+ int num_partprunedata;
+ PartitionPruningData *partprunedata[FLEXIBLE_ARRAY_MEMBER];
+} PartitionPruneState;
+
+extern PartitionTupleRouting *ExecSetupPartitionTupleRouting(EState *estate,
+ ModifyTableState *mtstate,
+ Relation rel);
+extern ResultRelInfo *ExecFindPartition(ModifyTableState *mtstate,
+ ResultRelInfo *rootResultRelInfo,
+ PartitionTupleRouting *proute,
+ TupleTableSlot *slot,
+ EState *estate);
+extern void ExecCleanupTupleRouting(ModifyTableState *mtstate,
+ PartitionTupleRouting *proute);
+extern PartitionPruneState *ExecCreatePartitionPruneState(PlanState *planstate,
+ PartitionPruneInfo *partitionpruneinfo);
+extern Bitmapset *ExecFindMatchingSubPlans(PartitionPruneState *prunestate);
+extern Bitmapset *ExecFindInitialMatchingSubPlans(PartitionPruneState *prunestate,
+ int nsubplans);
+
+#endif /* EXECPARTITION_H */
diff --git a/src/include/executor/execdebug.h b/src/include/executor/execdebug.h
new file mode 100644
index 0000000..4af6e00
--- /dev/null
+++ b/src/include/executor/execdebug.h
@@ -0,0 +1,130 @@
+/*-------------------------------------------------------------------------
+ *
+ * execdebug.h
+ * #defines governing debugging behaviour in the executor
+ *
+ * XXX this is all pretty old and crufty. Newer code tends to use elog()
+ * for debug printouts, because that's more flexible than printf().
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/execdebug.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXECDEBUG_H
+#define EXECDEBUG_H
+
+#include "executor/executor.h"
+#include "nodes/print.h"
+
+/* ----------------------------------------------------------------
+ * debugging defines.
+ *
+ * If you want certain debugging behaviour, then #define
+ * the variable to 1. No need to explicitly #undef by default,
+ * since we can use -D compiler options to enable features.
+ * - thomas 1999-02-20
+ * ----------------------------------------------------------------
+ */
+
+/* ----------------
+ * EXEC_NESTLOOPDEBUG is a flag which turns on debugging of the
+ * nest loop node by NL_printf() and ENL_printf() in nodeNestloop.c
+ * ----------------
+#undef EXEC_NESTLOOPDEBUG
+ */
+
+/* ----------------
+ * EXEC_SORTDEBUG is a flag which turns on debugging of
+ * the ExecSort() stuff by SO_printf() in nodeSort.c
+ * ----------------
+#undef EXEC_SORTDEBUG
+ */
+
+/* ----------------
+ * EXEC_MERGEJOINDEBUG is a flag which turns on debugging of
+ * the ExecMergeJoin() stuff by MJ_printf() in nodeMergejoin.c
+ * ----------------
+#undef EXEC_MERGEJOINDEBUG
+ */
+
+/* ----------------------------------------------------------------
+ * #defines controlled by above definitions
+ *
+ * Note: most of these are "incomplete" because I didn't
+ * need the ones not defined. More should be added
+ * only as necessary -cim 10/26/89
+ * ----------------------------------------------------------------
+ */
+#define T_OR_F(b) ((b) ? "true" : "false")
+#define NULL_OR_TUPLE(slot) (TupIsNull(slot) ? "null" : "a tuple")
+
+/* ----------------
+ * nest loop debugging defines
+ * ----------------
+ */
+#ifdef EXEC_NESTLOOPDEBUG
+#define NL_nodeDisplay(l) nodeDisplay(l)
+#define NL_printf(s) printf(s)
+#define NL1_printf(s, a) printf(s, a)
+#define ENL1_printf(message) printf("ExecNestLoop: %s\n", message)
+#else
+#define NL_nodeDisplay(l)
+#define NL_printf(s)
+#define NL1_printf(s, a)
+#define ENL1_printf(message)
+#endif /* EXEC_NESTLOOPDEBUG */
+
+/* ----------------
+ * sort node debugging defines
+ * ----------------
+ */
+#ifdef EXEC_SORTDEBUG
+#define SO_nodeDisplay(l) nodeDisplay(l)
+#define SO_printf(s) printf(s)
+#define SO1_printf(s, p) printf(s, p)
+#define SO2_printf(s, p1, p2) printf(s, p1, p2)
+#else
+#define SO_nodeDisplay(l)
+#define SO_printf(s)
+#define SO1_printf(s, p)
+#define SO2_printf(s, p1, p2)
+#endif /* EXEC_SORTDEBUG */
+
+/* ----------------
+ * merge join debugging defines
+ * ----------------
+ */
+#ifdef EXEC_MERGEJOINDEBUG
+
+#define MJ_nodeDisplay(l) nodeDisplay(l)
+#define MJ_printf(s) printf(s)
+#define MJ1_printf(s, p) printf(s, p)
+#define MJ2_printf(s, p1, p2) printf(s, p1, p2)
+#define MJ_debugtup(slot) debugtup(slot, NULL)
+#define MJ_dump(state) ExecMergeTupleDump(state)
+#define MJ_DEBUG_COMPARE(res) \
+ MJ1_printf(" MJCompare() returns %d\n", (res))
+#define MJ_DEBUG_QUAL(clause, res) \
+ MJ2_printf(" ExecQual(%s, econtext) returns %s\n", \
+ CppAsString(clause), T_OR_F(res))
+#define MJ_DEBUG_PROC_NODE(slot) \
+ MJ2_printf(" %s = ExecProcNode(...) returns %s\n", \
+ CppAsString(slot), NULL_OR_TUPLE(slot))
+#else
+
+#define MJ_nodeDisplay(l)
+#define MJ_printf(s)
+#define MJ1_printf(s, p)
+#define MJ2_printf(s, p1, p2)
+#define MJ_debugtup(slot)
+#define MJ_dump(state)
+#define MJ_DEBUG_COMPARE(res)
+#define MJ_DEBUG_QUAL(clause, res)
+#define MJ_DEBUG_PROC_NODE(slot)
+#endif /* EXEC_MERGEJOINDEBUG */
+
+#endif /* EXECDEBUG_H */
diff --git a/src/include/executor/execdesc.h b/src/include/executor/execdesc.h
new file mode 100644
index 0000000..b5cead3
--- /dev/null
+++ b/src/include/executor/execdesc.h
@@ -0,0 +1,70 @@
+/*-------------------------------------------------------------------------
+ *
+ * execdesc.h
+ * plan and query descriptor accessor macros used by the executor
+ * and related modules.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/execdesc.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXECDESC_H
+#define EXECDESC_H
+
+#include "nodes/execnodes.h"
+#include "tcop/dest.h"
+
+
+/* ----------------
+ * query descriptor:
+ *
+ * a QueryDesc encapsulates everything that the executor
+ * needs to execute the query.
+ *
+ * For the convenience of SQL-language functions, we also support QueryDescs
+ * containing utility statements; these must not be passed to the executor
+ * however.
+ * ---------------------
+ */
+typedef struct QueryDesc
+{
+ /* These fields are provided by CreateQueryDesc */
+ CmdType operation; /* CMD_SELECT, CMD_UPDATE, etc. */
+ PlannedStmt *plannedstmt; /* planner's output (could be utility, too) */
+ const char *sourceText; /* source text of the query */
+ Snapshot snapshot; /* snapshot to use for query */
+ Snapshot crosscheck_snapshot; /* crosscheck for RI update/delete */
+ DestReceiver *dest; /* the destination for tuple output */
+ ParamListInfo params; /* param values being passed in */
+ QueryEnvironment *queryEnv; /* query environment passed in */
+ int instrument_options; /* OR of InstrumentOption flags */
+
+ /* These fields are set by ExecutorStart */
+ TupleDesc tupDesc; /* descriptor for result tuples */
+ EState *estate; /* executor's query-wide state */
+ PlanState *planstate; /* tree of per-plan-node state */
+
+ /* This field is set by ExecutorRun */
+ bool already_executed; /* true if previously executed */
+
+ /* This is always set NULL by the core system, but plugins can change it */
+ struct Instrumentation *totaltime; /* total time spent in ExecutorRun */
+} QueryDesc;
+
+/* in pquery.c */
+extern QueryDesc *CreateQueryDesc(PlannedStmt *plannedstmt,
+ const char *sourceText,
+ Snapshot snapshot,
+ Snapshot crosscheck_snapshot,
+ DestReceiver *dest,
+ ParamListInfo params,
+ QueryEnvironment *queryEnv,
+ int instrument_options);
+
+extern void FreeQueryDesc(QueryDesc *qdesc);
+
+#endif /* EXECDESC_H */
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
new file mode 100644
index 0000000..18f834f
--- /dev/null
+++ b/src/include/executor/executor.h
@@ -0,0 +1,620 @@
+/*-------------------------------------------------------------------------
+ *
+ * executor.h
+ * support for the POSTGRES executor module
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/executor.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXECUTOR_H
+#define EXECUTOR_H
+
+#include "executor/execdesc.h"
+#include "fmgr.h"
+#include "nodes/lockoptions.h"
+#include "nodes/parsenodes.h"
+#include "utils/memutils.h"
+
+
+/*
+ * The "eflags" argument to ExecutorStart and the various ExecInitNode
+ * routines is a bitwise OR of the following flag bits, which tell the
+ * called plan node what to expect. Note that the flags will get modified
+ * as they are passed down the plan tree, since an upper node may require
+ * functionality in its subnode not demanded of the plan as a whole
+ * (example: MergeJoin requires mark/restore capability in its inner input),
+ * or an upper node may shield its input from some functionality requirement
+ * (example: Materialize shields its input from needing to do backward scan).
+ *
+ * EXPLAIN_ONLY indicates that the plan tree is being initialized just so
+ * EXPLAIN can print it out; it will not be run. Hence, no side-effects
+ * of startup should occur. However, error checks (such as permission checks)
+ * should be performed.
+ *
+ * REWIND indicates that the plan node should try to efficiently support
+ * rescans without parameter changes. (Nodes must support ExecReScan calls
+ * in any case, but if this flag was not given, they are at liberty to do it
+ * through complete recalculation. Note that a parameter change forces a
+ * full recalculation in any case.)
+ *
+ * BACKWARD indicates that the plan node must respect the es_direction flag.
+ * When this is not passed, the plan node will only be run forwards.
+ *
+ * MARK indicates that the plan node must support Mark/Restore calls.
+ * When this is not passed, no Mark/Restore will occur.
+ *
+ * SKIP_TRIGGERS tells ExecutorStart/ExecutorFinish to skip calling
+ * AfterTriggerBeginQuery/AfterTriggerEndQuery. This does not necessarily
+ * mean that the plan can't queue any AFTER triggers; just that the caller
+ * is responsible for there being a trigger context for them to be queued in.
+ */
+#define EXEC_FLAG_EXPLAIN_ONLY 0x0001 /* EXPLAIN, no ANALYZE */
+#define EXEC_FLAG_REWIND 0x0002 /* need efficient rescan */
+#define EXEC_FLAG_BACKWARD 0x0004 /* need backward scan */
+#define EXEC_FLAG_MARK 0x0008 /* need mark/restore */
+#define EXEC_FLAG_SKIP_TRIGGERS 0x0010 /* skip AfterTrigger calls */
+#define EXEC_FLAG_WITH_NO_DATA 0x0020 /* rel scannability doesn't matter */
+
+
+/* Hook for plugins to get control in ExecutorStart() */
+typedef void (*ExecutorStart_hook_type) (QueryDesc *queryDesc, int eflags);
+extern PGDLLIMPORT ExecutorStart_hook_type ExecutorStart_hook;
+
+/* Hook for plugins to get control in ExecutorRun() */
+typedef void (*ExecutorRun_hook_type) (QueryDesc *queryDesc,
+ ScanDirection direction,
+ uint64 count,
+ bool execute_once);
+extern PGDLLIMPORT ExecutorRun_hook_type ExecutorRun_hook;
+
+/* Hook for plugins to get control in ExecutorFinish() */
+typedef void (*ExecutorFinish_hook_type) (QueryDesc *queryDesc);
+extern PGDLLIMPORT ExecutorFinish_hook_type ExecutorFinish_hook;
+
+/* Hook for plugins to get control in ExecutorEnd() */
+typedef void (*ExecutorEnd_hook_type) (QueryDesc *queryDesc);
+extern PGDLLIMPORT ExecutorEnd_hook_type ExecutorEnd_hook;
+
+/* Hook for plugins to get control in ExecCheckRTPerms() */
+typedef bool (*ExecutorCheckPerms_hook_type) (List *, bool);
+extern PGDLLIMPORT ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook;
+
+
+/*
+ * prototypes from functions in execAmi.c
+ */
+struct Path; /* avoid including pathnodes.h here */
+
+extern void ExecReScan(PlanState *node);
+extern void ExecMarkPos(PlanState *node);
+extern void ExecRestrPos(PlanState *node);
+extern bool ExecSupportsMarkRestore(struct Path *pathnode);
+extern bool ExecSupportsBackwardScan(Plan *node);
+extern bool ExecMaterializesOutput(NodeTag plantype);
+
+/*
+ * prototypes from functions in execCurrent.c
+ */
+extern bool execCurrentOf(CurrentOfExpr *cexpr,
+ ExprContext *econtext,
+ Oid table_oid,
+ ItemPointer current_tid);
+
+/*
+ * prototypes from functions in execGrouping.c
+ */
+extern ExprState *execTuplesMatchPrepare(TupleDesc desc,
+ int numCols,
+ const AttrNumber *keyColIdx,
+ const Oid *eqOperators,
+ const Oid *collations,
+ PlanState *parent);
+extern void execTuplesHashPrepare(int numCols,
+ const Oid *eqOperators,
+ Oid **eqFuncOids,
+ FmgrInfo **hashFunctions);
+extern TupleHashTable BuildTupleHashTable(PlanState *parent,
+ TupleDesc inputDesc,
+ int numCols, AttrNumber *keyColIdx,
+ const Oid *eqfuncoids,
+ FmgrInfo *hashfunctions,
+ Oid *collations,
+ long nbuckets, Size additionalsize,
+ MemoryContext tablecxt,
+ MemoryContext tempcxt, bool use_variable_hash_iv);
+extern TupleHashTable BuildTupleHashTableExt(PlanState *parent,
+ TupleDesc inputDesc,
+ int numCols, AttrNumber *keyColIdx,
+ const Oid *eqfuncoids,
+ FmgrInfo *hashfunctions,
+ Oid *collations,
+ long nbuckets, Size additionalsize,
+ MemoryContext metacxt,
+ MemoryContext tablecxt,
+ MemoryContext tempcxt, bool use_variable_hash_iv);
+extern TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable,
+ TupleTableSlot *slot,
+ bool *isnew, uint32 *hash);
+extern uint32 TupleHashTableHash(TupleHashTable hashtable,
+ TupleTableSlot *slot);
+extern TupleHashEntry LookupTupleHashEntryHash(TupleHashTable hashtable,
+ TupleTableSlot *slot,
+ bool *isnew, uint32 hash);
+extern TupleHashEntry FindTupleHashEntry(TupleHashTable hashtable,
+ TupleTableSlot *slot,
+ ExprState *eqcomp,
+ FmgrInfo *hashfunctions);
+extern void ResetTupleHashTable(TupleHashTable hashtable);
+
+/*
+ * prototypes from functions in execJunk.c
+ */
+extern JunkFilter *ExecInitJunkFilter(List *targetList,
+ TupleTableSlot *slot);
+extern JunkFilter *ExecInitJunkFilterInsertion(List *targetList,
+ TupleDesc cleanTupType,
+ TupleTableSlot *slot);
+extern JunkFilter *ExecInitJunkFilterConversion(List *targetList,
+ TupleDesc cleanTupType,
+ TupleTableSlot *slot);
+extern AttrNumber ExecFindJunkAttribute(JunkFilter *junkfilter,
+ const char *attrName);
+extern AttrNumber ExecFindJunkAttributeInTlist(List *targetlist,
+ const char *attrName);
+extern Datum ExecGetJunkAttribute(TupleTableSlot *slot, AttrNumber attno,
+ bool *isNull);
+extern TupleTableSlot *ExecFilterJunk(JunkFilter *junkfilter,
+ TupleTableSlot *slot);
+
+
+/*
+ * prototypes from functions in execMain.c
+ */
+extern void ExecutorStart(QueryDesc *queryDesc, int eflags);
+extern void standard_ExecutorStart(QueryDesc *queryDesc, int eflags);
+extern void ExecutorRun(QueryDesc *queryDesc,
+ ScanDirection direction, uint64 count, bool execute_once);
+extern void standard_ExecutorRun(QueryDesc *queryDesc,
+ ScanDirection direction, uint64 count, bool execute_once);
+extern void ExecutorFinish(QueryDesc *queryDesc);
+extern void standard_ExecutorFinish(QueryDesc *queryDesc);
+extern void ExecutorEnd(QueryDesc *queryDesc);
+extern void standard_ExecutorEnd(QueryDesc *queryDesc);
+extern void ExecutorRewind(QueryDesc *queryDesc);
+extern bool ExecCheckRTPerms(List *rangeTable, bool ereport_on_violation);
+extern void CheckValidResultRel(ResultRelInfo *resultRelInfo, CmdType operation);
+extern void InitResultRelInfo(ResultRelInfo *resultRelInfo,
+ Relation resultRelationDesc,
+ Index resultRelationIndex,
+ ResultRelInfo *partition_root_rri,
+ int instrument_options);
+extern ResultRelInfo *ExecGetTriggerResultRel(EState *estate, Oid relid);
+extern void ExecCleanUpTriggerState(EState *estate);
+extern void ExecConstraints(ResultRelInfo *resultRelInfo,
+ TupleTableSlot *slot, EState *estate);
+extern bool ExecPartitionCheck(ResultRelInfo *resultRelInfo,
+ TupleTableSlot *slot, EState *estate, bool emitError);
+extern void ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo,
+ TupleTableSlot *slot, EState *estate);
+extern void ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo,
+ TupleTableSlot *slot, EState *estate);
+extern LockTupleMode ExecUpdateLockMode(EState *estate, ResultRelInfo *relinfo);
+extern ExecRowMark *ExecFindRowMark(EState *estate, Index rti, bool missing_ok);
+extern ExecAuxRowMark *ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist);
+extern TupleTableSlot *EvalPlanQual(EPQState *epqstate, Relation relation,
+ Index rti, TupleTableSlot *testslot);
+extern void EvalPlanQualInit(EPQState *epqstate, EState *parentestate,
+ Plan *subplan, List *auxrowmarks, int epqParam);
+extern void EvalPlanQualSetPlan(EPQState *epqstate,
+ Plan *subplan, List *auxrowmarks);
+extern TupleTableSlot *EvalPlanQualSlot(EPQState *epqstate,
+ Relation relation, Index rti);
+
+#define EvalPlanQualSetSlot(epqstate, slot) ((epqstate)->origslot = (slot))
+extern bool EvalPlanQualFetchRowMark(EPQState *epqstate, Index rti, TupleTableSlot *slot);
+extern TupleTableSlot *EvalPlanQualNext(EPQState *epqstate);
+extern void EvalPlanQualBegin(EPQState *epqstate);
+extern void EvalPlanQualEnd(EPQState *epqstate);
+
+/*
+ * functions in execProcnode.c
+ */
+extern PlanState *ExecInitNode(Plan *node, EState *estate, int eflags);
+extern void ExecSetExecProcNode(PlanState *node, ExecProcNodeMtd function);
+extern Node *MultiExecProcNode(PlanState *node);
+extern void ExecEndNode(PlanState *node);
+extern bool ExecShutdownNode(PlanState *node);
+extern void ExecSetTupleBound(int64 tuples_needed, PlanState *child_node);
+
+
+/* ----------------------------------------------------------------
+ * ExecProcNode
+ *
+ * Execute the given node to return a(nother) tuple.
+ * ----------------------------------------------------------------
+ */
+#ifndef FRONTEND
+static inline TupleTableSlot *
+ExecProcNode(PlanState *node)
+{
+ if (node->chgParam != NULL) /* something changed? */
+ ExecReScan(node); /* let ReScan handle this */
+
+ return node->ExecProcNode(node);
+}
+#endif
+
+/*
+ * prototypes from functions in execExpr.c
+ */
+extern ExprState *ExecInitExpr(Expr *node, PlanState *parent);
+extern ExprState *ExecInitExprWithParams(Expr *node, ParamListInfo ext_params);
+extern ExprState *ExecInitQual(List *qual, PlanState *parent);
+extern ExprState *ExecInitCheck(List *qual, PlanState *parent);
+extern List *ExecInitExprList(List *nodes, PlanState *parent);
+extern ExprState *ExecBuildAggTrans(AggState *aggstate, struct AggStatePerPhaseData *phase,
+ bool doSort, bool doHash, bool nullcheck);
+extern ExprState *ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
+ const TupleTableSlotOps *lops, const TupleTableSlotOps *rops,
+ int numCols,
+ const AttrNumber *keyColIdx,
+ const Oid *eqfunctions,
+ const Oid *collations,
+ PlanState *parent);
+extern ProjectionInfo *ExecBuildProjectionInfo(List *targetList,
+ ExprContext *econtext,
+ TupleTableSlot *slot,
+ PlanState *parent,
+ TupleDesc inputDesc);
+extern ProjectionInfo *ExecBuildProjectionInfoExt(List *targetList,
+ ExprContext *econtext,
+ TupleTableSlot *slot,
+ bool assignJunkEntries,
+ PlanState *parent,
+ TupleDesc inputDesc);
+extern ExprState *ExecPrepareExpr(Expr *node, EState *estate);
+extern ExprState *ExecPrepareQual(List *qual, EState *estate);
+extern ExprState *ExecPrepareCheck(List *qual, EState *estate);
+extern List *ExecPrepareExprList(List *nodes, EState *estate);
+
+/*
+ * ExecEvalExpr
+ *
+ * Evaluate expression identified by "state" in the execution context
+ * given by "econtext". *isNull is set to the is-null flag for the result,
+ * and the Datum value is the function result.
+ *
+ * The caller should already have switched into the temporary memory
+ * context econtext->ecxt_per_tuple_memory. The convenience entry point
+ * ExecEvalExprSwitchContext() is provided for callers who don't prefer to
+ * do the switch in an outer loop.
+ */
+#ifndef FRONTEND
+static inline Datum
+ExecEvalExpr(ExprState *state,
+ ExprContext *econtext,
+ bool *isNull)
+{
+ return state->evalfunc(state, econtext, isNull);
+}
+#endif
+
+/*
+ * ExecEvalExprSwitchContext
+ *
+ * Same as ExecEvalExpr, but get into the right allocation context explicitly.
+ */
+#ifndef FRONTEND
+static inline Datum
+ExecEvalExprSwitchContext(ExprState *state,
+ ExprContext *econtext,
+ bool *isNull)
+{
+ Datum retDatum;
+ MemoryContext oldContext;
+
+ oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
+ retDatum = state->evalfunc(state, econtext, isNull);
+ MemoryContextSwitchTo(oldContext);
+ return retDatum;
+}
+#endif
+
+/*
+ * ExecProject
+ *
+ * Projects a tuple based on projection info and stores it in the slot passed
+ * to ExecBuildProjectionInfo().
+ *
+ * Note: the result is always a virtual tuple; therefore it may reference
+ * the contents of the exprContext's scan tuples and/or temporary results
+ * constructed in the exprContext. If the caller wishes the result to be
+ * valid longer than that data will be valid, he must call ExecMaterializeSlot
+ * on the result slot.
+ */
+#ifndef FRONTEND
+static inline TupleTableSlot *
+ExecProject(ProjectionInfo *projInfo)
+{
+ ExprContext *econtext = projInfo->pi_exprContext;
+ ExprState *state = &projInfo->pi_state;
+ TupleTableSlot *slot = state->resultslot;
+ bool isnull;
+
+ /*
+ * Clear any former contents of the result slot. This makes it safe for
+ * us to use the slot's Datum/isnull arrays as workspace.
+ */
+ ExecClearTuple(slot);
+
+ /* Run the expression, discarding scalar result from the last column. */
+ (void) ExecEvalExprSwitchContext(state, econtext, &isnull);
+
+ /*
+ * Successfully formed a result row. Mark the result slot as containing a
+ * valid virtual tuple (inlined version of ExecStoreVirtualTuple()).
+ */
+ slot->tts_flags &= ~TTS_FLAG_EMPTY;
+ slot->tts_nvalid = slot->tts_tupleDescriptor->natts;
+
+ return slot;
+}
+#endif
+
+/*
+ * ExecQual - evaluate a qual prepared with ExecInitQual (possibly via
+ * ExecPrepareQual). Returns true if qual is satisfied, else false.
+ *
+ * Note: ExecQual used to have a third argument "resultForNull". The
+ * behavior of this function now corresponds to resultForNull == false.
+ * If you want the resultForNull == true behavior, see ExecCheck.
+ */
+#ifndef FRONTEND
+static inline bool
+ExecQual(ExprState *state, ExprContext *econtext)
+{
+ Datum ret;
+ bool isnull;
+
+ /* short-circuit (here and in ExecInitQual) for empty restriction list */
+ if (state == NULL)
+ return true;
+
+ /* verify that expression was compiled using ExecInitQual */
+ Assert(state->flags & EEO_FLAG_IS_QUAL);
+
+ ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
+
+ /* EEOP_QUAL should never return NULL */
+ Assert(!isnull);
+
+ return DatumGetBool(ret);
+}
+#endif
+
+/*
+ * ExecQualAndReset() - evaluate qual with ExecQual() and reset expression
+ * context.
+ */
+#ifndef FRONTEND
+static inline bool
+ExecQualAndReset(ExprState *state, ExprContext *econtext)
+{
+ bool ret = ExecQual(state, econtext);
+
+ /* inline ResetExprContext, to avoid ordering issue in this file */
+ MemoryContextReset(econtext->ecxt_per_tuple_memory);
+ return ret;
+}
+#endif
+
+extern bool ExecCheck(ExprState *state, ExprContext *context);
+
+/*
+ * prototypes from functions in execSRF.c
+ */
+extern SetExprState *ExecInitTableFunctionResult(Expr *expr,
+ ExprContext *econtext, PlanState *parent);
+extern Tuplestorestate *ExecMakeTableFunctionResult(SetExprState *setexpr,
+ ExprContext *econtext,
+ MemoryContext argContext,
+ TupleDesc expectedDesc,
+ bool randomAccess);
+extern SetExprState *ExecInitFunctionResultSet(Expr *expr,
+ ExprContext *econtext, PlanState *parent);
+extern Datum ExecMakeFunctionResultSet(SetExprState *fcache,
+ ExprContext *econtext,
+ MemoryContext argContext,
+ bool *isNull,
+ ExprDoneCond *isDone);
+
+/*
+ * prototypes from functions in execScan.c
+ */
+typedef TupleTableSlot *(*ExecScanAccessMtd) (ScanState *node);
+typedef bool (*ExecScanRecheckMtd) (ScanState *node, TupleTableSlot *slot);
+
+extern TupleTableSlot *ExecScan(ScanState *node, ExecScanAccessMtd accessMtd,
+ ExecScanRecheckMtd recheckMtd);
+extern void ExecAssignScanProjectionInfo(ScanState *node);
+extern void ExecAssignScanProjectionInfoWithVarno(ScanState *node, Index varno);
+extern void ExecScanReScan(ScanState *node);
+
+/*
+ * prototypes from functions in execTuples.c
+ */
+extern void ExecInitResultTypeTL(PlanState *planstate);
+extern void ExecInitResultSlot(PlanState *planstate,
+ const TupleTableSlotOps *tts_ops);
+extern void ExecInitResultTupleSlotTL(PlanState *planstate,
+ const TupleTableSlotOps *tts_ops);
+extern void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate,
+ TupleDesc tupleDesc,
+ const TupleTableSlotOps *tts_ops);
+extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate,
+ TupleDesc tupledesc,
+ const TupleTableSlotOps *tts_ops);
+extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate, TupleDesc tupType,
+ const TupleTableSlotOps *tts_ops);
+extern TupleDesc ExecTypeFromTL(List *targetList);
+extern TupleDesc ExecCleanTypeFromTL(List *targetList);
+extern TupleDesc ExecTypeFromExprList(List *exprList);
+extern void ExecTypeSetColNames(TupleDesc typeInfo, List *namesList);
+extern void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg);
+
+typedef struct TupOutputState
+{
+ TupleTableSlot *slot;
+ DestReceiver *dest;
+} TupOutputState;
+
+extern TupOutputState *begin_tup_output_tupdesc(DestReceiver *dest,
+ TupleDesc tupdesc,
+ const TupleTableSlotOps *tts_ops);
+extern void do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull);
+extern void do_text_output_multiline(TupOutputState *tstate, const char *txt);
+extern void end_tup_output(TupOutputState *tstate);
+
+/*
+ * Write a single line of text given as a C string.
+ *
+ * Should only be used with a single-TEXT-attribute tupdesc.
+ */
+#define do_text_output_oneline(tstate, str_to_emit) \
+ do { \
+ Datum values_[1]; \
+ bool isnull_[1]; \
+ values_[0] = PointerGetDatum(cstring_to_text(str_to_emit)); \
+ isnull_[0] = false; \
+ do_tup_output(tstate, values_, isnull_); \
+ pfree(DatumGetPointer(values_[0])); \
+ } while (0)
+
+
+/*
+ * prototypes from functions in execUtils.c
+ */
+extern EState *CreateExecutorState(void);
+extern void FreeExecutorState(EState *estate);
+extern ExprContext *CreateExprContext(EState *estate);
+extern ExprContext *CreateWorkExprContext(EState *estate);
+extern ExprContext *CreateStandaloneExprContext(void);
+extern void FreeExprContext(ExprContext *econtext, bool isCommit);
+extern void ReScanExprContext(ExprContext *econtext);
+
+#define ResetExprContext(econtext) \
+ MemoryContextReset((econtext)->ecxt_per_tuple_memory)
+
+extern ExprContext *MakePerTupleExprContext(EState *estate);
+
+/* Get an EState's per-output-tuple exprcontext, making it if first use */
+#define GetPerTupleExprContext(estate) \
+ ((estate)->es_per_tuple_exprcontext ? \
+ (estate)->es_per_tuple_exprcontext : \
+ MakePerTupleExprContext(estate))
+
+#define GetPerTupleMemoryContext(estate) \
+ (GetPerTupleExprContext(estate)->ecxt_per_tuple_memory)
+
+/* Reset an EState's per-output-tuple exprcontext, if one's been created */
+#define ResetPerTupleExprContext(estate) \
+ do { \
+ if ((estate)->es_per_tuple_exprcontext) \
+ ResetExprContext((estate)->es_per_tuple_exprcontext); \
+ } while (0)
+
+extern void ExecAssignExprContext(EState *estate, PlanState *planstate);
+extern TupleDesc ExecGetResultType(PlanState *planstate);
+extern const TupleTableSlotOps *ExecGetResultSlotOps(PlanState *planstate,
+ bool *isfixed);
+extern void ExecAssignProjectionInfo(PlanState *planstate,
+ TupleDesc inputDesc);
+extern void ExecConditionalAssignProjectionInfo(PlanState *planstate,
+ TupleDesc inputDesc, Index varno);
+extern void ExecFreeExprContext(PlanState *planstate);
+extern void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc);
+extern void ExecCreateScanSlotFromOuterPlan(EState *estate,
+ ScanState *scanstate,
+ const TupleTableSlotOps *tts_ops);
+
+extern bool ExecRelationIsTargetRelation(EState *estate, Index scanrelid);
+
+extern Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags);
+
+extern void ExecInitRangeTable(EState *estate, List *rangeTable);
+
+static inline RangeTblEntry *
+exec_rt_fetch(Index rti, EState *estate)
+{
+ return (RangeTblEntry *) list_nth(estate->es_range_table, rti - 1);
+}
+
+extern Relation ExecGetRangeTableRelation(EState *estate, Index rti);
+
+extern int executor_errposition(EState *estate, int location);
+
+extern void RegisterExprContextCallback(ExprContext *econtext,
+ ExprContextCallbackFunction function,
+ Datum arg);
+extern void UnregisterExprContextCallback(ExprContext *econtext,
+ ExprContextCallbackFunction function,
+ Datum arg);
+
+extern Datum GetAttributeByName(HeapTupleHeader tuple, const char *attname,
+ bool *isNull);
+extern Datum GetAttributeByNum(HeapTupleHeader tuple, AttrNumber attrno,
+ bool *isNull);
+
+extern int ExecTargetListLength(List *targetlist);
+extern int ExecCleanTargetListLength(List *targetlist);
+
+extern TupleTableSlot *ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relInfo);
+extern TupleTableSlot *ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo);
+extern TupleTableSlot *ExecGetReturningSlot(EState *estate, ResultRelInfo *relInfo);
+
+extern Bitmapset *ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate);
+extern Bitmapset *ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate);
+extern Bitmapset *ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate);
+extern Bitmapset *ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate);
+
+/*
+ * prototypes from functions in execIndexing.c
+ */
+extern void ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative);
+extern void ExecCloseIndices(ResultRelInfo *resultRelInfo);
+extern List *ExecInsertIndexTuples(TupleTableSlot *slot, EState *estate, bool noDupErr,
+ bool *specConflict, List *arbiterIndexes);
+extern bool ExecCheckIndexConstraints(TupleTableSlot *slot, EState *estate,
+ ItemPointer conflictTid, List *arbiterIndexes);
+extern void check_exclusion_constraint(Relation heap, Relation index,
+ IndexInfo *indexInfo,
+ ItemPointer tupleid,
+ Datum *values, bool *isnull,
+ EState *estate, bool newIndex);
+
+/*
+ * prototypes from functions in execReplication.c
+ */
+extern bool RelationFindReplTupleByIndex(Relation rel, Oid idxoid,
+ LockTupleMode lockmode,
+ TupleTableSlot *searchslot,
+ TupleTableSlot *outslot);
+extern bool RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode,
+ TupleTableSlot *searchslot, TupleTableSlot *outslot);
+
+extern void ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot);
+extern void ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
+ TupleTableSlot *searchslot, TupleTableSlot *slot);
+extern void ExecSimpleRelationDelete(EState *estate, EPQState *epqstate,
+ TupleTableSlot *searchslot);
+extern void CheckCmdReplicaIdentity(Relation rel, CmdType cmd);
+
+extern void CheckSubscriptionRelkind(char relkind, const char *nspname,
+ const char *relname);
+
+#endif /* EXECUTOR_H */
diff --git a/src/include/executor/functions.h b/src/include/executor/functions.h
new file mode 100644
index 0000000..a0db24b
--- /dev/null
+++ b/src/include/executor/functions.h
@@ -0,0 +1,41 @@
+/*-------------------------------------------------------------------------
+ *
+ * functions.h
+ * Declarations for execution of SQL-language functions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/functions.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FUNCTIONS_H
+#define FUNCTIONS_H
+
+#include "nodes/execnodes.h"
+#include "tcop/dest.h"
+
+/* This struct is known only within executor/functions.c */
+typedef struct SQLFunctionParseInfo *SQLFunctionParseInfoPtr;
+
+extern Datum fmgr_sql(PG_FUNCTION_ARGS);
+
+extern SQLFunctionParseInfoPtr prepare_sql_fn_parse_info(HeapTuple procedureTuple,
+ Node *call_expr,
+ Oid inputCollation);
+
+extern void sql_fn_parser_setup(struct ParseState *pstate,
+ SQLFunctionParseInfoPtr pinfo);
+
+extern void check_sql_fn_statements(List *queryTreeLists);
+
+extern bool check_sql_fn_retval(List *queryTreeLists,
+ Oid rettype, TupleDesc rettupdesc,
+ bool insertDroppedCols,
+ List **resultTargetList);
+
+extern DestReceiver *CreateSQLFunctionDestReceiver(void);
+
+#endif /* FUNCTIONS_H */
diff --git a/src/include/executor/hashjoin.h b/src/include/executor/hashjoin.h
new file mode 100644
index 0000000..eb5daba
--- /dev/null
+++ b/src/include/executor/hashjoin.h
@@ -0,0 +1,362 @@
+/*-------------------------------------------------------------------------
+ *
+ * hashjoin.h
+ * internal structures for hash joins
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/hashjoin.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef HASHJOIN_H
+#define HASHJOIN_H
+
+#include "nodes/execnodes.h"
+#include "port/atomics.h"
+#include "storage/barrier.h"
+#include "storage/buffile.h"
+#include "storage/lwlock.h"
+
+/* ----------------------------------------------------------------
+ * hash-join hash table structures
+ *
+ * Each active hashjoin has a HashJoinTable control block, which is
+ * palloc'd in the executor's per-query context. All other storage needed
+ * for the hashjoin is kept in private memory contexts, two for each hashjoin.
+ * This makes it easy and fast to release the storage when we don't need it
+ * anymore. (Exception: data associated with the temp files lives in the
+ * per-query context too, since we always call buffile.c in that context.)
+ *
+ * The hashtable contexts are made children of the per-query context, ensuring
+ * that they will be discarded at end of statement even if the join is
+ * aborted early by an error. (Likewise, any temporary files we make will
+ * be cleaned up by the virtual file manager in event of an error.)
+ *
+ * Storage that should live through the entire join is allocated from the
+ * "hashCxt", while storage that is only wanted for the current batch is
+ * allocated in the "batchCxt". By resetting the batchCxt at the end of
+ * each batch, we free all the per-batch storage reliably and without tedium.
+ *
+ * During first scan of inner relation, we get its tuples from executor.
+ * If nbatch > 1 then tuples that don't belong in first batch get saved
+ * into inner-batch temp files. The same statements apply for the
+ * first scan of the outer relation, except we write tuples to outer-batch
+ * temp files. After finishing the first scan, we do the following for
+ * each remaining batch:
+ * 1. Read tuples from inner batch file, load into hash buckets.
+ * 2. Read tuples from outer batch file, match to hash buckets and output.
+ *
+ * It is possible to increase nbatch on the fly if the in-memory hash table
+ * gets too big. The hash-value-to-batch computation is arranged so that this
+ * can only cause a tuple to go into a later batch than previously thought,
+ * never into an earlier batch. When we increase nbatch, we rescan the hash
+ * table and dump out any tuples that are now of a later batch to the correct
+ * inner batch file. Subsequently, while reading either inner or outer batch
+ * files, we might find tuples that no longer belong to the current batch;
+ * if so, we just dump them out to the correct batch file.
+ * ----------------------------------------------------------------
+ */
+
+/* these are in nodes/execnodes.h: */
+/* typedef struct HashJoinTupleData *HashJoinTuple; */
+/* typedef struct HashJoinTableData *HashJoinTable; */
+
+typedef struct HashJoinTupleData
+{
+ /* link to next tuple in same bucket */
+ union
+ {
+ struct HashJoinTupleData *unshared;
+ dsa_pointer shared;
+ } next;
+ uint32 hashvalue; /* tuple's hash code */
+ /* Tuple data, in MinimalTuple format, follows on a MAXALIGN boundary */
+} HashJoinTupleData;
+
+#define HJTUPLE_OVERHEAD MAXALIGN(sizeof(HashJoinTupleData))
+#define HJTUPLE_MINTUPLE(hjtup) \
+ ((MinimalTuple) ((char *) (hjtup) + HJTUPLE_OVERHEAD))
+
+/*
+ * If the outer relation's distribution is sufficiently nonuniform, we attempt
+ * to optimize the join by treating the hash values corresponding to the outer
+ * relation's MCVs specially. Inner relation tuples matching these hash
+ * values go into the "skew" hashtable instead of the main hashtable, and
+ * outer relation tuples with these hash values are matched against that
+ * table instead of the main one. Thus, tuples with these hash values are
+ * effectively handled as part of the first batch and will never go to disk.
+ * The skew hashtable is limited to SKEW_HASH_MEM_PERCENT of the total memory
+ * allowed for the join; while building the hashtables, we decrease the number
+ * of MCVs being specially treated if needed to stay under this limit.
+ *
+ * Note: you might wonder why we look at the outer relation stats for this,
+ * rather than the inner. One reason is that the outer relation is typically
+ * bigger, so we get more I/O savings by optimizing for its most common values.
+ * Also, for similarly-sized relations, the planner prefers to put the more
+ * uniformly distributed relation on the inside, so we're more likely to find
+ * interesting skew in the outer relation.
+ */
+typedef struct HashSkewBucket
+{
+ uint32 hashvalue; /* common hash value */
+ HashJoinTuple tuples; /* linked list of inner-relation tuples */
+} HashSkewBucket;
+
+#define SKEW_BUCKET_OVERHEAD MAXALIGN(sizeof(HashSkewBucket))
+#define INVALID_SKEW_BUCKET_NO (-1)
+#define SKEW_HASH_MEM_PERCENT 2
+#define SKEW_MIN_OUTER_FRACTION 0.01
+
+/*
+ * To reduce palloc overhead, the HashJoinTuples for the current batch are
+ * packed in 32kB buffers instead of pallocing each tuple individually.
+ */
+typedef struct HashMemoryChunkData
+{
+ int ntuples; /* number of tuples stored in this chunk */
+ size_t maxlen; /* size of the chunk's tuple buffer */
+ size_t used; /* number of buffer bytes already used */
+
+ /* pointer to the next chunk (linked list) */
+ union
+ {
+ struct HashMemoryChunkData *unshared;
+ dsa_pointer shared;
+ } next;
+
+ /*
+ * The chunk's tuple buffer starts after the HashMemoryChunkData struct,
+ * at offset HASH_CHUNK_HEADER_SIZE (which must be maxaligned). Note that
+ * that offset is not included in "maxlen" or "used".
+ */
+} HashMemoryChunkData;
+
+typedef struct HashMemoryChunkData *HashMemoryChunk;
+
+#define HASH_CHUNK_SIZE (32 * 1024L)
+#define HASH_CHUNK_HEADER_SIZE MAXALIGN(sizeof(HashMemoryChunkData))
+#define HASH_CHUNK_DATA(hc) (((char *) (hc)) + HASH_CHUNK_HEADER_SIZE)
+/* tuples exceeding HASH_CHUNK_THRESHOLD bytes are put in their own chunk */
+#define HASH_CHUNK_THRESHOLD (HASH_CHUNK_SIZE / 4)
+
+/*
+ * For each batch of a Parallel Hash Join, we have a ParallelHashJoinBatch
+ * object in shared memory to coordinate access to it. Since they are
+ * followed by variable-sized objects, they are arranged in contiguous memory
+ * but not accessed directly as an array.
+ */
+typedef struct ParallelHashJoinBatch
+{
+ dsa_pointer buckets; /* array of hash table buckets */
+ Barrier batch_barrier; /* synchronization for joining this batch */
+
+ dsa_pointer chunks; /* chunks of tuples loaded */
+ size_t size; /* size of buckets + chunks in memory */
+ size_t estimated_size; /* size of buckets + chunks while writing */
+ size_t ntuples; /* number of tuples loaded */
+ size_t old_ntuples; /* number of tuples before repartitioning */
+ bool space_exhausted;
+
+ /*
+ * Variable-sized SharedTuplestore objects follow this struct in memory.
+ * See the accessor macros below.
+ */
+} ParallelHashJoinBatch;
+
+/* Accessor for inner batch tuplestore following a ParallelHashJoinBatch. */
+#define ParallelHashJoinBatchInner(batch) \
+ ((SharedTuplestore *) \
+ ((char *) (batch) + MAXALIGN(sizeof(ParallelHashJoinBatch))))
+
+/* Accessor for outer batch tuplestore following a ParallelHashJoinBatch. */
+#define ParallelHashJoinBatchOuter(batch, nparticipants) \
+ ((SharedTuplestore *) \
+ ((char *) ParallelHashJoinBatchInner(batch) + \
+ MAXALIGN(sts_estimate(nparticipants))))
+
+/* Total size of a ParallelHashJoinBatch and tuplestores. */
+#define EstimateParallelHashJoinBatch(hashtable) \
+ (MAXALIGN(sizeof(ParallelHashJoinBatch)) + \
+ MAXALIGN(sts_estimate((hashtable)->parallel_state->nparticipants)) * 2)
+
+/* Accessor for the nth ParallelHashJoinBatch given the base. */
+#define NthParallelHashJoinBatch(base, n) \
+ ((ParallelHashJoinBatch *) \
+ ((char *) (base) + \
+ EstimateParallelHashJoinBatch(hashtable) * (n)))
+
+/*
+ * Each backend requires a small amount of per-batch state to interact with
+ * each ParallelHashJoinBatch.
+ */
+typedef struct ParallelHashJoinBatchAccessor
+{
+ ParallelHashJoinBatch *shared; /* pointer to shared state */
+
+ /* Per-backend partial counters to reduce contention. */
+ size_t preallocated; /* pre-allocated space for this backend */
+ size_t ntuples; /* number of tuples */
+ size_t size; /* size of partition in memory */
+ size_t estimated_size; /* size of partition on disk */
+ size_t old_ntuples; /* how many tuples before repartitioning? */
+ bool at_least_one_chunk; /* has this backend allocated a chunk? */
+
+ bool done; /* flag to remember that a batch is done */
+ SharedTuplestoreAccessor *inner_tuples;
+ SharedTuplestoreAccessor *outer_tuples;
+} ParallelHashJoinBatchAccessor;
+
+/*
+ * While hashing the inner relation, any participant might determine that it's
+ * time to increase the number of buckets to reduce the load factor or batches
+ * to reduce the memory size. This is indicated by setting the growth flag to
+ * these values.
+ */
+typedef enum ParallelHashGrowth
+{
+ /* The current dimensions are sufficient. */
+ PHJ_GROWTH_OK,
+ /* The load factor is too high, so we need to add buckets. */
+ PHJ_GROWTH_NEED_MORE_BUCKETS,
+ /* The memory budget would be exhausted, so we need to repartition. */
+ PHJ_GROWTH_NEED_MORE_BATCHES,
+ /* Repartitioning didn't help last time, so don't try to do that again. */
+ PHJ_GROWTH_DISABLED
+} ParallelHashGrowth;
+
+/*
+ * The shared state used to coordinate a Parallel Hash Join. This is stored
+ * in the DSM segment.
+ */
+typedef struct ParallelHashJoinState
+{
+ dsa_pointer batches; /* array of ParallelHashJoinBatch */
+ dsa_pointer old_batches; /* previous generation during repartition */
+ int nbatch; /* number of batches now */
+ int old_nbatch; /* previous number of batches */
+ int nbuckets; /* number of buckets */
+ ParallelHashGrowth growth; /* control batch/bucket growth */
+ dsa_pointer chunk_work_queue; /* chunk work queue */
+ int nparticipants;
+ size_t space_allowed;
+ size_t total_tuples; /* total number of inner tuples */
+ LWLock lock; /* lock protecting the above */
+
+ Barrier build_barrier; /* synchronization for the build phases */
+ Barrier grow_batches_barrier;
+ Barrier grow_buckets_barrier;
+ pg_atomic_uint32 distributor; /* counter for load balancing */
+
+ SharedFileSet fileset; /* space for shared temporary files */
+} ParallelHashJoinState;
+
+/* The phases for building batches, used by build_barrier. */
+#define PHJ_BUILD_ELECTING 0
+#define PHJ_BUILD_ALLOCATING 1
+#define PHJ_BUILD_HASHING_INNER 2
+#define PHJ_BUILD_HASHING_OUTER 3
+#define PHJ_BUILD_DONE 4
+
+/* The phases for probing each batch, used by for batch_barrier. */
+#define PHJ_BATCH_ELECTING 0
+#define PHJ_BATCH_ALLOCATING 1
+#define PHJ_BATCH_LOADING 2
+#define PHJ_BATCH_PROBING 3
+#define PHJ_BATCH_DONE 4
+
+/* The phases of batch growth while hashing, for grow_batches_barrier. */
+#define PHJ_GROW_BATCHES_ELECTING 0
+#define PHJ_GROW_BATCHES_ALLOCATING 1
+#define PHJ_GROW_BATCHES_REPARTITIONING 2
+#define PHJ_GROW_BATCHES_DECIDING 3
+#define PHJ_GROW_BATCHES_FINISHING 4
+#define PHJ_GROW_BATCHES_PHASE(n) ((n) % 5) /* circular phases */
+
+/* The phases of bucket growth while hashing, for grow_buckets_barrier. */
+#define PHJ_GROW_BUCKETS_ELECTING 0
+#define PHJ_GROW_BUCKETS_ALLOCATING 1
+#define PHJ_GROW_BUCKETS_REINSERTING 2
+#define PHJ_GROW_BUCKETS_PHASE(n) ((n) % 3) /* circular phases */
+
+typedef struct HashJoinTableData
+{
+ int nbuckets; /* # buckets in the in-memory hash table */
+ int log2_nbuckets; /* its log2 (nbuckets must be a power of 2) */
+
+ int nbuckets_original; /* # buckets when starting the first hash */
+ int nbuckets_optimal; /* optimal # buckets (per batch) */
+ int log2_nbuckets_optimal; /* log2(nbuckets_optimal) */
+
+ /* buckets[i] is head of list of tuples in i'th in-memory bucket */
+ union
+ {
+ /* unshared array is per-batch storage, as are all the tuples */
+ struct HashJoinTupleData **unshared;
+ /* shared array is per-query DSA area, as are all the tuples */
+ dsa_pointer_atomic *shared;
+ } buckets;
+
+ bool keepNulls; /* true to store unmatchable NULL tuples */
+
+ bool skewEnabled; /* are we using skew optimization? */
+ HashSkewBucket **skewBucket; /* hashtable of skew buckets */
+ int skewBucketLen; /* size of skewBucket array (a power of 2!) */
+ int nSkewBuckets; /* number of active skew buckets */
+ int *skewBucketNums; /* array indexes of active skew buckets */
+
+ int nbatch; /* number of batches */
+ int curbatch; /* current batch #; 0 during 1st pass */
+
+ int nbatch_original; /* nbatch when we started inner scan */
+ int nbatch_outstart; /* nbatch when we started outer scan */
+
+ bool growEnabled; /* flag to shut off nbatch increases */
+
+ double totalTuples; /* # tuples obtained from inner plan */
+ double partialTuples; /* # tuples obtained from inner plan by me */
+ double skewTuples; /* # tuples inserted into skew tuples */
+
+ /*
+ * These arrays are allocated for the life of the hash join, but only if
+ * nbatch > 1. A file is opened only when we first write a tuple into it
+ * (otherwise its pointer remains NULL). Note that the zero'th array
+ * elements never get used, since we will process rather than dump out any
+ * tuples of batch zero.
+ */
+ BufFile **innerBatchFile; /* buffered virtual temp file per batch */
+ BufFile **outerBatchFile; /* buffered virtual temp file per batch */
+
+ /*
+ * Info about the datatype-specific hash functions for the datatypes being
+ * hashed. These are arrays of the same length as the number of hash join
+ * clauses (hash keys).
+ */
+ FmgrInfo *outer_hashfunctions; /* lookup data for hash functions */
+ FmgrInfo *inner_hashfunctions; /* lookup data for hash functions */
+ bool *hashStrict; /* is each hash join operator strict? */
+ Oid *collations;
+
+ Size spaceUsed; /* memory space currently used by tuples */
+ Size spaceAllowed; /* upper limit for space used */
+ Size spacePeak; /* peak space used */
+ Size spaceUsedSkew; /* skew hash table's current space usage */
+ Size spaceAllowedSkew; /* upper limit for skew hashtable */
+
+ MemoryContext hashCxt; /* context for whole-hash-join storage */
+ MemoryContext batchCxt; /* context for this-batch-only storage */
+
+ /* used for dense allocation of tuples (into linked chunks) */
+ HashMemoryChunk chunks; /* one list for the whole batch */
+
+ /* Shared and private state for Parallel Hash. */
+ HashMemoryChunk current_chunk; /* this backend's current chunk */
+ dsa_area *area; /* DSA area to allocate memory from */
+ ParallelHashJoinState *parallel_state;
+ ParallelHashJoinBatchAccessor *batches;
+ dsa_pointer current_chunk_shared;
+} HashJoinTableData;
+
+#endif /* HASHJOIN_H */
diff --git a/src/include/executor/instrument.h b/src/include/executor/instrument.h
new file mode 100644
index 0000000..a97562e
--- /dev/null
+++ b/src/include/executor/instrument.h
@@ -0,0 +1,101 @@
+/*-------------------------------------------------------------------------
+ *
+ * instrument.h
+ * definitions for run-time statistics collection
+ *
+ *
+ * Copyright (c) 2001-2020, PostgreSQL Global Development Group
+ *
+ * src/include/executor/instrument.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef INSTRUMENT_H
+#define INSTRUMENT_H
+
+#include "portability/instr_time.h"
+
+
+typedef struct BufferUsage
+{
+ long shared_blks_hit; /* # of shared buffer hits */
+ long shared_blks_read; /* # of shared disk blocks read */
+ long shared_blks_dirtied; /* # of shared blocks dirtied */
+ long shared_blks_written; /* # of shared disk blocks written */
+ long local_blks_hit; /* # of local buffer hits */
+ long local_blks_read; /* # of local disk blocks read */
+ long local_blks_dirtied; /* # of shared blocks dirtied */
+ long local_blks_written; /* # of local disk blocks written */
+ long temp_blks_read; /* # of temp blocks read */
+ long temp_blks_written; /* # of temp blocks written */
+ instr_time blk_read_time; /* time spent reading */
+ instr_time blk_write_time; /* time spent writing */
+} BufferUsage;
+
+typedef struct WalUsage
+{
+ long wal_records; /* # of WAL records produced */
+ long wal_fpi; /* # of WAL full page images produced */
+ uint64 wal_bytes; /* size of WAL records produced */
+} WalUsage;
+
+/* Flag bits included in InstrAlloc's instrument_options bitmask */
+typedef enum InstrumentOption
+{
+ INSTRUMENT_TIMER = 1 << 0, /* needs timer (and row counts) */
+ INSTRUMENT_BUFFERS = 1 << 1, /* needs buffer usage */
+ INSTRUMENT_ROWS = 1 << 2, /* needs row count */
+ INSTRUMENT_WAL = 1 << 3, /* needs WAL usage */
+ INSTRUMENT_ALL = PG_INT32_MAX
+} InstrumentOption;
+
+typedef struct Instrumentation
+{
+ /* Parameters set at node creation: */
+ bool need_timer; /* true if we need timer data */
+ bool need_bufusage; /* true if we need buffer usage data */
+ bool need_walusage; /* true if we need WAL usage data */
+ /* Info about current plan cycle: */
+ bool running; /* true if we've completed first tuple */
+ instr_time starttime; /* start time of current iteration of node */
+ instr_time counter; /* accumulated runtime for this node */
+ double firsttuple; /* time for first tuple of this cycle */
+ double tuplecount; /* # of tuples emitted so far this cycle */
+ BufferUsage bufusage_start; /* buffer usage at start */
+ WalUsage walusage_start; /* WAL usage at start */
+ /* Accumulated statistics across all completed cycles: */
+ double startup; /* total startup time (in seconds) */
+ double total; /* total time (in seconds) */
+ double ntuples; /* total tuples produced */
+ double ntuples2; /* secondary node-specific tuple counter */
+ double nloops; /* # of run cycles for this node */
+ double nfiltered1; /* # of tuples removed by scanqual or joinqual */
+ double nfiltered2; /* # of tuples removed by "other" quals */
+ BufferUsage bufusage; /* total buffer usage */
+ WalUsage walusage; /* total WAL usage */
+} Instrumentation;
+
+typedef struct WorkerInstrumentation
+{
+ int num_workers; /* # of structures that follow */
+ Instrumentation instrument[FLEXIBLE_ARRAY_MEMBER];
+} WorkerInstrumentation;
+
+extern PGDLLIMPORT BufferUsage pgBufferUsage;
+extern PGDLLIMPORT WalUsage pgWalUsage;
+
+extern Instrumentation *InstrAlloc(int n, int instrument_options);
+extern void InstrInit(Instrumentation *instr, int instrument_options);
+extern void InstrStartNode(Instrumentation *instr);
+extern void InstrStopNode(Instrumentation *instr, double nTuples);
+extern void InstrEndLoop(Instrumentation *instr);
+extern void InstrAggNode(Instrumentation *dst, Instrumentation *add);
+extern void InstrStartParallelQuery(void);
+extern void InstrEndParallelQuery(BufferUsage *bufusage, WalUsage *walusage);
+extern void InstrAccumParallelQuery(BufferUsage *bufusage, WalUsage *walusage);
+extern void BufferUsageAccumDiff(BufferUsage *dst,
+ const BufferUsage *add, const BufferUsage *sub);
+extern void WalUsageAccumDiff(WalUsage *dst, const WalUsage *add,
+ const WalUsage *sub);
+
+#endif /* INSTRUMENT_H */
diff --git a/src/include/executor/nodeAgg.h b/src/include/executor/nodeAgg.h
new file mode 100644
index 0000000..b955169
--- /dev/null
+++ b/src/include/executor/nodeAgg.h
@@ -0,0 +1,333 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeAgg.h
+ * prototypes for nodeAgg.c
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeAgg.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEAGG_H
+#define NODEAGG_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+
+/*
+ * AggStatePerTransData - per aggregate state value information
+ *
+ * Working state for updating the aggregate's state value, by calling the
+ * transition function with an input row. This struct does not store the
+ * information needed to produce the final aggregate result from the transition
+ * state, that's stored in AggStatePerAggData instead. This separation allows
+ * multiple aggregate results to be produced from a single state value.
+ */
+typedef struct AggStatePerTransData
+{
+ /*
+ * These values are set up during ExecInitAgg() and do not change
+ * thereafter:
+ */
+
+ /*
+ * Link to an Aggref expr this state value is for.
+ *
+ * There can be multiple Aggref's sharing the same state value, so long as
+ * the inputs and transition functions are identical and the final
+ * functions are not read-write. This points to the first one of them.
+ */
+ Aggref *aggref;
+
+ /*
+ * Is this state value actually being shared by more than one Aggref?
+ */
+ bool aggshared;
+
+ /*
+ * Number of aggregated input columns. This includes ORDER BY expressions
+ * in both the plain-agg and ordered-set cases. Ordered-set direct args
+ * are not counted, though.
+ */
+ int numInputs;
+
+ /*
+ * Number of aggregated input columns to pass to the transfn. This
+ * includes the ORDER BY columns for ordered-set aggs, but not for plain
+ * aggs. (This doesn't count the transition state value!)
+ */
+ int numTransInputs;
+
+ /* Oid of the state transition or combine function */
+ Oid transfn_oid;
+
+ /* Oid of the serialization function or InvalidOid */
+ Oid serialfn_oid;
+
+ /* Oid of the deserialization function or InvalidOid */
+ Oid deserialfn_oid;
+
+ /* Oid of state value's datatype */
+ Oid aggtranstype;
+
+ /*
+ * fmgr lookup data for transition function or combine function. Note in
+ * particular that the fn_strict flag is kept here.
+ */
+ FmgrInfo transfn;
+
+ /* fmgr lookup data for serialization function */
+ FmgrInfo serialfn;
+
+ /* fmgr lookup data for deserialization function */
+ FmgrInfo deserialfn;
+
+ /* Input collation derived for aggregate */
+ Oid aggCollation;
+
+ /* number of sorting columns */
+ int numSortCols;
+
+ /* number of sorting columns to consider in DISTINCT comparisons */
+ /* (this is either zero or the same as numSortCols) */
+ int numDistinctCols;
+
+ /* deconstructed sorting information (arrays of length numSortCols) */
+ AttrNumber *sortColIdx;
+ Oid *sortOperators;
+ Oid *sortCollations;
+ bool *sortNullsFirst;
+
+ /*
+ * Comparators for input columns --- only set/used when aggregate has
+ * DISTINCT flag. equalfnOne version is used for single-column
+ * comparisons, equalfnMulti for the case of multiple columns.
+ */
+ FmgrInfo equalfnOne;
+ ExprState *equalfnMulti;
+
+ /*
+ * initial value from pg_aggregate entry
+ */
+ Datum initValue;
+ bool initValueIsNull;
+
+ /*
+ * We need the len and byval info for the agg's input and transition data
+ * types in order to know how to copy/delete values.
+ *
+ * Note that the info for the input type is used only when handling
+ * DISTINCT aggs with just one argument, so there is only one input type.
+ */
+ int16 inputtypeLen,
+ transtypeLen;
+ bool inputtypeByVal,
+ transtypeByVal;
+
+ /*
+ * Slots for holding the evaluated input arguments. These are set up
+ * during ExecInitAgg() and then used for each input row requiring either
+ * FILTER or ORDER BY/DISTINCT processing.
+ */
+ TupleTableSlot *sortslot; /* current input tuple */
+ TupleTableSlot *uniqslot; /* used for multi-column DISTINCT */
+ TupleDesc sortdesc; /* descriptor of input tuples */
+
+ /*
+ * These values are working state that is initialized at the start of an
+ * input tuple group and updated for each input tuple.
+ *
+ * For a simple (non DISTINCT/ORDER BY) aggregate, we just feed the input
+ * values straight to the transition function. If it's DISTINCT or
+ * requires ORDER BY, we pass the input values into a Tuplesort object;
+ * then at completion of the input tuple group, we scan the sorted values,
+ * eliminate duplicates if needed, and run the transition function on the
+ * rest.
+ *
+ * We need a separate tuplesort for each grouping set.
+ */
+
+ Tuplesortstate **sortstates; /* sort objects, if DISTINCT or ORDER BY */
+
+ /*
+ * This field is a pre-initialized FunctionCallInfo struct used for
+ * calling this aggregate's transfn. We save a few cycles per row by not
+ * re-initializing the unchanging fields; which isn't much, but it seems
+ * worth the extra space consumption.
+ */
+ FunctionCallInfo transfn_fcinfo;
+
+ /* Likewise for serialization and deserialization functions */
+ FunctionCallInfo serialfn_fcinfo;
+
+ FunctionCallInfo deserialfn_fcinfo;
+} AggStatePerTransData;
+
+/*
+ * AggStatePerAggData - per-aggregate information
+ *
+ * This contains the information needed to call the final function, to produce
+ * a final aggregate result from the state value. If there are multiple
+ * identical Aggrefs in the query, they can all share the same per-agg data.
+ *
+ * These values are set up during ExecInitAgg() and do not change thereafter.
+ */
+typedef struct AggStatePerAggData
+{
+ /*
+ * Link to an Aggref expr this state value is for.
+ *
+ * There can be multiple identical Aggref's sharing the same per-agg. This
+ * points to the first one of them.
+ */
+ Aggref *aggref;
+
+ /* index to the state value which this agg should use */
+ int transno;
+
+ /* Optional Oid of final function (may be InvalidOid) */
+ Oid finalfn_oid;
+
+ /*
+ * fmgr lookup data for final function --- only valid when finalfn_oid is
+ * not InvalidOid.
+ */
+ FmgrInfo finalfn;
+
+ /*
+ * Number of arguments to pass to the finalfn. This is always at least 1
+ * (the transition state value) plus any ordered-set direct args. If the
+ * finalfn wants extra args then we pass nulls corresponding to the
+ * aggregated input columns.
+ */
+ int numFinalArgs;
+
+ /* ExprStates for any direct-argument expressions */
+ List *aggdirectargs;
+
+ /*
+ * We need the len and byval info for the agg's result data type in order
+ * to know how to copy/delete values.
+ */
+ int16 resulttypeLen;
+ bool resulttypeByVal;
+
+ /*
+ * "shareable" is false if this agg cannot share state values with other
+ * aggregates because the final function is read-write.
+ */
+ bool shareable;
+} AggStatePerAggData;
+
+/*
+ * AggStatePerGroupData - per-aggregate-per-group working state
+ *
+ * These values are working state that is initialized at the start of
+ * an input tuple group and updated for each input tuple.
+ *
+ * In AGG_PLAIN and AGG_SORTED modes, we have a single array of these
+ * structs (pointed to by aggstate->pergroup); we re-use the array for
+ * each input group, if it's AGG_SORTED mode. In AGG_HASHED mode, the
+ * hash table contains an array of these structs for each tuple group.
+ *
+ * Logically, the sortstate field belongs in this struct, but we do not
+ * keep it here for space reasons: we don't support DISTINCT aggregates
+ * in AGG_HASHED mode, so there's no reason to use up a pointer field
+ * in every entry of the hashtable.
+ */
+typedef struct AggStatePerGroupData
+{
+#define FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE 0
+ Datum transValue; /* current transition value */
+#define FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL 1
+ bool transValueIsNull;
+
+#define FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE 2
+ bool noTransValue; /* true if transValue not set yet */
+
+ /*
+ * Note: noTransValue initially has the same value as transValueIsNull,
+ * and if true both are cleared to false at the same time. They are not
+ * the same though: if transfn later returns a NULL, we want to keep that
+ * NULL and not auto-replace it with a later input value. Only the first
+ * non-NULL input will be auto-substituted.
+ */
+} AggStatePerGroupData;
+
+/*
+ * AggStatePerPhaseData - per-grouping-set-phase state
+ *
+ * Grouping sets are divided into "phases", where a single phase can be
+ * processed in one pass over the input. If there is more than one phase, then
+ * at the end of input from the current phase, state is reset and another pass
+ * taken over the data which has been re-sorted in the mean time.
+ *
+ * Accordingly, each phase specifies a list of grouping sets and group clause
+ * information, plus each phase after the first also has a sort order.
+ */
+typedef struct AggStatePerPhaseData
+{
+ AggStrategy aggstrategy; /* strategy for this phase */
+ int numsets; /* number of grouping sets (or 0) */
+ int *gset_lengths; /* lengths of grouping sets */
+ Bitmapset **grouped_cols; /* column groupings for rollup */
+ ExprState **eqfunctions; /* expression returning equality, indexed by
+ * nr of cols to compare */
+ Agg *aggnode; /* Agg node for phase data */
+ Sort *sortnode; /* Sort node for input ordering for phase */
+
+ ExprState *evaltrans; /* evaluation of transition functions */
+
+ /*----------
+ * Cached variants of the compiled expression.
+ * first subscript: 0: outerops; 1: TTSOpsMinimalTuple
+ * second subscript: 0: no NULL check; 1: with NULL check
+ *----------
+ */
+ ExprState *evaltrans_cache[2][2];
+} AggStatePerPhaseData;
+
+/*
+ * AggStatePerHashData - per-hashtable state
+ *
+ * When doing grouping sets with hashing, we have one of these for each
+ * grouping set. (When doing hashing without grouping sets, we have just one of
+ * them.)
+ */
+typedef struct AggStatePerHashData
+{
+ TupleHashTable hashtable; /* hash table with one entry per group */
+ TupleHashIterator hashiter; /* for iterating through hash table */
+ TupleTableSlot *hashslot; /* slot for loading hash table */
+ FmgrInfo *hashfunctions; /* per-grouping-field hash fns */
+ Oid *eqfuncoids; /* per-grouping-field equality fns */
+ int numCols; /* number of hash key columns */
+ int numhashGrpCols; /* number of columns in hash table */
+ int largestGrpColIdx; /* largest col required for hashing */
+ AttrNumber *hashGrpColIdxInput; /* hash col indices in input slot */
+ AttrNumber *hashGrpColIdxHash; /* indices in hash table tuples */
+ Agg *aggnode; /* original Agg node, for numGroups etc. */
+} AggStatePerHashData;
+
+
+extern AggState *ExecInitAgg(Agg *node, EState *estate, int eflags);
+extern void ExecEndAgg(AggState *node);
+extern void ExecReScanAgg(AggState *node);
+
+extern Size hash_agg_entry_size(int numTrans, Size tupleWidth,
+ Size transitionSpace);
+extern void hash_agg_set_limits(double hashentrysize, double input_groups,
+ int used_bits, Size *mem_limit,
+ uint64 *ngroups_limit, int *num_partitions);
+
+/* parallel instrumentation support */
+extern void ExecAggEstimate(AggState *node, ParallelContext *pcxt);
+extern void ExecAggInitializeDSM(AggState *node, ParallelContext *pcxt);
+extern void ExecAggInitializeWorker(AggState *node, ParallelWorkerContext *pwcxt);
+extern void ExecAggRetrieveInstrumentation(AggState *node);
+
+#endif /* NODEAGG_H */
diff --git a/src/include/executor/nodeAppend.h b/src/include/executor/nodeAppend.h
new file mode 100644
index 0000000..be222eb
--- /dev/null
+++ b/src/include/executor/nodeAppend.h
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeAppend.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeAppend.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEAPPEND_H
+#define NODEAPPEND_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+extern AppendState *ExecInitAppend(Append *node, EState *estate, int eflags);
+extern void ExecEndAppend(AppendState *node);
+extern void ExecReScanAppend(AppendState *node);
+extern void ExecAppendEstimate(AppendState *node, ParallelContext *pcxt);
+extern void ExecAppendInitializeDSM(AppendState *node, ParallelContext *pcxt);
+extern void ExecAppendReInitializeDSM(AppendState *node, ParallelContext *pcxt);
+extern void ExecAppendInitializeWorker(AppendState *node, ParallelWorkerContext *pwcxt);
+
+#endif /* NODEAPPEND_H */
diff --git a/src/include/executor/nodeBitmapAnd.h b/src/include/executor/nodeBitmapAnd.h
new file mode 100644
index 0000000..2271bb7
--- /dev/null
+++ b/src/include/executor/nodeBitmapAnd.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeBitmapAnd.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeBitmapAnd.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEBITMAPAND_H
+#define NODEBITMAPAND_H
+
+#include "nodes/execnodes.h"
+
+extern BitmapAndState *ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags);
+extern Node *MultiExecBitmapAnd(BitmapAndState *node);
+extern void ExecEndBitmapAnd(BitmapAndState *node);
+extern void ExecReScanBitmapAnd(BitmapAndState *node);
+
+#endif /* NODEBITMAPAND_H */
diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h
new file mode 100644
index 0000000..10228af
--- /dev/null
+++ b/src/include/executor/nodeBitmapHeapscan.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeBitmapHeapscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeBitmapHeapscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEBITMAPHEAPSCAN_H
+#define NODEBITMAPHEAPSCAN_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+extern BitmapHeapScanState *ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags);
+extern void ExecEndBitmapHeapScan(BitmapHeapScanState *node);
+extern void ExecReScanBitmapHeapScan(BitmapHeapScanState *node);
+extern void ExecBitmapHeapEstimate(BitmapHeapScanState *node,
+ ParallelContext *pcxt);
+extern void ExecBitmapHeapInitializeDSM(BitmapHeapScanState *node,
+ ParallelContext *pcxt);
+extern void ExecBitmapHeapReInitializeDSM(BitmapHeapScanState *node,
+ ParallelContext *pcxt);
+extern void ExecBitmapHeapInitializeWorker(BitmapHeapScanState *node,
+ ParallelWorkerContext *pwcxt);
+
+#endif /* NODEBITMAPHEAPSCAN_H */
diff --git a/src/include/executor/nodeBitmapIndexscan.h b/src/include/executor/nodeBitmapIndexscan.h
new file mode 100644
index 0000000..42a24e6
--- /dev/null
+++ b/src/include/executor/nodeBitmapIndexscan.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeBitmapIndexscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeBitmapIndexscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEBITMAPINDEXSCAN_H
+#define NODEBITMAPINDEXSCAN_H
+
+#include "nodes/execnodes.h"
+
+extern BitmapIndexScanState *ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags);
+extern Node *MultiExecBitmapIndexScan(BitmapIndexScanState *node);
+extern void ExecEndBitmapIndexScan(BitmapIndexScanState *node);
+extern void ExecReScanBitmapIndexScan(BitmapIndexScanState *node);
+
+#endif /* NODEBITMAPINDEXSCAN_H */
diff --git a/src/include/executor/nodeBitmapOr.h b/src/include/executor/nodeBitmapOr.h
new file mode 100644
index 0000000..58a7b8c
--- /dev/null
+++ b/src/include/executor/nodeBitmapOr.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeBitmapOr.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeBitmapOr.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEBITMAPOR_H
+#define NODEBITMAPOR_H
+
+#include "nodes/execnodes.h"
+
+extern BitmapOrState *ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags);
+extern Node *MultiExecBitmapOr(BitmapOrState *node);
+extern void ExecEndBitmapOr(BitmapOrState *node);
+extern void ExecReScanBitmapOr(BitmapOrState *node);
+
+#endif /* NODEBITMAPOR_H */
diff --git a/src/include/executor/nodeCtescan.h b/src/include/executor/nodeCtescan.h
new file mode 100644
index 0000000..3e75552
--- /dev/null
+++ b/src/include/executor/nodeCtescan.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeCtescan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeCtescan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODECTESCAN_H
+#define NODECTESCAN_H
+
+#include "nodes/execnodes.h"
+
+extern CteScanState *ExecInitCteScan(CteScan *node, EState *estate, int eflags);
+extern void ExecEndCteScan(CteScanState *node);
+extern void ExecReScanCteScan(CteScanState *node);
+
+#endif /* NODECTESCAN_H */
diff --git a/src/include/executor/nodeCustom.h b/src/include/executor/nodeCustom.h
new file mode 100644
index 0000000..1d52875
--- /dev/null
+++ b/src/include/executor/nodeCustom.h
@@ -0,0 +1,42 @@
+/* ------------------------------------------------------------------------
+ *
+ * nodeCustom.h
+ *
+ * prototypes for CustomScan nodes
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * ------------------------------------------------------------------------
+ */
+#ifndef NODECUSTOM_H
+#define NODECUSTOM_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+/*
+ * General executor code
+ */
+extern CustomScanState *ExecInitCustomScan(CustomScan *cscan,
+ EState *estate, int eflags);
+extern void ExecEndCustomScan(CustomScanState *node);
+
+extern void ExecReScanCustomScan(CustomScanState *node);
+extern void ExecCustomMarkPos(CustomScanState *node);
+extern void ExecCustomRestrPos(CustomScanState *node);
+
+/*
+ * Parallel execution support
+ */
+extern void ExecCustomScanEstimate(CustomScanState *node,
+ ParallelContext *pcxt);
+extern void ExecCustomScanInitializeDSM(CustomScanState *node,
+ ParallelContext *pcxt);
+extern void ExecCustomScanReInitializeDSM(CustomScanState *node,
+ ParallelContext *pcxt);
+extern void ExecCustomScanInitializeWorker(CustomScanState *node,
+ ParallelWorkerContext *pwcxt);
+extern void ExecShutdownCustomScan(CustomScanState *node);
+
+#endif /* NODECUSTOM_H */
diff --git a/src/include/executor/nodeForeignscan.h b/src/include/executor/nodeForeignscan.h
new file mode 100644
index 0000000..326d713
--- /dev/null
+++ b/src/include/executor/nodeForeignscan.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeForeignscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeForeignscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEFOREIGNSCAN_H
+#define NODEFOREIGNSCAN_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+extern ForeignScanState *ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags);
+extern void ExecEndForeignScan(ForeignScanState *node);
+extern void ExecReScanForeignScan(ForeignScanState *node);
+
+extern void ExecForeignScanEstimate(ForeignScanState *node,
+ ParallelContext *pcxt);
+extern void ExecForeignScanInitializeDSM(ForeignScanState *node,
+ ParallelContext *pcxt);
+extern void ExecForeignScanReInitializeDSM(ForeignScanState *node,
+ ParallelContext *pcxt);
+extern void ExecForeignScanInitializeWorker(ForeignScanState *node,
+ ParallelWorkerContext *pwcxt);
+extern void ExecShutdownForeignScan(ForeignScanState *node);
+
+#endif /* NODEFOREIGNSCAN_H */
diff --git a/src/include/executor/nodeFunctionscan.h b/src/include/executor/nodeFunctionscan.h
new file mode 100644
index 0000000..74e8eef
--- /dev/null
+++ b/src/include/executor/nodeFunctionscan.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeFunctionscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeFunctionscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEFUNCTIONSCAN_H
+#define NODEFUNCTIONSCAN_H
+
+#include "nodes/execnodes.h"
+
+extern FunctionScanState *ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags);
+extern void ExecEndFunctionScan(FunctionScanState *node);
+extern void ExecReScanFunctionScan(FunctionScanState *node);
+
+#endif /* NODEFUNCTIONSCAN_H */
diff --git a/src/include/executor/nodeGather.h b/src/include/executor/nodeGather.h
new file mode 100644
index 0000000..105248b
--- /dev/null
+++ b/src/include/executor/nodeGather.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeGather.h
+ * prototypes for nodeGather.c
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeGather.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEGATHER_H
+#define NODEGATHER_H
+
+#include "nodes/execnodes.h"
+
+extern GatherState *ExecInitGather(Gather *node, EState *estate, int eflags);
+extern void ExecEndGather(GatherState *node);
+extern void ExecShutdownGather(GatherState *node);
+extern void ExecReScanGather(GatherState *node);
+
+#endif /* NODEGATHER_H */
diff --git a/src/include/executor/nodeGatherMerge.h b/src/include/executor/nodeGatherMerge.h
new file mode 100644
index 0000000..a8f960b
--- /dev/null
+++ b/src/include/executor/nodeGatherMerge.h
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeGatherMerge.h
+ * prototypes for nodeGatherMerge.c
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeGatherMerge.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEGATHERMERGE_H
+#define NODEGATHERMERGE_H
+
+#include "nodes/execnodes.h"
+
+extern GatherMergeState *ExecInitGatherMerge(GatherMerge *node,
+ EState *estate,
+ int eflags);
+extern void ExecEndGatherMerge(GatherMergeState *node);
+extern void ExecReScanGatherMerge(GatherMergeState *node);
+extern void ExecShutdownGatherMerge(GatherMergeState *node);
+
+#endif /* NODEGATHERMERGE_H */
diff --git a/src/include/executor/nodeGroup.h b/src/include/executor/nodeGroup.h
new file mode 100644
index 0000000..2965c74
--- /dev/null
+++ b/src/include/executor/nodeGroup.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeGroup.h
+ * prototypes for nodeGroup.c
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeGroup.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEGROUP_H
+#define NODEGROUP_H
+
+#include "nodes/execnodes.h"
+
+extern GroupState *ExecInitGroup(Group *node, EState *estate, int eflags);
+extern void ExecEndGroup(GroupState *node);
+extern void ExecReScanGroup(GroupState *node);
+
+#endif /* NODEGROUP_H */
diff --git a/src/include/executor/nodeHash.h b/src/include/executor/nodeHash.h
new file mode 100644
index 0000000..2db4e2f
--- /dev/null
+++ b/src/include/executor/nodeHash.h
@@ -0,0 +1,79 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeHash.h
+ * prototypes for nodeHash.c
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeHash.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEHASH_H
+#define NODEHASH_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+struct SharedHashJoinBatch;
+
+extern HashState *ExecInitHash(Hash *node, EState *estate, int eflags);
+extern Node *MultiExecHash(HashState *node);
+extern void ExecEndHash(HashState *node);
+extern void ExecReScanHash(HashState *node);
+
+extern HashJoinTable ExecHashTableCreate(HashState *state, List *hashOperators, List *hashCollations,
+ bool keepNulls);
+extern void ExecParallelHashTableAlloc(HashJoinTable hashtable,
+ int batchno);
+extern void ExecHashTableDestroy(HashJoinTable hashtable);
+extern void ExecHashTableDetach(HashJoinTable hashtable);
+extern void ExecHashTableDetachBatch(HashJoinTable hashtable);
+extern void ExecParallelHashTableSetCurrentBatch(HashJoinTable hashtable,
+ int batchno);
+
+extern void ExecHashTableInsert(HashJoinTable hashtable,
+ TupleTableSlot *slot,
+ uint32 hashvalue);
+extern void ExecParallelHashTableInsert(HashJoinTable hashtable,
+ TupleTableSlot *slot,
+ uint32 hashvalue);
+extern void ExecParallelHashTableInsertCurrentBatch(HashJoinTable hashtable,
+ TupleTableSlot *slot,
+ uint32 hashvalue);
+extern bool ExecHashGetHashValue(HashJoinTable hashtable,
+ ExprContext *econtext,
+ List *hashkeys,
+ bool outer_tuple,
+ bool keep_nulls,
+ uint32 *hashvalue);
+extern void ExecHashGetBucketAndBatch(HashJoinTable hashtable,
+ uint32 hashvalue,
+ int *bucketno,
+ int *batchno);
+extern bool ExecScanHashBucket(HashJoinState *hjstate, ExprContext *econtext);
+extern bool ExecParallelScanHashBucket(HashJoinState *hjstate, ExprContext *econtext);
+extern void ExecPrepHashTableForUnmatched(HashJoinState *hjstate);
+extern bool ExecScanHashTableForUnmatched(HashJoinState *hjstate,
+ ExprContext *econtext);
+extern void ExecHashTableReset(HashJoinTable hashtable);
+extern void ExecHashTableResetMatchFlags(HashJoinTable hashtable);
+extern void ExecChooseHashTableSize(double ntuples, int tupwidth, bool useskew,
+ bool try_combined_hash_mem,
+ int parallel_workers,
+ size_t *space_allowed,
+ int *numbuckets,
+ int *numbatches,
+ int *num_skew_mcvs);
+extern int ExecHashGetSkewBucket(HashJoinTable hashtable, uint32 hashvalue);
+extern void ExecHashEstimate(HashState *node, ParallelContext *pcxt);
+extern void ExecHashInitializeDSM(HashState *node, ParallelContext *pcxt);
+extern void ExecHashInitializeWorker(HashState *node, ParallelWorkerContext *pwcxt);
+extern void ExecHashRetrieveInstrumentation(HashState *node);
+extern void ExecShutdownHash(HashState *node);
+extern void ExecHashAccumInstrumentation(HashInstrumentation *instrument,
+ HashJoinTable hashtable);
+
+#endif /* NODEHASH_H */
diff --git a/src/include/executor/nodeHashjoin.h b/src/include/executor/nodeHashjoin.h
new file mode 100644
index 0000000..dc67162
--- /dev/null
+++ b/src/include/executor/nodeHashjoin.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeHashjoin.h
+ * prototypes for nodeHashjoin.c
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeHashjoin.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEHASHJOIN_H
+#define NODEHASHJOIN_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+#include "storage/buffile.h"
+
+extern HashJoinState *ExecInitHashJoin(HashJoin *node, EState *estate, int eflags);
+extern void ExecEndHashJoin(HashJoinState *node);
+extern void ExecReScanHashJoin(HashJoinState *node);
+extern void ExecShutdownHashJoin(HashJoinState *node);
+extern void ExecHashJoinEstimate(HashJoinState *state, ParallelContext *pcxt);
+extern void ExecHashJoinInitializeDSM(HashJoinState *state, ParallelContext *pcxt);
+extern void ExecHashJoinReInitializeDSM(HashJoinState *state, ParallelContext *pcxt);
+extern void ExecHashJoinInitializeWorker(HashJoinState *state,
+ ParallelWorkerContext *pwcxt);
+
+extern void ExecHashJoinSaveTuple(MinimalTuple tuple, uint32 hashvalue,
+ BufFile **fileptr);
+
+#endif /* NODEHASHJOIN_H */
diff --git a/src/include/executor/nodeIncrementalSort.h b/src/include/executor/nodeIncrementalSort.h
new file mode 100644
index 0000000..e62c02a
--- /dev/null
+++ b/src/include/executor/nodeIncrementalSort.h
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeIncrementalSort.h
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeIncrementalSort.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEINCREMENTALSORT_H
+#define NODEINCREMENTALSORT_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+extern IncrementalSortState *ExecInitIncrementalSort(IncrementalSort *node, EState *estate, int eflags);
+extern void ExecEndIncrementalSort(IncrementalSortState *node);
+extern void ExecReScanIncrementalSort(IncrementalSortState *node);
+
+/* parallel instrumentation support */
+extern void ExecIncrementalSortEstimate(IncrementalSortState *node, ParallelContext *pcxt);
+extern void ExecIncrementalSortInitializeDSM(IncrementalSortState *node, ParallelContext *pcxt);
+extern void ExecIncrementalSortInitializeWorker(IncrementalSortState *node, ParallelWorkerContext *pcxt);
+extern void ExecIncrementalSortRetrieveInstrumentation(IncrementalSortState *node);
+
+#endif /* NODEINCREMENTALSORT_H */
diff --git a/src/include/executor/nodeIndexonlyscan.h b/src/include/executor/nodeIndexonlyscan.h
new file mode 100644
index 0000000..9f1d26f
--- /dev/null
+++ b/src/include/executor/nodeIndexonlyscan.h
@@ -0,0 +1,36 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeIndexonlyscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeIndexonlyscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEINDEXONLYSCAN_H
+#define NODEINDEXONLYSCAN_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+extern IndexOnlyScanState *ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags);
+extern void ExecEndIndexOnlyScan(IndexOnlyScanState *node);
+extern void ExecIndexOnlyMarkPos(IndexOnlyScanState *node);
+extern void ExecIndexOnlyRestrPos(IndexOnlyScanState *node);
+extern void ExecReScanIndexOnlyScan(IndexOnlyScanState *node);
+
+/* Support functions for parallel index-only scans */
+extern void ExecIndexOnlyScanEstimate(IndexOnlyScanState *node,
+ ParallelContext *pcxt);
+extern void ExecIndexOnlyScanInitializeDSM(IndexOnlyScanState *node,
+ ParallelContext *pcxt);
+extern void ExecIndexOnlyScanReInitializeDSM(IndexOnlyScanState *node,
+ ParallelContext *pcxt);
+extern void ExecIndexOnlyScanInitializeWorker(IndexOnlyScanState *node,
+ ParallelWorkerContext *pwcxt);
+
+#endif /* NODEINDEXONLYSCAN_H */
diff --git a/src/include/executor/nodeIndexscan.h b/src/include/executor/nodeIndexscan.h
new file mode 100644
index 0000000..1b6b318
--- /dev/null
+++ b/src/include/executor/nodeIndexscan.h
@@ -0,0 +1,47 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeIndexscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeIndexscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEINDEXSCAN_H
+#define NODEINDEXSCAN_H
+
+#include "access/genam.h"
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+extern IndexScanState *ExecInitIndexScan(IndexScan *node, EState *estate, int eflags);
+extern void ExecEndIndexScan(IndexScanState *node);
+extern void ExecIndexMarkPos(IndexScanState *node);
+extern void ExecIndexRestrPos(IndexScanState *node);
+extern void ExecReScanIndexScan(IndexScanState *node);
+extern void ExecIndexScanEstimate(IndexScanState *node, ParallelContext *pcxt);
+extern void ExecIndexScanInitializeDSM(IndexScanState *node, ParallelContext *pcxt);
+extern void ExecIndexScanReInitializeDSM(IndexScanState *node, ParallelContext *pcxt);
+extern void ExecIndexScanInitializeWorker(IndexScanState *node,
+ ParallelWorkerContext *pwcxt);
+
+/*
+ * These routines are exported to share code with nodeIndexonlyscan.c and
+ * nodeBitmapIndexscan.c
+ */
+extern void ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
+ List *quals, bool isorderby,
+ ScanKey *scanKeys, int *numScanKeys,
+ IndexRuntimeKeyInfo **runtimeKeys, int *numRuntimeKeys,
+ IndexArrayKeyInfo **arrayKeys, int *numArrayKeys);
+extern void ExecIndexEvalRuntimeKeys(ExprContext *econtext,
+ IndexRuntimeKeyInfo *runtimeKeys, int numRuntimeKeys);
+extern bool ExecIndexEvalArrayKeys(ExprContext *econtext,
+ IndexArrayKeyInfo *arrayKeys, int numArrayKeys);
+extern bool ExecIndexAdvanceArrayKeys(IndexArrayKeyInfo *arrayKeys, int numArrayKeys);
+
+#endif /* NODEINDEXSCAN_H */
diff --git a/src/include/executor/nodeLimit.h b/src/include/executor/nodeLimit.h
new file mode 100644
index 0000000..cbcb941
--- /dev/null
+++ b/src/include/executor/nodeLimit.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeLimit.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeLimit.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODELIMIT_H
+#define NODELIMIT_H
+
+#include "nodes/execnodes.h"
+
+extern LimitState *ExecInitLimit(Limit *node, EState *estate, int eflags);
+extern void ExecEndLimit(LimitState *node);
+extern void ExecReScanLimit(LimitState *node);
+
+#endif /* NODELIMIT_H */
diff --git a/src/include/executor/nodeLockRows.h b/src/include/executor/nodeLockRows.h
new file mode 100644
index 0000000..85d0e17
--- /dev/null
+++ b/src/include/executor/nodeLockRows.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeLockRows.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeLockRows.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODELOCKROWS_H
+#define NODELOCKROWS_H
+
+#include "nodes/execnodes.h"
+
+extern LockRowsState *ExecInitLockRows(LockRows *node, EState *estate, int eflags);
+extern void ExecEndLockRows(LockRowsState *node);
+extern void ExecReScanLockRows(LockRowsState *node);
+
+#endif /* NODELOCKROWS_H */
diff --git a/src/include/executor/nodeMaterial.h b/src/include/executor/nodeMaterial.h
new file mode 100644
index 0000000..99e7cbf
--- /dev/null
+++ b/src/include/executor/nodeMaterial.h
@@ -0,0 +1,25 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeMaterial.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeMaterial.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEMATERIAL_H
+#define NODEMATERIAL_H
+
+#include "nodes/execnodes.h"
+
+extern MaterialState *ExecInitMaterial(Material *node, EState *estate, int eflags);
+extern void ExecEndMaterial(MaterialState *node);
+extern void ExecMaterialMarkPos(MaterialState *node);
+extern void ExecMaterialRestrPos(MaterialState *node);
+extern void ExecReScanMaterial(MaterialState *node);
+
+#endif /* NODEMATERIAL_H */
diff --git a/src/include/executor/nodeMergeAppend.h b/src/include/executor/nodeMergeAppend.h
new file mode 100644
index 0000000..2c86189
--- /dev/null
+++ b/src/include/executor/nodeMergeAppend.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeMergeAppend.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeMergeAppend.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEMERGEAPPEND_H
+#define NODEMERGEAPPEND_H
+
+#include "nodes/execnodes.h"
+
+extern MergeAppendState *ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags);
+extern void ExecEndMergeAppend(MergeAppendState *node);
+extern void ExecReScanMergeAppend(MergeAppendState *node);
+
+#endif /* NODEMERGEAPPEND_H */
diff --git a/src/include/executor/nodeMergejoin.h b/src/include/executor/nodeMergejoin.h
new file mode 100644
index 0000000..ae8105a
--- /dev/null
+++ b/src/include/executor/nodeMergejoin.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeMergejoin.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeMergejoin.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEMERGEJOIN_H
+#define NODEMERGEJOIN_H
+
+#include "nodes/execnodes.h"
+
+extern MergeJoinState *ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags);
+extern void ExecEndMergeJoin(MergeJoinState *node);
+extern void ExecReScanMergeJoin(MergeJoinState *node);
+
+#endif /* NODEMERGEJOIN_H */
diff --git a/src/include/executor/nodeModifyTable.h b/src/include/executor/nodeModifyTable.h
new file mode 100644
index 0000000..4ec4ebd
--- /dev/null
+++ b/src/include/executor/nodeModifyTable.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeModifyTable.h
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeModifyTable.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEMODIFYTABLE_H
+#define NODEMODIFYTABLE_H
+
+#include "nodes/execnodes.h"
+
+extern void ExecComputeStoredGenerated(EState *estate, TupleTableSlot *slot, CmdType cmdtype);
+
+extern ModifyTableState *ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags);
+extern void ExecEndModifyTable(ModifyTableState *node);
+extern void ExecReScanModifyTable(ModifyTableState *node);
+
+#endif /* NODEMODIFYTABLE_H */
diff --git a/src/include/executor/nodeNamedtuplestorescan.h b/src/include/executor/nodeNamedtuplestorescan.h
new file mode 100644
index 0000000..6fcf08e
--- /dev/null
+++ b/src/include/executor/nodeNamedtuplestorescan.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeNamedtuplestorescan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeNamedtuplestorescan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODENAMEDTUPLESTORESCAN_H
+#define NODENAMEDTUPLESTORESCAN_H
+
+#include "nodes/execnodes.h"
+
+extern NamedTuplestoreScanState *ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflags);
+extern void ExecEndNamedTuplestoreScan(NamedTuplestoreScanState *node);
+extern void ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState *node);
+
+#endif /* NODENAMEDTUPLESTORESCAN_H */
diff --git a/src/include/executor/nodeNestloop.h b/src/include/executor/nodeNestloop.h
new file mode 100644
index 0000000..5a048a7
--- /dev/null
+++ b/src/include/executor/nodeNestloop.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeNestloop.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeNestloop.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODENESTLOOP_H
+#define NODENESTLOOP_H
+
+#include "nodes/execnodes.h"
+
+extern NestLoopState *ExecInitNestLoop(NestLoop *node, EState *estate, int eflags);
+extern void ExecEndNestLoop(NestLoopState *node);
+extern void ExecReScanNestLoop(NestLoopState *node);
+
+#endif /* NODENESTLOOP_H */
diff --git a/src/include/executor/nodeProjectSet.h b/src/include/executor/nodeProjectSet.h
new file mode 100644
index 0000000..76e433f
--- /dev/null
+++ b/src/include/executor/nodeProjectSet.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeProjectSet.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeProjectSet.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEPROJECTSET_H
+#define NODEPROJECTSET_H
+
+#include "nodes/execnodes.h"
+
+extern ProjectSetState *ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags);
+extern void ExecEndProjectSet(ProjectSetState *node);
+extern void ExecReScanProjectSet(ProjectSetState *node);
+
+#endif /* NODEPROJECTSET_H */
diff --git a/src/include/executor/nodeRecursiveunion.h b/src/include/executor/nodeRecursiveunion.h
new file mode 100644
index 0000000..c7253ce
--- /dev/null
+++ b/src/include/executor/nodeRecursiveunion.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeRecursiveunion.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeRecursiveunion.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODERECURSIVEUNION_H
+#define NODERECURSIVEUNION_H
+
+#include "nodes/execnodes.h"
+
+extern RecursiveUnionState *ExecInitRecursiveUnion(RecursiveUnion *node, EState *estate, int eflags);
+extern void ExecEndRecursiveUnion(RecursiveUnionState *node);
+extern void ExecReScanRecursiveUnion(RecursiveUnionState *node);
+
+#endif /* NODERECURSIVEUNION_H */
diff --git a/src/include/executor/nodeResult.h b/src/include/executor/nodeResult.h
new file mode 100644
index 0000000..b861672
--- /dev/null
+++ b/src/include/executor/nodeResult.h
@@ -0,0 +1,25 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeResult.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeResult.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODERESULT_H
+#define NODERESULT_H
+
+#include "nodes/execnodes.h"
+
+extern ResultState *ExecInitResult(Result *node, EState *estate, int eflags);
+extern void ExecEndResult(ResultState *node);
+extern void ExecResultMarkPos(ResultState *node);
+extern void ExecResultRestrPos(ResultState *node);
+extern void ExecReScanResult(ResultState *node);
+
+#endif /* NODERESULT_H */
diff --git a/src/include/executor/nodeSamplescan.h b/src/include/executor/nodeSamplescan.h
new file mode 100644
index 0000000..c24fca5
--- /dev/null
+++ b/src/include/executor/nodeSamplescan.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeSamplescan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeSamplescan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODESAMPLESCAN_H
+#define NODESAMPLESCAN_H
+
+#include "nodes/execnodes.h"
+
+extern SampleScanState *ExecInitSampleScan(SampleScan *node, EState *estate, int eflags);
+extern void ExecEndSampleScan(SampleScanState *node);
+extern void ExecReScanSampleScan(SampleScanState *node);
+
+#endif /* NODESAMPLESCAN_H */
diff --git a/src/include/executor/nodeSeqscan.h b/src/include/executor/nodeSeqscan.h
new file mode 100644
index 0000000..2ef48ce
--- /dev/null
+++ b/src/include/executor/nodeSeqscan.h
@@ -0,0 +1,31 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeSeqscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeSeqscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODESEQSCAN_H
+#define NODESEQSCAN_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+extern SeqScanState *ExecInitSeqScan(SeqScan *node, EState *estate, int eflags);
+extern void ExecEndSeqScan(SeqScanState *node);
+extern void ExecReScanSeqScan(SeqScanState *node);
+
+/* parallel scan support */
+extern void ExecSeqScanEstimate(SeqScanState *node, ParallelContext *pcxt);
+extern void ExecSeqScanInitializeDSM(SeqScanState *node, ParallelContext *pcxt);
+extern void ExecSeqScanReInitializeDSM(SeqScanState *node, ParallelContext *pcxt);
+extern void ExecSeqScanInitializeWorker(SeqScanState *node,
+ ParallelWorkerContext *pwcxt);
+
+#endif /* NODESEQSCAN_H */
diff --git a/src/include/executor/nodeSetOp.h b/src/include/executor/nodeSetOp.h
new file mode 100644
index 0000000..a3577b3
--- /dev/null
+++ b/src/include/executor/nodeSetOp.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeSetOp.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeSetOp.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODESETOP_H
+#define NODESETOP_H
+
+#include "nodes/execnodes.h"
+
+extern SetOpState *ExecInitSetOp(SetOp *node, EState *estate, int eflags);
+extern void ExecEndSetOp(SetOpState *node);
+extern void ExecReScanSetOp(SetOpState *node);
+
+#endif /* NODESETOP_H */
diff --git a/src/include/executor/nodeSort.h b/src/include/executor/nodeSort.h
new file mode 100644
index 0000000..0925556
--- /dev/null
+++ b/src/include/executor/nodeSort.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeSort.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeSort.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODESORT_H
+#define NODESORT_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+
+extern SortState *ExecInitSort(Sort *node, EState *estate, int eflags);
+extern void ExecEndSort(SortState *node);
+extern void ExecSortMarkPos(SortState *node);
+extern void ExecSortRestrPos(SortState *node);
+extern void ExecReScanSort(SortState *node);
+
+/* parallel instrumentation support */
+extern void ExecSortEstimate(SortState *node, ParallelContext *pcxt);
+extern void ExecSortInitializeDSM(SortState *node, ParallelContext *pcxt);
+extern void ExecSortInitializeWorker(SortState *node, ParallelWorkerContext *pwcxt);
+extern void ExecSortRetrieveInstrumentation(SortState *node);
+
+#endif /* NODESORT_H */
diff --git a/src/include/executor/nodeSubplan.h b/src/include/executor/nodeSubplan.h
new file mode 100644
index 0000000..83e90b3
--- /dev/null
+++ b/src/include/executor/nodeSubplan.h
@@ -0,0 +1,33 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeSubplan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeSubplan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODESUBPLAN_H
+#define NODESUBPLAN_H
+
+#include "nodes/execnodes.h"
+
+extern SubPlanState *ExecInitSubPlan(SubPlan *subplan, PlanState *parent);
+
+extern AlternativeSubPlanState *ExecInitAlternativeSubPlan(AlternativeSubPlan *asplan, PlanState *parent);
+
+extern Datum ExecSubPlan(SubPlanState *node, ExprContext *econtext, bool *isNull);
+
+extern Datum ExecAlternativeSubPlan(AlternativeSubPlanState *node, ExprContext *econtext, bool *isNull);
+
+extern void ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent);
+
+extern void ExecSetParamPlan(SubPlanState *node, ExprContext *econtext);
+
+extern void ExecSetParamPlanMulti(const Bitmapset *params, ExprContext *econtext);
+
+#endif /* NODESUBPLAN_H */
diff --git a/src/include/executor/nodeSubqueryscan.h b/src/include/executor/nodeSubqueryscan.h
new file mode 100644
index 0000000..5e237b0
--- /dev/null
+++ b/src/include/executor/nodeSubqueryscan.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeSubqueryscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeSubqueryscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODESUBQUERYSCAN_H
+#define NODESUBQUERYSCAN_H
+
+#include "nodes/execnodes.h"
+
+extern SubqueryScanState *ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags);
+extern void ExecEndSubqueryScan(SubqueryScanState *node);
+extern void ExecReScanSubqueryScan(SubqueryScanState *node);
+
+#endif /* NODESUBQUERYSCAN_H */
diff --git a/src/include/executor/nodeTableFuncscan.h b/src/include/executor/nodeTableFuncscan.h
new file mode 100644
index 0000000..644babc
--- /dev/null
+++ b/src/include/executor/nodeTableFuncscan.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeTableFuncscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeTableFuncscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODETABLEFUNCSCAN_H
+#define NODETABLEFUNCSCAN_H
+
+#include "nodes/execnodes.h"
+
+extern TableFuncScanState *ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags);
+extern void ExecEndTableFuncScan(TableFuncScanState *node);
+extern void ExecReScanTableFuncScan(TableFuncScanState *node);
+
+#endif /* NODETABLEFUNCSCAN_H */
diff --git a/src/include/executor/nodeTidscan.h b/src/include/executor/nodeTidscan.h
new file mode 100644
index 0000000..92a818d
--- /dev/null
+++ b/src/include/executor/nodeTidscan.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeTidscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeTidscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODETIDSCAN_H
+#define NODETIDSCAN_H
+
+#include "nodes/execnodes.h"
+
+extern TidScanState *ExecInitTidScan(TidScan *node, EState *estate, int eflags);
+extern void ExecEndTidScan(TidScanState *node);
+extern void ExecReScanTidScan(TidScanState *node);
+
+#endif /* NODETIDSCAN_H */
diff --git a/src/include/executor/nodeUnique.h b/src/include/executor/nodeUnique.h
new file mode 100644
index 0000000..bc653fd
--- /dev/null
+++ b/src/include/executor/nodeUnique.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeUnique.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeUnique.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEUNIQUE_H
+#define NODEUNIQUE_H
+
+#include "nodes/execnodes.h"
+
+extern UniqueState *ExecInitUnique(Unique *node, EState *estate, int eflags);
+extern void ExecEndUnique(UniqueState *node);
+extern void ExecReScanUnique(UniqueState *node);
+
+#endif /* NODEUNIQUE_H */
diff --git a/src/include/executor/nodeValuesscan.h b/src/include/executor/nodeValuesscan.h
new file mode 100644
index 0000000..5f2a1d5
--- /dev/null
+++ b/src/include/executor/nodeValuesscan.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeValuesscan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeValuesscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEVALUESSCAN_H
+#define NODEVALUESSCAN_H
+
+#include "nodes/execnodes.h"
+
+extern ValuesScanState *ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags);
+extern void ExecEndValuesScan(ValuesScanState *node);
+extern void ExecReScanValuesScan(ValuesScanState *node);
+
+#endif /* NODEVALUESSCAN_H */
diff --git a/src/include/executor/nodeWindowAgg.h b/src/include/executor/nodeWindowAgg.h
new file mode 100644
index 0000000..4c53eb0
--- /dev/null
+++ b/src/include/executor/nodeWindowAgg.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeWindowAgg.h
+ * prototypes for nodeWindowAgg.c
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeWindowAgg.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEWINDOWAGG_H
+#define NODEWINDOWAGG_H
+
+#include "nodes/execnodes.h"
+
+extern WindowAggState *ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags);
+extern void ExecEndWindowAgg(WindowAggState *node);
+extern void ExecReScanWindowAgg(WindowAggState *node);
+
+#endif /* NODEWINDOWAGG_H */
diff --git a/src/include/executor/nodeWorktablescan.h b/src/include/executor/nodeWorktablescan.h
new file mode 100644
index 0000000..09ecc49
--- /dev/null
+++ b/src/include/executor/nodeWorktablescan.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeWorktablescan.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/nodeWorktablescan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEWORKTABLESCAN_H
+#define NODEWORKTABLESCAN_H
+
+#include "nodes/execnodes.h"
+
+extern WorkTableScanState *ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags);
+extern void ExecEndWorkTableScan(WorkTableScanState *node);
+extern void ExecReScanWorkTableScan(WorkTableScanState *node);
+
+#endif /* NODEWORKTABLESCAN_H */
diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h
new file mode 100644
index 0000000..06de20a
--- /dev/null
+++ b/src/include/executor/spi.h
@@ -0,0 +1,175 @@
+/*-------------------------------------------------------------------------
+ *
+ * spi.h
+ * Server Programming Interface public declarations
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/spi.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SPI_H
+#define SPI_H
+
+#include "commands/trigger.h"
+#include "lib/ilist.h"
+#include "nodes/parsenodes.h"
+#include "utils/portal.h"
+
+
+typedef struct SPITupleTable
+{
+ /* Public members */
+ TupleDesc tupdesc; /* tuple descriptor */
+ HeapTuple *vals; /* array of tuples */
+ uint64 numvals; /* number of valid tuples */
+
+ /* Private members, not intended for external callers */
+ uint64 alloced; /* allocated length of vals array */
+ MemoryContext tuptabcxt; /* memory context of result table */
+ slist_node next; /* link for internal bookkeeping */
+ SubTransactionId subid; /* subxact in which tuptable was created */
+} SPITupleTable;
+
+/* Plans are opaque structs for standard users of SPI */
+typedef struct _SPI_plan *SPIPlanPtr;
+
+#define SPI_ERROR_CONNECT (-1)
+#define SPI_ERROR_COPY (-2)
+#define SPI_ERROR_OPUNKNOWN (-3)
+#define SPI_ERROR_UNCONNECTED (-4)
+#define SPI_ERROR_CURSOR (-5) /* not used anymore */
+#define SPI_ERROR_ARGUMENT (-6)
+#define SPI_ERROR_PARAM (-7)
+#define SPI_ERROR_TRANSACTION (-8)
+#define SPI_ERROR_NOATTRIBUTE (-9)
+#define SPI_ERROR_NOOUTFUNC (-10)
+#define SPI_ERROR_TYPUNKNOWN (-11)
+#define SPI_ERROR_REL_DUPLICATE (-12)
+#define SPI_ERROR_REL_NOT_FOUND (-13)
+
+#define SPI_OK_CONNECT 1
+#define SPI_OK_FINISH 2
+#define SPI_OK_FETCH 3
+#define SPI_OK_UTILITY 4
+#define SPI_OK_SELECT 5
+#define SPI_OK_SELINTO 6
+#define SPI_OK_INSERT 7
+#define SPI_OK_DELETE 8
+#define SPI_OK_UPDATE 9
+#define SPI_OK_CURSOR 10
+#define SPI_OK_INSERT_RETURNING 11
+#define SPI_OK_DELETE_RETURNING 12
+#define SPI_OK_UPDATE_RETURNING 13
+#define SPI_OK_REWRITTEN 14
+#define SPI_OK_REL_REGISTER 15
+#define SPI_OK_REL_UNREGISTER 16
+#define SPI_OK_TD_REGISTER 17
+
+#define SPI_OPT_NONATOMIC (1 << 0)
+
+/* These used to be functions, now just no-ops for backwards compatibility */
+#define SPI_push() ((void) 0)
+#define SPI_pop() ((void) 0)
+#define SPI_push_conditional() false
+#define SPI_pop_conditional(pushed) ((void) 0)
+#define SPI_restore_connection() ((void) 0)
+
+extern PGDLLIMPORT uint64 SPI_processed;
+extern PGDLLIMPORT SPITupleTable *SPI_tuptable;
+extern PGDLLIMPORT int SPI_result;
+
+extern int SPI_connect(void);
+extern int SPI_connect_ext(int options);
+extern int SPI_finish(void);
+extern int SPI_execute(const char *src, bool read_only, long tcount);
+extern int SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls,
+ bool read_only, long tcount);
+extern int SPI_execute_plan_with_paramlist(SPIPlanPtr plan,
+ ParamListInfo params,
+ bool read_only, long tcount);
+extern int SPI_exec(const char *src, long tcount);
+extern int SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls,
+ long tcount);
+extern int SPI_execute_snapshot(SPIPlanPtr plan,
+ Datum *Values, const char *Nulls,
+ Snapshot snapshot,
+ Snapshot crosscheck_snapshot,
+ bool read_only, bool fire_triggers, long tcount);
+extern int SPI_execute_with_args(const char *src,
+ int nargs, Oid *argtypes,
+ Datum *Values, const char *Nulls,
+ bool read_only, long tcount);
+extern SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes);
+extern SPIPlanPtr SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes,
+ int cursorOptions);
+extern SPIPlanPtr SPI_prepare_params(const char *src,
+ ParserSetupHook parserSetup,
+ void *parserSetupArg,
+ int cursorOptions);
+extern int SPI_keepplan(SPIPlanPtr plan);
+extern SPIPlanPtr SPI_saveplan(SPIPlanPtr plan);
+extern int SPI_freeplan(SPIPlanPtr plan);
+
+extern Oid SPI_getargtypeid(SPIPlanPtr plan, int argIndex);
+extern int SPI_getargcount(SPIPlanPtr plan);
+extern bool SPI_is_cursor_plan(SPIPlanPtr plan);
+extern bool SPI_plan_is_valid(SPIPlanPtr plan);
+extern const char *SPI_result_code_string(int code);
+
+extern List *SPI_plan_get_plan_sources(SPIPlanPtr plan);
+extern CachedPlan *SPI_plan_get_cached_plan(SPIPlanPtr plan);
+
+extern HeapTuple SPI_copytuple(HeapTuple tuple);
+extern HeapTupleHeader SPI_returntuple(HeapTuple tuple, TupleDesc tupdesc);
+extern HeapTuple SPI_modifytuple(Relation rel, HeapTuple tuple, int natts,
+ int *attnum, Datum *Values, const char *Nulls);
+extern int SPI_fnumber(TupleDesc tupdesc, const char *fname);
+extern char *SPI_fname(TupleDesc tupdesc, int fnumber);
+extern char *SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber);
+extern Datum SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull);
+extern char *SPI_gettype(TupleDesc tupdesc, int fnumber);
+extern Oid SPI_gettypeid(TupleDesc tupdesc, int fnumber);
+extern char *SPI_getrelname(Relation rel);
+extern char *SPI_getnspname(Relation rel);
+extern void *SPI_palloc(Size size);
+extern void *SPI_repalloc(void *pointer, Size size);
+extern void SPI_pfree(void *pointer);
+extern Datum SPI_datumTransfer(Datum value, bool typByVal, int typLen);
+extern void SPI_freetuple(HeapTuple pointer);
+extern void SPI_freetuptable(SPITupleTable *tuptable);
+
+extern Portal SPI_cursor_open(const char *name, SPIPlanPtr plan,
+ Datum *Values, const char *Nulls, bool read_only);
+extern Portal SPI_cursor_open_with_args(const char *name,
+ const char *src,
+ int nargs, Oid *argtypes,
+ Datum *Values, const char *Nulls,
+ bool read_only, int cursorOptions);
+extern Portal SPI_cursor_open_with_paramlist(const char *name, SPIPlanPtr plan,
+ ParamListInfo params, bool read_only);
+extern Portal SPI_cursor_find(const char *name);
+extern void SPI_cursor_fetch(Portal portal, bool forward, long count);
+extern void SPI_cursor_move(Portal portal, bool forward, long count);
+extern void SPI_scroll_cursor_fetch(Portal, FetchDirection direction, long count);
+extern void SPI_scroll_cursor_move(Portal, FetchDirection direction, long count);
+extern void SPI_cursor_close(Portal portal);
+
+extern int SPI_register_relation(EphemeralNamedRelation enr);
+extern int SPI_unregister_relation(const char *name);
+extern int SPI_register_trigger_data(TriggerData *tdata);
+
+extern void SPI_start_transaction(void);
+extern void SPI_commit(void);
+extern void SPI_commit_and_chain(void);
+extern void SPI_rollback(void);
+extern void SPI_rollback_and_chain(void);
+
+extern void SPICleanup(void);
+extern void AtEOXact_SPI(bool isCommit);
+extern void AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid);
+extern bool SPI_inside_nonatomic_context(void);
+
+#endif /* SPI_H */
diff --git a/src/include/executor/spi_priv.h b/src/include/executor/spi_priv.h
new file mode 100644
index 0000000..5e6575d
--- /dev/null
+++ b/src/include/executor/spi_priv.h
@@ -0,0 +1,105 @@
+/*-------------------------------------------------------------------------
+ *
+ * spi_priv.h
+ * Server Programming Interface private declarations
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/spi_priv.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SPI_PRIV_H
+#define SPI_PRIV_H
+
+#include "executor/spi.h"
+#include "utils/queryenvironment.h"
+
+
+#define _SPI_PLAN_MAGIC 569278163
+
+typedef struct
+{
+ /* current results */
+ uint64 processed; /* by Executor */
+ SPITupleTable *tuptable; /* tuptable currently being built */
+
+ /* subtransaction in which current Executor call was started */
+ SubTransactionId execSubid;
+
+ /* resources of this execution context */
+ slist_head tuptables; /* list of all live SPITupleTables */
+ MemoryContext procCxt; /* procedure context */
+ MemoryContext execCxt; /* executor context */
+ MemoryContext savedcxt; /* context of SPI_connect's caller */
+ SubTransactionId connectSubid; /* ID of connecting subtransaction */
+ QueryEnvironment *queryEnv; /* query environment setup for SPI level */
+
+ /* transaction management support */
+ bool atomic; /* atomic execution context, does not allow
+ * transactions */
+ bool internal_xact; /* SPI-managed transaction boundary, skip
+ * cleanup */
+
+ /* saved values of API global variables for previous nesting level */
+ uint64 outer_processed;
+ SPITupleTable *outer_tuptable;
+ int outer_result;
+} _SPI_connection;
+
+/*
+ * SPI plans have three states: saved, unsaved, or temporary.
+ *
+ * Ordinarily, the _SPI_plan struct itself as well as the argtypes array
+ * are in a dedicated memory context identified by plancxt (which can be
+ * really small). All the other subsidiary state is in plancache entries
+ * identified by plancache_list (note: the list cells themselves are in
+ * plancxt).
+ *
+ * In an unsaved plan, the plancxt as well as the plancache entries' contexts
+ * are children of the SPI procedure context, so they'll all disappear at
+ * function exit. plancache.c also knows that the plancache entries are
+ * "unsaved", so it doesn't link them into its global list; hence they do
+ * not respond to inval events. This is OK since we are presumably holding
+ * adequate locks to prevent other backends from messing with the tables.
+ *
+ * For a saved plan, the plancxt is made a child of CacheMemoryContext
+ * since it should persist until explicitly destroyed. Likewise, the
+ * plancache entries will be under CacheMemoryContext since we tell
+ * plancache.c to save them. We rely on plancache.c to keep the cache
+ * entries up-to-date as needed in the face of invalidation events.
+ *
+ * There are also "temporary" SPI plans, in which the _SPI_plan struct is
+ * not even palloc'd but just exists in some function's local variable.
+ * The plancache entries are unsaved and exist under the SPI executor context,
+ * while additional data such as argtypes and list cells is loose in the SPI
+ * executor context. Such plans can be identified by having plancxt == NULL.
+ *
+ * We can also have "one-shot" SPI plans (which are typically temporary,
+ * as described above). These are meant to be executed once and discarded,
+ * and various optimizations are made on the assumption of single use.
+ * Note in particular that the CachedPlanSources within such an SPI plan
+ * are not "complete" until execution.
+ *
+ * Note: if the original query string contained only whitespace and comments,
+ * the plancache_list will be NIL and so there is no place to store the
+ * query string. We don't care about that, but we do care about the
+ * argument type array, which is why it's seemingly-redundantly stored.
+ */
+typedef struct _SPI_plan
+{
+ int magic; /* should equal _SPI_PLAN_MAGIC */
+ bool saved; /* saved or unsaved plan? */
+ bool oneshot; /* one-shot plan? */
+ bool no_snapshots; /* allow nonatomic CALL/DO execution */
+ List *plancache_list; /* one CachedPlanSource per parsetree */
+ MemoryContext plancxt; /* Context containing _SPI_plan and data */
+ int cursor_options; /* Cursor options used for planning */
+ int nargs; /* number of plan arguments */
+ Oid *argtypes; /* Argument types (NULL if nargs is 0) */
+ ParserSetupHook parserSetup; /* alternative parameter spec method */
+ void *parserSetupArg;
+} _SPI_plan;
+
+#endif /* SPI_PRIV_H */
diff --git a/src/include/executor/tablefunc.h b/src/include/executor/tablefunc.h
new file mode 100644
index 0000000..4131056
--- /dev/null
+++ b/src/include/executor/tablefunc.h
@@ -0,0 +1,67 @@
+/*-------------------------------------------------------------------------
+ *
+ * tablefunc.h
+ * interface for TableFunc executor node
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/tablefunc.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _TABLEFUNC_H
+#define _TABLEFUNC_H
+
+/* Forward-declare this to avoid including execnodes.h here */
+struct TableFuncScanState;
+
+/*
+ * TableFuncRoutine holds function pointers used for generating content of
+ * table-producer functions, such as XMLTABLE.
+ *
+ * InitOpaque initializes table builder private objects. The output tuple
+ * descriptor, input functions for the columns, and typioparams are passed
+ * from executor state.
+ *
+ * SetDocument is called to define the input document. The table builder may
+ * apply additional transformations not exposed outside the table builder
+ * context.
+ *
+ * SetNamespace is called to pass namespace declarations from the table
+ * expression. This function may be NULL if namespaces are not supported by
+ * the table builder. Namespaces must be given before setting the row and
+ * column filters. If the name is given as NULL, the entry shall be for the
+ * default namespace.
+ *
+ * SetRowFilter is called do define the row-generating filter, which shall be
+ * used to extract each row from the input document.
+ *
+ * SetColumnFilter is called once for each column, to define the column-
+ * generating filter for the given column.
+ *
+ * FetchRow shall be called repeatedly until it returns that no more rows are
+ * found in the document. On each invocation it shall set state in the table
+ * builder context such that each subsequent GetValue call returns the values
+ * for the indicated column for the row being processed.
+ *
+ * DestroyOpaque shall release all resources associated with a table builder
+ * context. It may be called either because all rows have been consumed, or
+ * because an error occurred while processing the table expression.
+ */
+typedef struct TableFuncRoutine
+{
+ void (*InitOpaque) (struct TableFuncScanState *state, int natts);
+ void (*SetDocument) (struct TableFuncScanState *state, Datum value);
+ void (*SetNamespace) (struct TableFuncScanState *state, const char *name,
+ const char *uri);
+ void (*SetRowFilter) (struct TableFuncScanState *state, const char *path);
+ void (*SetColumnFilter) (struct TableFuncScanState *state,
+ const char *path, int colnum);
+ bool (*FetchRow) (struct TableFuncScanState *state);
+ Datum (*GetValue) (struct TableFuncScanState *state, int colnum,
+ Oid typid, int32 typmod, bool *isnull);
+ void (*DestroyOpaque) (struct TableFuncScanState *state);
+} TableFuncRoutine;
+
+#endif /* _TABLEFUNC_H */
diff --git a/src/include/executor/tqueue.h b/src/include/executor/tqueue.h
new file mode 100644
index 0000000..93655ef
--- /dev/null
+++ b/src/include/executor/tqueue.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * tqueue.h
+ * Use shm_mq to send & receive tuples between parallel backends
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/tqueue.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef TQUEUE_H
+#define TQUEUE_H
+
+#include "storage/shm_mq.h"
+#include "tcop/dest.h"
+
+/* Opaque struct, only known inside tqueue.c. */
+typedef struct TupleQueueReader TupleQueueReader;
+
+/* Use this to send tuples to a shm_mq. */
+extern DestReceiver *CreateTupleQueueDestReceiver(shm_mq_handle *handle);
+
+/* Use these to receive tuples from a shm_mq. */
+extern TupleQueueReader *CreateTupleQueueReader(shm_mq_handle *handle);
+extern void DestroyTupleQueueReader(TupleQueueReader *reader);
+extern HeapTuple TupleQueueReaderNext(TupleQueueReader *reader,
+ bool nowait, bool *done);
+
+#endif /* TQUEUE_H */
diff --git a/src/include/executor/tstoreReceiver.h b/src/include/executor/tstoreReceiver.h
new file mode 100644
index 0000000..b2390c4
--- /dev/null
+++ b/src/include/executor/tstoreReceiver.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ *
+ * tstoreReceiver.h
+ * prototypes for tstoreReceiver.c
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/tstoreReceiver.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef TSTORE_RECEIVER_H
+#define TSTORE_RECEIVER_H
+
+#include "tcop/dest.h"
+#include "utils/tuplestore.h"
+
+
+extern DestReceiver *CreateTuplestoreDestReceiver(void);
+
+extern void SetTuplestoreDestReceiverParams(DestReceiver *self,
+ Tuplestorestate *tStore,
+ MemoryContext tContext,
+ bool detoast);
+
+#endif /* TSTORE_RECEIVER_H */
diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h
new file mode 100644
index 0000000..f7df70b
--- /dev/null
+++ b/src/include/executor/tuptable.h
@@ -0,0 +1,487 @@
+/*-------------------------------------------------------------------------
+ *
+ * tuptable.h
+ * tuple table support stuff
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/executor/tuptable.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TUPTABLE_H
+#define TUPTABLE_H
+
+#include "access/htup.h"
+#include "access/htup_details.h"
+#include "access/sysattr.h"
+#include "access/tupdesc.h"
+#include "storage/buf.h"
+
+/*----------
+ * The executor stores tuples in a "tuple table" which is a List of
+ * independent TupleTableSlots.
+ *
+ * There's various different types of tuple table slots, each being able to
+ * store different types of tuples. Additional types of slots can be added
+ * without modifying core code. The type of a slot is determined by the
+ * TupleTableSlotOps* passed to the slot creation routine. The builtin types
+ * of slots are
+ *
+ * 1. physical tuple in a disk buffer page (TTSOpsBufferHeapTuple)
+ * 2. physical tuple constructed in palloc'ed memory (TTSOpsHeapTuple)
+ * 3. "minimal" physical tuple constructed in palloc'ed memory
+ * (TTSOpsMinimalTuple)
+ * 4. "virtual" tuple consisting of Datum/isnull arrays (TTSOpsVirtual)
+ *
+ *
+ * The first two cases are similar in that they both deal with "materialized"
+ * tuples, but resource management is different. For a tuple in a disk page
+ * we need to hold a pin on the buffer until the TupleTableSlot's reference
+ * to the tuple is dropped; while for a palloc'd tuple we usually want the
+ * tuple pfree'd when the TupleTableSlot's reference is dropped.
+ *
+ * A "minimal" tuple is handled similarly to a palloc'd regular tuple.
+ * At present, minimal tuples never are stored in buffers, so there is no
+ * parallel to case 1. Note that a minimal tuple has no "system columns".
+ * (Actually, it could have an OID, but we have no need to access the OID.)
+ *
+ * A "virtual" tuple is an optimization used to minimize physical data copying
+ * in a nest of plan nodes. Until materialized pass-by-reference Datums in
+ * the slot point to storage that is not directly associated with the
+ * TupleTableSlot; generally they will point to part of a tuple stored in a
+ * lower plan node's output TupleTableSlot, or to a function result
+ * constructed in a plan node's per-tuple econtext. It is the responsibility
+ * of the generating plan node to be sure these resources are not released for
+ * as long as the virtual tuple needs to be valid or is materialized. Note
+ * also that a virtual tuple does not have any "system columns".
+ *
+ * The Datum/isnull arrays of a TupleTableSlot serve double duty. For virtual
+ * slots they are the authoritative data. For the other builtin slots,
+ * the arrays contain data extracted from the tuple. (In this state, any
+ * pass-by-reference Datums point into the physical tuple.) The extracted
+ * information is built "lazily", ie, only as needed. This serves to avoid
+ * repeated extraction of data from the physical tuple.
+ *
+ * A TupleTableSlot can also be "empty", indicated by flag TTS_FLAG_EMPTY set
+ * in tts_flags, holding no valid data. This is the only valid state for a
+ * freshly-created slot that has not yet had a tuple descriptor assigned to
+ * it. In this state, TTS_SHOULDFREE should not be set in tts_flags, tts_tuple
+ * must be NULL and tts_nvalid zero.
+ *
+ * The tupleDescriptor is simply referenced, not copied, by the TupleTableSlot
+ * code. The caller of ExecSetSlotDescriptor() is responsible for providing
+ * a descriptor that will live as long as the slot does. (Typically, both
+ * slots and descriptors are in per-query memory and are freed by memory
+ * context deallocation at query end; so it's not worth providing any extra
+ * mechanism to do more. However, the slot will increment the tupdesc
+ * reference count if a reference-counted tupdesc is supplied.)
+ *
+ * When TTS_SHOULDFREE is set in tts_flags, the physical tuple is "owned" by
+ * the slot and should be freed when the slot's reference to the tuple is
+ * dropped.
+ *
+ * tts_values/tts_isnull are allocated either when the slot is created (when
+ * the descriptor is provided), or when a descriptor is assigned to the slot;
+ * they are of length equal to the descriptor's natts.
+ *
+ * The TTS_FLAG_SLOW flag is saved state for
+ * slot_deform_heap_tuple, and should not be touched by any other code.
+ *----------
+ */
+
+/* true = slot is empty */
+#define TTS_FLAG_EMPTY (1 << 1)
+#define TTS_EMPTY(slot) (((slot)->tts_flags & TTS_FLAG_EMPTY) != 0)
+
+/* should pfree tuple "owned" by the slot? */
+#define TTS_FLAG_SHOULDFREE (1 << 2)
+#define TTS_SHOULDFREE(slot) (((slot)->tts_flags & TTS_FLAG_SHOULDFREE) != 0)
+
+/* saved state for slot_deform_heap_tuple */
+#define TTS_FLAG_SLOW (1 << 3)
+#define TTS_SLOW(slot) (((slot)->tts_flags & TTS_FLAG_SLOW) != 0)
+
+/* fixed tuple descriptor */
+#define TTS_FLAG_FIXED (1 << 4)
+#define TTS_FIXED(slot) (((slot)->tts_flags & TTS_FLAG_FIXED) != 0)
+
+struct TupleTableSlotOps;
+typedef struct TupleTableSlotOps TupleTableSlotOps;
+
+/* base tuple table slot type */
+typedef struct TupleTableSlot
+{
+ NodeTag type;
+#define FIELDNO_TUPLETABLESLOT_FLAGS 1
+ uint16 tts_flags; /* Boolean states */
+#define FIELDNO_TUPLETABLESLOT_NVALID 2
+ AttrNumber tts_nvalid; /* # of valid values in tts_values */
+ const TupleTableSlotOps *const tts_ops; /* implementation of slot */
+#define FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR 4
+ TupleDesc tts_tupleDescriptor; /* slot's tuple descriptor */
+#define FIELDNO_TUPLETABLESLOT_VALUES 5
+ Datum *tts_values; /* current per-attribute values */
+#define FIELDNO_TUPLETABLESLOT_ISNULL 6
+ bool *tts_isnull; /* current per-attribute isnull flags */
+ MemoryContext tts_mcxt; /* slot itself is in this context */
+ ItemPointerData tts_tid; /* stored tuple's tid */
+ Oid tts_tableOid; /* table oid of tuple */
+} TupleTableSlot;
+
+/* routines for a TupleTableSlot implementation */
+struct TupleTableSlotOps
+{
+ /* Minimum size of the slot */
+ size_t base_slot_size;
+
+ /* Initialization. */
+ void (*init) (TupleTableSlot *slot);
+
+ /* Destruction. */
+ void (*release) (TupleTableSlot *slot);
+
+ /*
+ * Clear the contents of the slot. Only the contents are expected to be
+ * cleared and not the tuple descriptor. Typically an implementation of
+ * this callback should free the memory allocated for the tuple contained
+ * in the slot.
+ */
+ void (*clear) (TupleTableSlot *slot);
+
+ /*
+ * Fill up first natts entries of tts_values and tts_isnull arrays with
+ * values from the tuple contained in the slot. The function may be called
+ * with natts more than the number of attributes available in the tuple,
+ * in which case it should set tts_nvalid to the number of returned
+ * columns.
+ */
+ void (*getsomeattrs) (TupleTableSlot *slot, int natts);
+
+ /*
+ * Returns value of the given system attribute as a datum and sets isnull
+ * to false, if it's not NULL. Throws an error if the slot type does not
+ * support system attributes.
+ */
+ Datum (*getsysattr) (TupleTableSlot *slot, int attnum, bool *isnull);
+
+ /*
+ * Make the contents of the slot solely depend on the slot, and not on
+ * underlying resources (like another memory context, buffers, etc).
+ */
+ void (*materialize) (TupleTableSlot *slot);
+
+ /*
+ * Copy the contents of the source slot into the destination slot's own
+ * context. Invoked using callback of the destination slot.
+ */
+ void (*copyslot) (TupleTableSlot *dstslot, TupleTableSlot *srcslot);
+
+ /*
+ * Return a heap tuple "owned" by the slot. It is slot's responsibility to
+ * free the memory consumed by the heap tuple. If the slot can not "own" a
+ * heap tuple, it should not implement this callback and should set it as
+ * NULL.
+ */
+ HeapTuple (*get_heap_tuple) (TupleTableSlot *slot);
+
+ /*
+ * Return a minimal tuple "owned" by the slot. It is slot's responsibility
+ * to free the memory consumed by the minimal tuple. If the slot can not
+ * "own" a minimal tuple, it should not implement this callback and should
+ * set it as NULL.
+ */
+ MinimalTuple (*get_minimal_tuple) (TupleTableSlot *slot);
+
+ /*
+ * Return a copy of heap tuple representing the contents of the slot. The
+ * copy needs to be palloc'd in the current memory context. The slot
+ * itself is expected to remain unaffected. It is *not* expected to have
+ * meaningful "system columns" in the copy. The copy is not be "owned" by
+ * the slot i.e. the caller has to take responsibility to free memory
+ * consumed by the slot.
+ */
+ HeapTuple (*copy_heap_tuple) (TupleTableSlot *slot);
+
+ /*
+ * Return a copy of minimal tuple representing the contents of the slot.
+ * The copy needs to be palloc'd in the current memory context. The slot
+ * itself is expected to remain unaffected. It is *not* expected to have
+ * meaningful "system columns" in the copy. The copy is not be "owned" by
+ * the slot i.e. the caller has to take responsibility to free memory
+ * consumed by the slot.
+ */
+ MinimalTuple (*copy_minimal_tuple) (TupleTableSlot *slot);
+};
+
+/*
+ * Predefined TupleTableSlotOps for various types of TupleTableSlotOps. The
+ * same are used to identify the type of a given slot.
+ */
+extern PGDLLIMPORT const TupleTableSlotOps TTSOpsVirtual;
+extern PGDLLIMPORT const TupleTableSlotOps TTSOpsHeapTuple;
+extern PGDLLIMPORT const TupleTableSlotOps TTSOpsMinimalTuple;
+extern PGDLLIMPORT const TupleTableSlotOps TTSOpsBufferHeapTuple;
+
+#define TTS_IS_VIRTUAL(slot) ((slot)->tts_ops == &TTSOpsVirtual)
+#define TTS_IS_HEAPTUPLE(slot) ((slot)->tts_ops == &TTSOpsHeapTuple)
+#define TTS_IS_MINIMALTUPLE(slot) ((slot)->tts_ops == &TTSOpsMinimalTuple)
+#define TTS_IS_BUFFERTUPLE(slot) ((slot)->tts_ops == &TTSOpsBufferHeapTuple)
+
+
+/*
+ * Tuple table slot implementations.
+ */
+
+typedef struct VirtualTupleTableSlot
+{
+ TupleTableSlot base;
+
+ char *data; /* data for materialized slots */
+} VirtualTupleTableSlot;
+
+typedef struct HeapTupleTableSlot
+{
+ TupleTableSlot base;
+
+#define FIELDNO_HEAPTUPLETABLESLOT_TUPLE 1
+ HeapTuple tuple; /* physical tuple */
+#define FIELDNO_HEAPTUPLETABLESLOT_OFF 2
+ uint32 off; /* saved state for slot_deform_heap_tuple */
+ HeapTupleData tupdata; /* optional workspace for storing tuple */
+} HeapTupleTableSlot;
+
+/* heap tuple residing in a buffer */
+typedef struct BufferHeapTupleTableSlot
+{
+ HeapTupleTableSlot base;
+
+ /*
+ * If buffer is not InvalidBuffer, then the slot is holding a pin on the
+ * indicated buffer page; drop the pin when we release the slot's
+ * reference to that buffer. (TTS_FLAG_SHOULDFREE should not be set in
+ * such a case, since presumably tts_tuple is pointing into the buffer.)
+ */
+ Buffer buffer; /* tuple's buffer, or InvalidBuffer */
+} BufferHeapTupleTableSlot;
+
+typedef struct MinimalTupleTableSlot
+{
+ TupleTableSlot base;
+
+ /*
+ * In a minimal slot tuple points at minhdr and the fields of that struct
+ * are set correctly for access to the minimal tuple; in particular,
+ * minhdr.t_data points MINIMAL_TUPLE_OFFSET bytes before mintuple. This
+ * allows column extraction to treat the case identically to regular
+ * physical tuples.
+ */
+#define FIELDNO_MINIMALTUPLETABLESLOT_TUPLE 1
+ HeapTuple tuple; /* tuple wrapper */
+ MinimalTuple mintuple; /* minimal tuple, or NULL if none */
+ HeapTupleData minhdr; /* workspace for minimal-tuple-only case */
+#define FIELDNO_MINIMALTUPLETABLESLOT_OFF 4
+ uint32 off; /* saved state for slot_deform_heap_tuple */
+} MinimalTupleTableSlot;
+
+/*
+ * TupIsNull -- is a TupleTableSlot empty?
+ */
+#define TupIsNull(slot) \
+ ((slot) == NULL || TTS_EMPTY(slot))
+
+/* in executor/execTuples.c */
+extern TupleTableSlot *MakeTupleTableSlot(TupleDesc tupleDesc,
+ const TupleTableSlotOps *tts_ops);
+extern TupleTableSlot *ExecAllocTableSlot(List **tupleTable, TupleDesc desc,
+ const TupleTableSlotOps *tts_ops);
+extern void ExecResetTupleTable(List *tupleTable, bool shouldFree);
+extern TupleTableSlot *MakeSingleTupleTableSlot(TupleDesc tupdesc,
+ const TupleTableSlotOps *tts_ops);
+extern void ExecDropSingleTupleTableSlot(TupleTableSlot *slot);
+extern void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc);
+extern TupleTableSlot *ExecStoreHeapTuple(HeapTuple tuple,
+ TupleTableSlot *slot,
+ bool shouldFree);
+extern void ExecForceStoreHeapTuple(HeapTuple tuple,
+ TupleTableSlot *slot,
+ bool shouldFree);
+extern TupleTableSlot *ExecStoreBufferHeapTuple(HeapTuple tuple,
+ TupleTableSlot *slot,
+ Buffer buffer);
+extern TupleTableSlot *ExecStorePinnedBufferHeapTuple(HeapTuple tuple,
+ TupleTableSlot *slot,
+ Buffer buffer);
+extern TupleTableSlot *ExecStoreMinimalTuple(MinimalTuple mtup,
+ TupleTableSlot *slot,
+ bool shouldFree);
+extern void ExecForceStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot,
+ bool shouldFree);
+extern TupleTableSlot *ExecStoreVirtualTuple(TupleTableSlot *slot);
+extern TupleTableSlot *ExecStoreAllNullTuple(TupleTableSlot *slot);
+extern void ExecStoreHeapTupleDatum(Datum data, TupleTableSlot *slot);
+extern HeapTuple ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree);
+extern MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot,
+ bool *shouldFree);
+extern Datum ExecFetchSlotHeapTupleDatum(TupleTableSlot *slot);
+extern void slot_getmissingattrs(TupleTableSlot *slot, int startAttNum,
+ int lastAttNum);
+extern void slot_getsomeattrs_int(TupleTableSlot *slot, int attnum);
+
+
+#ifndef FRONTEND
+
+/*
+ * This function forces the entries of the slot's Datum/isnull arrays to be
+ * valid at least up through the attnum'th entry.
+ */
+static inline void
+slot_getsomeattrs(TupleTableSlot *slot, int attnum)
+{
+ if (slot->tts_nvalid < attnum)
+ slot_getsomeattrs_int(slot, attnum);
+}
+
+/*
+ * slot_getallattrs
+ * This function forces all the entries of the slot's Datum/isnull
+ * arrays to be valid. The caller may then extract data directly
+ * from those arrays instead of using slot_getattr.
+ */
+static inline void
+slot_getallattrs(TupleTableSlot *slot)
+{
+ slot_getsomeattrs(slot, slot->tts_tupleDescriptor->natts);
+}
+
+
+/*
+ * slot_attisnull
+ *
+ * Detect whether an attribute of the slot is null, without actually fetching
+ * it.
+ */
+static inline bool
+slot_attisnull(TupleTableSlot *slot, int attnum)
+{
+ AssertArg(attnum > 0);
+
+ if (attnum > slot->tts_nvalid)
+ slot_getsomeattrs(slot, attnum);
+
+ return slot->tts_isnull[attnum - 1];
+}
+
+/*
+ * slot_getattr - fetch one attribute of the slot's contents.
+ */
+static inline Datum
+slot_getattr(TupleTableSlot *slot, int attnum,
+ bool *isnull)
+{
+ AssertArg(attnum > 0);
+
+ if (attnum > slot->tts_nvalid)
+ slot_getsomeattrs(slot, attnum);
+
+ *isnull = slot->tts_isnull[attnum - 1];
+
+ return slot->tts_values[attnum - 1];
+}
+
+/*
+ * slot_getsysattr - fetch a system attribute of the slot's current tuple.
+ *
+ * If the slot type does not contain system attributes, this will throw an
+ * error. Hence before calling this function, callers should make sure that
+ * the slot type is the one that supports system attributes.
+ */
+static inline Datum
+slot_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
+{
+ AssertArg(attnum < 0); /* caller error */
+
+ if (attnum == TableOidAttributeNumber)
+ {
+ *isnull = false;
+ return ObjectIdGetDatum(slot->tts_tableOid);
+ }
+ else if (attnum == SelfItemPointerAttributeNumber)
+ {
+ *isnull = false;
+ return PointerGetDatum(&slot->tts_tid);
+ }
+
+ /* Fetch the system attribute from the underlying tuple. */
+ return slot->tts_ops->getsysattr(slot, attnum, isnull);
+}
+
+/*
+ * ExecClearTuple - clear the slot's contents
+ */
+static inline TupleTableSlot *
+ExecClearTuple(TupleTableSlot *slot)
+{
+ slot->tts_ops->clear(slot);
+
+ return slot;
+}
+
+/* ExecMaterializeSlot - force a slot into the "materialized" state.
+ *
+ * This causes the slot's tuple to be a local copy not dependent on any
+ * external storage (i.e. pointing into a Buffer, or having allocations in
+ * another memory context).
+ *
+ * A typical use for this operation is to prepare a computed tuple for being
+ * stored on disk. The original data may or may not be virtual, but in any
+ * case we need a private copy for heap_insert to scribble on.
+ */
+static inline void
+ExecMaterializeSlot(TupleTableSlot *slot)
+{
+ slot->tts_ops->materialize(slot);
+}
+
+/*
+ * ExecCopySlotHeapTuple - return HeapTuple allocated in caller's context
+ */
+static inline HeapTuple
+ExecCopySlotHeapTuple(TupleTableSlot *slot)
+{
+ Assert(!TTS_EMPTY(slot));
+
+ return slot->tts_ops->copy_heap_tuple(slot);
+}
+
+/*
+ * ExecCopySlotMinimalTuple - return MinimalTuple allocated in caller's context
+ */
+static inline MinimalTuple
+ExecCopySlotMinimalTuple(TupleTableSlot *slot)
+{
+ return slot->tts_ops->copy_minimal_tuple(slot);
+}
+
+/*
+ * ExecCopySlot - copy one slot's contents into another.
+ *
+ * If a source's system attributes are supposed to be accessed in the target
+ * slot, the target slot and source slot types need to match.
+ */
+static inline TupleTableSlot *
+ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
+{
+ Assert(!TTS_EMPTY(srcslot));
+ AssertArg(srcslot != dstslot);
+
+ dstslot->tts_ops->copyslot(dstslot, srcslot);
+
+ return dstslot;
+}
+
+#endif /* FRONTEND */
+
+#endif /* TUPTABLE_H */
diff --git a/src/include/fe_utils/archive.h b/src/include/fe_utils/archive.h
new file mode 100644
index 0000000..a6beaf0
--- /dev/null
+++ b/src/include/fe_utils/archive.h
@@ -0,0 +1,21 @@
+/*-------------------------------------------------------------------------
+ *
+ * archive.h
+ * Routines to access WAL archives from frontend
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/fe_utils/archive.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FE_ARCHIVE_H
+#define FE_ARCHIVE_H
+
+extern int RestoreArchivedFile(const char *path,
+ const char *xlogfname,
+ off_t expectedSize,
+ const char *restoreCommand);
+
+#endif /* FE_ARCHIVE_H */
diff --git a/src/include/fe_utils/cancel.h b/src/include/fe_utils/cancel.h
new file mode 100644
index 0000000..2a1169a
--- /dev/null
+++ b/src/include/fe_utils/cancel.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * Query cancellation support for frontend code
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/fe_utils/cancel.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef CANCEL_H
+#define CANCEL_H
+
+#include <signal.h>
+
+#include "libpq-fe.h"
+
+extern volatile sig_atomic_t CancelRequested;
+
+extern void SetCancelConn(PGconn *conn);
+extern void ResetCancelConn(void);
+
+/*
+ * A callback can be optionally set up to be called at cancellation
+ * time.
+ */
+extern void setup_cancel_handler(void (*cancel_callback) (void));
+
+#endif /* CANCEL_H */
diff --git a/src/include/fe_utils/conditional.h b/src/include/fe_utils/conditional.h
new file mode 100644
index 0000000..999de3e
--- /dev/null
+++ b/src/include/fe_utils/conditional.h
@@ -0,0 +1,100 @@
+/*-------------------------------------------------------------------------
+ * A stack of automaton states to handle nested conditionals.
+ *
+ * This file describes a stack of automaton states which
+ * allow a manage nested conditionals.
+ *
+ * It is used by:
+ * - "psql" interpreter for handling \if ... \endif
+ * - "pgbench" interpreter for handling \if ... \endif
+ * - "pgbench" syntax checker to test for proper nesting
+ *
+ * The stack holds the state of enclosing conditionals (are we in
+ * a true branch? in a false branch? have we already encountered
+ * a true branch?) so that the interpreter knows whether to execute
+ * code and whether to evaluate conditions.
+ *
+ * Copyright (c) 2000-2020, PostgreSQL Global Development Group
+ *
+ * src/include/fe_utils/conditional.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef CONDITIONAL_H
+#define CONDITIONAL_H
+
+/*
+ * Possible states of a single level of \if block.
+ */
+typedef enum ifState
+{
+ IFSTATE_NONE = 0, /* not currently in an \if block */
+ IFSTATE_TRUE, /* currently in an \if or \elif that is true
+ * and all parent branches (if any) are true */
+ IFSTATE_FALSE, /* currently in an \if or \elif that is false
+ * but no true branch has yet been seen, and
+ * all parent branches (if any) are true */
+ IFSTATE_IGNORED, /* currently in an \elif that follows a true
+ * branch, or the whole \if is a child of a
+ * false parent branch */
+ IFSTATE_ELSE_TRUE, /* currently in an \else that is true and all
+ * parent branches (if any) are true */
+ IFSTATE_ELSE_FALSE /* currently in an \else that is false or
+ * ignored */
+} ifState;
+
+/*
+ * The state of nested \ifs is stored in a stack.
+ *
+ * query_len is used to determine what accumulated text to throw away at the
+ * end of an inactive branch. (We could, perhaps, teach the lexer to not add
+ * stuff to the query buffer in the first place when inside an inactive branch;
+ * but that would be very invasive.) We also need to save and restore the
+ * lexer's parenthesis nesting depth when throwing away text. (We don't need
+ * to save and restore any of its other state, such as comment nesting depth,
+ * because a backslash command could never appear inside a comment or SQL
+ * literal.)
+ */
+typedef struct IfStackElem
+{
+ ifState if_state; /* current state, see enum above */
+ int query_len; /* length of query_buf at last branch start */
+ int paren_depth; /* parenthesis depth at last branch start */
+ struct IfStackElem *next; /* next surrounding \if, if any */
+} IfStackElem;
+
+typedef struct ConditionalStackData
+{
+ IfStackElem *head;
+} ConditionalStackData;
+
+typedef struct ConditionalStackData *ConditionalStack;
+
+
+extern ConditionalStack conditional_stack_create(void);
+
+extern void conditional_stack_destroy(ConditionalStack cstack);
+
+extern int conditional_stack_depth(ConditionalStack cstack);
+
+extern void conditional_stack_push(ConditionalStack cstack, ifState new_state);
+
+extern bool conditional_stack_pop(ConditionalStack cstack);
+
+extern ifState conditional_stack_peek(ConditionalStack cstack);
+
+extern bool conditional_stack_poke(ConditionalStack cstack, ifState new_state);
+
+extern bool conditional_stack_empty(ConditionalStack cstack);
+
+extern bool conditional_active(ConditionalStack cstack);
+
+extern void conditional_stack_set_query_len(ConditionalStack cstack, int len);
+
+extern int conditional_stack_get_query_len(ConditionalStack cstack);
+
+extern void conditional_stack_set_paren_depth(ConditionalStack cstack, int depth);
+
+extern int conditional_stack_get_paren_depth(ConditionalStack cstack);
+
+#endif /* CONDITIONAL_H */
diff --git a/src/include/fe_utils/mbprint.h b/src/include/fe_utils/mbprint.h
new file mode 100644
index 0000000..1aa718b
--- /dev/null
+++ b/src/include/fe_utils/mbprint.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ *
+ * Multibyte character printing support for frontend code
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/fe_utils/mbprint.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef MBPRINT_H
+#define MBPRINT_H
+
+struct lineptr
+{
+ unsigned char *ptr;
+ int width;
+};
+
+extern unsigned char *mbvalidate(unsigned char *pwcs, int encoding);
+extern int pg_wcswidth(const char *pwcs, size_t len, int encoding);
+extern void pg_wcsformat(const unsigned char *pwcs, size_t len, int encoding,
+ struct lineptr *lines, int count);
+extern void pg_wcssize(const unsigned char *pwcs, size_t len, int encoding,
+ int *width, int *height, int *format_size);
+
+#endif /* MBPRINT_H */
diff --git a/src/include/fe_utils/print.h b/src/include/fe_utils/print.h
new file mode 100644
index 0000000..9a47efa
--- /dev/null
+++ b/src/include/fe_utils/print.h
@@ -0,0 +1,219 @@
+/*-------------------------------------------------------------------------
+ *
+ * Query-result printing support for frontend code
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/fe_utils/print.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PRINT_H
+#define PRINT_H
+
+#include <signal.h>
+
+#include "libpq-fe.h"
+
+
+/* This is not a particularly great place for this ... */
+#ifndef __CYGWIN__
+#define DEFAULT_PAGER "more"
+#else
+#define DEFAULT_PAGER "less"
+#endif
+
+enum printFormat
+{
+ PRINT_NOTHING = 0, /* to make sure someone initializes this */
+ PRINT_ALIGNED,
+ PRINT_ASCIIDOC,
+ PRINT_CSV,
+ PRINT_HTML,
+ PRINT_LATEX,
+ PRINT_LATEX_LONGTABLE,
+ PRINT_TROFF_MS,
+ PRINT_UNALIGNED,
+ PRINT_WRAPPED
+ /* add your favourite output format here ... */
+};
+
+typedef struct printTextLineFormat
+{
+ /* Line drawing characters to be used in various contexts */
+ const char *hrule; /* horizontal line character */
+ const char *leftvrule; /* left vertical line (+horizontal) */
+ const char *midvrule; /* intra-column vertical line (+horizontal) */
+ const char *rightvrule; /* right vertical line (+horizontal) */
+} printTextLineFormat;
+
+typedef enum printTextRule
+{
+ /* Additional context for selecting line drawing characters */
+ PRINT_RULE_TOP, /* top horizontal line */
+ PRINT_RULE_MIDDLE, /* intra-data horizontal line */
+ PRINT_RULE_BOTTOM, /* bottom horizontal line */
+ PRINT_RULE_DATA /* data line (hrule is unused here) */
+} printTextRule;
+
+typedef enum printTextLineWrap
+{
+ /* Line wrapping conditions */
+ PRINT_LINE_WRAP_NONE, /* No wrapping */
+ PRINT_LINE_WRAP_WRAP, /* Wraparound due to overlength line */
+ PRINT_LINE_WRAP_NEWLINE /* Newline in data */
+} printTextLineWrap;
+
+typedef struct printTextFormat
+{
+ /* A complete line style */
+ const char *name; /* for display purposes */
+ printTextLineFormat lrule[4]; /* indexed by enum printTextRule */
+ const char *midvrule_nl; /* vertical line for continue after newline */
+ const char *midvrule_wrap; /* vertical line for wrapped data */
+ const char *midvrule_blank; /* vertical line for blank data */
+ const char *header_nl_left; /* left mark after newline */
+ const char *header_nl_right; /* right mark for newline */
+ const char *nl_left; /* left mark after newline */
+ const char *nl_right; /* right mark for newline */
+ const char *wrap_left; /* left mark after wrapped data */
+ const char *wrap_right; /* right mark for wrapped data */
+ bool wrap_right_border; /* use right-hand border for wrap marks
+ * when border=0? */
+} printTextFormat;
+
+typedef enum unicode_linestyle
+{
+ UNICODE_LINESTYLE_SINGLE = 0,
+ UNICODE_LINESTYLE_DOUBLE
+} unicode_linestyle;
+
+struct separator
+{
+ char *separator;
+ bool separator_zero;
+};
+
+typedef struct printTableOpt
+{
+ enum printFormat format; /* see enum above */
+ unsigned short int expanded; /* expanded/vertical output (if supported
+ * by output format); 0=no, 1=yes, 2=auto */
+ unsigned short int border; /* Print a border around the table. 0=none,
+ * 1=dividing lines, 2=full */
+ unsigned short int pager; /* use pager for output (if to stdout and
+ * stdout is a tty) 0=off 1=on 2=always */
+ int pager_min_lines; /* don't use pager unless there are at
+ * least this many lines */
+ bool tuples_only; /* don't output headers, row counts, etc. */
+ bool start_table; /* print start decoration, eg <table> */
+ bool stop_table; /* print stop decoration, eg </table> */
+ bool default_footer; /* allow "(xx rows)" default footer */
+ unsigned long prior_records; /* start offset for record counters */
+ const printTextFormat *line_style; /* line style (NULL for default) */
+ struct separator fieldSep; /* field separator for unaligned text mode */
+ struct separator recordSep; /* record separator for unaligned text mode */
+ char csvFieldSep[2]; /* field separator for csv format */
+ bool numericLocale; /* locale-aware numeric units separator and
+ * decimal marker */
+ char *tableAttr; /* attributes for HTML <table ...> */
+ int encoding; /* character encoding */
+ int env_columns; /* $COLUMNS on psql start, 0 is unset */
+ int columns; /* target width for wrapped format */
+ unicode_linestyle unicode_border_linestyle;
+ unicode_linestyle unicode_column_linestyle;
+ unicode_linestyle unicode_header_linestyle;
+} printTableOpt;
+
+/*
+ * Table footers are implemented as a singly-linked list.
+ *
+ * This is so that you don't need to know the number of footers in order to
+ * initialise the printTableContent struct, which is very convenient when
+ * preparing complex footers (as in describeOneTableDetails).
+ */
+typedef struct printTableFooter
+{
+ char *data;
+ struct printTableFooter *next;
+} printTableFooter;
+
+/*
+ * The table content struct holds all the information which will be displayed
+ * by printTable().
+ */
+typedef struct printTableContent
+{
+ const printTableOpt *opt;
+ const char *title; /* May be NULL */
+ int ncolumns; /* Specified in Init() */
+ int nrows; /* Specified in Init() */
+ const char **headers; /* NULL-terminated array of header strings */
+ const char **header; /* Pointer to the last added header */
+ const char **cells; /* NULL-terminated array of cell content
+ * strings */
+ const char **cell; /* Pointer to the last added cell */
+ long cellsadded; /* Number of cells added this far */
+ bool *cellmustfree; /* true for cells that need to be free()d */
+ printTableFooter *footers; /* Pointer to the first footer */
+ printTableFooter *footer; /* Pointer to the last added footer */
+ char *aligns; /* Array of alignment specifiers; 'l' or 'r',
+ * one per column */
+ char *align; /* Pointer to the last added alignment */
+} printTableContent;
+
+typedef struct printQueryOpt
+{
+ printTableOpt topt; /* the options above */
+ char *nullPrint; /* how to print null entities */
+ char *title; /* override title */
+ char **footers; /* override footer (default is "(xx rows)") */
+ bool translate_header; /* do gettext on column headers */
+ const bool *translate_columns; /* translate_columns[i-1] => do gettext on
+ * col i */
+ int n_translate_columns; /* length of translate_columns[] */
+} printQueryOpt;
+
+
+extern volatile sig_atomic_t cancel_pressed;
+
+extern const printTextFormat pg_asciiformat;
+extern const printTextFormat pg_asciiformat_old;
+extern printTextFormat pg_utf8format; /* ideally would be const, but... */
+
+
+extern void disable_sigpipe_trap(void);
+extern void restore_sigpipe_trap(void);
+extern void set_sigpipe_trap_state(bool ignore);
+
+extern FILE *PageOutput(int lines, const printTableOpt *topt);
+extern void ClosePager(FILE *pagerpipe);
+
+extern void html_escaped_print(const char *in, FILE *fout);
+
+extern void printTableInit(printTableContent *const content,
+ const printTableOpt *opt, const char *title,
+ const int ncolumns, const int nrows);
+extern void printTableAddHeader(printTableContent *const content,
+ char *header, const bool translate, const char align);
+extern void printTableAddCell(printTableContent *const content,
+ char *cell, const bool translate, const bool mustfree);
+extern void printTableAddFooter(printTableContent *const content,
+ const char *footer);
+extern void printTableSetFooter(printTableContent *const content,
+ const char *footer);
+extern void printTableCleanup(printTableContent *const content);
+extern void printTable(const printTableContent *cont,
+ FILE *fout, bool is_pager, FILE *flog);
+extern void printQuery(const PGresult *result, const printQueryOpt *opt,
+ FILE *fout, bool is_pager, FILE *flog);
+
+extern char column_type_alignment(Oid);
+
+extern void setDecimalLocale(void);
+extern const printTextFormat *get_line_style(const printTableOpt *opt);
+extern void refresh_utf8format(const printTableOpt *opt);
+
+#endif /* PRINT_H */
diff --git a/src/include/fe_utils/psqlscan.h b/src/include/fe_utils/psqlscan.h
new file mode 100644
index 0000000..91d1091
--- /dev/null
+++ b/src/include/fe_utils/psqlscan.h
@@ -0,0 +1,90 @@
+/*-------------------------------------------------------------------------
+ *
+ * psqlscan.h
+ * lexical scanner for SQL commands
+ *
+ * This lexer used to be part of psql, and that heritage is reflected in
+ * the file name as well as function and typedef names, though it can now
+ * be used by other frontend programs as well. It's also possible to extend
+ * this lexer with a compatible add-on lexer to handle program-specific
+ * backslash commands.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/fe_utils/psqlscan.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PSQLSCAN_H
+#define PSQLSCAN_H
+
+#include "pqexpbuffer.h"
+
+
+/* Abstract type for lexer's internal state */
+typedef struct PsqlScanStateData *PsqlScanState;
+
+/* Termination states for psql_scan() */
+typedef enum
+{
+ PSCAN_SEMICOLON, /* found command-ending semicolon */
+ PSCAN_BACKSLASH, /* found backslash command */
+ PSCAN_INCOMPLETE, /* end of line, SQL statement incomplete */
+ PSCAN_EOL /* end of line, SQL possibly complete */
+} PsqlScanResult;
+
+/* Prompt type returned by psql_scan() */
+typedef enum _promptStatus
+{
+ PROMPT_READY,
+ PROMPT_CONTINUE,
+ PROMPT_COMMENT,
+ PROMPT_SINGLEQUOTE,
+ PROMPT_DOUBLEQUOTE,
+ PROMPT_DOLLARQUOTE,
+ PROMPT_PAREN,
+ PROMPT_COPY
+} promptStatus_t;
+
+/* Quoting request types for get_variable() callback */
+typedef enum
+{
+ PQUOTE_PLAIN, /* just return the actual value */
+ PQUOTE_SQL_LITERAL, /* add quotes to make a valid SQL literal */
+ PQUOTE_SQL_IDENT, /* quote if needed to make a SQL identifier */
+ PQUOTE_SHELL_ARG /* quote if needed to be safe in a shell cmd */
+} PsqlScanQuoteType;
+
+/* Callback functions to be used by the lexer */
+typedef struct PsqlScanCallbacks
+{
+ /* Fetch value of a variable, as a free'able string; NULL if unknown */
+ /* This pointer can be NULL if no variable substitution is wanted */
+ char *(*get_variable) (const char *varname, PsqlScanQuoteType quote,
+ void *passthrough);
+} PsqlScanCallbacks;
+
+
+extern PsqlScanState psql_scan_create(const PsqlScanCallbacks *callbacks);
+extern void psql_scan_destroy(PsqlScanState state);
+
+extern void psql_scan_set_passthrough(PsqlScanState state, void *passthrough);
+
+extern void psql_scan_setup(PsqlScanState state,
+ const char *line, int line_len,
+ int encoding, bool std_strings);
+extern void psql_scan_finish(PsqlScanState state);
+
+extern PsqlScanResult psql_scan(PsqlScanState state,
+ PQExpBuffer query_buf,
+ promptStatus_t *prompt);
+
+extern void psql_scan_reset(PsqlScanState state);
+
+extern void psql_scan_reselect_sql_lexer(PsqlScanState state);
+
+extern bool psql_scan_in_quote(PsqlScanState state);
+
+#endif /* PSQLSCAN_H */
diff --git a/src/include/fe_utils/psqlscan_int.h b/src/include/fe_utils/psqlscan_int.h
new file mode 100644
index 0000000..311f803
--- /dev/null
+++ b/src/include/fe_utils/psqlscan_int.h
@@ -0,0 +1,149 @@
+/*-------------------------------------------------------------------------
+ *
+ * psqlscan_int.h
+ * lexical scanner internal declarations
+ *
+ * This file declares the PsqlScanStateData structure used by psqlscan.l
+ * and shared by other lexers compatible with it, such as psqlscanslash.l.
+ *
+ * One difficult aspect of this code is that we need to work in multibyte
+ * encodings that are not ASCII-safe. A "safe" encoding is one in which each
+ * byte of a multibyte character has the high bit set (it's >= 0x80). Since
+ * all our lexing rules treat all high-bit-set characters alike, we don't
+ * really need to care whether such a byte is part of a sequence or not.
+ * In an "unsafe" encoding, we still expect the first byte of a multibyte
+ * sequence to be >= 0x80, but later bytes might not be. If we scan such
+ * a sequence as-is, the lexing rules could easily be fooled into matching
+ * such bytes to ordinary ASCII characters. Our solution for this is to
+ * substitute 0xFF for each non-first byte within the data presented to flex.
+ * The flex rules will then pass the FF's through unmolested. The
+ * psqlscan_emit() subroutine is responsible for looking back to the original
+ * string and replacing FF's with the corresponding original bytes.
+ *
+ * Another interesting thing we do here is scan different parts of the same
+ * input with physically separate flex lexers (ie, lexers written in separate
+ * .l files). We can get away with this because the only part of the
+ * persistent state of a flex lexer that depends on its parsing rule tables
+ * is the start state number, which is easy enough to manage --- usually,
+ * in fact, we just need to set it to INITIAL when changing lexers. But to
+ * make that work at all, we must use re-entrant lexers, so that all the
+ * relevant state is in the yyscan_t attached to the PsqlScanState;
+ * if we were using lexers with separate static state we would soon end up
+ * with dangling buffer pointers in one or the other. Also note that this
+ * is unlikely to work very nicely if the lexers aren't all built with the
+ * same flex version, or if they don't use the same flex options.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/fe_utils/psqlscan_int.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PSQLSCAN_INT_H
+#define PSQLSCAN_INT_H
+
+#include "fe_utils/psqlscan.h"
+
+/*
+ * These are just to allow this file to be compilable standalone for header
+ * validity checking; in actual use, this file should always be included
+ * from the body of a flex file, where these symbols are already defined.
+ */
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void *yyscan_t;
+#endif
+
+/*
+ * We use a stack of flex buffers to handle substitution of psql variables.
+ * Each stacked buffer contains the as-yet-unread text from one psql variable.
+ * When we pop the stack all the way, we resume reading from the outer buffer
+ * identified by scanbufhandle.
+ */
+typedef struct StackElem
+{
+ YY_BUFFER_STATE buf; /* flex input control structure */
+ char *bufstring; /* data actually being scanned by flex */
+ char *origstring; /* copy of original data, if needed */
+ char *varname; /* name of variable providing data, or NULL */
+ struct StackElem *next;
+} StackElem;
+
+/*
+ * All working state of the lexer must be stored in PsqlScanStateData
+ * between calls. This allows us to have multiple open lexer operations,
+ * which is needed for nested include files. The lexer itself is not
+ * recursive, but it must be re-entrant.
+ */
+typedef struct PsqlScanStateData
+{
+ yyscan_t scanner; /* Flex's state for this PsqlScanState */
+
+ PQExpBuffer output_buf; /* current output buffer */
+
+ StackElem *buffer_stack; /* stack of variable expansion buffers */
+
+ /*
+ * These variables always refer to the outer buffer, never to any stacked
+ * variable-expansion buffer.
+ */
+ YY_BUFFER_STATE scanbufhandle;
+ char *scanbuf; /* start of outer-level input buffer */
+ const char *scanline; /* current input line at outer level */
+
+ /* safe_encoding, curline, refline are used by emit() to replace FFs */
+ int encoding; /* encoding being used now */
+ bool safe_encoding; /* is current encoding "safe"? */
+ bool std_strings; /* are string literals standard? */
+ const char *curline; /* actual flex input string for cur buf */
+ const char *refline; /* original data for cur buffer */
+
+ /*
+ * All this state lives across successive input lines, until explicitly
+ * reset by psql_scan_reset. start_state is adopted by yylex() on entry,
+ * and updated with its finishing state on exit.
+ */
+ int start_state; /* yylex's starting/finishing state */
+ int state_before_str_stop; /* start cond. before end quote */
+ int paren_depth; /* depth of nesting in parentheses */
+ int xcdepth; /* depth of nesting in slash-star comments */
+ char *dolqstart; /* current $foo$ quote start string */
+
+ /*
+ * Callback functions provided by the program making use of the lexer,
+ * plus a void* callback passthrough argument.
+ */
+ const PsqlScanCallbacks *callbacks;
+ void *cb_passthrough;
+} PsqlScanStateData;
+
+
+/*
+ * Functions exported by psqlscan.l, but only meant for use within
+ * compatible lexers.
+ */
+extern void psqlscan_push_new_buffer(PsqlScanState state,
+ const char *newstr, const char *varname);
+extern void psqlscan_pop_buffer_stack(PsqlScanState state);
+extern void psqlscan_select_top_buffer(PsqlScanState state);
+extern bool psqlscan_var_is_current_source(PsqlScanState state,
+ const char *varname);
+extern YY_BUFFER_STATE psqlscan_prepare_buffer(PsqlScanState state,
+ const char *txt, int len,
+ char **txtcopy);
+extern void psqlscan_emit(PsqlScanState state, const char *txt, int len);
+extern char *psqlscan_extract_substring(PsqlScanState state,
+ const char *txt, int len);
+extern void psqlscan_escape_variable(PsqlScanState state,
+ const char *txt, int len,
+ PsqlScanQuoteType quote);
+extern void psqlscan_test_variable(PsqlScanState state,
+ const char *txt, int len);
+
+#endif /* PSQLSCAN_INT_H */
diff --git a/src/include/fe_utils/recovery_gen.h b/src/include/fe_utils/recovery_gen.h
new file mode 100644
index 0000000..c8655cd
--- /dev/null
+++ b/src/include/fe_utils/recovery_gen.h
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+ *
+ * Generator for recovery configuration
+ *
+ * Portions Copyright (c) 2011-2020, PostgreSQL Global Development Group
+ *
+ * src/include/fe_utils/recovery_gen.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RECOVERY_GEN_H
+#define RECOVERY_GEN_H
+
+#include "libpq-fe.h"
+#include "pqexpbuffer.h"
+
+/*
+ * recovery configuration is part of postgresql.conf in version 12 and up, and
+ * in recovery.conf before that.
+ */
+#define MINIMUM_VERSION_FOR_RECOVERY_GUC 120000
+
+extern PQExpBuffer GenerateRecoveryConfig(PGconn *pgconn,
+ char *pg_replication_slot);
+extern void WriteRecoveryConfig(PGconn *pgconn, char *target_dir,
+ PQExpBuffer contents);
+
+#endif /* RECOVERY_GEN_H */
diff --git a/src/include/fe_utils/simple_list.h b/src/include/fe_utils/simple_list.h
new file mode 100644
index 0000000..db04e67
--- /dev/null
+++ b/src/include/fe_utils/simple_list.h
@@ -0,0 +1,70 @@
+/*-------------------------------------------------------------------------
+ *
+ * Simple list facilities for frontend code
+ *
+ * Data structures for simple lists of OIDs, strings, and pointers. The
+ * support for these is very primitive compared to the backend's List
+ * facilities, but it's all we need in, eg, pg_dump.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/fe_utils/simple_list.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SIMPLE_LIST_H
+#define SIMPLE_LIST_H
+
+typedef struct SimpleOidListCell
+{
+ struct SimpleOidListCell *next;
+ Oid val;
+} SimpleOidListCell;
+
+typedef struct SimpleOidList
+{
+ SimpleOidListCell *head;
+ SimpleOidListCell *tail;
+} SimpleOidList;
+
+typedef struct SimpleStringListCell
+{
+ struct SimpleStringListCell *next;
+ bool touched; /* true, when this string was searched and
+ * touched */
+ char val[FLEXIBLE_ARRAY_MEMBER]; /* null-terminated string here */
+} SimpleStringListCell;
+
+typedef struct SimpleStringList
+{
+ SimpleStringListCell *head;
+ SimpleStringListCell *tail;
+} SimpleStringList;
+
+typedef struct SimplePtrListCell
+{
+ struct SimplePtrListCell *next;
+ void *ptr;
+} SimplePtrListCell;
+
+typedef struct SimplePtrList
+{
+ SimplePtrListCell *head;
+ SimplePtrListCell *tail;
+} SimplePtrList;
+
+extern void simple_oid_list_append(SimpleOidList *list, Oid val);
+extern bool simple_oid_list_member(SimpleOidList *list, Oid val);
+extern void simple_oid_list_destroy(SimpleOidList *list);
+
+extern void simple_string_list_append(SimpleStringList *list, const char *val);
+extern bool simple_string_list_member(SimpleStringList *list, const char *val);
+extern void simple_string_list_destroy(SimpleStringList *list);
+
+extern const char *simple_string_list_not_touched(SimpleStringList *list);
+
+extern void simple_ptr_list_append(SimplePtrList *list, void *val);
+
+#endif /* SIMPLE_LIST_H */
diff --git a/src/include/fe_utils/string_utils.h b/src/include/fe_utils/string_utils.h
new file mode 100644
index 0000000..5924d32
--- /dev/null
+++ b/src/include/fe_utils/string_utils.h
@@ -0,0 +1,59 @@
+/*-------------------------------------------------------------------------
+ *
+ * String-processing utility routines for frontend code
+ *
+ * Utility functions that interpret backend output or quote strings for
+ * assorted contexts.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/fe_utils/string_utils.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef STRING_UTILS_H
+#define STRING_UTILS_H
+
+#include "libpq-fe.h"
+#include "pqexpbuffer.h"
+
+/* Global variables controlling behavior of fmtId() and fmtQualifiedId() */
+extern int quote_all_identifiers;
+extern PQExpBuffer (*getLocalPQExpBuffer) (void);
+
+/* Functions */
+extern const char *fmtId(const char *identifier);
+extern const char *fmtQualifiedId(const char *schema, const char *id);
+
+extern char *formatPGVersionNumber(int version_number, bool include_minor,
+ char *buf, size_t buflen);
+
+extern void appendStringLiteral(PQExpBuffer buf, const char *str,
+ int encoding, bool std_strings);
+extern void appendStringLiteralConn(PQExpBuffer buf, const char *str,
+ PGconn *conn);
+extern void appendStringLiteralDQ(PQExpBuffer buf, const char *str,
+ const char *dqprefix);
+extern void appendByteaLiteral(PQExpBuffer buf,
+ const unsigned char *str, size_t length,
+ bool std_strings);
+
+extern void appendShellString(PQExpBuffer buf, const char *str);
+extern bool appendShellStringNoError(PQExpBuffer buf, const char *str);
+extern void appendConnStrVal(PQExpBuffer buf, const char *str);
+extern void appendPsqlMetaConnect(PQExpBuffer buf, const char *dbname);
+
+extern bool parsePGArray(const char *atext, char ***itemarray, int *nitems);
+
+extern bool appendReloptionsArray(PQExpBuffer buffer, const char *reloptions,
+ const char *prefix, int encoding, bool std_strings);
+
+extern bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf,
+ const char *pattern,
+ bool have_where, bool force_escape,
+ const char *schemavar, const char *namevar,
+ const char *altnamevar, const char *visibilityrule);
+
+#endif /* STRING_UTILS_H */
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
new file mode 100644
index 0000000..d349510
--- /dev/null
+++ b/src/include/fmgr.h
@@ -0,0 +1,775 @@
+/*-------------------------------------------------------------------------
+ *
+ * fmgr.h
+ * Definitions for the Postgres function manager and function-call
+ * interface.
+ *
+ * This file must be included by all Postgres modules that either define
+ * or call fmgr-callable functions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/fmgr.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FMGR_H
+#define FMGR_H
+
+/* We don't want to include primnodes.h here, so make some stub references */
+typedef struct Node *fmNodePtr;
+typedef struct Aggref *fmAggrefPtr;
+
+/* Likewise, avoid including execnodes.h here */
+typedef void (*fmExprContextCallbackFunction) (Datum arg);
+
+/* Likewise, avoid including stringinfo.h here */
+typedef struct StringInfoData *fmStringInfo;
+
+
+/*
+ * All functions that can be called directly by fmgr must have this signature.
+ * (Other functions can be called by using a handler that does have this
+ * signature.)
+ */
+
+typedef struct FunctionCallInfoBaseData *FunctionCallInfo;
+
+typedef Datum (*PGFunction) (FunctionCallInfo fcinfo);
+
+/*
+ * This struct holds the system-catalog information that must be looked up
+ * before a function can be called through fmgr. If the same function is
+ * to be called multiple times, the lookup need be done only once and the
+ * info struct saved for re-use.
+ *
+ * Note that fn_expr really is parse-time-determined information about the
+ * arguments, rather than about the function itself. But it's convenient to
+ * store it here rather than in FunctionCallInfoBaseData, where it might more
+ * logically belong.
+ *
+ * fn_extra is available for use by the called function; all other fields
+ * should be treated as read-only after the struct is created.
+ */
+typedef struct FmgrInfo
+{
+ PGFunction fn_addr; /* pointer to function or handler to be called */
+ Oid fn_oid; /* OID of function (NOT of handler, if any) */
+ short fn_nargs; /* number of input args (0..FUNC_MAX_ARGS) */
+ bool fn_strict; /* function is "strict" (NULL in => NULL out) */
+ bool fn_retset; /* function returns a set */
+ unsigned char fn_stats; /* collect stats if track_functions > this */
+ void *fn_extra; /* extra space for use by handler */
+ MemoryContext fn_mcxt; /* memory context to store fn_extra in */
+ fmNodePtr fn_expr; /* expression parse tree for call, or NULL */
+} FmgrInfo;
+
+/*
+ * This struct is the data actually passed to an fmgr-called function.
+ *
+ * The called function is expected to set isnull, and possibly resultinfo or
+ * fields in whatever resultinfo points to. It should not change any other
+ * fields. (In particular, scribbling on the argument arrays is a bad idea,
+ * since some callers assume they can re-call with the same arguments.)
+ *
+ * Note that enough space for arguments needs to be provided, either by using
+ * SizeForFunctionCallInfo() in dynamic allocations, or by using
+ * LOCAL_FCINFO() for on-stack allocations.
+ *
+ * This struct is named *BaseData, rather than *Data, to break pre v12 code
+ * that allocated FunctionCallInfoData itself, as it'd often silently break
+ * old code due to no space for arguments being provided.
+ */
+typedef struct FunctionCallInfoBaseData
+{
+ FmgrInfo *flinfo; /* ptr to lookup info used for this call */
+ fmNodePtr context; /* pass info about context of call */
+ fmNodePtr resultinfo; /* pass or return extra info about result */
+ Oid fncollation; /* collation for function to use */
+#define FIELDNO_FUNCTIONCALLINFODATA_ISNULL 4
+ bool isnull; /* function must set true if result is NULL */
+ short nargs; /* # arguments actually passed */
+#define FIELDNO_FUNCTIONCALLINFODATA_ARGS 6
+ NullableDatum args[FLEXIBLE_ARRAY_MEMBER];
+} FunctionCallInfoBaseData;
+
+/*
+ * Space needed for a FunctionCallInfoBaseData struct with sufficient space
+ * for `nargs` arguments.
+ */
+#define SizeForFunctionCallInfo(nargs) \
+ (offsetof(FunctionCallInfoBaseData, args) + \
+ sizeof(NullableDatum) * (nargs))
+
+/*
+ * This macro ensures that `name` points to a stack-allocated
+ * FunctionCallInfoBaseData struct with sufficient space for `nargs` arguments.
+ */
+#define LOCAL_FCINFO(name, nargs) \
+ /* use union with FunctionCallInfoBaseData to guarantee alignment */ \
+ union \
+ { \
+ FunctionCallInfoBaseData fcinfo; \
+ /* ensure enough space for nargs args is available */ \
+ char fcinfo_data[SizeForFunctionCallInfo(nargs)]; \
+ } name##data; \
+ FunctionCallInfo name = &name##data.fcinfo
+
+/*
+ * This routine fills a FmgrInfo struct, given the OID
+ * of the function to be called.
+ */
+extern void fmgr_info(Oid functionId, FmgrInfo *finfo);
+
+/*
+ * Same, when the FmgrInfo struct is in a memory context longer-lived than
+ * CurrentMemoryContext. The specified context will be set as fn_mcxt
+ * and used to hold all subsidiary data of finfo.
+ */
+extern void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo,
+ MemoryContext mcxt);
+
+/* Convenience macro for setting the fn_expr field */
+#define fmgr_info_set_expr(expr, finfo) \
+ ((finfo)->fn_expr = (expr))
+
+/*
+ * Copy an FmgrInfo struct
+ */
+extern void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo,
+ MemoryContext destcxt);
+
+extern void fmgr_symbol(Oid functionId, char **mod, char **fn);
+
+/*
+ * This macro initializes all the fields of a FunctionCallInfoBaseData except
+ * for the args[] array.
+ */
+#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo) \
+ do { \
+ (Fcinfo).flinfo = (Flinfo); \
+ (Fcinfo).context = (Context); \
+ (Fcinfo).resultinfo = (Resultinfo); \
+ (Fcinfo).fncollation = (Collation); \
+ (Fcinfo).isnull = false; \
+ (Fcinfo).nargs = (Nargs); \
+ } while (0)
+
+/*
+ * This macro invokes a function given a filled-in FunctionCallInfoBaseData
+ * struct. The macro result is the returned Datum --- but note that
+ * caller must still check fcinfo->isnull! Also, if function is strict,
+ * it is caller's responsibility to verify that no null arguments are present
+ * before calling.
+ *
+ * Some code performs multiple calls without redoing InitFunctionCallInfoData,
+ * possibly altering the argument values. This is okay, but be sure to reset
+ * the fcinfo->isnull flag before each call, since callees are permitted to
+ * assume that starts out false.
+ */
+#define FunctionCallInvoke(fcinfo) ((* (fcinfo)->flinfo->fn_addr) (fcinfo))
+
+
+/*-------------------------------------------------------------------------
+ * Support macros to ease writing fmgr-compatible functions
+ *
+ * A C-coded fmgr-compatible function should be declared as
+ *
+ * Datum
+ * function_name(PG_FUNCTION_ARGS)
+ * {
+ * ...
+ * }
+ *
+ * It should access its arguments using appropriate PG_GETARG_xxx macros
+ * and should return its result using PG_RETURN_xxx.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* Standard parameter list for fmgr-compatible functions */
+#define PG_FUNCTION_ARGS FunctionCallInfo fcinfo
+
+/*
+ * Get collation function should use.
+ */
+#define PG_GET_COLLATION() (fcinfo->fncollation)
+
+/*
+ * Get number of arguments passed to function.
+ */
+#define PG_NARGS() (fcinfo->nargs)
+
+/*
+ * If function is not marked "proisstrict" in pg_proc, it must check for
+ * null arguments using this macro. Do not try to GETARG a null argument!
+ */
+#define PG_ARGISNULL(n) (fcinfo->args[n].isnull)
+
+/*
+ * Support for fetching detoasted copies of toastable datatypes (all of
+ * which are varlena types). pg_detoast_datum() gives you either the input
+ * datum (if not toasted) or a detoasted copy allocated with palloc().
+ * pg_detoast_datum_copy() always gives you a palloc'd copy --- use it
+ * if you need a modifiable copy of the input. Caller is expected to have
+ * checked for null inputs first, if necessary.
+ *
+ * pg_detoast_datum_packed() will return packed (1-byte header) datums
+ * unmodified. It will still expand an externally toasted or compressed datum.
+ * The resulting datum can be accessed using VARSIZE_ANY() and VARDATA_ANY()
+ * (beware of multiple evaluations in those macros!)
+ *
+ * In consumers oblivious to data alignment, call PG_DETOAST_DATUM_PACKED(),
+ * VARDATA_ANY(), VARSIZE_ANY() and VARSIZE_ANY_EXHDR(). Elsewhere, call
+ * PG_DETOAST_DATUM(), VARDATA() and VARSIZE(). Directly fetching an int16,
+ * int32 or wider field in the struct representing the datum layout requires
+ * aligned data. memcpy() is alignment-oblivious, as are most operations on
+ * datatypes, such as text, whose layout struct contains only char fields.
+ *
+ * Note: it'd be nice if these could be macros, but I see no way to do that
+ * without evaluating the arguments multiple times, which is NOT acceptable.
+ */
+extern struct varlena *pg_detoast_datum(struct varlena *datum);
+extern struct varlena *pg_detoast_datum_copy(struct varlena *datum);
+extern struct varlena *pg_detoast_datum_slice(struct varlena *datum,
+ int32 first, int32 count);
+extern struct varlena *pg_detoast_datum_packed(struct varlena *datum);
+
+#define PG_DETOAST_DATUM(datum) \
+ pg_detoast_datum((struct varlena *) DatumGetPointer(datum))
+#define PG_DETOAST_DATUM_COPY(datum) \
+ pg_detoast_datum_copy((struct varlena *) DatumGetPointer(datum))
+#define PG_DETOAST_DATUM_SLICE(datum,f,c) \
+ pg_detoast_datum_slice((struct varlena *) DatumGetPointer(datum), \
+ (int32) (f), (int32) (c))
+/* WARNING -- unaligned pointer */
+#define PG_DETOAST_DATUM_PACKED(datum) \
+ pg_detoast_datum_packed((struct varlena *) DatumGetPointer(datum))
+
+/*
+ * Support for cleaning up detoasted copies of inputs. This must only
+ * be used for pass-by-ref datatypes, and normally would only be used
+ * for toastable types. If the given pointer is different from the
+ * original argument, assume it's a palloc'd detoasted copy, and pfree it.
+ * NOTE: most functions on toastable types do not have to worry about this,
+ * but we currently require that support functions for indexes not leak
+ * memory.
+ */
+#define PG_FREE_IF_COPY(ptr,n) \
+ do { \
+ if ((Pointer) (ptr) != PG_GETARG_POINTER(n)) \
+ pfree(ptr); \
+ } while (0)
+
+/* Macros for fetching arguments of standard types */
+
+#define PG_GETARG_DATUM(n) (fcinfo->args[n].value)
+#define PG_GETARG_INT32(n) DatumGetInt32(PG_GETARG_DATUM(n))
+#define PG_GETARG_UINT32(n) DatumGetUInt32(PG_GETARG_DATUM(n))
+#define PG_GETARG_INT16(n) DatumGetInt16(PG_GETARG_DATUM(n))
+#define PG_GETARG_UINT16(n) DatumGetUInt16(PG_GETARG_DATUM(n))
+#define PG_GETARG_CHAR(n) DatumGetChar(PG_GETARG_DATUM(n))
+#define PG_GETARG_BOOL(n) DatumGetBool(PG_GETARG_DATUM(n))
+#define PG_GETARG_OID(n) DatumGetObjectId(PG_GETARG_DATUM(n))
+#define PG_GETARG_POINTER(n) DatumGetPointer(PG_GETARG_DATUM(n))
+#define PG_GETARG_CSTRING(n) DatumGetCString(PG_GETARG_DATUM(n))
+#define PG_GETARG_NAME(n) DatumGetName(PG_GETARG_DATUM(n))
+/* these macros hide the pass-by-reference-ness of the datatype: */
+#define PG_GETARG_FLOAT4(n) DatumGetFloat4(PG_GETARG_DATUM(n))
+#define PG_GETARG_FLOAT8(n) DatumGetFloat8(PG_GETARG_DATUM(n))
+#define PG_GETARG_INT64(n) DatumGetInt64(PG_GETARG_DATUM(n))
+/* use this if you want the raw, possibly-toasted input datum: */
+#define PG_GETARG_RAW_VARLENA_P(n) ((struct varlena *) PG_GETARG_POINTER(n))
+/* use this if you want the input datum de-toasted: */
+#define PG_GETARG_VARLENA_P(n) PG_DETOAST_DATUM(PG_GETARG_DATUM(n))
+/* and this if you can handle 1-byte-header datums: */
+#define PG_GETARG_VARLENA_PP(n) PG_DETOAST_DATUM_PACKED(PG_GETARG_DATUM(n))
+/* DatumGetFoo macros for varlena types will typically look like this: */
+#define DatumGetByteaPP(X) ((bytea *) PG_DETOAST_DATUM_PACKED(X))
+#define DatumGetTextPP(X) ((text *) PG_DETOAST_DATUM_PACKED(X))
+#define DatumGetBpCharPP(X) ((BpChar *) PG_DETOAST_DATUM_PACKED(X))
+#define DatumGetVarCharPP(X) ((VarChar *) PG_DETOAST_DATUM_PACKED(X))
+#define DatumGetHeapTupleHeader(X) ((HeapTupleHeader) PG_DETOAST_DATUM(X))
+/* And we also offer variants that return an OK-to-write copy */
+#define DatumGetByteaPCopy(X) ((bytea *) PG_DETOAST_DATUM_COPY(X))
+#define DatumGetTextPCopy(X) ((text *) PG_DETOAST_DATUM_COPY(X))
+#define DatumGetBpCharPCopy(X) ((BpChar *) PG_DETOAST_DATUM_COPY(X))
+#define DatumGetVarCharPCopy(X) ((VarChar *) PG_DETOAST_DATUM_COPY(X))
+#define DatumGetHeapTupleHeaderCopy(X) ((HeapTupleHeader) PG_DETOAST_DATUM_COPY(X))
+/* Variants which return n bytes starting at pos. m */
+#define DatumGetByteaPSlice(X,m,n) ((bytea *) PG_DETOAST_DATUM_SLICE(X,m,n))
+#define DatumGetTextPSlice(X,m,n) ((text *) PG_DETOAST_DATUM_SLICE(X,m,n))
+#define DatumGetBpCharPSlice(X,m,n) ((BpChar *) PG_DETOAST_DATUM_SLICE(X,m,n))
+#define DatumGetVarCharPSlice(X,m,n) ((VarChar *) PG_DETOAST_DATUM_SLICE(X,m,n))
+/* GETARG macros for varlena types will typically look like this: */
+#define PG_GETARG_BYTEA_PP(n) DatumGetByteaPP(PG_GETARG_DATUM(n))
+#define PG_GETARG_TEXT_PP(n) DatumGetTextPP(PG_GETARG_DATUM(n))
+#define PG_GETARG_BPCHAR_PP(n) DatumGetBpCharPP(PG_GETARG_DATUM(n))
+#define PG_GETARG_VARCHAR_PP(n) DatumGetVarCharPP(PG_GETARG_DATUM(n))
+#define PG_GETARG_HEAPTUPLEHEADER(n) DatumGetHeapTupleHeader(PG_GETARG_DATUM(n))
+/* And we also offer variants that return an OK-to-write copy */
+#define PG_GETARG_BYTEA_P_COPY(n) DatumGetByteaPCopy(PG_GETARG_DATUM(n))
+#define PG_GETARG_TEXT_P_COPY(n) DatumGetTextPCopy(PG_GETARG_DATUM(n))
+#define PG_GETARG_BPCHAR_P_COPY(n) DatumGetBpCharPCopy(PG_GETARG_DATUM(n))
+#define PG_GETARG_VARCHAR_P_COPY(n) DatumGetVarCharPCopy(PG_GETARG_DATUM(n))
+#define PG_GETARG_HEAPTUPLEHEADER_COPY(n) DatumGetHeapTupleHeaderCopy(PG_GETARG_DATUM(n))
+/* And a b-byte slice from position a -also OK to write */
+#define PG_GETARG_BYTEA_P_SLICE(n,a,b) DatumGetByteaPSlice(PG_GETARG_DATUM(n),a,b)
+#define PG_GETARG_TEXT_P_SLICE(n,a,b) DatumGetTextPSlice(PG_GETARG_DATUM(n),a,b)
+#define PG_GETARG_BPCHAR_P_SLICE(n,a,b) DatumGetBpCharPSlice(PG_GETARG_DATUM(n),a,b)
+#define PG_GETARG_VARCHAR_P_SLICE(n,a,b) DatumGetVarCharPSlice(PG_GETARG_DATUM(n),a,b)
+/*
+ * Obsolescent variants that guarantee INT alignment for the return value.
+ * Few operations on these particular types need alignment, mainly operations
+ * that cast the VARDATA pointer to a type like int16[]. Most code should use
+ * the ...PP(X) counterpart. Nonetheless, these appear frequently in code
+ * predating the PostgreSQL 8.3 introduction of the ...PP(X) variants.
+ */
+#define DatumGetByteaP(X) ((bytea *) PG_DETOAST_DATUM(X))
+#define DatumGetTextP(X) ((text *) PG_DETOAST_DATUM(X))
+#define DatumGetBpCharP(X) ((BpChar *) PG_DETOAST_DATUM(X))
+#define DatumGetVarCharP(X) ((VarChar *) PG_DETOAST_DATUM(X))
+#define PG_GETARG_BYTEA_P(n) DatumGetByteaP(PG_GETARG_DATUM(n))
+#define PG_GETARG_TEXT_P(n) DatumGetTextP(PG_GETARG_DATUM(n))
+#define PG_GETARG_BPCHAR_P(n) DatumGetBpCharP(PG_GETARG_DATUM(n))
+#define PG_GETARG_VARCHAR_P(n) DatumGetVarCharP(PG_GETARG_DATUM(n))
+
+/* To access options from opclass support functions use this: */
+#define PG_HAS_OPCLASS_OPTIONS() has_fn_opclass_options(fcinfo->flinfo)
+#define PG_GET_OPCLASS_OPTIONS() get_fn_opclass_options(fcinfo->flinfo)
+
+/* To return a NULL do this: */
+#define PG_RETURN_NULL() \
+ do { fcinfo->isnull = true; return (Datum) 0; } while (0)
+
+/* A few internal functions return void (which is not the same as NULL!) */
+#define PG_RETURN_VOID() return (Datum) 0
+
+/* Macros for returning results of standard types */
+
+#define PG_RETURN_DATUM(x) return (x)
+#define PG_RETURN_INT32(x) return Int32GetDatum(x)
+#define PG_RETURN_UINT32(x) return UInt32GetDatum(x)
+#define PG_RETURN_INT16(x) return Int16GetDatum(x)
+#define PG_RETURN_UINT16(x) return UInt16GetDatum(x)
+#define PG_RETURN_CHAR(x) return CharGetDatum(x)
+#define PG_RETURN_BOOL(x) return BoolGetDatum(x)
+#define PG_RETURN_OID(x) return ObjectIdGetDatum(x)
+#define PG_RETURN_POINTER(x) return PointerGetDatum(x)
+#define PG_RETURN_CSTRING(x) return CStringGetDatum(x)
+#define PG_RETURN_NAME(x) return NameGetDatum(x)
+/* these macros hide the pass-by-reference-ness of the datatype: */
+#define PG_RETURN_FLOAT4(x) return Float4GetDatum(x)
+#define PG_RETURN_FLOAT8(x) return Float8GetDatum(x)
+#define PG_RETURN_INT64(x) return Int64GetDatum(x)
+#define PG_RETURN_UINT64(x) return UInt64GetDatum(x)
+/* RETURN macros for other pass-by-ref types will typically look like this: */
+#define PG_RETURN_BYTEA_P(x) PG_RETURN_POINTER(x)
+#define PG_RETURN_TEXT_P(x) PG_RETURN_POINTER(x)
+#define PG_RETURN_BPCHAR_P(x) PG_RETURN_POINTER(x)
+#define PG_RETURN_VARCHAR_P(x) PG_RETURN_POINTER(x)
+#define PG_RETURN_HEAPTUPLEHEADER(x) return HeapTupleHeaderGetDatum(x)
+
+
+/*-------------------------------------------------------------------------
+ * Support for detecting call convention of dynamically-loaded functions
+ *
+ * Dynamically loaded functions currently can only use the version-1 ("new
+ * style") calling convention. Version-0 ("old style") is not supported
+ * anymore. Version 1 is the call convention defined in this header file, and
+ * must be accompanied by the macro call
+ *
+ * PG_FUNCTION_INFO_V1(function_name);
+ *
+ * Note that internal functions do not need this decoration since they are
+ * assumed to be version-1.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+typedef struct
+{
+ int api_version; /* specifies call convention version number */
+ /* More fields may be added later, for version numbers > 1. */
+} Pg_finfo_record;
+
+/* Expected signature of an info function */
+typedef const Pg_finfo_record *(*PGFInfoFunction) (void);
+
+/*
+ * Macro to build an info function associated with the given function name.
+ *
+ * As a convenience, also provide an "extern" declaration for the given
+ * function name, so that writers of C functions need not write that too.
+ *
+ * On Windows, the function and info function must be exported. Our normal
+ * build processes take care of that via .DEF files or --export-all-symbols.
+ * Module authors using a different build process might need to manually
+ * declare the function PGDLLEXPORT. We do that automatically here for the
+ * info function, since authors shouldn't need to be explicitly aware of it.
+ */
+#define PG_FUNCTION_INFO_V1(funcname) \
+extern Datum funcname(PG_FUNCTION_ARGS); \
+extern PGDLLEXPORT const Pg_finfo_record * CppConcat(pg_finfo_,funcname)(void); \
+const Pg_finfo_record * \
+CppConcat(pg_finfo_,funcname) (void) \
+{ \
+ static const Pg_finfo_record my_finfo = { 1 }; \
+ return &my_finfo; \
+} \
+extern int no_such_variable
+
+
+/*-------------------------------------------------------------------------
+ * Support for verifying backend compatibility of loaded modules
+ *
+ * We require dynamically-loaded modules to include the macro call
+ * PG_MODULE_MAGIC;
+ * so that we can check for obvious incompatibility, such as being compiled
+ * for a different major PostgreSQL version.
+ *
+ * To compile with versions of PostgreSQL that do not support this,
+ * you may put an #ifdef/#endif test around it. Note that in a multiple-
+ * source-file module, the macro call should only appear once.
+ *
+ * The specific items included in the magic block are intended to be ones that
+ * are custom-configurable and especially likely to break dynamically loaded
+ * modules if they were compiled with other values. Also, the length field
+ * can be used to detect definition changes.
+ *
+ * Note: we compare magic blocks with memcmp(), so there had better not be
+ * any alignment pad bytes in them.
+ *
+ * Note: when changing the contents of magic blocks, be sure to adjust the
+ * incompatible_module_error() function in dfmgr.c.
+ *-------------------------------------------------------------------------
+ */
+
+/* Definition of the magic block structure */
+typedef struct
+{
+ int len; /* sizeof(this struct) */
+ int version; /* PostgreSQL major version */
+ int funcmaxargs; /* FUNC_MAX_ARGS */
+ int indexmaxkeys; /* INDEX_MAX_KEYS */
+ int namedatalen; /* NAMEDATALEN */
+ int float8byval; /* FLOAT8PASSBYVAL */
+} Pg_magic_struct;
+
+/* The actual data block contents */
+#define PG_MODULE_MAGIC_DATA \
+{ \
+ sizeof(Pg_magic_struct), \
+ PG_VERSION_NUM / 100, \
+ FUNC_MAX_ARGS, \
+ INDEX_MAX_KEYS, \
+ NAMEDATALEN, \
+ FLOAT8PASSBYVAL \
+}
+
+/*
+ * Declare the module magic function. It needs to be a function as the dlsym
+ * in the backend is only guaranteed to work on functions, not data
+ */
+typedef const Pg_magic_struct *(*PGModuleMagicFunction) (void);
+
+#define PG_MAGIC_FUNCTION_NAME Pg_magic_func
+#define PG_MAGIC_FUNCTION_NAME_STRING "Pg_magic_func"
+
+#define PG_MODULE_MAGIC \
+extern PGDLLEXPORT const Pg_magic_struct *PG_MAGIC_FUNCTION_NAME(void); \
+const Pg_magic_struct * \
+PG_MAGIC_FUNCTION_NAME(void) \
+{ \
+ static const Pg_magic_struct Pg_magic_data = PG_MODULE_MAGIC_DATA; \
+ return &Pg_magic_data; \
+} \
+extern int no_such_variable
+
+
+/*-------------------------------------------------------------------------
+ * Support routines and macros for callers of fmgr-compatible functions
+ *-------------------------------------------------------------------------
+ */
+
+/* These are for invocation of a specifically named function with a
+ * directly-computed parameter list. Note that neither arguments nor result
+ * are allowed to be NULL. Also, the function cannot be one that needs to
+ * look at FmgrInfo, since there won't be any.
+ */
+extern Datum DirectFunctionCall1Coll(PGFunction func, Oid collation,
+ Datum arg1);
+extern Datum DirectFunctionCall2Coll(PGFunction func, Oid collation,
+ Datum arg1, Datum arg2);
+extern Datum DirectFunctionCall3Coll(PGFunction func, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3);
+extern Datum DirectFunctionCall4Coll(PGFunction func, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4);
+extern Datum DirectFunctionCall5Coll(PGFunction func, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5);
+extern Datum DirectFunctionCall6Coll(PGFunction func, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6);
+extern Datum DirectFunctionCall7Coll(PGFunction func, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6, Datum arg7);
+extern Datum DirectFunctionCall8Coll(PGFunction func, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6, Datum arg7, Datum arg8);
+extern Datum DirectFunctionCall9Coll(PGFunction func, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6, Datum arg7, Datum arg8,
+ Datum arg9);
+
+/*
+ * These functions work like the DirectFunctionCall functions except that
+ * they use the flinfo parameter to initialise the fcinfo for the call.
+ * It's recommended that the callee only use the fn_extra and fn_mcxt
+ * fields, as other fields will typically describe the calling function
+ * not the callee. Conversely, the calling function should not have
+ * used fn_extra, unless its use is known to be compatible with the callee's.
+ */
+extern Datum CallerFInfoFunctionCall1(PGFunction func, FmgrInfo *flinfo,
+ Oid collation, Datum arg1);
+extern Datum CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo,
+ Oid collation, Datum arg1, Datum arg2);
+
+/* These are for invocation of a previously-looked-up function with a
+ * directly-computed parameter list. Note that neither arguments nor result
+ * are allowed to be NULL.
+ */
+extern Datum FunctionCall0Coll(FmgrInfo *flinfo, Oid collation);
+extern Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation,
+ Datum arg1);
+extern Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation,
+ Datum arg1, Datum arg2);
+extern Datum FunctionCall3Coll(FmgrInfo *flinfo, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3);
+extern Datum FunctionCall4Coll(FmgrInfo *flinfo, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4);
+extern Datum FunctionCall5Coll(FmgrInfo *flinfo, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5);
+extern Datum FunctionCall6Coll(FmgrInfo *flinfo, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6);
+extern Datum FunctionCall7Coll(FmgrInfo *flinfo, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6, Datum arg7);
+extern Datum FunctionCall8Coll(FmgrInfo *flinfo, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6, Datum arg7, Datum arg8);
+extern Datum FunctionCall9Coll(FmgrInfo *flinfo, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6, Datum arg7, Datum arg8,
+ Datum arg9);
+
+/* These are for invocation of a function identified by OID with a
+ * directly-computed parameter list. Note that neither arguments nor result
+ * are allowed to be NULL. These are essentially fmgr_info() followed by
+ * FunctionCallN(). If the same function is to be invoked repeatedly, do the
+ * fmgr_info() once and then use FunctionCallN().
+ */
+extern Datum OidFunctionCall0Coll(Oid functionId, Oid collation);
+extern Datum OidFunctionCall1Coll(Oid functionId, Oid collation,
+ Datum arg1);
+extern Datum OidFunctionCall2Coll(Oid functionId, Oid collation,
+ Datum arg1, Datum arg2);
+extern Datum OidFunctionCall3Coll(Oid functionId, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3);
+extern Datum OidFunctionCall4Coll(Oid functionId, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4);
+extern Datum OidFunctionCall5Coll(Oid functionId, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5);
+extern Datum OidFunctionCall6Coll(Oid functionId, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6);
+extern Datum OidFunctionCall7Coll(Oid functionId, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6, Datum arg7);
+extern Datum OidFunctionCall8Coll(Oid functionId, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6, Datum arg7, Datum arg8);
+extern Datum OidFunctionCall9Coll(Oid functionId, Oid collation,
+ Datum arg1, Datum arg2,
+ Datum arg3, Datum arg4, Datum arg5,
+ Datum arg6, Datum arg7, Datum arg8,
+ Datum arg9);
+
+/* These macros allow the collation argument to be omitted (with a default of
+ * InvalidOid, ie, no collation). They exist mostly for backwards
+ * compatibility of source code.
+ */
+#define DirectFunctionCall1(func, arg1) \
+ DirectFunctionCall1Coll(func, InvalidOid, arg1)
+#define DirectFunctionCall2(func, arg1, arg2) \
+ DirectFunctionCall2Coll(func, InvalidOid, arg1, arg2)
+#define DirectFunctionCall3(func, arg1, arg2, arg3) \
+ DirectFunctionCall3Coll(func, InvalidOid, arg1, arg2, arg3)
+#define DirectFunctionCall4(func, arg1, arg2, arg3, arg4) \
+ DirectFunctionCall4Coll(func, InvalidOid, arg1, arg2, arg3, arg4)
+#define DirectFunctionCall5(func, arg1, arg2, arg3, arg4, arg5) \
+ DirectFunctionCall5Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5)
+#define DirectFunctionCall6(func, arg1, arg2, arg3, arg4, arg5, arg6) \
+ DirectFunctionCall6Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6)
+#define DirectFunctionCall7(func, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
+ DirectFunctionCall7Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
+#define DirectFunctionCall8(func, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
+ DirectFunctionCall8Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
+#define DirectFunctionCall9(func, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
+ DirectFunctionCall9Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
+#define FunctionCall1(flinfo, arg1) \
+ FunctionCall1Coll(flinfo, InvalidOid, arg1)
+#define FunctionCall2(flinfo, arg1, arg2) \
+ FunctionCall2Coll(flinfo, InvalidOid, arg1, arg2)
+#define FunctionCall3(flinfo, arg1, arg2, arg3) \
+ FunctionCall3Coll(flinfo, InvalidOid, arg1, arg2, arg3)
+#define FunctionCall4(flinfo, arg1, arg2, arg3, arg4) \
+ FunctionCall4Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4)
+#define FunctionCall5(flinfo, arg1, arg2, arg3, arg4, arg5) \
+ FunctionCall5Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5)
+#define FunctionCall6(flinfo, arg1, arg2, arg3, arg4, arg5, arg6) \
+ FunctionCall6Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6)
+#define FunctionCall7(flinfo, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
+ FunctionCall7Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
+#define FunctionCall8(flinfo, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
+ FunctionCall8Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
+#define FunctionCall9(flinfo, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
+ FunctionCall9Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
+#define OidFunctionCall0(functionId) \
+ OidFunctionCall0Coll(functionId, InvalidOid)
+#define OidFunctionCall1(functionId, arg1) \
+ OidFunctionCall1Coll(functionId, InvalidOid, arg1)
+#define OidFunctionCall2(functionId, arg1, arg2) \
+ OidFunctionCall2Coll(functionId, InvalidOid, arg1, arg2)
+#define OidFunctionCall3(functionId, arg1, arg2, arg3) \
+ OidFunctionCall3Coll(functionId, InvalidOid, arg1, arg2, arg3)
+#define OidFunctionCall4(functionId, arg1, arg2, arg3, arg4) \
+ OidFunctionCall4Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4)
+#define OidFunctionCall5(functionId, arg1, arg2, arg3, arg4, arg5) \
+ OidFunctionCall5Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5)
+#define OidFunctionCall6(functionId, arg1, arg2, arg3, arg4, arg5, arg6) \
+ OidFunctionCall6Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6)
+#define OidFunctionCall7(functionId, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
+ OidFunctionCall7Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
+#define OidFunctionCall8(functionId, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
+ OidFunctionCall8Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
+#define OidFunctionCall9(functionId, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
+ OidFunctionCall9Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
+
+
+/* Special cases for convenient invocation of datatype I/O functions. */
+extern Datum InputFunctionCall(FmgrInfo *flinfo, char *str,
+ Oid typioparam, int32 typmod);
+extern Datum OidInputFunctionCall(Oid functionId, char *str,
+ Oid typioparam, int32 typmod);
+extern char *OutputFunctionCall(FmgrInfo *flinfo, Datum val);
+extern char *OidOutputFunctionCall(Oid functionId, Datum val);
+extern Datum ReceiveFunctionCall(FmgrInfo *flinfo, fmStringInfo buf,
+ Oid typioparam, int32 typmod);
+extern Datum OidReceiveFunctionCall(Oid functionId, fmStringInfo buf,
+ Oid typioparam, int32 typmod);
+extern bytea *SendFunctionCall(FmgrInfo *flinfo, Datum val);
+extern bytea *OidSendFunctionCall(Oid functionId, Datum val);
+
+
+/*
+ * Routines in fmgr.c
+ */
+extern const Pg_finfo_record *fetch_finfo_record(void *filehandle, const char *funcname);
+extern void clear_external_function_hash(void *filehandle);
+extern Oid fmgr_internal_function(const char *proname);
+extern Oid get_fn_expr_rettype(FmgrInfo *flinfo);
+extern Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum);
+extern Oid get_call_expr_argtype(fmNodePtr expr, int argnum);
+extern bool get_fn_expr_arg_stable(FmgrInfo *flinfo, int argnum);
+extern bool get_call_expr_arg_stable(fmNodePtr expr, int argnum);
+extern bool get_fn_expr_variadic(FmgrInfo *flinfo);
+extern bytea *get_fn_opclass_options(FmgrInfo *flinfo);
+extern bool has_fn_opclass_options(FmgrInfo *flinfo);
+extern void set_fn_opclass_options(FmgrInfo *flinfo, bytea *options);
+extern bool CheckFunctionValidatorAccess(Oid validatorOid, Oid functionOid);
+
+/*
+ * Routines in dfmgr.c
+ */
+extern char *Dynamic_library_path;
+
+extern PGFunction load_external_function(const char *filename, const char *funcname,
+ bool signalNotFound, void **filehandle);
+extern PGFunction lookup_external_function(void *filehandle, const char *funcname);
+extern void load_file(const char *filename, bool restricted);
+extern void **find_rendezvous_variable(const char *varName);
+extern Size EstimateLibraryStateSpace(void);
+extern void SerializeLibraryState(Size maxsize, char *start_address);
+extern void RestoreLibraryState(char *start_address);
+
+/*
+ * Support for aggregate functions
+ *
+ * These are actually in executor/nodeAgg.c, but we declare them here since
+ * the whole point is for callers to not be overly friendly with nodeAgg.
+ */
+
+/* AggCheckCallContext can return one of the following codes, or 0: */
+#define AGG_CONTEXT_AGGREGATE 1 /* regular aggregate */
+#define AGG_CONTEXT_WINDOW 2 /* window function */
+
+extern int AggCheckCallContext(FunctionCallInfo fcinfo,
+ MemoryContext *aggcontext);
+extern fmAggrefPtr AggGetAggref(FunctionCallInfo fcinfo);
+extern MemoryContext AggGetTempMemoryContext(FunctionCallInfo fcinfo);
+extern bool AggStateIsShared(FunctionCallInfo fcinfo);
+extern void AggRegisterCallback(FunctionCallInfo fcinfo,
+ fmExprContextCallbackFunction func,
+ Datum arg);
+
+/*
+ * We allow plugin modules to hook function entry/exit. This is intended
+ * as support for loadable security policy modules, which may want to
+ * perform additional privilege checks on function entry or exit, or to do
+ * other internal bookkeeping. To make this possible, such modules must be
+ * able not only to support normal function entry and exit, but also to trap
+ * the case where we bail out due to an error; and they must also be able to
+ * prevent inlining.
+ */
+typedef enum FmgrHookEventType
+{
+ FHET_START,
+ FHET_END,
+ FHET_ABORT
+} FmgrHookEventType;
+
+typedef bool (*needs_fmgr_hook_type) (Oid fn_oid);
+
+typedef void (*fmgr_hook_type) (FmgrHookEventType event,
+ FmgrInfo *flinfo, Datum *arg);
+
+extern PGDLLIMPORT needs_fmgr_hook_type needs_fmgr_hook;
+extern PGDLLIMPORT fmgr_hook_type fmgr_hook;
+
+#define FmgrHookIsNeeded(fn_oid) \
+ (!needs_fmgr_hook ? false : (*needs_fmgr_hook)(fn_oid))
+
+#endif /* FMGR_H */
diff --git a/src/include/foreign/fdwapi.h b/src/include/foreign/fdwapi.h
new file mode 100644
index 0000000..95556df
--- /dev/null
+++ b/src/include/foreign/fdwapi.h
@@ -0,0 +1,262 @@
+/*-------------------------------------------------------------------------
+ *
+ * fdwapi.h
+ * API for foreign-data wrappers
+ *
+ * Copyright (c) 2010-2020, PostgreSQL Global Development Group
+ *
+ * src/include/foreign/fdwapi.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FDWAPI_H
+#define FDWAPI_H
+
+#include "access/parallel.h"
+#include "nodes/execnodes.h"
+#include "nodes/pathnodes.h"
+
+/* To avoid including explain.h here, reference ExplainState thus: */
+struct ExplainState;
+
+
+/*
+ * Callback function signatures --- see fdwhandler.sgml for more info.
+ */
+
+typedef void (*GetForeignRelSize_function) (PlannerInfo *root,
+ RelOptInfo *baserel,
+ Oid foreigntableid);
+
+typedef void (*GetForeignPaths_function) (PlannerInfo *root,
+ RelOptInfo *baserel,
+ Oid foreigntableid);
+
+typedef ForeignScan *(*GetForeignPlan_function) (PlannerInfo *root,
+ RelOptInfo *baserel,
+ Oid foreigntableid,
+ ForeignPath *best_path,
+ List *tlist,
+ List *scan_clauses,
+ Plan *outer_plan);
+
+typedef void (*BeginForeignScan_function) (ForeignScanState *node,
+ int eflags);
+
+typedef TupleTableSlot *(*IterateForeignScan_function) (ForeignScanState *node);
+
+typedef bool (*RecheckForeignScan_function) (ForeignScanState *node,
+ TupleTableSlot *slot);
+
+typedef void (*ReScanForeignScan_function) (ForeignScanState *node);
+
+typedef void (*EndForeignScan_function) (ForeignScanState *node);
+
+typedef void (*GetForeignJoinPaths_function) (PlannerInfo *root,
+ RelOptInfo *joinrel,
+ RelOptInfo *outerrel,
+ RelOptInfo *innerrel,
+ JoinType jointype,
+ JoinPathExtraData *extra);
+
+typedef void (*GetForeignUpperPaths_function) (PlannerInfo *root,
+ UpperRelationKind stage,
+ RelOptInfo *input_rel,
+ RelOptInfo *output_rel,
+ void *extra);
+
+typedef void (*AddForeignUpdateTargets_function) (Query *parsetree,
+ RangeTblEntry *target_rte,
+ Relation target_relation);
+
+typedef List *(*PlanForeignModify_function) (PlannerInfo *root,
+ ModifyTable *plan,
+ Index resultRelation,
+ int subplan_index);
+
+typedef void (*BeginForeignModify_function) (ModifyTableState *mtstate,
+ ResultRelInfo *rinfo,
+ List *fdw_private,
+ int subplan_index,
+ int eflags);
+
+typedef TupleTableSlot *(*ExecForeignInsert_function) (EState *estate,
+ ResultRelInfo *rinfo,
+ TupleTableSlot *slot,
+ TupleTableSlot *planSlot);
+
+typedef TupleTableSlot *(*ExecForeignUpdate_function) (EState *estate,
+ ResultRelInfo *rinfo,
+ TupleTableSlot *slot,
+ TupleTableSlot *planSlot);
+
+typedef TupleTableSlot *(*ExecForeignDelete_function) (EState *estate,
+ ResultRelInfo *rinfo,
+ TupleTableSlot *slot,
+ TupleTableSlot *planSlot);
+
+typedef void (*EndForeignModify_function) (EState *estate,
+ ResultRelInfo *rinfo);
+
+typedef void (*BeginForeignInsert_function) (ModifyTableState *mtstate,
+ ResultRelInfo *rinfo);
+
+typedef void (*EndForeignInsert_function) (EState *estate,
+ ResultRelInfo *rinfo);
+
+typedef int (*IsForeignRelUpdatable_function) (Relation rel);
+
+typedef bool (*PlanDirectModify_function) (PlannerInfo *root,
+ ModifyTable *plan,
+ Index resultRelation,
+ int subplan_index);
+
+typedef void (*BeginDirectModify_function) (ForeignScanState *node,
+ int eflags);
+
+typedef TupleTableSlot *(*IterateDirectModify_function) (ForeignScanState *node);
+
+typedef void (*EndDirectModify_function) (ForeignScanState *node);
+
+typedef RowMarkType (*GetForeignRowMarkType_function) (RangeTblEntry *rte,
+ LockClauseStrength strength);
+
+typedef void (*RefetchForeignRow_function) (EState *estate,
+ ExecRowMark *erm,
+ Datum rowid,
+ TupleTableSlot *slot,
+ bool *updated);
+
+typedef void (*ExplainForeignScan_function) (ForeignScanState *node,
+ struct ExplainState *es);
+
+typedef void (*ExplainForeignModify_function) (ModifyTableState *mtstate,
+ ResultRelInfo *rinfo,
+ List *fdw_private,
+ int subplan_index,
+ struct ExplainState *es);
+
+typedef void (*ExplainDirectModify_function) (ForeignScanState *node,
+ struct ExplainState *es);
+
+typedef int (*AcquireSampleRowsFunc) (Relation relation, int elevel,
+ HeapTuple *rows, int targrows,
+ double *totalrows,
+ double *totaldeadrows);
+
+typedef bool (*AnalyzeForeignTable_function) (Relation relation,
+ AcquireSampleRowsFunc *func,
+ BlockNumber *totalpages);
+
+typedef List *(*ImportForeignSchema_function) (ImportForeignSchemaStmt *stmt,
+ Oid serverOid);
+
+typedef Size (*EstimateDSMForeignScan_function) (ForeignScanState *node,
+ ParallelContext *pcxt);
+typedef void (*InitializeDSMForeignScan_function) (ForeignScanState *node,
+ ParallelContext *pcxt,
+ void *coordinate);
+typedef void (*ReInitializeDSMForeignScan_function) (ForeignScanState *node,
+ ParallelContext *pcxt,
+ void *coordinate);
+typedef void (*InitializeWorkerForeignScan_function) (ForeignScanState *node,
+ shm_toc *toc,
+ void *coordinate);
+typedef void (*ShutdownForeignScan_function) (ForeignScanState *node);
+typedef bool (*IsForeignScanParallelSafe_function) (PlannerInfo *root,
+ RelOptInfo *rel,
+ RangeTblEntry *rte);
+typedef List *(*ReparameterizeForeignPathByChild_function) (PlannerInfo *root,
+ List *fdw_private,
+ RelOptInfo *child_rel);
+
+/*
+ * FdwRoutine is the struct returned by a foreign-data wrapper's handler
+ * function. It provides pointers to the callback functions needed by the
+ * planner and executor.
+ *
+ * More function pointers are likely to be added in the future. Therefore
+ * it's recommended that the handler initialize the struct with
+ * makeNode(FdwRoutine) so that all fields are set to NULL. This will
+ * ensure that no fields are accidentally left undefined.
+ */
+typedef struct FdwRoutine
+{
+ NodeTag type;
+
+ /* Functions for scanning foreign tables */
+ GetForeignRelSize_function GetForeignRelSize;
+ GetForeignPaths_function GetForeignPaths;
+ GetForeignPlan_function GetForeignPlan;
+ BeginForeignScan_function BeginForeignScan;
+ IterateForeignScan_function IterateForeignScan;
+ ReScanForeignScan_function ReScanForeignScan;
+ EndForeignScan_function EndForeignScan;
+
+ /*
+ * Remaining functions are optional. Set the pointer to NULL for any that
+ * are not provided.
+ */
+
+ /* Functions for remote-join planning */
+ GetForeignJoinPaths_function GetForeignJoinPaths;
+
+ /* Functions for remote upper-relation (post scan/join) planning */
+ GetForeignUpperPaths_function GetForeignUpperPaths;
+
+ /* Functions for updating foreign tables */
+ AddForeignUpdateTargets_function AddForeignUpdateTargets;
+ PlanForeignModify_function PlanForeignModify;
+ BeginForeignModify_function BeginForeignModify;
+ ExecForeignInsert_function ExecForeignInsert;
+ ExecForeignUpdate_function ExecForeignUpdate;
+ ExecForeignDelete_function ExecForeignDelete;
+ EndForeignModify_function EndForeignModify;
+ BeginForeignInsert_function BeginForeignInsert;
+ EndForeignInsert_function EndForeignInsert;
+ IsForeignRelUpdatable_function IsForeignRelUpdatable;
+ PlanDirectModify_function PlanDirectModify;
+ BeginDirectModify_function BeginDirectModify;
+ IterateDirectModify_function IterateDirectModify;
+ EndDirectModify_function EndDirectModify;
+
+ /* Functions for SELECT FOR UPDATE/SHARE row locking */
+ GetForeignRowMarkType_function GetForeignRowMarkType;
+ RefetchForeignRow_function RefetchForeignRow;
+ RecheckForeignScan_function RecheckForeignScan;
+
+ /* Support functions for EXPLAIN */
+ ExplainForeignScan_function ExplainForeignScan;
+ ExplainForeignModify_function ExplainForeignModify;
+ ExplainDirectModify_function ExplainDirectModify;
+
+ /* Support functions for ANALYZE */
+ AnalyzeForeignTable_function AnalyzeForeignTable;
+
+ /* Support functions for IMPORT FOREIGN SCHEMA */
+ ImportForeignSchema_function ImportForeignSchema;
+
+ /* Support functions for parallelism under Gather node */
+ IsForeignScanParallelSafe_function IsForeignScanParallelSafe;
+ EstimateDSMForeignScan_function EstimateDSMForeignScan;
+ InitializeDSMForeignScan_function InitializeDSMForeignScan;
+ ReInitializeDSMForeignScan_function ReInitializeDSMForeignScan;
+ InitializeWorkerForeignScan_function InitializeWorkerForeignScan;
+ ShutdownForeignScan_function ShutdownForeignScan;
+
+ /* Support functions for path reparameterization. */
+ ReparameterizeForeignPathByChild_function ReparameterizeForeignPathByChild;
+} FdwRoutine;
+
+
+/* Functions in foreign/foreign.c */
+extern FdwRoutine *GetFdwRoutine(Oid fdwhandler);
+extern Oid GetForeignServerIdByRelId(Oid relid);
+extern FdwRoutine *GetFdwRoutineByServerId(Oid serverid);
+extern FdwRoutine *GetFdwRoutineByRelId(Oid relid);
+extern FdwRoutine *GetFdwRoutineForRelation(Relation relation, bool makecopy);
+extern bool IsImportableForeignTable(const char *tablename,
+ ImportForeignSchemaStmt *stmt);
+extern Path *GetExistingLocalJoinPath(RelOptInfo *joinrel);
+
+#endif /* FDWAPI_H */
diff --git a/src/include/foreign/foreign.h b/src/include/foreign/foreign.h
new file mode 100644
index 0000000..5e0cf53
--- /dev/null
+++ b/src/include/foreign/foreign.h
@@ -0,0 +1,84 @@
+/*-------------------------------------------------------------------------
+ *
+ * foreign.h
+ * support for foreign-data wrappers, servers and user mappings.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ *
+ * src/include/foreign/foreign.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FOREIGN_H
+#define FOREIGN_H
+
+#include "nodes/parsenodes.h"
+
+
+/* Helper for obtaining username for user mapping */
+#define MappingUserName(userid) \
+ (OidIsValid(userid) ? GetUserNameFromId(userid, false) : "public")
+
+
+typedef struct ForeignDataWrapper
+{
+ Oid fdwid; /* FDW Oid */
+ Oid owner; /* FDW owner user Oid */
+ char *fdwname; /* Name of the FDW */
+ Oid fdwhandler; /* Oid of handler function, or 0 */
+ Oid fdwvalidator; /* Oid of validator function, or 0 */
+ List *options; /* fdwoptions as DefElem list */
+} ForeignDataWrapper;
+
+typedef struct ForeignServer
+{
+ Oid serverid; /* server Oid */
+ Oid fdwid; /* foreign-data wrapper */
+ Oid owner; /* server owner user Oid */
+ char *servername; /* name of the server */
+ char *servertype; /* server type, optional */
+ char *serverversion; /* server version, optional */
+ List *options; /* srvoptions as DefElem list */
+} ForeignServer;
+
+typedef struct UserMapping
+{
+ Oid umid; /* Oid of user mapping */
+ Oid userid; /* local user Oid */
+ Oid serverid; /* server Oid */
+ List *options; /* useoptions as DefElem list */
+} UserMapping;
+
+typedef struct ForeignTable
+{
+ Oid relid; /* relation Oid */
+ Oid serverid; /* server Oid */
+ List *options; /* ftoptions as DefElem list */
+} ForeignTable;
+
+/* Flags for GetForeignServerExtended */
+#define FSV_MISSING_OK 0x01
+
+/* Flags for GetForeignDataWrapperExtended */
+#define FDW_MISSING_OK 0x01
+
+
+extern ForeignServer *GetForeignServer(Oid serverid);
+extern ForeignServer *GetForeignServerExtended(Oid serverid,
+ bits16 flags);
+extern ForeignServer *GetForeignServerByName(const char *name, bool missing_ok);
+extern UserMapping *GetUserMapping(Oid userid, Oid serverid);
+extern ForeignDataWrapper *GetForeignDataWrapper(Oid fdwid);
+extern ForeignDataWrapper *GetForeignDataWrapperExtended(Oid fdwid,
+ bits16 flags);
+extern ForeignDataWrapper *GetForeignDataWrapperByName(const char *name,
+ bool missing_ok);
+extern ForeignTable *GetForeignTable(Oid relid);
+
+extern List *GetForeignColumnOptions(Oid relid, AttrNumber attnum);
+
+extern Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok);
+extern Oid get_foreign_server_oid(const char *servername, bool missing_ok);
+
+#endif /* FOREIGN_H */
diff --git a/src/include/funcapi.h b/src/include/funcapi.h
new file mode 100644
index 0000000..b047acd
--- /dev/null
+++ b/src/include/funcapi.h
@@ -0,0 +1,348 @@
+/*-------------------------------------------------------------------------
+ *
+ * funcapi.h
+ * Definitions for functions which return composite type and/or sets
+ * or work on VARIADIC inputs.
+ *
+ * This file must be included by all Postgres modules that either define
+ * or call FUNCAPI-callable functions or macros.
+ *
+ *
+ * Copyright (c) 2002-2020, PostgreSQL Global Development Group
+ *
+ * src/include/funcapi.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FUNCAPI_H
+#define FUNCAPI_H
+
+#include "access/tupdesc.h"
+#include "executor/executor.h"
+#include "executor/tuptable.h"
+#include "fmgr.h"
+
+/*-------------------------------------------------------------------------
+ * Support to ease writing Functions returning composite types
+ *-------------------------------------------------------------------------
+ *
+ * This struct holds arrays of individual attribute information
+ * needed to create a tuple from raw C strings. It also requires
+ * a copy of the TupleDesc. The information carried here
+ * is derived from the TupleDesc, but it is stored here to
+ * avoid redundant cpu cycles on each call to an SRF.
+ */
+typedef struct AttInMetadata
+{
+ /* full TupleDesc */
+ TupleDesc tupdesc;
+
+ /* array of attribute type input function finfo */
+ FmgrInfo *attinfuncs;
+
+ /* array of attribute type i/o parameter OIDs */
+ Oid *attioparams;
+
+ /* array of attribute typmod */
+ int32 *atttypmods;
+} AttInMetadata;
+
+/*-------------------------------------------------------------------------
+ * Support struct to ease writing Set Returning Functions (SRFs)
+ *-------------------------------------------------------------------------
+ *
+ * This struct holds function context for Set Returning Functions.
+ * Use fn_extra to hold a pointer to it across calls
+ */
+typedef struct FuncCallContext
+{
+ /*
+ * Number of times we've been called before
+ *
+ * call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and
+ * incremented for you every time SRF_RETURN_NEXT() is called.
+ */
+ uint64 call_cntr;
+
+ /*
+ * OPTIONAL maximum number of calls
+ *
+ * max_calls is here for convenience only and setting it is optional. If
+ * not set, you must provide alternative means to know when the function
+ * is done.
+ */
+ uint64 max_calls;
+
+ /*
+ * OPTIONAL pointer to miscellaneous user-provided context information
+ *
+ * user_fctx is for use as a pointer to your own struct to retain
+ * arbitrary context information between calls of your function.
+ */
+ void *user_fctx;
+
+ /*
+ * OPTIONAL pointer to struct containing attribute type input metadata
+ *
+ * attinmeta is for use when returning tuples (i.e. composite data types)
+ * and is not used when returning base data types. It is only needed if
+ * you intend to use BuildTupleFromCStrings() to create the return tuple.
+ */
+ AttInMetadata *attinmeta;
+
+ /*
+ * memory context used for structures that must live for multiple calls
+ *
+ * multi_call_memory_ctx is set by SRF_FIRSTCALL_INIT() for you, and used
+ * by SRF_RETURN_DONE() for cleanup. It is the most appropriate memory
+ * context for any memory that is to be reused across multiple calls of
+ * the SRF.
+ */
+ MemoryContext multi_call_memory_ctx;
+
+ /*
+ * OPTIONAL pointer to struct containing tuple description
+ *
+ * tuple_desc is for use when returning tuples (i.e. composite data types)
+ * and is only needed if you are going to build the tuples with
+ * heap_form_tuple() rather than with BuildTupleFromCStrings(). Note that
+ * the TupleDesc pointer stored here should usually have been run through
+ * BlessTupleDesc() first.
+ */
+ TupleDesc tuple_desc;
+
+} FuncCallContext;
+
+/*----------
+ * Support to ease writing functions returning composite types
+ *
+ * External declarations:
+ * get_call_result_type:
+ * Given a function's call info record, determine the kind of datatype
+ * it is supposed to return. If resultTypeId isn't NULL, *resultTypeId
+ * receives the actual datatype OID (this is mainly useful for scalar
+ * result types). If resultTupleDesc isn't NULL, *resultTupleDesc
+ * receives a pointer to a TupleDesc when the result is of a composite
+ * type, or NULL when it's a scalar result or the rowtype could not be
+ * determined. NB: the tupledesc should be copied if it is to be
+ * accessed over a long period.
+ * get_expr_result_type:
+ * Given an expression node, return the same info as for
+ * get_call_result_type. Note: the cases in which rowtypes cannot be
+ * determined are different from the cases for get_call_result_type.
+ * get_func_result_type:
+ * Given only a function's OID, return the same info as for
+ * get_call_result_type. Note: the cases in which rowtypes cannot be
+ * determined are different from the cases for get_call_result_type.
+ * Do *not* use this if you can use one of the others.
+ *
+ * See also get_expr_result_tupdesc(), which is a convenient wrapper around
+ * get_expr_result_type() for use when the caller only cares about
+ * determinable-rowtype cases.
+ *----------
+ */
+
+/* Type categories for get_call_result_type and siblings */
+typedef enum TypeFuncClass
+{
+ TYPEFUNC_SCALAR, /* scalar result type */
+ TYPEFUNC_COMPOSITE, /* determinable rowtype result */
+ TYPEFUNC_COMPOSITE_DOMAIN, /* domain over determinable rowtype result */
+ TYPEFUNC_RECORD, /* indeterminate rowtype result */
+ TYPEFUNC_OTHER /* bogus type, eg pseudotype */
+} TypeFuncClass;
+
+extern TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo,
+ Oid *resultTypeId,
+ TupleDesc *resultTupleDesc);
+extern TypeFuncClass get_expr_result_type(Node *expr,
+ Oid *resultTypeId,
+ TupleDesc *resultTupleDesc);
+extern TypeFuncClass get_func_result_type(Oid functionId,
+ Oid *resultTypeId,
+ TupleDesc *resultTupleDesc);
+
+extern TupleDesc get_expr_result_tupdesc(Node *expr, bool noError);
+
+extern bool resolve_polymorphic_argtypes(int numargs, Oid *argtypes,
+ char *argmodes,
+ Node *call_expr);
+
+extern int get_func_arg_info(HeapTuple procTup,
+ Oid **p_argtypes, char ***p_argnames,
+ char **p_argmodes);
+
+extern int get_func_input_arg_names(Datum proargnames, Datum proargmodes,
+ char ***arg_names);
+
+extern int get_func_trftypes(HeapTuple procTup, Oid **p_trftypes);
+extern char *get_func_result_name(Oid functionId);
+
+extern TupleDesc build_function_result_tupdesc_d(char prokind,
+ Datum proallargtypes,
+ Datum proargmodes,
+ Datum proargnames);
+extern TupleDesc build_function_result_tupdesc_t(HeapTuple procTuple);
+
+
+/*----------
+ * Support to ease writing functions returning composite types
+ *
+ * External declarations:
+ * TupleDesc BlessTupleDesc(TupleDesc tupdesc) - "Bless" a completed tuple
+ * descriptor so that it can be used to return properly labeled tuples.
+ * You need to call this if you are going to use heap_form_tuple directly.
+ * TupleDescGetAttInMetadata does it for you, however, so no need to call
+ * it if you call TupleDescGetAttInMetadata.
+ * AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc) - Build an
+ * AttInMetadata struct based on the given TupleDesc. AttInMetadata can
+ * be used in conjunction with C strings to produce a properly formed
+ * tuple.
+ * HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values) -
+ * build a HeapTuple given user data in C string form. values is an array
+ * of C strings, one for each attribute of the return tuple.
+ * Datum HeapTupleHeaderGetDatum(HeapTupleHeader tuple) - convert a
+ * HeapTupleHeader to a Datum.
+ *
+ * Macro declarations:
+ * HeapTupleGetDatum(HeapTuple tuple) - convert a HeapTuple to a Datum.
+ *
+ * Obsolete routines and macros:
+ * TupleDesc RelationNameGetTupleDesc(const char *relname) - Use to get a
+ * TupleDesc based on a named relation.
+ * TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases) - Use to get a
+ * TupleDesc based on a type OID.
+ * TupleGetDatum(TupleTableSlot *slot, HeapTuple tuple) - get a Datum
+ * given a tuple and a slot.
+ *----------
+ */
+
+#define HeapTupleGetDatum(tuple) HeapTupleHeaderGetDatum((tuple)->t_data)
+/* obsolete version of above */
+#define TupleGetDatum(_slot, _tuple) HeapTupleGetDatum(_tuple)
+
+extern TupleDesc RelationNameGetTupleDesc(const char *relname);
+extern TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases);
+
+/* from execTuples.c */
+extern TupleDesc BlessTupleDesc(TupleDesc tupdesc);
+extern AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc);
+extern HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values);
+extern Datum HeapTupleHeaderGetDatum(HeapTupleHeader tuple);
+
+
+/*----------
+ * Support for Set Returning Functions (SRFs)
+ *
+ * The basic API for SRFs using ValuePerCall mode looks something like this:
+ *
+ * Datum
+ * my_Set_Returning_Function(PG_FUNCTION_ARGS)
+ * {
+ * FuncCallContext *funcctx;
+ * Datum result;
+ * MemoryContext oldcontext;
+ * <user defined declarations>
+ *
+ * if (SRF_IS_FIRSTCALL())
+ * {
+ * funcctx = SRF_FIRSTCALL_INIT();
+ * // switch context when allocating stuff to be used in later calls
+ * oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+ * <user defined code>
+ * <if returning composite>
+ * <build TupleDesc, and perhaps AttInMetadata>
+ * <endif returning composite>
+ * <user defined code>
+ * // return to original context when allocating transient memory
+ * MemoryContextSwitchTo(oldcontext);
+ * }
+ * <user defined code>
+ * funcctx = SRF_PERCALL_SETUP();
+ * <user defined code>
+ *
+ * if (funcctx->call_cntr < funcctx->max_calls)
+ * {
+ * <user defined code>
+ * <obtain result Datum>
+ * SRF_RETURN_NEXT(funcctx, result);
+ * }
+ * else
+ * SRF_RETURN_DONE(funcctx);
+ * }
+ *
+ * NOTE: there is no guarantee that a SRF using ValuePerCall mode will be
+ * run to completion; for example, a query with LIMIT might stop short of
+ * fetching all the rows. Therefore, do not expect that you can do resource
+ * cleanup just before SRF_RETURN_DONE(). You need not worry about releasing
+ * memory allocated in multi_call_memory_ctx, but holding file descriptors or
+ * other non-memory resources open across calls is a bug. SRFs that need
+ * such resources should not use these macros, but instead populate a
+ * tuplestore during a single call, and return that using SFRM_Materialize
+ * mode (see fmgr/README). Alternatively, set up a callback to release
+ * resources at query shutdown, using RegisterExprContextCallback().
+ *
+ *----------
+ */
+
+/* from funcapi.c */
+extern FuncCallContext *init_MultiFuncCall(PG_FUNCTION_ARGS);
+extern FuncCallContext *per_MultiFuncCall(PG_FUNCTION_ARGS);
+extern void end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx);
+
+#define SRF_IS_FIRSTCALL() (fcinfo->flinfo->fn_extra == NULL)
+
+#define SRF_FIRSTCALL_INIT() init_MultiFuncCall(fcinfo)
+
+#define SRF_PERCALL_SETUP() per_MultiFuncCall(fcinfo)
+
+#define SRF_RETURN_NEXT(_funcctx, _result) \
+ do { \
+ ReturnSetInfo *rsi; \
+ (_funcctx)->call_cntr++; \
+ rsi = (ReturnSetInfo *) fcinfo->resultinfo; \
+ rsi->isDone = ExprMultipleResult; \
+ PG_RETURN_DATUM(_result); \
+ } while (0)
+
+#define SRF_RETURN_NEXT_NULL(_funcctx) \
+ do { \
+ ReturnSetInfo *rsi; \
+ (_funcctx)->call_cntr++; \
+ rsi = (ReturnSetInfo *) fcinfo->resultinfo; \
+ rsi->isDone = ExprMultipleResult; \
+ PG_RETURN_NULL(); \
+ } while (0)
+
+#define SRF_RETURN_DONE(_funcctx) \
+ do { \
+ ReturnSetInfo *rsi; \
+ end_MultiFuncCall(fcinfo, _funcctx); \
+ rsi = (ReturnSetInfo *) fcinfo->resultinfo; \
+ rsi->isDone = ExprEndResult; \
+ PG_RETURN_NULL(); \
+ } while (0)
+
+/*----------
+ * Support to ease writing of functions dealing with VARIADIC inputs
+ *----------
+ *
+ * This function extracts a set of argument values, types and NULL markers
+ * for a given input function. This returns a set of data:
+ * - **values includes the set of Datum values extracted.
+ * - **types the data type OID for each element.
+ * - **nulls tracks if an element is NULL.
+ *
+ * variadic_start indicates the argument number where the VARIADIC argument
+ * starts.
+ * convert_unknown set to true will enforce the conversion of arguments
+ * with unknown data type to text.
+ *
+ * The return result is the number of elements stored, or -1 in the case of
+ * "VARIADIC NULL".
+ */
+extern int extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start,
+ bool convert_unknown, Datum **values,
+ Oid **types, bool **nulls);
+
+#endif /* FUNCAPI_H */
diff --git a/src/include/getaddrinfo.h b/src/include/getaddrinfo.h
new file mode 100644
index 0000000..38fa3b8
--- /dev/null
+++ b/src/include/getaddrinfo.h
@@ -0,0 +1,162 @@
+/*-------------------------------------------------------------------------
+ *
+ * getaddrinfo.h
+ * Support getaddrinfo() on platforms that don't have it.
+ *
+ * Note: we use our own routines on platforms that don't HAVE_STRUCT_ADDRINFO,
+ * whether or not the library routine getaddrinfo() can be found. This
+ * policy is needed because on some platforms a manually installed libbind.a
+ * may provide getaddrinfo(), yet the system headers may not provide the
+ * struct definitions needed to call it. To avoid conflict with the libbind
+ * definition in such cases, we rename our routines to pg_xxx() via macros.
+ *
+ * This code will also work on platforms where struct addrinfo is defined
+ * in the system headers but no getaddrinfo() can be located.
+ *
+ * Copyright (c) 2003-2020, PostgreSQL Global Development Group
+ *
+ * src/include/getaddrinfo.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef GETADDRINFO_H
+#define GETADDRINFO_H
+
+#include <sys/socket.h>
+#include <netdb.h>
+
+
+/* Various macros that ought to be in <netdb.h>, but might not be */
+
+#ifndef EAI_FAIL
+#ifndef WIN32
+#define EAI_BADFLAGS (-1)
+#define EAI_NONAME (-2)
+#define EAI_AGAIN (-3)
+#define EAI_FAIL (-4)
+#define EAI_FAMILY (-6)
+#define EAI_SOCKTYPE (-7)
+#define EAI_SERVICE (-8)
+#define EAI_MEMORY (-10)
+#define EAI_SYSTEM (-11)
+#else /* WIN32 */
+#ifdef _MSC_VER
+#ifndef WSA_NOT_ENOUGH_MEMORY
+#define WSA_NOT_ENOUGH_MEMORY (WSAENOBUFS)
+#endif
+#define WSATYPE_NOT_FOUND (WSABASEERR+109)
+#endif
+#define EAI_AGAIN WSATRY_AGAIN
+#define EAI_BADFLAGS WSAEINVAL
+#define EAI_FAIL WSANO_RECOVERY
+#define EAI_FAMILY WSAEAFNOSUPPORT
+#define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY
+#define EAI_NODATA WSANO_DATA
+#define EAI_NONAME WSAHOST_NOT_FOUND
+#define EAI_SERVICE WSATYPE_NOT_FOUND
+#define EAI_SOCKTYPE WSAESOCKTNOSUPPORT
+#endif /* !WIN32 */
+#endif /* !EAI_FAIL */
+
+#ifndef AI_PASSIVE
+#define AI_PASSIVE 0x0001
+#endif
+
+#ifndef AI_NUMERICHOST
+/*
+ * some platforms don't support AI_NUMERICHOST; define as zero if using
+ * the system version of getaddrinfo...
+ */
+#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO)
+#define AI_NUMERICHOST 0
+#else
+#define AI_NUMERICHOST 0x0004
+#endif
+#endif
+
+#ifndef NI_NUMERICHOST
+#define NI_NUMERICHOST 1
+#endif
+#ifndef NI_NUMERICSERV
+#define NI_NUMERICSERV 2
+#endif
+#ifndef NI_NAMEREQD
+#define NI_NAMEREQD 4
+#endif
+
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 1025
+#endif
+#ifndef NI_MAXSERV
+#define NI_MAXSERV 32
+#endif
+
+
+#ifndef HAVE_STRUCT_ADDRINFO
+
+#ifndef WIN32
+struct addrinfo
+{
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+ size_t ai_addrlen;
+ struct sockaddr *ai_addr;
+ char *ai_canonname;
+ struct addrinfo *ai_next;
+};
+#else
+/*
+ * The order of the structure elements on Win32 doesn't match the
+ * order specified in the standard, but we have to match it for
+ * IPv6 to work.
+ */
+struct addrinfo
+{
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+ size_t ai_addrlen;
+ char *ai_canonname;
+ struct sockaddr *ai_addr;
+ struct addrinfo *ai_next;
+};
+#endif
+#endif /* HAVE_STRUCT_ADDRINFO */
+
+
+#ifndef HAVE_GETADDRINFO
+
+/* Rename private copies per comments above */
+#ifdef getaddrinfo
+#undef getaddrinfo
+#endif
+#define getaddrinfo pg_getaddrinfo
+
+#ifdef freeaddrinfo
+#undef freeaddrinfo
+#endif
+#define freeaddrinfo pg_freeaddrinfo
+
+#ifdef gai_strerror
+#undef gai_strerror
+#endif
+#define gai_strerror pg_gai_strerror
+
+#ifdef getnameinfo
+#undef getnameinfo
+#endif
+#define getnameinfo pg_getnameinfo
+
+extern int getaddrinfo(const char *node, const char *service,
+ const struct addrinfo *hints, struct addrinfo **res);
+extern void freeaddrinfo(struct addrinfo *res);
+extern const char *gai_strerror(int errcode);
+extern int getnameinfo(const struct sockaddr *sa, int salen,
+ char *node, int nodelen,
+ char *service, int servicelen, int flags);
+#endif /* HAVE_GETADDRINFO */
+
+#endif /* GETADDRINFO_H */
diff --git a/src/include/getopt_long.h b/src/include/getopt_long.h
new file mode 100644
index 0000000..47c4911
--- /dev/null
+++ b/src/include/getopt_long.h
@@ -0,0 +1,36 @@
+/*
+ * Portions Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Portions Copyright (c) 2003-2020, PostgreSQL Global Development Group
+ *
+ * src/include/getopt_long.h
+ */
+#ifndef GETOPT_LONG_H
+#define GETOPT_LONG_H
+
+#include "pg_getopt.h"
+
+#ifndef HAVE_STRUCT_OPTION
+
+struct option
+{
+ const char *name;
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+#endif
+
+#ifndef HAVE_GETOPT_LONG
+
+extern int getopt_long(int argc, char *const argv[],
+ const char *optstring,
+ const struct option *longopts, int *longindex);
+#endif
+
+#endif /* GETOPT_LONG_H */
diff --git a/src/include/jit/jit.h b/src/include/jit/jit.h
new file mode 100644
index 0000000..5a77f7d
--- /dev/null
+++ b/src/include/jit/jit.h
@@ -0,0 +1,105 @@
+/*-------------------------------------------------------------------------
+ * jit.h
+ * Provider independent JIT infrastructure.
+ *
+ * Copyright (c) 2016-2020, PostgreSQL Global Development Group
+ *
+ * src/include/jit/jit.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef JIT_H
+#define JIT_H
+
+#include "executor/instrument.h"
+#include "utils/resowner.h"
+
+
+/* Flags determining what kind of JIT operations to perform */
+#define PGJIT_NONE 0
+#define PGJIT_PERFORM (1 << 0)
+#define PGJIT_OPT3 (1 << 1)
+#define PGJIT_INLINE (1 << 2)
+#define PGJIT_EXPR (1 << 3)
+#define PGJIT_DEFORM (1 << 4)
+
+
+typedef struct JitInstrumentation
+{
+ /* number of emitted functions */
+ size_t created_functions;
+
+ /* accumulated time to generate code */
+ instr_time generation_counter;
+
+ /* accumulated time for inlining */
+ instr_time inlining_counter;
+
+ /* accumulated time for optimization */
+ instr_time optimization_counter;
+
+ /* accumulated time for code emission */
+ instr_time emission_counter;
+} JitInstrumentation;
+
+/*
+ * DSM structure for accumulating jit instrumentation of all workers.
+ */
+typedef struct SharedJitInstrumentation
+{
+ int num_workers;
+ JitInstrumentation jit_instr[FLEXIBLE_ARRAY_MEMBER];
+} SharedJitInstrumentation;
+
+typedef struct JitContext
+{
+ /* see PGJIT_* above */
+ int flags;
+
+ ResourceOwner resowner;
+
+ JitInstrumentation instr;
+} JitContext;
+
+typedef struct JitProviderCallbacks JitProviderCallbacks;
+
+extern void _PG_jit_provider_init(JitProviderCallbacks *cb);
+typedef void (*JitProviderInit) (JitProviderCallbacks *cb);
+typedef void (*JitProviderResetAfterErrorCB) (void);
+typedef void (*JitProviderReleaseContextCB) (JitContext *context);
+struct ExprState;
+typedef bool (*JitProviderCompileExprCB) (struct ExprState *state);
+
+struct JitProviderCallbacks
+{
+ JitProviderResetAfterErrorCB reset_after_error;
+ JitProviderReleaseContextCB release_context;
+ JitProviderCompileExprCB compile_expr;
+};
+
+
+/* GUCs */
+extern bool jit_enabled;
+extern char *jit_provider;
+extern bool jit_debugging_support;
+extern bool jit_dump_bitcode;
+extern bool jit_expressions;
+extern bool jit_profiling_support;
+extern bool jit_tuple_deforming;
+extern double jit_above_cost;
+extern double jit_inline_above_cost;
+extern double jit_optimize_above_cost;
+
+
+extern void jit_reset_after_error(void);
+extern void jit_release_context(JitContext *context);
+
+/*
+ * Functions for attempting to JIT code. Callers must accept that these might
+ * not be able to perform JIT (i.e. return false).
+ */
+extern bool jit_compile_expr(struct ExprState *state);
+extern void InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add);
+
+
+#endif /* JIT_H */
diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h
new file mode 100644
index 0000000..325409a
--- /dev/null
+++ b/src/include/jit/llvmjit.h
@@ -0,0 +1,139 @@
+/*-------------------------------------------------------------------------
+ * llvmjit.h
+ * LLVM JIT provider.
+ *
+ * Copyright (c) 2016-2020, PostgreSQL Global Development Group
+ *
+ * src/include/jit/llvmjit.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LLVMJIT_H
+#define LLVMJIT_H
+
+/*
+ * To avoid breaking cpluspluscheck, allow including the file even when LLVM
+ * is not available.
+ */
+#ifdef USE_LLVM
+
+#include <llvm-c/Types.h>
+
+
+/*
+ * File needs to be includable by both C and C++ code, and include other
+ * headers doing the same. Therefore wrap C portion in our own extern "C" if
+ * in C++ mode.
+ */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "access/tupdesc.h"
+#include "fmgr.h"
+#include "jit/jit.h"
+#include "nodes/pg_list.h"
+
+typedef struct LLVMJitContext
+{
+ JitContext base;
+
+ /* number of modules created */
+ size_t module_generation;
+
+ /* current, "open for write", module */
+ LLVMModuleRef module;
+
+ /* is there any pending code that needs to be emitted */
+ bool compiled;
+
+ /* # of objects emitted, used to generate non-conflicting names */
+ int counter;
+
+ /* list of handles for code emitted via Orc */
+ List *handles;
+} LLVMJitContext;
+
+/* llvm module containing information about types */
+extern LLVMModuleRef llvm_types_module;
+
+/* type and struct definitions */
+extern LLVMTypeRef TypeParamBool;
+extern LLVMTypeRef TypePGFunction;
+extern LLVMTypeRef TypeSizeT;
+extern LLVMTypeRef TypeStorageBool;
+
+extern LLVMTypeRef StructNullableDatum;
+extern LLVMTypeRef StructTupleDescData;
+extern LLVMTypeRef StructHeapTupleData;
+extern LLVMTypeRef StructTupleTableSlot;
+extern LLVMTypeRef StructHeapTupleTableSlot;
+extern LLVMTypeRef StructMinimalTupleTableSlot;
+extern LLVMTypeRef StructMemoryContextData;
+extern LLVMTypeRef StructFunctionCallInfoData;
+extern LLVMTypeRef StructExprContext;
+extern LLVMTypeRef StructExprEvalStep;
+extern LLVMTypeRef StructExprState;
+extern LLVMTypeRef StructAggState;
+extern LLVMTypeRef StructAggStatePerTransData;
+extern LLVMTypeRef StructAggStatePerGroupData;
+
+extern LLVMValueRef AttributeTemplate;
+
+
+extern void llvm_enter_fatal_on_oom(void);
+extern void llvm_leave_fatal_on_oom(void);
+extern void llvm_reset_after_error(void);
+extern void llvm_assert_in_fatal_section(void);
+
+extern LLVMJitContext *llvm_create_context(int jitFlags);
+extern LLVMModuleRef llvm_mutable_module(LLVMJitContext *context);
+extern char *llvm_expand_funcname(LLVMJitContext *context, const char *basename);
+extern void *llvm_get_function(LLVMJitContext *context, const char *funcname);
+extern void llvm_split_symbol_name(const char *name, char **modname, char **funcname);
+extern LLVMValueRef llvm_pg_func(LLVMModuleRef mod, const char *funcname);
+extern void llvm_copy_attributes(LLVMValueRef from, LLVMValueRef to);
+extern LLVMValueRef llvm_function_reference(LLVMJitContext *context,
+ LLVMBuilderRef builder,
+ LLVMModuleRef mod,
+ FunctionCallInfo fcinfo);
+
+extern void llvm_inline(LLVMModuleRef mod);
+
+/*
+ ****************************************************************************
+ * Code generation functions.
+ ****************************************************************************
+ */
+extern bool llvm_compile_expr(struct ExprState *state);
+struct TupleTableSlotOps;
+extern LLVMValueRef slot_compile_deform(struct LLVMJitContext *context, TupleDesc desc,
+ const struct TupleTableSlotOps *ops, int natts);
+
+/*
+ ****************************************************************************
+ * Extensions / Backward compatibility section of the LLVM C API
+ * Error handling related functions.
+ ****************************************************************************
+ */
+#if defined(HAVE_DECL_LLVMGETHOSTCPUNAME) && !HAVE_DECL_LLVMGETHOSTCPUNAME
+/** Get the host CPU as a string. The result needs to be disposed with
+ LLVMDisposeMessage. */
+extern char *LLVMGetHostCPUName(void);
+#endif
+
+#if defined(HAVE_DECL_LLVMGETHOSTCPUFEATURES) && !HAVE_DECL_LLVMGETHOSTCPUFEATURES
+/** Get the host CPU features as a string. The result needs to be disposed
+ with LLVMDisposeMessage. */
+extern char *LLVMGetHostCPUFeatures(void);
+#endif
+
+extern unsigned LLVMGetAttributeCountAtIndexPG(LLVMValueRef F, uint32 Idx);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* USE_LLVM */
+#endif /* LLVMJIT_H */
diff --git a/src/include/jit/llvmjit_emit.h b/src/include/jit/llvmjit_emit.h
new file mode 100644
index 0000000..45b782d
--- /dev/null
+++ b/src/include/jit/llvmjit_emit.h
@@ -0,0 +1,274 @@
+/*
+ * llvmjit_emit.h
+ * Helpers to make emitting LLVM IR a bit more concise and pgindent proof.
+ *
+ * Copyright (c) 2018-2020, PostgreSQL Global Development Group
+ *
+ * src/include/lib/llvmjit_emit.h
+ */
+#ifndef LLVMJIT_EMIT_H
+#define LLVMJIT_EMIT_H
+
+/*
+ * To avoid breaking cpluspluscheck, allow including the file even when LLVM
+ * is not available.
+ */
+#ifdef USE_LLVM
+
+#include <llvm-c/Core.h>
+
+#include "jit/llvmjit.h"
+
+
+/*
+ * Emit a non-LLVM pointer as an LLVM constant.
+ */
+static inline LLVMValueRef
+l_ptr_const(void *ptr, LLVMTypeRef type)
+{
+ LLVMValueRef c = LLVMConstInt(TypeSizeT, (uintptr_t) ptr, false);
+
+ return LLVMConstIntToPtr(c, type);
+}
+
+/*
+ * Emit pointer.
+ */
+static inline LLVMTypeRef
+l_ptr(LLVMTypeRef t)
+{
+ return LLVMPointerType(t, 0);
+}
+
+/*
+ * Emit constant integer.
+ */
+static inline LLVMValueRef
+l_int8_const(int8 i)
+{
+ return LLVMConstInt(LLVMInt8Type(), i, false);
+}
+
+/*
+ * Emit constant integer.
+ */
+static inline LLVMValueRef
+l_int16_const(int16 i)
+{
+ return LLVMConstInt(LLVMInt16Type(), i, false);
+}
+
+/*
+ * Emit constant integer.
+ */
+static inline LLVMValueRef
+l_int32_const(int32 i)
+{
+ return LLVMConstInt(LLVMInt32Type(), i, false);
+}
+
+/*
+ * Emit constant integer.
+ */
+static inline LLVMValueRef
+l_int64_const(int64 i)
+{
+ return LLVMConstInt(LLVMInt64Type(), i, false);
+}
+
+/*
+ * Emit constant integer.
+ */
+static inline LLVMValueRef
+l_sizet_const(size_t i)
+{
+ return LLVMConstInt(TypeSizeT, i, false);
+}
+
+/*
+ * Emit constant boolean, as used for storage (e.g. global vars, structs).
+ */
+static inline LLVMValueRef
+l_sbool_const(bool i)
+{
+ return LLVMConstInt(TypeStorageBool, (int) i, false);
+}
+
+/*
+ * Emit constant boolean, as used for parameters (e.g. function parameters).
+ */
+static inline LLVMValueRef
+l_pbool_const(bool i)
+{
+ return LLVMConstInt(TypeParamBool, (int) i, false);
+}
+
+/*
+ * Load a pointer member idx from a struct.
+ */
+static inline LLVMValueRef
+l_load_struct_gep(LLVMBuilderRef b, LLVMValueRef v, int32 idx, const char *name)
+{
+ LLVMValueRef v_ptr = LLVMBuildStructGEP(b, v, idx, "");
+
+ return LLVMBuildLoad(b, v_ptr, name);
+}
+
+/*
+ * Load value of a pointer, after applying one index operation.
+ */
+static inline LLVMValueRef
+l_load_gep1(LLVMBuilderRef b, LLVMValueRef v, LLVMValueRef idx, const char *name)
+{
+ LLVMValueRef v_ptr = LLVMBuildGEP(b, v, &idx, 1, "");
+
+ return LLVMBuildLoad(b, v_ptr, name);
+}
+
+/* separate, because pg_attribute_printf(2, 3) can't appear in definition */
+static inline LLVMBasicBlockRef l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...) pg_attribute_printf(2, 3);
+
+/*
+ * Insert a new basic block, just before r, the name being determined by fmt
+ * and arguments.
+ */
+static inline LLVMBasicBlockRef
+l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...)
+{
+ char buf[512];
+ va_list args;
+
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ return LLVMInsertBasicBlock(r, buf);
+}
+
+/* separate, because pg_attribute_printf(2, 3) can't appear in definition */
+static inline LLVMBasicBlockRef l_bb_append_v(LLVMValueRef f, const char *fmt,...) pg_attribute_printf(2, 3);
+
+/*
+ * Insert a new basic block after previous basic blocks, the name being
+ * determined by fmt and arguments.
+ */
+static inline LLVMBasicBlockRef
+l_bb_append_v(LLVMValueRef f, const char *fmt,...)
+{
+ char buf[512];
+ va_list args;
+
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ return LLVMAppendBasicBlock(f, buf);
+}
+
+/*
+ * Mark a callsite as readonly.
+ */
+static inline void
+l_callsite_ro(LLVMValueRef f)
+{
+ const char argname[] = "readonly";
+ LLVMAttributeRef ref;
+
+ ref = LLVMCreateStringAttribute(LLVMGetGlobalContext(),
+ argname,
+ sizeof(argname) - 1,
+ NULL, 0);
+
+ LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, ref);
+}
+
+/*
+ * Mark a callsite as alwaysinline.
+ */
+static inline void
+l_callsite_alwaysinline(LLVMValueRef f)
+{
+ const char argname[] = "alwaysinline";
+ int id;
+ LLVMAttributeRef attr;
+
+ id = LLVMGetEnumAttributeKindForName(argname,
+ sizeof(argname) - 1);
+ attr = LLVMCreateEnumAttribute(LLVMGetGlobalContext(), id, 0);
+ LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, attr);
+}
+
+/*
+ * Emit code to switch memory context.
+ */
+static inline LLVMValueRef
+l_mcxt_switch(LLVMModuleRef mod, LLVMBuilderRef b, LLVMValueRef nc)
+{
+ const char *cmc = "CurrentMemoryContext";
+ LLVMValueRef cur;
+ LLVMValueRef ret;
+
+ if (!(cur = LLVMGetNamedGlobal(mod, cmc)))
+ cur = LLVMAddGlobal(mod, l_ptr(StructMemoryContextData), cmc);
+ ret = LLVMBuildLoad(b, cur, cmc);
+ LLVMBuildStore(b, nc, cur);
+
+ return ret;
+}
+
+/*
+ * Return pointer to the argno'th argument nullness.
+ */
+static inline LLVMValueRef
+l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+{
+ LLVMValueRef v_args;
+ LLVMValueRef v_argn;
+
+ v_args = LLVMBuildStructGEP(b,
+ v_fcinfo,
+ FIELDNO_FUNCTIONCALLINFODATA_ARGS,
+ "");
+ v_argn = LLVMBuildStructGEP(b, v_args, argno, "");
+
+ return LLVMBuildStructGEP(b, v_argn, FIELDNO_NULLABLE_DATUM_ISNULL, "");
+}
+
+/*
+ * Return pointer to the argno'th argument datum.
+ */
+static inline LLVMValueRef
+l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+{
+ LLVMValueRef v_args;
+ LLVMValueRef v_argn;
+
+ v_args = LLVMBuildStructGEP(b,
+ v_fcinfo,
+ FIELDNO_FUNCTIONCALLINFODATA_ARGS,
+ "");
+ v_argn = LLVMBuildStructGEP(b, v_args, argno, "");
+
+ return LLVMBuildStructGEP(b, v_argn, FIELDNO_NULLABLE_DATUM_DATUM, "");
+}
+
+/*
+ * Return argno'th argument nullness.
+ */
+static inline LLVMValueRef
+l_funcnull(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+{
+ return LLVMBuildLoad(b, l_funcnullp(b, v_fcinfo, argno), "");
+}
+
+/*
+ * Return argno'th argument datum.
+ */
+static inline LLVMValueRef
+l_funcvalue(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+{
+ return LLVMBuildLoad(b, l_funcvaluep(b, v_fcinfo, argno), "");
+}
+
+#endif /* USE_LLVM */
+#endif
diff --git a/src/include/lib/binaryheap.h b/src/include/lib/binaryheap.h
new file mode 100644
index 0000000..8d5db56
--- /dev/null
+++ b/src/include/lib/binaryheap.h
@@ -0,0 +1,54 @@
+/*
+ * binaryheap.h
+ *
+ * A simple binary heap implementation
+ *
+ * Portions Copyright (c) 2012-2020, PostgreSQL Global Development Group
+ *
+ * src/include/lib/binaryheap.h
+ */
+
+#ifndef BINARYHEAP_H
+#define BINARYHEAP_H
+
+/*
+ * For a max-heap, the comparator must return <0 iff a < b, 0 iff a == b,
+ * and >0 iff a > b. For a min-heap, the conditions are reversed.
+ */
+typedef int (*binaryheap_comparator) (Datum a, Datum b, void *arg);
+
+/*
+ * binaryheap
+ *
+ * bh_size how many nodes are currently in "nodes"
+ * bh_space how many nodes can be stored in "nodes"
+ * bh_has_heap_property no unordered operations since last heap build
+ * bh_compare comparison function to define the heap property
+ * bh_arg user data for comparison function
+ * bh_nodes variable-length array of "space" nodes
+ */
+typedef struct binaryheap
+{
+ int bh_size;
+ int bh_space;
+ bool bh_has_heap_property; /* debugging cross-check */
+ binaryheap_comparator bh_compare;
+ void *bh_arg;
+ Datum bh_nodes[FLEXIBLE_ARRAY_MEMBER];
+} binaryheap;
+
+extern binaryheap *binaryheap_allocate(int capacity,
+ binaryheap_comparator compare,
+ void *arg);
+extern void binaryheap_reset(binaryheap *heap);
+extern void binaryheap_free(binaryheap *heap);
+extern void binaryheap_add_unordered(binaryheap *heap, Datum d);
+extern void binaryheap_build(binaryheap *heap);
+extern void binaryheap_add(binaryheap *heap, Datum d);
+extern Datum binaryheap_first(binaryheap *heap);
+extern Datum binaryheap_remove_first(binaryheap *heap);
+extern void binaryheap_replace_first(binaryheap *heap, Datum d);
+
+#define binaryheap_empty(h) ((h)->bh_size == 0)
+
+#endif /* BINARYHEAP_H */
diff --git a/src/include/lib/bipartite_match.h b/src/include/lib/bipartite_match.h
new file mode 100644
index 0000000..a4c3e7d
--- /dev/null
+++ b/src/include/lib/bipartite_match.h
@@ -0,0 +1,46 @@
+/*
+ * bipartite_match.h
+ *
+ * Copyright (c) 2015-2020, PostgreSQL Global Development Group
+ *
+ * src/include/lib/bipartite_match.h
+ */
+#ifndef BIPARTITE_MATCH_H
+#define BIPARTITE_MATCH_H
+
+/*
+ * Given a bipartite graph consisting of nodes U numbered 1..nU, nodes V
+ * numbered 1..nV, and an adjacency map of undirected edges in the form
+ * adjacency[u] = [k, v1, v2, v3, ... vk], we wish to find a "maximum
+ * cardinality matching", which is defined as follows: a matching is a subset
+ * of the original edges such that no node has more than one edge, and a
+ * matching has maximum cardinality if there exists no other matching with a
+ * greater number of edges.
+ *
+ * This matching has various applications in graph theory, but the motivating
+ * example here is Dilworth's theorem: a partially-ordered set can be divided
+ * into the minimum number of chains (i.e. subsets X where x1 < x2 < x3 ...) by
+ * a bipartite graph construction. This gives us a polynomial-time solution to
+ * the problem of planning a collection of grouping sets with the provably
+ * minimal number of sort operations.
+ */
+typedef struct BipartiteMatchState
+{
+ /* inputs: */
+ int u_size; /* size of U */
+ int v_size; /* size of V */
+ short **adjacency; /* adjacency[u] = [k, v1,v2,v3,...,vk] */
+ /* outputs: */
+ int matching; /* number of edges in matching */
+ short *pair_uv; /* pair_uv[u] -> v */
+ short *pair_vu; /* pair_vu[v] -> u */
+ /* private state for matching algorithm: */
+ short *distance; /* distance[u] */
+ short *queue; /* queue storage for breadth search */
+} BipartiteMatchState;
+
+extern BipartiteMatchState *BipartiteMatch(int u_size, int v_size, short **adjacency);
+
+extern void BipartiteMatchFree(BipartiteMatchState *state);
+
+#endif /* BIPARTITE_MATCH_H */
diff --git a/src/include/lib/bloomfilter.h b/src/include/lib/bloomfilter.h
new file mode 100644
index 0000000..52343ba
--- /dev/null
+++ b/src/include/lib/bloomfilter.h
@@ -0,0 +1,27 @@
+/*-------------------------------------------------------------------------
+ *
+ * bloomfilter.h
+ * Space-efficient set membership testing
+ *
+ * Copyright (c) 2018-2020, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/lib/bloomfilter.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BLOOMFILTER_H
+#define BLOOMFILTER_H
+
+typedef struct bloom_filter bloom_filter;
+
+extern bloom_filter *bloom_create(int64 total_elems, int bloom_work_mem,
+ uint64 seed);
+extern void bloom_free(bloom_filter *filter);
+extern void bloom_add_element(bloom_filter *filter, unsigned char *elem,
+ size_t len);
+extern bool bloom_lacks_element(bloom_filter *filter, unsigned char *elem,
+ size_t len);
+extern double bloom_prop_bits_set(bloom_filter *filter);
+
+#endif /* BLOOMFILTER_H */
diff --git a/src/include/lib/dshash.h b/src/include/lib/dshash.h
new file mode 100644
index 0000000..b86df68
--- /dev/null
+++ b/src/include/lib/dshash.h
@@ -0,0 +1,90 @@
+/*-------------------------------------------------------------------------
+ *
+ * dshash.h
+ * Concurrent hash tables backed by 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/lib/dshash.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DSHASH_H
+#define DSHASH_H
+
+#include "utils/dsa.h"
+
+/* The opaque type representing a hash table. */
+struct dshash_table;
+typedef struct dshash_table dshash_table;
+
+/* A handle for a dshash_table which can be shared with other processes. */
+typedef dsa_pointer dshash_table_handle;
+
+/* The type for hash values. */
+typedef uint32 dshash_hash;
+
+/* A function type for comparing keys. */
+typedef int (*dshash_compare_function) (const void *a, const void *b,
+ size_t size, void *arg);
+
+/* A function type for computing hash values for keys. */
+typedef dshash_hash (*dshash_hash_function) (const void *v, size_t size,
+ void *arg);
+
+/*
+ * The set of parameters needed to create or attach to a hash table. The
+ * members tranche_id and tranche_name do not need to be initialized when
+ * attaching to an existing hash table.
+ *
+ * Compare and hash functions must be supplied even when attaching, because we
+ * can't safely share function pointers between backends in general. Either
+ * the arg variants or the non-arg variants should be supplied; the other
+ * function pointers should be NULL. If the arg variants are supplied then the
+ * user data pointer supplied to the create and attach functions will be
+ * passed to the hash and compare functions.
+ */
+typedef struct dshash_parameters
+{
+ size_t key_size; /* Size of the key (initial bytes of entry) */
+ size_t entry_size; /* Total size of entry */
+ dshash_compare_function compare_function; /* Compare function */
+ dshash_hash_function hash_function; /* Hash function */
+ int tranche_id; /* The tranche ID to use for locks */
+} dshash_parameters;
+
+/* Forward declaration of private types for use only by dshash.c. */
+struct dshash_table_item;
+typedef struct dshash_table_item dshash_table_item;
+
+/* Creating, sharing and destroying from hash tables. */
+extern dshash_table *dshash_create(dsa_area *area,
+ const dshash_parameters *params,
+ void *arg);
+extern dshash_table *dshash_attach(dsa_area *area,
+ const dshash_parameters *params,
+ dshash_table_handle handle,
+ void *arg);
+extern void dshash_detach(dshash_table *hash_table);
+extern dshash_table_handle dshash_get_hash_table_handle(dshash_table *hash_table);
+extern void dshash_destroy(dshash_table *hash_table);
+
+/* Finding, creating, deleting entries. */
+extern void *dshash_find(dshash_table *hash_table,
+ const void *key, bool exclusive);
+extern void *dshash_find_or_insert(dshash_table *hash_table,
+ const void *key, bool *found);
+extern bool dshash_delete_key(dshash_table *hash_table, const void *key);
+extern void dshash_delete_entry(dshash_table *hash_table, void *entry);
+extern void dshash_release_lock(dshash_table *hash_table, void *entry);
+
+/* Convenience hash and compare functions wrapping memcmp and tag_hash. */
+extern int dshash_memcmp(const void *a, const void *b, size_t size, void *arg);
+extern dshash_hash dshash_memhash(const void *v, size_t size, void *arg);
+
+/* Debugging support. */
+extern void dshash_dump(dshash_table *hash_table);
+
+#endif /* DSHASH_H */
diff --git a/src/include/lib/hyperloglog.h b/src/include/lib/hyperloglog.h
new file mode 100644
index 0000000..dea4138
--- /dev/null
+++ b/src/include/lib/hyperloglog.h
@@ -0,0 +1,68 @@
+/*
+ * hyperloglog.h
+ *
+ * A simple HyperLogLog cardinality estimator implementation
+ *
+ * Portions Copyright (c) 2014-2020, PostgreSQL Global Development Group
+ *
+ * Based on Hideaki Ohno's C++ implementation. The copyright terms of Ohno's
+ * original version (the MIT license) follow.
+ *
+ * src/include/lib/hyperloglog.h
+ */
+
+/*
+ * Copyright (c) 2013 Hideaki Ohno <hide.o.j55{at}gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the 'Software'), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef HYPERLOGLOG_H
+#define HYPERLOGLOG_H
+
+/*
+ * HyperLogLog is an approximate technique for computing the number of distinct
+ * entries in a set. Importantly, it does this by using a fixed amount of
+ * memory. See the 2007 paper "HyperLogLog: the analysis of a near-optimal
+ * cardinality estimation algorithm" for more.
+ *
+ * hyperLogLogState
+ *
+ * registerWidth register width, in bits ("k")
+ * nRegisters number of registers
+ * alphaMM alpha * m ^ 2 (see initHyperLogLog())
+ * hashesArr array of hashes
+ * arrSize size of hashesArr
+ */
+typedef struct hyperLogLogState
+{
+ uint8 registerWidth;
+ Size nRegisters;
+ double alphaMM;
+ uint8 *hashesArr;
+ Size arrSize;
+} hyperLogLogState;
+
+extern void initHyperLogLog(hyperLogLogState *cState, uint8 bwidth);
+extern void initHyperLogLogError(hyperLogLogState *cState, double error);
+extern void addHyperLogLog(hyperLogLogState *cState, uint32 hash);
+extern double estimateHyperLogLog(hyperLogLogState *cState);
+extern void freeHyperLogLog(hyperLogLogState *cState);
+
+#endif /* HYPERLOGLOG_H */
diff --git a/src/include/lib/ilist.h b/src/include/lib/ilist.h
new file mode 100644
index 0000000..98db885
--- /dev/null
+++ b/src/include/lib/ilist.h
@@ -0,0 +1,727 @@
+/*-------------------------------------------------------------------------
+ *
+ * ilist.h
+ * integrated/inline doubly- and singly-linked lists
+ *
+ * These list types are useful when there are only a predetermined set of
+ * lists that an object could be in. List links are embedded directly into
+ * the objects, and thus no extra memory management overhead is required.
+ * (Of course, if only a small proportion of existing objects are in a list,
+ * the link fields in the remainder would be wasted space. But usually,
+ * it saves space to not have separately-allocated list nodes.)
+ *
+ * None of the functions here allocate any memory; they just manipulate
+ * externally managed memory. The APIs for singly and doubly linked lists
+ * are identical as far as capabilities of both allow.
+ *
+ * Each list has a list header, which exists even when the list is empty.
+ * An empty singly-linked list has a NULL pointer in its header.
+ * There are two kinds of empty doubly linked lists: those that have been
+ * initialized to NULL, and those that have been initialized to circularity.
+ * (If a dlist is modified and then all its elements are deleted, it will be
+ * in the circular state.) We prefer circular dlists because there are some
+ * operations that can be done without branches (and thus faster) on lists
+ * that use circular representation. However, it is often convenient to
+ * initialize list headers to zeroes rather than setting them up with an
+ * explicit initialization function, so we also allow the other case.
+ *
+ * EXAMPLES
+ *
+ * Here's a simple example demonstrating how this can be used. Let's assume
+ * we want to store information about the tables contained in a database.
+ *
+ * #include "lib/ilist.h"
+ *
+ * // Define struct for the databases including a list header that will be
+ * // used to access the nodes in the table list later on.
+ * typedef struct my_database
+ * {
+ * char *datname;
+ * dlist_head tables;
+ * // ...
+ * } my_database;
+ *
+ * // Define struct for the tables. Note the list_node element which stores
+ * // prev/next list links. The list_node element need not be first.
+ * typedef struct my_table
+ * {
+ * char *tablename;
+ * dlist_node list_node;
+ * perm_t permissions;
+ * // ...
+ * } my_table;
+ *
+ * // create a database
+ * my_database *db = create_database();
+ *
+ * // and add a few tables to its table list
+ * dlist_push_head(&db->tables, &create_table(db, "a")->list_node);
+ * ...
+ * dlist_push_head(&db->tables, &create_table(db, "b")->list_node);
+ *
+ *
+ * To iterate over the table list, we allocate an iterator variable and use
+ * a specialized looping construct. Inside a dlist_foreach, the iterator's
+ * 'cur' field can be used to access the current element. iter.cur points to
+ * a 'dlist_node', but most of the time what we want is the actual table
+ * information; dlist_container() gives us that, like so:
+ *
+ * dlist_iter iter;
+ * dlist_foreach(iter, &db->tables)
+ * {
+ * my_table *tbl = dlist_container(my_table, list_node, iter.cur);
+ * printf("we have a table: %s in database %s\n",
+ * tbl->tablename, db->datname);
+ * }
+ *
+ *
+ * While a simple iteration is useful, we sometimes also want to manipulate
+ * the list while iterating. There is a different iterator element and looping
+ * construct for that. Suppose we want to delete tables that meet a certain
+ * criterion:
+ *
+ * dlist_mutable_iter miter;
+ * dlist_foreach_modify(miter, &db->tables)
+ * {
+ * my_table *tbl = dlist_container(my_table, list_node, miter.cur);
+ *
+ * if (!tbl->to_be_deleted)
+ * continue; // don't touch this one
+ *
+ * // unlink the current table from the linked list
+ * dlist_delete(miter.cur);
+ * // as these lists never manage memory, we can still access the table
+ * // after it's been unlinked
+ * drop_table(db, tbl);
+ * }
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/lib/ilist.h
+ *-------------------------------------------------------------------------
+ */
+#ifndef ILIST_H
+#define ILIST_H
+
+/*
+ * Enable for extra debugging. This is rather expensive, so it's not enabled by
+ * default even when USE_ASSERT_CHECKING.
+ */
+/* #define ILIST_DEBUG */
+
+/*
+ * Node of a doubly linked list.
+ *
+ * Embed this in structs that need to be part of a doubly linked list.
+ */
+typedef struct dlist_node dlist_node;
+struct dlist_node
+{
+ dlist_node *prev;
+ dlist_node *next;
+};
+
+/*
+ * Head of a doubly linked list.
+ *
+ * Non-empty lists are internally circularly linked. Circular lists have the
+ * advantage of not needing any branches in the most common list manipulations.
+ * An empty list can also be represented as a pair of NULL pointers, making
+ * initialization easier.
+ */
+typedef struct dlist_head
+{
+ /*
+ * head.next either points to the first element of the list; to &head if
+ * it's a circular empty list; or to NULL if empty and not circular.
+ *
+ * head.prev either points to the last element of the list; to &head if
+ * it's a circular empty list; or to NULL if empty and not circular.
+ */
+ dlist_node head;
+} dlist_head;
+
+
+/*
+ * Doubly linked list iterator.
+ *
+ * Used as state in dlist_foreach() and dlist_reverse_foreach(). To get the
+ * current element of the iteration use the 'cur' member.
+ *
+ * Iterations using this are *not* allowed to change the list while iterating!
+ *
+ * NB: We use an extra "end" field here to avoid multiple evaluations of
+ * arguments in the dlist_foreach() macro.
+ */
+typedef struct dlist_iter
+{
+ dlist_node *cur; /* current element */
+ dlist_node *end; /* last node we'll iterate to */
+} dlist_iter;
+
+/*
+ * Doubly linked list iterator allowing some modifications while iterating.
+ *
+ * Used as state in dlist_foreach_modify(). To get the current element of the
+ * iteration use the 'cur' member.
+ *
+ * Iterations using this are only allowed to change the list at the current
+ * point of iteration. It is fine to delete the current node, but it is *not*
+ * fine to insert or delete adjacent nodes.
+ *
+ * NB: We need a separate type for mutable iterations so that we can store
+ * the 'next' node of the current node in case it gets deleted or modified.
+ */
+typedef struct dlist_mutable_iter
+{
+ dlist_node *cur; /* current element */
+ dlist_node *next; /* next node we'll iterate to */
+ dlist_node *end; /* last node we'll iterate to */
+} dlist_mutable_iter;
+
+/*
+ * Node of a singly linked list.
+ *
+ * Embed this in structs that need to be part of a singly linked list.
+ */
+typedef struct slist_node slist_node;
+struct slist_node
+{
+ slist_node *next;
+};
+
+/*
+ * Head of a singly linked list.
+ *
+ * Singly linked lists are not circularly linked, in contrast to doubly linked
+ * lists; we just set head.next to NULL if empty. This doesn't incur any
+ * additional branches in the usual manipulations.
+ */
+typedef struct slist_head
+{
+ slist_node head;
+} slist_head;
+
+/*
+ * Singly linked list iterator.
+ *
+ * Used as state in slist_foreach(). To get the current element of the
+ * iteration use the 'cur' member.
+ *
+ * It's allowed to modify the list while iterating, with the exception of
+ * deleting the iterator's current node; deletion of that node requires
+ * care if the iteration is to be continued afterward. (Doing so and also
+ * deleting or inserting adjacent list elements might misbehave; also, if
+ * the user frees the current node's storage, continuing the iteration is
+ * not safe.)
+ *
+ * NB: this wouldn't really need to be an extra struct, we could use an
+ * slist_node * directly. We prefer a separate type for consistency.
+ */
+typedef struct slist_iter
+{
+ slist_node *cur;
+} slist_iter;
+
+/*
+ * Singly linked list iterator allowing some modifications while iterating.
+ *
+ * Used as state in slist_foreach_modify(). To get the current element of the
+ * iteration use the 'cur' member.
+ *
+ * The only list modification allowed while iterating is to remove the current
+ * node via slist_delete_current() (*not* slist_delete()). Insertion or
+ * deletion of nodes adjacent to the current node would misbehave.
+ */
+typedef struct slist_mutable_iter
+{
+ slist_node *cur; /* current element */
+ slist_node *next; /* next node we'll iterate to */
+ slist_node *prev; /* prev node, for deletions */
+} slist_mutable_iter;
+
+
+/* Static initializers */
+#define DLIST_STATIC_INIT(name) {{&(name).head, &(name).head}}
+#define SLIST_STATIC_INIT(name) {{NULL}}
+
+
+/* Prototypes for functions too big to be inline */
+
+/* Caution: this is O(n); consider using slist_delete_current() instead */
+extern void slist_delete(slist_head *head, slist_node *node);
+
+#ifdef ILIST_DEBUG
+extern void dlist_check(dlist_head *head);
+extern void slist_check(slist_head *head);
+#else
+/*
+ * These seemingly useless casts to void are here to keep the compiler quiet
+ * about the argument being unused in many functions in a non-debug compile,
+ * in which functions the only point of passing the list head pointer is to be
+ * able to run these checks.
+ */
+#define dlist_check(head) ((void) (head))
+#define slist_check(head) ((void) (head))
+#endif /* ILIST_DEBUG */
+
+/* doubly linked list implementation */
+
+/*
+ * Initialize a doubly linked list.
+ * Previous state will be thrown away without any cleanup.
+ */
+static inline void
+dlist_init(dlist_head *head)
+{
+ head->head.next = head->head.prev = &head->head;
+}
+
+/*
+ * Is the list empty?
+ *
+ * An empty list has either its first 'next' pointer set to NULL, or to itself.
+ */
+static inline bool
+dlist_is_empty(dlist_head *head)
+{
+ dlist_check(head);
+
+ return head->head.next == NULL || head->head.next == &(head->head);
+}
+
+/*
+ * Insert a node at the beginning of the list.
+ */
+static inline void
+dlist_push_head(dlist_head *head, dlist_node *node)
+{
+ if (head->head.next == NULL) /* convert NULL header to circular */
+ dlist_init(head);
+
+ node->next = head->head.next;
+ node->prev = &head->head;
+ node->next->prev = node;
+ head->head.next = node;
+
+ dlist_check(head);
+}
+
+/*
+ * Insert a node at the end of the list.
+ */
+static inline void
+dlist_push_tail(dlist_head *head, dlist_node *node)
+{
+ if (head->head.next == NULL) /* convert NULL header to circular */
+ dlist_init(head);
+
+ node->next = &head->head;
+ node->prev = head->head.prev;
+ node->prev->next = node;
+ head->head.prev = node;
+
+ dlist_check(head);
+}
+
+/*
+ * Insert a node after another *in the same list*
+ */
+static inline void
+dlist_insert_after(dlist_node *after, dlist_node *node)
+{
+ node->prev = after;
+ node->next = after->next;
+ after->next = node;
+ node->next->prev = node;
+}
+
+/*
+ * Insert a node before another *in the same list*
+ */
+static inline void
+dlist_insert_before(dlist_node *before, dlist_node *node)
+{
+ node->prev = before->prev;
+ node->next = before;
+ before->prev = node;
+ node->prev->next = node;
+}
+
+/*
+ * Delete 'node' from its list (it must be in one).
+ */
+static inline void
+dlist_delete(dlist_node *node)
+{
+ node->prev->next = node->next;
+ node->next->prev = node->prev;
+}
+
+/*
+ * Remove and return the first node from a list (there must be one).
+ */
+static inline dlist_node *
+dlist_pop_head_node(dlist_head *head)
+{
+ dlist_node *node;
+
+ Assert(!dlist_is_empty(head));
+ node = head->head.next;
+ dlist_delete(node);
+ return node;
+}
+
+/*
+ * Move element from its current position in the list to the head position in
+ * the same list.
+ *
+ * Undefined behaviour if 'node' is not already part of the list.
+ */
+static inline void
+dlist_move_head(dlist_head *head, dlist_node *node)
+{
+ /* fast path if it's already at the head */
+ if (head->head.next == node)
+ return;
+
+ dlist_delete(node);
+ dlist_push_head(head, node);
+
+ dlist_check(head);
+}
+
+/*
+ * Check whether 'node' has a following node.
+ * Caution: unreliable if 'node' is not in the list.
+ */
+static inline bool
+dlist_has_next(dlist_head *head, dlist_node *node)
+{
+ return node->next != &head->head;
+}
+
+/*
+ * Check whether 'node' has a preceding node.
+ * Caution: unreliable if 'node' is not in the list.
+ */
+static inline bool
+dlist_has_prev(dlist_head *head, dlist_node *node)
+{
+ return node->prev != &head->head;
+}
+
+/*
+ * Return the next node in the list (there must be one).
+ */
+static inline dlist_node *
+dlist_next_node(dlist_head *head, dlist_node *node)
+{
+ Assert(dlist_has_next(head, node));
+ return node->next;
+}
+
+/*
+ * Return previous node in the list (there must be one).
+ */
+static inline dlist_node *
+dlist_prev_node(dlist_head *head, dlist_node *node)
+{
+ Assert(dlist_has_prev(head, node));
+ return node->prev;
+}
+
+/* internal support function to get address of head element's struct */
+static inline void *
+dlist_head_element_off(dlist_head *head, size_t off)
+{
+ Assert(!dlist_is_empty(head));
+ return (char *) head->head.next - off;
+}
+
+/*
+ * Return the first node in the list (there must be one).
+ */
+static inline dlist_node *
+dlist_head_node(dlist_head *head)
+{
+ return (dlist_node *) dlist_head_element_off(head, 0);
+}
+
+/* internal support function to get address of tail element's struct */
+static inline void *
+dlist_tail_element_off(dlist_head *head, size_t off)
+{
+ Assert(!dlist_is_empty(head));
+ return (char *) head->head.prev - off;
+}
+
+/*
+ * Return the last node in the list (there must be one).
+ */
+static inline dlist_node *
+dlist_tail_node(dlist_head *head)
+{
+ return (dlist_node *) dlist_tail_element_off(head, 0);
+}
+
+/*
+ * Return the containing struct of 'type' where 'membername' is the dlist_node
+ * pointed at by 'ptr'.
+ *
+ * This is used to convert a dlist_node * back to its containing struct.
+ */
+#define dlist_container(type, membername, ptr) \
+ (AssertVariableIsOfTypeMacro(ptr, dlist_node *), \
+ AssertVariableIsOfTypeMacro(((type *) NULL)->membername, dlist_node), \
+ ((type *) ((char *) (ptr) - offsetof(type, membername))))
+
+/*
+ * Return the address of the first element in the list.
+ *
+ * The list must not be empty.
+ */
+#define dlist_head_element(type, membername, lhead) \
+ (AssertVariableIsOfTypeMacro(((type *) NULL)->membername, dlist_node), \
+ (type *) dlist_head_element_off(lhead, offsetof(type, membername)))
+
+/*
+ * Return the address of the last element in the list.
+ *
+ * The list must not be empty.
+ */
+#define dlist_tail_element(type, membername, lhead) \
+ (AssertVariableIsOfTypeMacro(((type *) NULL)->membername, dlist_node), \
+ ((type *) dlist_tail_element_off(lhead, offsetof(type, membername))))
+
+/*
+ * Iterate through the list pointed at by 'lhead' storing the state in 'iter'.
+ *
+ * Access the current element with iter.cur.
+ *
+ * It is *not* allowed to manipulate the list during iteration.
+ */
+#define dlist_foreach(iter, lhead) \
+ for (AssertVariableIsOfTypeMacro(iter, dlist_iter), \
+ AssertVariableIsOfTypeMacro(lhead, dlist_head *), \
+ (iter).end = &(lhead)->head, \
+ (iter).cur = (iter).end->next ? (iter).end->next : (iter).end; \
+ (iter).cur != (iter).end; \
+ (iter).cur = (iter).cur->next)
+
+/*
+ * Iterate through the list pointed at by 'lhead' storing the state in 'iter'.
+ *
+ * Access the current element with iter.cur.
+ *
+ * Iterations using this are only allowed to change the list at the current
+ * point of iteration. It is fine to delete the current node, but it is *not*
+ * fine to insert or delete adjacent nodes.
+ */
+#define dlist_foreach_modify(iter, lhead) \
+ for (AssertVariableIsOfTypeMacro(iter, dlist_mutable_iter), \
+ AssertVariableIsOfTypeMacro(lhead, dlist_head *), \
+ (iter).end = &(lhead)->head, \
+ (iter).cur = (iter).end->next ? (iter).end->next : (iter).end, \
+ (iter).next = (iter).cur->next; \
+ (iter).cur != (iter).end; \
+ (iter).cur = (iter).next, (iter).next = (iter).cur->next)
+
+/*
+ * Iterate through the list in reverse order.
+ *
+ * It is *not* allowed to manipulate the list during iteration.
+ */
+#define dlist_reverse_foreach(iter, lhead) \
+ for (AssertVariableIsOfTypeMacro(iter, dlist_iter), \
+ AssertVariableIsOfTypeMacro(lhead, dlist_head *), \
+ (iter).end = &(lhead)->head, \
+ (iter).cur = (iter).end->prev ? (iter).end->prev : (iter).end; \
+ (iter).cur != (iter).end; \
+ (iter).cur = (iter).cur->prev)
+
+
+/* singly linked list implementation */
+
+/*
+ * Initialize a singly linked list.
+ * Previous state will be thrown away without any cleanup.
+ */
+static inline void
+slist_init(slist_head *head)
+{
+ head->head.next = NULL;
+}
+
+/*
+ * Is the list empty?
+ */
+static inline bool
+slist_is_empty(slist_head *head)
+{
+ slist_check(head);
+
+ return head->head.next == NULL;
+}
+
+/*
+ * Insert a node at the beginning of the list.
+ */
+static inline void
+slist_push_head(slist_head *head, slist_node *node)
+{
+ node->next = head->head.next;
+ head->head.next = node;
+
+ slist_check(head);
+}
+
+/*
+ * Insert a node after another *in the same list*
+ */
+static inline void
+slist_insert_after(slist_node *after, slist_node *node)
+{
+ node->next = after->next;
+ after->next = node;
+}
+
+/*
+ * Remove and return the first node from a list (there must be one).
+ */
+static inline slist_node *
+slist_pop_head_node(slist_head *head)
+{
+ slist_node *node;
+
+ Assert(!slist_is_empty(head));
+ node = head->head.next;
+ head->head.next = node->next;
+ slist_check(head);
+ return node;
+}
+
+/*
+ * Check whether 'node' has a following node.
+ */
+static inline bool
+slist_has_next(slist_head *head, slist_node *node)
+{
+ slist_check(head);
+
+ return node->next != NULL;
+}
+
+/*
+ * Return the next node in the list (there must be one).
+ */
+static inline slist_node *
+slist_next_node(slist_head *head, slist_node *node)
+{
+ Assert(slist_has_next(head, node));
+ return node->next;
+}
+
+/* internal support function to get address of head element's struct */
+static inline void *
+slist_head_element_off(slist_head *head, size_t off)
+{
+ Assert(!slist_is_empty(head));
+ return (char *) head->head.next - off;
+}
+
+/*
+ * Return the first node in the list (there must be one).
+ */
+static inline slist_node *
+slist_head_node(slist_head *head)
+{
+ return (slist_node *) slist_head_element_off(head, 0);
+}
+
+/*
+ * Delete the list element the iterator currently points to.
+ *
+ * Caution: this modifies iter->cur, so don't use that again in the current
+ * loop iteration.
+ */
+static inline void
+slist_delete_current(slist_mutable_iter *iter)
+{
+ /*
+ * Update previous element's forward link. If the iteration is at the
+ * first list element, iter->prev will point to the list header's "head"
+ * field, so we don't need a special case for that.
+ */
+ iter->prev->next = iter->next;
+
+ /*
+ * Reset cur to prev, so that prev will continue to point to the prior
+ * valid list element after slist_foreach_modify() advances to the next.
+ */
+ iter->cur = iter->prev;
+}
+
+/*
+ * Return the containing struct of 'type' where 'membername' is the slist_node
+ * pointed at by 'ptr'.
+ *
+ * This is used to convert a slist_node * back to its containing struct.
+ */
+#define slist_container(type, membername, ptr) \
+ (AssertVariableIsOfTypeMacro(ptr, slist_node *), \
+ AssertVariableIsOfTypeMacro(((type *) NULL)->membername, slist_node), \
+ ((type *) ((char *) (ptr) - offsetof(type, membername))))
+
+/*
+ * Return the address of the first element in the list.
+ *
+ * The list must not be empty.
+ */
+#define slist_head_element(type, membername, lhead) \
+ (AssertVariableIsOfTypeMacro(((type *) NULL)->membername, slist_node), \
+ (type *) slist_head_element_off(lhead, offsetof(type, membername)))
+
+/*
+ * Iterate through the list pointed at by 'lhead' storing the state in 'iter'.
+ *
+ * Access the current element with iter.cur.
+ *
+ * It's allowed to modify the list while iterating, with the exception of
+ * deleting the iterator's current node; deletion of that node requires
+ * care if the iteration is to be continued afterward. (Doing so and also
+ * deleting or inserting adjacent list elements might misbehave; also, if
+ * the user frees the current node's storage, continuing the iteration is
+ * not safe.)
+ */
+#define slist_foreach(iter, lhead) \
+ for (AssertVariableIsOfTypeMacro(iter, slist_iter), \
+ AssertVariableIsOfTypeMacro(lhead, slist_head *), \
+ (iter).cur = (lhead)->head.next; \
+ (iter).cur != NULL; \
+ (iter).cur = (iter).cur->next)
+
+/*
+ * Iterate through the list pointed at by 'lhead' storing the state in 'iter'.
+ *
+ * Access the current element with iter.cur.
+ *
+ * The only list modification allowed while iterating is to remove the current
+ * node via slist_delete_current() (*not* slist_delete()). Insertion or
+ * deletion of nodes adjacent to the current node would misbehave.
+ */
+#define slist_foreach_modify(iter, lhead) \
+ for (AssertVariableIsOfTypeMacro(iter, slist_mutable_iter), \
+ AssertVariableIsOfTypeMacro(lhead, slist_head *), \
+ (iter).prev = &(lhead)->head, \
+ (iter).cur = (iter).prev->next, \
+ (iter).next = (iter).cur ? (iter).cur->next : NULL; \
+ (iter).cur != NULL; \
+ (iter).prev = (iter).cur, \
+ (iter).cur = (iter).next, \
+ (iter).next = (iter).next ? (iter).next->next : NULL)
+
+#endif /* ILIST_H */
diff --git a/src/include/lib/integerset.h b/src/include/lib/integerset.h
new file mode 100644
index 0000000..67bf5c5
--- /dev/null
+++ b/src/include/lib/integerset.h
@@ -0,0 +1,24 @@
+/*
+ * integerset.h
+ * In-memory data structure to hold a large set of integers efficiently
+ *
+ * Portions Copyright (c) 2012-2020, PostgreSQL Global Development Group
+ *
+ * src/include/lib/integerset.h
+ */
+#ifndef INTEGERSET_H
+#define INTEGERSET_H
+
+typedef struct IntegerSet IntegerSet;
+
+extern IntegerSet *intset_create(void);
+extern void intset_add_member(IntegerSet *intset, uint64 x);
+extern bool intset_is_member(IntegerSet *intset, uint64 x);
+
+extern uint64 intset_num_entries(IntegerSet *intset);
+extern uint64 intset_memory_usage(IntegerSet *intset);
+
+extern void intset_begin_iterate(IntegerSet *intset);
+extern bool intset_iterate_next(IntegerSet *intset, uint64 *next);
+
+#endif /* INTEGERSET_H */
diff --git a/src/include/lib/knapsack.h b/src/include/lib/knapsack.h
new file mode 100644
index 0000000..2d90dc4
--- /dev/null
+++ b/src/include/lib/knapsack.h
@@ -0,0 +1,16 @@
+/*
+ * knapsack.h
+ *
+ * Copyright (c) 2017-2020, PostgreSQL Global Development Group
+ *
+ * src/include/lib/knapsack.h
+ */
+#ifndef KNAPSACK_H
+#define KNAPSACK_H
+
+#include "nodes/bitmapset.h"
+
+extern Bitmapset *DiscreteKnapsack(int max_weight, int num_items,
+ int *item_weights, double *item_values);
+
+#endif /* KNAPSACK_H */
diff --git a/src/include/lib/pairingheap.h b/src/include/lib/pairingheap.h
new file mode 100644
index 0000000..7c5c0f7
--- /dev/null
+++ b/src/include/lib/pairingheap.h
@@ -0,0 +1,102 @@
+/*
+ * pairingheap.h
+ *
+ * A Pairing Heap implementation
+ *
+ * Portions Copyright (c) 2012-2020, PostgreSQL Global Development Group
+ *
+ * src/include/lib/pairingheap.h
+ */
+
+#ifndef PAIRINGHEAP_H
+#define PAIRINGHEAP_H
+
+#include "lib/stringinfo.h"
+
+/* Enable if you need the pairingheap_dump() debug function */
+/* #define PAIRINGHEAP_DEBUG */
+
+/*
+ * This represents an element stored in the heap. Embed this in a larger
+ * struct containing the actual data you're storing.
+ *
+ * A node can have multiple children, which form a double-linked list.
+ * first_child points to the node's first child, and the subsequent children
+ * can be found by following the next_sibling pointers. The last child has
+ * next_sibling == NULL. The prev_or_parent pointer points to the node's
+ * previous sibling, or if the node is its parent's first child, to the
+ * parent.
+ */
+typedef struct pairingheap_node
+{
+ struct pairingheap_node *first_child;
+ struct pairingheap_node *next_sibling;
+ struct pairingheap_node *prev_or_parent;
+} pairingheap_node;
+
+/*
+ * Return the containing struct of 'type' where 'membername' is the
+ * pairingheap_node pointed at by 'ptr'.
+ *
+ * This is used to convert a pairingheap_node * back to its containing struct.
+ */
+#define pairingheap_container(type, membername, ptr) \
+ (AssertVariableIsOfTypeMacro(ptr, pairingheap_node *), \
+ AssertVariableIsOfTypeMacro(((type *) NULL)->membername, pairingheap_node), \
+ ((type *) ((char *) (ptr) - offsetof(type, membername))))
+
+/*
+ * Like pairingheap_container, but used when the pointer is 'const ptr'
+ */
+#define pairingheap_const_container(type, membername, ptr) \
+ (AssertVariableIsOfTypeMacro(ptr, const pairingheap_node *), \
+ AssertVariableIsOfTypeMacro(((type *) NULL)->membername, pairingheap_node), \
+ ((const type *) ((const char *) (ptr) - offsetof(type, membername))))
+
+/*
+ * For a max-heap, the comparator must return <0 iff a < b, 0 iff a == b,
+ * and >0 iff a > b. For a min-heap, the conditions are reversed.
+ */
+typedef int (*pairingheap_comparator) (const pairingheap_node *a,
+ const pairingheap_node *b,
+ void *arg);
+
+/*
+ * A pairing heap.
+ *
+ * You can use pairingheap_allocate() to create a new palloc'd heap, or embed
+ * this in a larger struct, set ph_compare and ph_arg directly and initialize
+ * ph_root to NULL.
+ */
+typedef struct pairingheap
+{
+ pairingheap_comparator ph_compare; /* comparison function */
+ void *ph_arg; /* opaque argument to ph_compare */
+ pairingheap_node *ph_root; /* current root of the heap */
+} pairingheap;
+
+extern pairingheap *pairingheap_allocate(pairingheap_comparator compare,
+ void *arg);
+extern void pairingheap_free(pairingheap *heap);
+extern void pairingheap_add(pairingheap *heap, pairingheap_node *node);
+extern pairingheap_node *pairingheap_first(pairingheap *heap);
+extern pairingheap_node *pairingheap_remove_first(pairingheap *heap);
+extern void pairingheap_remove(pairingheap *heap, pairingheap_node *node);
+
+#ifdef PAIRINGHEAP_DEBUG
+extern char *pairingheap_dump(pairingheap *heap,
+ void (*dumpfunc) (pairingheap_node *node, StringInfo buf, void *opaque),
+ void *opaque);
+#endif
+
+/* Resets the heap to be empty. */
+#define pairingheap_reset(h) ((h)->ph_root = NULL)
+
+/* Is the heap empty? */
+#define pairingheap_is_empty(h) ((h)->ph_root == NULL)
+
+/* Is there exactly one node in the heap? */
+#define pairingheap_is_singular(h) \
+ ((h)->ph_root && (h)->ph_root->first_child == NULL)
+
+#endif /* PAIRINGHEAP_H */
diff --git a/src/include/lib/qunique.h b/src/include/lib/qunique.h
new file mode 100644
index 0000000..95d9fef
--- /dev/null
+++ b/src/include/lib/qunique.h
@@ -0,0 +1,67 @@
+/*-------------------------------------------------------------------------
+ *
+ * qunique.h
+ * inline array unique functions
+ * Portions Copyright (c) 2019-2020, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/lib/qunique.h
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef QUNIQUE_H
+#define QUNIQUE_H
+
+/*
+ * Remove duplicates from a pre-sorted array, according to a user-supplied
+ * comparator. Usually the array should have been sorted with qsort() using
+ * the same arguments. Return the new size.
+ */
+static inline size_t
+qunique(void *array, size_t elements, size_t width,
+ int (*compare) (const void *, const void *))
+{
+ char *bytes = (char *) array;
+ size_t i,
+ j;
+
+ if (elements <= 1)
+ return elements;
+
+ for (i = 1, j = 0; i < elements; ++i)
+ {
+ if (compare(bytes + i * width, bytes + j * width) != 0 &&
+ ++j != i)
+ memcpy(bytes + j * width, bytes + i * width, width);
+ }
+
+ return j + 1;
+}
+
+/*
+ * Like qunique(), but takes a comparator with an extra user data argument
+ * which is passed through, for compatibility with qsort_arg().
+ */
+static inline size_t
+qunique_arg(void *array, size_t elements, size_t width,
+ int (*compare) (const void *, const void *, void *),
+ void *arg)
+{
+ char *bytes = (char *) array;
+ size_t i,
+ j;
+
+ if (elements <= 1)
+ return elements;
+
+ for (i = 1, j = 0; i < elements; ++i)
+ {
+ if (compare(bytes + i * width, bytes + j * width, arg) != 0 &&
+ ++j != i)
+ memcpy(bytes + j * width, bytes + i * width, width);
+ }
+
+ return j + 1;
+}
+
+#endif /* QUNIQUE_H */
diff --git a/src/include/lib/rbtree.h b/src/include/lib/rbtree.h
new file mode 100644
index 0000000..cd2c2fd
--- /dev/null
+++ b/src/include/lib/rbtree.h
@@ -0,0 +1,79 @@
+/*-------------------------------------------------------------------------
+ *
+ * rbtree.h
+ * interface for PostgreSQL generic Red-Black binary tree package
+ *
+ * Copyright (c) 2009-2020, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/lib/rbtree.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RBTREE_H
+#define RBTREE_H
+
+/*
+ * RBTNode is intended to be used as the first field of a larger struct,
+ * whose additional fields carry whatever payload data the caller needs
+ * for a tree entry. (The total size of that larger struct is passed to
+ * rbt_create.) RBTNode is declared here to support this usage, but
+ * callers must treat it as an opaque struct.
+ */
+typedef struct RBTNode
+{
+ char color; /* node's current color, red or black */
+ struct RBTNode *left; /* left child, or RBTNIL if none */
+ struct RBTNode *right; /* right child, or RBTNIL if none */
+ struct RBTNode *parent; /* parent, or NULL (not RBTNIL!) if none */
+} RBTNode;
+
+/* Opaque struct representing a whole tree */
+typedef struct RBTree RBTree;
+
+/* Available tree iteration orderings */
+typedef enum RBTOrderControl
+{
+ LeftRightWalk, /* inorder: left child, node, right child */
+ RightLeftWalk /* reverse inorder: right, node, left */
+} RBTOrderControl;
+
+/*
+ * RBTreeIterator holds state while traversing a tree. This is declared
+ * here so that callers can stack-allocate this, but must otherwise be
+ * treated as an opaque struct.
+ */
+typedef struct RBTreeIterator RBTreeIterator;
+
+struct RBTreeIterator
+{
+ RBTree *rbt;
+ RBTNode *(*iterate) (RBTreeIterator *iter);
+ RBTNode *last_visited;
+ bool is_over;
+};
+
+/* Support functions to be provided by caller */
+typedef int (*rbt_comparator) (const RBTNode *a, const RBTNode *b, void *arg);
+typedef void (*rbt_combiner) (RBTNode *existing, const RBTNode *newdata, void *arg);
+typedef RBTNode *(*rbt_allocfunc) (void *arg);
+typedef void (*rbt_freefunc) (RBTNode *x, void *arg);
+
+extern RBTree *rbt_create(Size node_size,
+ rbt_comparator comparator,
+ rbt_combiner combiner,
+ rbt_allocfunc allocfunc,
+ rbt_freefunc freefunc,
+ void *arg);
+
+extern RBTNode *rbt_find(RBTree *rbt, const RBTNode *data);
+extern RBTNode *rbt_leftmost(RBTree *rbt);
+
+extern RBTNode *rbt_insert(RBTree *rbt, const RBTNode *data, bool *isNew);
+extern void rbt_delete(RBTree *rbt, RBTNode *node);
+
+extern void rbt_begin_iterate(RBTree *rbt, RBTOrderControl ctrl,
+ RBTreeIterator *iter);
+extern RBTNode *rbt_iterate(RBTreeIterator *iter);
+
+#endif /* RBTREE_H */
diff --git a/src/include/lib/simplehash.h b/src/include/lib/simplehash.h
new file mode 100644
index 0000000..90dfa8a
--- /dev/null
+++ b/src/include/lib/simplehash.h
@@ -0,0 +1,1059 @@
+/*
+ * simplehash.h
+ *
+ * Hash table implementation which will be specialized to user-defined
+ * types, by including this file to generate the required code. It's
+ * probably not worthwhile to do so for hash tables that aren't performance
+ * or space sensitive.
+ *
+ * Usage notes:
+ *
+ * To generate a hash-table and associated functions for a use case several
+ * macros have to be #define'ed before this file is included. Including
+ * the file #undef's all those, so a new hash table can be generated
+ * afterwards.
+ * The relevant parameters are:
+ * - SH_PREFIX - prefix for all symbol names generated. A prefix of 'foo'
+ * will result in hash table type 'foo_hash' and functions like
+ * 'foo_insert'/'foo_lookup' and so forth.
+ * - SH_ELEMENT_TYPE - type of the contained elements
+ * - SH_KEY_TYPE - type of the hashtable's key
+ * - SH_DECLARE - if defined function prototypes and type declarations are
+ * generated
+ * - SH_DEFINE - if defined function definitions are generated
+ * - SH_SCOPE - in which scope (e.g. extern, static inline) do function
+ * declarations reside
+ * - SH_RAW_ALLOCATOR - if defined, memory contexts are not used; instead,
+ * use this to allocate bytes
+ * - SH_USE_NONDEFAULT_ALLOCATOR - if defined no element allocator functions
+ * are defined, so you can supply your own
+ * The following parameters are only relevant when SH_DEFINE is defined:
+ * - SH_KEY - name of the element in SH_ELEMENT_TYPE containing the hash key
+ * - SH_EQUAL(table, a, b) - compare two table keys
+ * - SH_HASH_KEY(table, key) - generate hash for the key
+ * - SH_STORE_HASH - if defined the hash is stored in the elements
+ * - SH_GET_HASH(tb, a) - return the field to store the hash in
+ *
+ * For examples of usage look at tidbitmap.c (file local definition) and
+ * execnodes.h/execGrouping.c (exposed declaration, file local
+ * implementation).
+ *
+ * Hash table design:
+ *
+ * The hash table design chosen is a variant of linear open-addressing. The
+ * reason for doing so is that linear addressing is CPU cache & pipeline
+ * friendly. The biggest disadvantage of simple linear addressing schemes
+ * are highly variable lookup times due to clustering, and deletions
+ * leaving a lot of tombstones around. To address these issues a variant
+ * of "robin hood" hashing is employed. Robin hood hashing optimizes
+ * chaining lengths by moving elements close to their optimal bucket
+ * ("rich" elements), out of the way if a to-be-inserted element is further
+ * away from its optimal position (i.e. it's "poor"). While that can make
+ * insertions slower, the average lookup performance is a lot better, and
+ * higher fill factors can be used in a still performant manner. To avoid
+ * tombstones - which normally solve the issue that a deleted node's
+ * presence is relevant to determine whether a lookup needs to continue
+ * looking or is done - buckets following a deleted element are shifted
+ * backwards, unless they're empty or already at their optimal position.
+ */
+
+#include "port/pg_bitutils.h"
+
+/* helpers */
+#define SH_MAKE_PREFIX(a) CppConcat(a,_)
+#define SH_MAKE_NAME(name) SH_MAKE_NAME_(SH_MAKE_PREFIX(SH_PREFIX),name)
+#define SH_MAKE_NAME_(a,b) CppConcat(a,b)
+
+/* name macros for: */
+
+/* type declarations */
+#define SH_TYPE SH_MAKE_NAME(hash)
+#define SH_STATUS SH_MAKE_NAME(status)
+#define SH_STATUS_EMPTY SH_MAKE_NAME(SH_EMPTY)
+#define SH_STATUS_IN_USE SH_MAKE_NAME(SH_IN_USE)
+#define SH_ITERATOR SH_MAKE_NAME(iterator)
+
+/* function declarations */
+#define SH_CREATE SH_MAKE_NAME(create)
+#define SH_DESTROY SH_MAKE_NAME(destroy)
+#define SH_RESET SH_MAKE_NAME(reset)
+#define SH_INSERT SH_MAKE_NAME(insert)
+#define SH_INSERT_HASH SH_MAKE_NAME(insert_hash)
+#define SH_DELETE SH_MAKE_NAME(delete)
+#define SH_LOOKUP SH_MAKE_NAME(lookup)
+#define SH_LOOKUP_HASH SH_MAKE_NAME(lookup_hash)
+#define SH_GROW SH_MAKE_NAME(grow)
+#define SH_START_ITERATE SH_MAKE_NAME(start_iterate)
+#define SH_START_ITERATE_AT SH_MAKE_NAME(start_iterate_at)
+#define SH_ITERATE SH_MAKE_NAME(iterate)
+#define SH_ALLOCATE SH_MAKE_NAME(allocate)
+#define SH_FREE SH_MAKE_NAME(free)
+#define SH_STAT SH_MAKE_NAME(stat)
+
+/* internal helper functions (no externally visible prototypes) */
+#define SH_COMPUTE_PARAMETERS SH_MAKE_NAME(compute_parameters)
+#define SH_NEXT SH_MAKE_NAME(next)
+#define SH_PREV SH_MAKE_NAME(prev)
+#define SH_DISTANCE_FROM_OPTIMAL SH_MAKE_NAME(distance)
+#define SH_INITIAL_BUCKET SH_MAKE_NAME(initial_bucket)
+#define SH_ENTRY_HASH SH_MAKE_NAME(entry_hash)
+#define SH_INSERT_HASH_INTERNAL SH_MAKE_NAME(insert_hash_internal)
+#define SH_LOOKUP_HASH_INTERNAL SH_MAKE_NAME(lookup_hash_internal)
+
+/* generate forward declarations necessary to use the hash table */
+#ifdef SH_DECLARE
+
+/* type definitions */
+typedef struct SH_TYPE
+{
+ /*
+ * Size of data / bucket array, 64 bits to handle UINT32_MAX sized hash
+ * tables. Note that the maximum number of elements is lower
+ * (SH_MAX_FILLFACTOR)
+ */
+ uint64 size;
+
+ /* how many elements have valid contents */
+ uint32 members;
+
+ /* mask for bucket and size calculations, based on size */
+ uint32 sizemask;
+
+ /* boundary after which to grow hashtable */
+ uint32 grow_threshold;
+
+ /* hash buckets */
+ SH_ELEMENT_TYPE *data;
+
+#ifndef SH_RAW_ALLOCATOR
+ /* memory context to use for allocations */
+ MemoryContext ctx;
+#endif
+
+ /* user defined data, useful for callbacks */
+ void *private_data;
+} SH_TYPE;
+
+typedef enum SH_STATUS
+{
+ SH_STATUS_EMPTY = 0x00,
+ SH_STATUS_IN_USE = 0x01
+} SH_STATUS;
+
+typedef struct SH_ITERATOR
+{
+ uint32 cur; /* current element */
+ uint32 end;
+ bool done; /* iterator exhausted? */
+} SH_ITERATOR;
+
+/* externally visible function prototypes */
+#ifdef SH_RAW_ALLOCATOR
+SH_SCOPE SH_TYPE *SH_CREATE(uint32 nelements, void *private_data);
+#else
+SH_SCOPE SH_TYPE *SH_CREATE(MemoryContext ctx, uint32 nelements,
+ void *private_data);
+#endif
+SH_SCOPE void SH_DESTROY(SH_TYPE * tb);
+SH_SCOPE void SH_RESET(SH_TYPE * tb);
+SH_SCOPE void SH_GROW(SH_TYPE * tb, uint32 newsize);
+SH_SCOPE SH_ELEMENT_TYPE *SH_INSERT(SH_TYPE * tb, SH_KEY_TYPE key, bool *found);
+SH_SCOPE SH_ELEMENT_TYPE *SH_INSERT_HASH(SH_TYPE * tb, SH_KEY_TYPE key,
+ uint32 hash, bool *found);
+SH_SCOPE SH_ELEMENT_TYPE *SH_LOOKUP(SH_TYPE * tb, SH_KEY_TYPE key);
+SH_SCOPE SH_ELEMENT_TYPE *SH_LOOKUP_HASH(SH_TYPE * tb, SH_KEY_TYPE key,
+ uint32 hash);
+SH_SCOPE bool SH_DELETE(SH_TYPE * tb, SH_KEY_TYPE key);
+SH_SCOPE void SH_START_ITERATE(SH_TYPE * tb, SH_ITERATOR * iter);
+SH_SCOPE void SH_START_ITERATE_AT(SH_TYPE * tb, SH_ITERATOR * iter, uint32 at);
+SH_SCOPE SH_ELEMENT_TYPE *SH_ITERATE(SH_TYPE * tb, SH_ITERATOR * iter);
+SH_SCOPE void SH_STAT(SH_TYPE * tb);
+
+#endif /* SH_DECLARE */
+
+
+/* generate implementation of the hash table */
+#ifdef SH_DEFINE
+
+#ifndef SH_RAW_ALLOCATOR
+#include "utils/memutils.h"
+#endif
+
+/* max data array size,we allow up to PG_UINT32_MAX buckets, including 0 */
+#define SH_MAX_SIZE (((uint64) PG_UINT32_MAX) + 1)
+
+/* normal fillfactor, unless already close to maximum */
+#ifndef SH_FILLFACTOR
+#define SH_FILLFACTOR (0.9)
+#endif
+/* increase fillfactor if we otherwise would error out */
+#define SH_MAX_FILLFACTOR (0.98)
+/* grow if actual and optimal location bigger than */
+#ifndef SH_GROW_MAX_DIB
+#define SH_GROW_MAX_DIB 25
+#endif
+/* grow if more than elements to move when inserting */
+#ifndef SH_GROW_MAX_MOVE
+#define SH_GROW_MAX_MOVE 150
+#endif
+#ifndef SH_GROW_MIN_FILLFACTOR
+/* but do not grow due to SH_GROW_MAX_* if below */
+#define SH_GROW_MIN_FILLFACTOR 0.1
+#endif
+
+#ifdef SH_STORE_HASH
+#define SH_COMPARE_KEYS(tb, ahash, akey, b) (ahash == SH_GET_HASH(tb, b) && SH_EQUAL(tb, b->SH_KEY, akey))
+#else
+#define SH_COMPARE_KEYS(tb, ahash, akey, b) (SH_EQUAL(tb, b->SH_KEY, akey))
+#endif
+
+/*
+ * Wrap the following definitions in include guards, to avoid multiple
+ * definition errors if this header is included more than once. The rest of
+ * the file deliberately has no include guards, because it can be included
+ * with different parameters to define functions and types with non-colliding
+ * names.
+ */
+#ifndef SIMPLEHASH_H
+#define SIMPLEHASH_H
+
+#ifdef FRONTEND
+#define sh_error(...) pg_log_error(__VA_ARGS__)
+#define sh_log(...) pg_log_info(__VA_ARGS__)
+#else
+#define sh_error(...) elog(ERROR, __VA_ARGS__)
+#define sh_log(...) elog(LOG, __VA_ARGS__)
+#endif
+
+#endif
+
+/*
+ * Compute sizing parameters for hashtable. Called when creating and growing
+ * the hashtable.
+ */
+static inline void
+SH_COMPUTE_PARAMETERS(SH_TYPE * tb, uint32 newsize)
+{
+ uint64 size;
+
+ /* supporting zero sized hashes would complicate matters */
+ size = Max(newsize, 2);
+
+ /* round up size to the next power of 2, that's how bucketing works */
+ size = pg_nextpower2_64(size);
+ Assert(size <= SH_MAX_SIZE);
+
+ /*
+ * Verify that allocation of ->data is possible on this platform, without
+ * overflowing Size.
+ */
+ if ((((uint64) sizeof(SH_ELEMENT_TYPE)) * size) >= SIZE_MAX / 2)
+ sh_error("hash table too large");
+
+ /* now set size */
+ tb->size = size;
+
+ if (tb->size == SH_MAX_SIZE)
+ tb->sizemask = 0;
+ else
+ tb->sizemask = tb->size - 1;
+
+ /*
+ * Compute the next threshold at which we need to grow the hash table
+ * again.
+ */
+ if (tb->size == SH_MAX_SIZE)
+ tb->grow_threshold = ((double) tb->size) * SH_MAX_FILLFACTOR;
+ else
+ tb->grow_threshold = ((double) tb->size) * SH_FILLFACTOR;
+}
+
+/* return the optimal bucket for the hash */
+static inline uint32
+SH_INITIAL_BUCKET(SH_TYPE * tb, uint32 hash)
+{
+ return hash & tb->sizemask;
+}
+
+/* return next bucket after the current, handling wraparound */
+static inline uint32
+SH_NEXT(SH_TYPE * tb, uint32 curelem, uint32 startelem)
+{
+ curelem = (curelem + 1) & tb->sizemask;
+
+ Assert(curelem != startelem);
+
+ return curelem;
+}
+
+/* return bucket before the current, handling wraparound */
+static inline uint32
+SH_PREV(SH_TYPE * tb, uint32 curelem, uint32 startelem)
+{
+ curelem = (curelem - 1) & tb->sizemask;
+
+ Assert(curelem != startelem);
+
+ return curelem;
+}
+
+/* return distance between bucket and its optimal position */
+static inline uint32
+SH_DISTANCE_FROM_OPTIMAL(SH_TYPE * tb, uint32 optimal, uint32 bucket)
+{
+ if (optimal <= bucket)
+ return bucket - optimal;
+ else
+ return (tb->size + bucket) - optimal;
+}
+
+static inline uint32
+SH_ENTRY_HASH(SH_TYPE * tb, SH_ELEMENT_TYPE * entry)
+{
+#ifdef SH_STORE_HASH
+ return SH_GET_HASH(tb, entry);
+#else
+ return SH_HASH_KEY(tb, entry->SH_KEY);
+#endif
+}
+
+/* default memory allocator function */
+static inline void *SH_ALLOCATE(SH_TYPE * type, Size size);
+static inline void SH_FREE(SH_TYPE * type, void *pointer);
+
+#ifndef SH_USE_NONDEFAULT_ALLOCATOR
+
+/* default memory allocator function */
+static inline void *
+SH_ALLOCATE(SH_TYPE * type, Size size)
+{
+#ifdef SH_RAW_ALLOCATOR
+ return SH_RAW_ALLOCATOR(size);
+#else
+ return MemoryContextAllocExtended(type->ctx, size,
+ MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO);
+#endif
+}
+
+/* default memory free function */
+static inline void
+SH_FREE(SH_TYPE * type, void *pointer)
+{
+ pfree(pointer);
+}
+
+#endif
+
+/*
+ * Create a hash table with enough space for `nelements` distinct members.
+ * Memory for the hash table is allocated from the passed-in context. If
+ * desired, the array of elements can be allocated using a passed-in allocator;
+ * this could be useful in order to place the array of elements in a shared
+ * memory, or in a context that will outlive the rest of the hash table.
+ * Memory other than for the array of elements will still be allocated from
+ * the passed-in context.
+ */
+#ifdef SH_RAW_ALLOCATOR
+SH_SCOPE SH_TYPE *
+SH_CREATE(uint32 nelements, void *private_data)
+#else
+SH_SCOPE SH_TYPE *
+SH_CREATE(MemoryContext ctx, uint32 nelements, void *private_data)
+#endif
+{
+ SH_TYPE *tb;
+ uint64 size;
+
+#ifdef SH_RAW_ALLOCATOR
+ tb = SH_RAW_ALLOCATOR(sizeof(SH_TYPE));
+#else
+ tb = MemoryContextAllocZero(ctx, sizeof(SH_TYPE));
+ tb->ctx = ctx;
+#endif
+ tb->private_data = private_data;
+
+ /* increase nelements by fillfactor, want to store nelements elements */
+ size = Min((double) SH_MAX_SIZE, ((double) nelements) / SH_FILLFACTOR);
+
+ SH_COMPUTE_PARAMETERS(tb, size);
+
+ tb->data = SH_ALLOCATE(tb, sizeof(SH_ELEMENT_TYPE) * tb->size);
+
+ return tb;
+}
+
+/* destroy a previously created hash table */
+SH_SCOPE void
+SH_DESTROY(SH_TYPE * tb)
+{
+ SH_FREE(tb, tb->data);
+ pfree(tb);
+}
+
+/* reset the contents of a previously created hash table */
+SH_SCOPE void
+SH_RESET(SH_TYPE * tb)
+{
+ memset(tb->data, 0, sizeof(SH_ELEMENT_TYPE) * tb->size);
+ tb->members = 0;
+}
+
+/*
+ * Grow a hash table to at least `newsize` buckets.
+ *
+ * Usually this will automatically be called by insertions/deletions, when
+ * necessary. But resizing to the exact input size can be advantageous
+ * performance-wise, when known at some point.
+ */
+SH_SCOPE void
+SH_GROW(SH_TYPE * tb, uint32 newsize)
+{
+ uint64 oldsize = tb->size;
+ SH_ELEMENT_TYPE *olddata = tb->data;
+ SH_ELEMENT_TYPE *newdata;
+ uint32 i;
+ uint32 startelem = 0;
+ uint32 copyelem;
+
+ Assert(oldsize == pg_nextpower2_64(oldsize));
+ Assert(oldsize != SH_MAX_SIZE);
+ Assert(oldsize < newsize);
+
+ /* compute parameters for new table */
+ SH_COMPUTE_PARAMETERS(tb, newsize);
+
+ tb->data = SH_ALLOCATE(tb, sizeof(SH_ELEMENT_TYPE) * tb->size);
+
+ newdata = tb->data;
+
+ /*
+ * Copy entries from the old data to newdata. We theoretically could use
+ * SH_INSERT here, to avoid code duplication, but that's more general than
+ * we need. We neither want tb->members increased, nor do we need to do
+ * deal with deleted elements, nor do we need to compare keys. So a
+ * special-cased implementation is lot faster. As resizing can be time
+ * consuming and frequent, that's worthwhile to optimize.
+ *
+ * To be able to simply move entries over, we have to start not at the
+ * first bucket (i.e olddata[0]), but find the first bucket that's either
+ * empty, or is occupied by an entry at its optimal position. Such a
+ * bucket has to exist in any table with a load factor under 1, as not all
+ * buckets are occupied, i.e. there always has to be an empty bucket. By
+ * starting at such a bucket we can move the entries to the larger table,
+ * without having to deal with conflicts.
+ */
+
+ /* search for the first element in the hash that's not wrapped around */
+ for (i = 0; i < oldsize; i++)
+ {
+ SH_ELEMENT_TYPE *oldentry = &olddata[i];
+ uint32 hash;
+ uint32 optimal;
+
+ if (oldentry->status != SH_STATUS_IN_USE)
+ {
+ startelem = i;
+ break;
+ }
+
+ hash = SH_ENTRY_HASH(tb, oldentry);
+ optimal = SH_INITIAL_BUCKET(tb, hash);
+
+ if (optimal == i)
+ {
+ startelem = i;
+ break;
+ }
+ }
+
+ /* and copy all elements in the old table */
+ copyelem = startelem;
+ for (i = 0; i < oldsize; i++)
+ {
+ SH_ELEMENT_TYPE *oldentry = &olddata[copyelem];
+
+ if (oldentry->status == SH_STATUS_IN_USE)
+ {
+ uint32 hash;
+ uint32 startelem;
+ uint32 curelem;
+ SH_ELEMENT_TYPE *newentry;
+
+ hash = SH_ENTRY_HASH(tb, oldentry);
+ startelem = SH_INITIAL_BUCKET(tb, hash);
+ curelem = startelem;
+
+ /* find empty element to put data into */
+ while (true)
+ {
+ newentry = &newdata[curelem];
+
+ if (newentry->status == SH_STATUS_EMPTY)
+ {
+ break;
+ }
+
+ curelem = SH_NEXT(tb, curelem, startelem);
+ }
+
+ /* copy entry to new slot */
+ memcpy(newentry, oldentry, sizeof(SH_ELEMENT_TYPE));
+ }
+
+ /* can't use SH_NEXT here, would use new size */
+ copyelem++;
+ if (copyelem >= oldsize)
+ {
+ copyelem = 0;
+ }
+ }
+
+ SH_FREE(tb, olddata);
+}
+
+/*
+ * This is a separate static inline function, so it can be reliably be inlined
+ * into its wrapper functions even if SH_SCOPE is extern.
+ */
+static inline SH_ELEMENT_TYPE *
+SH_INSERT_HASH_INTERNAL(SH_TYPE * tb, SH_KEY_TYPE key, uint32 hash, bool *found)
+{
+ uint32 startelem;
+ uint32 curelem;
+ SH_ELEMENT_TYPE *data;
+ uint32 insertdist;
+
+restart:
+ insertdist = 0;
+
+ /*
+ * We do the grow check even if the key is actually present, to avoid
+ * doing the check inside the loop. This also lets us avoid having to
+ * re-find our position in the hashtable after resizing.
+ *
+ * Note that this also reached when resizing the table due to
+ * SH_GROW_MAX_DIB / SH_GROW_MAX_MOVE.
+ */
+ if (unlikely(tb->members >= tb->grow_threshold))
+ {
+ if (tb->size == SH_MAX_SIZE)
+ {
+ sh_error("hash table size exceeded");
+ }
+
+ /*
+ * When optimizing, it can be very useful to print these out.
+ */
+ /* SH_STAT(tb); */
+ SH_GROW(tb, tb->size * 2);
+ /* SH_STAT(tb); */
+ }
+
+ /* perform insert, start bucket search at optimal location */
+ data = tb->data;
+ startelem = SH_INITIAL_BUCKET(tb, hash);
+ curelem = startelem;
+ while (true)
+ {
+ uint32 curdist;
+ uint32 curhash;
+ uint32 curoptimal;
+ SH_ELEMENT_TYPE *entry = &data[curelem];
+
+ /* any empty bucket can directly be used */
+ if (entry->status == SH_STATUS_EMPTY)
+ {
+ tb->members++;
+ entry->SH_KEY = key;
+#ifdef SH_STORE_HASH
+ SH_GET_HASH(tb, entry) = hash;
+#endif
+ entry->status = SH_STATUS_IN_USE;
+ *found = false;
+ return entry;
+ }
+
+ /*
+ * If the bucket is not empty, we either found a match (in which case
+ * we're done), or we have to decide whether to skip over or move the
+ * colliding entry. When the colliding element's distance to its
+ * optimal position is smaller than the to-be-inserted entry's, we
+ * shift the colliding entry (and its followers) forward by one.
+ */
+
+ if (SH_COMPARE_KEYS(tb, hash, key, entry))
+ {
+ Assert(entry->status == SH_STATUS_IN_USE);
+ *found = true;
+ return entry;
+ }
+
+ curhash = SH_ENTRY_HASH(tb, entry);
+ curoptimal = SH_INITIAL_BUCKET(tb, curhash);
+ curdist = SH_DISTANCE_FROM_OPTIMAL(tb, curoptimal, curelem);
+
+ if (insertdist > curdist)
+ {
+ SH_ELEMENT_TYPE *lastentry = entry;
+ uint32 emptyelem = curelem;
+ uint32 moveelem;
+ int32 emptydist = 0;
+
+ /* find next empty bucket */
+ while (true)
+ {
+ SH_ELEMENT_TYPE *emptyentry;
+
+ emptyelem = SH_NEXT(tb, emptyelem, startelem);
+ emptyentry = &data[emptyelem];
+
+ if (emptyentry->status == SH_STATUS_EMPTY)
+ {
+ lastentry = emptyentry;
+ break;
+ }
+
+ /*
+ * To avoid negative consequences from overly imbalanced
+ * hashtables, grow the hashtable if collisions would require
+ * us to move a lot of entries. The most likely cause of such
+ * imbalance is filling a (currently) small table, from a
+ * currently big one, in hash-table order. Don't grow if the
+ * hashtable would be too empty, to prevent quick space
+ * explosion for some weird edge cases.
+ */
+ if (unlikely(++emptydist > SH_GROW_MAX_MOVE) &&
+ ((double) tb->members / tb->size) >= SH_GROW_MIN_FILLFACTOR)
+ {
+ tb->grow_threshold = 0;
+ goto restart;
+ }
+ }
+
+ /* shift forward, starting at last occupied element */
+
+ /*
+ * TODO: This could be optimized to be one memcpy in many cases,
+ * excepting wrapping around at the end of ->data. Hasn't shown up
+ * in profiles so far though.
+ */
+ moveelem = emptyelem;
+ while (moveelem != curelem)
+ {
+ SH_ELEMENT_TYPE *moveentry;
+
+ moveelem = SH_PREV(tb, moveelem, startelem);
+ moveentry = &data[moveelem];
+
+ memcpy(lastentry, moveentry, sizeof(SH_ELEMENT_TYPE));
+ lastentry = moveentry;
+ }
+
+ /* and fill the now empty spot */
+ tb->members++;
+
+ entry->SH_KEY = key;
+#ifdef SH_STORE_HASH
+ SH_GET_HASH(tb, entry) = hash;
+#endif
+ entry->status = SH_STATUS_IN_USE;
+ *found = false;
+ return entry;
+ }
+
+ curelem = SH_NEXT(tb, curelem, startelem);
+ insertdist++;
+
+ /*
+ * To avoid negative consequences from overly imbalanced hashtables,
+ * grow the hashtable if collisions lead to large runs. The most
+ * likely cause of such imbalance is filling a (currently) small
+ * table, from a currently big one, in hash-table order. Don't grow
+ * if the hashtable would be too empty, to prevent quick space
+ * explosion for some weird edge cases.
+ */
+ if (unlikely(insertdist > SH_GROW_MAX_DIB) &&
+ ((double) tb->members / tb->size) >= SH_GROW_MIN_FILLFACTOR)
+ {
+ tb->grow_threshold = 0;
+ goto restart;
+ }
+ }
+}
+
+/*
+ * Insert the key key into the hash-table, set *found to true if the key
+ * already exists, false otherwise. Returns the hash-table entry in either
+ * case.
+ */
+SH_SCOPE SH_ELEMENT_TYPE *
+SH_INSERT(SH_TYPE * tb, SH_KEY_TYPE key, bool *found)
+{
+ uint32 hash = SH_HASH_KEY(tb, key);
+
+ return SH_INSERT_HASH_INTERNAL(tb, key, hash, found);
+}
+
+/*
+ * Insert the key key into the hash-table using an already-calculated
+ * hash. Set *found to true if the key already exists, false
+ * otherwise. Returns the hash-table entry in either case.
+ */
+SH_SCOPE SH_ELEMENT_TYPE *
+SH_INSERT_HASH(SH_TYPE * tb, SH_KEY_TYPE key, uint32 hash, bool *found)
+{
+ return SH_INSERT_HASH_INTERNAL(tb, key, hash, found);
+}
+
+/*
+ * This is a separate static inline function, so it can be reliably be inlined
+ * into its wrapper functions even if SH_SCOPE is extern.
+ */
+static inline SH_ELEMENT_TYPE *
+SH_LOOKUP_HASH_INTERNAL(SH_TYPE * tb, SH_KEY_TYPE key, uint32 hash)
+{
+ const uint32 startelem = SH_INITIAL_BUCKET(tb, hash);
+ uint32 curelem = startelem;
+
+ while (true)
+ {
+ SH_ELEMENT_TYPE *entry = &tb->data[curelem];
+
+ if (entry->status == SH_STATUS_EMPTY)
+ {
+ return NULL;
+ }
+
+ Assert(entry->status == SH_STATUS_IN_USE);
+
+ if (SH_COMPARE_KEYS(tb, hash, key, entry))
+ return entry;
+
+ /*
+ * TODO: we could stop search based on distance. If the current
+ * buckets's distance-from-optimal is smaller than what we've skipped
+ * already, the entry doesn't exist. Probably only do so if
+ * SH_STORE_HASH is defined, to avoid re-computing hashes?
+ */
+
+ curelem = SH_NEXT(tb, curelem, startelem);
+ }
+}
+
+/*
+ * Lookup up entry in hash table. Returns NULL if key not present.
+ */
+SH_SCOPE SH_ELEMENT_TYPE *
+SH_LOOKUP(SH_TYPE * tb, SH_KEY_TYPE key)
+{
+ uint32 hash = SH_HASH_KEY(tb, key);
+
+ return SH_LOOKUP_HASH_INTERNAL(tb, key, hash);
+}
+
+/*
+ * Lookup up entry in hash table using an already-calculated hash.
+ *
+ * Returns NULL if key not present.
+ */
+SH_SCOPE SH_ELEMENT_TYPE *
+SH_LOOKUP_HASH(SH_TYPE * tb, SH_KEY_TYPE key, uint32 hash)
+{
+ return SH_LOOKUP_HASH_INTERNAL(tb, key, hash);
+}
+
+/*
+ * Delete entry from hash table. Returns whether to-be-deleted key was
+ * present.
+ */
+SH_SCOPE bool
+SH_DELETE(SH_TYPE * tb, SH_KEY_TYPE key)
+{
+ uint32 hash = SH_HASH_KEY(tb, key);
+ uint32 startelem = SH_INITIAL_BUCKET(tb, hash);
+ uint32 curelem = startelem;
+
+ while (true)
+ {
+ SH_ELEMENT_TYPE *entry = &tb->data[curelem];
+
+ if (entry->status == SH_STATUS_EMPTY)
+ return false;
+
+ if (entry->status == SH_STATUS_IN_USE &&
+ SH_COMPARE_KEYS(tb, hash, key, entry))
+ {
+ SH_ELEMENT_TYPE *lastentry = entry;
+
+ tb->members--;
+
+ /*
+ * Backward shift following elements till either an empty element
+ * or an element at its optimal position is encountered.
+ *
+ * While that sounds expensive, the average chain length is short,
+ * and deletions would otherwise require tombstones.
+ */
+ while (true)
+ {
+ SH_ELEMENT_TYPE *curentry;
+ uint32 curhash;
+ uint32 curoptimal;
+
+ curelem = SH_NEXT(tb, curelem, startelem);
+ curentry = &tb->data[curelem];
+
+ if (curentry->status != SH_STATUS_IN_USE)
+ {
+ lastentry->status = SH_STATUS_EMPTY;
+ break;
+ }
+
+ curhash = SH_ENTRY_HASH(tb, curentry);
+ curoptimal = SH_INITIAL_BUCKET(tb, curhash);
+
+ /* current is at optimal position, done */
+ if (curoptimal == curelem)
+ {
+ lastentry->status = SH_STATUS_EMPTY;
+ break;
+ }
+
+ /* shift */
+ memcpy(lastentry, curentry, sizeof(SH_ELEMENT_TYPE));
+
+ lastentry = curentry;
+ }
+
+ return true;
+ }
+
+ /* TODO: return false; if distance too big */
+
+ curelem = SH_NEXT(tb, curelem, startelem);
+ }
+}
+
+/*
+ * Initialize iterator.
+ */
+SH_SCOPE void
+SH_START_ITERATE(SH_TYPE * tb, SH_ITERATOR * iter)
+{
+ int i;
+ uint64 startelem = PG_UINT64_MAX;
+
+ /*
+ * Search for the first empty element. As deletions during iterations are
+ * supported, we want to start/end at an element that cannot be affected
+ * by elements being shifted.
+ */
+ for (i = 0; i < tb->size; i++)
+ {
+ SH_ELEMENT_TYPE *entry = &tb->data[i];
+
+ if (entry->status != SH_STATUS_IN_USE)
+ {
+ startelem = i;
+ break;
+ }
+ }
+
+ Assert(startelem < SH_MAX_SIZE);
+
+ /*
+ * Iterate backwards, that allows the current element to be deleted, even
+ * if there are backward shifts
+ */
+ iter->cur = startelem;
+ iter->end = iter->cur;
+ iter->done = false;
+}
+
+/*
+ * Initialize iterator to a specific bucket. That's really only useful for
+ * cases where callers are partially iterating over the hashspace, and that
+ * iteration deletes and inserts elements based on visited entries. Doing that
+ * repeatedly could lead to an unbalanced keyspace when always starting at the
+ * same position.
+ */
+SH_SCOPE void
+SH_START_ITERATE_AT(SH_TYPE * tb, SH_ITERATOR * iter, uint32 at)
+{
+ /*
+ * Iterate backwards, that allows the current element to be deleted, even
+ * if there are backward shifts.
+ */
+ iter->cur = at & tb->sizemask; /* ensure at is within a valid range */
+ iter->end = iter->cur;
+ iter->done = false;
+}
+
+/*
+ * Iterate over all entries in the hash-table. Return the next occupied entry,
+ * or NULL if done.
+ *
+ * During iteration the current entry in the hash table may be deleted,
+ * without leading to elements being skipped or returned twice. Additionally
+ * the rest of the table may be modified (i.e. there can be insertions or
+ * deletions), but if so, there's neither a guarantee that all nodes are
+ * visited at least once, nor a guarantee that a node is visited at most once.
+ */
+SH_SCOPE SH_ELEMENT_TYPE *
+SH_ITERATE(SH_TYPE * tb, SH_ITERATOR * iter)
+{
+ while (!iter->done)
+ {
+ SH_ELEMENT_TYPE *elem;
+
+ elem = &tb->data[iter->cur];
+
+ /* next element in backward direction */
+ iter->cur = (iter->cur - 1) & tb->sizemask;
+
+ if ((iter->cur & tb->sizemask) == (iter->end & tb->sizemask))
+ iter->done = true;
+ if (elem->status == SH_STATUS_IN_USE)
+ {
+ return elem;
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Report some statistics about the state of the hashtable. For
+ * debugging/profiling purposes only.
+ */
+SH_SCOPE void
+SH_STAT(SH_TYPE * tb)
+{
+ uint32 max_chain_length = 0;
+ uint32 total_chain_length = 0;
+ double avg_chain_length;
+ double fillfactor;
+ uint32 i;
+
+ uint32 *collisions = palloc0(tb->size * sizeof(uint32));
+ uint32 total_collisions = 0;
+ uint32 max_collisions = 0;
+ double avg_collisions;
+
+ for (i = 0; i < tb->size; i++)
+ {
+ uint32 hash;
+ uint32 optimal;
+ uint32 dist;
+ SH_ELEMENT_TYPE *elem;
+
+ elem = &tb->data[i];
+
+ if (elem->status != SH_STATUS_IN_USE)
+ continue;
+
+ hash = SH_ENTRY_HASH(tb, elem);
+ optimal = SH_INITIAL_BUCKET(tb, hash);
+ dist = SH_DISTANCE_FROM_OPTIMAL(tb, optimal, i);
+
+ if (dist > max_chain_length)
+ max_chain_length = dist;
+ total_chain_length += dist;
+
+ collisions[optimal]++;
+ }
+
+ for (i = 0; i < tb->size; i++)
+ {
+ uint32 curcoll = collisions[i];
+
+ if (curcoll == 0)
+ continue;
+
+ /* single contained element is not a collision */
+ curcoll--;
+ total_collisions += curcoll;
+ if (curcoll > max_collisions)
+ max_collisions = curcoll;
+ }
+
+ if (tb->members > 0)
+ {
+ fillfactor = tb->members / ((double) tb->size);
+ avg_chain_length = ((double) total_chain_length) / tb->members;
+ avg_collisions = ((double) total_collisions) / tb->members;
+ }
+ else
+ {
+ fillfactor = 0;
+ avg_chain_length = 0;
+ avg_collisions = 0;
+ }
+
+ sh_log("size: " UINT64_FORMAT ", members: %u, filled: %f, total chain: %u, max chain: %u, avg chain: %f, total_collisions: %u, max_collisions: %i, avg_collisions: %f",
+ tb->size, tb->members, fillfactor, total_chain_length, max_chain_length, avg_chain_length,
+ total_collisions, max_collisions, avg_collisions);
+}
+
+#endif /* SH_DEFINE */
+
+
+/* undefine external parameters, so next hash table can be defined */
+#undef SH_PREFIX
+#undef SH_KEY_TYPE
+#undef SH_KEY
+#undef SH_ELEMENT_TYPE
+#undef SH_HASH_KEY
+#undef SH_SCOPE
+#undef SH_DECLARE
+#undef SH_DEFINE
+#undef SH_GET_HASH
+#undef SH_STORE_HASH
+#undef SH_USE_NONDEFAULT_ALLOCATOR
+#undef SH_EQUAL
+
+/* undefine locally declared macros */
+#undef SH_MAKE_PREFIX
+#undef SH_MAKE_NAME
+#undef SH_MAKE_NAME_
+#undef SH_FILLFACTOR
+#undef SH_MAX_FILLFACTOR
+#undef SH_GROW_MAX_DIB
+#undef SH_GROW_MAX_MOVE
+#undef SH_GROW_MIN_FILLFACTOR
+#undef SH_MAX_SIZE
+
+/* types */
+#undef SH_TYPE
+#undef SH_STATUS
+#undef SH_STATUS_EMPTY
+#undef SH_STATUS_IN_USE
+#undef SH_ITERATOR
+
+/* external function names */
+#undef SH_CREATE
+#undef SH_DESTROY
+#undef SH_RESET
+#undef SH_INSERT
+#undef SH_INSERT_HASH
+#undef SH_DELETE
+#undef SH_LOOKUP
+#undef SH_LOOKUP_HASH
+#undef SH_GROW
+#undef SH_START_ITERATE
+#undef SH_START_ITERATE_AT
+#undef SH_ITERATE
+#undef SH_ALLOCATE
+#undef SH_FREE
+#undef SH_STAT
+
+/* internal function names */
+#undef SH_COMPUTE_PARAMETERS
+#undef SH_COMPARE_KEYS
+#undef SH_INITIAL_BUCKET
+#undef SH_NEXT
+#undef SH_PREV
+#undef SH_DISTANCE_FROM_OPTIMAL
+#undef SH_ENTRY_HASH
+#undef SH_INSERT_HASH_INTERNAL
+#undef SH_LOOKUP_HASH_INTERNAL
diff --git a/src/include/lib/stringinfo.h b/src/include/lib/stringinfo.h
new file mode 100644
index 0000000..5a2a3db
--- /dev/null
+++ b/src/include/lib/stringinfo.h
@@ -0,0 +1,161 @@
+/*-------------------------------------------------------------------------
+ *
+ * stringinfo.h
+ * Declarations/definitions for "StringInfo" functions.
+ *
+ * StringInfo provides an extensible string data type (currently limited to a
+ * length of 1GB). It can be used to buffer either ordinary C strings
+ * (null-terminated text) or arbitrary binary data. All storage is allocated
+ * with palloc() (falling back to malloc in frontend code).
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/lib/stringinfo.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef STRINGINFO_H
+#define STRINGINFO_H
+
+/*-------------------------
+ * StringInfoData holds information about an extensible string.
+ * data is the current buffer for the string (allocated with palloc).
+ * len is the current string length. There is guaranteed to be
+ * a terminating '\0' at data[len], although this is not very
+ * useful when the string holds binary data rather than text.
+ * maxlen is the allocated size in bytes of 'data', i.e. the maximum
+ * string size (including the terminating '\0' char) that we can
+ * currently store in 'data' without having to reallocate
+ * more space. We must always have maxlen > len.
+ * cursor is initialized to zero by makeStringInfo or initStringInfo,
+ * but is not otherwise touched by the stringinfo.c routines.
+ * Some routines use it to scan through a StringInfo.
+ *-------------------------
+ */
+typedef struct StringInfoData
+{
+ char *data;
+ int len;
+ int maxlen;
+ int cursor;
+} StringInfoData;
+
+typedef StringInfoData *StringInfo;
+
+
+/*------------------------
+ * There are two ways to create a StringInfo object initially:
+ *
+ * StringInfo stringptr = makeStringInfo();
+ * Both the StringInfoData and the data buffer are palloc'd.
+ *
+ * StringInfoData string;
+ * initStringInfo(&string);
+ * The data buffer is palloc'd but the StringInfoData is just local.
+ * This is the easiest approach for a StringInfo object that will
+ * only live as long as the current routine.
+ *
+ * To destroy a StringInfo, pfree() the data buffer, and then pfree() the
+ * StringInfoData if it was palloc'd. There's no special support for this.
+ *
+ * NOTE: some routines build up a string using StringInfo, and then
+ * release the StringInfoData but return the data string itself to their
+ * caller. At that point the data string looks like a plain palloc'd
+ * string.
+ *-------------------------
+ */
+
+/*------------------------
+ * makeStringInfo
+ * Create an empty 'StringInfoData' & return a pointer to it.
+ */
+extern StringInfo makeStringInfo(void);
+
+/*------------------------
+ * initStringInfo
+ * Initialize a StringInfoData struct (with previously undefined contents)
+ * to describe an empty string.
+ */
+extern void initStringInfo(StringInfo str);
+
+/*------------------------
+ * resetStringInfo
+ * Clears the current content of the StringInfo, if any. The
+ * StringInfo remains valid.
+ */
+extern void resetStringInfo(StringInfo str);
+
+/*------------------------
+ * appendStringInfo
+ * Format text data under the control of fmt (an sprintf-style format string)
+ * and append it to whatever is already in str. More space is allocated
+ * to str if necessary. This is sort of like a combination of sprintf and
+ * strcat.
+ */
+extern void appendStringInfo(StringInfo str, const char *fmt,...) pg_attribute_printf(2, 3);
+
+/*------------------------
+ * appendStringInfoVA
+ * Attempt to format text data under the control of fmt (an sprintf-style
+ * format string) and append it to whatever is already in str. If successful
+ * return zero; if not (because there's not enough space), return an estimate
+ * of the space needed, without modifying str. Typically the caller should
+ * pass the return value to enlargeStringInfo() before trying again; see
+ * appendStringInfo for standard usage pattern.
+ */
+extern int appendStringInfoVA(StringInfo str, const char *fmt, va_list args) pg_attribute_printf(2, 0);
+
+/*------------------------
+ * appendStringInfoString
+ * Append a null-terminated string to str.
+ * Like appendStringInfo(str, "%s", s) but faster.
+ */
+extern void appendStringInfoString(StringInfo str, const char *s);
+
+/*------------------------
+ * appendStringInfoChar
+ * Append a single byte to str.
+ * Like appendStringInfo(str, "%c", ch) but much faster.
+ */
+extern void appendStringInfoChar(StringInfo str, char ch);
+
+/*------------------------
+ * appendStringInfoCharMacro
+ * As above, but a macro for even more speed where it matters.
+ * Caution: str argument will be evaluated multiple times.
+ */
+#define appendStringInfoCharMacro(str,ch) \
+ (((str)->len + 1 >= (str)->maxlen) ? \
+ appendStringInfoChar(str, ch) : \
+ (void)((str)->data[(str)->len] = (ch), (str)->data[++(str)->len] = '\0'))
+
+/*------------------------
+ * appendStringInfoSpaces
+ * Append a given number of spaces to str.
+ */
+extern void appendStringInfoSpaces(StringInfo str, int count);
+
+/*------------------------
+ * appendBinaryStringInfo
+ * Append arbitrary binary data to a StringInfo, allocating more space
+ * if necessary.
+ */
+extern void appendBinaryStringInfo(StringInfo str,
+ const char *data, int datalen);
+
+/*------------------------
+ * appendBinaryStringInfoNT
+ * Append arbitrary binary data to a StringInfo, allocating more space
+ * if necessary. Does not ensure a trailing null-byte exists.
+ */
+extern void appendBinaryStringInfoNT(StringInfo str,
+ const char *data, int datalen);
+
+/*------------------------
+ * enlargeStringInfo
+ * Make sure a StringInfo's buffer can hold at least 'needed' more bytes.
+ */
+extern void enlargeStringInfo(StringInfo str, int needed);
+
+#endif /* STRINGINFO_H */
diff --git a/src/include/libpq/auth.h b/src/include/libpq/auth.h
new file mode 100644
index 0000000..81202e6
--- /dev/null
+++ b/src/include/libpq/auth.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ *
+ * auth.h
+ * Definitions for network authentication routines
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/libpq/auth.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef AUTH_H
+#define AUTH_H
+
+#include "libpq/libpq-be.h"
+
+extern char *pg_krb_server_keyfile;
+extern bool pg_krb_caseins_users;
+extern char *pg_krb_realm;
+
+extern void ClientAuthentication(Port *port);
+
+/* Hook for plugins to get control in ClientAuthentication() */
+typedef void (*ClientAuthentication_hook_type) (Port *, int);
+extern PGDLLIMPORT ClientAuthentication_hook_type ClientAuthentication_hook;
+
+#endif /* AUTH_H */
diff --git a/src/include/libpq/be-fsstubs.h b/src/include/libpq/be-fsstubs.h
new file mode 100644
index 0000000..4fbd7cc
--- /dev/null
+++ b/src/include/libpq/be-fsstubs.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * be-fsstubs.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/libpq/be-fsstubs.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BE_FSSTUBS_H
+#define BE_FSSTUBS_H
+
+/*
+ * These are not fmgr-callable, but are available to C code.
+ * Probably these should have had the underscore-free names,
+ * but too late now...
+ */
+extern int lo_read(int fd, char *buf, int len);
+extern int lo_write(int fd, const char *buf, int len);
+
+/*
+ * Cleanup LOs at xact commit/abort
+ */
+extern void AtEOXact_LargeObject(bool isCommit);
+extern void AtEOSubXact_LargeObject(bool isCommit, SubTransactionId mySubid,
+ SubTransactionId parentSubid);
+
+#endif /* BE_FSSTUBS_H */
diff --git a/src/include/libpq/be-gssapi-common.h b/src/include/libpq/be-gssapi-common.h
new file mode 100644
index 0000000..e1c23ac
--- /dev/null
+++ b/src/include/libpq/be-gssapi-common.h
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ *
+ * be-gssapi-common.h
+ * Definitions for GSSAPI authentication and encryption handling
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/libpq/be-gssapi-common.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef BE_GSSAPI_COMMON_H
+#define BE_GSSAPI_COMMON_H
+
+#if defined(HAVE_GSSAPI_H)
+#include <gssapi.h>
+#else
+#include <gssapi/gssapi.h>
+#endif
+
+extern void pg_GSS_error(const char *errmsg,
+ OM_uint32 maj_stat, OM_uint32 min_stat);
+
+#endif /* BE_GSSAPI_COMMON_H */
diff --git a/src/include/libpq/crypt.h b/src/include/libpq/crypt.h
new file mode 100644
index 0000000..0c99e6c
--- /dev/null
+++ b/src/include/libpq/crypt.h
@@ -0,0 +1,46 @@
+/*-------------------------------------------------------------------------
+ *
+ * crypt.h
+ * Interface to libpq/crypt.c
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/libpq/crypt.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_CRYPT_H
+#define PG_CRYPT_H
+
+#include "datatype/timestamp.h"
+
+/*
+ * Types of password hashes or secrets.
+ *
+ * Plaintext passwords can be passed in by the user, in a CREATE/ALTER USER
+ * command. They will be encrypted to MD5 or SCRAM-SHA-256 format, before
+ * storing on-disk, so only MD5 and SCRAM-SHA-256 passwords should appear
+ * in pg_authid.rolpassword. They are also the allowed values for the
+ * password_encryption GUC.
+ */
+typedef enum PasswordType
+{
+ PASSWORD_TYPE_PLAINTEXT = 0,
+ PASSWORD_TYPE_MD5,
+ PASSWORD_TYPE_SCRAM_SHA_256
+} PasswordType;
+
+extern PasswordType get_password_type(const char *shadow_pass);
+extern char *encrypt_password(PasswordType target_type, const char *role,
+ const char *password);
+
+extern char *get_role_password(const char *role, char **logdetail);
+
+extern int md5_crypt_verify(const char *role, const char *shadow_pass,
+ const char *client_pass, const char *md5_salt,
+ int md5_salt_len, char **logdetail);
+extern int plain_crypt_verify(const char *role, const char *shadow_pass,
+ const char *client_pass, char **logdetail);
+
+#endif
diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h
new file mode 100644
index 0000000..c194d74
--- /dev/null
+++ b/src/include/libpq/hba.h
@@ -0,0 +1,140 @@
+/*-------------------------------------------------------------------------
+ *
+ * hba.h
+ * Interface to hba.c
+ *
+ *
+ * src/include/libpq/hba.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef HBA_H
+#define HBA_H
+
+#include "libpq/pqcomm.h" /* pgrminclude ignore */ /* needed for NetBSD */
+#include "nodes/pg_list.h"
+#include "regex/regex.h"
+
+
+/*
+ * The following enum represents the authentication methods that
+ * are supported by PostgreSQL.
+ *
+ * Note: keep this in sync with the UserAuthName array in hba.c.
+ */
+typedef enum UserAuth
+{
+ uaReject,
+ uaImplicitReject, /* Not a user-visible option */
+ uaTrust,
+ uaIdent,
+ uaPassword,
+ uaMD5,
+ uaSCRAM,
+ uaGSS,
+ uaSSPI,
+ uaPAM,
+ uaBSD,
+ uaLDAP,
+ uaCert,
+ uaRADIUS,
+ uaPeer
+#define USER_AUTH_LAST uaPeer /* Must be last value of this enum */
+} UserAuth;
+
+/*
+ * Data structures representing pg_hba.conf entries
+ */
+
+typedef enum IPCompareMethod
+{
+ ipCmpMask,
+ ipCmpSameHost,
+ ipCmpSameNet,
+ ipCmpAll
+} IPCompareMethod;
+
+typedef enum ConnType
+{
+ ctLocal,
+ ctHost,
+ ctHostSSL,
+ ctHostNoSSL,
+ ctHostGSS,
+ ctHostNoGSS,
+} ConnType;
+
+typedef enum ClientCertMode
+{
+ clientCertOff,
+ clientCertCA,
+ clientCertFull
+} ClientCertMode;
+
+typedef struct HbaLine
+{
+ int linenumber;
+ char *rawline;
+ ConnType conntype;
+ List *databases;
+ List *roles;
+ struct sockaddr_storage addr;
+ struct sockaddr_storage mask;
+ IPCompareMethod ip_cmp_method;
+ char *hostname;
+ UserAuth auth_method;
+
+ char *usermap;
+ char *pamservice;
+ bool pam_use_hostname;
+ bool ldaptls;
+ char *ldapscheme;
+ char *ldapserver;
+ int ldapport;
+ char *ldapbinddn;
+ char *ldapbindpasswd;
+ char *ldapsearchattribute;
+ char *ldapsearchfilter;
+ char *ldapbasedn;
+ int ldapscope;
+ char *ldapprefix;
+ char *ldapsuffix;
+ ClientCertMode clientcert;
+ char *krb_realm;
+ bool include_realm;
+ bool compat_realm;
+ bool upn_username;
+ List *radiusservers;
+ char *radiusservers_s;
+ List *radiussecrets;
+ char *radiussecrets_s;
+ List *radiusidentifiers;
+ char *radiusidentifiers_s;
+ List *radiusports;
+ char *radiusports_s;
+ int addrlen; /* zero if we don't have a valid addr */
+ int masklen; /* zero if we don't have a valid mask */
+} HbaLine;
+
+typedef struct IdentLine
+{
+ int linenumber;
+
+ char *usermap;
+ char *ident_user;
+ char *pg_role;
+ regex_t re;
+} IdentLine;
+
+/* kluge to avoid including libpq/libpq-be.h here */
+typedef struct Port hbaPort;
+
+extern bool load_hba(void);
+extern bool load_ident(void);
+extern void hba_getauthmethod(hbaPort *port);
+extern int check_usermap(const char *usermap_name,
+ const char *pg_role, const char *auth_user,
+ bool case_sensitive);
+extern bool pg_isblank(const char c);
+
+#endif /* HBA_H */
diff --git a/src/include/libpq/ifaddr.h b/src/include/libpq/ifaddr.h
new file mode 100644
index 0000000..4b61518
--- /dev/null
+++ b/src/include/libpq/ifaddr.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * ifaddr.h
+ * IP netmask calculations, and enumerating network interfaces.
+ *
+ * Copyright (c) 2003-2020, PostgreSQL Global Development Group
+ *
+ * src/include/libpq/ifaddr.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef IFADDR_H
+#define IFADDR_H
+
+#include "libpq/pqcomm.h" /* pgrminclude ignore */
+
+typedef void (*PgIfAddrCallback) (struct sockaddr *addr,
+ struct sockaddr *netmask,
+ void *cb_data);
+
+extern int pg_range_sockaddr(const struct sockaddr_storage *addr,
+ const struct sockaddr_storage *netaddr,
+ const struct sockaddr_storage *netmask);
+
+extern int pg_sockaddr_cidr_mask(struct sockaddr_storage *mask,
+ char *numbits, int family);
+
+extern int pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data);
+
+#endif /* IFADDR_H */
diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h
new file mode 100644
index 0000000..fa778e1
--- /dev/null
+++ b/src/include/libpq/libpq-be.h
@@ -0,0 +1,326 @@
+/*-------------------------------------------------------------------------
+ *
+ * libpq-be.h
+ * This file contains definitions for structures and externs used
+ * by the postmaster during client authentication.
+ *
+ * Note that this is backend-internal and is NOT exported to clients.
+ * Structs that need to be client-visible are in pqcomm.h.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/libpq/libpq-be.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LIBPQ_BE_H
+#define LIBPQ_BE_H
+
+#include <sys/time.h>
+#ifdef USE_OPENSSL
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#endif
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+
+#ifdef ENABLE_GSS
+#if defined(HAVE_GSSAPI_H)
+#include <gssapi.h>
+#else
+#include <gssapi/gssapi.h>
+#endif /* HAVE_GSSAPI_H */
+/*
+ * GSSAPI brings in headers that set a lot of things in the global namespace on win32,
+ * that doesn't match the msvc build. It gives a bunch of compiler warnings that we ignore,
+ * but also defines a symbol that simply does not exist. Undefine it again.
+ */
+#ifdef _MSC_VER
+#undef HAVE_GETADDRINFO
+#endif
+#endif /* ENABLE_GSS */
+
+#ifdef ENABLE_SSPI
+#define SECURITY_WIN32
+#if defined(WIN32) && !defined(_MSC_VER)
+#include <ntsecapi.h>
+#endif
+#include <security.h>
+#undef SECURITY_WIN32
+
+#ifndef ENABLE_GSS
+/*
+ * Define a fake structure compatible with GSSAPI on Unix.
+ */
+typedef struct
+{
+ void *value;
+ int length;
+} gss_buffer_desc;
+#endif
+#endif /* ENABLE_SSPI */
+
+#include "datatype/timestamp.h"
+#include "libpq/hba.h"
+#include "libpq/pqcomm.h"
+
+
+typedef enum CAC_state
+{
+ CAC_OK, CAC_STARTUP, CAC_SHUTDOWN, CAC_RECOVERY, CAC_TOOMANY,
+ CAC_SUPERUSER
+} CAC_state;
+
+
+/*
+ * GSSAPI specific state information
+ */
+#if defined(ENABLE_GSS) | defined(ENABLE_SSPI)
+typedef struct
+{
+ gss_buffer_desc outbuf; /* GSSAPI output token buffer */
+#ifdef ENABLE_GSS
+ gss_cred_id_t cred; /* GSSAPI connection cred's */
+ gss_ctx_id_t ctx; /* GSSAPI connection context */
+ gss_name_t name; /* GSSAPI client name */
+ char *princ; /* GSSAPI Principal used for auth, NULL if
+ * GSSAPI auth was not used */
+ bool auth; /* GSSAPI Authentication used */
+ bool enc; /* GSSAPI encryption in use */
+#endif
+} pg_gssinfo;
+#endif
+
+/*
+ * This is used by the postmaster in its communication with frontends. It
+ * contains all state information needed during this communication before the
+ * backend is run. The Port structure is kept in malloc'd memory and is
+ * still available when a backend is running (see MyProcPort). The data
+ * it points to must also be malloc'd, or else palloc'd in TopMemoryContext,
+ * so that it survives into PostgresMain execution!
+ *
+ * remote_hostname is set if we did a successful reverse lookup of the
+ * client's IP address during connection setup.
+ * remote_hostname_resolv tracks the state of hostname verification:
+ * +1 = remote_hostname is known to resolve to client's IP address
+ * -1 = remote_hostname is known NOT to resolve to client's IP address
+ * 0 = we have not done the forward DNS lookup yet
+ * -2 = there was an error in name resolution
+ * If reverse lookup of the client IP address fails, remote_hostname will be
+ * left NULL while remote_hostname_resolv is set to -2. If reverse lookup
+ * succeeds but forward lookup fails, remote_hostname_resolv is also set to -2
+ * (the case is distinguishable because remote_hostname isn't NULL). In
+ * either of the -2 cases, remote_hostname_errcode saves the lookup return
+ * code for possible later use with gai_strerror.
+ */
+
+typedef struct Port
+{
+ pgsocket sock; /* File descriptor */
+ bool noblock; /* is the socket in non-blocking mode? */
+ ProtocolVersion proto; /* FE/BE protocol version */
+ SockAddr laddr; /* local addr (postmaster) */
+ SockAddr raddr; /* remote addr (client) */
+ char *remote_host; /* name (or ip addr) of remote host */
+ char *remote_hostname; /* name (not ip addr) of remote host, if
+ * available */
+ int remote_hostname_resolv; /* see above */
+ int remote_hostname_errcode; /* see above */
+ char *remote_port; /* text rep of remote port */
+ CAC_state canAcceptConnections; /* postmaster connection status */
+
+ /*
+ * Information that needs to be saved from the startup packet and passed
+ * into backend execution. "char *" fields are NULL if not set.
+ * guc_options points to a List of alternating option names and values.
+ */
+ char *database_name;
+ char *user_name;
+ char *cmdline_options;
+ List *guc_options;
+
+ /*
+ * The startup packet application name, only used here for the "connection
+ * authorized" log message. We shouldn't use this post-startup, instead
+ * the GUC should be used as application can change it afterward.
+ */
+ char *application_name;
+
+ /*
+ * Information that needs to be held during the authentication cycle.
+ */
+ HbaLine *hba;
+
+ /*
+ * TCP keepalive and user timeout settings.
+ *
+ * default values are 0 if AF_UNIX or not yet known; current values are 0
+ * if AF_UNIX or using the default. Also, -1 in a default value means we
+ * were unable to find out the default (getsockopt failed).
+ */
+ int default_keepalives_idle;
+ int default_keepalives_interval;
+ int default_keepalives_count;
+ int default_tcp_user_timeout;
+ int keepalives_idle;
+ int keepalives_interval;
+ int keepalives_count;
+ int tcp_user_timeout;
+
+ /*
+ * GSSAPI structures.
+ */
+#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
+
+ /*
+ * If GSSAPI is supported and used on this connection, store GSSAPI
+ * information. Even when GSSAPI is not compiled in, store a NULL pointer
+ * to keep struct offsets the same (for extension ABI compatibility).
+ */
+ pg_gssinfo *gss;
+#else
+ void *gss;
+#endif
+
+ /*
+ * SSL structures.
+ */
+ bool ssl_in_use;
+ char *peer_cn;
+ bool peer_cert_valid;
+
+ /*
+ * OpenSSL structures. (Keep these last so that the locations of other
+ * fields are the same whether or not you build with OpenSSL.)
+ */
+#ifdef USE_OPENSSL
+ SSL *ssl;
+ X509 *peer;
+#endif
+} Port;
+
+#ifdef USE_SSL
+/*
+ * Hardcoded DH parameters, used in ephemeral DH keying. (See also
+ * README.SSL for more details on EDH.)
+ *
+ * This is the 2048-bit DH parameter from RFC 3526. The generation of the
+ * prime is specified in RFC 2412 Appendix E, which also discusses the
+ * design choice of the generator. Note that when loaded with OpenSSL
+ * this causes DH_check() to fail on DH_NOT_SUITABLE_GENERATOR, where
+ * leaking a bit is preferred.
+ */
+#define FILE_DH2048 \
+"-----BEGIN DH PARAMETERS-----\n\
+MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n\
+IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n\
+awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n\
+mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n\
+fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n\
+5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg==\n\
+-----END DH PARAMETERS-----\n"
+
+/*
+ * These functions are implemented by the glue code specific to each
+ * SSL implementation (e.g. be-secure-openssl.c)
+ */
+
+/*
+ * Initialize global SSL context.
+ *
+ * If isServerStart is true, report any errors as FATAL (so we don't return).
+ * Otherwise, log errors at LOG level and return -1 to indicate trouble,
+ * preserving the old SSL state if any. Returns 0 if OK.
+ */
+extern int be_tls_init(bool isServerStart);
+
+/*
+ * Destroy global SSL context, if any.
+ */
+extern void be_tls_destroy(void);
+
+/*
+ * Attempt to negotiate SSL connection.
+ */
+extern int be_tls_open_server(Port *port);
+
+/*
+ * Close SSL connection.
+ */
+extern void be_tls_close(Port *port);
+
+/*
+ * Read data from a secure connection.
+ */
+extern ssize_t be_tls_read(Port *port, void *ptr, size_t len, int *waitfor);
+
+/*
+ * Write data to a secure connection.
+ */
+extern ssize_t be_tls_write(Port *port, void *ptr, size_t len, int *waitfor);
+
+/*
+ * Return information about the SSL connection.
+ */
+extern int be_tls_get_cipher_bits(Port *port);
+extern bool be_tls_get_compression(Port *port);
+extern const char *be_tls_get_version(Port *port);
+extern const char *be_tls_get_cipher(Port *port);
+extern void be_tls_get_peer_subject_name(Port *port, char *ptr, size_t len);
+extern void be_tls_get_peer_issuer_name(Port *port, char *ptr, size_t len);
+extern void be_tls_get_peer_serial(Port *port, char *ptr, size_t len);
+
+/*
+ * Get the server certificate hash for SCRAM channel binding type
+ * tls-server-end-point.
+ *
+ * The result is a palloc'd hash of the server certificate with its
+ * size, and NULL if there is no certificate available.
+ *
+ * This is not supported with old versions of OpenSSL that don't have
+ * the X509_get_signature_nid() function.
+ */
+#if defined(USE_OPENSSL) && defined(HAVE_X509_GET_SIGNATURE_NID)
+#define HAVE_BE_TLS_GET_CERTIFICATE_HASH
+extern char *be_tls_get_certificate_hash(Port *port, size_t *len);
+#endif
+
+/* init hook for SSL, the default sets the password callback if appropriate */
+#ifdef USE_OPENSSL
+typedef void (*openssl_tls_init_hook_typ) (SSL_CTX *context, bool isServerStart);
+extern PGDLLIMPORT openssl_tls_init_hook_typ openssl_tls_init_hook;
+#endif
+
+#endif /* USE_SSL */
+
+#ifdef ENABLE_GSS
+/*
+ * Return information about the GSSAPI authenticated connection
+ */
+extern bool be_gssapi_get_auth(Port *port);
+extern bool be_gssapi_get_enc(Port *port);
+extern const char *be_gssapi_get_princ(Port *port);
+
+/* Read and write to a GSSAPI-encrypted connection. */
+extern ssize_t be_gssapi_read(Port *port, void *ptr, size_t len);
+extern ssize_t be_gssapi_write(Port *port, void *ptr, size_t len);
+#endif /* ENABLE_GSS */
+
+extern ProtocolVersion FrontendProtocol;
+
+/* TCP keepalives configuration. These are no-ops on an AF_UNIX socket. */
+
+extern int pq_getkeepalivesidle(Port *port);
+extern int pq_getkeepalivesinterval(Port *port);
+extern int pq_getkeepalivescount(Port *port);
+extern int pq_gettcpusertimeout(Port *port);
+
+extern int pq_setkeepalivesidle(int idle, Port *port);
+extern int pq_setkeepalivesinterval(int interval, Port *port);
+extern int pq_setkeepalivescount(int count, Port *port);
+extern int pq_settcpusertimeout(int timeout, Port *port);
+
+#endif /* LIBPQ_BE_H */
diff --git a/src/include/libpq/libpq-fs.h b/src/include/libpq/libpq-fs.h
new file mode 100644
index 0000000..a3c2cd9
--- /dev/null
+++ b/src/include/libpq/libpq-fs.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * libpq-fs.h
+ * definitions for using Inversion file system routines (ie, large objects)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/libpq/libpq-fs.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LIBPQ_FS_H
+#define LIBPQ_FS_H
+
+/*
+ * Read/write mode flags for inversion (large object) calls
+ */
+
+#define INV_WRITE 0x00020000
+#define INV_READ 0x00040000
+
+#endif /* LIBPQ_FS_H */
diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h
new file mode 100644
index 0000000..b115247
--- /dev/null
+++ b/src/include/libpq/libpq.h
@@ -0,0 +1,133 @@
+/*-------------------------------------------------------------------------
+ *
+ * libpq.h
+ * POSTGRES LIBPQ buffer structure definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/libpq/libpq.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LIBPQ_H
+#define LIBPQ_H
+
+#include <netinet/in.h>
+
+#include "lib/stringinfo.h"
+#include "libpq/libpq-be.h"
+#include "storage/latch.h"
+
+
+typedef struct
+{
+ void (*comm_reset) (void);
+ int (*flush) (void);
+ int (*flush_if_writable) (void);
+ bool (*is_send_pending) (void);
+ int (*putmessage) (char msgtype, const char *s, size_t len);
+ void (*putmessage_noblock) (char msgtype, const char *s, size_t len);
+ void (*startcopyout) (void);
+ void (*endcopyout) (bool errorAbort);
+} PQcommMethods;
+
+extern const PGDLLIMPORT PQcommMethods *PqCommMethods;
+
+#define pq_comm_reset() (PqCommMethods->comm_reset())
+#define pq_flush() (PqCommMethods->flush())
+#define pq_flush_if_writable() (PqCommMethods->flush_if_writable())
+#define pq_is_send_pending() (PqCommMethods->is_send_pending())
+#define pq_putmessage(msgtype, s, len) \
+ (PqCommMethods->putmessage(msgtype, s, len))
+#define pq_putmessage_noblock(msgtype, s, len) \
+ (PqCommMethods->putmessage_noblock(msgtype, s, len))
+#define pq_startcopyout() (PqCommMethods->startcopyout())
+#define pq_endcopyout(errorAbort) (PqCommMethods->endcopyout(errorAbort))
+
+/*
+ * External functions.
+ */
+
+/*
+ * prototypes for functions in pqcomm.c
+ */
+extern WaitEventSet *FeBeWaitSet;
+
+extern int StreamServerPort(int family, const char *hostName,
+ unsigned short portNumber, const char *unixSocketDir,
+ pgsocket ListenSocket[], int MaxListen);
+extern int StreamConnection(pgsocket server_fd, Port *port);
+extern void StreamClose(pgsocket sock);
+extern void TouchSocketFiles(void);
+extern void RemoveSocketFiles(void);
+extern void pq_init(void);
+extern int pq_getbytes(char *s, size_t len);
+extern int pq_getstring(StringInfo s);
+extern void pq_startmsgread(void);
+extern void pq_endmsgread(void);
+extern bool pq_is_reading_msg(void);
+extern int pq_getmessage(StringInfo s, int maxlen);
+extern int pq_getbyte(void);
+extern int pq_peekbyte(void);
+extern int pq_getbyte_if_available(unsigned char *c);
+extern int pq_putbytes(const char *s, size_t len);
+
+/*
+ * prototypes for functions in be-secure.c
+ */
+extern char *ssl_library;
+extern char *ssl_cert_file;
+extern char *ssl_key_file;
+extern char *ssl_ca_file;
+extern char *ssl_crl_file;
+extern char *ssl_dh_params_file;
+extern PGDLLIMPORT char *ssl_passphrase_command;
+extern PGDLLIMPORT bool ssl_passphrase_command_supports_reload;
+#ifdef USE_SSL
+extern bool ssl_loaded_verify_locations;
+#endif
+
+extern int secure_initialize(bool isServerStart);
+extern bool secure_loaded_verify_locations(void);
+extern void secure_destroy(void);
+extern int secure_open_server(Port *port);
+extern void secure_close(Port *port);
+extern ssize_t secure_read(Port *port, void *ptr, size_t len);
+extern ssize_t secure_write(Port *port, void *ptr, size_t len);
+extern ssize_t secure_raw_read(Port *port, void *ptr, size_t len);
+extern ssize_t secure_raw_write(Port *port, const void *ptr, size_t len);
+
+/*
+ * prototypes for functions in be-secure-gssapi.c
+ */
+#ifdef ENABLE_GSS
+extern ssize_t secure_open_gssapi(Port *port);
+#endif
+
+/* GUCs */
+extern char *SSLCipherSuites;
+extern char *SSLECDHCurve;
+extern bool SSLPreferServerCiphers;
+extern int ssl_min_protocol_version;
+extern int ssl_max_protocol_version;
+
+enum ssl_protocol_versions
+{
+ PG_TLS_ANY = 0,
+ PG_TLS1_VERSION,
+ PG_TLS1_1_VERSION,
+ PG_TLS1_2_VERSION,
+ PG_TLS1_3_VERSION,
+};
+
+/*
+ * prototypes for functions in be-secure-common.c
+ */
+extern int run_ssl_passphrase_command(const char *prompt, bool is_server_start,
+ char *buf, int size);
+extern bool check_ssl_key_file_permissions(const char *ssl_key_file,
+ bool isServerStart);
+
+#endif /* LIBPQ_H */
diff --git a/src/include/libpq/pqcomm.h b/src/include/libpq/pqcomm.h
new file mode 100644
index 0000000..781d86c
--- /dev/null
+++ b/src/include/libpq/pqcomm.h
@@ -0,0 +1,208 @@
+/*-------------------------------------------------------------------------
+ *
+ * pqcomm.h
+ * Definitions common to frontends and backends.
+ *
+ * NOTE: for historical reasons, this does not correspond to pqcomm.c.
+ * pqcomm.c's routines are declared in libpq.h.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/libpq/pqcomm.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PQCOMM_H
+#define PQCOMM_H
+
+#include <sys/socket.h>
+#include <netdb.h>
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#include <netinet/in.h>
+
+#ifdef HAVE_STRUCT_SOCKADDR_STORAGE
+
+#ifndef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
+#ifdef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY
+#define ss_family __ss_family
+#else
+#error struct sockaddr_storage does not provide an ss_family member
+#endif
+#endif
+
+#ifdef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN
+#define ss_len __ss_len
+#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN 1
+#endif
+#else /* !HAVE_STRUCT_SOCKADDR_STORAGE */
+
+/* Define a struct sockaddr_storage if we don't have one. */
+
+struct sockaddr_storage
+{
+ union
+ {
+ struct sockaddr sa; /* get the system-dependent fields */
+ int64 ss_align; /* ensures struct is properly aligned */
+ char ss_pad[128]; /* ensures struct has desired size */
+ } ss_stuff;
+};
+
+#define ss_family ss_stuff.sa.sa_family
+/* It should have an ss_len field if sockaddr has sa_len. */
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+#define ss_len ss_stuff.sa.sa_len
+#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN 1
+#endif
+#endif /* HAVE_STRUCT_SOCKADDR_STORAGE */
+
+typedef struct
+{
+ struct sockaddr_storage addr;
+ ACCEPT_TYPE_ARG3 salen;
+} SockAddr;
+
+/* Configure the UNIX socket location for the well known port. */
+
+#define UNIXSOCK_PATH(path, port, sockdir) \
+ (AssertMacro(sockdir), \
+ AssertMacro(*(sockdir) != '\0'), \
+ snprintf(path, sizeof(path), "%s/.s.PGSQL.%d", \
+ (sockdir), (port)))
+
+/*
+ * The maximum workable length of a socket path is what will fit into
+ * struct sockaddr_un. This is usually only 100 or so bytes :-(.
+ *
+ * For consistency, always pass a MAXPGPATH-sized buffer to UNIXSOCK_PATH(),
+ * then complain if the resulting string is >= UNIXSOCK_PATH_BUFLEN bytes.
+ * (Because the standard API for getaddrinfo doesn't allow it to complain in
+ * a useful way when the socket pathname is too long, we have to test for
+ * this explicitly, instead of just letting the subroutine return an error.)
+ */
+#define UNIXSOCK_PATH_BUFLEN sizeof(((struct sockaddr_un *) NULL)->sun_path)
+
+
+/*
+ * These manipulate the frontend/backend protocol version number.
+ *
+ * The major number should be incremented for incompatible changes. The minor
+ * number should be incremented for compatible changes (eg. additional
+ * functionality).
+ *
+ * If a backend supports version m.n of the protocol it must actually support
+ * versions m.[0..n]. Backend support for version m-1 can be dropped after a
+ * `reasonable' length of time.
+ *
+ * A frontend isn't required to support anything other than the current
+ * version.
+ */
+
+#define PG_PROTOCOL_MAJOR(v) ((v) >> 16)
+#define PG_PROTOCOL_MINOR(v) ((v) & 0x0000ffff)
+#define PG_PROTOCOL(m,n) (((m) << 16) | (n))
+
+/* The earliest and latest frontend/backend protocol version supported. */
+
+#define PG_PROTOCOL_EARLIEST PG_PROTOCOL(2,0)
+#define PG_PROTOCOL_LATEST PG_PROTOCOL(3,0)
+
+typedef uint32 ProtocolVersion; /* FE/BE protocol version number */
+
+typedef ProtocolVersion MsgType;
+
+
+/*
+ * Packet lengths are 4 bytes in network byte order.
+ *
+ * The initial length is omitted from the packet layouts appearing below.
+ */
+
+typedef uint32 PacketLen;
+
+
+/*
+ * Old-style startup packet layout with fixed-width fields. This is used in
+ * protocol 1.0 and 2.0, but not in later versions. Note that the fields
+ * in this layout are '\0' terminated only if there is room.
+ */
+
+#define SM_DATABASE 64
+#define SM_USER 32
+/* We append database name if db_user_namespace true. */
+#define SM_DATABASE_USER (SM_DATABASE+SM_USER+1) /* +1 for @ */
+#define SM_OPTIONS 64
+#define SM_UNUSED 64
+#define SM_TTY 64
+
+typedef struct StartupPacket
+{
+ ProtocolVersion protoVersion; /* Protocol version */
+ char database[SM_DATABASE]; /* Database name */
+ /* Db_user_namespace appends dbname */
+ char user[SM_USER]; /* User name */
+ char options[SM_OPTIONS]; /* Optional additional args */
+ char unused[SM_UNUSED]; /* Unused */
+ char tty[SM_TTY]; /* Tty for debug output */
+} StartupPacket;
+
+extern bool Db_user_namespace;
+
+/*
+ * In protocol 3.0 and later, the startup packet length is not fixed, but
+ * we set an arbitrary limit on it anyway. This is just to prevent simple
+ * denial-of-service attacks via sending enough data to run the server
+ * out of memory.
+ */
+#define MAX_STARTUP_PACKET_LENGTH 10000
+
+
+/* These are the authentication request codes sent by the backend. */
+
+#define AUTH_REQ_OK 0 /* User is authenticated */
+#define AUTH_REQ_KRB4 1 /* Kerberos V4. Not supported any more. */
+#define AUTH_REQ_KRB5 2 /* Kerberos V5. Not supported any more. */
+#define AUTH_REQ_PASSWORD 3 /* Password */
+#define AUTH_REQ_CRYPT 4 /* crypt password. Not supported any more. */
+#define AUTH_REQ_MD5 5 /* md5 password */
+#define AUTH_REQ_SCM_CREDS 6 /* transfer SCM credentials */
+#define AUTH_REQ_GSS 7 /* GSSAPI without wrap() */
+#define AUTH_REQ_GSS_CONT 8 /* Continue GSS exchanges */
+#define AUTH_REQ_SSPI 9 /* SSPI negotiate without wrap() */
+#define AUTH_REQ_SASL 10 /* Begin SASL authentication */
+#define AUTH_REQ_SASL_CONT 11 /* Continue SASL authentication */
+#define AUTH_REQ_SASL_FIN 12 /* Final SASL message */
+
+typedef uint32 AuthRequest;
+
+
+/*
+ * A client can also send a cancel-current-operation request to the postmaster.
+ * This is uglier than sending it directly to the client's backend, but it
+ * avoids depending on out-of-band communication facilities.
+ *
+ * The cancel request code must not match any protocol version number
+ * we're ever likely to use. This random choice should do.
+ */
+#define CANCEL_REQUEST_CODE PG_PROTOCOL(1234,5678)
+
+typedef struct CancelRequestPacket
+{
+ /* Note that each field is stored in network byte order! */
+ MsgType cancelRequestCode; /* code to identify a cancel request */
+ uint32 backendPID; /* PID of client's backend */
+ uint32 cancelAuthCode; /* secret key to authorize cancel */
+} CancelRequestPacket;
+
+
+/*
+ * A client can also start by sending a SSL or GSSAPI negotiation request to
+ * get a secure channel.
+ */
+#define NEGOTIATE_SSL_CODE PG_PROTOCOL(1234,5679)
+#define NEGOTIATE_GSS_CODE PG_PROTOCOL(1234,5680)
+
+#endif /* PQCOMM_H */
diff --git a/src/include/libpq/pqformat.h b/src/include/libpq/pqformat.h
new file mode 100644
index 0000000..af31e9c
--- /dev/null
+++ b/src/include/libpq/pqformat.h
@@ -0,0 +1,210 @@
+/*-------------------------------------------------------------------------
+ *
+ * pqformat.h
+ * Definitions for formatting and parsing frontend/backend messages
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/libpq/pqformat.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PQFORMAT_H
+#define PQFORMAT_H
+
+#include "lib/stringinfo.h"
+#include "mb/pg_wchar.h"
+#include "port/pg_bswap.h"
+
+extern void pq_beginmessage(StringInfo buf, char msgtype);
+extern void pq_beginmessage_reuse(StringInfo buf, char msgtype);
+extern void pq_endmessage(StringInfo buf);
+extern void pq_endmessage_reuse(StringInfo buf);
+
+extern void pq_sendbytes(StringInfo buf, const char *data, int datalen);
+extern void pq_sendcountedtext(StringInfo buf, const char *str, int slen,
+ bool countincludesself);
+extern void pq_sendtext(StringInfo buf, const char *str, int slen);
+extern void pq_sendstring(StringInfo buf, const char *str);
+extern void pq_send_ascii_string(StringInfo buf, const char *str);
+extern void pq_sendfloat4(StringInfo buf, float4 f);
+extern void pq_sendfloat8(StringInfo buf, float8 f);
+
+/*
+ * Append a [u]int8 to a StringInfo buffer, which already has enough space
+ * preallocated.
+ *
+ * The use of pg_restrict allows the compiler to optimize the code based on
+ * the assumption that buf, buf->len, buf->data and *buf->data don't
+ * overlap. Without the annotation buf->len etc cannot be kept in a register
+ * over subsequent pq_writeintN calls.
+ *
+ * The use of StringInfoData * rather than StringInfo is due to MSVC being
+ * overly picky and demanding a * before a restrict.
+ */
+static inline void
+pq_writeint8(StringInfoData *pg_restrict buf, uint8 i)
+{
+ uint8 ni = i;
+
+ Assert(buf->len + (int) sizeof(uint8) <= buf->maxlen);
+ memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(uint8));
+ buf->len += sizeof(uint8);
+}
+
+/*
+ * Append a [u]int16 to a StringInfo buffer, which already has enough space
+ * preallocated.
+ */
+static inline void
+pq_writeint16(StringInfoData *pg_restrict buf, uint16 i)
+{
+ uint16 ni = pg_hton16(i);
+
+ Assert(buf->len + (int) sizeof(uint16) <= buf->maxlen);
+ memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(uint16));
+ buf->len += sizeof(uint16);
+}
+
+/*
+ * Append a [u]int32 to a StringInfo buffer, which already has enough space
+ * preallocated.
+ */
+static inline void
+pq_writeint32(StringInfoData *pg_restrict buf, uint32 i)
+{
+ uint32 ni = pg_hton32(i);
+
+ Assert(buf->len + (int) sizeof(uint32) <= buf->maxlen);
+ memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(uint32));
+ buf->len += sizeof(uint32);
+}
+
+/*
+ * Append a [u]int64 to a StringInfo buffer, which already has enough space
+ * preallocated.
+ */
+static inline void
+pq_writeint64(StringInfoData *pg_restrict buf, uint64 i)
+{
+ uint64 ni = pg_hton64(i);
+
+ Assert(buf->len + (int) sizeof(uint64) <= buf->maxlen);
+ memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(uint64));
+ buf->len += sizeof(uint64);
+}
+
+/*
+ * Append a null-terminated text string (with conversion) to a buffer with
+ * preallocated space.
+ *
+ * NB: The pre-allocated space needs to be sufficient for the string after
+ * converting to client encoding.
+ *
+ * NB: passed text string must be null-terminated, and so is the data
+ * sent to the frontend.
+ */
+static inline void
+pq_writestring(StringInfoData *pg_restrict buf, const char *pg_restrict str)
+{
+ int slen = strlen(str);
+ char *p;
+
+ p = pg_server_to_client(str, slen);
+ if (p != str) /* actual conversion has been done? */
+ slen = strlen(p);
+
+ Assert(buf->len + slen + 1 <= buf->maxlen);
+
+ memcpy(((char *pg_restrict) buf->data + buf->len), p, slen + 1);
+ buf->len += slen + 1;
+
+ if (p != str)
+ pfree(p);
+}
+
+/* append a binary [u]int8 to a StringInfo buffer */
+static inline void
+pq_sendint8(StringInfo buf, uint8 i)
+{
+ enlargeStringInfo(buf, sizeof(uint8));
+ pq_writeint8(buf, i);
+}
+
+/* append a binary [u]int16 to a StringInfo buffer */
+static inline void
+pq_sendint16(StringInfo buf, uint16 i)
+{
+ enlargeStringInfo(buf, sizeof(uint16));
+ pq_writeint16(buf, i);
+}
+
+/* append a binary [u]int32 to a StringInfo buffer */
+static inline void
+pq_sendint32(StringInfo buf, uint32 i)
+{
+ enlargeStringInfo(buf, sizeof(uint32));
+ pq_writeint32(buf, i);
+}
+
+/* append a binary [u]int64 to a StringInfo buffer */
+static inline void
+pq_sendint64(StringInfo buf, uint64 i)
+{
+ enlargeStringInfo(buf, sizeof(uint64));
+ pq_writeint64(buf, i);
+}
+
+/* append a binary byte to a StringInfo buffer */
+static inline void
+pq_sendbyte(StringInfo buf, uint8 byt)
+{
+ pq_sendint8(buf, byt);
+}
+
+/*
+ * Append a binary integer to a StringInfo buffer
+ *
+ * This function is deprecated; prefer use of the functions above.
+ */
+static inline void
+pq_sendint(StringInfo buf, uint32 i, int b)
+{
+ switch (b)
+ {
+ case 1:
+ pq_sendint8(buf, (uint8) i);
+ break;
+ case 2:
+ pq_sendint16(buf, (uint16) i);
+ break;
+ case 4:
+ pq_sendint32(buf, (uint32) i);
+ break;
+ default:
+ elog(ERROR, "unsupported integer size %d", b);
+ break;
+ }
+}
+
+
+extern void pq_begintypsend(StringInfo buf);
+extern bytea *pq_endtypsend(StringInfo buf);
+
+extern void pq_puttextmessage(char msgtype, const char *str);
+extern void pq_putemptymessage(char msgtype);
+
+extern int pq_getmsgbyte(StringInfo msg);
+extern unsigned int pq_getmsgint(StringInfo msg, int b);
+extern int64 pq_getmsgint64(StringInfo msg);
+extern float4 pq_getmsgfloat4(StringInfo msg);
+extern float8 pq_getmsgfloat8(StringInfo msg);
+extern const char *pq_getmsgbytes(StringInfo msg, int datalen);
+extern void pq_copymsgbytes(StringInfo msg, char *buf, int datalen);
+extern char *pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes);
+extern const char *pq_getmsgstring(StringInfo msg);
+extern const char *pq_getmsgrawstring(StringInfo msg);
+extern void pq_getmsgend(StringInfo msg);
+
+#endif /* PQFORMAT_H */
diff --git a/src/include/libpq/pqmq.h b/src/include/libpq/pqmq.h
new file mode 100644
index 0000000..6a3ccba
--- /dev/null
+++ b/src/include/libpq/pqmq.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * pqmq.h
+ * Use the frontend/backend protocol for communication over a shm_mq
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/libpq/pqmq.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PQMQ_H
+#define PQMQ_H
+
+#include "lib/stringinfo.h"
+#include "storage/shm_mq.h"
+
+extern void pq_redirect_to_shm_mq(dsm_segment *seg, shm_mq_handle *mqh);
+extern void pq_set_parallel_master(pid_t pid, BackendId backend_id);
+
+extern void pq_parse_errornotice(StringInfo str, ErrorData *edata);
+
+#endif /* PQMQ_H */
diff --git a/src/include/libpq/pqsignal.h b/src/include/libpq/pqsignal.h
new file mode 100644
index 0000000..695c4dc
--- /dev/null
+++ b/src/include/libpq/pqsignal.h
@@ -0,0 +1,42 @@
+/*-------------------------------------------------------------------------
+ *
+ * pqsignal.h
+ * Backend signal(2) support (see also src/port/pqsignal.c)
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/libpq/pqsignal.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PQSIGNAL_H
+#define PQSIGNAL_H
+
+#include <signal.h>
+
+#ifndef WIN32
+#define PG_SETMASK(mask) sigprocmask(SIG_SETMASK, mask, NULL)
+#else
+/* Emulate POSIX sigset_t APIs on Windows */
+typedef int sigset_t;
+
+extern int pqsigsetmask(int mask);
+
+#define PG_SETMASK(mask) pqsigsetmask(*(mask))
+#define sigemptyset(set) (*(set) = 0)
+#define sigfillset(set) (*(set) = ~0)
+#define sigaddset(set, signum) (*(set) |= (sigmask(signum)))
+#define sigdelset(set, signum) (*(set) &= ~(sigmask(signum)))
+#endif /* WIN32 */
+
+extern sigset_t UnBlockSig,
+ BlockSig,
+ StartupBlockSig;
+
+extern void pqinitmask(void);
+
+/* pqsigfunc is declared in src/include/port.h */
+extern pqsigfunc pqsignal_pm(int signo, pqsigfunc func);
+
+#endif /* PQSIGNAL_H */
diff --git a/src/include/libpq/scram.h b/src/include/libpq/scram.h
new file mode 100644
index 0000000..83f1bbc
--- /dev/null
+++ b/src/include/libpq/scram.h
@@ -0,0 +1,37 @@
+/*-------------------------------------------------------------------------
+ *
+ * scram.h
+ * Interface to libpq/scram.c
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/libpq/scram.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_SCRAM_H
+#define PG_SCRAM_H
+
+#include "lib/stringinfo.h"
+#include "libpq/libpq-be.h"
+
+/* Status codes for message exchange */
+#define SASL_EXCHANGE_CONTINUE 0
+#define SASL_EXCHANGE_SUCCESS 1
+#define SASL_EXCHANGE_FAILURE 2
+
+/* Routines dedicated to authentication */
+extern void pg_be_scram_get_mechanisms(Port *port, StringInfo buf);
+extern void *pg_be_scram_init(Port *port, const char *selected_mech, const char *shadow_pass);
+extern int pg_be_scram_exchange(void *opaq, const char *input, int inputlen,
+ char **output, int *outputlen, char **logdetail);
+
+/* Routines to handle and check SCRAM-SHA-256 secret */
+extern char *pg_be_scram_build_secret(const char *password);
+extern bool parse_scram_secret(const char *secret, int *iterations, char **salt,
+ uint8 *stored_key, uint8 *server_key);
+extern bool scram_verify_plain_password(const char *username,
+ const char *password, const char *secret);
+
+#endif /* PG_SCRAM_H */
diff --git a/src/include/mb/pg_wchar.h b/src/include/mb/pg_wchar.h
new file mode 100644
index 0000000..b43454b
--- /dev/null
+++ b/src/include/mb/pg_wchar.h
@@ -0,0 +1,673 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_wchar.h
+ * multibyte-character support
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/mb/pg_wchar.h
+ *
+ * NOTES
+ * This is used both by the backend and by frontends, but should not be
+ * included by libpq client programs. In particular, a libpq client
+ * should not assume that the encoding IDs used by the version of libpq
+ * it's linked to match up with the IDs declared here.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_WCHAR_H
+#define PG_WCHAR_H
+
+/*
+ * The pg_wchar type
+ */
+typedef unsigned int pg_wchar;
+
+/*
+ * Maximum byte length of multibyte characters in any backend encoding
+ */
+#define MAX_MULTIBYTE_CHAR_LEN 4
+
+/*
+ * various definitions for EUC
+ */
+#define SS2 0x8e /* single shift 2 (JIS0201) */
+#define SS3 0x8f /* single shift 3 (JIS0212) */
+
+/*
+ * SJIS validation macros
+ */
+#define ISSJISHEAD(c) (((c) >= 0x81 && (c) <= 0x9f) || ((c) >= 0xe0 && (c) <= 0xfc))
+#define ISSJISTAIL(c) (((c) >= 0x40 && (c) <= 0x7e) || ((c) >= 0x80 && (c) <= 0xfc))
+
+/*----------------------------------------------------
+ * MULE Internal Encoding (MIC)
+ *
+ * This encoding follows the design used within XEmacs; it is meant to
+ * subsume many externally-defined character sets. Each character includes
+ * identification of the character set it belongs to, so the encoding is
+ * general but somewhat bulky.
+ *
+ * Currently PostgreSQL supports 5 types of MULE character sets:
+ *
+ * 1) 1-byte ASCII characters. Each byte is below 0x80.
+ *
+ * 2) "Official" single byte charsets such as ISO-8859-1 (Latin1).
+ * Each MULE character consists of 2 bytes: LC1 + C1, where LC1 is
+ * an identifier for the charset (in the range 0x81 to 0x8d) and C1
+ * is the character code (in the range 0xa0 to 0xff).
+ *
+ * 3) "Private" single byte charsets such as SISHENG. Each MULE
+ * character consists of 3 bytes: LCPRV1 + LC12 + C1, where LCPRV1
+ * is a private-charset flag, LC12 is an identifier for the charset,
+ * and C1 is the character code (in the range 0xa0 to 0xff).
+ * LCPRV1 is either 0x9a (if LC12 is in the range 0xa0 to 0xdf)
+ * or 0x9b (if LC12 is in the range 0xe0 to 0xef).
+ *
+ * 4) "Official" multibyte charsets such as JIS X0208. Each MULE
+ * character consists of 3 bytes: LC2 + C1 + C2, where LC2 is
+ * an identifier for the charset (in the range 0x90 to 0x99) and C1
+ * and C2 form the character code (each in the range 0xa0 to 0xff).
+ *
+ * 5) "Private" multibyte charsets such as CNS 11643-1992 Plane 3.
+ * Each MULE character consists of 4 bytes: LCPRV2 + LC22 + C1 + C2,
+ * where LCPRV2 is a private-charset flag, LC22 is an identifier for
+ * the charset, and C1 and C2 form the character code (each in the range
+ * 0xa0 to 0xff). LCPRV2 is either 0x9c (if LC22 is in the range 0xf0
+ * to 0xf4) or 0x9d (if LC22 is in the range 0xf5 to 0xfe).
+ *
+ * "Official" encodings are those that have been assigned code numbers by
+ * the XEmacs project; "private" encodings have Postgres-specific charset
+ * identifiers.
+ *
+ * See the "XEmacs Internals Manual", available at http://www.xemacs.org,
+ * for more details. Note that for historical reasons, Postgres'
+ * private-charset flag values do not match what XEmacs says they should be,
+ * so this isn't really exactly MULE (not that private charsets would be
+ * interoperable anyway).
+ *
+ * Note that XEmacs's implementation is different from what emacs does.
+ * We follow emacs's implementation, rather than XEmacs's.
+ *----------------------------------------------------
+ */
+
+/*
+ * Charset identifiers (also called "leading bytes" in the MULE documentation)
+ */
+
+/*
+ * Charset IDs for official single byte encodings (0x81-0x8e)
+ */
+#define LC_ISO8859_1 0x81 /* ISO8859 Latin 1 */
+#define LC_ISO8859_2 0x82 /* ISO8859 Latin 2 */
+#define LC_ISO8859_3 0x83 /* ISO8859 Latin 3 */
+#define LC_ISO8859_4 0x84 /* ISO8859 Latin 4 */
+#define LC_TIS620 0x85 /* Thai (not supported yet) */
+#define LC_ISO8859_7 0x86 /* Greek (not supported yet) */
+#define LC_ISO8859_6 0x87 /* Arabic (not supported yet) */
+#define LC_ISO8859_8 0x88 /* Hebrew (not supported yet) */
+#define LC_JISX0201K 0x89 /* Japanese 1 byte kana */
+#define LC_JISX0201R 0x8a /* Japanese 1 byte Roman */
+/* Note that 0x8b seems to be unused as of Emacs 20.7.
+ * However, there might be a chance that 0x8b could be used
+ * in later versions of Emacs.
+ */
+#define LC_KOI8_R 0x8b /* Cyrillic KOI8-R */
+#define LC_ISO8859_5 0x8c /* ISO8859 Cyrillic */
+#define LC_ISO8859_9 0x8d /* ISO8859 Latin 5 (not supported yet) */
+#define LC_ISO8859_15 0x8e /* ISO8859 Latin 15 (not supported yet) */
+/* #define CONTROL_1 0x8f control characters (unused) */
+
+/* Is a leading byte for "official" single byte encodings? */
+#define IS_LC1(c) ((unsigned char)(c) >= 0x81 && (unsigned char)(c) <= 0x8d)
+
+/*
+ * Charset IDs for official multibyte encodings (0x90-0x99)
+ * 0x9a-0x9d are free. 0x9e and 0x9f are reserved.
+ */
+#define LC_JISX0208_1978 0x90 /* Japanese Kanji, old JIS (not supported) */
+#define LC_GB2312_80 0x91 /* Chinese */
+#define LC_JISX0208 0x92 /* Japanese Kanji (JIS X 0208) */
+#define LC_KS5601 0x93 /* Korean */
+#define LC_JISX0212 0x94 /* Japanese Kanji (JIS X 0212) */
+#define LC_CNS11643_1 0x95 /* CNS 11643-1992 Plane 1 */
+#define LC_CNS11643_2 0x96 /* CNS 11643-1992 Plane 2 */
+#define LC_JISX0213_1 0x97 /* Japanese Kanji (JIS X 0213 Plane 1)
+ * (not supported) */
+#define LC_BIG5_1 0x98 /* Plane 1 Chinese traditional (not
+ * supported) */
+#define LC_BIG5_2 0x99 /* Plane 1 Chinese traditional (not
+ * supported) */
+
+/* Is a leading byte for "official" multibyte encodings? */
+#define IS_LC2(c) ((unsigned char)(c) >= 0x90 && (unsigned char)(c) <= 0x99)
+
+/*
+ * Postgres-specific prefix bytes for "private" single byte encodings
+ * (According to the MULE docs, we should be using 0x9e for this)
+ */
+#define LCPRV1_A 0x9a
+#define LCPRV1_B 0x9b
+#define IS_LCPRV1(c) ((unsigned char)(c) == LCPRV1_A || (unsigned char)(c) == LCPRV1_B)
+#define IS_LCPRV1_A_RANGE(c) \
+ ((unsigned char)(c) >= 0xa0 && (unsigned char)(c) <= 0xdf)
+#define IS_LCPRV1_B_RANGE(c) \
+ ((unsigned char)(c) >= 0xe0 && (unsigned char)(c) <= 0xef)
+
+/*
+ * Postgres-specific prefix bytes for "private" multibyte encodings
+ * (According to the MULE docs, we should be using 0x9f for this)
+ */
+#define LCPRV2_A 0x9c
+#define LCPRV2_B 0x9d
+#define IS_LCPRV2(c) ((unsigned char)(c) == LCPRV2_A || (unsigned char)(c) == LCPRV2_B)
+#define IS_LCPRV2_A_RANGE(c) \
+ ((unsigned char)(c) >= 0xf0 && (unsigned char)(c) <= 0xf4)
+#define IS_LCPRV2_B_RANGE(c) \
+ ((unsigned char)(c) >= 0xf5 && (unsigned char)(c) <= 0xfe)
+
+/*
+ * Charset IDs for private single byte encodings (0xa0-0xef)
+ */
+#define LC_SISHENG 0xa0 /* Chinese SiSheng characters for
+ * PinYin/ZhuYin (not supported) */
+#define LC_IPA 0xa1 /* IPA (International Phonetic
+ * Association) (not supported) */
+#define LC_VISCII_LOWER 0xa2 /* Vietnamese VISCII1.1 lower-case (not
+ * supported) */
+#define LC_VISCII_UPPER 0xa3 /* Vietnamese VISCII1.1 upper-case (not
+ * supported) */
+#define LC_ARABIC_DIGIT 0xa4 /* Arabic digit (not supported) */
+#define LC_ARABIC_1_COLUMN 0xa5 /* Arabic 1-column (not supported) */
+#define LC_ASCII_RIGHT_TO_LEFT 0xa6 /* ASCII (left half of ISO8859-1) with
+ * right-to-left direction (not
+ * supported) */
+#define LC_LAO 0xa7 /* Lao characters (ISO10646 0E80..0EDF)
+ * (not supported) */
+#define LC_ARABIC_2_COLUMN 0xa8 /* Arabic 1-column (not supported) */
+
+/*
+ * Charset IDs for private multibyte encodings (0xf0-0xff)
+ */
+#define LC_INDIAN_1_COLUMN 0xf0 /* Indian charset for 1-column width
+ * glyphs (not supported) */
+#define LC_TIBETAN_1_COLUMN 0xf1 /* Tibetan 1-column width glyphs (not
+ * supported) */
+#define LC_UNICODE_SUBSET_2 0xf2 /* Unicode characters of the range
+ * U+2500..U+33FF. (not supported) */
+#define LC_UNICODE_SUBSET_3 0xf3 /* Unicode characters of the range
+ * U+E000..U+FFFF. (not supported) */
+#define LC_UNICODE_SUBSET 0xf4 /* Unicode characters of the range
+ * U+0100..U+24FF. (not supported) */
+#define LC_ETHIOPIC 0xf5 /* Ethiopic characters (not supported) */
+#define LC_CNS11643_3 0xf6 /* CNS 11643-1992 Plane 3 */
+#define LC_CNS11643_4 0xf7 /* CNS 11643-1992 Plane 4 */
+#define LC_CNS11643_5 0xf8 /* CNS 11643-1992 Plane 5 */
+#define LC_CNS11643_6 0xf9 /* CNS 11643-1992 Plane 6 */
+#define LC_CNS11643_7 0xfa /* CNS 11643-1992 Plane 7 */
+#define LC_INDIAN_2_COLUMN 0xfb /* Indian charset for 2-column width
+ * glyphs (not supported) */
+#define LC_TIBETAN 0xfc /* Tibetan (not supported) */
+/* #define FREE 0xfd free (unused) */
+/* #define FREE 0xfe free (unused) */
+/* #define FREE 0xff free (unused) */
+
+/*----------------------------------------------------
+ * end of MULE stuff
+ *----------------------------------------------------
+ */
+
+/*
+ * PostgreSQL encoding identifiers
+ *
+ * WARNING: the order of this enum must be same as order of entries
+ * in the pg_enc2name_tbl[] array (in src/common/encnames.c), and
+ * in the pg_wchar_table[] array (in src/common/wchar.c)!
+ *
+ * If you add some encoding don't forget to check
+ * PG_ENCODING_BE_LAST macro.
+ *
+ * PG_SQL_ASCII is default encoding and must be = 0.
+ *
+ * XXX We must avoid renumbering any backend encoding until libpq's major
+ * version number is increased beyond 5; it turns out that the backend
+ * encoding IDs are effectively part of libpq's ABI as far as 8.2 initdb and
+ * psql are concerned.
+ */
+typedef enum pg_enc
+{
+ PG_SQL_ASCII = 0, /* SQL/ASCII */
+ PG_EUC_JP, /* EUC for Japanese */
+ PG_EUC_CN, /* EUC for Chinese */
+ PG_EUC_KR, /* EUC for Korean */
+ PG_EUC_TW, /* EUC for Taiwan */
+ PG_EUC_JIS_2004, /* EUC-JIS-2004 */
+ PG_UTF8, /* Unicode UTF8 */
+ PG_MULE_INTERNAL, /* Mule internal code */
+ PG_LATIN1, /* ISO-8859-1 Latin 1 */
+ PG_LATIN2, /* ISO-8859-2 Latin 2 */
+ PG_LATIN3, /* ISO-8859-3 Latin 3 */
+ PG_LATIN4, /* ISO-8859-4 Latin 4 */
+ PG_LATIN5, /* ISO-8859-9 Latin 5 */
+ PG_LATIN6, /* ISO-8859-10 Latin6 */
+ PG_LATIN7, /* ISO-8859-13 Latin7 */
+ PG_LATIN8, /* ISO-8859-14 Latin8 */
+ PG_LATIN9, /* ISO-8859-15 Latin9 */
+ PG_LATIN10, /* ISO-8859-16 Latin10 */
+ PG_WIN1256, /* windows-1256 */
+ PG_WIN1258, /* Windows-1258 */
+ PG_WIN866, /* (MS-DOS CP866) */
+ PG_WIN874, /* windows-874 */
+ PG_KOI8R, /* KOI8-R */
+ PG_WIN1251, /* windows-1251 */
+ PG_WIN1252, /* windows-1252 */
+ PG_ISO_8859_5, /* ISO-8859-5 */
+ PG_ISO_8859_6, /* ISO-8859-6 */
+ PG_ISO_8859_7, /* ISO-8859-7 */
+ PG_ISO_8859_8, /* ISO-8859-8 */
+ PG_WIN1250, /* windows-1250 */
+ PG_WIN1253, /* windows-1253 */
+ PG_WIN1254, /* windows-1254 */
+ PG_WIN1255, /* windows-1255 */
+ PG_WIN1257, /* windows-1257 */
+ PG_KOI8U, /* KOI8-U */
+ /* PG_ENCODING_BE_LAST points to the above entry */
+
+ /* followings are for client encoding only */
+ PG_SJIS, /* Shift JIS (Windows-932) */
+ PG_BIG5, /* Big5 (Windows-950) */
+ PG_GBK, /* GBK (Windows-936) */
+ PG_UHC, /* UHC (Windows-949) */
+ PG_GB18030, /* GB18030 */
+ PG_JOHAB, /* EUC for Korean JOHAB */
+ PG_SHIFT_JIS_2004, /* Shift-JIS-2004 */
+ _PG_LAST_ENCODING_ /* mark only */
+
+} pg_enc;
+
+#define PG_ENCODING_BE_LAST PG_KOI8U
+
+/*
+ * Please use these tests before access to pg_enc2name_tbl[]
+ * or to other places...
+ */
+#define PG_VALID_BE_ENCODING(_enc) \
+ ((_enc) >= 0 && (_enc) <= PG_ENCODING_BE_LAST)
+
+#define PG_ENCODING_IS_CLIENT_ONLY(_enc) \
+ ((_enc) > PG_ENCODING_BE_LAST && (_enc) < _PG_LAST_ENCODING_)
+
+#define PG_VALID_ENCODING(_enc) \
+ ((_enc) >= 0 && (_enc) < _PG_LAST_ENCODING_)
+
+/* On FE are possible all encodings */
+#define PG_VALID_FE_ENCODING(_enc) PG_VALID_ENCODING(_enc)
+
+/*
+ * When converting strings between different encodings, we assume that space
+ * for converted result is 4-to-1 growth in the worst case. The rate for
+ * currently supported encoding pairs are within 3 (SJIS JIS X0201 half width
+ * kanna -> UTF8 is the worst case). So "4" should be enough for the moment.
+ *
+ * Note that this is not the same as the maximum character width in any
+ * particular encoding.
+ */
+#define MAX_CONVERSION_GROWTH 4
+
+/*
+ * Maximum byte length of the string equivalent to any one Unicode code point,
+ * in any backend encoding. The current value assumes that a 4-byte UTF-8
+ * character might expand by MAX_CONVERSION_GROWTH, which is a huge
+ * overestimate. But in current usage we don't allocate large multiples of
+ * this, so there's little point in being stingy.
+ */
+#define MAX_UNICODE_EQUIVALENT_STRING 16
+
+/*
+ * Table for mapping an encoding number to official encoding name and
+ * possibly other subsidiary data. Be careful to check encoding number
+ * before accessing a table entry!
+ *
+ * if (PG_VALID_ENCODING(encoding))
+ * pg_enc2name_tbl[ encoding ];
+ */
+typedef struct pg_enc2name
+{
+ const char *name;
+ pg_enc encoding;
+#ifdef WIN32
+ unsigned codepage; /* codepage for WIN32 */
+#endif
+} pg_enc2name;
+
+extern const pg_enc2name pg_enc2name_tbl[];
+
+/*
+ * Encoding names for gettext
+ */
+typedef struct pg_enc2gettext
+{
+ pg_enc encoding;
+ const char *name;
+} pg_enc2gettext;
+
+extern const pg_enc2gettext pg_enc2gettext_tbl[];
+
+/*
+ * pg_wchar stuff
+ */
+typedef int (*mb2wchar_with_len_converter) (const unsigned char *from,
+ pg_wchar *to,
+ int len);
+
+typedef int (*wchar2mb_with_len_converter) (const pg_wchar *from,
+ unsigned char *to,
+ int len);
+
+typedef int (*mblen_converter) (const unsigned char *mbstr);
+
+typedef int (*mbdisplaylen_converter) (const unsigned char *mbstr);
+
+typedef bool (*mbcharacter_incrementer) (unsigned char *mbstr, int len);
+
+typedef int (*mbverifier) (const unsigned char *mbstr, int len);
+
+typedef struct
+{
+ mb2wchar_with_len_converter mb2wchar_with_len; /* convert a multibyte
+ * string to a wchar */
+ wchar2mb_with_len_converter wchar2mb_with_len; /* convert a wchar string
+ * to a multibyte */
+ mblen_converter mblen; /* get byte length of a char */
+ mbdisplaylen_converter dsplen; /* get display width of a char */
+ mbverifier mbverify; /* verify multibyte sequence */
+ int maxmblen; /* max bytes for a char in this encoding */
+} pg_wchar_tbl;
+
+extern const pg_wchar_tbl pg_wchar_table[];
+
+/*
+ * Data structures for conversions between UTF-8 and other encodings
+ * (UtfToLocal() and LocalToUtf()). In these data structures, characters of
+ * either encoding are represented by uint32 words; hence we can only support
+ * characters up to 4 bytes long. For example, the byte sequence 0xC2 0x89
+ * would be represented by 0x0000C289, and 0xE8 0xA2 0xB4 by 0x00E8A2B4.
+ *
+ * There are three possible ways a character can be mapped:
+ *
+ * 1. Using a radix tree, from source to destination code.
+ * 2. Using a sorted array of source -> destination code pairs. This
+ * method is used for "combining" characters. There are so few of
+ * them that building a radix tree would be wasteful.
+ * 3. Using a conversion function.
+ */
+
+/*
+ * Radix tree for character conversion.
+ *
+ * Logically, this is actually four different radix trees, for 1-byte,
+ * 2-byte, 3-byte and 4-byte inputs. The 1-byte tree is a simple lookup
+ * table from source to target code. The 2-byte tree consists of two levels:
+ * one lookup table for the first byte, where the value in the lookup table
+ * points to a lookup table for the second byte. And so on.
+ *
+ * Physically, all the trees are stored in one big array, in 'chars16' or
+ * 'chars32', depending on the maximum value that needs to be represented. For
+ * each level in each tree, we also store lower and upper bound of allowed
+ * values - values outside those bounds are considered invalid, and are left
+ * out of the tables.
+ *
+ * In the intermediate levels of the trees, the values stored are offsets
+ * into the chars[16|32] array.
+ *
+ * In the beginning of the chars[16|32] array, there is always a number of
+ * zeros, so that you safely follow an index from an intermediate table
+ * without explicitly checking for a zero. Following a zero any number of
+ * times will always bring you to the dummy, all-zeros table in the
+ * beginning. This helps to shave some cycles when looking up values.
+ */
+typedef struct
+{
+ /*
+ * Array containing all the values. Only one of chars16 or chars32 is
+ * used, depending on how wide the values we need to represent are.
+ */
+ const uint16 *chars16;
+ const uint32 *chars32;
+
+ /* Radix tree for 1-byte inputs */
+ uint32 b1root; /* offset of table in the chars[16|32] array */
+ uint8 b1_lower; /* min allowed value for a single byte input */
+ uint8 b1_upper; /* max allowed value for a single byte input */
+
+ /* Radix tree for 2-byte inputs */
+ uint32 b2root; /* offset of 1st byte's table */
+ uint8 b2_1_lower; /* min/max allowed value for 1st input byte */
+ uint8 b2_1_upper;
+ uint8 b2_2_lower; /* min/max allowed value for 2nd input byte */
+ uint8 b2_2_upper;
+
+ /* Radix tree for 3-byte inputs */
+ uint32 b3root; /* offset of 1st byte's table */
+ uint8 b3_1_lower; /* min/max allowed value for 1st input byte */
+ uint8 b3_1_upper;
+ uint8 b3_2_lower; /* min/max allowed value for 2nd input byte */
+ uint8 b3_2_upper;
+ uint8 b3_3_lower; /* min/max allowed value for 3rd input byte */
+ uint8 b3_3_upper;
+
+ /* Radix tree for 4-byte inputs */
+ uint32 b4root; /* offset of 1st byte's table */
+ uint8 b4_1_lower; /* min/max allowed value for 1st input byte */
+ uint8 b4_1_upper;
+ uint8 b4_2_lower; /* min/max allowed value for 2nd input byte */
+ uint8 b4_2_upper;
+ uint8 b4_3_lower; /* min/max allowed value for 3rd input byte */
+ uint8 b4_3_upper;
+ uint8 b4_4_lower; /* min/max allowed value for 4th input byte */
+ uint8 b4_4_upper;
+
+} pg_mb_radix_tree;
+
+/*
+ * UTF-8 to local code conversion map (for combined characters)
+ */
+typedef struct
+{
+ uint32 utf1; /* UTF-8 code 1 */
+ uint32 utf2; /* UTF-8 code 2 */
+ uint32 code; /* local code */
+} pg_utf_to_local_combined;
+
+/*
+ * local code to UTF-8 conversion map (for combined characters)
+ */
+typedef struct
+{
+ uint32 code; /* local code */
+ uint32 utf1; /* UTF-8 code 1 */
+ uint32 utf2; /* UTF-8 code 2 */
+} pg_local_to_utf_combined;
+
+/*
+ * callback function for algorithmic encoding conversions (in either direction)
+ *
+ * if function returns zero, it does not know how to convert the code
+ */
+typedef uint32 (*utf_local_conversion_func) (uint32 code);
+
+/*
+ * Support macro for encoding conversion functions to validate their
+ * arguments. (This could be made more compact if we included fmgr.h
+ * here, but we don't want to do that because this header file is also
+ * used by frontends.)
+ */
+#define CHECK_ENCODING_CONVERSION_ARGS(srcencoding,destencoding) \
+ check_encoding_conversion_args(PG_GETARG_INT32(0), \
+ PG_GETARG_INT32(1), \
+ PG_GETARG_INT32(4), \
+ (srcencoding), \
+ (destencoding))
+
+
+/*
+ * Some handy functions for Unicode-specific tests.
+ */
+static inline bool
+is_valid_unicode_codepoint(pg_wchar c)
+{
+ return (c > 0 && c <= 0x10FFFF);
+}
+
+static inline bool
+is_utf16_surrogate_first(pg_wchar c)
+{
+ return (c >= 0xD800 && c <= 0xDBFF);
+}
+
+static inline bool
+is_utf16_surrogate_second(pg_wchar c)
+{
+ return (c >= 0xDC00 && c <= 0xDFFF);
+}
+
+static inline pg_wchar
+surrogate_pair_to_codepoint(pg_wchar first, pg_wchar second)
+{
+ return ((first & 0x3FF) << 10) + 0x10000 + (second & 0x3FF);
+}
+
+
+/*
+ * These functions are considered part of libpq's exported API and
+ * are also declared in libpq-fe.h.
+ */
+extern int pg_char_to_encoding(const char *name);
+extern const char *pg_encoding_to_char(int encoding);
+extern int pg_valid_server_encoding_id(int encoding);
+
+/*
+ * These functions are available to frontend code that links with libpgcommon
+ * (in addition to the ones just above). The constant tables declared
+ * earlier in this file are also available from libpgcommon.
+ */
+extern int pg_encoding_mblen(int encoding, const char *mbstr);
+extern int pg_encoding_mblen_bounded(int encoding, const char *mbstr);
+extern int pg_encoding_dsplen(int encoding, const char *mbstr);
+extern int pg_encoding_verifymb(int encoding, const char *mbstr, int len);
+extern int pg_encoding_max_length(int encoding);
+extern int pg_valid_client_encoding(const char *name);
+extern int pg_valid_server_encoding(const char *name);
+extern bool is_encoding_supported_by_icu(int encoding);
+extern const char *get_encoding_name_for_icu(int encoding);
+
+extern unsigned char *unicode_to_utf8(pg_wchar c, unsigned char *utf8string);
+extern pg_wchar utf8_to_unicode(const unsigned char *c);
+extern bool pg_utf8_islegal(const unsigned char *source, int length);
+extern int pg_utf_mblen(const unsigned char *s);
+extern int pg_mule_mblen(const unsigned char *s);
+
+/*
+ * The remaining functions are backend-only.
+ */
+extern int pg_mb2wchar(const char *from, pg_wchar *to);
+extern int pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len);
+extern int pg_encoding_mb2wchar_with_len(int encoding,
+ const char *from, pg_wchar *to, int len);
+extern int pg_wchar2mb(const pg_wchar *from, char *to);
+extern int pg_wchar2mb_with_len(const pg_wchar *from, char *to, int len);
+extern int pg_encoding_wchar2mb_with_len(int encoding,
+ const pg_wchar *from, char *to, int len);
+extern int pg_char_and_wchar_strcmp(const char *s1, const pg_wchar *s2);
+extern int pg_wchar_strncmp(const pg_wchar *s1, const pg_wchar *s2, size_t n);
+extern int pg_char_and_wchar_strncmp(const char *s1, const pg_wchar *s2, size_t n);
+extern size_t pg_wchar_strlen(const pg_wchar *wstr);
+extern int pg_mblen(const char *mbstr);
+extern int pg_dsplen(const char *mbstr);
+extern int pg_mbstrlen(const char *mbstr);
+extern int pg_mbstrlen_with_len(const char *mbstr, int len);
+extern int pg_mbcliplen(const char *mbstr, int len, int limit);
+extern int pg_encoding_mbcliplen(int encoding, const char *mbstr,
+ int len, int limit);
+extern int pg_mbcharcliplen(const char *mbstr, int len, int limit);
+extern int pg_database_encoding_max_length(void);
+extern mbcharacter_incrementer pg_database_encoding_character_incrementer(void);
+
+extern int PrepareClientEncoding(int encoding);
+extern int SetClientEncoding(int encoding);
+extern void InitializeClientEncoding(void);
+extern int pg_get_client_encoding(void);
+extern const char *pg_get_client_encoding_name(void);
+
+extern void SetDatabaseEncoding(int encoding);
+extern int GetDatabaseEncoding(void);
+extern const char *GetDatabaseEncodingName(void);
+extern void SetMessageEncoding(int encoding);
+extern int GetMessageEncoding(void);
+
+#ifdef ENABLE_NLS
+extern int pg_bind_textdomain_codeset(const char *domainname);
+#endif
+
+extern unsigned char *pg_do_encoding_conversion(unsigned char *src, int len,
+ int src_encoding,
+ int dest_encoding);
+
+extern char *pg_client_to_server(const char *s, int len);
+extern char *pg_server_to_client(const char *s, int len);
+extern char *pg_any_to_server(const char *s, int len, int encoding);
+extern char *pg_server_to_any(const char *s, int len, int encoding);
+
+extern void pg_unicode_to_server(pg_wchar c, unsigned char *s);
+
+extern unsigned short BIG5toCNS(unsigned short big5, unsigned char *lc);
+extern unsigned short CNStoBIG5(unsigned short cns, unsigned char lc);
+
+extern void UtfToLocal(const unsigned char *utf, int len,
+ unsigned char *iso,
+ const pg_mb_radix_tree *map,
+ const pg_utf_to_local_combined *cmap, int cmapsize,
+ utf_local_conversion_func conv_func,
+ int encoding);
+extern void LocalToUtf(const unsigned char *iso, int len,
+ unsigned char *utf,
+ const pg_mb_radix_tree *map,
+ const pg_local_to_utf_combined *cmap, int cmapsize,
+ utf_local_conversion_func conv_func,
+ int encoding);
+
+extern bool pg_verifymbstr(const char *mbstr, int len, bool noError);
+extern bool pg_verify_mbstr(int encoding, const char *mbstr, int len,
+ bool noError);
+extern int pg_verify_mbstr_len(int encoding, const char *mbstr, int len,
+ bool noError);
+
+extern void check_encoding_conversion_args(int src_encoding,
+ int dest_encoding,
+ int len,
+ int expected_src_encoding,
+ int expected_dest_encoding);
+
+extern void report_invalid_encoding(int encoding, const char *mbstr, int len) pg_attribute_noreturn();
+extern void report_untranslatable_char(int src_encoding, int dest_encoding,
+ const char *mbstr, int len) pg_attribute_noreturn();
+
+extern void local2local(const unsigned char *l, unsigned char *p, int len,
+ int src_encoding, int dest_encoding, const unsigned char *tab);
+extern void latin2mic(const unsigned char *l, unsigned char *p, int len,
+ int lc, int encoding);
+extern void mic2latin(const unsigned char *mic, unsigned char *p, int len,
+ int lc, int encoding);
+extern void latin2mic_with_table(const unsigned char *l, unsigned char *p,
+ int len, int lc, int encoding,
+ const unsigned char *tab);
+extern void mic2latin_with_table(const unsigned char *mic, unsigned char *p,
+ int len, int lc, int encoding,
+ const unsigned char *tab);
+
+#ifdef WIN32
+extern WCHAR *pgwin32_message_to_UTF16(const char *str, int len, int *utf16len);
+#endif
+
+#endif /* PG_WCHAR_H */
diff --git a/src/include/mb/stringinfo_mb.h b/src/include/mb/stringinfo_mb.h
new file mode 100644
index 0000000..3bef568
--- /dev/null
+++ b/src/include/mb/stringinfo_mb.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * stringinfo_mb.h
+ * multibyte support for StringInfo
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/mb/stringinfo_mb.h
+ *-------------------------------------------------------------------------
+ */
+#ifndef STRINGINFO_MB_H
+#define STRINGINFO_MB_H
+
+
+#include "lib/stringinfo.h"
+
+/*
+ * Multibyte-aware StringInfo support function.
+ */
+extern void appendStringInfoStringQuoted(StringInfo str,
+ const char *s, int maxlen);
+
+#endif /* STRINGINFO_MB_H */
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
new file mode 100644
index 0000000..6b2b434
--- /dev/null
+++ b/src/include/miscadmin.h
@@ -0,0 +1,489 @@
+/*-------------------------------------------------------------------------
+ *
+ * miscadmin.h
+ * This file contains general postgres administration and initialization
+ * stuff that used to be spread out between the following files:
+ * globals.h global variables
+ * pdir.h directory path crud
+ * pinit.h postgres initialization
+ * pmod.h processing modes
+ * Over time, this has also become the preferred place for widely known
+ * resource-limitation stuff, such as work_mem and check_stack_depth().
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/miscadmin.h
+ *
+ * NOTES
+ * some of the information in this file should be moved to other files.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef MISCADMIN_H
+#define MISCADMIN_H
+
+#include <signal.h>
+
+#include "datatype/timestamp.h" /* for TimestampTz */
+#include "pgtime.h" /* for pg_time_t */
+
+
+#define InvalidPid (-1)
+
+
+/*****************************************************************************
+ * System interrupt and critical section handling
+ *
+ * There are two types of interrupts that a running backend needs to accept
+ * without messing up its state: QueryCancel (SIGINT) and ProcDie (SIGTERM).
+ * In both cases, we need to be able to clean up the current transaction
+ * gracefully, so we can't respond to the interrupt instantaneously ---
+ * there's no guarantee that internal data structures would be self-consistent
+ * if the code is interrupted at an arbitrary instant. Instead, the signal
+ * handlers set flags that are checked periodically during execution.
+ *
+ * The CHECK_FOR_INTERRUPTS() macro is called at strategically located spots
+ * where it is normally safe to accept a cancel or die interrupt. In some
+ * cases, we invoke CHECK_FOR_INTERRUPTS() inside low-level subroutines that
+ * might sometimes be called in contexts that do *not* want to allow a cancel
+ * or die interrupt. The HOLD_INTERRUPTS() and RESUME_INTERRUPTS() macros
+ * allow code to ensure that no cancel or die interrupt will be accepted,
+ * even if CHECK_FOR_INTERRUPTS() gets called in a subroutine. The interrupt
+ * will be held off until CHECK_FOR_INTERRUPTS() is done outside any
+ * HOLD_INTERRUPTS() ... RESUME_INTERRUPTS() section.
+ *
+ * There is also a mechanism to prevent query cancel interrupts, while still
+ * allowing die interrupts: HOLD_CANCEL_INTERRUPTS() and
+ * RESUME_CANCEL_INTERRUPTS().
+ *
+ * Note that ProcessInterrupts() has also acquired a number of tasks that
+ * do not necessarily cause a query-cancel-or-die response. Hence, it's
+ * possible that it will just clear InterruptPending and return.
+ *
+ * INTERRUPTS_PENDING_CONDITION() can be checked to see whether an
+ * interrupt needs to be serviced, without trying to do so immediately.
+ * Some callers are also interested in INTERRUPTS_CAN_BE_PROCESSED(),
+ * which tells whether ProcessInterrupts is sure to clear the interrupt.
+ *
+ * Special mechanisms are used to let an interrupt be accepted when we are
+ * waiting for a lock or when we are waiting for command input (but, of
+ * course, only if the interrupt holdoff counter is zero). See the
+ * related code for details.
+ *
+ * A lost connection is handled similarly, although the loss of connection
+ * does not raise a signal, but is detected when we fail to write to the
+ * socket. If there was a signal for a broken connection, we could make use of
+ * it by setting ClientConnectionLost in the signal handler.
+ *
+ * A related, but conceptually distinct, mechanism is the "critical section"
+ * mechanism. A critical section not only holds off cancel/die interrupts,
+ * but causes any ereport(ERROR) or ereport(FATAL) to become ereport(PANIC)
+ * --- that is, a system-wide reset is forced. Needless to say, only really
+ * *critical* code should be marked as a critical section! Currently, this
+ * mechanism is only used for XLOG-related code.
+ *
+ *****************************************************************************/
+
+/* in globals.c */
+/* these are marked volatile because they are set by signal handlers: */
+extern PGDLLIMPORT volatile sig_atomic_t InterruptPending;
+extern PGDLLIMPORT volatile sig_atomic_t QueryCancelPending;
+extern PGDLLIMPORT volatile sig_atomic_t ProcDiePending;
+extern PGDLLIMPORT volatile sig_atomic_t IdleInTransactionSessionTimeoutPending;
+extern PGDLLIMPORT volatile sig_atomic_t ProcSignalBarrierPending;
+
+extern PGDLLIMPORT volatile sig_atomic_t ClientConnectionLost;
+
+/* these are marked volatile because they are examined by signal handlers: */
+extern PGDLLIMPORT volatile uint32 InterruptHoldoffCount;
+extern PGDLLIMPORT volatile uint32 QueryCancelHoldoffCount;
+extern PGDLLIMPORT volatile uint32 CritSectionCount;
+
+/* in tcop/postgres.c */
+extern void ProcessInterrupts(void);
+
+/* Test whether an interrupt is pending */
+#ifndef WIN32
+#define INTERRUPTS_PENDING_CONDITION() \
+ (unlikely(InterruptPending))
+#else
+#define INTERRUPTS_PENDING_CONDITION() \
+ (unlikely(UNBLOCKED_SIGNAL_QUEUE()) ? pgwin32_dispatch_queued_signals() : 0, \
+ unlikely(InterruptPending))
+#endif
+
+/* Service interrupt, if one is pending and it's safe to service it now */
+#define CHECK_FOR_INTERRUPTS() \
+do { \
+ if (INTERRUPTS_PENDING_CONDITION()) \
+ ProcessInterrupts(); \
+} while(0)
+
+/* Is ProcessInterrupts() guaranteed to clear InterruptPending? */
+#define INTERRUPTS_CAN_BE_PROCESSED() \
+ (InterruptHoldoffCount == 0 && CritSectionCount == 0 && \
+ QueryCancelHoldoffCount == 0)
+
+#define HOLD_INTERRUPTS() (InterruptHoldoffCount++)
+
+#define RESUME_INTERRUPTS() \
+do { \
+ Assert(InterruptHoldoffCount > 0); \
+ InterruptHoldoffCount--; \
+} while(0)
+
+#define HOLD_CANCEL_INTERRUPTS() (QueryCancelHoldoffCount++)
+
+#define RESUME_CANCEL_INTERRUPTS() \
+do { \
+ Assert(QueryCancelHoldoffCount > 0); \
+ QueryCancelHoldoffCount--; \
+} while(0)
+
+#define START_CRIT_SECTION() (CritSectionCount++)
+
+#define END_CRIT_SECTION() \
+do { \
+ Assert(CritSectionCount > 0); \
+ CritSectionCount--; \
+} while(0)
+
+
+/*****************************************************************************
+ * globals.h -- *
+ *****************************************************************************/
+
+/*
+ * from utils/init/globals.c
+ */
+extern PGDLLIMPORT pid_t PostmasterPid;
+extern PGDLLIMPORT bool IsPostmasterEnvironment;
+extern PGDLLIMPORT bool IsUnderPostmaster;
+extern PGDLLIMPORT bool IsBackgroundWorker;
+extern PGDLLIMPORT bool IsBinaryUpgrade;
+
+extern PGDLLIMPORT bool ExitOnAnyError;
+
+extern PGDLLIMPORT char *DataDir;
+extern PGDLLIMPORT int data_directory_mode;
+
+extern PGDLLIMPORT int NBuffers;
+extern PGDLLIMPORT int MaxBackends;
+extern PGDLLIMPORT int MaxConnections;
+extern PGDLLIMPORT int max_worker_processes;
+extern PGDLLIMPORT int max_parallel_workers;
+
+extern PGDLLIMPORT int MyProcPid;
+extern PGDLLIMPORT pg_time_t MyStartTime;
+extern PGDLLIMPORT TimestampTz MyStartTimestamp;
+extern PGDLLIMPORT struct Port *MyProcPort;
+extern PGDLLIMPORT struct Latch *MyLatch;
+extern int32 MyCancelKey;
+extern int MyPMChildSlot;
+
+extern char OutputFileName[];
+extern PGDLLIMPORT char my_exec_path[];
+extern char pkglib_path[];
+
+#ifdef EXEC_BACKEND
+extern char postgres_exec_path[];
+#endif
+
+/*
+ * done in storage/backendid.h for now.
+ *
+ * extern BackendId MyBackendId;
+ */
+extern PGDLLIMPORT Oid MyDatabaseId;
+
+extern PGDLLIMPORT Oid MyDatabaseTableSpace;
+
+/*
+ * Date/Time Configuration
+ *
+ * DateStyle defines the output formatting choice for date/time types:
+ * USE_POSTGRES_DATES specifies traditional Postgres format
+ * USE_ISO_DATES specifies ISO-compliant format
+ * USE_SQL_DATES specifies Oracle/Ingres-compliant format
+ * USE_GERMAN_DATES specifies German-style dd.mm/yyyy
+ *
+ * DateOrder defines the field order to be assumed when reading an
+ * ambiguous date (anything not in YYYY-MM-DD format, with a four-digit
+ * year field first, is taken to be ambiguous):
+ * DATEORDER_YMD specifies field order yy-mm-dd
+ * DATEORDER_DMY specifies field order dd-mm-yy ("European" convention)
+ * DATEORDER_MDY specifies field order mm-dd-yy ("US" convention)
+ *
+ * In the Postgres and SQL DateStyles, DateOrder also selects output field
+ * order: day comes before month in DMY style, else month comes before day.
+ *
+ * The user-visible "DateStyle" run-time parameter subsumes both of these.
+ */
+
+/* valid DateStyle values */
+#define USE_POSTGRES_DATES 0
+#define USE_ISO_DATES 1
+#define USE_SQL_DATES 2
+#define USE_GERMAN_DATES 3
+#define USE_XSD_DATES 4
+
+/* valid DateOrder values */
+#define DATEORDER_YMD 0
+#define DATEORDER_DMY 1
+#define DATEORDER_MDY 2
+
+extern PGDLLIMPORT int DateStyle;
+extern PGDLLIMPORT int DateOrder;
+
+/*
+ * IntervalStyles
+ * INTSTYLE_POSTGRES Like Postgres < 8.4 when DateStyle = 'iso'
+ * INTSTYLE_POSTGRES_VERBOSE Like Postgres < 8.4 when DateStyle != 'iso'
+ * INTSTYLE_SQL_STANDARD SQL standard interval literals
+ * INTSTYLE_ISO_8601 ISO-8601-basic formatted intervals
+ */
+#define INTSTYLE_POSTGRES 0
+#define INTSTYLE_POSTGRES_VERBOSE 1
+#define INTSTYLE_SQL_STANDARD 2
+#define INTSTYLE_ISO_8601 3
+
+extern PGDLLIMPORT int IntervalStyle;
+
+#define MAXTZLEN 10 /* max TZ name len, not counting tr. null */
+
+extern bool enableFsync;
+extern PGDLLIMPORT bool allowSystemTableMods;
+extern PGDLLIMPORT int work_mem;
+extern PGDLLIMPORT double hash_mem_multiplier;
+extern PGDLLIMPORT int maintenance_work_mem;
+extern PGDLLIMPORT int max_parallel_maintenance_workers;
+
+extern int VacuumCostPageHit;
+extern int VacuumCostPageMiss;
+extern int VacuumCostPageDirty;
+extern int VacuumCostLimit;
+extern double VacuumCostDelay;
+
+extern int64 VacuumPageHit;
+extern int64 VacuumPageMiss;
+extern int64 VacuumPageDirty;
+
+extern int VacuumCostBalance;
+extern bool VacuumCostActive;
+
+extern double vacuum_cleanup_index_scale_factor;
+
+
+/* in tcop/postgres.c */
+
+#if defined(__ia64__) || defined(__ia64)
+typedef struct
+{
+ char *stack_base_ptr;
+ char *register_stack_base_ptr;
+} pg_stack_base_t;
+#else
+typedef char *pg_stack_base_t;
+#endif
+
+extern pg_stack_base_t set_stack_base(void);
+extern void restore_stack_base(pg_stack_base_t base);
+extern void check_stack_depth(void);
+extern bool stack_is_too_deep(void);
+
+/* in tcop/utility.c */
+extern void PreventCommandIfReadOnly(const char *cmdname);
+extern void PreventCommandIfParallelMode(const char *cmdname);
+extern void PreventCommandDuringRecovery(const char *cmdname);
+
+/* in utils/misc/guc.c */
+extern int trace_recovery_messages;
+extern int trace_recovery(int trace_level);
+
+/*****************************************************************************
+ * pdir.h -- *
+ * POSTGRES directory path definitions. *
+ *****************************************************************************/
+
+/* flags to be OR'd to form sec_context */
+#define SECURITY_LOCAL_USERID_CHANGE 0x0001
+#define SECURITY_RESTRICTED_OPERATION 0x0002
+#define SECURITY_NOFORCE_RLS 0x0004
+
+extern char *DatabasePath;
+
+/* now in utils/init/miscinit.c */
+extern void InitPostmasterChild(void);
+extern void InitStandaloneProcess(const char *argv0);
+extern void SwitchToSharedLatch(void);
+extern void SwitchBackToLocalLatch(void);
+
+typedef enum BackendType
+{
+ B_INVALID = 0,
+ B_AUTOVAC_LAUNCHER,
+ B_AUTOVAC_WORKER,
+ B_BACKEND,
+ B_BG_WORKER,
+ B_BG_WRITER,
+ B_CHECKPOINTER,
+ B_STARTUP,
+ B_WAL_RECEIVER,
+ B_WAL_SENDER,
+ B_WAL_WRITER,
+ B_ARCHIVER,
+ B_STATS_COLLECTOR,
+ B_LOGGER,
+} BackendType;
+
+extern BackendType MyBackendType;
+
+extern const char *GetBackendTypeDesc(BackendType backendType);
+
+extern void SetDatabasePath(const char *path);
+extern void checkDataDir(void);
+extern void SetDataDir(const char *dir);
+extern void ChangeToDataDir(void);
+
+extern char *GetUserNameFromId(Oid roleid, bool noerr);
+extern Oid GetUserId(void);
+extern Oid GetOuterUserId(void);
+extern Oid GetSessionUserId(void);
+extern Oid GetAuthenticatedUserId(void);
+extern void GetUserIdAndSecContext(Oid *userid, int *sec_context);
+extern void SetUserIdAndSecContext(Oid userid, int sec_context);
+extern bool InLocalUserIdChange(void);
+extern bool InSecurityRestrictedOperation(void);
+extern bool InNoForceRLSOperation(void);
+extern void GetUserIdAndContext(Oid *userid, bool *sec_def_context);
+extern void SetUserIdAndContext(Oid userid, bool sec_def_context);
+extern void InitializeSessionUserId(const char *rolename, Oid useroid);
+extern void InitializeSessionUserIdStandalone(void);
+extern void SetSessionAuthorization(Oid userid, bool is_superuser);
+extern Oid GetCurrentRoleId(void);
+extern void SetCurrentRoleId(Oid roleid, bool is_superuser);
+
+/* in utils/misc/superuser.c */
+extern bool superuser(void); /* current user is superuser */
+extern bool superuser_arg(Oid roleid); /* given user is superuser */
+
+
+/*****************************************************************************
+ * pmod.h -- *
+ * POSTGRES processing mode definitions. *
+ *****************************************************************************/
+
+/*
+ * Description:
+ * There are three processing modes in POSTGRES. They are
+ * BootstrapProcessing or "bootstrap," InitProcessing or
+ * "initialization," and NormalProcessing or "normal."
+ *
+ * The first two processing modes are used during special times. When the
+ * system state indicates bootstrap processing, transactions are all given
+ * transaction id "one" and are consequently guaranteed to commit. This mode
+ * is used during the initial generation of template databases.
+ *
+ * Initialization mode: used while starting a backend, until all normal
+ * initialization is complete. Some code behaves differently when executed
+ * in this mode to enable system bootstrapping.
+ *
+ * If a POSTGRES backend process is in normal mode, then all code may be
+ * executed normally.
+ */
+
+typedef enum ProcessingMode
+{
+ BootstrapProcessing, /* bootstrap creation of template database */
+ InitProcessing, /* initializing system */
+ NormalProcessing /* normal processing */
+} ProcessingMode;
+
+extern ProcessingMode Mode;
+
+#define IsBootstrapProcessingMode() (Mode == BootstrapProcessing)
+#define IsInitProcessingMode() (Mode == InitProcessing)
+#define IsNormalProcessingMode() (Mode == NormalProcessing)
+
+#define GetProcessingMode() Mode
+
+#define SetProcessingMode(mode) \
+ do { \
+ AssertArg((mode) == BootstrapProcessing || \
+ (mode) == InitProcessing || \
+ (mode) == NormalProcessing); \
+ Mode = (mode); \
+ } while(0)
+
+
+/*
+ * Auxiliary-process type identifiers. These used to be in bootstrap.h
+ * but it seems saner to have them here, with the ProcessingMode stuff.
+ * The MyAuxProcType global is defined and set in bootstrap.c.
+ */
+
+typedef enum
+{
+ NotAnAuxProcess = -1,
+ CheckerProcess = 0,
+ BootstrapProcess,
+ StartupProcess,
+ BgWriterProcess,
+ CheckpointerProcess,
+ WalWriterProcess,
+ WalReceiverProcess,
+
+ NUM_AUXPROCTYPES /* Must be last! */
+} AuxProcType;
+
+extern AuxProcType MyAuxProcType;
+
+#define AmBootstrapProcess() (MyAuxProcType == BootstrapProcess)
+#define AmStartupProcess() (MyAuxProcType == StartupProcess)
+#define AmBackgroundWriterProcess() (MyAuxProcType == BgWriterProcess)
+#define AmCheckpointerProcess() (MyAuxProcType == CheckpointerProcess)
+#define AmWalWriterProcess() (MyAuxProcType == WalWriterProcess)
+#define AmWalReceiverProcess() (MyAuxProcType == WalReceiverProcess)
+
+
+/*****************************************************************************
+ * pinit.h -- *
+ * POSTGRES initialization and cleanup definitions. *
+ *****************************************************************************/
+
+/* in utils/init/postinit.c */
+extern void pg_split_opts(char **argv, int *argcp, const char *optstr);
+extern void InitializeMaxBackends(void);
+extern void InitPostgres(const char *in_dbname, Oid dboid, const char *username,
+ Oid useroid, char *out_dbname, bool override_allow_connections);
+extern void BaseInit(void);
+
+/* in utils/init/miscinit.c */
+extern bool IgnoreSystemIndexes;
+extern PGDLLIMPORT bool process_shared_preload_libraries_in_progress;
+extern char *session_preload_libraries_string;
+extern char *shared_preload_libraries_string;
+extern char *local_preload_libraries_string;
+
+extern void CreateDataDirLockFile(bool amPostmaster);
+extern void CreateSocketLockFile(const char *socketfile, bool amPostmaster,
+ const char *socketDir);
+extern void TouchSocketLockFiles(void);
+extern void AddToDataDirLockFile(int target_line, const char *str);
+extern bool RecheckDataDirLockFile(void);
+extern void ValidatePgVersion(const char *path);
+extern void process_shared_preload_libraries(void);
+extern void process_session_preload_libraries(void);
+extern void pg_bindtextdomain(const char *domain);
+extern bool has_rolreplication(Oid roleid);
+
+/* in access/transam/xlog.c */
+extern bool BackupInProgress(void);
+extern void CancelBackup(void);
+
+/* in executor/nodeHash.c */
+extern size_t get_hash_memory_limit(void);
+extern int get_hash_mem(void);
+
+#endif /* MISCADMIN_H */
diff --git a/src/include/nodes/bitmapset.h b/src/include/nodes/bitmapset.h
new file mode 100644
index 0000000..d113c27
--- /dev/null
+++ b/src/include/nodes/bitmapset.h
@@ -0,0 +1,122 @@
+/*-------------------------------------------------------------------------
+ *
+ * bitmapset.h
+ * PostgreSQL generic bitmap set package
+ *
+ * A bitmap set can represent any set of nonnegative integers, although
+ * it is mainly intended for sets where the maximum value is not large,
+ * say at most a few hundred. By convention, a NULL pointer is always
+ * accepted by all operations to represent the empty set. (But beware
+ * that this is not the only representation of the empty set. Use
+ * bms_is_empty() in preference to testing for NULL.)
+ *
+ *
+ * Copyright (c) 2003-2020, PostgreSQL Global Development Group
+ *
+ * src/include/nodes/bitmapset.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BITMAPSET_H
+#define BITMAPSET_H
+
+/*
+ * Forward decl to save including pg_list.h
+ */
+struct List;
+
+/*
+ * Data representation
+ *
+ * Larger bitmap word sizes generally give better performance, so long as
+ * they're not wider than the processor can handle efficiently. We use
+ * 64-bit words if pointers are that large, else 32-bit words.
+ */
+#if SIZEOF_VOID_P >= 8
+
+#define BITS_PER_BITMAPWORD 64
+typedef uint64 bitmapword; /* must be an unsigned type */
+typedef int64 signedbitmapword; /* must be the matching signed type */
+
+#else
+
+#define BITS_PER_BITMAPWORD 32
+typedef uint32 bitmapword; /* must be an unsigned type */
+typedef int32 signedbitmapword; /* must be the matching signed type */
+
+#endif
+
+typedef struct Bitmapset
+{
+ int nwords; /* number of words in array */
+ bitmapword words[FLEXIBLE_ARRAY_MEMBER]; /* really [nwords] */
+} Bitmapset;
+
+
+/* result of bms_subset_compare */
+typedef enum
+{
+ BMS_EQUAL, /* sets are equal */
+ BMS_SUBSET1, /* first set is a subset of the second */
+ BMS_SUBSET2, /* second set is a subset of the first */
+ BMS_DIFFERENT /* neither set is a subset of the other */
+} BMS_Comparison;
+
+/* result of bms_membership */
+typedef enum
+{
+ BMS_EMPTY_SET, /* 0 members */
+ BMS_SINGLETON, /* 1 member */
+ BMS_MULTIPLE /* >1 member */
+} BMS_Membership;
+
+
+/*
+ * function prototypes in nodes/bitmapset.c
+ */
+
+extern Bitmapset *bms_copy(const Bitmapset *a);
+extern bool bms_equal(const Bitmapset *a, const Bitmapset *b);
+extern int bms_compare(const Bitmapset *a, const Bitmapset *b);
+extern Bitmapset *bms_make_singleton(int x);
+extern void bms_free(Bitmapset *a);
+
+extern Bitmapset *bms_union(const Bitmapset *a, const Bitmapset *b);
+extern Bitmapset *bms_intersect(const Bitmapset *a, const Bitmapset *b);
+extern Bitmapset *bms_difference(const Bitmapset *a, const Bitmapset *b);
+extern bool bms_is_subset(const Bitmapset *a, const Bitmapset *b);
+extern BMS_Comparison bms_subset_compare(const Bitmapset *a, const Bitmapset *b);
+extern bool bms_is_member(int x, const Bitmapset *a);
+extern int bms_member_index(Bitmapset *a, int x);
+extern bool bms_overlap(const Bitmapset *a, const Bitmapset *b);
+extern bool bms_overlap_list(const Bitmapset *a, const struct List *b);
+extern bool bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b);
+extern int bms_singleton_member(const Bitmapset *a);
+extern bool bms_get_singleton_member(const Bitmapset *a, int *member);
+extern int bms_num_members(const Bitmapset *a);
+
+/* optimized tests when we don't need to know exact membership count: */
+extern BMS_Membership bms_membership(const Bitmapset *a);
+extern bool bms_is_empty(const Bitmapset *a);
+
+/* these routines recycle (modify or free) their non-const inputs: */
+
+extern Bitmapset *bms_add_member(Bitmapset *a, int x);
+extern Bitmapset *bms_del_member(Bitmapset *a, int x);
+extern Bitmapset *bms_add_members(Bitmapset *a, const Bitmapset *b);
+extern Bitmapset *bms_add_range(Bitmapset *a, int lower, int upper);
+extern Bitmapset *bms_int_members(Bitmapset *a, const Bitmapset *b);
+extern Bitmapset *bms_del_members(Bitmapset *a, const Bitmapset *b);
+extern Bitmapset *bms_join(Bitmapset *a, Bitmapset *b);
+
+/* support for iterating through the integer elements of a set: */
+extern int bms_first_member(Bitmapset *a);
+extern int bms_next_member(const Bitmapset *a, int prevbit);
+extern int bms_prev_member(const Bitmapset *a, int prevbit);
+
+/* support for hashtables using Bitmapsets as keys: */
+extern uint32 bms_hash_value(const Bitmapset *a);
+extern uint32 bitmap_hash(const void *key, Size keysize);
+extern int bitmap_match(const void *key1, const void *key2, Size keysize);
+
+#endif /* BITMAPSET_H */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
new file mode 100644
index 0000000..3c6fecd
--- /dev/null
+++ b/src/include/nodes/execnodes.h
@@ -0,0 +1,2523 @@
+/*-------------------------------------------------------------------------
+ *
+ * execnodes.h
+ * definitions for executor state nodes
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/execnodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXECNODES_H
+#define EXECNODES_H
+
+#include "access/tupconvert.h"
+#include "executor/instrument.h"
+#include "fmgr.h"
+#include "lib/pairingheap.h"
+#include "nodes/params.h"
+#include "nodes/plannodes.h"
+#include "nodes/tidbitmap.h"
+#include "partitioning/partdefs.h"
+#include "storage/condition_variable.h"
+#include "utils/hsearch.h"
+#include "utils/queryenvironment.h"
+#include "utils/reltrigger.h"
+#include "utils/sharedtuplestore.h"
+#include "utils/snapshot.h"
+#include "utils/sortsupport.h"
+#include "utils/tuplesort.h"
+#include "utils/tuplestore.h"
+
+struct PlanState; /* forward references in this file */
+struct PartitionRoutingInfo;
+struct ParallelHashJoinState;
+struct ExecRowMark;
+struct ExprState;
+struct ExprContext;
+struct RangeTblEntry; /* avoid including parsenodes.h here */
+struct ExprEvalStep; /* avoid including execExpr.h everywhere */
+struct CopyMultiInsertBuffer;
+
+
+/* ----------------
+ * ExprState node
+ *
+ * ExprState is the top-level node for expression evaluation.
+ * It contains instructions (in ->steps) to evaluate the expression.
+ * ----------------
+ */
+typedef Datum (*ExprStateEvalFunc) (struct ExprState *expression,
+ struct ExprContext *econtext,
+ bool *isNull);
+
+/* Bits in ExprState->flags (see also execExpr.h for private flag bits): */
+/* expression is for use with ExecQual() */
+#define EEO_FLAG_IS_QUAL (1 << 0)
+
+typedef struct ExprState
+{
+ NodeTag tag;
+
+ uint8 flags; /* bitmask of EEO_FLAG_* bits, see above */
+
+ /*
+ * Storage for result value of a scalar expression, or for individual
+ * column results within expressions built by ExecBuildProjectionInfo().
+ */
+#define FIELDNO_EXPRSTATE_RESNULL 2
+ bool resnull;
+#define FIELDNO_EXPRSTATE_RESVALUE 3
+ Datum resvalue;
+
+ /*
+ * If projecting a tuple result, this slot holds the result; else NULL.
+ */
+#define FIELDNO_EXPRSTATE_RESULTSLOT 4
+ TupleTableSlot *resultslot;
+
+ /*
+ * Instructions to compute expression's return value.
+ */
+ struct ExprEvalStep *steps;
+
+ /*
+ * Function that actually evaluates the expression. This can be set to
+ * different values depending on the complexity of the expression.
+ */
+ ExprStateEvalFunc evalfunc;
+
+ /* original expression tree, for debugging only */
+ Expr *expr;
+
+ /* private state for an evalfunc */
+ void *evalfunc_private;
+
+ /*
+ * XXX: following fields only needed during "compilation" (ExecInitExpr);
+ * could be thrown away afterwards.
+ */
+
+ int steps_len; /* number of steps currently */
+ int steps_alloc; /* allocated length of steps array */
+
+#define FIELDNO_EXPRSTATE_PARENT 11
+ struct PlanState *parent; /* parent PlanState node, if any */
+ ParamListInfo ext_params; /* for compiling PARAM_EXTERN nodes */
+
+ Datum *innermost_caseval;
+ bool *innermost_casenull;
+
+ Datum *innermost_domainval;
+ bool *innermost_domainnull;
+} ExprState;
+
+
+/* ----------------
+ * IndexInfo information
+ *
+ * this struct holds the information needed to construct new index
+ * entries for a particular index. Used for both index_build and
+ * retail creation of index entries.
+ *
+ * NumIndexAttrs total number of columns in this index
+ * NumIndexKeyAttrs number of key columns in index
+ * IndexAttrNumbers underlying-rel attribute numbers used as keys
+ * (zeroes indicate expressions). It also contains
+ * info about included columns.
+ * Expressions expr trees for expression entries, or NIL if none
+ * ExpressionsState exec state for expressions, or NIL if none
+ * Predicate partial-index predicate, or NIL if none
+ * PredicateState exec state for predicate, or NIL if none
+ * ExclusionOps Per-column exclusion operators, or NULL if none
+ * ExclusionProcs Underlying function OIDs for ExclusionOps
+ * ExclusionStrats Opclass strategy numbers for ExclusionOps
+ * UniqueOps These are like Exclusion*, but for unique indexes
+ * UniqueProcs
+ * UniqueStrats
+ * Unique is it a unique index?
+ * OpclassOptions opclass-specific options, or NULL if none
+ * ReadyForInserts is it valid for inserts?
+ * Concurrent are we doing a concurrent index build?
+ * BrokenHotChain did we detect any broken HOT chains?
+ * ParallelWorkers # of workers requested (excludes leader)
+ * Am Oid of index AM
+ * AmCache private cache area for index AM
+ * Context memory context holding this IndexInfo
+ *
+ * ii_Concurrent, ii_BrokenHotChain, and ii_ParallelWorkers are used only
+ * during index build; they're conventionally zeroed otherwise.
+ * ----------------
+ */
+typedef struct IndexInfo
+{
+ NodeTag type;
+ int ii_NumIndexAttrs; /* total number of columns in index */
+ int ii_NumIndexKeyAttrs; /* number of key columns in index */
+ AttrNumber ii_IndexAttrNumbers[INDEX_MAX_KEYS];
+ List *ii_Expressions; /* list of Expr */
+ List *ii_ExpressionsState; /* list of ExprState */
+ List *ii_Predicate; /* list of Expr */
+ ExprState *ii_PredicateState;
+ Oid *ii_ExclusionOps; /* array with one entry per column */
+ Oid *ii_ExclusionProcs; /* array with one entry per column */
+ uint16 *ii_ExclusionStrats; /* array with one entry per column */
+ Oid *ii_UniqueOps; /* array with one entry per column */
+ Oid *ii_UniqueProcs; /* array with one entry per column */
+ uint16 *ii_UniqueStrats; /* array with one entry per column */
+ Datum *ii_OpclassOptions; /* array with one entry per column */
+ bool ii_Unique;
+ bool ii_ReadyForInserts;
+ bool ii_Concurrent;
+ bool ii_BrokenHotChain;
+ int ii_ParallelWorkers;
+ Oid ii_Am;
+ void *ii_AmCache;
+ MemoryContext ii_Context;
+} IndexInfo;
+
+/* ----------------
+ * ExprContext_CB
+ *
+ * List of callbacks to be called at ExprContext shutdown.
+ * ----------------
+ */
+typedef void (*ExprContextCallbackFunction) (Datum arg);
+
+typedef struct ExprContext_CB
+{
+ struct ExprContext_CB *next;
+ ExprContextCallbackFunction function;
+ Datum arg;
+} ExprContext_CB;
+
+/* ----------------
+ * ExprContext
+ *
+ * This class holds the "current context" information
+ * needed to evaluate expressions for doing tuple qualifications
+ * and tuple projections. For example, if an expression refers
+ * to an attribute in the current inner tuple then we need to know
+ * what the current inner tuple is and so we look at the expression
+ * context.
+ *
+ * There are two memory contexts associated with an ExprContext:
+ * * ecxt_per_query_memory is a query-lifespan context, typically the same
+ * context the ExprContext node itself is allocated in. This context
+ * can be used for purposes such as storing function call cache info.
+ * * ecxt_per_tuple_memory is a short-term context for expression results.
+ * As the name suggests, it will typically be reset once per tuple,
+ * before we begin to evaluate expressions for that tuple. Each
+ * ExprContext normally has its very own per-tuple memory context.
+ *
+ * CurrentMemoryContext should be set to ecxt_per_tuple_memory before
+ * calling ExecEvalExpr() --- see ExecEvalExprSwitchContext().
+ * ----------------
+ */
+typedef struct ExprContext
+{
+ NodeTag type;
+
+ /* Tuples that Var nodes in expression may refer to */
+#define FIELDNO_EXPRCONTEXT_SCANTUPLE 1
+ TupleTableSlot *ecxt_scantuple;
+#define FIELDNO_EXPRCONTEXT_INNERTUPLE 2
+ TupleTableSlot *ecxt_innertuple;
+#define FIELDNO_EXPRCONTEXT_OUTERTUPLE 3
+ TupleTableSlot *ecxt_outertuple;
+
+ /* Memory contexts for expression evaluation --- see notes above */
+ MemoryContext ecxt_per_query_memory;
+ MemoryContext ecxt_per_tuple_memory;
+
+ /* Values to substitute for Param nodes in expression */
+ ParamExecData *ecxt_param_exec_vals; /* for PARAM_EXEC params */
+ ParamListInfo ecxt_param_list_info; /* for other param types */
+
+ /*
+ * Values to substitute for Aggref nodes in the expressions of an Agg
+ * node, or for WindowFunc nodes within a WindowAgg node.
+ */
+#define FIELDNO_EXPRCONTEXT_AGGVALUES 8
+ Datum *ecxt_aggvalues; /* precomputed values for aggs/windowfuncs */
+#define FIELDNO_EXPRCONTEXT_AGGNULLS 9
+ bool *ecxt_aggnulls; /* null flags for aggs/windowfuncs */
+
+ /* Value to substitute for CaseTestExpr nodes in expression */
+#define FIELDNO_EXPRCONTEXT_CASEDATUM 10
+ Datum caseValue_datum;
+#define FIELDNO_EXPRCONTEXT_CASENULL 11
+ bool caseValue_isNull;
+
+ /* Value to substitute for CoerceToDomainValue nodes in expression */
+#define FIELDNO_EXPRCONTEXT_DOMAINDATUM 12
+ Datum domainValue_datum;
+#define FIELDNO_EXPRCONTEXT_DOMAINNULL 13
+ bool domainValue_isNull;
+
+ /* Link to containing EState (NULL if a standalone ExprContext) */
+ struct EState *ecxt_estate;
+
+ /* Functions to call back when ExprContext is shut down or rescanned */
+ ExprContext_CB *ecxt_callbacks;
+} ExprContext;
+
+/*
+ * Set-result status used when evaluating functions potentially returning a
+ * set.
+ */
+typedef enum
+{
+ ExprSingleResult, /* expression does not return a set */
+ ExprMultipleResult, /* this result is an element of a set */
+ ExprEndResult /* there are no more elements in the set */
+} ExprDoneCond;
+
+/*
+ * Return modes for functions returning sets. Note values must be chosen
+ * as separate bits so that a bitmask can be formed to indicate supported
+ * modes. SFRM_Materialize_Random and SFRM_Materialize_Preferred are
+ * auxiliary flags about SFRM_Materialize mode, rather than separate modes.
+ */
+typedef enum
+{
+ SFRM_ValuePerCall = 0x01, /* one value returned per call */
+ SFRM_Materialize = 0x02, /* result set instantiated in Tuplestore */
+ SFRM_Materialize_Random = 0x04, /* Tuplestore needs randomAccess */
+ SFRM_Materialize_Preferred = 0x08 /* caller prefers Tuplestore */
+} SetFunctionReturnMode;
+
+/*
+ * When calling a function that might return a set (multiple rows),
+ * a node of this type is passed as fcinfo->resultinfo to allow
+ * return status to be passed back. A function returning set should
+ * raise an error if no such resultinfo is provided.
+ */
+typedef struct ReturnSetInfo
+{
+ NodeTag type;
+ /* values set by caller: */
+ ExprContext *econtext; /* context function is being called in */
+ TupleDesc expectedDesc; /* tuple descriptor expected by caller */
+ int allowedModes; /* bitmask: return modes caller can handle */
+ /* result status from function (but pre-initialized by caller): */
+ SetFunctionReturnMode returnMode; /* actual return mode */
+ ExprDoneCond isDone; /* status for ValuePerCall mode */
+ /* fields filled by function in Materialize return mode: */
+ Tuplestorestate *setResult; /* holds the complete returned tuple set */
+ TupleDesc setDesc; /* actual descriptor for returned tuples */
+} ReturnSetInfo;
+
+/* ----------------
+ * ProjectionInfo node information
+ *
+ * This is all the information needed to perform projections ---
+ * that is, form new tuples by evaluation of targetlist expressions.
+ * Nodes which need to do projections create one of these.
+ *
+ * The target tuple slot is kept in ProjectionInfo->pi_state.resultslot.
+ * ExecProject() evaluates the tlist, forms a tuple, and stores it
+ * in the given slot. Note that the result will be a "virtual" tuple
+ * unless ExecMaterializeSlot() is then called to force it to be
+ * converted to a physical tuple. The slot must have a tupledesc
+ * that matches the output of the tlist!
+ * ----------------
+ */
+typedef struct ProjectionInfo
+{
+ NodeTag type;
+ /* instructions to evaluate projection */
+ ExprState pi_state;
+ /* expression context in which to evaluate expression */
+ ExprContext *pi_exprContext;
+} ProjectionInfo;
+
+/* ----------------
+ * JunkFilter
+ *
+ * This class is used to store information regarding junk attributes.
+ * A junk attribute is an attribute in a tuple that is needed only for
+ * storing intermediate information in the executor, and does not belong
+ * in emitted tuples. For example, when we do an UPDATE query,
+ * the planner adds a "junk" entry to the targetlist so that the tuples
+ * returned to ExecutePlan() contain an extra attribute: the ctid of
+ * the tuple to be updated. This is needed to do the update, but we
+ * don't want the ctid to be part of the stored new tuple! So, we
+ * apply a "junk filter" to remove the junk attributes and form the
+ * real output tuple. The junkfilter code also provides routines to
+ * extract the values of the junk attribute(s) from the input tuple.
+ *
+ * targetList: the original target list (including junk attributes).
+ * cleanTupType: the tuple descriptor for the "clean" tuple (with
+ * junk attributes removed).
+ * cleanMap: A map with the correspondence between the non-junk
+ * attribute numbers of the "original" tuple and the
+ * attribute numbers of the "clean" tuple.
+ * resultSlot: tuple slot used to hold cleaned tuple.
+ * junkAttNo: not used by junkfilter code. Can be used by caller
+ * to remember the attno of a specific junk attribute
+ * (nodeModifyTable.c keeps the "ctid" or "wholerow"
+ * attno here).
+ * ----------------
+ */
+typedef struct JunkFilter
+{
+ NodeTag type;
+ List *jf_targetList;
+ TupleDesc jf_cleanTupType;
+ AttrNumber *jf_cleanMap;
+ TupleTableSlot *jf_resultSlot;
+ AttrNumber jf_junkAttNo;
+} JunkFilter;
+
+/*
+ * OnConflictSetState
+ *
+ * Executor state of an ON CONFLICT DO UPDATE operation.
+ */
+typedef struct OnConflictSetState
+{
+ NodeTag type;
+
+ TupleTableSlot *oc_Existing; /* slot to store existing target tuple in */
+ TupleTableSlot *oc_ProjSlot; /* CONFLICT ... SET ... projection target */
+ ProjectionInfo *oc_ProjInfo; /* for ON CONFLICT DO UPDATE SET */
+ ExprState *oc_WhereClause; /* state for the WHERE clause */
+} OnConflictSetState;
+
+/*
+ * ResultRelInfo
+ *
+ * Whenever we update an existing relation, we have to update indexes on the
+ * relation, and perhaps also fire triggers. ResultRelInfo holds all the
+ * information needed about a result relation, including indexes.
+ *
+ * Normally, a ResultRelInfo refers to a table that is in the query's range
+ * table; then ri_RangeTableIndex is the RT index and ri_RelationDesc is
+ * just a copy of the relevant es_relations[] entry. However, in some
+ * situations we create ResultRelInfos for relations that are not in the
+ * range table, namely for targets of tuple routing in a partitioned table,
+ * and when firing triggers in tables other than the target tables (See
+ * ExecGetTriggerResultRel). In these situations, ri_RangeTableIndex is 0
+ * and ri_RelationDesc is a separately-opened relcache pointer that needs to
+ * be separately closed.
+ */
+typedef struct ResultRelInfo
+{
+ NodeTag type;
+
+ /* result relation's range table index, or 0 if not in range table */
+ Index ri_RangeTableIndex;
+
+ /* relation descriptor for result relation */
+ Relation ri_RelationDesc;
+
+ /* # of indices existing on result relation */
+ int ri_NumIndices;
+
+ /* array of relation descriptors for indices */
+ RelationPtr ri_IndexRelationDescs;
+
+ /* array of key/attr info for indices */
+ IndexInfo **ri_IndexRelationInfo;
+
+ /* triggers to be fired, if any */
+ TriggerDesc *ri_TrigDesc;
+
+ /* cached lookup info for trigger functions */
+ FmgrInfo *ri_TrigFunctions;
+
+ /* array of trigger WHEN expr states */
+ ExprState **ri_TrigWhenExprs;
+
+ /* optional runtime measurements for triggers */
+ Instrumentation *ri_TrigInstrument;
+
+ /* On-demand created slots for triggers / returning processing */
+ TupleTableSlot *ri_ReturningSlot; /* for trigger output tuples */
+ TupleTableSlot *ri_TrigOldSlot; /* for a trigger's old tuple */
+ TupleTableSlot *ri_TrigNewSlot; /* for a trigger's new tuple */
+
+ /* FDW callback functions, if foreign table */
+ struct FdwRoutine *ri_FdwRoutine;
+
+ /* available to save private state of FDW */
+ void *ri_FdwState;
+
+ /* true when modifying foreign table directly */
+ bool ri_usesFdwDirectModify;
+
+ /* list of WithCheckOption's to be checked */
+ List *ri_WithCheckOptions;
+
+ /* list of WithCheckOption expr states */
+ List *ri_WithCheckOptionExprs;
+
+ /* array of constraint-checking expr states */
+ ExprState **ri_ConstraintExprs;
+
+ /* array of stored generated columns expr states */
+ ExprState **ri_GeneratedExprs;
+
+ /* number of stored generated columns we need to compute */
+ int ri_NumGeneratedNeeded;
+
+ /* for removing junk attributes from tuples */
+ JunkFilter *ri_junkFilter;
+
+ /* list of RETURNING expressions */
+ List *ri_returningList;
+
+ /* for computing a RETURNING list */
+ ProjectionInfo *ri_projectReturning;
+
+ /* list of arbiter indexes to use to check conflicts */
+ List *ri_onConflictArbiterIndexes;
+
+ /* ON CONFLICT evaluation state */
+ OnConflictSetState *ri_onConflict;
+
+ /* partition check expression */
+ List *ri_PartitionCheck;
+
+ /* partition check expression state */
+ ExprState *ri_PartitionCheckExpr;
+
+ /*
+ * RootResultRelInfo gives the target relation mentioned in the query, if
+ * it's a partitioned table. It is not set if the target relation
+ * mentioned in the query is an inherited table, nor when tuple routing is
+ * not needed.
+ */
+ struct ResultRelInfo *ri_RootResultRelInfo;
+
+ /* Additional information specific to partition tuple routing */
+ struct PartitionRoutingInfo *ri_PartitionInfo;
+
+ /* For use by copy.c when performing multi-inserts */
+ struct CopyMultiInsertBuffer *ri_CopyMultiInsertBuffer;
+} ResultRelInfo;
+
+/* ----------------
+ * EState information
+ *
+ * Master working state for an Executor invocation
+ * ----------------
+ */
+typedef struct EState
+{
+ NodeTag type;
+
+ /* Basic state for all query types: */
+ ScanDirection es_direction; /* current scan direction */
+ Snapshot es_snapshot; /* time qual to use */
+ Snapshot es_crosscheck_snapshot; /* crosscheck time qual for RI */
+ List *es_range_table; /* List of RangeTblEntry */
+ Index es_range_table_size; /* size of the range table arrays */
+ Relation *es_relations; /* Array of per-range-table-entry Relation
+ * pointers, or NULL if not yet opened */
+ struct ExecRowMark **es_rowmarks; /* Array of per-range-table-entry
+ * ExecRowMarks, or NULL if none */
+ PlannedStmt *es_plannedstmt; /* link to top of plan tree */
+ const char *es_sourceText; /* Source text from QueryDesc */
+
+ JunkFilter *es_junkFilter; /* top-level junk filter, if any */
+
+ /* If query can insert/delete tuples, the command ID to mark them with */
+ CommandId es_output_cid;
+
+ /* Info about target table(s) for insert/update/delete queries: */
+ ResultRelInfo *es_result_relations; /* array of ResultRelInfos */
+ int es_num_result_relations; /* length of array */
+ ResultRelInfo *es_result_relation_info; /* currently active array elt */
+
+ /*
+ * Info about the partition root table(s) for insert/update/delete queries
+ * targeting partitioned tables. Only leaf partitions are mentioned in
+ * es_result_relations, but we need access to the roots for firing
+ * triggers and for runtime tuple routing.
+ */
+ ResultRelInfo *es_root_result_relations; /* array of ResultRelInfos */
+ int es_num_root_result_relations; /* length of the array */
+ PartitionDirectory es_partition_directory; /* for PartitionDesc lookup */
+
+ /*
+ * The following list contains ResultRelInfos created by the tuple routing
+ * code for partitions that don't already have one.
+ */
+ List *es_tuple_routing_result_relations;
+
+ /* Stuff used for firing triggers: */
+ List *es_trig_target_relations; /* trigger-only ResultRelInfos */
+
+ /* Parameter info: */
+ ParamListInfo es_param_list_info; /* values of external params */
+ ParamExecData *es_param_exec_vals; /* values of internal params */
+
+ QueryEnvironment *es_queryEnv; /* query environment */
+
+ /* Other working state: */
+ MemoryContext es_query_cxt; /* per-query context in which EState lives */
+
+ List *es_tupleTable; /* List of TupleTableSlots */
+
+ uint64 es_processed; /* # of tuples processed */
+
+ int es_top_eflags; /* eflags passed to ExecutorStart */
+ int es_instrument; /* OR of InstrumentOption flags */
+ bool es_finished; /* true when ExecutorFinish is done */
+
+ List *es_exprcontexts; /* List of ExprContexts within EState */
+
+ List *es_subplanstates; /* List of PlanState for SubPlans */
+
+ List *es_auxmodifytables; /* List of secondary ModifyTableStates */
+
+ /*
+ * this ExprContext is for per-output-tuple operations, such as constraint
+ * checks and index-value computations. It will be reset for each output
+ * tuple. Note that it will be created only if needed.
+ */
+ ExprContext *es_per_tuple_exprcontext;
+
+ /*
+ * If not NULL, this is an EPQState's EState. This is a field in EState
+ * both to allow EvalPlanQual aware executor nodes to detect that they
+ * need to perform EPQ related work, and to provide necessary information
+ * to do so.
+ */
+ struct EPQState *es_epq_active;
+
+ bool es_use_parallel_mode; /* can we use parallel workers? */
+
+ /* The per-query shared memory area to use for parallel execution. */
+ struct dsa_area *es_query_dsa;
+
+ /*
+ * JIT information. es_jit_flags indicates whether JIT should be performed
+ * and with which options. es_jit is created on-demand when JITing is
+ * performed.
+ *
+ * es_jit_worker_instr is the combined, on demand allocated,
+ * instrumentation from all workers. The leader's instrumentation is kept
+ * separate, and is combined on demand by ExplainPrintJITSummary().
+ */
+ int es_jit_flags;
+ struct JitContext *es_jit;
+ struct JitInstrumentation *es_jit_worker_instr;
+} EState;
+
+
+/*
+ * ExecRowMark -
+ * runtime representation of FOR [KEY] UPDATE/SHARE clauses
+ *
+ * When doing UPDATE, DELETE, or SELECT FOR [KEY] UPDATE/SHARE, we will have an
+ * ExecRowMark for each non-target relation in the query (except inheritance
+ * parent RTEs, which can be ignored at runtime). Virtual relations such as
+ * subqueries-in-FROM will have an ExecRowMark with relation == NULL. See
+ * PlanRowMark for details about most of the fields. In addition to fields
+ * directly derived from PlanRowMark, we store an activity flag (to denote
+ * inactive children of inheritance trees), curCtid, which is used by the
+ * WHERE CURRENT OF code, and ermExtra, which is available for use by the plan
+ * node that sources the relation (e.g., for a foreign table the FDW can use
+ * ermExtra to hold information).
+ *
+ * EState->es_rowmarks is an array of these structs, indexed by RT index,
+ * with NULLs for irrelevant RT indexes. es_rowmarks itself is NULL if
+ * there are no rowmarks.
+ */
+typedef struct ExecRowMark
+{
+ Relation relation; /* opened and suitably locked relation */
+ Oid relid; /* its OID (or InvalidOid, if subquery) */
+ Index rti; /* its range table index */
+ Index prti; /* parent range table index, if child */
+ Index rowmarkId; /* unique identifier for resjunk columns */
+ RowMarkType markType; /* see enum in nodes/plannodes.h */
+ LockClauseStrength strength; /* LockingClause's strength, or LCS_NONE */
+ LockWaitPolicy waitPolicy; /* NOWAIT and SKIP LOCKED */
+ bool ermActive; /* is this mark relevant for current tuple? */
+ ItemPointerData curCtid; /* ctid of currently locked tuple, if any */
+ void *ermExtra; /* available for use by relation source node */
+} ExecRowMark;
+
+/*
+ * ExecAuxRowMark -
+ * additional runtime representation of FOR [KEY] UPDATE/SHARE clauses
+ *
+ * Each LockRows and ModifyTable node keeps a list of the rowmarks it needs to
+ * deal with. In addition to a pointer to the related entry in es_rowmarks,
+ * this struct carries the column number(s) of the resjunk columns associated
+ * with the rowmark (see comments for PlanRowMark for more detail). In the
+ * case of ModifyTable, there has to be a separate ExecAuxRowMark list for
+ * each child plan, because the resjunk columns could be at different physical
+ * column positions in different subplans.
+ */
+typedef struct ExecAuxRowMark
+{
+ ExecRowMark *rowmark; /* related entry in es_rowmarks */
+ AttrNumber ctidAttNo; /* resno of ctid junk attribute, if any */
+ AttrNumber toidAttNo; /* resno of tableoid junk attribute, if any */
+ AttrNumber wholeAttNo; /* resno of whole-row junk attribute, if any */
+} ExecAuxRowMark;
+
+
+/* ----------------------------------------------------------------
+ * Tuple Hash Tables
+ *
+ * All-in-memory tuple hash tables are used for a number of purposes.
+ *
+ * Note: tab_hash_funcs are for the key datatype(s) stored in the table,
+ * and tab_eq_funcs are non-cross-type equality operators for those types.
+ * Normally these are the only functions used, but FindTupleHashEntry()
+ * supports searching a hashtable using cross-data-type hashing. For that,
+ * the caller must supply hash functions for the LHS datatype as well as
+ * the cross-type equality operators to use. in_hash_funcs and cur_eq_func
+ * are set to point to the caller's function arrays while doing such a search.
+ * During LookupTupleHashEntry(), they point to tab_hash_funcs and
+ * tab_eq_func respectively.
+ * ----------------------------------------------------------------
+ */
+typedef struct TupleHashEntryData *TupleHashEntry;
+typedef struct TupleHashTableData *TupleHashTable;
+
+typedef struct TupleHashEntryData
+{
+ MinimalTuple firstTuple; /* copy of first tuple in this group */
+ void *additional; /* user data */
+ uint32 status; /* hash status */
+ uint32 hash; /* hash value (cached) */
+} TupleHashEntryData;
+
+/* define parameters necessary to generate the tuple hash table interface */
+#define SH_PREFIX tuplehash
+#define SH_ELEMENT_TYPE TupleHashEntryData
+#define SH_KEY_TYPE MinimalTuple
+#define SH_SCOPE extern
+#define SH_DECLARE
+#include "lib/simplehash.h"
+
+typedef struct TupleHashTableData
+{
+ tuplehash_hash *hashtab; /* underlying hash table */
+ int numCols; /* number of columns in lookup key */
+ AttrNumber *keyColIdx; /* attr numbers of key columns */
+ FmgrInfo *tab_hash_funcs; /* hash functions for table datatype(s) */
+ ExprState *tab_eq_func; /* comparator for table datatype(s) */
+ Oid *tab_collations; /* collations for hash and comparison */
+ MemoryContext tablecxt; /* memory context containing table */
+ MemoryContext tempcxt; /* context for function evaluations */
+ Size entrysize; /* actual size to make each hash entry */
+ TupleTableSlot *tableslot; /* slot for referencing table entries */
+ /* The following fields are set transiently for each table search: */
+ TupleTableSlot *inputslot; /* current input tuple's slot */
+ FmgrInfo *in_hash_funcs; /* hash functions for input datatype(s) */
+ ExprState *cur_eq_func; /* comparator for input vs. table */
+ uint32 hash_iv; /* hash-function IV */
+ ExprContext *exprcontext; /* expression context */
+} TupleHashTableData;
+
+typedef tuplehash_iterator TupleHashIterator;
+
+/*
+ * Use InitTupleHashIterator/TermTupleHashIterator for a read/write scan.
+ * Use ResetTupleHashIterator if the table can be frozen (in this case no
+ * explicit scan termination is needed).
+ */
+#define InitTupleHashIterator(htable, iter) \
+ tuplehash_start_iterate(htable->hashtab, iter)
+#define TermTupleHashIterator(iter) \
+ ((void) 0)
+#define ResetTupleHashIterator(htable, iter) \
+ InitTupleHashIterator(htable, iter)
+#define ScanTupleHashTable(htable, iter) \
+ tuplehash_iterate(htable->hashtab, iter)
+
+
+/* ----------------------------------------------------------------
+ * Expression State Nodes
+ *
+ * Formerly, there was a separate executor expression state node corresponding
+ * to each node in a planned expression tree. That's no longer the case; for
+ * common expression node types, all the execution info is embedded into
+ * step(s) in a single ExprState node. But we still have a few executor state
+ * node types for selected expression node types, mostly those in which info
+ * has to be shared with other parts of the execution state tree.
+ * ----------------------------------------------------------------
+ */
+
+/* ----------------
+ * AggrefExprState node
+ * ----------------
+ */
+typedef struct AggrefExprState
+{
+ NodeTag type;
+ Aggref *aggref; /* expression plan node */
+ int aggno; /* ID number for agg within its plan node */
+} AggrefExprState;
+
+/* ----------------
+ * WindowFuncExprState node
+ * ----------------
+ */
+typedef struct WindowFuncExprState
+{
+ NodeTag type;
+ WindowFunc *wfunc; /* expression plan node */
+ List *args; /* ExprStates for argument expressions */
+ ExprState *aggfilter; /* FILTER expression */
+ int wfuncno; /* ID number for wfunc within its plan node */
+} WindowFuncExprState;
+
+
+/* ----------------
+ * SetExprState node
+ *
+ * State for evaluating a potentially set-returning expression (like FuncExpr
+ * or OpExpr). In some cases, like some of the expressions in ROWS FROM(...)
+ * the expression might not be a SRF, but nonetheless it uses the same
+ * machinery as SRFs; it will be treated as a SRF returning a single row.
+ * ----------------
+ */
+typedef struct SetExprState
+{
+ NodeTag type;
+ Expr *expr; /* expression plan node */
+ List *args; /* ExprStates for argument expressions */
+
+ /*
+ * In ROWS FROM, functions can be inlined, removing the FuncExpr normally
+ * inside. In such a case this is the compiled expression (which cannot
+ * return a set), which'll be evaluated using regular ExecEvalExpr().
+ */
+ ExprState *elidedFuncState;
+
+ /*
+ * Function manager's lookup info for the target function. If func.fn_oid
+ * is InvalidOid, we haven't initialized it yet (nor any of the following
+ * fields, except funcReturnsSet).
+ */
+ FmgrInfo func;
+
+ /*
+ * For a set-returning function (SRF) that returns a tuplestore, we keep
+ * the tuplestore here and dole out the result rows one at a time. The
+ * slot holds the row currently being returned.
+ */
+ Tuplestorestate *funcResultStore;
+ TupleTableSlot *funcResultSlot;
+
+ /*
+ * In some cases we need to compute a tuple descriptor for the function's
+ * output. If so, it's stored here.
+ */
+ TupleDesc funcResultDesc;
+ bool funcReturnsTuple; /* valid when funcResultDesc isn't NULL */
+
+ /*
+ * Remember whether the function is declared to return a set. This is set
+ * by ExecInitExpr, and is valid even before the FmgrInfo is set up.
+ */
+ bool funcReturnsSet;
+
+ /*
+ * setArgsValid is true when we are evaluating a set-returning function
+ * that uses value-per-call mode and we are in the middle of a call
+ * series; we want to pass the same argument values to the function again
+ * (and again, until it returns ExprEndResult). This indicates that
+ * fcinfo_data already contains valid argument data.
+ */
+ bool setArgsValid;
+
+ /*
+ * Flag to remember whether we have registered a shutdown callback for
+ * this SetExprState. We do so only if funcResultStore or setArgsValid
+ * has been set at least once (since all the callback is for is to release
+ * the tuplestore or clear setArgsValid).
+ */
+ bool shutdown_reg; /* a shutdown callback is registered */
+
+ /*
+ * Call parameter structure for the function. This has been initialized
+ * (by InitFunctionCallInfoData) if func.fn_oid is valid. It also saves
+ * argument values between calls, when setArgsValid is true.
+ */
+ FunctionCallInfo fcinfo;
+} SetExprState;
+
+/* ----------------
+ * SubPlanState node
+ * ----------------
+ */
+typedef struct SubPlanState
+{
+ NodeTag type;
+ SubPlan *subplan; /* expression plan node */
+ struct PlanState *planstate; /* subselect plan's state tree */
+ struct PlanState *parent; /* parent plan node's state tree */
+ ExprState *testexpr; /* state of combining expression */
+ List *args; /* states of argument expression(s) */
+ HeapTuple curTuple; /* copy of most recent tuple from subplan */
+ Datum curArray; /* most recent array from ARRAY() subplan */
+ /* these are used when hashing the subselect's output: */
+ TupleDesc descRight; /* subselect desc after projection */
+ ProjectionInfo *projLeft; /* for projecting lefthand exprs */
+ ProjectionInfo *projRight; /* for projecting subselect output */
+ TupleHashTable hashtable; /* hash table for no-nulls subselect rows */
+ TupleHashTable hashnulls; /* hash table for rows with null(s) */
+ bool havehashrows; /* true if hashtable is not empty */
+ bool havenullrows; /* true if hashnulls is not empty */
+ MemoryContext hashtablecxt; /* memory context containing hash tables */
+ MemoryContext hashtempcxt; /* temp memory context for hash tables */
+ ExprContext *innerecontext; /* econtext for computing inner tuples */
+ int numCols; /* number of columns being hashed */
+ /* each of the remaining fields is an array of length numCols: */
+ AttrNumber *keyColIdx; /* control data for hash tables */
+ Oid *tab_eq_funcoids; /* equality func oids for table
+ * datatype(s) */
+ Oid *tab_collations; /* collations for hash and comparison */
+ FmgrInfo *tab_hash_funcs; /* hash functions for table datatype(s) */
+ FmgrInfo *tab_eq_funcs; /* equality functions for table datatype(s) */
+ FmgrInfo *lhs_hash_funcs; /* hash functions for lefthand datatype(s) */
+ FmgrInfo *cur_eq_funcs; /* equality functions for LHS vs. table */
+ ExprState *cur_eq_comp; /* equality comparator for LHS vs. table */
+} SubPlanState;
+
+/* ----------------
+ * AlternativeSubPlanState node
+ * ----------------
+ */
+typedef struct AlternativeSubPlanState
+{
+ NodeTag type;
+ AlternativeSubPlan *subplan; /* expression plan node */
+ List *subplans; /* SubPlanStates of alternative subplans */
+ int active; /* list index of the one we're using */
+} AlternativeSubPlanState;
+
+/*
+ * DomainConstraintState - one item to check during CoerceToDomain
+ *
+ * Note: we consider this to be part of an ExprState tree, so we give it
+ * a name following the xxxState convention. But there's no directly
+ * associated plan-tree node.
+ */
+typedef enum DomainConstraintType
+{
+ DOM_CONSTRAINT_NOTNULL,
+ DOM_CONSTRAINT_CHECK
+} DomainConstraintType;
+
+typedef struct DomainConstraintState
+{
+ NodeTag type;
+ DomainConstraintType constrainttype; /* constraint type */
+ char *name; /* name of constraint (for error msgs) */
+ Expr *check_expr; /* for CHECK, a boolean expression */
+ ExprState *check_exprstate; /* check_expr's eval state, or NULL */
+} DomainConstraintState;
+
+
+/* ----------------------------------------------------------------
+ * Executor State Trees
+ *
+ * An executing query has a PlanState tree paralleling the Plan tree
+ * that describes the plan.
+ * ----------------------------------------------------------------
+ */
+
+/* ----------------
+ * ExecProcNodeMtd
+ *
+ * This is the method called by ExecProcNode to return the next tuple
+ * from an executor node. It returns NULL, or an empty TupleTableSlot,
+ * if no more tuples are available.
+ * ----------------
+ */
+typedef TupleTableSlot *(*ExecProcNodeMtd) (struct PlanState *pstate);
+
+/* ----------------
+ * PlanState node
+ *
+ * We never actually instantiate any PlanState nodes; this is just the common
+ * abstract superclass for all PlanState-type nodes.
+ * ----------------
+ */
+typedef struct PlanState
+{
+ NodeTag type;
+
+ Plan *plan; /* associated Plan node */
+
+ EState *state; /* at execution time, states of individual
+ * nodes point to one EState for the whole
+ * top-level plan */
+
+ ExecProcNodeMtd ExecProcNode; /* function to return next tuple */
+ ExecProcNodeMtd ExecProcNodeReal; /* actual function, if above is a
+ * wrapper */
+
+ Instrumentation *instrument; /* Optional runtime stats for this node */
+ WorkerInstrumentation *worker_instrument; /* per-worker instrumentation */
+
+ /* Per-worker JIT instrumentation */
+ struct SharedJitInstrumentation *worker_jit_instrument;
+
+ /*
+ * Common structural data for all Plan types. These links to subsidiary
+ * state trees parallel links in the associated plan tree (except for the
+ * subPlan list, which does not exist in the plan tree).
+ */
+ ExprState *qual; /* boolean qual condition */
+ struct PlanState *lefttree; /* input plan tree(s) */
+ struct PlanState *righttree;
+
+ List *initPlan; /* Init SubPlanState nodes (un-correlated expr
+ * subselects) */
+ List *subPlan; /* SubPlanState nodes in my expressions */
+
+ /*
+ * State for management of parameter-change-driven rescanning
+ */
+ Bitmapset *chgParam; /* set of IDs of changed Params */
+
+ /*
+ * Other run-time state needed by most if not all node types.
+ */
+ TupleDesc ps_ResultTupleDesc; /* node's return type */
+ TupleTableSlot *ps_ResultTupleSlot; /* slot for my result tuples */
+ ExprContext *ps_ExprContext; /* node's expression-evaluation context */
+ ProjectionInfo *ps_ProjInfo; /* info for doing tuple projection */
+
+ /*
+ * Scanslot's descriptor if known. This is a bit of a hack, but otherwise
+ * it's hard for expression compilation to optimize based on the
+ * descriptor, without encoding knowledge about all executor nodes.
+ */
+ TupleDesc scandesc;
+
+ /*
+ * Define the slot types for inner, outer and scanslots for expression
+ * contexts with this state as a parent. If *opsset is set, then
+ * *opsfixed indicates whether *ops is guaranteed to be the type of slot
+ * used. That means that every slot in the corresponding
+ * ExprContext.ecxt_*tuple will point to a slot of that type, while
+ * evaluating the expression. If *opsfixed is false, but *ops is set,
+ * that indicates the most likely type of slot.
+ *
+ * The scan* fields are set by ExecInitScanTupleSlot(). If that's not
+ * called, nodes can initialize the fields themselves.
+ *
+ * If outer/inneropsset is false, the information is inferred on-demand
+ * using ExecGetResultSlotOps() on ->righttree/lefttree, using the
+ * corresponding node's resultops* fields.
+ *
+ * The result* fields are automatically set when ExecInitResultSlot is
+ * used (be it directly or when the slot is created by
+ * ExecAssignScanProjectionInfo() /
+ * ExecConditionalAssignProjectionInfo()). If no projection is necessary
+ * ExecConditionalAssignProjectionInfo() defaults those fields to the scan
+ * operations.
+ */
+ const TupleTableSlotOps *scanops;
+ const TupleTableSlotOps *outerops;
+ const TupleTableSlotOps *innerops;
+ const TupleTableSlotOps *resultops;
+ bool scanopsfixed;
+ bool outeropsfixed;
+ bool inneropsfixed;
+ bool resultopsfixed;
+ bool scanopsset;
+ bool outeropsset;
+ bool inneropsset;
+ bool resultopsset;
+} PlanState;
+
+/* ----------------
+ * these are defined to avoid confusion problems with "left"
+ * and "right" and "inner" and "outer". The convention is that
+ * the "left" plan is the "outer" plan and the "right" plan is
+ * the inner plan, but these make the code more readable.
+ * ----------------
+ */
+#define innerPlanState(node) (((PlanState *)(node))->righttree)
+#define outerPlanState(node) (((PlanState *)(node))->lefttree)
+
+/* Macros for inline access to certain instrumentation counters */
+#define InstrCountTuples2(node, delta) \
+ do { \
+ if (((PlanState *)(node))->instrument) \
+ ((PlanState *)(node))->instrument->ntuples2 += (delta); \
+ } while (0)
+#define InstrCountFiltered1(node, delta) \
+ do { \
+ if (((PlanState *)(node))->instrument) \
+ ((PlanState *)(node))->instrument->nfiltered1 += (delta); \
+ } while(0)
+#define InstrCountFiltered2(node, delta) \
+ do { \
+ if (((PlanState *)(node))->instrument) \
+ ((PlanState *)(node))->instrument->nfiltered2 += (delta); \
+ } while(0)
+
+/*
+ * EPQState is state for executing an EvalPlanQual recheck on a candidate
+ * tuples e.g. in ModifyTable or LockRows.
+ *
+ * To execute EPQ a separate EState is created (stored in ->recheckestate),
+ * which shares some resources, like the rangetable, with the main query's
+ * EState (stored in ->parentestate). The (sub-)tree of the plan that needs to
+ * be rechecked (in ->plan), is separately initialized (into
+ * ->recheckplanstate), but shares plan nodes with the corresponding nodes in
+ * the main query. The scan nodes in that separate executor tree are changed
+ * to return only the current tuple of interest for the respective
+ * table. Those tuples are either provided by the caller (using
+ * EvalPlanQualSlot), and/or found using the rowmark mechanism (non-locking
+ * rowmarks by the EPQ machinery itself, locking ones by the caller).
+ *
+ * While the plan to be checked may be changed using EvalPlanQualSetPlan() -
+ * e.g. so all source plans for a ModifyTable node can be processed - all such
+ * plans need to share the same EState.
+ */
+typedef struct EPQState
+{
+ /* Initialized at EvalPlanQualInit() time: */
+
+ EState *parentestate; /* main query's EState */
+ int epqParam; /* ID of Param to force scan node re-eval */
+
+ /*
+ * Tuples to be substituted by scan nodes. They need to set up, before
+ * calling EvalPlanQual()/EvalPlanQualNext(), into the slot returned by
+ * EvalPlanQualSlot(scanrelid). The array is indexed by scanrelid - 1.
+ */
+ List *tuple_table; /* tuple table for relsubs_slot */
+ TupleTableSlot **relsubs_slot;
+
+ /*
+ * Initialized by EvalPlanQualInit(), may be changed later with
+ * EvalPlanQualSetPlan():
+ */
+
+ Plan *plan; /* plan tree to be executed */
+ List *arowMarks; /* ExecAuxRowMarks (non-locking only) */
+
+
+ /*
+ * The original output tuple to be rechecked. Set by
+ * EvalPlanQualSetSlot(), before EvalPlanQualNext() or EvalPlanQual() may
+ * be called.
+ */
+ TupleTableSlot *origslot;
+
+
+ /* Initialized or reset by EvalPlanQualBegin(): */
+
+ EState *recheckestate; /* EState for EPQ execution, see above */
+
+ /*
+ * Rowmarks that can be fetched on-demand using
+ * EvalPlanQualFetchRowMark(), indexed by scanrelid - 1. Only non-locking
+ * rowmarks.
+ */
+ ExecAuxRowMark **relsubs_rowmark;
+
+ /*
+ * True if a relation's EPQ tuple has been fetched for relation, indexed
+ * by scanrelid - 1.
+ */
+ bool *relsubs_done;
+
+ PlanState *recheckplanstate; /* EPQ specific exec nodes, for ->plan */
+} EPQState;
+
+
+/* ----------------
+ * ResultState information
+ * ----------------
+ */
+typedef struct ResultState
+{
+ PlanState ps; /* its first field is NodeTag */
+ ExprState *resconstantqual;
+ bool rs_done; /* are we done? */
+ bool rs_checkqual; /* do we need to check the qual? */
+} ResultState;
+
+/* ----------------
+ * ProjectSetState information
+ *
+ * Note: at least one of the "elems" will be a SetExprState; the rest are
+ * regular ExprStates.
+ * ----------------
+ */
+typedef struct ProjectSetState
+{
+ PlanState ps; /* its first field is NodeTag */
+ Node **elems; /* array of expression states */
+ ExprDoneCond *elemdone; /* array of per-SRF is-done states */
+ int nelems; /* length of elemdone[] array */
+ bool pending_srf_tuples; /* still evaluating srfs in tlist? */
+ MemoryContext argcontext; /* context for SRF arguments */
+} ProjectSetState;
+
+/* ----------------
+ * ModifyTableState information
+ * ----------------
+ */
+typedef struct ModifyTableState
+{
+ PlanState ps; /* its first field is NodeTag */
+ CmdType operation; /* INSERT, UPDATE, or DELETE */
+ bool canSetTag; /* do we set the command tag/es_processed? */
+ bool mt_done; /* are we done? */
+ PlanState **mt_plans; /* subplans (one per target rel) */
+ int mt_nplans; /* number of plans in the array */
+ int mt_whichplan; /* which one is being executed (0..n-1) */
+ TupleTableSlot **mt_scans; /* input tuple corresponding to underlying
+ * plans */
+ ResultRelInfo *resultRelInfo; /* per-subplan target relations */
+ ResultRelInfo *rootResultRelInfo; /* root target relation (partitioned
+ * table root) */
+ List **mt_arowmarks; /* per-subplan ExecAuxRowMark lists */
+ EPQState mt_epqstate; /* for evaluating EvalPlanQual rechecks */
+ bool fireBSTriggers; /* do we need to fire stmt triggers? */
+
+ /*
+ * Slot for storing tuples in the root partitioned table's rowtype during
+ * an UPDATE of a partitioned table.
+ */
+ TupleTableSlot *mt_root_tuple_slot;
+
+ /* Tuple-routing support info */
+ struct PartitionTupleRouting *mt_partition_tuple_routing;
+
+ /* controls transition table population for specified operation */
+ struct TransitionCaptureState *mt_transition_capture;
+
+ /* controls transition table population for INSERT...ON CONFLICT UPDATE */
+ struct TransitionCaptureState *mt_oc_transition_capture;
+
+ /* Per plan map for tuple conversion from child to root */
+ TupleConversionMap **mt_per_subplan_tupconv_maps;
+} ModifyTableState;
+
+/* ----------------
+ * AppendState information
+ *
+ * nplans how many plans are in the array
+ * whichplan which plan is being executed (0 .. n-1), or a
+ * special negative value. See nodeAppend.c.
+ * prune_state details required to allow partitions to be
+ * eliminated from the scan, or NULL if not possible.
+ * valid_subplans for runtime pruning, valid appendplans indexes to
+ * scan.
+ * ----------------
+ */
+
+struct AppendState;
+typedef struct AppendState AppendState;
+struct ParallelAppendState;
+typedef struct ParallelAppendState ParallelAppendState;
+struct PartitionPruneState;
+
+struct AppendState
+{
+ PlanState ps; /* its first field is NodeTag */
+ PlanState **appendplans; /* array of PlanStates for my inputs */
+ int as_nplans;
+ int as_whichplan;
+ int as_first_partial_plan; /* Index of 'appendplans' containing
+ * the first partial plan */
+ ParallelAppendState *as_pstate; /* parallel coordination info */
+ Size pstate_len; /* size of parallel coordination info */
+ struct PartitionPruneState *as_prune_state;
+ Bitmapset *as_valid_subplans;
+ bool (*choose_next_subplan) (AppendState *);
+};
+
+/* ----------------
+ * MergeAppendState information
+ *
+ * nplans how many plans are in the array
+ * nkeys number of sort key columns
+ * sortkeys sort keys in SortSupport representation
+ * slots current output tuple of each subplan
+ * heap heap of active tuples
+ * initialized true if we have fetched first tuple from each subplan
+ * prune_state details required to allow partitions to be
+ * eliminated from the scan, or NULL if not possible.
+ * valid_subplans for runtime pruning, valid mergeplans indexes to
+ * scan.
+ * ----------------
+ */
+typedef struct MergeAppendState
+{
+ PlanState ps; /* its first field is NodeTag */
+ PlanState **mergeplans; /* array of PlanStates for my inputs */
+ int ms_nplans;
+ int ms_nkeys;
+ SortSupport ms_sortkeys; /* array of length ms_nkeys */
+ TupleTableSlot **ms_slots; /* array of length ms_nplans */
+ struct binaryheap *ms_heap; /* binary heap of slot indices */
+ bool ms_initialized; /* are subplans started? */
+ struct PartitionPruneState *ms_prune_state;
+ Bitmapset *ms_valid_subplans;
+} MergeAppendState;
+
+/* ----------------
+ * RecursiveUnionState information
+ *
+ * RecursiveUnionState is used for performing a recursive union.
+ *
+ * recursing T when we're done scanning the non-recursive term
+ * intermediate_empty T if intermediate_table is currently empty
+ * working_table working table (to be scanned by recursive term)
+ * intermediate_table current recursive output (next generation of WT)
+ * ----------------
+ */
+typedef struct RecursiveUnionState
+{
+ PlanState ps; /* its first field is NodeTag */
+ bool recursing;
+ bool intermediate_empty;
+ Tuplestorestate *working_table;
+ Tuplestorestate *intermediate_table;
+ /* Remaining fields are unused in UNION ALL case */
+ Oid *eqfuncoids; /* per-grouping-field equality fns */
+ FmgrInfo *hashfunctions; /* per-grouping-field hash fns */
+ MemoryContext tempContext; /* short-term context for comparisons */
+ TupleHashTable hashtable; /* hash table for tuples already seen */
+ MemoryContext tableContext; /* memory context containing hash table */
+} RecursiveUnionState;
+
+/* ----------------
+ * BitmapAndState information
+ * ----------------
+ */
+typedef struct BitmapAndState
+{
+ PlanState ps; /* its first field is NodeTag */
+ PlanState **bitmapplans; /* array of PlanStates for my inputs */
+ int nplans; /* number of input plans */
+} BitmapAndState;
+
+/* ----------------
+ * BitmapOrState information
+ * ----------------
+ */
+typedef struct BitmapOrState
+{
+ PlanState ps; /* its first field is NodeTag */
+ PlanState **bitmapplans; /* array of PlanStates for my inputs */
+ int nplans; /* number of input plans */
+} BitmapOrState;
+
+/* ----------------------------------------------------------------
+ * Scan State Information
+ * ----------------------------------------------------------------
+ */
+
+/* ----------------
+ * ScanState information
+ *
+ * ScanState extends PlanState for node types that represent
+ * scans of an underlying relation. It can also be used for nodes
+ * that scan the output of an underlying plan node --- in that case,
+ * only ScanTupleSlot is actually useful, and it refers to the tuple
+ * retrieved from the subplan.
+ *
+ * currentRelation relation being scanned (NULL if none)
+ * currentScanDesc current scan descriptor for scan (NULL if none)
+ * ScanTupleSlot pointer to slot in tuple table holding scan tuple
+ * ----------------
+ */
+typedef struct ScanState
+{
+ PlanState ps; /* its first field is NodeTag */
+ Relation ss_currentRelation;
+ struct TableScanDescData *ss_currentScanDesc;
+ TupleTableSlot *ss_ScanTupleSlot;
+} ScanState;
+
+/* ----------------
+ * SeqScanState information
+ * ----------------
+ */
+typedef struct SeqScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ Size pscan_len; /* size of parallel heap scan descriptor */
+} SeqScanState;
+
+/* ----------------
+ * SampleScanState information
+ * ----------------
+ */
+typedef struct SampleScanState
+{
+ ScanState ss;
+ List *args; /* expr states for TABLESAMPLE params */
+ ExprState *repeatable; /* expr state for REPEATABLE expr */
+ /* use struct pointer to avoid including tsmapi.h here */
+ struct TsmRoutine *tsmroutine; /* descriptor for tablesample method */
+ void *tsm_state; /* tablesample method can keep state here */
+ bool use_bulkread; /* use bulkread buffer access strategy? */
+ bool use_pagemode; /* use page-at-a-time visibility checking? */
+ bool begun; /* false means need to call BeginSampleScan */
+ uint32 seed; /* random seed */
+ int64 donetuples; /* number of tuples already returned */
+ bool haveblock; /* has a block for sampling been determined */
+ bool done; /* exhausted all tuples? */
+} SampleScanState;
+
+/*
+ * These structs store information about index quals that don't have simple
+ * constant right-hand sides. See comments for ExecIndexBuildScanKeys()
+ * for discussion.
+ */
+typedef struct
+{
+ struct ScanKeyData *scan_key; /* scankey to put value into */
+ ExprState *key_expr; /* expr to evaluate to get value */
+ bool key_toastable; /* is expr's result a toastable datatype? */
+} IndexRuntimeKeyInfo;
+
+typedef struct
+{
+ struct ScanKeyData *scan_key; /* scankey to put value into */
+ ExprState *array_expr; /* expr to evaluate to get array value */
+ int next_elem; /* next array element to use */
+ int num_elems; /* number of elems in current array value */
+ Datum *elem_values; /* array of num_elems Datums */
+ bool *elem_nulls; /* array of num_elems is-null flags */
+} IndexArrayKeyInfo;
+
+/* ----------------
+ * IndexScanState information
+ *
+ * indexqualorig execution state for indexqualorig expressions
+ * indexorderbyorig execution state for indexorderbyorig expressions
+ * ScanKeys Skey structures for index quals
+ * NumScanKeys number of ScanKeys
+ * OrderByKeys Skey structures for index ordering operators
+ * NumOrderByKeys number of OrderByKeys
+ * RuntimeKeys info about Skeys that must be evaluated at runtime
+ * NumRuntimeKeys number of RuntimeKeys
+ * RuntimeKeysReady true if runtime Skeys have been computed
+ * RuntimeContext expr context for evaling runtime Skeys
+ * RelationDesc index relation descriptor
+ * ScanDesc index scan descriptor
+ *
+ * ReorderQueue tuples that need reordering due to re-check
+ * ReachedEnd have we fetched all tuples from index already?
+ * OrderByValues values of ORDER BY exprs of last fetched tuple
+ * OrderByNulls null flags for OrderByValues
+ * SortSupport for reordering ORDER BY exprs
+ * OrderByTypByVals is the datatype of order by expression pass-by-value?
+ * OrderByTypLens typlens of the datatypes of order by expressions
+ * PscanLen size of parallel index scan descriptor
+ * ----------------
+ */
+typedef struct IndexScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ ExprState *indexqualorig;
+ List *indexorderbyorig;
+ struct ScanKeyData *iss_ScanKeys;
+ int iss_NumScanKeys;
+ struct ScanKeyData *iss_OrderByKeys;
+ int iss_NumOrderByKeys;
+ IndexRuntimeKeyInfo *iss_RuntimeKeys;
+ int iss_NumRuntimeKeys;
+ bool iss_RuntimeKeysReady;
+ ExprContext *iss_RuntimeContext;
+ Relation iss_RelationDesc;
+ struct IndexScanDescData *iss_ScanDesc;
+
+ /* These are needed for re-checking ORDER BY expr ordering */
+ pairingheap *iss_ReorderQueue;
+ bool iss_ReachedEnd;
+ Datum *iss_OrderByValues;
+ bool *iss_OrderByNulls;
+ SortSupport iss_SortSupport;
+ bool *iss_OrderByTypByVals;
+ int16 *iss_OrderByTypLens;
+ Size iss_PscanLen;
+} IndexScanState;
+
+/* ----------------
+ * IndexOnlyScanState information
+ *
+ * indexqual execution state for indexqual expressions
+ * ScanKeys Skey structures for index quals
+ * NumScanKeys number of ScanKeys
+ * OrderByKeys Skey structures for index ordering operators
+ * NumOrderByKeys number of OrderByKeys
+ * RuntimeKeys info about Skeys that must be evaluated at runtime
+ * NumRuntimeKeys number of RuntimeKeys
+ * RuntimeKeysReady true if runtime Skeys have been computed
+ * RuntimeContext expr context for evaling runtime Skeys
+ * RelationDesc index relation descriptor
+ * ScanDesc index scan descriptor
+ * TableSlot slot for holding tuples fetched from the table
+ * VMBuffer buffer in use for visibility map testing, if any
+ * PscanLen size of parallel index-only scan descriptor
+ * ----------------
+ */
+typedef struct IndexOnlyScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ ExprState *indexqual;
+ struct ScanKeyData *ioss_ScanKeys;
+ int ioss_NumScanKeys;
+ struct ScanKeyData *ioss_OrderByKeys;
+ int ioss_NumOrderByKeys;
+ IndexRuntimeKeyInfo *ioss_RuntimeKeys;
+ int ioss_NumRuntimeKeys;
+ bool ioss_RuntimeKeysReady;
+ ExprContext *ioss_RuntimeContext;
+ Relation ioss_RelationDesc;
+ struct IndexScanDescData *ioss_ScanDesc;
+ TupleTableSlot *ioss_TableSlot;
+ Buffer ioss_VMBuffer;
+ Size ioss_PscanLen;
+} IndexOnlyScanState;
+
+/* ----------------
+ * BitmapIndexScanState information
+ *
+ * result bitmap to return output into, or NULL
+ * ScanKeys Skey structures for index quals
+ * NumScanKeys number of ScanKeys
+ * RuntimeKeys info about Skeys that must be evaluated at runtime
+ * NumRuntimeKeys number of RuntimeKeys
+ * ArrayKeys info about Skeys that come from ScalarArrayOpExprs
+ * NumArrayKeys number of ArrayKeys
+ * RuntimeKeysReady true if runtime Skeys have been computed
+ * RuntimeContext expr context for evaling runtime Skeys
+ * RelationDesc index relation descriptor
+ * ScanDesc index scan descriptor
+ * ----------------
+ */
+typedef struct BitmapIndexScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ TIDBitmap *biss_result;
+ struct ScanKeyData *biss_ScanKeys;
+ int biss_NumScanKeys;
+ IndexRuntimeKeyInfo *biss_RuntimeKeys;
+ int biss_NumRuntimeKeys;
+ IndexArrayKeyInfo *biss_ArrayKeys;
+ int biss_NumArrayKeys;
+ bool biss_RuntimeKeysReady;
+ ExprContext *biss_RuntimeContext;
+ Relation biss_RelationDesc;
+ struct IndexScanDescData *biss_ScanDesc;
+} BitmapIndexScanState;
+
+/* ----------------
+ * SharedBitmapState information
+ *
+ * BM_INITIAL TIDBitmap creation is not yet started, so first worker
+ * to see this state will set the state to BM_INPROGRESS
+ * and that process will be responsible for creating
+ * TIDBitmap.
+ * BM_INPROGRESS TIDBitmap creation is in progress; workers need to
+ * sleep until it's finished.
+ * BM_FINISHED TIDBitmap creation is done, so now all workers can
+ * proceed to iterate over TIDBitmap.
+ * ----------------
+ */
+typedef enum
+{
+ BM_INITIAL,
+ BM_INPROGRESS,
+ BM_FINISHED
+} SharedBitmapState;
+
+/* ----------------
+ * ParallelBitmapHeapState information
+ * tbmiterator iterator for scanning current pages
+ * prefetch_iterator iterator for prefetching ahead of current page
+ * mutex mutual exclusion for the prefetching variable
+ * and state
+ * prefetch_pages # pages prefetch iterator is ahead of current
+ * prefetch_target current target prefetch distance
+ * state current state of the TIDBitmap
+ * cv conditional wait variable
+ * phs_snapshot_data snapshot data shared to workers
+ * ----------------
+ */
+typedef struct ParallelBitmapHeapState
+{
+ dsa_pointer tbmiterator;
+ dsa_pointer prefetch_iterator;
+ slock_t mutex;
+ int prefetch_pages;
+ int prefetch_target;
+ SharedBitmapState state;
+ ConditionVariable cv;
+ char phs_snapshot_data[FLEXIBLE_ARRAY_MEMBER];
+} ParallelBitmapHeapState;
+
+/* ----------------
+ * BitmapHeapScanState information
+ *
+ * bitmapqualorig execution state for bitmapqualorig expressions
+ * tbm bitmap obtained from child index scan(s)
+ * tbmiterator iterator for scanning current pages
+ * tbmres current-page data
+ * can_skip_fetch can we potentially skip tuple fetches in this scan?
+ * return_empty_tuples number of empty tuples to return
+ * vmbuffer buffer for visibility-map lookups
+ * pvmbuffer ditto, for prefetched pages
+ * exact_pages total number of exact pages retrieved
+ * lossy_pages total number of lossy pages retrieved
+ * prefetch_iterator iterator for prefetching ahead of current page
+ * prefetch_pages # pages prefetch iterator is ahead of current
+ * prefetch_target current target prefetch distance
+ * prefetch_maximum maximum value for prefetch_target
+ * pscan_len size of the shared memory for parallel bitmap
+ * initialized is node is ready to iterate
+ * shared_tbmiterator shared iterator
+ * shared_prefetch_iterator shared iterator for prefetching
+ * pstate shared state for parallel bitmap scan
+ * ----------------
+ */
+typedef struct BitmapHeapScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ ExprState *bitmapqualorig;
+ TIDBitmap *tbm;
+ TBMIterator *tbmiterator;
+ TBMIterateResult *tbmres;
+ bool can_skip_fetch;
+ int return_empty_tuples;
+ Buffer vmbuffer;
+ Buffer pvmbuffer;
+ long exact_pages;
+ long lossy_pages;
+ TBMIterator *prefetch_iterator;
+ int prefetch_pages;
+ int prefetch_target;
+ int prefetch_maximum;
+ Size pscan_len;
+ bool initialized;
+ TBMSharedIterator *shared_tbmiterator;
+ TBMSharedIterator *shared_prefetch_iterator;
+ ParallelBitmapHeapState *pstate;
+} BitmapHeapScanState;
+
+/* ----------------
+ * TidScanState information
+ *
+ * tidexprs list of TidExpr structs (see nodeTidscan.c)
+ * isCurrentOf scan has a CurrentOfExpr qual
+ * NumTids number of tids in this scan
+ * TidPtr index of currently fetched tid
+ * TidList evaluated item pointers (array of size NumTids)
+ * htup currently-fetched tuple, if any
+ * ----------------
+ */
+typedef struct TidScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ List *tss_tidexprs;
+ bool tss_isCurrentOf;
+ int tss_NumTids;
+ int tss_TidPtr;
+ ItemPointerData *tss_TidList;
+ HeapTupleData tss_htup;
+} TidScanState;
+
+/* ----------------
+ * SubqueryScanState information
+ *
+ * SubqueryScanState is used for scanning a sub-query in the range table.
+ * ScanTupleSlot references the current output tuple of the sub-query.
+ * ----------------
+ */
+typedef struct SubqueryScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ PlanState *subplan;
+} SubqueryScanState;
+
+/* ----------------
+ * FunctionScanState information
+ *
+ * Function nodes are used to scan the results of a
+ * function appearing in FROM (typically a function returning set).
+ *
+ * eflags node's capability flags
+ * ordinality is this scan WITH ORDINALITY?
+ * simple true if we have 1 function and no ordinality
+ * ordinal current ordinal column value
+ * nfuncs number of functions being executed
+ * funcstates per-function execution states (private in
+ * nodeFunctionscan.c)
+ * argcontext memory context to evaluate function arguments in
+ * ----------------
+ */
+struct FunctionScanPerFuncState;
+
+typedef struct FunctionScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ int eflags;
+ bool ordinality;
+ bool simple;
+ int64 ordinal;
+ int nfuncs;
+ struct FunctionScanPerFuncState *funcstates; /* array of length nfuncs */
+ MemoryContext argcontext;
+} FunctionScanState;
+
+/* ----------------
+ * ValuesScanState information
+ *
+ * ValuesScan nodes are used to scan the results of a VALUES list
+ *
+ * rowcontext per-expression-list context
+ * exprlists array of expression lists being evaluated
+ * exprstatelists array of expression state lists, for SubPlans only
+ * array_len size of above arrays
+ * curr_idx current array index (0-based)
+ *
+ * Note: ss.ps.ps_ExprContext is used to evaluate any qual or projection
+ * expressions attached to the node. We create a second ExprContext,
+ * rowcontext, in which to build the executor expression state for each
+ * Values sublist. Resetting this context lets us get rid of expression
+ * state for each row, avoiding major memory leakage over a long values list.
+ * However, that doesn't work for sublists containing SubPlans, because a
+ * SubPlan has to be connected up to the outer plan tree to work properly.
+ * Therefore, for only those sublists containing SubPlans, we do expression
+ * state construction at executor start, and store those pointers in
+ * exprstatelists[]. NULL entries in that array correspond to simple
+ * subexpressions that are handled as described above.
+ * ----------------
+ */
+typedef struct ValuesScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ ExprContext *rowcontext;
+ List **exprlists;
+ List **exprstatelists;
+ int array_len;
+ int curr_idx;
+} ValuesScanState;
+
+/* ----------------
+ * TableFuncScanState node
+ *
+ * Used in table-expression functions like XMLTABLE.
+ * ----------------
+ */
+typedef struct TableFuncScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ ExprState *docexpr; /* state for document expression */
+ ExprState *rowexpr; /* state for row-generating expression */
+ List *colexprs; /* state for column-generating expression */
+ List *coldefexprs; /* state for column default expressions */
+ List *ns_names; /* same as TableFunc.ns_names */
+ List *ns_uris; /* list of states of namespace URI exprs */
+ Bitmapset *notnulls; /* nullability flag for each output column */
+ void *opaque; /* table builder private space */
+ const struct TableFuncRoutine *routine; /* table builder methods */
+ FmgrInfo *in_functions; /* input function for each column */
+ Oid *typioparams; /* typioparam for each column */
+ int64 ordinal; /* row number to be output next */
+ MemoryContext perTableCxt; /* per-table context */
+ Tuplestorestate *tupstore; /* output tuple store */
+} TableFuncScanState;
+
+/* ----------------
+ * CteScanState information
+ *
+ * CteScan nodes are used to scan a CommonTableExpr query.
+ *
+ * Multiple CteScan nodes can read out from the same CTE query. We use
+ * a tuplestore to hold rows that have been read from the CTE query but
+ * not yet consumed by all readers.
+ * ----------------
+ */
+typedef struct CteScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ int eflags; /* capability flags to pass to tuplestore */
+ int readptr; /* index of my tuplestore read pointer */
+ PlanState *cteplanstate; /* PlanState for the CTE query itself */
+ /* Link to the "leader" CteScanState (possibly this same node) */
+ struct CteScanState *leader;
+ /* The remaining fields are only valid in the "leader" CteScanState */
+ Tuplestorestate *cte_table; /* rows already read from the CTE query */
+ bool eof_cte; /* reached end of CTE query? */
+} CteScanState;
+
+/* ----------------
+ * NamedTuplestoreScanState information
+ *
+ * NamedTuplestoreScan nodes are used to scan a Tuplestore created and
+ * named prior to execution of the query. An example is a transition
+ * table for an AFTER trigger.
+ *
+ * Multiple NamedTuplestoreScan nodes can read out from the same Tuplestore.
+ * ----------------
+ */
+typedef struct NamedTuplestoreScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ int readptr; /* index of my tuplestore read pointer */
+ TupleDesc tupdesc; /* format of the tuples in the tuplestore */
+ Tuplestorestate *relation; /* the rows */
+} NamedTuplestoreScanState;
+
+/* ----------------
+ * WorkTableScanState information
+ *
+ * WorkTableScan nodes are used to scan the work table created by
+ * a RecursiveUnion node. We locate the RecursiveUnion node
+ * during executor startup.
+ * ----------------
+ */
+typedef struct WorkTableScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ RecursiveUnionState *rustate;
+} WorkTableScanState;
+
+/* ----------------
+ * ForeignScanState information
+ *
+ * ForeignScan nodes are used to scan foreign-data tables.
+ * ----------------
+ */
+typedef struct ForeignScanState
+{
+ ScanState ss; /* its first field is NodeTag */
+ ExprState *fdw_recheck_quals; /* original quals not in ss.ps.qual */
+ Size pscan_len; /* size of parallel coordination information */
+ /* use struct pointer to avoid including fdwapi.h here */
+ struct FdwRoutine *fdwroutine;
+ void *fdw_state; /* foreign-data wrapper can keep state here */
+} ForeignScanState;
+
+/* ----------------
+ * CustomScanState information
+ *
+ * CustomScan nodes are used to execute custom code within executor.
+ *
+ * Core code must avoid assuming that the CustomScanState is only as large as
+ * the structure declared here; providers are allowed to make it the first
+ * element in a larger structure, and typically would need to do so. The
+ * struct is actually allocated by the CreateCustomScanState method associated
+ * with the plan node. Any additional fields can be initialized there, or in
+ * the BeginCustomScan method.
+ * ----------------
+ */
+struct CustomExecMethods;
+
+typedef struct CustomScanState
+{
+ ScanState ss;
+ uint32 flags; /* mask of CUSTOMPATH_* flags, see
+ * nodes/extensible.h */
+ List *custom_ps; /* list of child PlanState nodes, if any */
+ Size pscan_len; /* size of parallel coordination information */
+ const struct CustomExecMethods *methods;
+} CustomScanState;
+
+/* ----------------------------------------------------------------
+ * Join State Information
+ * ----------------------------------------------------------------
+ */
+
+/* ----------------
+ * JoinState information
+ *
+ * Superclass for state nodes of join plans.
+ * ----------------
+ */
+typedef struct JoinState
+{
+ PlanState ps;
+ JoinType jointype;
+ bool single_match; /* True if we should skip to next outer tuple
+ * after finding one inner match */
+ ExprState *joinqual; /* JOIN quals (in addition to ps.qual) */
+} JoinState;
+
+/* ----------------
+ * NestLoopState information
+ *
+ * NeedNewOuter true if need new outer tuple on next call
+ * MatchedOuter true if found a join match for current outer tuple
+ * NullInnerTupleSlot prepared null tuple for left outer joins
+ * ----------------
+ */
+typedef struct NestLoopState
+{
+ JoinState js; /* its first field is NodeTag */
+ bool nl_NeedNewOuter;
+ bool nl_MatchedOuter;
+ TupleTableSlot *nl_NullInnerTupleSlot;
+} NestLoopState;
+
+/* ----------------
+ * MergeJoinState information
+ *
+ * NumClauses number of mergejoinable join clauses
+ * Clauses info for each mergejoinable clause
+ * JoinState current state of ExecMergeJoin state machine
+ * SkipMarkRestore true if we may skip Mark and Restore operations
+ * ExtraMarks true to issue extra Mark operations on inner scan
+ * ConstFalseJoin true if we have a constant-false joinqual
+ * FillOuter true if should emit unjoined outer tuples anyway
+ * FillInner true if should emit unjoined inner tuples anyway
+ * MatchedOuter true if found a join match for current outer tuple
+ * MatchedInner true if found a join match for current inner tuple
+ * OuterTupleSlot slot in tuple table for cur outer tuple
+ * InnerTupleSlot slot in tuple table for cur inner tuple
+ * MarkedTupleSlot slot in tuple table for marked tuple
+ * NullOuterTupleSlot prepared null tuple for right outer joins
+ * NullInnerTupleSlot prepared null tuple for left outer joins
+ * OuterEContext workspace for computing outer tuple's join values
+ * InnerEContext workspace for computing inner tuple's join values
+ * ----------------
+ */
+/* private in nodeMergejoin.c: */
+typedef struct MergeJoinClauseData *MergeJoinClause;
+
+typedef struct MergeJoinState
+{
+ JoinState js; /* its first field is NodeTag */
+ int mj_NumClauses;
+ MergeJoinClause mj_Clauses; /* array of length mj_NumClauses */
+ int mj_JoinState;
+ bool mj_SkipMarkRestore;
+ bool mj_ExtraMarks;
+ bool mj_ConstFalseJoin;
+ bool mj_FillOuter;
+ bool mj_FillInner;
+ bool mj_MatchedOuter;
+ bool mj_MatchedInner;
+ TupleTableSlot *mj_OuterTupleSlot;
+ TupleTableSlot *mj_InnerTupleSlot;
+ TupleTableSlot *mj_MarkedTupleSlot;
+ TupleTableSlot *mj_NullOuterTupleSlot;
+ TupleTableSlot *mj_NullInnerTupleSlot;
+ ExprContext *mj_OuterEContext;
+ ExprContext *mj_InnerEContext;
+} MergeJoinState;
+
+/* ----------------
+ * HashJoinState information
+ *
+ * hashclauses original form of the hashjoin condition
+ * hj_OuterHashKeys the outer hash keys in the hashjoin condition
+ * hj_HashOperators the join operators in the hashjoin condition
+ * hj_HashTable hash table for the hashjoin
+ * (NULL if table not built yet)
+ * hj_CurHashValue hash value for current outer tuple
+ * hj_CurBucketNo regular bucket# for current outer tuple
+ * hj_CurSkewBucketNo skew bucket# for current outer tuple
+ * hj_CurTuple last inner tuple matched to current outer
+ * tuple, or NULL if starting search
+ * (hj_CurXXX variables are undefined if
+ * OuterTupleSlot is empty!)
+ * hj_OuterTupleSlot tuple slot for outer tuples
+ * hj_HashTupleSlot tuple slot for inner (hashed) tuples
+ * hj_NullOuterTupleSlot prepared null tuple for right/full outer joins
+ * hj_NullInnerTupleSlot prepared null tuple for left/full outer joins
+ * hj_FirstOuterTupleSlot first tuple retrieved from outer plan
+ * hj_JoinState current state of ExecHashJoin state machine
+ * hj_MatchedOuter true if found a join match for current outer
+ * hj_OuterNotEmpty true if outer relation known not empty
+ * ----------------
+ */
+
+/* these structs are defined in executor/hashjoin.h: */
+typedef struct HashJoinTupleData *HashJoinTuple;
+typedef struct HashJoinTableData *HashJoinTable;
+
+typedef struct HashJoinState
+{
+ JoinState js; /* its first field is NodeTag */
+ ExprState *hashclauses;
+ List *hj_OuterHashKeys; /* list of ExprState nodes */
+ List *hj_HashOperators; /* list of operator OIDs */
+ List *hj_Collations;
+ HashJoinTable hj_HashTable;
+ uint32 hj_CurHashValue;
+ int hj_CurBucketNo;
+ int hj_CurSkewBucketNo;
+ HashJoinTuple hj_CurTuple;
+ TupleTableSlot *hj_OuterTupleSlot;
+ TupleTableSlot *hj_HashTupleSlot;
+ TupleTableSlot *hj_NullOuterTupleSlot;
+ TupleTableSlot *hj_NullInnerTupleSlot;
+ TupleTableSlot *hj_FirstOuterTupleSlot;
+ int hj_JoinState;
+ bool hj_MatchedOuter;
+ bool hj_OuterNotEmpty;
+} HashJoinState;
+
+
+/* ----------------------------------------------------------------
+ * Materialization State Information
+ * ----------------------------------------------------------------
+ */
+
+/* ----------------
+ * MaterialState information
+ *
+ * materialize nodes are used to materialize the results
+ * of a subplan into a temporary file.
+ *
+ * ss.ss_ScanTupleSlot refers to output of underlying plan.
+ * ----------------
+ */
+typedef struct MaterialState
+{
+ ScanState ss; /* its first field is NodeTag */
+ int eflags; /* capability flags to pass to tuplestore */
+ bool eof_underlying; /* reached end of underlying plan? */
+ Tuplestorestate *tuplestorestate;
+} MaterialState;
+
+
+/* ----------------
+ * When performing sorting by multiple keys, it's possible that the input
+ * dataset is already sorted on a prefix of those keys. We call these
+ * "presorted keys".
+ * PresortedKeyData represents information about one such key.
+ * ----------------
+ */
+typedef struct PresortedKeyData
+{
+ FmgrInfo flinfo; /* comparison function info */
+ FunctionCallInfo fcinfo; /* comparison function call info */
+ OffsetNumber attno; /* attribute number in tuple */
+} PresortedKeyData;
+
+/* ----------------
+ * Shared memory container for per-worker sort information
+ * ----------------
+ */
+typedef struct SharedSortInfo
+{
+ int num_workers;
+ TuplesortInstrumentation sinstrument[FLEXIBLE_ARRAY_MEMBER];
+} SharedSortInfo;
+
+/* ----------------
+ * SortState information
+ * ----------------
+ */
+typedef struct SortState
+{
+ ScanState ss; /* its first field is NodeTag */
+ bool randomAccess; /* need random access to sort output? */
+ bool bounded; /* is the result set bounded? */
+ int64 bound; /* if bounded, how many tuples are needed */
+ bool sort_Done; /* sort completed yet? */
+ bool bounded_Done; /* value of bounded we did the sort with */
+ int64 bound_Done; /* value of bound we did the sort with */
+ void *tuplesortstate; /* private state of tuplesort.c */
+ bool am_worker; /* are we a worker? */
+ SharedSortInfo *shared_info; /* one entry per worker */
+} SortState;
+
+/* ----------------
+ * Instrumentation information for IncrementalSort
+ * ----------------
+ */
+typedef struct IncrementalSortGroupInfo
+{
+ int64 groupCount;
+ int64 maxDiskSpaceUsed;
+ int64 totalDiskSpaceUsed;
+ int64 maxMemorySpaceUsed;
+ int64 totalMemorySpaceUsed;
+ bits32 sortMethods; /* bitmask of TuplesortMethod */
+} IncrementalSortGroupInfo;
+
+typedef struct IncrementalSortInfo
+{
+ IncrementalSortGroupInfo fullsortGroupInfo;
+ IncrementalSortGroupInfo prefixsortGroupInfo;
+} IncrementalSortInfo;
+
+/* ----------------
+ * Shared memory container for per-worker incremental sort information
+ * ----------------
+ */
+typedef struct SharedIncrementalSortInfo
+{
+ int num_workers;
+ IncrementalSortInfo sinfo[FLEXIBLE_ARRAY_MEMBER];
+} SharedIncrementalSortInfo;
+
+/* ----------------
+ * IncrementalSortState information
+ * ----------------
+ */
+typedef enum
+{
+ INCSORT_LOADFULLSORT,
+ INCSORT_LOADPREFIXSORT,
+ INCSORT_READFULLSORT,
+ INCSORT_READPREFIXSORT,
+} IncrementalSortExecutionStatus;
+
+typedef struct IncrementalSortState
+{
+ ScanState ss; /* its first field is NodeTag */
+ bool bounded; /* is the result set bounded? */
+ int64 bound; /* if bounded, how many tuples are needed */
+ bool outerNodeDone; /* finished fetching tuples from outer node */
+ int64 bound_Done; /* value of bound we did the sort with */
+ IncrementalSortExecutionStatus execution_status;
+ int64 n_fullsort_remaining;
+ Tuplesortstate *fullsort_state; /* private state of tuplesort.c */
+ Tuplesortstate *prefixsort_state; /* private state of tuplesort.c */
+ /* the keys by which the input path is already sorted */
+ PresortedKeyData *presorted_keys;
+
+ IncrementalSortInfo incsort_info;
+
+ /* slot for pivot tuple defining values of presorted keys within group */
+ TupleTableSlot *group_pivot;
+ TupleTableSlot *transfer_tuple;
+ bool am_worker; /* are we a worker? */
+ SharedIncrementalSortInfo *shared_info; /* one entry per worker */
+} IncrementalSortState;
+
+/* ---------------------
+ * GroupState information
+ * ---------------------
+ */
+typedef struct GroupState
+{
+ ScanState ss; /* its first field is NodeTag */
+ ExprState *eqfunction; /* equality function */
+ bool grp_done; /* indicates completion of Group scan */
+} GroupState;
+
+/* ---------------------
+ * per-worker aggregate information
+ * ---------------------
+ */
+typedef struct AggregateInstrumentation
+{
+ Size hash_mem_peak; /* peak hash table memory usage */
+ uint64 hash_disk_used; /* kB of disk space used */
+ int hash_batches_used; /* batches used during entire execution */
+} AggregateInstrumentation;
+
+/* ----------------
+ * Shared memory container for per-worker aggregate information
+ * ----------------
+ */
+typedef struct SharedAggInfo
+{
+ int num_workers;
+ AggregateInstrumentation sinstrument[FLEXIBLE_ARRAY_MEMBER];
+} SharedAggInfo;
+
+/* ---------------------
+ * AggState information
+ *
+ * ss.ss_ScanTupleSlot refers to output of underlying plan.
+ *
+ * Note: ss.ps.ps_ExprContext contains ecxt_aggvalues and
+ * ecxt_aggnulls arrays, which hold the computed agg values for the current
+ * input group during evaluation of an Agg node's output tuple(s). We
+ * create a second ExprContext, tmpcontext, in which to evaluate input
+ * expressions and run the aggregate transition functions.
+ * ---------------------
+ */
+/* these structs are private in nodeAgg.c: */
+typedef struct AggStatePerAggData *AggStatePerAgg;
+typedef struct AggStatePerTransData *AggStatePerTrans;
+typedef struct AggStatePerGroupData *AggStatePerGroup;
+typedef struct AggStatePerPhaseData *AggStatePerPhase;
+typedef struct AggStatePerHashData *AggStatePerHash;
+
+typedef struct AggState
+{
+ ScanState ss; /* its first field is NodeTag */
+ List *aggs; /* all Aggref nodes in targetlist & quals */
+ int numaggs; /* length of list (could be zero!) */
+ int numtrans; /* number of pertrans items */
+ AggStrategy aggstrategy; /* strategy mode */
+ AggSplit aggsplit; /* agg-splitting mode, see nodes.h */
+ AggStatePerPhase phase; /* pointer to current phase data */
+ int numphases; /* number of phases (including phase 0) */
+ int current_phase; /* current phase number */
+ AggStatePerAgg peragg; /* per-Aggref information */
+ AggStatePerTrans pertrans; /* per-Trans state information */
+ ExprContext *hashcontext; /* econtexts for long-lived data (hashtable) */
+ ExprContext **aggcontexts; /* econtexts for long-lived data (per GS) */
+ ExprContext *tmpcontext; /* econtext for input expressions */
+#define FIELDNO_AGGSTATE_CURAGGCONTEXT 14
+ ExprContext *curaggcontext; /* currently active aggcontext */
+ AggStatePerAgg curperagg; /* currently active aggregate, if any */
+#define FIELDNO_AGGSTATE_CURPERTRANS 16
+ AggStatePerTrans curpertrans; /* currently active trans state, if any */
+ bool input_done; /* indicates end of input */
+ bool agg_done; /* indicates completion of Agg scan */
+ int projected_set; /* The last projected grouping set */
+#define FIELDNO_AGGSTATE_CURRENT_SET 20
+ int current_set; /* The current grouping set being evaluated */
+ Bitmapset *grouped_cols; /* grouped cols in current projection */
+ List *all_grouped_cols; /* list of all grouped cols in DESC order */
+ Bitmapset *colnos_needed; /* all columns needed from the outer plan */
+ int max_colno_needed; /* highest colno needed from outer plan */
+ bool all_cols_needed; /* are all cols from outer plan needed? */
+ /* These fields are for grouping set phase data */
+ int maxsets; /* The max number of sets in any phase */
+ AggStatePerPhase phases; /* array of all phases */
+ Tuplesortstate *sort_in; /* sorted input to phases > 1 */
+ Tuplesortstate *sort_out; /* input is copied here for next phase */
+ TupleTableSlot *sort_slot; /* slot for sort results */
+ /* these fields are used in AGG_PLAIN and AGG_SORTED modes: */
+ AggStatePerGroup *pergroups; /* grouping set indexed array of per-group
+ * pointers */
+ HeapTuple grp_firstTuple; /* copy of first tuple of current group */
+ /* these fields are used in AGG_HASHED and AGG_MIXED modes: */
+ bool table_filled; /* hash table filled yet? */
+ int num_hashes;
+ MemoryContext hash_metacxt; /* memory for hash table itself */
+ struct HashTapeInfo *hash_tapeinfo; /* metadata for spill tapes */
+ struct HashAggSpill *hash_spills; /* HashAggSpill for each grouping set,
+ * exists only during first pass */
+ TupleTableSlot *hash_spill_rslot; /* for reading spill files */
+ TupleTableSlot *hash_spill_wslot; /* for writing spill files */
+ List *hash_batches; /* hash batches remaining to be processed */
+ bool hash_ever_spilled; /* ever spilled during this execution? */
+ bool hash_spill_mode; /* we hit a limit during the current batch
+ * and we must not create new groups */
+ Size hash_mem_limit; /* limit before spilling hash table */
+ uint64 hash_ngroups_limit; /* limit before spilling hash table */
+ int hash_planned_partitions; /* number of partitions planned
+ * for first pass */
+ double hashentrysize; /* estimate revised during execution */
+ Size hash_mem_peak; /* peak hash table memory usage */
+ uint64 hash_ngroups_current; /* number of groups currently in
+ * memory in all hash tables */
+ uint64 hash_disk_used; /* kB of disk space used */
+ int hash_batches_used; /* batches used during entire execution */
+
+ AggStatePerHash perhash; /* array of per-hashtable data */
+ AggStatePerGroup *hash_pergroup; /* grouping set indexed array of
+ * per-group pointers */
+
+ /* support for evaluation of agg input expressions: */
+#define FIELDNO_AGGSTATE_ALL_PERGROUPS 53
+ AggStatePerGroup *all_pergroups; /* array of first ->pergroups, than
+ * ->hash_pergroup */
+ ProjectionInfo *combinedproj; /* projection machinery */
+ SharedAggInfo *shared_info; /* one entry per worker */
+} AggState;
+
+/* ----------------
+ * WindowAggState information
+ * ----------------
+ */
+/* these structs are private in nodeWindowAgg.c: */
+typedef struct WindowStatePerFuncData *WindowStatePerFunc;
+typedef struct WindowStatePerAggData *WindowStatePerAgg;
+
+typedef struct WindowAggState
+{
+ ScanState ss; /* its first field is NodeTag */
+
+ /* these fields are filled in by ExecInitExpr: */
+ List *funcs; /* all WindowFunc nodes in targetlist */
+ int numfuncs; /* total number of window functions */
+ int numaggs; /* number that are plain aggregates */
+
+ WindowStatePerFunc perfunc; /* per-window-function information */
+ WindowStatePerAgg peragg; /* per-plain-aggregate information */
+ ExprState *partEqfunction; /* equality funcs for partition columns */
+ ExprState *ordEqfunction; /* equality funcs for ordering columns */
+ Tuplestorestate *buffer; /* stores rows of current partition */
+ int current_ptr; /* read pointer # for current row */
+ int framehead_ptr; /* read pointer # for frame head, if used */
+ int frametail_ptr; /* read pointer # for frame tail, if used */
+ int grouptail_ptr; /* read pointer # for group tail, if used */
+ int64 spooled_rows; /* total # of rows in buffer */
+ int64 currentpos; /* position of current row in partition */
+ int64 frameheadpos; /* current frame head position */
+ int64 frametailpos; /* current frame tail position (frame end+1) */
+ /* use struct pointer to avoid including windowapi.h here */
+ struct WindowObjectData *agg_winobj; /* winobj for aggregate fetches */
+ int64 aggregatedbase; /* start row for current aggregates */
+ int64 aggregatedupto; /* rows before this one are aggregated */
+
+ int frameOptions; /* frame_clause options, see WindowDef */
+ ExprState *startOffset; /* expression for starting bound offset */
+ ExprState *endOffset; /* expression for ending bound offset */
+ Datum startOffsetValue; /* result of startOffset evaluation */
+ Datum endOffsetValue; /* result of endOffset evaluation */
+
+ /* these fields are used with RANGE offset PRECEDING/FOLLOWING: */
+ FmgrInfo startInRangeFunc; /* in_range function for startOffset */
+ FmgrInfo endInRangeFunc; /* in_range function for endOffset */
+ Oid inRangeColl; /* collation for in_range tests */
+ bool inRangeAsc; /* use ASC sort order for in_range tests? */
+ bool inRangeNullsFirst; /* nulls sort first for in_range tests? */
+
+ /* these fields are used in GROUPS mode: */
+ int64 currentgroup; /* peer group # of current row in partition */
+ int64 frameheadgroup; /* peer group # of frame head row */
+ int64 frametailgroup; /* peer group # of frame tail row */
+ int64 groupheadpos; /* current row's peer group head position */
+ int64 grouptailpos; /* " " " " tail position (group end+1) */
+
+ MemoryContext partcontext; /* context for partition-lifespan data */
+ MemoryContext aggcontext; /* shared context for aggregate working data */
+ MemoryContext curaggcontext; /* current aggregate's working data */
+ ExprContext *tmpcontext; /* short-term evaluation context */
+
+ bool all_first; /* true if the scan is starting */
+ bool all_done; /* true if the scan is finished */
+ bool partition_spooled; /* true if all tuples in current partition
+ * have been spooled into tuplestore */
+ bool more_partitions; /* true if there's more partitions after
+ * this one */
+ bool framehead_valid; /* true if frameheadpos is known up to
+ * date for current row */
+ bool frametail_valid; /* true if frametailpos is known up to
+ * date for current row */
+ bool grouptail_valid; /* true if grouptailpos is known up to
+ * date for current row */
+
+ TupleTableSlot *first_part_slot; /* first tuple of current or next
+ * partition */
+ TupleTableSlot *framehead_slot; /* first tuple of current frame */
+ TupleTableSlot *frametail_slot; /* first tuple after current frame */
+
+ /* temporary slots for tuples fetched back from tuplestore */
+ TupleTableSlot *agg_row_slot;
+ TupleTableSlot *temp_slot_1;
+ TupleTableSlot *temp_slot_2;
+} WindowAggState;
+
+/* ----------------
+ * UniqueState information
+ *
+ * Unique nodes are used "on top of" sort nodes to discard
+ * duplicate tuples returned from the sort phase. Basically
+ * all it does is compare the current tuple from the subplan
+ * with the previously fetched tuple (stored in its result slot).
+ * If the two are identical in all interesting fields, then
+ * we just fetch another tuple from the sort and try again.
+ * ----------------
+ */
+typedef struct UniqueState
+{
+ PlanState ps; /* its first field is NodeTag */
+ ExprState *eqfunction; /* tuple equality qual */
+} UniqueState;
+
+/* ----------------
+ * GatherState information
+ *
+ * Gather nodes launch 1 or more parallel workers, run a subplan
+ * in those workers, and collect the results.
+ * ----------------
+ */
+typedef struct GatherState
+{
+ PlanState ps; /* its first field is NodeTag */
+ bool initialized; /* workers launched? */
+ bool need_to_scan_locally; /* need to read from local plan? */
+ int64 tuples_needed; /* tuple bound, see ExecSetTupleBound */
+ /* these fields are set up once: */
+ TupleTableSlot *funnel_slot;
+ struct ParallelExecutorInfo *pei;
+ /* all remaining fields are reinitialized during a rescan: */
+ int nworkers_launched; /* original number of workers */
+ int nreaders; /* number of still-active workers */
+ int nextreader; /* next one to try to read from */
+ struct TupleQueueReader **reader; /* array with nreaders active entries */
+} GatherState;
+
+/* ----------------
+ * GatherMergeState information
+ *
+ * Gather merge nodes launch 1 or more parallel workers, run a
+ * subplan which produces sorted output in each worker, and then
+ * merge the results into a single sorted stream.
+ * ----------------
+ */
+struct GMReaderTupleBuffer; /* private in nodeGatherMerge.c */
+
+typedef struct GatherMergeState
+{
+ PlanState ps; /* its first field is NodeTag */
+ bool initialized; /* workers launched? */
+ bool gm_initialized; /* gather_merge_init() done? */
+ bool need_to_scan_locally; /* need to read from local plan? */
+ int64 tuples_needed; /* tuple bound, see ExecSetTupleBound */
+ /* these fields are set up once: */
+ TupleDesc tupDesc; /* descriptor for subplan result tuples */
+ int gm_nkeys; /* number of sort columns */
+ SortSupport gm_sortkeys; /* array of length gm_nkeys */
+ struct ParallelExecutorInfo *pei;
+ /* all remaining fields are reinitialized during a rescan */
+ /* (but the arrays are not reallocated, just cleared) */
+ int nworkers_launched; /* original number of workers */
+ int nreaders; /* number of active workers */
+ TupleTableSlot **gm_slots; /* array with nreaders+1 entries */
+ struct TupleQueueReader **reader; /* array with nreaders active entries */
+ struct GMReaderTupleBuffer *gm_tuple_buffers; /* nreaders tuple buffers */
+ struct binaryheap *gm_heap; /* binary heap of slot indices */
+} GatherMergeState;
+
+/* ----------------
+ * Values displayed by EXPLAIN ANALYZE
+ * ----------------
+ */
+typedef struct HashInstrumentation
+{
+ int nbuckets; /* number of buckets at end of execution */
+ int nbuckets_original; /* planned number of buckets */
+ int nbatch; /* number of batches at end of execution */
+ int nbatch_original; /* planned number of batches */
+ Size space_peak; /* peak memory usage in bytes */
+} HashInstrumentation;
+
+/* ----------------
+ * Shared memory container for per-worker hash information
+ * ----------------
+ */
+typedef struct SharedHashInfo
+{
+ int num_workers;
+ HashInstrumentation hinstrument[FLEXIBLE_ARRAY_MEMBER];
+} SharedHashInfo;
+
+/* ----------------
+ * HashState information
+ * ----------------
+ */
+typedef struct HashState
+{
+ PlanState ps; /* its first field is NodeTag */
+ HashJoinTable hashtable; /* hash table for the hashjoin */
+ List *hashkeys; /* list of ExprState nodes */
+
+ /*
+ * In a parallelized hash join, the leader retains a pointer to the
+ * shared-memory stats area in its shared_info field, and then copies the
+ * shared-memory info back to local storage before DSM shutdown. The
+ * shared_info field remains NULL in workers, or in non-parallel joins.
+ */
+ SharedHashInfo *shared_info;
+
+ /*
+ * If we are collecting hash stats, this points to an initially-zeroed
+ * collection area, which could be either local storage or in shared
+ * memory; either way it's for just one process.
+ */
+ HashInstrumentation *hinstrument;
+
+ /* Parallel hash state. */
+ struct ParallelHashJoinState *parallel_state;
+} HashState;
+
+/* ----------------
+ * SetOpState information
+ *
+ * Even in "sorted" mode, SetOp nodes are more complex than a simple
+ * Unique, since we have to count how many duplicates to return. But
+ * we also support hashing, so this is really more like a cut-down
+ * form of Agg.
+ * ----------------
+ */
+/* this struct is private in nodeSetOp.c: */
+typedef struct SetOpStatePerGroupData *SetOpStatePerGroup;
+
+typedef struct SetOpState
+{
+ PlanState ps; /* its first field is NodeTag */
+ ExprState *eqfunction; /* equality comparator */
+ Oid *eqfuncoids; /* per-grouping-field equality fns */
+ FmgrInfo *hashfunctions; /* per-grouping-field hash fns */
+ bool setop_done; /* indicates completion of output scan */
+ long numOutput; /* number of dups left to output */
+ /* these fields are used in SETOP_SORTED mode: */
+ SetOpStatePerGroup pergroup; /* per-group working state */
+ HeapTuple grp_firstTuple; /* copy of first tuple of current group */
+ /* these fields are used in SETOP_HASHED mode: */
+ TupleHashTable hashtable; /* hash table with one entry per group */
+ MemoryContext tableContext; /* memory context containing hash table */
+ bool table_filled; /* hash table filled yet? */
+ TupleHashIterator hashiter; /* for iterating through hash table */
+} SetOpState;
+
+/* ----------------
+ * LockRowsState information
+ *
+ * LockRows nodes are used to enforce FOR [KEY] UPDATE/SHARE locking.
+ * ----------------
+ */
+typedef struct LockRowsState
+{
+ PlanState ps; /* its first field is NodeTag */
+ List *lr_arowMarks; /* List of ExecAuxRowMarks */
+ EPQState lr_epqstate; /* for evaluating EvalPlanQual rechecks */
+} LockRowsState;
+
+/* ----------------
+ * LimitState information
+ *
+ * Limit nodes are used to enforce LIMIT/OFFSET clauses.
+ * They just select the desired subrange of their subplan's output.
+ *
+ * offset is the number of initial tuples to skip (0 does nothing).
+ * count is the number of tuples to return after skipping the offset tuples.
+ * If no limit count was specified, count is undefined and noCount is true.
+ * When lstate == LIMIT_INITIAL, offset/count/noCount haven't been set yet.
+ * ----------------
+ */
+typedef enum
+{
+ LIMIT_INITIAL, /* initial state for LIMIT node */
+ LIMIT_RESCAN, /* rescan after recomputing parameters */
+ LIMIT_EMPTY, /* there are no returnable rows */
+ LIMIT_INWINDOW, /* have returned a row in the window */
+ LIMIT_WINDOWEND_TIES, /* have returned a tied row */
+ LIMIT_SUBPLANEOF, /* at EOF of subplan (within window) */
+ LIMIT_WINDOWEND, /* stepped off end of window */
+ LIMIT_WINDOWSTART /* stepped off beginning of window */
+} LimitStateCond;
+
+typedef struct LimitState
+{
+ PlanState ps; /* its first field is NodeTag */
+ ExprState *limitOffset; /* OFFSET parameter, or NULL if none */
+ ExprState *limitCount; /* COUNT parameter, or NULL if none */
+ LimitOption limitOption; /* limit specification type */
+ int64 offset; /* current OFFSET value */
+ int64 count; /* current COUNT, if any */
+ bool noCount; /* if true, ignore count */
+ LimitStateCond lstate; /* state machine status, as above */
+ int64 position; /* 1-based index of last tuple returned */
+ TupleTableSlot *subSlot; /* tuple last obtained from subplan */
+ ExprState *eqfunction; /* tuple equality qual in case of WITH TIES
+ * option */
+ TupleTableSlot *last_slot; /* slot for evaluation of ties */
+} LimitState;
+
+#endif /* EXECNODES_H */
diff --git a/src/include/nodes/extensible.h b/src/include/nodes/extensible.h
new file mode 100644
index 0000000..d7bf0ba
--- /dev/null
+++ b/src/include/nodes/extensible.h
@@ -0,0 +1,160 @@
+/*-------------------------------------------------------------------------
+ *
+ * extensible.h
+ * Definitions for extensible nodes and custom scans
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/extensible.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXTENSIBLE_H
+#define EXTENSIBLE_H
+
+#include "access/parallel.h"
+#include "commands/explain.h"
+#include "nodes/execnodes.h"
+#include "nodes/pathnodes.h"
+#include "nodes/plannodes.h"
+
+/* maximum length of an extensible node identifier */
+#define EXTNODENAME_MAX_LEN 64
+
+/*
+ * An extensible node is a new type of node defined by an extension. The
+ * type is always T_ExtensibleNode, while the extnodename identifies the
+ * specific type of node. extnodename can be looked up to find the
+ * ExtensibleNodeMethods for this node type.
+ */
+typedef struct ExtensibleNode
+{
+ NodeTag type;
+ const char *extnodename; /* identifier of ExtensibleNodeMethods */
+} ExtensibleNode;
+
+/*
+ * node_size is the size of an extensible node of this type in bytes.
+ *
+ * nodeCopy is a function which performs a deep copy from oldnode to newnode.
+ * It does not need to copy type or extnodename, which are copied by the
+ * core system.
+ *
+ * nodeEqual is a function which performs a deep equality comparison between
+ * a and b and returns true or false accordingly. It does not need to compare
+ * type or extnodename, which are compared by the core system.
+ *
+ * nodeOut is a serialization function for the node type. It should use the
+ * output conventions typical for outfuncs.c. It does not need to output
+ * type or extnodename; the core system handles those.
+ *
+ * nodeRead is a deserialization function for the node type. It does not need
+ * to read type or extnodename; the core system handles those. It should fetch
+ * the next token using pg_strtok() from the current input stream, and then
+ * reconstruct the private fields according to the manner in readfuncs.c.
+ *
+ * All callbacks are mandatory.
+ */
+typedef struct ExtensibleNodeMethods
+{
+ const char *extnodename;
+ Size node_size;
+ void (*nodeCopy) (struct ExtensibleNode *newnode,
+ const struct ExtensibleNode *oldnode);
+ bool (*nodeEqual) (const struct ExtensibleNode *a,
+ const struct ExtensibleNode *b);
+ void (*nodeOut) (struct StringInfoData *str,
+ const struct ExtensibleNode *node);
+ void (*nodeRead) (struct ExtensibleNode *node);
+} ExtensibleNodeMethods;
+
+extern void RegisterExtensibleNodeMethods(const ExtensibleNodeMethods *method);
+extern const ExtensibleNodeMethods *GetExtensibleNodeMethods(const char *name,
+ bool missing_ok);
+
+/*
+ * Flags for custom paths, indicating what capabilities the resulting scan
+ * will have.
+ */
+#define CUSTOMPATH_SUPPORT_BACKWARD_SCAN 0x0001
+#define CUSTOMPATH_SUPPORT_MARK_RESTORE 0x0002
+
+/*
+ * Custom path methods. Mostly, we just need to know how to convert a
+ * CustomPath to a plan.
+ */
+typedef struct CustomPathMethods
+{
+ const char *CustomName;
+
+ /* Convert Path to a Plan */
+ struct Plan *(*PlanCustomPath) (PlannerInfo *root,
+ RelOptInfo *rel,
+ struct CustomPath *best_path,
+ List *tlist,
+ List *clauses,
+ List *custom_plans);
+ struct List *(*ReparameterizeCustomPathByChild) (PlannerInfo *root,
+ List *custom_private,
+ RelOptInfo *child_rel);
+} CustomPathMethods;
+
+/*
+ * Custom scan. Here again, there's not much to do: we need to be able to
+ * generate a ScanState corresponding to the scan.
+ */
+typedef struct CustomScanMethods
+{
+ const char *CustomName;
+
+ /* Create execution state (CustomScanState) from a CustomScan plan node */
+ Node *(*CreateCustomScanState) (CustomScan *cscan);
+} CustomScanMethods;
+
+/*
+ * Execution-time methods for a CustomScanState. This is more complex than
+ * what we need for a custom path or scan.
+ */
+typedef struct CustomExecMethods
+{
+ const char *CustomName;
+
+ /* Required executor methods */
+ void (*BeginCustomScan) (CustomScanState *node,
+ EState *estate,
+ int eflags);
+ TupleTableSlot *(*ExecCustomScan) (CustomScanState *node);
+ void (*EndCustomScan) (CustomScanState *node);
+ void (*ReScanCustomScan) (CustomScanState *node);
+
+ /* Optional methods: needed if mark/restore is supported */
+ void (*MarkPosCustomScan) (CustomScanState *node);
+ void (*RestrPosCustomScan) (CustomScanState *node);
+
+ /* Optional methods: needed if parallel execution is supported */
+ Size (*EstimateDSMCustomScan) (CustomScanState *node,
+ ParallelContext *pcxt);
+ void (*InitializeDSMCustomScan) (CustomScanState *node,
+ ParallelContext *pcxt,
+ void *coordinate);
+ void (*ReInitializeDSMCustomScan) (CustomScanState *node,
+ ParallelContext *pcxt,
+ void *coordinate);
+ void (*InitializeWorkerCustomScan) (CustomScanState *node,
+ shm_toc *toc,
+ void *coordinate);
+ void (*ShutdownCustomScan) (CustomScanState *node);
+
+ /* Optional: print additional information in EXPLAIN */
+ void (*ExplainCustomScan) (CustomScanState *node,
+ List *ancestors,
+ ExplainState *es);
+} CustomExecMethods;
+
+extern void RegisterCustomScanMethods(const CustomScanMethods *methods);
+extern const CustomScanMethods *GetCustomScanMethods(const char *CustomName,
+ bool missing_ok);
+
+#endif /* EXTENSIBLE_H */
diff --git a/src/include/nodes/lockoptions.h b/src/include/nodes/lockoptions.h
new file mode 100644
index 0000000..56dfe32
--- /dev/null
+++ b/src/include/nodes/lockoptions.h
@@ -0,0 +1,61 @@
+/*-------------------------------------------------------------------------
+ *
+ * lockoptions.h
+ * Common header for some locking-related declarations.
+ *
+ *
+ * Copyright (c) 2014-2020, PostgreSQL Global Development Group
+ *
+ * src/include/nodes/lockoptions.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LOCKOPTIONS_H
+#define LOCKOPTIONS_H
+
+/*
+ * This enum represents the different strengths of FOR UPDATE/SHARE clauses.
+ * The ordering here is important, because the highest numerical value takes
+ * precedence when a RTE is specified multiple ways. See applyLockingClause.
+ */
+typedef enum LockClauseStrength
+{
+ LCS_NONE, /* no such clause - only used in PlanRowMark */
+ LCS_FORKEYSHARE, /* FOR KEY SHARE */
+ LCS_FORSHARE, /* FOR SHARE */
+ LCS_FORNOKEYUPDATE, /* FOR NO KEY UPDATE */
+ LCS_FORUPDATE /* FOR UPDATE */
+} LockClauseStrength;
+
+/*
+ * This enum controls how to deal with rows being locked by FOR UPDATE/SHARE
+ * clauses (i.e., it represents the NOWAIT and SKIP LOCKED options).
+ * The ordering here is important, because the highest numerical value takes
+ * precedence when a RTE is specified multiple ways. See applyLockingClause.
+ */
+typedef enum LockWaitPolicy
+{
+ /* Wait for the lock to become available (default behavior) */
+ LockWaitBlock,
+ /* Skip rows that can't be locked (SKIP LOCKED) */
+ LockWaitSkip,
+ /* Raise an error if a row cannot be locked (NOWAIT) */
+ LockWaitError
+} LockWaitPolicy;
+
+/*
+ * Possible lock modes for a tuple.
+ */
+typedef enum LockTupleMode
+{
+ /* SELECT FOR KEY SHARE */
+ LockTupleKeyShare,
+ /* SELECT FOR SHARE */
+ LockTupleShare,
+ /* SELECT FOR NO KEY UPDATE, and UPDATEs that don't modify key columns */
+ LockTupleNoKeyExclusive,
+ /* SELECT FOR UPDATE, UPDATEs that modify key columns, and DELETE */
+ LockTupleExclusive
+} LockTupleMode;
+
+#endif /* LOCKOPTIONS_H */
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
new file mode 100644
index 0000000..31d9aed
--- /dev/null
+++ b/src/include/nodes/makefuncs.h
@@ -0,0 +1,108 @@
+/*-------------------------------------------------------------------------
+ *
+ * makefuncs.h
+ * prototypes for the creator functions of various nodes
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/makefuncs.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef MAKEFUNC_H
+#define MAKEFUNC_H
+
+#include "nodes/execnodes.h"
+#include "nodes/parsenodes.h"
+
+
+extern A_Expr *makeA_Expr(A_Expr_Kind kind, List *name,
+ Node *lexpr, Node *rexpr, int location);
+
+extern A_Expr *makeSimpleA_Expr(A_Expr_Kind kind, char *name,
+ Node *lexpr, Node *rexpr, int location);
+
+extern Var *makeVar(Index varno,
+ AttrNumber varattno,
+ Oid vartype,
+ int32 vartypmod,
+ Oid varcollid,
+ Index varlevelsup);
+
+extern Var *makeVarFromTargetEntry(Index varno,
+ TargetEntry *tle);
+
+extern Var *makeWholeRowVar(RangeTblEntry *rte,
+ Index varno,
+ Index varlevelsup,
+ bool allowScalar);
+
+extern TargetEntry *makeTargetEntry(Expr *expr,
+ AttrNumber resno,
+ char *resname,
+ bool resjunk);
+
+extern TargetEntry *flatCopyTargetEntry(TargetEntry *src_tle);
+
+extern FromExpr *makeFromExpr(List *fromlist, Node *quals);
+
+extern Const *makeConst(Oid consttype,
+ int32 consttypmod,
+ Oid constcollid,
+ int constlen,
+ Datum constvalue,
+ bool constisnull,
+ bool constbyval);
+
+extern Const *makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid);
+
+extern Node *makeBoolConst(bool value, bool isnull);
+
+extern Expr *makeBoolExpr(BoolExprType boolop, List *args, int location);
+
+extern Alias *makeAlias(const char *aliasname, List *colnames);
+
+extern RelabelType *makeRelabelType(Expr *arg, Oid rtype, int32 rtypmod,
+ Oid rcollid, CoercionForm rformat);
+
+extern RangeVar *makeRangeVar(char *schemaname, char *relname, int location);
+
+extern TypeName *makeTypeName(char *typnam);
+extern TypeName *makeTypeNameFromNameList(List *names);
+extern TypeName *makeTypeNameFromOid(Oid typeOid, int32 typmod);
+
+extern ColumnDef *makeColumnDef(const char *colname,
+ Oid typeOid, int32 typmod, Oid collOid);
+
+extern FuncExpr *makeFuncExpr(Oid funcid, Oid rettype, List *args,
+ Oid funccollid, Oid inputcollid, CoercionForm fformat);
+
+extern FuncCall *makeFuncCall(List *name, List *args, int location);
+
+extern Expr *make_opclause(Oid opno, Oid opresulttype, bool opretset,
+ Expr *leftop, Expr *rightop,
+ Oid opcollid, Oid inputcollid);
+
+extern Expr *make_andclause(List *andclauses);
+extern Expr *make_orclause(List *orclauses);
+extern Expr *make_notclause(Expr *notclause);
+
+extern Node *make_and_qual(Node *qual1, Node *qual2);
+extern Expr *make_ands_explicit(List *andclauses);
+extern List *make_ands_implicit(Expr *clause);
+
+extern IndexInfo *makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid,
+ List *expressions, List *predicates,
+ bool unique, bool isready, bool concurrent);
+
+extern DefElem *makeDefElem(char *name, Node *arg, int location);
+extern DefElem *makeDefElemExtended(char *nameSpace, char *name, Node *arg,
+ DefElemAction defaction, int location);
+
+extern GroupingSet *makeGroupingSet(GroupingSetKind kind, List *content, int location);
+
+extern VacuumRelation *makeVacuumRelation(RangeVar *relation, Oid oid, List *va_cols);
+
+#endif /* MAKEFUNC_H */
diff --git a/src/include/nodes/memnodes.h b/src/include/nodes/memnodes.h
new file mode 100644
index 0000000..c9f2bbc
--- /dev/null
+++ b/src/include/nodes/memnodes.h
@@ -0,0 +1,108 @@
+/*-------------------------------------------------------------------------
+ *
+ * memnodes.h
+ * POSTGRES memory context node definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/memnodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef MEMNODES_H
+#define MEMNODES_H
+
+#include "nodes/nodes.h"
+
+/*
+ * MemoryContextCounters
+ * Summarization state for MemoryContextStats collection.
+ *
+ * The set of counters in this struct is biased towards AllocSet; if we ever
+ * add any context types that are based on fundamentally different approaches,
+ * we might need more or different counters here. A possible API spec then
+ * would be to print only nonzero counters, but for now we just summarize in
+ * the format historically used by AllocSet.
+ */
+typedef struct MemoryContextCounters
+{
+ Size nblocks; /* Total number of malloc blocks */
+ Size freechunks; /* Total number of free chunks */
+ Size totalspace; /* Total bytes requested from malloc */
+ Size freespace; /* The unused portion of totalspace */
+} MemoryContextCounters;
+
+/*
+ * MemoryContext
+ * A logical context in which memory allocations occur.
+ *
+ * MemoryContext itself is an abstract type that can have multiple
+ * implementations.
+ * The function pointers in MemoryContextMethods define one specific
+ * implementation of MemoryContext --- they are a virtual function table
+ * in C++ terms.
+ *
+ * Node types that are actual implementations of memory contexts must
+ * begin with the same fields as MemoryContextData.
+ *
+ * Note: for largely historical reasons, typedef MemoryContext is a pointer
+ * to the context struct rather than the struct type itself.
+ */
+
+typedef void (*MemoryStatsPrintFunc) (MemoryContext context, void *passthru,
+ const char *stats_string);
+
+typedef struct MemoryContextMethods
+{
+ void *(*alloc) (MemoryContext context, Size size);
+ /* call this free_p in case someone #define's free() */
+ void (*free_p) (MemoryContext context, void *pointer);
+ void *(*realloc) (MemoryContext context, void *pointer, Size size);
+ void (*reset) (MemoryContext context);
+ void (*delete_context) (MemoryContext context);
+ Size (*get_chunk_space) (MemoryContext context, void *pointer);
+ bool (*is_empty) (MemoryContext context);
+ void (*stats) (MemoryContext context,
+ MemoryStatsPrintFunc printfunc, void *passthru,
+ MemoryContextCounters *totals);
+#ifdef MEMORY_CONTEXT_CHECKING
+ void (*check) (MemoryContext context);
+#endif
+} MemoryContextMethods;
+
+
+typedef struct MemoryContextData
+{
+ NodeTag type; /* identifies exact kind of context */
+ /* these two fields are placed here to minimize alignment wastage: */
+ bool isReset; /* T = no space alloced since last reset */
+ bool allowInCritSection; /* allow palloc in critical section */
+ Size mem_allocated; /* track memory allocated for this context */
+ const MemoryContextMethods *methods; /* virtual function table */
+ MemoryContext parent; /* NULL if no parent (toplevel context) */
+ MemoryContext firstchild; /* head of linked list of children */
+ MemoryContext prevchild; /* previous child of same parent */
+ MemoryContext nextchild; /* next child of same parent */
+ const char *name; /* context name (just for debugging) */
+ const char *ident; /* context ID if any (just for debugging) */
+ MemoryContextCallback *reset_cbs; /* list of reset/delete callbacks */
+} MemoryContextData;
+
+/* utils/palloc.h contains typedef struct MemoryContextData *MemoryContext */
+
+
+/*
+ * MemoryContextIsValid
+ * True iff memory context is valid.
+ *
+ * Add new context types to the set accepted by this macro.
+ */
+#define MemoryContextIsValid(context) \
+ ((context) != NULL && \
+ (IsA((context), AllocSetContext) || \
+ IsA((context), SlabContext) || \
+ IsA((context), GenerationContext)))
+
+#endif /* MEMNODES_H */
diff --git a/src/include/nodes/nodeFuncs.h b/src/include/nodes/nodeFuncs.h
new file mode 100644
index 0000000..9cc56ee
--- /dev/null
+++ b/src/include/nodes/nodeFuncs.h
@@ -0,0 +1,162 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeFuncs.h
+ * Various general-purpose manipulations of Node trees
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/nodeFuncs.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODEFUNCS_H
+#define NODEFUNCS_H
+
+#include "nodes/parsenodes.h"
+
+
+/* flags bits for query_tree_walker and query_tree_mutator */
+#define QTW_IGNORE_RT_SUBQUERIES 0x01 /* subqueries in rtable */
+#define QTW_IGNORE_CTE_SUBQUERIES 0x02 /* subqueries in cteList */
+#define QTW_IGNORE_RC_SUBQUERIES 0x03 /* both of above */
+#define QTW_IGNORE_JOINALIASES 0x04 /* JOIN alias var lists */
+#define QTW_IGNORE_RANGE_TABLE 0x08 /* skip rangetable entirely */
+#define QTW_EXAMINE_RTES_BEFORE 0x10 /* examine RTE nodes before their
+ * contents */
+#define QTW_EXAMINE_RTES_AFTER 0x20 /* examine RTE nodes after their
+ * contents */
+#define QTW_DONT_COPY_QUERY 0x40 /* do not copy top Query */
+#define QTW_EXAMINE_SORTGROUP 0x80 /* include SortGroupNode lists */
+
+/* callback function for check_functions_in_node */
+typedef bool (*check_function_callback) (Oid func_id, void *context);
+
+
+extern Oid exprType(const Node *expr);
+extern int32 exprTypmod(const Node *expr);
+extern bool exprIsLengthCoercion(const Node *expr, int32 *coercedTypmod);
+extern Node *applyRelabelType(Node *arg, Oid rtype, int32 rtypmod, Oid rcollid,
+ CoercionForm rformat, int rlocation,
+ bool overwrite_ok);
+extern Node *relabel_to_typmod(Node *expr, int32 typmod);
+extern Node *strip_implicit_coercions(Node *node);
+extern bool expression_returns_set(Node *clause);
+
+extern Oid exprCollation(const Node *expr);
+extern Oid exprInputCollation(const Node *expr);
+extern void exprSetCollation(Node *expr, Oid collation);
+extern void exprSetInputCollation(Node *expr, Oid inputcollation);
+
+extern int exprLocation(const Node *expr);
+
+extern void fix_opfuncids(Node *node);
+extern void set_opfuncid(OpExpr *opexpr);
+extern void set_sa_opfuncid(ScalarArrayOpExpr *opexpr);
+
+/* Is clause a FuncExpr clause? */
+static inline bool
+is_funcclause(const void *clause)
+{
+ return clause != NULL && IsA(clause, FuncExpr);
+}
+
+/* Is clause an OpExpr clause? */
+static inline bool
+is_opclause(const void *clause)
+{
+ return clause != NULL && IsA(clause, OpExpr);
+}
+
+/* Extract left arg of a binary opclause, or only arg of a unary opclause */
+static inline Node *
+get_leftop(const void *clause)
+{
+ const OpExpr *expr = (const OpExpr *) clause;
+
+ if (expr->args != NIL)
+ return (Node *) linitial(expr->args);
+ else
+ return NULL;
+}
+
+/* Extract right arg of a binary opclause (NULL if it's a unary opclause) */
+static inline Node *
+get_rightop(const void *clause)
+{
+ const OpExpr *expr = (const OpExpr *) clause;
+
+ if (list_length(expr->args) >= 2)
+ return (Node *) lsecond(expr->args);
+ else
+ return NULL;
+}
+
+/* Is clause an AND clause? */
+static inline bool
+is_andclause(const void *clause)
+{
+ return (clause != NULL &&
+ IsA(clause, BoolExpr) &&
+ ((const BoolExpr *) clause)->boolop == AND_EXPR);
+}
+
+/* Is clause an OR clause? */
+static inline bool
+is_orclause(const void *clause)
+{
+ return (clause != NULL &&
+ IsA(clause, BoolExpr) &&
+ ((const BoolExpr *) clause)->boolop == OR_EXPR);
+}
+
+/* Is clause a NOT clause? */
+static inline bool
+is_notclause(const void *clause)
+{
+ return (clause != NULL &&
+ IsA(clause, BoolExpr) &&
+ ((const BoolExpr *) clause)->boolop == NOT_EXPR);
+}
+
+/* Extract argument from a clause known to be a NOT clause */
+static inline Expr *
+get_notclausearg(const void *notclause)
+{
+ return (Expr *) linitial(((const BoolExpr *) notclause)->args);
+}
+
+extern bool check_functions_in_node(Node *node, check_function_callback checker,
+ void *context);
+
+extern bool expression_tree_walker(Node *node, bool (*walker) (),
+ void *context);
+extern Node *expression_tree_mutator(Node *node, Node *(*mutator) (),
+ void *context);
+
+extern bool query_tree_walker(Query *query, bool (*walker) (),
+ void *context, int flags);
+extern Query *query_tree_mutator(Query *query, Node *(*mutator) (),
+ void *context, int flags);
+
+extern bool range_table_walker(List *rtable, bool (*walker) (),
+ void *context, int flags);
+extern List *range_table_mutator(List *rtable, Node *(*mutator) (),
+ void *context, int flags);
+
+extern bool range_table_entry_walker(RangeTblEntry *rte, bool (*walker) (),
+ void *context, int flags);
+
+extern bool query_or_expression_tree_walker(Node *node, bool (*walker) (),
+ void *context, int flags);
+extern Node *query_or_expression_tree_mutator(Node *node, Node *(*mutator) (),
+ void *context, int flags);
+
+extern bool raw_expression_tree_walker(Node *node, bool (*walker) (),
+ void *context);
+
+struct PlanState;
+extern bool planstate_tree_walker(struct PlanState *planstate, bool (*walker) (),
+ void *context);
+
+#endif /* NODEFUNCS_H */
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
new file mode 100644
index 0000000..381d84b
--- /dev/null
+++ b/src/include/nodes/nodes.h
@@ -0,0 +1,842 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodes.h
+ * Definitions for tagged nodes.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/nodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NODES_H
+#define NODES_H
+
+/*
+ * The first field of every node is NodeTag. Each node created (with makeNode)
+ * will have one of the following tags as the value of its first field.
+ *
+ * Note that inserting or deleting node types changes the numbers of other
+ * node types later in the list. This is no problem during development, since
+ * the node numbers are never stored on disk. But don't do it in a released
+ * branch, because that would represent an ABI break for extensions.
+ */
+typedef enum NodeTag
+{
+ T_Invalid = 0,
+
+ /*
+ * TAGS FOR EXECUTOR NODES (execnodes.h)
+ */
+ T_IndexInfo,
+ T_ExprContext,
+ T_ProjectionInfo,
+ T_JunkFilter,
+ T_OnConflictSetState,
+ T_ResultRelInfo,
+ T_EState,
+ T_TupleTableSlot,
+
+ /*
+ * TAGS FOR PLAN NODES (plannodes.h)
+ */
+ T_Plan,
+ T_Result,
+ T_ProjectSet,
+ T_ModifyTable,
+ T_Append,
+ T_MergeAppend,
+ T_RecursiveUnion,
+ T_BitmapAnd,
+ T_BitmapOr,
+ T_Scan,
+ T_SeqScan,
+ T_SampleScan,
+ T_IndexScan,
+ T_IndexOnlyScan,
+ T_BitmapIndexScan,
+ T_BitmapHeapScan,
+ T_TidScan,
+ T_SubqueryScan,
+ T_FunctionScan,
+ T_ValuesScan,
+ T_TableFuncScan,
+ T_CteScan,
+ T_NamedTuplestoreScan,
+ T_WorkTableScan,
+ T_ForeignScan,
+ T_CustomScan,
+ T_Join,
+ T_NestLoop,
+ T_MergeJoin,
+ T_HashJoin,
+ T_Material,
+ T_Sort,
+ T_IncrementalSort,
+ T_Group,
+ T_Agg,
+ T_WindowAgg,
+ T_Unique,
+ T_Gather,
+ T_GatherMerge,
+ T_Hash,
+ T_SetOp,
+ T_LockRows,
+ T_Limit,
+ /* these aren't subclasses of Plan: */
+ T_NestLoopParam,
+ T_PlanRowMark,
+ T_PartitionPruneInfo,
+ T_PartitionedRelPruneInfo,
+ T_PartitionPruneStepOp,
+ T_PartitionPruneStepCombine,
+ T_PlanInvalItem,
+
+ /*
+ * TAGS FOR PLAN STATE NODES (execnodes.h)
+ *
+ * These should correspond one-to-one with Plan node types.
+ */
+ T_PlanState,
+ T_ResultState,
+ T_ProjectSetState,
+ T_ModifyTableState,
+ T_AppendState,
+ T_MergeAppendState,
+ T_RecursiveUnionState,
+ T_BitmapAndState,
+ T_BitmapOrState,
+ T_ScanState,
+ T_SeqScanState,
+ T_SampleScanState,
+ T_IndexScanState,
+ T_IndexOnlyScanState,
+ T_BitmapIndexScanState,
+ T_BitmapHeapScanState,
+ T_TidScanState,
+ T_SubqueryScanState,
+ T_FunctionScanState,
+ T_TableFuncScanState,
+ T_ValuesScanState,
+ T_CteScanState,
+ T_NamedTuplestoreScanState,
+ T_WorkTableScanState,
+ T_ForeignScanState,
+ T_CustomScanState,
+ T_JoinState,
+ T_NestLoopState,
+ T_MergeJoinState,
+ T_HashJoinState,
+ T_MaterialState,
+ T_SortState,
+ T_IncrementalSortState,
+ T_GroupState,
+ T_AggState,
+ T_WindowAggState,
+ T_UniqueState,
+ T_GatherState,
+ T_GatherMergeState,
+ T_HashState,
+ T_SetOpState,
+ T_LockRowsState,
+ T_LimitState,
+
+ /*
+ * TAGS FOR PRIMITIVE NODES (primnodes.h)
+ */
+ T_Alias,
+ T_RangeVar,
+ T_TableFunc,
+ T_Expr,
+ T_Var,
+ T_Const,
+ T_Param,
+ T_Aggref,
+ T_GroupingFunc,
+ T_WindowFunc,
+ T_SubscriptingRef,
+ T_FuncExpr,
+ T_NamedArgExpr,
+ T_OpExpr,
+ T_DistinctExpr,
+ T_NullIfExpr,
+ T_ScalarArrayOpExpr,
+ T_BoolExpr,
+ T_SubLink,
+ T_SubPlan,
+ T_AlternativeSubPlan,
+ T_FieldSelect,
+ T_FieldStore,
+ T_RelabelType,
+ T_CoerceViaIO,
+ T_ArrayCoerceExpr,
+ T_ConvertRowtypeExpr,
+ T_CollateExpr,
+ T_CaseExpr,
+ T_CaseWhen,
+ T_CaseTestExpr,
+ T_ArrayExpr,
+ T_RowExpr,
+ T_RowCompareExpr,
+ T_CoalesceExpr,
+ T_MinMaxExpr,
+ T_SQLValueFunction,
+ T_XmlExpr,
+ T_NullTest,
+ T_BooleanTest,
+ T_CoerceToDomain,
+ T_CoerceToDomainValue,
+ T_SetToDefault,
+ T_CurrentOfExpr,
+ T_NextValueExpr,
+ T_InferenceElem,
+ T_TargetEntry,
+ T_RangeTblRef,
+ T_JoinExpr,
+ T_FromExpr,
+ T_OnConflictExpr,
+ T_IntoClause,
+
+ /*
+ * TAGS FOR EXPRESSION STATE NODES (execnodes.h)
+ *
+ * ExprState represents the evaluation state for a whole expression tree.
+ * Most Expr-based plan nodes do not have a corresponding expression state
+ * node, they're fully handled within execExpr* - but sometimes the state
+ * needs to be shared with other parts of the executor, as for example
+ * with AggrefExprState, which nodeAgg.c has to modify.
+ */
+ T_ExprState,
+ T_AggrefExprState,
+ T_WindowFuncExprState,
+ T_SetExprState,
+ T_SubPlanState,
+ T_AlternativeSubPlanState,
+ T_DomainConstraintState,
+
+ /*
+ * TAGS FOR PLANNER NODES (pathnodes.h)
+ */
+ T_PlannerInfo,
+ T_PlannerGlobal,
+ T_RelOptInfo,
+ T_IndexOptInfo,
+ T_ForeignKeyOptInfo,
+ T_ParamPathInfo,
+ T_Path,
+ T_IndexPath,
+ T_BitmapHeapPath,
+ T_BitmapAndPath,
+ T_BitmapOrPath,
+ T_TidPath,
+ T_SubqueryScanPath,
+ T_ForeignPath,
+ T_CustomPath,
+ T_NestPath,
+ T_MergePath,
+ T_HashPath,
+ T_AppendPath,
+ T_MergeAppendPath,
+ T_GroupResultPath,
+ T_MaterialPath,
+ T_UniquePath,
+ T_GatherPath,
+ T_GatherMergePath,
+ T_ProjectionPath,
+ T_ProjectSetPath,
+ T_SortPath,
+ T_IncrementalSortPath,
+ T_GroupPath,
+ T_UpperUniquePath,
+ T_AggPath,
+ T_GroupingSetsPath,
+ T_MinMaxAggPath,
+ T_WindowAggPath,
+ T_SetOpPath,
+ T_RecursiveUnionPath,
+ T_LockRowsPath,
+ T_ModifyTablePath,
+ T_LimitPath,
+ /* these aren't subclasses of Path: */
+ T_EquivalenceClass,
+ T_EquivalenceMember,
+ T_PathKey,
+ T_PathTarget,
+ T_RestrictInfo,
+ T_IndexClause,
+ T_PlaceHolderVar,
+ T_SpecialJoinInfo,
+ T_AppendRelInfo,
+ T_PlaceHolderInfo,
+ T_MinMaxAggInfo,
+ T_PlannerParamItem,
+ T_RollupData,
+ T_GroupingSetData,
+ T_StatisticExtInfo,
+
+ /*
+ * TAGS FOR MEMORY NODES (memnodes.h)
+ */
+ T_MemoryContext,
+ T_AllocSetContext,
+ T_SlabContext,
+ T_GenerationContext,
+
+ /*
+ * TAGS FOR VALUE NODES (value.h)
+ */
+ T_Value,
+ T_Integer,
+ T_Float,
+ T_String,
+ T_BitString,
+ T_Null,
+
+ /*
+ * TAGS FOR LIST NODES (pg_list.h)
+ */
+ T_List,
+ T_IntList,
+ T_OidList,
+
+ /*
+ * TAGS FOR EXTENSIBLE NODES (extensible.h)
+ */
+ T_ExtensibleNode,
+
+ /*
+ * TAGS FOR STATEMENT NODES (mostly in parsenodes.h)
+ */
+ T_RawStmt,
+ T_Query,
+ T_PlannedStmt,
+ T_InsertStmt,
+ T_DeleteStmt,
+ T_UpdateStmt,
+ T_SelectStmt,
+ T_AlterTableStmt,
+ T_AlterTableCmd,
+ T_AlterDomainStmt,
+ T_SetOperationStmt,
+ T_GrantStmt,
+ T_GrantRoleStmt,
+ T_AlterDefaultPrivilegesStmt,
+ T_ClosePortalStmt,
+ T_ClusterStmt,
+ T_CopyStmt,
+ T_CreateStmt,
+ T_DefineStmt,
+ T_DropStmt,
+ T_TruncateStmt,
+ T_CommentStmt,
+ T_FetchStmt,
+ T_IndexStmt,
+ T_CreateFunctionStmt,
+ T_AlterFunctionStmt,
+ T_DoStmt,
+ T_RenameStmt,
+ T_RuleStmt,
+ T_NotifyStmt,
+ T_ListenStmt,
+ T_UnlistenStmt,
+ T_TransactionStmt,
+ T_ViewStmt,
+ T_LoadStmt,
+ T_CreateDomainStmt,
+ T_CreatedbStmt,
+ T_DropdbStmt,
+ T_VacuumStmt,
+ T_ExplainStmt,
+ T_CreateTableAsStmt,
+ T_CreateSeqStmt,
+ T_AlterSeqStmt,
+ T_VariableSetStmt,
+ T_VariableShowStmt,
+ T_DiscardStmt,
+ T_CreateTrigStmt,
+ T_CreatePLangStmt,
+ T_CreateRoleStmt,
+ T_AlterRoleStmt,
+ T_DropRoleStmt,
+ T_LockStmt,
+ T_ConstraintsSetStmt,
+ T_ReindexStmt,
+ T_CheckPointStmt,
+ T_CreateSchemaStmt,
+ T_AlterDatabaseStmt,
+ T_AlterDatabaseSetStmt,
+ T_AlterRoleSetStmt,
+ T_CreateConversionStmt,
+ T_CreateCastStmt,
+ T_CreateOpClassStmt,
+ T_CreateOpFamilyStmt,
+ T_AlterOpFamilyStmt,
+ T_PrepareStmt,
+ T_ExecuteStmt,
+ T_DeallocateStmt,
+ T_DeclareCursorStmt,
+ T_CreateTableSpaceStmt,
+ T_DropTableSpaceStmt,
+ T_AlterObjectDependsStmt,
+ T_AlterObjectSchemaStmt,
+ T_AlterOwnerStmt,
+ T_AlterOperatorStmt,
+ T_AlterTypeStmt,
+ T_DropOwnedStmt,
+ T_ReassignOwnedStmt,
+ T_CompositeTypeStmt,
+ T_CreateEnumStmt,
+ T_CreateRangeStmt,
+ T_AlterEnumStmt,
+ T_AlterTSDictionaryStmt,
+ T_AlterTSConfigurationStmt,
+ T_CreateFdwStmt,
+ T_AlterFdwStmt,
+ T_CreateForeignServerStmt,
+ T_AlterForeignServerStmt,
+ T_CreateUserMappingStmt,
+ T_AlterUserMappingStmt,
+ T_DropUserMappingStmt,
+ T_AlterTableSpaceOptionsStmt,
+ T_AlterTableMoveAllStmt,
+ T_SecLabelStmt,
+ T_CreateForeignTableStmt,
+ T_ImportForeignSchemaStmt,
+ T_CreateExtensionStmt,
+ T_AlterExtensionStmt,
+ T_AlterExtensionContentsStmt,
+ T_CreateEventTrigStmt,
+ T_AlterEventTrigStmt,
+ T_RefreshMatViewStmt,
+ T_ReplicaIdentityStmt,
+ T_AlterSystemStmt,
+ T_CreatePolicyStmt,
+ T_AlterPolicyStmt,
+ T_CreateTransformStmt,
+ T_CreateAmStmt,
+ T_CreatePublicationStmt,
+ T_AlterPublicationStmt,
+ T_CreateSubscriptionStmt,
+ T_AlterSubscriptionStmt,
+ T_DropSubscriptionStmt,
+ T_CreateStatsStmt,
+ T_AlterCollationStmt,
+ T_CallStmt,
+ T_AlterStatsStmt,
+
+ /*
+ * TAGS FOR PARSE TREE NODES (parsenodes.h)
+ */
+ T_A_Expr,
+ T_ColumnRef,
+ T_ParamRef,
+ T_A_Const,
+ T_FuncCall,
+ T_A_Star,
+ T_A_Indices,
+ T_A_Indirection,
+ T_A_ArrayExpr,
+ T_ResTarget,
+ T_MultiAssignRef,
+ T_TypeCast,
+ T_CollateClause,
+ T_SortBy,
+ T_WindowDef,
+ T_RangeSubselect,
+ T_RangeFunction,
+ T_RangeTableSample,
+ T_RangeTableFunc,
+ T_RangeTableFuncCol,
+ T_TypeName,
+ T_ColumnDef,
+ T_IndexElem,
+ T_Constraint,
+ T_DefElem,
+ T_RangeTblEntry,
+ T_RangeTblFunction,
+ T_TableSampleClause,
+ T_WithCheckOption,
+ T_SortGroupClause,
+ T_GroupingSet,
+ T_WindowClause,
+ T_ObjectWithArgs,
+ T_AccessPriv,
+ T_CreateOpClassItem,
+ T_TableLikeClause,
+ T_FunctionParameter,
+ T_LockingClause,
+ T_RowMarkClause,
+ T_XmlSerialize,
+ T_WithClause,
+ T_InferClause,
+ T_OnConflictClause,
+ T_CommonTableExpr,
+ T_RoleSpec,
+ T_TriggerTransition,
+ T_PartitionElem,
+ T_PartitionSpec,
+ T_PartitionBoundSpec,
+ T_PartitionRangeDatum,
+ T_PartitionCmd,
+ T_VacuumRelation,
+
+ /*
+ * TAGS FOR REPLICATION GRAMMAR PARSE NODES (replnodes.h)
+ */
+ T_IdentifySystemCmd,
+ T_BaseBackupCmd,
+ T_CreateReplicationSlotCmd,
+ T_DropReplicationSlotCmd,
+ T_StartReplicationCmd,
+ T_TimeLineHistoryCmd,
+ T_SQLCmd,
+
+ /*
+ * TAGS FOR RANDOM OTHER STUFF
+ *
+ * These are objects that aren't part of parse/plan/execute node tree
+ * structures, but we give them NodeTags anyway for identification
+ * purposes (usually because they are involved in APIs where we want to
+ * pass multiple object types through the same pointer).
+ */
+ T_TriggerData, /* in commands/trigger.h */
+ T_EventTriggerData, /* in commands/event_trigger.h */
+ T_ReturnSetInfo, /* in nodes/execnodes.h */
+ T_WindowObjectData, /* private in nodeWindowAgg.c */
+ T_TIDBitmap, /* in nodes/tidbitmap.h */
+ T_InlineCodeBlock, /* in nodes/parsenodes.h */
+ T_FdwRoutine, /* in foreign/fdwapi.h */
+ T_IndexAmRoutine, /* in access/amapi.h */
+ T_TableAmRoutine, /* in access/tableam.h */
+ T_TsmRoutine, /* in access/tsmapi.h */
+ T_ForeignKeyCacheInfo, /* in utils/rel.h */
+ T_CallContext, /* in nodes/parsenodes.h */
+ T_SupportRequestSimplify, /* in nodes/supportnodes.h */
+ T_SupportRequestSelectivity, /* in nodes/supportnodes.h */
+ T_SupportRequestCost, /* in nodes/supportnodes.h */
+ T_SupportRequestRows, /* in nodes/supportnodes.h */
+ T_SupportRequestIndexCondition /* in nodes/supportnodes.h */
+} NodeTag;
+
+/*
+ * The first field of a node of any type is guaranteed to be the NodeTag.
+ * Hence the type of any node can be gotten by casting it to Node. Declaring
+ * a variable to be of Node * (instead of void *) can also facilitate
+ * debugging.
+ */
+typedef struct Node
+{
+ NodeTag type;
+} Node;
+
+#define nodeTag(nodeptr) (((const Node*)(nodeptr))->type)
+
+/*
+ * newNode -
+ * create a new node of the specified size and tag the node with the
+ * specified tag.
+ *
+ * !WARNING!: Avoid using newNode directly. You should be using the
+ * macro makeNode. eg. to create a Query node, use makeNode(Query)
+ *
+ * Note: the size argument should always be a compile-time constant, so the
+ * apparent risk of multiple evaluation doesn't matter in practice.
+ */
+#ifdef __GNUC__
+
+/* With GCC, we can use a compound statement within an expression */
+#define newNode(size, tag) \
+({ Node *_result; \
+ AssertMacro((size) >= sizeof(Node)); /* need the tag, at least */ \
+ _result = (Node *) palloc0fast(size); \
+ _result->type = (tag); \
+ _result; \
+})
+#else
+
+/*
+ * There is no way to dereference the palloc'ed pointer to assign the
+ * tag, and also return the pointer itself, so we need a holder variable.
+ * Fortunately, this macro isn't recursive so we just define
+ * a global variable for this purpose.
+ */
+extern PGDLLIMPORT Node *newNodeMacroHolder;
+
+#define newNode(size, tag) \
+( \
+ AssertMacro((size) >= sizeof(Node)), /* need the tag, at least */ \
+ newNodeMacroHolder = (Node *) palloc0fast(size), \
+ newNodeMacroHolder->type = (tag), \
+ newNodeMacroHolder \
+)
+#endif /* __GNUC__ */
+
+
+#define makeNode(_type_) ((_type_ *) newNode(sizeof(_type_),T_##_type_))
+#define NodeSetTag(nodeptr,t) (((Node*)(nodeptr))->type = (t))
+
+#define IsA(nodeptr,_type_) (nodeTag(nodeptr) == T_##_type_)
+
+/*
+ * castNode(type, ptr) casts ptr to "type *", and if assertions are enabled,
+ * verifies that the node has the appropriate type (using its nodeTag()).
+ *
+ * Use an inline function when assertions are enabled, to avoid multiple
+ * evaluations of the ptr argument (which could e.g. be a function call).
+ */
+#ifdef USE_ASSERT_CHECKING
+static inline Node *
+castNodeImpl(NodeTag type, void *ptr)
+{
+ Assert(ptr == NULL || nodeTag(ptr) == type);
+ return (Node *) ptr;
+}
+#define castNode(_type_, nodeptr) ((_type_ *) castNodeImpl(T_##_type_, nodeptr))
+#else
+#define castNode(_type_, nodeptr) ((_type_ *) (nodeptr))
+#endif /* USE_ASSERT_CHECKING */
+
+
+/* ----------------------------------------------------------------
+ * extern declarations follow
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * nodes/{outfuncs.c,print.c}
+ */
+struct Bitmapset; /* not to include bitmapset.h here */
+struct StringInfoData; /* not to include stringinfo.h here */
+
+extern void outNode(struct StringInfoData *str, const void *obj);
+extern void outToken(struct StringInfoData *str, const char *s);
+extern void outBitmapset(struct StringInfoData *str,
+ const struct Bitmapset *bms);
+extern void outDatum(struct StringInfoData *str, uintptr_t value,
+ int typlen, bool typbyval);
+extern char *nodeToString(const void *obj);
+extern char *bmsToString(const struct Bitmapset *bms);
+
+/*
+ * nodes/{readfuncs.c,read.c}
+ */
+extern void *stringToNode(const char *str);
+#ifdef WRITE_READ_PARSE_PLAN_TREES
+extern void *stringToNodeWithLocations(const char *str);
+#endif
+extern struct Bitmapset *readBitmapset(void);
+extern uintptr_t readDatum(bool typbyval);
+extern bool *readBoolCols(int numCols);
+extern int *readIntCols(int numCols);
+extern Oid *readOidCols(int numCols);
+extern int16 *readAttrNumberCols(int numCols);
+
+/*
+ * nodes/copyfuncs.c
+ */
+extern void *copyObjectImpl(const void *obj);
+
+/* cast result back to argument type, if supported by compiler */
+#ifdef HAVE_TYPEOF
+#define copyObject(obj) ((typeof(obj)) copyObjectImpl(obj))
+#else
+#define copyObject(obj) copyObjectImpl(obj)
+#endif
+
+/*
+ * nodes/equalfuncs.c
+ */
+extern bool equal(const void *a, const void *b);
+
+
+/*
+ * Typedefs for identifying qualifier selectivities and plan costs as such.
+ * These are just plain "double"s, but declaring a variable as Selectivity
+ * or Cost makes the intent more obvious.
+ *
+ * These could have gone into plannodes.h or some such, but many files
+ * depend on them...
+ */
+typedef double Selectivity; /* fraction of tuples a qualifier will pass */
+typedef double Cost; /* execution cost (in page-access units) */
+
+
+/*
+ * CmdType -
+ * enums for type of operation represented by a Query or PlannedStmt
+ *
+ * This is needed in both parsenodes.h and plannodes.h, so put it here...
+ */
+typedef enum CmdType
+{
+ CMD_UNKNOWN,
+ CMD_SELECT, /* select stmt */
+ CMD_UPDATE, /* update stmt */
+ CMD_INSERT, /* insert stmt */
+ CMD_DELETE,
+ CMD_UTILITY, /* cmds like create, destroy, copy, vacuum,
+ * etc. */
+ CMD_NOTHING /* dummy command for instead nothing rules
+ * with qual */
+} CmdType;
+
+
+/*
+ * JoinType -
+ * enums for types of relation joins
+ *
+ * JoinType determines the exact semantics of joining two relations using
+ * a matching qualification. For example, it tells what to do with a tuple
+ * that has no match in the other relation.
+ *
+ * This is needed in both parsenodes.h and plannodes.h, so put it here...
+ */
+typedef enum JoinType
+{
+ /*
+ * The canonical kinds of joins according to the SQL JOIN syntax. Only
+ * these codes can appear in parser output (e.g., JoinExpr nodes).
+ */
+ JOIN_INNER, /* matching tuple pairs only */
+ JOIN_LEFT, /* pairs + unmatched LHS tuples */
+ JOIN_FULL, /* pairs + unmatched LHS + unmatched RHS */
+ JOIN_RIGHT, /* pairs + unmatched RHS tuples */
+
+ /*
+ * Semijoins and anti-semijoins (as defined in relational theory) do not
+ * appear in the SQL JOIN syntax, but there are standard idioms for
+ * representing them (e.g., using EXISTS). The planner recognizes these
+ * cases and converts them to joins. So the planner and executor must
+ * support these codes. NOTE: in JOIN_SEMI output, it is unspecified
+ * which matching RHS row is joined to. In JOIN_ANTI output, the row is
+ * guaranteed to be null-extended.
+ */
+ JOIN_SEMI, /* 1 copy of each LHS row that has match(es) */
+ JOIN_ANTI, /* 1 copy of each LHS row that has no match */
+
+ /*
+ * These codes are used internally in the planner, but are not supported
+ * by the executor (nor, indeed, by most of the planner).
+ */
+ JOIN_UNIQUE_OUTER, /* LHS path must be made unique */
+ JOIN_UNIQUE_INNER /* RHS path must be made unique */
+
+ /*
+ * We might need additional join types someday.
+ */
+} JoinType;
+
+/*
+ * OUTER joins are those for which pushed-down quals must behave differently
+ * from the join's own quals. This is in fact everything except INNER and
+ * SEMI joins. However, this macro must also exclude the JOIN_UNIQUE symbols
+ * since those are temporary proxies for what will eventually be an INNER
+ * join.
+ *
+ * Note: semijoins are a hybrid case, but we choose to treat them as not
+ * being outer joins. This is okay principally because the SQL syntax makes
+ * it impossible to have a pushed-down qual that refers to the inner relation
+ * of a semijoin; so there is no strong need to distinguish join quals from
+ * pushed-down quals. This is convenient because for almost all purposes,
+ * quals attached to a semijoin can be treated the same as innerjoin quals.
+ */
+#define IS_OUTER_JOIN(jointype) \
+ (((1 << (jointype)) & \
+ ((1 << JOIN_LEFT) | \
+ (1 << JOIN_FULL) | \
+ (1 << JOIN_RIGHT) | \
+ (1 << JOIN_ANTI))) != 0)
+
+/*
+ * AggStrategy -
+ * overall execution strategies for Agg plan nodes
+ *
+ * This is needed in both pathnodes.h and plannodes.h, so put it here...
+ */
+typedef enum AggStrategy
+{
+ AGG_PLAIN, /* simple agg across all input rows */
+ AGG_SORTED, /* grouped agg, input must be sorted */
+ AGG_HASHED, /* grouped agg, use internal hashtable */
+ AGG_MIXED /* grouped agg, hash and sort both used */
+} AggStrategy;
+
+/*
+ * AggSplit -
+ * splitting (partial aggregation) modes for Agg plan nodes
+ *
+ * This is needed in both pathnodes.h and plannodes.h, so put it here...
+ */
+
+/* Primitive options supported by nodeAgg.c: */
+#define AGGSPLITOP_COMBINE 0x01 /* substitute combinefn for transfn */
+#define AGGSPLITOP_SKIPFINAL 0x02 /* skip finalfn, return state as-is */
+#define AGGSPLITOP_SERIALIZE 0x04 /* apply serialfn to output */
+#define AGGSPLITOP_DESERIALIZE 0x08 /* apply deserialfn to input */
+
+/* Supported operating modes (i.e., useful combinations of these options): */
+typedef enum AggSplit
+{
+ /* Basic, non-split aggregation: */
+ AGGSPLIT_SIMPLE = 0,
+ /* Initial phase of partial aggregation, with serialization: */
+ AGGSPLIT_INITIAL_SERIAL = AGGSPLITOP_SKIPFINAL | AGGSPLITOP_SERIALIZE,
+ /* Final phase of partial aggregation, with deserialization: */
+ AGGSPLIT_FINAL_DESERIAL = AGGSPLITOP_COMBINE | AGGSPLITOP_DESERIALIZE
+} AggSplit;
+
+/* Test whether an AggSplit value selects each primitive option: */
+#define DO_AGGSPLIT_COMBINE(as) (((as) & AGGSPLITOP_COMBINE) != 0)
+#define DO_AGGSPLIT_SKIPFINAL(as) (((as) & AGGSPLITOP_SKIPFINAL) != 0)
+#define DO_AGGSPLIT_SERIALIZE(as) (((as) & AGGSPLITOP_SERIALIZE) != 0)
+#define DO_AGGSPLIT_DESERIALIZE(as) (((as) & AGGSPLITOP_DESERIALIZE) != 0)
+
+/*
+ * SetOpCmd and SetOpStrategy -
+ * overall semantics and execution strategies for SetOp plan nodes
+ *
+ * This is needed in both pathnodes.h and plannodes.h, so put it here...
+ */
+typedef enum SetOpCmd
+{
+ SETOPCMD_INTERSECT,
+ SETOPCMD_INTERSECT_ALL,
+ SETOPCMD_EXCEPT,
+ SETOPCMD_EXCEPT_ALL
+} SetOpCmd;
+
+typedef enum SetOpStrategy
+{
+ SETOP_SORTED, /* input must be sorted */
+ SETOP_HASHED /* use internal hashtable */
+} SetOpStrategy;
+
+/*
+ * OnConflictAction -
+ * "ON CONFLICT" clause type of query
+ *
+ * This is needed in both parsenodes.h and plannodes.h, so put it here...
+ */
+typedef enum OnConflictAction
+{
+ ONCONFLICT_NONE, /* No "ON CONFLICT" clause */
+ ONCONFLICT_NOTHING, /* ON CONFLICT ... DO NOTHING */
+ ONCONFLICT_UPDATE /* ON CONFLICT ... DO UPDATE */
+} OnConflictAction;
+
+/*
+ * LimitOption -
+ * LIMIT option of query
+ *
+ * This is needed in both parsenodes.h and plannodes.h, so put it here...
+ */
+typedef enum LimitOption
+{
+ LIMIT_OPTION_COUNT, /* FETCH FIRST... ONLY */
+ LIMIT_OPTION_WITH_TIES, /* FETCH FIRST... WITH TIES */
+ LIMIT_OPTION_DEFAULT, /* No limit present */
+} LimitOption;
+
+#endif /* NODES_H */
diff --git a/src/include/nodes/params.h b/src/include/nodes/params.h
new file mode 100644
index 0000000..4898d90
--- /dev/null
+++ b/src/include/nodes/params.h
@@ -0,0 +1,170 @@
+/*-------------------------------------------------------------------------
+ *
+ * params.h
+ * Support for finding the values associated with Param nodes.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/params.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARAMS_H
+#define PARAMS_H
+
+/* Forward declarations, to avoid including other headers */
+struct Bitmapset;
+struct ExprState;
+struct Param;
+struct ParseState;
+
+
+/*
+ * ParamListInfo
+ *
+ * ParamListInfo structures are used to pass parameters into the executor
+ * for parameterized plans. We support two basic approaches to supplying
+ * parameter values, the "static" way and the "dynamic" way.
+ *
+ * In the static approach, per-parameter data is stored in an array of
+ * ParamExternData structs appended to the ParamListInfo struct.
+ * Each entry in the array defines the value to be substituted for a
+ * PARAM_EXTERN parameter. The "paramid" of a PARAM_EXTERN Param
+ * can range from 1 to numParams.
+ *
+ * Although parameter numbers are normally consecutive, we allow
+ * ptype == InvalidOid to signal an unused array entry.
+ *
+ * pflags is a flags field. Currently the only used bit is:
+ * PARAM_FLAG_CONST signals the planner that it may treat this parameter
+ * as a constant (i.e., generate a plan that works only for this value
+ * of the parameter).
+ *
+ * In the dynamic approach, all access to parameter values is done through
+ * hook functions found in the ParamListInfo struct. In this case,
+ * the ParamExternData array is typically unused and not allocated;
+ * but the legal range of paramid is still 1 to numParams.
+ *
+ * Although the data structure is really an array, not a list, we keep
+ * the old typedef name to avoid unnecessary code changes.
+ *
+ * There are 3 hook functions that can be associated with a ParamListInfo
+ * structure:
+ *
+ * If paramFetch isn't null, it is called to fetch the ParamExternData
+ * for a particular param ID, rather than accessing the relevant element
+ * of the ParamExternData array. This supports the case where the array
+ * isn't there at all, as well as cases where the data in the array
+ * might be obsolete or lazily evaluated. paramFetch must return the
+ * address of a ParamExternData struct describing the specified param ID;
+ * the convention above about ptype == InvalidOid signaling an invalid
+ * param ID still applies. The returned struct can either be placed in
+ * the "workspace" supplied by the caller, or it can be in storage
+ * controlled by the paramFetch hook if that's more convenient.
+ * (In either case, the struct is not expected to be long-lived.)
+ * If "speculative" is true, the paramFetch hook should not risk errors
+ * in trying to fetch the parameter value, and should report an invalid
+ * parameter instead.
+ *
+ * If paramCompile isn't null, then it controls what execExpr.c compiles
+ * for PARAM_EXTERN Param nodes --- typically, this hook would emit a
+ * EEOP_PARAM_CALLBACK step. This allows unnecessary work to be
+ * optimized away in compiled expressions.
+ *
+ * If parserSetup isn't null, then it is called to re-instantiate the
+ * original parsing hooks when a query needs to be re-parsed/planned.
+ * This is especially useful if the types of parameters might change
+ * from time to time, since it can replace the need to supply a fixed
+ * list of parameter types to the parser.
+ *
+ * Notice that the paramFetch and paramCompile hooks are actually passed
+ * the ParamListInfo struct's address; they can therefore access all
+ * three of the "arg" fields, and the distinction between paramFetchArg
+ * and paramCompileArg is rather arbitrary.
+ */
+
+#define PARAM_FLAG_CONST 0x0001 /* parameter is constant */
+
+typedef struct ParamExternData
+{
+ Datum value; /* parameter value */
+ bool isnull; /* is it NULL? */
+ uint16 pflags; /* flag bits, see above */
+ Oid ptype; /* parameter's datatype, or 0 */
+} ParamExternData;
+
+typedef struct ParamListInfoData *ParamListInfo;
+
+typedef ParamExternData *(*ParamFetchHook) (ParamListInfo params,
+ int paramid, bool speculative,
+ ParamExternData *workspace);
+
+typedef void (*ParamCompileHook) (ParamListInfo params, struct Param *param,
+ struct ExprState *state,
+ Datum *resv, bool *resnull);
+
+typedef void (*ParserSetupHook) (struct ParseState *pstate, void *arg);
+
+typedef struct ParamListInfoData
+{
+ ParamFetchHook paramFetch; /* parameter fetch hook */
+ void *paramFetchArg;
+ ParamCompileHook paramCompile; /* parameter compile hook */
+ void *paramCompileArg;
+ ParserSetupHook parserSetup; /* parser setup hook */
+ void *parserSetupArg;
+ char *paramValuesStr; /* params as a single string for errors */
+ int numParams; /* nominal/maximum # of Params represented */
+
+ /*
+ * params[] may be of length zero if paramFetch is supplied; otherwise it
+ * must be of length numParams.
+ */
+ ParamExternData params[FLEXIBLE_ARRAY_MEMBER];
+} ParamListInfoData;
+
+
+/* ----------------
+ * ParamExecData
+ *
+ * ParamExecData entries are used for executor internal parameters
+ * (that is, values being passed into or out of a sub-query). The
+ * paramid of a PARAM_EXEC Param is a (zero-based) index into an
+ * array of ParamExecData records, which is referenced through
+ * es_param_exec_vals or ecxt_param_exec_vals.
+ *
+ * If execPlan is not NULL, it points to a SubPlanState node that needs
+ * to be executed to produce the value. (This is done so that we can have
+ * lazy evaluation of InitPlans: they aren't executed until/unless a
+ * result value is needed.) Otherwise the value is assumed to be valid
+ * when needed.
+ * ----------------
+ */
+
+typedef struct ParamExecData
+{
+ void *execPlan; /* should be "SubPlanState *" */
+ Datum value;
+ bool isnull;
+} ParamExecData;
+
+/* type of argument for ParamsErrorCallback */
+typedef struct ParamsErrorCbData
+{
+ const char *portalName;
+ ParamListInfo params;
+} ParamsErrorCbData;
+
+/* Functions found in src/backend/nodes/params.c */
+extern ParamListInfo makeParamList(int numParams);
+extern ParamListInfo copyParamList(ParamListInfo from);
+extern Size EstimateParamListSpace(ParamListInfo paramLI);
+extern void SerializeParamList(ParamListInfo paramLI, char **start_address);
+extern ParamListInfo RestoreParamList(char **start_address);
+extern char *BuildParamLogString(ParamListInfo params, char **paramTextValues,
+ int valueLen);
+extern void ParamsErrorCallback(void *arg);
+
+#endif /* PARAMS_H */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
new file mode 100644
index 0000000..557074c
--- /dev/null
+++ b/src/include/nodes/parsenodes.h
@@ -0,0 +1,3579 @@
+/*-------------------------------------------------------------------------
+ *
+ * parsenodes.h
+ * definitions for parse tree nodes
+ *
+ * Many of the node types used in parsetrees include a "location" field.
+ * This is a byte (not character) offset in the original source text, to be
+ * used for positioning an error cursor when there is an error related to
+ * the node. Access to the original source text is needed to make use of
+ * the location. At the topmost (statement) level, we also provide a
+ * statement length, likewise measured in bytes, for convenience in
+ * identifying statement boundaries in multi-statement source strings.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/parsenodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSENODES_H
+#define PARSENODES_H
+
+#include "nodes/bitmapset.h"
+#include "nodes/lockoptions.h"
+#include "nodes/primnodes.h"
+#include "nodes/value.h"
+#include "partitioning/partdefs.h"
+
+
+typedef enum OverridingKind
+{
+ OVERRIDING_NOT_SET = 0,
+ OVERRIDING_USER_VALUE,
+ OVERRIDING_SYSTEM_VALUE
+} OverridingKind;
+
+/* Possible sources of a Query */
+typedef enum QuerySource
+{
+ QSRC_ORIGINAL, /* original parsetree (explicit query) */
+ QSRC_PARSER, /* added by parse analysis (now unused) */
+ QSRC_INSTEAD_RULE, /* added by unconditional INSTEAD rule */
+ QSRC_QUAL_INSTEAD_RULE, /* added by conditional INSTEAD rule */
+ QSRC_NON_INSTEAD_RULE /* added by non-INSTEAD rule */
+} QuerySource;
+
+/* Sort ordering options for ORDER BY and CREATE INDEX */
+typedef enum SortByDir
+{
+ SORTBY_DEFAULT,
+ SORTBY_ASC,
+ SORTBY_DESC,
+ SORTBY_USING /* not allowed in CREATE INDEX ... */
+} SortByDir;
+
+typedef enum SortByNulls
+{
+ SORTBY_NULLS_DEFAULT,
+ SORTBY_NULLS_FIRST,
+ SORTBY_NULLS_LAST
+} SortByNulls;
+
+/*
+ * Grantable rights are encoded so that we can OR them together in a bitmask.
+ * The present representation of AclItem limits us to 16 distinct rights,
+ * even though AclMode is defined as uint32. See utils/acl.h.
+ *
+ * Caution: changing these codes breaks stored ACLs, hence forces initdb.
+ */
+typedef uint32 AclMode; /* a bitmask of privilege bits */
+
+#define ACL_INSERT (1<<0) /* for relations */
+#define ACL_SELECT (1<<1)
+#define ACL_UPDATE (1<<2)
+#define ACL_DELETE (1<<3)
+#define ACL_TRUNCATE (1<<4)
+#define ACL_REFERENCES (1<<5)
+#define ACL_TRIGGER (1<<6)
+#define ACL_EXECUTE (1<<7) /* for functions */
+#define ACL_USAGE (1<<8) /* for languages, namespaces, FDWs, and
+ * servers */
+#define ACL_CREATE (1<<9) /* for namespaces and databases */
+#define ACL_CREATE_TEMP (1<<10) /* for databases */
+#define ACL_CONNECT (1<<11) /* for databases */
+#define N_ACL_RIGHTS 12 /* 1 plus the last 1<<x */
+#define ACL_NO_RIGHTS 0
+/* Currently, SELECT ... FOR [KEY] UPDATE/SHARE requires UPDATE privileges */
+#define ACL_SELECT_FOR_UPDATE ACL_UPDATE
+
+
+/*****************************************************************************
+ * Query Tree
+ *****************************************************************************/
+
+/*
+ * Query -
+ * Parse analysis turns all statements into a Query tree
+ * for further processing by the rewriter and planner.
+ *
+ * Utility statements (i.e. non-optimizable statements) have the
+ * utilityStmt field set, and the rest of the Query is mostly dummy.
+ *
+ * Planning converts a Query tree into a Plan tree headed by a PlannedStmt
+ * node --- the Query structure is not used by the executor.
+ */
+typedef struct Query
+{
+ NodeTag type;
+
+ CmdType commandType; /* select|insert|update|delete|utility */
+
+ QuerySource querySource; /* where did I come from? */
+
+ uint64 queryId; /* query identifier (can be set by plugins) */
+
+ bool canSetTag; /* do I set the command result tag? */
+
+ Node *utilityStmt; /* non-null if commandType == CMD_UTILITY */
+
+ int resultRelation; /* rtable index of target relation for
+ * INSERT/UPDATE/DELETE; 0 for SELECT */
+
+ bool hasAggs; /* has aggregates in tlist or havingQual */
+ bool hasWindowFuncs; /* has window functions in tlist */
+ bool hasTargetSRFs; /* has set-returning functions in tlist */
+ bool hasSubLinks; /* has subquery SubLink */
+ bool hasDistinctOn; /* distinctClause is from DISTINCT ON */
+ bool hasRecursive; /* WITH RECURSIVE was specified */
+ bool hasModifyingCTE; /* has INSERT/UPDATE/DELETE in WITH */
+ bool hasForUpdate; /* FOR [KEY] UPDATE/SHARE was specified */
+ bool hasRowSecurity; /* rewriter has applied some RLS policy */
+
+ List *cteList; /* WITH list (of CommonTableExpr's) */
+
+ List *rtable; /* list of range table entries */
+ FromExpr *jointree; /* table join tree (FROM and WHERE clauses) */
+
+ List *targetList; /* target list (of TargetEntry) */
+
+ OverridingKind override; /* OVERRIDING clause */
+
+ OnConflictExpr *onConflict; /* ON CONFLICT DO [NOTHING | UPDATE] */
+
+ List *returningList; /* return-values list (of TargetEntry) */
+
+ List *groupClause; /* a list of SortGroupClause's */
+
+ List *groupingSets; /* a list of GroupingSet's if present */
+
+ Node *havingQual; /* qualifications applied to groups */
+
+ List *windowClause; /* a list of WindowClause's */
+
+ List *distinctClause; /* a list of SortGroupClause's */
+
+ List *sortClause; /* a list of SortGroupClause's */
+
+ Node *limitOffset; /* # of result tuples to skip (int8 expr) */
+ Node *limitCount; /* # of result tuples to return (int8 expr) */
+ LimitOption limitOption; /* limit type */
+
+ List *rowMarks; /* a list of RowMarkClause's */
+
+ Node *setOperations; /* set-operation tree if this is top level of
+ * a UNION/INTERSECT/EXCEPT query */
+
+ List *constraintDeps; /* a list of pg_constraint OIDs that the query
+ * depends on to be semantically valid */
+
+ List *withCheckOptions; /* a list of WithCheckOption's (added
+ * during rewrite) */
+
+ /*
+ * The following two fields identify the portion of the source text string
+ * containing this query. They are typically only populated in top-level
+ * Queries, not in sub-queries. When not set, they might both be zero, or
+ * both be -1 meaning "unknown".
+ */
+ int stmt_location; /* start location, or -1 if unknown */
+ int stmt_len; /* length in bytes; 0 means "rest of string" */
+} Query;
+
+
+/****************************************************************************
+ * Supporting data structures for Parse Trees
+ *
+ * Most of these node types appear in raw parsetrees output by the grammar,
+ * and get transformed to something else by the analyzer. A few of them
+ * are used as-is in transformed querytrees.
+ ****************************************************************************/
+
+/*
+ * TypeName - specifies a type in definitions
+ *
+ * For TypeName structures generated internally, it is often easier to
+ * specify the type by OID than by name. If "names" is NIL then the
+ * actual type OID is given by typeOid, otherwise typeOid is unused.
+ * Similarly, if "typmods" is NIL then the actual typmod is expected to
+ * be prespecified in typemod, otherwise typemod is unused.
+ *
+ * If pct_type is true, then names is actually a field name and we look up
+ * the type of that field. Otherwise (the normal case), names is a type
+ * name possibly qualified with schema and database name.
+ */
+typedef struct TypeName
+{
+ NodeTag type;
+ List *names; /* qualified name (list of Value strings) */
+ Oid typeOid; /* type identified by OID */
+ bool setof; /* is a set? */
+ bool pct_type; /* %TYPE specified? */
+ List *typmods; /* type modifier expression(s) */
+ int32 typemod; /* prespecified type modifier */
+ List *arrayBounds; /* array bounds */
+ int location; /* token location, or -1 if unknown */
+} TypeName;
+
+/*
+ * ColumnRef - specifies a reference to a column, or possibly a whole tuple
+ *
+ * The "fields" list must be nonempty. It can contain string Value nodes
+ * (representing names) and A_Star nodes (representing occurrence of a '*').
+ * Currently, A_Star must appear only as the last list element --- the grammar
+ * is responsible for enforcing this!
+ *
+ * Note: any container subscripting or selection of fields from composite columns
+ * is represented by an A_Indirection node above the ColumnRef. However,
+ * for simplicity in the normal case, initial field selection from a table
+ * name is represented within ColumnRef and not by adding A_Indirection.
+ */
+typedef struct ColumnRef
+{
+ NodeTag type;
+ List *fields; /* field names (Value strings) or A_Star */
+ int location; /* token location, or -1 if unknown */
+} ColumnRef;
+
+/*
+ * ParamRef - specifies a $n parameter reference
+ */
+typedef struct ParamRef
+{
+ NodeTag type;
+ int number; /* the number of the parameter */
+ int location; /* token location, or -1 if unknown */
+} ParamRef;
+
+/*
+ * A_Expr - infix, prefix, and postfix expressions
+ */
+typedef enum A_Expr_Kind
+{
+ AEXPR_OP, /* normal operator */
+ AEXPR_OP_ANY, /* scalar op ANY (array) */
+ AEXPR_OP_ALL, /* scalar op ALL (array) */
+ AEXPR_DISTINCT, /* IS DISTINCT FROM - name must be "=" */
+ AEXPR_NOT_DISTINCT, /* IS NOT DISTINCT FROM - name must be "=" */
+ AEXPR_NULLIF, /* NULLIF - name must be "=" */
+ AEXPR_OF, /* IS [NOT] OF - name must be "=" or "<>" */
+ AEXPR_IN, /* [NOT] IN - name must be "=" or "<>" */
+ AEXPR_LIKE, /* [NOT] LIKE - name must be "~~" or "!~~" */
+ AEXPR_ILIKE, /* [NOT] ILIKE - name must be "~~*" or "!~~*" */
+ AEXPR_SIMILAR, /* [NOT] SIMILAR - name must be "~" or "!~" */
+ AEXPR_BETWEEN, /* name must be "BETWEEN" */
+ AEXPR_NOT_BETWEEN, /* name must be "NOT BETWEEN" */
+ AEXPR_BETWEEN_SYM, /* name must be "BETWEEN SYMMETRIC" */
+ AEXPR_NOT_BETWEEN_SYM, /* name must be "NOT BETWEEN SYMMETRIC" */
+ AEXPR_PAREN /* nameless dummy node for parentheses */
+} A_Expr_Kind;
+
+typedef struct A_Expr
+{
+ NodeTag type;
+ A_Expr_Kind kind; /* see above */
+ List *name; /* possibly-qualified name of operator */
+ Node *lexpr; /* left argument, or NULL if none */
+ Node *rexpr; /* right argument, or NULL if none */
+ int location; /* token location, or -1 if unknown */
+} A_Expr;
+
+/*
+ * A_Const - a literal constant
+ */
+typedef struct A_Const
+{
+ NodeTag type;
+ Value val; /* value (includes type info, see value.h) */
+ int location; /* token location, or -1 if unknown */
+} A_Const;
+
+/*
+ * TypeCast - a CAST expression
+ */
+typedef struct TypeCast
+{
+ NodeTag type;
+ Node *arg; /* the expression being casted */
+ TypeName *typeName; /* the target type */
+ int location; /* token location, or -1 if unknown */
+} TypeCast;
+
+/*
+ * CollateClause - a COLLATE expression
+ */
+typedef struct CollateClause
+{
+ NodeTag type;
+ Node *arg; /* input expression */
+ List *collname; /* possibly-qualified collation name */
+ int location; /* token location, or -1 if unknown */
+} CollateClause;
+
+/*
+ * RoleSpec - a role name or one of a few special values.
+ */
+typedef enum RoleSpecType
+{
+ ROLESPEC_CSTRING, /* role name is stored as a C string */
+ ROLESPEC_CURRENT_USER, /* role spec is CURRENT_USER */
+ ROLESPEC_SESSION_USER, /* role spec is SESSION_USER */
+ ROLESPEC_PUBLIC /* role name is "public" */
+} RoleSpecType;
+
+typedef struct RoleSpec
+{
+ NodeTag type;
+ RoleSpecType roletype; /* Type of this rolespec */
+ char *rolename; /* filled only for ROLESPEC_CSTRING */
+ int location; /* token location, or -1 if unknown */
+} RoleSpec;
+
+/*
+ * FuncCall - a function or aggregate invocation
+ *
+ * agg_order (if not NIL) indicates we saw 'foo(... ORDER BY ...)', or if
+ * agg_within_group is true, it was 'foo(...) WITHIN GROUP (ORDER BY ...)'.
+ * agg_star indicates we saw a 'foo(*)' construct, while agg_distinct
+ * indicates we saw 'foo(DISTINCT ...)'. In any of these cases, the
+ * construct *must* be an aggregate call. Otherwise, it might be either an
+ * aggregate or some other kind of function. However, if FILTER or OVER is
+ * present it had better be an aggregate or window function.
+ *
+ * Normally, you'd initialize this via makeFuncCall() and then only change the
+ * parts of the struct its defaults don't match afterwards, as needed.
+ */
+typedef struct FuncCall
+{
+ NodeTag type;
+ List *funcname; /* qualified name of function */
+ List *args; /* the arguments (list of exprs) */
+ List *agg_order; /* ORDER BY (list of SortBy) */
+ Node *agg_filter; /* FILTER clause, if any */
+ bool agg_within_group; /* ORDER BY appeared in WITHIN GROUP */
+ bool agg_star; /* argument was really '*' */
+ bool agg_distinct; /* arguments were labeled DISTINCT */
+ bool func_variadic; /* last argument was labeled VARIADIC */
+ struct WindowDef *over; /* OVER clause, if any */
+ int location; /* token location, or -1 if unknown */
+} FuncCall;
+
+/*
+ * A_Star - '*' representing all columns of a table or compound field
+ *
+ * This can appear within ColumnRef.fields, A_Indirection.indirection, and
+ * ResTarget.indirection lists.
+ */
+typedef struct A_Star
+{
+ NodeTag type;
+} A_Star;
+
+/*
+ * A_Indices - array subscript or slice bounds ([idx] or [lidx:uidx])
+ *
+ * In slice case, either or both of lidx and uidx can be NULL (omitted).
+ * In non-slice case, uidx holds the single subscript and lidx is always NULL.
+ */
+typedef struct A_Indices
+{
+ NodeTag type;
+ bool is_slice; /* true if slice (i.e., colon present) */
+ Node *lidx; /* slice lower bound, if any */
+ Node *uidx; /* subscript, or slice upper bound if any */
+} A_Indices;
+
+/*
+ * A_Indirection - select a field and/or array element from an expression
+ *
+ * The indirection list can contain A_Indices nodes (representing
+ * subscripting), string Value nodes (representing field selection --- the
+ * string value is the name of the field to select), and A_Star nodes
+ * (representing selection of all fields of a composite type).
+ * For example, a complex selection operation like
+ * (foo).field1[42][7].field2
+ * would be represented with a single A_Indirection node having a 4-element
+ * indirection list.
+ *
+ * Currently, A_Star must appear only as the last list element --- the grammar
+ * is responsible for enforcing this!
+ */
+typedef struct A_Indirection
+{
+ NodeTag type;
+ Node *arg; /* the thing being selected from */
+ List *indirection; /* subscripts and/or field names and/or * */
+} A_Indirection;
+
+/*
+ * A_ArrayExpr - an ARRAY[] construct
+ */
+typedef struct A_ArrayExpr
+{
+ NodeTag type;
+ List *elements; /* array element expressions */
+ int location; /* token location, or -1 if unknown */
+} A_ArrayExpr;
+
+/*
+ * ResTarget -
+ * result target (used in target list of pre-transformed parse trees)
+ *
+ * In a SELECT target list, 'name' is the column label from an
+ * 'AS ColumnLabel' clause, or NULL if there was none, and 'val' is the
+ * value expression itself. The 'indirection' field is not used.
+ *
+ * INSERT uses ResTarget in its target-column-names list. Here, 'name' is
+ * the name of the destination column, 'indirection' stores any subscripts
+ * attached to the destination, and 'val' is not used.
+ *
+ * In an UPDATE target list, 'name' is the name of the destination column,
+ * 'indirection' stores any subscripts attached to the destination, and
+ * 'val' is the expression to assign.
+ *
+ * See A_Indirection for more info about what can appear in 'indirection'.
+ */
+typedef struct ResTarget
+{
+ NodeTag type;
+ char *name; /* column name or NULL */
+ List *indirection; /* subscripts, field names, and '*', or NIL */
+ Node *val; /* the value expression to compute or assign */
+ int location; /* token location, or -1 if unknown */
+} ResTarget;
+
+/*
+ * MultiAssignRef - element of a row source expression for UPDATE
+ *
+ * In an UPDATE target list, when we have SET (a,b,c) = row-valued-expression,
+ * we generate separate ResTarget items for each of a,b,c. Their "val" trees
+ * are MultiAssignRef nodes numbered 1..n, linking to a common copy of the
+ * row-valued-expression (which parse analysis will process only once, when
+ * handling the MultiAssignRef with colno=1).
+ */
+typedef struct MultiAssignRef
+{
+ NodeTag type;
+ Node *source; /* the row-valued expression */
+ int colno; /* column number for this target (1..n) */
+ int ncolumns; /* number of targets in the construct */
+} MultiAssignRef;
+
+/*
+ * SortBy - for ORDER BY clause
+ */
+typedef struct SortBy
+{
+ NodeTag type;
+ Node *node; /* expression to sort on */
+ SortByDir sortby_dir; /* ASC/DESC/USING/default */
+ SortByNulls sortby_nulls; /* NULLS FIRST/LAST */
+ List *useOp; /* name of op to use, if SORTBY_USING */
+ int location; /* operator location, or -1 if none/unknown */
+} SortBy;
+
+/*
+ * WindowDef - raw representation of WINDOW and OVER clauses
+ *
+ * For entries in a WINDOW list, "name" is the window name being defined.
+ * For OVER clauses, we use "name" for the "OVER window" syntax, or "refname"
+ * for the "OVER (window)" syntax, which is subtly different --- the latter
+ * implies overriding the window frame clause.
+ */
+typedef struct WindowDef
+{
+ NodeTag type;
+ char *name; /* window's own name */
+ char *refname; /* referenced window name, if any */
+ List *partitionClause; /* PARTITION BY expression list */
+ List *orderClause; /* ORDER BY (list of SortBy) */
+ int frameOptions; /* frame_clause options, see below */
+ Node *startOffset; /* expression for starting bound, if any */
+ Node *endOffset; /* expression for ending bound, if any */
+ int location; /* parse location, or -1 if none/unknown */
+} WindowDef;
+
+/*
+ * frameOptions is an OR of these bits. The NONDEFAULT and BETWEEN bits are
+ * used so that ruleutils.c can tell which properties were specified and
+ * which were defaulted; the correct behavioral bits must be set either way.
+ * The START_foo and END_foo options must come in pairs of adjacent bits for
+ * the convenience of gram.y, even though some of them are useless/invalid.
+ */
+#define FRAMEOPTION_NONDEFAULT 0x00001 /* any specified? */
+#define FRAMEOPTION_RANGE 0x00002 /* RANGE behavior */
+#define FRAMEOPTION_ROWS 0x00004 /* ROWS behavior */
+#define FRAMEOPTION_GROUPS 0x00008 /* GROUPS behavior */
+#define FRAMEOPTION_BETWEEN 0x00010 /* BETWEEN given? */
+#define FRAMEOPTION_START_UNBOUNDED_PRECEDING 0x00020 /* start is U. P. */
+#define FRAMEOPTION_END_UNBOUNDED_PRECEDING 0x00040 /* (disallowed) */
+#define FRAMEOPTION_START_UNBOUNDED_FOLLOWING 0x00080 /* (disallowed) */
+#define FRAMEOPTION_END_UNBOUNDED_FOLLOWING 0x00100 /* end is U. F. */
+#define FRAMEOPTION_START_CURRENT_ROW 0x00200 /* start is C. R. */
+#define FRAMEOPTION_END_CURRENT_ROW 0x00400 /* end is C. R. */
+#define FRAMEOPTION_START_OFFSET_PRECEDING 0x00800 /* start is O. P. */
+#define FRAMEOPTION_END_OFFSET_PRECEDING 0x01000 /* end is O. P. */
+#define FRAMEOPTION_START_OFFSET_FOLLOWING 0x02000 /* start is O. F. */
+#define FRAMEOPTION_END_OFFSET_FOLLOWING 0x04000 /* end is O. F. */
+#define FRAMEOPTION_EXCLUDE_CURRENT_ROW 0x08000 /* omit C.R. */
+#define FRAMEOPTION_EXCLUDE_GROUP 0x10000 /* omit C.R. & peers */
+#define FRAMEOPTION_EXCLUDE_TIES 0x20000 /* omit C.R.'s peers */
+
+#define FRAMEOPTION_START_OFFSET \
+ (FRAMEOPTION_START_OFFSET_PRECEDING | FRAMEOPTION_START_OFFSET_FOLLOWING)
+#define FRAMEOPTION_END_OFFSET \
+ (FRAMEOPTION_END_OFFSET_PRECEDING | FRAMEOPTION_END_OFFSET_FOLLOWING)
+#define FRAMEOPTION_EXCLUSION \
+ (FRAMEOPTION_EXCLUDE_CURRENT_ROW | FRAMEOPTION_EXCLUDE_GROUP | \
+ FRAMEOPTION_EXCLUDE_TIES)
+
+#define FRAMEOPTION_DEFAULTS \
+ (FRAMEOPTION_RANGE | FRAMEOPTION_START_UNBOUNDED_PRECEDING | \
+ FRAMEOPTION_END_CURRENT_ROW)
+
+/*
+ * RangeSubselect - subquery appearing in a FROM clause
+ */
+typedef struct RangeSubselect
+{
+ NodeTag type;
+ bool lateral; /* does it have LATERAL prefix? */
+ Node *subquery; /* the untransformed sub-select clause */
+ Alias *alias; /* table alias & optional column aliases */
+} RangeSubselect;
+
+/*
+ * RangeFunction - function call appearing in a FROM clause
+ *
+ * functions is a List because we use this to represent the construct
+ * ROWS FROM(func1(...), func2(...), ...). Each element of this list is a
+ * two-element sublist, the first element being the untransformed function
+ * call tree, and the second element being a possibly-empty list of ColumnDef
+ * nodes representing any columndef list attached to that function within the
+ * ROWS FROM() syntax.
+ *
+ * alias and coldeflist represent any alias and/or columndef list attached
+ * at the top level. (We disallow coldeflist appearing both here and
+ * per-function, but that's checked in parse analysis, not by the grammar.)
+ */
+typedef struct RangeFunction
+{
+ NodeTag type;
+ bool lateral; /* does it have LATERAL prefix? */
+ bool ordinality; /* does it have WITH ORDINALITY suffix? */
+ bool is_rowsfrom; /* is result of ROWS FROM() syntax? */
+ List *functions; /* per-function information, see above */
+ Alias *alias; /* table alias & optional column aliases */
+ List *coldeflist; /* list of ColumnDef nodes to describe result
+ * of function returning RECORD */
+} RangeFunction;
+
+/*
+ * RangeTableFunc - raw form of "table functions" such as XMLTABLE
+ */
+typedef struct RangeTableFunc
+{
+ NodeTag type;
+ bool lateral; /* does it have LATERAL prefix? */
+ Node *docexpr; /* document expression */
+ Node *rowexpr; /* row generator expression */
+ List *namespaces; /* list of namespaces as ResTarget */
+ List *columns; /* list of RangeTableFuncCol */
+ Alias *alias; /* table alias & optional column aliases */
+ int location; /* token location, or -1 if unknown */
+} RangeTableFunc;
+
+/*
+ * RangeTableFuncCol - one column in a RangeTableFunc->columns
+ *
+ * If for_ordinality is true (FOR ORDINALITY), then the column is an int4
+ * column and the rest of the fields are ignored.
+ */
+typedef struct RangeTableFuncCol
+{
+ NodeTag type;
+ char *colname; /* name of generated column */
+ TypeName *typeName; /* type of generated column */
+ bool for_ordinality; /* does it have FOR ORDINALITY? */
+ bool is_not_null; /* does it have NOT NULL? */
+ Node *colexpr; /* column filter expression */
+ Node *coldefexpr; /* column default value expression */
+ int location; /* token location, or -1 if unknown */
+} RangeTableFuncCol;
+
+/*
+ * RangeTableSample - TABLESAMPLE appearing in a raw FROM clause
+ *
+ * This node, appearing only in raw parse trees, represents
+ * <relation> TABLESAMPLE <method> (<params>) REPEATABLE (<num>)
+ * Currently, the <relation> can only be a RangeVar, but we might in future
+ * allow RangeSubselect and other options. Note that the RangeTableSample
+ * is wrapped around the node representing the <relation>, rather than being
+ * a subfield of it.
+ */
+typedef struct RangeTableSample
+{
+ NodeTag type;
+ Node *relation; /* relation to be sampled */
+ List *method; /* sampling method name (possibly qualified) */
+ List *args; /* argument(s) for sampling method */
+ Node *repeatable; /* REPEATABLE expression, or NULL if none */
+ int location; /* method name location, or -1 if unknown */
+} RangeTableSample;
+
+/*
+ * ColumnDef - column definition (used in various creates)
+ *
+ * If the column has a default value, we may have the value expression
+ * in either "raw" form (an untransformed parse tree) or "cooked" form
+ * (a post-parse-analysis, executable expression tree), depending on
+ * how this ColumnDef node was created (by parsing, or by inheritance
+ * from an existing relation). We should never have both in the same node!
+ *
+ * Similarly, we may have a COLLATE specification in either raw form
+ * (represented as a CollateClause with arg==NULL) or cooked form
+ * (the collation's OID).
+ *
+ * The constraints list may contain a CONSTR_DEFAULT item in a raw
+ * parsetree produced by gram.y, but transformCreateStmt will remove
+ * the item and set raw_default instead. CONSTR_DEFAULT items
+ * should not appear in any subsequent processing.
+ */
+typedef struct ColumnDef
+{
+ NodeTag type;
+ char *colname; /* name of column */
+ TypeName *typeName; /* type of column */
+ int inhcount; /* number of times column is inherited */
+ bool is_local; /* column has local (non-inherited) def'n */
+ bool is_not_null; /* NOT NULL constraint specified? */
+ bool is_from_type; /* column definition came from table type */
+ char storage; /* attstorage setting, or 0 for default */
+ Node *raw_default; /* default value (untransformed parse tree) */
+ Node *cooked_default; /* default value (transformed expr tree) */
+ char identity; /* attidentity setting */
+ RangeVar *identitySequence; /* to store identity sequence name for
+ * ALTER TABLE ... ADD COLUMN */
+ char generated; /* attgenerated setting */
+ CollateClause *collClause; /* untransformed COLLATE spec, if any */
+ Oid collOid; /* collation OID (InvalidOid if not set) */
+ List *constraints; /* other constraints on column */
+ List *fdwoptions; /* per-column FDW options */
+ int location; /* parse location, or -1 if none/unknown */
+} ColumnDef;
+
+/*
+ * TableLikeClause - CREATE TABLE ( ... LIKE ... ) clause
+ */
+typedef struct TableLikeClause
+{
+ NodeTag type;
+ RangeVar *relation;
+ bits32 options; /* OR of TableLikeOption flags */
+ Oid relationOid; /* If table has been looked up, its OID */
+} TableLikeClause;
+
+typedef enum TableLikeOption
+{
+ CREATE_TABLE_LIKE_COMMENTS = 1 << 0,
+ CREATE_TABLE_LIKE_CONSTRAINTS = 1 << 1,
+ CREATE_TABLE_LIKE_DEFAULTS = 1 << 2,
+ CREATE_TABLE_LIKE_GENERATED = 1 << 3,
+ CREATE_TABLE_LIKE_IDENTITY = 1 << 4,
+ CREATE_TABLE_LIKE_INDEXES = 1 << 5,
+ CREATE_TABLE_LIKE_STATISTICS = 1 << 6,
+ CREATE_TABLE_LIKE_STORAGE = 1 << 7,
+ CREATE_TABLE_LIKE_ALL = PG_INT32_MAX
+} TableLikeOption;
+
+/*
+ * IndexElem - index parameters (used in CREATE INDEX, and in ON CONFLICT)
+ *
+ * For a plain index attribute, 'name' is the name of the table column to
+ * index, and 'expr' is NULL. For an index expression, 'name' is NULL and
+ * 'expr' is the expression tree.
+ */
+typedef struct IndexElem
+{
+ NodeTag type;
+ char *name; /* name of attribute to index, or NULL */
+ Node *expr; /* expression to index, or NULL */
+ char *indexcolname; /* name for index column; NULL = default */
+ List *collation; /* name of collation; NIL = default */
+ List *opclass; /* name of desired opclass; NIL = default */
+ List *opclassopts; /* opclass-specific options, or NIL */
+ SortByDir ordering; /* ASC/DESC/default */
+ SortByNulls nulls_ordering; /* FIRST/LAST/default */
+} IndexElem;
+
+/*
+ * DefElem - a generic "name = value" option definition
+ *
+ * In some contexts the name can be qualified. Also, certain SQL commands
+ * allow a SET/ADD/DROP action to be attached to option settings, so it's
+ * convenient to carry a field for that too. (Note: currently, it is our
+ * practice that the grammar allows namespace and action only in statements
+ * where they are relevant; C code can just ignore those fields in other
+ * statements.)
+ */
+typedef enum DefElemAction
+{
+ DEFELEM_UNSPEC, /* no action given */
+ DEFELEM_SET,
+ DEFELEM_ADD,
+ DEFELEM_DROP
+} DefElemAction;
+
+typedef struct DefElem
+{
+ NodeTag type;
+ char *defnamespace; /* NULL if unqualified name */
+ char *defname;
+ Node *arg; /* a (Value *) or a (TypeName *) */
+ DefElemAction defaction; /* unspecified action, or SET/ADD/DROP */
+ int location; /* token location, or -1 if unknown */
+} DefElem;
+
+/*
+ * LockingClause - raw representation of FOR [NO KEY] UPDATE/[KEY] SHARE
+ * options
+ *
+ * Note: lockedRels == NIL means "all relations in query". Otherwise it
+ * is a list of RangeVar nodes. (We use RangeVar mainly because it carries
+ * a location field --- currently, parse analysis insists on unqualified
+ * names in LockingClause.)
+ */
+typedef struct LockingClause
+{
+ NodeTag type;
+ List *lockedRels; /* FOR [KEY] UPDATE/SHARE relations */
+ LockClauseStrength strength;
+ LockWaitPolicy waitPolicy; /* NOWAIT and SKIP LOCKED */
+} LockingClause;
+
+/*
+ * XMLSERIALIZE (in raw parse tree only)
+ */
+typedef struct XmlSerialize
+{
+ NodeTag type;
+ XmlOptionType xmloption; /* DOCUMENT or CONTENT */
+ Node *expr;
+ TypeName *typeName;
+ int location; /* token location, or -1 if unknown */
+} XmlSerialize;
+
+/* Partitioning related definitions */
+
+/*
+ * PartitionElem - parse-time representation of a single partition key
+ *
+ * expr can be either a raw expression tree or a parse-analyzed expression.
+ * We don't store these on-disk, though.
+ */
+typedef struct PartitionElem
+{
+ NodeTag type;
+ char *name; /* name of column to partition on, or NULL */
+ Node *expr; /* expression to partition on, or NULL */
+ List *collation; /* name of collation; NIL = default */
+ List *opclass; /* name of desired opclass; NIL = default */
+ int location; /* token location, or -1 if unknown */
+} PartitionElem;
+
+/*
+ * PartitionSpec - parse-time representation of a partition key specification
+ *
+ * This represents the key space we will be partitioning on.
+ */
+typedef struct PartitionSpec
+{
+ NodeTag type;
+ char *strategy; /* partitioning strategy ('hash', 'list' or
+ * 'range') */
+ List *partParams; /* List of PartitionElems */
+ int location; /* token location, or -1 if unknown */
+} PartitionSpec;
+
+/* Internal codes for partitioning strategies */
+#define PARTITION_STRATEGY_HASH 'h'
+#define PARTITION_STRATEGY_LIST 'l'
+#define PARTITION_STRATEGY_RANGE 'r'
+
+/*
+ * PartitionBoundSpec - a partition bound specification
+ *
+ * This represents the portion of the partition key space assigned to a
+ * particular partition. These are stored on disk in pg_class.relpartbound.
+ */
+struct PartitionBoundSpec
+{
+ NodeTag type;
+
+ char strategy; /* see PARTITION_STRATEGY codes above */
+ bool is_default; /* is it a default partition bound? */
+
+ /* Partitioning info for HASH strategy: */
+ int modulus;
+ int remainder;
+
+ /* Partitioning info for LIST strategy: */
+ List *listdatums; /* List of Consts (or A_Consts in raw tree) */
+
+ /* Partitioning info for RANGE strategy: */
+ List *lowerdatums; /* List of PartitionRangeDatums */
+ List *upperdatums; /* List of PartitionRangeDatums */
+
+ int location; /* token location, or -1 if unknown */
+};
+
+/*
+ * PartitionRangeDatum - one of the values in a range partition bound
+ *
+ * This can be MINVALUE, MAXVALUE or a specific bounded value.
+ */
+typedef enum PartitionRangeDatumKind
+{
+ PARTITION_RANGE_DATUM_MINVALUE = -1, /* less than any other value */
+ PARTITION_RANGE_DATUM_VALUE = 0, /* a specific (bounded) value */
+ PARTITION_RANGE_DATUM_MAXVALUE = 1 /* greater than any other value */
+} PartitionRangeDatumKind;
+
+typedef struct PartitionRangeDatum
+{
+ NodeTag type;
+
+ PartitionRangeDatumKind kind;
+ Node *value; /* Const (or A_Const in raw tree), if kind is
+ * PARTITION_RANGE_DATUM_VALUE, else NULL */
+
+ int location; /* token location, or -1 if unknown */
+} PartitionRangeDatum;
+
+/*
+ * PartitionCmd - info for ALTER TABLE/INDEX ATTACH/DETACH PARTITION commands
+ */
+typedef struct PartitionCmd
+{
+ NodeTag type;
+ RangeVar *name; /* name of partition to attach/detach */
+ PartitionBoundSpec *bound; /* FOR VALUES, if attaching */
+} PartitionCmd;
+
+/****************************************************************************
+ * Nodes for a Query tree
+ ****************************************************************************/
+
+/*--------------------
+ * RangeTblEntry -
+ * A range table is a List of RangeTblEntry nodes.
+ *
+ * A range table entry may represent a plain relation, a sub-select in
+ * FROM, or the result of a JOIN clause. (Only explicit JOIN syntax
+ * produces an RTE, not the implicit join resulting from multiple FROM
+ * items. This is because we only need the RTE to deal with SQL features
+ * like outer joins and join-output-column aliasing.) Other special
+ * RTE types also exist, as indicated by RTEKind.
+ *
+ * Note that we consider RTE_RELATION to cover anything that has a pg_class
+ * entry. relkind distinguishes the sub-cases.
+ *
+ * alias is an Alias node representing the AS alias-clause attached to the
+ * FROM expression, or NULL if no clause.
+ *
+ * eref is the table reference name and column reference names (either
+ * real or aliases). Note that system columns (OID etc) are not included
+ * in the column list.
+ * eref->aliasname is required to be present, and should generally be used
+ * to identify the RTE for error messages etc.
+ *
+ * In RELATION RTEs, the colnames in both alias and eref are indexed by
+ * physical attribute number; this means there must be colname entries for
+ * dropped columns. When building an RTE we insert empty strings ("") for
+ * dropped columns. Note however that a stored rule may have nonempty
+ * colnames for columns dropped since the rule was created (and for that
+ * matter the colnames might be out of date due to column renamings).
+ * The same comments apply to FUNCTION RTEs when a function's return type
+ * is a named composite type.
+ *
+ * In JOIN RTEs, the colnames in both alias and eref are one-to-one with
+ * joinaliasvars entries. A JOIN RTE will omit columns of its inputs when
+ * those columns are known to be dropped at parse time. Again, however,
+ * a stored rule might contain entries for columns dropped since the rule
+ * was created. (This is only possible for columns not actually referenced
+ * in the rule.) When loading a stored rule, we replace the joinaliasvars
+ * items for any such columns with null pointers. (We can't simply delete
+ * them from the joinaliasvars list, because that would affect the attnums
+ * of Vars referencing the rest of the list.)
+ *
+ * inh is true for relation references that should be expanded to include
+ * inheritance children, if the rel has any. This *must* be false for
+ * RTEs other than RTE_RELATION entries.
+ *
+ * inFromCl marks those range variables that are listed in the FROM clause.
+ * It's false for RTEs that are added to a query behind the scenes, such
+ * as the NEW and OLD variables for a rule, or the subqueries of a UNION.
+ * This flag is not used anymore during parsing, since the parser now uses
+ * a separate "namespace" data structure to control visibility, but it is
+ * needed by ruleutils.c to determine whether RTEs should be shown in
+ * decompiled queries.
+ *
+ * requiredPerms and checkAsUser specify run-time access permissions
+ * checks to be performed at query startup. The user must have *all*
+ * of the permissions that are OR'd together in requiredPerms (zero
+ * indicates no permissions checking). If checkAsUser is not zero,
+ * then do the permissions checks using the access rights of that user,
+ * not the current effective user ID. (This allows rules to act as
+ * setuid gateways.) Permissions checks only apply to RELATION RTEs.
+ *
+ * For SELECT/INSERT/UPDATE permissions, if the user doesn't have
+ * table-wide permissions then it is sufficient to have the permissions
+ * on all columns identified in selectedCols (for SELECT) and/or
+ * insertedCols and/or updatedCols (INSERT with ON CONFLICT DO UPDATE may
+ * have all 3). selectedCols, insertedCols and updatedCols are bitmapsets,
+ * which cannot have negative integer members, so we subtract
+ * FirstLowInvalidHeapAttributeNumber from column numbers before storing
+ * them in these fields. A whole-row Var reference is represented by
+ * setting the bit for InvalidAttrNumber.
+ *
+ * updatedCols is also used in some other places, for example, to determine
+ * which triggers to fire and in FDWs to know which changed columns they
+ * need to ship off.
+ *
+ * Generated columns that are caused to be updated by an update to a base
+ * column are listed in extraUpdatedCols. This is not considered for
+ * permission checking, but it is useful in those places that want to know
+ * the full set of columns being updated as opposed to only the ones the
+ * user explicitly mentioned in the query. (There is currently no need for
+ * an extraInsertedCols, but it could exist.) Note that extraUpdatedCols
+ * is populated during query rewrite, NOT in the parser, since generated
+ * columns could be added after a rule has been parsed and stored.
+ *
+ * securityQuals is a list of security barrier quals (boolean expressions),
+ * to be tested in the listed order before returning a row from the
+ * relation. It is always NIL in parser output. Entries are added by the
+ * rewriter to implement security-barrier views and/or row-level security.
+ * Note that the planner turns each boolean expression into an implicitly
+ * AND'ed sublist, as is its usual habit with qualification expressions.
+ *--------------------
+ */
+typedef enum RTEKind
+{
+ RTE_RELATION, /* ordinary relation reference */
+ RTE_SUBQUERY, /* subquery in FROM */
+ RTE_JOIN, /* join */
+ RTE_FUNCTION, /* function in FROM */
+ RTE_TABLEFUNC, /* TableFunc(.., column list) */
+ RTE_VALUES, /* VALUES (<exprlist>), (<exprlist>), ... */
+ RTE_CTE, /* common table expr (WITH list element) */
+ RTE_NAMEDTUPLESTORE, /* tuplestore, e.g. for AFTER triggers */
+ RTE_RESULT /* RTE represents an empty FROM clause; such
+ * RTEs are added by the planner, they're not
+ * present during parsing or rewriting */
+} RTEKind;
+
+typedef struct RangeTblEntry
+{
+ NodeTag type;
+
+ RTEKind rtekind; /* see above */
+
+ /*
+ * XXX the fields applicable to only some rte kinds should be merged into
+ * a union. I didn't do this yet because the diffs would impact a lot of
+ * code that is being actively worked on. FIXME someday.
+ */
+
+ /*
+ * Fields valid for a plain relation RTE (else zero):
+ *
+ * As a special case, RTE_NAMEDTUPLESTORE can also set relid to indicate
+ * that the tuple format of the tuplestore is the same as the referenced
+ * relation. This allows plans referencing AFTER trigger transition
+ * tables to be invalidated if the underlying table is altered.
+ *
+ * rellockmode is really LOCKMODE, but it's declared int to avoid having
+ * to include lock-related headers here. It must be RowExclusiveLock if
+ * the RTE is an INSERT/UPDATE/DELETE target, else RowShareLock if the RTE
+ * is a SELECT FOR UPDATE/FOR SHARE target, else AccessShareLock.
+ *
+ * Note: in some cases, rule expansion may result in RTEs that are marked
+ * with RowExclusiveLock even though they are not the target of the
+ * current query; this happens if a DO ALSO rule simply scans the original
+ * target table. We leave such RTEs with their original lockmode so as to
+ * avoid getting an additional, lesser lock.
+ */
+ Oid relid; /* OID of the relation */
+ char relkind; /* relation kind (see pg_class.relkind) */
+ int rellockmode; /* lock level that query requires on the rel */
+ struct TableSampleClause *tablesample; /* sampling info, or NULL */
+
+ /*
+ * Fields valid for a subquery RTE (else NULL):
+ */
+ Query *subquery; /* the sub-query */
+ bool security_barrier; /* is from security_barrier view? */
+
+ /*
+ * Fields valid for a join RTE (else NULL/zero):
+ *
+ * joinaliasvars is a list of (usually) Vars corresponding to the columns
+ * of the join result. An alias Var referencing column K of the join
+ * result can be replaced by the K'th element of joinaliasvars --- but to
+ * simplify the task of reverse-listing aliases correctly, we do not do
+ * that until planning time. In detail: an element of joinaliasvars can
+ * be a Var of one of the join's input relations, or such a Var with an
+ * implicit coercion to the join's output column type, or a COALESCE
+ * expression containing the two input column Vars (possibly coerced).
+ * Elements beyond the first joinmergedcols entries are always just Vars,
+ * and are never referenced from elsewhere in the query (that is, join
+ * alias Vars are generated only for merged columns). We keep these
+ * entries only because they're needed in expandRTE() and similar code.
+ *
+ * Within a Query loaded from a stored rule, it is possible for non-merged
+ * joinaliasvars items to be null pointers, which are placeholders for
+ * (necessarily unreferenced) columns dropped since the rule was made.
+ * Also, once planning begins, joinaliasvars items can be almost anything,
+ * as a result of subquery-flattening substitutions.
+ *
+ * joinleftcols is an integer list of physical column numbers of the left
+ * join input rel that are included in the join; likewise joinrighttcols
+ * for the right join input rel. (Which rels those are can be determined
+ * from the associated JoinExpr.) If the join is USING/NATURAL, then the
+ * first joinmergedcols entries in each list identify the merged columns.
+ * The merged columns come first in the join output, then remaining
+ * columns of the left input, then remaining columns of the right.
+ *
+ * Note that input columns could have been dropped after creation of a
+ * stored rule, if they are not referenced in the query (in particular,
+ * merged columns could not be dropped); this is not accounted for in
+ * joinleftcols/joinrighttcols.
+ */
+ JoinType jointype; /* type of join */
+ int joinmergedcols; /* number of merged (JOIN USING) columns */
+ List *joinaliasvars; /* list of alias-var expansions */
+ List *joinleftcols; /* left-side input column numbers */
+ List *joinrightcols; /* right-side input column numbers */
+
+ /*
+ * Fields valid for a function RTE (else NIL/zero):
+ *
+ * When funcordinality is true, the eref->colnames list includes an alias
+ * for the ordinality column. The ordinality column is otherwise
+ * implicit, and must be accounted for "by hand" in places such as
+ * expandRTE().
+ */
+ List *functions; /* list of RangeTblFunction nodes */
+ bool funcordinality; /* is this called WITH ORDINALITY? */
+
+ /*
+ * Fields valid for a TableFunc RTE (else NULL):
+ */
+ TableFunc *tablefunc;
+
+ /*
+ * Fields valid for a values RTE (else NIL):
+ */
+ List *values_lists; /* list of expression lists */
+
+ /*
+ * Fields valid for a CTE RTE (else NULL/zero):
+ */
+ char *ctename; /* name of the WITH list item */
+ Index ctelevelsup; /* number of query levels up */
+ bool self_reference; /* is this a recursive self-reference? */
+
+ /*
+ * Fields valid for CTE, VALUES, ENR, and TableFunc RTEs (else NIL):
+ *
+ * We need these for CTE RTEs so that the types of self-referential
+ * columns are well-defined. For VALUES RTEs, storing these explicitly
+ * saves having to re-determine the info by scanning the values_lists. For
+ * ENRs, we store the types explicitly here (we could get the information
+ * from the catalogs if 'relid' was supplied, but we'd still need these
+ * for TupleDesc-based ENRs, so we might as well always store the type
+ * info here). For TableFuncs, these fields are redundant with data in
+ * the TableFunc node, but keeping them here allows some code sharing with
+ * the other cases.
+ *
+ * For ENRs only, we have to consider the possibility of dropped columns.
+ * A dropped column is included in these lists, but it will have zeroes in
+ * all three lists (as well as an empty-string entry in eref). Testing
+ * for zero coltype is the standard way to detect a dropped column.
+ */
+ List *coltypes; /* OID list of column type OIDs */
+ List *coltypmods; /* integer list of column typmods */
+ List *colcollations; /* OID list of column collation OIDs */
+
+ /*
+ * Fields valid for ENR RTEs (else NULL/zero):
+ */
+ char *enrname; /* name of ephemeral named relation */
+ double enrtuples; /* estimated or actual from caller */
+
+ /*
+ * Fields valid in all RTEs:
+ */
+ Alias *alias; /* user-written alias clause, if any */
+ Alias *eref; /* expanded reference names */
+ bool lateral; /* subquery, function, or values is LATERAL? */
+ bool inh; /* inheritance requested? */
+ bool inFromCl; /* present in FROM clause? */
+ AclMode requiredPerms; /* bitmask of required access permissions */
+ Oid checkAsUser; /* if valid, check access as this role */
+ Bitmapset *selectedCols; /* columns needing SELECT permission */
+ Bitmapset *insertedCols; /* columns needing INSERT permission */
+ Bitmapset *updatedCols; /* columns needing UPDATE permission */
+ Bitmapset *extraUpdatedCols; /* generated columns being updated */
+ List *securityQuals; /* security barrier quals to apply, if any */
+} RangeTblEntry;
+
+/*
+ * RangeTblFunction -
+ * RangeTblEntry subsidiary data for one function in a FUNCTION RTE.
+ *
+ * If the function had a column definition list (required for an
+ * otherwise-unspecified RECORD result), funccolnames lists the names given
+ * in the definition list, funccoltypes lists their declared column types,
+ * funccoltypmods lists their typmods, funccolcollations their collations.
+ * Otherwise, those fields are NIL.
+ *
+ * Notice we don't attempt to store info about the results of functions
+ * returning named composite types, because those can change from time to
+ * time. We do however remember how many columns we thought the type had
+ * (including dropped columns!), so that we can successfully ignore any
+ * columns added after the query was parsed.
+ */
+typedef struct RangeTblFunction
+{
+ NodeTag type;
+
+ Node *funcexpr; /* expression tree for func call */
+ int funccolcount; /* number of columns it contributes to RTE */
+ /* These fields record the contents of a column definition list, if any: */
+ List *funccolnames; /* column names (list of String) */
+ List *funccoltypes; /* OID list of column type OIDs */
+ List *funccoltypmods; /* integer list of column typmods */
+ List *funccolcollations; /* OID list of column collation OIDs */
+ /* This is set during planning for use by the executor: */
+ Bitmapset *funcparams; /* PARAM_EXEC Param IDs affecting this func */
+} RangeTblFunction;
+
+/*
+ * TableSampleClause - TABLESAMPLE appearing in a transformed FROM clause
+ *
+ * Unlike RangeTableSample, this is a subnode of the relevant RangeTblEntry.
+ */
+typedef struct TableSampleClause
+{
+ NodeTag type;
+ Oid tsmhandler; /* OID of the tablesample handler function */
+ List *args; /* tablesample argument expression(s) */
+ Expr *repeatable; /* REPEATABLE expression, or NULL if none */
+} TableSampleClause;
+
+/*
+ * WithCheckOption -
+ * representation of WITH CHECK OPTION checks to be applied to new tuples
+ * when inserting/updating an auto-updatable view, or RLS WITH CHECK
+ * policies to be applied when inserting/updating a relation with RLS.
+ */
+typedef enum WCOKind
+{
+ WCO_VIEW_CHECK, /* WCO on an auto-updatable view */
+ WCO_RLS_INSERT_CHECK, /* RLS INSERT WITH CHECK policy */
+ WCO_RLS_UPDATE_CHECK, /* RLS UPDATE WITH CHECK policy */
+ WCO_RLS_CONFLICT_CHECK /* RLS ON CONFLICT DO UPDATE USING policy */
+} WCOKind;
+
+typedef struct WithCheckOption
+{
+ NodeTag type;
+ WCOKind kind; /* kind of WCO */
+ char *relname; /* name of relation that specified the WCO */
+ char *polname; /* name of RLS policy being checked */
+ Node *qual; /* constraint qual to check */
+ bool cascaded; /* true for a cascaded WCO on a view */
+} WithCheckOption;
+
+/*
+ * SortGroupClause -
+ * representation of ORDER BY, GROUP BY, PARTITION BY,
+ * DISTINCT, DISTINCT ON items
+ *
+ * You might think that ORDER BY is only interested in defining ordering,
+ * and GROUP/DISTINCT are only interested in defining equality. However,
+ * one way to implement grouping is to sort and then apply a "uniq"-like
+ * filter. So it's also interesting to keep track of possible sort operators
+ * for GROUP/DISTINCT, and in particular to try to sort for the grouping
+ * in a way that will also yield a requested ORDER BY ordering. So we need
+ * to be able to compare ORDER BY and GROUP/DISTINCT lists, which motivates
+ * the decision to give them the same representation.
+ *
+ * tleSortGroupRef must match ressortgroupref of exactly one entry of the
+ * query's targetlist; that is the expression to be sorted or grouped by.
+ * eqop is the OID of the equality operator.
+ * sortop is the OID of the ordering operator (a "<" or ">" operator),
+ * or InvalidOid if not available.
+ * nulls_first means about what you'd expect. If sortop is InvalidOid
+ * then nulls_first is meaningless and should be set to false.
+ * hashable is true if eqop is hashable (note this condition also depends
+ * on the datatype of the input expression).
+ *
+ * In an ORDER BY item, all fields must be valid. (The eqop isn't essential
+ * here, but it's cheap to get it along with the sortop, and requiring it
+ * to be valid eases comparisons to grouping items.) Note that this isn't
+ * actually enough information to determine an ordering: if the sortop is
+ * collation-sensitive, a collation OID is needed too. We don't store the
+ * collation in SortGroupClause because it's not available at the time the
+ * parser builds the SortGroupClause; instead, consult the exposed collation
+ * of the referenced targetlist expression to find out what it is.
+ *
+ * In a grouping item, eqop must be valid. If the eqop is a btree equality
+ * operator, then sortop should be set to a compatible ordering operator.
+ * We prefer to set eqop/sortop/nulls_first to match any ORDER BY item that
+ * the query presents for the same tlist item. If there is none, we just
+ * use the default ordering op for the datatype.
+ *
+ * If the tlist item's type has a hash opclass but no btree opclass, then
+ * we will set eqop to the hash equality operator, sortop to InvalidOid,
+ * and nulls_first to false. A grouping item of this kind can only be
+ * implemented by hashing, and of course it'll never match an ORDER BY item.
+ *
+ * The hashable flag is provided since we generally have the requisite
+ * information readily available when the SortGroupClause is constructed,
+ * and it's relatively expensive to get it again later. Note there is no
+ * need for a "sortable" flag since OidIsValid(sortop) serves the purpose.
+ *
+ * A query might have both ORDER BY and DISTINCT (or DISTINCT ON) clauses.
+ * In SELECT DISTINCT, the distinctClause list is as long or longer than the
+ * sortClause list, while in SELECT DISTINCT ON it's typically shorter.
+ * The two lists must match up to the end of the shorter one --- the parser
+ * rearranges the distinctClause if necessary to make this true. (This
+ * restriction ensures that only one sort step is needed to both satisfy the
+ * ORDER BY and set up for the Unique step. This is semantically necessary
+ * for DISTINCT ON, and presents no real drawback for DISTINCT.)
+ */
+typedef struct SortGroupClause
+{
+ NodeTag type;
+ Index tleSortGroupRef; /* reference into targetlist */
+ Oid eqop; /* the equality operator ('=' op) */
+ Oid sortop; /* the ordering operator ('<' op), or 0 */
+ bool nulls_first; /* do NULLs come before normal values? */
+ bool hashable; /* can eqop be implemented by hashing? */
+} SortGroupClause;
+
+/*
+ * GroupingSet -
+ * representation of CUBE, ROLLUP and GROUPING SETS clauses
+ *
+ * In a Query with grouping sets, the groupClause contains a flat list of
+ * SortGroupClause nodes for each distinct expression used. The actual
+ * structure of the GROUP BY clause is given by the groupingSets tree.
+ *
+ * In the raw parser output, GroupingSet nodes (of all types except SIMPLE
+ * which is not used) are potentially mixed in with the expressions in the
+ * groupClause of the SelectStmt. (An expression can't contain a GroupingSet,
+ * but a list may mix GroupingSet and expression nodes.) At this stage, the
+ * content of each node is a list of expressions, some of which may be RowExprs
+ * which represent sublists rather than actual row constructors, and nested
+ * GroupingSet nodes where legal in the grammar. The structure directly
+ * reflects the query syntax.
+ *
+ * In parse analysis, the transformed expressions are used to build the tlist
+ * and groupClause list (of SortGroupClause nodes), and the groupingSets tree
+ * is eventually reduced to a fixed format:
+ *
+ * EMPTY nodes represent (), and obviously have no content
+ *
+ * SIMPLE nodes represent a list of one or more expressions to be treated as an
+ * atom by the enclosing structure; the content is an integer list of
+ * ressortgroupref values (see SortGroupClause)
+ *
+ * CUBE and ROLLUP nodes contain a list of one or more SIMPLE nodes.
+ *
+ * SETS nodes contain a list of EMPTY, SIMPLE, CUBE or ROLLUP nodes, but after
+ * parse analysis they cannot contain more SETS nodes; enough of the syntactic
+ * transforms of the spec have been applied that we no longer have arbitrarily
+ * deep nesting (though we still preserve the use of cube/rollup).
+ *
+ * Note that if the groupingSets tree contains no SIMPLE nodes (only EMPTY
+ * nodes at the leaves), then the groupClause will be empty, but this is still
+ * an aggregation query (similar to using aggs or HAVING without GROUP BY).
+ *
+ * As an example, the following clause:
+ *
+ * GROUP BY GROUPING SETS ((a,b), CUBE(c,(d,e)))
+ *
+ * looks like this after raw parsing:
+ *
+ * SETS( RowExpr(a,b) , CUBE( c, RowExpr(d,e) ) )
+ *
+ * and parse analysis converts it to:
+ *
+ * SETS( SIMPLE(1,2), CUBE( SIMPLE(3), SIMPLE(4,5) ) )
+ */
+typedef enum
+{
+ GROUPING_SET_EMPTY,
+ GROUPING_SET_SIMPLE,
+ GROUPING_SET_ROLLUP,
+ GROUPING_SET_CUBE,
+ GROUPING_SET_SETS
+} GroupingSetKind;
+
+typedef struct GroupingSet
+{
+ NodeTag type;
+ GroupingSetKind kind;
+ List *content;
+ int location;
+} GroupingSet;
+
+/*
+ * WindowClause -
+ * transformed representation of WINDOW and OVER clauses
+ *
+ * A parsed Query's windowClause list contains these structs. "name" is set
+ * if the clause originally came from WINDOW, and is NULL if it originally
+ * was an OVER clause (but note that we collapse out duplicate OVERs).
+ * partitionClause and orderClause are lists of SortGroupClause structs.
+ * If we have RANGE with offset PRECEDING/FOLLOWING, the semantics of that are
+ * specified by startInRangeFunc/inRangeColl/inRangeAsc/inRangeNullsFirst
+ * for the start offset, or endInRangeFunc/inRange* for the end offset.
+ * winref is an ID number referenced by WindowFunc nodes; it must be unique
+ * among the members of a Query's windowClause list.
+ * When refname isn't null, the partitionClause is always copied from there;
+ * the orderClause might or might not be copied (see copiedOrder); the framing
+ * options are never copied, per spec.
+ */
+typedef struct WindowClause
+{
+ NodeTag type;
+ char *name; /* window name (NULL in an OVER clause) */
+ char *refname; /* referenced window name, if any */
+ List *partitionClause; /* PARTITION BY list */
+ List *orderClause; /* ORDER BY list */
+ int frameOptions; /* frame_clause options, see WindowDef */
+ Node *startOffset; /* expression for starting bound, if any */
+ Node *endOffset; /* expression for ending bound, if any */
+ Oid startInRangeFunc; /* in_range function for startOffset */
+ Oid endInRangeFunc; /* in_range function for endOffset */
+ Oid inRangeColl; /* collation for in_range tests */
+ bool inRangeAsc; /* use ASC sort order for in_range tests? */
+ bool inRangeNullsFirst; /* nulls sort first for in_range tests? */
+ Index winref; /* ID referenced by window functions */
+ bool copiedOrder; /* did we copy orderClause from refname? */
+} WindowClause;
+
+/*
+ * RowMarkClause -
+ * parser output representation of FOR [KEY] UPDATE/SHARE clauses
+ *
+ * Query.rowMarks contains a separate RowMarkClause node for each relation
+ * identified as a FOR [KEY] UPDATE/SHARE target. If one of these clauses
+ * is applied to a subquery, we generate RowMarkClauses for all normal and
+ * subquery rels in the subquery, but they are marked pushedDown = true to
+ * distinguish them from clauses that were explicitly written at this query
+ * level. Also, Query.hasForUpdate tells whether there were explicit FOR
+ * UPDATE/SHARE/KEY SHARE clauses in the current query level.
+ */
+typedef struct RowMarkClause
+{
+ NodeTag type;
+ Index rti; /* range table index of target relation */
+ LockClauseStrength strength;
+ LockWaitPolicy waitPolicy; /* NOWAIT and SKIP LOCKED */
+ bool pushedDown; /* pushed down from higher query level? */
+} RowMarkClause;
+
+/*
+ * WithClause -
+ * representation of WITH clause
+ *
+ * Note: WithClause does not propagate into the Query representation;
+ * but CommonTableExpr does.
+ */
+typedef struct WithClause
+{
+ NodeTag type;
+ List *ctes; /* list of CommonTableExprs */
+ bool recursive; /* true = WITH RECURSIVE */
+ int location; /* token location, or -1 if unknown */
+} WithClause;
+
+/*
+ * InferClause -
+ * ON CONFLICT unique index inference clause
+ *
+ * Note: InferClause does not propagate into the Query representation.
+ */
+typedef struct InferClause
+{
+ NodeTag type;
+ List *indexElems; /* IndexElems to infer unique index */
+ Node *whereClause; /* qualification (partial-index predicate) */
+ char *conname; /* Constraint name, or NULL if unnamed */
+ int location; /* token location, or -1 if unknown */
+} InferClause;
+
+/*
+ * OnConflictClause -
+ * representation of ON CONFLICT clause
+ *
+ * Note: OnConflictClause does not propagate into the Query representation.
+ */
+typedef struct OnConflictClause
+{
+ NodeTag type;
+ OnConflictAction action; /* DO NOTHING or UPDATE? */
+ InferClause *infer; /* Optional index inference clause */
+ List *targetList; /* the target list (of ResTarget) */
+ Node *whereClause; /* qualifications */
+ int location; /* token location, or -1 if unknown */
+} OnConflictClause;
+
+/*
+ * CommonTableExpr -
+ * representation of WITH list element
+ *
+ * We don't currently support the SEARCH or CYCLE clause.
+ */
+typedef enum CTEMaterialize
+{
+ CTEMaterializeDefault, /* no option specified */
+ CTEMaterializeAlways, /* MATERIALIZED */
+ CTEMaterializeNever /* NOT MATERIALIZED */
+} CTEMaterialize;
+
+typedef struct CommonTableExpr
+{
+ NodeTag type;
+ char *ctename; /* query name (never qualified) */
+ List *aliascolnames; /* optional list of column names */
+ CTEMaterialize ctematerialized; /* is this an optimization fence? */
+ /* SelectStmt/InsertStmt/etc before parse analysis, Query afterwards: */
+ Node *ctequery; /* the CTE's subquery */
+ int location; /* token location, or -1 if unknown */
+ /* These fields are set during parse analysis: */
+ bool cterecursive; /* is this CTE actually recursive? */
+ int cterefcount; /* number of RTEs referencing this CTE
+ * (excluding internal self-references) */
+ List *ctecolnames; /* list of output column names */
+ List *ctecoltypes; /* OID list of output column type OIDs */
+ List *ctecoltypmods; /* integer list of output column typmods */
+ List *ctecolcollations; /* OID list of column collation OIDs */
+} CommonTableExpr;
+
+/* Convenience macro to get the output tlist of a CTE's query */
+#define GetCTETargetList(cte) \
+ (AssertMacro(IsA((cte)->ctequery, Query)), \
+ ((Query *) (cte)->ctequery)->commandType == CMD_SELECT ? \
+ ((Query *) (cte)->ctequery)->targetList : \
+ ((Query *) (cte)->ctequery)->returningList)
+
+/*
+ * TriggerTransition -
+ * representation of transition row or table naming clause
+ *
+ * Only transition tables are initially supported in the syntax, and only for
+ * AFTER triggers, but other permutations are accepted by the parser so we can
+ * give a meaningful message from C code.
+ */
+typedef struct TriggerTransition
+{
+ NodeTag type;
+ char *name;
+ bool isNew;
+ bool isTable;
+} TriggerTransition;
+
+/*****************************************************************************
+ * Raw Grammar Output Statements
+ *****************************************************************************/
+
+/*
+ * RawStmt --- container for any one statement's raw parse tree
+ *
+ * Parse analysis converts a raw parse tree headed by a RawStmt node into
+ * an analyzed statement headed by a Query node. For optimizable statements,
+ * the conversion is complex. For utility statements, the parser usually just
+ * transfers the raw parse tree (sans RawStmt) into the utilityStmt field of
+ * the Query node, and all the useful work happens at execution time.
+ *
+ * stmt_location/stmt_len identify the portion of the source text string
+ * containing this raw statement (useful for multi-statement strings).
+ */
+typedef struct RawStmt
+{
+ NodeTag type;
+ Node *stmt; /* raw parse tree */
+ int stmt_location; /* start location, or -1 if unknown */
+ int stmt_len; /* length in bytes; 0 means "rest of string" */
+} RawStmt;
+
+/*****************************************************************************
+ * Optimizable Statements
+ *****************************************************************************/
+
+/* ----------------------
+ * Insert Statement
+ *
+ * The source expression is represented by SelectStmt for both the
+ * SELECT and VALUES cases. If selectStmt is NULL, then the query
+ * is INSERT ... DEFAULT VALUES.
+ * ----------------------
+ */
+typedef struct InsertStmt
+{
+ NodeTag type;
+ RangeVar *relation; /* relation to insert into */
+ List *cols; /* optional: names of the target columns */
+ Node *selectStmt; /* the source SELECT/VALUES, or NULL */
+ OnConflictClause *onConflictClause; /* ON CONFLICT clause */
+ List *returningList; /* list of expressions to return */
+ WithClause *withClause; /* WITH clause */
+ OverridingKind override; /* OVERRIDING clause */
+} InsertStmt;
+
+/* ----------------------
+ * Delete Statement
+ * ----------------------
+ */
+typedef struct DeleteStmt
+{
+ NodeTag type;
+ RangeVar *relation; /* relation to delete from */
+ List *usingClause; /* optional using clause for more tables */
+ Node *whereClause; /* qualifications */
+ List *returningList; /* list of expressions to return */
+ WithClause *withClause; /* WITH clause */
+} DeleteStmt;
+
+/* ----------------------
+ * Update Statement
+ * ----------------------
+ */
+typedef struct UpdateStmt
+{
+ NodeTag type;
+ RangeVar *relation; /* relation to update */
+ List *targetList; /* the target list (of ResTarget) */
+ Node *whereClause; /* qualifications */
+ List *fromClause; /* optional from clause for more tables */
+ List *returningList; /* list of expressions to return */
+ WithClause *withClause; /* WITH clause */
+} UpdateStmt;
+
+/* ----------------------
+ * Select Statement
+ *
+ * A "simple" SELECT is represented in the output of gram.y by a single
+ * SelectStmt node; so is a VALUES construct. A query containing set
+ * operators (UNION, INTERSECT, EXCEPT) is represented by a tree of SelectStmt
+ * nodes, in which the leaf nodes are component SELECTs and the internal nodes
+ * represent UNION, INTERSECT, or EXCEPT operators. Using the same node
+ * type for both leaf and internal nodes allows gram.y to stick ORDER BY,
+ * LIMIT, etc, clause values into a SELECT statement without worrying
+ * whether it is a simple or compound SELECT.
+ * ----------------------
+ */
+typedef enum SetOperation
+{
+ SETOP_NONE = 0,
+ SETOP_UNION,
+ SETOP_INTERSECT,
+ SETOP_EXCEPT
+} SetOperation;
+
+typedef struct SelectStmt
+{
+ NodeTag type;
+
+ /*
+ * These fields are used only in "leaf" SelectStmts.
+ */
+ List *distinctClause; /* NULL, list of DISTINCT ON exprs, or
+ * lcons(NIL,NIL) for all (SELECT DISTINCT) */
+ IntoClause *intoClause; /* target for SELECT INTO */
+ List *targetList; /* the target list (of ResTarget) */
+ List *fromClause; /* the FROM clause */
+ Node *whereClause; /* WHERE qualification */
+ List *groupClause; /* GROUP BY clauses */
+ Node *havingClause; /* HAVING conditional-expression */
+ List *windowClause; /* WINDOW window_name AS (...), ... */
+
+ /*
+ * In a "leaf" node representing a VALUES list, the above fields are all
+ * null, and instead this field is set. Note that the elements of the
+ * sublists are just expressions, without ResTarget decoration. Also note
+ * that a list element can be DEFAULT (represented as a SetToDefault
+ * node), regardless of the context of the VALUES list. It's up to parse
+ * analysis to reject that where not valid.
+ */
+ List *valuesLists; /* untransformed list of expression lists */
+
+ /*
+ * These fields are used in both "leaf" SelectStmts and upper-level
+ * SelectStmts.
+ */
+ List *sortClause; /* sort clause (a list of SortBy's) */
+ Node *limitOffset; /* # of result tuples to skip */
+ Node *limitCount; /* # of result tuples to return */
+ LimitOption limitOption; /* limit type */
+ List *lockingClause; /* FOR UPDATE (list of LockingClause's) */
+ WithClause *withClause; /* WITH clause */
+
+ /*
+ * These fields are used only in upper-level SelectStmts.
+ */
+ SetOperation op; /* type of set op */
+ bool all; /* ALL specified? */
+ struct SelectStmt *larg; /* left child */
+ struct SelectStmt *rarg; /* right child */
+ /* Eventually add fields for CORRESPONDING spec here */
+} SelectStmt;
+
+
+/* ----------------------
+ * Set Operation node for post-analysis query trees
+ *
+ * After parse analysis, a SELECT with set operations is represented by a
+ * top-level Query node containing the leaf SELECTs as subqueries in its
+ * range table. Its setOperations field shows the tree of set operations,
+ * with leaf SelectStmt nodes replaced by RangeTblRef nodes, and internal
+ * nodes replaced by SetOperationStmt nodes. Information about the output
+ * column types is added, too. (Note that the child nodes do not necessarily
+ * produce these types directly, but we've checked that their output types
+ * can be coerced to the output column type.) Also, if it's not UNION ALL,
+ * information about the types' sort/group semantics is provided in the form
+ * of a SortGroupClause list (same representation as, eg, DISTINCT).
+ * The resolved common column collations are provided too; but note that if
+ * it's not UNION ALL, it's okay for a column to not have a common collation,
+ * so a member of the colCollations list could be InvalidOid even though the
+ * column has a collatable type.
+ * ----------------------
+ */
+typedef struct SetOperationStmt
+{
+ NodeTag type;
+ SetOperation op; /* type of set op */
+ bool all; /* ALL specified? */
+ Node *larg; /* left child */
+ Node *rarg; /* right child */
+ /* Eventually add fields for CORRESPONDING spec here */
+
+ /* Fields derived during parse analysis: */
+ List *colTypes; /* OID list of output column type OIDs */
+ List *colTypmods; /* integer list of output column typmods */
+ List *colCollations; /* OID list of output column collation OIDs */
+ List *groupClauses; /* a list of SortGroupClause's */
+ /* groupClauses is NIL if UNION ALL, but must be set otherwise */
+} SetOperationStmt;
+
+
+/*****************************************************************************
+ * Other Statements (no optimizations required)
+ *
+ * These are not touched by parser/analyze.c except to put them into
+ * the utilityStmt field of a Query. This is eventually passed to
+ * ProcessUtility (by-passing rewriting and planning). Some of the
+ * statements do need attention from parse analysis, and this is
+ * done by routines in parser/parse_utilcmd.c after ProcessUtility
+ * receives the command for execution.
+ * DECLARE CURSOR, EXPLAIN, and CREATE TABLE AS are special cases:
+ * they contain optimizable statements, which get processed normally
+ * by parser/analyze.c.
+ *****************************************************************************/
+
+/*
+ * When a command can act on several kinds of objects with only one
+ * parse structure required, use these constants to designate the
+ * object type. Note that commands typically don't support all the types.
+ */
+
+typedef enum ObjectType
+{
+ OBJECT_ACCESS_METHOD,
+ OBJECT_AGGREGATE,
+ OBJECT_AMOP,
+ OBJECT_AMPROC,
+ OBJECT_ATTRIBUTE, /* type's attribute, when distinct from column */
+ OBJECT_CAST,
+ OBJECT_COLUMN,
+ OBJECT_COLLATION,
+ OBJECT_CONVERSION,
+ OBJECT_DATABASE,
+ OBJECT_DEFAULT,
+ OBJECT_DEFACL,
+ OBJECT_DOMAIN,
+ OBJECT_DOMCONSTRAINT,
+ OBJECT_EVENT_TRIGGER,
+ OBJECT_EXTENSION,
+ OBJECT_FDW,
+ OBJECT_FOREIGN_SERVER,
+ OBJECT_FOREIGN_TABLE,
+ OBJECT_FUNCTION,
+ OBJECT_INDEX,
+ OBJECT_LANGUAGE,
+ OBJECT_LARGEOBJECT,
+ OBJECT_MATVIEW,
+ OBJECT_OPCLASS,
+ OBJECT_OPERATOR,
+ OBJECT_OPFAMILY,
+ OBJECT_POLICY,
+ OBJECT_PROCEDURE,
+ OBJECT_PUBLICATION,
+ OBJECT_PUBLICATION_REL,
+ OBJECT_ROLE,
+ OBJECT_ROUTINE,
+ OBJECT_RULE,
+ OBJECT_SCHEMA,
+ OBJECT_SEQUENCE,
+ OBJECT_SUBSCRIPTION,
+ OBJECT_STATISTIC_EXT,
+ OBJECT_TABCONSTRAINT,
+ OBJECT_TABLE,
+ OBJECT_TABLESPACE,
+ OBJECT_TRANSFORM,
+ OBJECT_TRIGGER,
+ OBJECT_TSCONFIGURATION,
+ OBJECT_TSDICTIONARY,
+ OBJECT_TSPARSER,
+ OBJECT_TSTEMPLATE,
+ OBJECT_TYPE,
+ OBJECT_USER_MAPPING,
+ OBJECT_VIEW
+} ObjectType;
+
+/* ----------------------
+ * Create Schema Statement
+ *
+ * NOTE: the schemaElts list contains raw parsetrees for component statements
+ * of the schema, such as CREATE TABLE, GRANT, etc. These are analyzed and
+ * executed after the schema itself is created.
+ * ----------------------
+ */
+typedef struct CreateSchemaStmt
+{
+ NodeTag type;
+ char *schemaname; /* the name of the schema to create */
+ RoleSpec *authrole; /* the owner of the created schema */
+ List *schemaElts; /* schema components (list of parsenodes) */
+ bool if_not_exists; /* just do nothing if schema already exists? */
+} CreateSchemaStmt;
+
+typedef enum DropBehavior
+{
+ DROP_RESTRICT, /* drop fails if any dependent objects */
+ DROP_CASCADE /* remove dependent objects too */
+} DropBehavior;
+
+/* ----------------------
+ * Alter Table
+ * ----------------------
+ */
+typedef struct AlterTableStmt
+{
+ NodeTag type;
+ RangeVar *relation; /* table to work on */
+ List *cmds; /* list of subcommands */
+ ObjectType relkind; /* type of object */
+ bool missing_ok; /* skip error if table missing */
+} AlterTableStmt;
+
+typedef enum AlterTableType
+{
+ AT_AddColumn, /* add column */
+ AT_AddColumnRecurse, /* internal to commands/tablecmds.c */
+ AT_AddColumnToView, /* implicitly via CREATE OR REPLACE VIEW */
+ AT_ColumnDefault, /* alter column default */
+ AT_CookedColumnDefault, /* add a pre-cooked column default */
+ AT_DropNotNull, /* alter column drop not null */
+ AT_SetNotNull, /* alter column set not null */
+ AT_DropExpression, /* alter column drop expression */
+ AT_CheckNotNull, /* check column is already marked not null */
+ AT_SetStatistics, /* alter column set statistics */
+ AT_SetOptions, /* alter column set ( options ) */
+ AT_ResetOptions, /* alter column reset ( options ) */
+ AT_SetStorage, /* alter column set storage */
+ AT_DropColumn, /* drop column */
+ AT_DropColumnRecurse, /* internal to commands/tablecmds.c */
+ AT_AddIndex, /* add index */
+ AT_ReAddIndex, /* internal to commands/tablecmds.c */
+ AT_AddConstraint, /* add constraint */
+ AT_AddConstraintRecurse, /* internal to commands/tablecmds.c */
+ AT_ReAddConstraint, /* internal to commands/tablecmds.c */
+ AT_ReAddDomainConstraint, /* internal to commands/tablecmds.c */
+ AT_AlterConstraint, /* alter constraint */
+ AT_ValidateConstraint, /* validate constraint */
+ AT_ValidateConstraintRecurse, /* internal to commands/tablecmds.c */
+ AT_AddIndexConstraint, /* add constraint using existing index */
+ AT_DropConstraint, /* drop constraint */
+ AT_DropConstraintRecurse, /* internal to commands/tablecmds.c */
+ AT_ReAddComment, /* internal to commands/tablecmds.c */
+ AT_AlterColumnType, /* alter column type */
+ AT_AlterColumnGenericOptions, /* alter column OPTIONS (...) */
+ AT_ChangeOwner, /* change owner */
+ AT_ClusterOn, /* CLUSTER ON */
+ AT_DropCluster, /* SET WITHOUT CLUSTER */
+ AT_SetLogged, /* SET LOGGED */
+ AT_SetUnLogged, /* SET UNLOGGED */
+ AT_DropOids, /* SET WITHOUT OIDS */
+ AT_SetTableSpace, /* SET TABLESPACE */
+ AT_SetRelOptions, /* SET (...) -- AM specific parameters */
+ AT_ResetRelOptions, /* RESET (...) -- AM specific parameters */
+ AT_ReplaceRelOptions, /* replace reloption list in its entirety */
+ AT_EnableTrig, /* ENABLE TRIGGER name */
+ AT_EnableAlwaysTrig, /* ENABLE ALWAYS TRIGGER name */
+ AT_EnableReplicaTrig, /* ENABLE REPLICA TRIGGER name */
+ AT_DisableTrig, /* DISABLE TRIGGER name */
+ AT_EnableTrigAll, /* ENABLE TRIGGER ALL */
+ AT_DisableTrigAll, /* DISABLE TRIGGER ALL */
+ AT_EnableTrigUser, /* ENABLE TRIGGER USER */
+ AT_DisableTrigUser, /* DISABLE TRIGGER USER */
+ AT_EnableRule, /* ENABLE RULE name */
+ AT_EnableAlwaysRule, /* ENABLE ALWAYS RULE name */
+ AT_EnableReplicaRule, /* ENABLE REPLICA RULE name */
+ AT_DisableRule, /* DISABLE RULE name */
+ AT_AddInherit, /* INHERIT parent */
+ AT_DropInherit, /* NO INHERIT parent */
+ AT_AddOf, /* OF <type_name> */
+ AT_DropOf, /* NOT OF */
+ AT_ReplicaIdentity, /* REPLICA IDENTITY */
+ AT_EnableRowSecurity, /* ENABLE ROW SECURITY */
+ AT_DisableRowSecurity, /* DISABLE ROW SECURITY */
+ AT_ForceRowSecurity, /* FORCE ROW SECURITY */
+ AT_NoForceRowSecurity, /* NO FORCE ROW SECURITY */
+ AT_GenericOptions, /* OPTIONS (...) */
+ AT_AttachPartition, /* ATTACH PARTITION */
+ AT_DetachPartition, /* DETACH PARTITION */
+ AT_AddIdentity, /* ADD IDENTITY */
+ AT_SetIdentity, /* SET identity column options */
+ AT_DropIdentity /* DROP IDENTITY */
+} AlterTableType;
+
+typedef struct ReplicaIdentityStmt
+{
+ NodeTag type;
+ char identity_type;
+ char *name;
+} ReplicaIdentityStmt;
+
+typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */
+{
+ NodeTag type;
+ AlterTableType subtype; /* Type of table alteration to apply */
+ char *name; /* column, constraint, or trigger to act on,
+ * or tablespace */
+ int16 num; /* attribute number for columns referenced by
+ * number */
+ RoleSpec *newowner;
+ Node *def; /* definition of new column, index,
+ * constraint, or parent table */
+ DropBehavior behavior; /* RESTRICT or CASCADE for DROP cases */
+ bool missing_ok; /* skip error if missing? */
+} AlterTableCmd;
+
+
+/* ----------------------
+ * Alter Collation
+ * ----------------------
+ */
+typedef struct AlterCollationStmt
+{
+ NodeTag type;
+ List *collname;
+} AlterCollationStmt;
+
+
+/* ----------------------
+ * Alter Domain
+ *
+ * The fields are used in different ways by the different variants of
+ * this command.
+ * ----------------------
+ */
+typedef struct AlterDomainStmt
+{
+ NodeTag type;
+ char subtype; /*------------
+ * T = alter column default
+ * N = alter column drop not null
+ * O = alter column set not null
+ * C = add constraint
+ * X = drop constraint
+ *------------
+ */
+ List *typeName; /* domain to work on */
+ char *name; /* column or constraint name to act on */
+ Node *def; /* definition of default or constraint */
+ DropBehavior behavior; /* RESTRICT or CASCADE for DROP cases */
+ bool missing_ok; /* skip error if missing? */
+} AlterDomainStmt;
+
+
+/* ----------------------
+ * Grant|Revoke Statement
+ * ----------------------
+ */
+typedef enum GrantTargetType
+{
+ ACL_TARGET_OBJECT, /* grant on specific named object(s) */
+ ACL_TARGET_ALL_IN_SCHEMA, /* grant on all objects in given schema(s) */
+ ACL_TARGET_DEFAULTS /* ALTER DEFAULT PRIVILEGES */
+} GrantTargetType;
+
+typedef struct GrantStmt
+{
+ NodeTag type;
+ bool is_grant; /* true = GRANT, false = REVOKE */
+ GrantTargetType targtype; /* type of the grant target */
+ ObjectType objtype; /* kind of object being operated on */
+ List *objects; /* list of RangeVar nodes, ObjectWithArgs
+ * nodes, or plain names (as Value strings) */
+ List *privileges; /* list of AccessPriv nodes */
+ /* privileges == NIL denotes ALL PRIVILEGES */
+ List *grantees; /* list of RoleSpec nodes */
+ bool grant_option; /* grant or revoke grant option */
+ DropBehavior behavior; /* drop behavior (for REVOKE) */
+} GrantStmt;
+
+/*
+ * Note: ObjectWithArgs carries only the types of the input parameters of the
+ * function. So it is sufficient to identify an existing function, but it
+ * is not enough info to define a function nor to call it.
+ */
+typedef struct ObjectWithArgs
+{
+ NodeTag type;
+ List *objname; /* qualified name of function/operator */
+ List *objargs; /* list of Typename nodes */
+ bool args_unspecified; /* argument list was omitted, so name must
+ * be unique (note that objargs == NIL
+ * means zero args) */
+} ObjectWithArgs;
+
+/*
+ * An access privilege, with optional list of column names
+ * priv_name == NULL denotes ALL PRIVILEGES (only used with a column list)
+ * cols == NIL denotes "all columns"
+ * Note that simple "ALL PRIVILEGES" is represented as a NIL list, not
+ * an AccessPriv with both fields null.
+ */
+typedef struct AccessPriv
+{
+ NodeTag type;
+ char *priv_name; /* string name of privilege */
+ List *cols; /* list of Value strings */
+} AccessPriv;
+
+/* ----------------------
+ * Grant/Revoke Role Statement
+ *
+ * Note: because of the parsing ambiguity with the GRANT <privileges>
+ * statement, granted_roles is a list of AccessPriv; the execution code
+ * should complain if any column lists appear. grantee_roles is a list
+ * of role names, as Value strings.
+ * ----------------------
+ */
+typedef struct GrantRoleStmt
+{
+ NodeTag type;
+ List *granted_roles; /* list of roles to be granted/revoked */
+ List *grantee_roles; /* list of member roles to add/delete */
+ bool is_grant; /* true = GRANT, false = REVOKE */
+ bool admin_opt; /* with admin option */
+ RoleSpec *grantor; /* set grantor to other than current role */
+ DropBehavior behavior; /* drop behavior (for REVOKE) */
+} GrantRoleStmt;
+
+/* ----------------------
+ * Alter Default Privileges Statement
+ * ----------------------
+ */
+typedef struct AlterDefaultPrivilegesStmt
+{
+ NodeTag type;
+ List *options; /* list of DefElem */
+ GrantStmt *action; /* GRANT/REVOKE action (with objects=NIL) */
+} AlterDefaultPrivilegesStmt;
+
+/* ----------------------
+ * Copy Statement
+ *
+ * We support "COPY relation FROM file", "COPY relation TO file", and
+ * "COPY (query) TO file". In any given CopyStmt, exactly one of "relation"
+ * and "query" must be non-NULL.
+ * ----------------------
+ */
+typedef struct CopyStmt
+{
+ NodeTag type;
+ RangeVar *relation; /* the relation to copy */
+ Node *query; /* the query (SELECT or DML statement with
+ * RETURNING) to copy, as a raw parse tree */
+ List *attlist; /* List of column names (as Strings), or NIL
+ * for all columns */
+ bool is_from; /* TO or FROM */
+ bool is_program; /* is 'filename' a program to popen? */
+ char *filename; /* filename, or NULL for STDIN/STDOUT */
+ List *options; /* List of DefElem nodes */
+ Node *whereClause; /* WHERE condition (or NULL) */
+} CopyStmt;
+
+/* ----------------------
+ * SET Statement (includes RESET)
+ *
+ * "SET var TO DEFAULT" and "RESET var" are semantically equivalent, but we
+ * preserve the distinction in VariableSetKind for CreateCommandTag().
+ * ----------------------
+ */
+typedef enum
+{
+ VAR_SET_VALUE, /* SET var = value */
+ VAR_SET_DEFAULT, /* SET var TO DEFAULT */
+ VAR_SET_CURRENT, /* SET var FROM CURRENT */
+ VAR_SET_MULTI, /* special case for SET TRANSACTION ... */
+ VAR_RESET, /* RESET var */
+ VAR_RESET_ALL /* RESET ALL */
+} VariableSetKind;
+
+typedef struct VariableSetStmt
+{
+ NodeTag type;
+ VariableSetKind kind;
+ char *name; /* variable to be set */
+ List *args; /* List of A_Const nodes */
+ bool is_local; /* SET LOCAL? */
+} VariableSetStmt;
+
+/* ----------------------
+ * Show Statement
+ * ----------------------
+ */
+typedef struct VariableShowStmt
+{
+ NodeTag type;
+ char *name;
+} VariableShowStmt;
+
+/* ----------------------
+ * Create Table Statement
+ *
+ * NOTE: in the raw gram.y output, ColumnDef and Constraint nodes are
+ * intermixed in tableElts, and constraints is NIL. After parse analysis,
+ * tableElts contains just ColumnDefs, and constraints contains just
+ * Constraint nodes (in fact, only CONSTR_CHECK nodes, in the present
+ * implementation).
+ * ----------------------
+ */
+
+typedef struct CreateStmt
+{
+ NodeTag type;
+ RangeVar *relation; /* relation to create */
+ List *tableElts; /* column definitions (list of ColumnDef) */
+ List *inhRelations; /* relations to inherit from (list of
+ * inhRelation) */
+ PartitionBoundSpec *partbound; /* FOR VALUES clause */
+ PartitionSpec *partspec; /* PARTITION BY clause */
+ TypeName *ofTypename; /* OF typename */
+ List *constraints; /* constraints (list of Constraint nodes) */
+ List *options; /* options from WITH clause */
+ OnCommitAction oncommit; /* what do we do at COMMIT? */
+ char *tablespacename; /* table space to use, or NULL */
+ char *accessMethod; /* table access method */
+ bool if_not_exists; /* just do nothing if it already exists? */
+} CreateStmt;
+
+/* ----------
+ * Definitions for constraints in CreateStmt
+ *
+ * Note that column defaults are treated as a type of constraint,
+ * even though that's a bit odd semantically.
+ *
+ * For constraints that use expressions (CONSTR_CHECK, CONSTR_DEFAULT)
+ * we may have the expression in either "raw" form (an untransformed
+ * parse tree) or "cooked" form (the nodeToString representation of
+ * an executable expression tree), depending on how this Constraint
+ * node was created (by parsing, or by inheritance from an existing
+ * relation). We should never have both in the same node!
+ *
+ * FKCONSTR_ACTION_xxx values are stored into pg_constraint.confupdtype
+ * and pg_constraint.confdeltype columns; FKCONSTR_MATCH_xxx values are
+ * stored into pg_constraint.confmatchtype. Changing the code values may
+ * require an initdb!
+ *
+ * If skip_validation is true then we skip checking that the existing rows
+ * in the table satisfy the constraint, and just install the catalog entries
+ * for the constraint. A new FK constraint is marked as valid iff
+ * initially_valid is true. (Usually skip_validation and initially_valid
+ * are inverses, but we can set both true if the table is known empty.)
+ *
+ * Constraint attributes (DEFERRABLE etc) are initially represented as
+ * separate Constraint nodes for simplicity of parsing. parse_utilcmd.c makes
+ * a pass through the constraints list to insert the info into the appropriate
+ * Constraint node.
+ * ----------
+ */
+
+typedef enum ConstrType /* types of constraints */
+{
+ CONSTR_NULL, /* not standard SQL, but a lot of people
+ * expect it */
+ CONSTR_NOTNULL,
+ CONSTR_DEFAULT,
+ CONSTR_IDENTITY,
+ CONSTR_GENERATED,
+ CONSTR_CHECK,
+ CONSTR_PRIMARY,
+ CONSTR_UNIQUE,
+ CONSTR_EXCLUSION,
+ CONSTR_FOREIGN,
+ CONSTR_ATTR_DEFERRABLE, /* attributes for previous constraint node */
+ CONSTR_ATTR_NOT_DEFERRABLE,
+ CONSTR_ATTR_DEFERRED,
+ CONSTR_ATTR_IMMEDIATE
+} ConstrType;
+
+/* Foreign key action codes */
+#define FKCONSTR_ACTION_NOACTION 'a'
+#define FKCONSTR_ACTION_RESTRICT 'r'
+#define FKCONSTR_ACTION_CASCADE 'c'
+#define FKCONSTR_ACTION_SETNULL 'n'
+#define FKCONSTR_ACTION_SETDEFAULT 'd'
+
+/* Foreign key matchtype codes */
+#define FKCONSTR_MATCH_FULL 'f'
+#define FKCONSTR_MATCH_PARTIAL 'p'
+#define FKCONSTR_MATCH_SIMPLE 's'
+
+typedef struct Constraint
+{
+ NodeTag type;
+ ConstrType contype; /* see above */
+
+ /* Fields used for most/all constraint types: */
+ char *conname; /* Constraint name, or NULL if unnamed */
+ bool deferrable; /* DEFERRABLE? */
+ bool initdeferred; /* INITIALLY DEFERRED? */
+ int location; /* token location, or -1 if unknown */
+
+ /* Fields used for constraints with expressions (CHECK and DEFAULT): */
+ bool is_no_inherit; /* is constraint non-inheritable? */
+ Node *raw_expr; /* expr, as untransformed parse tree */
+ char *cooked_expr; /* expr, as nodeToString representation */
+ char generated_when; /* ALWAYS or BY DEFAULT */
+
+ /* Fields used for unique constraints (UNIQUE and PRIMARY KEY): */
+ List *keys; /* String nodes naming referenced key
+ * column(s) */
+ List *including; /* String nodes naming referenced nonkey
+ * column(s) */
+
+ /* Fields used for EXCLUSION constraints: */
+ List *exclusions; /* list of (IndexElem, operator name) pairs */
+
+ /* Fields used for index constraints (UNIQUE, PRIMARY KEY, EXCLUSION): */
+ List *options; /* options from WITH clause */
+ char *indexname; /* existing index to use; otherwise NULL */
+ char *indexspace; /* index tablespace; NULL for default */
+ bool reset_default_tblspc; /* reset default_tablespace prior to
+ * creating the index */
+ /* These could be, but currently are not, used for UNIQUE/PKEY: */
+ char *access_method; /* index access method; NULL for default */
+ Node *where_clause; /* partial index predicate */
+
+ /* Fields used for FOREIGN KEY constraints: */
+ RangeVar *pktable; /* Primary key table */
+ List *fk_attrs; /* Attributes of foreign key */
+ List *pk_attrs; /* Corresponding attrs in PK table */
+ char fk_matchtype; /* FULL, PARTIAL, SIMPLE */
+ char fk_upd_action; /* ON UPDATE action */
+ char fk_del_action; /* ON DELETE action */
+ List *old_conpfeqop; /* pg_constraint.conpfeqop of my former self */
+ Oid old_pktable_oid; /* pg_constraint.confrelid of my former
+ * self */
+
+ /* Fields used for constraints that allow a NOT VALID specification */
+ bool skip_validation; /* skip validation of existing rows? */
+ bool initially_valid; /* mark the new constraint as valid? */
+} Constraint;
+
+/* ----------------------
+ * Create/Drop Table Space Statements
+ * ----------------------
+ */
+
+typedef struct CreateTableSpaceStmt
+{
+ NodeTag type;
+ char *tablespacename;
+ RoleSpec *owner;
+ char *location;
+ List *options;
+} CreateTableSpaceStmt;
+
+typedef struct DropTableSpaceStmt
+{
+ NodeTag type;
+ char *tablespacename;
+ bool missing_ok; /* skip error if missing? */
+} DropTableSpaceStmt;
+
+typedef struct AlterTableSpaceOptionsStmt
+{
+ NodeTag type;
+ char *tablespacename;
+ List *options;
+ bool isReset;
+} AlterTableSpaceOptionsStmt;
+
+typedef struct AlterTableMoveAllStmt
+{
+ NodeTag type;
+ char *orig_tablespacename;
+ ObjectType objtype; /* Object type to move */
+ List *roles; /* List of roles to move objects of */
+ char *new_tablespacename;
+ bool nowait;
+} AlterTableMoveAllStmt;
+
+/* ----------------------
+ * Create/Alter Extension Statements
+ * ----------------------
+ */
+
+typedef struct CreateExtensionStmt
+{
+ NodeTag type;
+ char *extname;
+ bool if_not_exists; /* just do nothing if it already exists? */
+ List *options; /* List of DefElem nodes */
+} CreateExtensionStmt;
+
+/* Only used for ALTER EXTENSION UPDATE; later might need an action field */
+typedef struct AlterExtensionStmt
+{
+ NodeTag type;
+ char *extname;
+ List *options; /* List of DefElem nodes */
+} AlterExtensionStmt;
+
+typedef struct AlterExtensionContentsStmt
+{
+ NodeTag type;
+ char *extname; /* Extension's name */
+ int action; /* +1 = add object, -1 = drop object */
+ ObjectType objtype; /* Object's type */
+ Node *object; /* Qualified name of the object */
+} AlterExtensionContentsStmt;
+
+/* ----------------------
+ * Create/Alter FOREIGN DATA WRAPPER Statements
+ * ----------------------
+ */
+
+typedef struct CreateFdwStmt
+{
+ NodeTag type;
+ char *fdwname; /* foreign-data wrapper name */
+ List *func_options; /* HANDLER/VALIDATOR options */
+ List *options; /* generic options to FDW */
+} CreateFdwStmt;
+
+typedef struct AlterFdwStmt
+{
+ NodeTag type;
+ char *fdwname; /* foreign-data wrapper name */
+ List *func_options; /* HANDLER/VALIDATOR options */
+ List *options; /* generic options to FDW */
+} AlterFdwStmt;
+
+/* ----------------------
+ * Create/Alter FOREIGN SERVER Statements
+ * ----------------------
+ */
+
+typedef struct CreateForeignServerStmt
+{
+ NodeTag type;
+ char *servername; /* server name */
+ char *servertype; /* optional server type */
+ char *version; /* optional server version */
+ char *fdwname; /* FDW name */
+ bool if_not_exists; /* just do nothing if it already exists? */
+ List *options; /* generic options to server */
+} CreateForeignServerStmt;
+
+typedef struct AlterForeignServerStmt
+{
+ NodeTag type;
+ char *servername; /* server name */
+ char *version; /* optional server version */
+ List *options; /* generic options to server */
+ bool has_version; /* version specified */
+} AlterForeignServerStmt;
+
+/* ----------------------
+ * Create FOREIGN TABLE Statement
+ * ----------------------
+ */
+
+typedef struct CreateForeignTableStmt
+{
+ CreateStmt base;
+ char *servername;
+ List *options;
+} CreateForeignTableStmt;
+
+/* ----------------------
+ * Create/Drop USER MAPPING Statements
+ * ----------------------
+ */
+
+typedef struct CreateUserMappingStmt
+{
+ NodeTag type;
+ RoleSpec *user; /* user role */
+ char *servername; /* server name */
+ bool if_not_exists; /* just do nothing if it already exists? */
+ List *options; /* generic options to server */
+} CreateUserMappingStmt;
+
+typedef struct AlterUserMappingStmt
+{
+ NodeTag type;
+ RoleSpec *user; /* user role */
+ char *servername; /* server name */
+ List *options; /* generic options to server */
+} AlterUserMappingStmt;
+
+typedef struct DropUserMappingStmt
+{
+ NodeTag type;
+ RoleSpec *user; /* user role */
+ char *servername; /* server name */
+ bool missing_ok; /* ignore missing mappings */
+} DropUserMappingStmt;
+
+/* ----------------------
+ * Import Foreign Schema Statement
+ * ----------------------
+ */
+
+typedef enum ImportForeignSchemaType
+{
+ FDW_IMPORT_SCHEMA_ALL, /* all relations wanted */
+ FDW_IMPORT_SCHEMA_LIMIT_TO, /* include only listed tables in import */
+ FDW_IMPORT_SCHEMA_EXCEPT /* exclude listed tables from import */
+} ImportForeignSchemaType;
+
+typedef struct ImportForeignSchemaStmt
+{
+ NodeTag type;
+ char *server_name; /* FDW server name */
+ char *remote_schema; /* remote schema name to query */
+ char *local_schema; /* local schema to create objects in */
+ ImportForeignSchemaType list_type; /* type of table list */
+ List *table_list; /* List of RangeVar */
+ List *options; /* list of options to pass to FDW */
+} ImportForeignSchemaStmt;
+
+/*----------------------
+ * Create POLICY Statement
+ *----------------------
+ */
+typedef struct CreatePolicyStmt
+{
+ NodeTag type;
+ char *policy_name; /* Policy's name */
+ RangeVar *table; /* the table name the policy applies to */
+ char *cmd_name; /* the command name the policy applies to */
+ bool permissive; /* restrictive or permissive policy */
+ List *roles; /* the roles associated with the policy */
+ Node *qual; /* the policy's condition */
+ Node *with_check; /* the policy's WITH CHECK condition. */
+} CreatePolicyStmt;
+
+/*----------------------
+ * Alter POLICY Statement
+ *----------------------
+ */
+typedef struct AlterPolicyStmt
+{
+ NodeTag type;
+ char *policy_name; /* Policy's name */
+ RangeVar *table; /* the table name the policy applies to */
+ List *roles; /* the roles associated with the policy */
+ Node *qual; /* the policy's condition */
+ Node *with_check; /* the policy's WITH CHECK condition. */
+} AlterPolicyStmt;
+
+/*----------------------
+ * Create ACCESS METHOD Statement
+ *----------------------
+ */
+typedef struct CreateAmStmt
+{
+ NodeTag type;
+ char *amname; /* access method name */
+ List *handler_name; /* handler function name */
+ char amtype; /* type of access method */
+} CreateAmStmt;
+
+/* ----------------------
+ * Create TRIGGER Statement
+ * ----------------------
+ */
+typedef struct CreateTrigStmt
+{
+ NodeTag type;
+ char *trigname; /* TRIGGER's name */
+ RangeVar *relation; /* relation trigger is on */
+ List *funcname; /* qual. name of function to call */
+ List *args; /* list of (T_String) Values or NIL */
+ bool row; /* ROW/STATEMENT */
+ /* timing uses the TRIGGER_TYPE bits defined in catalog/pg_trigger.h */
+ int16 timing; /* BEFORE, AFTER, or INSTEAD */
+ /* events uses the TRIGGER_TYPE bits defined in catalog/pg_trigger.h */
+ int16 events; /* "OR" of INSERT/UPDATE/DELETE/TRUNCATE */
+ List *columns; /* column names, or NIL for all columns */
+ Node *whenClause; /* qual expression, or NULL if none */
+ bool isconstraint; /* This is a constraint trigger */
+ /* explicitly named transition data */
+ List *transitionRels; /* TriggerTransition nodes, or NIL if none */
+ /* The remaining fields are only used for constraint triggers */
+ bool deferrable; /* [NOT] DEFERRABLE */
+ bool initdeferred; /* INITIALLY {DEFERRED|IMMEDIATE} */
+ RangeVar *constrrel; /* opposite relation, if RI trigger */
+} CreateTrigStmt;
+
+/* ----------------------
+ * Create EVENT TRIGGER Statement
+ * ----------------------
+ */
+typedef struct CreateEventTrigStmt
+{
+ NodeTag type;
+ char *trigname; /* TRIGGER's name */
+ char *eventname; /* event's identifier */
+ List *whenclause; /* list of DefElems indicating filtering */
+ List *funcname; /* qual. name of function to call */
+} CreateEventTrigStmt;
+
+/* ----------------------
+ * Alter EVENT TRIGGER Statement
+ * ----------------------
+ */
+typedef struct AlterEventTrigStmt
+{
+ NodeTag type;
+ char *trigname; /* TRIGGER's name */
+ char tgenabled; /* trigger's firing configuration WRT
+ * session_replication_role */
+} AlterEventTrigStmt;
+
+/* ----------------------
+ * Create LANGUAGE Statements
+ * ----------------------
+ */
+typedef struct CreatePLangStmt
+{
+ NodeTag type;
+ bool replace; /* T => replace if already exists */
+ char *plname; /* PL name */
+ List *plhandler; /* PL call handler function (qual. name) */
+ List *plinline; /* optional inline function (qual. name) */
+ List *plvalidator; /* optional validator function (qual. name) */
+ bool pltrusted; /* PL is trusted */
+} CreatePLangStmt;
+
+/* ----------------------
+ * Create/Alter/Drop Role Statements
+ *
+ * Note: these node types are also used for the backwards-compatible
+ * Create/Alter/Drop User/Group statements. In the ALTER and DROP cases
+ * there's really no need to distinguish what the original spelling was,
+ * but for CREATE we mark the type because the defaults vary.
+ * ----------------------
+ */
+typedef enum RoleStmtType
+{
+ ROLESTMT_ROLE,
+ ROLESTMT_USER,
+ ROLESTMT_GROUP
+} RoleStmtType;
+
+typedef struct CreateRoleStmt
+{
+ NodeTag type;
+ RoleStmtType stmt_type; /* ROLE/USER/GROUP */
+ char *role; /* role name */
+ List *options; /* List of DefElem nodes */
+} CreateRoleStmt;
+
+typedef struct AlterRoleStmt
+{
+ NodeTag type;
+ RoleSpec *role; /* role */
+ List *options; /* List of DefElem nodes */
+ int action; /* +1 = add members, -1 = drop members */
+} AlterRoleStmt;
+
+typedef struct AlterRoleSetStmt
+{
+ NodeTag type;
+ RoleSpec *role; /* role */
+ char *database; /* database name, or NULL */
+ VariableSetStmt *setstmt; /* SET or RESET subcommand */
+} AlterRoleSetStmt;
+
+typedef struct DropRoleStmt
+{
+ NodeTag type;
+ List *roles; /* List of roles to remove */
+ bool missing_ok; /* skip error if a role is missing? */
+} DropRoleStmt;
+
+/* ----------------------
+ * {Create|Alter} SEQUENCE Statement
+ * ----------------------
+ */
+
+typedef struct CreateSeqStmt
+{
+ NodeTag type;
+ RangeVar *sequence; /* the sequence to create */
+ List *options;
+ Oid ownerId; /* ID of owner, or InvalidOid for default */
+ bool for_identity;
+ bool if_not_exists; /* just do nothing if it already exists? */
+} CreateSeqStmt;
+
+typedef struct AlterSeqStmt
+{
+ NodeTag type;
+ RangeVar *sequence; /* the sequence to alter */
+ List *options;
+ bool for_identity;
+ bool missing_ok; /* skip error if a role is missing? */
+} AlterSeqStmt;
+
+/* ----------------------
+ * Create {Aggregate|Operator|Type} Statement
+ * ----------------------
+ */
+typedef struct DefineStmt
+{
+ NodeTag type;
+ ObjectType kind; /* aggregate, operator, type */
+ bool oldstyle; /* hack to signal old CREATE AGG syntax */
+ List *defnames; /* qualified name (list of Value strings) */
+ List *args; /* a list of TypeName (if needed) */
+ List *definition; /* a list of DefElem */
+ bool if_not_exists; /* just do nothing if it already exists? */
+ bool replace; /* replace if already exists? */
+} DefineStmt;
+
+/* ----------------------
+ * Create Domain Statement
+ * ----------------------
+ */
+typedef struct CreateDomainStmt
+{
+ NodeTag type;
+ List *domainname; /* qualified name (list of Value strings) */
+ TypeName *typeName; /* the base type */
+ CollateClause *collClause; /* untransformed COLLATE spec, if any */
+ List *constraints; /* constraints (list of Constraint nodes) */
+} CreateDomainStmt;
+
+/* ----------------------
+ * Create Operator Class Statement
+ * ----------------------
+ */
+typedef struct CreateOpClassStmt
+{
+ NodeTag type;
+ List *opclassname; /* qualified name (list of Value strings) */
+ List *opfamilyname; /* qualified name (ditto); NIL if omitted */
+ char *amname; /* name of index AM opclass is for */
+ TypeName *datatype; /* datatype of indexed column */
+ List *items; /* List of CreateOpClassItem nodes */
+ bool isDefault; /* Should be marked as default for type? */
+} CreateOpClassStmt;
+
+#define OPCLASS_ITEM_OPERATOR 1
+#define OPCLASS_ITEM_FUNCTION 2
+#define OPCLASS_ITEM_STORAGETYPE 3
+
+typedef struct CreateOpClassItem
+{
+ NodeTag type;
+ int itemtype; /* see codes above */
+ ObjectWithArgs *name; /* operator or function name and args */
+ int number; /* strategy num or support proc num */
+ List *order_family; /* only used for ordering operators */
+ List *class_args; /* amproclefttype/amprocrighttype or
+ * amoplefttype/amoprighttype */
+ /* fields used for a storagetype item: */
+ TypeName *storedtype; /* datatype stored in index */
+} CreateOpClassItem;
+
+/* ----------------------
+ * Create Operator Family Statement
+ * ----------------------
+ */
+typedef struct CreateOpFamilyStmt
+{
+ NodeTag type;
+ List *opfamilyname; /* qualified name (list of Value strings) */
+ char *amname; /* name of index AM opfamily is for */
+} CreateOpFamilyStmt;
+
+/* ----------------------
+ * Alter Operator Family Statement
+ * ----------------------
+ */
+typedef struct AlterOpFamilyStmt
+{
+ NodeTag type;
+ List *opfamilyname; /* qualified name (list of Value strings) */
+ char *amname; /* name of index AM opfamily is for */
+ bool isDrop; /* ADD or DROP the items? */
+ List *items; /* List of CreateOpClassItem nodes */
+} AlterOpFamilyStmt;
+
+/* ----------------------
+ * Drop Table|Sequence|View|Index|Type|Domain|Conversion|Schema Statement
+ * ----------------------
+ */
+
+typedef struct DropStmt
+{
+ NodeTag type;
+ List *objects; /* list of names */
+ ObjectType removeType; /* object type */
+ DropBehavior behavior; /* RESTRICT or CASCADE behavior */
+ bool missing_ok; /* skip error if object is missing? */
+ bool concurrent; /* drop index concurrently? */
+} DropStmt;
+
+/* ----------------------
+ * Truncate Table Statement
+ * ----------------------
+ */
+typedef struct TruncateStmt
+{
+ NodeTag type;
+ List *relations; /* relations (RangeVars) to be truncated */
+ bool restart_seqs; /* restart owned sequences? */
+ DropBehavior behavior; /* RESTRICT or CASCADE behavior */
+} TruncateStmt;
+
+/* ----------------------
+ * Comment On Statement
+ * ----------------------
+ */
+typedef struct CommentStmt
+{
+ NodeTag type;
+ ObjectType objtype; /* Object's type */
+ Node *object; /* Qualified name of the object */
+ char *comment; /* Comment to insert, or NULL to remove */
+} CommentStmt;
+
+/* ----------------------
+ * SECURITY LABEL Statement
+ * ----------------------
+ */
+typedef struct SecLabelStmt
+{
+ NodeTag type;
+ ObjectType objtype; /* Object's type */
+ Node *object; /* Qualified name of the object */
+ char *provider; /* Label provider (or NULL) */
+ char *label; /* New security label to be assigned */
+} SecLabelStmt;
+
+/* ----------------------
+ * Declare Cursor Statement
+ *
+ * The "query" field is initially a raw parse tree, and is converted to a
+ * Query node during parse analysis. Note that rewriting and planning
+ * of the query are always postponed until execution.
+ * ----------------------
+ */
+#define CURSOR_OPT_BINARY 0x0001 /* BINARY */
+#define CURSOR_OPT_SCROLL 0x0002 /* SCROLL explicitly given */
+#define CURSOR_OPT_NO_SCROLL 0x0004 /* NO SCROLL explicitly given */
+#define CURSOR_OPT_INSENSITIVE 0x0008 /* INSENSITIVE */
+#define CURSOR_OPT_HOLD 0x0010 /* WITH HOLD */
+/* these planner-control flags do not correspond to any SQL grammar: */
+#define CURSOR_OPT_FAST_PLAN 0x0020 /* prefer fast-start plan */
+#define CURSOR_OPT_GENERIC_PLAN 0x0040 /* force use of generic plan */
+#define CURSOR_OPT_CUSTOM_PLAN 0x0080 /* force use of custom plan */
+#define CURSOR_OPT_PARALLEL_OK 0x0100 /* parallel mode OK */
+
+typedef struct DeclareCursorStmt
+{
+ NodeTag type;
+ char *portalname; /* name of the portal (cursor) */
+ int options; /* bitmask of options (see above) */
+ Node *query; /* the query (see comments above) */
+} DeclareCursorStmt;
+
+/* ----------------------
+ * Close Portal Statement
+ * ----------------------
+ */
+typedef struct ClosePortalStmt
+{
+ NodeTag type;
+ char *portalname; /* name of the portal (cursor) */
+ /* NULL means CLOSE ALL */
+} ClosePortalStmt;
+
+/* ----------------------
+ * Fetch Statement (also Move)
+ * ----------------------
+ */
+typedef enum FetchDirection
+{
+ /* for these, howMany is how many rows to fetch; FETCH_ALL means ALL */
+ FETCH_FORWARD,
+ FETCH_BACKWARD,
+ /* for these, howMany indicates a position; only one row is fetched */
+ FETCH_ABSOLUTE,
+ FETCH_RELATIVE
+} FetchDirection;
+
+#define FETCH_ALL LONG_MAX
+
+typedef struct FetchStmt
+{
+ NodeTag type;
+ FetchDirection direction; /* see above */
+ long howMany; /* number of rows, or position argument */
+ char *portalname; /* name of portal (cursor) */
+ bool ismove; /* true if MOVE */
+} FetchStmt;
+
+/* ----------------------
+ * Create Index Statement
+ *
+ * This represents creation of an index and/or an associated constraint.
+ * If isconstraint is true, we should create a pg_constraint entry along
+ * with the index. But if indexOid isn't InvalidOid, we are not creating an
+ * index, just a UNIQUE/PKEY constraint using an existing index. isconstraint
+ * must always be true in this case, and the fields describing the index
+ * properties are empty.
+ * ----------------------
+ */
+typedef struct IndexStmt
+{
+ NodeTag type;
+ char *idxname; /* name of new index, or NULL for default */
+ RangeVar *relation; /* relation to build index on */
+ char *accessMethod; /* name of access method (eg. btree) */
+ char *tableSpace; /* tablespace, or NULL for default */
+ List *indexParams; /* columns to index: a list of IndexElem */
+ List *indexIncludingParams; /* additional columns to index: a list
+ * of IndexElem */
+ List *options; /* WITH clause options: a list of DefElem */
+ Node *whereClause; /* qualification (partial-index predicate) */
+ List *excludeOpNames; /* exclusion operator names, or NIL if none */
+ char *idxcomment; /* comment to apply to index, or NULL */
+ Oid indexOid; /* OID of an existing index, if any */
+ Oid oldNode; /* relfilenode of existing storage, if any */
+ SubTransactionId oldCreateSubid; /* rd_createSubid of oldNode */
+ SubTransactionId oldFirstRelfilenodeSubid; /* rd_firstRelfilenodeSubid of
+ * oldNode */
+ bool unique; /* is index unique? */
+ bool primary; /* is index a primary key? */
+ bool isconstraint; /* is it for a pkey/unique constraint? */
+ bool deferrable; /* is the constraint DEFERRABLE? */
+ bool initdeferred; /* is the constraint INITIALLY DEFERRED? */
+ bool transformed; /* true when transformIndexStmt is finished */
+ bool concurrent; /* should this be a concurrent index build? */
+ bool if_not_exists; /* just do nothing if index already exists? */
+ bool reset_default_tblspc; /* reset default_tablespace prior to
+ * executing */
+} IndexStmt;
+
+/* ----------------------
+ * Create Statistics Statement
+ * ----------------------
+ */
+typedef struct CreateStatsStmt
+{
+ NodeTag type;
+ List *defnames; /* qualified name (list of Value strings) */
+ List *stat_types; /* stat types (list of Value strings) */
+ List *exprs; /* expressions to build statistics on */
+ List *relations; /* rels to build stats on (list of RangeVar) */
+ char *stxcomment; /* comment to apply to stats, or NULL */
+ bool if_not_exists; /* do nothing if stats name already exists */
+} CreateStatsStmt;
+
+/* ----------------------
+ * Alter Statistics Statement
+ * ----------------------
+ */
+typedef struct AlterStatsStmt
+{
+ NodeTag type;
+ List *defnames; /* qualified name (list of Value strings) */
+ int stxstattarget; /* statistics target */
+ bool missing_ok; /* skip error if statistics object is missing */
+} AlterStatsStmt;
+
+/* ----------------------
+ * Create Function Statement
+ * ----------------------
+ */
+typedef struct CreateFunctionStmt
+{
+ NodeTag type;
+ bool is_procedure; /* it's really CREATE PROCEDURE */
+ bool replace; /* T => replace if already exists */
+ List *funcname; /* qualified name of function to create */
+ List *parameters; /* a list of FunctionParameter */
+ TypeName *returnType; /* the return type */
+ List *options; /* a list of DefElem */
+} CreateFunctionStmt;
+
+typedef enum FunctionParameterMode
+{
+ /* the assigned enum values appear in pg_proc, don't change 'em! */
+ FUNC_PARAM_IN = 'i', /* input only */
+ FUNC_PARAM_OUT = 'o', /* output only */
+ FUNC_PARAM_INOUT = 'b', /* both */
+ FUNC_PARAM_VARIADIC = 'v', /* variadic (always input) */
+ FUNC_PARAM_TABLE = 't' /* table function output column */
+} FunctionParameterMode;
+
+typedef struct FunctionParameter
+{
+ NodeTag type;
+ char *name; /* parameter name, or NULL if not given */
+ TypeName *argType; /* TypeName for parameter type */
+ FunctionParameterMode mode; /* IN/OUT/etc */
+ Node *defexpr; /* raw default expr, or NULL if not given */
+} FunctionParameter;
+
+typedef struct AlterFunctionStmt
+{
+ NodeTag type;
+ ObjectType objtype;
+ ObjectWithArgs *func; /* name and args of function */
+ List *actions; /* list of DefElem */
+} AlterFunctionStmt;
+
+/* ----------------------
+ * DO Statement
+ *
+ * DoStmt is the raw parser output, InlineCodeBlock is the execution-time API
+ * ----------------------
+ */
+typedef struct DoStmt
+{
+ NodeTag type;
+ List *args; /* List of DefElem nodes */
+} DoStmt;
+
+typedef struct InlineCodeBlock
+{
+ NodeTag type;
+ char *source_text; /* source text of anonymous code block */
+ Oid langOid; /* OID of selected language */
+ bool langIsTrusted; /* trusted property of the language */
+ bool atomic; /* atomic execution context */
+} InlineCodeBlock;
+
+/* ----------------------
+ * CALL statement
+ * ----------------------
+ */
+typedef struct CallStmt
+{
+ NodeTag type;
+ FuncCall *funccall; /* from the parser */
+ FuncExpr *funcexpr; /* transformed */
+} CallStmt;
+
+typedef struct CallContext
+{
+ NodeTag type;
+ bool atomic;
+} CallContext;
+
+/* ----------------------
+ * Alter Object Rename Statement
+ * ----------------------
+ */
+typedef struct RenameStmt
+{
+ NodeTag type;
+ ObjectType renameType; /* OBJECT_TABLE, OBJECT_COLUMN, etc */
+ ObjectType relationType; /* if column name, associated relation type */
+ RangeVar *relation; /* in case it's a table */
+ Node *object; /* in case it's some other object */
+ char *subname; /* name of contained object (column, rule,
+ * trigger, etc) */
+ char *newname; /* the new name */
+ DropBehavior behavior; /* RESTRICT or CASCADE behavior */
+ bool missing_ok; /* skip error if missing? */
+} RenameStmt;
+
+/* ----------------------
+ * ALTER object DEPENDS ON EXTENSION extname
+ * ----------------------
+ */
+typedef struct AlterObjectDependsStmt
+{
+ NodeTag type;
+ ObjectType objectType; /* OBJECT_FUNCTION, OBJECT_TRIGGER, etc */
+ RangeVar *relation; /* in case a table is involved */
+ Node *object; /* name of the object */
+ Value *extname; /* extension name */
+ bool remove; /* set true to remove dep rather than add */
+} AlterObjectDependsStmt;
+
+/* ----------------------
+ * ALTER object SET SCHEMA Statement
+ * ----------------------
+ */
+typedef struct AlterObjectSchemaStmt
+{
+ NodeTag type;
+ ObjectType objectType; /* OBJECT_TABLE, OBJECT_TYPE, etc */
+ RangeVar *relation; /* in case it's a table */
+ Node *object; /* in case it's some other object */
+ char *newschema; /* the new schema */
+ bool missing_ok; /* skip error if missing? */
+} AlterObjectSchemaStmt;
+
+/* ----------------------
+ * Alter Object Owner Statement
+ * ----------------------
+ */
+typedef struct AlterOwnerStmt
+{
+ NodeTag type;
+ ObjectType objectType; /* OBJECT_TABLE, OBJECT_TYPE, etc */
+ RangeVar *relation; /* in case it's a table */
+ Node *object; /* in case it's some other object */
+ RoleSpec *newowner; /* the new owner */
+} AlterOwnerStmt;
+
+/* ----------------------
+ * Alter Operator Set ( this-n-that )
+ * ----------------------
+ */
+typedef struct AlterOperatorStmt
+{
+ NodeTag type;
+ ObjectWithArgs *opername; /* operator name and argument types */
+ List *options; /* List of DefElem nodes */
+} AlterOperatorStmt;
+
+/* ------------------------
+ * Alter Type Set ( this-n-that )
+ * ------------------------
+ */
+typedef struct AlterTypeStmt
+{
+ NodeTag type;
+ List *typeName; /* type name (possibly qualified) */
+ List *options; /* List of DefElem nodes */
+} AlterTypeStmt;
+
+/* ----------------------
+ * Create Rule Statement
+ * ----------------------
+ */
+typedef struct RuleStmt
+{
+ NodeTag type;
+ RangeVar *relation; /* relation the rule is for */
+ char *rulename; /* name of the rule */
+ Node *whereClause; /* qualifications */
+ CmdType event; /* SELECT, INSERT, etc */
+ bool instead; /* is a 'do instead'? */
+ List *actions; /* the action statements */
+ bool replace; /* OR REPLACE */
+} RuleStmt;
+
+/* ----------------------
+ * Notify Statement
+ * ----------------------
+ */
+typedef struct NotifyStmt
+{
+ NodeTag type;
+ char *conditionname; /* condition name to notify */
+ char *payload; /* the payload string, or NULL if none */
+} NotifyStmt;
+
+/* ----------------------
+ * Listen Statement
+ * ----------------------
+ */
+typedef struct ListenStmt
+{
+ NodeTag type;
+ char *conditionname; /* condition name to listen on */
+} ListenStmt;
+
+/* ----------------------
+ * Unlisten Statement
+ * ----------------------
+ */
+typedef struct UnlistenStmt
+{
+ NodeTag type;
+ char *conditionname; /* name to unlisten on, or NULL for all */
+} UnlistenStmt;
+
+/* ----------------------
+ * {Begin|Commit|Rollback} Transaction Statement
+ * ----------------------
+ */
+typedef enum TransactionStmtKind
+{
+ TRANS_STMT_BEGIN,
+ TRANS_STMT_START, /* semantically identical to BEGIN */
+ TRANS_STMT_COMMIT,
+ TRANS_STMT_ROLLBACK,
+ TRANS_STMT_SAVEPOINT,
+ TRANS_STMT_RELEASE,
+ TRANS_STMT_ROLLBACK_TO,
+ TRANS_STMT_PREPARE,
+ TRANS_STMT_COMMIT_PREPARED,
+ TRANS_STMT_ROLLBACK_PREPARED
+} TransactionStmtKind;
+
+typedef struct TransactionStmt
+{
+ NodeTag type;
+ TransactionStmtKind kind; /* see above */
+ List *options; /* for BEGIN/START commands */
+ char *savepoint_name; /* for savepoint commands */
+ char *gid; /* for two-phase-commit related commands */
+ bool chain; /* AND CHAIN option */
+} TransactionStmt;
+
+/* ----------------------
+ * Create Type Statement, composite types
+ * ----------------------
+ */
+typedef struct CompositeTypeStmt
+{
+ NodeTag type;
+ RangeVar *typevar; /* the composite type to be created */
+ List *coldeflist; /* list of ColumnDef nodes */
+} CompositeTypeStmt;
+
+/* ----------------------
+ * Create Type Statement, enum types
+ * ----------------------
+ */
+typedef struct CreateEnumStmt
+{
+ NodeTag type;
+ List *typeName; /* qualified name (list of Value strings) */
+ List *vals; /* enum values (list of Value strings) */
+} CreateEnumStmt;
+
+/* ----------------------
+ * Create Type Statement, range types
+ * ----------------------
+ */
+typedef struct CreateRangeStmt
+{
+ NodeTag type;
+ List *typeName; /* qualified name (list of Value strings) */
+ List *params; /* range parameters (list of DefElem) */
+} CreateRangeStmt;
+
+/* ----------------------
+ * Alter Type Statement, enum types
+ * ----------------------
+ */
+typedef struct AlterEnumStmt
+{
+ NodeTag type;
+ List *typeName; /* qualified name (list of Value strings) */
+ char *oldVal; /* old enum value's name, if renaming */
+ char *newVal; /* new enum value's name */
+ char *newValNeighbor; /* neighboring enum value, if specified */
+ bool newValIsAfter; /* place new enum value after neighbor? */
+ bool skipIfNewValExists; /* no error if new already exists? */
+} AlterEnumStmt;
+
+/* ----------------------
+ * Create View Statement
+ * ----------------------
+ */
+typedef enum ViewCheckOption
+{
+ NO_CHECK_OPTION,
+ LOCAL_CHECK_OPTION,
+ CASCADED_CHECK_OPTION
+} ViewCheckOption;
+
+typedef struct ViewStmt
+{
+ NodeTag type;
+ RangeVar *view; /* the view to be created */
+ List *aliases; /* target column names */
+ Node *query; /* the SELECT query (as a raw parse tree) */
+ bool replace; /* replace an existing view? */
+ List *options; /* options from WITH clause */
+ ViewCheckOption withCheckOption; /* WITH CHECK OPTION */
+} ViewStmt;
+
+/* ----------------------
+ * Load Statement
+ * ----------------------
+ */
+typedef struct LoadStmt
+{
+ NodeTag type;
+ char *filename; /* file to load */
+} LoadStmt;
+
+/* ----------------------
+ * Createdb Statement
+ * ----------------------
+ */
+typedef struct CreatedbStmt
+{
+ NodeTag type;
+ char *dbname; /* name of database to create */
+ List *options; /* List of DefElem nodes */
+} CreatedbStmt;
+
+/* ----------------------
+ * Alter Database
+ * ----------------------
+ */
+typedef struct AlterDatabaseStmt
+{
+ NodeTag type;
+ char *dbname; /* name of database to alter */
+ List *options; /* List of DefElem nodes */
+} AlterDatabaseStmt;
+
+typedef struct AlterDatabaseSetStmt
+{
+ NodeTag type;
+ char *dbname; /* database name */
+ VariableSetStmt *setstmt; /* SET or RESET subcommand */
+} AlterDatabaseSetStmt;
+
+/* ----------------------
+ * Dropdb Statement
+ * ----------------------
+ */
+typedef struct DropdbStmt
+{
+ NodeTag type;
+ char *dbname; /* database to drop */
+ bool missing_ok; /* skip error if db is missing? */
+ List *options; /* currently only FORCE is supported */
+} DropdbStmt;
+
+/* ----------------------
+ * Alter System Statement
+ * ----------------------
+ */
+typedef struct AlterSystemStmt
+{
+ NodeTag type;
+ VariableSetStmt *setstmt; /* SET subcommand */
+} AlterSystemStmt;
+
+/* ----------------------
+ * Cluster Statement (support pbrown's cluster index implementation)
+ * ----------------------
+ */
+typedef enum ClusterOption
+{
+ CLUOPT_RECHECK = 1 << 0, /* recheck relation state */
+ CLUOPT_VERBOSE = 1 << 1 /* print progress info */
+} ClusterOption;
+
+typedef struct ClusterStmt
+{
+ NodeTag type;
+ RangeVar *relation; /* relation being indexed, or NULL if all */
+ char *indexname; /* original index defined */
+ int options; /* OR of ClusterOption flags */
+} ClusterStmt;
+
+/* ----------------------
+ * Vacuum and Analyze Statements
+ *
+ * Even though these are nominally two statements, it's convenient to use
+ * just one node type for both.
+ * ----------------------
+ */
+typedef struct VacuumStmt
+{
+ NodeTag type;
+ List *options; /* list of DefElem nodes */
+ List *rels; /* list of VacuumRelation, or NIL for all */
+ bool is_vacuumcmd; /* true for VACUUM, false for ANALYZE */
+} VacuumStmt;
+
+/*
+ * Info about a single target table of VACUUM/ANALYZE.
+ *
+ * If the OID field is set, it always identifies the table to process.
+ * Then the relation field can be NULL; if it isn't, it's used only to report
+ * failure to open/lock the relation.
+ */
+typedef struct VacuumRelation
+{
+ NodeTag type;
+ RangeVar *relation; /* table name to process, or NULL */
+ Oid oid; /* table's OID; InvalidOid if not looked up */
+ List *va_cols; /* list of column names, or NIL for all */
+} VacuumRelation;
+
+/* ----------------------
+ * Explain Statement
+ *
+ * The "query" field is initially a raw parse tree, and is converted to a
+ * Query node during parse analysis. Note that rewriting and planning
+ * of the query are always postponed until execution.
+ * ----------------------
+ */
+typedef struct ExplainStmt
+{
+ NodeTag type;
+ Node *query; /* the query (see comments above) */
+ List *options; /* list of DefElem nodes */
+} ExplainStmt;
+
+/* ----------------------
+ * CREATE TABLE AS Statement (a/k/a SELECT INTO)
+ *
+ * A query written as CREATE TABLE AS will produce this node type natively.
+ * A query written as SELECT ... INTO will be transformed to this form during
+ * parse analysis.
+ * A query written as CREATE MATERIALIZED view will produce this node type,
+ * during parse analysis, since it needs all the same data.
+ *
+ * The "query" field is handled similarly to EXPLAIN, though note that it
+ * can be a SELECT or an EXECUTE, but not other DML statements.
+ * ----------------------
+ */
+typedef struct CreateTableAsStmt
+{
+ NodeTag type;
+ Node *query; /* the query (see comments above) */
+ IntoClause *into; /* destination table */
+ ObjectType relkind; /* OBJECT_TABLE or OBJECT_MATVIEW */
+ bool is_select_into; /* it was written as SELECT INTO */
+ bool if_not_exists; /* just do nothing if it already exists? */
+} CreateTableAsStmt;
+
+/* ----------------------
+ * REFRESH MATERIALIZED VIEW Statement
+ * ----------------------
+ */
+typedef struct RefreshMatViewStmt
+{
+ NodeTag type;
+ bool concurrent; /* allow concurrent access? */
+ bool skipData; /* true for WITH NO DATA */
+ RangeVar *relation; /* relation to insert into */
+} RefreshMatViewStmt;
+
+/* ----------------------
+ * Checkpoint Statement
+ * ----------------------
+ */
+typedef struct CheckPointStmt
+{
+ NodeTag type;
+} CheckPointStmt;
+
+/* ----------------------
+ * Discard Statement
+ * ----------------------
+ */
+
+typedef enum DiscardMode
+{
+ DISCARD_ALL,
+ DISCARD_PLANS,
+ DISCARD_SEQUENCES,
+ DISCARD_TEMP
+} DiscardMode;
+
+typedef struct DiscardStmt
+{
+ NodeTag type;
+ DiscardMode target;
+} DiscardStmt;
+
+/* ----------------------
+ * LOCK Statement
+ * ----------------------
+ */
+typedef struct LockStmt
+{
+ NodeTag type;
+ List *relations; /* relations to lock */
+ int mode; /* lock mode */
+ bool nowait; /* no wait mode */
+} LockStmt;
+
+/* ----------------------
+ * SET CONSTRAINTS Statement
+ * ----------------------
+ */
+typedef struct ConstraintsSetStmt
+{
+ NodeTag type;
+ List *constraints; /* List of names as RangeVars */
+ bool deferred;
+} ConstraintsSetStmt;
+
+/* ----------------------
+ * REINDEX Statement
+ * ----------------------
+ */
+
+/* Reindex options */
+#define REINDEXOPT_VERBOSE (1 << 0) /* print progress info */
+#define REINDEXOPT_REPORT_PROGRESS (1 << 1) /* report pgstat progress */
+
+typedef enum ReindexObjectType
+{
+ REINDEX_OBJECT_INDEX, /* index */
+ REINDEX_OBJECT_TABLE, /* table or materialized view */
+ REINDEX_OBJECT_SCHEMA, /* schema */
+ REINDEX_OBJECT_SYSTEM, /* system catalogs */
+ REINDEX_OBJECT_DATABASE /* database */
+} ReindexObjectType;
+
+typedef struct ReindexStmt
+{
+ NodeTag type;
+ ReindexObjectType kind; /* REINDEX_OBJECT_INDEX, REINDEX_OBJECT_TABLE,
+ * etc. */
+ RangeVar *relation; /* Table or index to reindex */
+ const char *name; /* name of database to reindex */
+ int options; /* Reindex options flags */
+ bool concurrent; /* reindex concurrently? */
+} ReindexStmt;
+
+/* ----------------------
+ * CREATE CONVERSION Statement
+ * ----------------------
+ */
+typedef struct CreateConversionStmt
+{
+ NodeTag type;
+ List *conversion_name; /* Name of the conversion */
+ char *for_encoding_name; /* source encoding name */
+ char *to_encoding_name; /* destination encoding name */
+ List *func_name; /* qualified conversion function name */
+ bool def; /* is this a default conversion? */
+} CreateConversionStmt;
+
+/* ----------------------
+ * CREATE CAST Statement
+ * ----------------------
+ */
+typedef struct CreateCastStmt
+{
+ NodeTag type;
+ TypeName *sourcetype;
+ TypeName *targettype;
+ ObjectWithArgs *func;
+ CoercionContext context;
+ bool inout;
+} CreateCastStmt;
+
+/* ----------------------
+ * CREATE TRANSFORM Statement
+ * ----------------------
+ */
+typedef struct CreateTransformStmt
+{
+ NodeTag type;
+ bool replace;
+ TypeName *type_name;
+ char *lang;
+ ObjectWithArgs *fromsql;
+ ObjectWithArgs *tosql;
+} CreateTransformStmt;
+
+/* ----------------------
+ * PREPARE Statement
+ * ----------------------
+ */
+typedef struct PrepareStmt
+{
+ NodeTag type;
+ char *name; /* Name of plan, arbitrary */
+ List *argtypes; /* Types of parameters (List of TypeName) */
+ Node *query; /* The query itself (as a raw parsetree) */
+} PrepareStmt;
+
+
+/* ----------------------
+ * EXECUTE Statement
+ * ----------------------
+ */
+
+typedef struct ExecuteStmt
+{
+ NodeTag type;
+ char *name; /* The name of the plan to execute */
+ List *params; /* Values to assign to parameters */
+} ExecuteStmt;
+
+
+/* ----------------------
+ * DEALLOCATE Statement
+ * ----------------------
+ */
+typedef struct DeallocateStmt
+{
+ NodeTag type;
+ char *name; /* The name of the plan to remove */
+ /* NULL means DEALLOCATE ALL */
+} DeallocateStmt;
+
+/*
+ * DROP OWNED statement
+ */
+typedef struct DropOwnedStmt
+{
+ NodeTag type;
+ List *roles;
+ DropBehavior behavior;
+} DropOwnedStmt;
+
+/*
+ * REASSIGN OWNED statement
+ */
+typedef struct ReassignOwnedStmt
+{
+ NodeTag type;
+ List *roles;
+ RoleSpec *newrole;
+} ReassignOwnedStmt;
+
+/*
+ * TS Dictionary stmts: DefineStmt, RenameStmt and DropStmt are default
+ */
+typedef struct AlterTSDictionaryStmt
+{
+ NodeTag type;
+ List *dictname; /* qualified name (list of Value strings) */
+ List *options; /* List of DefElem nodes */
+} AlterTSDictionaryStmt;
+
+/*
+ * TS Configuration stmts: DefineStmt, RenameStmt and DropStmt are default
+ */
+typedef enum AlterTSConfigType
+{
+ ALTER_TSCONFIG_ADD_MAPPING,
+ ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN,
+ ALTER_TSCONFIG_REPLACE_DICT,
+ ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN,
+ ALTER_TSCONFIG_DROP_MAPPING
+} AlterTSConfigType;
+
+typedef struct AlterTSConfigurationStmt
+{
+ NodeTag type;
+ AlterTSConfigType kind; /* ALTER_TSCONFIG_ADD_MAPPING, etc */
+ List *cfgname; /* qualified name (list of Value strings) */
+
+ /*
+ * dicts will be non-NIL if ADD/ALTER MAPPING was specified. If dicts is
+ * NIL, but tokentype isn't, DROP MAPPING was specified.
+ */
+ List *tokentype; /* list of Value strings */
+ List *dicts; /* list of list of Value strings */
+ bool override; /* if true - remove old variant */
+ bool replace; /* if true - replace dictionary by another */
+ bool missing_ok; /* for DROP - skip error if missing? */
+} AlterTSConfigurationStmt;
+
+
+typedef struct CreatePublicationStmt
+{
+ NodeTag type;
+ char *pubname; /* Name of the publication */
+ List *options; /* List of DefElem nodes */
+ List *tables; /* Optional list of tables to add */
+ bool for_all_tables; /* Special publication for all tables in db */
+} CreatePublicationStmt;
+
+typedef struct AlterPublicationStmt
+{
+ NodeTag type;
+ char *pubname; /* Name of the publication */
+
+ /* parameters used for ALTER PUBLICATION ... WITH */
+ List *options; /* List of DefElem nodes */
+
+ /* parameters used for ALTER PUBLICATION ... ADD/DROP TABLE */
+ List *tables; /* List of tables to add/drop */
+ bool for_all_tables; /* Special publication for all tables in db */
+ DefElemAction tableAction; /* What action to perform with the tables */
+} AlterPublicationStmt;
+
+typedef struct CreateSubscriptionStmt
+{
+ NodeTag type;
+ char *subname; /* Name of the subscription */
+ char *conninfo; /* Connection string to publisher */
+ List *publication; /* One or more publication to subscribe to */
+ List *options; /* List of DefElem nodes */
+} CreateSubscriptionStmt;
+
+typedef enum AlterSubscriptionType
+{
+ ALTER_SUBSCRIPTION_OPTIONS,
+ ALTER_SUBSCRIPTION_CONNECTION,
+ ALTER_SUBSCRIPTION_PUBLICATION,
+ ALTER_SUBSCRIPTION_REFRESH,
+ ALTER_SUBSCRIPTION_ENABLED
+} AlterSubscriptionType;
+
+typedef struct AlterSubscriptionStmt
+{
+ NodeTag type;
+ AlterSubscriptionType kind; /* ALTER_SUBSCRIPTION_OPTIONS, etc */
+ char *subname; /* Name of the subscription */
+ char *conninfo; /* Connection string to publisher */
+ List *publication; /* One or more publication to subscribe to */
+ List *options; /* List of DefElem nodes */
+} AlterSubscriptionStmt;
+
+typedef struct DropSubscriptionStmt
+{
+ NodeTag type;
+ char *subname; /* Name of the subscription */
+ bool missing_ok; /* Skip error if missing? */
+ DropBehavior behavior; /* RESTRICT or CASCADE behavior */
+} DropSubscriptionStmt;
+
+#endif /* PARSENODES_H */
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
new file mode 100644
index 0000000..69150e4
--- /dev/null
+++ b/src/include/nodes/pathnodes.h
@@ -0,0 +1,2556 @@
+/*-------------------------------------------------------------------------
+ *
+ * pathnodes.h
+ * Definitions for planner's internal data structures, especially Paths.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/pathnodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PATHNODES_H
+#define PATHNODES_H
+
+#include "access/sdir.h"
+#include "lib/stringinfo.h"
+#include "nodes/params.h"
+#include "nodes/parsenodes.h"
+#include "storage/block.h"
+
+
+/*
+ * Relids
+ * Set of relation identifiers (indexes into the rangetable).
+ */
+typedef Bitmapset *Relids;
+
+/*
+ * When looking for a "cheapest path", this enum specifies whether we want
+ * cheapest startup cost or cheapest total cost.
+ */
+typedef enum CostSelector
+{
+ STARTUP_COST, TOTAL_COST
+} CostSelector;
+
+/*
+ * The cost estimate produced by cost_qual_eval() includes both a one-time
+ * (startup) cost, and a per-tuple cost.
+ */
+typedef struct QualCost
+{
+ Cost startup; /* one-time cost */
+ Cost per_tuple; /* per-evaluation cost */
+} QualCost;
+
+/*
+ * Costing aggregate function execution requires these statistics about
+ * the aggregates to be executed by a given Agg node. Note that the costs
+ * include the execution costs of the aggregates' argument expressions as
+ * well as the aggregate functions themselves. Also, the fields must be
+ * defined so that initializing the struct to zeroes with memset is correct.
+ */
+typedef struct AggClauseCosts
+{
+ int numAggs; /* total number of aggregate functions */
+ int numOrderedAggs; /* number w/ DISTINCT/ORDER BY/WITHIN GROUP */
+ bool hasNonPartial; /* does any agg not support partial mode? */
+ bool hasNonSerial; /* is any partial agg non-serializable? */
+ QualCost transCost; /* total per-input-row execution costs */
+ QualCost finalCost; /* total per-aggregated-row costs */
+ Size transitionSpace; /* space for pass-by-ref transition data */
+} AggClauseCosts;
+
+/*
+ * This enum identifies the different types of "upper" (post-scan/join)
+ * relations that we might deal with during planning.
+ */
+typedef enum UpperRelationKind
+{
+ UPPERREL_SETOP, /* result of UNION/INTERSECT/EXCEPT, if any */
+ UPPERREL_PARTIAL_GROUP_AGG, /* result of partial grouping/aggregation, if
+ * any */
+ UPPERREL_GROUP_AGG, /* result of grouping/aggregation, if any */
+ UPPERREL_WINDOW, /* result of window functions, if any */
+ UPPERREL_DISTINCT, /* result of "SELECT DISTINCT", if any */
+ UPPERREL_ORDERED, /* result of ORDER BY, if any */
+ UPPERREL_FINAL /* result of any remaining top-level actions */
+ /* NB: UPPERREL_FINAL must be last enum entry; it's used to size arrays */
+} UpperRelationKind;
+
+/*
+ * This enum identifies which type of relation is being planned through the
+ * inheritance planner. INHKIND_NONE indicates the inheritance planner
+ * was not used.
+ */
+typedef enum InheritanceKind
+{
+ INHKIND_NONE,
+ INHKIND_INHERITED,
+ INHKIND_PARTITIONED
+} InheritanceKind;
+
+/*----------
+ * PlannerGlobal
+ * Global information for planning/optimization
+ *
+ * PlannerGlobal holds state for an entire planner invocation; this state
+ * is shared across all levels of sub-Queries that exist in the command being
+ * planned.
+ *----------
+ */
+typedef struct PlannerGlobal
+{
+ NodeTag type;
+
+ ParamListInfo boundParams; /* Param values provided to planner() */
+
+ List *subplans; /* Plans for SubPlan nodes */
+
+ List *subroots; /* PlannerInfos for SubPlan nodes */
+
+ Bitmapset *rewindPlanIDs; /* indices of subplans that require REWIND */
+
+ List *finalrtable; /* "flat" rangetable for executor */
+
+ List *finalrowmarks; /* "flat" list of PlanRowMarks */
+
+ List *resultRelations; /* "flat" list of integer RT indexes */
+
+ List *rootResultRelations; /* "flat" list of integer RT indexes */
+
+ List *appendRelations; /* "flat" list of AppendRelInfos */
+
+ List *relationOids; /* OIDs of relations the plan depends on */
+
+ List *invalItems; /* other dependencies, as PlanInvalItems */
+
+ List *paramExecTypes; /* type OIDs for PARAM_EXEC Params */
+
+ Index lastPHId; /* highest PlaceHolderVar ID assigned */
+
+ Index lastRowMarkId; /* highest PlanRowMark ID assigned */
+
+ int lastPlanNodeId; /* highest plan node ID assigned */
+
+ bool transientPlan; /* redo plan when TransactionXmin changes? */
+
+ bool dependsOnRole; /* is plan specific to current role? */
+
+ bool parallelModeOK; /* parallel mode potentially OK? */
+
+ bool parallelModeNeeded; /* parallel mode actually required? */
+
+ char maxParallelHazard; /* worst PROPARALLEL hazard level */
+
+ PartitionDirectory partition_directory; /* partition descriptors */
+} PlannerGlobal;
+
+/* macro for fetching the Plan associated with a SubPlan node */
+#define planner_subplan_get_plan(root, subplan) \
+ ((Plan *) list_nth((root)->glob->subplans, (subplan)->plan_id - 1))
+
+
+/*----------
+ * PlannerInfo
+ * Per-query information for planning/optimization
+ *
+ * This struct is conventionally called "root" in all the planner routines.
+ * It holds links to all of the planner's working state, in addition to the
+ * original Query. Note that at present the planner extensively modifies
+ * the passed-in Query data structure; someday that should stop.
+ *
+ * For reasons explained in optimizer/optimizer.h, we define the typedef
+ * either here or in that header, whichever is read first.
+ *----------
+ */
+#ifndef HAVE_PLANNERINFO_TYPEDEF
+typedef struct PlannerInfo PlannerInfo;
+#define HAVE_PLANNERINFO_TYPEDEF 1
+#endif
+
+struct PlannerInfo
+{
+ NodeTag type;
+
+ Query *parse; /* the Query being planned */
+
+ PlannerGlobal *glob; /* global info for current planner run */
+
+ Index query_level; /* 1 at the outermost Query */
+
+ PlannerInfo *parent_root; /* NULL at outermost Query */
+
+ /*
+ * plan_params contains the expressions that this query level needs to
+ * make available to a lower query level that is currently being planned.
+ * outer_params contains the paramIds of PARAM_EXEC Params that outer
+ * query levels will make available to this query level.
+ */
+ List *plan_params; /* list of PlannerParamItems, see below */
+ Bitmapset *outer_params;
+
+ /*
+ * simple_rel_array holds pointers to "base rels" and "other rels" (see
+ * comments for RelOptInfo for more info). It is indexed by rangetable
+ * index (so entry 0 is always wasted). Entries can be NULL when an RTE
+ * does not correspond to a base relation, such as a join RTE or an
+ * unreferenced view RTE; or if the RelOptInfo hasn't been made yet.
+ */
+ struct RelOptInfo **simple_rel_array; /* All 1-rel RelOptInfos */
+ int simple_rel_array_size; /* allocated size of array */
+
+ /*
+ * simple_rte_array is the same length as simple_rel_array and holds
+ * pointers to the associated rangetable entries. Using this is a shade
+ * faster than using rt_fetch(), mostly due to fewer indirections.
+ */
+ RangeTblEntry **simple_rte_array; /* rangetable as an array */
+
+ /*
+ * append_rel_array is the same length as the above arrays, and holds
+ * pointers to the corresponding AppendRelInfo entry indexed by
+ * child_relid, or NULL if the rel is not an appendrel child. The array
+ * itself is not allocated if append_rel_list is empty.
+ */
+ struct AppendRelInfo **append_rel_array;
+
+ /*
+ * all_baserels is a Relids set of all base relids (but not "other"
+ * relids) in the query; that is, the Relids identifier of the final join
+ * we need to form. This is computed in make_one_rel, just before we
+ * start making Paths.
+ */
+ Relids all_baserels;
+
+ /*
+ * nullable_baserels is a Relids set of base relids that are nullable by
+ * some outer join in the jointree; these are rels that are potentially
+ * nullable below the WHERE clause, SELECT targetlist, etc. This is
+ * computed in deconstruct_jointree.
+ */
+ Relids nullable_baserels;
+
+ /*
+ * join_rel_list is a list of all join-relation RelOptInfos we have
+ * considered in this planning run. For small problems we just scan the
+ * list to do lookups, but when there are many join relations we build a
+ * hash table for faster lookups. The hash table is present and valid
+ * when join_rel_hash is not NULL. Note that we still maintain the list
+ * even when using the hash table for lookups; this simplifies life for
+ * GEQO.
+ */
+ List *join_rel_list; /* list of join-relation RelOptInfos */
+ struct HTAB *join_rel_hash; /* optional hashtable for join relations */
+
+ /*
+ * When doing a dynamic-programming-style join search, join_rel_level[k]
+ * is a list of all join-relation RelOptInfos of level k, and
+ * join_cur_level is the current level. New join-relation RelOptInfos are
+ * automatically added to the join_rel_level[join_cur_level] list.
+ * join_rel_level is NULL if not in use.
+ */
+ List **join_rel_level; /* lists of join-relation RelOptInfos */
+ int join_cur_level; /* index of list being extended */
+
+ List *init_plans; /* init SubPlans for query */
+
+ List *cte_plan_ids; /* per-CTE-item list of subplan IDs */
+
+ List *multiexpr_params; /* List of Lists of Params for MULTIEXPR
+ * subquery outputs */
+
+ List *eq_classes; /* list of active EquivalenceClasses */
+
+ bool ec_merging_done; /* set true once ECs are canonical */
+
+ List *canon_pathkeys; /* list of "canonical" PathKeys */
+
+ List *left_join_clauses; /* list of RestrictInfos for mergejoinable
+ * outer join clauses w/nonnullable var on
+ * left */
+
+ List *right_join_clauses; /* list of RestrictInfos for mergejoinable
+ * outer join clauses w/nonnullable var on
+ * right */
+
+ List *full_join_clauses; /* list of RestrictInfos for mergejoinable
+ * full join clauses */
+
+ List *join_info_list; /* list of SpecialJoinInfos */
+
+ /*
+ * Note: for AppendRelInfos describing partitions of a partitioned table,
+ * we guarantee that partitions that come earlier in the partitioned
+ * table's PartitionDesc will appear earlier in append_rel_list.
+ */
+ List *append_rel_list; /* list of AppendRelInfos */
+
+ List *rowMarks; /* list of PlanRowMarks */
+
+ List *placeholder_list; /* list of PlaceHolderInfos */
+
+ List *fkey_list; /* list of ForeignKeyOptInfos */
+
+ List *query_pathkeys; /* desired pathkeys for query_planner() */
+
+ List *group_pathkeys; /* groupClause pathkeys, if any */
+ List *window_pathkeys; /* pathkeys of bottom window, if any */
+ List *distinct_pathkeys; /* distinctClause pathkeys, if any */
+ List *sort_pathkeys; /* sortClause pathkeys, if any */
+
+ List *part_schemes; /* Canonicalised partition schemes used in the
+ * query. */
+
+ List *initial_rels; /* RelOptInfos we are now trying to join */
+
+ /* Use fetch_upper_rel() to get any particular upper rel */
+ List *upper_rels[UPPERREL_FINAL + 1]; /* upper-rel RelOptInfos */
+
+ /* Result tlists chosen by grouping_planner for upper-stage processing */
+ struct PathTarget *upper_targets[UPPERREL_FINAL + 1];
+
+ /*
+ * The fully-processed targetlist is kept here. It differs from
+ * parse->targetList in that (for INSERT and UPDATE) it's been reordered
+ * to match the target table, and defaults have been filled in. Also,
+ * additional resjunk targets may be present. preprocess_targetlist()
+ * does most of this work, but note that more resjunk targets can get
+ * added during appendrel expansion. (Hence, upper_targets mustn't get
+ * set up till after that.)
+ */
+ List *processed_tlist;
+
+ /* Fields filled during create_plan() for use in setrefs.c */
+ AttrNumber *grouping_map; /* for GroupingFunc fixup */
+ List *minmax_aggs; /* List of MinMaxAggInfos */
+
+ MemoryContext planner_cxt; /* context holding PlannerInfo */
+
+ double total_table_pages; /* # of pages in all non-dummy tables of
+ * query */
+
+ double tuple_fraction; /* tuple_fraction passed to query_planner */
+ double limit_tuples; /* limit_tuples passed to query_planner */
+
+ Index qual_security_level; /* minimum security_level for quals */
+ /* Note: qual_security_level is zero if there are no securityQuals */
+
+ InheritanceKind inhTargetKind; /* indicates if the target relation is an
+ * inheritance child or partition or a
+ * partitioned table */
+ bool hasJoinRTEs; /* true if any RTEs are RTE_JOIN kind */
+ bool hasLateralRTEs; /* true if any RTEs are marked LATERAL */
+ bool hasHavingQual; /* true if havingQual was non-null */
+ bool hasPseudoConstantQuals; /* true if any RestrictInfo has
+ * pseudoconstant = true */
+ bool hasRecursion; /* true if planning a recursive WITH item */
+
+ /* These fields are used only when hasRecursion is true: */
+ int wt_param_id; /* PARAM_EXEC ID for the work table */
+ struct Path *non_recursive_path; /* a path for non-recursive term */
+
+ /* These fields are workspace for createplan.c */
+ Relids curOuterRels; /* outer rels above current node */
+ List *curOuterParams; /* not-yet-assigned NestLoopParams */
+
+ /* optional private data for join_search_hook, e.g., GEQO */
+ void *join_search_private;
+
+ /* Does this query modify any partition key columns? */
+ bool partColsUpdated;
+};
+
+
+/*
+ * In places where it's known that simple_rte_array[] must have been prepared
+ * already, we just index into it to fetch RTEs. In code that might be
+ * executed before or after entering query_planner(), use this macro.
+ */
+#define planner_rt_fetch(rti, root) \
+ ((root)->simple_rte_array ? (root)->simple_rte_array[rti] : \
+ rt_fetch(rti, (root)->parse->rtable))
+
+/*
+ * If multiple relations are partitioned the same way, all such partitions
+ * will have a pointer to the same PartitionScheme. A list of PartitionScheme
+ * objects is attached to the PlannerInfo. By design, the partition scheme
+ * incorporates only the general properties of the partition method (LIST vs.
+ * RANGE, number of partitioning columns and the type information for each)
+ * and not the specific bounds.
+ *
+ * We store the opclass-declared input data types instead of the partition key
+ * datatypes since the former rather than the latter are used to compare
+ * partition bounds. Since partition key data types and the opclass declared
+ * input data types are expected to be binary compatible (per ResolveOpClass),
+ * both of those should have same byval and length properties.
+ */
+typedef struct PartitionSchemeData
+{
+ char strategy; /* partition strategy */
+ int16 partnatts; /* number of partition attributes */
+ Oid *partopfamily; /* OIDs of operator families */
+ Oid *partopcintype; /* OIDs of opclass declared input data types */
+ Oid *partcollation; /* OIDs of partitioning collations */
+
+ /* Cached information about partition key data types. */
+ int16 *parttyplen;
+ bool *parttypbyval;
+
+ /* Cached information about partition comparison functions. */
+ struct FmgrInfo *partsupfunc;
+} PartitionSchemeData;
+
+typedef struct PartitionSchemeData *PartitionScheme;
+
+/*----------
+ * RelOptInfo
+ * Per-relation information for planning/optimization
+ *
+ * For planning purposes, a "base rel" is either a plain relation (a table)
+ * or the output of a sub-SELECT or function that appears in the range table.
+ * In either case it is uniquely identified by an RT index. A "joinrel"
+ * is the joining of two or more base rels. A joinrel is identified by
+ * the set of RT indexes for its component baserels. We create RelOptInfo
+ * nodes for each baserel and joinrel, and store them in the PlannerInfo's
+ * simple_rel_array and join_rel_list respectively.
+ *
+ * Note that there is only one joinrel for any given set of component
+ * baserels, no matter what order we assemble them in; so an unordered
+ * set is the right datatype to identify it with.
+ *
+ * We also have "other rels", which are like base rels in that they refer to
+ * single RT indexes; but they are not part of the join tree, and are given
+ * a different RelOptKind to identify them.
+ * Currently the only kind of otherrels are those made for member relations
+ * of an "append relation", that is an inheritance set or UNION ALL subquery.
+ * An append relation has a parent RTE that is a base rel, which represents
+ * the entire append relation. The member RTEs are otherrels. The parent
+ * is present in the query join tree but the members are not. The member
+ * RTEs and otherrels are used to plan the scans of the individual tables or
+ * subqueries of the append set; then the parent baserel is given Append
+ * and/or MergeAppend paths comprising the best paths for the individual
+ * member rels. (See comments for AppendRelInfo for more information.)
+ *
+ * At one time we also made otherrels to represent join RTEs, for use in
+ * handling join alias Vars. Currently this is not needed because all join
+ * alias Vars are expanded to non-aliased form during preprocess_expression.
+ *
+ * We also have relations representing joins between child relations of
+ * different partitioned tables. These relations are not added to
+ * join_rel_level lists as they are not joined directly by the dynamic
+ * programming algorithm.
+ *
+ * There is also a RelOptKind for "upper" relations, which are RelOptInfos
+ * that describe post-scan/join processing steps, such as aggregation.
+ * Many of the fields in these RelOptInfos are meaningless, but their Path
+ * fields always hold Paths showing ways to do that processing step.
+ *
+ * Lastly, there is a RelOptKind for "dead" relations, which are base rels
+ * that we have proven we don't need to join after all.
+ *
+ * Parts of this data structure are specific to various scan and join
+ * mechanisms. It didn't seem worth creating new node types for them.
+ *
+ * relids - Set of base-relation identifiers; it is a base relation
+ * if there is just one, a join relation if more than one
+ * rows - estimated number of tuples in the relation after restriction
+ * clauses have been applied (ie, output rows of a plan for it)
+ * consider_startup - true if there is any value in keeping plain paths for
+ * this rel on the basis of having cheap startup cost
+ * consider_param_startup - the same for parameterized paths
+ * reltarget - Default Path output tlist for this rel; normally contains
+ * Var and PlaceHolderVar nodes for the values we need to
+ * output from this relation.
+ * List is in no particular order, but all rels of an
+ * appendrel set must use corresponding orders.
+ * NOTE: in an appendrel child relation, may contain
+ * arbitrary expressions pulled up from a subquery!
+ * pathlist - List of Path nodes, one for each potentially useful
+ * method of generating the relation
+ * ppilist - ParamPathInfo nodes for parameterized Paths, if any
+ * cheapest_startup_path - the pathlist member with lowest startup cost
+ * (regardless of ordering) among the unparameterized paths;
+ * or NULL if there is no unparameterized path
+ * cheapest_total_path - the pathlist member with lowest total cost
+ * (regardless of ordering) among the unparameterized paths;
+ * or if there is no unparameterized path, the path with lowest
+ * total cost among the paths with minimum parameterization
+ * cheapest_unique_path - for caching cheapest path to produce unique
+ * (no duplicates) output from relation; NULL if not yet requested
+ * cheapest_parameterized_paths - best paths for their parameterizations;
+ * always includes cheapest_total_path, even if that's unparameterized
+ * direct_lateral_relids - rels this rel has direct LATERAL references to
+ * lateral_relids - required outer rels for LATERAL, as a Relids set
+ * (includes both direct and indirect lateral references)
+ *
+ * If the relation is a base relation it will have these fields set:
+ *
+ * relid - RTE index (this is redundant with the relids field, but
+ * is provided for convenience of access)
+ * rtekind - copy of RTE's rtekind field
+ * min_attr, max_attr - range of valid AttrNumbers for rel
+ * attr_needed - array of bitmapsets indicating the highest joinrel
+ * in which each attribute is needed; if bit 0 is set then
+ * the attribute is needed as part of final targetlist
+ * attr_widths - cache space for per-attribute width estimates;
+ * zero means not computed yet
+ * lateral_vars - lateral cross-references of rel, if any (list of
+ * Vars and PlaceHolderVars)
+ * lateral_referencers - relids of rels that reference this one laterally
+ * (includes both direct and indirect lateral references)
+ * indexlist - list of IndexOptInfo nodes for relation's indexes
+ * (always NIL if it's not a table)
+ * pages - number of disk pages in relation (zero if not a table)
+ * tuples - number of tuples in relation (not considering restrictions)
+ * allvisfrac - fraction of disk pages that are marked all-visible
+ * eclass_indexes - EquivalenceClasses that mention this rel (filled
+ * only after EC merging is complete)
+ * subroot - PlannerInfo for subquery (NULL if it's not a subquery)
+ * subplan_params - list of PlannerParamItems to be passed to subquery
+ *
+ * Note: for a subquery, tuples and subroot are not set immediately
+ * upon creation of the RelOptInfo object; they are filled in when
+ * set_subquery_pathlist processes the object.
+ *
+ * For otherrels that are appendrel members, these fields are filled
+ * in just as for a baserel, except we don't bother with lateral_vars.
+ *
+ * If the relation is either a foreign table or a join of foreign tables that
+ * all belong to the same foreign server and are assigned to the same user to
+ * check access permissions as (cf checkAsUser), these fields will be set:
+ *
+ * serverid - OID of foreign server, if foreign table (else InvalidOid)
+ * userid - OID of user to check access as (InvalidOid means current user)
+ * useridiscurrent - we've assumed that userid equals current user
+ * fdwroutine - function hooks for FDW, if foreign table (else NULL)
+ * fdw_private - private state for FDW, if foreign table (else NULL)
+ *
+ * Two fields are used to cache knowledge acquired during the join search
+ * about whether this rel is provably unique when being joined to given other
+ * relation(s), ie, it can have at most one row matching any given row from
+ * that join relation. Currently we only attempt such proofs, and thus only
+ * populate these fields, for base rels; but someday they might be used for
+ * join rels too:
+ *
+ * unique_for_rels - list of Relid sets, each one being a set of other
+ * rels for which this one has been proven unique
+ * non_unique_for_rels - list of Relid sets, each one being a set of
+ * other rels for which we have tried and failed to prove
+ * this one unique
+ *
+ * The presence of the following fields depends on the restrictions
+ * and joins that the relation participates in:
+ *
+ * baserestrictinfo - List of RestrictInfo nodes, containing info about
+ * each non-join qualification clause in which this relation
+ * participates (only used for base rels)
+ * baserestrictcost - Estimated cost of evaluating the baserestrictinfo
+ * clauses at a single tuple (only used for base rels)
+ * baserestrict_min_security - Smallest security_level found among
+ * clauses in baserestrictinfo
+ * joininfo - List of RestrictInfo nodes, containing info about each
+ * join clause in which this relation participates (but
+ * note this excludes clauses that might be derivable from
+ * EquivalenceClasses)
+ * has_eclass_joins - flag that EquivalenceClass joins are possible
+ *
+ * Note: Keeping a restrictinfo list in the RelOptInfo is useful only for
+ * base rels, because for a join rel the set of clauses that are treated as
+ * restrict clauses varies depending on which sub-relations we choose to join.
+ * (For example, in a 3-base-rel join, a clause relating rels 1 and 2 must be
+ * treated as a restrictclause if we join {1} and {2 3} to make {1 2 3}; but
+ * if we join {1 2} and {3} then that clause will be a restrictclause in {1 2}
+ * and should not be processed again at the level of {1 2 3}.) Therefore,
+ * the restrictinfo list in the join case appears in individual JoinPaths
+ * (field joinrestrictinfo), not in the parent relation. But it's OK for
+ * the RelOptInfo to store the joininfo list, because that is the same
+ * for a given rel no matter how we form it.
+ *
+ * We store baserestrictcost in the RelOptInfo (for base relations) because
+ * we know we will need it at least once (to price the sequential scan)
+ * and may need it multiple times to price index scans.
+ *
+ * A join relation is considered to be partitioned if it is formed from a
+ * join of two relations that are partitioned, have matching partitioning
+ * schemes, and are joined on an equijoin of the partitioning columns.
+ * Under those conditions we can consider the join relation to be partitioned
+ * by either relation's partitioning keys, though some care is needed if
+ * either relation can be forced to null by outer-joining. For example, an
+ * outer join like (A LEFT JOIN B ON A.a = B.b) may produce rows with B.b
+ * NULL. These rows may not fit the partitioning conditions imposed on B.
+ * Hence, strictly speaking, the join is not partitioned by B.b and thus
+ * partition keys of an outer join should include partition key expressions
+ * from the non-nullable side only. However, if a subsequent join uses
+ * strict comparison operators (and all commonly-used equijoin operators are
+ * strict), the presence of nulls doesn't cause a problem: such rows couldn't
+ * match anything on the other side and thus they don't create a need to do
+ * any cross-partition sub-joins. Hence we can treat such values as still
+ * partitioning the join output for the purpose of additional partitionwise
+ * joining, so long as a strict join operator is used by the next join.
+ *
+ * If the relation is partitioned, these fields will be set:
+ *
+ * part_scheme - Partitioning scheme of the relation
+ * nparts - Number of partitions
+ * boundinfo - Partition bounds
+ * partbounds_merged - true if partition bounds are merged ones
+ * partition_qual - Partition constraint if not the root
+ * part_rels - RelOptInfos for each partition
+ * all_partrels - Relids set of all partition relids
+ * partexprs, nullable_partexprs - Partition key expressions
+ * partitioned_child_rels - RT indexes of unpruned partitions of
+ * this relation that are partitioned tables
+ * themselves, in hierarchical order
+ *
+ * The partexprs and nullable_partexprs arrays each contain
+ * part_scheme->partnatts elements. Each of the elements is a list of
+ * partition key expressions. For partitioned base relations, there is one
+ * expression in each partexprs element, and nullable_partexprs is empty.
+ * For partitioned join relations, each base relation within the join
+ * contributes one partition key expression per partitioning column;
+ * that expression goes in the partexprs[i] list if the base relation
+ * is not nullable by this join or any lower outer join, or in the
+ * nullable_partexprs[i] list if the base relation is nullable.
+ * Furthermore, FULL JOINs add extra nullable_partexprs expressions
+ * corresponding to COALESCE expressions of the left and right join columns,
+ * to simplify matching join clauses to those lists.
+ *----------
+ */
+typedef enum RelOptKind
+{
+ RELOPT_BASEREL,
+ RELOPT_JOINREL,
+ RELOPT_OTHER_MEMBER_REL,
+ RELOPT_OTHER_JOINREL,
+ RELOPT_UPPER_REL,
+ RELOPT_OTHER_UPPER_REL,
+ RELOPT_DEADREL
+} RelOptKind;
+
+/*
+ * Is the given relation a simple relation i.e a base or "other" member
+ * relation?
+ */
+#define IS_SIMPLE_REL(rel) \
+ ((rel)->reloptkind == RELOPT_BASEREL || \
+ (rel)->reloptkind == RELOPT_OTHER_MEMBER_REL)
+
+/* Is the given relation a join relation? */
+#define IS_JOIN_REL(rel) \
+ ((rel)->reloptkind == RELOPT_JOINREL || \
+ (rel)->reloptkind == RELOPT_OTHER_JOINREL)
+
+/* Is the given relation an upper relation? */
+#define IS_UPPER_REL(rel) \
+ ((rel)->reloptkind == RELOPT_UPPER_REL || \
+ (rel)->reloptkind == RELOPT_OTHER_UPPER_REL)
+
+/* Is the given relation an "other" relation? */
+#define IS_OTHER_REL(rel) \
+ ((rel)->reloptkind == RELOPT_OTHER_MEMBER_REL || \
+ (rel)->reloptkind == RELOPT_OTHER_JOINREL || \
+ (rel)->reloptkind == RELOPT_OTHER_UPPER_REL)
+
+typedef struct RelOptInfo
+{
+ NodeTag type;
+
+ RelOptKind reloptkind;
+
+ /* all relations included in this RelOptInfo */
+ Relids relids; /* set of base relids (rangetable indexes) */
+
+ /* size estimates generated by planner */
+ double rows; /* estimated number of result tuples */
+
+ /* per-relation planner control flags */
+ bool consider_startup; /* keep cheap-startup-cost paths? */
+ bool consider_param_startup; /* ditto, for parameterized paths? */
+ bool consider_parallel; /* consider parallel paths? */
+
+ /* default result targetlist for Paths scanning this relation */
+ struct PathTarget *reltarget; /* list of Vars/Exprs, cost, width */
+
+ /* materialization information */
+ List *pathlist; /* Path structures */
+ List *ppilist; /* ParamPathInfos used in pathlist */
+ List *partial_pathlist; /* partial Paths */
+ struct Path *cheapest_startup_path;
+ struct Path *cheapest_total_path;
+ struct Path *cheapest_unique_path;
+ List *cheapest_parameterized_paths;
+
+ /* parameterization information needed for both base rels and join rels */
+ /* (see also lateral_vars and lateral_referencers) */
+ Relids direct_lateral_relids; /* rels directly laterally referenced */
+ Relids lateral_relids; /* minimum parameterization of rel */
+
+ /* information about a base rel (not set for join rels!) */
+ Index relid;
+ Oid reltablespace; /* containing tablespace */
+ RTEKind rtekind; /* RELATION, SUBQUERY, FUNCTION, etc */
+ AttrNumber min_attr; /* smallest attrno of rel (often <0) */
+ AttrNumber max_attr; /* largest attrno of rel */
+ Relids *attr_needed; /* array indexed [min_attr .. max_attr] */
+ int32 *attr_widths; /* array indexed [min_attr .. max_attr] */
+ List *lateral_vars; /* LATERAL Vars and PHVs referenced by rel */
+ Relids lateral_referencers; /* rels that reference me laterally */
+ List *indexlist; /* list of IndexOptInfo */
+ List *statlist; /* list of StatisticExtInfo */
+ BlockNumber pages; /* size estimates derived from pg_class */
+ double tuples;
+ double allvisfrac;
+ Bitmapset *eclass_indexes; /* Indexes in PlannerInfo's eq_classes list of
+ * ECs that mention this rel */
+ PlannerInfo *subroot; /* if subquery */
+ List *subplan_params; /* if subquery */
+ int rel_parallel_workers; /* wanted number of parallel workers */
+
+ /* Information about foreign tables and foreign joins */
+ Oid serverid; /* identifies server for the table or join */
+ Oid userid; /* identifies user to check access as */
+ bool useridiscurrent; /* join is only valid for current user */
+ /* use "struct FdwRoutine" to avoid including fdwapi.h here */
+ struct FdwRoutine *fdwroutine;
+ void *fdw_private;
+
+ /* cache space for remembering if we have proven this relation unique */
+ List *unique_for_rels; /* known unique for these other relid
+ * set(s) */
+ List *non_unique_for_rels; /* known not unique for these set(s) */
+
+ /* used by various scans and joins: */
+ List *baserestrictinfo; /* RestrictInfo structures (if base rel) */
+ QualCost baserestrictcost; /* cost of evaluating the above */
+ Index baserestrict_min_security; /* min security_level found in
+ * baserestrictinfo */
+ List *joininfo; /* RestrictInfo structures for join clauses
+ * involving this rel */
+ bool has_eclass_joins; /* T means joininfo is incomplete */
+
+ /* used by partitionwise joins: */
+ bool consider_partitionwise_join; /* consider partitionwise join
+ * paths? (if partitioned rel) */
+ Relids top_parent_relids; /* Relids of topmost parents (if "other"
+ * rel) */
+
+ /* used for partitioned relations: */
+ PartitionScheme part_scheme; /* Partitioning scheme */
+ int nparts; /* Number of partitions; -1 if not yet set; in
+ * case of a join relation 0 means it's
+ * considered unpartitioned */
+ struct PartitionBoundInfoData *boundinfo; /* Partition bounds */
+ bool partbounds_merged; /* True if partition bounds were created
+ * by partition_bounds_merge() */
+ List *partition_qual; /* Partition constraint, if not the root */
+ struct RelOptInfo **part_rels; /* Array of RelOptInfos of partitions,
+ * stored in the same order as bounds */
+ Relids all_partrels; /* Relids set of all partition relids */
+ List **partexprs; /* Non-nullable partition key expressions */
+ List **nullable_partexprs; /* Nullable partition key expressions */
+ List *partitioned_child_rels; /* List of RT indexes */
+} RelOptInfo;
+
+/*
+ * Is given relation partitioned?
+ *
+ * It's not enough to test whether rel->part_scheme is set, because it might
+ * be that the basic partitioning properties of the input relations matched
+ * but the partition bounds did not. Also, if we are able to prove a rel
+ * dummy (empty), we should henceforth treat it as unpartitioned.
+ */
+#define IS_PARTITIONED_REL(rel) \
+ ((rel)->part_scheme && (rel)->boundinfo && (rel)->nparts > 0 && \
+ (rel)->part_rels && !IS_DUMMY_REL(rel))
+
+/*
+ * Convenience macro to make sure that a partitioned relation has all the
+ * required members set.
+ */
+#define REL_HAS_ALL_PART_PROPS(rel) \
+ ((rel)->part_scheme && (rel)->boundinfo && (rel)->nparts > 0 && \
+ (rel)->part_rels && (rel)->partexprs && (rel)->nullable_partexprs)
+
+/*
+ * IndexOptInfo
+ * Per-index information for planning/optimization
+ *
+ * indexkeys[], indexcollations[] each have ncolumns entries.
+ * opfamily[], and opcintype[] each have nkeycolumns entries. They do
+ * not contain any information about included attributes.
+ *
+ * sortopfamily[], reverse_sort[], and nulls_first[] have
+ * nkeycolumns entries, if the index is ordered; but if it is unordered,
+ * those pointers are NULL.
+ *
+ * Zeroes in the indexkeys[] array indicate index columns that are
+ * expressions; there is one element in indexprs for each such column.
+ *
+ * For an ordered index, reverse_sort[] and nulls_first[] describe the
+ * sort ordering of a forward indexscan; we can also consider a backward
+ * indexscan, which will generate the reverse ordering.
+ *
+ * The indexprs and indpred expressions have been run through
+ * prepqual.c and eval_const_expressions() for ease of matching to
+ * WHERE clauses. indpred is in implicit-AND form.
+ *
+ * indextlist is a TargetEntry list representing the index columns.
+ * It provides an equivalent base-relation Var for each simple column,
+ * and links to the matching indexprs element for each expression column.
+ *
+ * While most of these fields are filled when the IndexOptInfo is created
+ * (by plancat.c), indrestrictinfo and predOK are set later, in
+ * check_index_predicates().
+ */
+#ifndef HAVE_INDEXOPTINFO_TYPEDEF
+typedef struct IndexOptInfo IndexOptInfo;
+#define HAVE_INDEXOPTINFO_TYPEDEF 1
+#endif
+
+struct IndexOptInfo
+{
+ NodeTag type;
+
+ Oid indexoid; /* OID of the index relation */
+ Oid reltablespace; /* tablespace of index (not table) */
+ RelOptInfo *rel; /* back-link to index's table */
+
+ /* index-size statistics (from pg_class and elsewhere) */
+ BlockNumber pages; /* number of disk pages in index */
+ double tuples; /* number of index tuples in index */
+ int tree_height; /* index tree height, or -1 if unknown */
+
+ /* index descriptor information */
+ int ncolumns; /* number of columns in index */
+ int nkeycolumns; /* number of key columns in index */
+ int *indexkeys; /* column numbers of index's attributes both
+ * key and included columns, or 0 */
+ Oid *indexcollations; /* OIDs of collations of index columns */
+ Oid *opfamily; /* OIDs of operator families for columns */
+ Oid *opcintype; /* OIDs of opclass declared input data types */
+ Oid *sortopfamily; /* OIDs of btree opfamilies, if orderable */
+ bool *reverse_sort; /* is sort order descending? */
+ bool *nulls_first; /* do NULLs come first in the sort order? */
+ bytea **opclassoptions; /* opclass-specific options for columns */
+ bool *canreturn; /* which index cols can be returned in an
+ * index-only scan? */
+ Oid relam; /* OID of the access method (in pg_am) */
+
+ List *indexprs; /* expressions for non-simple index columns */
+ List *indpred; /* predicate if a partial index, else NIL */
+
+ List *indextlist; /* targetlist representing index columns */
+
+ List *indrestrictinfo; /* parent relation's baserestrictinfo
+ * list, less any conditions implied by
+ * the index's predicate (unless it's a
+ * target rel, see comments in
+ * check_index_predicates()) */
+
+ bool predOK; /* true if index predicate matches query */
+ bool unique; /* true if a unique index */
+ bool immediate; /* is uniqueness enforced immediately? */
+ bool hypothetical; /* true if index doesn't really exist */
+
+ /* Remaining fields are copied from the index AM's API struct: */
+ bool amcanorderbyop; /* does AM support order by operator result? */
+ bool amoptionalkey; /* can query omit key for the first column? */
+ bool amsearcharray; /* can AM handle ScalarArrayOpExpr quals? */
+ bool amsearchnulls; /* can AM search for NULL/NOT NULL entries? */
+ bool amhasgettuple; /* does AM have amgettuple interface? */
+ bool amhasgetbitmap; /* does AM have amgetbitmap interface? */
+ bool amcanparallel; /* does AM support parallel scan? */
+ bool amcanmarkpos; /* does AM support mark/restore? */
+ /* Rather than include amapi.h here, we declare amcostestimate like this */
+ void (*amcostestimate) (); /* AM's cost estimator */
+};
+
+/*
+ * ForeignKeyOptInfo
+ * Per-foreign-key information for planning/optimization
+ *
+ * The per-FK-column arrays can be fixed-size because we allow at most
+ * INDEX_MAX_KEYS columns in a foreign key constraint. Each array has
+ * nkeys valid entries.
+ */
+typedef struct ForeignKeyOptInfo
+{
+ NodeTag type;
+
+ /* Basic data about the foreign key (fetched from catalogs): */
+ Index con_relid; /* RT index of the referencing table */
+ Index ref_relid; /* RT index of the referenced table */
+ int nkeys; /* number of columns in the foreign key */
+ 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 */
+
+ /* Derived info about whether FK's equality conditions match the query: */
+ int nmatched_ec; /* # of FK cols matched by ECs */
+ int nmatched_rcols; /* # of FK cols matched by non-EC rinfos */
+ int nmatched_ri; /* total # of non-EC rinfos matched to FK */
+ /* Pointer to eclass matching each column's condition, if there is one */
+ struct EquivalenceClass *eclass[INDEX_MAX_KEYS];
+ /* List of non-EC RestrictInfos matching each column's condition */
+ List *rinfos[INDEX_MAX_KEYS];
+} ForeignKeyOptInfo;
+
+/*
+ * StatisticExtInfo
+ * Information about extended statistics for planning/optimization
+ *
+ * Each pg_statistic_ext row is represented by one or more nodes of this
+ * type, or even zero if ANALYZE has not computed them.
+ */
+typedef struct StatisticExtInfo
+{
+ NodeTag type;
+
+ Oid statOid; /* OID of the statistics row */
+ RelOptInfo *rel; /* back-link to statistic's table */
+ char kind; /* statistics kind of this entry */
+ Bitmapset *keys; /* attnums of the columns covered */
+} StatisticExtInfo;
+
+/*
+ * EquivalenceClasses
+ *
+ * Whenever we can determine that a mergejoinable equality clause A = B is
+ * not delayed by any outer join, we create an EquivalenceClass containing
+ * the expressions A and B to record this knowledge. If we later find another
+ * equivalence B = C, we add C to the existing EquivalenceClass; this may
+ * require merging two existing EquivalenceClasses. At the end of the qual
+ * distribution process, we have sets of values that are known all transitively
+ * equal to each other, where "equal" is according to the rules of the btree
+ * operator family(s) shown in ec_opfamilies, as well as the collation shown
+ * by ec_collation. (We restrict an EC to contain only equalities whose
+ * operators belong to the same set of opfamilies. This could probably be
+ * relaxed, but for now it's not worth the trouble, since nearly all equality
+ * operators belong to only one btree opclass anyway. Similarly, we suppose
+ * that all or none of the input datatypes are collatable, so that a single
+ * collation value is sufficient.)
+ *
+ * We also use EquivalenceClasses as the base structure for PathKeys, letting
+ * us represent knowledge about different sort orderings being equivalent.
+ * Since every PathKey must reference an EquivalenceClass, we will end up
+ * with single-member EquivalenceClasses whenever a sort key expression has
+ * not been equivalenced to anything else. It is also possible that such an
+ * EquivalenceClass will contain a volatile expression ("ORDER BY random()"),
+ * which is a case that can't arise otherwise since clauses containing
+ * volatile functions are never considered mergejoinable. We mark such
+ * EquivalenceClasses specially to prevent them from being merged with
+ * ordinary EquivalenceClasses. Also, for volatile expressions we have
+ * to be careful to match the EquivalenceClass to the correct targetlist
+ * entry: consider SELECT random() AS a, random() AS b ... ORDER BY b,a.
+ * So we record the SortGroupRef of the originating sort clause.
+ *
+ * We allow equality clauses appearing below the nullable side of an outer join
+ * to form EquivalenceClasses, but these have a slightly different meaning:
+ * the included values might be all NULL rather than all the same non-null
+ * values. See src/backend/optimizer/README for more on that point.
+ *
+ * NB: if ec_merged isn't NULL, this class has been merged into another, and
+ * should be ignored in favor of using the pointed-to class.
+ */
+typedef struct EquivalenceClass
+{
+ NodeTag type;
+
+ List *ec_opfamilies; /* btree operator family OIDs */
+ Oid ec_collation; /* collation, if datatypes are collatable */
+ List *ec_members; /* list of EquivalenceMembers */
+ List *ec_sources; /* list of generating RestrictInfos */
+ List *ec_derives; /* list of derived RestrictInfos */
+ Relids ec_relids; /* all relids appearing in ec_members, except
+ * for child members (see below) */
+ bool ec_has_const; /* any pseudoconstants in ec_members? */
+ bool ec_has_volatile; /* the (sole) member is a volatile expr */
+ bool ec_below_outer_join; /* equivalence applies below an OJ */
+ bool ec_broken; /* failed to generate needed clauses? */
+ Index ec_sortref; /* originating sortclause label, or 0 */
+ Index ec_min_security; /* minimum security_level in ec_sources */
+ Index ec_max_security; /* maximum security_level in ec_sources */
+ struct EquivalenceClass *ec_merged; /* set if merged into another EC */
+} EquivalenceClass;
+
+/*
+ * If an EC contains a const and isn't below-outer-join, any PathKey depending
+ * on it must be redundant, since there's only one possible value of the key.
+ */
+#define EC_MUST_BE_REDUNDANT(eclass) \
+ ((eclass)->ec_has_const && !(eclass)->ec_below_outer_join)
+
+/*
+ * EquivalenceMember - one member expression of an EquivalenceClass
+ *
+ * em_is_child signifies that this element was built by transposing a member
+ * for an appendrel parent relation to represent the corresponding expression
+ * for an appendrel child. These members are used for determining the
+ * pathkeys of scans on the child relation and for explicitly sorting the
+ * child when necessary to build a MergeAppend path for the whole appendrel
+ * tree. An em_is_child member has no impact on the properties of the EC as a
+ * whole; in particular the EC's ec_relids field does NOT include the child
+ * relation. An em_is_child member should never be marked em_is_const nor
+ * cause ec_has_const or ec_has_volatile to be set, either. Thus, em_is_child
+ * members are not really full-fledged members of the EC, but just reflections
+ * or doppelgangers of real members. Most operations on EquivalenceClasses
+ * should ignore em_is_child members, and those that don't should test
+ * em_relids to make sure they only consider relevant members.
+ *
+ * em_datatype is usually the same as exprType(em_expr), but can be
+ * different when dealing with a binary-compatible opfamily; in particular
+ * anyarray_ops would never work without this. Use em_datatype when
+ * looking up a specific btree operator to work with this expression.
+ */
+typedef struct EquivalenceMember
+{
+ NodeTag type;
+
+ Expr *em_expr; /* the expression represented */
+ Relids em_relids; /* all relids appearing in em_expr */
+ Relids em_nullable_relids; /* nullable by lower outer joins */
+ bool em_is_const; /* expression is pseudoconstant? */
+ bool em_is_child; /* derived version for a child relation? */
+ Oid em_datatype; /* the "nominal type" used by the opfamily */
+} EquivalenceMember;
+
+/*
+ * PathKeys
+ *
+ * The sort ordering of a path is represented by a list of PathKey nodes.
+ * An empty list implies no known ordering. Otherwise the first item
+ * represents the primary sort key, the second the first secondary sort key,
+ * etc. The value being sorted is represented by linking to an
+ * EquivalenceClass containing that value and including pk_opfamily among its
+ * ec_opfamilies. The EquivalenceClass tells which collation to use, too.
+ * This is a convenient method because it makes it trivial to detect
+ * equivalent and closely-related orderings. (See optimizer/README for more
+ * information.)
+ *
+ * Note: pk_strategy is either BTLessStrategyNumber (for ASC) or
+ * BTGreaterStrategyNumber (for DESC). We assume that all ordering-capable
+ * index types will use btree-compatible strategy numbers.
+ */
+typedef struct PathKey
+{
+ NodeTag type;
+
+ EquivalenceClass *pk_eclass; /* the value that is ordered */
+ Oid pk_opfamily; /* btree opfamily defining the ordering */
+ int pk_strategy; /* sort direction (ASC or DESC) */
+ bool pk_nulls_first; /* do NULLs come before normal values? */
+} PathKey;
+
+
+/*
+ * PathTarget
+ *
+ * This struct contains what we need to know during planning about the
+ * targetlist (output columns) that a Path will compute. Each RelOptInfo
+ * includes a default PathTarget, which its individual Paths may simply
+ * reference. However, in some cases a Path may compute outputs different
+ * from other Paths, and in that case we make a custom PathTarget for it.
+ * For example, an indexscan might return index expressions that would
+ * otherwise need to be explicitly calculated. (Note also that "upper"
+ * relations generally don't have useful default PathTargets.)
+ *
+ * exprs contains bare expressions; they do not have TargetEntry nodes on top,
+ * though those will appear in finished Plans.
+ *
+ * sortgrouprefs[] is an array of the same length as exprs, containing the
+ * corresponding sort/group refnos, or zeroes for expressions not referenced
+ * by sort/group clauses. If sortgrouprefs is NULL (which it generally is in
+ * RelOptInfo.reltarget targets; only upper-level Paths contain this info),
+ * we have not identified sort/group columns in this tlist. This allows us to
+ * deal with sort/group refnos when needed with less expense than including
+ * TargetEntry nodes in the exprs list.
+ */
+typedef struct PathTarget
+{
+ NodeTag type;
+ List *exprs; /* list of expressions to be computed */
+ Index *sortgrouprefs; /* corresponding sort/group refnos, or 0 */
+ QualCost cost; /* cost of evaluating the expressions */
+ int width; /* estimated avg width of result tuples */
+} PathTarget;
+
+/* Convenience macro to get a sort/group refno from a PathTarget */
+#define get_pathtarget_sortgroupref(target, colno) \
+ ((target)->sortgrouprefs ? (target)->sortgrouprefs[colno] : (Index) 0)
+
+
+/*
+ * ParamPathInfo
+ *
+ * All parameterized paths for a given relation with given required outer rels
+ * link to a single ParamPathInfo, which stores common information such as
+ * the estimated rowcount for this parameterization. We do this partly to
+ * avoid recalculations, but mostly to ensure that the estimated rowcount
+ * is in fact the same for every such path.
+ *
+ * Note: ppi_clauses is only used in ParamPathInfos for base relation paths;
+ * in join cases it's NIL because the set of relevant clauses varies depending
+ * on how the join is formed. The relevant clauses will appear in each
+ * parameterized join path's joinrestrictinfo list, instead.
+ */
+typedef struct ParamPathInfo
+{
+ NodeTag type;
+
+ Relids ppi_req_outer; /* rels supplying parameters used by path */
+ double ppi_rows; /* estimated number of result tuples */
+ List *ppi_clauses; /* join clauses available from outer rels */
+} ParamPathInfo;
+
+
+/*
+ * Type "Path" is used as-is for sequential-scan paths, as well as some other
+ * simple plan types that we don't need any extra information in the path for.
+ * For other path types it is the first component of a larger struct.
+ *
+ * "pathtype" is the NodeTag of the Plan node we could build from this Path.
+ * It is partially redundant with the Path's NodeTag, but allows us to use
+ * the same Path type for multiple Plan types when there is no need to
+ * distinguish the Plan type during path processing.
+ *
+ * "parent" identifies the relation this Path scans, and "pathtarget"
+ * describes the precise set of output columns the Path would compute.
+ * In simple cases all Paths for a given rel share the same targetlist,
+ * which we represent by having path->pathtarget equal to parent->reltarget.
+ *
+ * "param_info", if not NULL, links to a ParamPathInfo that identifies outer
+ * relation(s) that provide parameter values to each scan of this path.
+ * That means this path can only be joined to those rels by means of nestloop
+ * joins with this path on the inside. Also note that a parameterized path
+ * is responsible for testing all "movable" joinclauses involving this rel
+ * and the specified outer rel(s).
+ *
+ * "rows" is the same as parent->rows in simple paths, but in parameterized
+ * paths and UniquePaths it can be less than parent->rows, reflecting the
+ * fact that we've filtered by extra join conditions or removed duplicates.
+ *
+ * "pathkeys" is a List of PathKey nodes (see above), describing the sort
+ * ordering of the path's output rows.
+ */
+typedef struct Path
+{
+ NodeTag type;
+
+ NodeTag pathtype; /* tag identifying scan/join method */
+
+ RelOptInfo *parent; /* the relation this path can build */
+ PathTarget *pathtarget; /* list of Vars/Exprs, cost, width */
+
+ ParamPathInfo *param_info; /* parameterization info, or NULL if none */
+
+ bool parallel_aware; /* engage parallel-aware logic? */
+ bool parallel_safe; /* OK to use as part of parallel plan? */
+ int parallel_workers; /* desired # of workers; 0 = not parallel */
+
+ /* estimated size/costs for path (see costsize.c for more info) */
+ double rows; /* estimated number of result tuples */
+ Cost startup_cost; /* cost expended before fetching any tuples */
+ Cost total_cost; /* total cost (assuming all tuples fetched) */
+
+ List *pathkeys; /* sort ordering of path's output */
+ /* pathkeys is a List of PathKey nodes; see above */
+} Path;
+
+/* Macro for extracting a path's parameterization relids; beware double eval */
+#define PATH_REQ_OUTER(path) \
+ ((path)->param_info ? (path)->param_info->ppi_req_outer : (Relids) NULL)
+
+/*----------
+ * IndexPath represents an index scan over a single index.
+ *
+ * This struct is used for both regular indexscans and index-only scans;
+ * path.pathtype is T_IndexScan or T_IndexOnlyScan to show which is meant.
+ *
+ * 'indexinfo' is the index to be scanned.
+ *
+ * 'indexclauses' is a list of IndexClause nodes, each representing one
+ * index-checkable restriction, with implicit AND semantics across the list.
+ * An empty list implies a full index scan.
+ *
+ * 'indexorderbys', if not NIL, is a list of ORDER BY expressions that have
+ * been found to be usable as ordering operators for an amcanorderbyop index.
+ * The list must match the path's pathkeys, ie, one expression per pathkey
+ * in the same order. These are not RestrictInfos, just bare expressions,
+ * since they generally won't yield booleans. It's guaranteed that each
+ * expression has the index key on the left side of the operator.
+ *
+ * 'indexorderbycols' is an integer list of index column numbers (zero-based)
+ * of the same length as 'indexorderbys', showing which index column each
+ * ORDER BY expression is meant to be used with. (There is no restriction
+ * on which index column each ORDER BY can be used with.)
+ *
+ * 'indexscandir' is one of:
+ * ForwardScanDirection: forward scan of an ordered index
+ * BackwardScanDirection: backward scan of an ordered index
+ * NoMovementScanDirection: scan of an unordered index, or don't care
+ * (The executor doesn't care whether it gets ForwardScanDirection or
+ * NoMovementScanDirection for an indexscan, but the planner wants to
+ * distinguish ordered from unordered indexes for building pathkeys.)
+ *
+ * 'indextotalcost' and 'indexselectivity' are saved in the IndexPath so that
+ * we need not recompute them when considering using the same index in a
+ * bitmap index/heap scan (see BitmapHeapPath). The costs of the IndexPath
+ * itself represent the costs of an IndexScan or IndexOnlyScan plan type.
+ *----------
+ */
+typedef struct IndexPath
+{
+ Path path;
+ IndexOptInfo *indexinfo;
+ List *indexclauses;
+ List *indexorderbys;
+ List *indexorderbycols;
+ ScanDirection indexscandir;
+ Cost indextotalcost;
+ Selectivity indexselectivity;
+} IndexPath;
+
+/*
+ * Each IndexClause references a RestrictInfo node from the query's WHERE
+ * or JOIN conditions, and shows how that restriction can be applied to
+ * the particular index. We support both indexclauses that are directly
+ * usable by the index machinery, which are typically of the form
+ * "indexcol OP pseudoconstant", and those from which an indexable qual
+ * can be derived. The simplest such transformation is that a clause
+ * of the form "pseudoconstant OP indexcol" can be commuted to produce an
+ * indexable qual (the index machinery expects the indexcol to be on the
+ * left always). Another example is that we might be able to extract an
+ * indexable range condition from a LIKE condition, as in "x LIKE 'foo%bar'"
+ * giving rise to "x >= 'foo' AND x < 'fop'". Derivation of such lossy
+ * conditions is done by a planner support function attached to the
+ * indexclause's top-level function or operator.
+ *
+ * indexquals is a list of RestrictInfos for the directly-usable index
+ * conditions associated with this IndexClause. In the simplest case
+ * it's a one-element list whose member is iclause->rinfo. Otherwise,
+ * it contains one or more directly-usable indexqual conditions extracted
+ * from the given clause. The 'lossy' flag indicates whether the
+ * indexquals are semantically equivalent to the original clause, or
+ * represent a weaker condition.
+ *
+ * Normally, indexcol is the index of the single index column the clause
+ * works on, and indexcols is NIL. But if the clause is a RowCompareExpr,
+ * indexcol is the index of the leading column, and indexcols is a list of
+ * all the affected columns. (Note that indexcols matches up with the
+ * columns of the actual indexable RowCompareExpr in indexquals, which
+ * might be different from the original in rinfo.)
+ *
+ * An IndexPath's IndexClause list is required to be ordered by index
+ * column, i.e. the indexcol values must form a nondecreasing sequence.
+ * (The order of multiple clauses for the same index column is unspecified.)
+ */
+typedef struct IndexClause
+{
+ NodeTag type;
+ struct RestrictInfo *rinfo; /* original restriction or join clause */
+ List *indexquals; /* indexqual(s) derived from it */
+ bool lossy; /* are indexquals a lossy version of clause? */
+ AttrNumber indexcol; /* index column the clause uses (zero-based) */
+ List *indexcols; /* multiple index columns, if RowCompare */
+} IndexClause;
+
+/*
+ * BitmapHeapPath represents one or more indexscans that generate TID bitmaps
+ * instead of directly accessing the heap, followed by AND/OR combinations
+ * to produce a single bitmap, followed by a heap scan that uses the bitmap.
+ * Note that the output is always considered unordered, since it will come
+ * out in physical heap order no matter what the underlying indexes did.
+ *
+ * The individual indexscans are represented by IndexPath nodes, and any
+ * logic on top of them is represented by a tree of BitmapAndPath and
+ * BitmapOrPath nodes. Notice that we can use the same IndexPath node both
+ * to represent a regular (or index-only) index scan plan, and as the child
+ * of a BitmapHeapPath that represents scanning the same index using a
+ * BitmapIndexScan. The startup_cost and total_cost figures of an IndexPath
+ * always represent the costs to use it as a regular (or index-only)
+ * IndexScan. The costs of a BitmapIndexScan can be computed using the
+ * IndexPath's indextotalcost and indexselectivity.
+ */
+typedef struct BitmapHeapPath
+{
+ Path path;
+ Path *bitmapqual; /* IndexPath, BitmapAndPath, BitmapOrPath */
+} BitmapHeapPath;
+
+/*
+ * BitmapAndPath represents a BitmapAnd plan node; it can only appear as
+ * part of the substructure of a BitmapHeapPath. The Path structure is
+ * a bit more heavyweight than we really need for this, but for simplicity
+ * we make it a derivative of Path anyway.
+ */
+typedef struct BitmapAndPath
+{
+ Path path;
+ List *bitmapquals; /* IndexPaths and BitmapOrPaths */
+ Selectivity bitmapselectivity;
+} BitmapAndPath;
+
+/*
+ * BitmapOrPath represents a BitmapOr plan node; it can only appear as
+ * part of the substructure of a BitmapHeapPath. The Path structure is
+ * a bit more heavyweight than we really need for this, but for simplicity
+ * we make it a derivative of Path anyway.
+ */
+typedef struct BitmapOrPath
+{
+ Path path;
+ List *bitmapquals; /* IndexPaths and BitmapAndPaths */
+ Selectivity bitmapselectivity;
+} BitmapOrPath;
+
+/*
+ * TidPath represents a scan by TID
+ *
+ * tidquals is an implicitly OR'ed list of qual expressions of the form
+ * "CTID = pseudoconstant", or "CTID = ANY(pseudoconstant_array)",
+ * or a CurrentOfExpr for the relation.
+ */
+typedef struct TidPath
+{
+ Path path;
+ List *tidquals; /* qual(s) involving CTID = something */
+} TidPath;
+
+/*
+ * SubqueryScanPath represents a scan of an unflattened subquery-in-FROM
+ *
+ * Note that the subpath comes from a different planning domain; for example
+ * RTE indexes within it mean something different from those known to the
+ * SubqueryScanPath. path.parent->subroot is the planning context needed to
+ * interpret the subpath.
+ */
+typedef struct SubqueryScanPath
+{
+ Path path;
+ Path *subpath; /* path representing subquery execution */
+} SubqueryScanPath;
+
+/*
+ * ForeignPath represents a potential scan of a foreign table, foreign join
+ * or foreign upper-relation.
+ *
+ * fdw_private stores FDW private data about the scan. While fdw_private is
+ * not actually touched by the core code during normal operations, it's
+ * generally a good idea to use a representation that can be dumped by
+ * nodeToString(), so that you can examine the structure during debugging
+ * with tools like pprint().
+ */
+typedef struct ForeignPath
+{
+ Path path;
+ Path *fdw_outerpath;
+ List *fdw_private;
+} ForeignPath;
+
+/*
+ * CustomPath represents a table scan done by some out-of-core extension.
+ *
+ * We provide a set of hooks here - which the provider must take care to set
+ * up correctly - to allow extensions to supply their own methods of scanning
+ * a relation. For example, a provider might provide GPU acceleration, a
+ * cache-based scan, or some other kind of logic we haven't dreamed up yet.
+ *
+ * CustomPaths can be injected into the planning process for a relation by
+ * set_rel_pathlist_hook functions.
+ *
+ * Core code must avoid assuming that the CustomPath is only as large as
+ * the structure declared here; providers are allowed to make it the first
+ * element in a larger structure. (Since the planner never copies Paths,
+ * this doesn't add any complication.) However, for consistency with the
+ * FDW case, we provide a "custom_private" field in CustomPath; providers
+ * may prefer to use that rather than define another struct type.
+ */
+
+struct CustomPathMethods;
+
+typedef struct CustomPath
+{
+ Path path;
+ uint32 flags; /* mask of CUSTOMPATH_* flags, see
+ * nodes/extensible.h */
+ List *custom_paths; /* list of child Path nodes, if any */
+ List *custom_private;
+ const struct CustomPathMethods *methods;
+} CustomPath;
+
+/*
+ * AppendPath represents an Append plan, ie, successive execution of
+ * several member plans.
+ *
+ * For partial Append, 'subpaths' contains non-partial subpaths followed by
+ * partial subpaths.
+ *
+ * Note: it is possible for "subpaths" to contain only one, or even no,
+ * elements. These cases are optimized during create_append_plan.
+ * In particular, an AppendPath with no subpaths is a "dummy" path that
+ * is created to represent the case that a relation is provably empty.
+ * (This is a convenient representation because it means that when we build
+ * an appendrel and find that all its children have been excluded, no extra
+ * action is needed to recognize the relation as dummy.)
+ */
+typedef struct AppendPath
+{
+ Path path;
+ /* RT indexes of non-leaf tables in a partition tree */
+ List *partitioned_rels;
+ List *subpaths; /* list of component Paths */
+ /* Index of first partial path in subpaths; list_length(subpaths) if none */
+ int first_partial_path;
+ double limit_tuples; /* hard limit on output tuples, or -1 */
+} AppendPath;
+
+#define IS_DUMMY_APPEND(p) \
+ (IsA((p), AppendPath) && ((AppendPath *) (p))->subpaths == NIL)
+
+/*
+ * A relation that's been proven empty will have one path that is dummy
+ * (but might have projection paths on top). For historical reasons,
+ * this is provided as a macro that wraps is_dummy_rel().
+ */
+#define IS_DUMMY_REL(r) is_dummy_rel(r)
+extern bool is_dummy_rel(RelOptInfo *rel);
+
+/*
+ * MergeAppendPath represents a MergeAppend plan, ie, the merging of sorted
+ * results from several member plans to produce similarly-sorted output.
+ */
+typedef struct MergeAppendPath
+{
+ Path path;
+ /* RT indexes of non-leaf tables in a partition tree */
+ List *partitioned_rels;
+ List *subpaths; /* list of component Paths */
+ double limit_tuples; /* hard limit on output tuples, or -1 */
+} MergeAppendPath;
+
+/*
+ * GroupResultPath represents use of a Result plan node to compute the
+ * output of a degenerate GROUP BY case, wherein we know we should produce
+ * exactly one row, which might then be filtered by a HAVING qual.
+ *
+ * Note that quals is a list of bare clauses, not RestrictInfos.
+ */
+typedef struct GroupResultPath
+{
+ Path path;
+ List *quals;
+} GroupResultPath;
+
+/*
+ * MaterialPath represents use of a Material plan node, i.e., caching of
+ * the output of its subpath. This is used when the subpath is expensive
+ * and needs to be scanned repeatedly, or when we need mark/restore ability
+ * and the subpath doesn't have it.
+ */
+typedef struct MaterialPath
+{
+ Path path;
+ Path *subpath;
+} MaterialPath;
+
+/*
+ * UniquePath represents elimination of distinct rows from the output of
+ * its subpath.
+ *
+ * This can represent significantly different plans: either hash-based or
+ * sort-based implementation, or a no-op if the input path can be proven
+ * distinct already. The decision is sufficiently localized that it's not
+ * worth having separate Path node types. (Note: in the no-op case, we could
+ * eliminate the UniquePath node entirely and just return the subpath; but
+ * it's convenient to have a UniquePath in the path tree to signal upper-level
+ * routines that the input is known distinct.)
+ */
+typedef enum
+{
+ UNIQUE_PATH_NOOP, /* input is known unique already */
+ UNIQUE_PATH_HASH, /* use hashing */
+ UNIQUE_PATH_SORT /* use sorting */
+} UniquePathMethod;
+
+typedef struct UniquePath
+{
+ Path path;
+ Path *subpath;
+ UniquePathMethod umethod;
+ List *in_operators; /* equality operators of the IN clause */
+ List *uniq_exprs; /* expressions to be made unique */
+} UniquePath;
+
+/*
+ * GatherPath runs several copies of a plan in parallel and collects the
+ * results. The parallel leader may also execute the plan, unless the
+ * single_copy flag is set.
+ */
+typedef struct GatherPath
+{
+ Path path;
+ Path *subpath; /* path for each worker */
+ bool single_copy; /* don't execute path more than once */
+ int num_workers; /* number of workers sought to help */
+} GatherPath;
+
+/*
+ * GatherMergePath runs several copies of a plan in parallel and collects
+ * the results, preserving their common sort order.
+ */
+typedef struct GatherMergePath
+{
+ Path path;
+ Path *subpath; /* path for each worker */
+ int num_workers; /* number of workers sought to help */
+} GatherMergePath;
+
+
+/*
+ * All join-type paths share these fields.
+ */
+
+typedef struct JoinPath
+{
+ Path path;
+
+ JoinType jointype;
+
+ bool inner_unique; /* each outer tuple provably matches no more
+ * than one inner tuple */
+
+ Path *outerjoinpath; /* path for the outer side of the join */
+ Path *innerjoinpath; /* path for the inner side of the join */
+
+ List *joinrestrictinfo; /* RestrictInfos to apply to join */
+
+ /*
+ * See the notes for RelOptInfo and ParamPathInfo to understand why
+ * joinrestrictinfo is needed in JoinPath, and can't be merged into the
+ * parent RelOptInfo.
+ */
+} JoinPath;
+
+/*
+ * A nested-loop path needs no special fields.
+ */
+
+typedef JoinPath NestPath;
+
+/*
+ * A mergejoin path has these fields.
+ *
+ * Unlike other path types, a MergePath node doesn't represent just a single
+ * run-time plan node: it can represent up to four. Aside from the MergeJoin
+ * node itself, there can be a Sort node for the outer input, a Sort node
+ * for the inner input, and/or a Material node for the inner input. We could
+ * represent these nodes by separate path nodes, but considering how many
+ * different merge paths are investigated during a complex join problem,
+ * it seems better to avoid unnecessary palloc overhead.
+ *
+ * path_mergeclauses lists the clauses (in the form of RestrictInfos)
+ * that will be used in the merge.
+ *
+ * Note that the mergeclauses are a subset of the parent relation's
+ * restriction-clause list. Any join clauses that are not mergejoinable
+ * appear only in the parent's restrict list, and must be checked by a
+ * qpqual at execution time.
+ *
+ * outersortkeys (resp. innersortkeys) is NIL if the outer path
+ * (resp. inner path) is already ordered appropriately for the
+ * mergejoin. If it is not NIL then it is a PathKeys list describing
+ * the ordering that must be created by an explicit Sort node.
+ *
+ * skip_mark_restore is true if the executor need not do mark/restore calls.
+ * Mark/restore overhead is usually required, but can be skipped if we know
+ * that the executor need find only one match per outer tuple, and that the
+ * mergeclauses are sufficient to identify a match. In such cases the
+ * executor can immediately advance the outer relation after processing a
+ * match, and therefore it need never back up the inner relation.
+ *
+ * materialize_inner is true if a Material node should be placed atop the
+ * inner input. This may appear with or without an inner Sort step.
+ */
+
+typedef struct MergePath
+{
+ JoinPath jpath;
+ List *path_mergeclauses; /* join clauses to be used for merge */
+ List *outersortkeys; /* keys for explicit sort, if any */
+ List *innersortkeys; /* keys for explicit sort, if any */
+ bool skip_mark_restore; /* can executor skip mark/restore? */
+ bool materialize_inner; /* add Materialize to inner? */
+} MergePath;
+
+/*
+ * A hashjoin path has these fields.
+ *
+ * The remarks above for mergeclauses apply for hashclauses as well.
+ *
+ * Hashjoin does not care what order its inputs appear in, so we have
+ * no need for sortkeys.
+ */
+
+typedef struct HashPath
+{
+ JoinPath jpath;
+ List *path_hashclauses; /* join clauses used for hashing */
+ int num_batches; /* number of batches expected */
+ double inner_rows_total; /* total inner rows expected */
+} HashPath;
+
+/*
+ * ProjectionPath represents a projection (that is, targetlist computation)
+ *
+ * Nominally, this path node represents using a Result plan node to do a
+ * projection step. However, if the input plan node supports projection,
+ * we can just modify its output targetlist to do the required calculations
+ * directly, and not need a Result. In some places in the planner we can just
+ * jam the desired PathTarget into the input path node (and adjust its cost
+ * accordingly), so we don't need a ProjectionPath. But in other places
+ * it's necessary to not modify the input path node, so we need a separate
+ * ProjectionPath node, which is marked dummy to indicate that we intend to
+ * assign the work to the input plan node. The estimated cost for the
+ * ProjectionPath node will account for whether a Result will be used or not.
+ */
+typedef struct ProjectionPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+ bool dummypp; /* true if no separate Result is needed */
+} ProjectionPath;
+
+/*
+ * ProjectSetPath represents evaluation of a targetlist that includes
+ * set-returning function(s), which will need to be implemented by a
+ * ProjectSet plan node.
+ */
+typedef struct ProjectSetPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+} ProjectSetPath;
+
+/*
+ * SortPath represents an explicit sort step
+ *
+ * The sort keys are, by definition, the same as path.pathkeys.
+ *
+ * Note: the Sort plan node cannot project, so path.pathtarget must be the
+ * same as the input's pathtarget.
+ */
+typedef struct SortPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+} SortPath;
+
+/*
+ * IncrementalSortPath represents an incremental sort step
+ *
+ * This is like a regular sort, except some leading key columns are assumed
+ * to be ordered already.
+ */
+typedef struct IncrementalSortPath
+{
+ SortPath spath;
+ int nPresortedCols; /* number of presorted columns */
+} IncrementalSortPath;
+
+/*
+ * GroupPath represents grouping (of presorted input)
+ *
+ * groupClause represents the columns to be grouped on; the input path
+ * must be at least that well sorted.
+ *
+ * We can also apply a qual to the grouped rows (equivalent of HAVING)
+ */
+typedef struct GroupPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+ List *groupClause; /* a list of SortGroupClause's */
+ List *qual; /* quals (HAVING quals), if any */
+} GroupPath;
+
+/*
+ * UpperUniquePath represents adjacent-duplicate removal (in presorted input)
+ *
+ * The columns to be compared are the first numkeys columns of the path's
+ * pathkeys. The input is presumed already sorted that way.
+ */
+typedef struct UpperUniquePath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+ int numkeys; /* number of pathkey columns to compare */
+} UpperUniquePath;
+
+/*
+ * AggPath represents generic computation of aggregate functions
+ *
+ * This may involve plain grouping (but not grouping sets), using either
+ * sorted or hashed grouping; for the AGG_SORTED case, the input must be
+ * appropriately presorted.
+ */
+typedef struct AggPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+ AggStrategy aggstrategy; /* basic strategy, see nodes.h */
+ AggSplit aggsplit; /* agg-splitting mode, see nodes.h */
+ double numGroups; /* estimated number of groups in input */
+ uint64 transitionSpace; /* for pass-by-ref transition data */
+ List *groupClause; /* a list of SortGroupClause's */
+ List *qual; /* quals (HAVING quals), if any */
+} AggPath;
+
+/*
+ * Various annotations used for grouping sets in the planner.
+ */
+
+typedef struct GroupingSetData
+{
+ NodeTag type;
+ List *set; /* grouping set as list of sortgrouprefs */
+ double numGroups; /* est. number of result groups */
+} GroupingSetData;
+
+typedef struct RollupData
+{
+ NodeTag type;
+ List *groupClause; /* applicable subset of parse->groupClause */
+ List *gsets; /* lists of integer indexes into groupClause */
+ List *gsets_data; /* list of GroupingSetData */
+ double numGroups; /* est. number of result groups */
+ bool hashable; /* can be hashed */
+ bool is_hashed; /* to be implemented as a hashagg */
+} RollupData;
+
+/*
+ * GroupingSetsPath represents a GROUPING SETS aggregation
+ */
+
+typedef struct GroupingSetsPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+ AggStrategy aggstrategy; /* basic strategy */
+ List *rollups; /* list of RollupData */
+ List *qual; /* quals (HAVING quals), if any */
+ uint64 transitionSpace; /* for pass-by-ref transition data */
+} GroupingSetsPath;
+
+/*
+ * MinMaxAggPath represents computation of MIN/MAX aggregates from indexes
+ */
+typedef struct MinMaxAggPath
+{
+ Path path;
+ List *mmaggregates; /* list of MinMaxAggInfo */
+ List *quals; /* HAVING quals, if any */
+} MinMaxAggPath;
+
+/*
+ * WindowAggPath represents generic computation of window functions
+ */
+typedef struct WindowAggPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+ WindowClause *winclause; /* WindowClause we'll be using */
+} WindowAggPath;
+
+/*
+ * SetOpPath represents a set-operation, that is INTERSECT or EXCEPT
+ */
+typedef struct SetOpPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+ SetOpCmd cmd; /* what to do, see nodes.h */
+ SetOpStrategy strategy; /* how to do it, see nodes.h */
+ List *distinctList; /* SortGroupClauses identifying target cols */
+ AttrNumber flagColIdx; /* where is the flag column, if any */
+ int firstFlag; /* flag value for first input relation */
+ double numGroups; /* estimated number of groups in input */
+} SetOpPath;
+
+/*
+ * RecursiveUnionPath represents a recursive UNION node
+ */
+typedef struct RecursiveUnionPath
+{
+ Path path;
+ Path *leftpath; /* paths representing input sources */
+ Path *rightpath;
+ List *distinctList; /* SortGroupClauses identifying target cols */
+ int wtParam; /* ID of Param representing work table */
+ double numGroups; /* estimated number of groups in input */
+} RecursiveUnionPath;
+
+/*
+ * LockRowsPath represents acquiring row locks for SELECT FOR UPDATE/SHARE
+ */
+typedef struct LockRowsPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+ List *rowMarks; /* a list of PlanRowMark's */
+ int epqParam; /* ID of Param for EvalPlanQual re-eval */
+} LockRowsPath;
+
+/*
+ * ModifyTablePath represents performing INSERT/UPDATE/DELETE modifications
+ *
+ * We represent most things that will be in the ModifyTable plan node
+ * literally, except we have child Path(s) not Plan(s). But analysis of the
+ * OnConflictExpr is deferred to createplan.c, as is collection of FDW data.
+ */
+typedef struct ModifyTablePath
+{
+ Path path;
+ CmdType operation; /* INSERT, UPDATE, or DELETE */
+ bool canSetTag; /* do we set the command tag/es_processed? */
+ Index nominalRelation; /* Parent RT index for use of EXPLAIN */
+ Index rootRelation; /* Root RT index, if target is partitioned */
+ bool partColsUpdated; /* some part key in hierarchy updated */
+ List *resultRelations; /* integer list of RT indexes */
+ List *subpaths; /* Path(s) producing source data */
+ List *subroots; /* per-target-table PlannerInfos */
+ List *withCheckOptionLists; /* per-target-table WCO lists */
+ List *returningLists; /* per-target-table RETURNING tlists */
+ List *rowMarks; /* PlanRowMarks (non-locking only) */
+ OnConflictExpr *onconflict; /* ON CONFLICT clause, or NULL */
+ int epqParam; /* ID of Param for EvalPlanQual re-eval */
+} ModifyTablePath;
+
+/*
+ * LimitPath represents applying LIMIT/OFFSET restrictions
+ */
+typedef struct LimitPath
+{
+ Path path;
+ Path *subpath; /* path representing input source */
+ Node *limitOffset; /* OFFSET parameter, or NULL if none */
+ Node *limitCount; /* COUNT parameter, or NULL if none */
+ LimitOption limitOption; /* FETCH FIRST with ties or exact number */
+} LimitPath;
+
+
+/*
+ * Restriction clause info.
+ *
+ * We create one of these for each AND sub-clause of a restriction condition
+ * (WHERE or JOIN/ON clause). Since the restriction clauses are logically
+ * ANDed, we can use any one of them or any subset of them to filter out
+ * tuples, without having to evaluate the rest. The RestrictInfo node itself
+ * stores data used by the optimizer while choosing the best query plan.
+ *
+ * If a restriction clause references a single base relation, it will appear
+ * in the baserestrictinfo list of the RelOptInfo for that base rel.
+ *
+ * If a restriction clause references more than one base rel, it will
+ * appear in the joininfo list of every RelOptInfo that describes a strict
+ * subset of the base rels mentioned in the clause. The joininfo lists are
+ * used to drive join tree building by selecting plausible join candidates.
+ * The clause cannot actually be applied until we have built a join rel
+ * containing all the base rels it references, however.
+ *
+ * When we construct a join rel that includes all the base rels referenced
+ * in a multi-relation restriction clause, we place that clause into the
+ * joinrestrictinfo lists of paths for the join rel, if neither left nor
+ * right sub-path includes all base rels referenced in the clause. The clause
+ * will be applied at that join level, and will not propagate any further up
+ * the join tree. (Note: the "predicate migration" code was once intended to
+ * push restriction clauses up and down the plan tree based on evaluation
+ * costs, but it's dead code and is unlikely to be resurrected in the
+ * foreseeable future.)
+ *
+ * Note that in the presence of more than two rels, a multi-rel restriction
+ * might reach different heights in the join tree depending on the join
+ * sequence we use. So, these clauses cannot be associated directly with
+ * the join RelOptInfo, but must be kept track of on a per-join-path basis.
+ *
+ * RestrictInfos that represent equivalence conditions (i.e., mergejoinable
+ * equalities that are not outerjoin-delayed) are handled a bit differently.
+ * Initially we attach them to the EquivalenceClasses that are derived from
+ * them. When we construct a scan or join path, we look through all the
+ * EquivalenceClasses and generate derived RestrictInfos representing the
+ * minimal set of conditions that need to be checked for this particular scan
+ * or join to enforce that all members of each EquivalenceClass are in fact
+ * equal in all rows emitted by the scan or join.
+ *
+ * When dealing with outer joins we have to be very careful about pushing qual
+ * clauses up and down the tree. An outer join's own JOIN/ON conditions must
+ * be evaluated exactly at that join node, unless they are "degenerate"
+ * conditions that reference only Vars from the nullable side of the join.
+ * Quals appearing in WHERE or in a JOIN above the outer join cannot be pushed
+ * down below the outer join, if they reference any nullable Vars.
+ * RestrictInfo nodes contain a flag to indicate whether a qual has been
+ * pushed down to a lower level than its original syntactic placement in the
+ * join tree would suggest. If an outer join prevents us from pushing a qual
+ * down to its "natural" semantic level (the level associated with just the
+ * base rels used in the qual) then we mark the qual with a "required_relids"
+ * value including more than just the base rels it actually uses. By
+ * pretending that the qual references all the rels required to form the outer
+ * join, we prevent it from being evaluated below the outer join's joinrel.
+ * When we do form the outer join's joinrel, we still need to distinguish
+ * those quals that are actually in that join's JOIN/ON condition from those
+ * that appeared elsewhere in the tree and were pushed down to the join rel
+ * because they used no other rels. That's what the is_pushed_down flag is
+ * for; it tells us that a qual is not an OUTER JOIN qual for the set of base
+ * rels listed in required_relids. A clause that originally came from WHERE
+ * or an INNER JOIN condition will *always* have its is_pushed_down flag set.
+ * It's possible for an OUTER JOIN clause to be marked is_pushed_down too,
+ * if we decide that it can be pushed down into the nullable side of the join.
+ * In that case it acts as a plain filter qual for wherever it gets evaluated.
+ * (In short, is_pushed_down is only false for non-degenerate outer join
+ * conditions. Possibly we should rename it to reflect that meaning? But
+ * see also the comments for RINFO_IS_PUSHED_DOWN, below.)
+ *
+ * RestrictInfo nodes also contain an outerjoin_delayed flag, which is true
+ * if the clause's applicability must be delayed due to any outer joins
+ * appearing below it (ie, it has to be postponed to some join level higher
+ * than the set of relations it actually references).
+ *
+ * There is also an outer_relids field, which is NULL except for outer join
+ * clauses; for those, it is the set of relids on the outer side of the
+ * clause's outer join. (These are rels that the clause cannot be applied to
+ * in parameterized scans, since pushing it into the join's outer side would
+ * lead to wrong answers.)
+ *
+ * There is also a nullable_relids field, which is the set of rels the clause
+ * references that can be forced null by some outer join below the clause.
+ *
+ * outerjoin_delayed = true is subtly different from nullable_relids != NULL:
+ * a clause might reference some nullable rels and yet not be
+ * outerjoin_delayed because it also references all the other rels of the
+ * outer join(s). A clause that is not outerjoin_delayed can be enforced
+ * anywhere it is computable.
+ *
+ * To handle security-barrier conditions efficiently, we mark RestrictInfo
+ * nodes with a security_level field, in which higher values identify clauses
+ * coming from less-trusted sources. The exact semantics are that a clause
+ * cannot be evaluated before another clause with a lower security_level value
+ * unless the first clause is leakproof. As with outer-join clauses, this
+ * creates a reason for clauses to sometimes need to be evaluated higher in
+ * the join tree than their contents would suggest; and even at a single plan
+ * node, this rule constrains the order of application of clauses.
+ *
+ * In general, the referenced clause might be arbitrarily complex. The
+ * kinds of clauses we can handle as indexscan quals, mergejoin clauses,
+ * or hashjoin clauses are limited (e.g., no volatile functions). The code
+ * for each kind of path is responsible for identifying the restrict clauses
+ * it can use and ignoring the rest. Clauses not implemented by an indexscan,
+ * mergejoin, or hashjoin will be placed in the plan qual or joinqual field
+ * of the finished Plan node, where they will be enforced by general-purpose
+ * qual-expression-evaluation code. (But we are still entitled to count
+ * their selectivity when estimating the result tuple count, if we
+ * can guess what it is...)
+ *
+ * When the referenced clause is an OR clause, we generate a modified copy
+ * in which additional RestrictInfo nodes are inserted below the top-level
+ * OR/AND structure. This is a convenience for OR indexscan processing:
+ * indexquals taken from either the top level or an OR subclause will have
+ * associated RestrictInfo nodes.
+ *
+ * The can_join flag is set true if the clause looks potentially useful as
+ * a merge or hash join clause, that is if it is a binary opclause with
+ * nonoverlapping sets of relids referenced in the left and right sides.
+ * (Whether the operator is actually merge or hash joinable isn't checked,
+ * however.)
+ *
+ * The pseudoconstant flag is set true if the clause contains no Vars of
+ * the current query level and no volatile functions. Such a clause can be
+ * pulled out and used as a one-time qual in a gating Result node. We keep
+ * pseudoconstant clauses in the same lists as other RestrictInfos so that
+ * the regular clause-pushing machinery can assign them to the correct join
+ * level, but they need to be treated specially for cost and selectivity
+ * estimates. Note that a pseudoconstant clause can never be an indexqual
+ * or merge or hash join clause, so it's of no interest to large parts of
+ * the planner.
+ *
+ * When join clauses are generated from EquivalenceClasses, there may be
+ * several equally valid ways to enforce join equivalence, of which we need
+ * apply only one. We mark clauses of this kind by setting parent_ec to
+ * point to the generating EquivalenceClass. Multiple clauses with the same
+ * parent_ec in the same join are redundant.
+ */
+
+typedef struct RestrictInfo
+{
+ NodeTag type;
+
+ Expr *clause; /* the represented clause of WHERE or JOIN */
+
+ bool is_pushed_down; /* true if clause was pushed down in level */
+
+ bool outerjoin_delayed; /* true if delayed by lower outer join */
+
+ bool can_join; /* see comment above */
+
+ bool pseudoconstant; /* see comment above */
+
+ bool leakproof; /* true if known to contain no leaked Vars */
+
+ Index security_level; /* see comment above */
+
+ /* The set of relids (varnos) actually referenced in the clause: */
+ Relids clause_relids;
+
+ /* The set of relids required to evaluate the clause: */
+ Relids required_relids;
+
+ /* If an outer-join clause, the outer-side relations, else NULL: */
+ Relids outer_relids;
+
+ /* The relids used in the clause that are nullable by lower outer joins: */
+ Relids nullable_relids;
+
+ /* These fields are set for any binary opclause: */
+ Relids left_relids; /* relids in left side of clause */
+ Relids right_relids; /* relids in right side of clause */
+
+ /* This field is NULL unless clause is an OR clause: */
+ Expr *orclause; /* modified clause with RestrictInfos */
+
+ /* This field is NULL unless clause is potentially redundant: */
+ EquivalenceClass *parent_ec; /* generating EquivalenceClass */
+
+ /* cache space for cost and selectivity */
+ QualCost eval_cost; /* eval cost of clause; -1 if not yet set */
+ Selectivity norm_selec; /* selectivity for "normal" (JOIN_INNER)
+ * semantics; -1 if not yet set; >1 means a
+ * redundant clause */
+ Selectivity outer_selec; /* selectivity for outer join semantics; -1 if
+ * not yet set */
+
+ /* valid if clause is mergejoinable, else NIL */
+ List *mergeopfamilies; /* opfamilies containing clause operator */
+
+ /* cache space for mergeclause processing; NULL if not yet set */
+ EquivalenceClass *left_ec; /* EquivalenceClass containing lefthand */
+ EquivalenceClass *right_ec; /* EquivalenceClass containing righthand */
+ EquivalenceMember *left_em; /* EquivalenceMember for lefthand */
+ EquivalenceMember *right_em; /* EquivalenceMember for righthand */
+ List *scansel_cache; /* list of MergeScanSelCache structs */
+
+ /* transient workspace for use while considering a specific join path */
+ bool outer_is_left; /* T = outer var on left, F = on right */
+
+ /* valid if clause is hashjoinable, else InvalidOid: */
+ Oid hashjoinoperator; /* copy of clause operator */
+
+ /* cache space for hashclause processing; -1 if not yet set */
+ Selectivity left_bucketsize; /* avg bucketsize of left side */
+ Selectivity right_bucketsize; /* avg bucketsize of right side */
+ Selectivity left_mcvfreq; /* left side's most common val's freq */
+ Selectivity right_mcvfreq; /* right side's most common val's freq */
+} RestrictInfo;
+
+/*
+ * This macro embodies the correct way to test whether a RestrictInfo is
+ * "pushed down" to a given outer join, that is, should be treated as a filter
+ * clause rather than a join clause at that outer join. This is certainly so
+ * if is_pushed_down is true; but examining that is not sufficient anymore,
+ * because outer-join clauses will get pushed down to lower outer joins when
+ * we generate a path for the lower outer join that is parameterized by the
+ * LHS of the upper one. We can detect such a clause by noting that its
+ * required_relids exceed the scope of the join.
+ */
+#define RINFO_IS_PUSHED_DOWN(rinfo, joinrelids) \
+ ((rinfo)->is_pushed_down || \
+ !bms_is_subset((rinfo)->required_relids, joinrelids))
+
+/*
+ * Since mergejoinscansel() is a relatively expensive function, and would
+ * otherwise be invoked many times while planning a large join tree,
+ * we go out of our way to cache its results. Each mergejoinable
+ * RestrictInfo carries a list of the specific sort orderings that have
+ * been considered for use with it, and the resulting selectivities.
+ */
+typedef struct MergeScanSelCache
+{
+ /* Ordering details (cache lookup key) */
+ Oid opfamily; /* btree opfamily defining the ordering */
+ Oid collation; /* collation for the ordering */
+ int strategy; /* sort direction (ASC or DESC) */
+ bool nulls_first; /* do NULLs come before normal values? */
+ /* Results */
+ Selectivity leftstartsel; /* first-join fraction for clause left side */
+ Selectivity leftendsel; /* last-join fraction for clause left side */
+ Selectivity rightstartsel; /* first-join fraction for clause right side */
+ Selectivity rightendsel; /* last-join fraction for clause right side */
+} MergeScanSelCache;
+
+/*
+ * Placeholder node for an expression to be evaluated below the top level
+ * of a plan tree. This is used during planning to represent the contained
+ * expression. At the end of the planning process it is replaced by either
+ * the contained expression or a Var referring to a lower-level evaluation of
+ * the contained expression. Typically the evaluation occurs below an outer
+ * join, and Var references above the outer join might thereby yield NULL
+ * instead of the expression value.
+ *
+ * Although the planner treats this as an expression node type, it is not
+ * recognized by the parser or executor, so we declare it here rather than
+ * in primnodes.h.
+ */
+
+typedef struct PlaceHolderVar
+{
+ Expr xpr;
+ Expr *phexpr; /* the represented expression */
+ Relids phrels; /* base relids syntactically within expr src */
+ Index phid; /* ID for PHV (unique within planner run) */
+ Index phlevelsup; /* > 0 if PHV belongs to outer query */
+} PlaceHolderVar;
+
+/*
+ * "Special join" info.
+ *
+ * One-sided outer joins constrain the order of joining partially but not
+ * completely. We flatten such joins into the planner's top-level list of
+ * relations to join, but record information about each outer join in a
+ * SpecialJoinInfo struct. These structs are kept in the PlannerInfo node's
+ * join_info_list.
+ *
+ * Similarly, semijoins and antijoins created by flattening IN (subselect)
+ * and EXISTS(subselect) clauses create partial constraints on join order.
+ * These are likewise recorded in SpecialJoinInfo structs.
+ *
+ * We make SpecialJoinInfos for FULL JOINs even though there is no flexibility
+ * of planning for them, because this simplifies make_join_rel()'s API.
+ *
+ * min_lefthand and min_righthand are the sets of base relids that must be
+ * available on each side when performing the special join. lhs_strict is
+ * true if the special join's condition cannot succeed when the LHS variables
+ * are all NULL (this means that an outer join can commute with upper-level
+ * outer joins even if it appears in their RHS). We don't bother to set
+ * lhs_strict for FULL JOINs, however.
+ *
+ * It is not valid for either min_lefthand or min_righthand to be empty sets;
+ * if they were, this would break the logic that enforces join order.
+ *
+ * syn_lefthand and syn_righthand are the sets of base relids that are
+ * syntactically below this special join. (These are needed to help compute
+ * min_lefthand and min_righthand for higher joins.)
+ *
+ * delay_upper_joins is set true if we detect a pushed-down clause that has
+ * to be evaluated after this join is formed (because it references the RHS).
+ * Any outer joins that have such a clause and this join in their RHS cannot
+ * commute with this join, because that would leave noplace to check the
+ * pushed-down clause. (We don't track this for FULL JOINs, either.)
+ *
+ * For a semijoin, we also extract the join operators and their RHS arguments
+ * and set semi_operators, semi_rhs_exprs, semi_can_btree, and semi_can_hash.
+ * This is done in support of possibly unique-ifying the RHS, so we don't
+ * bother unless at least one of semi_can_btree and semi_can_hash can be set
+ * true. (You might expect that this information would be computed during
+ * join planning; but it's helpful to have it available during planning of
+ * parameterized table scans, so we store it in the SpecialJoinInfo structs.)
+ *
+ * jointype is never JOIN_RIGHT; a RIGHT JOIN is handled by switching
+ * the inputs to make it a LEFT JOIN. So the allowed values of jointype
+ * in a join_info_list member are only LEFT, FULL, SEMI, or ANTI.
+ *
+ * For purposes of join selectivity estimation, we create transient
+ * SpecialJoinInfo structures for regular inner joins; so it is possible
+ * to have jointype == JOIN_INNER in such a structure, even though this is
+ * not allowed within join_info_list. We also create transient
+ * SpecialJoinInfos with jointype == JOIN_INNER for outer joins, since for
+ * cost estimation purposes it is sometimes useful to know the join size under
+ * plain innerjoin semantics. Note that lhs_strict, delay_upper_joins, and
+ * of course the semi_xxx fields are not set meaningfully within such structs.
+ */
+#ifndef HAVE_SPECIALJOININFO_TYPEDEF
+typedef struct SpecialJoinInfo SpecialJoinInfo;
+#define HAVE_SPECIALJOININFO_TYPEDEF 1
+#endif
+
+struct SpecialJoinInfo
+{
+ NodeTag type;
+ Relids min_lefthand; /* base relids in minimum LHS for join */
+ Relids min_righthand; /* base relids in minimum RHS for join */
+ Relids syn_lefthand; /* base relids syntactically within LHS */
+ Relids syn_righthand; /* base relids syntactically within RHS */
+ JoinType jointype; /* always INNER, LEFT, FULL, SEMI, or ANTI */
+ bool lhs_strict; /* joinclause is strict for some LHS rel */
+ bool delay_upper_joins; /* can't commute with upper RHS */
+ /* Remaining fields are set only for JOIN_SEMI jointype: */
+ bool semi_can_btree; /* true if semi_operators are all btree */
+ bool semi_can_hash; /* true if semi_operators are all hash */
+ List *semi_operators; /* OIDs of equality join operators */
+ List *semi_rhs_exprs; /* righthand-side expressions of these ops */
+};
+
+/*
+ * Append-relation info.
+ *
+ * When we expand an inheritable table or a UNION-ALL subselect into an
+ * "append relation" (essentially, a list of child RTEs), we build an
+ * AppendRelInfo for each child RTE. The list of AppendRelInfos indicates
+ * which child RTEs must be included when expanding the parent, and each node
+ * carries information needed to translate between columns of the parent and
+ * columns of the child.
+ *
+ * These structs are kept in the PlannerInfo node's append_rel_list, with
+ * append_rel_array[] providing a convenient lookup method for the struct
+ * associated with a particular child relid (there can be only one, though
+ * parent rels may have many entries in append_rel_list).
+ *
+ * Note: after completion of the planner prep phase, any given RTE is an
+ * append parent having entries in append_rel_list if and only if its
+ * "inh" flag is set. We clear "inh" for plain tables that turn out not
+ * to have inheritance children, and (in an abuse of the original meaning
+ * of the flag) we set "inh" for subquery RTEs that turn out to be
+ * flattenable UNION ALL queries. This lets us avoid useless searches
+ * of append_rel_list.
+ *
+ * Note: the data structure assumes that append-rel members are single
+ * baserels. This is OK for inheritance, but it prevents us from pulling
+ * up a UNION ALL member subquery if it contains a join. While that could
+ * be fixed with a more complex data structure, at present there's not much
+ * point because no improvement in the plan could result.
+ */
+
+typedef struct AppendRelInfo
+{
+ NodeTag type;
+
+ /*
+ * These fields uniquely identify this append relationship. There can be
+ * (in fact, always should be) multiple AppendRelInfos for the same
+ * parent_relid, but never more than one per child_relid, since a given
+ * RTE cannot be a child of more than one append parent.
+ */
+ Index parent_relid; /* RT index of append parent rel */
+ Index child_relid; /* RT index of append child rel */
+
+ /*
+ * For an inheritance appendrel, the parent and child are both regular
+ * relations, and we store their rowtype OIDs here for use in translating
+ * whole-row Vars. For a UNION-ALL appendrel, the parent and child are
+ * both subqueries with no named rowtype, and we store InvalidOid here.
+ */
+ Oid parent_reltype; /* OID of parent's composite type */
+ Oid child_reltype; /* OID of child's composite type */
+
+ /*
+ * The N'th element of this list is a Var or expression representing the
+ * child column corresponding to the N'th column of the parent. This is
+ * used to translate Vars referencing the parent rel into references to
+ * the child. A list element is NULL if it corresponds to a dropped
+ * column of the parent (this is only possible for inheritance cases, not
+ * UNION ALL). The list elements are always simple Vars for inheritance
+ * cases, but can be arbitrary expressions in UNION ALL cases.
+ *
+ * Notice we only store entries for user columns (attno > 0). Whole-row
+ * Vars are special-cased, and system columns (attno < 0) need no special
+ * translation since their attnos are the same for all tables.
+ *
+ * Caution: the Vars have varlevelsup = 0. Be careful to adjust as needed
+ * when copying into a subquery.
+ */
+ List *translated_vars; /* Expressions in the child's Vars */
+
+ /*
+ * This array simplifies translations in the reverse direction, from
+ * child's column numbers to parent's. The entry at [ccolno - 1] is the
+ * 1-based parent column number for child column ccolno, or zero if that
+ * child column is dropped or doesn't exist in the parent.
+ */
+ int num_child_cols; /* length of array */
+ AttrNumber *parent_colnos; /* array of parent attnos, or zeroes */
+
+ /*
+ * We store the parent table's OID here for inheritance, or InvalidOid for
+ * UNION ALL. This is only needed to help in generating error messages if
+ * an attempt is made to reference a dropped parent column.
+ */
+ Oid parent_reloid; /* OID of parent relation */
+} AppendRelInfo;
+
+/*
+ * For each distinct placeholder expression generated during planning, we
+ * store a PlaceHolderInfo node in the PlannerInfo node's placeholder_list.
+ * This stores info that is needed centrally rather than in each copy of the
+ * PlaceHolderVar. The phid fields identify which PlaceHolderInfo goes with
+ * each PlaceHolderVar. Note that phid is unique throughout a planner run,
+ * not just within a query level --- this is so that we need not reassign ID's
+ * when pulling a subquery into its parent.
+ *
+ * The idea is to evaluate the expression at (only) the ph_eval_at join level,
+ * then allow it to bubble up like a Var until the ph_needed join level.
+ * ph_needed has the same definition as attr_needed for a regular Var.
+ *
+ * The PlaceHolderVar's expression might contain LATERAL references to vars
+ * coming from outside its syntactic scope. If so, those rels are *not*
+ * included in ph_eval_at, but they are recorded in ph_lateral.
+ *
+ * Notice that when ph_eval_at is a join rather than a single baserel, the
+ * PlaceHolderInfo may create constraints on join order: the ph_eval_at join
+ * has to be formed below any outer joins that should null the PlaceHolderVar.
+ *
+ * We create a PlaceHolderInfo only after determining that the PlaceHolderVar
+ * is actually referenced in the plan tree, so that unreferenced placeholders
+ * don't result in unnecessary constraints on join order.
+ */
+
+typedef struct PlaceHolderInfo
+{
+ NodeTag type;
+
+ Index phid; /* ID for PH (unique within planner run) */
+ PlaceHolderVar *ph_var; /* copy of PlaceHolderVar tree */
+ Relids ph_eval_at; /* lowest level we can evaluate value at */
+ Relids ph_lateral; /* relids of contained lateral refs, if any */
+ Relids ph_needed; /* highest level the value is needed at */
+ int32 ph_width; /* estimated attribute width */
+} PlaceHolderInfo;
+
+/*
+ * This struct describes one potentially index-optimizable MIN/MAX aggregate
+ * function. MinMaxAggPath contains a list of these, and if we accept that
+ * path, the list is stored into root->minmax_aggs for use during setrefs.c.
+ */
+typedef struct MinMaxAggInfo
+{
+ NodeTag type;
+
+ Oid aggfnoid; /* pg_proc Oid of the aggregate */
+ Oid aggsortop; /* Oid of its sort operator */
+ Expr *target; /* expression we are aggregating on */
+ PlannerInfo *subroot; /* modified "root" for planning the subquery */
+ Path *path; /* access path for subquery */
+ Cost pathcost; /* estimated cost to fetch first row */
+ Param *param; /* param for subplan's output */
+} MinMaxAggInfo;
+
+/*
+ * At runtime, PARAM_EXEC slots are used to pass values around from one plan
+ * node to another. They can be used to pass values down into subqueries (for
+ * outer references in subqueries), or up out of subqueries (for the results
+ * of a subplan), or from a NestLoop plan node into its inner relation (when
+ * the inner scan is parameterized with values from the outer relation).
+ * The planner is responsible for assigning nonconflicting PARAM_EXEC IDs to
+ * the PARAM_EXEC Params it generates.
+ *
+ * Outer references are managed via root->plan_params, which is a list of
+ * PlannerParamItems. While planning a subquery, each parent query level's
+ * plan_params contains the values required from it by the current subquery.
+ * During create_plan(), we use plan_params to track values that must be
+ * passed from outer to inner sides of NestLoop plan nodes.
+ *
+ * The item a PlannerParamItem represents can be one of three kinds:
+ *
+ * A Var: the slot represents a variable of this level that must be passed
+ * down because subqueries have outer references to it, or must be passed
+ * from a NestLoop node to its inner scan. The varlevelsup value in the Var
+ * will always be zero.
+ *
+ * A PlaceHolderVar: this works much like the Var case, except that the
+ * entry is a PlaceHolderVar node with a contained expression. The PHV
+ * will have phlevelsup = 0, and the contained expression is adjusted
+ * to match in level.
+ *
+ * An Aggref (with an expression tree representing its argument): the slot
+ * represents an aggregate expression that is an outer reference for some
+ * subquery. The Aggref itself has agglevelsup = 0, and its argument tree
+ * is adjusted to match in level.
+ *
+ * Note: we detect duplicate Var and PlaceHolderVar parameters and coalesce
+ * them into one slot, but we do not bother to do that for Aggrefs.
+ * The scope of duplicate-elimination only extends across the set of
+ * parameters passed from one query level into a single subquery, or for
+ * nestloop parameters across the set of nestloop parameters used in a single
+ * query level. So there is no possibility of a PARAM_EXEC slot being used
+ * for conflicting purposes.
+ *
+ * In addition, PARAM_EXEC slots are assigned for Params representing outputs
+ * from subplans (values that are setParam items for those subplans). These
+ * IDs need not be tracked via PlannerParamItems, since we do not need any
+ * duplicate-elimination nor later processing of the represented expressions.
+ * Instead, we just record the assignment of the slot number by appending to
+ * root->glob->paramExecTypes.
+ */
+typedef struct PlannerParamItem
+{
+ NodeTag type;
+
+ Node *item; /* the Var, PlaceHolderVar, or Aggref */
+ int paramId; /* its assigned PARAM_EXEC slot number */
+} PlannerParamItem;
+
+/*
+ * When making cost estimates for a SEMI/ANTI/inner_unique join, there are
+ * some correction factors that are needed in both nestloop and hash joins
+ * to account for the fact that the executor can stop scanning inner rows
+ * as soon as it finds a match to the current outer row. These numbers
+ * depend only on the selected outer and inner join relations, not on the
+ * particular paths used for them, so it's worthwhile to calculate them
+ * just once per relation pair not once per considered path. This struct
+ * is filled by compute_semi_anti_join_factors and must be passed along
+ * to the join cost estimation functions.
+ *
+ * outer_match_frac is the fraction of the outer tuples that are
+ * expected to have at least one match.
+ * match_count is the average number of matches expected for
+ * outer tuples that have at least one match.
+ */
+typedef struct SemiAntiJoinFactors
+{
+ Selectivity outer_match_frac;
+ Selectivity match_count;
+} SemiAntiJoinFactors;
+
+/*
+ * Struct for extra information passed to subroutines of add_paths_to_joinrel
+ *
+ * restrictlist contains all of the RestrictInfo nodes for restriction
+ * clauses that apply to this join
+ * mergeclause_list is a list of RestrictInfo nodes for available
+ * mergejoin clauses in this join
+ * inner_unique is true if each outer tuple provably matches no more
+ * than one inner tuple
+ * sjinfo is extra info about special joins for selectivity estimation
+ * semifactors is as shown above (only valid for SEMI/ANTI/inner_unique joins)
+ * param_source_rels are OK targets for parameterization of result paths
+ */
+typedef struct JoinPathExtraData
+{
+ List *restrictlist;
+ List *mergeclause_list;
+ bool inner_unique;
+ SpecialJoinInfo *sjinfo;
+ SemiAntiJoinFactors semifactors;
+ Relids param_source_rels;
+} JoinPathExtraData;
+
+/*
+ * Various flags indicating what kinds of grouping are possible.
+ *
+ * GROUPING_CAN_USE_SORT should be set if it's possible to perform
+ * sort-based implementations of grouping. When grouping sets are in use,
+ * this will be true if sorting is potentially usable for any of the grouping
+ * sets, even if it's not usable for all of them.
+ *
+ * GROUPING_CAN_USE_HASH should be set if it's possible to perform
+ * hash-based implementations of grouping.
+ *
+ * GROUPING_CAN_PARTIAL_AGG should be set if the aggregation is of a type
+ * for which we support partial aggregation (not, for example, grouping sets).
+ * It says nothing about parallel-safety or the availability of suitable paths.
+ */
+#define GROUPING_CAN_USE_SORT 0x0001
+#define GROUPING_CAN_USE_HASH 0x0002
+#define GROUPING_CAN_PARTIAL_AGG 0x0004
+
+/*
+ * What kind of partitionwise aggregation is in use?
+ *
+ * PARTITIONWISE_AGGREGATE_NONE: Not used.
+ *
+ * PARTITIONWISE_AGGREGATE_FULL: Aggregate each partition separately, and
+ * append the results.
+ *
+ * PARTITIONWISE_AGGREGATE_PARTIAL: Partially aggregate each partition
+ * separately, append the results, and then finalize aggregation.
+ */
+typedef enum
+{
+ PARTITIONWISE_AGGREGATE_NONE,
+ PARTITIONWISE_AGGREGATE_FULL,
+ PARTITIONWISE_AGGREGATE_PARTIAL
+} PartitionwiseAggregateType;
+
+/*
+ * Struct for extra information passed to subroutines of create_grouping_paths
+ *
+ * flags indicating what kinds of grouping are possible.
+ * partial_costs_set is true if the agg_partial_costs and agg_final_costs
+ * have been initialized.
+ * agg_partial_costs gives partial aggregation costs.
+ * agg_final_costs gives finalization costs.
+ * target_parallel_safe is true if target is parallel safe.
+ * havingQual gives list of quals to be applied after aggregation.
+ * targetList gives list of columns to be projected.
+ * patype is the type of partitionwise aggregation that is being performed.
+ */
+typedef struct
+{
+ /* Data which remains constant once set. */
+ int flags;
+ bool partial_costs_set;
+ AggClauseCosts agg_partial_costs;
+ AggClauseCosts agg_final_costs;
+
+ /* Data which may differ across partitions. */
+ bool target_parallel_safe;
+ Node *havingQual;
+ List *targetList;
+ PartitionwiseAggregateType patype;
+} GroupPathExtraData;
+
+/*
+ * Struct for extra information passed to subroutines of grouping_planner
+ *
+ * limit_needed is true if we actually need a Limit plan node.
+ * limit_tuples is an estimated bound on the number of output tuples,
+ * or -1 if no LIMIT or couldn't estimate.
+ * count_est and offset_est are the estimated values of the LIMIT and OFFSET
+ * expressions computed by preprocess_limit() (see comments for
+ * preprocess_limit() for more information).
+ */
+typedef struct
+{
+ bool limit_needed;
+ double limit_tuples;
+ int64 count_est;
+ int64 offset_est;
+} FinalPathExtraData;
+
+/*
+ * For speed reasons, cost estimation for join paths is performed in two
+ * phases: the first phase tries to quickly derive a lower bound for the
+ * join cost, and then we check if that's sufficient to reject the path.
+ * If not, we come back for a more refined cost estimate. The first phase
+ * fills a JoinCostWorkspace struct with its preliminary cost estimates
+ * and possibly additional intermediate values. The second phase takes
+ * these values as inputs to avoid repeating work.
+ *
+ * (Ideally we'd declare this in cost.h, but it's also needed in pathnode.h,
+ * so seems best to put it here.)
+ */
+typedef struct JoinCostWorkspace
+{
+ /* Preliminary cost estimates --- must not be larger than final ones! */
+ Cost startup_cost; /* cost expended before fetching any tuples */
+ Cost total_cost; /* total cost (assuming all tuples fetched) */
+
+ /* Fields below here should be treated as private to costsize.c */
+ Cost run_cost; /* non-startup cost components */
+
+ /* private for cost_nestloop code */
+ Cost inner_run_cost; /* also used by cost_mergejoin code */
+ Cost inner_rescan_run_cost;
+
+ /* private for cost_mergejoin code */
+ double outer_rows;
+ double inner_rows;
+ double outer_skip_rows;
+ double inner_skip_rows;
+
+ /* private for cost_hashjoin code */
+ int numbuckets;
+ int numbatches;
+ double inner_rows_total;
+} JoinCostWorkspace;
+
+#endif /* PATHNODES_H */
diff --git a/src/include/nodes/pg_list.h b/src/include/nodes/pg_list.h
new file mode 100644
index 0000000..54447bb
--- /dev/null
+++ b/src/include/nodes/pg_list.h
@@ -0,0 +1,605 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_list.h
+ * interface for PostgreSQL generic list package
+ *
+ * Once upon a time, parts of Postgres were written in Lisp and used real
+ * cons-cell lists for major data structures. When that code was rewritten
+ * in C, we initially had a faithful emulation of cons-cell lists, which
+ * unsurprisingly was a performance bottleneck. A couple of major rewrites
+ * later, these data structures are actually simple expansible arrays;
+ * but the "List" name and a lot of the notation survives.
+ *
+ * One important concession to the original implementation is that an empty
+ * list is always represented by a null pointer (preferentially written NIL).
+ * Non-empty lists have a header, which will not be relocated as long as the
+ * list remains non-empty, and an expansible data array.
+ *
+ * We support three types of lists:
+ *
+ * T_List: lists of pointers
+ * (in practice usually pointers to Nodes, but not always;
+ * declared as "void *" to minimize casting annoyances)
+ * T_IntList: lists of integers
+ * T_OidList: lists of Oids
+ *
+ * (At the moment, ints and Oids are the same size, but they may not
+ * always be so; try to be careful to maintain the distinction.)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/pg_list.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_LIST_H
+#define PG_LIST_H
+
+#include "nodes/nodes.h"
+
+
+typedef union ListCell
+{
+ void *ptr_value;
+ int int_value;
+ Oid oid_value;
+} ListCell;
+
+typedef struct List
+{
+ NodeTag type; /* T_List, T_IntList, or T_OidList */
+ int length; /* number of elements currently present */
+ int max_length; /* allocated length of elements[] */
+ ListCell *elements; /* re-allocatable array of cells */
+ /* We may allocate some cells along with the List header: */
+ ListCell initial_elements[FLEXIBLE_ARRAY_MEMBER];
+ /* If elements == initial_elements, it's not a separate allocation */
+} List;
+
+/*
+ * The *only* valid representation of an empty list is NIL; in other
+ * words, a non-NIL list is guaranteed to have length >= 1.
+ */
+#define NIL ((List *) NULL)
+
+/*
+ * State structs for various looping macros below.
+ */
+typedef struct ForEachState
+{
+ const List *l; /* list we're looping through */
+ int i; /* current element index */
+} ForEachState;
+
+typedef struct ForBothState
+{
+ const List *l1; /* lists we're looping through */
+ const List *l2;
+ int i; /* common element index */
+} ForBothState;
+
+typedef struct ForBothCellState
+{
+ const List *l1; /* lists we're looping through */
+ const List *l2;
+ int i1; /* current element indexes */
+ int i2;
+} ForBothCellState;
+
+typedef struct ForThreeState
+{
+ const List *l1; /* lists we're looping through */
+ const List *l2;
+ const List *l3;
+ int i; /* common element index */
+} ForThreeState;
+
+typedef struct ForFourState
+{
+ const List *l1; /* lists we're looping through */
+ const List *l2;
+ const List *l3;
+ const List *l4;
+ int i; /* common element index */
+} ForFourState;
+
+typedef struct ForFiveState
+{
+ const List *l1; /* lists we're looping through */
+ const List *l2;
+ const List *l3;
+ const List *l4;
+ const List *l5;
+ int i; /* common element index */
+} ForFiveState;
+
+/*
+ * These routines are small enough, and used often enough, to justify being
+ * inline.
+ */
+
+/* Fetch address of list's first cell; NULL if empty list */
+static inline ListCell *
+list_head(const List *l)
+{
+ return l ? &l->elements[0] : NULL;
+}
+
+/* Fetch address of list's last cell; NULL if empty list */
+static inline ListCell *
+list_tail(const List *l)
+{
+ return l ? &l->elements[l->length - 1] : NULL;
+}
+
+/* Fetch address of list's second cell, if it has one, else NULL */
+static inline ListCell *
+list_second_cell(const List *l)
+{
+ if (l && l->length >= 2)
+ return &l->elements[1];
+ else
+ return NULL;
+}
+
+/* Fetch address of list's third cell, if it has one, else NULL */
+static inline ListCell *
+list_third_cell(const List *l)
+{
+ if (l && l->length >= 3)
+ return &l->elements[2];
+ else
+ return NULL;
+}
+
+/* Fetch address of list's fourth cell, if it has one, else NULL */
+static inline ListCell *
+list_fourth_cell(const List *l)
+{
+ if (l && l->length >= 4)
+ return &l->elements[3];
+ else
+ return NULL;
+}
+
+/* Fetch list's length */
+static inline int
+list_length(const List *l)
+{
+ return l ? l->length : 0;
+}
+
+/*
+ * Macros to access the data values within List cells.
+ *
+ * Note that with the exception of the "xxx_node" macros, these are
+ * lvalues and can be assigned to.
+ *
+ * NB: There is an unfortunate legacy from a previous incarnation of
+ * the List API: the macro lfirst() was used to mean "the data in this
+ * cons cell". To avoid changing every usage of lfirst(), that meaning
+ * has been kept. As a result, lfirst() takes a ListCell and returns
+ * the data it contains; to get the data in the first cell of a
+ * List, use linitial(). Worse, lsecond() is more closely related to
+ * linitial() than lfirst(): given a List, lsecond() returns the data
+ * in the second list cell.
+ */
+
+#define lfirst(lc) ((lc)->ptr_value)
+#define lfirst_int(lc) ((lc)->int_value)
+#define lfirst_oid(lc) ((lc)->oid_value)
+#define lfirst_node(type,lc) castNode(type, lfirst(lc))
+
+#define linitial(l) lfirst(list_head(l))
+#define linitial_int(l) lfirst_int(list_head(l))
+#define linitial_oid(l) lfirst_oid(list_head(l))
+#define linitial_node(type,l) castNode(type, linitial(l))
+
+#define lsecond(l) lfirst(list_second_cell(l))
+#define lsecond_int(l) lfirst_int(list_second_cell(l))
+#define lsecond_oid(l) lfirst_oid(list_second_cell(l))
+#define lsecond_node(type,l) castNode(type, lsecond(l))
+
+#define lthird(l) lfirst(list_third_cell(l))
+#define lthird_int(l) lfirst_int(list_third_cell(l))
+#define lthird_oid(l) lfirst_oid(list_third_cell(l))
+#define lthird_node(type,l) castNode(type, lthird(l))
+
+#define lfourth(l) lfirst(list_fourth_cell(l))
+#define lfourth_int(l) lfirst_int(list_fourth_cell(l))
+#define lfourth_oid(l) lfirst_oid(list_fourth_cell(l))
+#define lfourth_node(type,l) castNode(type, lfourth(l))
+
+#define llast(l) lfirst(list_tail(l))
+#define llast_int(l) lfirst_int(list_tail(l))
+#define llast_oid(l) lfirst_oid(list_tail(l))
+#define llast_node(type,l) castNode(type, llast(l))
+
+/*
+ * Convenience macros for building fixed-length lists
+ */
+#define list_make_ptr_cell(v) ((ListCell) {.ptr_value = (v)})
+#define list_make_int_cell(v) ((ListCell) {.int_value = (v)})
+#define list_make_oid_cell(v) ((ListCell) {.oid_value = (v)})
+
+#define list_make1(x1) \
+ list_make1_impl(T_List, list_make_ptr_cell(x1))
+#define list_make2(x1,x2) \
+ list_make2_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2))
+#define list_make3(x1,x2,x3) \
+ list_make3_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2), \
+ list_make_ptr_cell(x3))
+#define list_make4(x1,x2,x3,x4) \
+ list_make4_impl(T_List, list_make_ptr_cell(x1), list_make_ptr_cell(x2), \
+ list_make_ptr_cell(x3), list_make_ptr_cell(x4))
+
+#define list_make1_int(x1) \
+ list_make1_impl(T_IntList, list_make_int_cell(x1))
+#define list_make2_int(x1,x2) \
+ list_make2_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2))
+#define list_make3_int(x1,x2,x3) \
+ list_make3_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2), \
+ list_make_int_cell(x3))
+#define list_make4_int(x1,x2,x3,x4) \
+ list_make4_impl(T_IntList, list_make_int_cell(x1), list_make_int_cell(x2), \
+ list_make_int_cell(x3), list_make_int_cell(x4))
+
+#define list_make1_oid(x1) \
+ list_make1_impl(T_OidList, list_make_oid_cell(x1))
+#define list_make2_oid(x1,x2) \
+ list_make2_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2))
+#define list_make3_oid(x1,x2,x3) \
+ list_make3_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2), \
+ list_make_oid_cell(x3))
+#define list_make4_oid(x1,x2,x3,x4) \
+ list_make4_impl(T_OidList, list_make_oid_cell(x1), list_make_oid_cell(x2), \
+ list_make_oid_cell(x3), list_make_oid_cell(x4))
+
+/*
+ * Locate the n'th cell (counting from 0) of the list.
+ * It is an assertion failure if there is no such cell.
+ */
+static inline ListCell *
+list_nth_cell(const List *list, int n)
+{
+ Assert(list != NIL);
+ Assert(n >= 0 && n < list->length);
+ return &list->elements[n];
+}
+
+/*
+ * Return the pointer value contained in the n'th element of the
+ * specified list. (List elements begin at 0.)
+ */
+static inline void *
+list_nth(const List *list, int n)
+{
+ Assert(IsA(list, List));
+ return lfirst(list_nth_cell(list, n));
+}
+
+/*
+ * Return the integer value contained in the n'th element of the
+ * specified list.
+ */
+static inline int
+list_nth_int(const List *list, int n)
+{
+ Assert(IsA(list, IntList));
+ return lfirst_int(list_nth_cell(list, n));
+}
+
+/*
+ * Return the OID value contained in the n'th element of the specified
+ * list.
+ */
+static inline Oid
+list_nth_oid(const List *list, int n)
+{
+ Assert(IsA(list, OidList));
+ return lfirst_oid(list_nth_cell(list, n));
+}
+
+#define list_nth_node(type,list,n) castNode(type, list_nth(list, n))
+
+/*
+ * Get the given ListCell's index (from 0) in the given List.
+ */
+static inline int
+list_cell_number(const List *l, const ListCell *c)
+{
+ Assert(c >= &l->elements[0] && c < &l->elements[l->length]);
+ return c - l->elements;
+}
+
+/*
+ * Get the address of the next cell after "c" within list "l", or NULL if none.
+ */
+static inline ListCell *
+lnext(const List *l, const ListCell *c)
+{
+ Assert(c >= &l->elements[0] && c < &l->elements[l->length]);
+ c++;
+ if (c < &l->elements[l->length])
+ return (ListCell *) c;
+ else
+ return NULL;
+}
+
+/*
+ * foreach -
+ * a convenience macro for looping through a list
+ *
+ * "cell" must be the name of a "ListCell *" variable; it's made to point
+ * to each List element in turn. "cell" will be NULL after normal exit from
+ * the loop, but an early "break" will leave it pointing at the current
+ * List element.
+ *
+ * Beware of changing the List object while the loop is iterating.
+ * The current semantics are that we examine successive list indices in
+ * each iteration, so that insertion or deletion of list elements could
+ * cause elements to be re-visited or skipped unexpectedly. Previous
+ * implementations of foreach() behaved differently. However, it's safe
+ * to append elements to the List (or in general, insert them after the
+ * current element); such new elements are guaranteed to be visited.
+ * Also, the current element of the List can be deleted, if you use
+ * foreach_delete_current() to do so. BUT: either of these actions will
+ * invalidate the "cell" pointer for the remainder of the current iteration.
+ */
+#define foreach(cell, lst) \
+ for (ForEachState cell##__state = {(lst), 0}; \
+ (cell##__state.l != NIL && \
+ cell##__state.i < cell##__state.l->length) ? \
+ (cell = &cell##__state.l->elements[cell##__state.i], true) : \
+ (cell = NULL, false); \
+ cell##__state.i++)
+
+/*
+ * foreach_delete_current -
+ * delete the current list element from the List associated with a
+ * surrounding foreach() loop, returning the new List pointer.
+ *
+ * This is equivalent to list_delete_cell(), but it also adjusts the foreach
+ * loop's state so that no list elements will be missed. Do not delete
+ * elements from an active foreach loop's list in any other way!
+ */
+#define foreach_delete_current(lst, cell) \
+ (cell##__state.i--, \
+ (List *) (cell##__state.l = list_delete_cell(lst, cell)))
+
+/*
+ * foreach_current_index -
+ * get the zero-based list index of a surrounding foreach() loop's
+ * current element; pass the name of the "ListCell *" iterator variable.
+ *
+ * Beware of using this after foreach_delete_current(); the value will be
+ * out of sync for the rest of the current loop iteration. Anyway, since
+ * you just deleted the current element, the value is pretty meaningless.
+ */
+#define foreach_current_index(cell) (cell##__state.i)
+
+/*
+ * for_each_from -
+ * Like foreach(), but start from the N'th (zero-based) list element,
+ * not necessarily the first one.
+ *
+ * It's okay for N to exceed the list length, but not for it to be negative.
+ *
+ * The caveats for foreach() apply equally here.
+ */
+#define for_each_from(cell, lst, N) \
+ for (ForEachState cell##__state = for_each_from_setup(lst, N); \
+ (cell##__state.l != NIL && \
+ cell##__state.i < cell##__state.l->length) ? \
+ (cell = &cell##__state.l->elements[cell##__state.i], true) : \
+ (cell = NULL, false); \
+ cell##__state.i++)
+
+static inline ForEachState
+for_each_from_setup(const List *lst, int N)
+{
+ ForEachState r = {lst, N};
+
+ Assert(N >= 0);
+ return r;
+}
+
+/*
+ * for_each_cell -
+ * a convenience macro which loops through a list starting from a
+ * specified cell
+ *
+ * The caveats for foreach() apply equally here.
+ */
+#define for_each_cell(cell, lst, initcell) \
+ for (ForEachState cell##__state = for_each_cell_setup(lst, initcell); \
+ (cell##__state.l != NIL && \
+ cell##__state.i < cell##__state.l->length) ? \
+ (cell = &cell##__state.l->elements[cell##__state.i], true) : \
+ (cell = NULL, false); \
+ cell##__state.i++)
+
+static inline ForEachState
+for_each_cell_setup(const List *lst, const ListCell *initcell)
+{
+ ForEachState r = {lst,
+ initcell ? list_cell_number(lst, initcell) : list_length(lst)};
+
+ return r;
+}
+
+/*
+ * forboth -
+ * a convenience macro for advancing through two linked lists
+ * simultaneously. This macro loops through both lists at the same
+ * time, stopping when either list runs out of elements. Depending
+ * on the requirements of the call site, it may also be wise to
+ * assert that the lengths of the two lists are equal. (But, if they
+ * are not, some callers rely on the ending cell values being separately
+ * NULL or non-NULL as defined here; don't try to optimize that.)
+ *
+ * The caveats for foreach() apply equally here.
+ */
+#define forboth(cell1, list1, cell2, list2) \
+ for (ForBothState cell1##__state = {(list1), (list2), 0}; \
+ multi_for_advance_cell(cell1, cell1##__state, l1, i), \
+ multi_for_advance_cell(cell2, cell1##__state, l2, i), \
+ (cell1 != NULL && cell2 != NULL); \
+ cell1##__state.i++)
+
+#define multi_for_advance_cell(cell, state, l, i) \
+ (cell = (state.l != NIL && state.i < state.l->length) ? \
+ &state.l->elements[state.i] : NULL)
+
+/*
+ * for_both_cell -
+ * a convenience macro which loops through two lists starting from the
+ * specified cells of each. This macro loops through both lists at the same
+ * time, stopping when either list runs out of elements. Depending on the
+ * requirements of the call site, it may also be wise to assert that the
+ * lengths of the two lists are equal, and initcell1 and initcell2 are at
+ * the same position in the respective lists.
+ *
+ * The caveats for foreach() apply equally here.
+ */
+#define for_both_cell(cell1, list1, initcell1, cell2, list2, initcell2) \
+ for (ForBothCellState cell1##__state = \
+ for_both_cell_setup(list1, initcell1, list2, initcell2); \
+ multi_for_advance_cell(cell1, cell1##__state, l1, i1), \
+ multi_for_advance_cell(cell2, cell1##__state, l2, i2), \
+ (cell1 != NULL && cell2 != NULL); \
+ cell1##__state.i1++, cell1##__state.i2++)
+
+static inline ForBothCellState
+for_both_cell_setup(const List *list1, const ListCell *initcell1,
+ const List *list2, const ListCell *initcell2)
+{
+ ForBothCellState r = {list1, list2,
+ initcell1 ? list_cell_number(list1, initcell1) : list_length(list1),
+ initcell2 ? list_cell_number(list2, initcell2) : list_length(list2)};
+
+ return r;
+}
+
+/*
+ * forthree -
+ * the same for three lists
+ */
+#define forthree(cell1, list1, cell2, list2, cell3, list3) \
+ for (ForThreeState cell1##__state = {(list1), (list2), (list3), 0}; \
+ multi_for_advance_cell(cell1, cell1##__state, l1, i), \
+ multi_for_advance_cell(cell2, cell1##__state, l2, i), \
+ multi_for_advance_cell(cell3, cell1##__state, l3, i), \
+ (cell1 != NULL && cell2 != NULL && cell3 != NULL); \
+ cell1##__state.i++)
+
+/*
+ * forfour -
+ * the same for four lists
+ */
+#define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4) \
+ for (ForFourState cell1##__state = {(list1), (list2), (list3), (list4), 0}; \
+ multi_for_advance_cell(cell1, cell1##__state, l1, i), \
+ multi_for_advance_cell(cell2, cell1##__state, l2, i), \
+ multi_for_advance_cell(cell3, cell1##__state, l3, i), \
+ multi_for_advance_cell(cell4, cell1##__state, l4, i), \
+ (cell1 != NULL && cell2 != NULL && cell3 != NULL && cell4 != NULL); \
+ cell1##__state.i++)
+
+/*
+ * forfive -
+ * the same for five lists
+ */
+#define forfive(cell1, list1, cell2, list2, cell3, list3, cell4, list4, cell5, list5) \
+ for (ForFiveState cell1##__state = {(list1), (list2), (list3), (list4), (list5), 0}; \
+ multi_for_advance_cell(cell1, cell1##__state, l1, i), \
+ multi_for_advance_cell(cell2, cell1##__state, l2, i), \
+ multi_for_advance_cell(cell3, cell1##__state, l3, i), \
+ multi_for_advance_cell(cell4, cell1##__state, l4, i), \
+ multi_for_advance_cell(cell5, cell1##__state, l5, i), \
+ (cell1 != NULL && cell2 != NULL && cell3 != NULL && \
+ cell4 != NULL && cell5 != NULL); \
+ cell1##__state.i++)
+
+/* Functions in src/backend/nodes/list.c */
+
+extern List *list_make1_impl(NodeTag t, ListCell datum1);
+extern List *list_make2_impl(NodeTag t, ListCell datum1, ListCell datum2);
+extern List *list_make3_impl(NodeTag t, ListCell datum1, ListCell datum2,
+ ListCell datum3);
+extern List *list_make4_impl(NodeTag t, ListCell datum1, ListCell datum2,
+ ListCell datum3, ListCell datum4);
+
+extern List *lappend(List *list, void *datum);
+extern List *lappend_int(List *list, int datum);
+extern List *lappend_oid(List *list, Oid datum);
+
+extern List *list_insert_nth(List *list, int pos, void *datum);
+extern List *list_insert_nth_int(List *list, int pos, int datum);
+extern List *list_insert_nth_oid(List *list, int pos, Oid datum);
+
+extern List *lcons(void *datum, List *list);
+extern List *lcons_int(int datum, List *list);
+extern List *lcons_oid(Oid datum, List *list);
+
+extern List *list_concat(List *list1, const List *list2);
+extern List *list_concat_copy(const List *list1, const List *list2);
+
+extern List *list_truncate(List *list, int new_size);
+
+extern bool list_member(const List *list, const void *datum);
+extern bool list_member_ptr(const List *list, const void *datum);
+extern bool list_member_int(const List *list, int datum);
+extern bool list_member_oid(const List *list, Oid datum);
+
+extern List *list_delete(List *list, void *datum);
+extern List *list_delete_ptr(List *list, void *datum);
+extern List *list_delete_int(List *list, int datum);
+extern List *list_delete_oid(List *list, Oid datum);
+extern List *list_delete_first(List *list);
+extern List *list_delete_last(List *list);
+extern List *list_delete_nth_cell(List *list, int n);
+extern List *list_delete_cell(List *list, ListCell *cell);
+
+extern List *list_union(const List *list1, const List *list2);
+extern List *list_union_ptr(const List *list1, const List *list2);
+extern List *list_union_int(const List *list1, const List *list2);
+extern List *list_union_oid(const List *list1, const List *list2);
+
+extern List *list_intersection(const List *list1, const List *list2);
+extern List *list_intersection_int(const List *list1, const List *list2);
+
+/* currently, there's no need for list_intersection_ptr etc */
+
+extern List *list_difference(const List *list1, const List *list2);
+extern List *list_difference_ptr(const List *list1, const List *list2);
+extern List *list_difference_int(const List *list1, const List *list2);
+extern List *list_difference_oid(const List *list1, const List *list2);
+
+extern List *list_append_unique(List *list, void *datum);
+extern List *list_append_unique_ptr(List *list, void *datum);
+extern List *list_append_unique_int(List *list, int datum);
+extern List *list_append_unique_oid(List *list, Oid datum);
+
+extern List *list_concat_unique(List *list1, const List *list2);
+extern List *list_concat_unique_ptr(List *list1, const List *list2);
+extern List *list_concat_unique_int(List *list1, const List *list2);
+extern List *list_concat_unique_oid(List *list1, const List *list2);
+
+extern void list_deduplicate_oid(List *list);
+
+extern void list_free(List *list);
+extern void list_free_deep(List *list);
+
+extern List *list_copy(const List *list);
+extern List *list_copy_tail(const List *list, int nskip);
+extern List *list_copy_deep(const List *oldlist);
+
+typedef int (*list_sort_comparator) (const ListCell *a, const ListCell *b);
+extern void list_sort(List *list, list_sort_comparator cmp);
+
+extern int list_oid_cmp(const ListCell *p1, const ListCell *p2);
+
+#endif /* PG_LIST_H */
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
new file mode 100644
index 0000000..83e0107
--- /dev/null
+++ b/src/include/nodes/plannodes.h
@@ -0,0 +1,1251 @@
+/*-------------------------------------------------------------------------
+ *
+ * plannodes.h
+ * definitions for query plan nodes
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/plannodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PLANNODES_H
+#define PLANNODES_H
+
+#include "access/sdir.h"
+#include "access/stratnum.h"
+#include "lib/stringinfo.h"
+#include "nodes/bitmapset.h"
+#include "nodes/lockoptions.h"
+#include "nodes/primnodes.h"
+
+
+/* ----------------------------------------------------------------
+ * node definitions
+ * ----------------------------------------------------------------
+ */
+
+/* ----------------
+ * PlannedStmt node
+ *
+ * The output of the planner is a Plan tree headed by a PlannedStmt node.
+ * PlannedStmt holds the "one time" information needed by the executor.
+ *
+ * For simplicity in APIs, we also wrap utility statements in PlannedStmt
+ * nodes; in such cases, commandType == CMD_UTILITY, the statement itself
+ * is in the utilityStmt field, and the rest of the struct is mostly dummy.
+ * (We do use canSetTag, stmt_location, stmt_len, and possibly queryId.)
+ * ----------------
+ */
+typedef struct PlannedStmt
+{
+ NodeTag type;
+
+ CmdType commandType; /* select|insert|update|delete|utility */
+
+ uint64 queryId; /* query identifier (copied from Query) */
+
+ bool hasReturning; /* is it insert|update|delete RETURNING? */
+
+ bool hasModifyingCTE; /* has insert|update|delete in WITH? */
+
+ bool canSetTag; /* do I set the command result tag? */
+
+ bool transientPlan; /* redo plan when TransactionXmin changes? */
+
+ bool dependsOnRole; /* is plan specific to current role? */
+
+ bool parallelModeNeeded; /* parallel mode required to execute? */
+
+ int jitFlags; /* which forms of JIT should be performed */
+
+ struct Plan *planTree; /* tree of Plan nodes */
+
+ List *rtable; /* list of RangeTblEntry nodes */
+
+ /* rtable indexes of target relations for INSERT/UPDATE/DELETE */
+ List *resultRelations; /* integer list of RT indexes, or NIL */
+
+ /*
+ * rtable indexes of partitioned table roots that are UPDATE/DELETE
+ * targets; needed for trigger firing.
+ */
+ List *rootResultRelations;
+
+ List *appendRelations; /* list of AppendRelInfo nodes */
+
+ List *subplans; /* Plan trees for SubPlan expressions; note
+ * that some could be NULL */
+
+ Bitmapset *rewindPlanIDs; /* indices of subplans that require REWIND */
+
+ List *rowMarks; /* a list of PlanRowMark's */
+
+ List *relationOids; /* OIDs of relations the plan depends on */
+
+ List *invalItems; /* other dependencies, as PlanInvalItems */
+
+ List *paramExecTypes; /* type OIDs for PARAM_EXEC Params */
+
+ Node *utilityStmt; /* non-null if this is utility stmt */
+
+ /* statement location in source string (copied from Query) */
+ int stmt_location; /* start location, or -1 if unknown */
+ int stmt_len; /* length in bytes; 0 means "rest of string" */
+} PlannedStmt;
+
+/* macro for fetching the Plan associated with a SubPlan node */
+#define exec_subplan_get_plan(plannedstmt, subplan) \
+ ((Plan *) list_nth((plannedstmt)->subplans, (subplan)->plan_id - 1))
+
+
+/* ----------------
+ * Plan node
+ *
+ * All plan nodes "derive" from the Plan structure by having the
+ * Plan structure as the first field. This ensures that everything works
+ * when nodes are cast to Plan's. (node pointers are frequently cast to Plan*
+ * when passed around generically in the executor)
+ *
+ * We never actually instantiate any Plan nodes; this is just the common
+ * abstract superclass for all Plan-type nodes.
+ * ----------------
+ */
+typedef struct Plan
+{
+ NodeTag type;
+
+ /*
+ * estimated execution costs for plan (see costsize.c for more info)
+ */
+ Cost startup_cost; /* cost expended before fetching any tuples */
+ Cost total_cost; /* total cost (assuming all tuples fetched) */
+
+ /*
+ * planner's estimate of result size of this plan step
+ */
+ double plan_rows; /* number of rows plan is expected to emit */
+ int plan_width; /* average row width in bytes */
+
+ /*
+ * information needed for parallel query
+ */
+ bool parallel_aware; /* engage parallel-aware logic? */
+ bool parallel_safe; /* OK to use as part of parallel plan? */
+
+ /*
+ * Common structural data for all Plan types.
+ */
+ int plan_node_id; /* unique across entire final plan tree */
+ List *targetlist; /* target list to be computed at this node */
+ List *qual; /* implicitly-ANDed qual conditions */
+ struct Plan *lefttree; /* input plan tree(s) */
+ struct Plan *righttree;
+ List *initPlan; /* Init Plan nodes (un-correlated expr
+ * subselects) */
+
+ /*
+ * Information for management of parameter-change-driven rescanning
+ *
+ * extParam includes the paramIDs of all external PARAM_EXEC params
+ * affecting this plan node or its children. setParam params from the
+ * node's initPlans are not included, but their extParams are.
+ *
+ * allParam includes all the extParam paramIDs, plus the IDs of local
+ * params that affect the node (i.e., the setParams of its initplans).
+ * These are _all_ the PARAM_EXEC params that affect this node.
+ */
+ Bitmapset *extParam;
+ Bitmapset *allParam;
+} Plan;
+
+/* ----------------
+ * these are defined to avoid confusion problems with "left"
+ * and "right" and "inner" and "outer". The convention is that
+ * the "left" plan is the "outer" plan and the "right" plan is
+ * the inner plan, but these make the code more readable.
+ * ----------------
+ */
+#define innerPlan(node) (((Plan *)(node))->righttree)
+#define outerPlan(node) (((Plan *)(node))->lefttree)
+
+
+/* ----------------
+ * Result node -
+ * If no outer plan, evaluate a variable-free targetlist.
+ * If outer plan, return tuples from outer plan (after a level of
+ * projection as shown by targetlist).
+ *
+ * If resconstantqual isn't NULL, it represents a one-time qualification
+ * test (i.e., one that doesn't depend on any variables from the outer plan,
+ * so needs to be evaluated only once).
+ * ----------------
+ */
+typedef struct Result
+{
+ Plan plan;
+ Node *resconstantqual;
+} Result;
+
+/* ----------------
+ * ProjectSet node -
+ * Apply a projection that includes set-returning functions to the
+ * output tuples of the outer plan.
+ * ----------------
+ */
+typedef struct ProjectSet
+{
+ Plan plan;
+} ProjectSet;
+
+/* ----------------
+ * ModifyTable node -
+ * Apply rows produced by subplan(s) to result table(s),
+ * by inserting, updating, or deleting.
+ *
+ * If the originally named target table is a partitioned table, both
+ * nominalRelation and rootRelation contain the RT index of the partition
+ * root, which is not otherwise mentioned in the plan. Otherwise rootRelation
+ * is zero. However, nominalRelation will always be set, as it's the rel that
+ * EXPLAIN should claim is the INSERT/UPDATE/DELETE target.
+ *
+ * Note that rowMarks and epqParam are presumed to be valid for all the
+ * subplan(s); they can't contain any info that varies across subplans.
+ * ----------------
+ */
+typedef struct ModifyTable
+{
+ Plan plan;
+ CmdType operation; /* INSERT, UPDATE, or DELETE */
+ bool canSetTag; /* do we set the command tag/es_processed? */
+ Index nominalRelation; /* Parent RT index for use of EXPLAIN */
+ Index rootRelation; /* Root RT index, if target is partitioned */
+ bool partColsUpdated; /* some part key in hierarchy updated */
+ List *resultRelations; /* integer list of RT indexes */
+ int resultRelIndex; /* index of first resultRel in plan's list */
+ int rootResultRelIndex; /* index of the partitioned table root */
+ List *plans; /* plan(s) producing source data */
+ List *withCheckOptionLists; /* per-target-table WCO lists */
+ List *returningLists; /* per-target-table RETURNING tlists */
+ List *fdwPrivLists; /* per-target-table FDW private data lists */
+ Bitmapset *fdwDirectModifyPlans; /* indices of FDW DM plans */
+ List *rowMarks; /* PlanRowMarks (non-locking only) */
+ int epqParam; /* ID of Param for EvalPlanQual re-eval */
+ OnConflictAction onConflictAction; /* ON CONFLICT action */
+ List *arbiterIndexes; /* List of ON CONFLICT arbiter index OIDs */
+ List *onConflictSet; /* SET for INSERT ON CONFLICT DO UPDATE */
+ Node *onConflictWhere; /* WHERE for ON CONFLICT UPDATE */
+ Index exclRelRTI; /* RTI of the EXCLUDED pseudo relation */
+ List *exclRelTlist; /* tlist of the EXCLUDED pseudo relation */
+} ModifyTable;
+
+struct PartitionPruneInfo; /* forward reference to struct below */
+
+/* ----------------
+ * Append node -
+ * Generate the concatenation of the results of sub-plans.
+ * ----------------
+ */
+typedef struct Append
+{
+ Plan plan;
+ Bitmapset *apprelids; /* RTIs of appendrel(s) formed by this node */
+ List *appendplans;
+
+ /*
+ * All 'appendplans' preceding this index are non-partial plans. All
+ * 'appendplans' from this index onwards are partial plans.
+ */
+ int first_partial_plan;
+
+ /* Info for run-time subplan pruning; NULL if we're not doing that */
+ struct PartitionPruneInfo *part_prune_info;
+} Append;
+
+/* ----------------
+ * MergeAppend node -
+ * Merge the results of pre-sorted sub-plans to preserve the ordering.
+ * ----------------
+ */
+typedef struct MergeAppend
+{
+ Plan plan;
+ Bitmapset *apprelids; /* RTIs of appendrel(s) formed by this node */
+ List *mergeplans;
+ /* these fields are just like the sort-key info in struct Sort: */
+ int numCols; /* number of sort-key columns */
+ AttrNumber *sortColIdx; /* their indexes in the target list */
+ Oid *sortOperators; /* OIDs of operators to sort them by */
+ Oid *collations; /* OIDs of collations */
+ bool *nullsFirst; /* NULLS FIRST/LAST directions */
+ /* Info for run-time subplan pruning; NULL if we're not doing that */
+ struct PartitionPruneInfo *part_prune_info;
+} MergeAppend;
+
+/* ----------------
+ * RecursiveUnion node -
+ * Generate a recursive union of two subplans.
+ *
+ * The "outer" subplan is always the non-recursive term, and the "inner"
+ * subplan is the recursive term.
+ * ----------------
+ */
+typedef struct RecursiveUnion
+{
+ Plan plan;
+ int wtParam; /* ID of Param representing work table */
+ /* Remaining fields are zero/null in UNION ALL case */
+ int numCols; /* number of columns to check for
+ * duplicate-ness */
+ AttrNumber *dupColIdx; /* their indexes in the target list */
+ Oid *dupOperators; /* equality operators to compare with */
+ Oid *dupCollations;
+ long numGroups; /* estimated number of groups in input */
+} RecursiveUnion;
+
+/* ----------------
+ * BitmapAnd node -
+ * Generate the intersection of the results of sub-plans.
+ *
+ * The subplans must be of types that yield tuple bitmaps. The targetlist
+ * and qual fields of the plan are unused and are always NIL.
+ * ----------------
+ */
+typedef struct BitmapAnd
+{
+ Plan plan;
+ List *bitmapplans;
+} BitmapAnd;
+
+/* ----------------
+ * BitmapOr node -
+ * Generate the union of the results of sub-plans.
+ *
+ * The subplans must be of types that yield tuple bitmaps. The targetlist
+ * and qual fields of the plan are unused and are always NIL.
+ * ----------------
+ */
+typedef struct BitmapOr
+{
+ Plan plan;
+ bool isshared;
+ List *bitmapplans;
+} BitmapOr;
+
+/*
+ * ==========
+ * Scan nodes
+ * ==========
+ */
+typedef struct Scan
+{
+ Plan plan;
+ Index scanrelid; /* relid is index into the range table */
+} Scan;
+
+/* ----------------
+ * sequential scan node
+ * ----------------
+ */
+typedef Scan SeqScan;
+
+/* ----------------
+ * table sample scan node
+ * ----------------
+ */
+typedef struct SampleScan
+{
+ Scan scan;
+ /* use struct pointer to avoid including parsenodes.h here */
+ struct TableSampleClause *tablesample;
+} SampleScan;
+
+/* ----------------
+ * index scan node
+ *
+ * indexqualorig is an implicitly-ANDed list of index qual expressions, each
+ * in the same form it appeared in the query WHERE condition. Each should
+ * be of the form (indexkey OP comparisonval) or (comparisonval OP indexkey).
+ * The indexkey is a Var or expression referencing column(s) of the index's
+ * base table. The comparisonval might be any expression, but it won't use
+ * any columns of the base table. The expressions are ordered by index
+ * column position (but items referencing the same index column can appear
+ * in any order). indexqualorig is used at runtime only if we have to recheck
+ * a lossy indexqual.
+ *
+ * indexqual has the same form, but the expressions have been commuted if
+ * necessary to put the indexkeys on the left, and the indexkeys are replaced
+ * by Var nodes identifying the index columns (their varno is INDEX_VAR and
+ * their varattno is the index column number).
+ *
+ * indexorderbyorig is similarly the original form of any ORDER BY expressions
+ * that are being implemented by the index, while indexorderby is modified to
+ * have index column Vars on the left-hand side. Here, multiple expressions
+ * must appear in exactly the ORDER BY order, and this is not necessarily the
+ * index column order. Only the expressions are provided, not the auxiliary
+ * sort-order information from the ORDER BY SortGroupClauses; it's assumed
+ * that the sort ordering is fully determinable from the top-level operators.
+ * indexorderbyorig is used at runtime to recheck the ordering, if the index
+ * cannot calculate an accurate ordering. It is also needed for EXPLAIN.
+ *
+ * indexorderbyops is a list of the OIDs of the operators used to sort the
+ * ORDER BY expressions. This is used together with indexorderbyorig to
+ * recheck ordering at run time. (Note that indexorderby, indexorderbyorig,
+ * and indexorderbyops are used for amcanorderbyop cases, not amcanorder.)
+ *
+ * indexorderdir specifies the scan ordering, for indexscans on amcanorder
+ * indexes (for other indexes it should be "don't care").
+ * ----------------
+ */
+typedef struct IndexScan
+{
+ Scan scan;
+ Oid indexid; /* OID of index to scan */
+ List *indexqual; /* list of index quals (usually OpExprs) */
+ List *indexqualorig; /* the same in original form */
+ List *indexorderby; /* list of index ORDER BY exprs */
+ List *indexorderbyorig; /* the same in original form */
+ List *indexorderbyops; /* OIDs of sort ops for ORDER BY exprs */
+ ScanDirection indexorderdir; /* forward or backward or don't care */
+} IndexScan;
+
+/* ----------------
+ * index-only scan node
+ *
+ * IndexOnlyScan is very similar to IndexScan, but it specifies an
+ * index-only scan, in which the data comes from the index not the heap.
+ * Because of this, *all* Vars in the plan node's targetlist, qual, and
+ * index expressions reference index columns and have varno = INDEX_VAR.
+ * Hence we do not need separate indexqualorig and indexorderbyorig lists,
+ * since their contents would be equivalent to indexqual and indexorderby.
+ *
+ * To help EXPLAIN interpret the index Vars for display, we provide
+ * indextlist, which represents the contents of the index as a targetlist
+ * with one TLE per index column. Vars appearing in this list reference
+ * the base table, and this is the only field in the plan node that may
+ * contain such Vars.
+ * ----------------
+ */
+typedef struct IndexOnlyScan
+{
+ Scan scan;
+ Oid indexid; /* OID of index to scan */
+ List *indexqual; /* list of index quals (usually OpExprs) */
+ List *indexorderby; /* list of index ORDER BY exprs */
+ List *indextlist; /* TargetEntry list describing index's cols */
+ ScanDirection indexorderdir; /* forward or backward or don't care */
+} IndexOnlyScan;
+
+/* ----------------
+ * bitmap index scan node
+ *
+ * BitmapIndexScan delivers a bitmap of potential tuple locations;
+ * it does not access the heap itself. The bitmap is used by an
+ * ancestor BitmapHeapScan node, possibly after passing through
+ * intermediate BitmapAnd and/or BitmapOr nodes to combine it with
+ * the results of other BitmapIndexScans.
+ *
+ * The fields have the same meanings as for IndexScan, except we don't
+ * store a direction flag because direction is uninteresting.
+ *
+ * In a BitmapIndexScan plan node, the targetlist and qual fields are
+ * not used and are always NIL. The indexqualorig field is unused at
+ * run time too, but is saved for the benefit of EXPLAIN.
+ * ----------------
+ */
+typedef struct BitmapIndexScan
+{
+ Scan scan;
+ Oid indexid; /* OID of index to scan */
+ bool isshared; /* Create shared bitmap if set */
+ List *indexqual; /* list of index quals (OpExprs) */
+ List *indexqualorig; /* the same in original form */
+} BitmapIndexScan;
+
+/* ----------------
+ * bitmap sequential scan node
+ *
+ * This needs a copy of the qual conditions being used by the input index
+ * scans because there are various cases where we need to recheck the quals;
+ * for example, when the bitmap is lossy about the specific rows on a page
+ * that meet the index condition.
+ * ----------------
+ */
+typedef struct BitmapHeapScan
+{
+ Scan scan;
+ List *bitmapqualorig; /* index quals, in standard expr form */
+} BitmapHeapScan;
+
+/* ----------------
+ * tid scan node
+ *
+ * tidquals is an implicitly OR'ed list of qual expressions of the form
+ * "CTID = pseudoconstant", or "CTID = ANY(pseudoconstant_array)",
+ * or a CurrentOfExpr for the relation.
+ * ----------------
+ */
+typedef struct TidScan
+{
+ Scan scan;
+ List *tidquals; /* qual(s) involving CTID = something */
+} TidScan;
+
+/* ----------------
+ * subquery scan node
+ *
+ * SubqueryScan is for scanning the output of a sub-query in the range table.
+ * We often need an extra plan node above the sub-query's plan to perform
+ * expression evaluations (which we can't push into the sub-query without
+ * risking changing its semantics). Although we are not scanning a physical
+ * relation, we make this a descendant of Scan anyway for code-sharing
+ * purposes.
+ *
+ * Note: we store the sub-plan in the type-specific subplan field, not in
+ * the generic lefttree field as you might expect. This is because we do
+ * not want plan-tree-traversal routines to recurse into the subplan without
+ * knowing that they are changing Query contexts.
+ * ----------------
+ */
+typedef struct SubqueryScan
+{
+ Scan scan;
+ Plan *subplan;
+} SubqueryScan;
+
+/* ----------------
+ * FunctionScan node
+ * ----------------
+ */
+typedef struct FunctionScan
+{
+ Scan scan;
+ List *functions; /* list of RangeTblFunction nodes */
+ bool funcordinality; /* WITH ORDINALITY */
+} FunctionScan;
+
+/* ----------------
+ * ValuesScan node
+ * ----------------
+ */
+typedef struct ValuesScan
+{
+ Scan scan;
+ List *values_lists; /* list of expression lists */
+} ValuesScan;
+
+/* ----------------
+ * TableFunc scan node
+ * ----------------
+ */
+typedef struct TableFuncScan
+{
+ Scan scan;
+ TableFunc *tablefunc; /* table function node */
+} TableFuncScan;
+
+/* ----------------
+ * CteScan node
+ * ----------------
+ */
+typedef struct CteScan
+{
+ Scan scan;
+ int ctePlanId; /* ID of init SubPlan for CTE */
+ int cteParam; /* ID of Param representing CTE output */
+} CteScan;
+
+/* ----------------
+ * NamedTuplestoreScan node
+ * ----------------
+ */
+typedef struct NamedTuplestoreScan
+{
+ Scan scan;
+ char *enrname; /* Name given to Ephemeral Named Relation */
+} NamedTuplestoreScan;
+
+/* ----------------
+ * WorkTableScan node
+ * ----------------
+ */
+typedef struct WorkTableScan
+{
+ Scan scan;
+ int wtParam; /* ID of Param representing work table */
+} WorkTableScan;
+
+/* ----------------
+ * ForeignScan node
+ *
+ * fdw_exprs and fdw_private are both under the control of the foreign-data
+ * wrapper, but fdw_exprs is presumed to contain expression trees and will
+ * be post-processed accordingly by the planner; fdw_private won't be.
+ * Note that everything in both lists must be copiable by copyObject().
+ * One way to store an arbitrary blob of bytes is to represent it as a bytea
+ * Const. Usually, though, you'll be better off choosing a representation
+ * that can be dumped usefully by nodeToString().
+ *
+ * fdw_scan_tlist is a targetlist describing the contents of the scan tuple
+ * returned by the FDW; it can be NIL if the scan tuple matches the declared
+ * rowtype of the foreign table, which is the normal case for a simple foreign
+ * table scan. (If the plan node represents a foreign join, fdw_scan_tlist
+ * is required since there is no rowtype available from the system catalogs.)
+ * When fdw_scan_tlist is provided, Vars in the node's tlist and quals must
+ * have varno INDEX_VAR, and their varattnos correspond to resnos in the
+ * fdw_scan_tlist (which are also column numbers in the actual scan tuple).
+ * fdw_scan_tlist is never actually executed; it just holds expression trees
+ * describing what is in the scan tuple's columns.
+ *
+ * fdw_recheck_quals should contain any quals which the core system passed to
+ * the FDW but which were not added to scan.plan.qual; that is, it should
+ * contain the quals being checked remotely. This is needed for correct
+ * behavior during EvalPlanQual rechecks.
+ *
+ * When the plan node represents a foreign join, scan.scanrelid is zero and
+ * fs_relids must be consulted to identify the join relation. (fs_relids
+ * is valid for simple scans as well, but will always match scan.scanrelid.)
+ * ----------------
+ */
+typedef struct ForeignScan
+{
+ Scan scan;
+ CmdType operation; /* SELECT/INSERT/UPDATE/DELETE */
+ Oid fs_server; /* OID of foreign server */
+ List *fdw_exprs; /* expressions that FDW may evaluate */
+ List *fdw_private; /* private data for FDW */
+ List *fdw_scan_tlist; /* optional tlist describing scan tuple */
+ List *fdw_recheck_quals; /* original quals not in scan.plan.qual */
+ Bitmapset *fs_relids; /* RTIs generated by this scan */
+ bool fsSystemCol; /* true if any "system column" is needed */
+} ForeignScan;
+
+/* ----------------
+ * CustomScan node
+ *
+ * The comments for ForeignScan's fdw_exprs, fdw_private, fdw_scan_tlist,
+ * and fs_relids fields apply equally to CustomScan's custom_exprs,
+ * custom_private, custom_scan_tlist, and custom_relids fields. The
+ * convention of setting scan.scanrelid to zero for joins applies as well.
+ *
+ * Note that since Plan trees can be copied, custom scan providers *must*
+ * fit all plan data they need into those fields; embedding CustomScan in
+ * a larger struct will not work.
+ * ----------------
+ */
+struct CustomScanMethods;
+
+typedef struct CustomScan
+{
+ Scan scan;
+ uint32 flags; /* mask of CUSTOMPATH_* flags, see
+ * nodes/extensible.h */
+ List *custom_plans; /* list of Plan nodes, if any */
+ List *custom_exprs; /* expressions that custom code may evaluate */
+ List *custom_private; /* private data for custom code */
+ List *custom_scan_tlist; /* optional tlist describing scan tuple */
+ Bitmapset *custom_relids; /* RTIs generated by this scan */
+ const struct CustomScanMethods *methods;
+} CustomScan;
+
+/*
+ * ==========
+ * Join nodes
+ * ==========
+ */
+
+/* ----------------
+ * Join node
+ *
+ * jointype: rule for joining tuples from left and right subtrees
+ * inner_unique each outer tuple can match to no more than one inner tuple
+ * joinqual: qual conditions that came from JOIN/ON or JOIN/USING
+ * (plan.qual contains conditions that came from WHERE)
+ *
+ * When jointype is INNER, joinqual and plan.qual are semantically
+ * interchangeable. For OUTER jointypes, the two are *not* interchangeable;
+ * only joinqual is used to determine whether a match has been found for
+ * the purpose of deciding whether to generate null-extended tuples.
+ * (But plan.qual is still applied before actually returning a tuple.)
+ * For an outer join, only joinquals are allowed to be used as the merge
+ * or hash condition of a merge or hash join.
+ *
+ * inner_unique is set if the joinquals are such that no more than one inner
+ * tuple could match any given outer tuple. This allows the executor to
+ * skip searching for additional matches. (This must be provable from just
+ * the joinquals, ignoring plan.qual, due to where the executor tests it.)
+ * ----------------
+ */
+typedef struct Join
+{
+ Plan plan;
+ JoinType jointype;
+ bool inner_unique;
+ List *joinqual; /* JOIN quals (in addition to plan.qual) */
+} Join;
+
+/* ----------------
+ * nest loop join node
+ *
+ * The nestParams list identifies any executor Params that must be passed
+ * into execution of the inner subplan carrying values from the current row
+ * of the outer subplan. Currently we restrict these values to be simple
+ * Vars, but perhaps someday that'd be worth relaxing. (Note: during plan
+ * creation, the paramval can actually be a PlaceHolderVar expression; but it
+ * must be a Var with varno OUTER_VAR by the time it gets to the executor.)
+ * ----------------
+ */
+typedef struct NestLoop
+{
+ Join join;
+ List *nestParams; /* list of NestLoopParam nodes */
+} NestLoop;
+
+typedef struct NestLoopParam
+{
+ NodeTag type;
+ int paramno; /* number of the PARAM_EXEC Param to set */
+ Var *paramval; /* outer-relation Var to assign to Param */
+} NestLoopParam;
+
+/* ----------------
+ * merge join node
+ *
+ * The expected ordering of each mergeable column is described by a btree
+ * opfamily OID, a collation OID, a direction (BTLessStrategyNumber or
+ * BTGreaterStrategyNumber) and a nulls-first flag. Note that the two sides
+ * of each mergeclause may be of different datatypes, but they are ordered the
+ * same way according to the common opfamily and collation. The operator in
+ * each mergeclause must be an equality operator of the indicated opfamily.
+ * ----------------
+ */
+typedef struct MergeJoin
+{
+ Join join;
+ bool skip_mark_restore; /* Can we skip mark/restore calls? */
+ List *mergeclauses; /* mergeclauses as expression trees */
+ /* these are arrays, but have the same length as the mergeclauses list: */
+ Oid *mergeFamilies; /* per-clause OIDs of btree opfamilies */
+ Oid *mergeCollations; /* per-clause OIDs of collations */
+ int *mergeStrategies; /* per-clause ordering (ASC or DESC) */
+ bool *mergeNullsFirst; /* per-clause nulls ordering */
+} MergeJoin;
+
+/* ----------------
+ * hash join node
+ * ----------------
+ */
+typedef struct HashJoin
+{
+ Join join;
+ List *hashclauses;
+ List *hashoperators;
+ List *hashcollations;
+
+ /*
+ * List of expressions to be hashed for tuples from the outer plan, to
+ * perform lookups in the hashtable over the inner plan.
+ */
+ List *hashkeys;
+} HashJoin;
+
+/* ----------------
+ * materialization node
+ * ----------------
+ */
+typedef struct Material
+{
+ Plan plan;
+} Material;
+
+/* ----------------
+ * sort node
+ * ----------------
+ */
+typedef struct Sort
+{
+ Plan plan;
+ int numCols; /* number of sort-key columns */
+ AttrNumber *sortColIdx; /* their indexes in the target list */
+ Oid *sortOperators; /* OIDs of operators to sort them by */
+ Oid *collations; /* OIDs of collations */
+ bool *nullsFirst; /* NULLS FIRST/LAST directions */
+} Sort;
+
+/* ----------------
+ * incremental sort node
+ * ----------------
+ */
+typedef struct IncrementalSort
+{
+ Sort sort;
+ int nPresortedCols; /* number of presorted columns */
+} IncrementalSort;
+
+/* ---------------
+ * group node -
+ * Used for queries with GROUP BY (but no aggregates) specified.
+ * The input must be presorted according to the grouping columns.
+ * ---------------
+ */
+typedef struct Group
+{
+ Plan plan;
+ int numCols; /* number of grouping columns */
+ AttrNumber *grpColIdx; /* their indexes in the target list */
+ Oid *grpOperators; /* equality operators to compare with */
+ Oid *grpCollations;
+} Group;
+
+/* ---------------
+ * aggregate node
+ *
+ * An Agg node implements plain or grouped aggregation. For grouped
+ * aggregation, we can work with presorted input or unsorted input;
+ * the latter strategy uses an internal hashtable.
+ *
+ * Notice the lack of any direct info about the aggregate functions to be
+ * computed. They are found by scanning the node's tlist and quals during
+ * executor startup. (It is possible that there are no aggregate functions;
+ * this could happen if they get optimized away by constant-folding, or if
+ * we are using the Agg node to implement hash-based grouping.)
+ * ---------------
+ */
+typedef struct Agg
+{
+ Plan plan;
+ AggStrategy aggstrategy; /* basic strategy, see nodes.h */
+ AggSplit aggsplit; /* agg-splitting mode, see nodes.h */
+ int numCols; /* number of grouping columns */
+ AttrNumber *grpColIdx; /* their indexes in the target list */
+ Oid *grpOperators; /* equality operators to compare with */
+ Oid *grpCollations;
+ long numGroups; /* estimated number of groups in input */
+ uint64 transitionSpace; /* for pass-by-ref transition data */
+ Bitmapset *aggParams; /* IDs of Params used in Aggref inputs */
+ /* Note: planner provides numGroups & aggParams only in HASHED/MIXED case */
+ List *groupingSets; /* grouping sets to use */
+ List *chain; /* chained Agg/Sort nodes */
+} Agg;
+
+/* ----------------
+ * window aggregate node
+ * ----------------
+ */
+typedef struct WindowAgg
+{
+ Plan plan;
+ Index winref; /* ID referenced by window functions */
+ int partNumCols; /* number of columns in partition clause */
+ AttrNumber *partColIdx; /* their indexes in the target list */
+ Oid *partOperators; /* equality operators for partition columns */
+ Oid *partCollations; /* collations for partition columns */
+ int ordNumCols; /* number of columns in ordering clause */
+ AttrNumber *ordColIdx; /* their indexes in the target list */
+ Oid *ordOperators; /* equality operators for ordering columns */
+ Oid *ordCollations; /* collations for ordering columns */
+ int frameOptions; /* frame_clause options, see WindowDef */
+ Node *startOffset; /* expression for starting bound, if any */
+ Node *endOffset; /* expression for ending bound, if any */
+ /* these fields are used with RANGE offset PRECEDING/FOLLOWING: */
+ Oid startInRangeFunc; /* in_range function for startOffset */
+ Oid endInRangeFunc; /* in_range function for endOffset */
+ Oid inRangeColl; /* collation for in_range tests */
+ bool inRangeAsc; /* use ASC sort order for in_range tests? */
+ bool inRangeNullsFirst; /* nulls sort first for in_range tests? */
+} WindowAgg;
+
+/* ----------------
+ * unique node
+ * ----------------
+ */
+typedef struct Unique
+{
+ Plan plan;
+ int numCols; /* number of columns to check for uniqueness */
+ AttrNumber *uniqColIdx; /* their indexes in the target list */
+ Oid *uniqOperators; /* equality operators to compare with */
+ Oid *uniqCollations; /* collations for equality comparisons */
+} Unique;
+
+/* ------------
+ * gather node
+ *
+ * Note: rescan_param is the ID of a PARAM_EXEC parameter slot. That slot
+ * will never actually contain a value, but the Gather node must flag it as
+ * having changed whenever it is rescanned. The child parallel-aware scan
+ * nodes are marked as depending on that parameter, so that the rescan
+ * machinery is aware that their output is likely to change across rescans.
+ * In some cases we don't need a rescan Param, so rescan_param is set to -1.
+ * ------------
+ */
+typedef struct Gather
+{
+ Plan plan;
+ int num_workers; /* planned number of worker processes */
+ int rescan_param; /* ID of Param that signals a rescan, or -1 */
+ bool single_copy; /* don't execute plan more than once */
+ bool invisible; /* suppress EXPLAIN display (for testing)? */
+ Bitmapset *initParam; /* param id's of initplans which are referred
+ * at gather or one of it's child node */
+} Gather;
+
+/* ------------
+ * gather merge node
+ * ------------
+ */
+typedef struct GatherMerge
+{
+ Plan plan;
+ int num_workers; /* planned number of worker processes */
+ int rescan_param; /* ID of Param that signals a rescan, or -1 */
+ /* remaining fields are just like the sort-key info in struct Sort */
+ int numCols; /* number of sort-key columns */
+ AttrNumber *sortColIdx; /* their indexes in the target list */
+ Oid *sortOperators; /* OIDs of operators to sort them by */
+ Oid *collations; /* OIDs of collations */
+ bool *nullsFirst; /* NULLS FIRST/LAST directions */
+ Bitmapset *initParam; /* param id's of initplans which are referred
+ * at gather merge or one of it's child node */
+} GatherMerge;
+
+/* ----------------
+ * hash build node
+ *
+ * If the executor is supposed to try to apply skew join optimization, then
+ * skewTable/skewColumn/skewInherit identify the outer relation's join key
+ * column, from which the relevant MCV statistics can be fetched.
+ * ----------------
+ */
+typedef struct Hash
+{
+ Plan plan;
+
+ /*
+ * List of expressions to be hashed for tuples from Hash's outer plan,
+ * needed to put them into the hashtable.
+ */
+ List *hashkeys; /* hash keys for the hashjoin condition */
+ Oid skewTable; /* outer join key's table OID, or InvalidOid */
+ AttrNumber skewColumn; /* outer join key's column #, or zero */
+ bool skewInherit; /* is outer join rel an inheritance tree? */
+ /* all other info is in the parent HashJoin node */
+ double rows_total; /* estimate total rows if parallel_aware */
+} Hash;
+
+/* ----------------
+ * setop node
+ * ----------------
+ */
+typedef struct SetOp
+{
+ Plan plan;
+ SetOpCmd cmd; /* what to do, see nodes.h */
+ SetOpStrategy strategy; /* how to do it, see nodes.h */
+ int numCols; /* number of columns to check for
+ * duplicate-ness */
+ AttrNumber *dupColIdx; /* their indexes in the target list */
+ Oid *dupOperators; /* equality operators to compare with */
+ Oid *dupCollations;
+ AttrNumber flagColIdx; /* where is the flag column, if any */
+ int firstFlag; /* flag value for first input relation */
+ long numGroups; /* estimated number of groups in input */
+} SetOp;
+
+/* ----------------
+ * lock-rows node
+ *
+ * rowMarks identifies the rels to be locked by this node; it should be
+ * a subset of the rowMarks listed in the top-level PlannedStmt.
+ * epqParam is a Param that all scan nodes below this one must depend on.
+ * It is used to force re-evaluation of the plan during EvalPlanQual.
+ * ----------------
+ */
+typedef struct LockRows
+{
+ Plan plan;
+ List *rowMarks; /* a list of PlanRowMark's */
+ int epqParam; /* ID of Param for EvalPlanQual re-eval */
+} LockRows;
+
+/* ----------------
+ * limit node
+ *
+ * Note: as of Postgres 8.2, the offset and count expressions are expected
+ * to yield int8, rather than int4 as before.
+ * ----------------
+ */
+typedef struct Limit
+{
+ Plan plan;
+ Node *limitOffset; /* OFFSET parameter, or NULL if none */
+ Node *limitCount; /* COUNT parameter, or NULL if none */
+ LimitOption limitOption; /* limit type */
+ int uniqNumCols; /* number of columns to check for similarity */
+ AttrNumber *uniqColIdx; /* their indexes in the target list */
+ Oid *uniqOperators; /* equality operators to compare with */
+ Oid *uniqCollations; /* collations for equality comparisons */
+} Limit;
+
+
+/*
+ * RowMarkType -
+ * enums for types of row-marking operations
+ *
+ * The first four of these values represent different lock strengths that
+ * we can take on tuples according to SELECT FOR [KEY] UPDATE/SHARE requests.
+ * We support these on regular tables, as well as on foreign tables whose FDWs
+ * report support for late locking. For other foreign tables, any locking
+ * that might be done for such requests must happen during the initial row
+ * fetch; their FDWs provide no mechanism for going back to lock a row later.
+ * This means that the semantics will be a bit different than for a local
+ * table; in particular we are likely to lock more rows than would be locked
+ * locally, since remote rows will be locked even if they then fail
+ * locally-checked restriction or join quals. However, the prospect of
+ * doing a separate remote query to lock each selected row is usually pretty
+ * unappealing, so early locking remains a credible design choice for FDWs.
+ *
+ * When doing UPDATE, DELETE, or SELECT FOR UPDATE/SHARE, we have to uniquely
+ * identify all the source rows, not only those from the target relations, so
+ * that we can perform EvalPlanQual rechecking at need. For plain tables we
+ * can just fetch the TID, much as for a target relation; this case is
+ * represented by ROW_MARK_REFERENCE. Otherwise (for example for VALUES or
+ * FUNCTION scans) we have to copy the whole row value. ROW_MARK_COPY is
+ * pretty inefficient, since most of the time we'll never need the data; but
+ * fortunately the overhead is usually not performance-critical in practice.
+ * By default we use ROW_MARK_COPY for foreign tables, but if the FDW has
+ * a concept of rowid it can request to use ROW_MARK_REFERENCE instead.
+ * (Again, this probably doesn't make sense if a physical remote fetch is
+ * needed, but for FDWs that map to local storage it might be credible.)
+ */
+typedef enum RowMarkType
+{
+ ROW_MARK_EXCLUSIVE, /* obtain exclusive tuple lock */
+ ROW_MARK_NOKEYEXCLUSIVE, /* obtain no-key exclusive tuple lock */
+ ROW_MARK_SHARE, /* obtain shared tuple lock */
+ ROW_MARK_KEYSHARE, /* obtain keyshare tuple lock */
+ ROW_MARK_REFERENCE, /* just fetch the TID, don't lock it */
+ ROW_MARK_COPY /* physically copy the row value */
+} RowMarkType;
+
+#define RowMarkRequiresRowShareLock(marktype) ((marktype) <= ROW_MARK_KEYSHARE)
+
+/*
+ * PlanRowMark -
+ * plan-time representation of FOR [KEY] UPDATE/SHARE clauses
+ *
+ * When doing UPDATE, DELETE, or SELECT FOR UPDATE/SHARE, we create a separate
+ * PlanRowMark node for each non-target relation in the query. Relations that
+ * are not specified as FOR UPDATE/SHARE are marked ROW_MARK_REFERENCE (if
+ * regular tables or supported foreign tables) or ROW_MARK_COPY (if not).
+ *
+ * Initially all PlanRowMarks have rti == prti and isParent == false.
+ * When the planner discovers that a relation is the root of an inheritance
+ * tree, it sets isParent true, and adds an additional PlanRowMark to the
+ * list for each child relation (including the target rel itself in its role
+ * as a child). isParent is also set to true for the partitioned child
+ * relations, which are not scanned just like the root parent. The child
+ * entries have rti == child rel's RT index and prti == parent's RT index,
+ * and can therefore be recognized as children by the fact that prti != rti.
+ * The parent's allMarkTypes field gets the OR of (1<<markType) across all
+ * its children (this definition allows children to use different markTypes).
+ *
+ * The planner also adds resjunk output columns to the plan that carry
+ * information sufficient to identify the locked or fetched rows. When
+ * markType != ROW_MARK_COPY, these columns are named
+ * tableoid%u OID of table
+ * ctid%u TID of row
+ * The tableoid column is only present for an inheritance hierarchy.
+ * When markType == ROW_MARK_COPY, there is instead a single column named
+ * wholerow%u whole-row value of relation
+ * (An inheritance hierarchy could have all three resjunk output columns,
+ * if some children use a different markType than others.)
+ * In all three cases, %u represents the rowmark ID number (rowmarkId).
+ * This number is unique within a plan tree, except that child relation
+ * entries copy their parent's rowmarkId. (Assigning unique numbers
+ * means we needn't renumber rowmarkIds when flattening subqueries, which
+ * would require finding and renaming the resjunk columns as well.)
+ * Note this means that all tables in an inheritance hierarchy share the
+ * same resjunk column names. However, in an inherited UPDATE/DELETE the
+ * columns could have different physical column numbers in each subplan.
+ */
+typedef struct PlanRowMark
+{
+ NodeTag type;
+ Index rti; /* range table index of markable relation */
+ Index prti; /* range table index of parent relation */
+ Index rowmarkId; /* unique identifier for resjunk columns */
+ RowMarkType markType; /* see enum above */
+ int allMarkTypes; /* OR of (1<<markType) for all children */
+ LockClauseStrength strength; /* LockingClause's strength, or LCS_NONE */
+ LockWaitPolicy waitPolicy; /* NOWAIT and SKIP LOCKED options */
+ bool isParent; /* true if this is a "dummy" parent entry */
+} PlanRowMark;
+
+
+/*
+ * Node types to represent partition pruning information.
+ */
+
+/*
+ * PartitionPruneInfo - Details required to allow the executor to prune
+ * partitions.
+ *
+ * Here we store mapping details to allow translation of a partitioned table's
+ * index as returned by the partition pruning code into subplan indexes for
+ * plan types which support arbitrary numbers of subplans, such as Append.
+ * We also store various details to tell the executor when it should be
+ * performing partition pruning.
+ *
+ * Each PartitionedRelPruneInfo describes the partitioning rules for a single
+ * partitioned table (a/k/a level of partitioning). Since a partitioning
+ * hierarchy could contain multiple levels, we represent it by a List of
+ * PartitionedRelPruneInfos, where the first entry represents the topmost
+ * partitioned table and additional entries represent non-leaf child
+ * partitions, ordered such that parents appear before their children.
+ * Then, since an Append-type node could have multiple partitioning
+ * hierarchies among its children, we have an unordered List of those Lists.
+ *
+ * prune_infos List of Lists containing PartitionedRelPruneInfo nodes,
+ * one sublist per run-time-prunable partition hierarchy
+ * appearing in the parent plan node's subplans.
+ * other_subplans Indexes of any subplans that are not accounted for
+ * by any of the PartitionedRelPruneInfo nodes in
+ * "prune_infos". These subplans must not be pruned.
+ */
+typedef struct PartitionPruneInfo
+{
+ NodeTag type;
+ List *prune_infos;
+ Bitmapset *other_subplans;
+} PartitionPruneInfo;
+
+/*
+ * PartitionedRelPruneInfo - Details required to allow the executor to prune
+ * partitions for a single partitioned table.
+ *
+ * subplan_map[] and subpart_map[] are indexed by partition index of the
+ * partitioned table referenced by 'rtindex', the partition index being the
+ * order that the partitions are defined in the table's PartitionDesc. For a
+ * leaf partition p, subplan_map[p] contains the zero-based index of the
+ * partition's subplan in the parent plan's subplan list; it is -1 if the
+ * partition is non-leaf or has been pruned. For a non-leaf partition p,
+ * subpart_map[p] contains the zero-based index of that sub-partition's
+ * PartitionedRelPruneInfo in the hierarchy's PartitionedRelPruneInfo list;
+ * it is -1 if the partition is a leaf or has been pruned. Note that subplan
+ * indexes, as stored in 'subplan_map', are global across the parent plan
+ * node, but partition indexes are valid only within a particular hierarchy.
+ * relid_map[p] contains the partition's OID, or 0 if the partition was pruned.
+ */
+typedef struct PartitionedRelPruneInfo
+{
+ NodeTag type;
+ Index rtindex; /* RT index of partition rel for this level */
+ Bitmapset *present_parts; /* Indexes of all partitions which subplans or
+ * subparts are present for */
+ int nparts; /* Length of the following arrays: */
+ int *subplan_map; /* subplan index by partition index, or -1 */
+ int *subpart_map; /* subpart index by partition index, or -1 */
+ Oid *relid_map; /* relation OID by partition index, or 0 */
+
+ /*
+ * initial_pruning_steps shows how to prune during executor startup (i.e.,
+ * without use of any PARAM_EXEC Params); it is NIL if no startup pruning
+ * is required. exec_pruning_steps shows how to prune with PARAM_EXEC
+ * Params; it is NIL if no per-scan pruning is required.
+ */
+ List *initial_pruning_steps; /* List of PartitionPruneStep */
+ List *exec_pruning_steps; /* List of PartitionPruneStep */
+ Bitmapset *execparamids; /* All PARAM_EXEC Param IDs in
+ * exec_pruning_steps */
+} PartitionedRelPruneInfo;
+
+/*
+ * Abstract Node type for partition pruning steps (there are no concrete
+ * Nodes of this type).
+ *
+ * step_id is the global identifier of the step within its pruning context.
+ */
+typedef struct PartitionPruneStep
+{
+ NodeTag type;
+ int step_id;
+} PartitionPruneStep;
+
+/*
+ * PartitionPruneStepOp - Information to prune using a set of mutually AND'd
+ * OpExpr clauses
+ *
+ * This contains information extracted from up to partnatts OpExpr clauses,
+ * where partnatts is the number of partition key columns. 'opstrategy' is the
+ * strategy of the operator in the clause matched to the last partition key.
+ * 'exprs' contains expressions which comprise the lookup key to be passed to
+ * the partition bound search function. 'cmpfns' contains the OIDs of
+ * comparison functions used to compare aforementioned expressions with
+ * partition bounds. Both 'exprs' and 'cmpfns' contain the same number of
+ * items, up to partnatts items.
+ *
+ * Once we find the offset of a partition bound using the lookup key, we
+ * determine which partitions to include in the result based on the value of
+ * 'opstrategy'. For example, if it were equality, we'd return just the
+ * partition that would contain that key or a set of partitions if the key
+ * didn't consist of all partitioning columns. For non-equality strategies,
+ * we'd need to include other partitions as appropriate.
+ *
+ * 'nullkeys' is the set containing the offset of the partition keys (0 to
+ * partnatts - 1) that were matched to an IS NULL clause. This is only
+ * considered for hash partitioning as we need to pass which keys are null
+ * to the hash partition bound search function. It is never possible to
+ * have an expression be present in 'exprs' for a given partition key and
+ * the corresponding bit set in 'nullkeys'.
+ */
+typedef struct PartitionPruneStepOp
+{
+ PartitionPruneStep step;
+
+ StrategyNumber opstrategy;
+ List *exprs;
+ List *cmpfns;
+ Bitmapset *nullkeys;
+} PartitionPruneStepOp;
+
+/*
+ * PartitionPruneStepCombine - Information to prune using a BoolExpr clause
+ *
+ * For BoolExpr clauses, we combine the set of partitions determined for each
+ * of the argument clauses.
+ */
+typedef enum PartitionPruneCombineOp
+{
+ PARTPRUNE_COMBINE_UNION,
+ PARTPRUNE_COMBINE_INTERSECT
+} PartitionPruneCombineOp;
+
+typedef struct PartitionPruneStepCombine
+{
+ PartitionPruneStep step;
+
+ PartitionPruneCombineOp combineOp;
+ List *source_stepids;
+} PartitionPruneStepCombine;
+
+
+/*
+ * Plan invalidation info
+ *
+ * We track the objects on which a PlannedStmt depends in two ways:
+ * relations are recorded as a simple list of OIDs, and everything else
+ * is represented as a list of PlanInvalItems. A PlanInvalItem is designed
+ * to be used with the syscache invalidation mechanism, so it identifies a
+ * system catalog entry by cache ID and hash value.
+ */
+typedef struct PlanInvalItem
+{
+ NodeTag type;
+ int cacheId; /* a syscache ID, see utils/syscache.h */
+ uint32 hashValue; /* hash value of object's cache lookup key */
+} PlanInvalItem;
+
+#endif /* PLANNODES_H */
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
new file mode 100644
index 0000000..d73be2a
--- /dev/null
+++ b/src/include/nodes/primnodes.h
@@ -0,0 +1,1541 @@
+/*-------------------------------------------------------------------------
+ *
+ * primnodes.h
+ * Definitions for "primitive" node types, those that are used in more
+ * than one of the parse/plan/execute stages of the query pipeline.
+ * Currently, these are mostly nodes for executable expressions
+ * and join trees.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/primnodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PRIMNODES_H
+#define PRIMNODES_H
+
+#include "access/attnum.h"
+#include "nodes/bitmapset.h"
+#include "nodes/pg_list.h"
+
+
+/* ----------------------------------------------------------------
+ * node definitions
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * Alias -
+ * specifies an alias for a range variable; the alias might also
+ * specify renaming of columns within the table.
+ *
+ * Note: colnames is a list of Value nodes (always strings). In Alias structs
+ * associated with RTEs, there may be entries corresponding to dropped
+ * columns; these are normally empty strings (""). See parsenodes.h for info.
+ */
+typedef struct Alias
+{
+ NodeTag type;
+ char *aliasname; /* aliased rel name (never qualified) */
+ List *colnames; /* optional list of column aliases */
+} Alias;
+
+/* What to do at commit time for temporary relations */
+typedef enum OnCommitAction
+{
+ ONCOMMIT_NOOP, /* No ON COMMIT clause (do nothing) */
+ ONCOMMIT_PRESERVE_ROWS, /* ON COMMIT PRESERVE ROWS (do nothing) */
+ ONCOMMIT_DELETE_ROWS, /* ON COMMIT DELETE ROWS */
+ ONCOMMIT_DROP /* ON COMMIT DROP */
+} OnCommitAction;
+
+/*
+ * RangeVar - range variable, used in FROM clauses
+ *
+ * Also used to represent table names in utility statements; there, the alias
+ * field is not used, and inh tells whether to apply the operation
+ * recursively to child tables. In some contexts it is also useful to carry
+ * a TEMP table indication here.
+ */
+typedef struct RangeVar
+{
+ NodeTag type;
+ char *catalogname; /* the catalog (database) name, or NULL */
+ char *schemaname; /* the schema name, or NULL */
+ char *relname; /* the relation/sequence name */
+ bool inh; /* expand rel by inheritance? recursively act
+ * on children? */
+ char relpersistence; /* see RELPERSISTENCE_* in pg_class.h */
+ Alias *alias; /* table alias & optional column aliases */
+ int location; /* token location, or -1 if unknown */
+} RangeVar;
+
+/*
+ * TableFunc - node for a table function, such as XMLTABLE.
+ *
+ * Entries in the ns_names list are either string Value nodes containing
+ * literal namespace names, or NULL pointers to represent DEFAULT.
+ */
+typedef struct TableFunc
+{
+ NodeTag type;
+ List *ns_uris; /* list of namespace URI expressions */
+ List *ns_names; /* list of namespace names or NULL */
+ Node *docexpr; /* input document expression */
+ Node *rowexpr; /* row filter expression */
+ List *colnames; /* column names (list of String) */
+ List *coltypes; /* OID list of column type OIDs */
+ List *coltypmods; /* integer list of column typmods */
+ List *colcollations; /* OID list of column collation OIDs */
+ List *colexprs; /* list of column filter expressions */
+ List *coldefexprs; /* list of column default expressions */
+ Bitmapset *notnulls; /* nullability flag for each output column */
+ int ordinalitycol; /* counts from 0; -1 if none specified */
+ int location; /* token location, or -1 if unknown */
+} TableFunc;
+
+/*
+ * IntoClause - target information for SELECT INTO, CREATE TABLE AS, and
+ * CREATE MATERIALIZED VIEW
+ *
+ * For CREATE MATERIALIZED VIEW, viewQuery is the parsed-but-not-rewritten
+ * SELECT Query for the view; otherwise it's NULL. (Although it's actually
+ * Query*, we declare it as Node* to avoid a forward reference.)
+ */
+typedef struct IntoClause
+{
+ NodeTag type;
+
+ RangeVar *rel; /* target relation name */
+ List *colNames; /* column names to assign, or NIL */
+ char *accessMethod; /* table access method */
+ List *options; /* options from WITH clause */
+ OnCommitAction onCommit; /* what do we do at COMMIT? */
+ char *tableSpaceName; /* table space to use, or NULL */
+ Node *viewQuery; /* materialized view's SELECT query */
+ bool skipData; /* true for WITH NO DATA */
+} IntoClause;
+
+
+/* ----------------------------------------------------------------
+ * node types for executable expressions
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * Expr - generic superclass for executable-expression nodes
+ *
+ * All node types that are used in executable expression trees should derive
+ * from Expr (that is, have Expr as their first field). Since Expr only
+ * contains NodeTag, this is a formality, but it is an easy form of
+ * documentation. See also the ExprState node types in execnodes.h.
+ */
+typedef struct Expr
+{
+ NodeTag type;
+} Expr;
+
+/*
+ * Var - expression node representing a variable (ie, a table column)
+ *
+ * In the parser and planner, varno and varattno identify the semantic
+ * referent, which is a base-relation column unless the reference is to a join
+ * USING column that isn't semantically equivalent to either join input column
+ * (because it is a FULL join or the input column requires a type coercion).
+ * In those cases varno and varattno refer to the JOIN RTE. (Early in the
+ * planner, we replace such join references by the implied expression; but up
+ * till then we want join reference Vars to keep their original identity for
+ * query-printing purposes.)
+ *
+ * At the end of planning, Var nodes appearing in upper-level plan nodes are
+ * reassigned to point to the outputs of their subplans; for example, in a
+ * join node varno becomes INNER_VAR or OUTER_VAR and varattno becomes the
+ * index of the proper element of that subplan's target list. Similarly,
+ * INDEX_VAR is used to identify Vars that reference an index column rather
+ * than a heap column. (In ForeignScan and CustomScan plan nodes, INDEX_VAR
+ * is abused to signify references to columns of a custom scan tuple type.)
+ *
+ * In the parser, varnosyn and varattnosyn are either identical to
+ * varno/varattno, or they specify the column's position in an aliased JOIN
+ * RTE that hides the semantic referent RTE's refname. This is a syntactic
+ * identifier as opposed to the semantic identifier; it tells ruleutils.c
+ * how to print the Var properly. varnosyn/varattnosyn retain their values
+ * throughout planning and execution, so they are particularly helpful to
+ * identify Vars when debugging. Note, however, that a Var that is generated
+ * in the planner and doesn't correspond to any simple relation column may
+ * have varnosyn = varattnosyn = 0.
+ */
+#define INNER_VAR 65000 /* reference to inner subplan */
+#define OUTER_VAR 65001 /* reference to outer subplan */
+#define INDEX_VAR 65002 /* reference to index column */
+
+#define IS_SPECIAL_VARNO(varno) ((varno) >= INNER_VAR)
+
+/* Symbols for the indexes of the special RTE entries in rules */
+#define PRS2_OLD_VARNO 1
+#define PRS2_NEW_VARNO 2
+
+typedef struct Var
+{
+ Expr xpr;
+ Index varno; /* index of this var's relation in the range
+ * table, or INNER_VAR/OUTER_VAR/INDEX_VAR */
+ AttrNumber varattno; /* attribute number of this var, or zero for
+ * all attrs ("whole-row Var") */
+ Oid vartype; /* pg_type OID for the type of this var */
+ int32 vartypmod; /* pg_attribute typmod value */
+ Oid varcollid; /* OID of collation, or InvalidOid if none */
+ Index varlevelsup; /* for subquery variables referencing outer
+ * relations; 0 in a normal var, >0 means N
+ * levels up */
+ Index varnosyn; /* syntactic relation index (0 if unknown) */
+ AttrNumber varattnosyn; /* syntactic attribute number */
+ int location; /* token location, or -1 if unknown */
+} Var;
+
+/*
+ * Const
+ *
+ * Note: for varlena data types, we make a rule that a Const node's value
+ * must be in non-extended form (4-byte header, no compression or external
+ * references). This ensures that the Const node is self-contained and makes
+ * it more likely that equal() will see logically identical values as equal.
+ */
+typedef struct Const
+{
+ Expr xpr;
+ Oid consttype; /* pg_type OID of the constant's datatype */
+ int32 consttypmod; /* typmod value, if any */
+ Oid constcollid; /* OID of collation, or InvalidOid if none */
+ int constlen; /* typlen of the constant's datatype */
+ Datum constvalue; /* the constant's value */
+ bool constisnull; /* whether the constant is null (if true,
+ * constvalue is undefined) */
+ bool constbyval; /* whether this datatype is passed by value.
+ * If true, then all the information is stored
+ * in the Datum. If false, then the Datum
+ * contains a pointer to the information. */
+ int location; /* token location, or -1 if unknown */
+} Const;
+
+/*
+ * Param
+ *
+ * paramkind specifies the kind of parameter. The possible values
+ * for this field are:
+ *
+ * PARAM_EXTERN: The parameter value is supplied from outside the plan.
+ * Such parameters are numbered from 1 to n.
+ *
+ * PARAM_EXEC: The parameter is an internal executor parameter, used
+ * for passing values into and out of sub-queries or from
+ * nestloop joins to their inner scans.
+ * For historical reasons, such parameters are numbered from 0.
+ * These numbers are independent of PARAM_EXTERN numbers.
+ *
+ * PARAM_SUBLINK: The parameter represents an output column of a SubLink
+ * node's sub-select. The column number is contained in the
+ * `paramid' field. (This type of Param is converted to
+ * PARAM_EXEC during planning.)
+ *
+ * PARAM_MULTIEXPR: Like PARAM_SUBLINK, the parameter represents an
+ * output column of a SubLink node's sub-select, but here, the
+ * SubLink is always a MULTIEXPR SubLink. The high-order 16 bits
+ * of the `paramid' field contain the SubLink's subLinkId, and
+ * the low-order 16 bits contain the column number. (This type
+ * of Param is also converted to PARAM_EXEC during planning.)
+ */
+typedef enum ParamKind
+{
+ PARAM_EXTERN,
+ PARAM_EXEC,
+ PARAM_SUBLINK,
+ PARAM_MULTIEXPR
+} ParamKind;
+
+typedef struct Param
+{
+ Expr xpr;
+ ParamKind paramkind; /* kind of parameter. See above */
+ int paramid; /* numeric ID for parameter */
+ Oid paramtype; /* pg_type OID of parameter's datatype */
+ int32 paramtypmod; /* typmod value, if known */
+ Oid paramcollid; /* OID of collation, or InvalidOid if none */
+ int location; /* token location, or -1 if unknown */
+} Param;
+
+/*
+ * Aggref
+ *
+ * The aggregate's args list is a targetlist, ie, a list of TargetEntry nodes.
+ *
+ * For a normal (non-ordered-set) aggregate, the non-resjunk TargetEntries
+ * represent the aggregate's regular arguments (if any) and resjunk TLEs can
+ * be added at the end to represent ORDER BY expressions that are not also
+ * arguments. As in a top-level Query, the TLEs can be marked with
+ * ressortgroupref indexes to let them be referenced by SortGroupClause
+ * entries in the aggorder and/or aggdistinct lists. This represents ORDER BY
+ * and DISTINCT operations to be applied to the aggregate input rows before
+ * they are passed to the transition function. The grammar only allows a
+ * simple "DISTINCT" specifier for the arguments, but we use the full
+ * query-level representation to allow more code sharing.
+ *
+ * For an ordered-set aggregate, the args list represents the WITHIN GROUP
+ * (aggregated) arguments, all of which will be listed in the aggorder list.
+ * DISTINCT is not supported in this case, so aggdistinct will be NIL.
+ * The direct arguments appear in aggdirectargs (as a list of plain
+ * expressions, not TargetEntry nodes).
+ *
+ * aggtranstype is the data type of the state transition values for this
+ * aggregate (resolved to an actual type, if agg's transtype is polymorphic).
+ * This is determined during planning and is InvalidOid before that.
+ *
+ * aggargtypes is an OID list of the data types of the direct and regular
+ * arguments. Normally it's redundant with the aggdirectargs and args lists,
+ * but in a combining aggregate, it's not because the args list has been
+ * replaced with a single argument representing the partial-aggregate
+ * transition values.
+ *
+ * aggsplit indicates the expected partial-aggregation mode for the Aggref's
+ * parent plan node. It's always set to AGGSPLIT_SIMPLE in the parser, but
+ * the planner might change it to something else. We use this mainly as
+ * a crosscheck that the Aggrefs match the plan; but note that when aggsplit
+ * indicates a non-final mode, aggtype reflects the transition data type
+ * not the SQL-level output type of the aggregate.
+ */
+typedef struct Aggref
+{
+ Expr xpr;
+ Oid aggfnoid; /* pg_proc Oid of the aggregate */
+ Oid aggtype; /* type Oid of result of the aggregate */
+ Oid aggcollid; /* OID of collation of result */
+ Oid inputcollid; /* OID of collation that function should use */
+ Oid aggtranstype; /* type Oid of aggregate's transition value */
+ List *aggargtypes; /* type Oids of direct and aggregated args */
+ List *aggdirectargs; /* direct arguments, if an ordered-set agg */
+ List *args; /* aggregated arguments and sort expressions */
+ List *aggorder; /* ORDER BY (list of SortGroupClause) */
+ List *aggdistinct; /* DISTINCT (list of SortGroupClause) */
+ Expr *aggfilter; /* FILTER expression, if any */
+ bool aggstar; /* true if argument list was really '*' */
+ bool aggvariadic; /* true if variadic arguments have been
+ * combined into an array last argument */
+ char aggkind; /* aggregate kind (see pg_aggregate.h) */
+ Index agglevelsup; /* > 0 if agg belongs to outer query */
+ AggSplit aggsplit; /* expected agg-splitting mode of parent Agg */
+ int location; /* token location, or -1 if unknown */
+} Aggref;
+
+/*
+ * GroupingFunc
+ *
+ * A GroupingFunc is a GROUPING(...) expression, which behaves in many ways
+ * like an aggregate function (e.g. it "belongs" to a specific query level,
+ * which might not be the one immediately containing it), but also differs in
+ * an important respect: it never evaluates its arguments, they merely
+ * designate expressions from the GROUP BY clause of the query level to which
+ * it belongs.
+ *
+ * The spec defines the evaluation of GROUPING() purely by syntactic
+ * replacement, but we make it a real expression for optimization purposes so
+ * that one Agg node can handle multiple grouping sets at once. Evaluating the
+ * result only needs the column positions to check against the grouping set
+ * being projected. However, for EXPLAIN to produce meaningful output, we have
+ * to keep the original expressions around, since expression deparse does not
+ * give us any feasible way to get at the GROUP BY clause.
+ *
+ * Also, we treat two GroupingFunc nodes as equal if they have equal arguments
+ * lists and agglevelsup, without comparing the refs and cols annotations.
+ *
+ * In raw parse output we have only the args list; parse analysis fills in the
+ * refs list, and the planner fills in the cols list.
+ */
+typedef struct GroupingFunc
+{
+ Expr xpr;
+ List *args; /* arguments, not evaluated but kept for
+ * benefit of EXPLAIN etc. */
+ List *refs; /* ressortgrouprefs of arguments */
+ List *cols; /* actual column positions set by planner */
+ Index agglevelsup; /* same as Aggref.agglevelsup */
+ int location; /* token location */
+} GroupingFunc;
+
+/*
+ * WindowFunc
+ */
+typedef struct WindowFunc
+{
+ Expr xpr;
+ Oid winfnoid; /* pg_proc Oid of the function */
+ Oid wintype; /* type Oid of result of the window function */
+ Oid wincollid; /* OID of collation of result */
+ Oid inputcollid; /* OID of collation that function should use */
+ List *args; /* arguments to the window function */
+ Expr *aggfilter; /* FILTER expression, if any */
+ Index winref; /* index of associated WindowClause */
+ bool winstar; /* true if argument list was really '*' */
+ bool winagg; /* is function a simple aggregate? */
+ int location; /* token location, or -1 if unknown */
+} WindowFunc;
+
+/* ----------------
+ * SubscriptingRef: describes a subscripting operation over a container
+ * (array, etc).
+ *
+ * A SubscriptingRef can describe fetching a single element from a container,
+ * fetching a part of container (e.g. array slice), storing a single element into
+ * a container, or storing a slice. The "store" cases work with an
+ * initial container value and a source value that is inserted into the
+ * appropriate part of the container; the result of the operation is an
+ * entire new modified container value.
+ *
+ * If reflowerindexpr = NIL, then we are fetching or storing a single container
+ * element at the subscripts given by refupperindexpr. Otherwise we are
+ * fetching or storing a container slice, that is a rectangular subcontainer
+ * with lower and upper bounds given by the index expressions.
+ * reflowerindexpr must be the same length as refupperindexpr when it
+ * is not NIL.
+ *
+ * In the slice case, individual expressions in the subscript lists can be
+ * NULL, meaning "substitute the array's current lower or upper bound".
+ *
+ * Note: the result datatype is the element type when fetching a single
+ * element; but it is the array type when doing subarray fetch or either
+ * type of store.
+ *
+ * Note: for the cases where a container is returned, if refexpr yields a R/W
+ * expanded container, then the implementation is allowed to modify that object
+ * in-place and return the same object.)
+ * ----------------
+ */
+typedef struct SubscriptingRef
+{
+ Expr xpr;
+ Oid refcontainertype; /* type of the container proper */
+ Oid refelemtype; /* type of the container elements */
+ int32 reftypmod; /* typmod of the container (and elements too) */
+ Oid refcollid; /* OID of collation, or InvalidOid if none */
+ List *refupperindexpr; /* expressions that evaluate to upper
+ * container indexes */
+ List *reflowerindexpr; /* expressions that evaluate to lower
+ * container indexes, or NIL for single
+ * container element */
+ Expr *refexpr; /* the expression that evaluates to a
+ * container value */
+
+ Expr *refassgnexpr; /* expression for the source value, or NULL if
+ * fetch */
+} SubscriptingRef;
+
+/*
+ * CoercionContext - distinguishes the allowed set of type casts
+ *
+ * NB: ordering of the alternatives is significant; later (larger) values
+ * allow more casts than earlier ones.
+ */
+typedef enum CoercionContext
+{
+ COERCION_IMPLICIT, /* coercion in context of expression */
+ COERCION_ASSIGNMENT, /* coercion in context of assignment */
+ COERCION_EXPLICIT /* explicit cast operation */
+} CoercionContext;
+
+/*
+ * CoercionForm - how to display a node that could have come from a cast
+ *
+ * NB: equal() ignores CoercionForm fields, therefore this *must* not carry
+ * any semantically significant information. We need that behavior so that
+ * the planner will consider equivalent implicit and explicit casts to be
+ * equivalent. In cases where those actually behave differently, the coercion
+ * function's arguments will be different.
+ */
+typedef enum CoercionForm
+{
+ COERCE_EXPLICIT_CALL, /* display as a function call */
+ COERCE_EXPLICIT_CAST, /* display as an explicit cast */
+ COERCE_IMPLICIT_CAST /* implicit cast, so hide it */
+} CoercionForm;
+
+/*
+ * FuncExpr - expression node for a function call
+ */
+typedef struct FuncExpr
+{
+ Expr xpr;
+ Oid funcid; /* PG_PROC OID of the function */
+ Oid funcresulttype; /* PG_TYPE OID of result value */
+ bool funcretset; /* true if function returns set */
+ bool funcvariadic; /* true if variadic arguments have been
+ * combined into an array last argument */
+ CoercionForm funcformat; /* how to display this function call */
+ Oid funccollid; /* OID of collation of result */
+ Oid inputcollid; /* OID of collation that function should use */
+ List *args; /* arguments to the function */
+ int location; /* token location, or -1 if unknown */
+} FuncExpr;
+
+/*
+ * NamedArgExpr - a named argument of a function
+ *
+ * This node type can only appear in the args list of a FuncCall or FuncExpr
+ * node. We support pure positional call notation (no named arguments),
+ * named notation (all arguments are named), and mixed notation (unnamed
+ * arguments followed by named ones).
+ *
+ * Parse analysis sets argnumber to the positional index of the argument,
+ * but doesn't rearrange the argument list.
+ *
+ * The planner will convert argument lists to pure positional notation
+ * during expression preprocessing, so execution never sees a NamedArgExpr.
+ */
+typedef struct NamedArgExpr
+{
+ Expr xpr;
+ Expr *arg; /* the argument expression */
+ char *name; /* the name */
+ int argnumber; /* argument's number in positional notation */
+ int location; /* argument name location, or -1 if unknown */
+} NamedArgExpr;
+
+/*
+ * OpExpr - expression node for an operator invocation
+ *
+ * Semantically, this is essentially the same as a function call.
+ *
+ * Note that opfuncid is not necessarily filled in immediately on creation
+ * of the node. The planner makes sure it is valid before passing the node
+ * tree to the executor, but during parsing/planning opfuncid can be 0.
+ */
+typedef struct OpExpr
+{
+ Expr xpr;
+ Oid opno; /* PG_OPERATOR OID of the operator */
+ Oid opfuncid; /* PG_PROC OID of underlying function */
+ Oid opresulttype; /* PG_TYPE OID of result value */
+ bool opretset; /* true if operator returns set */
+ Oid opcollid; /* OID of collation of result */
+ Oid inputcollid; /* OID of collation that operator should use */
+ List *args; /* arguments to the operator (1 or 2) */
+ int location; /* token location, or -1 if unknown */
+} OpExpr;
+
+/*
+ * DistinctExpr - expression node for "x IS DISTINCT FROM y"
+ *
+ * Except for the nodetag, this is represented identically to an OpExpr
+ * referencing the "=" operator for x and y.
+ * We use "=", not the more obvious "<>", because more datatypes have "="
+ * than "<>". This means the executor must invert the operator result.
+ * Note that the operator function won't be called at all if either input
+ * is NULL, since then the result can be determined directly.
+ */
+typedef OpExpr DistinctExpr;
+
+/*
+ * NullIfExpr - a NULLIF expression
+ *
+ * Like DistinctExpr, this is represented the same as an OpExpr referencing
+ * the "=" operator for x and y.
+ */
+typedef OpExpr NullIfExpr;
+
+/*
+ * ScalarArrayOpExpr - expression node for "scalar op ANY/ALL (array)"
+ *
+ * The operator must yield boolean. It is applied to the left operand
+ * and each element of the righthand array, and the results are combined
+ * with OR or AND (for ANY or ALL respectively). The node representation
+ * is almost the same as for the underlying operator, but we need a useOr
+ * flag to remember whether it's ANY or ALL, and we don't have to store
+ * the result type (or the collation) because it must be boolean.
+ */
+typedef struct ScalarArrayOpExpr
+{
+ Expr xpr;
+ Oid opno; /* PG_OPERATOR OID of the operator */
+ Oid opfuncid; /* PG_PROC OID of underlying function */
+ bool useOr; /* true for ANY, false for ALL */
+ Oid inputcollid; /* OID of collation that operator should use */
+ List *args; /* the scalar and array operands */
+ int location; /* token location, or -1 if unknown */
+} ScalarArrayOpExpr;
+
+/*
+ * BoolExpr - expression node for the basic Boolean operators AND, OR, NOT
+ *
+ * Notice the arguments are given as a List. For NOT, of course the list
+ * must always have exactly one element. For AND and OR, there can be two
+ * or more arguments.
+ */
+typedef enum BoolExprType
+{
+ AND_EXPR, OR_EXPR, NOT_EXPR
+} BoolExprType;
+
+typedef struct BoolExpr
+{
+ Expr xpr;
+ BoolExprType boolop;
+ List *args; /* arguments to this expression */
+ int location; /* token location, or -1 if unknown */
+} BoolExpr;
+
+/*
+ * SubLink
+ *
+ * A SubLink represents a subselect appearing in an expression, and in some
+ * cases also the combining operator(s) just above it. The subLinkType
+ * indicates the form of the expression represented:
+ * EXISTS_SUBLINK EXISTS(SELECT ...)
+ * ALL_SUBLINK (lefthand) op ALL (SELECT ...)
+ * ANY_SUBLINK (lefthand) op ANY (SELECT ...)
+ * ROWCOMPARE_SUBLINK (lefthand) op (SELECT ...)
+ * EXPR_SUBLINK (SELECT with single targetlist item ...)
+ * MULTIEXPR_SUBLINK (SELECT with multiple targetlist items ...)
+ * ARRAY_SUBLINK ARRAY(SELECT with single targetlist item ...)
+ * CTE_SUBLINK WITH query (never actually part of an expression)
+ * For ALL, ANY, and ROWCOMPARE, the lefthand is a list of expressions of the
+ * same length as the subselect's targetlist. ROWCOMPARE will *always* have
+ * a list with more than one entry; if the subselect has just one target
+ * then the parser will create an EXPR_SUBLINK instead (and any operator
+ * above the subselect will be represented separately).
+ * ROWCOMPARE, EXPR, and MULTIEXPR require the subselect to deliver at most
+ * one row (if it returns no rows, the result is NULL).
+ * ALL, ANY, and ROWCOMPARE require the combining operators to deliver boolean
+ * results. ALL and ANY combine the per-row results using AND and OR
+ * semantics respectively.
+ * ARRAY requires just one target column, and creates an array of the target
+ * column's type using any number of rows resulting from the subselect.
+ *
+ * SubLink is classed as an Expr node, but it is not actually executable;
+ * it must be replaced in the expression tree by a SubPlan node during
+ * planning.
+ *
+ * NOTE: in the raw output of gram.y, testexpr contains just the raw form
+ * of the lefthand expression (if any), and operName is the String name of
+ * the combining operator. Also, subselect is a raw parsetree. During parse
+ * analysis, the parser transforms testexpr into a complete boolean expression
+ * that compares the lefthand value(s) to PARAM_SUBLINK nodes representing the
+ * output columns of the subselect. And subselect is transformed to a Query.
+ * This is the representation seen in saved rules and in the rewriter.
+ *
+ * In EXISTS, EXPR, MULTIEXPR, and ARRAY SubLinks, testexpr and operName
+ * are unused and are always null.
+ *
+ * subLinkId is currently used only for MULTIEXPR SubLinks, and is zero in
+ * other SubLinks. This number identifies different multiple-assignment
+ * subqueries within an UPDATE statement's SET list. It is unique only
+ * within a particular targetlist. The output column(s) of the MULTIEXPR
+ * are referenced by PARAM_MULTIEXPR Params appearing elsewhere in the tlist.
+ *
+ * The CTE_SUBLINK case never occurs in actual SubLink nodes, but it is used
+ * in SubPlans generated for WITH subqueries.
+ */
+typedef enum SubLinkType
+{
+ EXISTS_SUBLINK,
+ ALL_SUBLINK,
+ ANY_SUBLINK,
+ ROWCOMPARE_SUBLINK,
+ EXPR_SUBLINK,
+ MULTIEXPR_SUBLINK,
+ ARRAY_SUBLINK,
+ CTE_SUBLINK /* for SubPlans only */
+} SubLinkType;
+
+
+typedef struct SubLink
+{
+ Expr xpr;
+ SubLinkType subLinkType; /* see above */
+ int subLinkId; /* ID (1..n); 0 if not MULTIEXPR */
+ Node *testexpr; /* outer-query test for ALL/ANY/ROWCOMPARE */
+ List *operName; /* originally specified operator name */
+ Node *subselect; /* subselect as Query* or raw parsetree */
+ int location; /* token location, or -1 if unknown */
+} SubLink;
+
+/*
+ * SubPlan - executable expression node for a subplan (sub-SELECT)
+ *
+ * The planner replaces SubLink nodes in expression trees with SubPlan
+ * nodes after it has finished planning the subquery. SubPlan references
+ * a sub-plantree stored in the subplans list of the toplevel PlannedStmt.
+ * (We avoid a direct link to make it easier to copy expression trees
+ * without causing multiple processing of the subplan.)
+ *
+ * In an ordinary subplan, testexpr points to an executable expression
+ * (OpExpr, an AND/OR tree of OpExprs, or RowCompareExpr) for the combining
+ * operator(s); the left-hand arguments are the original lefthand expressions,
+ * and the right-hand arguments are PARAM_EXEC Param nodes representing the
+ * outputs of the sub-select. (NOTE: runtime coercion functions may be
+ * inserted as well.) This is just the same expression tree as testexpr in
+ * the original SubLink node, but the PARAM_SUBLINK nodes are replaced by
+ * suitably numbered PARAM_EXEC nodes.
+ *
+ * If the sub-select becomes an initplan rather than a subplan, the executable
+ * expression is part of the outer plan's expression tree (and the SubPlan
+ * node itself is not, but rather is found in the outer plan's initPlan
+ * list). In this case testexpr is NULL to avoid duplication.
+ *
+ * The planner also derives lists of the values that need to be passed into
+ * and out of the subplan. Input values are represented as a list "args" of
+ * expressions to be evaluated in the outer-query context (currently these
+ * args are always just Vars, but in principle they could be any expression).
+ * The values are assigned to the global PARAM_EXEC params indexed by parParam
+ * (the parParam and args lists must have the same ordering). setParam is a
+ * list of the PARAM_EXEC params that are computed by the sub-select, if it
+ * is an initplan; they are listed in order by sub-select output column
+ * position. (parParam and setParam are integer Lists, not Bitmapsets,
+ * because their ordering is significant.)
+ *
+ * Also, the planner computes startup and per-call costs for use of the
+ * SubPlan. Note that these include the cost of the subquery proper,
+ * evaluation of the testexpr if any, and any hashtable management overhead.
+ */
+typedef struct SubPlan
+{
+ Expr xpr;
+ /* Fields copied from original SubLink: */
+ SubLinkType subLinkType; /* see above */
+ /* The combining operators, transformed to an executable expression: */
+ Node *testexpr; /* OpExpr or RowCompareExpr expression tree */
+ List *paramIds; /* IDs of Params embedded in the above */
+ /* Identification of the Plan tree to use: */
+ int plan_id; /* Index (from 1) in PlannedStmt.subplans */
+ /* Identification of the SubPlan for EXPLAIN and debugging purposes: */
+ char *plan_name; /* A name assigned during planning */
+ /* Extra data useful for determining subplan's output type: */
+ Oid firstColType; /* Type of first column of subplan result */
+ int32 firstColTypmod; /* Typmod of first column of subplan result */
+ Oid firstColCollation; /* Collation of first column of subplan
+ * result */
+ /* Information about execution strategy: */
+ bool useHashTable; /* true to store subselect output in a hash
+ * table (implies we are doing "IN") */
+ bool unknownEqFalse; /* true if it's okay to return FALSE when the
+ * spec result is UNKNOWN; this allows much
+ * simpler handling of null values */
+ bool parallel_safe; /* is the subplan parallel-safe? */
+ /* Note: parallel_safe does not consider contents of testexpr or args */
+ /* Information for passing params into and out of the subselect: */
+ /* setParam and parParam are lists of integers (param IDs) */
+ List *setParam; /* initplan subqueries have to set these
+ * Params for parent plan */
+ List *parParam; /* indices of input Params from parent plan */
+ List *args; /* exprs to pass as parParam values */
+ /* Estimated execution costs: */
+ Cost startup_cost; /* one-time setup cost */
+ Cost per_call_cost; /* cost for each subplan evaluation */
+} SubPlan;
+
+/*
+ * AlternativeSubPlan - expression node for a choice among SubPlans
+ *
+ * The subplans are given as a List so that the node definition need not
+ * change if there's ever more than two alternatives. For the moment,
+ * though, there are always exactly two; and the first one is the fast-start
+ * plan.
+ */
+typedef struct AlternativeSubPlan
+{
+ Expr xpr;
+ List *subplans; /* SubPlan(s) with equivalent results */
+} AlternativeSubPlan;
+
+/* ----------------
+ * FieldSelect
+ *
+ * FieldSelect represents the operation of extracting one field from a tuple
+ * value. At runtime, the input expression is expected to yield a rowtype
+ * Datum. The specified field number is extracted and returned as a Datum.
+ * ----------------
+ */
+
+typedef struct FieldSelect
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ AttrNumber fieldnum; /* attribute number of field to extract */
+ Oid resulttype; /* type of the field (result type of this
+ * node) */
+ int32 resulttypmod; /* output typmod (usually -1) */
+ Oid resultcollid; /* OID of collation of the field */
+} FieldSelect;
+
+/* ----------------
+ * FieldStore
+ *
+ * FieldStore represents the operation of modifying one field in a tuple
+ * value, yielding a new tuple value (the input is not touched!). Like
+ * the assign case of SubscriptingRef, this is used to implement UPDATE of a
+ * portion of a column.
+ *
+ * resulttype is always a named composite type (not a domain). To update
+ * a composite domain value, apply CoerceToDomain to the FieldStore.
+ *
+ * A single FieldStore can actually represent updates of several different
+ * fields. The parser only generates FieldStores with single-element lists,
+ * but the planner will collapse multiple updates of the same base column
+ * into one FieldStore.
+ * ----------------
+ */
+
+typedef struct FieldStore
+{
+ Expr xpr;
+ Expr *arg; /* input tuple value */
+ List *newvals; /* new value(s) for field(s) */
+ List *fieldnums; /* integer list of field attnums */
+ Oid resulttype; /* type of result (same as type of arg) */
+ /* Like RowExpr, we deliberately omit a typmod and collation here */
+} FieldStore;
+
+/* ----------------
+ * RelabelType
+ *
+ * RelabelType represents a "dummy" type coercion between two binary-
+ * compatible datatypes, such as reinterpreting the result of an OID
+ * expression as an int4. It is a no-op at runtime; we only need it
+ * to provide a place to store the correct type to be attributed to
+ * the expression result during type resolution. (We can't get away
+ * with just overwriting the type field of the input expression node,
+ * so we need a separate node to show the coercion's result type.)
+ * ----------------
+ */
+
+typedef struct RelabelType
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ Oid resulttype; /* output type of coercion expression */
+ int32 resulttypmod; /* output typmod (usually -1) */
+ Oid resultcollid; /* OID of collation, or InvalidOid if none */
+ CoercionForm relabelformat; /* how to display this node */
+ int location; /* token location, or -1 if unknown */
+} RelabelType;
+
+/* ----------------
+ * CoerceViaIO
+ *
+ * CoerceViaIO represents a type coercion between two types whose textual
+ * representations are compatible, implemented by invoking the source type's
+ * typoutput function then the destination type's typinput function.
+ * ----------------
+ */
+
+typedef struct CoerceViaIO
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ Oid resulttype; /* output type of coercion */
+ /* output typmod is not stored, but is presumed -1 */
+ Oid resultcollid; /* OID of collation, or InvalidOid if none */
+ CoercionForm coerceformat; /* how to display this node */
+ int location; /* token location, or -1 if unknown */
+} CoerceViaIO;
+
+/* ----------------
+ * ArrayCoerceExpr
+ *
+ * ArrayCoerceExpr represents a type coercion from one array type to another,
+ * which is implemented by applying the per-element coercion expression
+ * "elemexpr" to each element of the source array. Within elemexpr, the
+ * source element is represented by a CaseTestExpr node. Note that even if
+ * elemexpr is a no-op (that is, just CaseTestExpr + RelabelType), the
+ * coercion still requires some effort: we have to fix the element type OID
+ * stored in the array header.
+ * ----------------
+ */
+
+typedef struct ArrayCoerceExpr
+{
+ Expr xpr;
+ Expr *arg; /* input expression (yields an array) */
+ Expr *elemexpr; /* expression representing per-element work */
+ Oid resulttype; /* output type of coercion (an array type) */
+ int32 resulttypmod; /* output typmod (also element typmod) */
+ Oid resultcollid; /* OID of collation, or InvalidOid if none */
+ CoercionForm coerceformat; /* how to display this node */
+ int location; /* token location, or -1 if unknown */
+} ArrayCoerceExpr;
+
+/* ----------------
+ * ConvertRowtypeExpr
+ *
+ * ConvertRowtypeExpr represents a type coercion from one composite type
+ * to another, where the source type is guaranteed to contain all the columns
+ * needed for the destination type plus possibly others; the columns need not
+ * be in the same positions, but are matched up by name. This is primarily
+ * used to convert a whole-row value of an inheritance child table into a
+ * valid whole-row value of its parent table's rowtype. Both resulttype
+ * and the exposed type of "arg" must be named composite types (not domains).
+ * ----------------
+ */
+
+typedef struct ConvertRowtypeExpr
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ Oid resulttype; /* output type (always a composite type) */
+ /* Like RowExpr, we deliberately omit a typmod and collation here */
+ CoercionForm convertformat; /* how to display this node */
+ int location; /* token location, or -1 if unknown */
+} ConvertRowtypeExpr;
+
+/*----------
+ * CollateExpr - COLLATE
+ *
+ * The planner replaces CollateExpr with RelabelType during expression
+ * preprocessing, so execution never sees a CollateExpr.
+ *----------
+ */
+typedef struct CollateExpr
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ Oid collOid; /* collation's OID */
+ int location; /* token location, or -1 if unknown */
+} CollateExpr;
+
+/*----------
+ * CaseExpr - a CASE expression
+ *
+ * We support two distinct forms of CASE expression:
+ * CASE WHEN boolexpr THEN expr [ WHEN boolexpr THEN expr ... ]
+ * CASE testexpr WHEN compexpr THEN expr [ WHEN compexpr THEN expr ... ]
+ * These are distinguishable by the "arg" field being NULL in the first case
+ * and the testexpr in the second case.
+ *
+ * In the raw grammar output for the second form, the condition expressions
+ * of the WHEN clauses are just the comparison values. Parse analysis
+ * converts these to valid boolean expressions of the form
+ * CaseTestExpr '=' compexpr
+ * where the CaseTestExpr node is a placeholder that emits the correct
+ * value at runtime. This structure is used so that the testexpr need be
+ * evaluated only once. Note that after parse analysis, the condition
+ * expressions always yield boolean.
+ *
+ * Note: we can test whether a CaseExpr has been through parse analysis
+ * yet by checking whether casetype is InvalidOid or not.
+ *----------
+ */
+typedef struct CaseExpr
+{
+ Expr xpr;
+ Oid casetype; /* type of expression result */
+ Oid casecollid; /* OID of collation, or InvalidOid if none */
+ Expr *arg; /* implicit equality comparison argument */
+ List *args; /* the arguments (list of WHEN clauses) */
+ Expr *defresult; /* the default result (ELSE clause) */
+ int location; /* token location, or -1 if unknown */
+} CaseExpr;
+
+/*
+ * CaseWhen - one arm of a CASE expression
+ */
+typedef struct CaseWhen
+{
+ Expr xpr;
+ Expr *expr; /* condition expression */
+ Expr *result; /* substitution result */
+ int location; /* token location, or -1 if unknown */
+} CaseWhen;
+
+/*
+ * Placeholder node for the test value to be processed by a CASE expression.
+ * This is effectively like a Param, but can be implemented more simply
+ * since we need only one replacement value at a time.
+ *
+ * We also abuse this node type for some other purposes, including:
+ * * Placeholder for the current array element value in ArrayCoerceExpr;
+ * see build_coercion_expression().
+ * * Nested FieldStore/SubscriptingRef assignment expressions in INSERT/UPDATE;
+ * see transformAssignmentIndirection().
+ *
+ * The uses in CaseExpr and ArrayCoerceExpr are safe only to the extent that
+ * there is not any other CaseExpr or ArrayCoerceExpr between the value source
+ * node and its child CaseTestExpr(s). This is true in the parse analysis
+ * output, but the planner's function-inlining logic has to be careful not to
+ * break it.
+ *
+ * The nested-assignment-expression case is safe because the only node types
+ * that can be above such CaseTestExprs are FieldStore and SubscriptingRef.
+ */
+typedef struct CaseTestExpr
+{
+ Expr xpr;
+ Oid typeId; /* type for substituted value */
+ int32 typeMod; /* typemod for substituted value */
+ Oid collation; /* collation for the substituted value */
+} CaseTestExpr;
+
+/*
+ * ArrayExpr - an ARRAY[] expression
+ *
+ * Note: if multidims is false, the constituent expressions all yield the
+ * scalar type identified by element_typeid. If multidims is true, the
+ * constituent expressions all yield arrays of element_typeid (ie, the same
+ * type as array_typeid); at runtime we must check for compatible subscripts.
+ */
+typedef struct ArrayExpr
+{
+ Expr xpr;
+ Oid array_typeid; /* type of expression result */
+ Oid array_collid; /* OID of collation, or InvalidOid if none */
+ Oid element_typeid; /* common type of array elements */
+ List *elements; /* the array elements or sub-arrays */
+ bool multidims; /* true if elements are sub-arrays */
+ int location; /* token location, or -1 if unknown */
+} ArrayExpr;
+
+/*
+ * RowExpr - a ROW() expression
+ *
+ * Note: the list of fields must have a one-for-one correspondence with
+ * physical fields of the associated rowtype, although it is okay for it
+ * to be shorter than the rowtype. That is, the N'th list element must
+ * match up with the N'th physical field. When the N'th physical field
+ * is a dropped column (attisdropped) then the N'th list element can just
+ * be a NULL constant. (This case can only occur for named composite types,
+ * not RECORD types, since those are built from the RowExpr itself rather
+ * than vice versa.) It is important not to assume that length(args) is
+ * the same as the number of columns logically present in the rowtype.
+ *
+ * colnames provides field names in cases where the names can't easily be
+ * obtained otherwise. Names *must* be provided if row_typeid is RECORDOID.
+ * If row_typeid identifies a known composite type, colnames can be NIL to
+ * indicate the type's cataloged field names apply. Note that colnames can
+ * be non-NIL even for a composite type, and typically is when the RowExpr
+ * was created by expanding a whole-row Var. This is so that we can retain
+ * the column alias names of the RTE that the Var referenced (which would
+ * otherwise be very difficult to extract from the parsetree). Like the
+ * args list, colnames is one-for-one with physical fields of the rowtype.
+ */
+typedef struct RowExpr
+{
+ Expr xpr;
+ List *args; /* the fields */
+ Oid row_typeid; /* RECORDOID or a composite type's ID */
+
+ /*
+ * row_typeid cannot be a domain over composite, only plain composite. To
+ * create a composite domain value, apply CoerceToDomain to the RowExpr.
+ *
+ * Note: we deliberately do NOT store a typmod. Although a typmod will be
+ * associated with specific RECORD types at runtime, it will differ for
+ * different backends, and so cannot safely be stored in stored
+ * parsetrees. We must assume typmod -1 for a RowExpr node.
+ *
+ * We don't need to store a collation either. The result type is
+ * necessarily composite, and composite types never have a collation.
+ */
+ CoercionForm row_format; /* how to display this node */
+ List *colnames; /* list of String, or NIL */
+ int location; /* token location, or -1 if unknown */
+} RowExpr;
+
+/*
+ * RowCompareExpr - row-wise comparison, such as (a, b) <= (1, 2)
+ *
+ * We support row comparison for any operator that can be determined to
+ * act like =, <>, <, <=, >, or >= (we determine this by looking for the
+ * operator in btree opfamilies). Note that the same operator name might
+ * map to a different operator for each pair of row elements, since the
+ * element datatypes can vary.
+ *
+ * A RowCompareExpr node is only generated for the < <= > >= cases;
+ * the = and <> cases are translated to simple AND or OR combinations
+ * of the pairwise comparisons. However, we include = and <> in the
+ * RowCompareType enum for the convenience of parser logic.
+ */
+typedef enum RowCompareType
+{
+ /* Values of this enum are chosen to match btree strategy numbers */
+ ROWCOMPARE_LT = 1, /* BTLessStrategyNumber */
+ ROWCOMPARE_LE = 2, /* BTLessEqualStrategyNumber */
+ ROWCOMPARE_EQ = 3, /* BTEqualStrategyNumber */
+ ROWCOMPARE_GE = 4, /* BTGreaterEqualStrategyNumber */
+ ROWCOMPARE_GT = 5, /* BTGreaterStrategyNumber */
+ ROWCOMPARE_NE = 6 /* no such btree strategy */
+} RowCompareType;
+
+typedef struct RowCompareExpr
+{
+ Expr xpr;
+ RowCompareType rctype; /* LT LE GE or GT, never EQ or NE */
+ List *opnos; /* OID list of pairwise comparison ops */
+ List *opfamilies; /* OID list of containing operator families */
+ List *inputcollids; /* OID list of collations for comparisons */
+ List *largs; /* the left-hand input arguments */
+ List *rargs; /* the right-hand input arguments */
+} RowCompareExpr;
+
+/*
+ * CoalesceExpr - a COALESCE expression
+ */
+typedef struct CoalesceExpr
+{
+ Expr xpr;
+ Oid coalescetype; /* type of expression result */
+ Oid coalescecollid; /* OID of collation, or InvalidOid if none */
+ List *args; /* the arguments */
+ int location; /* token location, or -1 if unknown */
+} CoalesceExpr;
+
+/*
+ * MinMaxExpr - a GREATEST or LEAST function
+ */
+typedef enum MinMaxOp
+{
+ IS_GREATEST,
+ IS_LEAST
+} MinMaxOp;
+
+typedef struct MinMaxExpr
+{
+ Expr xpr;
+ Oid minmaxtype; /* common type of arguments and result */
+ Oid minmaxcollid; /* OID of collation of result */
+ Oid inputcollid; /* OID of collation that function should use */
+ MinMaxOp op; /* function to execute */
+ List *args; /* the arguments */
+ int location; /* token location, or -1 if unknown */
+} MinMaxExpr;
+
+/*
+ * SQLValueFunction - parameterless functions with special grammar productions
+ *
+ * The SQL standard categorizes some of these as <datetime value function>
+ * and others as <general value specification>. We call 'em SQLValueFunctions
+ * for lack of a better term. We store type and typmod of the result so that
+ * some code doesn't need to know each function individually, and because
+ * we would need to store typmod anyway for some of the datetime functions.
+ * Note that currently, all variants return non-collating datatypes, so we do
+ * not need a collation field; also, all these functions are stable.
+ */
+typedef enum SQLValueFunctionOp
+{
+ SVFOP_CURRENT_DATE,
+ SVFOP_CURRENT_TIME,
+ SVFOP_CURRENT_TIME_N,
+ SVFOP_CURRENT_TIMESTAMP,
+ SVFOP_CURRENT_TIMESTAMP_N,
+ SVFOP_LOCALTIME,
+ SVFOP_LOCALTIME_N,
+ SVFOP_LOCALTIMESTAMP,
+ SVFOP_LOCALTIMESTAMP_N,
+ SVFOP_CURRENT_ROLE,
+ SVFOP_CURRENT_USER,
+ SVFOP_USER,
+ SVFOP_SESSION_USER,
+ SVFOP_CURRENT_CATALOG,
+ SVFOP_CURRENT_SCHEMA
+} SQLValueFunctionOp;
+
+typedef struct SQLValueFunction
+{
+ Expr xpr;
+ SQLValueFunctionOp op; /* which function this is */
+ Oid type; /* result type/typmod */
+ int32 typmod;
+ int location; /* token location, or -1 if unknown */
+} SQLValueFunction;
+
+/*
+ * XmlExpr - various SQL/XML functions requiring special grammar productions
+ *
+ * 'name' carries the "NAME foo" argument (already XML-escaped).
+ * 'named_args' and 'arg_names' represent an xml_attribute list.
+ * 'args' carries all other arguments.
+ *
+ * Note: result type/typmod/collation are not stored, but can be deduced
+ * from the XmlExprOp. The type/typmod fields are just used for display
+ * purposes, and are NOT necessarily the true result type of the node.
+ */
+typedef enum XmlExprOp
+{
+ IS_XMLCONCAT, /* XMLCONCAT(args) */
+ IS_XMLELEMENT, /* XMLELEMENT(name, xml_attributes, args) */
+ IS_XMLFOREST, /* XMLFOREST(xml_attributes) */
+ IS_XMLPARSE, /* XMLPARSE(text, is_doc, preserve_ws) */
+ IS_XMLPI, /* XMLPI(name [, args]) */
+ IS_XMLROOT, /* XMLROOT(xml, version, standalone) */
+ IS_XMLSERIALIZE, /* XMLSERIALIZE(is_document, xmlval) */
+ IS_DOCUMENT /* xmlval IS DOCUMENT */
+} XmlExprOp;
+
+typedef enum
+{
+ XMLOPTION_DOCUMENT,
+ XMLOPTION_CONTENT
+} XmlOptionType;
+
+typedef struct XmlExpr
+{
+ Expr xpr;
+ XmlExprOp op; /* xml function ID */
+ char *name; /* name in xml(NAME foo ...) syntaxes */
+ List *named_args; /* non-XML expressions for xml_attributes */
+ List *arg_names; /* parallel list of Value strings */
+ List *args; /* list of expressions */
+ XmlOptionType xmloption; /* DOCUMENT or CONTENT */
+ Oid type; /* target type/typmod for XMLSERIALIZE */
+ int32 typmod;
+ int location; /* token location, or -1 if unknown */
+} XmlExpr;
+
+/* ----------------
+ * NullTest
+ *
+ * NullTest represents the operation of testing a value for NULLness.
+ * The appropriate test is performed and returned as a boolean Datum.
+ *
+ * When argisrow is false, this simply represents a test for the null value.
+ *
+ * When argisrow is true, the input expression must yield a rowtype, and
+ * the node implements "row IS [NOT] NULL" per the SQL standard. This
+ * includes checking individual fields for NULLness when the row datum
+ * itself isn't NULL.
+ *
+ * NOTE: the combination of a rowtype input and argisrow==false does NOT
+ * correspond to the SQL notation "row IS [NOT] NULL"; instead, this case
+ * represents the SQL notation "row IS [NOT] DISTINCT FROM NULL".
+ * ----------------
+ */
+
+typedef enum NullTestType
+{
+ IS_NULL, IS_NOT_NULL
+} NullTestType;
+
+typedef struct NullTest
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ NullTestType nulltesttype; /* IS NULL, IS NOT NULL */
+ bool argisrow; /* T to perform field-by-field null checks */
+ int location; /* token location, or -1 if unknown */
+} NullTest;
+
+/*
+ * BooleanTest
+ *
+ * BooleanTest represents the operation of determining whether a boolean
+ * is TRUE, FALSE, or UNKNOWN (ie, NULL). All six meaningful combinations
+ * are supported. Note that a NULL input does *not* cause a NULL result.
+ * The appropriate test is performed and returned as a boolean Datum.
+ */
+
+typedef enum BoolTestType
+{
+ IS_TRUE, IS_NOT_TRUE, IS_FALSE, IS_NOT_FALSE, IS_UNKNOWN, IS_NOT_UNKNOWN
+} BoolTestType;
+
+typedef struct BooleanTest
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ BoolTestType booltesttype; /* test type */
+ int location; /* token location, or -1 if unknown */
+} BooleanTest;
+
+/*
+ * CoerceToDomain
+ *
+ * CoerceToDomain represents the operation of coercing a value to a domain
+ * type. At runtime (and not before) the precise set of constraints to be
+ * checked will be determined. If the value passes, it is returned as the
+ * result; if not, an error is raised. Note that this is equivalent to
+ * RelabelType in the scenario where no constraints are applied.
+ */
+typedef struct CoerceToDomain
+{
+ Expr xpr;
+ Expr *arg; /* input expression */
+ Oid resulttype; /* domain type ID (result type) */
+ int32 resulttypmod; /* output typmod (currently always -1) */
+ Oid resultcollid; /* OID of collation, or InvalidOid if none */
+ CoercionForm coercionformat; /* how to display this node */
+ int location; /* token location, or -1 if unknown */
+} CoerceToDomain;
+
+/*
+ * Placeholder node for the value to be processed by a domain's check
+ * constraint. This is effectively like a Param, but can be implemented more
+ * simply since we need only one replacement value at a time.
+ *
+ * Note: the typeId/typeMod/collation will be set from the domain's base type,
+ * not the domain itself. This is because we shouldn't consider the value
+ * to be a member of the domain if we haven't yet checked its constraints.
+ */
+typedef struct CoerceToDomainValue
+{
+ Expr xpr;
+ Oid typeId; /* type for substituted value */
+ int32 typeMod; /* typemod for substituted value */
+ Oid collation; /* collation for the substituted value */
+ int location; /* token location, or -1 if unknown */
+} CoerceToDomainValue;
+
+/*
+ * Placeholder node for a DEFAULT marker in an INSERT or UPDATE command.
+ *
+ * This is not an executable expression: it must be replaced by the actual
+ * column default expression during rewriting. But it is convenient to
+ * treat it as an expression node during parsing and rewriting.
+ */
+typedef struct SetToDefault
+{
+ Expr xpr;
+ Oid typeId; /* type for substituted value */
+ int32 typeMod; /* typemod for substituted value */
+ Oid collation; /* collation for the substituted value */
+ int location; /* token location, or -1 if unknown */
+} SetToDefault;
+
+/*
+ * Node representing [WHERE] CURRENT OF cursor_name
+ *
+ * CURRENT OF is a bit like a Var, in that it carries the rangetable index
+ * of the target relation being constrained; this aids placing the expression
+ * correctly during planning. We can assume however that its "levelsup" is
+ * always zero, due to the syntactic constraints on where it can appear.
+ *
+ * The referenced cursor can be represented either as a hardwired string
+ * or as a reference to a run-time parameter of type REFCURSOR. The latter
+ * case is for the convenience of plpgsql.
+ */
+typedef struct CurrentOfExpr
+{
+ Expr xpr;
+ Index cvarno; /* RT index of target relation */
+ char *cursor_name; /* name of referenced cursor, or NULL */
+ int cursor_param; /* refcursor parameter number, or 0 */
+} CurrentOfExpr;
+
+/*
+ * NextValueExpr - get next value from sequence
+ *
+ * This has the same effect as calling the nextval() function, but it does not
+ * check permissions on the sequence. This is used for identity columns,
+ * where the sequence is an implicit dependency without its own permissions.
+ */
+typedef struct NextValueExpr
+{
+ Expr xpr;
+ Oid seqid;
+ Oid typeId;
+} NextValueExpr;
+
+/*
+ * InferenceElem - an element of a unique index inference specification
+ *
+ * This mostly matches the structure of IndexElems, but having a dedicated
+ * primnode allows for a clean separation between the use of index parameters
+ * by utility commands, and this node.
+ */
+typedef struct InferenceElem
+{
+ Expr xpr;
+ Node *expr; /* expression to infer from, or NULL */
+ Oid infercollid; /* OID of collation, or InvalidOid */
+ Oid inferopclass; /* OID of att opclass, or InvalidOid */
+} InferenceElem;
+
+/*--------------------
+ * TargetEntry -
+ * a target entry (used in query target lists)
+ *
+ * Strictly speaking, a TargetEntry isn't an expression node (since it can't
+ * be evaluated by ExecEvalExpr). But we treat it as one anyway, since in
+ * very many places it's convenient to process a whole query targetlist as a
+ * single expression tree.
+ *
+ * In a SELECT's targetlist, resno should always be equal to the item's
+ * ordinal position (counting from 1). However, in an INSERT or UPDATE
+ * targetlist, resno represents the attribute number of the destination
+ * column for the item; so there may be missing or out-of-order resnos.
+ * It is even legal to have duplicated resnos; consider
+ * UPDATE table SET arraycol[1] = ..., arraycol[2] = ..., ...
+ * The two meanings come together in the executor, because the planner
+ * transforms INSERT/UPDATE tlists into a normalized form with exactly
+ * one entry for each column of the destination table. Before that's
+ * happened, however, it is risky to assume that resno == position.
+ * Generally get_tle_by_resno() should be used rather than list_nth()
+ * to fetch tlist entries by resno, and only in SELECT should you assume
+ * that resno is a unique identifier.
+ *
+ * resname is required to represent the correct column name in non-resjunk
+ * entries of top-level SELECT targetlists, since it will be used as the
+ * column title sent to the frontend. In most other contexts it is only
+ * a debugging aid, and may be wrong or even NULL. (In particular, it may
+ * be wrong in a tlist from a stored rule, if the referenced column has been
+ * renamed by ALTER TABLE since the rule was made. Also, the planner tends
+ * to store NULL rather than look up a valid name for tlist entries in
+ * non-toplevel plan nodes.) In resjunk entries, resname should be either
+ * a specific system-generated name (such as "ctid") or NULL; anything else
+ * risks confusing ExecGetJunkAttribute!
+ *
+ * ressortgroupref is used in the representation of ORDER BY, GROUP BY, and
+ * DISTINCT items. Targetlist entries with ressortgroupref=0 are not
+ * sort/group items. If ressortgroupref>0, then this item is an ORDER BY,
+ * GROUP BY, and/or DISTINCT target value. No two entries in a targetlist
+ * may have the same nonzero ressortgroupref --- but there is no particular
+ * meaning to the nonzero values, except as tags. (For example, one must
+ * not assume that lower ressortgroupref means a more significant sort key.)
+ * The order of the associated SortGroupClause lists determine the semantics.
+ *
+ * resorigtbl/resorigcol identify the source of the column, if it is a
+ * simple reference to a column of a base table (or view). If it is not
+ * a simple reference, these fields are zeroes.
+ *
+ * If resjunk is true then the column is a working column (such as a sort key)
+ * that should be removed from the final output of the query. Resjunk columns
+ * must have resnos that cannot duplicate any regular column's resno. Also
+ * note that there are places that assume resjunk columns come after non-junk
+ * columns.
+ *--------------------
+ */
+typedef struct TargetEntry
+{
+ Expr xpr;
+ Expr *expr; /* expression to evaluate */
+ AttrNumber resno; /* attribute number (see notes above) */
+ char *resname; /* name of the column (could be NULL) */
+ Index ressortgroupref; /* nonzero if referenced by a sort/group
+ * clause */
+ Oid resorigtbl; /* OID of column's source table */
+ AttrNumber resorigcol; /* column's number in source table */
+ bool resjunk; /* set to true to eliminate the attribute from
+ * final target list */
+} TargetEntry;
+
+
+/* ----------------------------------------------------------------
+ * node types for join trees
+ *
+ * The leaves of a join tree structure are RangeTblRef nodes. Above
+ * these, JoinExpr nodes can appear to denote a specific kind of join
+ * or qualified join. Also, FromExpr nodes can appear to denote an
+ * ordinary cross-product join ("FROM foo, bar, baz WHERE ...").
+ * FromExpr is like a JoinExpr of jointype JOIN_INNER, except that it
+ * may have any number of child nodes, not just two.
+ *
+ * NOTE: the top level of a Query's jointree is always a FromExpr.
+ * Even if the jointree contains no rels, there will be a FromExpr.
+ *
+ * NOTE: the qualification expressions present in JoinExpr nodes are
+ * *in addition to* the query's main WHERE clause, which appears as the
+ * qual of the top-level FromExpr. The reason for associating quals with
+ * specific nodes in the jointree is that the position of a qual is critical
+ * when outer joins are present. (If we enforce a qual too soon or too late,
+ * that may cause the outer join to produce the wrong set of NULL-extended
+ * rows.) If all joins are inner joins then all the qual positions are
+ * semantically interchangeable.
+ *
+ * NOTE: in the raw output of gram.y, a join tree contains RangeVar,
+ * RangeSubselect, and RangeFunction nodes, which are all replaced by
+ * RangeTblRef nodes during the parse analysis phase. Also, the top-level
+ * FromExpr is added during parse analysis; the grammar regards FROM and
+ * WHERE as separate.
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * RangeTblRef - reference to an entry in the query's rangetable
+ *
+ * We could use direct pointers to the RT entries and skip having these
+ * nodes, but multiple pointers to the same node in a querytree cause
+ * lots of headaches, so it seems better to store an index into the RT.
+ */
+typedef struct RangeTblRef
+{
+ NodeTag type;
+ int rtindex;
+} RangeTblRef;
+
+/*----------
+ * JoinExpr - for SQL JOIN expressions
+ *
+ * isNatural, usingClause, and quals are interdependent. The user can write
+ * only one of NATURAL, USING(), or ON() (this is enforced by the grammar).
+ * If he writes NATURAL then parse analysis generates the equivalent USING()
+ * list, and from that fills in "quals" with the right equality comparisons.
+ * If he writes USING() then "quals" is filled with equality comparisons.
+ * If he writes ON() then only "quals" is set. Note that NATURAL/USING
+ * are not equivalent to ON() since they also affect the output column list.
+ *
+ * alias is an Alias node representing the AS alias-clause attached to the
+ * join expression, or NULL if no clause. NB: presence or absence of the
+ * alias has a critical impact on semantics, because a join with an alias
+ * restricts visibility of the tables/columns inside it.
+ *
+ * During parse analysis, an RTE is created for the Join, and its index
+ * is filled into rtindex. This RTE is present mainly so that Vars can
+ * be created that refer to the outputs of the join. The planner sometimes
+ * generates JoinExprs internally; these can have rtindex = 0 if there are
+ * no join alias variables referencing such joins.
+ *----------
+ */
+typedef struct JoinExpr
+{
+ NodeTag type;
+ JoinType jointype; /* type of join */
+ bool isNatural; /* Natural join? Will need to shape table */
+ Node *larg; /* left subtree */
+ Node *rarg; /* right subtree */
+ List *usingClause; /* USING clause, if any (list of String) */
+ Node *quals; /* qualifiers on join, if any */
+ Alias *alias; /* user-written alias clause, if any */
+ int rtindex; /* RT index assigned for join, or 0 */
+} JoinExpr;
+
+/*----------
+ * FromExpr - represents a FROM ... WHERE ... construct
+ *
+ * This is both more flexible than a JoinExpr (it can have any number of
+ * children, including zero) and less so --- we don't need to deal with
+ * aliases and so on. The output column set is implicitly just the union
+ * of the outputs of the children.
+ *----------
+ */
+typedef struct FromExpr
+{
+ NodeTag type;
+ List *fromlist; /* List of join subtrees */
+ Node *quals; /* qualifiers on join, if any */
+} FromExpr;
+
+/*----------
+ * OnConflictExpr - represents an ON CONFLICT DO ... expression
+ *
+ * The optimizer requires a list of inference elements, and optionally a WHERE
+ * clause to infer a unique index. The unique index (or, occasionally,
+ * indexes) inferred are used to arbitrate whether or not the alternative ON
+ * CONFLICT path is taken.
+ *----------
+ */
+typedef struct OnConflictExpr
+{
+ NodeTag type;
+ OnConflictAction action; /* DO NOTHING or UPDATE? */
+
+ /* Arbiter */
+ List *arbiterElems; /* unique index arbiter list (of
+ * InferenceElem's) */
+ Node *arbiterWhere; /* unique index arbiter WHERE clause */
+ Oid constraint; /* pg_constraint OID for arbiter */
+
+ /* ON CONFLICT UPDATE */
+ List *onConflictSet; /* List of ON CONFLICT SET TargetEntrys */
+ Node *onConflictWhere; /* qualifiers to restrict UPDATE to */
+ int exclRelIndex; /* RT index of 'excluded' relation */
+ List *exclRelTlist; /* tlist of the EXCLUDED pseudo relation */
+} OnConflictExpr;
+
+#endif /* PRIMNODES_H */
diff --git a/src/include/nodes/print.h b/src/include/nodes/print.h
new file mode 100644
index 0000000..6126b49
--- /dev/null
+++ b/src/include/nodes/print.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * print.h
+ * definitions for nodes/print.c
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/print.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PRINT_H
+#define PRINT_H
+
+#include "executor/tuptable.h"
+
+
+#define nodeDisplay(x) pprint(x)
+
+extern void print(const void *obj);
+extern void pprint(const void *obj);
+extern void elog_node_display(int lev, const char *title,
+ const void *obj, bool pretty);
+extern char *format_node_dump(const char *dump);
+extern char *pretty_format_node_dump(const char *dump);
+extern void print_rt(const List *rtable);
+extern void print_expr(const Node *expr, const List *rtable);
+extern void print_pathkeys(const List *pathkeys, const List *rtable);
+extern void print_tl(const List *tlist, const List *rtable);
+extern void print_slot(TupleTableSlot *slot);
+
+#endif /* PRINT_H */
diff --git a/src/include/nodes/readfuncs.h b/src/include/nodes/readfuncs.h
new file mode 100644
index 0000000..4eb04ca
--- /dev/null
+++ b/src/include/nodes/readfuncs.h
@@ -0,0 +1,38 @@
+/*-------------------------------------------------------------------------
+ *
+ * readfuncs.h
+ * header file for read.c and readfuncs.c. These functions are internal
+ * to the stringToNode interface and should not be used by anyone else.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/readfuncs.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef READFUNCS_H
+#define READFUNCS_H
+
+#include "nodes/nodes.h"
+
+/*
+ * variable in read.c that needs to be accessible to readfuncs.c
+ */
+#ifdef WRITE_READ_PARSE_PLAN_TREES
+extern bool restore_location_fields;
+#endif
+
+/*
+ * prototypes for functions in read.c (the lisp token parser)
+ */
+extern const char *pg_strtok(int *length);
+extern char *debackslash(const char *token, int length);
+extern void *nodeRead(const char *token, int tok_len);
+
+/*
+ * prototypes for functions in readfuncs.c
+ */
+extern Node *parseNodeString(void);
+
+#endif /* READFUNCS_H */
diff --git a/src/include/nodes/replnodes.h b/src/include/nodes/replnodes.h
new file mode 100644
index 0000000..5456141
--- /dev/null
+++ b/src/include/nodes/replnodes.h
@@ -0,0 +1,109 @@
+/*-------------------------------------------------------------------------
+ *
+ * replnodes.h
+ * definitions for replication grammar parse nodes
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/replnodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef REPLNODES_H
+#define REPLNODES_H
+
+#include "access/xlogdefs.h"
+#include "nodes/pg_list.h"
+
+typedef enum ReplicationKind
+{
+ REPLICATION_KIND_PHYSICAL,
+ REPLICATION_KIND_LOGICAL
+} ReplicationKind;
+
+
+/* ----------------------
+ * IDENTIFY_SYSTEM command
+ * ----------------------
+ */
+typedef struct IdentifySystemCmd
+{
+ NodeTag type;
+} IdentifySystemCmd;
+
+
+/* ----------------------
+ * BASE_BACKUP command
+ * ----------------------
+ */
+typedef struct BaseBackupCmd
+{
+ NodeTag type;
+ List *options;
+} BaseBackupCmd;
+
+
+/* ----------------------
+ * CREATE_REPLICATION_SLOT command
+ * ----------------------
+ */
+typedef struct CreateReplicationSlotCmd
+{
+ NodeTag type;
+ char *slotname;
+ ReplicationKind kind;
+ char *plugin;
+ bool temporary;
+ List *options;
+} CreateReplicationSlotCmd;
+
+
+/* ----------------------
+ * DROP_REPLICATION_SLOT command
+ * ----------------------
+ */
+typedef struct DropReplicationSlotCmd
+{
+ NodeTag type;
+ char *slotname;
+ bool wait;
+} DropReplicationSlotCmd;
+
+
+/* ----------------------
+ * START_REPLICATION command
+ * ----------------------
+ */
+typedef struct StartReplicationCmd
+{
+ NodeTag type;
+ ReplicationKind kind;
+ char *slotname;
+ TimeLineID timeline;
+ XLogRecPtr startpoint;
+ List *options;
+} StartReplicationCmd;
+
+
+/* ----------------------
+ * TIMELINE_HISTORY command
+ * ----------------------
+ */
+typedef struct TimeLineHistoryCmd
+{
+ NodeTag type;
+ TimeLineID timeline;
+} TimeLineHistoryCmd;
+
+/* ----------------------
+ * SQL commands
+ * ----------------------
+ */
+typedef struct SQLCmd
+{
+ NodeTag type;
+} SQLCmd;
+
+#endif /* REPLNODES_H */
diff --git a/src/include/nodes/supportnodes.h b/src/include/nodes/supportnodes.h
new file mode 100644
index 0000000..9a33c4c
--- /dev/null
+++ b/src/include/nodes/supportnodes.h
@@ -0,0 +1,242 @@
+/*-------------------------------------------------------------------------
+ *
+ * supportnodes.h
+ * Definitions for planner support functions.
+ *
+ * This file defines the API for "planner support functions", which
+ * are SQL functions (normally written in C) that can be attached to
+ * another "target" function to give the system additional knowledge
+ * about the target function. All the current capabilities have to do
+ * with planning queries that use the target function, though it is
+ * possible that future extensions will add functionality to be invoked
+ * by the parser or executor.
+ *
+ * A support function must have the SQL signature
+ * supportfn(internal) returns internal
+ * The argument is a pointer to one of the Node types defined in this file.
+ * The result is usually also a Node pointer, though its type depends on
+ * which capability is being invoked. In all cases, a NULL pointer result
+ * (that's PG_RETURN_POINTER(NULL), not PG_RETURN_NULL()) indicates that
+ * the support function cannot do anything useful for the given request.
+ * Support functions must return a NULL pointer, not fail, if they do not
+ * recognize the request node type or cannot handle the given case; this
+ * allows for future extensions of the set of request cases.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/nodes/supportnodes.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SUPPORTNODES_H
+#define SUPPORTNODES_H
+
+#include "nodes/primnodes.h"
+
+struct PlannerInfo; /* avoid including pathnodes.h here */
+struct IndexOptInfo;
+struct SpecialJoinInfo;
+
+
+/*
+ * The Simplify request allows the support function to perform plan-time
+ * simplification of a call to its target function. For example, a varchar
+ * length coercion that does not decrease the allowed length of its argument
+ * could be replaced by a RelabelType node, or "x + 0" could be replaced by
+ * "x". This is invoked during the planner's constant-folding pass, so the
+ * function's arguments can be presumed already simplified.
+ *
+ * The planner's PlannerInfo "root" is typically not needed, but can be
+ * consulted if it's necessary to obtain info about Vars present in
+ * the given node tree. Beware that root could be NULL in some usages.
+ *
+ * "fcall" will be a FuncExpr invoking the support function's target
+ * function. (This is true even if the original parsetree node was an
+ * operator call; a FuncExpr is synthesized for this purpose.)
+ *
+ * The result should be a semantically-equivalent transformed node tree,
+ * or NULL if no simplification could be performed. Do *not* return or
+ * modify *fcall, as it isn't really a separately allocated Node. But
+ * it's okay to use fcall->args, or parts of it, in the result tree.
+ */
+typedef struct SupportRequestSimplify
+{
+ NodeTag type;
+
+ struct PlannerInfo *root; /* Planner's infrastructure */
+ FuncExpr *fcall; /* Function call to be simplified */
+} SupportRequestSimplify;
+
+/*
+ * The Selectivity request allows the support function to provide a
+ * selectivity estimate for a function appearing at top level of a WHERE
+ * clause (so it applies only to functions returning boolean).
+ *
+ * The input arguments are the same as are supplied to operator restriction
+ * and join estimators, except that we unify those two APIs into just one
+ * request type. See clause_selectivity() for the details.
+ *
+ * If an estimate can be made, store it into the "selectivity" field and
+ * return the address of the SupportRequestSelectivity node; the estimate
+ * must be between 0 and 1 inclusive. Return NULL if no estimate can be
+ * made (in which case the planner will fall back to a default estimate,
+ * traditionally 1/3).
+ *
+ * If the target function is being used as the implementation of an operator,
+ * the support function will not be used for this purpose; the operator's
+ * restriction or join estimator is consulted instead.
+ */
+typedef struct SupportRequestSelectivity
+{
+ NodeTag type;
+
+ /* Input fields: */
+ struct PlannerInfo *root; /* Planner's infrastructure */
+ Oid funcid; /* function we are inquiring about */
+ List *args; /* pre-simplified arguments to function */
+ Oid inputcollid; /* function's input collation */
+ bool is_join; /* is this a join or restriction case? */
+ int varRelid; /* if restriction, RTI of target relation */
+ JoinType jointype; /* if join, outer join type */
+ struct SpecialJoinInfo *sjinfo; /* if outer join, info about join */
+
+ /* Output fields: */
+ Selectivity selectivity; /* returned selectivity estimate */
+} SupportRequestSelectivity;
+
+/*
+ * The Cost request allows the support function to provide an execution
+ * cost estimate for its target function. The cost estimate can include
+ * both a one-time (query startup) component and a per-execution component.
+ * The estimate should *not* include the costs of evaluating the target
+ * function's arguments, only the target function itself.
+ *
+ * The "node" argument is normally the parse node that is invoking the
+ * target function. This is a FuncExpr in the simplest case, but it could
+ * also be an OpExpr, DistinctExpr, NullIfExpr, or WindowFunc, or possibly
+ * other cases in future. NULL is passed if the function cannot presume
+ * its arguments to be equivalent to what the calling node presents as
+ * arguments; that happens for, e.g., aggregate support functions and
+ * per-column comparison operators used by RowExprs.
+ *
+ * If an estimate can be made, store it into the cost fields and return the
+ * address of the SupportRequestCost node. Return NULL if no estimate can be
+ * made, in which case the planner will rely on the target function's procost
+ * field. (Note: while procost is automatically scaled by cpu_operator_cost,
+ * this is not the case for the outputs of the Cost request; the support
+ * function must scale its results appropriately on its own.)
+ */
+typedef struct SupportRequestCost
+{
+ NodeTag type;
+
+ /* Input fields: */
+ struct PlannerInfo *root; /* Planner's infrastructure (could be NULL) */
+ Oid funcid; /* function we are inquiring about */
+ Node *node; /* parse node invoking function, or NULL */
+
+ /* Output fields: */
+ Cost startup; /* one-time cost */
+ Cost per_tuple; /* per-evaluation cost */
+} SupportRequestCost;
+
+/*
+ * The Rows request allows the support function to provide an output rowcount
+ * estimate for its target function (so it applies only to set-returning
+ * functions).
+ *
+ * The "node" argument is the parse node that is invoking the target function;
+ * currently this will always be a FuncExpr or OpExpr.
+ *
+ * If an estimate can be made, store it into the rows field and return the
+ * address of the SupportRequestRows node. Return NULL if no estimate can be
+ * made, in which case the planner will rely on the target function's prorows
+ * field.
+ */
+typedef struct SupportRequestRows
+{
+ NodeTag type;
+
+ /* Input fields: */
+ struct PlannerInfo *root; /* Planner's infrastructure (could be NULL) */
+ Oid funcid; /* function we are inquiring about */
+ Node *node; /* parse node invoking function */
+
+ /* Output fields: */
+ double rows; /* number of rows expected to be returned */
+} SupportRequestRows;
+
+/*
+ * The IndexCondition request allows the support function to generate
+ * a directly-indexable condition based on a target function call that is
+ * not itself indexable. The target function call must appear at the top
+ * level of WHERE or JOIN/ON, so this applies only to functions returning
+ * boolean.
+ *
+ * The "node" argument is the parse node that is invoking the target function;
+ * currently this will always be a FuncExpr or OpExpr. The call is made
+ * only if at least one function argument matches an index column's variable
+ * or expression. "indexarg" identifies the matching argument (it's the
+ * argument's zero-based index in the node's args list).
+ *
+ * If the transformation is possible, return a List of directly-indexable
+ * condition expressions, else return NULL. (A List is used because it's
+ * sometimes useful to generate more than one indexable condition, such as
+ * when a LIKE with constant prefix gives rise to both >= and < conditions.)
+ *
+ * "Directly indexable" means that the condition must be directly executable
+ * by the index machinery. Typically this means that it is a binary OpExpr
+ * with the index column value on the left, a pseudo-constant on the right,
+ * and an operator that is in the index column's operator family. Other
+ * possibilities include RowCompareExpr, ScalarArrayOpExpr, and NullTest,
+ * depending on the index type; but those seem less likely to be useful for
+ * derived index conditions. "Pseudo-constant" means that the right-hand
+ * expression must not contain any volatile functions, nor any Vars of the
+ * table the index is for; use is_pseudo_constant_for_index() to check this.
+ * (Note: if the passed "node" is an OpExpr, the core planner already verified
+ * that the non-indexkey operand is pseudo-constant; but when the "node"
+ * is a FuncExpr, it does not check, since it doesn't know which of the
+ * function's arguments you might need to use in an index comparison value.)
+ *
+ * In many cases, an index condition can be generated but it is weaker than
+ * the function condition itself; for example, a LIKE with a constant prefix
+ * can produce an index range check based on the prefix, but we still need
+ * to execute the LIKE operator to verify the rest of the pattern. We say
+ * that such an index condition is "lossy". When returning an index condition,
+ * you should set the "lossy" request field to true if the condition is lossy,
+ * or false if it is an exact equivalent of the function's result. The core
+ * code will initialize that field to true, which is the common case.
+ *
+ * It is important to verify that the index operator family is the correct
+ * one for the condition you want to generate. Core support functions tend
+ * to use the known OID of a built-in opfamily for this, but extensions need
+ * to work harder, since their OIDs aren't fixed. A possibly workable
+ * answer for an index on an extension datatype is to verify the index AM's
+ * OID instead, and then assume that there's only one relevant opclass for
+ * your datatype so the opfamily must be the right one. Generating OpExpr
+ * nodes may also require knowing extension datatype OIDs (often you can
+ * find these out by applying exprType() to a function argument) and
+ * operator OIDs (which you can look up using get_opfamily_member).
+ */
+typedef struct SupportRequestIndexCondition
+{
+ NodeTag type;
+
+ /* Input fields: */
+ struct PlannerInfo *root; /* Planner's infrastructure */
+ Oid funcid; /* function we are inquiring about */
+ Node *node; /* parse node invoking function */
+ int indexarg; /* index of function arg matching indexcol */
+ struct IndexOptInfo *index; /* planner's info about target index */
+ int indexcol; /* index of target index column (0-based) */
+ Oid opfamily; /* index column's operator family */
+ Oid indexcollation; /* index column's collation */
+
+ /* Output fields: */
+ bool lossy; /* set to false if index condition is an exact
+ * equivalent of the function call */
+} SupportRequestIndexCondition;
+
+#endif /* SUPPORTNODES_H */
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
new file mode 100644
index 0000000..d562fca
--- /dev/null
+++ b/src/include/nodes/tidbitmap.h
@@ -0,0 +1,75 @@
+/*-------------------------------------------------------------------------
+ *
+ * tidbitmap.h
+ * PostgreSQL tuple-id (TID) bitmap package
+ *
+ * This module provides bitmap data structures that are spiritually
+ * similar to Bitmapsets, but are specially adapted to store sets of
+ * tuple identifiers (TIDs), or ItemPointers. In particular, the division
+ * of an ItemPointer into BlockNumber and OffsetNumber is catered for.
+ * Also, since we wish to be able to store very large tuple sets in
+ * memory with this data structure, we support "lossy" storage, in which
+ * we no longer remember individual tuple offsets on a page but only the
+ * fact that a particular page needs to be visited.
+ *
+ *
+ * Copyright (c) 2003-2020, PostgreSQL Global Development Group
+ *
+ * src/include/nodes/tidbitmap.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TIDBITMAP_H
+#define TIDBITMAP_H
+
+#include "storage/itemptr.h"
+#include "utils/dsa.h"
+
+
+/*
+ * Actual bitmap representation is private to tidbitmap.c. Callers can
+ * do IsA(x, TIDBitmap) on it, but nothing else.
+ */
+typedef struct TIDBitmap TIDBitmap;
+
+/* Likewise, TBMIterator is private */
+typedef struct TBMIterator TBMIterator;
+typedef struct TBMSharedIterator TBMSharedIterator;
+
+/* Result structure for tbm_iterate */
+typedef struct TBMIterateResult
+{
+ BlockNumber blockno; /* page number containing tuples */
+ int ntuples; /* -1 indicates lossy result */
+ bool recheck; /* should the tuples be rechecked? */
+ /* Note: recheck is always true if ntuples < 0 */
+ OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
+} TBMIterateResult;
+
+/* function prototypes in nodes/tidbitmap.c */
+
+extern TIDBitmap *tbm_create(long maxbytes, dsa_area *dsa);
+extern void tbm_free(TIDBitmap *tbm);
+extern void tbm_free_shared_area(dsa_area *dsa, dsa_pointer dp);
+
+extern void tbm_add_tuples(TIDBitmap *tbm,
+ const ItemPointer tids, int ntids,
+ bool recheck);
+extern void tbm_add_page(TIDBitmap *tbm, BlockNumber pageno);
+
+extern void tbm_union(TIDBitmap *a, const TIDBitmap *b);
+extern void tbm_intersect(TIDBitmap *a, const TIDBitmap *b);
+
+extern bool tbm_is_empty(const TIDBitmap *tbm);
+
+extern TBMIterator *tbm_begin_iterate(TIDBitmap *tbm);
+extern dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm);
+extern TBMIterateResult *tbm_iterate(TBMIterator *iterator);
+extern TBMIterateResult *tbm_shared_iterate(TBMSharedIterator *iterator);
+extern void tbm_end_iterate(TBMIterator *iterator);
+extern void tbm_end_shared_iterate(TBMSharedIterator *iterator);
+extern TBMSharedIterator *tbm_attach_shared_iterate(dsa_area *dsa,
+ dsa_pointer dp);
+extern long tbm_calculate_entries(double maxbytes);
+
+#endif /* TIDBITMAP_H */
diff --git a/src/include/nodes/value.h b/src/include/nodes/value.h
new file mode 100644
index 0000000..d4911b5
--- /dev/null
+++ b/src/include/nodes/value.h
@@ -0,0 +1,61 @@
+/*-------------------------------------------------------------------------
+ *
+ * value.h
+ * interface for Value nodes
+ *
+ *
+ * Copyright (c) 2003-2020, PostgreSQL Global Development Group
+ *
+ * src/include/nodes/value.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef VALUE_H
+#define VALUE_H
+
+#include "nodes/nodes.h"
+
+/*----------------------
+ * Value node
+ *
+ * The same Value struct is used for five node types: T_Integer,
+ * T_Float, T_String, T_BitString, T_Null.
+ *
+ * Integral values are actually represented by a machine integer,
+ * but both floats and strings are represented as strings.
+ * Using T_Float as the node type simply indicates that
+ * the contents of the string look like a valid numeric literal.
+ *
+ * (Before Postgres 7.0, we used a double to represent T_Float,
+ * but that creates loss-of-precision problems when the value is
+ * ultimately destined to be converted to NUMERIC. Since Value nodes
+ * are only used in the parsing process, not for runtime data, it's
+ * better to use the more general representation.)
+ *
+ * Note that an integer-looking string will get lexed as T_Float if
+ * the value is too large to fit in an 'int'.
+ *
+ * Nulls, of course, don't need the value part at all.
+ *----------------------
+ */
+typedef struct Value
+{
+ NodeTag type; /* tag appropriately (eg. T_String) */
+ union ValUnion
+ {
+ int ival; /* machine integer */
+ char *str; /* string */
+ } val;
+} Value;
+
+#define intVal(v) (((Value *)(v))->val.ival)
+#define floatVal(v) atof(((Value *)(v))->val.str)
+#define strVal(v) (((Value *)(v))->val.str)
+
+extern Value *makeInteger(int i);
+extern Value *makeFloat(char *numericStr);
+extern Value *makeString(char *str);
+extern Value *makeBitString(char *str);
+
+#endif /* VALUE_H */
diff --git a/src/include/optimizer/appendinfo.h b/src/include/optimizer/appendinfo.h
new file mode 100644
index 0000000..d6a27a6
--- /dev/null
+++ b/src/include/optimizer/appendinfo.h
@@ -0,0 +1,35 @@
+/*-------------------------------------------------------------------------
+ *
+ * appendinfo.h
+ * Routines for mapping expressions between append rel parent(s) and
+ * children
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/appendinfo.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef APPENDINFO_H
+#define APPENDINFO_H
+
+#include "nodes/pathnodes.h"
+#include "utils/relcache.h"
+
+extern AppendRelInfo *make_append_rel_info(Relation parentrel,
+ Relation childrel,
+ Index parentRTindex, Index childRTindex);
+extern Node *adjust_appendrel_attrs(PlannerInfo *root, Node *node,
+ int nappinfos, AppendRelInfo **appinfos);
+extern Node *adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node,
+ Relids child_relids,
+ Relids top_parent_relids);
+extern Relids adjust_child_relids(Relids relids, int nappinfos,
+ AppendRelInfo **appinfos);
+extern Relids adjust_child_relids_multilevel(PlannerInfo *root, Relids relids,
+ Relids child_relids, Relids top_parent_relids);
+extern AppendRelInfo **find_appinfos_by_relids(PlannerInfo *root,
+ Relids relids, int *nappinfos);
+
+#endif /* APPENDINFO_H */
diff --git a/src/include/optimizer/clauses.h b/src/include/optimizer/clauses.h
new file mode 100644
index 0000000..e71b06b
--- /dev/null
+++ b/src/include/optimizer/clauses.h
@@ -0,0 +1,60 @@
+/*-------------------------------------------------------------------------
+ *
+ * clauses.h
+ * prototypes for clauses.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/clauses.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef CLAUSES_H
+#define CLAUSES_H
+
+#include "access/htup.h"
+#include "nodes/pathnodes.h"
+
+typedef struct
+{
+ int numWindowFuncs; /* total number of WindowFuncs found */
+ Index maxWinRef; /* windowFuncs[] is indexed 0 .. maxWinRef */
+ List **windowFuncs; /* lists of WindowFuncs for each winref */
+} WindowFuncLists;
+
+extern bool contain_agg_clause(Node *clause);
+extern void get_agg_clause_costs(PlannerInfo *root, Node *clause,
+ AggSplit aggsplit, AggClauseCosts *costs);
+
+extern bool contain_window_function(Node *clause);
+extern WindowFuncLists *find_window_functions(Node *clause, Index maxWinRef);
+
+extern double expression_returns_set_rows(PlannerInfo *root, Node *clause);
+
+extern bool contain_subplans(Node *clause);
+
+extern char max_parallel_hazard(Query *parse);
+extern bool is_parallel_safe(PlannerInfo *root, Node *node);
+extern bool contain_nonstrict_functions(Node *clause);
+extern bool contain_exec_param(Node *clause, List *param_ids);
+extern bool contain_leaked_vars(Node *clause);
+
+extern Relids find_nonnullable_rels(Node *clause);
+extern List *find_nonnullable_vars(Node *clause);
+extern List *find_forced_null_vars(Node *clause);
+extern Var *find_forced_null_var(Node *clause);
+
+extern bool is_pseudo_constant_clause(Node *clause);
+extern bool is_pseudo_constant_clause_relids(Node *clause, Relids relids);
+
+extern int NumRelids(Node *clause);
+extern int NumRelids_new(PlannerInfo *root, Node *clause);
+
+extern void CommuteOpExpr(OpExpr *clause);
+
+extern Query *inline_set_returning_function(PlannerInfo *root,
+ RangeTblEntry *rte);
+
+#endif /* CLAUSES_H */
diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h
new file mode 100644
index 0000000..6141654
--- /dev/null
+++ b/src/include/optimizer/cost.h
@@ -0,0 +1,206 @@
+/*-------------------------------------------------------------------------
+ *
+ * cost.h
+ * prototypes for costsize.c and clausesel.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/cost.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef COST_H
+#define COST_H
+
+#include "nodes/pathnodes.h"
+#include "nodes/plannodes.h"
+
+
+/* defaults for costsize.c's Cost parameters */
+/* NB: cost-estimation code should use the variables, not these constants! */
+/* If you change these, update backend/utils/misc/postgresql.sample.conf */
+#define DEFAULT_SEQ_PAGE_COST 1.0
+#define DEFAULT_RANDOM_PAGE_COST 4.0
+#define DEFAULT_CPU_TUPLE_COST 0.01
+#define DEFAULT_CPU_INDEX_TUPLE_COST 0.005
+#define DEFAULT_CPU_OPERATOR_COST 0.0025
+#define DEFAULT_PARALLEL_TUPLE_COST 0.1
+#define DEFAULT_PARALLEL_SETUP_COST 1000.0
+
+#define DEFAULT_EFFECTIVE_CACHE_SIZE 524288 /* measured in pages */
+
+typedef enum
+{
+ CONSTRAINT_EXCLUSION_OFF, /* do not use c_e */
+ CONSTRAINT_EXCLUSION_ON, /* apply c_e to all rels */
+ CONSTRAINT_EXCLUSION_PARTITION /* apply c_e to otherrels only */
+} ConstraintExclusionType;
+
+
+/*
+ * prototypes for costsize.c
+ * routines to compute costs and sizes
+ */
+
+/* parameter variables and flags (see also optimizer.h) */
+extern PGDLLIMPORT Cost disable_cost;
+extern PGDLLIMPORT int max_parallel_workers_per_gather;
+extern PGDLLIMPORT bool enable_seqscan;
+extern PGDLLIMPORT bool enable_indexscan;
+extern PGDLLIMPORT bool enable_indexonlyscan;
+extern PGDLLIMPORT bool enable_bitmapscan;
+extern PGDLLIMPORT bool enable_tidscan;
+extern PGDLLIMPORT bool enable_sort;
+extern PGDLLIMPORT bool enable_incremental_sort;
+extern PGDLLIMPORT bool enable_hashagg;
+extern PGDLLIMPORT bool enable_nestloop;
+extern PGDLLIMPORT bool enable_material;
+extern PGDLLIMPORT bool enable_mergejoin;
+extern PGDLLIMPORT bool enable_hashjoin;
+extern PGDLLIMPORT bool enable_gathermerge;
+extern PGDLLIMPORT bool enable_partitionwise_join;
+extern PGDLLIMPORT bool enable_partitionwise_aggregate;
+extern PGDLLIMPORT bool enable_parallel_append;
+extern PGDLLIMPORT bool enable_parallel_hash;
+extern PGDLLIMPORT bool enable_partition_pruning;
+extern PGDLLIMPORT int constraint_exclusion;
+
+extern double index_pages_fetched(double tuples_fetched, BlockNumber pages,
+ double index_pages, PlannerInfo *root);
+extern void cost_seqscan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
+ ParamPathInfo *param_info);
+extern void cost_samplescan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
+ ParamPathInfo *param_info);
+extern void cost_index(IndexPath *path, PlannerInfo *root,
+ double loop_count, bool partial_path);
+extern void cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
+ ParamPathInfo *param_info,
+ Path *bitmapqual, double loop_count);
+extern void cost_bitmap_and_node(BitmapAndPath *path, PlannerInfo *root);
+extern void cost_bitmap_or_node(BitmapOrPath *path, PlannerInfo *root);
+extern void cost_bitmap_tree_node(Path *path, Cost *cost, Selectivity *selec);
+extern void cost_tidscan(Path *path, PlannerInfo *root,
+ RelOptInfo *baserel, List *tidquals, ParamPathInfo *param_info);
+extern void cost_subqueryscan(SubqueryScanPath *path, PlannerInfo *root,
+ RelOptInfo *baserel, ParamPathInfo *param_info);
+extern void cost_functionscan(Path *path, PlannerInfo *root,
+ RelOptInfo *baserel, ParamPathInfo *param_info);
+extern void cost_valuesscan(Path *path, PlannerInfo *root,
+ RelOptInfo *baserel, ParamPathInfo *param_info);
+extern void cost_tablefuncscan(Path *path, PlannerInfo *root,
+ RelOptInfo *baserel, ParamPathInfo *param_info);
+extern void cost_ctescan(Path *path, PlannerInfo *root,
+ RelOptInfo *baserel, ParamPathInfo *param_info);
+extern void cost_namedtuplestorescan(Path *path, PlannerInfo *root,
+ RelOptInfo *baserel, ParamPathInfo *param_info);
+extern void cost_resultscan(Path *path, PlannerInfo *root,
+ RelOptInfo *baserel, ParamPathInfo *param_info);
+extern void cost_recursive_union(Path *runion, Path *nrterm, Path *rterm);
+extern void cost_sort(Path *path, PlannerInfo *root,
+ List *pathkeys, Cost input_cost, double tuples, int width,
+ Cost comparison_cost, int sort_mem,
+ double limit_tuples);
+extern void cost_incremental_sort(Path *path,
+ PlannerInfo *root, List *pathkeys, int presorted_keys,
+ Cost input_startup_cost, Cost input_total_cost,
+ double input_tuples, int width, Cost comparison_cost, int sort_mem,
+ double limit_tuples);
+extern void cost_append(AppendPath *path);
+extern void cost_merge_append(Path *path, PlannerInfo *root,
+ List *pathkeys, int n_streams,
+ Cost input_startup_cost, Cost input_total_cost,
+ double tuples);
+extern void cost_material(Path *path,
+ Cost input_startup_cost, Cost input_total_cost,
+ double tuples, int width);
+extern void cost_agg(Path *path, PlannerInfo *root,
+ AggStrategy aggstrategy, const AggClauseCosts *aggcosts,
+ int numGroupCols, double numGroups,
+ List *quals,
+ Cost input_startup_cost, Cost input_total_cost,
+ double input_tuples, double input_width);
+extern void cost_windowagg(Path *path, PlannerInfo *root,
+ List *windowFuncs, int numPartCols, int numOrderCols,
+ Cost input_startup_cost, Cost input_total_cost,
+ double input_tuples);
+extern void cost_group(Path *path, PlannerInfo *root,
+ int numGroupCols, double numGroups,
+ List *quals,
+ Cost input_startup_cost, Cost input_total_cost,
+ double input_tuples);
+extern void initial_cost_nestloop(PlannerInfo *root,
+ JoinCostWorkspace *workspace,
+ JoinType jointype,
+ Path *outer_path, Path *inner_path,
+ JoinPathExtraData *extra);
+extern void final_cost_nestloop(PlannerInfo *root, NestPath *path,
+ JoinCostWorkspace *workspace,
+ JoinPathExtraData *extra);
+extern void initial_cost_mergejoin(PlannerInfo *root,
+ JoinCostWorkspace *workspace,
+ JoinType jointype,
+ List *mergeclauses,
+ Path *outer_path, Path *inner_path,
+ List *outersortkeys, List *innersortkeys,
+ JoinPathExtraData *extra);
+extern void final_cost_mergejoin(PlannerInfo *root, MergePath *path,
+ JoinCostWorkspace *workspace,
+ JoinPathExtraData *extra);
+extern void initial_cost_hashjoin(PlannerInfo *root,
+ JoinCostWorkspace *workspace,
+ JoinType jointype,
+ List *hashclauses,
+ Path *outer_path, Path *inner_path,
+ JoinPathExtraData *extra,
+ bool parallel_hash);
+extern void final_cost_hashjoin(PlannerInfo *root, HashPath *path,
+ JoinCostWorkspace *workspace,
+ JoinPathExtraData *extra);
+extern void cost_gather(GatherPath *path, PlannerInfo *root,
+ RelOptInfo *baserel, ParamPathInfo *param_info, double *rows);
+extern void cost_gather_merge(GatherMergePath *path, PlannerInfo *root,
+ RelOptInfo *rel, ParamPathInfo *param_info,
+ Cost input_startup_cost, Cost input_total_cost,
+ double *rows);
+extern void cost_subplan(PlannerInfo *root, SubPlan *subplan, Plan *plan);
+extern void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root);
+extern void cost_qual_eval_node(QualCost *cost, Node *qual, PlannerInfo *root);
+extern void compute_semi_anti_join_factors(PlannerInfo *root,
+ RelOptInfo *joinrel,
+ RelOptInfo *outerrel,
+ RelOptInfo *innerrel,
+ JoinType jointype,
+ SpecialJoinInfo *sjinfo,
+ List *restrictlist,
+ SemiAntiJoinFactors *semifactors);
+extern void set_baserel_size_estimates(PlannerInfo *root, RelOptInfo *rel);
+extern double get_parameterized_baserel_size(PlannerInfo *root,
+ RelOptInfo *rel,
+ List *param_clauses);
+extern double get_parameterized_joinrel_size(PlannerInfo *root,
+ RelOptInfo *rel,
+ Path *outer_path,
+ Path *inner_path,
+ SpecialJoinInfo *sjinfo,
+ List *restrict_clauses);
+extern void set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
+ RelOptInfo *outer_rel,
+ RelOptInfo *inner_rel,
+ SpecialJoinInfo *sjinfo,
+ List *restrictlist);
+extern void set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel);
+extern void set_function_size_estimates(PlannerInfo *root, RelOptInfo *rel);
+extern void set_values_size_estimates(PlannerInfo *root, RelOptInfo *rel);
+extern void set_cte_size_estimates(PlannerInfo *root, RelOptInfo *rel,
+ double cte_rows);
+extern void set_tablefunc_size_estimates(PlannerInfo *root, RelOptInfo *rel);
+extern void set_namedtuplestore_size_estimates(PlannerInfo *root, RelOptInfo *rel);
+extern void set_result_size_estimates(PlannerInfo *root, RelOptInfo *rel);
+extern void set_foreign_size_estimates(PlannerInfo *root, RelOptInfo *rel);
+extern PathTarget *set_pathtarget_cost_width(PlannerInfo *root, PathTarget *target);
+extern double compute_bitmap_pages(PlannerInfo *root, RelOptInfo *baserel,
+ Path *bitmapqual, int loop_count, Cost *cost, double *tuple);
+
+#endif /* COST_H */
diff --git a/src/include/optimizer/geqo.h b/src/include/optimizer/geqo.h
new file mode 100644
index 0000000..aba549f
--- /dev/null
+++ b/src/include/optimizer/geqo.h
@@ -0,0 +1,88 @@
+/*-------------------------------------------------------------------------
+ *
+ * geqo.h
+ * prototypes for various files in optimizer/geqo
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/geqo.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* contributed by:
+ =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+ * Martin Utesch * Institute of Automatic Control *
+ = = University of Mining and Technology =
+ * utesch@aut.tu-freiberg.de * Freiberg, Germany *
+ =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+ */
+
+#ifndef GEQO_H
+#define GEQO_H
+
+#include "nodes/pathnodes.h"
+#include "optimizer/geqo_gene.h"
+
+
+/* GEQO debug flag */
+/*
+ #define GEQO_DEBUG
+ */
+
+/* choose one recombination mechanism here */
+/*
+ #define ERX
+ #define PMX
+ #define CX
+ #define PX
+ #define OX1
+ #define OX2
+ */
+#define ERX
+
+
+/*
+ * Configuration options
+ *
+ * If you change these, update backend/utils/misc/postgresql.conf.sample
+ */
+extern int Geqo_effort; /* 1 .. 10, knob for adjustment of defaults */
+
+#define DEFAULT_GEQO_EFFORT 5
+#define MIN_GEQO_EFFORT 1
+#define MAX_GEQO_EFFORT 10
+
+extern int Geqo_pool_size; /* 2 .. inf, or 0 to use default */
+
+extern int Geqo_generations; /* 1 .. inf, or 0 to use default */
+
+extern double Geqo_selection_bias;
+
+#define DEFAULT_GEQO_SELECTION_BIAS 2.0
+#define MIN_GEQO_SELECTION_BIAS 1.5
+#define MAX_GEQO_SELECTION_BIAS 2.0
+
+extern double Geqo_seed; /* 0 .. 1 */
+
+
+/*
+ * Private state for a GEQO run --- accessible via root->join_search_private
+ */
+typedef struct
+{
+ List *initial_rels; /* the base relations we are joining */
+ unsigned short random_state[3]; /* state for pg_erand48() */
+} GeqoPrivateData;
+
+
+/* routines in geqo_main.c */
+extern RelOptInfo *geqo(PlannerInfo *root,
+ int number_of_rels, List *initial_rels);
+
+/* routines in geqo_eval.c */
+extern Cost geqo_eval(PlannerInfo *root, Gene *tour, int num_gene);
+extern RelOptInfo *gimme_tree(PlannerInfo *root, Gene *tour, int num_gene);
+
+#endif /* GEQO_H */
diff --git a/src/include/optimizer/geqo_copy.h b/src/include/optimizer/geqo_copy.h
new file mode 100644
index 0000000..87444b6
--- /dev/null
+++ b/src/include/optimizer/geqo_copy.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * geqo_copy.h
+ * prototypes for copy functions in optimizer/geqo
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/geqo_copy.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* contributed by:
+ =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+ * Martin Utesch * Institute of Automatic Control *
+ = = University of Mining and Technology =
+ * utesch@aut.tu-freiberg.de * Freiberg, Germany *
+ =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+ */
+
+#ifndef GEQO_COPY_H
+#define GEQO_COPY_H
+
+#include "optimizer/geqo.h"
+
+
+extern void geqo_copy(PlannerInfo *root, Chromosome *chromo1, Chromosome *chromo2, int string_length);
+
+#endif /* GEQO_COPY_H */
diff --git a/src/include/optimizer/geqo_gene.h b/src/include/optimizer/geqo_gene.h
new file mode 100644
index 0000000..9d3a94f
--- /dev/null
+++ b/src/include/optimizer/geqo_gene.h
@@ -0,0 +1,45 @@
+/*-------------------------------------------------------------------------
+ *
+ * geqo_gene.h
+ * genome representation in optimizer/geqo
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/geqo_gene.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* contributed by:
+ =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+ * Martin Utesch * Institute of Automatic Control *
+ = = University of Mining and Technology =
+ * utesch@aut.tu-freiberg.de * Freiberg, Germany *
+ =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+ */
+
+
+#ifndef GEQO_GENE_H
+#define GEQO_GENE_H
+
+#include "nodes/nodes.h"
+
+/* we presume that int instead of Relid
+ is o.k. for Gene; so don't change it! */
+typedef int Gene;
+
+typedef struct Chromosome
+{
+ Gene *string;
+ Cost worth;
+} Chromosome;
+
+typedef struct Pool
+{
+ Chromosome *data;
+ int size;
+ int string_length;
+} Pool;
+
+#endif /* GEQO_GENE_H */
diff --git a/src/include/optimizer/geqo_misc.h b/src/include/optimizer/geqo_misc.h
new file mode 100644
index 0000000..93e6123
--- /dev/null
+++ b/src/include/optimizer/geqo_misc.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * geqo_misc.h
+ * prototypes for printout routines in optimizer/geqo
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/geqo_misc.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* contributed by:
+ =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+ * Martin Utesch * Institute of Automatic Control *
+ = = University of Mining and Technology =
+ * utesch@aut.tu-freiberg.de * Freiberg, Germany *
+ =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+ */
+
+#ifndef GEQO_MISC_H
+#define GEQO_MISC_H
+
+#include "optimizer/geqo_recombination.h"
+
+#ifdef GEQO_DEBUG
+
+extern void print_pool(FILE *fp, Pool *pool, int start, int stop);
+extern void print_gen(FILE *fp, Pool *pool, int generation);
+extern void print_edge_table(FILE *fp, Edge *edge_table, int num_gene);
+#endif /* GEQO_DEBUG */
+
+#endif /* GEQO_MISC_H */
diff --git a/src/include/optimizer/geqo_mutation.h b/src/include/optimizer/geqo_mutation.h
new file mode 100644
index 0000000..bed5696
--- /dev/null
+++ b/src/include/optimizer/geqo_mutation.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * geqo_mutation.h
+ * prototypes for mutation functions in optimizer/geqo
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/geqo_mutation.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* contributed by:
+ =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+ * Martin Utesch * Institute of Automatic Control *
+ = = University of Mining and Technology =
+ * utesch@aut.tu-freiberg.de * Freiberg, Germany *
+ =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+ */
+
+#ifndef GEQO_MUTATION_H
+#define GEQO_MUTATION_H
+
+#include "optimizer/geqo.h"
+
+
+extern void geqo_mutation(PlannerInfo *root, Gene *tour, int num_gene);
+
+#endif /* GEQO_MUTATION_H */
diff --git a/src/include/optimizer/geqo_pool.h b/src/include/optimizer/geqo_pool.h
new file mode 100644
index 0000000..c3497a6
--- /dev/null
+++ b/src/include/optimizer/geqo_pool.h
@@ -0,0 +1,40 @@
+/*-------------------------------------------------------------------------
+ *
+ * geqo_pool.h
+ * pool representation in optimizer/geqo
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/geqo_pool.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* contributed by:
+ =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+ * Martin Utesch * Institute of Automatic Control *
+ = = University of Mining and Technology =
+ * utesch@aut.tu-freiberg.de * Freiberg, Germany *
+ =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+ */
+
+
+#ifndef GEQO_POOL_H
+#define GEQO_POOL_H
+
+#include "optimizer/geqo.h"
+
+
+extern Pool *alloc_pool(PlannerInfo *root, int pool_size, int string_length);
+extern void free_pool(PlannerInfo *root, Pool *pool);
+
+extern void random_init_pool(PlannerInfo *root, Pool *pool);
+extern Chromosome *alloc_chromo(PlannerInfo *root, int string_length);
+extern void free_chromo(PlannerInfo *root, Chromosome *chromo);
+
+extern void spread_chromo(PlannerInfo *root, Chromosome *chromo, Pool *pool);
+
+extern void sort_pool(PlannerInfo *root, Pool *pool);
+
+#endif /* GEQO_POOL_H */
diff --git a/src/include/optimizer/geqo_random.h b/src/include/optimizer/geqo_random.h
new file mode 100644
index 0000000..54898c1
--- /dev/null
+++ b/src/include/optimizer/geqo_random.h
@@ -0,0 +1,41 @@
+/*-------------------------------------------------------------------------
+ *
+ * geqo_random.h
+ * random number generator
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/geqo_random.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* contributed by:
+ =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+ * Martin Utesch * Institute of Automatic Control *
+ = = University of Mining and Technology =
+ * utesch@aut.tu-freiberg.de * Freiberg, Germany *
+ =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+ */
+
+/* -- parts of this are adapted from D. Whitley's Genitor algorithm -- */
+
+#ifndef GEQO_RANDOM_H
+#define GEQO_RANDOM_H
+
+#include <math.h>
+
+#include "optimizer/geqo.h"
+
+
+extern void geqo_set_seed(PlannerInfo *root, double seed);
+
+/* geqo_rand returns a random float value between 0 and 1 inclusive */
+extern double geqo_rand(PlannerInfo *root);
+
+/* geqo_randint returns integer value between lower and upper inclusive */
+#define geqo_randint(root, upper, lower) \
+ ( (int) floor( geqo_rand(root)*(((upper)-(lower))+0.999999) ) + (lower) )
+
+#endif /* GEQO_RANDOM_H */
diff --git a/src/include/optimizer/geqo_recombination.h b/src/include/optimizer/geqo_recombination.h
new file mode 100644
index 0000000..921cf14
--- /dev/null
+++ b/src/include/optimizer/geqo_recombination.h
@@ -0,0 +1,89 @@
+/*-------------------------------------------------------------------------
+ *
+ * geqo_recombination.h
+ * prototypes for recombination in the genetic query optimizer
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/geqo_recombination.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* contributed by:
+ =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+ * Martin Utesch * Institute of Automatic Control *
+ = = University of Mining and Technology =
+ * utesch@aut.tu-freiberg.de * Freiberg, Germany *
+ =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+ */
+
+/* -- parts of this are adapted from D. Whitley's Genitor algorithm -- */
+
+#ifndef GEQO_RECOMBINATION_H
+#define GEQO_RECOMBINATION_H
+
+#include "optimizer/geqo.h"
+
+
+extern void init_tour(PlannerInfo *root, Gene *tour, int num_gene);
+
+
+/* edge recombination crossover [ERX] */
+
+typedef struct Edge
+{
+ Gene edge_list[4]; /* list of edges */
+ int total_edges;
+ int unused_edges;
+} Edge;
+
+extern Edge *alloc_edge_table(PlannerInfo *root, int num_gene);
+extern void free_edge_table(PlannerInfo *root, Edge *edge_table);
+
+extern float gimme_edge_table(PlannerInfo *root, Gene *tour1, Gene *tour2,
+ int num_gene, Edge *edge_table);
+
+extern int gimme_tour(PlannerInfo *root, Edge *edge_table, Gene *new_gene,
+ int num_gene);
+
+
+/* partially matched crossover [PMX] */
+
+#define DAD 1 /* indicator for gene from dad */
+#define MOM 0 /* indicator for gene from mom */
+
+extern void pmx(PlannerInfo *root,
+ Gene *tour1, Gene *tour2,
+ Gene *offspring, int num_gene);
+
+
+typedef struct City
+{
+ int tour2_position;
+ int tour1_position;
+ int used;
+ int select_list;
+} City;
+
+extern City * alloc_city_table(PlannerInfo *root, int num_gene);
+extern void free_city_table(PlannerInfo *root, City * city_table);
+
+/* cycle crossover [CX] */
+extern int cx(PlannerInfo *root, Gene *tour1, Gene *tour2,
+ Gene *offspring, int num_gene, City * city_table);
+
+/* position crossover [PX] */
+extern void px(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring,
+ int num_gene, City * city_table);
+
+/* order crossover [OX1] according to Davis */
+extern void ox1(PlannerInfo *root, Gene *mom, Gene *dad, Gene *offspring,
+ int num_gene, City * city_table);
+
+/* order crossover [OX2] according to Syswerda */
+extern void ox2(PlannerInfo *root, Gene *mom, Gene *dad, Gene *offspring,
+ int num_gene, City * city_table);
+
+#endif /* GEQO_RECOMBINATION_H */
diff --git a/src/include/optimizer/geqo_selection.h b/src/include/optimizer/geqo_selection.h
new file mode 100644
index 0000000..9f0f7b7
--- /dev/null
+++ b/src/include/optimizer/geqo_selection.h
@@ -0,0 +1,33 @@
+/*-------------------------------------------------------------------------
+ *
+ * geqo_selection.h
+ * prototypes for selection routines in optimizer/geqo
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/geqo_selection.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* contributed by:
+ =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+ * Martin Utesch * Institute of Automatic Control *
+ = = University of Mining and Technology =
+ * utesch@aut.tu-freiberg.de * Freiberg, Germany *
+ =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
+ */
+
+
+#ifndef GEQO_SELECTION_H
+#define GEQO_SELECTION_H
+
+#include "optimizer/geqo.h"
+
+
+extern void geqo_selection(PlannerInfo *root,
+ Chromosome *momma, Chromosome *daddy,
+ Pool *pool, double bias);
+
+#endif /* GEQO_SELECTION_H */
diff --git a/src/include/optimizer/inherit.h b/src/include/optimizer/inherit.h
new file mode 100644
index 0000000..0ba6132
--- /dev/null
+++ b/src/include/optimizer/inherit.h
@@ -0,0 +1,27 @@
+/*-------------------------------------------------------------------------
+ *
+ * inherit.h
+ * prototypes for inherit.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/inherit.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef INHERIT_H
+#define INHERIT_H
+
+#include "nodes/pathnodes.h"
+
+
+extern void expand_inherited_rtentry(PlannerInfo *root, RelOptInfo *rel,
+ RangeTblEntry *rte, Index rti);
+
+extern bool apply_child_basequals(PlannerInfo *root, RelOptInfo *parentrel,
+ RelOptInfo *childrel, RangeTblEntry *childRTE,
+ AppendRelInfo *appinfo);
+
+#endif /* INHERIT_H */
diff --git a/src/include/optimizer/joininfo.h b/src/include/optimizer/joininfo.h
new file mode 100644
index 0000000..753d2ef
--- /dev/null
+++ b/src/include/optimizer/joininfo.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * joininfo.h
+ * prototypes for joininfo.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/joininfo.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef JOININFO_H
+#define JOININFO_H
+
+#include "nodes/pathnodes.h"
+
+
+extern bool have_relevant_joinclause(PlannerInfo *root,
+ RelOptInfo *rel1, RelOptInfo *rel2);
+
+extern void add_join_clause_to_rels(PlannerInfo *root,
+ RestrictInfo *restrictinfo,
+ Relids join_relids);
+extern void remove_join_clause_from_rels(PlannerInfo *root,
+ RestrictInfo *restrictinfo,
+ Relids join_relids);
+
+#endif /* JOININFO_H */
diff --git a/src/include/optimizer/optimizer.h b/src/include/optimizer/optimizer.h
new file mode 100644
index 0000000..3c588de
--- /dev/null
+++ b/src/include/optimizer/optimizer.h
@@ -0,0 +1,199 @@
+/*-------------------------------------------------------------------------
+ *
+ * optimizer.h
+ * External API for the Postgres planner.
+ *
+ * This header is meant to define everything that the core planner
+ * exposes for use by non-planner modules.
+ *
+ * Note that there are files outside src/backend/optimizer/ that are
+ * considered planner modules, because they're too much in bed with
+ * planner operations to be treated otherwise. FDW planning code is an
+ * example. For the most part, however, code outside the core planner
+ * should not need to include any optimizer/ header except this one.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/optimizer.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef OPTIMIZER_H
+#define OPTIMIZER_H
+
+#include "nodes/parsenodes.h"
+
+/* Test if an expression node represents a SRF call. Beware multiple eval! */
+#define IS_SRF_CALL(node) \
+ ((IsA(node, FuncExpr) && ((FuncExpr *) (node))->funcretset) || \
+ (IsA(node, OpExpr) && ((OpExpr *) (node))->opretset))
+
+/*
+ * We don't want to include nodes/pathnodes.h here, because non-planner
+ * code should generally treat PlannerInfo as an opaque typedef.
+ * But we'd like such code to use that typedef name, so define the
+ * typedef either here or in pathnodes.h, whichever is read first.
+ */
+#ifndef HAVE_PLANNERINFO_TYPEDEF
+typedef struct PlannerInfo PlannerInfo;
+#define HAVE_PLANNERINFO_TYPEDEF 1
+#endif
+
+/* Likewise for IndexOptInfo and SpecialJoinInfo. */
+#ifndef HAVE_INDEXOPTINFO_TYPEDEF
+typedef struct IndexOptInfo IndexOptInfo;
+#define HAVE_INDEXOPTINFO_TYPEDEF 1
+#endif
+#ifndef HAVE_SPECIALJOININFO_TYPEDEF
+typedef struct SpecialJoinInfo SpecialJoinInfo;
+#define HAVE_SPECIALJOININFO_TYPEDEF 1
+#endif
+
+/* It also seems best not to include plannodes.h, params.h, or htup.h here */
+struct PlannedStmt;
+struct ParamListInfoData;
+struct HeapTupleData;
+
+
+/* in path/clausesel.c: */
+
+extern Selectivity clause_selectivity(PlannerInfo *root,
+ Node *clause,
+ int varRelid,
+ JoinType jointype,
+ SpecialJoinInfo *sjinfo);
+extern Selectivity clauselist_selectivity_simple(PlannerInfo *root,
+ List *clauses,
+ int varRelid,
+ JoinType jointype,
+ SpecialJoinInfo *sjinfo,
+ Bitmapset *estimatedclauses);
+extern Selectivity clauselist_selectivity(PlannerInfo *root,
+ List *clauses,
+ int varRelid,
+ JoinType jointype,
+ SpecialJoinInfo *sjinfo);
+
+/* in path/costsize.c: */
+
+/* widely used cost parameters */
+extern PGDLLIMPORT double seq_page_cost;
+extern PGDLLIMPORT double random_page_cost;
+extern PGDLLIMPORT double cpu_tuple_cost;
+extern PGDLLIMPORT double cpu_index_tuple_cost;
+extern PGDLLIMPORT double cpu_operator_cost;
+extern PGDLLIMPORT double parallel_tuple_cost;
+extern PGDLLIMPORT double parallel_setup_cost;
+extern PGDLLIMPORT int effective_cache_size;
+
+extern double clamp_row_est(double nrows);
+
+/* in path/indxpath.c: */
+
+extern bool is_pseudo_constant_for_index(Node *expr, IndexOptInfo *index);
+extern bool is_pseudo_constant_for_index_new(PlannerInfo *root, Node *expr,
+ IndexOptInfo *index);
+
+/* in plan/planner.c: */
+
+/* possible values for force_parallel_mode */
+typedef enum
+{
+ FORCE_PARALLEL_OFF,
+ FORCE_PARALLEL_ON,
+ FORCE_PARALLEL_REGRESS
+} ForceParallelMode;
+
+/* GUC parameters */
+extern int force_parallel_mode;
+extern bool parallel_leader_participation;
+
+extern struct PlannedStmt *planner(Query *parse, const char *query_string,
+ int cursorOptions,
+ struct ParamListInfoData *boundParams);
+
+extern Expr *expression_planner(Expr *expr);
+extern Expr *expression_planner_with_deps(Expr *expr,
+ List **relationOids,
+ List **invalItems);
+
+extern bool plan_cluster_use_sort(Oid tableOid, Oid indexOid);
+extern int plan_create_index_workers(Oid tableOid, Oid indexOid);
+
+/* in plan/setrefs.c: */
+
+extern void extract_query_dependencies(Node *query,
+ List **relationOids,
+ List **invalItems,
+ bool *hasRowSecurity);
+
+/* in prep/prepqual.c: */
+
+extern Node *negate_clause(Node *node);
+extern Expr *canonicalize_qual(Expr *qual, bool is_check);
+
+/* in util/clauses.c: */
+
+extern bool contain_mutable_functions(Node *clause);
+extern bool contain_volatile_functions(Node *clause);
+extern bool contain_volatile_functions_not_nextval(Node *clause);
+
+extern Node *eval_const_expressions(PlannerInfo *root, Node *node);
+
+extern Node *estimate_expression_value(PlannerInfo *root, Node *node);
+
+extern Expr *evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
+ Oid result_collation);
+
+extern List *expand_function_arguments(List *args, Oid result_type,
+ struct HeapTupleData *func_tuple);
+
+/* in util/predtest.c: */
+
+extern bool predicate_implied_by(List *predicate_list, List *clause_list,
+ bool weak);
+extern bool predicate_refuted_by(List *predicate_list, List *clause_list,
+ bool weak);
+
+/* in util/tlist.c: */
+
+extern int count_nonjunk_tlist_entries(List *tlist);
+extern TargetEntry *get_sortgroupref_tle(Index sortref,
+ List *targetList);
+extern TargetEntry *get_sortgroupclause_tle(SortGroupClause *sgClause,
+ List *targetList);
+extern Node *get_sortgroupclause_expr(SortGroupClause *sgClause,
+ List *targetList);
+extern List *get_sortgrouplist_exprs(List *sgClauses,
+ List *targetList);
+extern SortGroupClause *get_sortgroupref_clause(Index sortref,
+ List *clauses);
+extern SortGroupClause *get_sortgroupref_clause_noerr(Index sortref,
+ List *clauses);
+
+/* in util/var.c: */
+
+/* Bits that can be OR'd into the flags argument of pull_var_clause() */
+#define PVC_INCLUDE_AGGREGATES 0x0001 /* include Aggrefs in output list */
+#define PVC_RECURSE_AGGREGATES 0x0002 /* recurse into Aggref arguments */
+#define PVC_INCLUDE_WINDOWFUNCS 0x0004 /* include WindowFuncs in output list */
+#define PVC_RECURSE_WINDOWFUNCS 0x0008 /* recurse into WindowFunc arguments */
+#define PVC_INCLUDE_PLACEHOLDERS 0x0010 /* include PlaceHolderVars in
+ * output list */
+#define PVC_RECURSE_PLACEHOLDERS 0x0020 /* recurse into PlaceHolderVar
+ * arguments */
+
+extern Bitmapset *pull_varnos(Node *node);
+extern Bitmapset *pull_varnos_of_level(Node *node, int levelsup);
+extern Bitmapset *pull_varnos_new(PlannerInfo *root, Node *node);
+extern Bitmapset *pull_varnos_of_level_new(PlannerInfo *root, Node *node, int levelsup);
+extern void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos);
+extern List *pull_vars_of_level(Node *node, int levelsup);
+extern bool contain_var_clause(Node *node);
+extern bool contain_vars_of_level(Node *node, int levelsup);
+extern int locate_var_of_level(Node *node, int levelsup);
+extern List *pull_var_clause(Node *node, int flags);
+extern Node *flatten_join_alias_vars(Query *query, Node *node);
+
+#endif /* OPTIMIZER_H */
diff --git a/src/include/optimizer/orclauses.h b/src/include/optimizer/orclauses.h
new file mode 100644
index 0000000..b5377fc
--- /dev/null
+++ b/src/include/optimizer/orclauses.h
@@ -0,0 +1,21 @@
+/*-------------------------------------------------------------------------
+ *
+ * orclauses.h
+ * prototypes for orclauses.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/orclauses.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ORCLAUSES_H
+#define ORCLAUSES_H
+
+#include "nodes/pathnodes.h"
+
+extern void extract_restriction_or_clauses(PlannerInfo *root);
+
+#endif /* ORCLAUSES_H */
diff --git a/src/include/optimizer/paramassign.h b/src/include/optimizer/paramassign.h
new file mode 100644
index 0000000..02b4b50
--- /dev/null
+++ b/src/include/optimizer/paramassign.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * paramassign.h
+ * Functions for assigning PARAM_EXEC slots during planning.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/paramassign.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARAMASSIGN_H
+#define PARAMASSIGN_H
+
+#include "nodes/pathnodes.h"
+
+extern Param *replace_outer_var(PlannerInfo *root, Var *var);
+extern Param *replace_outer_placeholdervar(PlannerInfo *root,
+ PlaceHolderVar *phv);
+extern Param *replace_outer_agg(PlannerInfo *root, Aggref *agg);
+extern Param *replace_outer_grouping(PlannerInfo *root, GroupingFunc *grp);
+extern Param *replace_nestloop_param_var(PlannerInfo *root, Var *var);
+extern Param *replace_nestloop_param_placeholdervar(PlannerInfo *root,
+ PlaceHolderVar *phv);
+extern void process_subquery_nestloop_params(PlannerInfo *root,
+ List *subplan_params);
+extern List *identify_current_nestloop_params(PlannerInfo *root,
+ Relids leftrelids);
+extern Param *generate_new_exec_param(PlannerInfo *root, Oid paramtype,
+ int32 paramtypmod, Oid paramcollation);
+extern int assign_special_exec_param(PlannerInfo *root);
+
+#endif /* PARAMASSIGN_H */
diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h
new file mode 100644
index 0000000..3bd7072
--- /dev/null
+++ b/src/include/optimizer/pathnode.h
@@ -0,0 +1,324 @@
+/*-------------------------------------------------------------------------
+ *
+ * pathnode.h
+ * prototypes for pathnode.c, relnode.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/pathnode.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PATHNODE_H
+#define PATHNODE_H
+
+#include "nodes/bitmapset.h"
+#include "nodes/pathnodes.h"
+
+
+/*
+ * prototypes for pathnode.c
+ */
+extern int compare_path_costs(Path *path1, Path *path2,
+ CostSelector criterion);
+extern int compare_fractional_path_costs(Path *path1, Path *path2,
+ double fraction);
+extern void set_cheapest(RelOptInfo *parent_rel);
+extern void add_path(RelOptInfo *parent_rel, Path *new_path);
+extern bool add_path_precheck(RelOptInfo *parent_rel,
+ Cost startup_cost, Cost total_cost,
+ List *pathkeys, Relids required_outer);
+extern void add_partial_path(RelOptInfo *parent_rel, Path *new_path);
+extern bool add_partial_path_precheck(RelOptInfo *parent_rel,
+ Cost total_cost, List *pathkeys);
+
+extern Path *create_seqscan_path(PlannerInfo *root, RelOptInfo *rel,
+ Relids required_outer, int parallel_workers);
+extern Path *create_samplescan_path(PlannerInfo *root, RelOptInfo *rel,
+ Relids required_outer);
+extern IndexPath *create_index_path(PlannerInfo *root,
+ IndexOptInfo *index,
+ List *indexclauses,
+ List *indexorderbys,
+ List *indexorderbycols,
+ List *pathkeys,
+ ScanDirection indexscandir,
+ bool indexonly,
+ Relids required_outer,
+ double loop_count,
+ bool partial_path);
+extern BitmapHeapPath *create_bitmap_heap_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ Path *bitmapqual,
+ Relids required_outer,
+ double loop_count,
+ int parallel_degree);
+extern BitmapAndPath *create_bitmap_and_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ List *bitmapquals);
+extern BitmapOrPath *create_bitmap_or_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ List *bitmapquals);
+extern TidPath *create_tidscan_path(PlannerInfo *root, RelOptInfo *rel,
+ List *tidquals, Relids required_outer);
+extern AppendPath *create_append_path(PlannerInfo *root, RelOptInfo *rel,
+ List *subpaths, List *partial_subpaths,
+ List *pathkeys, Relids required_outer,
+ int parallel_workers, bool parallel_aware,
+ List *partitioned_rels, double rows);
+extern MergeAppendPath *create_merge_append_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ List *subpaths,
+ List *pathkeys,
+ Relids required_outer,
+ List *partitioned_rels);
+extern GroupResultPath *create_group_result_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ PathTarget *target,
+ List *havingqual);
+extern MaterialPath *create_material_path(RelOptInfo *rel, Path *subpath);
+extern UniquePath *create_unique_path(PlannerInfo *root, RelOptInfo *rel,
+ Path *subpath, SpecialJoinInfo *sjinfo);
+extern GatherPath *create_gather_path(PlannerInfo *root,
+ RelOptInfo *rel, Path *subpath, PathTarget *target,
+ Relids required_outer, double *rows);
+extern GatherMergePath *create_gather_merge_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ Path *subpath,
+ PathTarget *target,
+ List *pathkeys,
+ Relids required_outer,
+ double *rows);
+extern SubqueryScanPath *create_subqueryscan_path(PlannerInfo *root,
+ RelOptInfo *rel, Path *subpath,
+ List *pathkeys, Relids required_outer);
+extern Path *create_functionscan_path(PlannerInfo *root, RelOptInfo *rel,
+ List *pathkeys, Relids required_outer);
+extern Path *create_valuesscan_path(PlannerInfo *root, RelOptInfo *rel,
+ Relids required_outer);
+extern Path *create_tablefuncscan_path(PlannerInfo *root, RelOptInfo *rel,
+ Relids required_outer);
+extern Path *create_ctescan_path(PlannerInfo *root, RelOptInfo *rel,
+ Relids required_outer);
+extern Path *create_namedtuplestorescan_path(PlannerInfo *root, RelOptInfo *rel,
+ Relids required_outer);
+extern Path *create_resultscan_path(PlannerInfo *root, RelOptInfo *rel,
+ Relids required_outer);
+extern Path *create_worktablescan_path(PlannerInfo *root, RelOptInfo *rel,
+ Relids required_outer);
+extern ForeignPath *create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel,
+ PathTarget *target,
+ double rows, Cost startup_cost, Cost total_cost,
+ List *pathkeys,
+ Relids required_outer,
+ Path *fdw_outerpath,
+ List *fdw_private);
+extern ForeignPath *create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel,
+ PathTarget *target,
+ double rows, Cost startup_cost, Cost total_cost,
+ List *pathkeys,
+ Relids required_outer,
+ Path *fdw_outerpath,
+ List *fdw_private);
+extern ForeignPath *create_foreign_upper_path(PlannerInfo *root, RelOptInfo *rel,
+ PathTarget *target,
+ double rows, Cost startup_cost, Cost total_cost,
+ List *pathkeys,
+ Path *fdw_outerpath,
+ List *fdw_private);
+
+extern Relids calc_nestloop_required_outer(Relids outerrelids,
+ Relids outer_paramrels,
+ Relids innerrelids,
+ Relids inner_paramrels);
+extern Relids calc_non_nestloop_required_outer(Path *outer_path, Path *inner_path);
+
+extern NestPath *create_nestloop_path(PlannerInfo *root,
+ RelOptInfo *joinrel,
+ JoinType jointype,
+ JoinCostWorkspace *workspace,
+ JoinPathExtraData *extra,
+ Path *outer_path,
+ Path *inner_path,
+ List *restrict_clauses,
+ List *pathkeys,
+ Relids required_outer);
+
+extern MergePath *create_mergejoin_path(PlannerInfo *root,
+ RelOptInfo *joinrel,
+ JoinType jointype,
+ JoinCostWorkspace *workspace,
+ JoinPathExtraData *extra,
+ Path *outer_path,
+ Path *inner_path,
+ List *restrict_clauses,
+ List *pathkeys,
+ Relids required_outer,
+ List *mergeclauses,
+ List *outersortkeys,
+ List *innersortkeys);
+
+extern HashPath *create_hashjoin_path(PlannerInfo *root,
+ RelOptInfo *joinrel,
+ JoinType jointype,
+ JoinCostWorkspace *workspace,
+ JoinPathExtraData *extra,
+ Path *outer_path,
+ Path *inner_path,
+ bool parallel_hash,
+ List *restrict_clauses,
+ Relids required_outer,
+ List *hashclauses);
+
+extern ProjectionPath *create_projection_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ Path *subpath,
+ PathTarget *target);
+extern Path *apply_projection_to_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ Path *path,
+ PathTarget *target);
+extern ProjectSetPath *create_set_projection_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ Path *subpath,
+ PathTarget *target);
+extern SortPath *create_sort_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ Path *subpath,
+ List *pathkeys,
+ double limit_tuples);
+extern IncrementalSortPath *create_incremental_sort_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ Path *subpath,
+ List *pathkeys,
+ int presorted_keys,
+ double limit_tuples);
+extern GroupPath *create_group_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ Path *subpath,
+ List *groupClause,
+ List *qual,
+ double numGroups);
+extern UpperUniquePath *create_upper_unique_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ Path *subpath,
+ int numCols,
+ double numGroups);
+extern AggPath *create_agg_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ Path *subpath,
+ PathTarget *target,
+ AggStrategy aggstrategy,
+ AggSplit aggsplit,
+ List *groupClause,
+ List *qual,
+ const AggClauseCosts *aggcosts,
+ double numGroups);
+extern GroupingSetsPath *create_groupingsets_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ Path *subpath,
+ List *having_qual,
+ AggStrategy aggstrategy,
+ List *rollups,
+ const AggClauseCosts *agg_costs,
+ double numGroups);
+extern MinMaxAggPath *create_minmaxagg_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ PathTarget *target,
+ List *mmaggregates,
+ List *quals);
+extern WindowAggPath *create_windowagg_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ Path *subpath,
+ PathTarget *target,
+ List *windowFuncs,
+ WindowClause *winclause);
+extern SetOpPath *create_setop_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ Path *subpath,
+ SetOpCmd cmd,
+ SetOpStrategy strategy,
+ List *distinctList,
+ AttrNumber flagColIdx,
+ int firstFlag,
+ double numGroups,
+ double outputRows);
+extern RecursiveUnionPath *create_recursiveunion_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ Path *leftpath,
+ Path *rightpath,
+ PathTarget *target,
+ List *distinctList,
+ int wtParam,
+ double numGroups);
+extern LockRowsPath *create_lockrows_path(PlannerInfo *root, RelOptInfo *rel,
+ Path *subpath, List *rowMarks, int epqParam);
+extern ModifyTablePath *create_modifytable_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ CmdType operation, bool canSetTag,
+ Index nominalRelation, Index rootRelation,
+ bool partColsUpdated,
+ List *resultRelations, List *subpaths,
+ List *subroots,
+ List *withCheckOptionLists, List *returningLists,
+ List *rowMarks, OnConflictExpr *onconflict,
+ int epqParam);
+extern LimitPath *create_limit_path(PlannerInfo *root, RelOptInfo *rel,
+ Path *subpath,
+ Node *limitOffset, Node *limitCount,
+ LimitOption limitOption,
+ int64 offset_est, int64 count_est);
+extern void adjust_limit_rows_costs(double *rows,
+ Cost *startup_cost, Cost *total_cost,
+ int64 offset_est, int64 count_est);
+
+extern Path *reparameterize_path(PlannerInfo *root, Path *path,
+ Relids required_outer,
+ double loop_count);
+extern Path *reparameterize_path_by_child(PlannerInfo *root, Path *path,
+ RelOptInfo *child_rel);
+
+/*
+ * prototypes for relnode.c
+ */
+extern void setup_simple_rel_arrays(PlannerInfo *root);
+extern void expand_planner_arrays(PlannerInfo *root, int add_size);
+extern RelOptInfo *build_simple_rel(PlannerInfo *root, int relid,
+ RelOptInfo *parent);
+extern RelOptInfo *find_base_rel(PlannerInfo *root, int relid);
+extern RelOptInfo *find_join_rel(PlannerInfo *root, Relids relids);
+extern RelOptInfo *build_join_rel(PlannerInfo *root,
+ Relids joinrelids,
+ RelOptInfo *outer_rel,
+ RelOptInfo *inner_rel,
+ SpecialJoinInfo *sjinfo,
+ List **restrictlist_ptr);
+extern Relids min_join_parameterization(PlannerInfo *root,
+ Relids joinrelids,
+ RelOptInfo *outer_rel,
+ RelOptInfo *inner_rel);
+extern RelOptInfo *fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind,
+ Relids relids);
+extern Relids find_childrel_parents(PlannerInfo *root, RelOptInfo *rel);
+extern ParamPathInfo *get_baserel_parampathinfo(PlannerInfo *root,
+ RelOptInfo *baserel,
+ Relids required_outer);
+extern ParamPathInfo *get_joinrel_parampathinfo(PlannerInfo *root,
+ RelOptInfo *joinrel,
+ Path *outer_path,
+ Path *inner_path,
+ SpecialJoinInfo *sjinfo,
+ Relids required_outer,
+ List **restrict_clauses);
+extern ParamPathInfo *get_appendrel_parampathinfo(RelOptInfo *appendrel,
+ Relids required_outer);
+extern ParamPathInfo *find_param_path_info(RelOptInfo *rel,
+ Relids required_outer);
+extern RelOptInfo *build_child_join_rel(PlannerInfo *root,
+ RelOptInfo *outer_rel, RelOptInfo *inner_rel,
+ RelOptInfo *parent_joinrel, List *restrictlist,
+ SpecialJoinInfo *sjinfo, JoinType jointype);
+
+#endif /* PATHNODE_H */
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
new file mode 100644
index 0000000..9254ee0
--- /dev/null
+++ b/src/include/optimizer/paths.h
@@ -0,0 +1,257 @@
+/*-------------------------------------------------------------------------
+ *
+ * paths.h
+ * prototypes for various files in optimizer/path
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/paths.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PATHS_H
+#define PATHS_H
+
+#include "nodes/pathnodes.h"
+
+
+/*
+ * allpaths.c
+ */
+extern PGDLLIMPORT bool enable_geqo;
+extern PGDLLIMPORT int geqo_threshold;
+extern PGDLLIMPORT int min_parallel_table_scan_size;
+extern PGDLLIMPORT int min_parallel_index_scan_size;
+
+/* Hook for plugins to get control in set_rel_pathlist() */
+typedef void (*set_rel_pathlist_hook_type) (PlannerInfo *root,
+ RelOptInfo *rel,
+ Index rti,
+ RangeTblEntry *rte);
+extern PGDLLIMPORT set_rel_pathlist_hook_type set_rel_pathlist_hook;
+
+/* Hook for plugins to get control in add_paths_to_joinrel() */
+typedef void (*set_join_pathlist_hook_type) (PlannerInfo *root,
+ RelOptInfo *joinrel,
+ RelOptInfo *outerrel,
+ RelOptInfo *innerrel,
+ JoinType jointype,
+ JoinPathExtraData *extra);
+extern PGDLLIMPORT set_join_pathlist_hook_type set_join_pathlist_hook;
+
+/* Hook for plugins to replace standard_join_search() */
+typedef RelOptInfo *(*join_search_hook_type) (PlannerInfo *root,
+ int levels_needed,
+ List *initial_rels);
+extern PGDLLIMPORT join_search_hook_type join_search_hook;
+
+
+extern RelOptInfo *make_one_rel(PlannerInfo *root, List *joinlist);
+extern RelOptInfo *standard_join_search(PlannerInfo *root, int levels_needed,
+ List *initial_rels);
+
+extern void generate_gather_paths(PlannerInfo *root, RelOptInfo *rel,
+ bool override_rows);
+extern void generate_useful_gather_paths(PlannerInfo *root, RelOptInfo *rel,
+ bool override_rows);
+extern int compute_parallel_worker(RelOptInfo *rel, double heap_pages,
+ double index_pages, int max_workers);
+extern void create_partial_bitmap_paths(PlannerInfo *root, RelOptInfo *rel,
+ Path *bitmapqual);
+extern void generate_partitionwise_join_paths(PlannerInfo *root,
+ RelOptInfo *rel);
+
+#ifdef OPTIMIZER_DEBUG
+extern void debug_print_rel(PlannerInfo *root, RelOptInfo *rel);
+#endif
+
+/*
+ * indxpath.c
+ * routines to generate index paths
+ */
+extern void create_index_paths(PlannerInfo *root, RelOptInfo *rel);
+extern bool relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel,
+ List *restrictlist,
+ List *exprlist, List *oprlist);
+extern bool indexcol_is_bool_constant_for_query(PlannerInfo *root,
+ IndexOptInfo *index,
+ int indexcol);
+extern bool match_index_to_operand(Node *operand, int indexcol,
+ IndexOptInfo *index);
+extern void check_index_predicates(PlannerInfo *root, RelOptInfo *rel);
+
+/*
+ * tidpath.h
+ * routines to generate tid paths
+ */
+extern void create_tidscan_paths(PlannerInfo *root, RelOptInfo *rel);
+
+/*
+ * joinpath.c
+ * routines to create join paths
+ */
+extern void add_paths_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel,
+ RelOptInfo *outerrel, RelOptInfo *innerrel,
+ JoinType jointype, SpecialJoinInfo *sjinfo,
+ List *restrictlist);
+
+/*
+ * joinrels.c
+ * routines to determine which relations to join
+ */
+extern void join_search_one_level(PlannerInfo *root, int level);
+extern RelOptInfo *make_join_rel(PlannerInfo *root,
+ RelOptInfo *rel1, RelOptInfo *rel2);
+extern bool have_join_order_restriction(PlannerInfo *root,
+ RelOptInfo *rel1, RelOptInfo *rel2);
+extern bool have_dangerous_phv(PlannerInfo *root,
+ Relids outer_relids, Relids inner_params);
+extern void mark_dummy_rel(RelOptInfo *rel);
+
+/*
+ * equivclass.c
+ * routines for managing EquivalenceClasses
+ */
+typedef bool (*ec_matches_callback_type) (PlannerInfo *root,
+ RelOptInfo *rel,
+ EquivalenceClass *ec,
+ EquivalenceMember *em,
+ void *arg);
+
+extern bool process_equivalence(PlannerInfo *root,
+ RestrictInfo **p_restrictinfo,
+ bool below_outer_join);
+extern Expr *canonicalize_ec_expression(Expr *expr,
+ Oid req_type, Oid req_collation);
+extern void reconsider_outer_join_clauses(PlannerInfo *root);
+extern EquivalenceClass *get_eclass_for_sort_expr(PlannerInfo *root,
+ Expr *expr,
+ Relids nullable_relids,
+ List *opfamilies,
+ Oid opcintype,
+ Oid collation,
+ Index sortref,
+ Relids rel,
+ bool create_it);
+extern EquivalenceMember *find_ec_member_matching_expr(EquivalenceClass *ec,
+ Expr *expr,
+ Relids relids);
+extern EquivalenceMember *find_computable_ec_member(PlannerInfo *root,
+ EquivalenceClass *ec,
+ List *exprs,
+ Relids relids,
+ bool require_parallel_safe);
+extern Expr *find_em_expr_for_rel(EquivalenceClass *ec, RelOptInfo *rel);
+extern Expr *find_em_expr_usable_for_sorting_rel(PlannerInfo *root,
+ EquivalenceClass *ec,
+ RelOptInfo *rel,
+ bool require_parallel_safe);
+extern void generate_base_implied_equalities(PlannerInfo *root);
+extern List *generate_join_implied_equalities(PlannerInfo *root,
+ Relids join_relids,
+ Relids outer_relids,
+ RelOptInfo *inner_rel);
+extern List *generate_join_implied_equalities_for_ecs(PlannerInfo *root,
+ List *eclasses,
+ Relids join_relids,
+ Relids outer_relids,
+ RelOptInfo *inner_rel);
+extern bool exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2);
+extern EquivalenceClass *match_eclasses_to_foreign_key_col(PlannerInfo *root,
+ ForeignKeyOptInfo *fkinfo,
+ int colno);
+extern void add_child_rel_equivalences(PlannerInfo *root,
+ AppendRelInfo *appinfo,
+ RelOptInfo *parent_rel,
+ RelOptInfo *child_rel);
+extern void add_child_join_rel_equivalences(PlannerInfo *root,
+ int nappinfos,
+ AppendRelInfo **appinfos,
+ RelOptInfo *parent_rel,
+ RelOptInfo *child_rel);
+extern List *generate_implied_equalities_for_column(PlannerInfo *root,
+ RelOptInfo *rel,
+ ec_matches_callback_type callback,
+ void *callback_arg,
+ Relids prohibited_rels);
+extern bool have_relevant_eclass_joinclause(PlannerInfo *root,
+ RelOptInfo *rel1, RelOptInfo *rel2);
+extern bool has_relevant_eclass_joinclause(PlannerInfo *root,
+ RelOptInfo *rel1);
+extern bool eclass_useful_for_merging(PlannerInfo *root,
+ EquivalenceClass *eclass,
+ RelOptInfo *rel);
+extern bool is_redundant_derived_clause(RestrictInfo *rinfo, List *clauselist);
+extern bool is_redundant_with_indexclauses(RestrictInfo *rinfo,
+ List *indexclauses);
+
+/*
+ * pathkeys.c
+ * utilities for matching and building path keys
+ */
+typedef enum
+{
+ PATHKEYS_EQUAL, /* pathkeys are identical */
+ PATHKEYS_BETTER1, /* pathkey 1 is a superset of pathkey 2 */
+ PATHKEYS_BETTER2, /* vice versa */
+ PATHKEYS_DIFFERENT /* neither pathkey includes the other */
+} PathKeysComparison;
+
+extern PathKeysComparison compare_pathkeys(List *keys1, List *keys2);
+extern bool pathkeys_contained_in(List *keys1, List *keys2);
+extern bool pathkeys_count_contained_in(List *keys1, List *keys2, int *n_common);
+extern Path *get_cheapest_path_for_pathkeys(List *paths, List *pathkeys,
+ Relids required_outer,
+ CostSelector cost_criterion,
+ bool require_parallel_safe);
+extern Path *get_cheapest_fractional_path_for_pathkeys(List *paths,
+ List *pathkeys,
+ Relids required_outer,
+ double fraction);
+extern Path *get_cheapest_parallel_safe_total_inner(List *paths);
+extern List *build_index_pathkeys(PlannerInfo *root, IndexOptInfo *index,
+ ScanDirection scandir);
+extern List *build_partition_pathkeys(PlannerInfo *root, RelOptInfo *partrel,
+ ScanDirection scandir, bool *partialkeys);
+extern List *build_expression_pathkey(PlannerInfo *root, Expr *expr,
+ Relids nullable_relids, Oid opno,
+ Relids rel, bool create_it);
+extern List *convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
+ List *subquery_pathkeys,
+ List *subquery_tlist);
+extern List *build_join_pathkeys(PlannerInfo *root,
+ RelOptInfo *joinrel,
+ JoinType jointype,
+ List *outer_pathkeys);
+extern List *make_pathkeys_for_sortclauses(PlannerInfo *root,
+ List *sortclauses,
+ List *tlist);
+extern void initialize_mergeclause_eclasses(PlannerInfo *root,
+ RestrictInfo *restrictinfo);
+extern void update_mergeclause_eclasses(PlannerInfo *root,
+ RestrictInfo *restrictinfo);
+extern List *find_mergeclauses_for_outer_pathkeys(PlannerInfo *root,
+ List *pathkeys,
+ List *restrictinfos);
+extern List *select_outer_pathkeys_for_merge(PlannerInfo *root,
+ List *mergeclauses,
+ RelOptInfo *joinrel);
+extern List *make_inner_pathkeys_for_merge(PlannerInfo *root,
+ List *mergeclauses,
+ List *outer_pathkeys);
+extern List *trim_mergeclauses_for_inner_pathkeys(PlannerInfo *root,
+ List *mergeclauses,
+ List *pathkeys);
+extern List *truncate_useless_pathkeys(PlannerInfo *root,
+ RelOptInfo *rel,
+ List *pathkeys);
+extern bool has_useful_pathkeys(PlannerInfo *root, RelOptInfo *rel);
+extern PathKey *make_canonical_pathkey(PlannerInfo *root,
+ EquivalenceClass *eclass, Oid opfamily,
+ int strategy, bool nulls_first);
+extern void add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
+ List *live_childrels);
+
+#endif /* PATHS_H */
diff --git a/src/include/optimizer/placeholder.h b/src/include/optimizer/placeholder.h
new file mode 100644
index 0000000..b5a6b30
--- /dev/null
+++ b/src/include/optimizer/placeholder.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * placeholder.h
+ * prototypes for optimizer/util/placeholder.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/placeholder.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PLACEHOLDER_H
+#define PLACEHOLDER_H
+
+#include "nodes/pathnodes.h"
+
+
+extern PlaceHolderVar *make_placeholder_expr(PlannerInfo *root, Expr *expr,
+ Relids phrels);
+extern PlaceHolderInfo *find_placeholder_info(PlannerInfo *root,
+ PlaceHolderVar *phv, bool create_new_ph);
+extern void find_placeholders_in_jointree(PlannerInfo *root);
+extern void update_placeholder_eval_levels(PlannerInfo *root,
+ SpecialJoinInfo *new_sjinfo);
+extern void fix_placeholder_input_needed_levels(PlannerInfo *root);
+extern void add_placeholders_to_base_rels(PlannerInfo *root);
+extern void add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel,
+ RelOptInfo *outer_rel, RelOptInfo *inner_rel);
+
+#endif /* PLACEHOLDER_H */
diff --git a/src/include/optimizer/plancat.h b/src/include/optimizer/plancat.h
new file mode 100644
index 0000000..c29a709
--- /dev/null
+++ b/src/include/optimizer/plancat.h
@@ -0,0 +1,77 @@
+/*-------------------------------------------------------------------------
+ *
+ * plancat.h
+ * prototypes for plancat.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/plancat.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PLANCAT_H
+#define PLANCAT_H
+
+#include "nodes/pathnodes.h"
+#include "utils/relcache.h"
+
+/* Hook for plugins to get control in get_relation_info() */
+typedef void (*get_relation_info_hook_type) (PlannerInfo *root,
+ Oid relationObjectId,
+ bool inhparent,
+ RelOptInfo *rel);
+extern PGDLLIMPORT get_relation_info_hook_type get_relation_info_hook;
+
+
+extern void get_relation_info(PlannerInfo *root, Oid relationObjectId,
+ bool inhparent, RelOptInfo *rel);
+
+extern List *infer_arbiter_indexes(PlannerInfo *root);
+
+extern void estimate_rel_size(Relation rel, int32 *attr_widths,
+ BlockNumber *pages, double *tuples, double *allvisfrac);
+
+extern int32 get_rel_data_width(Relation rel, int32 *attr_widths);
+extern int32 get_relation_data_width(Oid relid, int32 *attr_widths);
+
+extern bool relation_excluded_by_constraints(PlannerInfo *root,
+ RelOptInfo *rel, RangeTblEntry *rte);
+
+extern List *build_physical_tlist(PlannerInfo *root, RelOptInfo *rel);
+
+extern bool has_unique_index(RelOptInfo *rel, AttrNumber attno);
+
+extern Selectivity restriction_selectivity(PlannerInfo *root,
+ Oid operatorid,
+ List *args,
+ Oid inputcollid,
+ int varRelid);
+
+extern Selectivity join_selectivity(PlannerInfo *root,
+ Oid operatorid,
+ List *args,
+ Oid inputcollid,
+ JoinType jointype,
+ SpecialJoinInfo *sjinfo);
+
+extern Selectivity function_selectivity(PlannerInfo *root,
+ Oid funcid,
+ List *args,
+ Oid inputcollid,
+ bool is_join,
+ int varRelid,
+ JoinType jointype,
+ SpecialJoinInfo *sjinfo);
+
+extern void add_function_cost(PlannerInfo *root, Oid funcid, Node *node,
+ QualCost *cost);
+
+extern double get_function_rows(PlannerInfo *root, Oid funcid, Node *node);
+
+extern bool has_row_triggers(PlannerInfo *root, Index rti, CmdType event);
+
+extern bool has_stored_generated_columns(PlannerInfo *root, Index rti);
+
+#endif /* PLANCAT_H */
diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h
new file mode 100644
index 0000000..8ce60e2
--- /dev/null
+++ b/src/include/optimizer/planmain.h
@@ -0,0 +1,119 @@
+/*-------------------------------------------------------------------------
+ *
+ * planmain.h
+ * prototypes for various files in optimizer/plan
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/planmain.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PLANMAIN_H
+#define PLANMAIN_H
+
+#include "nodes/pathnodes.h"
+#include "nodes/plannodes.h"
+
+/* GUC parameters */
+#define DEFAULT_CURSOR_TUPLE_FRACTION 0.1
+extern double cursor_tuple_fraction;
+
+/* query_planner callback to compute query_pathkeys */
+typedef void (*query_pathkeys_callback) (PlannerInfo *root, void *extra);
+
+/*
+ * prototypes for plan/planmain.c
+ */
+extern RelOptInfo *query_planner(PlannerInfo *root,
+ query_pathkeys_callback qp_callback, void *qp_extra);
+
+/*
+ * prototypes for plan/planagg.c
+ */
+extern void preprocess_minmax_aggregates(PlannerInfo *root);
+
+/*
+ * prototypes for plan/createplan.c
+ */
+extern Plan *create_plan(PlannerInfo *root, Path *best_path);
+extern ForeignScan *make_foreignscan(List *qptlist, List *qpqual,
+ Index scanrelid, List *fdw_exprs, List *fdw_private,
+ List *fdw_scan_tlist, List *fdw_recheck_quals,
+ Plan *outer_plan);
+extern Plan *change_plan_targetlist(Plan *subplan, List *tlist,
+ bool tlist_parallel_safe);
+extern Plan *materialize_finished_plan(Plan *subplan);
+extern bool is_projection_capable_path(Path *path);
+extern bool is_projection_capable_plan(Plan *plan);
+
+/* External use of these functions is deprecated: */
+extern Sort *make_sort_from_sortclauses(List *sortcls, Plan *lefttree);
+extern Agg *make_agg(List *tlist, List *qual,
+ AggStrategy aggstrategy, AggSplit aggsplit,
+ int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations,
+ List *groupingSets, List *chain, double dNumGroups,
+ Size transitionSpace, Plan *lefttree);
+extern Limit *make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount,
+ LimitOption limitOption, int uniqNumCols,
+ AttrNumber *uniqColIdx, Oid *uniqOperators,
+ Oid *uniqCollations);
+
+/*
+ * prototypes for plan/initsplan.c
+ */
+extern int from_collapse_limit;
+extern int join_collapse_limit;
+
+extern void add_base_rels_to_query(PlannerInfo *root, Node *jtnode);
+extern void add_other_rels_to_query(PlannerInfo *root);
+extern void build_base_rel_tlists(PlannerInfo *root, List *final_tlist);
+extern void add_vars_to_targetlist(PlannerInfo *root, List *vars,
+ Relids where_needed, bool create_new_ph);
+extern void find_lateral_references(PlannerInfo *root);
+extern void create_lateral_join_info(PlannerInfo *root);
+extern List *deconstruct_jointree(PlannerInfo *root);
+extern void distribute_restrictinfo_to_rels(PlannerInfo *root,
+ RestrictInfo *restrictinfo);
+extern void process_implied_equality(PlannerInfo *root,
+ Oid opno,
+ Oid collation,
+ Expr *item1,
+ Expr *item2,
+ Relids qualscope,
+ Relids nullable_relids,
+ Index security_level,
+ bool below_outer_join,
+ bool both_const);
+extern RestrictInfo *build_implied_join_equality(PlannerInfo *root,
+ Oid opno,
+ Oid collation,
+ Expr *item1,
+ Expr *item2,
+ Relids qualscope,
+ Relids nullable_relids,
+ Index security_level);
+extern void match_foreign_keys_to_quals(PlannerInfo *root);
+
+/*
+ * prototypes for plan/analyzejoins.c
+ */
+extern List *remove_useless_joins(PlannerInfo *root, List *joinlist);
+extern void reduce_unique_semijoins(PlannerInfo *root);
+extern bool query_supports_distinctness(Query *query);
+extern bool query_is_distinct_for(Query *query, List *colnos, List *opids);
+extern bool innerrel_is_unique(PlannerInfo *root,
+ Relids joinrelids, Relids outerrelids, RelOptInfo *innerrel,
+ JoinType jointype, List *restrictlist, bool force_cache);
+
+/*
+ * prototypes for plan/setrefs.c
+ */
+extern Plan *set_plan_references(PlannerInfo *root, Plan *plan);
+extern void record_plan_function_dependency(PlannerInfo *root, Oid funcid);
+extern void record_plan_type_dependency(PlannerInfo *root, Oid typid);
+extern bool extract_query_dependencies_walker(Node *node, PlannerInfo *root);
+
+#endif /* PLANMAIN_H */
diff --git a/src/include/optimizer/planner.h b/src/include/optimizer/planner.h
new file mode 100644
index 0000000..beb7dbb
--- /dev/null
+++ b/src/include/optimizer/planner.h
@@ -0,0 +1,61 @@
+/*-------------------------------------------------------------------------
+ *
+ * planner.h
+ * prototypes for planner.c.
+ *
+ * Note that the primary entry points for planner.c are declared in
+ * optimizer/optimizer.h, because they're intended to be called from
+ * non-planner code. Declarations here are meant for use by other
+ * planner modules.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/planner.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PLANNER_H
+#define PLANNER_H
+
+#include "nodes/pathnodes.h"
+#include "nodes/plannodes.h"
+
+
+/* Hook for plugins to get control in planner() */
+typedef PlannedStmt *(*planner_hook_type) (Query *parse,
+ const char *query_string,
+ int cursorOptions,
+ ParamListInfo boundParams);
+extern PGDLLIMPORT planner_hook_type planner_hook;
+
+/* Hook for plugins to get control when grouping_planner() plans upper rels */
+typedef void (*create_upper_paths_hook_type) (PlannerInfo *root,
+ UpperRelationKind stage,
+ RelOptInfo *input_rel,
+ RelOptInfo *output_rel,
+ void *extra);
+extern PGDLLIMPORT create_upper_paths_hook_type create_upper_paths_hook;
+
+
+extern PlannedStmt *standard_planner(Query *parse, const char *query_string,
+ int cursorOptions,
+ ParamListInfo boundParams);
+
+extern PlannerInfo *subquery_planner(PlannerGlobal *glob, Query *parse,
+ PlannerInfo *parent_root,
+ bool hasRecursion, double tuple_fraction);
+
+extern RowMarkType select_rowmark_type(RangeTblEntry *rte,
+ LockClauseStrength strength);
+
+extern bool limit_needed(Query *parse);
+
+extern void mark_partial_aggref(Aggref *agg, AggSplit aggsplit);
+
+extern Path *get_cheapest_fractional_path(RelOptInfo *rel,
+ double tuple_fraction);
+
+extern Expr *preprocess_phv_expression(PlannerInfo *root, Expr *expr);
+
+#endif /* PLANNER_H */
diff --git a/src/include/optimizer/prep.h b/src/include/optimizer/prep.h
new file mode 100644
index 0000000..19c9230
--- /dev/null
+++ b/src/include/optimizer/prep.h
@@ -0,0 +1,46 @@
+/*-------------------------------------------------------------------------
+ *
+ * prep.h
+ * prototypes for files in optimizer/prep/
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/prep.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PREP_H
+#define PREP_H
+
+#include "nodes/pathnodes.h"
+#include "nodes/plannodes.h"
+
+
+/*
+ * prototypes for prepjointree.c
+ */
+extern void replace_empty_jointree(Query *parse);
+extern void pull_up_sublinks(PlannerInfo *root);
+extern void preprocess_function_rtes(PlannerInfo *root);
+extern void pull_up_subqueries(PlannerInfo *root);
+extern void flatten_simple_union_all(PlannerInfo *root);
+extern void reduce_outer_joins(PlannerInfo *root);
+extern void remove_useless_result_rtes(PlannerInfo *root);
+extern Relids get_relids_in_jointree(Node *jtnode, bool include_joins);
+extern Relids get_relids_for_join(Query *query, int joinrelid);
+
+/*
+ * prototypes for preptlist.c
+ */
+extern List *preprocess_targetlist(PlannerInfo *root);
+
+extern PlanRowMark *get_plan_rowmark(List *rowmarks, Index rtindex);
+
+/*
+ * prototypes for prepunion.c
+ */
+extern RelOptInfo *plan_set_operations(PlannerInfo *root);
+
+#endif /* PREP_H */
diff --git a/src/include/optimizer/restrictinfo.h b/src/include/optimizer/restrictinfo.h
new file mode 100644
index 0000000..e0e1ade
--- /dev/null
+++ b/src/include/optimizer/restrictinfo.h
@@ -0,0 +1,57 @@
+/*-------------------------------------------------------------------------
+ *
+ * restrictinfo.h
+ * prototypes for restrictinfo.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/restrictinfo.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RESTRICTINFO_H
+#define RESTRICTINFO_H
+
+#include "nodes/pathnodes.h"
+
+
+/* Convenience macro for the common case of a valid-everywhere qual */
+#define make_simple_restrictinfo(clause) \
+ make_restrictinfo(clause, true, false, false, 0, NULL, NULL, NULL)
+
+extern RestrictInfo *make_restrictinfo(Expr *clause,
+ bool is_pushed_down,
+ bool outerjoin_delayed,
+ bool pseudoconstant,
+ Index security_level,
+ Relids required_relids,
+ Relids outer_relids,
+ Relids nullable_relids);
+extern RestrictInfo *make_restrictinfo_new(PlannerInfo *root,
+ Expr *clause,
+ bool is_pushed_down,
+ bool outerjoin_delayed,
+ bool pseudoconstant,
+ Index security_level,
+ Relids required_relids,
+ Relids outer_relids,
+ Relids nullable_relids);
+extern RestrictInfo *commute_restrictinfo(RestrictInfo *rinfo, Oid comm_op);
+extern bool restriction_is_or_clause(RestrictInfo *restrictinfo);
+extern bool restriction_is_securely_promotable(RestrictInfo *restrictinfo,
+ RelOptInfo *rel);
+extern List *get_actual_clauses(List *restrictinfo_list);
+extern List *extract_actual_clauses(List *restrictinfo_list,
+ bool pseudoconstant);
+extern void extract_actual_join_clauses(List *restrictinfo_list,
+ Relids joinrelids,
+ List **joinquals,
+ List **otherquals);
+extern bool join_clause_is_movable_to(RestrictInfo *rinfo, RelOptInfo *baserel);
+extern bool join_clause_is_movable_into(RestrictInfo *rinfo,
+ Relids currentrelids,
+ Relids current_and_outer);
+
+#endif /* RESTRICTINFO_H */
diff --git a/src/include/optimizer/subselect.h b/src/include/optimizer/subselect.h
new file mode 100644
index 0000000..d6a872b
--- /dev/null
+++ b/src/include/optimizer/subselect.h
@@ -0,0 +1,40 @@
+/*-------------------------------------------------------------------------
+ *
+ * subselect.h
+ * Planning routines for subselects.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/subselect.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SUBSELECT_H
+#define SUBSELECT_H
+
+#include "nodes/pathnodes.h"
+#include "nodes/plannodes.h"
+
+extern void SS_process_ctes(PlannerInfo *root);
+extern JoinExpr *convert_ANY_sublink_to_join(PlannerInfo *root,
+ SubLink *sublink,
+ Relids available_rels);
+extern JoinExpr *convert_EXISTS_sublink_to_join(PlannerInfo *root,
+ SubLink *sublink,
+ bool under_not,
+ Relids available_rels);
+extern Node *SS_replace_correlation_vars(PlannerInfo *root, Node *expr);
+extern Node *SS_process_sublinks(PlannerInfo *root, Node *expr, bool isQual);
+extern void SS_identify_outer_params(PlannerInfo *root);
+extern void SS_charge_for_initplans(PlannerInfo *root, RelOptInfo *final_rel);
+extern void SS_attach_initplans(PlannerInfo *root, Plan *plan);
+extern void SS_finalize_plan(PlannerInfo *root, Plan *plan);
+extern Param *SS_make_initplan_output_param(PlannerInfo *root,
+ Oid resulttype, int32 resulttypmod,
+ Oid resultcollation);
+extern void SS_make_initplan_from_plan(PlannerInfo *root,
+ PlannerInfo *subroot, Plan *plan,
+ Param *prm);
+
+#endif /* SUBSELECT_H */
diff --git a/src/include/optimizer/tlist.h b/src/include/optimizer/tlist.h
new file mode 100644
index 0000000..1d4c7da
--- /dev/null
+++ b/src/include/optimizer/tlist.h
@@ -0,0 +1,57 @@
+/*-------------------------------------------------------------------------
+ *
+ * tlist.h
+ * prototypes for tlist.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/optimizer/tlist.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TLIST_H
+#define TLIST_H
+
+#include "nodes/pathnodes.h"
+
+
+extern TargetEntry *tlist_member(Expr *node, List *targetlist);
+extern TargetEntry *tlist_member_ignore_relabel(Expr *node, List *targetlist);
+
+extern List *add_to_flat_tlist(List *tlist, List *exprs);
+
+extern List *get_tlist_exprs(List *tlist, bool includeJunk);
+
+extern bool tlist_same_exprs(List *tlist1, List *tlist2);
+
+extern bool tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK);
+extern bool tlist_same_collations(List *tlist, List *colCollations, bool junkOK);
+
+extern void apply_tlist_labeling(List *dest_tlist, List *src_tlist);
+
+extern Oid *extract_grouping_ops(List *groupClause);
+extern Oid *extract_grouping_collations(List *groupClause, List *tlist);
+extern AttrNumber *extract_grouping_cols(List *groupClause, List *tlist);
+extern bool grouping_is_sortable(List *groupClause);
+extern bool grouping_is_hashable(List *groupClause);
+
+extern PathTarget *make_pathtarget_from_tlist(List *tlist);
+extern List *make_tlist_from_pathtarget(PathTarget *target);
+extern PathTarget *copy_pathtarget(PathTarget *src);
+extern PathTarget *create_empty_pathtarget(void);
+extern void add_column_to_pathtarget(PathTarget *target,
+ Expr *expr, Index sortgroupref);
+extern void add_new_column_to_pathtarget(PathTarget *target, Expr *expr);
+extern void add_new_columns_to_pathtarget(PathTarget *target, List *exprs);
+extern void apply_pathtarget_labeling_to_tlist(List *tlist, PathTarget *target);
+extern void split_pathtarget_at_srfs(PlannerInfo *root,
+ PathTarget *target, PathTarget *input_target,
+ List **targets, List **targets_contain_srfs);
+
+/* Convenience macro to get a PathTarget with valid cost/width fields */
+#define create_pathtarget(root, tlist) \
+ set_pathtarget_cost_width(root, make_pathtarget_from_tlist(tlist))
+
+#endif /* TLIST_H */
diff --git a/src/include/parser/.gitignore b/src/include/parser/.gitignore
new file mode 100644
index 0000000..19ea955
--- /dev/null
+++ b/src/include/parser/.gitignore
@@ -0,0 +1 @@
+/gram.h
diff --git a/src/include/parser/analyze.h b/src/include/parser/analyze.h
new file mode 100644
index 0000000..d6a467a
--- /dev/null
+++ b/src/include/parser/analyze.h
@@ -0,0 +1,49 @@
+/*-------------------------------------------------------------------------
+ *
+ * analyze.h
+ * parse analysis for optimizable statements
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/analyze.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ANALYZE_H
+#define ANALYZE_H
+
+#include "parser/parse_node.h"
+
+/* Hook for plugins to get control at end of parse analysis */
+typedef void (*post_parse_analyze_hook_type) (ParseState *pstate,
+ Query *query);
+extern PGDLLIMPORT post_parse_analyze_hook_type post_parse_analyze_hook;
+
+
+extern Query *parse_analyze(RawStmt *parseTree, const char *sourceText,
+ Oid *paramTypes, int numParams, QueryEnvironment *queryEnv);
+extern Query *parse_analyze_varparams(RawStmt *parseTree, const char *sourceText,
+ Oid **paramTypes, int *numParams);
+
+extern Query *parse_sub_analyze(Node *parseTree, ParseState *parentParseState,
+ CommonTableExpr *parentCTE,
+ bool locked_from_parent,
+ bool resolve_unknowns);
+
+extern Query *transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree);
+extern Query *transformStmt(ParseState *pstate, Node *parseTree);
+
+extern bool analyze_requires_snapshot(RawStmt *parseTree);
+
+extern const char *LCS_asString(LockClauseStrength strength);
+extern void CheckSelectLocking(Query *qry, LockClauseStrength strength);
+extern void applyLockingClause(Query *qry, Index rtindex,
+ LockClauseStrength strength,
+ LockWaitPolicy waitPolicy, bool pushedDown);
+
+extern List *BuildOnConflictExcludedTargetlist(Relation targetrel,
+ Index exclRelIndex);
+
+#endif /* ANALYZE_H */
diff --git a/src/include/parser/gramparse.h b/src/include/parser/gramparse.h
new file mode 100644
index 0000000..7c7be13
--- /dev/null
+++ b/src/include/parser/gramparse.h
@@ -0,0 +1,75 @@
+/*-------------------------------------------------------------------------
+ *
+ * gramparse.h
+ * Shared definitions for the "raw" parser (flex and bison phases only)
+ *
+ * NOTE: this file is only meant to be included in the core parsing files,
+ * ie, parser.c, gram.y, scan.l, and src/common/keywords.c.
+ * Definitions that are needed outside the core parser should be in parser.h.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/gramparse.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef GRAMPARSE_H
+#define GRAMPARSE_H
+
+#include "nodes/parsenodes.h"
+#include "parser/scanner.h"
+
+/*
+ * NB: include gram.h only AFTER including scanner.h, because scanner.h
+ * is what #defines YYLTYPE.
+ */
+#include "parser/gram.h"
+
+/*
+ * The YY_EXTRA data that a flex scanner allows us to pass around. Private
+ * state needed for raw parsing/lexing goes here.
+ */
+typedef struct base_yy_extra_type
+{
+ /*
+ * Fields used by the core scanner.
+ */
+ core_yy_extra_type core_yy_extra;
+
+ /*
+ * State variables for base_yylex().
+ */
+ bool have_lookahead; /* is lookahead info valid? */
+ int lookahead_token; /* one-token lookahead */
+ core_YYSTYPE lookahead_yylval; /* yylval for lookahead token */
+ YYLTYPE lookahead_yylloc; /* yylloc for lookahead token */
+ char *lookahead_end; /* end of current token */
+ char lookahead_hold_char; /* to be put back at *lookahead_end */
+
+ /*
+ * State variables that belong to the grammar.
+ */
+ List *parsetree; /* final parse result is delivered here */
+} base_yy_extra_type;
+
+/*
+ * In principle we should use yyget_extra() to fetch the yyextra field
+ * from a yyscanner struct. However, flex always puts that field first,
+ * and this is sufficiently performance-critical to make it seem worth
+ * cheating a bit to use an inline macro.
+ */
+#define pg_yyget_extra(yyscanner) (*((base_yy_extra_type **) (yyscanner)))
+
+
+/* from parser.c */
+extern int base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp,
+ core_yyscan_t yyscanner);
+
+/* from gram.y */
+extern void parser_init(base_yy_extra_type *yyext);
+extern int base_yyparse(core_yyscan_t yyscanner);
+
+#endif /* GRAMPARSE_H */
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
new file mode 100644
index 0000000..08f22ce
--- /dev/null
+++ b/src/include/parser/kwlist.h
@@ -0,0 +1,477 @@
+/*-------------------------------------------------------------------------
+ *
+ * kwlist.h
+ *
+ * The keyword lists are kept in their own source files for use by
+ * automatic tools. The exact representation of a keyword is determined
+ * by the PG_KEYWORD macro, which is not defined in this file; it can
+ * be defined by the caller for special purposes.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/parser/kwlist.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* there is deliberately not an #ifndef KWLIST_H here */
+
+/*
+ * List of keyword (name, token-value, category) entries.
+ *
+ * Note: gen_keywordlist.pl requires the entries to appear in ASCII order.
+ */
+
+/* name, value, category */
+PG_KEYWORD("abort", ABORT_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("absolute", ABSOLUTE_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("access", ACCESS, UNRESERVED_KEYWORD)
+PG_KEYWORD("action", ACTION, UNRESERVED_KEYWORD)
+PG_KEYWORD("add", ADD_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("admin", ADMIN, UNRESERVED_KEYWORD)
+PG_KEYWORD("after", AFTER, UNRESERVED_KEYWORD)
+PG_KEYWORD("aggregate", AGGREGATE, UNRESERVED_KEYWORD)
+PG_KEYWORD("all", ALL, RESERVED_KEYWORD)
+PG_KEYWORD("also", ALSO, UNRESERVED_KEYWORD)
+PG_KEYWORD("alter", ALTER, UNRESERVED_KEYWORD)
+PG_KEYWORD("always", ALWAYS, UNRESERVED_KEYWORD)
+PG_KEYWORD("analyse", ANALYSE, RESERVED_KEYWORD) /* British spelling */
+PG_KEYWORD("analyze", ANALYZE, RESERVED_KEYWORD)
+PG_KEYWORD("and", AND, RESERVED_KEYWORD)
+PG_KEYWORD("any", ANY, RESERVED_KEYWORD)
+PG_KEYWORD("array", ARRAY, RESERVED_KEYWORD)
+PG_KEYWORD("as", AS, RESERVED_KEYWORD)
+PG_KEYWORD("asc", ASC, RESERVED_KEYWORD)
+PG_KEYWORD("assertion", ASSERTION, UNRESERVED_KEYWORD)
+PG_KEYWORD("assignment", ASSIGNMENT, UNRESERVED_KEYWORD)
+PG_KEYWORD("asymmetric", ASYMMETRIC, RESERVED_KEYWORD)
+PG_KEYWORD("at", AT, UNRESERVED_KEYWORD)
+PG_KEYWORD("attach", ATTACH, UNRESERVED_KEYWORD)
+PG_KEYWORD("attribute", ATTRIBUTE, UNRESERVED_KEYWORD)
+PG_KEYWORD("authorization", AUTHORIZATION, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("backward", BACKWARD, UNRESERVED_KEYWORD)
+PG_KEYWORD("before", BEFORE, UNRESERVED_KEYWORD)
+PG_KEYWORD("begin", BEGIN_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("between", BETWEEN, COL_NAME_KEYWORD)
+PG_KEYWORD("bigint", BIGINT, COL_NAME_KEYWORD)
+PG_KEYWORD("binary", BINARY, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("bit", BIT, COL_NAME_KEYWORD)
+PG_KEYWORD("boolean", BOOLEAN_P, COL_NAME_KEYWORD)
+PG_KEYWORD("both", BOTH, RESERVED_KEYWORD)
+PG_KEYWORD("by", BY, UNRESERVED_KEYWORD)
+PG_KEYWORD("cache", CACHE, UNRESERVED_KEYWORD)
+PG_KEYWORD("call", CALL, UNRESERVED_KEYWORD)
+PG_KEYWORD("called", CALLED, UNRESERVED_KEYWORD)
+PG_KEYWORD("cascade", CASCADE, UNRESERVED_KEYWORD)
+PG_KEYWORD("cascaded", CASCADED, UNRESERVED_KEYWORD)
+PG_KEYWORD("case", CASE, RESERVED_KEYWORD)
+PG_KEYWORD("cast", CAST, RESERVED_KEYWORD)
+PG_KEYWORD("catalog", CATALOG_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("chain", CHAIN, UNRESERVED_KEYWORD)
+PG_KEYWORD("char", CHAR_P, COL_NAME_KEYWORD)
+PG_KEYWORD("character", CHARACTER, COL_NAME_KEYWORD)
+PG_KEYWORD("characteristics", CHARACTERISTICS, UNRESERVED_KEYWORD)
+PG_KEYWORD("check", CHECK, RESERVED_KEYWORD)
+PG_KEYWORD("checkpoint", CHECKPOINT, UNRESERVED_KEYWORD)
+PG_KEYWORD("class", CLASS, UNRESERVED_KEYWORD)
+PG_KEYWORD("close", CLOSE, UNRESERVED_KEYWORD)
+PG_KEYWORD("cluster", CLUSTER, UNRESERVED_KEYWORD)
+PG_KEYWORD("coalesce", COALESCE, COL_NAME_KEYWORD)
+PG_KEYWORD("collate", COLLATE, RESERVED_KEYWORD)
+PG_KEYWORD("collation", COLLATION, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("column", COLUMN, RESERVED_KEYWORD)
+PG_KEYWORD("columns", COLUMNS, UNRESERVED_KEYWORD)
+PG_KEYWORD("comment", COMMENT, UNRESERVED_KEYWORD)
+PG_KEYWORD("comments", COMMENTS, UNRESERVED_KEYWORD)
+PG_KEYWORD("commit", COMMIT, UNRESERVED_KEYWORD)
+PG_KEYWORD("committed", COMMITTED, UNRESERVED_KEYWORD)
+PG_KEYWORD("concurrently", CONCURRENTLY, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("configuration", CONFIGURATION, UNRESERVED_KEYWORD)
+PG_KEYWORD("conflict", CONFLICT, UNRESERVED_KEYWORD)
+PG_KEYWORD("connection", CONNECTION, UNRESERVED_KEYWORD)
+PG_KEYWORD("constraint", CONSTRAINT, RESERVED_KEYWORD)
+PG_KEYWORD("constraints", CONSTRAINTS, UNRESERVED_KEYWORD)
+PG_KEYWORD("content", CONTENT_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("continue", CONTINUE_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("conversion", CONVERSION_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("copy", COPY, UNRESERVED_KEYWORD)
+PG_KEYWORD("cost", COST, UNRESERVED_KEYWORD)
+PG_KEYWORD("create", CREATE, RESERVED_KEYWORD)
+PG_KEYWORD("cross", CROSS, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("csv", CSV, UNRESERVED_KEYWORD)
+PG_KEYWORD("cube", CUBE, UNRESERVED_KEYWORD)
+PG_KEYWORD("current", CURRENT_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("current_catalog", CURRENT_CATALOG, RESERVED_KEYWORD)
+PG_KEYWORD("current_date", CURRENT_DATE, RESERVED_KEYWORD)
+PG_KEYWORD("current_role", CURRENT_ROLE, RESERVED_KEYWORD)
+PG_KEYWORD("current_schema", CURRENT_SCHEMA, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("current_time", CURRENT_TIME, RESERVED_KEYWORD)
+PG_KEYWORD("current_timestamp", CURRENT_TIMESTAMP, RESERVED_KEYWORD)
+PG_KEYWORD("current_user", CURRENT_USER, RESERVED_KEYWORD)
+PG_KEYWORD("cursor", CURSOR, UNRESERVED_KEYWORD)
+PG_KEYWORD("cycle", CYCLE, UNRESERVED_KEYWORD)
+PG_KEYWORD("data", DATA_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("database", DATABASE, UNRESERVED_KEYWORD)
+PG_KEYWORD("day", DAY_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("deallocate", DEALLOCATE, UNRESERVED_KEYWORD)
+PG_KEYWORD("dec", DEC, COL_NAME_KEYWORD)
+PG_KEYWORD("decimal", DECIMAL_P, COL_NAME_KEYWORD)
+PG_KEYWORD("declare", DECLARE, UNRESERVED_KEYWORD)
+PG_KEYWORD("default", DEFAULT, RESERVED_KEYWORD)
+PG_KEYWORD("defaults", DEFAULTS, UNRESERVED_KEYWORD)
+PG_KEYWORD("deferrable", DEFERRABLE, RESERVED_KEYWORD)
+PG_KEYWORD("deferred", DEFERRED, UNRESERVED_KEYWORD)
+PG_KEYWORD("definer", DEFINER, UNRESERVED_KEYWORD)
+PG_KEYWORD("delete", DELETE_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("delimiter", DELIMITER, UNRESERVED_KEYWORD)
+PG_KEYWORD("delimiters", DELIMITERS, UNRESERVED_KEYWORD)
+PG_KEYWORD("depends", DEPENDS, UNRESERVED_KEYWORD)
+PG_KEYWORD("desc", DESC, RESERVED_KEYWORD)
+PG_KEYWORD("detach", DETACH, UNRESERVED_KEYWORD)
+PG_KEYWORD("dictionary", DICTIONARY, UNRESERVED_KEYWORD)
+PG_KEYWORD("disable", DISABLE_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("discard", DISCARD, UNRESERVED_KEYWORD)
+PG_KEYWORD("distinct", DISTINCT, RESERVED_KEYWORD)
+PG_KEYWORD("do", DO, RESERVED_KEYWORD)
+PG_KEYWORD("document", DOCUMENT_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("domain", DOMAIN_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("double", DOUBLE_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("drop", DROP, UNRESERVED_KEYWORD)
+PG_KEYWORD("each", EACH, UNRESERVED_KEYWORD)
+PG_KEYWORD("else", ELSE, RESERVED_KEYWORD)
+PG_KEYWORD("enable", ENABLE_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("encoding", ENCODING, UNRESERVED_KEYWORD)
+PG_KEYWORD("encrypted", ENCRYPTED, UNRESERVED_KEYWORD)
+PG_KEYWORD("end", END_P, RESERVED_KEYWORD)
+PG_KEYWORD("enum", ENUM_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("escape", ESCAPE, UNRESERVED_KEYWORD)
+PG_KEYWORD("event", EVENT, UNRESERVED_KEYWORD)
+PG_KEYWORD("except", EXCEPT, RESERVED_KEYWORD)
+PG_KEYWORD("exclude", EXCLUDE, UNRESERVED_KEYWORD)
+PG_KEYWORD("excluding", EXCLUDING, UNRESERVED_KEYWORD)
+PG_KEYWORD("exclusive", EXCLUSIVE, UNRESERVED_KEYWORD)
+PG_KEYWORD("execute", EXECUTE, UNRESERVED_KEYWORD)
+PG_KEYWORD("exists", EXISTS, COL_NAME_KEYWORD)
+PG_KEYWORD("explain", EXPLAIN, UNRESERVED_KEYWORD)
+PG_KEYWORD("expression", EXPRESSION, UNRESERVED_KEYWORD)
+PG_KEYWORD("extension", EXTENSION, UNRESERVED_KEYWORD)
+PG_KEYWORD("external", EXTERNAL, UNRESERVED_KEYWORD)
+PG_KEYWORD("extract", EXTRACT, COL_NAME_KEYWORD)
+PG_KEYWORD("false", FALSE_P, RESERVED_KEYWORD)
+PG_KEYWORD("family", FAMILY, UNRESERVED_KEYWORD)
+PG_KEYWORD("fetch", FETCH, RESERVED_KEYWORD)
+PG_KEYWORD("filter", FILTER, UNRESERVED_KEYWORD)
+PG_KEYWORD("first", FIRST_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("float", FLOAT_P, COL_NAME_KEYWORD)
+PG_KEYWORD("following", FOLLOWING, UNRESERVED_KEYWORD)
+PG_KEYWORD("for", FOR, RESERVED_KEYWORD)
+PG_KEYWORD("force", FORCE, UNRESERVED_KEYWORD)
+PG_KEYWORD("foreign", FOREIGN, RESERVED_KEYWORD)
+PG_KEYWORD("forward", FORWARD, UNRESERVED_KEYWORD)
+PG_KEYWORD("freeze", FREEZE, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("from", FROM, RESERVED_KEYWORD)
+PG_KEYWORD("full", FULL, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("function", FUNCTION, UNRESERVED_KEYWORD)
+PG_KEYWORD("functions", FUNCTIONS, UNRESERVED_KEYWORD)
+PG_KEYWORD("generated", GENERATED, UNRESERVED_KEYWORD)
+PG_KEYWORD("global", GLOBAL, UNRESERVED_KEYWORD)
+PG_KEYWORD("grant", GRANT, RESERVED_KEYWORD)
+PG_KEYWORD("granted", GRANTED, UNRESERVED_KEYWORD)
+PG_KEYWORD("greatest", GREATEST, COL_NAME_KEYWORD)
+PG_KEYWORD("group", GROUP_P, RESERVED_KEYWORD)
+PG_KEYWORD("grouping", GROUPING, COL_NAME_KEYWORD)
+PG_KEYWORD("groups", GROUPS, UNRESERVED_KEYWORD)
+PG_KEYWORD("handler", HANDLER, UNRESERVED_KEYWORD)
+PG_KEYWORD("having", HAVING, RESERVED_KEYWORD)
+PG_KEYWORD("header", HEADER_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("hold", HOLD, UNRESERVED_KEYWORD)
+PG_KEYWORD("hour", HOUR_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("identity", IDENTITY_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("if", IF_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("ilike", ILIKE, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("immediate", IMMEDIATE, UNRESERVED_KEYWORD)
+PG_KEYWORD("immutable", IMMUTABLE, UNRESERVED_KEYWORD)
+PG_KEYWORD("implicit", IMPLICIT_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("import", IMPORT_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("in", IN_P, RESERVED_KEYWORD)
+PG_KEYWORD("include", INCLUDE, UNRESERVED_KEYWORD)
+PG_KEYWORD("including", INCLUDING, UNRESERVED_KEYWORD)
+PG_KEYWORD("increment", INCREMENT, UNRESERVED_KEYWORD)
+PG_KEYWORD("index", INDEX, UNRESERVED_KEYWORD)
+PG_KEYWORD("indexes", INDEXES, UNRESERVED_KEYWORD)
+PG_KEYWORD("inherit", INHERIT, UNRESERVED_KEYWORD)
+PG_KEYWORD("inherits", INHERITS, UNRESERVED_KEYWORD)
+PG_KEYWORD("initially", INITIALLY, RESERVED_KEYWORD)
+PG_KEYWORD("inline", INLINE_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("inner", INNER_P, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("inout", INOUT, COL_NAME_KEYWORD)
+PG_KEYWORD("input", INPUT_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("insensitive", INSENSITIVE, UNRESERVED_KEYWORD)
+PG_KEYWORD("insert", INSERT, UNRESERVED_KEYWORD)
+PG_KEYWORD("instead", INSTEAD, UNRESERVED_KEYWORD)
+PG_KEYWORD("int", INT_P, COL_NAME_KEYWORD)
+PG_KEYWORD("integer", INTEGER, COL_NAME_KEYWORD)
+PG_KEYWORD("intersect", INTERSECT, RESERVED_KEYWORD)
+PG_KEYWORD("interval", INTERVAL, COL_NAME_KEYWORD)
+PG_KEYWORD("into", INTO, RESERVED_KEYWORD)
+PG_KEYWORD("invoker", INVOKER, UNRESERVED_KEYWORD)
+PG_KEYWORD("is", IS, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("isnull", ISNULL, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("isolation", ISOLATION, UNRESERVED_KEYWORD)
+PG_KEYWORD("join", JOIN, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("key", KEY, UNRESERVED_KEYWORD)
+PG_KEYWORD("label", LABEL, UNRESERVED_KEYWORD)
+PG_KEYWORD("language", LANGUAGE, UNRESERVED_KEYWORD)
+PG_KEYWORD("large", LARGE_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("last", LAST_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("lateral", LATERAL_P, RESERVED_KEYWORD)
+PG_KEYWORD("leading", LEADING, RESERVED_KEYWORD)
+PG_KEYWORD("leakproof", LEAKPROOF, UNRESERVED_KEYWORD)
+PG_KEYWORD("least", LEAST, COL_NAME_KEYWORD)
+PG_KEYWORD("left", LEFT, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("level", LEVEL, UNRESERVED_KEYWORD)
+PG_KEYWORD("like", LIKE, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("limit", LIMIT, RESERVED_KEYWORD)
+PG_KEYWORD("listen", LISTEN, UNRESERVED_KEYWORD)
+PG_KEYWORD("load", LOAD, UNRESERVED_KEYWORD)
+PG_KEYWORD("local", LOCAL, UNRESERVED_KEYWORD)
+PG_KEYWORD("localtime", LOCALTIME, RESERVED_KEYWORD)
+PG_KEYWORD("localtimestamp", LOCALTIMESTAMP, RESERVED_KEYWORD)
+PG_KEYWORD("location", LOCATION, UNRESERVED_KEYWORD)
+PG_KEYWORD("lock", LOCK_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("locked", LOCKED, UNRESERVED_KEYWORD)
+PG_KEYWORD("logged", LOGGED, UNRESERVED_KEYWORD)
+PG_KEYWORD("mapping", MAPPING, UNRESERVED_KEYWORD)
+PG_KEYWORD("match", MATCH, UNRESERVED_KEYWORD)
+PG_KEYWORD("materialized", MATERIALIZED, UNRESERVED_KEYWORD)
+PG_KEYWORD("maxvalue", MAXVALUE, UNRESERVED_KEYWORD)
+PG_KEYWORD("method", METHOD, UNRESERVED_KEYWORD)
+PG_KEYWORD("minute", MINUTE_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("minvalue", MINVALUE, UNRESERVED_KEYWORD)
+PG_KEYWORD("mode", MODE, UNRESERVED_KEYWORD)
+PG_KEYWORD("month", MONTH_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("move", MOVE, UNRESERVED_KEYWORD)
+PG_KEYWORD("name", NAME_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("names", NAMES, UNRESERVED_KEYWORD)
+PG_KEYWORD("national", NATIONAL, COL_NAME_KEYWORD)
+PG_KEYWORD("natural", NATURAL, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("nchar", NCHAR, COL_NAME_KEYWORD)
+PG_KEYWORD("new", NEW, UNRESERVED_KEYWORD)
+PG_KEYWORD("next", NEXT, UNRESERVED_KEYWORD)
+PG_KEYWORD("nfc", NFC, UNRESERVED_KEYWORD)
+PG_KEYWORD("nfd", NFD, UNRESERVED_KEYWORD)
+PG_KEYWORD("nfkc", NFKC, UNRESERVED_KEYWORD)
+PG_KEYWORD("nfkd", NFKD, UNRESERVED_KEYWORD)
+PG_KEYWORD("no", NO, UNRESERVED_KEYWORD)
+PG_KEYWORD("none", NONE, COL_NAME_KEYWORD)
+PG_KEYWORD("normalize", NORMALIZE, COL_NAME_KEYWORD)
+PG_KEYWORD("normalized", NORMALIZED, UNRESERVED_KEYWORD)
+PG_KEYWORD("not", NOT, RESERVED_KEYWORD)
+PG_KEYWORD("nothing", NOTHING, UNRESERVED_KEYWORD)
+PG_KEYWORD("notify", NOTIFY, UNRESERVED_KEYWORD)
+PG_KEYWORD("notnull", NOTNULL, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("nowait", NOWAIT, UNRESERVED_KEYWORD)
+PG_KEYWORD("null", NULL_P, RESERVED_KEYWORD)
+PG_KEYWORD("nullif", NULLIF, COL_NAME_KEYWORD)
+PG_KEYWORD("nulls", NULLS_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("numeric", NUMERIC, COL_NAME_KEYWORD)
+PG_KEYWORD("object", OBJECT_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("of", OF, UNRESERVED_KEYWORD)
+PG_KEYWORD("off", OFF, UNRESERVED_KEYWORD)
+PG_KEYWORD("offset", OFFSET, RESERVED_KEYWORD)
+PG_KEYWORD("oids", OIDS, UNRESERVED_KEYWORD)
+PG_KEYWORD("old", OLD, UNRESERVED_KEYWORD)
+PG_KEYWORD("on", ON, RESERVED_KEYWORD)
+PG_KEYWORD("only", ONLY, RESERVED_KEYWORD)
+PG_KEYWORD("operator", OPERATOR, UNRESERVED_KEYWORD)
+PG_KEYWORD("option", OPTION, UNRESERVED_KEYWORD)
+PG_KEYWORD("options", OPTIONS, UNRESERVED_KEYWORD)
+PG_KEYWORD("or", OR, RESERVED_KEYWORD)
+PG_KEYWORD("order", ORDER, RESERVED_KEYWORD)
+PG_KEYWORD("ordinality", ORDINALITY, UNRESERVED_KEYWORD)
+PG_KEYWORD("others", OTHERS, UNRESERVED_KEYWORD)
+PG_KEYWORD("out", OUT_P, COL_NAME_KEYWORD)
+PG_KEYWORD("outer", OUTER_P, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("over", OVER, UNRESERVED_KEYWORD)
+PG_KEYWORD("overlaps", OVERLAPS, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("overlay", OVERLAY, COL_NAME_KEYWORD)
+PG_KEYWORD("overriding", OVERRIDING, UNRESERVED_KEYWORD)
+PG_KEYWORD("owned", OWNED, UNRESERVED_KEYWORD)
+PG_KEYWORD("owner", OWNER, UNRESERVED_KEYWORD)
+PG_KEYWORD("parallel", PARALLEL, UNRESERVED_KEYWORD)
+PG_KEYWORD("parser", PARSER, UNRESERVED_KEYWORD)
+PG_KEYWORD("partial", PARTIAL, UNRESERVED_KEYWORD)
+PG_KEYWORD("partition", PARTITION, UNRESERVED_KEYWORD)
+PG_KEYWORD("passing", PASSING, UNRESERVED_KEYWORD)
+PG_KEYWORD("password", PASSWORD, UNRESERVED_KEYWORD)
+PG_KEYWORD("placing", PLACING, RESERVED_KEYWORD)
+PG_KEYWORD("plans", PLANS, UNRESERVED_KEYWORD)
+PG_KEYWORD("policy", POLICY, UNRESERVED_KEYWORD)
+PG_KEYWORD("position", POSITION, COL_NAME_KEYWORD)
+PG_KEYWORD("preceding", PRECEDING, UNRESERVED_KEYWORD)
+PG_KEYWORD("precision", PRECISION, COL_NAME_KEYWORD)
+PG_KEYWORD("prepare", PREPARE, UNRESERVED_KEYWORD)
+PG_KEYWORD("prepared", PREPARED, UNRESERVED_KEYWORD)
+PG_KEYWORD("preserve", PRESERVE, UNRESERVED_KEYWORD)
+PG_KEYWORD("primary", PRIMARY, RESERVED_KEYWORD)
+PG_KEYWORD("prior", PRIOR, UNRESERVED_KEYWORD)
+PG_KEYWORD("privileges", PRIVILEGES, UNRESERVED_KEYWORD)
+PG_KEYWORD("procedural", PROCEDURAL, UNRESERVED_KEYWORD)
+PG_KEYWORD("procedure", PROCEDURE, UNRESERVED_KEYWORD)
+PG_KEYWORD("procedures", PROCEDURES, UNRESERVED_KEYWORD)
+PG_KEYWORD("program", PROGRAM, UNRESERVED_KEYWORD)
+PG_KEYWORD("publication", PUBLICATION, UNRESERVED_KEYWORD)
+PG_KEYWORD("quote", QUOTE, UNRESERVED_KEYWORD)
+PG_KEYWORD("range", RANGE, UNRESERVED_KEYWORD)
+PG_KEYWORD("read", READ, UNRESERVED_KEYWORD)
+PG_KEYWORD("real", REAL, COL_NAME_KEYWORD)
+PG_KEYWORD("reassign", REASSIGN, UNRESERVED_KEYWORD)
+PG_KEYWORD("recheck", RECHECK, UNRESERVED_KEYWORD)
+PG_KEYWORD("recursive", RECURSIVE, UNRESERVED_KEYWORD)
+PG_KEYWORD("ref", REF, UNRESERVED_KEYWORD)
+PG_KEYWORD("references", REFERENCES, RESERVED_KEYWORD)
+PG_KEYWORD("referencing", REFERENCING, UNRESERVED_KEYWORD)
+PG_KEYWORD("refresh", REFRESH, UNRESERVED_KEYWORD)
+PG_KEYWORD("reindex", REINDEX, UNRESERVED_KEYWORD)
+PG_KEYWORD("relative", RELATIVE_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("release", RELEASE, UNRESERVED_KEYWORD)
+PG_KEYWORD("rename", RENAME, UNRESERVED_KEYWORD)
+PG_KEYWORD("repeatable", REPEATABLE, UNRESERVED_KEYWORD)
+PG_KEYWORD("replace", REPLACE, UNRESERVED_KEYWORD)
+PG_KEYWORD("replica", REPLICA, UNRESERVED_KEYWORD)
+PG_KEYWORD("reset", RESET, UNRESERVED_KEYWORD)
+PG_KEYWORD("restart", RESTART, UNRESERVED_KEYWORD)
+PG_KEYWORD("restrict", RESTRICT, UNRESERVED_KEYWORD)
+PG_KEYWORD("returning", RETURNING, RESERVED_KEYWORD)
+PG_KEYWORD("returns", RETURNS, UNRESERVED_KEYWORD)
+PG_KEYWORD("revoke", REVOKE, UNRESERVED_KEYWORD)
+PG_KEYWORD("right", RIGHT, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("role", ROLE, UNRESERVED_KEYWORD)
+PG_KEYWORD("rollback", ROLLBACK, UNRESERVED_KEYWORD)
+PG_KEYWORD("rollup", ROLLUP, UNRESERVED_KEYWORD)
+PG_KEYWORD("routine", ROUTINE, UNRESERVED_KEYWORD)
+PG_KEYWORD("routines", ROUTINES, UNRESERVED_KEYWORD)
+PG_KEYWORD("row", ROW, COL_NAME_KEYWORD)
+PG_KEYWORD("rows", ROWS, UNRESERVED_KEYWORD)
+PG_KEYWORD("rule", RULE, UNRESERVED_KEYWORD)
+PG_KEYWORD("savepoint", SAVEPOINT, UNRESERVED_KEYWORD)
+PG_KEYWORD("schema", SCHEMA, UNRESERVED_KEYWORD)
+PG_KEYWORD("schemas", SCHEMAS, UNRESERVED_KEYWORD)
+PG_KEYWORD("scroll", SCROLL, UNRESERVED_KEYWORD)
+PG_KEYWORD("search", SEARCH, UNRESERVED_KEYWORD)
+PG_KEYWORD("second", SECOND_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("security", SECURITY, UNRESERVED_KEYWORD)
+PG_KEYWORD("select", SELECT, RESERVED_KEYWORD)
+PG_KEYWORD("sequence", SEQUENCE, UNRESERVED_KEYWORD)
+PG_KEYWORD("sequences", SEQUENCES, UNRESERVED_KEYWORD)
+PG_KEYWORD("serializable", SERIALIZABLE, UNRESERVED_KEYWORD)
+PG_KEYWORD("server", SERVER, UNRESERVED_KEYWORD)
+PG_KEYWORD("session", SESSION, UNRESERVED_KEYWORD)
+PG_KEYWORD("session_user", SESSION_USER, RESERVED_KEYWORD)
+PG_KEYWORD("set", SET, UNRESERVED_KEYWORD)
+PG_KEYWORD("setof", SETOF, COL_NAME_KEYWORD)
+PG_KEYWORD("sets", SETS, UNRESERVED_KEYWORD)
+PG_KEYWORD("share", SHARE, UNRESERVED_KEYWORD)
+PG_KEYWORD("show", SHOW, UNRESERVED_KEYWORD)
+PG_KEYWORD("similar", SIMILAR, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("simple", SIMPLE, UNRESERVED_KEYWORD)
+PG_KEYWORD("skip", SKIP, UNRESERVED_KEYWORD)
+PG_KEYWORD("smallint", SMALLINT, COL_NAME_KEYWORD)
+PG_KEYWORD("snapshot", SNAPSHOT, UNRESERVED_KEYWORD)
+PG_KEYWORD("some", SOME, RESERVED_KEYWORD)
+PG_KEYWORD("sql", SQL_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("stable", STABLE, UNRESERVED_KEYWORD)
+PG_KEYWORD("standalone", STANDALONE_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("start", START, UNRESERVED_KEYWORD)
+PG_KEYWORD("statement", STATEMENT, UNRESERVED_KEYWORD)
+PG_KEYWORD("statistics", STATISTICS, UNRESERVED_KEYWORD)
+PG_KEYWORD("stdin", STDIN, UNRESERVED_KEYWORD)
+PG_KEYWORD("stdout", STDOUT, UNRESERVED_KEYWORD)
+PG_KEYWORD("storage", STORAGE, UNRESERVED_KEYWORD)
+PG_KEYWORD("stored", STORED, UNRESERVED_KEYWORD)
+PG_KEYWORD("strict", STRICT_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("strip", STRIP_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("subscription", SUBSCRIPTION, UNRESERVED_KEYWORD)
+PG_KEYWORD("substring", SUBSTRING, COL_NAME_KEYWORD)
+PG_KEYWORD("support", SUPPORT, UNRESERVED_KEYWORD)
+PG_KEYWORD("symmetric", SYMMETRIC, RESERVED_KEYWORD)
+PG_KEYWORD("sysid", SYSID, UNRESERVED_KEYWORD)
+PG_KEYWORD("system", SYSTEM_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("table", TABLE, RESERVED_KEYWORD)
+PG_KEYWORD("tables", TABLES, UNRESERVED_KEYWORD)
+PG_KEYWORD("tablesample", TABLESAMPLE, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("tablespace", TABLESPACE, UNRESERVED_KEYWORD)
+PG_KEYWORD("temp", TEMP, UNRESERVED_KEYWORD)
+PG_KEYWORD("template", TEMPLATE, UNRESERVED_KEYWORD)
+PG_KEYWORD("temporary", TEMPORARY, UNRESERVED_KEYWORD)
+PG_KEYWORD("text", TEXT_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("then", THEN, RESERVED_KEYWORD)
+PG_KEYWORD("ties", TIES, UNRESERVED_KEYWORD)
+PG_KEYWORD("time", TIME, COL_NAME_KEYWORD)
+PG_KEYWORD("timestamp", TIMESTAMP, COL_NAME_KEYWORD)
+PG_KEYWORD("to", TO, RESERVED_KEYWORD)
+PG_KEYWORD("trailing", TRAILING, RESERVED_KEYWORD)
+PG_KEYWORD("transaction", TRANSACTION, UNRESERVED_KEYWORD)
+PG_KEYWORD("transform", TRANSFORM, UNRESERVED_KEYWORD)
+PG_KEYWORD("treat", TREAT, COL_NAME_KEYWORD)
+PG_KEYWORD("trigger", TRIGGER, UNRESERVED_KEYWORD)
+PG_KEYWORD("trim", TRIM, COL_NAME_KEYWORD)
+PG_KEYWORD("true", TRUE_P, RESERVED_KEYWORD)
+PG_KEYWORD("truncate", TRUNCATE, UNRESERVED_KEYWORD)
+PG_KEYWORD("trusted", TRUSTED, UNRESERVED_KEYWORD)
+PG_KEYWORD("type", TYPE_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("types", TYPES_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("uescape", UESCAPE, UNRESERVED_KEYWORD)
+PG_KEYWORD("unbounded", UNBOUNDED, UNRESERVED_KEYWORD)
+PG_KEYWORD("uncommitted", UNCOMMITTED, UNRESERVED_KEYWORD)
+PG_KEYWORD("unencrypted", UNENCRYPTED, UNRESERVED_KEYWORD)
+PG_KEYWORD("union", UNION, RESERVED_KEYWORD)
+PG_KEYWORD("unique", UNIQUE, RESERVED_KEYWORD)
+PG_KEYWORD("unknown", UNKNOWN, UNRESERVED_KEYWORD)
+PG_KEYWORD("unlisten", UNLISTEN, UNRESERVED_KEYWORD)
+PG_KEYWORD("unlogged", UNLOGGED, UNRESERVED_KEYWORD)
+PG_KEYWORD("until", UNTIL, UNRESERVED_KEYWORD)
+PG_KEYWORD("update", UPDATE, UNRESERVED_KEYWORD)
+PG_KEYWORD("user", USER, RESERVED_KEYWORD)
+PG_KEYWORD("using", USING, RESERVED_KEYWORD)
+PG_KEYWORD("vacuum", VACUUM, UNRESERVED_KEYWORD)
+PG_KEYWORD("valid", VALID, UNRESERVED_KEYWORD)
+PG_KEYWORD("validate", VALIDATE, UNRESERVED_KEYWORD)
+PG_KEYWORD("validator", VALIDATOR, UNRESERVED_KEYWORD)
+PG_KEYWORD("value", VALUE_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("values", VALUES, COL_NAME_KEYWORD)
+PG_KEYWORD("varchar", VARCHAR, COL_NAME_KEYWORD)
+PG_KEYWORD("variadic", VARIADIC, RESERVED_KEYWORD)
+PG_KEYWORD("varying", VARYING, UNRESERVED_KEYWORD)
+PG_KEYWORD("verbose", VERBOSE, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("version", VERSION_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("view", VIEW, UNRESERVED_KEYWORD)
+PG_KEYWORD("views", VIEWS, UNRESERVED_KEYWORD)
+PG_KEYWORD("volatile", VOLATILE, UNRESERVED_KEYWORD)
+PG_KEYWORD("when", WHEN, RESERVED_KEYWORD)
+PG_KEYWORD("where", WHERE, RESERVED_KEYWORD)
+PG_KEYWORD("whitespace", WHITESPACE_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("window", WINDOW, RESERVED_KEYWORD)
+PG_KEYWORD("with", WITH, RESERVED_KEYWORD)
+PG_KEYWORD("within", WITHIN, UNRESERVED_KEYWORD)
+PG_KEYWORD("without", WITHOUT, UNRESERVED_KEYWORD)
+PG_KEYWORD("work", WORK, UNRESERVED_KEYWORD)
+PG_KEYWORD("wrapper", WRAPPER, UNRESERVED_KEYWORD)
+PG_KEYWORD("write", WRITE, UNRESERVED_KEYWORD)
+PG_KEYWORD("xml", XML_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("xmlattributes", XMLATTRIBUTES, COL_NAME_KEYWORD)
+PG_KEYWORD("xmlconcat", XMLCONCAT, COL_NAME_KEYWORD)
+PG_KEYWORD("xmlelement", XMLELEMENT, COL_NAME_KEYWORD)
+PG_KEYWORD("xmlexists", XMLEXISTS, COL_NAME_KEYWORD)
+PG_KEYWORD("xmlforest", XMLFOREST, COL_NAME_KEYWORD)
+PG_KEYWORD("xmlnamespaces", XMLNAMESPACES, COL_NAME_KEYWORD)
+PG_KEYWORD("xmlparse", XMLPARSE, COL_NAME_KEYWORD)
+PG_KEYWORD("xmlpi", XMLPI, COL_NAME_KEYWORD)
+PG_KEYWORD("xmlroot", XMLROOT, COL_NAME_KEYWORD)
+PG_KEYWORD("xmlserialize", XMLSERIALIZE, COL_NAME_KEYWORD)
+PG_KEYWORD("xmltable", XMLTABLE, COL_NAME_KEYWORD)
+PG_KEYWORD("year", YEAR_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("yes", YES_P, UNRESERVED_KEYWORD)
+PG_KEYWORD("zone", ZONE, UNRESERVED_KEYWORD)
diff --git a/src/include/parser/parse_agg.h b/src/include/parser/parse_agg.h
new file mode 100644
index 0000000..1a364d5
--- /dev/null
+++ b/src/include/parser/parse_agg.h
@@ -0,0 +1,68 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_agg.h
+ * handle aggregates and window functions in parser
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/parse_agg.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_AGG_H
+#define PARSE_AGG_H
+
+#include "parser/parse_node.h"
+
+extern void transformAggregateCall(ParseState *pstate, Aggref *agg,
+ List *args, List *aggorder,
+ bool agg_distinct);
+
+extern Node *transformGroupingFunc(ParseState *pstate, GroupingFunc *g);
+
+extern void transformWindowFuncCall(ParseState *pstate, WindowFunc *wfunc,
+ WindowDef *windef);
+
+extern void parseCheckAggregates(ParseState *pstate, Query *qry);
+
+extern List *expand_grouping_sets(List *groupingSets, int limit);
+
+extern int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes);
+
+extern Oid resolve_aggregate_transtype(Oid aggfuncid,
+ Oid aggtranstype,
+ Oid *inputTypes,
+ int numArguments);
+
+extern void build_aggregate_transfn_expr(Oid *agg_input_types,
+ int agg_num_inputs,
+ int agg_num_direct_inputs,
+ bool agg_variadic,
+ Oid agg_state_type,
+ Oid agg_input_collation,
+ Oid transfn_oid,
+ Oid invtransfn_oid,
+ Expr **transfnexpr,
+ Expr **invtransfnexpr);
+
+extern void build_aggregate_combinefn_expr(Oid agg_state_type,
+ Oid agg_input_collation,
+ Oid combinefn_oid,
+ Expr **combinefnexpr);
+
+extern void build_aggregate_serialfn_expr(Oid serialfn_oid,
+ Expr **serialfnexpr);
+
+extern void build_aggregate_deserialfn_expr(Oid deserialfn_oid,
+ Expr **deserialfnexpr);
+
+extern void build_aggregate_finalfn_expr(Oid *agg_input_types,
+ int num_finalfn_inputs,
+ Oid agg_state_type,
+ Oid agg_result_type,
+ Oid agg_input_collation,
+ Oid finalfn_oid,
+ Expr **finalfnexpr);
+
+#endif /* PARSE_AGG_H */
diff --git a/src/include/parser/parse_clause.h b/src/include/parser/parse_clause.h
new file mode 100644
index 0000000..75a4fcf
--- /dev/null
+++ b/src/include/parser/parse_clause.h
@@ -0,0 +1,54 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_clause.h
+ * handle clauses in parser
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/parse_clause.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_CLAUSE_H
+#define PARSE_CLAUSE_H
+
+#include "parser/parse_node.h"
+
+extern void transformFromClause(ParseState *pstate, List *frmList);
+extern int setTargetTable(ParseState *pstate, RangeVar *relation,
+ bool inh, bool alsoSource, AclMode requiredPerms);
+
+extern Node *transformWhereClause(ParseState *pstate, Node *clause,
+ ParseExprKind exprKind, const char *constructName);
+extern Node *transformLimitClause(ParseState *pstate, Node *clause,
+ ParseExprKind exprKind, const char *constructName,
+ LimitOption limitOption);
+extern List *transformGroupClause(ParseState *pstate, List *grouplist,
+ List **groupingSets,
+ List **targetlist, List *sortClause,
+ ParseExprKind exprKind, bool useSQL99);
+extern List *transformSortClause(ParseState *pstate, List *orderlist,
+ List **targetlist, ParseExprKind exprKind,
+ bool useSQL99);
+
+extern List *transformWindowDefinitions(ParseState *pstate,
+ List *windowdefs,
+ List **targetlist);
+
+extern List *transformDistinctClause(ParseState *pstate,
+ List **targetlist, List *sortClause, bool is_agg);
+extern List *transformDistinctOnClause(ParseState *pstate, List *distinctlist,
+ List **targetlist, List *sortClause);
+extern void transformOnConflictArbiter(ParseState *pstate,
+ OnConflictClause *onConflictClause,
+ List **arbiterExpr, Node **arbiterWhere,
+ Oid *constraint);
+
+extern List *addTargetToSortList(ParseState *pstate, TargetEntry *tle,
+ List *sortlist, List *targetlist, SortBy *sortby);
+extern Index assignSortGroupRef(TargetEntry *tle, List *tlist);
+extern bool targetIsInSortList(TargetEntry *tle, Oid sortop, List *sortList);
+
+#endif /* PARSE_CLAUSE_H */
diff --git a/src/include/parser/parse_coerce.h b/src/include/parser/parse_coerce.h
new file mode 100644
index 0000000..8686eaa
--- /dev/null
+++ b/src/include/parser/parse_coerce.h
@@ -0,0 +1,97 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_coerce.h
+ * Routines for type coercion.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/parse_coerce.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_COERCE_H
+#define PARSE_COERCE_H
+
+#include "parser/parse_node.h"
+
+
+/* Type categories (see TYPCATEGORY_xxx symbols in catalog/pg_type.h) */
+typedef char TYPCATEGORY;
+
+/* Result codes for find_coercion_pathway */
+typedef enum CoercionPathType
+{
+ COERCION_PATH_NONE, /* failed to find any coercion pathway */
+ COERCION_PATH_FUNC, /* apply the specified coercion function */
+ COERCION_PATH_RELABELTYPE, /* binary-compatible cast, no function */
+ COERCION_PATH_ARRAYCOERCE, /* need an ArrayCoerceExpr node */
+ COERCION_PATH_COERCEVIAIO /* need a CoerceViaIO node */
+} CoercionPathType;
+
+
+extern bool IsBinaryCoercible(Oid srctype, Oid targettype);
+extern bool IsPreferredType(TYPCATEGORY category, Oid type);
+extern TYPCATEGORY TypeCategory(Oid type);
+
+extern Node *coerce_to_target_type(ParseState *pstate,
+ Node *expr, Oid exprtype,
+ Oid targettype, int32 targettypmod,
+ CoercionContext ccontext,
+ CoercionForm cformat,
+ int location);
+extern bool can_coerce_type(int nargs, const Oid *input_typeids, const Oid *target_typeids,
+ CoercionContext ccontext);
+extern Node *coerce_type(ParseState *pstate, Node *node,
+ Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod,
+ CoercionContext ccontext, CoercionForm cformat, int location);
+extern Node *coerce_to_domain(Node *arg, Oid baseTypeId, int32 baseTypeMod,
+ Oid typeId,
+ CoercionContext ccontext, CoercionForm cformat, int location,
+ bool hideInputCoercion);
+
+extern Node *coerce_to_boolean(ParseState *pstate, Node *node,
+ const char *constructName);
+extern Node *coerce_to_specific_type(ParseState *pstate, Node *node,
+ Oid targetTypeId,
+ const char *constructName);
+
+extern Node *coerce_to_specific_type_typmod(ParseState *pstate, Node *node,
+ Oid targetTypeId, int32 targetTypmod,
+ const char *constructName);
+
+extern int parser_coercion_errposition(ParseState *pstate,
+ int coerce_location,
+ Node *input_expr);
+
+extern Oid select_common_type(ParseState *pstate, List *exprs,
+ const char *context, Node **which_expr);
+extern Node *coerce_to_common_type(ParseState *pstate, Node *node,
+ Oid targetTypeId,
+ const char *context);
+
+extern bool check_generic_type_consistency(const Oid *actual_arg_types,
+ const Oid *declared_arg_types,
+ int nargs);
+extern Oid enforce_generic_type_consistency(const Oid *actual_arg_types,
+ Oid *declared_arg_types,
+ int nargs,
+ Oid rettype,
+ bool allow_poly);
+
+extern char *check_valid_polymorphic_signature(Oid ret_type,
+ const Oid *declared_arg_types,
+ int nargs);
+extern char *check_valid_internal_signature(Oid ret_type,
+ const Oid *declared_arg_types,
+ int nargs);
+
+extern CoercionPathType find_coercion_pathway(Oid targetTypeId,
+ Oid sourceTypeId,
+ CoercionContext ccontext,
+ Oid *funcid);
+extern CoercionPathType find_typmod_coercion_function(Oid typeId,
+ Oid *funcid);
+
+#endif /* PARSE_COERCE_H */
diff --git a/src/include/parser/parse_collate.h b/src/include/parser/parse_collate.h
new file mode 100644
index 0000000..c1021e7
--- /dev/null
+++ b/src/include/parser/parse_collate.h
@@ -0,0 +1,27 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_collate.h
+ * Routines for assigning collation information.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/parse_collate.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_COLLATE_H
+#define PARSE_COLLATE_H
+
+#include "parser/parse_node.h"
+
+extern void assign_query_collations(ParseState *pstate, Query *query);
+
+extern void assign_list_collations(ParseState *pstate, List *exprs);
+
+extern void assign_expr_collations(ParseState *pstate, Node *expr);
+
+extern Oid select_common_collation(ParseState *pstate, List *exprs, bool none_ok);
+
+#endif /* PARSE_COLLATE_H */
diff --git a/src/include/parser/parse_cte.h b/src/include/parser/parse_cte.h
new file mode 100644
index 0000000..63b3241
--- /dev/null
+++ b/src/include/parser/parse_cte.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_cte.h
+ * handle CTEs (common table expressions) in parser
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/parse_cte.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_CTE_H
+#define PARSE_CTE_H
+
+#include "parser/parse_node.h"
+
+extern List *transformWithClause(ParseState *pstate, WithClause *withClause);
+
+extern void analyzeCTETargetList(ParseState *pstate, CommonTableExpr *cte,
+ List *tlist);
+
+#endif /* PARSE_CTE_H */
diff --git a/src/include/parser/parse_enr.h b/src/include/parser/parse_enr.h
new file mode 100644
index 0000000..a013f10
--- /dev/null
+++ b/src/include/parser/parse_enr.h
@@ -0,0 +1,22 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_enr.h
+ * Internal definitions for parser
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/parse_enr.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_ENR_H
+#define PARSE_ENR_H
+
+#include "parser/parse_node.h"
+
+extern bool name_matches_visible_ENR(ParseState *pstate, const char *refname);
+extern EphemeralNamedRelationMetadata get_visible_ENR(ParseState *pstate, const char *refname);
+
+#endif /* PARSE_ENR_H */
diff --git a/src/include/parser/parse_expr.h b/src/include/parser/parse_expr.h
new file mode 100644
index 0000000..b01d3b7
--- /dev/null
+++ b/src/include/parser/parse_expr.h
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_expr.h
+ * handle expressions in parser
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/parse_expr.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_EXPR_H
+#define PARSE_EXPR_H
+
+#include "parser/parse_node.h"
+
+/* GUC parameters */
+extern bool operator_precedence_warning;
+extern bool Transform_null_equals;
+
+extern Node *transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind);
+
+extern const char *ParseExprKindName(ParseExprKind exprKind);
+
+#endif /* PARSE_EXPR_H */
diff --git a/src/include/parser/parse_func.h b/src/include/parser/parse_func.h
new file mode 100644
index 0000000..dd189f5
--- /dev/null
+++ b/src/include/parser/parse_func.h
@@ -0,0 +1,73 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_func.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/parse_func.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_FUNC_H
+#define PARSE_FUNC_H
+
+#include "catalog/namespace.h"
+#include "parser/parse_node.h"
+
+
+/* Result codes for func_get_detail */
+typedef enum
+{
+ FUNCDETAIL_NOTFOUND, /* no matching function */
+ FUNCDETAIL_MULTIPLE, /* too many matching functions */
+ FUNCDETAIL_NORMAL, /* found a matching regular function */
+ FUNCDETAIL_PROCEDURE, /* found a matching procedure */
+ FUNCDETAIL_AGGREGATE, /* found a matching aggregate function */
+ FUNCDETAIL_WINDOWFUNC, /* found a matching window function */
+ FUNCDETAIL_COERCION /* it's a type coercion request */
+} FuncDetailCode;
+
+
+extern Node *ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
+ Node *last_srf, FuncCall *fn, bool proc_call,
+ int location);
+
+extern FuncDetailCode func_get_detail(List *funcname,
+ List *fargs, List *fargnames,
+ int nargs, Oid *argtypes,
+ bool expand_variadic, bool expand_defaults,
+ Oid *funcid, Oid *rettype,
+ bool *retset, int *nvargs, Oid *vatype,
+ Oid **true_typeids, List **argdefaults);
+
+extern int func_match_argtypes(int nargs,
+ Oid *input_typeids,
+ FuncCandidateList raw_candidates,
+ FuncCandidateList *candidates);
+
+extern FuncCandidateList func_select_candidate(int nargs,
+ Oid *input_typeids,
+ FuncCandidateList candidates);
+
+extern void make_fn_arguments(ParseState *pstate,
+ List *fargs,
+ Oid *actual_arg_types,
+ Oid *declared_arg_types);
+
+extern const char *funcname_signature_string(const char *funcname, int nargs,
+ List *argnames, const Oid *argtypes);
+extern const char *func_signature_string(List *funcname, int nargs,
+ List *argnames, const Oid *argtypes);
+
+extern Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes,
+ bool missing_ok);
+extern Oid LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func,
+ bool missing_ok);
+
+extern void check_srf_call_placement(ParseState *pstate, Node *last_srf,
+ int location);
+
+#endif /* PARSE_FUNC_H */
diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h
new file mode 100644
index 0000000..d25819a
--- /dev/null
+++ b/src/include/parser/parse_node.h
@@ -0,0 +1,327 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_node.h
+ * Internal definitions for parser
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/parse_node.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_NODE_H
+#define PARSE_NODE_H
+
+#include "nodes/parsenodes.h"
+#include "utils/queryenvironment.h"
+#include "utils/relcache.h"
+
+
+/* Forward references for some structs declared below */
+typedef struct ParseState ParseState;
+typedef struct ParseNamespaceItem ParseNamespaceItem;
+typedef struct ParseNamespaceColumn ParseNamespaceColumn;
+
+/*
+ * Expression kinds distinguished by transformExpr(). Many of these are not
+ * semantically distinct so far as expression transformation goes; rather,
+ * we distinguish them so that context-specific error messages can be printed.
+ *
+ * Note: EXPR_KIND_OTHER is not used in the core code, but is left for use
+ * by extension code that might need to call transformExpr(). The core code
+ * will not enforce any context-driven restrictions on EXPR_KIND_OTHER
+ * expressions, so the caller would have to check for sub-selects, aggregates,
+ * window functions, SRFs, etc if those need to be disallowed.
+ */
+typedef enum ParseExprKind
+{
+ EXPR_KIND_NONE = 0, /* "not in an expression" */
+ EXPR_KIND_OTHER, /* reserved for extensions */
+ EXPR_KIND_JOIN_ON, /* JOIN ON */
+ EXPR_KIND_JOIN_USING, /* JOIN USING */
+ EXPR_KIND_FROM_SUBSELECT, /* sub-SELECT in FROM clause */
+ EXPR_KIND_FROM_FUNCTION, /* function in FROM clause */
+ EXPR_KIND_WHERE, /* WHERE */
+ EXPR_KIND_HAVING, /* HAVING */
+ EXPR_KIND_FILTER, /* FILTER */
+ EXPR_KIND_WINDOW_PARTITION, /* window definition PARTITION BY */
+ EXPR_KIND_WINDOW_ORDER, /* window definition ORDER BY */
+ EXPR_KIND_WINDOW_FRAME_RANGE, /* window frame clause with RANGE */
+ EXPR_KIND_WINDOW_FRAME_ROWS, /* window frame clause with ROWS */
+ EXPR_KIND_WINDOW_FRAME_GROUPS, /* window frame clause with GROUPS */
+ EXPR_KIND_SELECT_TARGET, /* SELECT target list item */
+ EXPR_KIND_INSERT_TARGET, /* INSERT target list item */
+ EXPR_KIND_UPDATE_SOURCE, /* UPDATE assignment source item */
+ EXPR_KIND_UPDATE_TARGET, /* UPDATE assignment target item */
+ EXPR_KIND_GROUP_BY, /* GROUP BY */
+ EXPR_KIND_ORDER_BY, /* ORDER BY */
+ EXPR_KIND_DISTINCT_ON, /* DISTINCT ON */
+ EXPR_KIND_LIMIT, /* LIMIT */
+ EXPR_KIND_OFFSET, /* OFFSET */
+ EXPR_KIND_RETURNING, /* RETURNING */
+ EXPR_KIND_VALUES, /* VALUES */
+ EXPR_KIND_VALUES_SINGLE, /* single-row VALUES (in INSERT only) */
+ EXPR_KIND_CHECK_CONSTRAINT, /* CHECK constraint for a table */
+ EXPR_KIND_DOMAIN_CHECK, /* CHECK constraint for a domain */
+ EXPR_KIND_COLUMN_DEFAULT, /* default value for a table column */
+ EXPR_KIND_FUNCTION_DEFAULT, /* default parameter value for function */
+ EXPR_KIND_INDEX_EXPRESSION, /* index expression */
+ EXPR_KIND_INDEX_PREDICATE, /* index predicate */
+ EXPR_KIND_ALTER_COL_TRANSFORM, /* transform expr in ALTER COLUMN TYPE */
+ EXPR_KIND_EXECUTE_PARAMETER, /* parameter value in EXECUTE */
+ EXPR_KIND_TRIGGER_WHEN, /* WHEN condition in CREATE TRIGGER */
+ EXPR_KIND_POLICY, /* USING or WITH CHECK expr in policy */
+ EXPR_KIND_PARTITION_BOUND, /* partition bound expression */
+ EXPR_KIND_PARTITION_EXPRESSION, /* PARTITION BY expression */
+ EXPR_KIND_CALL_ARGUMENT, /* procedure argument in CALL */
+ EXPR_KIND_COPY_WHERE, /* WHERE condition in COPY FROM */
+ EXPR_KIND_GENERATED_COLUMN, /* generation expression for a column */
+} ParseExprKind;
+
+
+/*
+ * Function signatures for parser hooks
+ */
+typedef Node *(*PreParseColumnRefHook) (ParseState *pstate, ColumnRef *cref);
+typedef Node *(*PostParseColumnRefHook) (ParseState *pstate, ColumnRef *cref, Node *var);
+typedef Node *(*ParseParamRefHook) (ParseState *pstate, ParamRef *pref);
+typedef Node *(*CoerceParamHook) (ParseState *pstate, Param *param,
+ Oid targetTypeId, int32 targetTypeMod,
+ int location);
+
+
+/*
+ * State information used during parse analysis
+ *
+ * parentParseState: NULL in a top-level ParseState. When parsing a subquery,
+ * links to current parse state of outer query.
+ *
+ * p_sourcetext: source string that generated the raw parsetree being
+ * analyzed, or NULL if not available. (The string is used only to
+ * generate cursor positions in error messages: we need it to convert
+ * byte-wise locations in parse structures to character-wise cursor
+ * positions.)
+ *
+ * p_rtable: list of RTEs that will become the rangetable of the query.
+ * Note that neither relname nor refname of these entries are necessarily
+ * unique; searching the rtable by name is a bad idea.
+ *
+ * p_joinexprs: list of JoinExpr nodes associated with p_rtable entries.
+ * This is one-for-one with p_rtable, but contains NULLs for non-join
+ * RTEs, and may be shorter than p_rtable if the last RTE(s) aren't joins.
+ *
+ * p_joinlist: list of join items (RangeTblRef and JoinExpr nodes) that
+ * will become the fromlist of the query's top-level FromExpr node.
+ *
+ * p_namespace: list of ParseNamespaceItems that represents the current
+ * namespace for table and column lookup. (The RTEs listed here may be just
+ * a subset of the whole rtable. See ParseNamespaceItem comments below.)
+ *
+ * p_lateral_active: true if we are currently parsing a LATERAL subexpression
+ * of this parse level. This makes p_lateral_only namespace items visible,
+ * whereas they are not visible when p_lateral_active is FALSE.
+ *
+ * p_ctenamespace: list of CommonTableExprs (WITH items) that are visible
+ * at the moment. This is entirely different from p_namespace because a CTE
+ * is not an RTE, rather "visibility" means you could make an RTE from it.
+ *
+ * p_future_ctes: list of CommonTableExprs (WITH items) that are not yet
+ * visible due to scope rules. This is used to help improve error messages.
+ *
+ * p_parent_cte: CommonTableExpr that immediately contains the current query,
+ * if any.
+ *
+ * p_target_relation: target relation, if query is INSERT, UPDATE, or DELETE.
+ *
+ * p_target_nsitem: target relation's ParseNamespaceItem.
+ *
+ * p_is_insert: true to process assignment expressions like INSERT, false
+ * to process them like UPDATE. (Note this can change intra-statement, for
+ * cases like INSERT ON CONFLICT UPDATE.)
+ *
+ * p_windowdefs: list of WindowDefs representing WINDOW and OVER clauses.
+ * We collect these while transforming expressions and then transform them
+ * afterwards (so that any resjunk tlist items needed for the sort/group
+ * clauses end up at the end of the query tlist). A WindowDef's location in
+ * this list, counting from 1, is the winref number to use to reference it.
+ *
+ * p_expr_kind: kind of expression we're currently parsing, as per enum above;
+ * EXPR_KIND_NONE when not in an expression.
+ *
+ * p_next_resno: next TargetEntry.resno to assign, starting from 1.
+ *
+ * p_multiassign_exprs: partially-processed MultiAssignRef source expressions.
+ *
+ * p_locking_clause: query's FOR UPDATE/FOR SHARE clause, if any.
+ *
+ * p_locked_from_parent: true if parent query level applies FOR UPDATE/SHARE
+ * to this subquery as a whole.
+ *
+ * p_resolve_unknowns: resolve unknown-type SELECT output columns as type TEXT
+ * (this is true by default).
+ *
+ * p_hasAggs, p_hasWindowFuncs, etc: true if we've found any of the indicated
+ * constructs in the query.
+ *
+ * p_last_srf: the set-returning FuncExpr or OpExpr most recently found in
+ * the query, or NULL if none.
+ *
+ * p_pre_columnref_hook, etc: optional parser hook functions for modifying the
+ * interpretation of ColumnRefs and ParamRefs.
+ *
+ * p_ref_hook_state: passthrough state for the parser hook functions.
+ */
+struct ParseState
+{
+ ParseState *parentParseState; /* stack link */
+ const char *p_sourcetext; /* source text, or NULL if not available */
+ List *p_rtable; /* range table so far */
+ List *p_joinexprs; /* JoinExprs for RTE_JOIN p_rtable entries */
+ List *p_joinlist; /* join items so far (will become FromExpr
+ * node's fromlist) */
+ List *p_namespace; /* currently-referenceable RTEs (List of
+ * ParseNamespaceItem) */
+ bool p_lateral_active; /* p_lateral_only items visible? */
+ List *p_ctenamespace; /* current namespace for common table exprs */
+ List *p_future_ctes; /* common table exprs not yet in namespace */
+ CommonTableExpr *p_parent_cte; /* this query's containing CTE */
+ Relation p_target_relation; /* INSERT/UPDATE/DELETE target rel */
+ ParseNamespaceItem *p_target_nsitem; /* target rel's NSItem, or NULL */
+ bool p_is_insert; /* process assignment like INSERT not UPDATE */
+ List *p_windowdefs; /* raw representations of window clauses */
+ ParseExprKind p_expr_kind; /* what kind of expression we're parsing */
+ int p_next_resno; /* next targetlist resno to assign */
+ List *p_multiassign_exprs; /* junk tlist entries for multiassign */
+ List *p_locking_clause; /* raw FOR UPDATE/FOR SHARE info */
+ bool p_locked_from_parent; /* parent has marked this subquery
+ * with FOR UPDATE/FOR SHARE */
+ bool p_resolve_unknowns; /* resolve unknown-type SELECT outputs as
+ * type text */
+
+ QueryEnvironment *p_queryEnv; /* curr env, incl refs to enclosing env */
+
+ /* Flags telling about things found in the query: */
+ bool p_hasAggs;
+ bool p_hasWindowFuncs;
+ bool p_hasTargetSRFs;
+ bool p_hasSubLinks;
+ bool p_hasModifyingCTE;
+
+ Node *p_last_srf; /* most recent set-returning func/op found */
+
+ /*
+ * Optional hook functions for parser callbacks. These are null unless
+ * set up by the caller of make_parsestate.
+ */
+ PreParseColumnRefHook p_pre_columnref_hook;
+ PostParseColumnRefHook p_post_columnref_hook;
+ ParseParamRefHook p_paramref_hook;
+ CoerceParamHook p_coerce_param_hook;
+ void *p_ref_hook_state; /* common passthrough link for above */
+};
+
+/*
+ * An element of a namespace list.
+ *
+ * The p_nscolumns array contains info showing how to construct Vars
+ * referencing corresponding elements of the RTE's colnames list.
+ *
+ * Namespace items with p_rel_visible set define which RTEs are accessible by
+ * qualified names, while those with p_cols_visible set define which RTEs are
+ * accessible by unqualified names. These sets are different because a JOIN
+ * without an alias does not hide the contained tables (so they must be
+ * visible for qualified references) but it does hide their columns
+ * (unqualified references to the columns refer to the JOIN, not the member
+ * tables, so we must not complain that such a reference is ambiguous).
+ * Various special RTEs such as NEW/OLD for rules may also appear with only
+ * one flag set.
+ *
+ * While processing the FROM clause, namespace items may appear with
+ * p_lateral_only set, meaning they are visible only to LATERAL
+ * subexpressions. (The pstate's p_lateral_active flag tells whether we are
+ * inside such a subexpression at the moment.) If p_lateral_ok is not set,
+ * it's an error to actually use such a namespace item. One might think it
+ * would be better to just exclude such items from visibility, but the wording
+ * of SQL:2008 requires us to do it this way. We also use p_lateral_ok to
+ * forbid LATERAL references to an UPDATE/DELETE target table.
+ *
+ * At no time should a namespace list contain two entries that conflict
+ * according to the rules in checkNameSpaceConflicts; but note that those
+ * are more complicated than "must have different alias names", so in practice
+ * code searching a namespace list has to check for ambiguous references.
+ */
+struct ParseNamespaceItem
+{
+ RangeTblEntry *p_rte; /* The relation's rangetable entry */
+ int p_rtindex; /* The relation's index in the rangetable */
+ /* array of same length as p_rte->eref->colnames: */
+ ParseNamespaceColumn *p_nscolumns; /* per-column data */
+ bool p_rel_visible; /* Relation name is visible? */
+ bool p_cols_visible; /* Column names visible as unqualified refs? */
+ bool p_lateral_only; /* Is only visible to LATERAL expressions? */
+ bool p_lateral_ok; /* If so, does join type allow use? */
+};
+
+/*
+ * Data about one column of a ParseNamespaceItem.
+ *
+ * We track the info needed to construct a Var referencing the column
+ * (but only for user-defined columns; system column references and
+ * whole-row references are handled separately).
+ *
+ * p_varno and p_varattno identify the semantic referent, which is a
+ * base-relation column unless the reference is to a join USING column that
+ * isn't semantically equivalent to either join input column (because it is a
+ * FULL join or the input column requires a type coercion). In those cases
+ * p_varno and p_varattno refer to the JOIN RTE.
+ *
+ * p_varnosyn and p_varattnosyn are either identical to p_varno/p_varattno,
+ * or they specify the column's position in an aliased JOIN RTE that hides
+ * the semantic referent RTE's refname. (That could be either the JOIN RTE
+ * in which this ParseNamespaceColumn entry exists, or some lower join level.)
+ *
+ * If an RTE contains a dropped column, its ParseNamespaceColumn struct
+ * is all-zeroes. (Conventionally, test for p_varno == 0 to detect this.)
+ */
+struct ParseNamespaceColumn
+{
+ Index p_varno; /* rangetable index */
+ AttrNumber p_varattno; /* attribute number of the column */
+ Oid p_vartype; /* pg_type OID */
+ int32 p_vartypmod; /* type modifier value */
+ Oid p_varcollid; /* OID of collation, or InvalidOid */
+ Index p_varnosyn; /* rangetable index of syntactic referent */
+ AttrNumber p_varattnosyn; /* attribute number of syntactic referent */
+};
+
+/* Support for parser_errposition_callback function */
+typedef struct ParseCallbackState
+{
+ ParseState *pstate;
+ int location;
+ ErrorContextCallback errcallback;
+} ParseCallbackState;
+
+
+extern ParseState *make_parsestate(ParseState *parentParseState);
+extern void free_parsestate(ParseState *pstate);
+extern int parser_errposition(ParseState *pstate, int location);
+
+extern void setup_parser_errposition_callback(ParseCallbackState *pcbstate,
+ ParseState *pstate, int location);
+extern void cancel_parser_errposition_callback(ParseCallbackState *pcbstate);
+
+extern Oid transformContainerType(Oid *containerType, int32 *containerTypmod);
+
+extern SubscriptingRef *transformContainerSubscripts(ParseState *pstate,
+ Node *containerBase,
+ Oid containerType,
+ Oid elementType,
+ int32 containerTypMod,
+ List *indirection,
+ Node *assignFrom);
+extern Const *make_const(ParseState *pstate, Value *value, int location);
+
+#endif /* PARSE_NODE_H */
diff --git a/src/include/parser/parse_oper.h b/src/include/parser/parse_oper.h
new file mode 100644
index 0000000..bcd861e
--- /dev/null
+++ b/src/include/parser/parse_oper.h
@@ -0,0 +1,67 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_oper.h
+ * handle operator things for parser
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/parse_oper.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_OPER_H
+#define PARSE_OPER_H
+
+#include "access/htup.h"
+#include "nodes/parsenodes.h"
+#include "parser/parse_node.h"
+
+
+typedef HeapTuple Operator;
+
+/* Routines to look up an operator given name and exact input type(s) */
+extern Oid LookupOperName(ParseState *pstate, List *opername,
+ Oid oprleft, Oid oprright,
+ bool noError, int location);
+extern Oid LookupOperWithArgs(ObjectWithArgs *oper, bool noError);
+
+/* Routines to find operators matching a name and given input types */
+/* NB: the selected operator may require coercion of the input types! */
+extern Operator oper(ParseState *pstate, List *op, Oid arg1, Oid arg2,
+ bool noError, int location);
+extern Operator right_oper(ParseState *pstate, List *op, Oid arg,
+ bool noError, int location);
+extern Operator left_oper(ParseState *pstate, List *op, Oid arg,
+ bool noError, int location);
+
+/* Routines to find operators that DO NOT require coercion --- ie, their */
+/* input types are either exactly as given, or binary-compatible */
+extern Operator compatible_oper(ParseState *pstate, List *op,
+ Oid arg1, Oid arg2,
+ bool noError, int location);
+
+/* currently no need for compatible_left_oper/compatible_right_oper */
+
+/* Routines for identifying "<", "=", ">" operators for a type */
+extern void get_sort_group_operators(Oid argtype,
+ bool needLT, bool needEQ, bool needGT,
+ Oid *ltOpr, Oid *eqOpr, Oid *gtOpr,
+ bool *isHashable);
+
+/* Convenience routines for common calls on the above */
+extern Oid compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError);
+
+/* Extract operator OID or underlying-function OID from an Operator tuple */
+extern Oid oprid(Operator op);
+extern Oid oprfuncid(Operator op);
+
+/* Build expression tree for an operator invocation */
+extern Expr *make_op(ParseState *pstate, List *opname,
+ Node *ltree, Node *rtree, Node *last_srf, int location);
+extern Expr *make_scalar_array_op(ParseState *pstate, List *opname,
+ bool useOr,
+ Node *ltree, Node *rtree, int location);
+
+#endif /* PARSE_OPER_H */
diff --git a/src/include/parser/parse_param.h b/src/include/parser/parse_param.h
new file mode 100644
index 0000000..833f78d
--- /dev/null
+++ b/src/include/parser/parse_param.h
@@ -0,0 +1,25 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_param.h
+ * handle parameters in parser
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/parse_param.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_PARAM_H
+#define PARSE_PARAM_H
+
+#include "parser/parse_node.h"
+
+extern void parse_fixed_parameters(ParseState *pstate,
+ Oid *paramTypes, int numParams);
+extern void parse_variable_parameters(ParseState *pstate,
+ Oid **paramTypes, int *numParams);
+extern void check_variable_parameters(ParseState *pstate, Query *query);
+extern bool query_contains_extern_params(Query *query);
+
+#endif /* PARSE_PARAM_H */
diff --git a/src/include/parser/parse_relation.h b/src/include/parser/parse_relation.h
new file mode 100644
index 0000000..93f9446
--- /dev/null
+++ b/src/include/parser/parse_relation.h
@@ -0,0 +1,123 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_relation.h
+ * prototypes for parse_relation.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/parse_relation.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_RELATION_H
+#define PARSE_RELATION_H
+
+#include "parser/parse_node.h"
+
+
+extern ParseNamespaceItem *refnameNamespaceItem(ParseState *pstate,
+ const char *schemaname,
+ const char *refname,
+ int location,
+ int *sublevels_up);
+extern CommonTableExpr *scanNameSpaceForCTE(ParseState *pstate,
+ const char *refname,
+ Index *ctelevelsup);
+extern bool scanNameSpaceForENR(ParseState *pstate, const char *refname);
+extern void checkNameSpaceConflicts(ParseState *pstate, List *namespace1,
+ List *namespace2);
+extern ParseNamespaceItem *GetNSItemByRangeTablePosn(ParseState *pstate,
+ int varno,
+ int sublevels_up);
+extern RangeTblEntry *GetRTEByRangeTablePosn(ParseState *pstate,
+ int varno,
+ int sublevels_up);
+extern CommonTableExpr *GetCTEForRTE(ParseState *pstate, RangeTblEntry *rte,
+ int rtelevelsup);
+extern Node *scanNSItemForColumn(ParseState *pstate, ParseNamespaceItem *nsitem,
+ int sublevels_up, const char *colname,
+ int location);
+extern Node *colNameToVar(ParseState *pstate, const char *colname, bool localonly,
+ int location);
+extern void markVarForSelectPriv(ParseState *pstate, Var *var,
+ RangeTblEntry *rte);
+extern Relation parserOpenTable(ParseState *pstate, const RangeVar *relation,
+ int lockmode);
+extern ParseNamespaceItem *addRangeTableEntry(ParseState *pstate,
+ RangeVar *relation,
+ Alias *alias,
+ bool inh,
+ bool inFromCl);
+extern ParseNamespaceItem *addRangeTableEntryForRelation(ParseState *pstate,
+ Relation rel,
+ int lockmode,
+ Alias *alias,
+ bool inh,
+ bool inFromCl);
+extern ParseNamespaceItem *addRangeTableEntryForSubquery(ParseState *pstate,
+ Query *subquery,
+ Alias *alias,
+ bool lateral,
+ bool inFromCl);
+extern ParseNamespaceItem *addRangeTableEntryForFunction(ParseState *pstate,
+ List *funcnames,
+ List *funcexprs,
+ List *coldeflists,
+ RangeFunction *rangefunc,
+ bool lateral,
+ bool inFromCl);
+extern ParseNamespaceItem *addRangeTableEntryForValues(ParseState *pstate,
+ List *exprs,
+ List *coltypes,
+ List *coltypmods,
+ List *colcollations,
+ Alias *alias,
+ bool lateral,
+ bool inFromCl);
+extern ParseNamespaceItem *addRangeTableEntryForTableFunc(ParseState *pstate,
+ TableFunc *tf,
+ Alias *alias,
+ bool lateral,
+ bool inFromCl);
+extern ParseNamespaceItem *addRangeTableEntryForJoin(ParseState *pstate,
+ List *colnames,
+ ParseNamespaceColumn *nscolumns,
+ JoinType jointype,
+ int nummergedcols,
+ List *aliasvars,
+ List *leftcols,
+ List *rightcols,
+ Alias *alias,
+ bool inFromCl);
+extern ParseNamespaceItem *addRangeTableEntryForCTE(ParseState *pstate,
+ CommonTableExpr *cte,
+ Index levelsup,
+ RangeVar *rv,
+ bool inFromCl);
+extern ParseNamespaceItem *addRangeTableEntryForENR(ParseState *pstate,
+ RangeVar *rv,
+ bool inFromCl);
+extern bool isLockedRefname(ParseState *pstate, const char *refname);
+extern void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem,
+ bool addToJoinList,
+ bool addToRelNameSpace, bool addToVarNameSpace);
+extern void errorMissingRTE(ParseState *pstate, RangeVar *relation) pg_attribute_noreturn();
+extern void errorMissingColumn(ParseState *pstate,
+ const char *relname, const char *colname, int location) pg_attribute_noreturn();
+extern void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
+ int location, bool include_dropped,
+ List **colnames, List **colvars);
+extern List *expandNSItemVars(ParseNamespaceItem *nsitem,
+ int sublevels_up, int location,
+ List **colnames);
+extern List *expandNSItemAttrs(ParseState *pstate, ParseNamespaceItem *nsitem,
+ int sublevels_up, int location);
+extern int attnameAttNum(Relation rd, const char *attname, bool sysColOK);
+extern const NameData *attnumAttName(Relation rd, int attid);
+extern Oid attnumTypeId(Relation rd, int attid);
+extern Oid attnumCollationId(Relation rd, int attid);
+extern bool isQueryUsingTempRelation(Query *query);
+
+#endif /* PARSE_RELATION_H */
diff --git a/src/include/parser/parse_target.h b/src/include/parser/parse_target.h
new file mode 100644
index 0000000..7039df2
--- /dev/null
+++ b/src/include/parser/parse_target.h
@@ -0,0 +1,46 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_target.h
+ * handle target lists
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/parse_target.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_TARGET_H
+#define PARSE_TARGET_H
+
+#include "parser/parse_node.h"
+
+
+extern List *transformTargetList(ParseState *pstate, List *targetlist,
+ ParseExprKind exprKind);
+extern List *transformExpressionList(ParseState *pstate, List *exprlist,
+ ParseExprKind exprKind, bool allowDefault);
+extern void resolveTargetListUnknowns(ParseState *pstate, List *targetlist);
+extern void markTargetListOrigins(ParseState *pstate, List *targetlist);
+extern TargetEntry *transformTargetEntry(ParseState *pstate,
+ Node *node, Node *expr, ParseExprKind exprKind,
+ char *colname, bool resjunk);
+extern Expr *transformAssignedExpr(ParseState *pstate, Expr *expr,
+ ParseExprKind exprKind,
+ const char *colname,
+ int attrno,
+ List *indirection,
+ int location);
+extern void updateTargetListEntry(ParseState *pstate, TargetEntry *tle,
+ char *colname, int attrno,
+ List *indirection,
+ int location);
+extern List *checkInsertTargets(ParseState *pstate, List *cols,
+ List **attrnos);
+extern TupleDesc expandRecordVariable(ParseState *pstate, Var *var,
+ int levelsup);
+extern char *FigureColname(Node *node);
+extern char *FigureIndexColname(Node *node);
+
+#endif /* PARSE_TARGET_H */
diff --git a/src/include/parser/parse_type.h b/src/include/parser/parse_type.h
new file mode 100644
index 0000000..bb83d72
--- /dev/null
+++ b/src/include/parser/parse_type.h
@@ -0,0 +1,60 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_type.h
+ * handle type operations for parser
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/parse_type.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_TYPE_H
+#define PARSE_TYPE_H
+
+#include "access/htup.h"
+#include "parser/parse_node.h"
+
+
+typedef HeapTuple Type;
+
+extern Type LookupTypeName(ParseState *pstate, const TypeName *typeName,
+ int32 *typmod_p, bool missing_ok);
+extern Type LookupTypeNameExtended(ParseState *pstate,
+ const TypeName *typeName, int32 *typmod_p,
+ bool temp_ok, bool missing_ok);
+extern Oid LookupTypeNameOid(ParseState *pstate, const TypeName *typeName,
+ bool missing_ok);
+extern Type typenameType(ParseState *pstate, const TypeName *typeName,
+ int32 *typmod_p);
+extern Oid typenameTypeId(ParseState *pstate, const TypeName *typeName);
+extern void typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName,
+ Oid *typeid_p, int32 *typmod_p);
+
+extern char *TypeNameToString(const TypeName *typeName);
+extern char *TypeNameListToString(List *typenames);
+
+extern Oid LookupCollation(ParseState *pstate, List *collnames, int location);
+extern Oid GetColumnDefCollation(ParseState *pstate, ColumnDef *coldef, Oid typeOid);
+
+extern Type typeidType(Oid id);
+
+extern Oid typeTypeId(Type tp);
+extern int16 typeLen(Type t);
+extern bool typeByVal(Type t);
+extern char *typeTypeName(Type t);
+extern Oid typeTypeRelid(Type typ);
+extern Oid typeTypeCollation(Type typ);
+extern Datum stringTypeDatum(Type tp, char *string, int32 atttypmod);
+
+extern Oid typeidTypeRelid(Oid type_id);
+extern Oid typeOrDomainTypeRelid(Oid type_id);
+
+extern TypeName *typeStringToTypeName(const char *str);
+extern void parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p, bool missing_ok);
+
+/* true if typeid is composite, or domain over composite, but not RECORD */
+#define ISCOMPLEX(typeid) (typeOrDomainTypeRelid(typeid) != InvalidOid)
+
+#endif /* PARSE_TYPE_H */
diff --git a/src/include/parser/parse_utilcmd.h b/src/include/parser/parse_utilcmd.h
new file mode 100644
index 0000000..bc3d66e
--- /dev/null
+++ b/src/include/parser/parse_utilcmd.h
@@ -0,0 +1,41 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_utilcmd.h
+ * parse analysis for utility commands
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/parse_utilcmd.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_UTILCMD_H
+#define PARSE_UTILCMD_H
+
+#include "parser/parse_node.h"
+
+struct AttrMap; /* avoid including attmap.h here */
+
+
+extern List *transformCreateStmt(CreateStmt *stmt, const char *queryString);
+extern AlterTableStmt *transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
+ const char *queryString,
+ List **beforeStmts,
+ List **afterStmts);
+extern IndexStmt *transformIndexStmt(Oid relid, IndexStmt *stmt,
+ const char *queryString);
+extern void transformRuleStmt(RuleStmt *stmt, const char *queryString,
+ List **actions, Node **whereClause);
+extern List *transformCreateSchemaStmt(CreateSchemaStmt *stmt);
+extern PartitionBoundSpec *transformPartitionBound(ParseState *pstate, Relation parent,
+ PartitionBoundSpec *spec);
+extern List *expandTableLikeClause(RangeVar *heapRel,
+ TableLikeClause *table_like_clause);
+extern IndexStmt *generateClonedIndexStmt(RangeVar *heapRel,
+ Relation source_idx,
+ const struct AttrMap *attmap,
+ Oid *constraintOid);
+
+#endif /* PARSE_UTILCMD_H */
diff --git a/src/include/parser/parser.h b/src/include/parser/parser.h
new file mode 100644
index 0000000..3bdeeb8
--- /dev/null
+++ b/src/include/parser/parser.h
@@ -0,0 +1,41 @@
+/*-------------------------------------------------------------------------
+ *
+ * parser.h
+ * Definitions for the "raw" parser (flex and bison phases only)
+ *
+ * This is the external API for the raw lexing/parsing functions.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/parser.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSER_H
+#define PARSER_H
+
+#include "nodes/parsenodes.h"
+
+
+typedef enum
+{
+ BACKSLASH_QUOTE_OFF,
+ BACKSLASH_QUOTE_ON,
+ BACKSLASH_QUOTE_SAFE_ENCODING
+} BackslashQuoteType;
+
+/* GUC variables in scan.l (every one of these is a bad idea :-() */
+extern int backslash_quote;
+extern bool escape_string_warning;
+extern PGDLLIMPORT bool standard_conforming_strings;
+
+
+/* Primary entry point for the raw parsing functions */
+extern List *raw_parser(const char *str);
+
+/* Utility functions exported by gram.y (perhaps these should be elsewhere) */
+extern List *SystemFuncName(char *name);
+extern TypeName *SystemTypeName(char *name);
+
+#endif /* PARSER_H */
diff --git a/src/include/parser/parsetree.h b/src/include/parser/parsetree.h
new file mode 100644
index 0000000..3ed5862
--- /dev/null
+++ b/src/include/parser/parsetree.h
@@ -0,0 +1,61 @@
+/*-------------------------------------------------------------------------
+ *
+ * parsetree.h
+ * Routines to access various components and subcomponents of
+ * parse trees.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/parsetree.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSETREE_H
+#define PARSETREE_H
+
+#include "nodes/parsenodes.h"
+
+
+/* ----------------
+ * range table operations
+ * ----------------
+ */
+
+/*
+ * rt_fetch
+ *
+ * NB: this will crash and burn if handed an out-of-range RT index
+ */
+#define rt_fetch(rangetable_index, rangetable) \
+ ((RangeTblEntry *) list_nth(rangetable, (rangetable_index)-1))
+
+/*
+ * Given an RTE and an attribute number, return the appropriate
+ * variable name or alias for that attribute of that RTE.
+ */
+extern char *get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum);
+
+/*
+ * Check whether an attribute of an RTE has been dropped
+ */
+extern bool get_rte_attribute_is_dropped(RangeTblEntry *rte,
+ AttrNumber attnum);
+
+
+/* ----------------
+ * target list operations
+ * ----------------
+ */
+
+extern TargetEntry *get_tle_by_resno(List *tlist, AttrNumber resno);
+
+/* ----------------
+ * FOR UPDATE/SHARE info
+ * ----------------
+ */
+
+extern RowMarkClause *get_parse_rowmark(Query *qry, Index rtindex);
+
+#endif /* PARSETREE_H */
diff --git a/src/include/parser/scanner.h b/src/include/parser/scanner.h
new file mode 100644
index 0000000..a27352a
--- /dev/null
+++ b/src/include/parser/scanner.h
@@ -0,0 +1,150 @@
+/*-------------------------------------------------------------------------
+ *
+ * scanner.h
+ * API for the core scanner (flex machine)
+ *
+ * The core scanner is also used by PL/pgSQL, so we provide a public API
+ * for it. However, the rest of the backend is only expected to use the
+ * higher-level API provided by parser.h.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/scanner.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef SCANNER_H
+#define SCANNER_H
+
+#include "common/keywords.h"
+
+/*
+ * The scanner returns extra data about scanned tokens in this union type.
+ * Note that this is a subset of the fields used in YYSTYPE of the bison
+ * parsers built atop the scanner.
+ */
+typedef union core_YYSTYPE
+{
+ int ival; /* for integer literals */
+ char *str; /* for identifiers and non-integer literals */
+ const char *keyword; /* canonical spelling of keywords */
+} core_YYSTYPE;
+
+/*
+ * We track token locations in terms of byte offsets from the start of the
+ * source string, not the column number/line number representation that
+ * bison uses by default. Also, to minimize overhead we track only one
+ * location (usually the first token location) for each construct, not
+ * the beginning and ending locations as bison does by default. It's
+ * therefore sufficient to make YYLTYPE an int.
+ */
+#define YYLTYPE int
+
+/*
+ * Another important component of the scanner's API is the token code numbers.
+ * However, those are not defined in this file, because bison insists on
+ * defining them for itself. The token codes used by the core scanner are
+ * the ASCII characters plus these:
+ * %token <str> IDENT UIDENT FCONST SCONST USCONST BCONST XCONST Op
+ * %token <ival> ICONST PARAM
+ * %token TYPECAST DOT_DOT COLON_EQUALS EQUALS_GREATER
+ * %token LESS_EQUALS GREATER_EQUALS NOT_EQUALS
+ * The above token definitions *must* be the first ones declared in any
+ * bison parser built atop this scanner, so that they will have consistent
+ * numbers assigned to them (specifically, IDENT = 258 and so on).
+ */
+
+/*
+ * The YY_EXTRA data that a flex scanner allows us to pass around.
+ * Private state needed by the core scanner goes here. Note that the actual
+ * yy_extra struct may be larger and have this as its first component, thus
+ * allowing the calling parser to keep some fields of its own in YY_EXTRA.
+ */
+typedef struct core_yy_extra_type
+{
+ /*
+ * The string the scanner is physically scanning. We keep this mainly so
+ * that we can cheaply compute the offset of the current token (yytext).
+ */
+ char *scanbuf;
+ Size scanbuflen;
+
+ /*
+ * The keyword list to use, and the associated grammar token codes.
+ */
+ const ScanKeywordList *keywordlist;
+ const uint16 *keyword_tokens;
+
+ /*
+ * Scanner settings to use. These are initialized from the corresponding
+ * GUC variables by scanner_init(). Callers can modify them after
+ * scanner_init() if they don't want the scanner's behavior to follow the
+ * prevailing GUC settings.
+ */
+ int backslash_quote;
+ bool escape_string_warning;
+ bool standard_conforming_strings;
+
+ /*
+ * literalbuf is used to accumulate literal values when multiple rules are
+ * needed to parse a single literal. Call startlit() to reset buffer to
+ * empty, addlit() to add text. NOTE: the string in literalbuf is NOT
+ * necessarily null-terminated, but there always IS room to add a trailing
+ * null at offset literallen. We store a null only when we need it.
+ */
+ char *literalbuf; /* palloc'd expandable buffer */
+ int literallen; /* actual current string length */
+ int literalalloc; /* current allocated buffer size */
+
+ /*
+ * Random assorted scanner state.
+ */
+ int state_before_str_stop; /* start cond. before end quote */
+ int xcdepth; /* depth of nesting in slash-star comments */
+ char *dolqstart; /* current $foo$ quote start string */
+ YYLTYPE save_yylloc; /* one-element stack for PUSH_YYLLOC() */
+
+ /* first part of UTF16 surrogate pair for Unicode escapes */
+ int32 utf16_first_part;
+
+ /* state variables for literal-lexing warnings */
+ bool warn_on_first_escape;
+ bool saw_non_ascii;
+} core_yy_extra_type;
+
+/*
+ * The type of yyscanner is opaque outside scan.l.
+ */
+typedef void *core_yyscan_t;
+
+/* Support for scanner_errposition_callback function */
+typedef struct ScannerCallbackState
+{
+ core_yyscan_t yyscanner;
+ int location;
+ ErrorContextCallback errcallback;
+} ScannerCallbackState;
+
+
+/* Constant data exported from parser/scan.l */
+extern PGDLLIMPORT const uint16 ScanKeywordTokens[];
+
+/* Entry points in parser/scan.l */
+extern core_yyscan_t scanner_init(const char *str,
+ core_yy_extra_type *yyext,
+ const ScanKeywordList *keywordlist,
+ const uint16 *keyword_tokens);
+extern void scanner_finish(core_yyscan_t yyscanner);
+extern int core_yylex(core_YYSTYPE *lvalp, YYLTYPE *llocp,
+ core_yyscan_t yyscanner);
+extern int scanner_errposition(int location, core_yyscan_t yyscanner);
+extern void setup_scanner_errposition_callback(ScannerCallbackState *scbstate,
+ core_yyscan_t yyscanner,
+ int location);
+extern void cancel_scanner_errposition_callback(ScannerCallbackState *scbstate);
+extern void scanner_yyerror(const char *message, core_yyscan_t yyscanner) pg_attribute_noreturn();
+
+#endif /* SCANNER_H */
diff --git a/src/include/parser/scansup.h b/src/include/parser/scansup.h
new file mode 100644
index 0000000..7a6ee52
--- /dev/null
+++ b/src/include/parser/scansup.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * scansup.h
+ * scanner support routines. used by both the bootstrap lexer
+ * as well as the normal lexer
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/parser/scansup.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef SCANSUP_H
+#define SCANSUP_H
+
+extern char *scanstr(const char *s);
+
+extern char *downcase_truncate_identifier(const char *ident, int len,
+ bool warn);
+
+extern char *downcase_identifier(const char *ident, int len,
+ bool warn, bool truncate);
+
+extern void truncate_identifier(char *ident, int len, bool warn);
+
+extern bool scanner_isspace(char ch);
+
+#endif /* SCANSUP_H */
diff --git a/src/include/partitioning/partbounds.h b/src/include/partitioning/partbounds.h
new file mode 100644
index 0000000..05fd424
--- /dev/null
+++ b/src/include/partitioning/partbounds.h
@@ -0,0 +1,128 @@
+/*-------------------------------------------------------------------------
+ *
+ * partbounds.h
+ *
+ * Copyright (c) 2007-2020, PostgreSQL Global Development Group
+ *
+ * src/include/partitioning/partbounds.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARTBOUNDS_H
+#define PARTBOUNDS_H
+
+#include "fmgr.h"
+#include "nodes/parsenodes.h"
+#include "nodes/pg_list.h"
+#include "partitioning/partdefs.h"
+#include "utils/relcache.h"
+struct RelOptInfo; /* avoid including pathnodes.h here */
+
+
+/*
+ * PartitionBoundInfoData encapsulates a set of partition bounds. It is
+ * usually associated with partitioned tables as part of its partition
+ * descriptor, but may also be used to represent a virtual partitioned
+ * table such as a partitioned joinrel within the planner.
+ *
+ * A list partition datum that is known to be NULL is never put into the
+ * datums array. Instead, it is tracked using the null_index field.
+ *
+ * In the case of range partitioning, ndatums will typically be far less than
+ * 2 * nparts, because a partition's upper bound and the next partition's lower
+ * bound are the same in most common cases, and we only store one of them (the
+ * upper bound). In case of hash partitioning, ndatums will be the same as the
+ * number of partitions.
+ *
+ * For range and list partitioned tables, datums is an array of datum-tuples
+ * with key->partnatts datums each. For hash partitioned tables, it is an array
+ * of datum-tuples with 2 datums, modulus and remainder, corresponding to a
+ * given partition.
+ *
+ * The datums in datums array are arranged in increasing order as defined by
+ * functions qsort_partition_rbound_cmp(), qsort_partition_list_value_cmp() and
+ * qsort_partition_hbound_cmp() for range, list and hash partitioned tables
+ * respectively. For range and list partitions this simply means that the
+ * datums in the datums array are arranged in increasing order as defined by
+ * the partition key's operator classes and collations.
+ *
+ * In the case of list partitioning, the indexes array stores one entry for
+ * each datum-array entry, which is the index of the partition that accepts
+ * rows matching that datum. So nindexes == ndatums.
+ *
+ * In the case of range partitioning, the indexes array stores one entry per
+ * distinct range datum, which is the index of the partition for which that
+ * datum is an upper bound (or -1 for a "gap" that has no partition). It is
+ * convenient to have an extra -1 entry representing values above the last
+ * range datum, so nindexes == ndatums + 1.
+ *
+ * In the case of hash partitioning, the number of entries in the indexes
+ * array is the same as the greatest modulus amongst all partitions (which
+ * is a multiple of all partition moduli), so nindexes == greatest modulus.
+ * The indexes array is indexed according to the hash key's remainder modulo
+ * the greatest modulus, and it contains either the partition index accepting
+ * that remainder, or -1 if there is no partition for that remainder.
+ */
+typedef struct PartitionBoundInfoData
+{
+ char strategy; /* hash, list or range? */
+ int ndatums; /* Length of the datums[] array */
+ Datum **datums;
+ PartitionRangeDatumKind **kind; /* The kind of each range bound datum;
+ * NULL for hash and list partitioned
+ * tables */
+ int *indexes; /* Partition indexes */
+ int null_index; /* Index of the null-accepting partition; -1
+ * if there isn't one */
+ int default_index; /* Index of the default partition; -1 if there
+ * isn't one */
+ int nindexes; /* Length of the indexes[] array */
+} PartitionBoundInfoData;
+
+#define partition_bound_accepts_nulls(bi) ((bi)->null_index != -1)
+#define partition_bound_has_default(bi) ((bi)->default_index != -1)
+
+extern int get_hash_partition_greatest_modulus(PartitionBoundInfo b);
+extern uint64 compute_partition_hash_value(int partnatts, FmgrInfo *partsupfunc,
+ Oid *partcollation,
+ Datum *values, bool *isnull);
+extern List *get_qual_from_partbound(Relation rel, Relation parent,
+ PartitionBoundSpec *spec);
+extern PartitionBoundInfo partition_bounds_create(PartitionBoundSpec **boundspecs,
+ int nparts, PartitionKey key, int **mapping);
+extern bool partition_bounds_equal(int partnatts, int16 *parttyplen,
+ bool *parttypbyval, PartitionBoundInfo b1,
+ PartitionBoundInfo b2);
+extern PartitionBoundInfo partition_bounds_copy(PartitionBoundInfo src,
+ PartitionKey key);
+extern PartitionBoundInfo partition_bounds_merge(int partnatts,
+ FmgrInfo *partsupfunc,
+ Oid *partcollation,
+ struct RelOptInfo *outer_rel,
+ struct RelOptInfo *inner_rel,
+ JoinType jointype,
+ List **outer_parts,
+ List **inner_parts);
+extern bool partitions_are_ordered(PartitionBoundInfo boundinfo, int nparts);
+extern void check_new_partition_bound(char *relname, Relation parent,
+ PartitionBoundSpec *spec);
+extern void check_default_partition_contents(Relation parent,
+ Relation defaultRel,
+ PartitionBoundSpec *new_spec);
+
+extern int32 partition_rbound_datum_cmp(FmgrInfo *partsupfunc,
+ Oid *partcollation,
+ Datum *rb_datums, PartitionRangeDatumKind *rb_kind,
+ Datum *tuple_datums, int n_tuple_datums);
+extern int partition_list_bsearch(FmgrInfo *partsupfunc,
+ Oid *partcollation,
+ PartitionBoundInfo boundinfo,
+ Datum value, bool *is_equal);
+extern int partition_range_datum_bsearch(FmgrInfo *partsupfunc,
+ Oid *partcollation,
+ PartitionBoundInfo boundinfo,
+ int nvalues, Datum *values, bool *is_equal);
+extern int partition_hash_bsearch(PartitionBoundInfo boundinfo,
+ int modulus, int remainder);
+
+#endif /* PARTBOUNDS_H */
diff --git a/src/include/partitioning/partdefs.h b/src/include/partitioning/partdefs.h
new file mode 100644
index 0000000..6414e2c
--- /dev/null
+++ b/src/include/partitioning/partdefs.h
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ *
+ * partdefs.h
+ * Base definitions for partitioned table handling
+ *
+ * Copyright (c) 2007-2020, PostgreSQL Global Development Group
+ *
+ * src/include/partitioning/partdefs.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARTDEFS_H
+#define PARTDEFS_H
+
+
+typedef struct PartitionBoundInfoData *PartitionBoundInfo;
+
+typedef struct PartitionKeyData *PartitionKey;
+
+typedef struct PartitionBoundSpec PartitionBoundSpec;
+
+typedef struct PartitionDescData *PartitionDesc;
+
+typedef struct PartitionDirectoryData *PartitionDirectory;
+
+#endif /* PARTDEFS_H */
diff --git a/src/include/partitioning/partdesc.h b/src/include/partitioning/partdesc.h
new file mode 100644
index 0000000..fb416e0
--- /dev/null
+++ b/src/include/partitioning/partdesc.h
@@ -0,0 +1,41 @@
+/*-------------------------------------------------------------------------
+ *
+ * partdesc.h
+ *
+ * Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ *
+ * src/include/utils/partdesc.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef PARTDESC_H
+#define PARTDESC_H
+
+#include "partitioning/partdefs.h"
+#include "utils/relcache.h"
+
+/*
+ * Information about partitions of a partitioned table.
+ */
+typedef struct PartitionDescData
+{
+ int nparts; /* Number of partitions */
+ Oid *oids; /* Array of 'nparts' elements containing
+ * partition OIDs in order of the their bounds */
+ bool *is_leaf; /* Array of 'nparts' elements storing whether
+ * the corresponding 'oids' element belongs to
+ * a leaf partition or not */
+ PartitionBoundInfo boundinfo; /* collection of partition bounds */
+} PartitionDescData;
+
+
+extern PartitionDesc RelationGetPartitionDesc(Relation rel);
+
+extern PartitionDirectory CreatePartitionDirectory(MemoryContext mcxt);
+extern PartitionDesc PartitionDirectoryLookup(PartitionDirectory, Relation);
+extern void DestroyPartitionDirectory(PartitionDirectory pdir);
+
+extern Oid get_default_oid_from_partdesc(PartitionDesc partdesc);
+
+#endif /* PARTCACHE_H */
diff --git a/src/include/partitioning/partprune.h b/src/include/partitioning/partprune.h
new file mode 100644
index 0000000..babdad2
--- /dev/null
+++ b/src/include/partitioning/partprune.h
@@ -0,0 +1,80 @@
+/*-------------------------------------------------------------------------
+ *
+ * partprune.h
+ * prototypes for partprune.c
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/partitioning/partprune.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARTPRUNE_H
+#define PARTPRUNE_H
+
+#include "nodes/execnodes.h"
+#include "partitioning/partdefs.h"
+
+struct PlannerInfo; /* avoid including pathnodes.h here */
+struct RelOptInfo;
+
+
+/*
+ * PartitionPruneContext
+ * Stores information needed at runtime for pruning computations
+ * related to a single partitioned table.
+ *
+ * strategy Partition strategy, e.g. LIST, RANGE, HASH.
+ * partnatts Number of columns in the partition key.
+ * nparts Number of partitions in this partitioned table.
+ * boundinfo Partition boundary info for the partitioned table.
+ * partcollation Array of partnatts elements, storing the collations of the
+ * partition key columns.
+ * partsupfunc Array of FmgrInfos for the comparison or hashing functions
+ * associated with the partition keys (partnatts elements).
+ * (This points into the partrel's partition key, typically.)
+ * stepcmpfuncs Array of FmgrInfos for the comparison or hashing function
+ * for each pruning step and partition key.
+ * ppccontext Memory context holding this PartitionPruneContext's
+ * subsidiary data, such as the FmgrInfos.
+ * planstate Points to the parent plan node's PlanState when called
+ * during execution; NULL when called from the planner.
+ * exprstates Array of ExprStates, indexed as per PruneCxtStateIdx; one
+ * for each partition key in each pruning step. Allocated if
+ * planstate is non-NULL, otherwise NULL.
+ */
+typedef struct PartitionPruneContext
+{
+ char strategy;
+ int partnatts;
+ int nparts;
+ PartitionBoundInfo boundinfo;
+ Oid *partcollation;
+ FmgrInfo *partsupfunc;
+ FmgrInfo *stepcmpfuncs;
+ MemoryContext ppccontext;
+ PlanState *planstate;
+ ExprState **exprstates;
+} PartitionPruneContext;
+
+/*
+ * PruneCxtStateIdx() computes the correct index into the stepcmpfuncs[]
+ * and exprstates[] arrays for step step_id and partition key column keyno.
+ * (Note: there is code that assumes the entries for a given step are
+ * sequential, so this is not chosen freely.)
+ */
+#define PruneCxtStateIdx(partnatts, step_id, keyno) \
+ ((partnatts) * (step_id) + (keyno))
+
+extern PartitionPruneInfo *make_partition_pruneinfo(struct PlannerInfo *root,
+ struct RelOptInfo *parentrel,
+ List *subpaths,
+ List *partitioned_rels,
+ List *prunequal);
+extern Bitmapset *prune_append_rel_partitions(struct RelOptInfo *rel);
+extern Bitmapset *get_matching_partitions(PartitionPruneContext *context,
+ List *pruning_steps);
+
+#endif /* PARTPRUNE_H */
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
new file mode 100644
index 0000000..66c53c5
--- /dev/null
+++ b/src/include/pg_config.h.in
@@ -0,0 +1,980 @@
+/* src/include/pg_config.h.in. Generated from configure.in by autoheader. */
+
+/* Define to the type of arg 1 of 'accept' */
+#undef ACCEPT_TYPE_ARG1
+
+/* Define to the type of arg 2 of 'accept' */
+#undef ACCEPT_TYPE_ARG2
+
+/* Define to the type of arg 3 of 'accept' */
+#undef ACCEPT_TYPE_ARG3
+
+/* Define to the return type of 'accept' */
+#undef ACCEPT_TYPE_RETURN
+
+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
+/* The normal alignment of `double', in bytes. */
+#undef ALIGNOF_DOUBLE
+
+/* The normal alignment of `int', in bytes. */
+#undef ALIGNOF_INT
+
+/* The normal alignment of `long', in bytes. */
+#undef ALIGNOF_LONG
+
+/* The normal alignment of `long long int', in bytes. */
+#undef ALIGNOF_LONG_LONG_INT
+
+/* The normal alignment of `PG_INT128_TYPE', in bytes. */
+#undef ALIGNOF_PG_INT128_TYPE
+
+/* The normal alignment of `short', in bytes. */
+#undef ALIGNOF_SHORT
+
+/* Size of a disk block --- this also limits the size of a tuple. You can set
+ it bigger if you need bigger tuples (although TOAST should reduce the need
+ to have large tuples, since fields can be spread across multiple tuples).
+ BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is
+ currently 2^15 (32768). This is determined by the 15-bit widths of the
+ lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h).
+ Changing BLCKSZ requires an initdb. */
+#undef BLCKSZ
+
+/* Saved arguments from configure */
+#undef CONFIGURE_ARGS
+
+/* Define to the default TCP port number on which the server listens and to
+ which clients will try to connect. This can be overridden at run-time, but
+ it's convenient if your clients have the right default compiled in.
+ (--with-pgport=PORTNUM) */
+#undef DEF_PGPORT
+
+/* Define to the default TCP port number as a string constant. */
+#undef DEF_PGPORT_STR
+
+/* Define to build with GSSAPI support. (--with-gssapi) */
+#undef ENABLE_GSS
+
+/* Define to 1 if you want National Language Support. (--enable-nls) */
+#undef ENABLE_NLS
+
+/* Define to 1 to build client libraries as thread-safe code.
+ (--enable-thread-safety) */
+#undef ENABLE_THREAD_SAFETY
+
+/* Define to 1 if gettimeofday() takes only 1 argument. */
+#undef GETTIMEOFDAY_1ARG
+
+#ifdef GETTIMEOFDAY_1ARG
+# define gettimeofday(a,b) gettimeofday(a)
+#endif
+
+/* Define to 1 if you have the `append_history' function. */
+#undef HAVE_APPEND_HISTORY
+
+/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
+#undef HAVE_ASN1_STRING_GET0_DATA
+
+/* Define to 1 if you want to use atomics if available. */
+#undef HAVE_ATOMICS
+
+/* Define to 1 if you have the <atomic.h> header file. */
+#undef HAVE_ATOMIC_H
+
+/* Define to 1 if you have the `backtrace_symbols' function. */
+#undef HAVE_BACKTRACE_SYMBOLS
+
+/* Define to 1 if you have the `BIO_get_data' function. */
+#undef HAVE_BIO_GET_DATA
+
+/* Define to 1 if you have the `BIO_meth_new' function. */
+#undef HAVE_BIO_METH_NEW
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
+/* Define to 1 if your compiler handles computed gotos. */
+#undef HAVE_COMPUTED_GOTO
+
+/* Define to 1 if you have the `copyfile' function. */
+#undef HAVE_COPYFILE
+
+/* Define to 1 if you have the <copyfile.h> header file. */
+#undef HAVE_COPYFILE_H
+
+/* Define to 1 if you have the <crtdefs.h> header file. */
+#undef HAVE_CRTDEFS_H
+
+/* Define to 1 if you have the `CRYPTO_lock' function. */
+#undef HAVE_CRYPTO_LOCK
+
+/* Define to 1 if you have the declaration of `fdatasync', and to 0 if you
+ don't. */
+#undef HAVE_DECL_FDATASYNC
+
+/* Define to 1 if you have the declaration of `F_FULLFSYNC', and to 0 if you
+ don't. */
+#undef HAVE_DECL_F_FULLFSYNC
+
+/* Define to 1 if you have the declaration of
+ `LLVMCreateGDBRegistrationListener', and to 0 if you don't. */
+#undef HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER
+
+/* Define to 1 if you have the declaration of
+ `LLVMCreatePerfJITEventListener', and to 0 if you don't. */
+#undef HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER
+
+/* Define to 1 if you have the declaration of `LLVMGetHostCPUFeatures', and to
+ 0 if you don't. */
+#undef HAVE_DECL_LLVMGETHOSTCPUFEATURES
+
+/* Define to 1 if you have the declaration of `LLVMGetHostCPUName', and to 0
+ if you don't. */
+#undef HAVE_DECL_LLVMGETHOSTCPUNAME
+
+/* Define to 1 if you have the declaration of `LLVMOrcGetSymbolAddressIn', and
+ to 0 if you don't. */
+#undef HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN
+
+/* Define to 1 if you have the declaration of `posix_fadvise', and to 0 if you
+ don't. */
+#undef HAVE_DECL_POSIX_FADVISE
+
+/* Define to 1 if you have the declaration of `RTLD_GLOBAL', and to 0 if you
+ don't. */
+#undef HAVE_DECL_RTLD_GLOBAL
+
+/* Define to 1 if you have the declaration of `RTLD_NOW', and to 0 if you
+ don't. */
+#undef HAVE_DECL_RTLD_NOW
+
+/* Define to 1 if you have the declaration of `strlcat', and to 0 if you
+ don't. */
+#undef HAVE_DECL_STRLCAT
+
+/* Define to 1 if you have the declaration of `strlcpy', and to 0 if you
+ don't. */
+#undef HAVE_DECL_STRLCPY
+
+/* Define to 1 if you have the declaration of `strnlen', and to 0 if you
+ don't. */
+#undef HAVE_DECL_STRNLEN
+
+/* Define to 1 if you have the declaration of `strtoll', and to 0 if you
+ don't. */
+#undef HAVE_DECL_STRTOLL
+
+/* Define to 1 if you have the declaration of `strtoull', and to 0 if you
+ don't. */
+#undef HAVE_DECL_STRTOULL
+
+/* Define to 1 if you have the `dlopen' function. */
+#undef HAVE_DLOPEN
+
+/* Define to 1 if you have the <editline/history.h> header file. */
+#undef HAVE_EDITLINE_HISTORY_H
+
+/* Define to 1 if you have the <editline/readline.h> header file. */
+#undef HAVE_EDITLINE_READLINE_H
+
+/* Define to 1 if you have the <execinfo.h> header file. */
+#undef HAVE_EXECINFO_H
+
+/* Define to 1 if you have the `explicit_bzero' function. */
+#undef HAVE_EXPLICIT_BZERO
+
+/* Define to 1 if you have the `fdatasync' function. */
+#undef HAVE_FDATASYNC
+
+/* Define to 1 if you have the `fls' function. */
+#undef HAVE_FLS
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#undef HAVE_FSEEKO
+
+/* Define to 1 if your compiler understands __func__. */
+#undef HAVE_FUNCNAME__FUNC
+
+/* Define to 1 if your compiler understands __FUNCTION__. */
+#undef HAVE_FUNCNAME__FUNCTION
+
+/* Define to 1 if you have __atomic_compare_exchange_n(int *, int *, int). */
+#undef HAVE_GCC__ATOMIC_INT32_CAS
+
+/* Define to 1 if you have __atomic_compare_exchange_n(int64 *, int64 *,
+ int64). */
+#undef HAVE_GCC__ATOMIC_INT64_CAS
+
+/* Define to 1 if you have __sync_lock_test_and_set(char *) and friends. */
+#undef HAVE_GCC__SYNC_CHAR_TAS
+
+/* Define to 1 if you have __sync_val_compare_and_swap(int *, int, int). */
+#undef HAVE_GCC__SYNC_INT32_CAS
+
+/* Define to 1 if you have __sync_lock_test_and_set(int *) and friends. */
+#undef HAVE_GCC__SYNC_INT32_TAS
+
+/* Define to 1 if you have __sync_val_compare_and_swap(int64 *, int64, int64).
+ */
+#undef HAVE_GCC__SYNC_INT64_CAS
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#undef HAVE_GETADDRINFO
+
+/* Define to 1 if you have the `gethostbyname_r' function. */
+#undef HAVE_GETHOSTBYNAME_R
+
+/* Define to 1 if you have the `getifaddrs' function. */
+#undef HAVE_GETIFADDRS
+
+/* Define to 1 if you have the `getopt' function. */
+#undef HAVE_GETOPT
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#undef HAVE_GETOPT_H
+
+/* Define to 1 if you have the `getopt_long' function. */
+#undef HAVE_GETOPT_LONG
+
+/* Define to 1 if you have the `getpeereid' function. */
+#undef HAVE_GETPEEREID
+
+/* Define to 1 if you have the `getpeerucred' function. */
+#undef HAVE_GETPEERUCRED
+
+/* Define to 1 if you have the `getpwuid_r' function. */
+#undef HAVE_GETPWUID_R
+
+/* Define to 1 if you have the `getrlimit' function. */
+#undef HAVE_GETRLIMIT
+
+/* Define to 1 if you have the `getrusage' function. */
+#undef HAVE_GETRUSAGE
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+#undef HAVE_GSSAPI_GSSAPI_H
+
+/* Define to 1 if you have the <gssapi.h> header file. */
+#undef HAVE_GSSAPI_H
+
+/* Define to 1 if you have the <history.h> header file. */
+#undef HAVE_HISTORY_H
+
+/* Define to 1 if you have the `history_truncate_file' function. */
+#undef HAVE_HISTORY_TRUNCATE_FILE
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#undef HAVE_IFADDRS_H
+
+/* Define to 1 if you have the `inet_aton' function. */
+#undef HAVE_INET_ATON
+
+/* Define to 1 if the system has the type `int64'. */
+#undef HAVE_INT64
+
+/* Define to 1 if the system has the type `int8'. */
+#undef HAVE_INT8
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the global variable 'int opterr'. */
+#undef HAVE_INT_OPTERR
+
+/* Define to 1 if you have the global variable 'int optreset'. */
+#undef HAVE_INT_OPTRESET
+
+/* Define to 1 if you have the global variable 'int timezone'. */
+#undef HAVE_INT_TIMEZONE
+
+/* Define to 1 if you have support for IPv6. */
+#undef HAVE_IPV6
+
+/* Define to 1 if __builtin_constant_p(x) implies "i"(x) acceptance. */
+#undef HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P
+
+/* Define to 1 if you have the `kqueue' function. */
+#undef HAVE_KQUEUE
+
+/* Define to 1 if you have the <langinfo.h> header file. */
+#undef HAVE_LANGINFO_H
+
+/* Define to 1 if you have the <ldap.h> header file. */
+#undef HAVE_LDAP_H
+
+/* Define to 1 if you have the `ldap_initialize' function. */
+#undef HAVE_LDAP_INITIALIZE
+
+/* Define to 1 if you have the `crypto' library (-lcrypto). */
+#undef HAVE_LIBCRYPTO
+
+/* Define to 1 if you have the `ldap' library (-lldap). */
+#undef HAVE_LIBLDAP
+
+/* Define to 1 if you have the `m' library (-lm). */
+#undef HAVE_LIBM
+
+/* Define to 1 if you have the `pam' library (-lpam). */
+#undef HAVE_LIBPAM
+
+/* Define if you have a function readline library */
+#undef HAVE_LIBREADLINE
+
+/* Define to 1 if you have the `selinux' library (-lselinux). */
+#undef HAVE_LIBSELINUX
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+#undef HAVE_LIBSSL
+
+/* Define to 1 if you have the `wldap32' library (-lwldap32). */
+#undef HAVE_LIBWLDAP32
+
+/* Define to 1 if you have the `xml2' library (-lxml2). */
+#undef HAVE_LIBXML2
+
+/* Define to 1 if you have the `xslt' library (-lxslt). */
+#undef HAVE_LIBXSLT
+
+/* Define to 1 if you have the `z' library (-lz). */
+#undef HAVE_LIBZ
+
+/* Define to 1 if you have the `link' function. */
+#undef HAVE_LINK
+
+/* Define to 1 if the system has the type `locale_t'. */
+#undef HAVE_LOCALE_T
+
+/* Define to 1 if `long int' works and is 64 bits. */
+#undef HAVE_LONG_INT_64
+
+/* Define to 1 if `long long int' works and is 64 bits. */
+#undef HAVE_LONG_LONG_INT_64
+
+/* Define to 1 if you have the <mbarrier.h> header file. */
+#undef HAVE_MBARRIER_H
+
+/* Define to 1 if you have the `mbstowcs_l' function. */
+#undef HAVE_MBSTOWCS_L
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset_s' function. */
+#undef HAVE_MEMSET_S
+
+/* Define to 1 if the system has the type `MINIDUMP_TYPE'. */
+#undef HAVE_MINIDUMP_TYPE
+
+/* Define to 1 if you have the `mkdtemp' function. */
+#undef HAVE_MKDTEMP
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#undef HAVE_NETINET_TCP_H
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#undef HAVE_NET_IF_H
+
+/* Define to 1 if you have the `OPENSSL_init_ssl' function. */
+#undef HAVE_OPENSSL_INIT_SSL
+
+/* Define to 1 if you have the <ossp/uuid.h> header file. */
+#undef HAVE_OSSP_UUID_H
+
+/* Define to 1 if you have the <pam/pam_appl.h> header file. */
+#undef HAVE_PAM_PAM_APPL_H
+
+/* Define to 1 if you have the `poll' function. */
+#undef HAVE_POLL
+
+/* Define to 1 if you have the <poll.h> header file. */
+#undef HAVE_POLL_H
+
+/* Define to 1 if you have the `posix_fadvise' function. */
+#undef HAVE_POSIX_FADVISE
+
+/* Define to 1 if you have the `posix_fallocate' function. */
+#undef HAVE_POSIX_FALLOCATE
+
+/* Define to 1 if the assembler supports PPC's LWARX mutex hint bit. */
+#undef HAVE_PPC_LWARX_MUTEX_HINT
+
+/* Define to 1 if you have the `ppoll' function. */
+#undef HAVE_PPOLL
+
+/* Define to 1 if you have the `pread' function. */
+#undef HAVE_PREAD
+
+/* Define to 1 if you have the `pstat' function. */
+#undef HAVE_PSTAT
+
+/* Define to 1 if the PS_STRINGS thing exists. */
+#undef HAVE_PS_STRINGS
+
+/* Define if you have POSIX threads libraries and header files. */
+#undef HAVE_PTHREAD
+
+/* Define to 1 if you have the `pthread_is_threaded_np' function. */
+#undef HAVE_PTHREAD_IS_THREADED_NP
+
+/* Have PTHREAD_PRIO_INHERIT. */
+#undef HAVE_PTHREAD_PRIO_INHERIT
+
+/* Define to 1 if you have the `pwrite' function. */
+#undef HAVE_PWRITE
+
+/* Define to 1 if you have the `random' function. */
+#undef HAVE_RANDOM
+
+/* Define to 1 if you have the <readline.h> header file. */
+#undef HAVE_READLINE_H
+
+/* Define to 1 if you have the <readline/history.h> header file. */
+#undef HAVE_READLINE_HISTORY_H
+
+/* Define to 1 if you have the <readline/readline.h> header file. */
+#undef HAVE_READLINE_READLINE_H
+
+/* Define to 1 if you have the `readlink' function. */
+#undef HAVE_READLINK
+
+/* Define to 1 if you have the global variable
+ 'rl_completion_append_character'. */
+#undef HAVE_RL_COMPLETION_APPEND_CHARACTER
+
+/* Define to 1 if you have the `rl_completion_matches' function. */
+#undef HAVE_RL_COMPLETION_MATCHES
+
+/* Define to 1 if you have the global variable 'rl_completion_suppress_quote'.
+ */
+#undef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
+
+/* Define to 1 if you have the `rl_filename_completion_function' function. */
+#undef HAVE_RL_FILENAME_COMPLETION_FUNCTION
+
+/* Define to 1 if you have the global variable 'rl_filename_quote_characters'.
+ */
+#undef HAVE_RL_FILENAME_QUOTE_CHARACTERS
+
+/* Define to 1 if you have the global variable 'rl_filename_quoting_function'.
+ */
+#undef HAVE_RL_FILENAME_QUOTING_FUNCTION
+
+/* Define to 1 if you have the `rl_reset_screen_size' function. */
+#undef HAVE_RL_RESET_SCREEN_SIZE
+
+/* Define to 1 if you have the <security/pam_appl.h> header file. */
+#undef HAVE_SECURITY_PAM_APPL_H
+
+/* Define to 1 if you have the `setenv' function. */
+#undef HAVE_SETENV
+
+/* Define to 1 if you have the `setproctitle' function. */
+#undef HAVE_SETPROCTITLE
+
+/* Define to 1 if you have the `setproctitle_fast' function. */
+#undef HAVE_SETPROCTITLE_FAST
+
+/* Define to 1 if you have the `setsid' function. */
+#undef HAVE_SETSID
+
+/* Define to 1 if you have the `shm_open' function. */
+#undef HAVE_SHM_OPEN
+
+/* Define to 1 if you have spinlocks. */
+#undef HAVE_SPINLOCKS
+
+/* Define to 1 if you have the `srandom' function. */
+#undef HAVE_SRANDOM
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strchrnul' function. */
+#undef HAVE_STRCHRNUL
+
+/* Define to 1 if you have the `strerror_r' function. */
+#undef HAVE_STRERROR_R
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strlcat' function. */
+#undef HAVE_STRLCAT
+
+/* Define to 1 if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define to 1 if you have the `strnlen' function. */
+#undef HAVE_STRNLEN
+
+/* Define to 1 if you have the `strsignal' function. */
+#undef HAVE_STRSIGNAL
+
+/* Define to 1 if you have the `strtof' function. */
+#undef HAVE_STRTOF
+
+/* Define to 1 if you have the `strtoll' function. */
+#undef HAVE_STRTOLL
+
+/* Define to 1 if you have the `strtoq' function. */
+#undef HAVE_STRTOQ
+
+/* Define to 1 if you have the `strtoull' function. */
+#undef HAVE_STRTOULL
+
+/* Define to 1 if you have the `strtouq' function. */
+#undef HAVE_STRTOUQ
+
+/* Define to 1 if the system has the type `struct addrinfo'. */
+#undef HAVE_STRUCT_ADDRINFO
+
+/* Define to 1 if the system has the type `struct cmsgcred'. */
+#undef HAVE_STRUCT_CMSGCRED
+
+/* Define to 1 if the system has the type `struct option'. */
+#undef HAVE_STRUCT_OPTION
+
+/* Define to 1 if `sa_len' is a member of `struct sockaddr'. */
+#undef HAVE_STRUCT_SOCKADDR_SA_LEN
+
+/* Define to 1 if the system has the type `struct sockaddr_storage'. */
+#undef HAVE_STRUCT_SOCKADDR_STORAGE
+
+/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */
+#undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
+
+/* Define to 1 if `ss_len' is a member of `struct sockaddr_storage'. */
+#undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
+
+/* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */
+#undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY
+
+/* Define to 1 if `__ss_len' is a member of `struct sockaddr_storage'. */
+#undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN
+
+/* Define to 1 if the system has the type `struct sockaddr_un'. */
+#undef HAVE_STRUCT_SOCKADDR_UN
+
+/* Define to 1 if `tm_zone' is a member of `struct tm'. */
+#undef HAVE_STRUCT_TM_TM_ZONE
+
+/* Define to 1 if you have the `symlink' function. */
+#undef HAVE_SYMLINK
+
+/* Define to 1 if you have the `sync_file_range' function. */
+#undef HAVE_SYNC_FILE_RANGE
+
+/* Define to 1 if you have the syslog interface. */
+#undef HAVE_SYSLOG
+
+/* Define to 1 if you have the <sys/epoll.h> header file. */
+#undef HAVE_SYS_EPOLL_H
+
+/* Define to 1 if you have the <sys/event.h> header file. */
+#undef HAVE_SYS_EVENT_H
+
+/* Define to 1 if you have the <sys/ipc.h> header file. */
+#undef HAVE_SYS_IPC_H
+
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+#undef HAVE_SYS_PRCTL_H
+
+/* Define to 1 if you have the <sys/procctl.h> header file. */
+#undef HAVE_SYS_PROCCTL_H
+
+/* Define to 1 if you have the <sys/pstat.h> header file. */
+#undef HAVE_SYS_PSTAT_H
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/sem.h> header file. */
+#undef HAVE_SYS_SEM_H
+
+/* Define to 1 if you have the <sys/shm.h> header file. */
+#undef HAVE_SYS_SHM_H
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#undef HAVE_SYS_SOCKIO_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/tas.h> header file. */
+#undef HAVE_SYS_TAS_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <sys/ucred.h> header file. */
+#undef HAVE_SYS_UCRED_H
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#undef HAVE_SYS_UN_H
+
+/* Define to 1 if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
+/* Define to 1 if your compiler understands `typeof' or something similar. */
+#undef HAVE_TYPEOF
+
+/* Define to 1 if you have the <ucred.h> header file. */
+#undef HAVE_UCRED_H
+
+/* Define to 1 if the system has the type `uint64'. */
+#undef HAVE_UINT64
+
+/* Define to 1 if the system has the type `uint8'. */
+#undef HAVE_UINT8
+
+/* Define to 1 if the system has the type `union semun'. */
+#undef HAVE_UNION_SEMUN
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `unsetenv' function. */
+#undef HAVE_UNSETENV
+
+/* Define to 1 if you have the `uselocale' function. */
+#undef HAVE_USELOCALE
+
+/* Define to 1 if you have BSD UUID support. */
+#undef HAVE_UUID_BSD
+
+/* Define to 1 if you have E2FS UUID support. */
+#undef HAVE_UUID_E2FS
+
+/* Define to 1 if you have the <uuid.h> header file. */
+#undef HAVE_UUID_H
+
+/* Define to 1 if you have OSSP UUID support. */
+#undef HAVE_UUID_OSSP
+
+/* Define to 1 if you have the <uuid/uuid.h> header file. */
+#undef HAVE_UUID_UUID_H
+
+/* Define to 1 if you have the `wcstombs_l' function. */
+#undef HAVE_WCSTOMBS_L
+
+/* Define to 1 if you have the <wctype.h> header file. */
+#undef HAVE_WCTYPE_H
+
+/* Define to 1 if you have the <winldap.h> header file. */
+#undef HAVE_WINLDAP_H
+
+/* Define to 1 if you have the `X509_get_signature_nid' function. */
+#undef HAVE_X509_GET_SIGNATURE_NID
+
+/* Define to 1 if the assembler supports X86_64's POPCNTQ instruction. */
+#undef HAVE_X86_64_POPCNTQ
+
+/* Define to 1 if the system has the type `_Bool'. */
+#undef HAVE__BOOL
+
+/* Define to 1 if your compiler understands __builtin_bswap16. */
+#undef HAVE__BUILTIN_BSWAP16
+
+/* Define to 1 if your compiler understands __builtin_bswap32. */
+#undef HAVE__BUILTIN_BSWAP32
+
+/* Define to 1 if your compiler understands __builtin_bswap64. */
+#undef HAVE__BUILTIN_BSWAP64
+
+/* Define to 1 if your compiler understands __builtin_clz. */
+#undef HAVE__BUILTIN_CLZ
+
+/* Define to 1 if your compiler understands __builtin_constant_p. */
+#undef HAVE__BUILTIN_CONSTANT_P
+
+/* Define to 1 if your compiler understands __builtin_ctz. */
+#undef HAVE__BUILTIN_CTZ
+
+/* Define to 1 if your compiler understands __builtin_$op_overflow. */
+#undef HAVE__BUILTIN_OP_OVERFLOW
+
+/* Define to 1 if your compiler understands __builtin_popcount. */
+#undef HAVE__BUILTIN_POPCOUNT
+
+/* Define to 1 if your compiler understands __builtin_types_compatible_p. */
+#undef HAVE__BUILTIN_TYPES_COMPATIBLE_P
+
+/* Define to 1 if your compiler understands __builtin_unreachable. */
+#undef HAVE__BUILTIN_UNREACHABLE
+
+/* Define to 1 if you have the `_configthreadlocale' function. */
+#undef HAVE__CONFIGTHREADLOCALE
+
+/* Define to 1 if you have __cpuid. */
+#undef HAVE__CPUID
+
+/* Define to 1 if you have __get_cpuid. */
+#undef HAVE__GET_CPUID
+
+/* Define to 1 if your compiler understands _Static_assert. */
+#undef HAVE__STATIC_ASSERT
+
+/* Define to 1 if you have the `__strtoll' function. */
+#undef HAVE___STRTOLL
+
+/* Define to 1 if you have the `__strtoull' function. */
+#undef HAVE___STRTOULL
+
+/* Define to the appropriate printf length modifier for 64-bit ints. */
+#undef INT64_MODIFIER
+
+/* Define to 1 if `locale_t' requires <xlocale.h>. */
+#undef LOCALE_T_IN_XLOCALE
+
+/* Define as the maximum alignment requirement of any C data type. */
+#undef MAXIMUM_ALIGNOF
+
+/* Define bytes to use libc memset(). */
+#undef MEMSET_LOOP_LIMIT
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to the name of a signed 128-bit integer type. */
+#undef PG_INT128_TYPE
+
+/* Define to the name of a signed 64-bit integer type. */
+#undef PG_INT64_TYPE
+
+/* Define to the name of the default PostgreSQL service principal in Kerberos
+ (GSSAPI). (--with-krb-srvnam=NAME) */
+#undef PG_KRB_SRVNAM
+
+/* PostgreSQL major version as a string */
+#undef PG_MAJORVERSION
+
+/* PostgreSQL major version number */
+#undef PG_MAJORVERSION_NUM
+
+/* PostgreSQL minor version number */
+#undef PG_MINORVERSION_NUM
+
+/* Define to best printf format archetype, usually gnu_printf if available. */
+#undef PG_PRINTF_ATTRIBUTE
+
+/* Define to 1 to use <stdbool.h> to define type bool. */
+#undef PG_USE_STDBOOL
+
+/* PostgreSQL version as a string */
+#undef PG_VERSION
+
+/* PostgreSQL version as a number */
+#undef PG_VERSION_NUM
+
+/* A string containing the version number, platform, and C compiler */
+#undef PG_VERSION_STR
+
+/* Define to 1 to allow profiling output to be saved separately for each
+ process. */
+#undef PROFILE_PID_DIR
+
+/* Define to necessary symbol if this constant uses a non-standard name on
+ your system. */
+#undef PTHREAD_CREATE_JOINABLE
+
+/* RELSEG_SIZE is the maximum number of blocks allowed in one disk file. Thus,
+ the maximum size of a single file is RELSEG_SIZE * BLCKSZ; relations bigger
+ than that are divided into multiple files. RELSEG_SIZE * BLCKSZ must be
+ less than your OS' limit on file size. This is often 2 GB or 4GB in a
+ 32-bit operating system, unless you have large file support enabled. By
+ default, we make the limit 1 GB to avoid any possible integer-overflow
+ problems within the OS. A limit smaller than necessary only means we divide
+ a large relation into more chunks than necessary, so it seems best to err
+ in the direction of a small limit. A power-of-2 value is recommended to
+ save a few cycles in md.c, but is not absolutely required. Changing
+ RELSEG_SIZE requires an initdb. */
+#undef RELSEG_SIZE
+
+/* The size of `bool', as computed by sizeof. */
+#undef SIZEOF_BOOL
+
+/* The size of `long', as computed by sizeof. */
+#undef SIZEOF_LONG
+
+/* The size of `off_t', as computed by sizeof. */
+#undef SIZEOF_OFF_T
+
+/* The size of `size_t', as computed by sizeof. */
+#undef SIZEOF_SIZE_T
+
+/* The size of `void *', as computed by sizeof. */
+#undef SIZEOF_VOID_P
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if strerror_r() returns int. */
+#undef STRERROR_R_INT
+
+/* Define to 1 to use ARMv8 CRC Extension. */
+#undef USE_ARMV8_CRC32C
+
+/* Define to 1 to use ARMv8 CRC Extension with a runtime check. */
+#undef USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK
+
+/* Define to 1 to build with assertion checks. (--enable-cassert) */
+#undef USE_ASSERT_CHECKING
+
+/* Define to 1 to build with Bonjour support. (--with-bonjour) */
+#undef USE_BONJOUR
+
+/* Define to 1 to build with BSD Authentication support. (--with-bsd-auth) */
+#undef USE_BSD_AUTH
+
+/* Define to use /dev/urandom for random number generation */
+#undef USE_DEV_URANDOM
+
+/* Define to build with ICU support. (--with-icu) */
+#undef USE_ICU
+
+/* Define to 1 to build with LDAP support. (--with-ldap) */
+#undef USE_LDAP
+
+/* Define to 1 to build with XML support. (--with-libxml) */
+#undef USE_LIBXML
+
+/* Define to 1 to use XSLT support when building contrib/xml2.
+ (--with-libxslt) */
+#undef USE_LIBXSLT
+
+/* Define to 1 to build with LLVM based JIT support. (--with-llvm) */
+#undef USE_LLVM
+
+/* Define to select named POSIX semaphores. */
+#undef USE_NAMED_POSIX_SEMAPHORES
+
+/* Define to build with OpenSSL support. (--with-openssl) */
+#undef USE_OPENSSL
+
+/* Define to use OpenSSL for random number generation */
+#undef USE_OPENSSL_RANDOM
+
+/* Define to 1 to build with PAM support. (--with-pam) */
+#undef USE_PAM
+
+/* Define to 1 to use software CRC-32C implementation (slicing-by-8). */
+#undef USE_SLICING_BY_8_CRC32C
+
+/* Define to 1 use Intel SSE 4.2 CRC instructions. */
+#undef USE_SSE42_CRC32C
+
+/* Define to 1 to use Intel SSE 4.2 CRC instructions with a runtime check. */
+#undef USE_SSE42_CRC32C_WITH_RUNTIME_CHECK
+
+/* Define to build with systemd support. (--with-systemd) */
+#undef USE_SYSTEMD
+
+/* Define to select SysV-style semaphores. */
+#undef USE_SYSV_SEMAPHORES
+
+/* Define to select SysV-style shared memory. */
+#undef USE_SYSV_SHARED_MEMORY
+
+/* Define to select unnamed POSIX semaphores. */
+#undef USE_UNNAMED_POSIX_SEMAPHORES
+
+/* Define to use native Windows API for random number generation */
+#undef USE_WIN32_RANDOM
+
+/* Define to select Win32-style semaphores. */
+#undef USE_WIN32_SEMAPHORES
+
+/* Define to select Win32-style shared memory. */
+#undef USE_WIN32_SHARED_MEMORY
+
+/* Define to 1 if `wcstombs_l' requires <xlocale.h>. */
+#undef WCSTOMBS_L_IN_XLOCALE
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+# undef WORDS_BIGENDIAN
+# endif
+#endif
+
+/* Size of a WAL file block. This need have no particular relation to BLCKSZ.
+ XLOG_BLCKSZ must be a power of 2, and if your system supports O_DIRECT I/O,
+ XLOG_BLCKSZ must be a multiple of the alignment requirement for direct-I/O
+ buffers, else direct I/O may fail. Changing XLOG_BLCKSZ requires an initdb.
+ */
+#undef XLOG_BLCKSZ
+
+
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+#undef _LARGEFILE_SOURCE
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to keyword to use for C99 restrict support, or to nothing if not
+ supported */
+#undef pg_restrict
+
+/* Define to the equivalent of the C99 'restrict' keyword, or to
+ nothing if this is not supported. Do not define if restrict is
+ supported directly. */
+#undef restrict
+/* Work around a bug in Sun C++: it does not support _Restrict or
+ __restrict__, even though the corresponding Sun C compiler ends up with
+ "#define restrict _Restrict" or "#define restrict __restrict__" in the
+ previous line. Perhaps some future version of Sun C++ will work with
+ restrict; if so, hopefully it defines __RESTRICT like Sun C does. */
+#if defined __SUNPRO_CC && !defined __RESTRICT
+# define _Restrict
+# define __restrict__
+#endif
+
+/* Define to how the compiler spells `typeof'. */
+#undef typeof
diff --git a/src/include/pg_config_ext.h.in b/src/include/pg_config_ext.h.in
new file mode 100644
index 0000000..8acadbd
--- /dev/null
+++ b/src/include/pg_config_ext.h.in
@@ -0,0 +1,7 @@
+/*
+ * src/include/pg_config_ext.h.in. This is generated manually, not by
+ * autoheader, since we want to limit which symbols get defined here.
+ */
+
+/* Define to the name of a signed 64-bit integer type. */
+#undef PG_INT64_TYPE
diff --git a/src/include/pg_config_manual.h b/src/include/pg_config_manual.h
new file mode 100644
index 0000000..966da99
--- /dev/null
+++ b/src/include/pg_config_manual.h
@@ -0,0 +1,357 @@
+/*------------------------------------------------------------------------
+ * PostgreSQL manual configuration settings
+ *
+ * This file contains various configuration symbols and limits. In
+ * all cases, changing them is only useful in very rare situations or
+ * for developers. If you edit any of these, be sure to do a *full*
+ * rebuild (and an initdb if noted).
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/pg_config_manual.h
+ *------------------------------------------------------------------------
+ */
+
+/*
+ * This is the default value for wal_segment_size to be used when initdb is run
+ * without the --wal-segsize option. It must be a valid segment size.
+ */
+#define DEFAULT_XLOG_SEG_SIZE (16*1024*1024)
+
+/*
+ * Maximum length for identifiers (e.g. table names, column names,
+ * function names). Names actually are limited to one less byte than this,
+ * because the length must include a trailing zero byte.
+ *
+ * Changing this requires an initdb.
+ */
+#define NAMEDATALEN 64
+
+/*
+ * Maximum number of arguments to a function.
+ *
+ * The minimum value is 8 (GIN indexes use 8-argument support functions).
+ * The maximum possible value is around 600 (limited by index tuple size in
+ * pg_proc's index; BLCKSZ larger than 8K would allow more). Values larger
+ * than needed will waste memory and processing time, but do not directly
+ * cost disk space.
+ *
+ * Changing this does not require an initdb, but it does require a full
+ * backend recompile (including any user-defined C functions).
+ */
+#define FUNC_MAX_ARGS 100
+
+/*
+ * Maximum number of columns in an index. There is little point in making
+ * this anything but a multiple of 32, because the main cost is associated
+ * with index tuple header size (see access/itup.h).
+ *
+ * Changing this requires an initdb.
+ */
+#define INDEX_MAX_KEYS 32
+
+/*
+ * Maximum number of columns in a partition key
+ */
+#define PARTITION_MAX_KEYS 32
+
+/*
+ * Decide whether built-in 8-byte types, including float8, int8, and
+ * timestamp, are passed by value. This is on by default if sizeof(Datum) >=
+ * 8 (that is, on 64-bit platforms). If sizeof(Datum) < 8 (32-bit platforms),
+ * this must be off. We keep this here as an option so that it is easy to
+ * test the pass-by-reference code paths on 64-bit platforms.
+ *
+ * Changing this requires an initdb.
+ */
+#if SIZEOF_VOID_P >= 8
+#define USE_FLOAT8_BYVAL 1
+#endif
+
+/*
+ * When we don't have native spinlocks, we use semaphores to simulate them.
+ * Decreasing this value reduces consumption of OS resources; increasing it
+ * may improve performance, but supplying a real spinlock implementation is
+ * probably far better.
+ */
+#define NUM_SPINLOCK_SEMAPHORES 128
+
+/*
+ * When we have neither spinlocks nor atomic operations support we're
+ * implementing atomic operations on top of spinlock on top of semaphores. To
+ * be safe against atomic operations while holding a spinlock separate
+ * semaphores have to be used.
+ */
+#define NUM_ATOMICS_SEMAPHORES 64
+
+/*
+ * MAXPGPATH: standard size of a pathname buffer in PostgreSQL (hence,
+ * maximum usable pathname length is one less).
+ *
+ * We'd use a standard system header symbol for this, if there weren't
+ * so many to choose from: MAXPATHLEN, MAX_PATH, PATH_MAX are all
+ * defined by different "standards", and often have different values
+ * on the same platform! So we just punt and use a reasonably
+ * generous setting here.
+ */
+#define MAXPGPATH 1024
+
+/*
+ * PG_SOMAXCONN: maximum accept-queue length limit passed to
+ * listen(2). You'd think we should use SOMAXCONN from
+ * <sys/socket.h>, but on many systems that symbol is much smaller
+ * than the kernel's actual limit. In any case, this symbol need be
+ * twiddled only if you have a kernel that refuses large limit values,
+ * rather than silently reducing the value to what it can handle
+ * (which is what most if not all Unixen do).
+ */
+#define PG_SOMAXCONN 10000
+
+/*
+ * You can try changing this if you have a machine with bytes of
+ * another size, but no guarantee...
+ */
+#define BITS_PER_BYTE 8
+
+/*
+ * Preferred alignment for disk I/O buffers. On some CPUs, copies between
+ * user space and kernel space are significantly faster if the user buffer
+ * is aligned on a larger-than-MAXALIGN boundary. Ideally this should be
+ * a platform-dependent value, but for now we just hard-wire it.
+ */
+#define ALIGNOF_BUFFER 32
+
+/*
+ * If EXEC_BACKEND is defined, the postmaster uses an alternative method for
+ * starting subprocesses: Instead of simply using fork(), as is standard on
+ * Unix platforms, it uses fork()+exec() or something equivalent on Windows,
+ * as well as lots of extra code to bring the required global state to those
+ * new processes. This must be enabled on Windows (because there is no
+ * fork()). On other platforms, it's only useful for verifying those
+ * otherwise Windows-specific code paths.
+ */
+#if defined(WIN32) && !defined(__CYGWIN__)
+#define EXEC_BACKEND
+#endif
+
+/*
+ * Define this if your operating system supports link()
+ */
+#if !defined(WIN32) && !defined(__CYGWIN__)
+#define HAVE_WORKING_LINK 1
+#endif
+
+/*
+ * USE_POSIX_FADVISE controls whether Postgres will attempt to use the
+ * posix_fadvise() kernel call. Usually the automatic configure tests are
+ * sufficient, but some older Linux distributions had broken versions of
+ * posix_fadvise(). If necessary you can remove the #define here.
+ */
+#if HAVE_DECL_POSIX_FADVISE && defined(HAVE_POSIX_FADVISE)
+#define USE_POSIX_FADVISE
+#endif
+
+/*
+ * USE_PREFETCH code should be compiled only if we have a way to implement
+ * prefetching. (This is decoupled from USE_POSIX_FADVISE because there
+ * might in future be support for alternative low-level prefetch APIs.
+ * If you change this, you probably need to adjust the error message in
+ * check_effective_io_concurrency.)
+ */
+#ifdef USE_POSIX_FADVISE
+#define USE_PREFETCH
+#endif
+
+/*
+ * Default and maximum values for backend_flush_after, bgwriter_flush_after
+ * and checkpoint_flush_after; measured in blocks. Currently, these are
+ * enabled by default if sync_file_range() exists, ie, only on Linux. Perhaps
+ * we could also enable by default if we have mmap and msync(MS_ASYNC)?
+ */
+#ifdef HAVE_SYNC_FILE_RANGE
+#define DEFAULT_BACKEND_FLUSH_AFTER 0 /* never enabled by default */
+#define DEFAULT_BGWRITER_FLUSH_AFTER 64
+#define DEFAULT_CHECKPOINT_FLUSH_AFTER 32
+#else
+#define DEFAULT_BACKEND_FLUSH_AFTER 0
+#define DEFAULT_BGWRITER_FLUSH_AFTER 0
+#define DEFAULT_CHECKPOINT_FLUSH_AFTER 0
+#endif
+/* upper limit for all three variables */
+#define WRITEBACK_MAX_PENDING_FLUSHES 256
+
+/*
+ * USE_SSL code should be compiled only when compiling with an SSL
+ * implementation. (Currently, only OpenSSL is supported, but we might add
+ * more implementations in the future.)
+ */
+#ifdef USE_OPENSSL
+#define USE_SSL
+#endif
+
+/*
+ * This is the default directory in which AF_UNIX socket files are
+ * placed. Caution: changing this risks breaking your existing client
+ * applications, which are likely to continue to look in the old
+ * directory. But if you just hate the idea of sockets in /tmp,
+ * here's where to twiddle it. You can also override this at runtime
+ * with the postmaster's -k switch.
+ *
+ * If set to an empty string, then AF_UNIX sockets are not used by default: A
+ * server will not create an AF_UNIX socket unless the run-time configuration
+ * is changed, a client will connect via TCP/IP by default and will only use
+ * an AF_UNIX socket if one is explicitly specified.
+ *
+ * This is done by default on Windows because there is no good standard
+ * location for AF_UNIX sockets and many installations on Windows don't
+ * support them yet.
+ */
+#ifndef WIN32
+#define DEFAULT_PGSOCKET_DIR "/tmp"
+#else
+#define DEFAULT_PGSOCKET_DIR ""
+#endif
+
+/*
+ * This is the default event source for Windows event log.
+ */
+#define DEFAULT_EVENT_SOURCE "PostgreSQL"
+
+/*
+ * The random() function is expected to yield values between 0 and
+ * MAX_RANDOM_VALUE. Currently, all known implementations yield
+ * 0..2^31-1, so we just hardwire this constant. We could do a
+ * configure test if it proves to be necessary. CAUTION: Think not to
+ * replace this with RAND_MAX. RAND_MAX defines the maximum value of
+ * the older rand() function, which is often different from --- and
+ * considerably inferior to --- random().
+ */
+#define MAX_RANDOM_VALUE PG_INT32_MAX
+
+/*
+ * On PPC machines, decide whether to use the mutex hint bit in LWARX
+ * instructions. Setting the hint bit will slightly improve spinlock
+ * performance on POWER6 and later machines, but does nothing before that,
+ * and will result in illegal-instruction failures on some pre-POWER4
+ * machines. By default we use the hint bit when building for 64-bit PPC,
+ * which should be safe in nearly all cases. You might want to override
+ * this if you are building 32-bit code for a known-recent PPC machine.
+ */
+#ifdef HAVE_PPC_LWARX_MUTEX_HINT /* must have assembler support in any case */
+#if defined(__ppc64__) || defined(__powerpc64__)
+#define USE_PPC_LWARX_MUTEX_HINT
+#endif
+#endif
+
+/*
+ * On PPC machines, decide whether to use LWSYNC instructions in place of
+ * ISYNC and SYNC. This provides slightly better performance, but will
+ * result in illegal-instruction failures on some pre-POWER4 machines.
+ * By default we use LWSYNC when building for 64-bit PPC, which should be
+ * safe in nearly all cases.
+ */
+#if defined(__ppc64__) || defined(__powerpc64__)
+#define USE_PPC_LWSYNC
+#endif
+
+/*
+ * Assumed cache line size. This doesn't affect correctness, but can be used
+ * for low-level optimizations. Currently, this is used to pad some data
+ * structures in xlog.c, to ensure that highly-contended fields are on
+ * different cache lines. Too small a value can hurt performance due to false
+ * sharing, while the only downside of too large a value is a few bytes of
+ * wasted memory. The default is 128, which should be large enough for all
+ * supported platforms.
+ */
+#define PG_CACHE_LINE_SIZE 128
+
+/*
+ *------------------------------------------------------------------------
+ * The following symbols are for enabling debugging code, not for
+ * controlling user-visible features or resource limits.
+ *------------------------------------------------------------------------
+ */
+
+/*
+ * Include Valgrind "client requests", mostly in the memory allocator, so
+ * Valgrind understands PostgreSQL memory contexts. This permits detecting
+ * memory errors that Valgrind would not detect on a vanilla build. See also
+ * src/tools/valgrind.supp. "make installcheck" runs 20-30x longer under
+ * Valgrind. Note that USE_VALGRIND slowed older versions of Valgrind by an
+ * additional order of magnitude; Valgrind 3.8.1 does not have this problem.
+ * The client requests fall in hot code paths, so USE_VALGRIND also slows
+ * native execution by a few percentage points.
+ *
+ * You should normally use MEMORY_CONTEXT_CHECKING with USE_VALGRIND;
+ * instrumentation of repalloc() is inferior without it.
+ */
+/* #define USE_VALGRIND */
+
+/*
+ * Define this to cause pfree()'d memory to be cleared immediately, to
+ * facilitate catching bugs that refer to already-freed values.
+ * Right now, this gets defined automatically if --enable-cassert.
+ */
+#ifdef USE_ASSERT_CHECKING
+#define CLOBBER_FREED_MEMORY
+#endif
+
+/*
+ * Define this to check memory allocation errors (scribbling on more
+ * bytes than were allocated). Right now, this gets defined
+ * automatically if --enable-cassert or USE_VALGRIND.
+ */
+#if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
+#define MEMORY_CONTEXT_CHECKING
+#endif
+
+/*
+ * Define this to cause palloc()'d memory to be filled with random data, to
+ * facilitate catching code that depends on the contents of uninitialized
+ * memory. Caution: this is horrendously expensive.
+ */
+/* #define RANDOMIZE_ALLOCATED_MEMORY */
+
+/*
+ * Define this to force all parse and plan trees to be passed through
+ * copyObject(), to facilitate catching errors and omissions in
+ * copyObject().
+ */
+/* #define COPY_PARSE_PLAN_TREES */
+
+/*
+ * Define this to force all parse and plan trees to be passed through
+ * outfuncs.c/readfuncs.c, to facilitate catching errors and omissions in
+ * those modules.
+ */
+/* #define WRITE_READ_PARSE_PLAN_TREES */
+
+/*
+ * Define this to force all raw parse trees for DML statements to be scanned
+ * by raw_expression_tree_walker(), to facilitate catching errors and
+ * omissions in that function.
+ */
+/* #define RAW_EXPRESSION_COVERAGE_TEST */
+
+/*
+ * Enable debugging print statements for lock-related operations.
+ */
+/* #define LOCK_DEBUG */
+
+/*
+ * Enable debugging print statements for WAL-related operations; see
+ * also the wal_debug GUC var.
+ */
+/* #define WAL_DEBUG */
+
+/*
+ * Enable tracing of resource consumption during sort operations;
+ * see also the trace_sort GUC var. For 8.1 this is enabled by default.
+ */
+#define TRACE_SORT 1
+
+/*
+ * Enable tracing of syncscan operations (see also the trace_syncscan GUC var).
+ */
+/* #define TRACE_SYNCSCAN */
diff --git a/src/include/pg_getopt.h b/src/include/pg_getopt.h
new file mode 100644
index 0000000..e646fc3
--- /dev/null
+++ b/src/include/pg_getopt.h
@@ -0,0 +1,56 @@
+/*
+ * Postgres files that use getopt(3) always include this file.
+ * We must cope with three different scenarios:
+ * 1. We're using the platform's getopt(), and we should just import the
+ * appropriate declarations.
+ * 2. The platform lacks getopt(), and we must declare everything.
+ * 3. The platform has getopt(), but we're not using it because we don't
+ * like its behavior. The declarations we make here must be compatible
+ * with both the platform's getopt() and our src/port/getopt.c.
+ *
+ * Portions Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Portions Copyright (c) 2003-2020, PostgreSQL Global Development Group
+ *
+ * src/include/pg_getopt.h
+ */
+#ifndef PG_GETOPT_H
+#define PG_GETOPT_H
+
+/* POSIX says getopt() is provided by unistd.h */
+#include <unistd.h>
+
+/* rely on the system's getopt.h if present */
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+
+/*
+ * If we have <getopt.h>, assume it declares these variables, else do that
+ * ourselves. (We used to just declare them unconditionally, but Cygwin
+ * doesn't like that.)
+ */
+#ifndef HAVE_GETOPT_H
+
+extern char *optarg;
+extern int optind;
+extern int opterr;
+extern int optopt;
+
+#endif /* HAVE_GETOPT_H */
+
+/*
+ * Some platforms have optreset but fail to declare it in <getopt.h>, so cope.
+ * Cygwin, however, doesn't like this either.
+ */
+#if defined(HAVE_INT_OPTRESET) && !defined(__CYGWIN__)
+extern int optreset;
+#endif
+
+/* Provide getopt() declaration if the platform doesn't have it */
+#ifndef HAVE_GETOPT
+extern int getopt(int nargc, char *const *nargv, const char *ostr);
+#endif
+
+#endif /* PG_GETOPT_H */
diff --git a/src/include/pg_trace.h b/src/include/pg_trace.h
new file mode 100644
index 0000000..cf212ae
--- /dev/null
+++ b/src/include/pg_trace.h
@@ -0,0 +1,17 @@
+/* ----------
+ * pg_trace.h
+ *
+ * Definitions for the PostgreSQL tracing framework
+ *
+ * Copyright (c) 2006-2020, PostgreSQL Global Development Group
+ *
+ * src/include/pg_trace.h
+ * ----------
+ */
+
+#ifndef PG_TRACE_H
+#define PG_TRACE_H
+
+#include "utils/probes.h" /* pgrminclude ignore */
+
+#endif /* PG_TRACE_H */
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
new file mode 100644
index 0000000..c55dc14
--- /dev/null
+++ b/src/include/pgstat.h
@@ -0,0 +1,1487 @@
+/* ----------
+ * pgstat.h
+ *
+ * Definitions for the PostgreSQL statistics collector daemon.
+ *
+ * Copyright (c) 2001-2020, PostgreSQL Global Development Group
+ *
+ * src/include/pgstat.h
+ * ----------
+ */
+#ifndef PGSTAT_H
+#define PGSTAT_H
+
+#include "datatype/timestamp.h"
+#include "libpq/pqcomm.h"
+#include "miscadmin.h"
+#include "port/atomics.h"
+#include "portability/instr_time.h"
+#include "postmaster/pgarch.h"
+#include "storage/proc.h"
+#include "utils/hsearch.h"
+#include "utils/relcache.h"
+
+
+/* ----------
+ * Paths for the statistics files (relative to installation's $PGDATA).
+ * ----------
+ */
+#define PGSTAT_STAT_PERMANENT_DIRECTORY "pg_stat"
+#define PGSTAT_STAT_PERMANENT_FILENAME "pg_stat/global.stat"
+#define PGSTAT_STAT_PERMANENT_TMPFILE "pg_stat/global.tmp"
+
+/* Default directory to store temporary statistics data in */
+#define PG_STAT_TMP_DIR "pg_stat_tmp"
+
+/* Values for track_functions GUC variable --- order is significant! */
+typedef enum TrackFunctionsLevel
+{
+ TRACK_FUNC_OFF,
+ TRACK_FUNC_PL,
+ TRACK_FUNC_ALL
+} TrackFunctionsLevel;
+
+/* ----------
+ * The types of backend -> collector messages
+ * ----------
+ */
+typedef enum StatMsgType
+{
+ PGSTAT_MTYPE_DUMMY,
+ PGSTAT_MTYPE_INQUIRY,
+ PGSTAT_MTYPE_TABSTAT,
+ PGSTAT_MTYPE_TABPURGE,
+ PGSTAT_MTYPE_DROPDB,
+ PGSTAT_MTYPE_RESETCOUNTER,
+ PGSTAT_MTYPE_RESETSHAREDCOUNTER,
+ PGSTAT_MTYPE_RESETSINGLECOUNTER,
+ PGSTAT_MTYPE_RESETSLRUCOUNTER,
+ PGSTAT_MTYPE_AUTOVAC_START,
+ PGSTAT_MTYPE_VACUUM,
+ PGSTAT_MTYPE_ANALYZE,
+ PGSTAT_MTYPE_ARCHIVER,
+ PGSTAT_MTYPE_BGWRITER,
+ PGSTAT_MTYPE_SLRU,
+ PGSTAT_MTYPE_FUNCSTAT,
+ PGSTAT_MTYPE_FUNCPURGE,
+ PGSTAT_MTYPE_RECOVERYCONFLICT,
+ PGSTAT_MTYPE_TEMPFILE,
+ PGSTAT_MTYPE_DEADLOCK,
+ PGSTAT_MTYPE_CHECKSUMFAILURE
+} StatMsgType;
+
+/* ----------
+ * The data type used for counters.
+ * ----------
+ */
+typedef int64 PgStat_Counter;
+
+/* ----------
+ * PgStat_TableCounts The actual per-table counts kept by a backend
+ *
+ * This struct should contain only actual event counters, because we memcmp
+ * it against zeroes to detect whether there are any counts to transmit.
+ * It is a component of PgStat_TableStatus (within-backend state) and
+ * PgStat_TableEntry (the transmitted message format).
+ *
+ * Note: for a table, tuples_returned is the number of tuples successfully
+ * fetched by heap_getnext, while tuples_fetched is the number of tuples
+ * successfully fetched by heap_fetch under the control of bitmap indexscans.
+ * For an index, tuples_returned is the number of index entries returned by
+ * the index AM, while tuples_fetched is the number of tuples successfully
+ * fetched by heap_fetch under the control of simple indexscans for this index.
+ *
+ * tuples_inserted/updated/deleted/hot_updated count attempted actions,
+ * regardless of whether the transaction committed. delta_live_tuples,
+ * delta_dead_tuples, and changed_tuples are set depending on commit or abort.
+ * Note that delta_live_tuples and delta_dead_tuples can be negative!
+ * ----------
+ */
+typedef struct PgStat_TableCounts
+{
+ PgStat_Counter t_numscans;
+
+ PgStat_Counter t_tuples_returned;
+ PgStat_Counter t_tuples_fetched;
+
+ PgStat_Counter t_tuples_inserted;
+ PgStat_Counter t_tuples_updated;
+ PgStat_Counter t_tuples_deleted;
+ PgStat_Counter t_tuples_hot_updated;
+ bool t_truncated;
+
+ PgStat_Counter t_delta_live_tuples;
+ PgStat_Counter t_delta_dead_tuples;
+ PgStat_Counter t_changed_tuples;
+
+ PgStat_Counter t_blocks_fetched;
+ PgStat_Counter t_blocks_hit;
+} PgStat_TableCounts;
+
+/* Possible targets for resetting cluster-wide shared values */
+typedef enum PgStat_Shared_Reset_Target
+{
+ RESET_ARCHIVER,
+ RESET_BGWRITER
+} PgStat_Shared_Reset_Target;
+
+/* Possible object types for resetting single counters */
+typedef enum PgStat_Single_Reset_Type
+{
+ RESET_TABLE,
+ RESET_FUNCTION
+} PgStat_Single_Reset_Type;
+
+/* ------------------------------------------------------------
+ * Structures kept in backend local memory while accumulating counts
+ * ------------------------------------------------------------
+ */
+
+
+/* ----------
+ * PgStat_TableStatus Per-table status within a backend
+ *
+ * Many of the event counters are nontransactional, ie, we count events
+ * in committed and aborted transactions alike. For these, we just count
+ * directly in the PgStat_TableStatus. However, delta_live_tuples,
+ * delta_dead_tuples, and changed_tuples must be derived from event counts
+ * with awareness of whether the transaction or subtransaction committed or
+ * aborted. Hence, we also keep a stack of per-(sub)transaction status
+ * records for every table modified in the current transaction. At commit
+ * or abort, we propagate tuples_inserted/updated/deleted up to the
+ * parent subtransaction level, or out to the parent PgStat_TableStatus,
+ * as appropriate.
+ * ----------
+ */
+typedef struct PgStat_TableStatus
+{
+ Oid t_id; /* table's OID */
+ bool t_shared; /* is it a shared catalog? */
+ struct PgStat_TableXactStatus *trans; /* lowest subxact's counts */
+ PgStat_TableCounts t_counts; /* event counts to be sent */
+} PgStat_TableStatus;
+
+/* ----------
+ * PgStat_TableXactStatus Per-table, per-subtransaction status
+ * ----------
+ */
+typedef struct PgStat_TableXactStatus
+{
+ PgStat_Counter tuples_inserted; /* tuples inserted in (sub)xact */
+ PgStat_Counter tuples_updated; /* tuples updated in (sub)xact */
+ PgStat_Counter tuples_deleted; /* tuples deleted in (sub)xact */
+ bool truncated; /* relation truncated in this (sub)xact */
+ PgStat_Counter inserted_pre_trunc; /* tuples inserted prior to truncate */
+ PgStat_Counter updated_pre_trunc; /* tuples updated prior to truncate */
+ PgStat_Counter deleted_pre_trunc; /* tuples deleted prior to truncate */
+ int nest_level; /* subtransaction nest level */
+ /* links to other structs for same relation: */
+ struct PgStat_TableXactStatus *upper; /* next higher subxact if any */
+ PgStat_TableStatus *parent; /* per-table status */
+ /* structs of same subxact level are linked here: */
+ struct PgStat_TableXactStatus *next; /* next of same subxact */
+} PgStat_TableXactStatus;
+
+
+/* ------------------------------------------------------------
+ * Message formats follow
+ * ------------------------------------------------------------
+ */
+
+
+/* ----------
+ * PgStat_MsgHdr The common message header
+ * ----------
+ */
+typedef struct PgStat_MsgHdr
+{
+ StatMsgType m_type;
+ int m_size;
+} PgStat_MsgHdr;
+
+/* ----------
+ * Space available in a message. This will keep the UDP packets below 1K,
+ * which should fit unfragmented into the MTU of the loopback interface.
+ * (Larger values of PGSTAT_MAX_MSG_SIZE would work for that on most
+ * platforms, but we're being conservative here.)
+ * ----------
+ */
+#define PGSTAT_MAX_MSG_SIZE 1000
+#define PGSTAT_MSG_PAYLOAD (PGSTAT_MAX_MSG_SIZE - sizeof(PgStat_MsgHdr))
+
+
+/* ----------
+ * PgStat_MsgDummy A dummy message, ignored by the collector
+ * ----------
+ */
+typedef struct PgStat_MsgDummy
+{
+ PgStat_MsgHdr m_hdr;
+} PgStat_MsgDummy;
+
+
+/* ----------
+ * PgStat_MsgInquiry Sent by a backend to ask the collector
+ * to write the stats file(s).
+ *
+ * Ordinarily, an inquiry message prompts writing of the global stats file,
+ * the stats file for shared catalogs, and the stats file for the specified
+ * database. If databaseid is InvalidOid, only the first two are written.
+ *
+ * New file(s) will be written only if the existing file has a timestamp
+ * older than the specified cutoff_time; this prevents duplicated effort
+ * when multiple requests arrive at nearly the same time, assuming that
+ * backends send requests with cutoff_times a little bit in the past.
+ *
+ * clock_time should be the requestor's current local time; the collector
+ * uses this to check for the system clock going backward, but it has no
+ * effect unless that occurs. We assume clock_time >= cutoff_time, though.
+ * ----------
+ */
+
+typedef struct PgStat_MsgInquiry
+{
+ PgStat_MsgHdr m_hdr;
+ TimestampTz clock_time; /* observed local clock time */
+ TimestampTz cutoff_time; /* minimum acceptable file timestamp */
+ Oid databaseid; /* requested DB (InvalidOid => shared only) */
+} PgStat_MsgInquiry;
+
+
+/* ----------
+ * PgStat_TableEntry Per-table info in a MsgTabstat
+ * ----------
+ */
+typedef struct PgStat_TableEntry
+{
+ Oid t_id;
+ PgStat_TableCounts t_counts;
+} PgStat_TableEntry;
+
+/* ----------
+ * PgStat_MsgTabstat Sent by the backend to report table
+ * and buffer access statistics.
+ * ----------
+ */
+#define PGSTAT_NUM_TABENTRIES \
+ ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - 3 * sizeof(int) - 2 * sizeof(PgStat_Counter)) \
+ / sizeof(PgStat_TableEntry))
+
+typedef struct PgStat_MsgTabstat
+{
+ PgStat_MsgHdr m_hdr;
+ Oid m_databaseid;
+ int m_nentries;
+ int m_xact_commit;
+ int m_xact_rollback;
+ PgStat_Counter m_block_read_time; /* times in microseconds */
+ PgStat_Counter m_block_write_time;
+ PgStat_TableEntry m_entry[PGSTAT_NUM_TABENTRIES];
+} PgStat_MsgTabstat;
+
+
+/* ----------
+ * PgStat_MsgTabpurge Sent by the backend to tell the collector
+ * about dead tables.
+ * ----------
+ */
+#define PGSTAT_NUM_TABPURGE \
+ ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - sizeof(int)) \
+ / sizeof(Oid))
+
+typedef struct PgStat_MsgTabpurge
+{
+ PgStat_MsgHdr m_hdr;
+ Oid m_databaseid;
+ int m_nentries;
+ Oid m_tableid[PGSTAT_NUM_TABPURGE];
+} PgStat_MsgTabpurge;
+
+
+/* ----------
+ * PgStat_MsgDropdb Sent by the backend to tell the collector
+ * about a dropped database
+ * ----------
+ */
+typedef struct PgStat_MsgDropdb
+{
+ PgStat_MsgHdr m_hdr;
+ Oid m_databaseid;
+} PgStat_MsgDropdb;
+
+
+/* ----------
+ * PgStat_MsgResetcounter Sent by the backend to tell the collector
+ * to reset counters
+ * ----------
+ */
+typedef struct PgStat_MsgResetcounter
+{
+ PgStat_MsgHdr m_hdr;
+ Oid m_databaseid;
+} PgStat_MsgResetcounter;
+
+/* ----------
+ * PgStat_MsgResetsharedcounter Sent by the backend to tell the collector
+ * to reset a shared counter
+ * ----------
+ */
+typedef struct PgStat_MsgResetsharedcounter
+{
+ PgStat_MsgHdr m_hdr;
+ PgStat_Shared_Reset_Target m_resettarget;
+} PgStat_MsgResetsharedcounter;
+
+/* ----------
+ * PgStat_MsgResetsinglecounter Sent by the backend to tell the collector
+ * to reset a single counter
+ * ----------
+ */
+typedef struct PgStat_MsgResetsinglecounter
+{
+ PgStat_MsgHdr m_hdr;
+ Oid m_databaseid;
+ PgStat_Single_Reset_Type m_resettype;
+ Oid m_objectid;
+} PgStat_MsgResetsinglecounter;
+
+/* ----------
+ * PgStat_MsgResetslrucounter Sent by the backend to tell the collector
+ * to reset a SLRU counter
+ * ----------
+ */
+typedef struct PgStat_MsgResetslrucounter
+{
+ PgStat_MsgHdr m_hdr;
+ int m_index;
+} PgStat_MsgResetslrucounter;
+
+/* ----------
+ * PgStat_MsgAutovacStart Sent by the autovacuum daemon to signal
+ * that a database is going to be processed
+ * ----------
+ */
+typedef struct PgStat_MsgAutovacStart
+{
+ PgStat_MsgHdr m_hdr;
+ Oid m_databaseid;
+ TimestampTz m_start_time;
+} PgStat_MsgAutovacStart;
+
+
+/* ----------
+ * PgStat_MsgVacuum Sent by the backend or autovacuum daemon
+ * after VACUUM
+ * ----------
+ */
+typedef struct PgStat_MsgVacuum
+{
+ PgStat_MsgHdr m_hdr;
+ Oid m_databaseid;
+ Oid m_tableoid;
+ bool m_autovacuum;
+ TimestampTz m_vacuumtime;
+ PgStat_Counter m_live_tuples;
+ PgStat_Counter m_dead_tuples;
+} PgStat_MsgVacuum;
+
+
+/* ----------
+ * PgStat_MsgAnalyze Sent by the backend or autovacuum daemon
+ * after ANALYZE
+ * ----------
+ */
+typedef struct PgStat_MsgAnalyze
+{
+ PgStat_MsgHdr m_hdr;
+ Oid m_databaseid;
+ Oid m_tableoid;
+ bool m_autovacuum;
+ bool m_resetcounter;
+ TimestampTz m_analyzetime;
+ PgStat_Counter m_live_tuples;
+ PgStat_Counter m_dead_tuples;
+} PgStat_MsgAnalyze;
+
+
+/* ----------
+ * PgStat_MsgArchiver Sent by the archiver to update statistics.
+ * ----------
+ */
+typedef struct PgStat_MsgArchiver
+{
+ PgStat_MsgHdr m_hdr;
+ bool m_failed; /* Failed attempt */
+ char m_xlog[MAX_XFN_CHARS + 1];
+ TimestampTz m_timestamp;
+} PgStat_MsgArchiver;
+
+/* ----------
+ * PgStat_MsgBgWriter Sent by the bgwriter to update statistics.
+ * ----------
+ */
+typedef struct PgStat_MsgBgWriter
+{
+ PgStat_MsgHdr m_hdr;
+
+ PgStat_Counter m_timed_checkpoints;
+ PgStat_Counter m_requested_checkpoints;
+ PgStat_Counter m_buf_written_checkpoints;
+ PgStat_Counter m_buf_written_clean;
+ PgStat_Counter m_maxwritten_clean;
+ PgStat_Counter m_buf_written_backend;
+ PgStat_Counter m_buf_fsync_backend;
+ PgStat_Counter m_buf_alloc;
+ PgStat_Counter m_checkpoint_write_time; /* times in milliseconds */
+ PgStat_Counter m_checkpoint_sync_time;
+} PgStat_MsgBgWriter;
+
+/* ----------
+ * PgStat_MsgSLRU Sent by a backend to update SLRU statistics.
+ * ----------
+ */
+typedef struct PgStat_MsgSLRU
+{
+ PgStat_MsgHdr m_hdr;
+ PgStat_Counter m_index;
+ PgStat_Counter m_blocks_zeroed;
+ PgStat_Counter m_blocks_hit;
+ PgStat_Counter m_blocks_read;
+ PgStat_Counter m_blocks_written;
+ PgStat_Counter m_blocks_exists;
+ PgStat_Counter m_flush;
+ PgStat_Counter m_truncate;
+} PgStat_MsgSLRU;
+
+/* ----------
+ * PgStat_MsgRecoveryConflict Sent by the backend upon recovery conflict
+ * ----------
+ */
+typedef struct PgStat_MsgRecoveryConflict
+{
+ PgStat_MsgHdr m_hdr;
+
+ Oid m_databaseid;
+ int m_reason;
+} PgStat_MsgRecoveryConflict;
+
+/* ----------
+ * PgStat_MsgTempFile Sent by the backend upon creating a temp file
+ * ----------
+ */
+typedef struct PgStat_MsgTempFile
+{
+ PgStat_MsgHdr m_hdr;
+
+ Oid m_databaseid;
+ size_t m_filesize;
+} PgStat_MsgTempFile;
+
+/* ----------
+ * PgStat_FunctionCounts The actual per-function counts kept by a backend
+ *
+ * This struct should contain only actual event counters, because we memcmp
+ * it against zeroes to detect whether there are any counts to transmit.
+ *
+ * Note that the time counters are in instr_time format here. We convert to
+ * microseconds in PgStat_Counter format when transmitting to the collector.
+ * ----------
+ */
+typedef struct PgStat_FunctionCounts
+{
+ PgStat_Counter f_numcalls;
+ instr_time f_total_time;
+ instr_time f_self_time;
+} PgStat_FunctionCounts;
+
+/* ----------
+ * PgStat_BackendFunctionEntry Entry in backend's per-function hash table
+ * ----------
+ */
+typedef struct PgStat_BackendFunctionEntry
+{
+ Oid f_id;
+ PgStat_FunctionCounts f_counts;
+} PgStat_BackendFunctionEntry;
+
+/* ----------
+ * PgStat_FunctionEntry Per-function info in a MsgFuncstat
+ * ----------
+ */
+typedef struct PgStat_FunctionEntry
+{
+ Oid f_id;
+ PgStat_Counter f_numcalls;
+ PgStat_Counter f_total_time; /* times in microseconds */
+ PgStat_Counter f_self_time;
+} PgStat_FunctionEntry;
+
+/* ----------
+ * PgStat_MsgFuncstat Sent by the backend to report function
+ * usage statistics.
+ * ----------
+ */
+#define PGSTAT_NUM_FUNCENTRIES \
+ ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - sizeof(int)) \
+ / sizeof(PgStat_FunctionEntry))
+
+typedef struct PgStat_MsgFuncstat
+{
+ PgStat_MsgHdr m_hdr;
+ Oid m_databaseid;
+ int m_nentries;
+ PgStat_FunctionEntry m_entry[PGSTAT_NUM_FUNCENTRIES];
+} PgStat_MsgFuncstat;
+
+/* ----------
+ * PgStat_MsgFuncpurge Sent by the backend to tell the collector
+ * about dead functions.
+ * ----------
+ */
+#define PGSTAT_NUM_FUNCPURGE \
+ ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - sizeof(int)) \
+ / sizeof(Oid))
+
+typedef struct PgStat_MsgFuncpurge
+{
+ PgStat_MsgHdr m_hdr;
+ Oid m_databaseid;
+ int m_nentries;
+ Oid m_functionid[PGSTAT_NUM_FUNCPURGE];
+} PgStat_MsgFuncpurge;
+
+/* ----------
+ * PgStat_MsgDeadlock Sent by the backend to tell the collector
+ * about a deadlock that occurred.
+ * ----------
+ */
+typedef struct PgStat_MsgDeadlock
+{
+ PgStat_MsgHdr m_hdr;
+ Oid m_databaseid;
+} PgStat_MsgDeadlock;
+
+/* ----------
+ * PgStat_MsgChecksumFailure Sent by the backend to tell the collector
+ * about checksum failures noticed.
+ * ----------
+ */
+typedef struct PgStat_MsgChecksumFailure
+{
+ PgStat_MsgHdr m_hdr;
+ Oid m_databaseid;
+ int m_failurecount;
+ TimestampTz m_failure_time;
+} PgStat_MsgChecksumFailure;
+
+
+/* ----------
+ * PgStat_Msg Union over all possible messages.
+ * ----------
+ */
+typedef union PgStat_Msg
+{
+ PgStat_MsgHdr msg_hdr;
+ PgStat_MsgDummy msg_dummy;
+ PgStat_MsgInquiry msg_inquiry;
+ PgStat_MsgTabstat msg_tabstat;
+ PgStat_MsgTabpurge msg_tabpurge;
+ PgStat_MsgDropdb msg_dropdb;
+ PgStat_MsgResetcounter msg_resetcounter;
+ PgStat_MsgResetsharedcounter msg_resetsharedcounter;
+ PgStat_MsgResetsinglecounter msg_resetsinglecounter;
+ PgStat_MsgResetslrucounter msg_resetslrucounter;
+ PgStat_MsgAutovacStart msg_autovacuum_start;
+ PgStat_MsgVacuum msg_vacuum;
+ PgStat_MsgAnalyze msg_analyze;
+ PgStat_MsgArchiver msg_archiver;
+ PgStat_MsgBgWriter msg_bgwriter;
+ PgStat_MsgSLRU msg_slru;
+ PgStat_MsgFuncstat msg_funcstat;
+ PgStat_MsgFuncpurge msg_funcpurge;
+ PgStat_MsgRecoveryConflict msg_recoveryconflict;
+ PgStat_MsgDeadlock msg_deadlock;
+ PgStat_MsgTempFile msg_tempfile;
+ PgStat_MsgChecksumFailure msg_checksumfailure;
+} PgStat_Msg;
+
+
+/* ------------------------------------------------------------
+ * Statistic collector data structures follow
+ *
+ * PGSTAT_FILE_FORMAT_ID should be changed whenever any of these
+ * data structures change.
+ * ------------------------------------------------------------
+ */
+
+#define PGSTAT_FILE_FORMAT_ID 0x01A5BC9D
+
+/* ----------
+ * PgStat_StatDBEntry The collector's data per database
+ * ----------
+ */
+typedef struct PgStat_StatDBEntry
+{
+ Oid databaseid;
+ PgStat_Counter n_xact_commit;
+ PgStat_Counter n_xact_rollback;
+ PgStat_Counter n_blocks_fetched;
+ PgStat_Counter n_blocks_hit;
+ PgStat_Counter n_tuples_returned;
+ PgStat_Counter n_tuples_fetched;
+ PgStat_Counter n_tuples_inserted;
+ PgStat_Counter n_tuples_updated;
+ PgStat_Counter n_tuples_deleted;
+ TimestampTz last_autovac_time;
+ PgStat_Counter n_conflict_tablespace;
+ PgStat_Counter n_conflict_lock;
+ PgStat_Counter n_conflict_snapshot;
+ PgStat_Counter n_conflict_bufferpin;
+ PgStat_Counter n_conflict_startup_deadlock;
+ PgStat_Counter n_temp_files;
+ PgStat_Counter n_temp_bytes;
+ PgStat_Counter n_deadlocks;
+ PgStat_Counter n_checksum_failures;
+ TimestampTz last_checksum_failure;
+ PgStat_Counter n_block_read_time; /* times in microseconds */
+ PgStat_Counter n_block_write_time;
+
+ TimestampTz stat_reset_timestamp;
+ TimestampTz stats_timestamp; /* time of db stats file update */
+
+ /*
+ * tables and functions must be last in the struct, because we don't write
+ * the pointers out to the stats file.
+ */
+ HTAB *tables;
+ HTAB *functions;
+} PgStat_StatDBEntry;
+
+
+/* ----------
+ * PgStat_StatTabEntry The collector's data per table (or index)
+ * ----------
+ */
+typedef struct PgStat_StatTabEntry
+{
+ Oid tableid;
+
+ PgStat_Counter numscans;
+
+ PgStat_Counter tuples_returned;
+ PgStat_Counter tuples_fetched;
+
+ PgStat_Counter tuples_inserted;
+ PgStat_Counter tuples_updated;
+ PgStat_Counter tuples_deleted;
+ PgStat_Counter tuples_hot_updated;
+
+ PgStat_Counter n_live_tuples;
+ PgStat_Counter n_dead_tuples;
+ PgStat_Counter changes_since_analyze;
+ PgStat_Counter inserts_since_vacuum;
+
+ PgStat_Counter blocks_fetched;
+ PgStat_Counter blocks_hit;
+
+ TimestampTz vacuum_timestamp; /* user initiated vacuum */
+ PgStat_Counter vacuum_count;
+ TimestampTz autovac_vacuum_timestamp; /* autovacuum initiated */
+ PgStat_Counter autovac_vacuum_count;
+ TimestampTz analyze_timestamp; /* user initiated */
+ PgStat_Counter analyze_count;
+ TimestampTz autovac_analyze_timestamp; /* autovacuum initiated */
+ PgStat_Counter autovac_analyze_count;
+} PgStat_StatTabEntry;
+
+
+/* ----------
+ * PgStat_StatFuncEntry The collector's data per function
+ * ----------
+ */
+typedef struct PgStat_StatFuncEntry
+{
+ Oid functionid;
+
+ PgStat_Counter f_numcalls;
+
+ PgStat_Counter f_total_time; /* times in microseconds */
+ PgStat_Counter f_self_time;
+} PgStat_StatFuncEntry;
+
+
+/*
+ * Archiver statistics kept in the stats collector
+ */
+typedef struct PgStat_ArchiverStats
+{
+ PgStat_Counter archived_count; /* archival successes */
+ char last_archived_wal[MAX_XFN_CHARS + 1]; /* last WAL file
+ * archived */
+ TimestampTz last_archived_timestamp; /* last archival success time */
+ PgStat_Counter failed_count; /* failed archival attempts */
+ char last_failed_wal[MAX_XFN_CHARS + 1]; /* WAL file involved in
+ * last failure */
+ TimestampTz last_failed_timestamp; /* last archival failure time */
+ TimestampTz stat_reset_timestamp;
+} PgStat_ArchiverStats;
+
+/*
+ * Global statistics kept in the stats collector
+ */
+typedef struct PgStat_GlobalStats
+{
+ TimestampTz stats_timestamp; /* time of stats file update */
+ PgStat_Counter timed_checkpoints;
+ PgStat_Counter requested_checkpoints;
+ PgStat_Counter checkpoint_write_time; /* times in milliseconds */
+ PgStat_Counter checkpoint_sync_time;
+ PgStat_Counter buf_written_checkpoints;
+ PgStat_Counter buf_written_clean;
+ PgStat_Counter maxwritten_clean;
+ PgStat_Counter buf_written_backend;
+ PgStat_Counter buf_fsync_backend;
+ PgStat_Counter buf_alloc;
+ TimestampTz stat_reset_timestamp;
+} PgStat_GlobalStats;
+
+/*
+ * SLRU statistics kept in the stats collector
+ */
+typedef struct PgStat_SLRUStats
+{
+ PgStat_Counter blocks_zeroed;
+ PgStat_Counter blocks_hit;
+ PgStat_Counter blocks_read;
+ PgStat_Counter blocks_written;
+ PgStat_Counter blocks_exists;
+ PgStat_Counter flush;
+ PgStat_Counter truncate;
+ TimestampTz stat_reset_timestamp;
+} PgStat_SLRUStats;
+
+
+/* ----------
+ * Backend states
+ * ----------
+ */
+typedef enum BackendState
+{
+ STATE_UNDEFINED,
+ STATE_IDLE,
+ STATE_RUNNING,
+ STATE_IDLEINTRANSACTION,
+ STATE_FASTPATH,
+ STATE_IDLEINTRANSACTION_ABORTED,
+ STATE_DISABLED
+} BackendState;
+
+
+/* ----------
+ * Wait Classes
+ * ----------
+ */
+#define PG_WAIT_LWLOCK 0x01000000U
+#define PG_WAIT_LOCK 0x03000000U
+#define PG_WAIT_BUFFER_PIN 0x04000000U
+#define PG_WAIT_ACTIVITY 0x05000000U
+#define PG_WAIT_CLIENT 0x06000000U
+#define PG_WAIT_EXTENSION 0x07000000U
+#define PG_WAIT_IPC 0x08000000U
+#define PG_WAIT_TIMEOUT 0x09000000U
+#define PG_WAIT_IO 0x0A000000U
+
+/* ----------
+ * Wait Events - Activity
+ *
+ * Use this category when a process is waiting because it has no work to do,
+ * unless the "Client" or "Timeout" category describes the situation better.
+ * Typically, this should only be used for background processes.
+ * ----------
+ */
+typedef enum
+{
+ WAIT_EVENT_ARCHIVER_MAIN = PG_WAIT_ACTIVITY,
+ WAIT_EVENT_AUTOVACUUM_MAIN,
+ WAIT_EVENT_BGWRITER_HIBERNATE,
+ WAIT_EVENT_BGWRITER_MAIN,
+ WAIT_EVENT_CHECKPOINTER_MAIN,
+ WAIT_EVENT_LOGICAL_APPLY_MAIN,
+ WAIT_EVENT_LOGICAL_LAUNCHER_MAIN,
+ WAIT_EVENT_PGSTAT_MAIN,
+ WAIT_EVENT_RECOVERY_WAL_STREAM,
+ WAIT_EVENT_SYSLOGGER_MAIN,
+ WAIT_EVENT_WAL_RECEIVER_MAIN,
+ WAIT_EVENT_WAL_SENDER_MAIN,
+ WAIT_EVENT_WAL_WRITER_MAIN
+} WaitEventActivity;
+
+/* ----------
+ * Wait Events - Client
+ *
+ * Use this category when a process is waiting to send data to or receive data
+ * from the frontend process to which it is connected. This is never used for
+ * a background process, which has no client connection.
+ * ----------
+ */
+typedef enum
+{
+ WAIT_EVENT_CLIENT_READ = PG_WAIT_CLIENT,
+ WAIT_EVENT_CLIENT_WRITE,
+ WAIT_EVENT_GSS_OPEN_SERVER,
+ WAIT_EVENT_LIBPQWALRECEIVER_CONNECT,
+ WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE,
+ WAIT_EVENT_SSL_OPEN_SERVER,
+ WAIT_EVENT_WAL_RECEIVER_WAIT_START,
+ WAIT_EVENT_WAL_SENDER_WAIT_WAL,
+ WAIT_EVENT_WAL_SENDER_WRITE_DATA,
+} WaitEventClient;
+
+/* ----------
+ * Wait Events - IPC
+ *
+ * Use this category when a process cannot complete the work it is doing because
+ * it is waiting for a notification from another process.
+ * ----------
+ */
+typedef enum
+{
+ WAIT_EVENT_BACKUP_WAIT_WAL_ARCHIVE = PG_WAIT_IPC,
+ WAIT_EVENT_BGWORKER_SHUTDOWN,
+ WAIT_EVENT_BGWORKER_STARTUP,
+ WAIT_EVENT_BTREE_PAGE,
+ WAIT_EVENT_CHECKPOINT_DONE,
+ WAIT_EVENT_CHECKPOINT_START,
+ WAIT_EVENT_EXECUTE_GATHER,
+ WAIT_EVENT_HASH_BATCH_ALLOCATE,
+ WAIT_EVENT_HASH_BATCH_ELECT,
+ WAIT_EVENT_HASH_BATCH_LOAD,
+ WAIT_EVENT_HASH_BUILD_ALLOCATE,
+ WAIT_EVENT_HASH_BUILD_ELECT,
+ WAIT_EVENT_HASH_BUILD_HASH_INNER,
+ WAIT_EVENT_HASH_BUILD_HASH_OUTER,
+ WAIT_EVENT_HASH_GROW_BATCHES_ALLOCATE,
+ WAIT_EVENT_HASH_GROW_BATCHES_DECIDE,
+ WAIT_EVENT_HASH_GROW_BATCHES_ELECT,
+ WAIT_EVENT_HASH_GROW_BATCHES_FINISH,
+ WAIT_EVENT_HASH_GROW_BATCHES_REPARTITION,
+ WAIT_EVENT_HASH_GROW_BUCKETS_ALLOCATE,
+ WAIT_EVENT_HASH_GROW_BUCKETS_ELECT,
+ WAIT_EVENT_HASH_GROW_BUCKETS_REINSERT,
+ WAIT_EVENT_LOGICAL_SYNC_DATA,
+ WAIT_EVENT_LOGICAL_SYNC_STATE_CHANGE,
+ WAIT_EVENT_MQ_INTERNAL,
+ WAIT_EVENT_MQ_PUT_MESSAGE,
+ WAIT_EVENT_MQ_RECEIVE,
+ WAIT_EVENT_MQ_SEND,
+ WAIT_EVENT_PARALLEL_BITMAP_SCAN,
+ WAIT_EVENT_PARALLEL_CREATE_INDEX_SCAN,
+ WAIT_EVENT_PARALLEL_FINISH,
+ WAIT_EVENT_PROCARRAY_GROUP_UPDATE,
+ WAIT_EVENT_PROC_SIGNAL_BARRIER,
+ WAIT_EVENT_PROMOTE,
+ WAIT_EVENT_RECOVERY_CONFLICT_SNAPSHOT,
+ WAIT_EVENT_RECOVERY_CONFLICT_TABLESPACE,
+ WAIT_EVENT_RECOVERY_PAUSE,
+ WAIT_EVENT_REPLICATION_ORIGIN_DROP,
+ WAIT_EVENT_REPLICATION_SLOT_DROP,
+ WAIT_EVENT_SAFE_SNAPSHOT,
+ WAIT_EVENT_SYNC_REP,
+ WAIT_EVENT_XACT_GROUP_UPDATE
+} WaitEventIPC;
+
+/* ----------
+ * Wait Events - Timeout
+ *
+ * Use this category when a process is waiting for a timeout to expire.
+ * ----------
+ */
+typedef enum
+{
+ WAIT_EVENT_BASE_BACKUP_THROTTLE = PG_WAIT_TIMEOUT,
+ WAIT_EVENT_PG_SLEEP,
+ WAIT_EVENT_RECOVERY_APPLY_DELAY,
+ WAIT_EVENT_RECOVERY_RETRIEVE_RETRY_INTERVAL,
+ WAIT_EVENT_VACUUM_DELAY
+} WaitEventTimeout;
+
+/* ----------
+ * Wait Events - IO
+ *
+ * Use this category when a process is waiting for a IO.
+ * ----------
+ */
+typedef enum
+{
+ WAIT_EVENT_BUFFILE_READ = PG_WAIT_IO,
+ WAIT_EVENT_BUFFILE_WRITE,
+ WAIT_EVENT_CONTROL_FILE_READ,
+ WAIT_EVENT_CONTROL_FILE_SYNC,
+ WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE,
+ WAIT_EVENT_CONTROL_FILE_WRITE,
+ WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE,
+ WAIT_EVENT_COPY_FILE_READ,
+ WAIT_EVENT_COPY_FILE_WRITE,
+ WAIT_EVENT_DATA_FILE_EXTEND,
+ WAIT_EVENT_DATA_FILE_FLUSH,
+ WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC,
+ WAIT_EVENT_DATA_FILE_PREFETCH,
+ WAIT_EVENT_DATA_FILE_READ,
+ WAIT_EVENT_DATA_FILE_SYNC,
+ WAIT_EVENT_DATA_FILE_TRUNCATE,
+ WAIT_EVENT_DATA_FILE_WRITE,
+ WAIT_EVENT_DSM_FILL_ZERO_WRITE,
+ WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ,
+ WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC,
+ WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE,
+ WAIT_EVENT_LOCK_FILE_CREATE_READ,
+ WAIT_EVENT_LOCK_FILE_CREATE_SYNC,
+ WAIT_EVENT_LOCK_FILE_CREATE_WRITE,
+ WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ,
+ WAIT_EVENT_LOGICAL_REWRITE_CHECKPOINT_SYNC,
+ WAIT_EVENT_LOGICAL_REWRITE_MAPPING_SYNC,
+ WAIT_EVENT_LOGICAL_REWRITE_MAPPING_WRITE,
+ WAIT_EVENT_LOGICAL_REWRITE_SYNC,
+ WAIT_EVENT_LOGICAL_REWRITE_TRUNCATE,
+ WAIT_EVENT_LOGICAL_REWRITE_WRITE,
+ WAIT_EVENT_RELATION_MAP_READ,
+ WAIT_EVENT_RELATION_MAP_SYNC,
+ WAIT_EVENT_RELATION_MAP_WRITE,
+ WAIT_EVENT_REORDER_BUFFER_READ,
+ WAIT_EVENT_REORDER_BUFFER_WRITE,
+ WAIT_EVENT_REORDER_LOGICAL_MAPPING_READ,
+ WAIT_EVENT_REPLICATION_SLOT_READ,
+ WAIT_EVENT_REPLICATION_SLOT_RESTORE_SYNC,
+ WAIT_EVENT_REPLICATION_SLOT_SYNC,
+ WAIT_EVENT_REPLICATION_SLOT_WRITE,
+ WAIT_EVENT_SLRU_FLUSH_SYNC,
+ WAIT_EVENT_SLRU_READ,
+ WAIT_EVENT_SLRU_SYNC,
+ WAIT_EVENT_SLRU_WRITE,
+ WAIT_EVENT_SNAPBUILD_READ,
+ WAIT_EVENT_SNAPBUILD_SYNC,
+ WAIT_EVENT_SNAPBUILD_WRITE,
+ WAIT_EVENT_TIMELINE_HISTORY_FILE_SYNC,
+ WAIT_EVENT_TIMELINE_HISTORY_FILE_WRITE,
+ WAIT_EVENT_TIMELINE_HISTORY_READ,
+ WAIT_EVENT_TIMELINE_HISTORY_SYNC,
+ WAIT_EVENT_TIMELINE_HISTORY_WRITE,
+ WAIT_EVENT_TWOPHASE_FILE_READ,
+ WAIT_EVENT_TWOPHASE_FILE_SYNC,
+ WAIT_EVENT_TWOPHASE_FILE_WRITE,
+ WAIT_EVENT_WALSENDER_TIMELINE_HISTORY_READ,
+ WAIT_EVENT_WAL_BOOTSTRAP_SYNC,
+ WAIT_EVENT_WAL_BOOTSTRAP_WRITE,
+ WAIT_EVENT_WAL_COPY_READ,
+ WAIT_EVENT_WAL_COPY_SYNC,
+ WAIT_EVENT_WAL_COPY_WRITE,
+ WAIT_EVENT_WAL_INIT_SYNC,
+ WAIT_EVENT_WAL_INIT_WRITE,
+ WAIT_EVENT_WAL_READ,
+ WAIT_EVENT_WAL_SYNC,
+ WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN,
+ WAIT_EVENT_WAL_WRITE
+} WaitEventIO;
+
+/* ----------
+ * Command type for progress reporting purposes
+ * ----------
+ */
+typedef enum ProgressCommandType
+{
+ PROGRESS_COMMAND_INVALID,
+ PROGRESS_COMMAND_VACUUM,
+ PROGRESS_COMMAND_ANALYZE,
+ PROGRESS_COMMAND_CLUSTER,
+ PROGRESS_COMMAND_CREATE_INDEX,
+ PROGRESS_COMMAND_BASEBACKUP
+} ProgressCommandType;
+
+#define PGSTAT_NUM_PROGRESS_PARAM 20
+
+/* ----------
+ * Shared-memory data structures
+ * ----------
+ */
+
+
+/*
+ * PgBackendSSLStatus
+ *
+ * For each backend, we keep the SSL status in a separate struct, that
+ * is only filled in if SSL is enabled.
+ *
+ * All char arrays must be null-terminated.
+ */
+typedef struct PgBackendSSLStatus
+{
+ /* Information about SSL connection */
+ int ssl_bits;
+ bool ssl_compression;
+ char ssl_version[NAMEDATALEN];
+ char ssl_cipher[NAMEDATALEN];
+ char ssl_client_dn[NAMEDATALEN];
+
+ /*
+ * serial number is max "20 octets" per RFC 5280, so this size should be
+ * fine
+ */
+ char ssl_client_serial[NAMEDATALEN];
+
+ char ssl_issuer_dn[NAMEDATALEN];
+} PgBackendSSLStatus;
+
+/*
+ * PgBackendGSSStatus
+ *
+ * For each backend, we keep the GSS status in a separate struct, that
+ * is only filled in if GSS is enabled.
+ *
+ * All char arrays must be null-terminated.
+ */
+typedef struct PgBackendGSSStatus
+{
+ /* Information about GSSAPI connection */
+ char gss_princ[NAMEDATALEN]; /* GSSAPI Principal used to auth */
+ bool gss_auth; /* If GSSAPI authentication was used */
+ bool gss_enc; /* If encryption is being used */
+
+} PgBackendGSSStatus;
+
+
+/* ----------
+ * PgBackendStatus
+ *
+ * Each live backend maintains a PgBackendStatus struct in shared memory
+ * showing its current activity. (The structs are allocated according to
+ * BackendId, but that is not critical.) Note that the collector process
+ * has no involvement in, or even access to, these structs.
+ *
+ * Each auxiliary process also maintains a PgBackendStatus struct in shared
+ * memory.
+ * ----------
+ */
+typedef struct PgBackendStatus
+{
+ /*
+ * To avoid locking overhead, we use the following protocol: a backend
+ * increments st_changecount before modifying its entry, and again after
+ * finishing a modification. A would-be reader should note the value of
+ * st_changecount, copy the entry into private memory, then check
+ * st_changecount again. If the value hasn't changed, and if it's even,
+ * the copy is valid; otherwise start over. This makes updates cheap
+ * while reads are potentially expensive, but that's the tradeoff we want.
+ *
+ * The above protocol needs memory barriers to ensure that the apparent
+ * order of execution is as it desires. Otherwise, for example, the CPU
+ * might rearrange the code so that st_changecount is incremented twice
+ * before the modification on a machine with weak memory ordering. Hence,
+ * use the macros defined below for manipulating st_changecount, rather
+ * than touching it directly.
+ */
+ int st_changecount;
+
+ /* The entry is valid iff st_procpid > 0, unused if st_procpid == 0 */
+ int st_procpid;
+
+ /* Type of backends */
+ BackendType st_backendType;
+
+ /* Times when current backend, transaction, and activity started */
+ TimestampTz st_proc_start_timestamp;
+ TimestampTz st_xact_start_timestamp;
+ TimestampTz st_activity_start_timestamp;
+ TimestampTz st_state_start_timestamp;
+
+ /* Database OID, owning user's OID, connection client address */
+ Oid st_databaseid;
+ Oid st_userid;
+ SockAddr st_clientaddr;
+ char *st_clienthostname; /* MUST be null-terminated */
+
+ /* Information about SSL connection */
+ bool st_ssl;
+ PgBackendSSLStatus *st_sslstatus;
+
+ /* Information about GSSAPI connection */
+ bool st_gss;
+ PgBackendGSSStatus *st_gssstatus;
+
+ /* current state */
+ BackendState st_state;
+
+ /* application name; MUST be null-terminated */
+ char *st_appname;
+
+ /*
+ * Current command string; MUST be null-terminated. Note that this string
+ * possibly is truncated in the middle of a multi-byte character. As
+ * activity strings are stored more frequently than read, that allows to
+ * move the cost of correct truncation to the display side. Use
+ * pgstat_clip_activity() to truncate correctly.
+ */
+ char *st_activity_raw;
+
+ /*
+ * Command progress reporting. Any command which wishes can advertise
+ * that it is running by setting st_progress_command,
+ * st_progress_command_target, and st_progress_param[].
+ * st_progress_command_target should be the OID of the relation which the
+ * command targets (we assume there's just one, as this is meant for
+ * utility commands), but the meaning of each element in the
+ * st_progress_param array is command-specific.
+ */
+ ProgressCommandType st_progress_command;
+ Oid st_progress_command_target;
+ int64 st_progress_param[PGSTAT_NUM_PROGRESS_PARAM];
+} PgBackendStatus;
+
+/*
+ * Macros to load and store st_changecount with appropriate memory barriers.
+ *
+ * Use PGSTAT_BEGIN_WRITE_ACTIVITY() before, and PGSTAT_END_WRITE_ACTIVITY()
+ * after, modifying the current process's PgBackendStatus data. Note that,
+ * since there is no mechanism for cleaning up st_changecount after an error,
+ * THESE MACROS FORM A CRITICAL SECTION. Any error between them will be
+ * promoted to PANIC, causing a database restart to clean up shared memory!
+ * Hence, keep the critical section as short and straight-line as possible.
+ * Aside from being safer, that minimizes the window in which readers will
+ * have to loop.
+ *
+ * Reader logic should follow this sketch:
+ *
+ * for (;;)
+ * {
+ * int before_ct, after_ct;
+ *
+ * pgstat_begin_read_activity(beentry, before_ct);
+ * ... copy beentry data to local memory ...
+ * pgstat_end_read_activity(beentry, after_ct);
+ * if (pgstat_read_activity_complete(before_ct, after_ct))
+ * break;
+ * CHECK_FOR_INTERRUPTS();
+ * }
+ *
+ * For extra safety, we generally use volatile beentry pointers, although
+ * the memory barriers should theoretically be sufficient.
+ */
+#define PGSTAT_BEGIN_WRITE_ACTIVITY(beentry) \
+ do { \
+ START_CRIT_SECTION(); \
+ (beentry)->st_changecount++; \
+ pg_write_barrier(); \
+ } while (0)
+
+#define PGSTAT_END_WRITE_ACTIVITY(beentry) \
+ do { \
+ pg_write_barrier(); \
+ (beentry)->st_changecount++; \
+ Assert(((beentry)->st_changecount & 1) == 0); \
+ END_CRIT_SECTION(); \
+ } while (0)
+
+#define pgstat_begin_read_activity(beentry, before_changecount) \
+ do { \
+ (before_changecount) = (beentry)->st_changecount; \
+ pg_read_barrier(); \
+ } while (0)
+
+#define pgstat_end_read_activity(beentry, after_changecount) \
+ do { \
+ pg_read_barrier(); \
+ (after_changecount) = (beentry)->st_changecount; \
+ } while (0)
+
+#define pgstat_read_activity_complete(before_changecount, after_changecount) \
+ ((before_changecount) == (after_changecount) && \
+ ((before_changecount) & 1) == 0)
+
+
+/* ----------
+ * LocalPgBackendStatus
+ *
+ * When we build the backend status array, we use LocalPgBackendStatus to be
+ * able to add new values to the struct when needed without adding new fields
+ * to the shared memory. It contains the backend status as a first member.
+ * ----------
+ */
+typedef struct LocalPgBackendStatus
+{
+ /*
+ * Local version of the backend status entry.
+ */
+ PgBackendStatus backendStatus;
+
+ /*
+ * The xid of the current transaction if available, InvalidTransactionId
+ * if not.
+ */
+ TransactionId backend_xid;
+
+ /*
+ * The xmin of the current session if available, InvalidTransactionId if
+ * not.
+ */
+ TransactionId backend_xmin;
+} LocalPgBackendStatus;
+
+/*
+ * Working state needed to accumulate per-function-call timing statistics.
+ */
+typedef struct PgStat_FunctionCallUsage
+{
+ /* Link to function's hashtable entry (must still be there at exit!) */
+ /* NULL means we are not tracking the current function call */
+ PgStat_FunctionCounts *fs;
+ /* Total time previously charged to function, as of function start */
+ instr_time save_f_total_time;
+ /* Backend-wide total time as of function start */
+ instr_time save_total;
+ /* system clock as of function start */
+ instr_time f_start;
+} PgStat_FunctionCallUsage;
+
+
+/* ----------
+ * GUC parameters
+ * ----------
+ */
+extern PGDLLIMPORT bool pgstat_track_activities;
+extern PGDLLIMPORT bool pgstat_track_counts;
+extern PGDLLIMPORT int pgstat_track_functions;
+extern PGDLLIMPORT int pgstat_track_activity_query_size;
+extern char *pgstat_stat_directory;
+extern char *pgstat_stat_tmpname;
+extern char *pgstat_stat_filename;
+
+/*
+ * BgWriter statistics counters are updated directly by bgwriter and bufmgr
+ */
+extern PgStat_MsgBgWriter BgWriterStats;
+
+/*
+ * Updated by pgstat_count_buffer_*_time macros
+ */
+extern PgStat_Counter pgStatBlockReadTime;
+extern PgStat_Counter pgStatBlockWriteTime;
+
+/* ----------
+ * Functions called from postmaster
+ * ----------
+ */
+extern Size BackendStatusShmemSize(void);
+extern void CreateSharedBackendStatus(void);
+
+extern void pgstat_init(void);
+extern int pgstat_start(void);
+extern void pgstat_reset_all(void);
+extern void allow_immediate_pgstat_restart(void);
+
+#ifdef EXEC_BACKEND
+extern void PgstatCollectorMain(int argc, char *argv[]) pg_attribute_noreturn();
+#endif
+
+
+/* ----------
+ * Functions called from backends
+ * ----------
+ */
+extern void pgstat_ping(void);
+
+extern void pgstat_report_stat(bool force);
+extern void pgstat_vacuum_stat(void);
+extern void pgstat_drop_database(Oid databaseid);
+
+extern void pgstat_clear_snapshot(void);
+extern void pgstat_reset_counters(void);
+extern void pgstat_reset_shared_counters(const char *);
+extern void pgstat_reset_single_counter(Oid objectid, PgStat_Single_Reset_Type type);
+extern void pgstat_reset_slru_counter(const char *);
+
+extern void pgstat_report_autovac(Oid dboid);
+extern void pgstat_report_vacuum(Oid tableoid, bool shared,
+ PgStat_Counter livetuples, PgStat_Counter deadtuples);
+extern void pgstat_report_analyze(Relation rel,
+ PgStat_Counter livetuples, PgStat_Counter deadtuples,
+ bool resetcounter);
+
+extern void pgstat_report_recovery_conflict(int reason);
+extern void pgstat_report_deadlock(void);
+extern void pgstat_report_checksum_failures_in_db(Oid dboid, int failurecount);
+extern void pgstat_report_checksum_failure(void);
+
+extern void pgstat_initialize(void);
+extern void pgstat_bestart(void);
+
+extern void pgstat_report_activity(BackendState state, const char *cmd_str);
+extern void pgstat_report_tempfile(size_t filesize);
+extern void pgstat_report_appname(const char *appname);
+extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
+extern const char *pgstat_get_wait_event(uint32 wait_event_info);
+extern const char *pgstat_get_wait_event_type(uint32 wait_event_info);
+extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
+extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
+ int buflen);
+
+extern void pgstat_progress_start_command(ProgressCommandType cmdtype,
+ Oid relid);
+extern void pgstat_progress_update_param(int index, int64 val);
+extern void pgstat_progress_update_multi_param(int nparam, const int *index,
+ const int64 *val);
+extern void pgstat_progress_end_command(void);
+
+extern PgStat_TableStatus *find_tabstat_entry(Oid rel_id);
+extern PgStat_BackendFunctionEntry *find_funcstat_entry(Oid func_id);
+
+extern void pgstat_initstats(Relation rel);
+
+extern char *pgstat_clip_activity(const char *raw_activity);
+
+/* ----------
+ * pgstat_report_wait_start() -
+ *
+ * Called from places where server process needs to wait. This is called
+ * to report wait event information. The wait information is stored
+ * as 4-bytes where first byte represents the wait event class (type of
+ * wait, for different types of wait, refer WaitClass) and the next
+ * 3-bytes represent the actual wait event. Currently 2-bytes are used
+ * for wait event which is sufficient for current usage, 1-byte is
+ * reserved for future usage.
+ *
+ * NB: this *must* be able to survive being called before MyProc has been
+ * initialized.
+ * ----------
+ */
+static inline void
+pgstat_report_wait_start(uint32 wait_event_info)
+{
+ volatile PGPROC *proc = MyProc;
+
+ if (!pgstat_track_activities || !proc)
+ return;
+
+ /*
+ * Since this is a four-byte field which is always read and written as
+ * four-bytes, updates are atomic.
+ */
+ proc->wait_event_info = wait_event_info;
+}
+
+/* ----------
+ * pgstat_report_wait_end() -
+ *
+ * Called to report end of a wait.
+ *
+ * NB: this *must* be able to survive being called before MyProc has been
+ * initialized.
+ * ----------
+ */
+static inline void
+pgstat_report_wait_end(void)
+{
+ volatile PGPROC *proc = MyProc;
+
+ if (!pgstat_track_activities || !proc)
+ return;
+
+ /*
+ * Since this is a four-byte field which is always read and written as
+ * four-bytes, updates are atomic.
+ */
+ proc->wait_event_info = 0;
+}
+
+/* nontransactional event counts are simple enough to inline */
+
+#define pgstat_count_heap_scan(rel) \
+ do { \
+ if ((rel)->pgstat_info != NULL) \
+ (rel)->pgstat_info->t_counts.t_numscans++; \
+ } while (0)
+#define pgstat_count_heap_getnext(rel) \
+ do { \
+ if ((rel)->pgstat_info != NULL) \
+ (rel)->pgstat_info->t_counts.t_tuples_returned++; \
+ } while (0)
+#define pgstat_count_heap_fetch(rel) \
+ do { \
+ if ((rel)->pgstat_info != NULL) \
+ (rel)->pgstat_info->t_counts.t_tuples_fetched++; \
+ } while (0)
+#define pgstat_count_index_scan(rel) \
+ do { \
+ if ((rel)->pgstat_info != NULL) \
+ (rel)->pgstat_info->t_counts.t_numscans++; \
+ } while (0)
+#define pgstat_count_index_tuples(rel, n) \
+ do { \
+ if ((rel)->pgstat_info != NULL) \
+ (rel)->pgstat_info->t_counts.t_tuples_returned += (n); \
+ } while (0)
+#define pgstat_count_buffer_read(rel) \
+ do { \
+ if ((rel)->pgstat_info != NULL) \
+ (rel)->pgstat_info->t_counts.t_blocks_fetched++; \
+ } while (0)
+#define pgstat_count_buffer_hit(rel) \
+ do { \
+ if ((rel)->pgstat_info != NULL) \
+ (rel)->pgstat_info->t_counts.t_blocks_hit++; \
+ } while (0)
+#define pgstat_count_buffer_read_time(n) \
+ (pgStatBlockReadTime += (n))
+#define pgstat_count_buffer_write_time(n) \
+ (pgStatBlockWriteTime += (n))
+
+extern void pgstat_count_heap_insert(Relation rel, PgStat_Counter n);
+extern void pgstat_count_heap_update(Relation rel, bool hot);
+extern void pgstat_count_heap_delete(Relation rel);
+extern void pgstat_count_truncate(Relation rel);
+extern void pgstat_update_heap_dead_tuples(Relation rel, int delta);
+
+struct FunctionCallInfoBaseData;
+extern void pgstat_init_function_usage(struct FunctionCallInfoBaseData *fcinfo,
+ PgStat_FunctionCallUsage *fcu);
+extern void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu,
+ bool finalize);
+
+extern void AtEOXact_PgStat(bool isCommit, bool parallel);
+extern void AtEOSubXact_PgStat(bool isCommit, int nestDepth);
+
+extern void AtPrepare_PgStat(void);
+extern void PostPrepare_PgStat(void);
+
+extern void pgstat_twophase_postcommit(TransactionId xid, uint16 info,
+ void *recdata, uint32 len);
+extern void pgstat_twophase_postabort(TransactionId xid, uint16 info,
+ void *recdata, uint32 len);
+
+extern void pgstat_send_archiver(const char *xlog, bool failed);
+extern void pgstat_send_bgwriter(void);
+
+/* ----------
+ * Support functions for the SQL-callable functions to
+ * generate the pgstat* views.
+ * ----------
+ */
+extern PgStat_StatDBEntry *pgstat_fetch_stat_dbentry(Oid dbid);
+extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid);
+extern PgBackendStatus *pgstat_fetch_stat_beentry(int beid);
+extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
+extern PgStat_StatFuncEntry *pgstat_fetch_stat_funcentry(Oid funcid);
+extern int pgstat_fetch_stat_numbackends(void);
+extern PgStat_ArchiverStats *pgstat_fetch_stat_archiver(void);
+extern PgStat_GlobalStats *pgstat_fetch_global(void);
+extern PgStat_SLRUStats *pgstat_fetch_slru(void);
+
+extern void pgstat_count_slru_page_zeroed(int slru_idx);
+extern void pgstat_count_slru_page_hit(int slru_idx);
+extern void pgstat_count_slru_page_read(int slru_idx);
+extern void pgstat_count_slru_page_written(int slru_idx);
+extern void pgstat_count_slru_page_exists(int slru_idx);
+extern void pgstat_count_slru_flush(int slru_idx);
+extern void pgstat_count_slru_truncate(int slru_idx);
+extern const char *pgstat_slru_name(int slru_idx);
+extern int pgstat_slru_index(const char *name);
+
+#endif /* PGSTAT_H */
diff --git a/src/include/pgtar.h b/src/include/pgtar.h
new file mode 100644
index 0000000..0a87590
--- /dev/null
+++ b/src/include/pgtar.h
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgtar.h
+ * Functions for manipulating tarfile datastructures (src/port/tar.c)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/pgtar.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+enum tarError
+{
+ TAR_OK = 0,
+ TAR_NAME_TOO_LONG,
+ TAR_SYMLINK_TOO_LONG
+};
+
+extern enum tarError tarCreateHeader(char *h, const char *filename, const char *linktarget,
+ pgoff_t size, mode_t mode, uid_t uid, gid_t gid, time_t mtime);
+extern uint64 read_tar_number(const char *s, int len);
+extern void print_tar_number(char *s, int len, uint64 val);
+extern int tarChecksum(char *header);
diff --git a/src/include/pgtime.h b/src/include/pgtime.h
new file mode 100644
index 0000000..0fc76d0
--- /dev/null
+++ b/src/include/pgtime.h
@@ -0,0 +1,84 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgtime.h
+ * PostgreSQL internal timezone library
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/pgtime.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _PGTIME_H
+#define _PGTIME_H
+
+
+/*
+ * The API of this library is generally similar to the corresponding
+ * C library functions, except that we use pg_time_t which (we hope) is
+ * 64 bits wide, and which is most definitely signed not unsigned.
+ */
+
+typedef int64 pg_time_t;
+
+struct pg_tm
+{
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon; /* origin 1, not 0! */
+ int tm_year; /* relative to 1900 */
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+ long int tm_gmtoff;
+ const char *tm_zone;
+};
+
+typedef struct pg_tz pg_tz;
+typedef struct pg_tzenum pg_tzenum;
+
+/* Maximum length of a timezone name (not including trailing null) */
+#define TZ_STRLEN_MAX 255
+
+/* these functions are in localtime.c */
+
+extern struct pg_tm *pg_localtime(const pg_time_t *timep, const pg_tz *tz);
+extern struct pg_tm *pg_gmtime(const pg_time_t *timep);
+extern int pg_next_dst_boundary(const pg_time_t *timep,
+ long int *before_gmtoff,
+ int *before_isdst,
+ pg_time_t *boundary,
+ long int *after_gmtoff,
+ int *after_isdst,
+ const pg_tz *tz);
+extern bool pg_interpret_timezone_abbrev(const char *abbrev,
+ const pg_time_t *timep,
+ long int *gmtoff,
+ int *isdst,
+ const pg_tz *tz);
+extern bool pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff);
+extern const char *pg_get_timezone_name(pg_tz *tz);
+extern bool pg_tz_acceptable(pg_tz *tz);
+
+/* these functions are in strftime.c */
+
+extern size_t pg_strftime(char *s, size_t max, const char *format,
+ const struct pg_tm *tm);
+
+/* these functions and variables are in pgtz.c */
+
+extern PGDLLIMPORT pg_tz *session_timezone;
+extern pg_tz *log_timezone;
+
+extern void pg_timezone_initialize(void);
+extern pg_tz *pg_tzset(const char *tzname);
+extern pg_tz *pg_tzset_offset(long gmtoffset);
+
+extern pg_tzenum *pg_tzenumerate_start(void);
+extern pg_tz *pg_tzenumerate_next(pg_tzenum *dir);
+extern void pg_tzenumerate_end(pg_tzenum *dir);
+
+#endif /* _PGTIME_H */
diff --git a/src/include/port.h b/src/include/port.h
new file mode 100644
index 0000000..d4c94a4
--- /dev/null
+++ b/src/include/port.h
@@ -0,0 +1,528 @@
+/*-------------------------------------------------------------------------
+ *
+ * port.h
+ * Header for src/port/ compatibility functions.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/port.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_PORT_H
+#define PG_PORT_H
+
+#include <ctype.h>
+#include <netdb.h>
+#include <pwd.h>
+
+/*
+ * Windows has enough specialized port stuff that we push most of it off
+ * into another file.
+ * Note: Some CYGWIN includes might #define WIN32.
+ */
+#if defined(WIN32) && !defined(__CYGWIN__)
+#include "port/win32_port.h"
+#endif
+
+/* socket has a different definition on WIN32 */
+#ifndef WIN32
+typedef int pgsocket;
+
+#define PGINVALID_SOCKET (-1)
+#else
+typedef SOCKET pgsocket;
+
+#define PGINVALID_SOCKET INVALID_SOCKET
+#endif
+
+/* non-blocking */
+extern bool pg_set_noblock(pgsocket sock);
+extern bool pg_set_block(pgsocket sock);
+
+/* Portable path handling for Unix/Win32 (in path.c) */
+
+extern bool has_drive_prefix(const char *filename);
+extern char *first_dir_separator(const char *filename);
+extern char *last_dir_separator(const char *filename);
+extern char *first_path_var_separator(const char *pathlist);
+extern void join_path_components(char *ret_path,
+ const char *head, const char *tail);
+extern void canonicalize_path(char *path);
+extern void make_native_path(char *path);
+extern void cleanup_path(char *path);
+extern bool path_contains_parent_reference(const char *path);
+extern bool path_is_relative_and_below_cwd(const char *path);
+extern bool path_is_prefix_of_path(const char *path1, const char *path2);
+extern char *make_absolute_path(const char *path);
+extern const char *get_progname(const char *argv0);
+extern void get_share_path(const char *my_exec_path, char *ret_path);
+extern void get_etc_path(const char *my_exec_path, char *ret_path);
+extern void get_include_path(const char *my_exec_path, char *ret_path);
+extern void get_pkginclude_path(const char *my_exec_path, char *ret_path);
+extern void get_includeserver_path(const char *my_exec_path, char *ret_path);
+extern void get_lib_path(const char *my_exec_path, char *ret_path);
+extern void get_pkglib_path(const char *my_exec_path, char *ret_path);
+extern void get_locale_path(const char *my_exec_path, char *ret_path);
+extern void get_doc_path(const char *my_exec_path, char *ret_path);
+extern void get_html_path(const char *my_exec_path, char *ret_path);
+extern void get_man_path(const char *my_exec_path, char *ret_path);
+extern bool get_home_path(char *ret_path);
+extern void get_parent_directory(char *path);
+
+/* common/pgfnames.c */
+extern char **pgfnames(const char *path);
+extern void pgfnames_cleanup(char **filenames);
+
+/*
+ * is_absolute_path
+ *
+ * By making this a macro we avoid needing to include path.c in libpq.
+ */
+#ifndef WIN32
+#define IS_DIR_SEP(ch) ((ch) == '/')
+
+#define is_absolute_path(filename) \
+( \
+ IS_DIR_SEP((filename)[0]) \
+)
+#else
+#define IS_DIR_SEP(ch) ((ch) == '/' || (ch) == '\\')
+
+/* See path_is_relative_and_below_cwd() for how we handle 'E:abc'. */
+#define is_absolute_path(filename) \
+( \
+ IS_DIR_SEP((filename)[0]) || \
+ (isalpha((unsigned char) ((filename)[0])) && (filename)[1] == ':' && \
+ IS_DIR_SEP((filename)[2])) \
+)
+#endif
+
+/* Portable locale initialization (in exec.c) */
+extern void set_pglocale_pgservice(const char *argv0, const char *app);
+
+/* Portable way to find and execute binaries (in exec.c) */
+extern int find_my_exec(const char *argv0, char *retpath);
+extern int find_other_exec(const char *argv0, const char *target,
+ const char *versionstr, char *retpath);
+extern char *pipe_read_line(char *cmd, char *line, int maxsize);
+
+/* Doesn't belong here, but this is used with find_other_exec(), so... */
+#define PG_BACKEND_VERSIONSTR "postgres (PostgreSQL) " PG_VERSION "\n"
+
+
+#if defined(WIN32) || defined(__CYGWIN__)
+#define EXE ".exe"
+#else
+#define EXE ""
+#endif
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+#define DEVNULL "nul"
+#else
+#define DEVNULL "/dev/null"
+#endif
+
+/* Portable delay handling */
+extern void pg_usleep(long microsec);
+
+/* Portable SQL-like case-independent comparisons and conversions */
+extern int pg_strcasecmp(const char *s1, const char *s2);
+extern int pg_strncasecmp(const char *s1, const char *s2, size_t n);
+extern unsigned char pg_toupper(unsigned char ch);
+extern unsigned char pg_tolower(unsigned char ch);
+extern unsigned char pg_ascii_toupper(unsigned char ch);
+extern unsigned char pg_ascii_tolower(unsigned char ch);
+
+/*
+ * Beginning in v12, we always replace snprintf() and friends with our own
+ * implementation. This symbol is no longer consulted by the core code,
+ * but keep it defined anyway in case any extensions are looking at it.
+ */
+#define USE_REPL_SNPRINTF 1
+
+/*
+ * Versions of libintl >= 0.13 try to replace printf() and friends with
+ * macros to their own versions that understand the %$ format. We do the
+ * same, so disable their macros, if they exist.
+ */
+#ifdef vsnprintf
+#undef vsnprintf
+#endif
+#ifdef snprintf
+#undef snprintf
+#endif
+#ifdef vsprintf
+#undef vsprintf
+#endif
+#ifdef sprintf
+#undef sprintf
+#endif
+#ifdef vfprintf
+#undef vfprintf
+#endif
+#ifdef fprintf
+#undef fprintf
+#endif
+#ifdef vprintf
+#undef vprintf
+#endif
+#ifdef printf
+#undef printf
+#endif
+
+extern int pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args);
+extern int pg_snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3, 4);
+extern int pg_vsprintf(char *str, const char *fmt, va_list args);
+extern int pg_sprintf(char *str, const char *fmt,...) pg_attribute_printf(2, 3);
+extern int pg_vfprintf(FILE *stream, const char *fmt, va_list args);
+extern int pg_fprintf(FILE *stream, const char *fmt,...) pg_attribute_printf(2, 3);
+extern int pg_vprintf(const char *fmt, va_list args);
+extern int pg_printf(const char *fmt,...) pg_attribute_printf(1, 2);
+
+/*
+ * We use __VA_ARGS__ for printf to prevent replacing references to
+ * the "printf" format archetype in format() attribute declarations.
+ * That unfortunately means that taking a function pointer to printf
+ * will not do what we'd wish. (If you need to do that, you must name
+ * pg_printf explicitly.) For printf's sibling functions, use
+ * parameterless macros so that function pointers will work unsurprisingly.
+ */
+#define vsnprintf pg_vsnprintf
+#define snprintf pg_snprintf
+#define vsprintf pg_vsprintf
+#define sprintf pg_sprintf
+#define vfprintf pg_vfprintf
+#define fprintf pg_fprintf
+#define vprintf pg_vprintf
+#define printf(...) pg_printf(__VA_ARGS__)
+
+/* This is also provided by snprintf.c */
+extern int pg_strfromd(char *str, size_t count, int precision, double value);
+
+/* Replace strerror() with our own, somewhat more robust wrapper */
+extern char *pg_strerror(int errnum);
+#define strerror pg_strerror
+
+/* Likewise for strerror_r(); note we prefer the GNU API for that */
+extern char *pg_strerror_r(int errnum, char *buf, size_t buflen);
+#define strerror_r pg_strerror_r
+#define PG_STRERROR_R_BUFLEN 256 /* Recommended buffer size for strerror_r */
+
+/* Wrap strsignal(), or provide our own version if necessary */
+extern const char *pg_strsignal(int signum);
+
+/* Portable prompt handling */
+extern void simple_prompt(const char *prompt, char *destination, size_t destlen,
+ bool echo);
+
+extern int pclose_check(FILE *stream);
+
+/* Global variable holding time zone information. */
+#if defined(WIN32) || defined(__CYGWIN__)
+#define TIMEZONE_GLOBAL _timezone
+#define TZNAME_GLOBAL _tzname
+#else
+#define TIMEZONE_GLOBAL timezone
+#define TZNAME_GLOBAL tzname
+#endif
+
+#if defined(WIN32) || defined(__CYGWIN__)
+/*
+ * Win32 doesn't have reliable rename/unlink during concurrent access.
+ */
+extern int pgrename(const char *from, const char *to);
+extern int pgunlink(const char *path);
+
+/* Include this first so later includes don't see these defines */
+#ifdef _MSC_VER
+#include <io.h>
+#endif
+
+#define rename(from, to) pgrename(from, to)
+#define unlink(path) pgunlink(path)
+#endif /* defined(WIN32) || defined(__CYGWIN__) */
+
+/*
+ * Win32 also doesn't have symlinks, but we can emulate them with
+ * junction points on newer Win32 versions.
+ *
+ * Cygwin has its own symlinks which work on Win95/98/ME where
+ * junction points don't, so use those instead. We have no way of
+ * knowing what type of system Cygwin binaries will be run on.
+ * Note: Some CYGWIN includes might #define WIN32.
+ */
+#if defined(WIN32) && !defined(__CYGWIN__)
+extern int pgsymlink(const char *oldpath, const char *newpath);
+extern int pgreadlink(const char *path, char *buf, size_t size);
+extern bool pgwin32_is_junction(const char *path);
+
+#define symlink(oldpath, newpath) pgsymlink(oldpath, newpath)
+#define readlink(path, buf, size) pgreadlink(path, buf, size)
+#endif
+
+extern bool rmtree(const char *path, bool rmtopdir);
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+
+/*
+ * open() and fopen() replacements to allow deletion of open files and
+ * passing of other special options.
+ */
+#define O_DIRECT 0x80000000
+extern int pgwin32_open(const char *, int,...);
+extern FILE *pgwin32_fopen(const char *, const char *);
+#define open(a,b,c) pgwin32_open(a,b,c)
+#define fopen(a,b) pgwin32_fopen(a,b)
+
+/*
+ * Mingw-w64 headers #define popen and pclose to _popen and _pclose. We want
+ * to use our popen wrapper, rather than plain _popen, so override that. For
+ * consistency, use our version of pclose, too.
+ */
+#ifdef popen
+#undef popen
+#endif
+#ifdef pclose
+#undef pclose
+#endif
+
+/*
+ * system() and popen() replacements to enclose the command in an extra
+ * pair of quotes.
+ */
+extern int pgwin32_system(const char *command);
+extern FILE *pgwin32_popen(const char *command, const char *type);
+
+#define system(a) pgwin32_system(a)
+#define popen(a,b) pgwin32_popen(a,b)
+#define pclose(a) _pclose(a)
+
+/* New versions of MingW have gettimeofday, old mingw and msvc don't */
+#ifndef HAVE_GETTIMEOFDAY
+/* Last parameter not used */
+extern int gettimeofday(struct timeval *tp, struct timezone *tzp);
+#endif
+#else /* !WIN32 */
+
+/*
+ * Win32 requires a special close for sockets and pipes, while on Unix
+ * close() does them all.
+ */
+#define closesocket close
+#endif /* WIN32 */
+
+/*
+ * On Windows, setvbuf() does not support _IOLBF mode, and interprets that
+ * as _IOFBF. To add insult to injury, setvbuf(file, NULL, _IOFBF, 0)
+ * crashes outright if "parameter validation" is enabled. Therefore, in
+ * places where we'd like to select line-buffered mode, we fall back to
+ * unbuffered mode instead on Windows. Always use PG_IOLBF not _IOLBF
+ * directly in order to implement this behavior.
+ */
+#ifndef WIN32
+#define PG_IOLBF _IOLBF
+#else
+#define PG_IOLBF _IONBF
+#endif
+
+/*
+ * Default "extern" declarations or macro substitutes for library routines.
+ * When necessary, these routines are provided by files in src/port/.
+ */
+
+/* Type to use with fseeko/ftello */
+#ifndef WIN32 /* WIN32 is handled in port/win32_port.h */
+#define pgoff_t off_t
+#endif
+
+extern double pg_erand48(unsigned short xseed[3]);
+extern long pg_lrand48(void);
+extern long pg_jrand48(unsigned short xseed[3]);
+extern void pg_srand48(long seed);
+
+#ifndef HAVE_FLS
+extern int fls(int mask);
+#endif
+
+#ifndef HAVE_GETPEEREID
+/* On Windows, Perl might have incompatible definitions of uid_t and gid_t. */
+#ifndef PLPERL_HAVE_UID_GID
+extern int getpeereid(int sock, uid_t *uid, gid_t *gid);
+#endif
+#endif
+
+/*
+ * Glibc doesn't use the builtin for clang due to a *gcc* bug in a version
+ * newer than the gcc compatibility clang claims to have. This would cause a
+ * *lot* of superfluous function calls, therefore revert when using clang. In
+ * C++ there's issues with libc++ (not libstdc++), so disable as well.
+ */
+#if defined(__clang__) && !defined(__cplusplus)
+/* needs to be separate to not confuse other compilers */
+#if __has_builtin(__builtin_isinf)
+/* need to include before, to avoid getting overwritten */
+#include <math.h>
+#undef isinf
+#define isinf __builtin_isinf
+#endif /* __has_builtin(isinf) */
+#endif /* __clang__ && !__cplusplus */
+
+#ifndef HAVE_EXPLICIT_BZERO
+extern void explicit_bzero(void *buf, size_t len);
+#endif
+
+#ifndef HAVE_STRTOF
+extern float strtof(const char *nptr, char **endptr);
+#endif
+
+#ifdef HAVE_BUGGY_STRTOF
+extern float pg_strtof(const char *nptr, char **endptr);
+#define strtof(a,b) (pg_strtof((a),(b)))
+#endif
+
+#ifndef HAVE_LINK
+extern int link(const char *src, const char *dst);
+#endif
+
+#ifndef HAVE_MKDTEMP
+extern char *mkdtemp(char *path);
+#endif
+
+#ifndef HAVE_INET_ATON
+#include <netinet/in.h>
+#include <arpa/inet.h>
+extern int inet_aton(const char *cp, struct in_addr *addr);
+#endif
+
+/*
+ * Windows and older Unix don't have pread(2) and pwrite(2). We have
+ * replacement functions, but they have slightly different semantics so we'll
+ * use a name with a pg_ prefix to avoid confusion.
+ */
+#ifdef HAVE_PREAD
+#define pg_pread pread
+#else
+extern ssize_t pg_pread(int fd, void *buf, size_t nbyte, off_t offset);
+#endif
+
+#ifdef HAVE_PWRITE
+#define pg_pwrite pwrite
+#else
+extern ssize_t pg_pwrite(int fd, const void *buf, size_t nbyte, off_t offset);
+#endif
+
+#if !HAVE_DECL_STRLCAT
+extern size_t strlcat(char *dst, const char *src, size_t siz);
+#endif
+
+#if !HAVE_DECL_STRLCPY
+extern size_t strlcpy(char *dst, const char *src, size_t siz);
+#endif
+
+#if !HAVE_DECL_STRNLEN
+extern size_t strnlen(const char *str, size_t maxlen);
+#endif
+
+#if !defined(HAVE_RANDOM)
+extern long random(void);
+#endif
+
+#ifndef HAVE_SETENV
+extern int setenv(const char *name, const char *value, int overwrite);
+#endif
+
+#ifndef HAVE_UNSETENV
+extern void unsetenv(const char *name);
+#endif
+
+#ifndef HAVE_SRANDOM
+extern void srandom(unsigned int seed);
+#endif
+
+#ifndef HAVE_DLOPEN
+extern void *dlopen(const char *file, int mode);
+extern void *dlsym(void *handle, const char *symbol);
+extern int dlclose(void *handle);
+extern char *dlerror(void);
+#endif
+
+/*
+ * In some older systems, the RTLD_NOW flag isn't defined and the mode
+ * argument to dlopen must always be 1.
+ */
+#if !HAVE_DECL_RTLD_NOW
+#define RTLD_NOW 1
+#endif
+
+/*
+ * The RTLD_GLOBAL flag is wanted if available, but it doesn't exist
+ * everywhere. If it doesn't exist, set it to 0 so it has no effect.
+ */
+#if !HAVE_DECL_RTLD_GLOBAL
+#define RTLD_GLOBAL 0
+#endif
+
+/* thread.h */
+#ifndef WIN32
+extern int pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
+ size_t buflen, struct passwd **result);
+#endif
+
+extern int pqGethostbyname(const char *name,
+ struct hostent *resultbuf,
+ char *buffer, size_t buflen,
+ struct hostent **result,
+ int *herrno);
+
+extern void pg_qsort(void *base, size_t nel, size_t elsize,
+ int (*cmp) (const void *, const void *));
+extern int pg_qsort_strcmp(const void *a, const void *b);
+
+#define qsort(a,b,c,d) pg_qsort(a,b,c,d)
+
+typedef int (*qsort_arg_comparator) (const void *a, const void *b, void *arg);
+
+extern void qsort_arg(void *base, size_t nel, size_t elsize,
+ qsort_arg_comparator cmp, void *arg);
+
+/* port/chklocale.c */
+extern int pg_get_encoding_from_locale(const char *ctype, bool write_message);
+
+#if defined(WIN32) && !defined(FRONTEND)
+extern int pg_codepage_to_encoding(UINT cp);
+#endif
+
+/* port/inet_net_ntop.c */
+extern char *pg_inet_net_ntop(int af, const void *src, int bits,
+ char *dst, size_t size);
+
+/* port/pg_strong_random.c */
+extern bool pg_strong_random(void *buf, size_t len);
+
+/*
+ * pg_backend_random used to be a wrapper for pg_strong_random before
+ * Postgres 12 for the backend code.
+ */
+#define pg_backend_random pg_strong_random
+
+/* port/pgcheckdir.c */
+extern int pg_check_dir(const char *dir);
+
+/* port/pgmkdirp.c */
+extern int pg_mkdir_p(char *path, int omode);
+
+/* port/pqsignal.c */
+typedef void (*pqsigfunc) (int signo);
+extern pqsigfunc pqsignal(int signo, pqsigfunc func);
+
+/* port/quotes.c */
+extern char *escape_single_quotes_ascii(const char *src);
+
+/* common/wait_error.c */
+extern char *wait_result_to_str(int exit_status);
+extern bool wait_result_is_signal(int exit_status, int signum);
+extern bool wait_result_is_any_signal(int exit_status, bool include_command_not_found);
+
+#endif /* PG_PORT_H */
diff --git a/src/include/port/aix.h b/src/include/port/aix.h
new file mode 100644
index 0000000..5b1159c
--- /dev/null
+++ b/src/include/port/aix.h
@@ -0,0 +1,14 @@
+/*
+ * src/include/port/aix.h
+ */
+#define CLASS_CONFLICT
+#define DISABLE_XOPEN_NLS
+
+/*
+ * "IBM XL C/C++ for AIX, V12.1" miscompiles, for 32-bit, some inline
+ * expansions of ginCompareItemPointers() "long long" arithmetic. To take
+ * advantage of inlining, build a 64-bit PostgreSQL.
+ */
+#if defined(__ILP32__) && defined(__IBMC__)
+#define PG_FORCE_DISABLE_INLINE
+#endif
diff --git a/src/include/port/atomics.h b/src/include/port/atomics.h
new file mode 100644
index 0000000..4956ec5
--- /dev/null
+++ b/src/include/port/atomics.h
@@ -0,0 +1,524 @@
+/*-------------------------------------------------------------------------
+ *
+ * atomics.h
+ * Atomic operations.
+ *
+ * Hardware and compiler dependent functions for manipulating memory
+ * atomically and dealing with cache coherency. Used to implement locking
+ * facilities and lockless algorithms/data structures.
+ *
+ * To bring up postgres on a platform/compiler at the very least
+ * implementations for the following operations should be provided:
+ * * pg_compiler_barrier(), pg_write_barrier(), pg_read_barrier()
+ * * pg_atomic_compare_exchange_u32(), pg_atomic_fetch_add_u32()
+ * * pg_atomic_test_set_flag(), pg_atomic_init_flag(), pg_atomic_clear_flag()
+ * * PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY should be defined if appropriate.
+ *
+ * There exist generic, hardware independent, implementations for several
+ * compilers which might be sufficient, although possibly not optimal, for a
+ * new platform. If no such generic implementation is available spinlocks (or
+ * even OS provided semaphores) will be used to implement the API.
+ *
+ * Implement _u64 atomics if and only if your platform can use them
+ * efficiently (and obviously correctly).
+ *
+ * Use higher level functionality (lwlocks, spinlocks, heavyweight locks)
+ * whenever possible. Writing correct code using these facilities is hard.
+ *
+ * For an introduction to using memory barriers within the PostgreSQL backend,
+ * see src/backend/storage/lmgr/README.barrier
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/port/atomics.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ATOMICS_H
+#define ATOMICS_H
+
+#ifdef FRONTEND
+#error "atomics.h may not be included from frontend code"
+#endif
+
+#define INSIDE_ATOMICS_H
+
+#include <limits.h>
+
+/*
+ * First a set of architecture specific files is included.
+ *
+ * These files can provide the full set of atomics or can do pretty much
+ * nothing if all the compilers commonly used on these platforms provide
+ * usable generics.
+ *
+ * Don't add an inline assembly of the actual atomic operations if all the
+ * common implementations of your platform provide intrinsics. Intrinsics are
+ * much easier to understand and potentially support more architectures.
+ *
+ * It will often make sense to define memory barrier semantics here, since
+ * e.g. generic compiler intrinsics for x86 memory barriers can't know that
+ * postgres doesn't need x86 read/write barriers do anything more than a
+ * compiler barrier.
+ *
+ */
+#if defined(__arm__) || defined(__arm) || \
+ defined(__aarch64__) || defined(__aarch64)
+#include "port/atomics/arch-arm.h"
+#elif defined(__i386__) || defined(__i386) || defined(__x86_64__)
+#include "port/atomics/arch-x86.h"
+#elif defined(__ia64__) || defined(__ia64)
+#include "port/atomics/arch-ia64.h"
+#elif defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
+#include "port/atomics/arch-ppc.h"
+#elif defined(__hppa) || defined(__hppa__)
+#include "port/atomics/arch-hppa.h"
+#endif
+
+/*
+ * Compiler specific, but architecture independent implementations.
+ *
+ * Provide architecture independent implementations of the atomic
+ * facilities. At the very least compiler barriers should be provided, but a
+ * full implementation of
+ * * pg_compiler_barrier(), pg_write_barrier(), pg_read_barrier()
+ * * pg_atomic_compare_exchange_u32(), pg_atomic_fetch_add_u32()
+ * using compiler intrinsics are a good idea.
+ */
+/*
+ * gcc or compatible, including clang and icc. Exclude xlc. The ppc64le "IBM
+ * XL C/C++ for Linux, V13.1.2" emulates gcc, but __sync_lock_test_and_set()
+ * of one-byte types elicits SIGSEGV. That bug was gone by V13.1.5 (2016-12).
+ */
+#if (defined(__GNUC__) || defined(__INTEL_COMPILER)) && !(defined(__IBMC__) || defined(__IBMCPP__))
+#include "port/atomics/generic-gcc.h"
+#elif defined(_MSC_VER)
+#include "port/atomics/generic-msvc.h"
+#elif defined(__hpux) && defined(__ia64) && !defined(__GNUC__)
+#include "port/atomics/generic-acc.h"
+#elif defined(__SUNPRO_C) && !defined(__GNUC__)
+#include "port/atomics/generic-sunpro.h"
+#else
+/*
+ * Unsupported compiler, we'll likely use slower fallbacks... At least
+ * compiler barriers should really be provided.
+ */
+#endif
+
+/*
+ * Provide a full fallback of the pg_*_barrier(), pg_atomic**_flag and
+ * pg_atomic_* APIs for platforms without sufficient spinlock and/or atomics
+ * support. In the case of spinlock backed atomics the emulation is expected
+ * to be efficient, although less so than native atomics support.
+ */
+#include "port/atomics/fallback.h"
+
+/*
+ * Provide additional operations using supported infrastructure. These are
+ * expected to be efficient if the underlying atomic operations are efficient.
+ */
+#include "port/atomics/generic.h"
+
+
+/*
+ * pg_compiler_barrier - prevent the compiler from moving code across
+ *
+ * A compiler barrier need not (and preferably should not) emit any actual
+ * machine code, but must act as an optimization fence: the compiler must not
+ * reorder loads or stores to main memory around the barrier. However, the
+ * CPU may still reorder loads or stores at runtime, if the architecture's
+ * memory model permits this.
+ */
+#define pg_compiler_barrier() pg_compiler_barrier_impl()
+
+/*
+ * pg_memory_barrier - prevent the CPU from reordering memory access
+ *
+ * A memory barrier must act as a compiler barrier, and in addition must
+ * guarantee that all loads and stores issued prior to the barrier are
+ * completed before any loads or stores issued after the barrier. Unless
+ * loads and stores are totally ordered (which is not the case on most
+ * architectures) this requires issuing some sort of memory fencing
+ * instruction.
+ */
+#define pg_memory_barrier() pg_memory_barrier_impl()
+
+/*
+ * pg_(read|write)_barrier - prevent the CPU from reordering memory access
+ *
+ * A read barrier must act as a compiler barrier, and in addition must
+ * guarantee that any loads issued prior to the barrier are completed before
+ * any loads issued after the barrier. Similarly, a write barrier acts
+ * as a compiler barrier, and also orders stores. Read and write barriers
+ * are thus weaker than a full memory barrier, but stronger than a compiler
+ * barrier. In practice, on machines with strong memory ordering, read and
+ * write barriers may require nothing more than a compiler barrier.
+ */
+#define pg_read_barrier() pg_read_barrier_impl()
+#define pg_write_barrier() pg_write_barrier_impl()
+
+/*
+ * Spinloop delay - Allow CPU to relax in busy loops
+ */
+#define pg_spin_delay() pg_spin_delay_impl()
+
+/*
+ * pg_atomic_init_flag - initialize atomic flag.
+ *
+ * No barrier semantics.
+ */
+static inline void
+pg_atomic_init_flag(volatile pg_atomic_flag *ptr)
+{
+ pg_atomic_init_flag_impl(ptr);
+}
+
+/*
+ * pg_atomic_test_set_flag - TAS()
+ *
+ * Returns true if the flag has successfully been set, false otherwise.
+ *
+ * Acquire (including read barrier) semantics.
+ */
+static inline bool
+pg_atomic_test_set_flag(volatile pg_atomic_flag *ptr)
+{
+ return pg_atomic_test_set_flag_impl(ptr);
+}
+
+/*
+ * pg_atomic_unlocked_test_flag - Check if the lock is free
+ *
+ * Returns true if the flag currently is not set, false otherwise.
+ *
+ * No barrier semantics.
+ */
+static inline bool
+pg_atomic_unlocked_test_flag(volatile pg_atomic_flag *ptr)
+{
+ return pg_atomic_unlocked_test_flag_impl(ptr);
+}
+
+/*
+ * pg_atomic_clear_flag - release lock set by TAS()
+ *
+ * Release (including write barrier) semantics.
+ */
+static inline void
+pg_atomic_clear_flag(volatile pg_atomic_flag *ptr)
+{
+ pg_atomic_clear_flag_impl(ptr);
+}
+
+
+/*
+ * pg_atomic_init_u32 - initialize atomic variable
+ *
+ * Has to be done before any concurrent usage..
+ *
+ * No barrier semantics.
+ */
+static inline void
+pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
+{
+ AssertPointerAlignment(ptr, 4);
+
+ pg_atomic_init_u32_impl(ptr, val);
+}
+
+/*
+ * pg_atomic_read_u32 - unlocked read from atomic variable.
+ *
+ * The read is guaranteed to return a value as it has been written by this or
+ * another process at some point in the past. There's however no cache
+ * coherency interaction guaranteeing the value hasn't since been written to
+ * again.
+ *
+ * No barrier semantics.
+ */
+static inline uint32
+pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
+{
+ AssertPointerAlignment(ptr, 4);
+ return pg_atomic_read_u32_impl(ptr);
+}
+
+/*
+ * pg_atomic_write_u32 - write to atomic variable.
+ *
+ * The write is guaranteed to succeed as a whole, i.e. it's not possible to
+ * observe a partial write for any reader. Note that this correctly interacts
+ * with pg_atomic_compare_exchange_u32, in contrast to
+ * pg_atomic_unlocked_write_u32().
+ *
+ * No barrier semantics.
+ */
+static inline void
+pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
+{
+ AssertPointerAlignment(ptr, 4);
+
+ pg_atomic_write_u32_impl(ptr, val);
+}
+
+/*
+ * pg_atomic_unlocked_write_u32 - unlocked write to atomic variable.
+ *
+ * The write is guaranteed to succeed as a whole, i.e. it's not possible to
+ * observe a partial write for any reader. But note that writing this way is
+ * not guaranteed to correctly interact with read-modify-write operations like
+ * pg_atomic_compare_exchange_u32. This should only be used in cases where
+ * minor performance regressions due to atomics emulation are unacceptable.
+ *
+ * No barrier semantics.
+ */
+static inline void
+pg_atomic_unlocked_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
+{
+ AssertPointerAlignment(ptr, 4);
+
+ pg_atomic_unlocked_write_u32_impl(ptr, val);
+}
+
+/*
+ * pg_atomic_exchange_u32 - exchange newval with current value
+ *
+ * Returns the old value of 'ptr' before the swap.
+ *
+ * Full barrier semantics.
+ */
+static inline uint32
+pg_atomic_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 newval)
+{
+ AssertPointerAlignment(ptr, 4);
+
+ return pg_atomic_exchange_u32_impl(ptr, newval);
+}
+
+/*
+ * pg_atomic_compare_exchange_u32 - CAS operation
+ *
+ * Atomically compare the current value of ptr with *expected and store newval
+ * iff ptr and *expected have the same value. The current value of *ptr will
+ * always be stored in *expected.
+ *
+ * Return true if values have been exchanged, false otherwise.
+ *
+ * Full barrier semantics.
+ */
+static inline bool
+pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr,
+ uint32 *expected, uint32 newval)
+{
+ AssertPointerAlignment(ptr, 4);
+ AssertPointerAlignment(expected, 4);
+
+ return pg_atomic_compare_exchange_u32_impl(ptr, expected, newval);
+}
+
+/*
+ * pg_atomic_fetch_add_u32 - atomically add to variable
+ *
+ * Returns the value of ptr before the arithmetic operation.
+ *
+ * Full barrier semantics.
+ */
+static inline uint32
+pg_atomic_fetch_add_u32(volatile pg_atomic_uint32 *ptr, int32 add_)
+{
+ AssertPointerAlignment(ptr, 4);
+ return pg_atomic_fetch_add_u32_impl(ptr, add_);
+}
+
+/*
+ * pg_atomic_fetch_sub_u32 - atomically subtract from variable
+ *
+ * Returns the value of ptr before the arithmetic operation. Note that sub_
+ * may not be INT_MIN due to platform limitations.
+ *
+ * Full barrier semantics.
+ */
+static inline uint32
+pg_atomic_fetch_sub_u32(volatile pg_atomic_uint32 *ptr, int32 sub_)
+{
+ AssertPointerAlignment(ptr, 4);
+ Assert(sub_ != INT_MIN);
+ return pg_atomic_fetch_sub_u32_impl(ptr, sub_);
+}
+
+/*
+ * pg_atomic_fetch_and_u32 - atomically bit-and and_ with variable
+ *
+ * Returns the value of ptr before the arithmetic operation.
+ *
+ * Full barrier semantics.
+ */
+static inline uint32
+pg_atomic_fetch_and_u32(volatile pg_atomic_uint32 *ptr, uint32 and_)
+{
+ AssertPointerAlignment(ptr, 4);
+ return pg_atomic_fetch_and_u32_impl(ptr, and_);
+}
+
+/*
+ * pg_atomic_fetch_or_u32 - atomically bit-or or_ with variable
+ *
+ * Returns the value of ptr before the arithmetic operation.
+ *
+ * Full barrier semantics.
+ */
+static inline uint32
+pg_atomic_fetch_or_u32(volatile pg_atomic_uint32 *ptr, uint32 or_)
+{
+ AssertPointerAlignment(ptr, 4);
+ return pg_atomic_fetch_or_u32_impl(ptr, or_);
+}
+
+/*
+ * pg_atomic_add_fetch_u32 - atomically add to variable
+ *
+ * Returns the value of ptr after the arithmetic operation.
+ *
+ * Full barrier semantics.
+ */
+static inline uint32
+pg_atomic_add_fetch_u32(volatile pg_atomic_uint32 *ptr, int32 add_)
+{
+ AssertPointerAlignment(ptr, 4);
+ return pg_atomic_add_fetch_u32_impl(ptr, add_);
+}
+
+/*
+ * pg_atomic_sub_fetch_u32 - atomically subtract from variable
+ *
+ * Returns the value of ptr after the arithmetic operation. Note that sub_ may
+ * not be INT_MIN due to platform limitations.
+ *
+ * Full barrier semantics.
+ */
+static inline uint32
+pg_atomic_sub_fetch_u32(volatile pg_atomic_uint32 *ptr, int32 sub_)
+{
+ AssertPointerAlignment(ptr, 4);
+ Assert(sub_ != INT_MIN);
+ return pg_atomic_sub_fetch_u32_impl(ptr, sub_);
+}
+
+/* ----
+ * The 64 bit operations have the same semantics as their 32bit counterparts
+ * if they are available. Check the corresponding 32bit function for
+ * documentation.
+ * ----
+ */
+static inline void
+pg_atomic_init_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
+{
+ /*
+ * Can't necessarily enforce alignment - and don't need it - when using
+ * the spinlock based fallback implementation. Therefore only assert when
+ * not using it.
+ */
+#ifndef PG_HAVE_ATOMIC_U64_SIMULATION
+ AssertPointerAlignment(ptr, 8);
+#endif
+ pg_atomic_init_u64_impl(ptr, val);
+}
+
+static inline uint64
+pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
+{
+#ifndef PG_HAVE_ATOMIC_U64_SIMULATION
+ AssertPointerAlignment(ptr, 8);
+#endif
+ return pg_atomic_read_u64_impl(ptr);
+}
+
+static inline void
+pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
+{
+#ifndef PG_HAVE_ATOMIC_U64_SIMULATION
+ AssertPointerAlignment(ptr, 8);
+#endif
+ pg_atomic_write_u64_impl(ptr, val);
+}
+
+static inline uint64
+pg_atomic_exchange_u64(volatile pg_atomic_uint64 *ptr, uint64 newval)
+{
+#ifndef PG_HAVE_ATOMIC_U64_SIMULATION
+ AssertPointerAlignment(ptr, 8);
+#endif
+ return pg_atomic_exchange_u64_impl(ptr, newval);
+}
+
+static inline bool
+pg_atomic_compare_exchange_u64(volatile pg_atomic_uint64 *ptr,
+ uint64 *expected, uint64 newval)
+{
+#ifndef PG_HAVE_ATOMIC_U64_SIMULATION
+ AssertPointerAlignment(ptr, 8);
+ AssertPointerAlignment(expected, 8);
+#endif
+ return pg_atomic_compare_exchange_u64_impl(ptr, expected, newval);
+}
+
+static inline uint64
+pg_atomic_fetch_add_u64(volatile pg_atomic_uint64 *ptr, int64 add_)
+{
+#ifndef PG_HAVE_ATOMIC_U64_SIMULATION
+ AssertPointerAlignment(ptr, 8);
+#endif
+ return pg_atomic_fetch_add_u64_impl(ptr, add_);
+}
+
+static inline uint64
+pg_atomic_fetch_sub_u64(volatile pg_atomic_uint64 *ptr, int64 sub_)
+{
+#ifndef PG_HAVE_ATOMIC_U64_SIMULATION
+ AssertPointerAlignment(ptr, 8);
+#endif
+ Assert(sub_ != PG_INT64_MIN);
+ return pg_atomic_fetch_sub_u64_impl(ptr, sub_);
+}
+
+static inline uint64
+pg_atomic_fetch_and_u64(volatile pg_atomic_uint64 *ptr, uint64 and_)
+{
+#ifndef PG_HAVE_ATOMIC_U64_SIMULATION
+ AssertPointerAlignment(ptr, 8);
+#endif
+ return pg_atomic_fetch_and_u64_impl(ptr, and_);
+}
+
+static inline uint64
+pg_atomic_fetch_or_u64(volatile pg_atomic_uint64 *ptr, uint64 or_)
+{
+#ifndef PG_HAVE_ATOMIC_U64_SIMULATION
+ AssertPointerAlignment(ptr, 8);
+#endif
+ return pg_atomic_fetch_or_u64_impl(ptr, or_);
+}
+
+static inline uint64
+pg_atomic_add_fetch_u64(volatile pg_atomic_uint64 *ptr, int64 add_)
+{
+#ifndef PG_HAVE_ATOMIC_U64_SIMULATION
+ AssertPointerAlignment(ptr, 8);
+#endif
+ return pg_atomic_add_fetch_u64_impl(ptr, add_);
+}
+
+static inline uint64
+pg_atomic_sub_fetch_u64(volatile pg_atomic_uint64 *ptr, int64 sub_)
+{
+#ifndef PG_HAVE_ATOMIC_U64_SIMULATION
+ AssertPointerAlignment(ptr, 8);
+#endif
+ Assert(sub_ != PG_INT64_MIN);
+ return pg_atomic_sub_fetch_u64_impl(ptr, sub_);
+}
+
+#undef INSIDE_ATOMICS_H
+
+#endif /* ATOMICS_H */
diff --git a/src/include/port/atomics/arch-arm.h b/src/include/port/atomics/arch-arm.h
new file mode 100644
index 0000000..6b925a7
--- /dev/null
+++ b/src/include/port/atomics/arch-arm.h
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ *
+ * arch-arm.h
+ * Atomic operations considerations specific to ARM
+ *
+ * Portions Copyright (c) 2013-2020, PostgreSQL Global Development Group
+ *
+ * NOTES:
+ *
+ * src/include/port/atomics/arch-arm.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* intentionally no include guards, should only be included by atomics.h */
+#ifndef INSIDE_ATOMICS_H
+#error "should be included via atomics.h"
+#endif
+
+/*
+ * 64 bit atomics on ARM32 are implemented using kernel fallbacks and thus
+ * might be slow, so disable entirely. On ARM64 that problem doesn't exist.
+ */
+#if !defined(__aarch64__) && !defined(__aarch64)
+#define PG_DISABLE_64_BIT_ATOMICS
+#endif /* __aarch64__ || __aarch64 */
diff --git a/src/include/port/atomics/arch-hppa.h b/src/include/port/atomics/arch-hppa.h
new file mode 100644
index 0000000..a581b3f
--- /dev/null
+++ b/src/include/port/atomics/arch-hppa.h
@@ -0,0 +1,17 @@
+/*-------------------------------------------------------------------------
+ *
+ * arch-hppa.h
+ * Atomic operations considerations specific to HPPA
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES:
+ *
+ * src/include/port/atomics/arch-hppa.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* HPPA doesn't do either read or write reordering */
+#define pg_memory_barrier_impl() pg_compiler_barrier_impl()
diff --git a/src/include/port/atomics/arch-ia64.h b/src/include/port/atomics/arch-ia64.h
new file mode 100644
index 0000000..9feb153
--- /dev/null
+++ b/src/include/port/atomics/arch-ia64.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ *
+ * arch-ia64.h
+ * Atomic operations considerations specific to intel itanium
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES:
+ *
+ * src/include/port/atomics/arch-ia64.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/*
+ * Itanium is weakly ordered, so read and write barriers require a full
+ * fence.
+ */
+#if defined(__INTEL_COMPILER)
+# define pg_memory_barrier_impl() __mf()
+#elif defined(__GNUC__)
+# define pg_memory_barrier_impl() __asm__ __volatile__ ("mf" : : : "memory")
+#elif defined(__hpux)
+# define pg_memory_barrier_impl() _Asm_mf()
+#endif
+
+/* per architecture manual doubleword accesses have single copy atomicity */
+#define PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY
diff --git a/src/include/port/atomics/arch-ppc.h b/src/include/port/atomics/arch-ppc.h
new file mode 100644
index 0000000..a82ae38
--- /dev/null
+++ b/src/include/port/atomics/arch-ppc.h
@@ -0,0 +1,254 @@
+/*-------------------------------------------------------------------------
+ *
+ * arch-ppc.h
+ * Atomic operations considerations specific to PowerPC
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES:
+ *
+ * src/include/port/atomics/arch-ppc.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#if defined(__GNUC__)
+
+/*
+ * lwsync orders loads with respect to each other, and similarly with stores.
+ * But a load can be performed before a subsequent store, so sync must be used
+ * for a full memory barrier.
+ */
+#define pg_memory_barrier_impl() __asm__ __volatile__ ("sync" : : : "memory")
+#define pg_read_barrier_impl() __asm__ __volatile__ ("lwsync" : : : "memory")
+#define pg_write_barrier_impl() __asm__ __volatile__ ("lwsync" : : : "memory")
+#endif
+
+#define PG_HAVE_ATOMIC_U32_SUPPORT
+typedef struct pg_atomic_uint32
+{
+ volatile uint32 value;
+} pg_atomic_uint32;
+
+/* 64bit atomics are only supported in 64bit mode */
+#if SIZEOF_VOID_P >= 8
+#define PG_HAVE_ATOMIC_U64_SUPPORT
+typedef struct pg_atomic_uint64
+{
+ volatile uint64 value pg_attribute_aligned(8);
+} pg_atomic_uint64;
+
+#endif
+
+/*
+ * This mimics gcc __atomic_compare_exchange_n(..., __ATOMIC_SEQ_CST), but
+ * code generation differs at the end. __atomic_compare_exchange_n():
+ * 100: isync
+ * 104: mfcr r3
+ * 108: rlwinm r3,r3,3,31,31
+ * 10c: bne 120 <.eb+0x10>
+ * 110: clrldi r3,r3,63
+ * 114: addi r1,r1,112
+ * 118: blr
+ * 11c: nop
+ * 120: clrldi r3,r3,63
+ * 124: stw r9,0(r4)
+ * 128: addi r1,r1,112
+ * 12c: blr
+ *
+ * This:
+ * f0: isync
+ * f4: mfcr r9
+ * f8: rldicl. r3,r9,35,63
+ * fc: bne 104 <.eb>
+ * 100: stw r10,0(r4)
+ * 104: addi r1,r1,112
+ * 108: blr
+ *
+ * This implementation may or may not have materially different performance.
+ * It's not exploiting the fact that cr0 still holds the relevant comparison
+ * bits, set during the __asm__. One could fix that by moving more code into
+ * the __asm__. (That would remove the freedom to eliminate dead stores when
+ * the caller ignores "expected", but few callers do.)
+ *
+ * Recognizing constant "newval" would be superfluous, because there's no
+ * immediate-operand version of stwcx.
+ */
+#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
+static inline bool
+pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
+ uint32 *expected, uint32 newval)
+{
+ uint32 found;
+ uint32 condition_register;
+ bool ret;
+
+#ifdef HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P
+ if (__builtin_constant_p(*expected) &&
+ (int32) *expected <= PG_INT16_MAX &&
+ (int32) *expected >= PG_INT16_MIN)
+ __asm__ __volatile__(
+ " sync \n"
+ " lwarx %0,0,%5 \n"
+ " cmpwi %0,%3 \n"
+ " bne $+12 \n" /* branch to isync */
+ " stwcx. %4,0,%5 \n"
+ " bne $-16 \n" /* branch to lwarx */
+ " isync \n"
+ " mfcr %1 \n"
+: "=&r"(found), "=r"(condition_register), "+m"(ptr->value)
+: "i"(*expected), "r"(newval), "r"(&ptr->value)
+: "memory", "cc");
+ else
+#endif
+ __asm__ __volatile__(
+ " sync \n"
+ " lwarx %0,0,%5 \n"
+ " cmpw %0,%3 \n"
+ " bne $+12 \n" /* branch to isync */
+ " stwcx. %4,0,%5 \n"
+ " bne $-16 \n" /* branch to lwarx */
+ " isync \n"
+ " mfcr %1 \n"
+: "=&r"(found), "=r"(condition_register), "+m"(ptr->value)
+: "r"(*expected), "r"(newval), "r"(&ptr->value)
+: "memory", "cc");
+
+ ret = (condition_register >> 29) & 1; /* test eq bit of cr0 */
+ if (!ret)
+ *expected = found;
+ return ret;
+}
+
+/*
+ * This mirrors gcc __sync_fetch_and_add().
+ *
+ * Like tas(), use constraint "=&b" to avoid allocating r0.
+ */
+#define PG_HAVE_ATOMIC_FETCH_ADD_U32
+static inline uint32
+pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
+{
+ uint32 _t;
+ uint32 res;
+
+#ifdef HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P
+ if (__builtin_constant_p(add_) &&
+ add_ <= PG_INT16_MAX && add_ >= PG_INT16_MIN)
+ __asm__ __volatile__(
+ " sync \n"
+ " lwarx %1,0,%4 \n"
+ " addi %0,%1,%3 \n"
+ " stwcx. %0,0,%4 \n"
+ " bne $-12 \n" /* branch to lwarx */
+ " isync \n"
+: "=&r"(_t), "=&b"(res), "+m"(ptr->value)
+: "i"(add_), "r"(&ptr->value)
+: "memory", "cc");
+ else
+#endif
+ __asm__ __volatile__(
+ " sync \n"
+ " lwarx %1,0,%4 \n"
+ " add %0,%1,%3 \n"
+ " stwcx. %0,0,%4 \n"
+ " bne $-12 \n" /* branch to lwarx */
+ " isync \n"
+: "=&r"(_t), "=&r"(res), "+m"(ptr->value)
+: "r"(add_), "r"(&ptr->value)
+: "memory", "cc");
+
+ return res;
+}
+
+#ifdef PG_HAVE_ATOMIC_U64_SUPPORT
+
+#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64
+static inline bool
+pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
+ uint64 *expected, uint64 newval)
+{
+ uint64 found;
+ uint32 condition_register;
+ bool ret;
+
+ /* Like u32, but s/lwarx/ldarx/; s/stwcx/stdcx/; s/cmpw/cmpd/ */
+#ifdef HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P
+ if (__builtin_constant_p(*expected) &&
+ (int64) *expected <= PG_INT16_MAX &&
+ (int64) *expected >= PG_INT16_MIN)
+ __asm__ __volatile__(
+ " sync \n"
+ " ldarx %0,0,%5 \n"
+ " cmpdi %0,%3 \n"
+ " bne $+12 \n" /* branch to isync */
+ " stdcx. %4,0,%5 \n"
+ " bne $-16 \n" /* branch to ldarx */
+ " isync \n"
+ " mfcr %1 \n"
+: "=&r"(found), "=r"(condition_register), "+m"(ptr->value)
+: "i"(*expected), "r"(newval), "r"(&ptr->value)
+: "memory", "cc");
+ else
+#endif
+ __asm__ __volatile__(
+ " sync \n"
+ " ldarx %0,0,%5 \n"
+ " cmpd %0,%3 \n"
+ " bne $+12 \n" /* branch to isync */
+ " stdcx. %4,0,%5 \n"
+ " bne $-16 \n" /* branch to ldarx */
+ " isync \n"
+ " mfcr %1 \n"
+: "=&r"(found), "=r"(condition_register), "+m"(ptr->value)
+: "r"(*expected), "r"(newval), "r"(&ptr->value)
+: "memory", "cc");
+
+ ret = (condition_register >> 29) & 1; /* test eq bit of cr0 */
+ if (!ret)
+ *expected = found;
+ return ret;
+}
+
+#define PG_HAVE_ATOMIC_FETCH_ADD_U64
+static inline uint64
+pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
+{
+ uint64 _t;
+ uint64 res;
+
+ /* Like u32, but s/lwarx/ldarx/; s/stwcx/stdcx/ */
+#ifdef HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P
+ if (__builtin_constant_p(add_) &&
+ add_ <= PG_INT16_MAX && add_ >= PG_INT16_MIN)
+ __asm__ __volatile__(
+ " sync \n"
+ " ldarx %1,0,%4 \n"
+ " addi %0,%1,%3 \n"
+ " stdcx. %0,0,%4 \n"
+ " bne $-12 \n" /* branch to ldarx */
+ " isync \n"
+: "=&r"(_t), "=&b"(res), "+m"(ptr->value)
+: "i"(add_), "r"(&ptr->value)
+: "memory", "cc");
+ else
+#endif
+ __asm__ __volatile__(
+ " sync \n"
+ " ldarx %1,0,%4 \n"
+ " add %0,%1,%3 \n"
+ " stdcx. %0,0,%4 \n"
+ " bne $-12 \n" /* branch to ldarx */
+ " isync \n"
+: "=&r"(_t), "=&r"(res), "+m"(ptr->value)
+: "r"(add_), "r"(&ptr->value)
+: "memory", "cc");
+
+ return res;
+}
+
+#endif /* PG_HAVE_ATOMIC_U64_SUPPORT */
+
+/* per architecture manual doubleword accesses have single copy atomicity */
+#define PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY
diff --git a/src/include/port/atomics/arch-x86.h b/src/include/port/atomics/arch-x86.h
new file mode 100644
index 0000000..13cc4f5
--- /dev/null
+++ b/src/include/port/atomics/arch-x86.h
@@ -0,0 +1,252 @@
+/*-------------------------------------------------------------------------
+ *
+ * arch-x86.h
+ * Atomic operations considerations specific to intel x86
+ *
+ * Note that we actually require a 486 upwards because the 386 doesn't have
+ * support for xadd and cmpxchg. Given that the 386 isn't supported anywhere
+ * anymore that's not much of a restriction luckily.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES:
+ *
+ * src/include/port/atomics/arch-x86.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/*
+ * Both 32 and 64 bit x86 do not allow loads to be reordered with other loads,
+ * or stores to be reordered with other stores, but a load can be performed
+ * before a subsequent store.
+ *
+ * Technically, some x86-ish chips support uncached memory access and/or
+ * special instructions that are weakly ordered. In those cases we'd need
+ * the read and write barriers to be lfence and sfence. But since we don't
+ * do those things, a compiler barrier should be enough.
+ *
+ * "lock; addl" has worked for longer than "mfence". It's also rumored to be
+ * faster in many scenarios.
+ */
+
+#if defined(__GNUC__) || defined(__INTEL_COMPILER)
+#if defined(__i386__) || defined(__i386)
+#define pg_memory_barrier_impl() \
+ __asm__ __volatile__ ("lock; addl $0,0(%%esp)" : : : "memory", "cc")
+#elif defined(__x86_64__)
+#define pg_memory_barrier_impl() \
+ __asm__ __volatile__ ("lock; addl $0,0(%%rsp)" : : : "memory", "cc")
+#endif
+#endif /* defined(__GNUC__) || defined(__INTEL_COMPILER) */
+
+#define pg_read_barrier_impl() pg_compiler_barrier_impl()
+#define pg_write_barrier_impl() pg_compiler_barrier_impl()
+
+/*
+ * Provide implementation for atomics using inline assembly on x86 gcc. It's
+ * nice to support older gcc's and the compare/exchange implementation here is
+ * actually more efficient than the * __sync variant.
+ */
+#if defined(HAVE_ATOMICS)
+
+#if defined(__GNUC__) || defined(__INTEL_COMPILER)
+
+#define PG_HAVE_ATOMIC_FLAG_SUPPORT
+typedef struct pg_atomic_flag
+{
+ volatile char value;
+} pg_atomic_flag;
+
+#define PG_HAVE_ATOMIC_U32_SUPPORT
+typedef struct pg_atomic_uint32
+{
+ volatile uint32 value;
+} pg_atomic_uint32;
+
+/*
+ * It's too complicated to write inline asm for 64bit types on 32bit and the
+ * 486 can't do it anyway.
+ */
+#ifdef __x86_64__
+#define PG_HAVE_ATOMIC_U64_SUPPORT
+typedef struct pg_atomic_uint64
+{
+ /* alignment guaranteed due to being on a 64bit platform */
+ volatile uint64 value;
+} pg_atomic_uint64;
+#endif /* __x86_64__ */
+
+#endif /* defined(__GNUC__) || defined(__INTEL_COMPILER) */
+
+#endif /* defined(HAVE_ATOMICS) */
+
+#if !defined(PG_HAVE_SPIN_DELAY)
+/*
+ * This sequence is equivalent to the PAUSE instruction ("rep" is
+ * ignored by old IA32 processors if the following instruction is
+ * not a string operation); the IA-32 Architecture Software
+ * Developer's Manual, Vol. 3, Section 7.7.2 describes why using
+ * PAUSE in the inner loop of a spin lock is necessary for good
+ * performance:
+ *
+ * The PAUSE instruction improves the performance of IA-32
+ * processors supporting Hyper-Threading Technology when
+ * executing spin-wait loops and other routines where one
+ * thread is accessing a shared lock or semaphore in a tight
+ * polling loop. When executing a spin-wait loop, the
+ * processor can suffer a severe performance penalty when
+ * exiting the loop because it detects a possible memory order
+ * violation and flushes the core processor's pipeline. The
+ * PAUSE instruction provides a hint to the processor that the
+ * code sequence is a spin-wait loop. The processor uses this
+ * hint to avoid the memory order violation and prevent the
+ * pipeline flush. In addition, the PAUSE instruction
+ * de-pipelines the spin-wait loop to prevent it from
+ * consuming execution resources excessively.
+ */
+#if defined(__GNUC__) || defined(__INTEL_COMPILER)
+#define PG_HAVE_SPIN_DELAY
+static __inline__ void
+pg_spin_delay_impl(void)
+{
+ __asm__ __volatile__(" rep; nop \n");
+}
+#elif defined(_MSC_VER) && defined(__x86_64__)
+#define PG_HAVE_SPIN_DELAY
+static __forceinline void
+pg_spin_delay_impl(void)
+{
+ _mm_pause();
+}
+#elif defined(_MSC_VER)
+#define PG_HAVE_SPIN_DELAY
+static __forceinline void
+pg_spin_delay_impl(void)
+{
+ /* See comment for gcc code. Same code, MASM syntax */
+ __asm rep nop;
+}
+#endif
+#endif /* !defined(PG_HAVE_SPIN_DELAY) */
+
+
+#if defined(HAVE_ATOMICS)
+
+#if defined(__GNUC__) || defined(__INTEL_COMPILER)
+
+#define PG_HAVE_ATOMIC_TEST_SET_FLAG
+static inline bool
+pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ register char _res = 1;
+
+ __asm__ __volatile__(
+ " lock \n"
+ " xchgb %0,%1 \n"
+: "+q"(_res), "+m"(ptr->value)
+:
+: "memory");
+ return _res == 0;
+}
+
+#define PG_HAVE_ATOMIC_CLEAR_FLAG
+static inline void
+pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ /*
+ * On a TSO architecture like x86 it's sufficient to use a compiler
+ * barrier to achieve release semantics.
+ */
+ __asm__ __volatile__("" ::: "memory");
+ ptr->value = 0;
+}
+
+#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
+static inline bool
+pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
+ uint32 *expected, uint32 newval)
+{
+ char ret;
+
+ /*
+ * Perform cmpxchg and use the zero flag which it implicitly sets when
+ * equal to measure the success.
+ */
+ __asm__ __volatile__(
+ " lock \n"
+ " cmpxchgl %4,%5 \n"
+ " setz %2 \n"
+: "=a" (*expected), "=m"(ptr->value), "=q" (ret)
+: "a" (*expected), "r" (newval), "m"(ptr->value)
+: "memory", "cc");
+ return (bool) ret;
+}
+
+#define PG_HAVE_ATOMIC_FETCH_ADD_U32
+static inline uint32
+pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
+{
+ uint32 res;
+ __asm__ __volatile__(
+ " lock \n"
+ " xaddl %0,%1 \n"
+: "=q"(res), "=m"(ptr->value)
+: "0" (add_), "m"(ptr->value)
+: "memory", "cc");
+ return res;
+}
+
+#ifdef __x86_64__
+
+#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64
+static inline bool
+pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
+ uint64 *expected, uint64 newval)
+{
+ char ret;
+
+ /*
+ * Perform cmpxchg and use the zero flag which it implicitly sets when
+ * equal to measure the success.
+ */
+ __asm__ __volatile__(
+ " lock \n"
+ " cmpxchgq %4,%5 \n"
+ " setz %2 \n"
+: "=a" (*expected), "=m"(ptr->value), "=q" (ret)
+: "a" (*expected), "r" (newval), "m"(ptr->value)
+: "memory", "cc");
+ return (bool) ret;
+}
+
+#define PG_HAVE_ATOMIC_FETCH_ADD_U64
+static inline uint64
+pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
+{
+ uint64 res;
+ __asm__ __volatile__(
+ " lock \n"
+ " xaddq %0,%1 \n"
+: "=q"(res), "=m"(ptr->value)
+: "0" (add_), "m"(ptr->value)
+: "memory", "cc");
+ return res;
+}
+
+#endif /* __x86_64__ */
+
+#endif /* defined(__GNUC__) || defined(__INTEL_COMPILER) */
+
+/*
+ * 8 byte reads / writes have single-copy atomicity on 32 bit x86 platforms
+ * since at least the 586. As well as on all x86-64 cpus.
+ */
+#if defined(__i568__) || defined(__i668__) || /* gcc i586+ */ \
+ (defined(_M_IX86) && _M_IX86 >= 500) || /* msvc i586+ */ \
+ defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) /* gcc, sunpro, msvc */
+#define PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY
+#endif /* 8 byte single-copy atomicity */
+
+#endif /* HAVE_ATOMICS */
diff --git a/src/include/port/atomics/fallback.h b/src/include/port/atomics/fallback.h
new file mode 100644
index 0000000..e3849c8
--- /dev/null
+++ b/src/include/port/atomics/fallback.h
@@ -0,0 +1,170 @@
+/*-------------------------------------------------------------------------
+ *
+ * fallback.h
+ * Fallback for platforms without spinlock and/or atomics support. Slower
+ * than native atomics support, but not unusably slow.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/port/atomics/fallback.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* intentionally no include guards, should only be included by atomics.h */
+#ifndef INSIDE_ATOMICS_H
+# error "should be included via atomics.h"
+#endif
+
+#ifndef pg_memory_barrier_impl
+/*
+ * If we have no memory barrier implementation for this architecture, we
+ * fall back to acquiring and releasing a spinlock. This might, in turn,
+ * fall back to the semaphore-based spinlock implementation, which will be
+ * amazingly slow.
+ *
+ * It's not self-evident that every possible legal implementation of a
+ * spinlock acquire-and-release would be equivalent to a full memory barrier.
+ * For example, I'm not sure that Itanium's acq and rel add up to a full
+ * fence. But all of our actual implementations seem OK in this regard.
+ */
+#define PG_HAVE_MEMORY_BARRIER_EMULATION
+
+extern void pg_spinlock_barrier(void);
+#define pg_memory_barrier_impl pg_spinlock_barrier
+#endif
+
+#ifndef pg_compiler_barrier_impl
+/*
+ * If the compiler/arch combination does not provide compiler barriers,
+ * provide a fallback. The fallback simply consists of a function call into
+ * an externally defined function. That should guarantee compiler barrier
+ * semantics except for compilers that do inter translation unit/global
+ * optimization - those better provide an actual compiler barrier.
+ *
+ * A native compiler barrier for sure is a lot faster than this...
+ */
+#define PG_HAVE_COMPILER_BARRIER_EMULATION
+extern void pg_extern_compiler_barrier(void);
+#define pg_compiler_barrier_impl pg_extern_compiler_barrier
+#endif
+
+
+/*
+ * If we have atomics implementation for this platform, fall back to providing
+ * the atomics API using a spinlock to protect the internal state. Possibly
+ * the spinlock implementation uses semaphores internally...
+ *
+ * We have to be a bit careful here, as it's not guaranteed that atomic
+ * variables are mapped to the same address in every process (e.g. dynamic
+ * shared memory segments). We can't just hash the address and use that to map
+ * to a spinlock. Instead assign a spinlock on initialization of the atomic
+ * variable.
+ */
+#if !defined(PG_HAVE_ATOMIC_FLAG_SUPPORT) && !defined(PG_HAVE_ATOMIC_U32_SUPPORT)
+
+#define PG_HAVE_ATOMIC_FLAG_SIMULATION
+#define PG_HAVE_ATOMIC_FLAG_SUPPORT
+
+typedef struct pg_atomic_flag
+{
+ /*
+ * To avoid circular includes we can't use s_lock as a type here. Instead
+ * just reserve enough space for all spinlock types. Some platforms would
+ * be content with just one byte instead of 4, but that's not too much
+ * waste.
+ */
+#if defined(__hppa) || defined(__hppa__) /* HP PA-RISC, GCC and HP compilers */
+ int sema[4];
+#else
+ int sema;
+#endif
+ volatile bool value;
+} pg_atomic_flag;
+
+#endif /* PG_HAVE_ATOMIC_FLAG_SUPPORT */
+
+#if !defined(PG_HAVE_ATOMIC_U32_SUPPORT)
+
+#define PG_HAVE_ATOMIC_U32_SIMULATION
+
+#define PG_HAVE_ATOMIC_U32_SUPPORT
+typedef struct pg_atomic_uint32
+{
+ /* Check pg_atomic_flag's definition above for an explanation */
+#if defined(__hppa) || defined(__hppa__) /* HP PA-RISC, GCC and HP compilers */
+ int sema[4];
+#else
+ int sema;
+#endif
+ volatile uint32 value;
+} pg_atomic_uint32;
+
+#endif /* PG_HAVE_ATOMIC_U32_SUPPORT */
+
+#if !defined(PG_HAVE_ATOMIC_U64_SUPPORT)
+
+#define PG_HAVE_ATOMIC_U64_SIMULATION
+
+#define PG_HAVE_ATOMIC_U64_SUPPORT
+typedef struct pg_atomic_uint64
+{
+ /* Check pg_atomic_flag's definition above for an explanation */
+#if defined(__hppa) || defined(__hppa__) /* HP PA-RISC, GCC and HP compilers */
+ int sema[4];
+#else
+ int sema;
+#endif
+ volatile uint64 value;
+} pg_atomic_uint64;
+
+#endif /* PG_HAVE_ATOMIC_U64_SUPPORT */
+
+#ifdef PG_HAVE_ATOMIC_FLAG_SIMULATION
+
+#define PG_HAVE_ATOMIC_INIT_FLAG
+extern void pg_atomic_init_flag_impl(volatile pg_atomic_flag *ptr);
+
+#define PG_HAVE_ATOMIC_TEST_SET_FLAG
+extern bool pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr);
+
+#define PG_HAVE_ATOMIC_CLEAR_FLAG
+extern void pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr);
+
+#define PG_HAVE_ATOMIC_UNLOCKED_TEST_FLAG
+extern bool pg_atomic_unlocked_test_flag_impl(volatile pg_atomic_flag *ptr);
+
+#endif /* PG_HAVE_ATOMIC_FLAG_SIMULATION */
+
+#ifdef PG_HAVE_ATOMIC_U32_SIMULATION
+
+#define PG_HAVE_ATOMIC_INIT_U32
+extern void pg_atomic_init_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val_);
+
+#define PG_HAVE_ATOMIC_WRITE_U32
+extern void pg_atomic_write_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val);
+
+#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
+extern bool pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
+ uint32 *expected, uint32 newval);
+
+#define PG_HAVE_ATOMIC_FETCH_ADD_U32
+extern uint32 pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_);
+
+#endif /* PG_HAVE_ATOMIC_U32_SIMULATION */
+
+
+#ifdef PG_HAVE_ATOMIC_U64_SIMULATION
+
+#define PG_HAVE_ATOMIC_INIT_U64
+extern void pg_atomic_init_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 val_);
+
+#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64
+extern bool pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
+ uint64 *expected, uint64 newval);
+
+#define PG_HAVE_ATOMIC_FETCH_ADD_U64
+extern uint64 pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_);
+
+#endif /* PG_HAVE_ATOMIC_U64_SIMULATION */
diff --git a/src/include/port/atomics/generic-acc.h b/src/include/port/atomics/generic-acc.h
new file mode 100644
index 0000000..195b8f4
--- /dev/null
+++ b/src/include/port/atomics/generic-acc.h
@@ -0,0 +1,106 @@
+/*-------------------------------------------------------------------------
+ *
+ * generic-acc.h
+ * Atomic operations support when using HPs acc on HPUX
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES:
+ *
+ * Documentation:
+ * * inline assembly for Itanium-based HP-UX:
+ * http://h21007.www2.hp.com/portal/download/files/unprot/Itanium/inline_assem_ERS.pdf
+ * * Implementing Spinlocks on the Intel (R) Itanium (R) Architecture and PA-RISC
+ * http://h21007.www2.hp.com/portal/download/files/unprot/itanium/spinlocks.pdf
+ *
+ * Itanium only supports a small set of numbers (6, -8, -4, -1, 1, 4, 8, 16)
+ * for atomic add/sub, so we just implement everything but compare_exchange
+ * via the compare_exchange fallbacks in atomics/generic.h.
+ *
+ * src/include/port/atomics/generic-acc.h
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <machine/sys/inline.h>
+
+#define pg_compiler_barrier_impl() _Asm_sched_fence()
+
+#if defined(HAVE_ATOMICS)
+
+/* IA64 always has 32/64 bit atomics */
+
+#define PG_HAVE_ATOMIC_U32_SUPPORT
+typedef struct pg_atomic_uint32
+{
+ volatile uint32 value;
+} pg_atomic_uint32;
+
+#define PG_HAVE_ATOMIC_U64_SUPPORT
+typedef struct pg_atomic_uint64
+{
+ /*
+ * Alignment is guaranteed to be 64bit. Search for "Well-behaved
+ * application restrictions" => "Data alignment and data sharing" on HP's
+ * website. Unfortunately the URL doesn't seem to stable enough to
+ * include.
+ */
+ volatile uint64 value;
+} pg_atomic_uint64;
+
+
+#define MINOR_FENCE (_Asm_fence) (_UP_CALL_FENCE | _UP_SYS_FENCE | \
+ _DOWN_CALL_FENCE | _DOWN_SYS_FENCE )
+
+#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
+static inline bool
+pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
+ uint32 *expected, uint32 newval)
+{
+ bool ret;
+ uint32 current;
+
+ _Asm_mov_to_ar(_AREG_CCV, *expected, MINOR_FENCE);
+ /*
+ * We want a barrier, not just release/acquire semantics.
+ */
+ _Asm_mf();
+ /*
+ * Notes:
+ * _DOWN_MEM_FENCE | _UP_MEM_FENCE prevents reordering by the compiler
+ */
+ current = _Asm_cmpxchg(_SZ_W, /* word */
+ _SEM_REL,
+ &ptr->value,
+ newval, _LDHINT_NONE,
+ _DOWN_MEM_FENCE | _UP_MEM_FENCE);
+ ret = current == *expected;
+ *expected = current;
+ return ret;
+}
+
+
+#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64
+static inline bool
+pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
+ uint64 *expected, uint64 newval)
+{
+ bool ret;
+ uint64 current;
+
+ _Asm_mov_to_ar(_AREG_CCV, *expected, MINOR_FENCE);
+ _Asm_mf();
+ current = _Asm_cmpxchg(_SZ_D, /* doubleword */
+ _SEM_REL,
+ &ptr->value,
+ newval, _LDHINT_NONE,
+ _DOWN_MEM_FENCE | _UP_MEM_FENCE);
+ ret = current == *expected;
+ *expected = current;
+ return ret;
+}
+
+#undef MINOR_FENCE
+
+#endif /* defined(HAVE_ATOMICS) */
diff --git a/src/include/port/atomics/generic-gcc.h b/src/include/port/atomics/generic-gcc.h
new file mode 100644
index 0000000..2d84305
--- /dev/null
+++ b/src/include/port/atomics/generic-gcc.h
@@ -0,0 +1,286 @@
+/*-------------------------------------------------------------------------
+ *
+ * generic-gcc.h
+ * Atomic operations, implemented using gcc (or compatible) intrinsics.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES:
+ *
+ * Documentation:
+ * * Legacy __sync Built-in Functions for Atomic Memory Access
+ * http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/_005f_005fsync-Builtins.html
+ * * Built-in functions for memory model aware atomic operations
+ * http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/_005f_005fatomic-Builtins.html
+ *
+ * src/include/port/atomics/generic-gcc.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* intentionally no include guards, should only be included by atomics.h */
+#ifndef INSIDE_ATOMICS_H
+#error "should be included via atomics.h"
+#endif
+
+/*
+ * An empty asm block should be a sufficient compiler barrier.
+ */
+#define pg_compiler_barrier_impl() __asm__ __volatile__("" ::: "memory")
+
+/*
+ * If we're on GCC 4.1.0 or higher, we should be able to get a memory barrier
+ * out of this compiler built-in. But we prefer to rely on platform specific
+ * definitions where possible, and use this only as a fallback.
+ */
+#if !defined(pg_memory_barrier_impl)
+# if defined(HAVE_GCC__ATOMIC_INT32_CAS)
+# define pg_memory_barrier_impl() __atomic_thread_fence(__ATOMIC_SEQ_CST)
+# elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
+# define pg_memory_barrier_impl() __sync_synchronize()
+# endif
+#endif /* !defined(pg_memory_barrier_impl) */
+
+#if !defined(pg_read_barrier_impl) && defined(HAVE_GCC__ATOMIC_INT32_CAS)
+/* acquire semantics include read barrier semantics */
+# define pg_read_barrier_impl() __atomic_thread_fence(__ATOMIC_ACQUIRE)
+#endif
+
+#if !defined(pg_write_barrier_impl) && defined(HAVE_GCC__ATOMIC_INT32_CAS)
+/* release semantics include write barrier semantics */
+# define pg_write_barrier_impl() __atomic_thread_fence(__ATOMIC_RELEASE)
+#endif
+
+
+#ifdef HAVE_ATOMICS
+
+/* generic gcc based atomic flag implementation */
+#if !defined(PG_HAVE_ATOMIC_FLAG_SUPPORT) \
+ && (defined(HAVE_GCC__SYNC_INT32_TAS) || defined(HAVE_GCC__SYNC_CHAR_TAS))
+
+#define PG_HAVE_ATOMIC_FLAG_SUPPORT
+typedef struct pg_atomic_flag
+{
+ /*
+ * If we have a choice, use int-width TAS, because that is more efficient
+ * and/or more reliably implemented on most non-Intel platforms. (Note
+ * that this code isn't used on x86[_64]; see arch-x86.h for that.)
+ */
+#ifdef HAVE_GCC__SYNC_INT32_TAS
+ volatile int value;
+#else
+ volatile char value;
+#endif
+} pg_atomic_flag;
+
+#endif /* !ATOMIC_FLAG_SUPPORT && SYNC_INT32_TAS */
+
+/* generic gcc based atomic uint32 implementation */
+#if !defined(PG_HAVE_ATOMIC_U32_SUPPORT) \
+ && (defined(HAVE_GCC__ATOMIC_INT32_CAS) || defined(HAVE_GCC__SYNC_INT32_CAS))
+
+#define PG_HAVE_ATOMIC_U32_SUPPORT
+typedef struct pg_atomic_uint32
+{
+ volatile uint32 value;
+} pg_atomic_uint32;
+
+#endif /* defined(HAVE_GCC__ATOMIC_INT32_CAS) || defined(HAVE_GCC__SYNC_INT32_CAS) */
+
+/* generic gcc based atomic uint64 implementation */
+#if !defined(PG_HAVE_ATOMIC_U64_SUPPORT) \
+ && !defined(PG_DISABLE_64_BIT_ATOMICS) \
+ && (defined(HAVE_GCC__ATOMIC_INT64_CAS) || defined(HAVE_GCC__SYNC_INT64_CAS))
+
+#define PG_HAVE_ATOMIC_U64_SUPPORT
+
+typedef struct pg_atomic_uint64
+{
+ volatile uint64 value pg_attribute_aligned(8);
+} pg_atomic_uint64;
+
+#endif /* defined(HAVE_GCC__ATOMIC_INT64_CAS) || defined(HAVE_GCC__SYNC_INT64_CAS) */
+
+#ifdef PG_HAVE_ATOMIC_FLAG_SUPPORT
+
+#if defined(HAVE_GCC__SYNC_CHAR_TAS) || defined(HAVE_GCC__SYNC_INT32_TAS)
+
+#ifndef PG_HAVE_ATOMIC_TEST_SET_FLAG
+#define PG_HAVE_ATOMIC_TEST_SET_FLAG
+static inline bool
+pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ /* NB: only an acquire barrier, not a full one */
+ /* some platform only support a 1 here */
+ return __sync_lock_test_and_set(&ptr->value, 1) == 0;
+}
+#endif
+
+#endif /* defined(HAVE_GCC__SYNC_*_TAS) */
+
+#ifndef PG_HAVE_ATOMIC_UNLOCKED_TEST_FLAG
+#define PG_HAVE_ATOMIC_UNLOCKED_TEST_FLAG
+static inline bool
+pg_atomic_unlocked_test_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ return ptr->value == 0;
+}
+#endif
+
+#ifndef PG_HAVE_ATOMIC_CLEAR_FLAG
+#define PG_HAVE_ATOMIC_CLEAR_FLAG
+static inline void
+pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ __sync_lock_release(&ptr->value);
+}
+#endif
+
+#ifndef PG_HAVE_ATOMIC_INIT_FLAG
+#define PG_HAVE_ATOMIC_INIT_FLAG
+static inline void
+pg_atomic_init_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ pg_atomic_clear_flag_impl(ptr);
+}
+#endif
+
+#endif /* defined(PG_HAVE_ATOMIC_FLAG_SUPPORT) */
+
+/* prefer __atomic, it has a better API */
+#if !defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32) && defined(HAVE_GCC__ATOMIC_INT32_CAS)
+#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
+static inline bool
+pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
+ uint32 *expected, uint32 newval)
+{
+ /* FIXME: we can probably use a lower consistency model */
+ return __atomic_compare_exchange_n(&ptr->value, expected, newval, false,
+ __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32) && defined(HAVE_GCC__SYNC_INT32_CAS)
+#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
+static inline bool
+pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
+ uint32 *expected, uint32 newval)
+{
+ bool ret;
+ uint32 current;
+ current = __sync_val_compare_and_swap(&ptr->value, *expected, newval);
+ ret = current == *expected;
+ *expected = current;
+ return ret;
+}
+#endif
+
+/* if we have 32-bit __sync_val_compare_and_swap, assume we have these too: */
+
+#if !defined(PG_HAVE_ATOMIC_FETCH_ADD_U32) && defined(HAVE_GCC__SYNC_INT32_CAS)
+#define PG_HAVE_ATOMIC_FETCH_ADD_U32
+static inline uint32
+pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
+{
+ return __sync_fetch_and_add(&ptr->value, add_);
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_FETCH_SUB_U32) && defined(HAVE_GCC__SYNC_INT32_CAS)
+#define PG_HAVE_ATOMIC_FETCH_SUB_U32
+static inline uint32
+pg_atomic_fetch_sub_u32_impl(volatile pg_atomic_uint32 *ptr, int32 sub_)
+{
+ return __sync_fetch_and_sub(&ptr->value, sub_);
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_FETCH_AND_U32) && defined(HAVE_GCC__SYNC_INT32_CAS)
+#define PG_HAVE_ATOMIC_FETCH_AND_U32
+static inline uint32
+pg_atomic_fetch_and_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 and_)
+{
+ return __sync_fetch_and_and(&ptr->value, and_);
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_FETCH_OR_U32) && defined(HAVE_GCC__SYNC_INT32_CAS)
+#define PG_HAVE_ATOMIC_FETCH_OR_U32
+static inline uint32
+pg_atomic_fetch_or_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 or_)
+{
+ return __sync_fetch_and_or(&ptr->value, or_);
+}
+#endif
+
+
+#if !defined(PG_DISABLE_64_BIT_ATOMICS)
+
+#if !defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64) && defined(HAVE_GCC__ATOMIC_INT64_CAS)
+#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64
+static inline bool
+pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
+ uint64 *expected, uint64 newval)
+{
+ return __atomic_compare_exchange_n(&ptr->value, expected, newval, false,
+ __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64) && defined(HAVE_GCC__SYNC_INT64_CAS)
+#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64
+static inline bool
+pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
+ uint64 *expected, uint64 newval)
+{
+ bool ret;
+ uint64 current;
+ current = __sync_val_compare_and_swap(&ptr->value, *expected, newval);
+ ret = current == *expected;
+ *expected = current;
+ return ret;
+}
+#endif
+
+/* if we have 64-bit __sync_val_compare_and_swap, assume we have these too: */
+
+#if !defined(PG_HAVE_ATOMIC_FETCH_ADD_U64) && defined(HAVE_GCC__SYNC_INT64_CAS)
+#define PG_HAVE_ATOMIC_FETCH_ADD_U64
+static inline uint64
+pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
+{
+ return __sync_fetch_and_add(&ptr->value, add_);
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_FETCH_SUB_U64) && defined(HAVE_GCC__SYNC_INT64_CAS)
+#define PG_HAVE_ATOMIC_FETCH_SUB_U64
+static inline uint64
+pg_atomic_fetch_sub_u64_impl(volatile pg_atomic_uint64 *ptr, int64 sub_)
+{
+ return __sync_fetch_and_sub(&ptr->value, sub_);
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_FETCH_AND_U64) && defined(HAVE_GCC__SYNC_INT64_CAS)
+#define PG_HAVE_ATOMIC_FETCH_AND_U64
+static inline uint64
+pg_atomic_fetch_and_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 and_)
+{
+ return __sync_fetch_and_and(&ptr->value, and_);
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_FETCH_OR_U64) && defined(HAVE_GCC__SYNC_INT64_CAS)
+#define PG_HAVE_ATOMIC_FETCH_OR_U64
+static inline uint64
+pg_atomic_fetch_or_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 or_)
+{
+ return __sync_fetch_and_or(&ptr->value, or_);
+}
+#endif
+
+#endif /* !defined(PG_DISABLE_64_BIT_ATOMICS) */
+
+#endif /* defined(HAVE_ATOMICS) */
diff --git a/src/include/port/atomics/generic-msvc.h b/src/include/port/atomics/generic-msvc.h
new file mode 100644
index 0000000..c74c609
--- /dev/null
+++ b/src/include/port/atomics/generic-msvc.h
@@ -0,0 +1,101 @@
+/*-------------------------------------------------------------------------
+ *
+ * generic-msvc.h
+ * Atomic operations support when using MSVC
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES:
+ *
+ * Documentation:
+ * * Interlocked Variable Access
+ * http://msdn.microsoft.com/en-us/library/ms684122%28VS.85%29.aspx
+ *
+ * src/include/port/atomics/generic-msvc.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <intrin.h>
+
+/* intentionally no include guards, should only be included by atomics.h */
+#ifndef INSIDE_ATOMICS_H
+#error "should be included via atomics.h"
+#endif
+
+#pragma intrinsic(_ReadWriteBarrier)
+#define pg_compiler_barrier_impl() _ReadWriteBarrier()
+
+#ifndef pg_memory_barrier_impl
+#define pg_memory_barrier_impl() MemoryBarrier()
+#endif
+
+#if defined(HAVE_ATOMICS)
+
+#define PG_HAVE_ATOMIC_U32_SUPPORT
+typedef struct pg_atomic_uint32
+{
+ volatile uint32 value;
+} pg_atomic_uint32;
+
+#define PG_HAVE_ATOMIC_U64_SUPPORT
+typedef struct __declspec(align(8)) pg_atomic_uint64
+{
+ volatile uint64 value;
+} pg_atomic_uint64;
+
+
+#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
+static inline bool
+pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
+ uint32 *expected, uint32 newval)
+{
+ bool ret;
+ uint32 current;
+ current = InterlockedCompareExchange(&ptr->value, newval, *expected);
+ ret = current == *expected;
+ *expected = current;
+ return ret;
+}
+
+#define PG_HAVE_ATOMIC_FETCH_ADD_U32
+static inline uint32
+pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
+{
+ return InterlockedExchangeAdd(&ptr->value, add_);
+}
+
+/*
+ * The non-intrinsics versions are only available in vista upwards, so use the
+ * intrinsic version. Only supported on >486, but we require XP as a minimum
+ * baseline, which doesn't support the 486, so we don't need to add checks for
+ * that case.
+ */
+#pragma intrinsic(_InterlockedCompareExchange64)
+
+#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64
+static inline bool
+pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
+ uint64 *expected, uint64 newval)
+{
+ bool ret;
+ uint64 current;
+ current = _InterlockedCompareExchange64(&ptr->value, newval, *expected);
+ ret = current == *expected;
+ *expected = current;
+ return ret;
+}
+
+/* Only implemented on itanium and 64bit builds */
+#ifdef _WIN64
+#pragma intrinsic(_InterlockedExchangeAdd64)
+
+#define PG_HAVE_ATOMIC_FETCH_ADD_U64
+static inline uint64
+pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
+{
+ return _InterlockedExchangeAdd64(&ptr->value, add_);
+}
+#endif /* _WIN64 */
+
+#endif /* HAVE_ATOMICS */
diff --git a/src/include/port/atomics/generic-sunpro.h b/src/include/port/atomics/generic-sunpro.h
new file mode 100644
index 0000000..9aaeb73
--- /dev/null
+++ b/src/include/port/atomics/generic-sunpro.h
@@ -0,0 +1,106 @@
+/*-------------------------------------------------------------------------
+ *
+ * generic-sunpro.h
+ * Atomic operations for solaris' CC
+ *
+ * Portions Copyright (c) 2013-2020, PostgreSQL Global Development Group
+ *
+ * NOTES:
+ *
+ * Documentation:
+ * * manpage for atomic_cas(3C)
+ * http://www.unix.com/man-page/opensolaris/3c/atomic_cas/
+ * http://docs.oracle.com/cd/E23824_01/html/821-1465/atomic-cas-3c.html
+ *
+ * src/include/port/atomics/generic-sunpro.h
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#if defined(HAVE_ATOMICS)
+
+#ifdef HAVE_MBARRIER_H
+#include <mbarrier.h>
+
+#define pg_compiler_barrier_impl() __compiler_barrier()
+
+#ifndef pg_memory_barrier_impl
+/*
+ * Despite the name this is actually a full barrier. Expanding to mfence/
+ * membar #StoreStore | #LoadStore | #StoreLoad | #LoadLoad on x86/sparc
+ * respectively.
+ */
+# define pg_memory_barrier_impl() __machine_rw_barrier()
+#endif
+#ifndef pg_read_barrier_impl
+# define pg_read_barrier_impl() __machine_r_barrier()
+#endif
+#ifndef pg_write_barrier_impl
+# define pg_write_barrier_impl() __machine_w_barrier()
+#endif
+
+#endif /* HAVE_MBARRIER_H */
+
+/* Older versions of the compiler don't have atomic.h... */
+#ifdef HAVE_ATOMIC_H
+
+#include <atomic.h>
+
+#define PG_HAVE_ATOMIC_U32_SUPPORT
+typedef struct pg_atomic_uint32
+{
+ volatile uint32 value;
+} pg_atomic_uint32;
+
+#define PG_HAVE_ATOMIC_U64_SUPPORT
+typedef struct pg_atomic_uint64
+{
+ /*
+ * Syntax to enforce variable alignment should be supported by versions
+ * supporting atomic.h, but it's hard to find accurate documentation. If
+ * it proves to be a problem, we'll have to add more version checks for 64
+ * bit support.
+ */
+ volatile uint64 value pg_attribute_aligned(8);
+} pg_atomic_uint64;
+
+#endif /* HAVE_ATOMIC_H */
+
+#endif /* defined(HAVE_ATOMICS) */
+
+
+#if defined(HAVE_ATOMICS)
+
+#ifdef HAVE_ATOMIC_H
+
+#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
+static inline bool
+pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
+ uint32 *expected, uint32 newval)
+{
+ bool ret;
+ uint32 current;
+
+ current = atomic_cas_32(&ptr->value, *expected, newval);
+ ret = current == *expected;
+ *expected = current;
+ return ret;
+}
+
+#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64
+static inline bool
+pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
+ uint64 *expected, uint64 newval)
+{
+ bool ret;
+ uint64 current;
+
+ current = atomic_cas_64(&ptr->value, *expected, newval);
+ ret = current == *expected;
+ *expected = current;
+ return ret;
+}
+
+#endif /* HAVE_ATOMIC_H */
+
+#endif /* defined(HAVE_ATOMICS) */
diff --git a/src/include/port/atomics/generic.h b/src/include/port/atomics/generic.h
new file mode 100644
index 0000000..d60a0d9
--- /dev/null
+++ b/src/include/port/atomics/generic.h
@@ -0,0 +1,401 @@
+/*-------------------------------------------------------------------------
+ *
+ * generic.h
+ * Implement higher level operations based on some lower level atomic
+ * operations.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/port/atomics/generic.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* intentionally no include guards, should only be included by atomics.h */
+#ifndef INSIDE_ATOMICS_H
+# error "should be included via atomics.h"
+#endif
+
+/*
+ * If read or write barriers are undefined, we upgrade them to full memory
+ * barriers.
+ */
+#if !defined(pg_read_barrier_impl)
+# define pg_read_barrier_impl pg_memory_barrier_impl
+#endif
+#if !defined(pg_write_barrier_impl)
+# define pg_write_barrier_impl pg_memory_barrier_impl
+#endif
+
+#ifndef PG_HAVE_SPIN_DELAY
+#define PG_HAVE_SPIN_DELAY
+#define pg_spin_delay_impl() ((void)0)
+#endif
+
+
+/* provide fallback */
+#if !defined(PG_HAVE_ATOMIC_FLAG_SUPPORT) && defined(PG_HAVE_ATOMIC_U32_SUPPORT)
+#define PG_HAVE_ATOMIC_FLAG_SUPPORT
+typedef pg_atomic_uint32 pg_atomic_flag;
+#endif
+
+#ifndef PG_HAVE_ATOMIC_READ_U32
+#define PG_HAVE_ATOMIC_READ_U32
+static inline uint32
+pg_atomic_read_u32_impl(volatile pg_atomic_uint32 *ptr)
+{
+ return ptr->value;
+}
+#endif
+
+#ifndef PG_HAVE_ATOMIC_WRITE_U32
+#define PG_HAVE_ATOMIC_WRITE_U32
+static inline void
+pg_atomic_write_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val)
+{
+ ptr->value = val;
+}
+#endif
+
+#ifndef PG_HAVE_ATOMIC_UNLOCKED_WRITE_U32
+#define PG_HAVE_ATOMIC_UNLOCKED_WRITE_U32
+static inline void
+pg_atomic_unlocked_write_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val)
+{
+ ptr->value = val;
+}
+#endif
+
+/*
+ * provide fallback for test_and_set using atomic_exchange if available
+ */
+#if !defined(PG_HAVE_ATOMIC_TEST_SET_FLAG) && defined(PG_HAVE_ATOMIC_EXCHANGE_U32)
+
+#define PG_HAVE_ATOMIC_INIT_FLAG
+static inline void
+pg_atomic_init_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ pg_atomic_write_u32_impl(ptr, 0);
+}
+
+#define PG_HAVE_ATOMIC_TEST_SET_FLAG
+static inline bool
+pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ return pg_atomic_exchange_u32_impl(ptr, &value, 1) == 0;
+}
+
+#define PG_HAVE_ATOMIC_UNLOCKED_TEST_FLAG
+static inline bool
+pg_atomic_unlocked_test_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ return pg_atomic_read_u32_impl(ptr) == 0;
+}
+
+
+#define PG_HAVE_ATOMIC_CLEAR_FLAG
+static inline void
+pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ /* XXX: release semantics suffice? */
+ pg_memory_barrier_impl();
+ pg_atomic_write_u32_impl(ptr, 0);
+}
+
+/*
+ * provide fallback for test_and_set using atomic_compare_exchange if
+ * available.
+ */
+#elif !defined(PG_HAVE_ATOMIC_TEST_SET_FLAG) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32)
+
+#define PG_HAVE_ATOMIC_INIT_FLAG
+static inline void
+pg_atomic_init_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ pg_atomic_write_u32_impl(ptr, 0);
+}
+
+#define PG_HAVE_ATOMIC_TEST_SET_FLAG
+static inline bool
+pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ uint32 value = 0;
+ return pg_atomic_compare_exchange_u32_impl(ptr, &value, 1);
+}
+
+#define PG_HAVE_ATOMIC_UNLOCKED_TEST_FLAG
+static inline bool
+pg_atomic_unlocked_test_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ return pg_atomic_read_u32_impl(ptr) == 0;
+}
+
+#define PG_HAVE_ATOMIC_CLEAR_FLAG
+static inline void
+pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ /*
+ * Use a memory barrier + plain write if we have a native memory
+ * barrier. But don't do so if memory barriers use spinlocks - that'd lead
+ * to circularity if flags are used to implement spinlocks.
+ */
+#ifndef PG_HAVE_MEMORY_BARRIER_EMULATION
+ /* XXX: release semantics suffice? */
+ pg_memory_barrier_impl();
+ pg_atomic_write_u32_impl(ptr, 0);
+#else
+ uint32 value = 1;
+ pg_atomic_compare_exchange_u32_impl(ptr, &value, 0);
+#endif
+}
+
+#elif !defined(PG_HAVE_ATOMIC_TEST_SET_FLAG)
+# error "No pg_atomic_test_and_set provided"
+#endif /* !defined(PG_HAVE_ATOMIC_TEST_SET_FLAG) */
+
+
+#ifndef PG_HAVE_ATOMIC_INIT_U32
+#define PG_HAVE_ATOMIC_INIT_U32
+static inline void
+pg_atomic_init_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val_)
+{
+ ptr->value = val_;
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_EXCHANGE_U32) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32)
+#define PG_HAVE_ATOMIC_EXCHANGE_U32
+static inline uint32
+pg_atomic_exchange_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 xchg_)
+{
+ uint32 old;
+ old = ptr->value; /* ok if read is not atomic */
+ while (!pg_atomic_compare_exchange_u32_impl(ptr, &old, xchg_))
+ /* skip */;
+ return old;
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_FETCH_ADD_U32) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32)
+#define PG_HAVE_ATOMIC_FETCH_ADD_U32
+static inline uint32
+pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
+{
+ uint32 old;
+ old = ptr->value; /* ok if read is not atomic */
+ while (!pg_atomic_compare_exchange_u32_impl(ptr, &old, old + add_))
+ /* skip */;
+ return old;
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_FETCH_SUB_U32) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32)
+#define PG_HAVE_ATOMIC_FETCH_SUB_U32
+static inline uint32
+pg_atomic_fetch_sub_u32_impl(volatile pg_atomic_uint32 *ptr, int32 sub_)
+{
+ return pg_atomic_fetch_add_u32_impl(ptr, -sub_);
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_FETCH_AND_U32) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32)
+#define PG_HAVE_ATOMIC_FETCH_AND_U32
+static inline uint32
+pg_atomic_fetch_and_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 and_)
+{
+ uint32 old;
+ old = ptr->value; /* ok if read is not atomic */
+ while (!pg_atomic_compare_exchange_u32_impl(ptr, &old, old & and_))
+ /* skip */;
+ return old;
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_FETCH_OR_U32) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32)
+#define PG_HAVE_ATOMIC_FETCH_OR_U32
+static inline uint32
+pg_atomic_fetch_or_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 or_)
+{
+ uint32 old;
+ old = ptr->value; /* ok if read is not atomic */
+ while (!pg_atomic_compare_exchange_u32_impl(ptr, &old, old | or_))
+ /* skip */;
+ return old;
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_ADD_FETCH_U32) && defined(PG_HAVE_ATOMIC_FETCH_ADD_U32)
+#define PG_HAVE_ATOMIC_ADD_FETCH_U32
+static inline uint32
+pg_atomic_add_fetch_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
+{
+ return pg_atomic_fetch_add_u32_impl(ptr, add_) + add_;
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_SUB_FETCH_U32) && defined(PG_HAVE_ATOMIC_FETCH_SUB_U32)
+#define PG_HAVE_ATOMIC_SUB_FETCH_U32
+static inline uint32
+pg_atomic_sub_fetch_u32_impl(volatile pg_atomic_uint32 *ptr, int32 sub_)
+{
+ return pg_atomic_fetch_sub_u32_impl(ptr, sub_) - sub_;
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_EXCHANGE_U64) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64)
+#define PG_HAVE_ATOMIC_EXCHANGE_U64
+static inline uint64
+pg_atomic_exchange_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 xchg_)
+{
+ uint64 old;
+ old = ptr->value; /* ok if read is not atomic */
+ while (!pg_atomic_compare_exchange_u64_impl(ptr, &old, xchg_))
+ /* skip */;
+ return old;
+}
+#endif
+
+#ifndef PG_HAVE_ATOMIC_WRITE_U64
+#define PG_HAVE_ATOMIC_WRITE_U64
+
+#if defined(PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY) && \
+ !defined(PG_HAVE_ATOMIC_U64_SIMULATION)
+
+static inline void
+pg_atomic_write_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 val)
+{
+ /*
+ * On this platform aligned 64bit writes are guaranteed to be atomic,
+ * except if using the fallback implementation, where can't guarantee the
+ * required alignment.
+ */
+ AssertPointerAlignment(ptr, 8);
+ ptr->value = val;
+}
+
+#else
+
+static inline void
+pg_atomic_write_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 val)
+{
+ /*
+ * 64 bit writes aren't safe on all platforms. In the generic
+ * implementation implement them as an atomic exchange.
+ */
+ pg_atomic_exchange_u64_impl(ptr, val);
+}
+
+#endif /* PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY && !PG_HAVE_ATOMIC_U64_SIMULATION */
+#endif /* PG_HAVE_ATOMIC_WRITE_U64 */
+
+#ifndef PG_HAVE_ATOMIC_READ_U64
+#define PG_HAVE_ATOMIC_READ_U64
+
+#if defined(PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY) && \
+ !defined(PG_HAVE_ATOMIC_U64_SIMULATION)
+
+static inline uint64
+pg_atomic_read_u64_impl(volatile pg_atomic_uint64 *ptr)
+{
+ /*
+ * On this platform aligned 64-bit reads are guaranteed to be atomic.
+ */
+ AssertPointerAlignment(ptr, 8);
+ return ptr->value;
+}
+
+#else
+
+static inline uint64
+pg_atomic_read_u64_impl(volatile pg_atomic_uint64 *ptr)
+{
+ uint64 old = 0;
+
+ /*
+ * 64-bit reads aren't atomic on all platforms. In the generic
+ * implementation implement them as a compare/exchange with 0. That'll
+ * fail or succeed, but always return the old value. Possibly might store
+ * a 0, but only if the previous value also was a 0 - i.e. harmless.
+ */
+ pg_atomic_compare_exchange_u64_impl(ptr, &old, 0);
+
+ return old;
+}
+#endif /* PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY && !PG_HAVE_ATOMIC_U64_SIMULATION */
+#endif /* PG_HAVE_ATOMIC_READ_U64 */
+
+#ifndef PG_HAVE_ATOMIC_INIT_U64
+#define PG_HAVE_ATOMIC_INIT_U64
+static inline void
+pg_atomic_init_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 val_)
+{
+ ptr->value = val_;
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_FETCH_ADD_U64) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64)
+#define PG_HAVE_ATOMIC_FETCH_ADD_U64
+static inline uint64
+pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
+{
+ uint64 old;
+ old = ptr->value; /* ok if read is not atomic */
+ while (!pg_atomic_compare_exchange_u64_impl(ptr, &old, old + add_))
+ /* skip */;
+ return old;
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_FETCH_SUB_U64) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64)
+#define PG_HAVE_ATOMIC_FETCH_SUB_U64
+static inline uint64
+pg_atomic_fetch_sub_u64_impl(volatile pg_atomic_uint64 *ptr, int64 sub_)
+{
+ return pg_atomic_fetch_add_u64_impl(ptr, -sub_);
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_FETCH_AND_U64) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64)
+#define PG_HAVE_ATOMIC_FETCH_AND_U64
+static inline uint64
+pg_atomic_fetch_and_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 and_)
+{
+ uint64 old;
+ old = ptr->value; /* ok if read is not atomic */
+ while (!pg_atomic_compare_exchange_u64_impl(ptr, &old, old & and_))
+ /* skip */;
+ return old;
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_FETCH_OR_U64) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64)
+#define PG_HAVE_ATOMIC_FETCH_OR_U64
+static inline uint64
+pg_atomic_fetch_or_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 or_)
+{
+ uint64 old;
+ old = ptr->value; /* ok if read is not atomic */
+ while (!pg_atomic_compare_exchange_u64_impl(ptr, &old, old | or_))
+ /* skip */;
+ return old;
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_ADD_FETCH_U64) && defined(PG_HAVE_ATOMIC_FETCH_ADD_U64)
+#define PG_HAVE_ATOMIC_ADD_FETCH_U64
+static inline uint64
+pg_atomic_add_fetch_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
+{
+ return pg_atomic_fetch_add_u64_impl(ptr, add_) + add_;
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_SUB_FETCH_U64) && defined(PG_HAVE_ATOMIC_FETCH_SUB_U64)
+#define PG_HAVE_ATOMIC_SUB_FETCH_U64
+static inline uint64
+pg_atomic_sub_fetch_u64_impl(volatile pg_atomic_uint64 *ptr, int64 sub_)
+{
+ return pg_atomic_fetch_sub_u64_impl(ptr, sub_) - sub_;
+}
+#endif
diff --git a/src/include/port/cygwin.h b/src/include/port/cygwin.h
new file mode 100644
index 0000000..f1fc1a9
--- /dev/null
+++ b/src/include/port/cygwin.h
@@ -0,0 +1,26 @@
+/* src/include/port/cygwin.h */
+
+#include <cygwin/version.h>
+
+/*
+ * Check for b20.1 and disable AF_UNIX family socket support.
+ */
+#if CYGWIN_VERSION_DLL_MAJOR < 1001
+#undef HAVE_UNIX_SOCKETS
+#endif
+
+#ifdef BUILDING_DLL
+#define PGDLLIMPORT __declspec (dllexport)
+#else
+#define PGDLLIMPORT __declspec (dllimport)
+#endif
+
+#define PGDLLEXPORT
+
+/*
+ * Cygwin has a strtof() which is literally just (float)strtod(), which means
+ * we get misrounding _and_ silent over/underflow. Using our wrapper doesn't
+ * fix the misrounding but does fix the error checks, which cuts down on the
+ * number of test variant files needed.
+ */
+#define HAVE_BUGGY_STRTOF 1
diff --git a/src/include/port/darwin.h b/src/include/port/darwin.h
new file mode 100644
index 0000000..15fb69d
--- /dev/null
+++ b/src/include/port/darwin.h
@@ -0,0 +1,8 @@
+/* src/include/port/darwin.h */
+
+#define __darwin__ 1
+
+#if HAVE_DECL_F_FULLFSYNC /* not present before macOS 10.3 */
+#define HAVE_FSYNC_WRITETHROUGH
+
+#endif
diff --git a/src/include/port/freebsd.h b/src/include/port/freebsd.h
new file mode 100644
index 0000000..2e2e749
--- /dev/null
+++ b/src/include/port/freebsd.h
@@ -0,0 +1,10 @@
+/* src/include/port/freebsd.h */
+
+/*
+ * Set the default wal_sync_method to fdatasync. xlogdefs.h's normal rules
+ * would prefer open_datasync on FreeBSD 13+, but that is not a good choice on
+ * many systems.
+ */
+#ifdef HAVE_FDATASYNC
+#define PLATFORM_DEFAULT_SYNC_METHOD SYNC_METHOD_FDATASYNC
+#endif
diff --git a/src/include/port/hpux.h b/src/include/port/hpux.h
new file mode 100644
index 0000000..4d1dcea
--- /dev/null
+++ b/src/include/port/hpux.h
@@ -0,0 +1,3 @@
+/* src/include/port/hpux.h */
+
+/* nothing needed */
diff --git a/src/include/port/linux.h b/src/include/port/linux.h
new file mode 100644
index 0000000..7a6e46c
--- /dev/null
+++ b/src/include/port/linux.h
@@ -0,0 +1,22 @@
+/* src/include/port/linux.h */
+
+/*
+ * As of July 2007, all known versions of the Linux kernel will sometimes
+ * return EIDRM for a shmctl() operation when EINVAL is correct (it happens
+ * when the low-order 15 bits of the supplied shm ID match the slot number
+ * assigned to a newer shmem segment). We deal with this by assuming that
+ * EIDRM means EINVAL in PGSharedMemoryIsInUse(). This is reasonably safe
+ * since in fact Linux has no excuse for ever returning EIDRM; it doesn't
+ * track removed segments in a way that would allow distinguishing them from
+ * private ones. But someday that code might get upgraded, and we'd have
+ * to have a kernel version test here.
+ */
+#define HAVE_LINUX_EIDRM_BUG
+
+/*
+ * Set the default wal_sync_method to fdatasync. With recent Linux versions,
+ * xlogdefs.h's normal rules will prefer open_datasync, which (a) doesn't
+ * perform better and (b) causes outright failures on ext4 data=journal
+ * filesystems, because those don't support O_DIRECT.
+ */
+#define PLATFORM_DEFAULT_SYNC_METHOD SYNC_METHOD_FDATASYNC
diff --git a/src/include/port/netbsd.h b/src/include/port/netbsd.h
new file mode 100644
index 0000000..590233f
--- /dev/null
+++ b/src/include/port/netbsd.h
@@ -0,0 +1 @@
+/* src/include/port/netbsd.h */
diff --git a/src/include/port/openbsd.h b/src/include/port/openbsd.h
new file mode 100644
index 0000000..395319b
--- /dev/null
+++ b/src/include/port/openbsd.h
@@ -0,0 +1 @@
+/* src/include/port/openbsd.h */
diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h
new file mode 100644
index 0000000..77fe42c
--- /dev/null
+++ b/src/include/port/pg_bitutils.h
@@ -0,0 +1,272 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_bitutils.h
+ * Miscellaneous functions for bit-wise operations.
+ *
+ *
+ * Copyright (c) 2019-2020, PostgreSQL Global Development Group
+ *
+ * src/include/port/pg_bitutils.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_BITUTILS_H
+#define PG_BITUTILS_H
+
+#ifndef FRONTEND
+extern PGDLLIMPORT const uint8 pg_leftmost_one_pos[256];
+extern PGDLLIMPORT const uint8 pg_rightmost_one_pos[256];
+extern PGDLLIMPORT const uint8 pg_number_of_ones[256];
+#else
+extern const uint8 pg_leftmost_one_pos[256];
+extern const uint8 pg_rightmost_one_pos[256];
+extern const uint8 pg_number_of_ones[256];
+#endif
+
+/*
+ * pg_leftmost_one_pos32
+ * Returns the position of the most significant set bit in "word",
+ * measured from the least significant bit. word must not be 0.
+ */
+static inline int
+pg_leftmost_one_pos32(uint32 word)
+{
+#ifdef HAVE__BUILTIN_CLZ
+ Assert(word != 0);
+
+ return 31 - __builtin_clz(word);
+#else
+ int shift = 32 - 8;
+
+ Assert(word != 0);
+
+ while ((word >> shift) == 0)
+ shift -= 8;
+
+ return shift + pg_leftmost_one_pos[(word >> shift) & 255];
+#endif /* HAVE__BUILTIN_CLZ */
+}
+
+/*
+ * pg_leftmost_one_pos64
+ * As above, but for a 64-bit word.
+ */
+static inline int
+pg_leftmost_one_pos64(uint64 word)
+{
+#ifdef HAVE__BUILTIN_CLZ
+ Assert(word != 0);
+
+#if defined(HAVE_LONG_INT_64)
+ return 63 - __builtin_clzl(word);
+#elif defined(HAVE_LONG_LONG_INT_64)
+ return 63 - __builtin_clzll(word);
+#else
+#error must have a working 64-bit integer datatype
+#endif
+#else /* !HAVE__BUILTIN_CLZ */
+ int shift = 64 - 8;
+
+ Assert(word != 0);
+
+ while ((word >> shift) == 0)
+ shift -= 8;
+
+ return shift + pg_leftmost_one_pos[(word >> shift) & 255];
+#endif /* HAVE__BUILTIN_CLZ */
+}
+
+/*
+ * pg_rightmost_one_pos32
+ * Returns the position of the least significant set bit in "word",
+ * measured from the least significant bit. word must not be 0.
+ */
+static inline int
+pg_rightmost_one_pos32(uint32 word)
+{
+#ifdef HAVE__BUILTIN_CTZ
+ Assert(word != 0);
+
+ return __builtin_ctz(word);
+#else
+ int result = 0;
+
+ Assert(word != 0);
+
+ while ((word & 255) == 0)
+ {
+ word >>= 8;
+ result += 8;
+ }
+ result += pg_rightmost_one_pos[word & 255];
+ return result;
+#endif /* HAVE__BUILTIN_CTZ */
+}
+
+/*
+ * pg_rightmost_one_pos64
+ * As above, but for a 64-bit word.
+ */
+static inline int
+pg_rightmost_one_pos64(uint64 word)
+{
+#ifdef HAVE__BUILTIN_CTZ
+ Assert(word != 0);
+
+#if defined(HAVE_LONG_INT_64)
+ return __builtin_ctzl(word);
+#elif defined(HAVE_LONG_LONG_INT_64)
+ return __builtin_ctzll(word);
+#else
+#error must have a working 64-bit integer datatype
+#endif
+#else /* !HAVE__BUILTIN_CTZ */
+ int result = 0;
+
+ Assert(word != 0);
+
+ while ((word & 255) == 0)
+ {
+ word >>= 8;
+ result += 8;
+ }
+ result += pg_rightmost_one_pos[word & 255];
+ return result;
+#endif /* HAVE__BUILTIN_CTZ */
+}
+
+/*
+ * pg_nextpower2_32
+ * Returns the next higher power of 2 above 'num', or 'num' if it's
+ * already a power of 2.
+ *
+ * 'num' mustn't be 0 or be above PG_UINT32_MAX / 2 + 1.
+ */
+static inline uint32
+pg_nextpower2_32(uint32 num)
+{
+ Assert(num > 0 && num <= PG_UINT32_MAX / 2 + 1);
+
+ /*
+ * A power 2 number has only 1 bit set. Subtracting 1 from such a number
+ * will turn on all previous bits resulting in no common bits being set
+ * between num and num-1.
+ */
+ if ((num & (num - 1)) == 0)
+ return num; /* already power 2 */
+
+ return ((uint32) 1) << (pg_leftmost_one_pos32(num) + 1);
+}
+
+/*
+ * pg_nextpower2_64
+ * Returns the next higher power of 2 above 'num', or 'num' if it's
+ * already a power of 2.
+ *
+ * 'num' mustn't be 0 or be above PG_UINT64_MAX / 2 + 1.
+ */
+static inline uint64
+pg_nextpower2_64(uint64 num)
+{
+ Assert(num > 0 && num <= PG_UINT64_MAX / 2 + 1);
+
+ /*
+ * A power 2 number has only 1 bit set. Subtracting 1 from such a number
+ * will turn on all previous bits resulting in no common bits being set
+ * between num and num-1.
+ */
+ if ((num & (num - 1)) == 0)
+ return num; /* already power 2 */
+
+ return ((uint64) 1) << (pg_leftmost_one_pos64(num) + 1);
+}
+
+/*
+ * pg_nextpower2_size_t
+ * Returns the next higher power of 2 above 'num', for a size_t input.
+ */
+#if SIZEOF_SIZE_T == 4
+#define pg_nextpower2_size_t(num) pg_nextpower2_32(num)
+#else
+#define pg_nextpower2_size_t(num) pg_nextpower2_64(num)
+#endif
+
+/*
+ * pg_prevpower2_32
+ * Returns the next lower power of 2 below 'num', or 'num' if it's
+ * already a power of 2.
+ *
+ * 'num' mustn't be 0.
+ */
+static inline uint32
+pg_prevpower2_32(uint32 num)
+{
+ return ((uint32) 1) << pg_leftmost_one_pos32(num);
+}
+
+/*
+ * pg_prevpower2_64
+ * Returns the next lower power of 2 below 'num', or 'num' if it's
+ * already a power of 2.
+ *
+ * 'num' mustn't be 0.
+ */
+static inline uint64
+pg_prevpower2_64(uint64 num)
+{
+ return ((uint64) 1) << pg_leftmost_one_pos64(num);
+}
+
+/*
+ * pg_prevpower2_size_t
+ * Returns the next lower power of 2 below 'num', for a size_t input.
+ */
+#if SIZEOF_SIZE_T == 4
+#define pg_prevpower2_size_t(num) pg_prevpower2_32(num)
+#else
+#define pg_prevpower2_size_t(num) pg_prevpower2_64(num)
+#endif
+
+/*
+ * pg_ceil_log2_32
+ * Returns equivalent of ceil(log2(num))
+ */
+static inline uint32
+pg_ceil_log2_32(uint32 num)
+{
+ if (num < 2)
+ return 0;
+ else
+ return pg_leftmost_one_pos32(num - 1) + 1;
+}
+
+/*
+ * pg_ceil_log2_64
+ * Returns equivalent of ceil(log2(num))
+ */
+static inline uint64
+pg_ceil_log2_64(uint64 num)
+{
+ if (num < 2)
+ return 0;
+ else
+ return pg_leftmost_one_pos64(num - 1) + 1;
+}
+
+/* Count the number of one-bits in a uint32 or uint64 */
+extern int (*pg_popcount32) (uint32 word);
+extern int (*pg_popcount64) (uint64 word);
+
+/* Count the number of one-bits in a byte array */
+extern uint64 pg_popcount(const char *buf, int bytes);
+
+/*
+ * Rotate the bits of "word" to the right by n bits.
+ */
+static inline uint32
+pg_rotate_right32(uint32 word, int n)
+{
+ return (word >> n) | (word << (sizeof(word) * BITS_PER_BYTE - n));
+}
+
+#endif /* PG_BITUTILS_H */
diff --git a/src/include/port/pg_bswap.h b/src/include/port/pg_bswap.h
new file mode 100644
index 0000000..9fd14d1
--- /dev/null
+++ b/src/include/port/pg_bswap.h
@@ -0,0 +1,161 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_bswap.h
+ * Byte swapping.
+ *
+ * Macros for reversing the byte order of 16, 32 and 64-bit unsigned integers.
+ * For example, 0xAABBCCDD becomes 0xDDCCBBAA. These are just wrappers for
+ * built-in functions provided by the compiler where support exists.
+ *
+ * Note that all of these functions accept unsigned integers as arguments and
+ * return the same. Use caution when using these wrapper macros with signed
+ * integers.
+ *
+ * Copyright (c) 2015-2020, PostgreSQL Global Development Group
+ *
+ * src/include/port/pg_bswap.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_BSWAP_H
+#define PG_BSWAP_H
+
+
+/*
+ * In all supported versions msvc provides _byteswap_* functions in stdlib.h,
+ * already included by c.h.
+ */
+
+
+/* implementation of uint16 pg_bswap16(uint16) */
+#if defined(HAVE__BUILTIN_BSWAP16)
+
+#define pg_bswap16(x) __builtin_bswap16(x)
+
+#elif defined(_MSC_VER)
+
+#define pg_bswap16(x) _byteswap_ushort(x)
+
+#else
+
+static inline uint16
+pg_bswap16(uint16 x)
+{
+ return
+ ((x << 8) & 0xff00) |
+ ((x >> 8) & 0x00ff);
+}
+
+#endif /* HAVE__BUILTIN_BSWAP16 */
+
+
+/* implementation of uint32 pg_bswap32(uint32) */
+#if defined(HAVE__BUILTIN_BSWAP32)
+
+#define pg_bswap32(x) __builtin_bswap32(x)
+
+#elif defined(_MSC_VER)
+
+#define pg_bswap32(x) _byteswap_ulong(x)
+
+#else
+
+static inline uint32
+pg_bswap32(uint32 x)
+{
+ return
+ ((x << 24) & 0xff000000) |
+ ((x << 8) & 0x00ff0000) |
+ ((x >> 8) & 0x0000ff00) |
+ ((x >> 24) & 0x000000ff);
+}
+
+#endif /* HAVE__BUILTIN_BSWAP32 */
+
+
+/* implementation of uint64 pg_bswap64(uint64) */
+#if defined(HAVE__BUILTIN_BSWAP64)
+
+#define pg_bswap64(x) __builtin_bswap64(x)
+
+
+#elif defined(_MSC_VER)
+
+#define pg_bswap64(x) _byteswap_uint64(x)
+
+#else
+
+static inline uint64
+pg_bswap64(uint64 x)
+{
+ return
+ ((x << 56) & UINT64CONST(0xff00000000000000)) |
+ ((x << 40) & UINT64CONST(0x00ff000000000000)) |
+ ((x << 24) & UINT64CONST(0x0000ff0000000000)) |
+ ((x << 8) & UINT64CONST(0x000000ff00000000)) |
+ ((x >> 8) & UINT64CONST(0x00000000ff000000)) |
+ ((x >> 24) & UINT64CONST(0x0000000000ff0000)) |
+ ((x >> 40) & UINT64CONST(0x000000000000ff00)) |
+ ((x >> 56) & UINT64CONST(0x00000000000000ff));
+}
+#endif /* HAVE__BUILTIN_BSWAP64 */
+
+
+/*
+ * Portable and fast equivalents for ntohs, ntohl, htons, htonl,
+ * additionally extended to 64 bits.
+ */
+#ifdef WORDS_BIGENDIAN
+
+#define pg_hton16(x) (x)
+#define pg_hton32(x) (x)
+#define pg_hton64(x) (x)
+
+#define pg_ntoh16(x) (x)
+#define pg_ntoh32(x) (x)
+#define pg_ntoh64(x) (x)
+
+#else
+
+#define pg_hton16(x) pg_bswap16(x)
+#define pg_hton32(x) pg_bswap32(x)
+#define pg_hton64(x) pg_bswap64(x)
+
+#define pg_ntoh16(x) pg_bswap16(x)
+#define pg_ntoh32(x) pg_bswap32(x)
+#define pg_ntoh64(x) pg_bswap64(x)
+
+#endif /* WORDS_BIGENDIAN */
+
+
+/*
+ * Rearrange the bytes of a Datum from big-endian order into the native byte
+ * order. On big-endian machines, this does nothing at all. Note that the C
+ * type Datum is an unsigned integer type on all platforms.
+ *
+ * One possible application of the DatumBigEndianToNative() macro is to make
+ * bitwise comparisons cheaper. A simple 3-way comparison of Datums
+ * transformed by the macro (based on native, unsigned comparisons) will return
+ * the same result as a memcmp() of the corresponding original Datums, but can
+ * be much cheaper. It's generally safe to do this on big-endian systems
+ * without any special transformation occurring first.
+ *
+ * If SIZEOF_DATUM is not defined, then postgres.h wasn't included and these
+ * macros probably shouldn't be used, so we define nothing. Note that
+ * SIZEOF_DATUM == 8 would evaluate as 0 == 8 in that case, potentially
+ * leading to the wrong implementation being selected and confusing errors, so
+ * defining nothing is safest.
+ */
+#ifdef SIZEOF_DATUM
+#ifdef WORDS_BIGENDIAN
+#define DatumBigEndianToNative(x) (x)
+#else /* !WORDS_BIGENDIAN */
+#if SIZEOF_DATUM == 8
+#define DatumBigEndianToNative(x) pg_bswap64(x)
+#else /* SIZEOF_DATUM != 8 */
+#define DatumBigEndianToNative(x) pg_bswap32(x)
+#endif /* SIZEOF_DATUM == 8 */
+#endif /* WORDS_BIGENDIAN */
+#endif /* SIZEOF_DATUM */
+
+#endif /* PG_BSWAP_H */
diff --git a/src/include/port/pg_crc32c.h b/src/include/port/pg_crc32c.h
new file mode 100644
index 0000000..3c6f906
--- /dev/null
+++ b/src/include/port/pg_crc32c.h
@@ -0,0 +1,101 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_crc32c.h
+ * Routines for computing CRC-32C checksums.
+ *
+ * The speed of CRC-32C calculation has a big impact on performance, so we
+ * jump through some hoops to get the best implementation for each
+ * platform. Some CPU architectures have special instructions for speeding
+ * up CRC calculations (e.g. Intel SSE 4.2), on other platforms we use the
+ * Slicing-by-8 algorithm which uses lookup tables.
+ *
+ * The public interface consists of four macros:
+ *
+ * INIT_CRC32C(crc)
+ * Initialize a CRC accumulator
+ *
+ * COMP_CRC32C(crc, data, len)
+ * Accumulate some (more) bytes into a CRC
+ *
+ * FIN_CRC32C(crc)
+ * Finish a CRC calculation
+ *
+ * EQ_CRC32C(c1, c2)
+ * Check for equality of two CRCs.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/port/pg_crc32c.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_CRC32C_H
+#define PG_CRC32C_H
+
+#include "port/pg_bswap.h"
+
+typedef uint32 pg_crc32c;
+
+/* The INIT and EQ macros are the same for all implementations. */
+#define INIT_CRC32C(crc) ((crc) = 0xFFFFFFFF)
+#define EQ_CRC32C(c1, c2) ((c1) == (c2))
+
+#if defined(USE_SSE42_CRC32C)
+/* Use Intel SSE4.2 instructions. */
+#define COMP_CRC32C(crc, data, len) \
+ ((crc) = pg_comp_crc32c_sse42((crc), (data), (len)))
+#define FIN_CRC32C(crc) ((crc) ^= 0xFFFFFFFF)
+
+extern pg_crc32c pg_comp_crc32c_sse42(pg_crc32c crc, const void *data, size_t len);
+
+#elif defined(USE_ARMV8_CRC32C)
+/* Use ARMv8 CRC Extension instructions. */
+
+#define COMP_CRC32C(crc, data, len) \
+ ((crc) = pg_comp_crc32c_armv8((crc), (data), (len)))
+#define FIN_CRC32C(crc) ((crc) ^= 0xFFFFFFFF)
+
+extern pg_crc32c pg_comp_crc32c_armv8(pg_crc32c crc, const void *data, size_t len);
+
+#elif defined(USE_SSE42_CRC32C_WITH_RUNTIME_CHECK) || defined(USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK)
+
+/*
+ * Use Intel SSE 4.2 or ARMv8 instructions, but perform a runtime check first
+ * to check that they are available.
+ */
+#define COMP_CRC32C(crc, data, len) \
+ ((crc) = pg_comp_crc32c((crc), (data), (len)))
+#define FIN_CRC32C(crc) ((crc) ^= 0xFFFFFFFF)
+
+extern pg_crc32c pg_comp_crc32c_sb8(pg_crc32c crc, const void *data, size_t len);
+extern pg_crc32c (*pg_comp_crc32c) (pg_crc32c crc, const void *data, size_t len);
+
+#ifdef USE_SSE42_CRC32C_WITH_RUNTIME_CHECK
+extern pg_crc32c pg_comp_crc32c_sse42(pg_crc32c crc, const void *data, size_t len);
+#endif
+#ifdef USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK
+extern pg_crc32c pg_comp_crc32c_armv8(pg_crc32c crc, const void *data, size_t len);
+#endif
+
+#else
+/*
+ * Use slicing-by-8 algorithm.
+ *
+ * On big-endian systems, the intermediate value is kept in reverse byte
+ * order, to avoid byte-swapping during the calculation. FIN_CRC32C reverses
+ * the bytes to the final order.
+ */
+#define COMP_CRC32C(crc, data, len) \
+ ((crc) = pg_comp_crc32c_sb8((crc), (data), (len)))
+#ifdef WORDS_BIGENDIAN
+#define FIN_CRC32C(crc) ((crc) = pg_bswap32(crc) ^ 0xFFFFFFFF)
+#else
+#define FIN_CRC32C(crc) ((crc) ^= 0xFFFFFFFF)
+#endif
+
+extern pg_crc32c pg_comp_crc32c_sb8(pg_crc32c crc, const void *data, size_t len);
+
+#endif
+
+#endif /* PG_CRC32C_H */
diff --git a/src/include/port/solaris.h b/src/include/port/solaris.h
new file mode 100644
index 0000000..eeb1a32
--- /dev/null
+++ b/src/include/port/solaris.h
@@ -0,0 +1,38 @@
+/* src/include/port/solaris.h */
+
+/*
+ * Sort this out for all operating systems some time. The __xxx
+ * symbols are defined on both GCC and Solaris CC, although GCC
+ * doesn't document them. The __xxx__ symbols are only on GCC.
+ */
+#if defined(__i386) && !defined(__i386__)
+#define __i386__
+#endif
+
+#if defined(__amd64) && !defined(__amd64__)
+#define __amd64__
+#endif
+
+#if defined(__x86_64) && !defined(__x86_64__)
+#define __x86_64__
+#endif
+
+#if defined(__sparc) && !defined(__sparc__)
+#define __sparc__
+#endif
+
+#if defined(__i386__)
+#include <sys/isa_defs.h>
+#endif
+
+/*
+ * Many versions of Solaris have broken strtod() --- see bug #4751182.
+ * This has been fixed in current versions of Solaris:
+ *
+ * http://sunsolve.sun.com/search/document.do?assetkey=1-21-108993-62-1&searchclause=108993-62
+ * http://sunsolve.sun.com/search/document.do?assetkey=1-21-112874-34-1&searchclause=112874-34
+ *
+ * However, many people might not have patched versions, so
+ * still use our own fix for the buggy version.
+ */
+#define HAVE_BUGGY_SOLARIS_STRTOD
diff --git a/src/include/port/win32.h b/src/include/port/win32.h
new file mode 100644
index 0000000..d8ae49e
--- /dev/null
+++ b/src/include/port/win32.h
@@ -0,0 +1,69 @@
+/* src/include/port/win32.h */
+
+/*
+ * We always rely on the WIN32 macro being set by our build system,
+ * but _WIN32 is the compiler pre-defined macro. So make sure we define
+ * WIN32 whenever _WIN32 is set, to facilitate standalone building.
+ */
+#if defined(_WIN32) && !defined(WIN32)
+#define WIN32
+#endif
+
+/*
+ * Make sure _WIN32_WINNT has the minimum required value.
+ * Leave a higher value in place. When building with at least Visual
+ * Studio 2015 the minimum requirement is Windows Vista (0x0600) to
+ * get support for GetLocaleInfoEx() with locales. For everything else
+ * the minimum version is Windows XP (0x0501).
+ */
+#if defined(_MSC_VER) && _MSC_VER >= 1900
+#define MIN_WINNT 0x0600
+#else
+#define MIN_WINNT 0x0501
+#endif
+
+#if defined(_WIN32_WINNT) && _WIN32_WINNT < MIN_WINNT
+#undef _WIN32_WINNT
+#endif
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT MIN_WINNT
+#endif
+
+/*
+ * We need to prevent <crtdefs.h> from defining a symbol conflicting with
+ * our errcode() function. Since it's likely to get included by standard
+ * system headers, pre-emptively include it now.
+ */
+#if defined(_MSC_VER) || defined(HAVE_CRTDEFS_H)
+#define errcode __msvc_errcode
+#include <crtdefs.h>
+#undef errcode
+#endif
+
+/*
+ * defines for dynamic linking on Win32 platform
+ */
+
+#ifdef BUILDING_DLL
+#define PGDLLIMPORT __declspec (dllexport)
+#else
+#define PGDLLIMPORT __declspec (dllimport)
+#endif
+
+#ifdef _MSC_VER
+#define PGDLLEXPORT __declspec (dllexport)
+#else
+#define PGDLLEXPORT
+#endif
+
+/*
+ * Windows headers don't define this structure, but you can define it yourself
+ * to use the functionality.
+ */
+struct sockaddr_un
+{
+ unsigned short sun_family;
+ char sun_path[108];
+};
+#define HAVE_STRUCT_SOCKADDR_UN 1
diff --git a/src/include/port/win32/arpa/inet.h b/src/include/port/win32/arpa/inet.h
new file mode 100644
index 0000000..ad18031
--- /dev/null
+++ b/src/include/port/win32/arpa/inet.h
@@ -0,0 +1,3 @@
+/* src/include/port/win32/arpa/inet.h */
+
+#include <sys/socket.h>
diff --git a/src/include/port/win32/dlfcn.h b/src/include/port/win32/dlfcn.h
new file mode 100644
index 0000000..b6e43c0
--- /dev/null
+++ b/src/include/port/win32/dlfcn.h
@@ -0,0 +1 @@
+/* src/include/port/win32/dlfcn.h */
diff --git a/src/include/port/win32/grp.h b/src/include/port/win32/grp.h
new file mode 100644
index 0000000..8b4f213
--- /dev/null
+++ b/src/include/port/win32/grp.h
@@ -0,0 +1 @@
+/* src/include/port/win32/grp.h */
diff --git a/src/include/port/win32/netdb.h b/src/include/port/win32/netdb.h
new file mode 100644
index 0000000..ad0627e
--- /dev/null
+++ b/src/include/port/win32/netdb.h
@@ -0,0 +1 @@
+/* src/include/port/win32/netdb.h */
diff --git a/src/include/port/win32/netinet/in.h b/src/include/port/win32/netinet/in.h
new file mode 100644
index 0000000..a4e22f8
--- /dev/null
+++ b/src/include/port/win32/netinet/in.h
@@ -0,0 +1,3 @@
+/* src/include/port/win32/netinet/in.h */
+
+#include <sys/socket.h>
diff --git a/src/include/port/win32/pwd.h b/src/include/port/win32/pwd.h
new file mode 100644
index 0000000..b8c7178
--- /dev/null
+++ b/src/include/port/win32/pwd.h
@@ -0,0 +1,3 @@
+/*
+ * src/include/port/win32/pwd.h
+ */
diff --git a/src/include/port/win32/sys/socket.h b/src/include/port/win32/sys/socket.h
new file mode 100644
index 0000000..9b2cdf3
--- /dev/null
+++ b/src/include/port/win32/sys/socket.h
@@ -0,0 +1,33 @@
+/*
+ * src/include/port/win32/sys/socket.h
+ */
+#ifndef WIN32_SYS_SOCKET_H
+#define WIN32_SYS_SOCKET_H
+
+/*
+ * Unfortunately, <wingdi.h> of VC++ also defines ERROR.
+ * To avoid the conflict, we include <windows.h> here and undefine ERROR
+ * immediately.
+ *
+ * Note: Don't include <wingdi.h> directly. It causes compile errors.
+ */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windows.h>
+
+#undef ERROR
+#undef small
+
+/* Restore old ERROR value */
+#ifdef PGERROR
+#define ERROR PGERROR
+#endif
+
+/*
+ * we can't use the windows gai_strerror{AW} functions because
+ * they are defined inline in the MS header files. So we'll use our
+ * own
+ */
+#undef gai_strerror
+
+#endif /* WIN32_SYS_SOCKET_H */
diff --git a/src/include/port/win32/sys/wait.h b/src/include/port/win32/sys/wait.h
new file mode 100644
index 0000000..eaeb566
--- /dev/null
+++ b/src/include/port/win32/sys/wait.h
@@ -0,0 +1,3 @@
+/*
+ * src/include/port/win32/sys/wait.h
+ */
diff --git a/src/include/port/win32_msvc/dirent.h b/src/include/port/win32_msvc/dirent.h
new file mode 100644
index 0000000..9fabdf3
--- /dev/null
+++ b/src/include/port/win32_msvc/dirent.h
@@ -0,0 +1,23 @@
+/*
+ * Headers for port/dirent.c, win32 native implementation of dirent functions
+ *
+ * src/include/port/win32_msvc/dirent.h
+ */
+
+#ifndef _WIN32VC_DIRENT_H
+#define _WIN32VC_DIRENT_H
+struct dirent
+{
+ long d_ino;
+ unsigned short d_reclen;
+ unsigned short d_namlen;
+ char d_name[MAX_PATH];
+};
+
+typedef struct DIR DIR;
+
+DIR *opendir(const char *);
+struct dirent *readdir(DIR *);
+int closedir(DIR *);
+
+#endif
diff --git a/src/include/port/win32_msvc/sys/file.h b/src/include/port/win32_msvc/sys/file.h
new file mode 100644
index 0000000..76be3e7
--- /dev/null
+++ b/src/include/port/win32_msvc/sys/file.h
@@ -0,0 +1 @@
+/* src/include/port/win32_msvc/sys/file.h */
diff --git a/src/include/port/win32_msvc/sys/param.h b/src/include/port/win32_msvc/sys/param.h
new file mode 100644
index 0000000..160df3b
--- /dev/null
+++ b/src/include/port/win32_msvc/sys/param.h
@@ -0,0 +1 @@
+/* src/include/port/win32_msvc/sys/param.h */
diff --git a/src/include/port/win32_msvc/sys/time.h b/src/include/port/win32_msvc/sys/time.h
new file mode 100644
index 0000000..9d943ec
--- /dev/null
+++ b/src/include/port/win32_msvc/sys/time.h
@@ -0,0 +1 @@
+/* src/include/port/win32_msvc/sys/time.h */
diff --git a/src/include/port/win32_msvc/unistd.h b/src/include/port/win32_msvc/unistd.h
new file mode 100644
index 0000000..b63f477
--- /dev/null
+++ b/src/include/port/win32_msvc/unistd.h
@@ -0,0 +1 @@
+/* src/include/port/win32_msvc/unistd.h */
diff --git a/src/include/port/win32_msvc/utime.h b/src/include/port/win32_msvc/utime.h
new file mode 100644
index 0000000..c78e79c
--- /dev/null
+++ b/src/include/port/win32_msvc/utime.h
@@ -0,0 +1,3 @@
+/* src/include/port/win32_msvc/utime.h */
+
+#include <sys/utime.h> /* for non-unicode version */
diff --git a/src/include/port/win32_port.h b/src/include/port/win32_port.h
new file mode 100644
index 0000000..8b6576b
--- /dev/null
+++ b/src/include/port/win32_port.h
@@ -0,0 +1,516 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32_port.h
+ * Windows-specific compatibility stuff.
+ *
+ * Note this is read in MinGW as well as native Windows builds,
+ * but not in Cygwin builds.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/port/win32_port.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_WIN32_PORT_H
+#define PG_WIN32_PORT_H
+
+/*
+ * Always build with SSPI support. Keep it as a #define in case
+ * we want a switch to disable it sometime in the future.
+ */
+#define ENABLE_SSPI 1
+
+/* undefine and redefine after #include */
+#undef mkdir
+
+#undef ERROR
+
+/*
+ * VS2013 and later issue warnings about using the old Winsock API,
+ * which we don't really want to hear about.
+ */
+#ifdef _MSC_VER
+#define _WINSOCK_DEPRECATED_NO_WARNINGS
+#endif
+
+/*
+ * The MinGW64 headers choke if this is already defined - they
+ * define it themselves.
+ */
+#if !defined(__MINGW64_VERSION_MAJOR) || defined(_MSC_VER)
+#define _WINSOCKAPI_
+#endif
+
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windows.h>
+#undef small
+#include <process.h>
+#include <signal.h>
+#include <direct.h>
+#undef near
+#include <sys/stat.h> /* needed before sys/stat hacking below */
+
+/* Must be here to avoid conflicting with prototype in windows.h */
+#define mkdir(a,b) mkdir(a)
+
+#define ftruncate(a,b) chsize(a,b)
+
+/* Windows doesn't have fsync() as such, use _commit() */
+#define fsync(fd) _commit(fd)
+
+/*
+ * For historical reasons, we allow setting wal_sync_method to
+ * fsync_writethrough on Windows, even though it's really identical to fsync
+ * (both code paths wind up at _commit()).
+ */
+#define HAVE_FSYNC_WRITETHROUGH
+#define FSYNC_WRITETHROUGH_IS_FSYNC
+
+#define USES_WINSOCK
+
+/*
+ * IPC defines
+ */
+#undef HAVE_UNION_SEMUN
+#define HAVE_UNION_SEMUN 1
+
+#define IPC_RMID 256
+#define IPC_CREAT 512
+#define IPC_EXCL 1024
+#define IPC_PRIVATE 234564
+#define IPC_NOWAIT 2048
+#define IPC_STAT 4096
+
+#define EACCESS 2048
+#ifndef EIDRM
+#define EIDRM 4096
+#endif
+
+#define SETALL 8192
+#define GETNCNT 16384
+#define GETVAL 65536
+#define SETVAL 131072
+#define GETPID 262144
+
+
+/*
+ * Signal stuff
+ *
+ * For WIN32, there is no wait() call so there are no wait() macros
+ * to interpret the return value of system(). Instead, system()
+ * return values < 0x100 are used for exit() termination, and higher
+ * values are used to indicate non-exit() termination, which is
+ * similar to a unix-style signal exit (think SIGSEGV ==
+ * STATUS_ACCESS_VIOLATION). Return values are broken up into groups:
+ *
+ * https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values
+ *
+ * NT_SUCCESS 0 - 0x3FFFFFFF
+ * NT_INFORMATION 0x40000000 - 0x7FFFFFFF
+ * NT_WARNING 0x80000000 - 0xBFFFFFFF
+ * NT_ERROR 0xC0000000 - 0xFFFFFFFF
+ *
+ * Effectively, we don't care on the severity of the return value from
+ * system(), we just need to know if it was because of exit() or generated
+ * by the system, and it seems values >= 0x100 are system-generated.
+ * See this URL for a list of WIN32 STATUS_* values:
+ *
+ * Wine (URL used in our error messages) -
+ * http://source.winehq.org/source/include/ntstatus.h
+ * Descriptions -
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55
+ *
+ * The comprehensive exception list is included in ntstatus.h from the
+ * Windows Driver Kit (WDK). A subset of the list is also included in
+ * winnt.h from the Windows SDK. Defining WIN32_NO_STATUS before including
+ * windows.h helps to avoid any conflicts.
+ *
+ * Some day we might want to print descriptions for the most common
+ * exceptions, rather than printing an include file name. We could use
+ * RtlNtStatusToDosError() and pass to FormatMessage(), which can print
+ * the text of error values, but MinGW does not support
+ * RtlNtStatusToDosError().
+ */
+#define WIFEXITED(w) (((w) & 0XFFFFFF00) == 0)
+#define WIFSIGNALED(w) (!WIFEXITED(w))
+#define WEXITSTATUS(w) (w)
+#define WTERMSIG(w) (w)
+
+#define sigmask(sig) ( 1 << ((sig)-1) )
+
+/* Signal function return values */
+#undef SIG_DFL
+#undef SIG_ERR
+#undef SIG_IGN
+#define SIG_DFL ((pqsigfunc)0)
+#define SIG_ERR ((pqsigfunc)-1)
+#define SIG_IGN ((pqsigfunc)1)
+
+/* Some extra signals */
+#define SIGHUP 1
+#define SIGQUIT 3
+#define SIGTRAP 5
+#define SIGABRT 22 /* Set to match W32 value -- not UNIX value */
+#define SIGKILL 9
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGSTOP 17
+#define SIGTSTP 18
+#define SIGCONT 19
+#define SIGCHLD 20
+#define SIGWINCH 28
+#define SIGUSR1 30
+#define SIGUSR2 31
+
+/*
+ * New versions of MinGW have gettimeofday() and also declare
+ * struct timezone to support it.
+ */
+#ifndef HAVE_GETTIMEOFDAY
+struct timezone
+{
+ int tz_minuteswest; /* Minutes west of GMT. */
+ int tz_dsttime; /* Nonzero if DST is ever in effect. */
+};
+#endif
+
+/* for setitimer in backend/port/win32/timer.c */
+#define ITIMER_REAL 0
+struct itimerval
+{
+ struct timeval it_interval;
+ struct timeval it_value;
+};
+
+int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);
+
+/*
+ * WIN32 does not provide 64-bit off_t, but does provide the functions operating
+ * with 64-bit offsets.
+ */
+#define pgoff_t __int64
+
+#ifdef _MSC_VER
+#define fseeko(stream, offset, origin) _fseeki64(stream, offset, origin)
+#define ftello(stream) _ftelli64(stream)
+#else
+#ifndef fseeko
+#define fseeko(stream, offset, origin) fseeko64(stream, offset, origin)
+#endif
+#ifndef ftello
+#define ftello(stream) ftello64(stream)
+#endif
+#endif
+
+/*
+ * Win32 also doesn't have symlinks, but we can emulate them with
+ * junction points on newer Win32 versions.
+ *
+ * Cygwin has its own symlinks which work on Win95/98/ME where
+ * junction points don't, so use those instead. We have no way of
+ * knowing what type of system Cygwin binaries will be run on.
+ * Note: Some CYGWIN includes might #define WIN32.
+ */
+extern int pgsymlink(const char *oldpath, const char *newpath);
+extern int pgreadlink(const char *path, char *buf, size_t size);
+extern bool pgwin32_is_junction(const char *path);
+
+#define symlink(oldpath, newpath) pgsymlink(oldpath, newpath)
+#define readlink(path, buf, size) pgreadlink(path, buf, size)
+
+/*
+ * Supplement to <sys/types.h>.
+ *
+ * Perl already has typedefs for uid_t and gid_t.
+ */
+#ifndef PLPERL_HAVE_UID_GID
+typedef int uid_t;
+typedef int gid_t;
+#endif
+typedef long key_t;
+
+#ifdef _MSC_VER
+typedef int pid_t;
+#endif
+
+/*
+ * Supplement to <sys/stat.h>.
+ *
+ * We must pull in sys/stat.h before this part, else our overrides lose.
+ */
+#define lstat(path, sb) stat(path, sb)
+
+/*
+ * stat() is not guaranteed to set the st_size field on win32, so we
+ * redefine it to our own implementation that is.
+ *
+ * Some frontends don't need the size from stat, so if UNSAFE_STAT_OK
+ * is defined we don't bother with this.
+ */
+#ifndef UNSAFE_STAT_OK
+extern int pgwin32_safestat(const char *path, struct stat *buf);
+#define stat(a,b) pgwin32_safestat(a,b)
+#endif
+
+/* These macros are not provided by older MinGW, nor by MSVC */
+#ifndef S_IRUSR
+#define S_IRUSR _S_IREAD
+#endif
+#ifndef S_IWUSR
+#define S_IWUSR _S_IWRITE
+#endif
+#ifndef S_IXUSR
+#define S_IXUSR _S_IEXEC
+#endif
+#ifndef S_IRWXU
+#define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR)
+#endif
+#ifndef S_IRGRP
+#define S_IRGRP 0
+#endif
+#ifndef S_IWGRP
+#define S_IWGRP 0
+#endif
+#ifndef S_IXGRP
+#define S_IXGRP 0
+#endif
+#ifndef S_IRWXG
+#define S_IRWXG 0
+#endif
+#ifndef S_IROTH
+#define S_IROTH 0
+#endif
+#ifndef S_IWOTH
+#define S_IWOTH 0
+#endif
+#ifndef S_IXOTH
+#define S_IXOTH 0
+#endif
+#ifndef S_IRWXO
+#define S_IRWXO 0
+#endif
+#ifndef S_ISDIR
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+#ifndef S_ISREG
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+
+/*
+ * Supplement to <fcntl.h>.
+ * This is the same value as _O_NOINHERIT in the MS header file. This is
+ * to ensure that we don't collide with a future definition. It means
+ * we cannot use _O_NOINHERIT ourselves.
+ */
+#define O_DSYNC 0x0080
+
+/*
+ * Supplement to <errno.h>.
+ *
+ * We redefine network-related Berkeley error symbols as the corresponding WSA
+ * constants. This allows strerror.c to recognize them as being in the Winsock
+ * error code range and pass them off to win32_socket_strerror(), since
+ * Windows' version of plain strerror() won't cope. Note that this will break
+ * if these names are used for anything else besides Windows Sockets errors.
+ * See TranslateSocketError() when changing this list.
+ */
+#undef EAGAIN
+#define EAGAIN WSAEWOULDBLOCK
+#undef EINTR
+#define EINTR WSAEINTR
+#undef EMSGSIZE
+#define EMSGSIZE WSAEMSGSIZE
+#undef EAFNOSUPPORT
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#undef EWOULDBLOCK
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#undef ECONNABORTED
+#define ECONNABORTED WSAECONNABORTED
+#undef ECONNRESET
+#define ECONNRESET WSAECONNRESET
+#undef EINPROGRESS
+#define EINPROGRESS WSAEINPROGRESS
+#undef EISCONN
+#define EISCONN WSAEISCONN
+#undef ENOBUFS
+#define ENOBUFS WSAENOBUFS
+#undef EPROTONOSUPPORT
+#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+#undef ECONNREFUSED
+#define ECONNREFUSED WSAECONNREFUSED
+#undef ENOTSOCK
+#define ENOTSOCK WSAENOTSOCK
+#undef EOPNOTSUPP
+#define EOPNOTSUPP WSAEOPNOTSUPP
+#undef EADDRINUSE
+#define EADDRINUSE WSAEADDRINUSE
+#undef EADDRNOTAVAIL
+#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+#undef EHOSTUNREACH
+#define EHOSTUNREACH WSAEHOSTUNREACH
+#undef ENOTCONN
+#define ENOTCONN WSAENOTCONN
+
+/*
+ * Locale stuff.
+ *
+ * Extended locale functions with gratuitous underscore prefixes.
+ * (These APIs are nevertheless fully documented by Microsoft.)
+ */
+#define locale_t _locale_t
+#define tolower_l _tolower_l
+#define toupper_l _toupper_l
+#define towlower_l _towlower_l
+#define towupper_l _towupper_l
+#define isdigit_l _isdigit_l
+#define iswdigit_l _iswdigit_l
+#define isalpha_l _isalpha_l
+#define iswalpha_l _iswalpha_l
+#define isalnum_l _isalnum_l
+#define iswalnum_l _iswalnum_l
+#define isupper_l _isupper_l
+#define iswupper_l _iswupper_l
+#define islower_l _islower_l
+#define iswlower_l _iswlower_l
+#define isgraph_l _isgraph_l
+#define iswgraph_l _iswgraph_l
+#define isprint_l _isprint_l
+#define iswprint_l _iswprint_l
+#define ispunct_l _ispunct_l
+#define iswpunct_l _iswpunct_l
+#define isspace_l _isspace_l
+#define iswspace_l _iswspace_l
+#define strcoll_l _strcoll_l
+#define strxfrm_l _strxfrm_l
+#define wcscoll_l _wcscoll_l
+#define wcstombs_l _wcstombs_l
+#define mbstowcs_l _mbstowcs_l
+
+/*
+ * Versions of libintl >= 0.18? try to replace setlocale() with a macro
+ * to their own versions. Remove the macro, if it exists, because it
+ * ends up calling the wrong version when the backend and libintl use
+ * different versions of msvcrt.
+ */
+#if defined(setlocale)
+#undef setlocale
+#endif
+
+/*
+ * Define our own wrapper macro around setlocale() to work around bugs in
+ * Windows' native setlocale() function.
+ */
+extern char *pgwin32_setlocale(int category, const char *locale);
+
+#define setlocale(a,b) pgwin32_setlocale(a,b)
+
+
+/* In backend/port/win32/signal.c */
+extern PGDLLIMPORT volatile int pg_signal_queue;
+extern PGDLLIMPORT int pg_signal_mask;
+extern HANDLE pgwin32_signal_event;
+extern HANDLE pgwin32_initial_signal_pipe;
+
+#define UNBLOCKED_SIGNAL_QUEUE() (pg_signal_queue & ~pg_signal_mask)
+#define PG_SIGNAL_COUNT 32
+
+void pgwin32_signal_initialize(void);
+HANDLE pgwin32_create_signal_listener(pid_t pid);
+void pgwin32_dispatch_queued_signals(void);
+void pg_queue_signal(int signum);
+
+/* In src/port/kill.c */
+#define kill(pid,sig) pgkill(pid,sig)
+extern int pgkill(int pid, int sig);
+
+/* In backend/port/win32/socket.c */
+#ifndef FRONTEND
+#define socket(af, type, protocol) pgwin32_socket(af, type, protocol)
+#define bind(s, addr, addrlen) pgwin32_bind(s, addr, addrlen)
+#define listen(s, backlog) pgwin32_listen(s, backlog)
+#define accept(s, addr, addrlen) pgwin32_accept(s, addr, addrlen)
+#define connect(s, name, namelen) pgwin32_connect(s, name, namelen)
+#define select(n, r, w, e, timeout) pgwin32_select(n, r, w, e, timeout)
+#define recv(s, buf, len, flags) pgwin32_recv(s, buf, len, flags)
+#define send(s, buf, len, flags) pgwin32_send(s, buf, len, flags)
+
+SOCKET pgwin32_socket(int af, int type, int protocol);
+int pgwin32_bind(SOCKET s, struct sockaddr *addr, int addrlen);
+int pgwin32_listen(SOCKET s, int backlog);
+SOCKET pgwin32_accept(SOCKET s, struct sockaddr *addr, int *addrlen);
+int pgwin32_connect(SOCKET s, const struct sockaddr *name, int namelen);
+int pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout);
+int pgwin32_recv(SOCKET s, char *buf, int len, int flags);
+int pgwin32_send(SOCKET s, const void *buf, int len, int flags);
+int pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout);
+
+extern int pgwin32_noblock;
+
+#endif /* FRONTEND */
+
+/* in backend/port/win32_shmem.c */
+extern int pgwin32_ReserveSharedMemoryRegion(HANDLE);
+
+/* in backend/port/win32/crashdump.c */
+extern void pgwin32_install_crashdump_handler(void);
+
+/* in port/win32error.c */
+extern void _dosmaperr(unsigned long);
+
+/* in port/win32env.c */
+extern int pgwin32_putenv(const char *);
+extern void pgwin32_unsetenv(const char *);
+
+/* in port/win32security.c */
+extern int pgwin32_is_service(void);
+extern int pgwin32_is_admin(void);
+
+/* Windows security token manipulation (in src/common/exec.c) */
+extern BOOL AddUserToTokenDacl(HANDLE hToken);
+
+#define putenv(x) pgwin32_putenv(x)
+#define unsetenv(x) pgwin32_unsetenv(x)
+
+/* Things that exist in MinGW headers, but need to be added to MSVC */
+#ifdef _MSC_VER
+
+#ifndef _WIN64
+typedef long ssize_t;
+#else
+typedef __int64 ssize_t;
+#endif
+
+typedef unsigned short mode_t;
+
+#define F_OK 0
+#define W_OK 2
+#define R_OK 4
+
+/* Pulled from Makefile.port in MinGW */
+#define DLSUFFIX ".dll"
+
+#endif /* _MSC_VER */
+
+#if (defined(_MSC_VER) && (_MSC_VER < 1900)) || \
+ defined(__MINGW32__) || defined(__MINGW64__)
+/*
+ * VS2013 has a strtof() that seems to give correct answers for valid input,
+ * even on the rounding edge cases, but which doesn't handle out-of-range
+ * input correctly. Work around that.
+ *
+ * Mingw claims to have a strtof, and my reading of its source code suggests
+ * that it ought to work (and not need this hack), but the regression test
+ * results disagree with me; whether this is a version issue or not is not
+ * clear. However, using our wrapper (and the misrounded-input variant file,
+ * already required for supporting ancient systems) can't make things any
+ * worse, except for a tiny performance loss when reading zeros.
+ *
+ * See also cygwin.h for another instance of this.
+ */
+#define HAVE_BUGGY_STRTOF 1
+#endif
+
+#endif /* PG_WIN32_PORT_H */
diff --git a/src/include/portability/instr_time.h b/src/include/portability/instr_time.h
new file mode 100644
index 0000000..d645932
--- /dev/null
+++ b/src/include/portability/instr_time.h
@@ -0,0 +1,256 @@
+/*-------------------------------------------------------------------------
+ *
+ * instr_time.h
+ * portable high-precision interval timing
+ *
+ * This file provides an abstraction layer to hide portability issues in
+ * interval timing. On Unix we use clock_gettime() if available, else
+ * gettimeofday(). On Windows, gettimeofday() gives a low-precision result
+ * so we must use QueryPerformanceCounter() instead. These macros also give
+ * some breathing room to use other high-precision-timing APIs.
+ *
+ * The basic data type is instr_time, which all callers should treat as an
+ * opaque typedef. instr_time can store either an absolute time (of
+ * unspecified reference time) or an interval. The operations provided
+ * for it are:
+ *
+ * INSTR_TIME_IS_ZERO(t) is t equal to zero?
+ *
+ * INSTR_TIME_SET_ZERO(t) set t to zero (memset is acceptable too)
+ *
+ * INSTR_TIME_SET_CURRENT(t) set t to current time
+ *
+ * INSTR_TIME_SET_CURRENT_LAZY(t) set t to current time if t is zero,
+ * evaluates to whether t changed
+ *
+ * INSTR_TIME_ADD(x, y) x += y
+ *
+ * INSTR_TIME_SUBTRACT(x, y) x -= y
+ *
+ * INSTR_TIME_ACCUM_DIFF(x, y, z) x += (y - z)
+ *
+ * INSTR_TIME_GET_DOUBLE(t) convert t to double (in seconds)
+ *
+ * INSTR_TIME_GET_MILLISEC(t) convert t to double (in milliseconds)
+ *
+ * INSTR_TIME_GET_MICROSEC(t) convert t to uint64 (in microseconds)
+ *
+ * Note that INSTR_TIME_SUBTRACT and INSTR_TIME_ACCUM_DIFF convert
+ * absolute times to intervals. The INSTR_TIME_GET_xxx operations are
+ * only useful on intervals.
+ *
+ * When summing multiple measurements, it's recommended to leave the
+ * running sum in instr_time form (ie, use INSTR_TIME_ADD or
+ * INSTR_TIME_ACCUM_DIFF) and convert to a result format only at the end.
+ *
+ * Beware of multiple evaluations of the macro arguments.
+ *
+ *
+ * Copyright (c) 2001-2020, PostgreSQL Global Development Group
+ *
+ * src/include/portability/instr_time.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef INSTR_TIME_H
+#define INSTR_TIME_H
+
+#ifndef WIN32
+
+#ifdef HAVE_CLOCK_GETTIME
+
+/* Use clock_gettime() */
+
+#include <time.h>
+
+/*
+ * The best clockid to use according to the POSIX spec is CLOCK_MONOTONIC,
+ * since that will give reliable interval timing even in the face of changes
+ * to the system clock. However, POSIX doesn't require implementations to
+ * provide anything except CLOCK_REALTIME, so fall back to that if we don't
+ * find CLOCK_MONOTONIC.
+ *
+ * Also, some implementations have nonstandard clockids with better properties
+ * than CLOCK_MONOTONIC. In particular, as of macOS 10.12, Apple provides
+ * CLOCK_MONOTONIC_RAW which is both faster to read and higher resolution than
+ * their version of CLOCK_MONOTONIC.
+ */
+#if defined(__darwin__) && defined(CLOCK_MONOTONIC_RAW)
+#define PG_INSTR_CLOCK CLOCK_MONOTONIC_RAW
+#elif defined(CLOCK_MONOTONIC)
+#define PG_INSTR_CLOCK CLOCK_MONOTONIC
+#else
+#define PG_INSTR_CLOCK CLOCK_REALTIME
+#endif
+
+typedef struct timespec instr_time;
+
+#define INSTR_TIME_IS_ZERO(t) ((t).tv_nsec == 0 && (t).tv_sec == 0)
+
+#define INSTR_TIME_SET_ZERO(t) ((t).tv_sec = 0, (t).tv_nsec = 0)
+
+#define INSTR_TIME_SET_CURRENT(t) ((void) clock_gettime(PG_INSTR_CLOCK, &(t)))
+
+#define INSTR_TIME_ADD(x,y) \
+ do { \
+ (x).tv_sec += (y).tv_sec; \
+ (x).tv_nsec += (y).tv_nsec; \
+ /* Normalize */ \
+ while ((x).tv_nsec >= 1000000000) \
+ { \
+ (x).tv_nsec -= 1000000000; \
+ (x).tv_sec++; \
+ } \
+ } while (0)
+
+#define INSTR_TIME_SUBTRACT(x,y) \
+ do { \
+ (x).tv_sec -= (y).tv_sec; \
+ (x).tv_nsec -= (y).tv_nsec; \
+ /* Normalize */ \
+ while ((x).tv_nsec < 0) \
+ { \
+ (x).tv_nsec += 1000000000; \
+ (x).tv_sec--; \
+ } \
+ } while (0)
+
+#define INSTR_TIME_ACCUM_DIFF(x,y,z) \
+ do { \
+ (x).tv_sec += (y).tv_sec - (z).tv_sec; \
+ (x).tv_nsec += (y).tv_nsec - (z).tv_nsec; \
+ /* Normalize after each add to avoid overflow/underflow of tv_nsec */ \
+ while ((x).tv_nsec < 0) \
+ { \
+ (x).tv_nsec += 1000000000; \
+ (x).tv_sec--; \
+ } \
+ while ((x).tv_nsec >= 1000000000) \
+ { \
+ (x).tv_nsec -= 1000000000; \
+ (x).tv_sec++; \
+ } \
+ } while (0)
+
+#define INSTR_TIME_GET_DOUBLE(t) \
+ (((double) (t).tv_sec) + ((double) (t).tv_nsec) / 1000000000.0)
+
+#define INSTR_TIME_GET_MILLISEC(t) \
+ (((double) (t).tv_sec * 1000.0) + ((double) (t).tv_nsec) / 1000000.0)
+
+#define INSTR_TIME_GET_MICROSEC(t) \
+ (((uint64) (t).tv_sec * (uint64) 1000000) + (uint64) ((t).tv_nsec / 1000))
+
+#else /* !HAVE_CLOCK_GETTIME */
+
+/* Use gettimeofday() */
+
+#include <sys/time.h>
+
+typedef struct timeval instr_time;
+
+#define INSTR_TIME_IS_ZERO(t) ((t).tv_usec == 0 && (t).tv_sec == 0)
+
+#define INSTR_TIME_SET_ZERO(t) ((t).tv_sec = 0, (t).tv_usec = 0)
+
+#define INSTR_TIME_SET_CURRENT(t) gettimeofday(&(t), NULL)
+
+#define INSTR_TIME_ADD(x,y) \
+ do { \
+ (x).tv_sec += (y).tv_sec; \
+ (x).tv_usec += (y).tv_usec; \
+ /* Normalize */ \
+ while ((x).tv_usec >= 1000000) \
+ { \
+ (x).tv_usec -= 1000000; \
+ (x).tv_sec++; \
+ } \
+ } while (0)
+
+#define INSTR_TIME_SUBTRACT(x,y) \
+ do { \
+ (x).tv_sec -= (y).tv_sec; \
+ (x).tv_usec -= (y).tv_usec; \
+ /* Normalize */ \
+ while ((x).tv_usec < 0) \
+ { \
+ (x).tv_usec += 1000000; \
+ (x).tv_sec--; \
+ } \
+ } while (0)
+
+#define INSTR_TIME_ACCUM_DIFF(x,y,z) \
+ do { \
+ (x).tv_sec += (y).tv_sec - (z).tv_sec; \
+ (x).tv_usec += (y).tv_usec - (z).tv_usec; \
+ /* Normalize after each add to avoid overflow/underflow of tv_usec */ \
+ while ((x).tv_usec < 0) \
+ { \
+ (x).tv_usec += 1000000; \
+ (x).tv_sec--; \
+ } \
+ while ((x).tv_usec >= 1000000) \
+ { \
+ (x).tv_usec -= 1000000; \
+ (x).tv_sec++; \
+ } \
+ } while (0)
+
+#define INSTR_TIME_GET_DOUBLE(t) \
+ (((double) (t).tv_sec) + ((double) (t).tv_usec) / 1000000.0)
+
+#define INSTR_TIME_GET_MILLISEC(t) \
+ (((double) (t).tv_sec * 1000.0) + ((double) (t).tv_usec) / 1000.0)
+
+#define INSTR_TIME_GET_MICROSEC(t) \
+ (((uint64) (t).tv_sec * (uint64) 1000000) + (uint64) (t).tv_usec)
+
+#endif /* HAVE_CLOCK_GETTIME */
+
+#else /* WIN32 */
+
+/* Use QueryPerformanceCounter() */
+
+typedef LARGE_INTEGER instr_time;
+
+#define INSTR_TIME_IS_ZERO(t) ((t).QuadPart == 0)
+
+#define INSTR_TIME_SET_ZERO(t) ((t).QuadPart = 0)
+
+#define INSTR_TIME_SET_CURRENT(t) QueryPerformanceCounter(&(t))
+
+#define INSTR_TIME_ADD(x,y) \
+ ((x).QuadPart += (y).QuadPart)
+
+#define INSTR_TIME_SUBTRACT(x,y) \
+ ((x).QuadPart -= (y).QuadPart)
+
+#define INSTR_TIME_ACCUM_DIFF(x,y,z) \
+ ((x).QuadPart += (y).QuadPart - (z).QuadPart)
+
+#define INSTR_TIME_GET_DOUBLE(t) \
+ (((double) (t).QuadPart) / GetTimerFrequency())
+
+#define INSTR_TIME_GET_MILLISEC(t) \
+ (((double) (t).QuadPart * 1000.0) / GetTimerFrequency())
+
+#define INSTR_TIME_GET_MICROSEC(t) \
+ ((uint64) (((double) (t).QuadPart * 1000000.0) / GetTimerFrequency()))
+
+static inline double
+GetTimerFrequency(void)
+{
+ LARGE_INTEGER f;
+
+ QueryPerformanceFrequency(&f);
+ return (double) f.QuadPart;
+}
+
+#endif /* WIN32 */
+
+/* same macro on all platforms */
+
+#define INSTR_TIME_SET_CURRENT_LAZY(t) \
+ (INSTR_TIME_IS_ZERO(t) ? INSTR_TIME_SET_CURRENT(t), true : false)
+
+#endif /* INSTR_TIME_H */
diff --git a/src/include/portability/mem.h b/src/include/portability/mem.h
new file mode 100644
index 0000000..c1c8eb5
--- /dev/null
+++ b/src/include/portability/mem.h
@@ -0,0 +1,48 @@
+/*-------------------------------------------------------------------------
+ *
+ * mem.h
+ * portability definitions for various memory operations
+ *
+ * Copyright (c) 2001-2020, PostgreSQL Global Development Group
+ *
+ * src/include/portability/mem.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef MEM_H
+#define MEM_H
+
+#define IPCProtection (0600) /* access/modify by user only */
+
+#ifdef SHM_SHARE_MMU /* use intimate shared memory on Solaris */
+#define PG_SHMAT_FLAGS SHM_SHARE_MMU
+#else
+#define PG_SHMAT_FLAGS 0
+#endif
+
+/* Linux prefers MAP_ANONYMOUS, but the flag is called MAP_ANON on other systems. */
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+/* BSD-derived systems have MAP_HASSEMAPHORE, but it's not present (or needed) on Linux. */
+#ifndef MAP_HASSEMAPHORE
+#define MAP_HASSEMAPHORE 0
+#endif
+
+/*
+ * BSD-derived systems use the MAP_NOSYNC flag to prevent dirty mmap(2)
+ * pages from being gratuitously flushed to disk.
+ */
+#ifndef MAP_NOSYNC
+#define MAP_NOSYNC 0
+#endif
+
+#define PG_MMAP_FLAGS (MAP_SHARED|MAP_ANONYMOUS|MAP_HASSEMAPHORE)
+
+/* Some really old systems don't define MAP_FAILED. */
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *) -1)
+#endif
+
+#endif /* MEM_H */
diff --git a/src/include/postgres.h b/src/include/postgres.h
new file mode 100644
index 0000000..c48f47e
--- /dev/null
+++ b/src/include/postgres.h
@@ -0,0 +1,764 @@
+/*-------------------------------------------------------------------------
+ *
+ * postgres.h
+ * Primary include file for PostgreSQL server .c files
+ *
+ * This should be the first file included by PostgreSQL backend modules.
+ * Client-side code should include postgres_fe.h instead.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1995, Regents of the University of California
+ *
+ * src/include/postgres.h
+ *
+ *-------------------------------------------------------------------------
+ */
+/*
+ *----------------------------------------------------------------
+ * TABLE OF CONTENTS
+ *
+ * When adding stuff to this file, please try to put stuff
+ * into the relevant section, or add new sections as appropriate.
+ *
+ * section description
+ * ------- ------------------------------------------------
+ * 1) variable-length datatypes (TOAST support)
+ * 2) Datum type + support macros
+ *
+ * NOTES
+ *
+ * In general, this file should contain declarations that are widely needed
+ * in the backend environment, but are of no interest outside the backend.
+ *
+ * Simple type definitions live in c.h, where they are shared with
+ * postgres_fe.h. We do that since those type definitions are needed by
+ * frontend modules that want to deal with binary data transmission to or
+ * from the backend. Type definitions in this file should be for
+ * representations that never escape the backend, such as Datum or
+ * TOASTed varlena objects.
+ *
+ *----------------------------------------------------------------
+ */
+#ifndef POSTGRES_H
+#define POSTGRES_H
+
+#include "c.h"
+#include "utils/elog.h"
+#include "utils/palloc.h"
+
+/* ----------------------------------------------------------------
+ * Section 1: variable-length datatypes (TOAST support)
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * struct varatt_external is a traditional "TOAST pointer", that is, the
+ * information needed to fetch a Datum stored out-of-line in a TOAST table.
+ * The data is compressed if and only if va_extsize < va_rawsize - VARHDRSZ.
+ * This struct must not contain any padding, because we sometimes compare
+ * these pointers using memcmp.
+ *
+ * Note that this information is stored unaligned within actual tuples, so
+ * you need to memcpy from the tuple into a local struct variable before
+ * you can look at these fields! (The reason we use memcmp is to avoid
+ * having to do that just to detect equality of two TOAST pointers...)
+ */
+typedef struct varatt_external
+{
+ int32 va_rawsize; /* Original data size (includes header) */
+ int32 va_extsize; /* External saved size (doesn't) */
+ Oid va_valueid; /* Unique ID of value within TOAST table */
+ Oid va_toastrelid; /* RelID of TOAST table containing it */
+} varatt_external;
+
+/*
+ * struct varatt_indirect is a "TOAST pointer" representing an out-of-line
+ * Datum that's stored in memory, not in an external toast relation.
+ * The creator of such a Datum is entirely responsible that the referenced
+ * storage survives for as long as referencing pointer Datums can exist.
+ *
+ * Note that just as for struct varatt_external, this struct is stored
+ * unaligned within any containing tuple.
+ */
+typedef struct varatt_indirect
+{
+ struct varlena *pointer; /* Pointer to in-memory varlena */
+} varatt_indirect;
+
+/*
+ * struct varatt_expanded is a "TOAST pointer" representing an out-of-line
+ * Datum that is stored in memory, in some type-specific, not necessarily
+ * physically contiguous format that is convenient for computation not
+ * storage. APIs for this, in particular the definition of struct
+ * ExpandedObjectHeader, are in src/include/utils/expandeddatum.h.
+ *
+ * Note that just as for struct varatt_external, this struct is stored
+ * unaligned within any containing tuple.
+ */
+typedef struct ExpandedObjectHeader ExpandedObjectHeader;
+
+typedef struct varatt_expanded
+{
+ ExpandedObjectHeader *eohptr;
+} varatt_expanded;
+
+/*
+ * Type tag for the various sorts of "TOAST pointer" datums. The peculiar
+ * value for VARTAG_ONDISK comes from a requirement for on-disk compatibility
+ * with a previous notion that the tag field was the pointer datum's length.
+ */
+typedef enum vartag_external
+{
+ VARTAG_INDIRECT = 1,
+ VARTAG_EXPANDED_RO = 2,
+ VARTAG_EXPANDED_RW = 3,
+ VARTAG_ONDISK = 18
+} vartag_external;
+
+/* this test relies on the specific tag values above */
+#define VARTAG_IS_EXPANDED(tag) \
+ (((tag) & ~1) == VARTAG_EXPANDED_RO)
+
+#define VARTAG_SIZE(tag) \
+ ((tag) == VARTAG_INDIRECT ? sizeof(varatt_indirect) : \
+ VARTAG_IS_EXPANDED(tag) ? sizeof(varatt_expanded) : \
+ (tag) == VARTAG_ONDISK ? sizeof(varatt_external) : \
+ TrapMacro(true, "unrecognized TOAST vartag"))
+
+/*
+ * These structs describe the header of a varlena object that may have been
+ * TOASTed. Generally, don't reference these structs directly, but use the
+ * macros below.
+ *
+ * We use separate structs for the aligned and unaligned cases because the
+ * compiler might otherwise think it could generate code that assumes
+ * alignment while touching fields of a 1-byte-header varlena.
+ */
+typedef union
+{
+ struct /* Normal varlena (4-byte length) */
+ {
+ uint32 va_header;
+ char va_data[FLEXIBLE_ARRAY_MEMBER];
+ } va_4byte;
+ struct /* Compressed-in-line format */
+ {
+ uint32 va_header;
+ uint32 va_rawsize; /* Original data size (excludes header) */
+ char va_data[FLEXIBLE_ARRAY_MEMBER]; /* Compressed data */
+ } va_compressed;
+} varattrib_4b;
+
+typedef struct
+{
+ uint8 va_header;
+ char va_data[FLEXIBLE_ARRAY_MEMBER]; /* Data begins here */
+} varattrib_1b;
+
+/* TOAST pointers are a subset of varattrib_1b with an identifying tag byte */
+typedef struct
+{
+ uint8 va_header; /* Always 0x80 or 0x01 */
+ uint8 va_tag; /* Type of datum */
+ char va_data[FLEXIBLE_ARRAY_MEMBER]; /* Type-specific data */
+} varattrib_1b_e;
+
+/*
+ * Bit layouts for varlena headers on big-endian machines:
+ *
+ * 00xxxxxx 4-byte length word, aligned, uncompressed data (up to 1G)
+ * 01xxxxxx 4-byte length word, aligned, *compressed* data (up to 1G)
+ * 10000000 1-byte length word, unaligned, TOAST pointer
+ * 1xxxxxxx 1-byte length word, unaligned, uncompressed data (up to 126b)
+ *
+ * Bit layouts for varlena headers on little-endian machines:
+ *
+ * xxxxxx00 4-byte length word, aligned, uncompressed data (up to 1G)
+ * xxxxxx10 4-byte length word, aligned, *compressed* data (up to 1G)
+ * 00000001 1-byte length word, unaligned, TOAST pointer
+ * xxxxxxx1 1-byte length word, unaligned, uncompressed data (up to 126b)
+ *
+ * The "xxx" bits are the length field (which includes itself in all cases).
+ * In the big-endian case we mask to extract the length, in the little-endian
+ * case we shift. Note that in both cases the flag bits are in the physically
+ * first byte. Also, it is not possible for a 1-byte length word to be zero;
+ * this lets us disambiguate alignment padding bytes from the start of an
+ * unaligned datum. (We now *require* pad bytes to be filled with zero!)
+ *
+ * In TOAST pointers the va_tag field (see varattrib_1b_e) is used to discern
+ * the specific type and length of the pointer datum.
+ */
+
+/*
+ * Endian-dependent macros. These are considered internal --- use the
+ * external macros below instead of using these directly.
+ *
+ * Note: IS_1B is true for external toast records but VARSIZE_1B will return 0
+ * for such records. Hence you should usually check for IS_EXTERNAL before
+ * checking for IS_1B.
+ */
+
+#ifdef WORDS_BIGENDIAN
+
+#define VARATT_IS_4B(PTR) \
+ ((((varattrib_1b *) (PTR))->va_header & 0x80) == 0x00)
+#define VARATT_IS_4B_U(PTR) \
+ ((((varattrib_1b *) (PTR))->va_header & 0xC0) == 0x00)
+#define VARATT_IS_4B_C(PTR) \
+ ((((varattrib_1b *) (PTR))->va_header & 0xC0) == 0x40)
+#define VARATT_IS_1B(PTR) \
+ ((((varattrib_1b *) (PTR))->va_header & 0x80) == 0x80)
+#define VARATT_IS_1B_E(PTR) \
+ ((((varattrib_1b *) (PTR))->va_header) == 0x80)
+#define VARATT_NOT_PAD_BYTE(PTR) \
+ (*((uint8 *) (PTR)) != 0)
+
+/* VARSIZE_4B() should only be used on known-aligned data */
+#define VARSIZE_4B(PTR) \
+ (((varattrib_4b *) (PTR))->va_4byte.va_header & 0x3FFFFFFF)
+#define VARSIZE_1B(PTR) \
+ (((varattrib_1b *) (PTR))->va_header & 0x7F)
+#define VARTAG_1B_E(PTR) \
+ (((varattrib_1b_e *) (PTR))->va_tag)
+
+#define SET_VARSIZE_4B(PTR,len) \
+ (((varattrib_4b *) (PTR))->va_4byte.va_header = (len) & 0x3FFFFFFF)
+#define SET_VARSIZE_4B_C(PTR,len) \
+ (((varattrib_4b *) (PTR))->va_4byte.va_header = ((len) & 0x3FFFFFFF) | 0x40000000)
+#define SET_VARSIZE_1B(PTR,len) \
+ (((varattrib_1b *) (PTR))->va_header = (len) | 0x80)
+#define SET_VARTAG_1B_E(PTR,tag) \
+ (((varattrib_1b_e *) (PTR))->va_header = 0x80, \
+ ((varattrib_1b_e *) (PTR))->va_tag = (tag))
+#else /* !WORDS_BIGENDIAN */
+
+#define VARATT_IS_4B(PTR) \
+ ((((varattrib_1b *) (PTR))->va_header & 0x01) == 0x00)
+#define VARATT_IS_4B_U(PTR) \
+ ((((varattrib_1b *) (PTR))->va_header & 0x03) == 0x00)
+#define VARATT_IS_4B_C(PTR) \
+ ((((varattrib_1b *) (PTR))->va_header & 0x03) == 0x02)
+#define VARATT_IS_1B(PTR) \
+ ((((varattrib_1b *) (PTR))->va_header & 0x01) == 0x01)
+#define VARATT_IS_1B_E(PTR) \
+ ((((varattrib_1b *) (PTR))->va_header) == 0x01)
+#define VARATT_NOT_PAD_BYTE(PTR) \
+ (*((uint8 *) (PTR)) != 0)
+
+/* VARSIZE_4B() should only be used on known-aligned data */
+#define VARSIZE_4B(PTR) \
+ ((((varattrib_4b *) (PTR))->va_4byte.va_header >> 2) & 0x3FFFFFFF)
+#define VARSIZE_1B(PTR) \
+ ((((varattrib_1b *) (PTR))->va_header >> 1) & 0x7F)
+#define VARTAG_1B_E(PTR) \
+ (((varattrib_1b_e *) (PTR))->va_tag)
+
+#define SET_VARSIZE_4B(PTR,len) \
+ (((varattrib_4b *) (PTR))->va_4byte.va_header = (((uint32) (len)) << 2))
+#define SET_VARSIZE_4B_C(PTR,len) \
+ (((varattrib_4b *) (PTR))->va_4byte.va_header = (((uint32) (len)) << 2) | 0x02)
+#define SET_VARSIZE_1B(PTR,len) \
+ (((varattrib_1b *) (PTR))->va_header = (((uint8) (len)) << 1) | 0x01)
+#define SET_VARTAG_1B_E(PTR,tag) \
+ (((varattrib_1b_e *) (PTR))->va_header = 0x01, \
+ ((varattrib_1b_e *) (PTR))->va_tag = (tag))
+#endif /* WORDS_BIGENDIAN */
+
+#define VARHDRSZ_SHORT offsetof(varattrib_1b, va_data)
+#define VARATT_SHORT_MAX 0x7F
+#define VARATT_CAN_MAKE_SHORT(PTR) \
+ (VARATT_IS_4B_U(PTR) && \
+ (VARSIZE(PTR) - VARHDRSZ + VARHDRSZ_SHORT) <= VARATT_SHORT_MAX)
+#define VARATT_CONVERTED_SHORT_SIZE(PTR) \
+ (VARSIZE(PTR) - VARHDRSZ + VARHDRSZ_SHORT)
+
+#define VARHDRSZ_EXTERNAL offsetof(varattrib_1b_e, va_data)
+
+#define VARDATA_4B(PTR) (((varattrib_4b *) (PTR))->va_4byte.va_data)
+#define VARDATA_4B_C(PTR) (((varattrib_4b *) (PTR))->va_compressed.va_data)
+#define VARDATA_1B(PTR) (((varattrib_1b *) (PTR))->va_data)
+#define VARDATA_1B_E(PTR) (((varattrib_1b_e *) (PTR))->va_data)
+
+#define VARRAWSIZE_4B_C(PTR) \
+ (((varattrib_4b *) (PTR))->va_compressed.va_rawsize)
+
+/* Externally visible macros */
+
+/*
+ * In consumers oblivious to data alignment, call PG_DETOAST_DATUM_PACKED(),
+ * VARDATA_ANY(), VARSIZE_ANY() and VARSIZE_ANY_EXHDR(). Elsewhere, call
+ * PG_DETOAST_DATUM(), VARDATA() and VARSIZE(). Directly fetching an int16,
+ * int32 or wider field in the struct representing the datum layout requires
+ * aligned data. memcpy() is alignment-oblivious, as are most operations on
+ * datatypes, such as text, whose layout struct contains only char fields.
+ *
+ * Code assembling a new datum should call VARDATA() and SET_VARSIZE().
+ * (Datums begin life untoasted.)
+ *
+ * Other macros here should usually be used only by tuple assembly/disassembly
+ * code and code that specifically wants to work with still-toasted Datums.
+ */
+#define VARDATA(PTR) VARDATA_4B(PTR)
+#define VARSIZE(PTR) VARSIZE_4B(PTR)
+
+#define VARSIZE_SHORT(PTR) VARSIZE_1B(PTR)
+#define VARDATA_SHORT(PTR) VARDATA_1B(PTR)
+
+#define VARTAG_EXTERNAL(PTR) VARTAG_1B_E(PTR)
+#define VARSIZE_EXTERNAL(PTR) (VARHDRSZ_EXTERNAL + VARTAG_SIZE(VARTAG_EXTERNAL(PTR)))
+#define VARDATA_EXTERNAL(PTR) VARDATA_1B_E(PTR)
+
+#define VARATT_IS_COMPRESSED(PTR) VARATT_IS_4B_C(PTR)
+#define VARATT_IS_EXTERNAL(PTR) VARATT_IS_1B_E(PTR)
+#define VARATT_IS_EXTERNAL_ONDISK(PTR) \
+ (VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_ONDISK)
+#define VARATT_IS_EXTERNAL_INDIRECT(PTR) \
+ (VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_INDIRECT)
+#define VARATT_IS_EXTERNAL_EXPANDED_RO(PTR) \
+ (VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_EXPANDED_RO)
+#define VARATT_IS_EXTERNAL_EXPANDED_RW(PTR) \
+ (VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_EXPANDED_RW)
+#define VARATT_IS_EXTERNAL_EXPANDED(PTR) \
+ (VARATT_IS_EXTERNAL(PTR) && VARTAG_IS_EXPANDED(VARTAG_EXTERNAL(PTR)))
+#define VARATT_IS_EXTERNAL_NON_EXPANDED(PTR) \
+ (VARATT_IS_EXTERNAL(PTR) && !VARTAG_IS_EXPANDED(VARTAG_EXTERNAL(PTR)))
+#define VARATT_IS_SHORT(PTR) VARATT_IS_1B(PTR)
+#define VARATT_IS_EXTENDED(PTR) (!VARATT_IS_4B_U(PTR))
+
+#define SET_VARSIZE(PTR, len) SET_VARSIZE_4B(PTR, len)
+#define SET_VARSIZE_SHORT(PTR, len) SET_VARSIZE_1B(PTR, len)
+#define SET_VARSIZE_COMPRESSED(PTR, len) SET_VARSIZE_4B_C(PTR, len)
+
+#define SET_VARTAG_EXTERNAL(PTR, tag) SET_VARTAG_1B_E(PTR, tag)
+
+#define VARSIZE_ANY(PTR) \
+ (VARATT_IS_1B_E(PTR) ? VARSIZE_EXTERNAL(PTR) : \
+ (VARATT_IS_1B(PTR) ? VARSIZE_1B(PTR) : \
+ VARSIZE_4B(PTR)))
+
+/* Size of a varlena data, excluding header */
+#define VARSIZE_ANY_EXHDR(PTR) \
+ (VARATT_IS_1B_E(PTR) ? VARSIZE_EXTERNAL(PTR)-VARHDRSZ_EXTERNAL : \
+ (VARATT_IS_1B(PTR) ? VARSIZE_1B(PTR)-VARHDRSZ_SHORT : \
+ VARSIZE_4B(PTR)-VARHDRSZ))
+
+/* caution: this will not work on an external or compressed-in-line Datum */
+/* caution: this will return a possibly unaligned pointer */
+#define VARDATA_ANY(PTR) \
+ (VARATT_IS_1B(PTR) ? VARDATA_1B(PTR) : VARDATA_4B(PTR))
+
+
+/* ----------------------------------------------------------------
+ * Section 2: Datum type + support macros
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * A Datum contains either a value of a pass-by-value type or a pointer to a
+ * value of a pass-by-reference type. Therefore, we require:
+ *
+ * sizeof(Datum) == sizeof(void *) == 4 or 8
+ *
+ * The macros below and the analogous macros for other types should be used to
+ * convert between a Datum and the appropriate C type.
+ */
+
+typedef uintptr_t Datum;
+
+/*
+ * A NullableDatum is used in places where both a Datum and its nullness needs
+ * to be stored. This can be more efficient than storing datums and nullness
+ * in separate arrays, due to better spatial locality, even if more space may
+ * be wasted due to padding.
+ */
+typedef struct NullableDatum
+{
+#define FIELDNO_NULLABLE_DATUM_DATUM 0
+ Datum value;
+#define FIELDNO_NULLABLE_DATUM_ISNULL 1
+ bool isnull;
+ /* due to alignment padding this could be used for flags for free */
+} NullableDatum;
+
+#define SIZEOF_DATUM SIZEOF_VOID_P
+
+/*
+ * DatumGetBool
+ * Returns boolean value of a datum.
+ *
+ * Note: any nonzero value will be considered true.
+ */
+
+#define DatumGetBool(X) ((bool) ((X) != 0))
+
+/*
+ * BoolGetDatum
+ * Returns datum representation for a boolean.
+ *
+ * Note: any nonzero value will be considered true.
+ */
+
+#define BoolGetDatum(X) ((Datum) ((X) ? 1 : 0))
+
+/*
+ * DatumGetChar
+ * Returns character value of a datum.
+ */
+
+#define DatumGetChar(X) ((char) (X))
+
+/*
+ * CharGetDatum
+ * Returns datum representation for a character.
+ */
+
+#define CharGetDatum(X) ((Datum) (X))
+
+/*
+ * Int8GetDatum
+ * Returns datum representation for an 8-bit integer.
+ */
+
+#define Int8GetDatum(X) ((Datum) (X))
+
+/*
+ * DatumGetUInt8
+ * Returns 8-bit unsigned integer value of a datum.
+ */
+
+#define DatumGetUInt8(X) ((uint8) (X))
+
+/*
+ * UInt8GetDatum
+ * Returns datum representation for an 8-bit unsigned integer.
+ */
+
+#define UInt8GetDatum(X) ((Datum) (X))
+
+/*
+ * DatumGetInt16
+ * Returns 16-bit integer value of a datum.
+ */
+
+#define DatumGetInt16(X) ((int16) (X))
+
+/*
+ * Int16GetDatum
+ * Returns datum representation for a 16-bit integer.
+ */
+
+#define Int16GetDatum(X) ((Datum) (X))
+
+/*
+ * DatumGetUInt16
+ * Returns 16-bit unsigned integer value of a datum.
+ */
+
+#define DatumGetUInt16(X) ((uint16) (X))
+
+/*
+ * UInt16GetDatum
+ * Returns datum representation for a 16-bit unsigned integer.
+ */
+
+#define UInt16GetDatum(X) ((Datum) (X))
+
+/*
+ * DatumGetInt32
+ * Returns 32-bit integer value of a datum.
+ */
+
+#define DatumGetInt32(X) ((int32) (X))
+
+/*
+ * Int32GetDatum
+ * Returns datum representation for a 32-bit integer.
+ */
+
+#define Int32GetDatum(X) ((Datum) (X))
+
+/*
+ * DatumGetUInt32
+ * Returns 32-bit unsigned integer value of a datum.
+ */
+
+#define DatumGetUInt32(X) ((uint32) (X))
+
+/*
+ * UInt32GetDatum
+ * Returns datum representation for a 32-bit unsigned integer.
+ */
+
+#define UInt32GetDatum(X) ((Datum) (X))
+
+/*
+ * DatumGetObjectId
+ * Returns object identifier value of a datum.
+ */
+
+#define DatumGetObjectId(X) ((Oid) (X))
+
+/*
+ * ObjectIdGetDatum
+ * Returns datum representation for an object identifier.
+ */
+
+#define ObjectIdGetDatum(X) ((Datum) (X))
+
+/*
+ * DatumGetTransactionId
+ * Returns transaction identifier value of a datum.
+ */
+
+#define DatumGetTransactionId(X) ((TransactionId) (X))
+
+/*
+ * TransactionIdGetDatum
+ * Returns datum representation for a transaction identifier.
+ */
+
+#define TransactionIdGetDatum(X) ((Datum) (X))
+
+/*
+ * MultiXactIdGetDatum
+ * Returns datum representation for a multixact identifier.
+ */
+
+#define MultiXactIdGetDatum(X) ((Datum) (X))
+
+/*
+ * DatumGetCommandId
+ * Returns command identifier value of a datum.
+ */
+
+#define DatumGetCommandId(X) ((CommandId) (X))
+
+/*
+ * CommandIdGetDatum
+ * Returns datum representation for a command identifier.
+ */
+
+#define CommandIdGetDatum(X) ((Datum) (X))
+
+/*
+ * DatumGetPointer
+ * Returns pointer value of a datum.
+ */
+
+#define DatumGetPointer(X) ((Pointer) (X))
+
+/*
+ * PointerGetDatum
+ * Returns datum representation for a pointer.
+ */
+
+#define PointerGetDatum(X) ((Datum) (X))
+
+/*
+ * DatumGetCString
+ * Returns C string (null-terminated string) value of a datum.
+ *
+ * Note: C string is not a full-fledged Postgres type at present,
+ * but type input functions use this conversion for their inputs.
+ */
+
+#define DatumGetCString(X) ((char *) DatumGetPointer(X))
+
+/*
+ * CStringGetDatum
+ * Returns datum representation for a C string (null-terminated string).
+ *
+ * Note: C string is not a full-fledged Postgres type at present,
+ * but type output functions use this conversion for their outputs.
+ * Note: CString is pass-by-reference; caller must ensure the pointed-to
+ * value has adequate lifetime.
+ */
+
+#define CStringGetDatum(X) PointerGetDatum(X)
+
+/*
+ * DatumGetName
+ * Returns name value of a datum.
+ */
+
+#define DatumGetName(X) ((Name) DatumGetPointer(X))
+
+/*
+ * NameGetDatum
+ * Returns datum representation for a name.
+ *
+ * Note: Name is pass-by-reference; caller must ensure the pointed-to
+ * value has adequate lifetime.
+ */
+
+#define NameGetDatum(X) CStringGetDatum(NameStr(*(X)))
+
+/*
+ * DatumGetInt64
+ * Returns 64-bit integer value of a datum.
+ *
+ * Note: this macro hides whether int64 is pass by value or by reference.
+ */
+
+#ifdef USE_FLOAT8_BYVAL
+#define DatumGetInt64(X) ((int64) (X))
+#else
+#define DatumGetInt64(X) (* ((int64 *) DatumGetPointer(X)))
+#endif
+
+/*
+ * Int64GetDatum
+ * Returns datum representation for a 64-bit integer.
+ *
+ * Note: if int64 is pass by reference, this function returns a reference
+ * to palloc'd space.
+ */
+
+#ifdef USE_FLOAT8_BYVAL
+#define Int64GetDatum(X) ((Datum) (X))
+#else
+extern Datum Int64GetDatum(int64 X);
+#endif
+
+/*
+ * DatumGetUInt64
+ * Returns 64-bit unsigned integer value of a datum.
+ *
+ * Note: this macro hides whether int64 is pass by value or by reference.
+ */
+
+#ifdef USE_FLOAT8_BYVAL
+#define DatumGetUInt64(X) ((uint64) (X))
+#else
+#define DatumGetUInt64(X) (* ((uint64 *) DatumGetPointer(X)))
+#endif
+
+/*
+ * UInt64GetDatum
+ * Returns datum representation for a 64-bit unsigned integer.
+ *
+ * Note: if int64 is pass by reference, this function returns a reference
+ * to palloc'd space.
+ */
+
+#ifdef USE_FLOAT8_BYVAL
+#define UInt64GetDatum(X) ((Datum) (X))
+#else
+#define UInt64GetDatum(X) Int64GetDatum((int64) (X))
+#endif
+
+/*
+ * Float <-> Datum conversions
+ *
+ * These have to be implemented as inline functions rather than macros, when
+ * passing by value, because many machines pass int and float function
+ * parameters/results differently; so we need to play weird games with unions.
+ */
+
+/*
+ * DatumGetFloat4
+ * Returns 4-byte floating point value of a datum.
+ */
+static inline float4
+DatumGetFloat4(Datum X)
+{
+ union
+ {
+ int32 value;
+ float4 retval;
+ } myunion;
+
+ myunion.value = DatumGetInt32(X);
+ return myunion.retval;
+}
+
+/*
+ * Float4GetDatum
+ * Returns datum representation for a 4-byte floating point number.
+ */
+static inline Datum
+Float4GetDatum(float4 X)
+{
+ union
+ {
+ float4 value;
+ int32 retval;
+ } myunion;
+
+ myunion.value = X;
+ return Int32GetDatum(myunion.retval);
+}
+
+/*
+ * DatumGetFloat8
+ * Returns 8-byte floating point value of a datum.
+ *
+ * Note: this macro hides whether float8 is pass by value or by reference.
+ */
+
+#ifdef USE_FLOAT8_BYVAL
+static inline float8
+DatumGetFloat8(Datum X)
+{
+ union
+ {
+ int64 value;
+ float8 retval;
+ } myunion;
+
+ myunion.value = DatumGetInt64(X);
+ return myunion.retval;
+}
+#else
+#define DatumGetFloat8(X) (* ((float8 *) DatumGetPointer(X)))
+#endif
+
+/*
+ * Float8GetDatum
+ * Returns datum representation for an 8-byte floating point number.
+ *
+ * Note: if float8 is pass by reference, this function returns a reference
+ * to palloc'd space.
+ */
+
+#ifdef USE_FLOAT8_BYVAL
+static inline Datum
+Float8GetDatum(float8 X)
+{
+ union
+ {
+ float8 value;
+ int64 retval;
+ } myunion;
+
+ myunion.value = X;
+ return Int64GetDatum(myunion.retval);
+}
+#else
+extern Datum Float8GetDatum(float8 X);
+#endif
+
+
+/*
+ * Int64GetDatumFast
+ * Float8GetDatumFast
+ *
+ * These macros are intended to allow writing code that does not depend on
+ * whether int64 and float8 are pass-by-reference types, while not
+ * sacrificing performance when they are. The argument must be a variable
+ * that will exist and have the same value for as long as the Datum is needed.
+ * In the pass-by-ref case, the address of the variable is taken to use as
+ * the Datum. In the pass-by-val case, these will be the same as the non-Fast
+ * macros.
+ */
+
+#ifdef USE_FLOAT8_BYVAL
+#define Int64GetDatumFast(X) Int64GetDatum(X)
+#define Float8GetDatumFast(X) Float8GetDatum(X)
+#else
+#define Int64GetDatumFast(X) PointerGetDatum(&(X))
+#define Float8GetDatumFast(X) PointerGetDatum(&(X))
+#endif
+
+#endif /* POSTGRES_H */
diff --git a/src/include/postgres_ext.h b/src/include/postgres_ext.h
new file mode 100644
index 0000000..fdb61b7
--- /dev/null
+++ b/src/include/postgres_ext.h
@@ -0,0 +1,74 @@
+/*-------------------------------------------------------------------------
+ *
+ * postgres_ext.h
+ *
+ * This file contains declarations of things that are visible everywhere
+ * in PostgreSQL *and* are visible to clients of frontend interface libraries.
+ * For example, the Oid type is part of the API of libpq and other libraries.
+ *
+ * Declarations which are specific to a particular interface should
+ * go in the header file for that interface (such as libpq-fe.h). This
+ * file is only for fundamental Postgres declarations.
+ *
+ * User-written C functions don't count as "external to Postgres."
+ * Those function much as local modifications to the backend itself, and
+ * use header files that are otherwise internal to Postgres to interface
+ * with the backend.
+ *
+ * src/include/postgres_ext.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef POSTGRES_EXT_H
+#define POSTGRES_EXT_H
+
+#include "pg_config_ext.h"
+
+/*
+ * Object ID is a fundamental type in Postgres.
+ */
+typedef unsigned int Oid;
+
+#ifdef __cplusplus
+#define InvalidOid (Oid(0))
+#else
+#define InvalidOid ((Oid) 0)
+#endif
+
+#define OID_MAX UINT_MAX
+/* you will need to include <limits.h> to use the above #define */
+
+#define atooid(x) ((Oid) strtoul((x), NULL, 10))
+/* the above needs <stdlib.h> */
+
+
+/* Define a signed 64-bit integer type for use in client API declarations. */
+typedef PG_INT64_TYPE pg_int64;
+
+
+/*
+ * Identifiers of error message fields. Kept here to keep common
+ * between frontend and backend, and also to export them to libpq
+ * applications.
+ */
+#define PG_DIAG_SEVERITY 'S'
+#define PG_DIAG_SEVERITY_NONLOCALIZED 'V'
+#define PG_DIAG_SQLSTATE 'C'
+#define PG_DIAG_MESSAGE_PRIMARY 'M'
+#define PG_DIAG_MESSAGE_DETAIL 'D'
+#define PG_DIAG_MESSAGE_HINT 'H'
+#define PG_DIAG_STATEMENT_POSITION 'P'
+#define PG_DIAG_INTERNAL_POSITION 'p'
+#define PG_DIAG_INTERNAL_QUERY 'q'
+#define PG_DIAG_CONTEXT 'W'
+#define PG_DIAG_SCHEMA_NAME 's'
+#define PG_DIAG_TABLE_NAME 't'
+#define PG_DIAG_COLUMN_NAME 'c'
+#define PG_DIAG_DATATYPE_NAME 'd'
+#define PG_DIAG_CONSTRAINT_NAME 'n'
+#define PG_DIAG_SOURCE_FILE 'F'
+#define PG_DIAG_SOURCE_LINE 'L'
+#define PG_DIAG_SOURCE_FUNCTION 'R'
+
+#endif /* POSTGRES_EXT_H */
diff --git a/src/include/postgres_fe.h b/src/include/postgres_fe.h
new file mode 100644
index 0000000..e99258f
--- /dev/null
+++ b/src/include/postgres_fe.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ *
+ * postgres_fe.h
+ * Primary include file for PostgreSQL client-side .c files
+ *
+ * This should be the first file included by PostgreSQL client libraries and
+ * application programs --- but not by backend modules, which should include
+ * postgres.h.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1995, Regents of the University of California
+ *
+ * src/include/postgres_fe.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef POSTGRES_FE_H
+#define POSTGRES_FE_H
+
+#ifndef FRONTEND
+#define FRONTEND 1
+#endif
+
+#include "c.h"
+
+#include "common/fe_memutils.h"
+
+#endif /* POSTGRES_FE_H */
diff --git a/src/include/postmaster/autovacuum.h b/src/include/postmaster/autovacuum.h
new file mode 100644
index 0000000..7277eff
--- /dev/null
+++ b/src/include/postmaster/autovacuum.h
@@ -0,0 +1,83 @@
+/*-------------------------------------------------------------------------
+ *
+ * autovacuum.h
+ * header file for integrated autovacuum daemon
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/postmaster/autovacuum.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef AUTOVACUUM_H
+#define AUTOVACUUM_H
+
+#include "storage/block.h"
+
+/*
+ * Other processes can request specific work from autovacuum, identified by
+ * AutoVacuumWorkItem elements.
+ */
+typedef enum
+{
+ AVW_BRINSummarizeRange
+} AutoVacuumWorkItemType;
+
+
+/* GUC variables */
+extern bool autovacuum_start_daemon;
+extern int autovacuum_max_workers;
+extern int autovacuum_work_mem;
+extern int autovacuum_naptime;
+extern int autovacuum_vac_thresh;
+extern double autovacuum_vac_scale;
+extern int autovacuum_vac_ins_thresh;
+extern double autovacuum_vac_ins_scale;
+extern int autovacuum_anl_thresh;
+extern double autovacuum_anl_scale;
+extern int autovacuum_freeze_max_age;
+extern int autovacuum_multixact_freeze_max_age;
+extern double autovacuum_vac_cost_delay;
+extern int autovacuum_vac_cost_limit;
+
+/* autovacuum launcher PID, only valid when worker is shutting down */
+extern int AutovacuumLauncherPid;
+
+extern int Log_autovacuum_min_duration;
+
+/* Status inquiry functions */
+extern bool AutoVacuumingActive(void);
+extern bool IsAutoVacuumLauncherProcess(void);
+extern bool IsAutoVacuumWorkerProcess(void);
+
+#define IsAnyAutoVacuumProcess() \
+ (IsAutoVacuumLauncherProcess() || IsAutoVacuumWorkerProcess())
+
+/* Functions to start autovacuum process, called from postmaster */
+extern void autovac_init(void);
+extern int StartAutoVacLauncher(void);
+extern int StartAutoVacWorker(void);
+
+/* called from postmaster when a worker could not be forked */
+extern void AutoVacWorkerFailed(void);
+
+/* autovacuum cost-delay balancer */
+extern void AutoVacuumUpdateDelay(void);
+
+#ifdef EXEC_BACKEND
+extern void AutoVacLauncherMain(int argc, char *argv[]) pg_attribute_noreturn();
+extern void AutoVacWorkerMain(int argc, char *argv[]) pg_attribute_noreturn();
+extern void AutovacuumWorkerIAm(void);
+extern void AutovacuumLauncherIAm(void);
+#endif
+
+extern bool AutoVacuumRequestWork(AutoVacuumWorkItemType type,
+ Oid relationId, BlockNumber blkno);
+
+/* shared memory stuff */
+extern Size AutoVacuumShmemSize(void);
+extern void AutoVacuumShmemInit(void);
+
+#endif /* AUTOVACUUM_H */
diff --git a/src/include/postmaster/bgworker.h b/src/include/postmaster/bgworker.h
new file mode 100644
index 0000000..4c6ebaa
--- /dev/null
+++ b/src/include/postmaster/bgworker.h
@@ -0,0 +1,161 @@
+/*--------------------------------------------------------------------
+ * bgworker.h
+ * POSTGRES pluggable background workers interface
+ *
+ * A background worker is a process able to run arbitrary, user-supplied code,
+ * including normal transactions.
+ *
+ * Any external module loaded via shared_preload_libraries can register a
+ * worker. Workers can also be registered dynamically at runtime. In either
+ * case, the worker process is forked from the postmaster and runs the
+ * user-supplied "main" function. This code may connect to a database and
+ * run transactions. Workers can remain active indefinitely, but will be
+ * terminated if a shutdown or crash occurs.
+ *
+ * If the fork() call fails in the postmaster, it will try again later. Note
+ * that the failure can only be transient (fork failure due to high load,
+ * memory pressure, too many processes, etc); more permanent problems, like
+ * failure to connect to a database, are detected later in the worker and dealt
+ * with just by having the worker exit normally. A worker which exits with
+ * a return code of 0 will never be restarted and will be removed from worker
+ * list. A worker which exits with a return code of 1 will be restarted after
+ * the configured restart interval (unless that interval is BGW_NEVER_RESTART).
+ * The TerminateBackgroundWorker() function can be used to terminate a
+ * dynamically registered background worker; the worker will be sent a SIGTERM
+ * and will not be restarted after it exits. Whenever the postmaster knows
+ * that a worker will not be restarted, it unregisters the worker, freeing up
+ * that worker's slot for use by a new worker.
+ *
+ * Note that there might be more than one worker in a database concurrently,
+ * and the same module may request more than one worker running the same (or
+ * different) code.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/postmaster/bgworker.h
+ *--------------------------------------------------------------------
+ */
+#ifndef BGWORKER_H
+#define BGWORKER_H
+
+/*---------------------------------------------------------------------
+ * External module API.
+ *---------------------------------------------------------------------
+ */
+
+/*
+ * Pass this flag to have your worker be able to connect to shared memory.
+ */
+#define BGWORKER_SHMEM_ACCESS 0x0001
+
+/*
+ * This flag means the bgworker requires a database connection. The connection
+ * is not established automatically; the worker must establish it later.
+ * It requires that BGWORKER_SHMEM_ACCESS was passed too.
+ */
+#define BGWORKER_BACKEND_DATABASE_CONNECTION 0x0002
+
+/*
+ * This class is used internally for parallel queries, to keep track of the
+ * number of active parallel workers and make sure we never launch more than
+ * max_parallel_workers parallel workers at the same time. Third party
+ * background workers should not use this class.
+ */
+#define BGWORKER_CLASS_PARALLEL 0x0010
+/* add additional bgworker classes here */
+
+
+typedef void (*bgworker_main_type) (Datum main_arg);
+
+/*
+ * Points in time at which a bgworker can request to be started
+ */
+typedef enum
+{
+ BgWorkerStart_PostmasterStart,
+ BgWorkerStart_ConsistentState,
+ BgWorkerStart_RecoveryFinished
+} BgWorkerStartTime;
+
+#define BGW_DEFAULT_RESTART_INTERVAL 60
+#define BGW_NEVER_RESTART -1
+#define BGW_MAXLEN 96
+#define BGW_EXTRALEN 128
+
+typedef struct BackgroundWorker
+{
+ char bgw_name[BGW_MAXLEN];
+ char bgw_type[BGW_MAXLEN];
+ int bgw_flags;
+ BgWorkerStartTime bgw_start_time;
+ int bgw_restart_time; /* in seconds, or BGW_NEVER_RESTART */
+ char bgw_library_name[BGW_MAXLEN];
+ char bgw_function_name[BGW_MAXLEN];
+ Datum bgw_main_arg;
+ char bgw_extra[BGW_EXTRALEN];
+ pid_t bgw_notify_pid; /* SIGUSR1 this backend on start/stop */
+} BackgroundWorker;
+
+typedef enum BgwHandleStatus
+{
+ BGWH_STARTED, /* worker is running */
+ BGWH_NOT_YET_STARTED, /* worker hasn't been started yet */
+ BGWH_STOPPED, /* worker has exited */
+ BGWH_POSTMASTER_DIED /* postmaster died; worker status unclear */
+} BgwHandleStatus;
+
+struct BackgroundWorkerHandle;
+typedef struct BackgroundWorkerHandle BackgroundWorkerHandle;
+
+/* Register a new bgworker during shared_preload_libraries */
+extern void RegisterBackgroundWorker(BackgroundWorker *worker);
+
+/* Register a new bgworker from a regular backend */
+extern bool RegisterDynamicBackgroundWorker(BackgroundWorker *worker,
+ BackgroundWorkerHandle **handle);
+
+/* Query the status of a bgworker */
+extern BgwHandleStatus GetBackgroundWorkerPid(BackgroundWorkerHandle *handle,
+ pid_t *pidp);
+extern BgwHandleStatus WaitForBackgroundWorkerStartup(BackgroundWorkerHandle *handle, pid_t *pid);
+extern BgwHandleStatus
+ WaitForBackgroundWorkerShutdown(BackgroundWorkerHandle *);
+extern const char *GetBackgroundWorkerTypeByPid(pid_t pid);
+
+/* Terminate a bgworker */
+extern void TerminateBackgroundWorker(BackgroundWorkerHandle *handle);
+
+/* This is valid in a running worker */
+extern PGDLLIMPORT BackgroundWorker *MyBgworkerEntry;
+
+/*
+ * Connect to the specified database, as the specified user. Only a worker
+ * that passed BGWORKER_BACKEND_DATABASE_CONNECTION during registration may
+ * call this.
+ *
+ * If username is NULL, bootstrapping superuser is used.
+ * If dbname is NULL, connection is made to no specific database;
+ * only shared catalogs can be accessed.
+ */
+extern void BackgroundWorkerInitializeConnection(const char *dbname, const char *username, uint32 flags);
+
+/* Just like the above, but specifying database and user by OID. */
+extern void BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid, uint32 flags);
+
+/*
+ * Flags to BackgroundWorkerInitializeConnection et al
+ *
+ *
+ * Allow bypassing datallowconn restrictions when connecting to database
+ */
+#define BGWORKER_BYPASS_ALLOWCONN 1
+
+
+/* Block/unblock signals in a background worker process */
+extern void BackgroundWorkerBlockSignals(void);
+extern void BackgroundWorkerUnblockSignals(void);
+
+#endif /* BGWORKER_H */
diff --git a/src/include/postmaster/bgworker_internals.h b/src/include/postmaster/bgworker_internals.h
new file mode 100644
index 0000000..dd6cabc
--- /dev/null
+++ b/src/include/postmaster/bgworker_internals.h
@@ -0,0 +1,64 @@
+/*--------------------------------------------------------------------
+ * bgworker_internals.h
+ * POSTGRES pluggable background workers internals
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/postmaster/bgworker_internals.h
+ *--------------------------------------------------------------------
+ */
+#ifndef BGWORKER_INTERNALS_H
+#define BGWORKER_INTERNALS_H
+
+#include "datatype/timestamp.h"
+#include "lib/ilist.h"
+#include "postmaster/bgworker.h"
+
+/* GUC options */
+
+/*
+ * Maximum possible value of parallel workers.
+ */
+#define MAX_PARALLEL_WORKER_LIMIT 1024
+
+/*
+ * List of background workers, private to postmaster.
+ *
+ * A worker that requests a database connection during registration will have
+ * rw_backend set, and will be present in BackendList. Note: do not rely on
+ * rw_backend being non-NULL for shmem-connected workers!
+ */
+typedef struct RegisteredBgWorker
+{
+ BackgroundWorker rw_worker; /* its registry entry */
+ struct bkend *rw_backend; /* its BackendList entry, or NULL */
+ pid_t rw_pid; /* 0 if not running */
+ int rw_child_slot;
+ TimestampTz rw_crashed_at; /* if not 0, time it last crashed */
+ int rw_shmem_slot;
+ bool rw_terminate;
+ slist_node rw_lnode; /* list link */
+} RegisteredBgWorker;
+
+extern slist_head BackgroundWorkerList;
+
+extern Size BackgroundWorkerShmemSize(void);
+extern void BackgroundWorkerShmemInit(void);
+extern void BackgroundWorkerStateChange(bool allow_new_workers);
+extern void ForgetBackgroundWorker(slist_mutable_iter *cur);
+extern void ReportBackgroundWorkerPID(RegisteredBgWorker *);
+extern void ReportBackgroundWorkerExit(slist_mutable_iter *cur);
+extern void BackgroundWorkerStopNotifications(pid_t pid);
+extern void ForgetUnstartedBackgroundWorkers(void);
+extern void ResetBackgroundWorkerCrashTimes(void);
+
+/* Function to start a background worker, called from postmaster.c */
+extern void StartBackgroundWorker(void) pg_attribute_noreturn();
+
+#ifdef EXEC_BACKEND
+extern BackgroundWorker *BackgroundWorkerEntry(int slotno);
+#endif
+
+#endif /* BGWORKER_INTERNALS_H */
diff --git a/src/include/postmaster/bgwriter.h b/src/include/postmaster/bgwriter.h
new file mode 100644
index 0000000..0a5708b
--- /dev/null
+++ b/src/include/postmaster/bgwriter.h
@@ -0,0 +1,45 @@
+/*-------------------------------------------------------------------------
+ *
+ * bgwriter.h
+ * Exports from postmaster/bgwriter.c and postmaster/checkpointer.c.
+ *
+ * The bgwriter process used to handle checkpointing duties too. Now
+ * there is a separate process, but we did not bother to split this header.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ *
+ * src/include/postmaster/bgwriter.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _BGWRITER_H
+#define _BGWRITER_H
+
+#include "storage/block.h"
+#include "storage/relfilenode.h"
+#include "storage/smgr.h"
+#include "storage/sync.h"
+
+
+/* GUC options */
+extern int BgWriterDelay;
+extern int CheckPointTimeout;
+extern int CheckPointWarning;
+extern double CheckPointCompletionTarget;
+
+extern void BackgroundWriterMain(void) pg_attribute_noreturn();
+extern void CheckpointerMain(void) pg_attribute_noreturn();
+
+extern void RequestCheckpoint(int flags);
+extern void CheckpointWriteDelay(int flags, double progress);
+
+extern bool ForwardSyncRequest(const FileTag *ftag, SyncRequestType type);
+
+extern void AbsorbSyncRequests(void);
+
+extern Size CheckpointerShmemSize(void);
+extern void CheckpointerShmemInit(void);
+
+extern bool FirstCallSinceLastCheckpoint(void);
+
+#endif /* _BGWRITER_H */
diff --git a/src/include/postmaster/fork_process.h b/src/include/postmaster/fork_process.h
new file mode 100644
index 0000000..8cb568f
--- /dev/null
+++ b/src/include/postmaster/fork_process.h
@@ -0,0 +1,17 @@
+/*-------------------------------------------------------------------------
+ *
+ * fork_process.h
+ * Exports from postmaster/fork_process.c.
+ *
+ * Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ *
+ * src/include/postmaster/fork_process.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FORK_PROCESS_H
+#define FORK_PROCESS_H
+
+extern pid_t fork_process(void);
+
+#endif /* FORK_PROCESS_H */
diff --git a/src/include/postmaster/interrupt.h b/src/include/postmaster/interrupt.h
new file mode 100644
index 0000000..4f56712
--- /dev/null
+++ b/src/include/postmaster/interrupt.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * interrupt.h
+ * Interrupt handling routines.
+ *
+ * Responses to interrupts are fairly varied and many types of backends
+ * have their own implementations, but we provide a few generic things
+ * here to facilitate code reuse.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/postmaster/interrupt.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef INTERRUPT_H
+#define INTERRUPT_H
+
+#include <signal.h>
+
+extern PGDLLIMPORT volatile sig_atomic_t ConfigReloadPending;
+extern PGDLLIMPORT volatile sig_atomic_t ShutdownRequestPending;
+
+extern void HandleMainLoopInterrupts(void);
+extern void SignalHandlerForConfigReload(SIGNAL_ARGS);
+extern void SignalHandlerForCrashExit(SIGNAL_ARGS);
+extern void SignalHandlerForShutdownRequest(SIGNAL_ARGS);
+
+#endif
diff --git a/src/include/postmaster/pgarch.h b/src/include/postmaster/pgarch.h
new file mode 100644
index 0000000..b320087
--- /dev/null
+++ b/src/include/postmaster/pgarch.h
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgarch.h
+ * Exports from postmaster/pgarch.c.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/postmaster/pgarch.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _PGARCH_H
+#define _PGARCH_H
+
+/* ----------
+ * Archiver control info.
+ *
+ * We expect that archivable files within pg_wal will have names between
+ * MIN_XFN_CHARS and MAX_XFN_CHARS in length, consisting only of characters
+ * appearing in VALID_XFN_CHARS. The status files in archive_status have
+ * corresponding names with ".ready" or ".done" appended.
+ * ----------
+ */
+#define MIN_XFN_CHARS 16
+#define MAX_XFN_CHARS 40
+#define VALID_XFN_CHARS "0123456789ABCDEF.history.backup.partial"
+
+/* ----------
+ * Functions called from postmaster
+ * ----------
+ */
+extern int pgarch_start(void);
+
+#ifdef EXEC_BACKEND
+extern void PgArchiverMain(int argc, char *argv[]) pg_attribute_noreturn();
+#endif
+
+#endif /* _PGARCH_H */
diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h
new file mode 100644
index 0000000..babc87d
--- /dev/null
+++ b/src/include/postmaster/postmaster.h
@@ -0,0 +1,77 @@
+/*-------------------------------------------------------------------------
+ *
+ * postmaster.h
+ * Exports from postmaster/postmaster.c.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/postmaster/postmaster.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _POSTMASTER_H
+#define _POSTMASTER_H
+
+/* GUC options */
+extern bool EnableSSL;
+extern int ReservedBackends;
+extern PGDLLIMPORT int PostPortNumber;
+extern int Unix_socket_permissions;
+extern char *Unix_socket_group;
+extern char *Unix_socket_directories;
+extern char *ListenAddresses;
+extern bool ClientAuthInProgress;
+extern int PreAuthDelay;
+extern int AuthenticationTimeout;
+extern bool Log_connections;
+extern bool log_hostname;
+extern bool enable_bonjour;
+extern char *bonjour_name;
+extern bool restart_after_crash;
+
+#ifdef WIN32
+extern HANDLE PostmasterHandle;
+#else
+extern int postmaster_alive_fds[2];
+
+/*
+ * Constants that represent which of postmaster_alive_fds is held by
+ * postmaster, and which is used in children to check for postmaster death.
+ */
+#define POSTMASTER_FD_WATCH 0 /* used in children to check for
+ * postmaster death */
+#define POSTMASTER_FD_OWN 1 /* kept open by postmaster only */
+#endif
+
+extern PGDLLIMPORT const char *progname;
+
+extern void PostmasterMain(int argc, char *argv[]) pg_attribute_noreturn();
+extern void ClosePostmasterPorts(bool am_syslogger);
+extern void InitProcessGlobals(void);
+
+extern int MaxLivePostmasterChildren(void);
+
+extern bool PostmasterMarkPIDForWorkerNotify(int);
+
+#ifdef EXEC_BACKEND
+extern pid_t postmaster_forkexec(int argc, char *argv[]);
+extern void SubPostmasterMain(int argc, char *argv[]) pg_attribute_noreturn();
+
+extern Size ShmemBackendArraySize(void);
+extern void ShmemBackendArrayAllocation(void);
+#endif
+
+/*
+ * Note: MAX_BACKENDS is limited to 2^18-1 because that's the width reserved
+ * for buffer references in buf_internals.h. This limitation could be lifted
+ * by using a 64bit state; but it's unlikely to be worthwhile as 2^18-1
+ * backends exceed currently realistic configurations. Even if that limitation
+ * were removed, we still could not a) exceed 2^23-1 because inval.c stores
+ * the backend ID as a 3-byte signed integer, b) INT_MAX/4 because some places
+ * compute 4*MaxBackends without any overflow check. This is rechecked in the
+ * relevant GUC check hooks and in RegisterBackgroundWorker().
+ */
+#define MAX_BACKENDS 0x3FFFF
+
+#endif /* _POSTMASTER_H */
diff --git a/src/include/postmaster/startup.h b/src/include/postmaster/startup.h
new file mode 100644
index 0000000..bec3137
--- /dev/null
+++ b/src/include/postmaster/startup.h
@@ -0,0 +1,22 @@
+/*-------------------------------------------------------------------------
+ *
+ * startup.h
+ * Exports from postmaster/startup.c.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ *
+ * src/include/postmaster/startup.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _STARTUP_H
+#define _STARTUP_H
+
+extern void HandleStartupProcInterrupts(void);
+extern void StartupProcessMain(void) pg_attribute_noreturn();
+extern void PreRestoreCommand(void);
+extern void PostRestoreCommand(void);
+extern bool IsPromoteSignaled(void);
+extern void ResetPromoteSignaled(void);
+
+#endif /* _STARTUP_H */
diff --git a/src/include/postmaster/syslogger.h b/src/include/postmaster/syslogger.h
new file mode 100644
index 0000000..f611bd1
--- /dev/null
+++ b/src/include/postmaster/syslogger.h
@@ -0,0 +1,98 @@
+/*-------------------------------------------------------------------------
+ *
+ * syslogger.h
+ * Exports from postmaster/syslogger.c.
+ *
+ * Copyright (c) 2004-2020, PostgreSQL Global Development Group
+ *
+ * src/include/postmaster/syslogger.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _SYSLOGGER_H
+#define _SYSLOGGER_H
+
+#include <limits.h> /* for PIPE_BUF */
+
+
+/*
+ * Primitive protocol structure for writing to syslogger pipe(s). The idea
+ * here is to divide long messages into chunks that are not more than
+ * PIPE_BUF bytes long, which according to POSIX spec must be written into
+ * the pipe atomically. The pipe reader then uses the protocol headers to
+ * reassemble the parts of a message into a single string. The reader can
+ * also cope with non-protocol data coming down the pipe, though we cannot
+ * guarantee long strings won't get split apart.
+ *
+ * We use non-nul bytes in is_last to make the protocol a tiny bit
+ * more robust against finding a false double nul byte prologue. But
+ * we still might find it in the len and/or pid bytes unless we're careful.
+ */
+
+#ifdef PIPE_BUF
+/* Are there any systems with PIPE_BUF > 64K? Unlikely, but ... */
+#if PIPE_BUF > 65536
+#define PIPE_CHUNK_SIZE 65536
+#else
+#define PIPE_CHUNK_SIZE ((int) PIPE_BUF)
+#endif
+#else /* not defined */
+/* POSIX says the value of PIPE_BUF must be at least 512, so use that */
+#define PIPE_CHUNK_SIZE 512
+#endif
+
+typedef struct
+{
+ char nuls[2]; /* always \0\0 */
+ uint16 len; /* size of this chunk (counts data only) */
+ int32 pid; /* writer's pid */
+ char is_last; /* last chunk of message? 't' or 'f' ('T' or
+ * 'F' for CSV case) */
+ char data[FLEXIBLE_ARRAY_MEMBER]; /* data payload starts here */
+} PipeProtoHeader;
+
+typedef union
+{
+ PipeProtoHeader proto;
+ char filler[PIPE_CHUNK_SIZE];
+} PipeProtoChunk;
+
+#define PIPE_HEADER_SIZE offsetof(PipeProtoHeader, data)
+#define PIPE_MAX_PAYLOAD ((int) (PIPE_CHUNK_SIZE - PIPE_HEADER_SIZE))
+
+
+/* GUC options */
+extern bool Logging_collector;
+extern int Log_RotationAge;
+extern int Log_RotationSize;
+extern PGDLLIMPORT char *Log_directory;
+extern PGDLLIMPORT char *Log_filename;
+extern bool Log_truncate_on_rotation;
+extern int Log_file_mode;
+
+#ifndef WIN32
+extern int syslogPipe[2];
+#else
+extern HANDLE syslogPipe[2];
+#endif
+
+
+extern int SysLogger_Start(void);
+
+extern void write_syslogger_file(const char *buffer, int count, int dest);
+
+#ifdef EXEC_BACKEND
+extern void SysLoggerMain(int argc, char *argv[]) pg_attribute_noreturn();
+#endif
+
+extern bool CheckLogrotateSignal(void);
+extern void RemoveLogrotateSignalFiles(void);
+
+/*
+ * Name of files saving meta-data information about the log
+ * files currently in use by the syslogger
+ */
+#define LOG_METAINFO_DATAFILE "current_logfiles"
+#define LOG_METAINFO_DATAFILE_TMP LOG_METAINFO_DATAFILE ".tmp"
+
+#endif /* _SYSLOGGER_H */
diff --git a/src/include/postmaster/walwriter.h b/src/include/postmaster/walwriter.h
new file mode 100644
index 0000000..011dc26
--- /dev/null
+++ b/src/include/postmaster/walwriter.h
@@ -0,0 +1,21 @@
+/*-------------------------------------------------------------------------
+ *
+ * walwriter.h
+ * Exports from postmaster/walwriter.c.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ *
+ * src/include/postmaster/walwriter.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _WALWRITER_H
+#define _WALWRITER_H
+
+/* GUC options */
+extern int WalWriterDelay;
+extern int WalWriterFlushAfter;
+
+extern void WalWriterMain(void) pg_attribute_noreturn();
+
+#endif /* _WALWRITER_H */
diff --git a/src/include/regex/regcustom.h b/src/include/regex/regcustom.h
new file mode 100644
index 0000000..100c52d
--- /dev/null
+++ b/src/include/regex/regcustom.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
+ *
+ * Development of this software was funded, in part, by Cray Research Inc.,
+ * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
+ * Corporation, none of whom are responsible for the results. The author
+ * thanks all of them.
+ *
+ * Redistribution and use in source and binary forms -- with or without
+ * modification -- are permitted for any purpose, provided that
+ * redistributions in source form retain this entire copyright notice and
+ * indicate the origin and nature of any modifications.
+ *
+ * I'd appreciate being given credit for this package in the documentation
+ * of software which uses it, but that is not a requirement.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * src/include/regex/regcustom.h
+ */
+
+/* headers if any */
+
+/*
+ * It's against Postgres coding conventions to include postgres.h in a
+ * header file, but we allow the violation here because the regexp library
+ * files specifically intend this file to supply application-dependent
+ * headers, and are careful to include this file before anything else.
+ */
+#include "postgres.h"
+
+#include <ctype.h>
+#include <limits.h>
+
+/*
+ * towlower() and friends should be in <wctype.h>, but some pre-C99 systems
+ * declare them in <wchar.h>, so include that too.
+ */
+#include <wchar.h>
+#ifdef HAVE_WCTYPE_H
+#include <wctype.h>
+#endif
+
+#include "mb/pg_wchar.h"
+
+#include "miscadmin.h" /* needed by rcancelrequested/rstacktoodeep */
+
+
+/* overrides for regguts.h definitions, if any */
+#define FUNCPTR(name, args) (*name) args
+#define MALLOC(n) malloc(n)
+#define FREE(p) free(VS(p))
+#define REALLOC(p,n) realloc(VS(p),n)
+#define assert(x) Assert(x)
+
+/* internal character type and related */
+typedef pg_wchar chr; /* the type itself */
+typedef unsigned uchr; /* unsigned type that will hold a chr */
+
+#define CHR(c) ((unsigned char) (c)) /* turn char literal into chr literal */
+#define DIGITVAL(c) ((c)-'0') /* turn chr digit into its value */
+#define CHRBITS 32 /* bits in a chr; must not use sizeof */
+#define CHR_MIN 0x00000000 /* smallest and largest chr; the value */
+#define CHR_MAX 0x7ffffffe /* CHR_MAX-CHR_MIN+1 must fit in an int, and
+ * CHR_MAX+1 must fit in a chr variable */
+
+/*
+ * Check if a chr value is in range. Ideally we'd just write this as
+ * ((c) >= CHR_MIN && (c) <= CHR_MAX)
+ * However, if chr is unsigned and CHR_MIN is zero, the first part of that
+ * is a no-op, and certain overly-nannyish compilers give warnings about it.
+ * So we leave that out here. If you want to make chr signed and/or CHR_MIN
+ * not zero, redefine this macro as above. Callers should assume that the
+ * macro may multiply evaluate its argument, even though it does not today.
+ */
+#define CHR_IS_IN_RANGE(c) ((c) <= CHR_MAX)
+
+/*
+ * MAX_SIMPLE_CHR is the cutoff between "simple" and "complicated" processing
+ * in the color map logic. It should usually be chosen high enough to ensure
+ * that all common characters are <= MAX_SIMPLE_CHR. However, very large
+ * values will be counterproductive since they cause more regex setup time.
+ * Also, small values can be helpful for testing the high-color-map logic
+ * with plain old ASCII input.
+ */
+#define MAX_SIMPLE_CHR 0x7FF /* suitable value for Unicode */
+
+/* functions operating on chr */
+#define iscalnum(x) pg_wc_isalnum(x)
+#define iscalpha(x) pg_wc_isalpha(x)
+#define iscdigit(x) pg_wc_isdigit(x)
+#define iscspace(x) pg_wc_isspace(x)
+
+/* and pick up the standard header */
+#include "regex.h"
diff --git a/src/include/regex/regerrs.h b/src/include/regex/regerrs.h
new file mode 100644
index 0000000..41e25f7
--- /dev/null
+++ b/src/include/regex/regerrs.h
@@ -0,0 +1,87 @@
+/*
+ * src/include/regex/regerrs.h
+ */
+
+{
+ REG_OKAY, "REG_OKAY", "no errors detected"
+},
+
+{
+ REG_NOMATCH, "REG_NOMATCH", "failed to match"
+},
+
+{
+ REG_BADPAT, "REG_BADPAT", "invalid regexp (reg version 0.8)"
+},
+
+{
+ REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element"
+},
+
+{
+ REG_ECTYPE, "REG_ECTYPE", "invalid character class"
+},
+
+{
+ REG_EESCAPE, "REG_EESCAPE", "invalid escape \\ sequence"
+},
+
+{
+ REG_ESUBREG, "REG_ESUBREG", "invalid backreference number"
+},
+
+{
+ REG_EBRACK, "REG_EBRACK", "brackets [] not balanced"
+},
+
+{
+ REG_EPAREN, "REG_EPAREN", "parentheses () not balanced"
+},
+
+{
+ REG_EBRACE, "REG_EBRACE", "braces {} not balanced"
+},
+
+{
+ REG_BADBR, "REG_BADBR", "invalid repetition count(s)"
+},
+
+{
+ REG_ERANGE, "REG_ERANGE", "invalid character range"
+},
+
+{
+ REG_ESPACE, "REG_ESPACE", "out of memory"
+},
+
+{
+ REG_BADRPT, "REG_BADRPT", "quantifier operand invalid"
+},
+
+{
+ REG_ASSERT, "REG_ASSERT", "\"cannot happen\" -- you found a bug"
+},
+
+{
+ REG_INVARG, "REG_INVARG", "invalid argument to regex function"
+},
+
+{
+ REG_MIXED, "REG_MIXED", "character widths of regex and string differ"
+},
+
+{
+ REG_BADOPT, "REG_BADOPT", "invalid embedded option"
+},
+
+{
+ REG_ETOOBIG, "REG_ETOOBIG", "regular expression is too complex"
+},
+
+{
+ REG_ECOLORS, "REG_ECOLORS", "too many colors"
+},
+
+{
+ REG_CANCEL, "REG_CANCEL", "operation cancelled"
+},
diff --git a/src/include/regex/regex.h b/src/include/regex/regex.h
new file mode 100644
index 0000000..dc31899
--- /dev/null
+++ b/src/include/regex/regex.h
@@ -0,0 +1,184 @@
+#ifndef _REGEX_H_
+#define _REGEX_H_ /* never again */
+/*
+ * regular expressions
+ *
+ * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
+ *
+ * Development of this software was funded, in part, by Cray Research Inc.,
+ * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
+ * Corporation, none of whom are responsible for the results. The author
+ * thanks all of them.
+ *
+ * Redistribution and use in source and binary forms -- with or without
+ * modification -- are permitted for any purpose, provided that
+ * redistributions in source form retain this entire copyright notice and
+ * indicate the origin and nature of any modifications.
+ *
+ * I'd appreciate being given credit for this package in the documentation
+ * of software which uses it, but that is not a requirement.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * src/include/regex/regex.h
+ */
+
+/*
+ * Add your own defines, if needed, here.
+ */
+#include "mb/pg_wchar.h"
+
+/*
+ * interface types etc.
+ */
+
+/*
+ * regoff_t has to be large enough to hold either off_t or ssize_t,
+ * and must be signed; it's only a guess that long is suitable.
+ */
+typedef long regoff_t;
+
+/*
+ * other interface types
+ */
+
+/* the biggie, a compiled RE (or rather, a front end to same) */
+typedef struct
+{
+ int re_magic; /* magic number */
+ size_t re_nsub; /* number of subexpressions */
+ long re_info; /* information about RE */
+#define REG_UBACKREF 000001
+#define REG_ULOOKAROUND 000002
+#define REG_UBOUNDS 000004
+#define REG_UBRACES 000010
+#define REG_UBSALNUM 000020
+#define REG_UPBOTCH 000040
+#define REG_UBBS 000100
+#define REG_UNONPOSIX 000200
+#define REG_UUNSPEC 000400
+#define REG_UUNPORT 001000
+#define REG_ULOCALE 002000
+#define REG_UEMPTYMATCH 004000
+#define REG_UIMPOSSIBLE 010000
+#define REG_USHORTEST 020000
+ int re_csize; /* sizeof(character) */
+ char *re_endp; /* backward compatibility kludge */
+ Oid re_collation; /* Collation that defines LC_CTYPE behavior */
+ /* the rest is opaque pointers to hidden innards */
+ char *re_guts; /* `char *' is more portable than `void *' */
+ char *re_fns;
+} regex_t;
+
+/* result reporting (may acquire more fields later) */
+typedef struct
+{
+ regoff_t rm_so; /* start of substring */
+ regoff_t rm_eo; /* end of substring */
+} regmatch_t;
+
+/* supplementary control and reporting */
+typedef struct
+{
+ regmatch_t rm_extend; /* see REG_EXPECT */
+} rm_detail_t;
+
+
+
+/*
+ * regex compilation flags
+ */
+#define REG_BASIC 000000 /* BREs (convenience) */
+#define REG_EXTENDED 000001 /* EREs */
+#define REG_ADVF 000002 /* advanced features in EREs */
+#define REG_ADVANCED 000003 /* AREs (which are also EREs) */
+#define REG_QUOTE 000004 /* no special characters, none */
+#define REG_NOSPEC REG_QUOTE /* historical synonym */
+#define REG_ICASE 000010 /* ignore case */
+#define REG_NOSUB 000020 /* don't care about subexpressions */
+#define REG_EXPANDED 000040 /* expanded format, white space & comments */
+#define REG_NLSTOP 000100 /* \n doesn't match . or [^ ] */
+#define REG_NLANCH 000200 /* ^ matches after \n, $ before */
+#define REG_NEWLINE 000300 /* newlines are line terminators */
+#define REG_PEND 000400 /* ugh -- backward-compatibility hack */
+#define REG_EXPECT 001000 /* report details on partial/limited matches */
+#define REG_BOSONLY 002000 /* temporary kludge for BOS-only matches */
+#define REG_DUMP 004000 /* none of your business :-) */
+#define REG_FAKE 010000 /* none of your business :-) */
+#define REG_PROGRESS 020000 /* none of your business :-) */
+
+
+
+/*
+ * regex execution flags
+ */
+#define REG_NOTBOL 0001 /* BOS is not BOL */
+#define REG_NOTEOL 0002 /* EOS is not EOL */
+#define REG_STARTEND 0004 /* backward compatibility kludge */
+#define REG_FTRACE 0010 /* none of your business */
+#define REG_MTRACE 0020 /* none of your business */
+#define REG_SMALL 0040 /* none of your business */
+
+
+/*
+ * error reporting
+ * Be careful if modifying the list of error codes -- the table used by
+ * regerror() is generated automatically from this file!
+ */
+#define REG_OKAY 0 /* no errors detected */
+#define REG_NOMATCH 1 /* failed to match */
+#define REG_BADPAT 2 /* invalid regexp */
+#define REG_ECOLLATE 3 /* invalid collating element */
+#define REG_ECTYPE 4 /* invalid character class */
+#define REG_EESCAPE 5 /* invalid escape \ sequence */
+#define REG_ESUBREG 6 /* invalid backreference number */
+#define REG_EBRACK 7 /* brackets [] not balanced */
+#define REG_EPAREN 8 /* parentheses () not balanced */
+#define REG_EBRACE 9 /* braces {} not balanced */
+#define REG_BADBR 10 /* invalid repetition count(s) */
+#define REG_ERANGE 11 /* invalid character range */
+#define REG_ESPACE 12 /* out of memory */
+#define REG_BADRPT 13 /* quantifier operand invalid */
+#define REG_ASSERT 15 /* "can't happen" -- you found a bug */
+#define REG_INVARG 16 /* invalid argument to regex function */
+#define REG_MIXED 17 /* character widths of regex and string differ */
+#define REG_BADOPT 18 /* invalid embedded option */
+#define REG_ETOOBIG 19 /* regular expression is too complex */
+#define REG_ECOLORS 20 /* too many colors */
+#define REG_CANCEL 21 /* operation cancelled */
+/* two specials for debugging and testing */
+#define REG_ATOI 101 /* convert error-code name to number */
+#define REG_ITOA 102 /* convert error-code number to name */
+/* non-error result codes for pg_regprefix */
+#define REG_PREFIX (-1) /* identified a common prefix */
+#define REG_EXACT (-2) /* identified an exact match */
+
+
+
+/*
+ * the prototypes for exported functions
+ */
+
+/* regcomp.c */
+extern int pg_regcomp(regex_t *, const pg_wchar *, size_t, int, Oid);
+extern int pg_regexec(regex_t *, const pg_wchar *, size_t, size_t, rm_detail_t *, size_t, regmatch_t[], int);
+extern int pg_regprefix(regex_t *, pg_wchar **, size_t *);
+extern void pg_regfree(regex_t *);
+extern size_t pg_regerror(int, const regex_t *, char *, size_t);
+
+/* regexp.c */
+extern regex_t *RE_compile_and_cache(text *text_re, int cflags, Oid collation);
+extern bool RE_compile_and_execute(text *text_re, char *dat, int dat_len,
+ int cflags, Oid collation,
+ int nmatch, regmatch_t *pmatch);
+
+#endif /* _REGEX_H_ */
diff --git a/src/include/regex/regexport.h b/src/include/regex/regexport.h
new file mode 100644
index 0000000..23e599d
--- /dev/null
+++ b/src/include/regex/regexport.h
@@ -0,0 +1,57 @@
+/*-------------------------------------------------------------------------
+ *
+ * regexport.h
+ * Declarations for exporting info about a regex's NFA (nondeterministic
+ * finite automaton)
+ *
+ * The functions declared here provide accessors to extract the NFA state
+ * graph and color character sets of a successfully-compiled regex.
+ *
+ * An NFA contains one or more states, numbered 0..N-1. There is an initial
+ * state, as well as a final state --- reaching the final state denotes
+ * successful matching of an input string. Each state except the final one
+ * has some out-arcs that lead to successor states, each arc being labeled
+ * with a color that represents one or more concrete character codes.
+ * (The colors of a state's out-arcs need not be distinct, since this is an
+ * NFA not a DFA.) There are also "pseudocolors" representing start/end of
+ * line and start/end of string. Colors are numbered 0..C-1, but note that
+ * color 0 is "white" (all unused characters) and can generally be ignored.
+ *
+ * Portions Copyright (c) 2013-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1998, 1999 Henry Spencer
+ *
+ * IDENTIFICATION
+ * src/include/regex/regexport.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _REGEXPORT_H_
+#define _REGEXPORT_H_
+
+#include "regex/regex.h"
+
+/* information about one arc of a regex's NFA */
+typedef struct
+{
+ int co; /* label (character-set color) of arc */
+ int to; /* next state number */
+} regex_arc_t;
+
+
+/* Functions for gathering information about NFA states and arcs */
+extern int pg_reg_getnumstates(const regex_t *regex);
+extern int pg_reg_getinitialstate(const regex_t *regex);
+extern int pg_reg_getfinalstate(const regex_t *regex);
+extern int pg_reg_getnumoutarcs(const regex_t *regex, int st);
+extern void pg_reg_getoutarcs(const regex_t *regex, int st,
+ regex_arc_t *arcs, int arcs_len);
+
+/* Functions for gathering information about colors */
+extern int pg_reg_getnumcolors(const regex_t *regex);
+extern int pg_reg_colorisbegin(const regex_t *regex, int co);
+extern int pg_reg_colorisend(const regex_t *regex, int co);
+extern int pg_reg_getnumcharacters(const regex_t *regex, int co);
+extern void pg_reg_getcharacters(const regex_t *regex, int co,
+ pg_wchar *chars, int chars_len);
+
+#endif /* _REGEXPORT_H_ */
diff --git a/src/include/regex/regguts.h b/src/include/regex/regguts.h
new file mode 100644
index 0000000..5d0e7a9
--- /dev/null
+++ b/src/include/regex/regguts.h
@@ -0,0 +1,482 @@
+/*
+ * Internal interface definitions, etc., for the reg package
+ *
+ * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
+ *
+ * Development of this software was funded, in part, by Cray Research Inc.,
+ * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
+ * Corporation, none of whom are responsible for the results. The author
+ * thanks all of them.
+ *
+ * Redistribution and use in source and binary forms -- with or without
+ * modification -- are permitted for any purpose, provided that
+ * redistributions in source form retain this entire copyright notice and
+ * indicate the origin and nature of any modifications.
+ *
+ * I'd appreciate being given credit for this package in the documentation
+ * of software which uses it, but that is not a requirement.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * src/include/regex/regguts.h
+ */
+
+
+
+/*
+ * Environmental customization. It should not (I hope) be necessary to
+ * alter the file you are now reading -- regcustom.h should handle it all,
+ * given care here and elsewhere.
+ */
+#include "regcustom.h"
+
+
+
+/*
+ * Things that regcustom.h might override.
+ */
+
+/* assertions */
+#ifndef assert
+#ifndef REG_DEBUG
+#define NDEBUG /* no assertions */
+#endif
+#include <assert.h>
+#endif
+
+/* voids */
+#ifndef DISCARD
+#define DISCARD void /* for throwing values away */
+#endif
+#ifndef VS
+#define VS(x) ((void *)(x)) /* cast something to generic ptr */
+#endif
+
+/* function-pointer declarator */
+#ifndef FUNCPTR
+#define FUNCPTR(name, args) (*(name)) args
+#endif
+
+/* memory allocation */
+#ifndef MALLOC
+#define MALLOC(n) malloc(n)
+#endif
+#ifndef REALLOC
+#define REALLOC(p, n) realloc(VS(p), n)
+#endif
+#ifndef FREE
+#define FREE(p) free(VS(p))
+#endif
+
+/* want size of a char in bits, and max value in bounded quantifiers */
+#ifndef _POSIX2_RE_DUP_MAX
+#define _POSIX2_RE_DUP_MAX 255 /* normally from <limits.h> */
+#endif
+
+
+
+/*
+ * misc
+ */
+
+#define NOTREACHED 0
+
+#define DUPMAX _POSIX2_RE_DUP_MAX
+#define DUPINF (DUPMAX+1)
+
+#define REMAGIC 0xfed7 /* magic number for main struct */
+
+/* Type codes for lookaround constraints */
+#define LATYPE_AHEAD_POS 03 /* positive lookahead */
+#define LATYPE_AHEAD_NEG 02 /* negative lookahead */
+#define LATYPE_BEHIND_POS 01 /* positive lookbehind */
+#define LATYPE_BEHIND_NEG 00 /* negative lookbehind */
+#define LATYPE_IS_POS(la) ((la) & 01)
+#define LATYPE_IS_AHEAD(la) ((la) & 02)
+
+
+/*
+ * debugging facilities
+ */
+#ifdef REG_DEBUG
+/* FDEBUG does finite-state tracing */
+#define FDEBUG(arglist) { if (v->eflags&REG_FTRACE) printf arglist; }
+/* MDEBUG does higher-level tracing */
+#define MDEBUG(arglist) { if (v->eflags&REG_MTRACE) printf arglist; }
+#else
+#define FDEBUG(arglist) {}
+#define MDEBUG(arglist) {}
+#endif
+
+
+
+/*
+ * bitmap manipulation
+ */
+#define UBITS (CHAR_BIT * sizeof(unsigned))
+#define BSET(uv, sn) ((uv)[(sn)/UBITS] |= (unsigned)1 << ((sn)%UBITS))
+#define ISBSET(uv, sn) ((uv)[(sn)/UBITS] & ((unsigned)1 << ((sn)%UBITS)))
+
+
+/*
+ * As soon as possible, we map chrs into equivalence classes -- "colors" --
+ * which are of much more manageable number.
+ */
+typedef short color; /* colors of characters */
+
+#define MAX_COLOR 32767 /* max color (must fit in 'color' datatype) */
+#define COLORLESS (-1) /* impossible color */
+#define WHITE 0 /* default color, parent of all others */
+/* Note: various places in the code know that WHITE is zero */
+
+
+/*
+ * Per-color data structure for the compile-time color machinery
+ *
+ * If "sub" is not NOSUB then it is the number of the color's current
+ * subcolor, i.e. we are in process of dividing this color (character
+ * equivalence class) into two colors. See src/backend/regex/README for
+ * discussion of subcolors.
+ *
+ * Currently-unused colors have the FREECOL bit set and are linked into a
+ * freelist using their "sub" fields, but only if their color numbers are
+ * less than colormap.max. Any array entries beyond "max" are just garbage.
+ */
+struct colordesc
+{
+ int nschrs; /* number of simple chars of this color */
+ int nuchrs; /* number of upper map entries of this color */
+ color sub; /* open subcolor, if any; or free-chain ptr */
+#define NOSUB COLORLESS /* value of "sub" when no open subcolor */
+ struct arc *arcs; /* chain of all arcs of this color */
+ chr firstchr; /* simple char first assigned to this color */
+ int flags; /* bit values defined next */
+#define FREECOL 01 /* currently free */
+#define PSEUDO 02 /* pseudocolor, no real chars */
+#define UNUSEDCOLOR(cd) ((cd)->flags & FREECOL)
+};
+
+/*
+ * The color map itself
+ *
+ * This struct holds both data used only at compile time, and the chr to
+ * color mapping information, used at both compile and run time. The latter
+ * is the bulk of the space, so it's not really worth separating out the
+ * compile-only portion.
+ *
+ * Ideally, the mapping data would just be an array of colors indexed by
+ * chr codes; but for large character sets that's impractical. Fortunately,
+ * common characters have smaller codes, so we can use a simple array for chr
+ * codes up to MAX_SIMPLE_CHR, and do something more complex for codes above
+ * that, without much loss of performance. The "something more complex" is a
+ * 2-D array of color entries, where row indexes correspond to individual chrs
+ * or chr ranges that have been mentioned in the regex (with row zero
+ * representing all other chrs), and column indexes correspond to different
+ * sets of locale-dependent character classes such as "isalpha". The
+ * classbits[k] entry is zero if we do not care about the k'th character class
+ * in this regex, and otherwise it is the bit to be OR'd into the column index
+ * if the character in question is a member of that class. We find the color
+ * of a high-valued chr by identifying which colormaprange it is in to get
+ * the row index (use row zero if it's in none of them), identifying which of
+ * the interesting cclasses it's in to get the column index, and then indexing
+ * into the 2-D hicolormap array.
+ *
+ * The colormapranges are required to be nonempty, nonoverlapping, and to
+ * appear in increasing chr-value order.
+ */
+
+#define NUM_CCLASSES 13 /* must match data in regc_locale.c */
+
+typedef struct colormaprange
+{
+ chr cmin; /* range represents cmin..cmax inclusive */
+ chr cmax;
+ int rownum; /* row index in hicolormap array (>= 1) */
+} colormaprange;
+
+struct colormap
+{
+ int magic;
+#define CMMAGIC 0x876
+ struct vars *v; /* for compile error reporting */
+ size_t ncds; /* allocated length of colordescs array */
+ size_t max; /* highest color number currently in use */
+ color free; /* beginning of free chain (if non-0) */
+ struct colordesc *cd; /* pointer to array of colordescs */
+#define CDEND(cm) (&(cm)->cd[(cm)->max + 1])
+
+ /* mapping data for chrs <= MAX_SIMPLE_CHR: */
+ color *locolormap; /* simple array indexed by chr code */
+
+ /* mapping data for chrs > MAX_SIMPLE_CHR: */
+ int classbits[NUM_CCLASSES]; /* see comment above */
+ int numcmranges; /* number of colormapranges */
+ colormaprange *cmranges; /* ranges of high chrs */
+ color *hicolormap; /* 2-D array of color entries */
+ int maxarrayrows; /* number of array rows allocated */
+ int hiarrayrows; /* number of array rows in use */
+ int hiarraycols; /* number of array columns (2^N) */
+
+ /* If we need up to NINLINECDS, we store them here to save a malloc */
+#define NINLINECDS ((size_t) 10)
+ struct colordesc cdspace[NINLINECDS];
+};
+
+/* fetch color for chr; beware of multiple evaluation of c argument */
+#define GETCOLOR(cm, c) \
+ ((c) <= MAX_SIMPLE_CHR ? (cm)->locolormap[(c) - CHR_MIN] : pg_reg_getcolor(cm, c))
+
+
+/*
+ * Interface definitions for locale-interface functions in regc_locale.c.
+ */
+
+/*
+ * Representation of a set of characters. chrs[] represents individual
+ * code points, ranges[] represents ranges in the form min..max inclusive.
+ *
+ * If the cvec represents a locale-specific character class, eg [[:alpha:]],
+ * then the chrs[] and ranges[] arrays contain only members of that class
+ * up to MAX_SIMPLE_CHR (inclusive). cclasscode is set to regc_locale.c's
+ * code for the class, rather than being -1 as it is in an ordinary cvec.
+ *
+ * Note that in cvecs gotten from newcvec() and intended to be freed by
+ * freecvec(), both arrays of chrs are after the end of the struct, not
+ * separately malloc'd; so chrspace and rangespace are effectively immutable.
+ */
+struct cvec
+{
+ int nchrs; /* number of chrs */
+ int chrspace; /* number of chrs allocated in chrs[] */
+ chr *chrs; /* pointer to vector of chrs */
+ int nranges; /* number of ranges (chr pairs) */
+ int rangespace; /* number of ranges allocated in ranges[] */
+ chr *ranges; /* pointer to vector of chr pairs */
+ int cclasscode; /* value of "enum classes", or -1 */
+};
+
+
+/*
+ * definitions for NFA internal representation
+ *
+ * Having a "from" pointer within each arc may seem redundant, but it
+ * saves a lot of hassle.
+ */
+struct state;
+
+struct arc
+{
+ int type; /* 0 if free, else an NFA arc type code */
+ color co;
+ struct state *from; /* where it's from (and contained within) */
+ struct state *to; /* where it's to */
+ struct arc *outchain; /* link in *from's outs chain or free chain */
+ struct arc *outchainRev; /* back-link in *from's outs chain */
+#define freechain outchain /* we do not maintain "freechainRev" */
+ struct arc *inchain; /* link in *to's ins chain */
+ struct arc *inchainRev; /* back-link in *to's ins chain */
+ struct arc *colorchain; /* link in color's arc chain */
+ struct arc *colorchainRev; /* back-link in color's arc chain */
+};
+
+struct arcbatch
+{ /* for bulk allocation of arcs */
+ struct arcbatch *next;
+#define ABSIZE 10
+ struct arc a[ABSIZE];
+};
+
+struct state
+{
+ int no;
+#define FREESTATE (-1)
+ char flag; /* marks special states */
+ int nins; /* number of inarcs */
+ struct arc *ins; /* chain of inarcs */
+ int nouts; /* number of outarcs */
+ struct arc *outs; /* chain of outarcs */
+ struct arc *free; /* chain of free arcs */
+ struct state *tmp; /* temporary for traversal algorithms */
+ struct state *next; /* chain for traversing all */
+ struct state *prev; /* back chain */
+ struct arcbatch oas; /* first arcbatch, avoid malloc in easy case */
+ int noas; /* number of arcs used in first arcbatch */
+};
+
+struct nfa
+{
+ struct state *pre; /* pre-initial state */
+ struct state *init; /* initial state */
+ struct state *final; /* final state */
+ struct state *post; /* post-final state */
+ int nstates; /* for numbering states */
+ struct state *states; /* state-chain header */
+ struct state *slast; /* tail of the chain */
+ struct state *free; /* free list */
+ struct colormap *cm; /* the color map */
+ color bos[2]; /* colors, if any, assigned to BOS and BOL */
+ color eos[2]; /* colors, if any, assigned to EOS and EOL */
+ struct vars *v; /* simplifies compile error reporting */
+ struct nfa *parent; /* parent NFA, if any */
+};
+
+
+
+/*
+ * definitions for compacted NFA
+ *
+ * The main space savings in a compacted NFA is from making the arcs as small
+ * as possible. We store only the transition color and next-state number for
+ * each arc. The list of out arcs for each state is an array beginning at
+ * cnfa.states[statenumber], and terminated by a dummy carc struct with
+ * co == COLORLESS.
+ *
+ * The non-dummy carc structs are of two types: plain arcs and LACON arcs.
+ * Plain arcs just store the transition color number as "co". LACON arcs
+ * store the lookaround constraint number plus cnfa.ncolors as "co". LACON
+ * arcs can be distinguished from plain by testing for co >= cnfa.ncolors.
+ */
+struct carc
+{
+ color co; /* COLORLESS is list terminator */
+ int to; /* next-state number */
+};
+
+struct cnfa
+{
+ int nstates; /* number of states */
+ int ncolors; /* number of colors (max color in use + 1) */
+ int flags;
+#define HASLACONS 01 /* uses lookaround constraints */
+ int pre; /* setup state number */
+ int post; /* teardown state number */
+ color bos[2]; /* colors, if any, assigned to BOS and BOL */
+ color eos[2]; /* colors, if any, assigned to EOS and EOL */
+ char *stflags; /* vector of per-state flags bytes */
+#define CNFA_NOPROGRESS 01 /* flag bit for a no-progress state */
+ struct carc **states; /* vector of pointers to outarc lists */
+ /* states[n] are pointers into a single malloc'd array of arcs */
+ struct carc *arcs; /* the area for the lists */
+};
+
+#define ZAPCNFA(cnfa) ((cnfa).nstates = 0)
+#define NULLCNFA(cnfa) ((cnfa).nstates == 0)
+
+/*
+ * This symbol limits the transient heap space used by the regex compiler,
+ * and thereby also the maximum complexity of NFAs that we'll deal with.
+ * Currently we only count NFA states and arcs against this; the other
+ * transient data is generally not large enough to notice compared to those.
+ * Note that we do not charge anything for the final output data structures
+ * (the compacted NFA and the colormap).
+ */
+#ifndef REG_MAX_COMPILE_SPACE
+#define REG_MAX_COMPILE_SPACE \
+ (100000 * sizeof(struct state) + 100000 * sizeof(struct arcbatch))
+#endif
+
+/*
+ * subexpression tree
+ *
+ * "op" is one of:
+ * '=' plain regex without interesting substructure (implemented as DFA)
+ * 'b' back-reference (has no substructure either)
+ * '(' capture node: captures the match of its single child
+ * '.' concatenation: matches a match for left, then a match for right
+ * '|' alternation: matches a match for left or a match for right
+ * '*' iteration: matches some number of matches of its single child
+ *
+ * Note: the right child of an alternation must be another alternation or
+ * NULL; hence, an N-way branch requires N alternation nodes, not N-1 as you
+ * might expect. This could stand to be changed. Actually I'd rather see
+ * a single alternation node with N children, but that will take revising
+ * the representation of struct subre.
+ *
+ * Note: when a backref is directly quantified, we stick the min/max counts
+ * into the backref rather than plastering an iteration node on top. This is
+ * for efficiency: there is no need to search for possible division points.
+ */
+struct subre
+{
+ char op; /* see type codes above */
+ char flags;
+#define LONGER 01 /* prefers longer match */
+#define SHORTER 02 /* prefers shorter match */
+#define MIXED 04 /* mixed preference below */
+#define CAP 010 /* capturing parens below */
+#define BACKR 020 /* back reference below */
+#define INUSE 0100 /* in use in final tree */
+#define NOPROP 03 /* bits which may not propagate up */
+#define LMIX(f) ((f)<<2) /* LONGER -> MIXED */
+#define SMIX(f) ((f)<<1) /* SHORTER -> MIXED */
+#define UP(f) (((f)&~NOPROP) | (LMIX(f) & SMIX(f) & MIXED))
+#define MESSY(f) ((f)&(MIXED|CAP|BACKR))
+#define PREF(f) ((f)&NOPROP)
+#define PREF2(f1, f2) ((PREF(f1) != 0) ? PREF(f1) : PREF(f2))
+#define COMBINE(f1, f2) (UP((f1)|(f2)) | PREF2(f1, f2))
+ short id; /* ID of subre (1..ntree-1) */
+ int subno; /* subexpression number for 'b' and '(', or
+ * LATYPE code for lookaround constraint */
+ short min; /* min repetitions for iteration or backref */
+ short max; /* max repetitions for iteration or backref */
+ struct subre *left; /* left child, if any (also freelist chain) */
+ struct subre *right; /* right child, if any */
+ struct state *begin; /* outarcs from here... */
+ struct state *end; /* ...ending in inarcs here */
+ struct cnfa cnfa; /* compacted NFA, if any */
+ struct subre *chain; /* for bookkeeping and error cleanup */
+};
+
+
+
+/*
+ * table of function pointers for generic manipulation functions
+ * A regex_t's re_fns points to one of these.
+ */
+struct fns
+{
+ void FUNCPTR(free, (regex_t *));
+ int FUNCPTR(cancel_requested, (void));
+ int FUNCPTR(stack_too_deep, (void));
+};
+
+#define CANCEL_REQUESTED(re) \
+ ((*((struct fns *) (re)->re_fns)->cancel_requested) ())
+
+#define STACK_TOO_DEEP(re) \
+ ((*((struct fns *) (re)->re_fns)->stack_too_deep) ())
+
+
+/*
+ * the insides of a regex_t, hidden behind a void *
+ */
+struct guts
+{
+ int magic;
+#define GUTSMAGIC 0xfed9
+ int cflags; /* copy of compile flags */
+ long info; /* copy of re_info */
+ size_t nsub; /* copy of re_nsub */
+ struct subre *tree;
+ struct cnfa search; /* for fast preliminary search */
+ int ntree; /* number of subre's, plus one */
+ struct colormap cmap;
+ int FUNCPTR(compare, (const chr *, const chr *, size_t));
+ struct subre *lacons; /* lookaround-constraint vector */
+ int nlacons; /* size of lacons[]; note that only slots
+ * numbered 1 .. nlacons-1 are used */
+};
+
+
+/* prototypes for functions that are exported from regcomp.c to regexec.c */
+extern void pg_set_regex_collation(Oid collation);
+extern color pg_reg_getcolor(struct colormap *cm, chr c);
diff --git a/src/include/replication/backup_manifest.h b/src/include/replication/backup_manifest.h
new file mode 100644
index 0000000..fb1291c
--- /dev/null
+++ b/src/include/replication/backup_manifest.h
@@ -0,0 +1,52 @@
+/*-------------------------------------------------------------------------
+ *
+ * backup_manifest.h
+ * Routines for generating a backup manifest.
+ *
+ * Portions Copyright (c) 2010-2020, PostgreSQL Global Development Group
+ *
+ * src/include/replication/backup_manifest.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BACKUP_MANIFEST_H
+#define BACKUP_MANIFEST_H
+
+#include "access/xlogdefs.h"
+#include "common/checksum_helper.h"
+#include "pgtime.h"
+#include "storage/buffile.h"
+
+typedef enum manifest_option
+{
+ MANIFEST_OPTION_YES,
+ MANIFEST_OPTION_NO,
+ MANIFEST_OPTION_FORCE_ENCODE
+} backup_manifest_option;
+
+typedef struct backup_manifest_info
+{
+ BufFile *buffile;
+ pg_checksum_type checksum_type;
+ pg_sha256_ctx manifest_ctx;
+ uint64 manifest_size;
+ bool force_encode;
+ bool first_file;
+ bool still_checksumming;
+} backup_manifest_info;
+
+extern void InitializeBackupManifest(backup_manifest_info *manifest,
+ backup_manifest_option want_manifest,
+ pg_checksum_type manifest_checksum_type);
+extern void AddFileToBackupManifest(backup_manifest_info *manifest,
+ const char *spcoid,
+ const char *pathname, size_t size,
+ pg_time_t mtime,
+ pg_checksum_context *checksum_ctx);
+extern void AddWALInfoToBackupManifest(backup_manifest_info *manifest,
+ XLogRecPtr startptr,
+ TimeLineID starttli, XLogRecPtr endptr,
+ TimeLineID endtli);
+extern void SendBackupManifest(backup_manifest_info *manifest);
+
+#endif
diff --git a/src/include/replication/basebackup.h b/src/include/replication/basebackup.h
new file mode 100644
index 0000000..923a651
--- /dev/null
+++ b/src/include/replication/basebackup.h
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * basebackup.h
+ * Exports from replication/basebackup.c.
+ *
+ * Portions Copyright (c) 2010-2020, PostgreSQL Global Development Group
+ *
+ * src/include/replication/basebackup.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _BASEBACKUP_H
+#define _BASEBACKUP_H
+
+#include "nodes/replnodes.h"
+
+struct backup_manifest_info; /* avoid including backup_manifest.h */
+
+
+/*
+ * Minimum and maximum values of MAX_RATE option in BASE_BACKUP command.
+ */
+#define MAX_RATE_LOWER 32
+#define MAX_RATE_UPPER 1048576
+
+typedef struct
+{
+ char *oid;
+ char *path;
+ char *rpath; /* relative path within PGDATA, or NULL */
+ int64 size;
+} tablespaceinfo;
+
+extern void SendBaseBackup(BaseBackupCmd *cmd);
+
+extern int64 sendTablespace(char *path, char *oid, bool sizeonly,
+ struct backup_manifest_info *manifest);
+
+#endif /* _BASEBACKUP_H */
diff --git a/src/include/replication/decode.h b/src/include/replication/decode.h
new file mode 100644
index 0000000..8479e16
--- /dev/null
+++ b/src/include/replication/decode.h
@@ -0,0 +1,20 @@
+/*-------------------------------------------------------------------------
+ * decode.h
+ * PostgreSQL WAL to logical transformation
+ *
+ * Portions Copyright (c) 2012-2020, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DECODE_H
+#define DECODE_H
+
+#include "access/xlogreader.h"
+#include "access/xlogrecord.h"
+#include "replication/logical.h"
+#include "replication/reorderbuffer.h"
+
+void LogicalDecodingProcessRecord(LogicalDecodingContext *ctx,
+ XLogReaderState *record);
+
+#endif
diff --git a/src/include/replication/logical.h b/src/include/replication/logical.h
new file mode 100644
index 0000000..c2f2475
--- /dev/null
+++ b/src/include/replication/logical.h
@@ -0,0 +1,120 @@
+/*-------------------------------------------------------------------------
+ * logical.h
+ * PostgreSQL logical decoding coordination
+ *
+ * Copyright (c) 2012-2020, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LOGICAL_H
+#define LOGICAL_H
+
+#include "access/xlog.h"
+#include "access/xlogreader.h"
+#include "replication/output_plugin.h"
+#include "replication/slot.h"
+
+struct LogicalDecodingContext;
+
+typedef void (*LogicalOutputPluginWriterWrite) (struct LogicalDecodingContext *lr,
+ XLogRecPtr Ptr,
+ TransactionId xid,
+ bool last_write
+);
+
+typedef LogicalOutputPluginWriterWrite LogicalOutputPluginWriterPrepareWrite;
+
+typedef void (*LogicalOutputPluginWriterUpdateProgress) (struct LogicalDecodingContext *lr,
+ XLogRecPtr Ptr,
+ TransactionId xid
+);
+
+typedef struct LogicalDecodingContext
+{
+ /* memory context this is all allocated in */
+ MemoryContext context;
+
+ /* The associated replication slot */
+ ReplicationSlot *slot;
+
+ /* infrastructure pieces for decoding */
+ XLogReaderState *reader;
+ struct ReorderBuffer *reorder;
+ struct SnapBuild *snapshot_builder;
+
+ /*
+ * Marks the logical decoding context as fast forward decoding one. Such a
+ * context does not have plugin loaded so most of the following properties
+ * are unused.
+ */
+ bool fast_forward;
+
+ OutputPluginCallbacks callbacks;
+ OutputPluginOptions options;
+
+ /*
+ * User specified options
+ */
+ List *output_plugin_options;
+
+ /*
+ * User-Provided callback for writing/streaming out data.
+ */
+ LogicalOutputPluginWriterPrepareWrite prepare_write;
+ LogicalOutputPluginWriterWrite write;
+ LogicalOutputPluginWriterUpdateProgress update_progress;
+
+ /*
+ * Output buffer.
+ */
+ StringInfo out;
+
+ /*
+ * Private data pointer of the output plugin.
+ */
+ void *output_plugin_private;
+
+ /*
+ * Private data pointer for the data writer.
+ */
+ void *output_writer_private;
+
+ /*
+ * State for writing output.
+ */
+ bool accept_writes;
+ bool prepared_write;
+ XLogRecPtr write_location;
+ TransactionId write_xid;
+} LogicalDecodingContext;
+
+
+extern void CheckLogicalDecodingRequirements(void);
+
+extern LogicalDecodingContext *CreateInitDecodingContext(char *plugin,
+ List *output_plugin_options,
+ bool need_full_snapshot,
+ XLogRecPtr restart_lsn,
+ XLogReaderRoutine *xl_routine,
+ LogicalOutputPluginWriterPrepareWrite prepare_write,
+ LogicalOutputPluginWriterWrite do_write,
+ LogicalOutputPluginWriterUpdateProgress update_progress);
+extern LogicalDecodingContext *CreateDecodingContext(XLogRecPtr start_lsn,
+ List *output_plugin_options,
+ bool fast_forward,
+ XLogReaderRoutine *xl_routine,
+ LogicalOutputPluginWriterPrepareWrite prepare_write,
+ LogicalOutputPluginWriterWrite do_write,
+ LogicalOutputPluginWriterUpdateProgress update_progress);
+extern void DecodingContextFindStartpoint(LogicalDecodingContext *ctx);
+extern bool DecodingContextReady(LogicalDecodingContext *ctx);
+extern void FreeDecodingContext(LogicalDecodingContext *ctx);
+
+extern void LogicalIncreaseXminForSlot(XLogRecPtr lsn, TransactionId xmin);
+extern void LogicalIncreaseRestartDecodingForSlot(XLogRecPtr current_lsn,
+ XLogRecPtr restart_lsn);
+extern void LogicalConfirmReceivedLocation(XLogRecPtr lsn);
+
+extern bool filter_by_origin_cb_wrapper(LogicalDecodingContext *ctx, RepOriginId origin_id);
+
+#endif
diff --git a/src/include/replication/logicallauncher.h b/src/include/replication/logicallauncher.h
new file mode 100644
index 0000000..b22e591
--- /dev/null
+++ b/src/include/replication/logicallauncher.h
@@ -0,0 +1,31 @@
+/*-------------------------------------------------------------------------
+ *
+ * logicallauncher.h
+ * Exports for logical replication launcher.
+ *
+ * Portions Copyright (c) 2016-2020, PostgreSQL Global Development Group
+ *
+ * src/include/replication/logicallauncher.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LOGICALLAUNCHER_H
+#define LOGICALLAUNCHER_H
+
+extern int max_logical_replication_workers;
+extern int max_sync_workers_per_subscription;
+
+extern void ApplyLauncherRegister(void);
+extern void ApplyLauncherMain(Datum main_arg);
+
+extern Size ApplyLauncherShmemSize(void);
+extern void ApplyLauncherShmemInit(void);
+
+extern void ApplyLauncherWakeupAtCommit(void);
+extern bool XactManipulatesLogicalReplicationWorkers(void);
+extern void AtEOXact_ApplyLauncher(bool isCommit);
+extern void AtEOSubXact_ApplyLauncher(bool isCommit, int nestDepth);
+
+extern bool IsLogicalLauncher(void);
+
+#endif /* LOGICALLAUNCHER_H */
diff --git a/src/include/replication/logicalproto.h b/src/include/replication/logicalproto.h
new file mode 100644
index 0000000..4860561
--- /dev/null
+++ b/src/include/replication/logicalproto.h
@@ -0,0 +1,110 @@
+/*-------------------------------------------------------------------------
+ *
+ * logicalproto.h
+ * logical replication protocol
+ *
+ * Copyright (c) 2015-2020, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/replication/logicalproto.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LOGICAL_PROTO_H
+#define LOGICAL_PROTO_H
+
+#include "replication/reorderbuffer.h"
+#include "utils/rel.h"
+
+/*
+ * Protocol capabilities
+ *
+ * LOGICALREP_PROTO_VERSION_NUM is our native protocol and the greatest version
+ * we can support. LOGICALREP_PROTO_MIN_VERSION_NUM is the oldest version we
+ * have backwards compatibility for. The client requests protocol version at
+ * connect time.
+ */
+#define LOGICALREP_PROTO_MIN_VERSION_NUM 1
+#define LOGICALREP_PROTO_VERSION_NUM 1
+
+/* Tuple coming via logical replication. */
+typedef struct LogicalRepTupleData
+{
+ /* column values in text format, or NULL for a null value: */
+ char *values[MaxTupleAttributeNumber];
+ /* markers for changed/unchanged column values: */
+ bool changed[MaxTupleAttributeNumber];
+} LogicalRepTupleData;
+
+typedef uint32 LogicalRepRelId;
+
+/* Relation information */
+typedef struct LogicalRepRelation
+{
+ /* Info coming from the remote side. */
+ LogicalRepRelId remoteid; /* unique id of the relation */
+ char *nspname; /* schema name */
+ char *relname; /* relation name */
+ int natts; /* number of columns */
+ char **attnames; /* column names */
+ Oid *atttyps; /* column types */
+ char replident; /* replica identity */
+ char relkind; /* remote relation kind */
+ Bitmapset *attkeys; /* Bitmap of key columns */
+} LogicalRepRelation;
+
+/* Type mapping info */
+typedef struct LogicalRepTyp
+{
+ Oid remoteid; /* unique id of the remote type */
+ char *nspname; /* schema name of remote type */
+ char *typname; /* name of the remote type */
+} LogicalRepTyp;
+
+/* Transaction info */
+typedef struct LogicalRepBeginData
+{
+ XLogRecPtr final_lsn;
+ TimestampTz committime;
+ TransactionId xid;
+} LogicalRepBeginData;
+
+typedef struct LogicalRepCommitData
+{
+ XLogRecPtr commit_lsn;
+ XLogRecPtr end_lsn;
+ TimestampTz committime;
+} LogicalRepCommitData;
+
+extern void logicalrep_write_begin(StringInfo out, ReorderBufferTXN *txn);
+extern void logicalrep_read_begin(StringInfo in,
+ LogicalRepBeginData *begin_data);
+extern void logicalrep_write_commit(StringInfo out, ReorderBufferTXN *txn,
+ XLogRecPtr commit_lsn);
+extern void logicalrep_read_commit(StringInfo in,
+ LogicalRepCommitData *commit_data);
+extern void logicalrep_write_origin(StringInfo out, const char *origin,
+ XLogRecPtr origin_lsn);
+extern char *logicalrep_read_origin(StringInfo in, XLogRecPtr *origin_lsn);
+extern void logicalrep_write_insert(StringInfo out, Relation rel,
+ HeapTuple newtuple);
+extern LogicalRepRelId logicalrep_read_insert(StringInfo in, LogicalRepTupleData *newtup);
+extern void logicalrep_write_update(StringInfo out, Relation rel, HeapTuple oldtuple,
+ HeapTuple newtuple);
+extern LogicalRepRelId logicalrep_read_update(StringInfo in,
+ bool *has_oldtuple, LogicalRepTupleData *oldtup,
+ LogicalRepTupleData *newtup);
+extern void logicalrep_write_delete(StringInfo out, Relation rel,
+ HeapTuple oldtuple);
+extern LogicalRepRelId logicalrep_read_delete(StringInfo in,
+ LogicalRepTupleData *oldtup);
+extern void logicalrep_write_truncate(StringInfo out, int nrelids, Oid relids[],
+ bool cascade, bool restart_seqs);
+extern List *logicalrep_read_truncate(StringInfo in,
+ bool *cascade, bool *restart_seqs);
+extern void logicalrep_write_rel(StringInfo out, Relation rel);
+extern LogicalRepRelation *logicalrep_read_rel(StringInfo in);
+extern void logicalrep_write_typ(StringInfo out, Oid typoid);
+extern void logicalrep_read_typ(StringInfo out, LogicalRepTyp *ltyp);
+
+#endif /* LOGICAL_PROTO_H */
diff --git a/src/include/replication/logicalrelation.h b/src/include/replication/logicalrelation.h
new file mode 100644
index 0000000..e369b27
--- /dev/null
+++ b/src/include/replication/logicalrelation.h
@@ -0,0 +1,44 @@
+/*-------------------------------------------------------------------------
+ *
+ * logicalrelation.h
+ * Relation definitions for logical replication relation mapping.
+ *
+ * Portions Copyright (c) 2016-2020, PostgreSQL Global Development Group
+ *
+ * src/include/replication/logicalrelation.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LOGICALRELATION_H
+#define LOGICALRELATION_H
+
+#include "access/attmap.h"
+#include "replication/logicalproto.h"
+
+typedef struct LogicalRepRelMapEntry
+{
+ LogicalRepRelation remoterel; /* key is remoterel.remoteid */
+
+ /* Mapping to local relation. */
+ Oid localreloid; /* local relation id */
+ Relation localrel; /* relcache entry (NULL when closed) */
+ AttrMap *attrmap; /* map of local attributes to remote ones */
+ bool updatable; /* Can apply updates/deletes? */
+
+ /* Sync state. */
+ char state;
+ /* Validity flag ... inserted here to avoid ABI break in back branches. */
+ bool localrelvalid;
+ XLogRecPtr statelsn;
+} LogicalRepRelMapEntry;
+
+extern void logicalrep_relmap_update(LogicalRepRelation *remoterel);
+
+extern LogicalRepRelMapEntry *logicalrep_rel_open(LogicalRepRelId remoteid,
+ LOCKMODE lockmode);
+extern LogicalRepRelMapEntry *logicalrep_partition_open(LogicalRepRelMapEntry *root,
+ Relation partrel, AttrMap *map);
+extern void logicalrep_rel_close(LogicalRepRelMapEntry *rel,
+ LOCKMODE lockmode);
+
+#endif /* LOGICALRELATION_H */
diff --git a/src/include/replication/logicalworker.h b/src/include/replication/logicalworker.h
new file mode 100644
index 0000000..7ea1436
--- /dev/null
+++ b/src/include/replication/logicalworker.h
@@ -0,0 +1,19 @@
+/*-------------------------------------------------------------------------
+ *
+ * logicalworker.h
+ * Exports for logical replication workers.
+ *
+ * Portions Copyright (c) 2016-2020, PostgreSQL Global Development Group
+ *
+ * src/include/replication/logicalworker.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LOGICALWORKER_H
+#define LOGICALWORKER_H
+
+extern void ApplyWorkerMain(Datum main_arg);
+
+extern bool IsLogicalWorker(void);
+
+#endif /* LOGICALWORKER_H */
diff --git a/src/include/replication/message.h b/src/include/replication/message.h
new file mode 100644
index 0000000..937addd
--- /dev/null
+++ b/src/include/replication/message.h
@@ -0,0 +1,42 @@
+/*-------------------------------------------------------------------------
+ * message.h
+ * Exports from replication/logical/message.c
+ *
+ * Copyright (c) 2013-2020, PostgreSQL Global Development Group
+ *
+ * src/include/replication/message.h
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_LOGICAL_MESSAGE_H
+#define PG_LOGICAL_MESSAGE_H
+
+#include "access/xlog.h"
+#include "access/xlogdefs.h"
+#include "access/xlogreader.h"
+
+/*
+ * Generic logical decoding message wal record.
+ */
+typedef struct xl_logical_message
+{
+ Oid dbId; /* database Oid emitted from */
+ bool transactional; /* is message transactional? */
+ Size prefix_size; /* length of prefix */
+ Size message_size; /* size of the message */
+ char message[FLEXIBLE_ARRAY_MEMBER]; /* message including the null
+ * terminated prefix of length
+ * prefix_size */
+} xl_logical_message;
+
+#define SizeOfLogicalMessage (offsetof(xl_logical_message, message))
+
+extern XLogRecPtr LogLogicalMessage(const char *prefix, const char *message,
+ size_t size, bool transactional);
+
+/* RMGR API*/
+#define XLOG_LOGICAL_MESSAGE 0x00
+void logicalmsg_redo(XLogReaderState *record);
+void logicalmsg_desc(StringInfo buf, XLogReaderState *record);
+const char *logicalmsg_identify(uint8 info);
+
+#endif /* PG_LOGICAL_MESSAGE_H */
diff --git a/src/include/replication/origin.h b/src/include/replication/origin.h
new file mode 100644
index 0000000..7e06375
--- /dev/null
+++ b/src/include/replication/origin.h
@@ -0,0 +1,73 @@
+/*-------------------------------------------------------------------------
+ * origin.h
+ * Exports from replication/logical/origin.c
+ *
+ * Copyright (c) 2013-2020, PostgreSQL Global Development Group
+ *
+ * src/include/replication/origin.h
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_ORIGIN_H
+#define PG_ORIGIN_H
+
+#include "access/xlog.h"
+#include "access/xlogdefs.h"
+#include "access/xlogreader.h"
+#include "catalog/pg_replication_origin.h"
+
+typedef struct xl_replorigin_set
+{
+ XLogRecPtr remote_lsn;
+ RepOriginId node_id;
+ bool force;
+} xl_replorigin_set;
+
+typedef struct xl_replorigin_drop
+{
+ RepOriginId node_id;
+} xl_replorigin_drop;
+
+#define XLOG_REPLORIGIN_SET 0x00
+#define XLOG_REPLORIGIN_DROP 0x10
+
+#define InvalidRepOriginId 0
+#define DoNotReplicateId PG_UINT16_MAX
+
+extern PGDLLIMPORT RepOriginId replorigin_session_origin;
+extern PGDLLIMPORT XLogRecPtr replorigin_session_origin_lsn;
+extern PGDLLIMPORT TimestampTz replorigin_session_origin_timestamp;
+
+/* API for querying & manipulating replication origins */
+extern RepOriginId replorigin_by_name(char *name, bool missing_ok);
+extern RepOriginId replorigin_create(char *name);
+extern void replorigin_drop(RepOriginId roident, bool nowait);
+extern bool replorigin_by_oid(RepOriginId roident, bool missing_ok,
+ char **roname);
+
+/* API for querying & manipulating replication progress tracking */
+extern void replorigin_advance(RepOriginId node,
+ XLogRecPtr remote_commit,
+ XLogRecPtr local_commit,
+ bool go_backward, bool wal_log);
+extern XLogRecPtr replorigin_get_progress(RepOriginId node, bool flush);
+
+extern void replorigin_session_advance(XLogRecPtr remote_commit,
+ XLogRecPtr local_commit);
+extern void replorigin_session_setup(RepOriginId node);
+extern void replorigin_session_reset(void);
+extern XLogRecPtr replorigin_session_get_progress(bool flush);
+
+/* Checkpoint/Startup integration */
+extern void CheckPointReplicationOrigin(void);
+extern void StartupReplicationOrigin(void);
+
+/* WAL logging */
+void replorigin_redo(XLogReaderState *record);
+void replorigin_desc(StringInfo buf, XLogReaderState *record);
+const char *replorigin_identify(uint8 info);
+
+/* shared memory allocation */
+extern Size ReplicationOriginShmemSize(void);
+extern void ReplicationOriginShmemInit(void);
+
+#endif /* PG_ORIGIN_H */
diff --git a/src/include/replication/output_plugin.h b/src/include/replication/output_plugin.h
new file mode 100644
index 0000000..3dd9236
--- /dev/null
+++ b/src/include/replication/output_plugin.h
@@ -0,0 +1,122 @@
+/*-------------------------------------------------------------------------
+ * output_plugin.h
+ * PostgreSQL Logical Decode Plugin Interface
+ *
+ * Copyright (c) 2012-2020, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef OUTPUT_PLUGIN_H
+#define OUTPUT_PLUGIN_H
+
+#include "replication/reorderbuffer.h"
+
+struct LogicalDecodingContext;
+struct OutputPluginCallbacks;
+
+typedef enum OutputPluginOutputType
+{
+ OUTPUT_PLUGIN_BINARY_OUTPUT,
+ OUTPUT_PLUGIN_TEXTUAL_OUTPUT
+} OutputPluginOutputType;
+
+/*
+ * Options set by the output plugin, in the startup callback.
+ */
+typedef struct OutputPluginOptions
+{
+ OutputPluginOutputType output_type;
+ bool receive_rewrites;
+} OutputPluginOptions;
+
+/*
+ * Type of the shared library symbol _PG_output_plugin_init that is looked up
+ * when loading an output plugin shared library.
+ */
+typedef void (*LogicalOutputPluginInit) (struct OutputPluginCallbacks *cb);
+
+/*
+ * Callback that gets called in a user-defined plugin. ctx->private_data can
+ * be set to some private data.
+ *
+ * "is_init" will be set to "true" if the decoding slot just got defined. When
+ * the same slot is used from there one, it will be "false".
+ */
+typedef void (*LogicalDecodeStartupCB) (struct LogicalDecodingContext *ctx,
+ OutputPluginOptions *options,
+ bool is_init);
+
+/*
+ * Callback called for every (explicit or implicit) BEGIN of a successful
+ * transaction.
+ */
+typedef void (*LogicalDecodeBeginCB) (struct LogicalDecodingContext *ctx,
+ ReorderBufferTXN *txn);
+
+/*
+ * Callback for every individual change in a successful transaction.
+ */
+typedef void (*LogicalDecodeChangeCB) (struct LogicalDecodingContext *ctx,
+ ReorderBufferTXN *txn,
+ Relation relation,
+ ReorderBufferChange *change);
+
+/*
+ * Callback for every TRUNCATE in a successful transaction.
+ */
+typedef void (*LogicalDecodeTruncateCB) (struct LogicalDecodingContext *ctx,
+ ReorderBufferTXN *txn,
+ int nrelations,
+ Relation relations[],
+ ReorderBufferChange *change);
+
+/*
+ * Called for every (explicit or implicit) COMMIT of a successful transaction.
+ */
+typedef void (*LogicalDecodeCommitCB) (struct LogicalDecodingContext *ctx,
+ ReorderBufferTXN *txn,
+ XLogRecPtr commit_lsn);
+
+/*
+ * Called for the generic logical decoding messages.
+ */
+typedef void (*LogicalDecodeMessageCB) (struct LogicalDecodingContext *ctx,
+ ReorderBufferTXN *txn,
+ XLogRecPtr message_lsn,
+ bool transactional,
+ const char *prefix,
+ Size message_size,
+ const char *message);
+
+/*
+ * Filter changes by origin.
+ */
+typedef bool (*LogicalDecodeFilterByOriginCB) (struct LogicalDecodingContext *ctx,
+ RepOriginId origin_id);
+
+/*
+ * Called to shutdown an output plugin.
+ */
+typedef void (*LogicalDecodeShutdownCB) (struct LogicalDecodingContext *ctx);
+
+/*
+ * Output plugin callbacks
+ */
+typedef struct OutputPluginCallbacks
+{
+ LogicalDecodeStartupCB startup_cb;
+ LogicalDecodeBeginCB begin_cb;
+ LogicalDecodeChangeCB change_cb;
+ LogicalDecodeTruncateCB truncate_cb;
+ LogicalDecodeCommitCB commit_cb;
+ LogicalDecodeMessageCB message_cb;
+ LogicalDecodeFilterByOriginCB filter_by_origin_cb;
+ LogicalDecodeShutdownCB shutdown_cb;
+} OutputPluginCallbacks;
+
+/* Functions in replication/logical/logical.c */
+extern void OutputPluginPrepareWrite(struct LogicalDecodingContext *ctx, bool last_write);
+extern void OutputPluginWrite(struct LogicalDecodingContext *ctx, bool last_write);
+extern void OutputPluginUpdateProgress(struct LogicalDecodingContext *ctx);
+
+#endif /* OUTPUT_PLUGIN_H */
diff --git a/src/include/replication/pgoutput.h b/src/include/replication/pgoutput.h
new file mode 100644
index 0000000..2e8e9da
--- /dev/null
+++ b/src/include/replication/pgoutput.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgoutput.h
+ * Logical Replication output plugin
+ *
+ * Copyright (c) 2015-2020, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * pgoutput.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PGOUTPUT_H
+#define PGOUTPUT_H
+
+#include "nodes/pg_list.h"
+
+typedef struct PGOutputData
+{
+ MemoryContext context; /* private memory context for transient
+ * allocations */
+
+ /* client info */
+ uint32 protocol_version;
+
+ List *publication_names;
+ List *publications;
+} PGOutputData;
+
+#endif /* PGOUTPUT_H */
diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h
new file mode 100644
index 0000000..5347597
--- /dev/null
+++ b/src/include/replication/reorderbuffer.h
@@ -0,0 +1,468 @@
+/*
+ * reorderbuffer.h
+ * PostgreSQL logical replay/reorder buffer management.
+ *
+ * Copyright (c) 2012-2020, PostgreSQL Global Development Group
+ *
+ * src/include/replication/reorderbuffer.h
+ */
+#ifndef REORDERBUFFER_H
+#define REORDERBUFFER_H
+
+#include "access/htup_details.h"
+#include "lib/ilist.h"
+#include "storage/sinval.h"
+#include "utils/hsearch.h"
+#include "utils/relcache.h"
+#include "utils/snapshot.h"
+#include "utils/timestamp.h"
+
+extern PGDLLIMPORT int logical_decoding_work_mem;
+
+/* an individual tuple, stored in one chunk of memory */
+typedef struct ReorderBufferTupleBuf
+{
+ /* position in preallocated list */
+ slist_node node;
+
+ /* tuple header, the interesting bit for users of logical decoding */
+ HeapTupleData tuple;
+
+ /* pre-allocated size of tuple buffer, different from tuple size */
+ Size alloc_tuple_size;
+
+ /* actual tuple data follows */
+} ReorderBufferTupleBuf;
+
+/* pointer to the data stored in a TupleBuf */
+#define ReorderBufferTupleBufData(p) \
+ ((HeapTupleHeader) MAXALIGN(((char *) p) + sizeof(ReorderBufferTupleBuf)))
+
+/*
+ * Types of the change passed to a 'change' callback.
+ *
+ * For efficiency and simplicity reasons we want to keep Snapshots, CommandIds
+ * and ComboCids in the same list with the user visible INSERT/UPDATE/DELETE
+ * changes. Users of the decoding facilities will never see changes with
+ * *_INTERNAL_* actions.
+ *
+ * The INTERNAL_SPEC_INSERT and INTERNAL_SPEC_CONFIRM, and INTERNAL_SPEC_ABORT
+ * changes concern "speculative insertions", their confirmation, and abort
+ * respectively. They're used by INSERT .. ON CONFLICT .. UPDATE. Users of
+ * logical decoding don't have to care about these.
+ */
+enum ReorderBufferChangeType
+{
+ REORDER_BUFFER_CHANGE_INSERT,
+ REORDER_BUFFER_CHANGE_UPDATE,
+ REORDER_BUFFER_CHANGE_DELETE,
+ REORDER_BUFFER_CHANGE_MESSAGE,
+ REORDER_BUFFER_CHANGE_INTERNAL_SNAPSHOT,
+ REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID,
+ REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID,
+ REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT,
+ REORDER_BUFFER_CHANGE_INTERNAL_SPEC_CONFIRM,
+ REORDER_BUFFER_CHANGE_TRUNCATE,
+ REORDER_BUFFER_CHANGE_INTERNAL_SPEC_ABORT
+};
+
+/* forward declaration */
+struct ReorderBufferTXN;
+
+/*
+ * a single 'change', can be an insert (with one tuple), an update (old, new),
+ * or a delete (old).
+ *
+ * The same struct is also used internally for other purposes but that should
+ * never be visible outside reorderbuffer.c.
+ */
+typedef struct ReorderBufferChange
+{
+ XLogRecPtr lsn;
+
+ /* The type of change. */
+ enum ReorderBufferChangeType action;
+
+ /* Transaction this change belongs to. */
+ struct ReorderBufferTXN *txn;
+
+ RepOriginId origin_id;
+
+ /*
+ * Context data for the change. Which part of the union is valid depends
+ * on action.
+ */
+ union
+ {
+ /* Old, new tuples when action == *_INSERT|UPDATE|DELETE */
+ struct
+ {
+ /* relation that has been changed */
+ RelFileNode relnode;
+
+ /* no previously reassembled toast chunks are necessary anymore */
+ bool clear_toast_afterwards;
+
+ /* valid for DELETE || UPDATE */
+ ReorderBufferTupleBuf *oldtuple;
+ /* valid for INSERT || UPDATE */
+ ReorderBufferTupleBuf *newtuple;
+ } tp;
+
+ /*
+ * Truncate data for REORDER_BUFFER_CHANGE_TRUNCATE representing one
+ * set of relations to be truncated.
+ */
+ struct
+ {
+ Size nrelids;
+ bool cascade;
+ bool restart_seqs;
+ Oid *relids;
+ } truncate;
+
+ /* Message with arbitrary data. */
+ struct
+ {
+ char *prefix;
+ Size message_size;
+ char *message;
+ } msg;
+
+ /* New snapshot, set when action == *_INTERNAL_SNAPSHOT */
+ Snapshot snapshot;
+
+ /*
+ * New command id for existing snapshot in a catalog changing tx. Set
+ * when action == *_INTERNAL_COMMAND_ID.
+ */
+ CommandId command_id;
+
+ /*
+ * New cid mapping for catalog changing transaction, set when action
+ * == *_INTERNAL_TUPLECID.
+ */
+ struct
+ {
+ RelFileNode node;
+ ItemPointerData tid;
+ CommandId cmin;
+ CommandId cmax;
+ CommandId combocid;
+ } tuplecid;
+ } data;
+
+ /*
+ * While in use this is how a change is linked into a transactions,
+ * otherwise it's the preallocated list.
+ */
+ dlist_node node;
+} ReorderBufferChange;
+
+/* ReorderBufferTXN txn_flags */
+#define RBTXN_HAS_CATALOG_CHANGES 0x0001
+#define RBTXN_IS_SUBXACT 0x0002
+#define RBTXN_IS_SERIALIZED 0x0004
+
+/* Does the transaction have catalog changes? */
+#define rbtxn_has_catalog_changes(txn) \
+( \
+ ((txn)->txn_flags & RBTXN_HAS_CATALOG_CHANGES) != 0 \
+)
+
+/* Is the transaction known as a subxact? */
+#define rbtxn_is_known_subxact(txn) \
+( \
+ ((txn)->txn_flags & RBTXN_IS_SUBXACT) != 0 \
+)
+
+/* Has this transaction been spilled to disk? */
+#define rbtxn_is_serialized(txn) \
+( \
+ ((txn)->txn_flags & RBTXN_IS_SERIALIZED) != 0 \
+)
+
+typedef struct ReorderBufferTXN
+{
+ /* See above */
+ bits32 txn_flags;
+
+ /* The transaction's transaction id, can be a toplevel or sub xid. */
+ TransactionId xid;
+
+ /* Xid of top-level transaction, if known */
+ TransactionId toplevel_xid;
+
+ /*
+ * LSN of the first data carrying, WAL record with knowledge about this
+ * xid. This is allowed to *not* be first record adorned with this xid, if
+ * the previous records aren't relevant for logical decoding.
+ */
+ XLogRecPtr first_lsn;
+
+ /* ----
+ * LSN of the record that lead to this xact to be committed or
+ * aborted. This can be a
+ * * plain commit record
+ * * plain commit record, of a parent transaction
+ * * prepared transaction commit
+ * * plain abort record
+ * * prepared transaction abort
+ *
+ * This can also become set to earlier values than transaction end when
+ * a transaction is spilled to disk; specifically it's set to the LSN of
+ * the latest change written to disk so far.
+ * ----
+ */
+ XLogRecPtr final_lsn;
+
+ /*
+ * LSN pointing to the end of the commit record + 1.
+ */
+ XLogRecPtr end_lsn;
+
+ /*
+ * LSN of the last lsn at which snapshot information reside, so we can
+ * restart decoding from there and fully recover this transaction from
+ * WAL.
+ */
+ XLogRecPtr restart_decoding_lsn;
+
+ /* origin of the change that caused this transaction */
+ RepOriginId origin_id;
+ XLogRecPtr origin_lsn;
+
+ /*
+ * Commit time, only known when we read the actual commit record.
+ */
+ TimestampTz commit_time;
+
+ /*
+ * The base snapshot is used to decode all changes until either this
+ * transaction modifies the catalog, or another catalog-modifying
+ * transaction commits.
+ */
+ Snapshot base_snapshot;
+ XLogRecPtr base_snapshot_lsn;
+ dlist_node base_snapshot_node; /* link in txns_by_base_snapshot_lsn */
+
+ /*
+ * How many ReorderBufferChange's do we have in this txn.
+ *
+ * Changes in subtransactions are *not* included but tracked separately.
+ */
+ uint64 nentries;
+
+ /*
+ * How many of the above entries are stored in memory in contrast to being
+ * spilled to disk.
+ */
+ uint64 nentries_mem;
+
+ /*
+ * List of ReorderBufferChange structs, including new Snapshots and new
+ * CommandIds
+ */
+ dlist_head changes;
+
+ /*
+ * List of (relation, ctid) => (cmin, cmax) mappings for catalog tuples.
+ * Those are always assigned to the toplevel transaction. (Keep track of
+ * #entries to create a hash of the right size)
+ */
+ dlist_head tuplecids;
+ uint64 ntuplecids;
+
+ /*
+ * On-demand built hash for looking up the above values.
+ */
+ HTAB *tuplecid_hash;
+
+ /*
+ * Hash containing (potentially partial) toast entries. NULL if no toast
+ * tuples have been found for the current change.
+ */
+ HTAB *toast_hash;
+
+ /*
+ * non-hierarchical list of subtransactions that are *not* aborted. Only
+ * used in toplevel transactions.
+ */
+ dlist_head subtxns;
+ uint32 nsubtxns;
+
+ /*
+ * Stored cache invalidations. This is not a linked list because we get
+ * all the invalidations at once.
+ */
+ uint32 ninvalidations;
+ SharedInvalidationMessage *invalidations;
+
+ /* ---
+ * Position in one of three lists:
+ * * list of subtransactions if we are *known* to be subxact
+ * * list of toplevel xacts (can be an as-yet unknown subxact)
+ * * list of preallocated ReorderBufferTXNs (if unused)
+ * ---
+ */
+ dlist_node node;
+
+ /*
+ * Size of this transaction (changes currently in memory, in bytes).
+ */
+ Size size;
+} ReorderBufferTXN;
+
+/* so we can define the callbacks used inside struct ReorderBuffer itself */
+typedef struct ReorderBuffer ReorderBuffer;
+
+/* change callback signature */
+typedef void (*ReorderBufferApplyChangeCB) (ReorderBuffer *rb,
+ ReorderBufferTXN *txn,
+ Relation relation,
+ ReorderBufferChange *change);
+
+/* truncate callback signature */
+typedef void (*ReorderBufferApplyTruncateCB) (ReorderBuffer *rb,
+ ReorderBufferTXN *txn,
+ int nrelations,
+ Relation relations[],
+ ReorderBufferChange *change);
+
+/* begin callback signature */
+typedef void (*ReorderBufferBeginCB) (ReorderBuffer *rb,
+ ReorderBufferTXN *txn);
+
+/* commit callback signature */
+typedef void (*ReorderBufferCommitCB) (ReorderBuffer *rb,
+ ReorderBufferTXN *txn,
+ XLogRecPtr commit_lsn);
+
+/* message callback signature */
+typedef void (*ReorderBufferMessageCB) (ReorderBuffer *rb,
+ ReorderBufferTXN *txn,
+ XLogRecPtr message_lsn,
+ bool transactional,
+ const char *prefix, Size sz,
+ const char *message);
+
+struct ReorderBuffer
+{
+ /*
+ * xid => ReorderBufferTXN lookup table
+ */
+ HTAB *by_txn;
+
+ /*
+ * Transactions that could be a toplevel xact, ordered by LSN of the first
+ * record bearing that xid.
+ */
+ dlist_head toplevel_by_lsn;
+
+ /*
+ * Transactions and subtransactions that have a base snapshot, ordered by
+ * LSN of the record which caused us to first obtain the base snapshot.
+ * This is not the same as toplevel_by_lsn, because we only set the base
+ * snapshot on the first logical-decoding-relevant record (eg. heap
+ * writes), whereas the initial LSN could be set by other operations.
+ */
+ dlist_head txns_by_base_snapshot_lsn;
+
+ /*
+ * one-entry sized cache for by_txn. Very frequently the same txn gets
+ * looked up over and over again.
+ */
+ TransactionId by_txn_last_xid;
+ ReorderBufferTXN *by_txn_last_txn;
+
+ /*
+ * Callbacks to be called when a transactions commits.
+ */
+ ReorderBufferBeginCB begin;
+ ReorderBufferApplyChangeCB apply_change;
+ ReorderBufferApplyTruncateCB apply_truncate;
+ ReorderBufferCommitCB commit;
+ ReorderBufferMessageCB message;
+
+ /*
+ * Pointer that will be passed untouched to the callbacks.
+ */
+ void *private_data;
+
+ /*
+ * Saved output plugin option
+ */
+ bool output_rewrites;
+
+ /*
+ * Private memory context.
+ */
+ MemoryContext context;
+
+ /*
+ * Memory contexts for specific types objects
+ */
+ MemoryContext change_context;
+ MemoryContext txn_context;
+ MemoryContext tup_context;
+
+ XLogRecPtr current_restart_decoding_lsn;
+
+ /* buffer for disk<->memory conversions */
+ char *outbuf;
+ Size outbufsize;
+
+ /* memory accounting */
+ Size size;
+};
+
+
+ReorderBuffer *ReorderBufferAllocate(void);
+void ReorderBufferFree(ReorderBuffer *);
+
+ReorderBufferTupleBuf *ReorderBufferGetTupleBuf(ReorderBuffer *, Size tuple_len);
+void ReorderBufferReturnTupleBuf(ReorderBuffer *, ReorderBufferTupleBuf *tuple);
+ReorderBufferChange *ReorderBufferGetChange(ReorderBuffer *);
+void ReorderBufferReturnChange(ReorderBuffer *, ReorderBufferChange *);
+
+Oid *ReorderBufferGetRelids(ReorderBuffer *, int nrelids);
+void ReorderBufferReturnRelids(ReorderBuffer *, Oid *relids);
+
+void ReorderBufferQueueChange(ReorderBuffer *, TransactionId, XLogRecPtr lsn, ReorderBufferChange *);
+void ReorderBufferQueueMessage(ReorderBuffer *, TransactionId, Snapshot snapshot, XLogRecPtr lsn,
+ bool transactional, const char *prefix,
+ Size message_size, const char *message);
+void ReorderBufferCommit(ReorderBuffer *, TransactionId,
+ XLogRecPtr commit_lsn, XLogRecPtr end_lsn,
+ TimestampTz commit_time, RepOriginId origin_id, XLogRecPtr origin_lsn);
+void ReorderBufferAssignChild(ReorderBuffer *, TransactionId, TransactionId, XLogRecPtr commit_lsn);
+void ReorderBufferCommitChild(ReorderBuffer *, TransactionId, TransactionId,
+ XLogRecPtr commit_lsn, XLogRecPtr end_lsn);
+void ReorderBufferAbort(ReorderBuffer *, TransactionId, XLogRecPtr lsn);
+void ReorderBufferAbortOld(ReorderBuffer *, TransactionId xid);
+void ReorderBufferForget(ReorderBuffer *, TransactionId, XLogRecPtr lsn);
+
+void ReorderBufferSetBaseSnapshot(ReorderBuffer *, TransactionId, XLogRecPtr lsn, struct SnapshotData *snap);
+void ReorderBufferAddSnapshot(ReorderBuffer *, TransactionId, XLogRecPtr lsn, struct SnapshotData *snap);
+void ReorderBufferAddNewCommandId(ReorderBuffer *, TransactionId, XLogRecPtr lsn,
+ CommandId cid);
+void ReorderBufferAddNewTupleCids(ReorderBuffer *, TransactionId, XLogRecPtr lsn,
+ RelFileNode node, ItemPointerData pt,
+ CommandId cmin, CommandId cmax, CommandId combocid);
+void ReorderBufferAddInvalidations(ReorderBuffer *, TransactionId, XLogRecPtr lsn,
+ Size nmsgs, SharedInvalidationMessage *msgs);
+void ReorderBufferImmediateInvalidation(ReorderBuffer *, uint32 ninvalidations,
+ SharedInvalidationMessage *invalidations);
+void ReorderBufferProcessXid(ReorderBuffer *, TransactionId xid, XLogRecPtr lsn);
+void ReorderBufferXidSetCatalogChanges(ReorderBuffer *, TransactionId xid, XLogRecPtr lsn);
+bool ReorderBufferXidHasCatalogChanges(ReorderBuffer *, TransactionId xid);
+bool ReorderBufferXidHasBaseSnapshot(ReorderBuffer *, TransactionId xid);
+
+ReorderBufferTXN *ReorderBufferGetOldestTXN(ReorderBuffer *);
+TransactionId ReorderBufferGetOldestXmin(ReorderBuffer *rb);
+
+void ReorderBufferSetRestartPoint(ReorderBuffer *, XLogRecPtr ptr);
+
+void StartupReorderBuffer(void);
+
+#endif
diff --git a/src/include/replication/slot.h b/src/include/replication/slot.h
new file mode 100644
index 0000000..12c68dd
--- /dev/null
+++ b/src/include/replication/slot.h
@@ -0,0 +1,219 @@
+/*-------------------------------------------------------------------------
+ * slot.h
+ * Replication slot management.
+ *
+ * Copyright (c) 2012-2020, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SLOT_H
+#define SLOT_H
+
+#include "access/xlog.h"
+#include "access/xlogreader.h"
+#include "storage/condition_variable.h"
+#include "storage/lwlock.h"
+#include "storage/shmem.h"
+#include "storage/spin.h"
+
+/*
+ * Behaviour of replication slots, upon release or crash.
+ *
+ * Slots marked as PERSISTENT are crash-safe and will not be dropped when
+ * released. Slots marked as EPHEMERAL will be dropped when released or after
+ * restarts. Slots marked TEMPORARY will be dropped at the end of a session
+ * or on error.
+ *
+ * EPHEMERAL is used as a not-quite-ready state when creating persistent
+ * slots. EPHEMERAL slots can be made PERSISTENT by calling
+ * ReplicationSlotPersist(). For a slot that goes away at the end of a
+ * session, TEMPORARY is the appropriate choice.
+ */
+typedef enum ReplicationSlotPersistency
+{
+ RS_PERSISTENT,
+ RS_EPHEMERAL,
+ RS_TEMPORARY
+} ReplicationSlotPersistency;
+
+/* For ReplicationSlotAcquire, q.v. */
+typedef enum SlotAcquireBehavior
+{
+ SAB_Error,
+ SAB_Block,
+ SAB_Inquire
+} SlotAcquireBehavior;
+
+/*
+ * On-Disk data of a replication slot, preserved across restarts.
+ */
+typedef struct ReplicationSlotPersistentData
+{
+ /* The slot's identifier */
+ NameData name;
+
+ /* database the slot is active on */
+ Oid database;
+
+ /*
+ * The slot's behaviour when being dropped (or restored after a crash).
+ */
+ ReplicationSlotPersistency persistency;
+
+ /*
+ * xmin horizon for data
+ *
+ * NB: This may represent a value that hasn't been written to disk yet;
+ * see notes for effective_xmin, below.
+ */
+ TransactionId xmin;
+
+ /*
+ * xmin horizon for catalog tuples
+ *
+ * NB: This may represent a value that hasn't been written to disk yet;
+ * see notes for effective_xmin, below.
+ */
+ TransactionId catalog_xmin;
+
+ /* oldest LSN that might be required by this replication slot */
+ XLogRecPtr restart_lsn;
+
+ /* restart_lsn is copied here when the slot is invalidated */
+ XLogRecPtr invalidated_at;
+
+ /*
+ * Oldest LSN that the client has acked receipt for. This is used as the
+ * start_lsn point in case the client doesn't specify one, and also as a
+ * safety measure to jump forwards in case the client specifies a
+ * start_lsn that's further in the past than this value.
+ */
+ XLogRecPtr confirmed_flush;
+
+ /* plugin name */
+ NameData plugin;
+} ReplicationSlotPersistentData;
+
+/*
+ * Shared memory state of a single replication slot.
+ *
+ * The in-memory data of replication slots follows a locking model based
+ * on two linked concepts:
+ * - A replication slot's in_use flag is switched when added or discarded using
+ * the LWLock ReplicationSlotControlLock, which needs to be hold in exclusive
+ * mode when updating the flag by the backend owning the slot and doing the
+ * operation, while readers (concurrent backends not owning the slot) need
+ * to hold it in shared mode when looking at replication slot data.
+ * - Individual fields are protected by mutex where only the backend owning
+ * the slot is authorized to update the fields from its own slot. The
+ * backend owning the slot does not need to take this lock when reading its
+ * own fields, while concurrent backends not owning this slot should take the
+ * lock when reading this slot's data.
+ */
+typedef struct ReplicationSlot
+{
+ /* lock, on same cacheline as effective_xmin */
+ slock_t mutex;
+
+ /* is this slot defined */
+ bool in_use;
+
+ /* Who is streaming out changes for this slot? 0 in unused slots. */
+ pid_t active_pid;
+
+ /* any outstanding modifications? */
+ bool just_dirtied;
+ bool dirty;
+
+ /*
+ * For logical decoding, it's extremely important that we never remove any
+ * data that's still needed for decoding purposes, even after a crash;
+ * otherwise, decoding will produce wrong answers. Ordinary streaming
+ * replication also needs to prevent old row versions from being removed
+ * too soon, but the worst consequence we might encounter there is
+ * unwanted query cancellations on the standby. Thus, for logical
+ * decoding, this value represents the latest xmin that has actually been
+ * written to disk, whereas for streaming replication, it's just the same
+ * as the persistent value (data.xmin).
+ */
+ TransactionId effective_xmin;
+ TransactionId effective_catalog_xmin;
+
+ /* data surviving shutdowns and crashes */
+ ReplicationSlotPersistentData data;
+
+ /* is somebody performing io on this slot? */
+ LWLock io_in_progress_lock;
+
+ /* Condition variable signaled when active_pid changes */
+ ConditionVariable active_cv;
+
+ /* all the remaining data is only used for logical slots */
+
+ /*
+ * When the client has confirmed flushes >= candidate_xmin_lsn we can
+ * advance the catalog xmin. When restart_valid has been passed,
+ * restart_lsn can be increased.
+ */
+ TransactionId candidate_catalog_xmin;
+ XLogRecPtr candidate_xmin_lsn;
+ XLogRecPtr candidate_restart_valid;
+ XLogRecPtr candidate_restart_lsn;
+} ReplicationSlot;
+
+#define SlotIsPhysical(slot) ((slot)->data.database == InvalidOid)
+#define SlotIsLogical(slot) ((slot)->data.database != InvalidOid)
+
+/*
+ * Shared memory control area for all of replication slots.
+ */
+typedef struct ReplicationSlotCtlData
+{
+ /*
+ * This array should be declared [FLEXIBLE_ARRAY_MEMBER], but for some
+ * reason you can't do that in an otherwise-empty struct.
+ */
+ ReplicationSlot replication_slots[1];
+} ReplicationSlotCtlData;
+
+/*
+ * Pointers to shared memory
+ */
+extern PGDLLIMPORT ReplicationSlotCtlData *ReplicationSlotCtl;
+extern PGDLLIMPORT ReplicationSlot *MyReplicationSlot;
+
+/* GUCs */
+extern PGDLLIMPORT int max_replication_slots;
+
+/* shmem initialization functions */
+extern Size ReplicationSlotsShmemSize(void);
+extern void ReplicationSlotsShmemInit(void);
+
+/* management of individual slots */
+extern void ReplicationSlotCreate(const char *name, bool db_specific,
+ ReplicationSlotPersistency p);
+extern void ReplicationSlotPersist(void);
+extern void ReplicationSlotDrop(const char *name, bool nowait);
+
+extern int ReplicationSlotAcquire(const char *name, SlotAcquireBehavior behavior);
+extern void ReplicationSlotRelease(void);
+extern void ReplicationSlotCleanup(void);
+extern void ReplicationSlotSave(void);
+extern void ReplicationSlotMarkDirty(void);
+
+/* misc stuff */
+extern bool ReplicationSlotValidateName(const char *name, int elevel);
+extern void ReplicationSlotReserveWal(void);
+extern void ReplicationSlotsComputeRequiredXmin(bool already_locked);
+extern void ReplicationSlotsComputeRequiredLSN(void);
+extern XLogRecPtr ReplicationSlotsComputeLogicalRestartLSN(void);
+extern bool ReplicationSlotsCountDBSlots(Oid dboid, int *nslots, int *nactive);
+extern void ReplicationSlotsDropDBSlots(Oid dboid);
+extern bool InvalidateObsoleteReplicationSlots(XLogSegNo oldestSegno);
+
+extern void StartupReplicationSlots(void);
+extern void CheckPointReplicationSlots(void);
+
+extern void CheckSlotRequirements(void);
+
+#endif /* SLOT_H */
diff --git a/src/include/replication/snapbuild.h b/src/include/replication/snapbuild.h
new file mode 100644
index 0000000..7f0f3ca
--- /dev/null
+++ b/src/include/replication/snapbuild.h
@@ -0,0 +1,90 @@
+/*-------------------------------------------------------------------------
+ *
+ * snapbuild.h
+ * Exports from replication/logical/snapbuild.c.
+ *
+ * Copyright (c) 2012-2020, PostgreSQL Global Development Group
+ *
+ * src/include/replication/snapbuild.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SNAPBUILD_H
+#define SNAPBUILD_H
+
+#include "access/xlogdefs.h"
+#include "utils/snapmgr.h"
+
+typedef enum
+{
+ /*
+ * Initial state, we can't do much yet.
+ */
+ SNAPBUILD_START = -1,
+
+ /*
+ * Collecting committed transactions, to build the initial catalog
+ * snapshot.
+ */
+ SNAPBUILD_BUILDING_SNAPSHOT = 0,
+
+ /*
+ * We have collected enough information to decode tuples in transactions
+ * that started after this.
+ *
+ * Once we reached this we start to collect changes. We cannot apply them
+ * yet, because they might be based on transactions that were still
+ * running when FULL_SNAPSHOT was reached.
+ */
+ SNAPBUILD_FULL_SNAPSHOT = 1,
+
+ /*
+ * Found a point after SNAPBUILD_FULL_SNAPSHOT where all transactions that
+ * were running at that point finished. Till we reach that we hold off
+ * calling any commit callbacks.
+ */
+ SNAPBUILD_CONSISTENT = 2
+} SnapBuildState;
+
+/* forward declare so we don't have to expose the struct to the public */
+struct SnapBuild;
+typedef struct SnapBuild SnapBuild;
+
+/* forward declare so we don't have to include reorderbuffer.h */
+struct ReorderBuffer;
+
+/* forward declare so we don't have to include heapam_xlog.h */
+struct xl_heap_new_cid;
+struct xl_running_xacts;
+
+extern void CheckPointSnapBuild(void);
+
+extern SnapBuild *AllocateSnapshotBuilder(struct ReorderBuffer *cache,
+ TransactionId xmin_horizon, XLogRecPtr start_lsn,
+ bool need_full_snapshot);
+extern void FreeSnapshotBuilder(SnapBuild *cache);
+
+extern void SnapBuildSnapDecRefcount(Snapshot snap);
+
+extern Snapshot SnapBuildInitialSnapshot(SnapBuild *builder);
+extern const char *SnapBuildExportSnapshot(SnapBuild *snapstate);
+extern void SnapBuildClearExportedSnapshot(void);
+
+extern SnapBuildState SnapBuildCurrentState(SnapBuild *snapstate);
+extern Snapshot SnapBuildGetOrBuildSnapshot(SnapBuild *builder,
+ TransactionId xid);
+
+extern bool SnapBuildXactNeedsSkip(SnapBuild *snapstate, XLogRecPtr ptr);
+
+extern void SnapBuildCommitTxn(SnapBuild *builder, XLogRecPtr lsn,
+ TransactionId xid, int nsubxacts,
+ TransactionId *subxacts);
+extern bool SnapBuildProcessChange(SnapBuild *builder, TransactionId xid,
+ XLogRecPtr lsn);
+extern void SnapBuildProcessNewCid(SnapBuild *builder, TransactionId xid,
+ XLogRecPtr lsn, struct xl_heap_new_cid *cid);
+extern void SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn,
+ struct xl_running_xacts *running);
+extern void SnapBuildSerializationPoint(SnapBuild *builder, XLogRecPtr lsn);
+
+#endif /* SNAPBUILD_H */
diff --git a/src/include/replication/syncrep.h b/src/include/replication/syncrep.h
new file mode 100644
index 0000000..9d286b6
--- /dev/null
+++ b/src/include/replication/syncrep.h
@@ -0,0 +1,115 @@
+/*-------------------------------------------------------------------------
+ *
+ * syncrep.h
+ * Exports from replication/syncrep.c.
+ *
+ * Portions Copyright (c) 2010-2020, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/replication/syncrep.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _SYNCREP_H
+#define _SYNCREP_H
+
+#include "access/xlogdefs.h"
+#include "utils/guc.h"
+
+#define SyncRepRequested() \
+ (max_wal_senders > 0 && synchronous_commit > SYNCHRONOUS_COMMIT_LOCAL_FLUSH)
+
+/* SyncRepWaitMode */
+#define SYNC_REP_NO_WAIT (-1)
+#define SYNC_REP_WAIT_WRITE 0
+#define SYNC_REP_WAIT_FLUSH 1
+#define SYNC_REP_WAIT_APPLY 2
+
+#define NUM_SYNC_REP_WAIT_MODE 3
+
+/* syncRepState */
+#define SYNC_REP_NOT_WAITING 0
+#define SYNC_REP_WAITING 1
+#define SYNC_REP_WAIT_COMPLETE 2
+
+/* syncrep_method of SyncRepConfigData */
+#define SYNC_REP_PRIORITY 0
+#define SYNC_REP_QUORUM 1
+
+/*
+ * SyncRepGetCandidateStandbys returns an array of these structs,
+ * one per candidate synchronous walsender.
+ */
+typedef struct SyncRepStandbyData
+{
+ /* Copies of relevant fields from WalSnd shared-memory struct */
+ pid_t pid;
+ XLogRecPtr write;
+ XLogRecPtr flush;
+ XLogRecPtr apply;
+ int sync_standby_priority;
+ /* Index of this walsender in the WalSnd shared-memory array */
+ int walsnd_index;
+ /* This flag indicates whether this struct is about our own process */
+ bool is_me;
+} SyncRepStandbyData;
+
+/*
+ * Struct for the configuration of synchronous replication.
+ *
+ * Note: this must be a flat representation that can be held in a single
+ * chunk of malloc'd memory, so that it can be stored as the "extra" data
+ * for the synchronous_standby_names GUC.
+ */
+typedef struct SyncRepConfigData
+{
+ int config_size; /* total size of this struct, in bytes */
+ int num_sync; /* number of sync standbys that we need to
+ * wait for */
+ uint8 syncrep_method; /* method to choose sync standbys */
+ int nmembers; /* number of members in the following list */
+ /* member_names contains nmembers consecutive nul-terminated C strings */
+ char member_names[FLEXIBLE_ARRAY_MEMBER];
+} SyncRepConfigData;
+
+extern SyncRepConfigData *SyncRepConfig;
+
+/* communication variables for parsing synchronous_standby_names GUC */
+extern SyncRepConfigData *syncrep_parse_result;
+extern char *syncrep_parse_error_msg;
+
+/* user-settable parameters for synchronous replication */
+extern char *SyncRepStandbyNames;
+
+/* called by user backend */
+extern void SyncRepWaitForLSN(XLogRecPtr lsn, bool commit);
+
+/* called at backend exit */
+extern void SyncRepCleanupAtProcExit(void);
+
+/* called by wal sender */
+extern void SyncRepInitConfig(void);
+extern void SyncRepReleaseWaiters(void);
+
+/* called by wal sender and user backend */
+extern int SyncRepGetCandidateStandbys(SyncRepStandbyData **standbys);
+
+/* called by checkpointer */
+extern void SyncRepUpdateSyncStandbysDefined(void);
+
+/* GUC infrastructure */
+extern bool check_synchronous_standby_names(char **newval, void **extra, GucSource source);
+extern void assign_synchronous_standby_names(const char *newval, void *extra);
+extern void assign_synchronous_commit(int newval, void *extra);
+
+/*
+ * Internal functions for parsing synchronous_standby_names grammar,
+ * in syncrep_gram.y and syncrep_scanner.l
+ */
+extern int syncrep_yyparse(void);
+extern int syncrep_yylex(void);
+extern void syncrep_yyerror(const char *str);
+extern void syncrep_scanner_init(const char *query_string);
+extern void syncrep_scanner_finish(void);
+
+#endif /* _SYNCREP_H */
diff --git a/src/include/replication/walreceiver.h b/src/include/replication/walreceiver.h
new file mode 100644
index 0000000..ac1acbb
--- /dev/null
+++ b/src/include/replication/walreceiver.h
@@ -0,0 +1,340 @@
+/*-------------------------------------------------------------------------
+ *
+ * walreceiver.h
+ * Exports from replication/walreceiverfuncs.c.
+ *
+ * Portions Copyright (c) 2010-2020, PostgreSQL Global Development Group
+ *
+ * src/include/replication/walreceiver.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _WALRECEIVER_H
+#define _WALRECEIVER_H
+
+#include "access/xlog.h"
+#include "access/xlogdefs.h"
+#include "getaddrinfo.h" /* for NI_MAXHOST */
+#include "pgtime.h"
+#include "port/atomics.h"
+#include "replication/logicalproto.h"
+#include "replication/walsender.h"
+#include "storage/latch.h"
+#include "storage/spin.h"
+#include "utils/tuplestore.h"
+
+/* user-settable parameters */
+extern int wal_receiver_status_interval;
+extern int wal_receiver_timeout;
+extern bool hot_standby_feedback;
+
+/*
+ * MAXCONNINFO: maximum size of a connection string.
+ *
+ * XXX: Should this move to pg_config_manual.h?
+ */
+#define MAXCONNINFO 1024
+
+/* Can we allow the standby to accept replication connection from another standby? */
+#define AllowCascadeReplication() (EnableHotStandby && max_wal_senders > 0)
+
+/*
+ * Values for WalRcv->walRcvState.
+ */
+typedef enum
+{
+ WALRCV_STOPPED, /* stopped and mustn't start up again */
+ WALRCV_STARTING, /* launched, but the process hasn't
+ * initialized yet */
+ WALRCV_STREAMING, /* walreceiver is streaming */
+ WALRCV_WAITING, /* stopped streaming, waiting for orders */
+ WALRCV_RESTARTING, /* asked to restart streaming */
+ WALRCV_STOPPING /* requested to stop, but still running */
+} WalRcvState;
+
+/* Shared memory area for management of walreceiver process */
+typedef struct
+{
+ /*
+ * PID of currently active walreceiver process, its current state and
+ * start time (actually, the time at which it was requested to be
+ * started).
+ */
+ pid_t pid;
+ WalRcvState walRcvState;
+ pg_time_t startTime;
+
+ /*
+ * receiveStart and receiveStartTLI indicate the first byte position and
+ * timeline that will be received. When startup process starts the
+ * walreceiver, it sets these to the point where it wants the streaming to
+ * begin.
+ */
+ XLogRecPtr receiveStart;
+ TimeLineID receiveStartTLI;
+
+ /*
+ * flushedUpto-1 is the last byte position that has already been received,
+ * and receivedTLI is the timeline it came from. At the first startup of
+ * walreceiver, these are set to receiveStart and receiveStartTLI. After
+ * that, walreceiver updates these whenever it flushes the received WAL to
+ * disk.
+ */
+ XLogRecPtr flushedUpto;
+ TimeLineID receivedTLI;
+
+ /*
+ * latestChunkStart is the starting byte position of the current "batch"
+ * of received WAL. It's actually the same as the previous value of
+ * flushedUpto before the last flush to disk. Startup process can use
+ * this to detect whether it's keeping up or not.
+ */
+ XLogRecPtr latestChunkStart;
+
+ /*
+ * Time of send and receive of any message received.
+ */
+ TimestampTz lastMsgSendTime;
+ TimestampTz lastMsgReceiptTime;
+
+ /*
+ * Latest reported end of WAL on the sender
+ */
+ XLogRecPtr latestWalEnd;
+ TimestampTz latestWalEndTime;
+
+ /*
+ * connection string; initially set to connect to the primary, and later
+ * clobbered to hide security-sensitive fields.
+ */
+ char conninfo[MAXCONNINFO];
+
+ /*
+ * Host name (this can be a host name, an IP address, or a directory path)
+ * and port number of the active replication connection.
+ */
+ char sender_host[NI_MAXHOST];
+ int sender_port;
+
+ /*
+ * replication slot name; is also used for walreceiver to connect with the
+ * primary
+ */
+ char slotname[NAMEDATALEN];
+
+ /*
+ * If it's a temporary replication slot, it needs to be recreated when
+ * connecting.
+ */
+ bool is_temp_slot;
+
+ /* set true once conninfo is ready to display (obfuscated pwds etc) */
+ bool ready_to_display;
+
+ /*
+ * Latch used by startup process to wake up walreceiver after telling it
+ * where to start streaming (after setting receiveStart and
+ * receiveStartTLI), and also to tell it to send apply feedback to the
+ * primary whenever specially marked commit records are applied. This is
+ * normally mapped to procLatch when walreceiver is running.
+ */
+ Latch *latch;
+
+ slock_t mutex; /* locks shared variables shown above */
+
+ /*
+ * Like flushedUpto, but advanced after writing and before flushing,
+ * without the need to acquire the spin lock. Data can be read by another
+ * process up to this point, but shouldn't be used for data integrity
+ * purposes.
+ */
+ pg_atomic_uint64 writtenUpto;
+
+ /*
+ * force walreceiver reply? This doesn't need to be locked; memory
+ * barriers for ordering are sufficient. But we do need atomic fetch and
+ * store semantics, so use sig_atomic_t.
+ */
+ sig_atomic_t force_reply; /* used as a bool */
+} WalRcvData;
+
+extern WalRcvData *WalRcv;
+
+typedef struct
+{
+ bool logical; /* True if this is logical replication stream,
+ * false if physical stream. */
+ char *slotname; /* Name of the replication slot or NULL. */
+ XLogRecPtr startpoint; /* LSN of starting point. */
+
+ union
+ {
+ struct
+ {
+ TimeLineID startpointTLI; /* Starting timeline */
+ } physical;
+ struct
+ {
+ uint32 proto_version; /* Logical protocol version */
+ List *publication_names; /* String list of publications */
+ } logical;
+ } proto;
+} WalRcvStreamOptions;
+
+struct WalReceiverConn;
+typedef struct WalReceiverConn WalReceiverConn;
+
+/*
+ * Status of walreceiver query execution.
+ *
+ * We only define statuses that are currently used.
+ */
+typedef enum
+{
+ WALRCV_ERROR, /* There was error when executing the query. */
+ WALRCV_OK_COMMAND, /* Query executed utility or replication
+ * command. */
+ WALRCV_OK_TUPLES, /* Query returned tuples. */
+ WALRCV_OK_COPY_IN, /* Query started COPY FROM. */
+ WALRCV_OK_COPY_OUT, /* Query started COPY TO. */
+ WALRCV_OK_COPY_BOTH /* Query started COPY BOTH replication
+ * protocol. */
+} WalRcvExecStatus;
+
+/*
+ * Return value for walrcv_exec, returns the status of the execution and
+ * tuples if any.
+ */
+typedef struct WalRcvExecResult
+{
+ WalRcvExecStatus status;
+ char *err;
+ Tuplestorestate *tuplestore;
+ TupleDesc tupledesc;
+} WalRcvExecResult;
+
+/* libpqwalreceiver hooks */
+typedef WalReceiverConn *(*walrcv_connect_fn) (const char *conninfo, bool logical,
+ const char *appname,
+ char **err);
+typedef void (*walrcv_check_conninfo_fn) (const char *conninfo);
+typedef char *(*walrcv_get_conninfo_fn) (WalReceiverConn *conn);
+typedef void (*walrcv_get_senderinfo_fn) (WalReceiverConn *conn,
+ char **sender_host,
+ int *sender_port);
+typedef char *(*walrcv_identify_system_fn) (WalReceiverConn *conn,
+ TimeLineID *primary_tli);
+typedef int (*walrcv_server_version_fn) (WalReceiverConn *conn);
+typedef void (*walrcv_readtimelinehistoryfile_fn) (WalReceiverConn *conn,
+ TimeLineID tli,
+ char **filename,
+ char **content, int *size);
+typedef bool (*walrcv_startstreaming_fn) (WalReceiverConn *conn,
+ const WalRcvStreamOptions *options);
+typedef void (*walrcv_endstreaming_fn) (WalReceiverConn *conn,
+ TimeLineID *next_tli);
+typedef int (*walrcv_receive_fn) (WalReceiverConn *conn, char **buffer,
+ pgsocket *wait_fd);
+typedef void (*walrcv_send_fn) (WalReceiverConn *conn, const char *buffer,
+ int nbytes);
+typedef char *(*walrcv_create_slot_fn) (WalReceiverConn *conn,
+ const char *slotname, bool temporary,
+ CRSSnapshotAction snapshot_action,
+ XLogRecPtr *lsn);
+typedef pid_t (*walrcv_get_backend_pid_fn) (WalReceiverConn *conn);
+typedef WalRcvExecResult *(*walrcv_exec_fn) (WalReceiverConn *conn,
+ const char *query,
+ const int nRetTypes,
+ const Oid *retTypes);
+typedef void (*walrcv_disconnect_fn) (WalReceiverConn *conn);
+
+typedef struct WalReceiverFunctionsType
+{
+ walrcv_connect_fn walrcv_connect;
+ walrcv_check_conninfo_fn walrcv_check_conninfo;
+ walrcv_get_conninfo_fn walrcv_get_conninfo;
+ walrcv_get_senderinfo_fn walrcv_get_senderinfo;
+ walrcv_identify_system_fn walrcv_identify_system;
+ walrcv_server_version_fn walrcv_server_version;
+ walrcv_readtimelinehistoryfile_fn walrcv_readtimelinehistoryfile;
+ walrcv_startstreaming_fn walrcv_startstreaming;
+ walrcv_endstreaming_fn walrcv_endstreaming;
+ walrcv_receive_fn walrcv_receive;
+ walrcv_send_fn walrcv_send;
+ walrcv_create_slot_fn walrcv_create_slot;
+ walrcv_get_backend_pid_fn walrcv_get_backend_pid;
+ walrcv_exec_fn walrcv_exec;
+ walrcv_disconnect_fn walrcv_disconnect;
+} WalReceiverFunctionsType;
+
+extern PGDLLIMPORT WalReceiverFunctionsType *WalReceiverFunctions;
+
+#define walrcv_connect(conninfo, logical, appname, err) \
+ WalReceiverFunctions->walrcv_connect(conninfo, logical, appname, err)
+#define walrcv_check_conninfo(conninfo) \
+ WalReceiverFunctions->walrcv_check_conninfo(conninfo)
+#define walrcv_get_conninfo(conn) \
+ WalReceiverFunctions->walrcv_get_conninfo(conn)
+#define walrcv_get_senderinfo(conn, sender_host, sender_port) \
+ WalReceiverFunctions->walrcv_get_senderinfo(conn, sender_host, sender_port)
+#define walrcv_identify_system(conn, primary_tli) \
+ WalReceiverFunctions->walrcv_identify_system(conn, primary_tli)
+#define walrcv_server_version(conn) \
+ WalReceiverFunctions->walrcv_server_version(conn)
+#define walrcv_readtimelinehistoryfile(conn, tli, filename, content, size) \
+ WalReceiverFunctions->walrcv_readtimelinehistoryfile(conn, tli, filename, content, size)
+#define walrcv_startstreaming(conn, options) \
+ WalReceiverFunctions->walrcv_startstreaming(conn, options)
+#define walrcv_endstreaming(conn, next_tli) \
+ WalReceiverFunctions->walrcv_endstreaming(conn, next_tli)
+#define walrcv_receive(conn, buffer, wait_fd) \
+ WalReceiverFunctions->walrcv_receive(conn, buffer, wait_fd)
+#define walrcv_send(conn, buffer, nbytes) \
+ WalReceiverFunctions->walrcv_send(conn, buffer, nbytes)
+#define walrcv_create_slot(conn, slotname, temporary, snapshot_action, lsn) \
+ WalReceiverFunctions->walrcv_create_slot(conn, slotname, temporary, snapshot_action, lsn)
+#define walrcv_get_backend_pid(conn) \
+ WalReceiverFunctions->walrcv_get_backend_pid(conn)
+#define walrcv_exec(conn, exec, nRetTypes, retTypes) \
+ WalReceiverFunctions->walrcv_exec(conn, exec, nRetTypes, retTypes)
+#define walrcv_disconnect(conn) \
+ WalReceiverFunctions->walrcv_disconnect(conn)
+
+static inline void
+walrcv_clear_result(WalRcvExecResult *walres)
+{
+ if (!walres)
+ return;
+
+ if (walres->err)
+ pfree(walres->err);
+
+ if (walres->tuplestore)
+ tuplestore_end(walres->tuplestore);
+
+ if (walres->tupledesc)
+ FreeTupleDesc(walres->tupledesc);
+
+ pfree(walres);
+}
+
+/* prototypes for functions in walreceiver.c */
+extern void WalReceiverMain(void) pg_attribute_noreturn();
+extern void ProcessWalRcvInterrupts(void);
+
+/* prototypes for functions in walreceiverfuncs.c */
+extern Size WalRcvShmemSize(void);
+extern void WalRcvShmemInit(void);
+extern void ShutdownWalRcv(void);
+extern bool WalRcvStreaming(void);
+extern bool WalRcvRunning(void);
+extern void RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr,
+ const char *conninfo, const char *slotname,
+ bool create_temp_slot);
+extern XLogRecPtr GetWalRcvFlushRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI);
+extern XLogRecPtr GetWalRcvWriteRecPtr(void);
+extern int GetReplicationApplyDelay(void);
+extern int GetReplicationTransferLatency(void);
+extern void WalRcvForceReply(void);
+
+#endif /* _WALRECEIVER_H */
diff --git a/src/include/replication/walsender.h b/src/include/replication/walsender.h
new file mode 100644
index 0000000..40d81b8
--- /dev/null
+++ b/src/include/replication/walsender.h
@@ -0,0 +1,74 @@
+/*-------------------------------------------------------------------------
+ *
+ * walsender.h
+ * Exports from replication/walsender.c.
+ *
+ * Portions Copyright (c) 2010-2020, PostgreSQL Global Development Group
+ *
+ * src/include/replication/walsender.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _WALSENDER_H
+#define _WALSENDER_H
+
+#include <signal.h>
+
+/*
+ * What to do with a snapshot in create replication slot command.
+ */
+typedef enum
+{
+ CRS_EXPORT_SNAPSHOT,
+ CRS_NOEXPORT_SNAPSHOT,
+ CRS_USE_SNAPSHOT
+} CRSSnapshotAction;
+
+/* global state */
+extern bool am_walsender;
+extern bool am_cascading_walsender;
+extern bool am_db_walsender;
+extern bool wake_wal_senders;
+
+/* user-settable parameters */
+extern int max_wal_senders;
+extern int wal_sender_timeout;
+extern bool log_replication_commands;
+
+extern void InitWalSender(void);
+extern bool exec_replication_command(const char *query_string);
+extern void WalSndErrorCleanup(void);
+extern void WalSndResourceCleanup(bool isCommit);
+extern void WalSndSignals(void);
+extern Size WalSndShmemSize(void);
+extern void WalSndShmemInit(void);
+extern void WalSndWakeup(void);
+extern void WalSndInitStopping(void);
+extern void WalSndWaitStopping(void);
+extern void HandleWalSndInitStopping(void);
+extern void WalSndRqstFileReload(void);
+
+/*
+ * Remember that we want to wakeup walsenders later
+ *
+ * This is separated from doing the actual wakeup because the writeout is done
+ * while holding contended locks.
+ */
+#define WalSndWakeupRequest() \
+ do { wake_wal_senders = true; } while (0)
+
+/*
+ * wakeup walsenders if there is work to be done
+ */
+#define WalSndWakeupProcessRequests() \
+ do \
+ { \
+ if (wake_wal_senders) \
+ { \
+ wake_wal_senders = false; \
+ if (max_wal_senders > 0) \
+ WalSndWakeup(); \
+ } \
+ } while (0)
+
+#endif /* _WALSENDER_H */
diff --git a/src/include/replication/walsender_private.h b/src/include/replication/walsender_private.h
new file mode 100644
index 0000000..509856c
--- /dev/null
+++ b/src/include/replication/walsender_private.h
@@ -0,0 +1,127 @@
+/*-------------------------------------------------------------------------
+ *
+ * walsender_private.h
+ * Private definitions from replication/walsender.c.
+ *
+ * Portions Copyright (c) 2010-2020, PostgreSQL Global Development Group
+ *
+ * src/include/replication/walsender_private.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _WALSENDER_PRIVATE_H
+#define _WALSENDER_PRIVATE_H
+
+#include "access/xlog.h"
+#include "nodes/nodes.h"
+#include "replication/syncrep.h"
+#include "storage/latch.h"
+#include "storage/shmem.h"
+#include "storage/spin.h"
+
+typedef enum WalSndState
+{
+ WALSNDSTATE_STARTUP = 0,
+ WALSNDSTATE_BACKUP,
+ WALSNDSTATE_CATCHUP,
+ WALSNDSTATE_STREAMING,
+ WALSNDSTATE_STOPPING
+} WalSndState;
+
+/*
+ * Each walsender has a WalSnd struct in shared memory.
+ *
+ * This struct is protected by its 'mutex' spinlock field, except that some
+ * members are only written by the walsender process itself, and thus that
+ * process is free to read those members without holding spinlock. pid and
+ * needreload always require the spinlock to be held for all accesses.
+ */
+typedef struct WalSnd
+{
+ pid_t pid; /* this walsender's PID, or 0 if not active */
+
+ WalSndState state; /* this walsender's state */
+ XLogRecPtr sentPtr; /* WAL has been sent up to this point */
+ bool needreload; /* does currently-open file need to be
+ * reloaded? */
+
+ /*
+ * The xlog locations that have been written, flushed, and applied by
+ * standby-side. These may be invalid if the standby-side has not offered
+ * values yet.
+ */
+ XLogRecPtr write;
+ XLogRecPtr flush;
+ XLogRecPtr apply;
+
+ /* Measured lag times, or -1 for unknown/none. */
+ TimeOffset writeLag;
+ TimeOffset flushLag;
+ TimeOffset applyLag;
+
+ /*
+ * The priority order of the standby managed by this WALSender, as listed
+ * in synchronous_standby_names, or 0 if not-listed.
+ */
+ int sync_standby_priority;
+
+ /* Protects shared variables shown above. */
+ slock_t mutex;
+
+ /*
+ * Pointer to the walsender's latch. Used by backends to wake up this
+ * walsender when it has work to do. NULL if the walsender isn't active.
+ */
+ Latch *latch;
+
+ /*
+ * Timestamp of the last message received from standby.
+ */
+ TimestampTz replyTime;
+} WalSnd;
+
+extern WalSnd *MyWalSnd;
+
+/* There is one WalSndCtl struct for the whole database cluster */
+typedef struct
+{
+ /*
+ * Synchronous replication queue with one queue per request type.
+ * Protected by SyncRepLock.
+ */
+ SHM_QUEUE SyncRepQueue[NUM_SYNC_REP_WAIT_MODE];
+
+ /*
+ * Current location of the head of the queue. All waiters should have a
+ * waitLSN that follows this value. Protected by SyncRepLock.
+ */
+ XLogRecPtr lsn[NUM_SYNC_REP_WAIT_MODE];
+
+ /*
+ * Are any sync standbys defined? Waiting backends can't reload the
+ * config file safely, so checkpointer updates this value as needed.
+ * Protected by SyncRepLock.
+ */
+ bool sync_standbys_defined;
+
+ WalSnd walsnds[FLEXIBLE_ARRAY_MEMBER];
+} WalSndCtlData;
+
+extern WalSndCtlData *WalSndCtl;
+
+
+extern void WalSndSetState(WalSndState state);
+
+/*
+ * Internal functions for parsing the replication grammar, in repl_gram.y and
+ * repl_scanner.l
+ */
+extern int replication_yyparse(void);
+extern int replication_yylex(void);
+extern void replication_yyerror(const char *str) pg_attribute_noreturn();
+extern void replication_scanner_init(const char *query_string);
+extern void replication_scanner_finish(void);
+
+extern Node *replication_parse_result;
+
+#endif /* _WALSENDER_PRIVATE_H */
diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h
new file mode 100644
index 0000000..58abc3e
--- /dev/null
+++ b/src/include/replication/worker_internal.h
@@ -0,0 +1,95 @@
+/*-------------------------------------------------------------------------
+ *
+ * worker_internal.h
+ * Internal headers shared by logical replication workers.
+ *
+ * Portions Copyright (c) 2016-2020, PostgreSQL Global Development Group
+ *
+ * src/include/replication/worker_internal.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef WORKER_INTERNAL_H
+#define WORKER_INTERNAL_H
+
+#include <signal.h>
+
+#include "access/xlogdefs.h"
+#include "catalog/pg_subscription.h"
+#include "datatype/timestamp.h"
+#include "storage/lock.h"
+
+typedef struct LogicalRepWorker
+{
+ /* Time at which this worker was launched. */
+ TimestampTz launch_time;
+
+ /* Indicates if this slot is used or free. */
+ bool in_use;
+
+ /* Increased every time the slot is taken by new worker. */
+ uint16 generation;
+
+ /* Pointer to proc array. NULL if not running. */
+ PGPROC *proc;
+
+ /* Database id to connect to. */
+ Oid dbid;
+
+ /* User to use for connection (will be same as owner of subscription). */
+ Oid userid;
+
+ /* Subscription id for the worker. */
+ Oid subid;
+
+ /* Used for initial table synchronization. */
+ Oid relid;
+ char relstate;
+ XLogRecPtr relstate_lsn;
+ slock_t relmutex;
+
+ /* Stats. */
+ XLogRecPtr last_lsn;
+ TimestampTz last_send_time;
+ TimestampTz last_recv_time;
+ XLogRecPtr reply_lsn;
+ TimestampTz reply_time;
+} LogicalRepWorker;
+
+/* Main memory context for apply worker. Permanent during worker lifetime. */
+extern MemoryContext ApplyContext;
+
+/* libpqreceiver connection */
+extern struct WalReceiverConn *LogRepWorkerWalRcvConn;
+
+/* Worker and subscription objects. */
+extern Subscription *MySubscription;
+extern LogicalRepWorker *MyLogicalRepWorker;
+
+extern bool in_remote_transaction;
+
+extern void logicalrep_worker_attach(int slot);
+extern LogicalRepWorker *logicalrep_worker_find(Oid subid, Oid relid,
+ bool only_running);
+extern List *logicalrep_workers_find(Oid subid, bool only_running);
+extern void logicalrep_worker_launch(Oid dbid, Oid subid, const char *subname,
+ Oid userid, Oid relid);
+extern void logicalrep_worker_stop(Oid subid, Oid relid);
+extern void logicalrep_worker_stop_at_commit(Oid subid, Oid relid);
+extern void logicalrep_worker_wakeup(Oid subid, Oid relid);
+extern void logicalrep_worker_wakeup_ptr(LogicalRepWorker *worker);
+
+extern int logicalrep_sync_worker_count(Oid subid);
+
+extern char *LogicalRepSyncTableStart(XLogRecPtr *origin_startpos);
+void process_syncing_tables(XLogRecPtr current_lsn);
+void invalidate_syncing_table_states(Datum arg, int cacheid,
+ uint32 hashvalue);
+
+static inline bool
+am_tablesync_worker(void)
+{
+ return OidIsValid(MyLogicalRepWorker->relid);
+}
+
+#endif /* WORKER_INTERNAL_H */
diff --git a/src/include/rewrite/prs2lock.h b/src/include/rewrite/prs2lock.h
new file mode 100644
index 0000000..84ee6a5
--- /dev/null
+++ b/src/include/rewrite/prs2lock.h
@@ -0,0 +1,46 @@
+/*-------------------------------------------------------------------------
+ *
+ * prs2lock.h
+ * data structures for POSTGRES Rule System II (rewrite rules only)
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/rewrite/prs2lock.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PRS2LOCK_H
+#define PRS2LOCK_H
+
+#include "access/attnum.h"
+#include "nodes/pg_list.h"
+
+/*
+ * RewriteRule -
+ * holds an info for a rewrite rule
+ *
+ */
+typedef struct RewriteRule
+{
+ Oid ruleId;
+ CmdType event;
+ Node *qual;
+ List *actions;
+ char enabled;
+ bool isInstead;
+} RewriteRule;
+
+/*
+ * RuleLock -
+ * all rules that apply to a particular relation. Even though we only
+ * have the rewrite rule system left and these are not really "locks",
+ * the name is kept for historical reasons.
+ */
+typedef struct RuleLock
+{
+ int numLocks;
+ RewriteRule **rules;
+} RuleLock;
+
+#endif /* PRS2LOCK_H */
diff --git a/src/include/rewrite/rewriteDefine.h b/src/include/rewrite/rewriteDefine.h
new file mode 100644
index 0000000..c25733a
--- /dev/null
+++ b/src/include/rewrite/rewriteDefine.h
@@ -0,0 +1,44 @@
+/*-------------------------------------------------------------------------
+ *
+ * rewriteDefine.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/rewrite/rewriteDefine.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef REWRITEDEFINE_H
+#define REWRITEDEFINE_H
+
+#include "catalog/objectaddress.h"
+#include "nodes/parsenodes.h"
+#include "utils/relcache.h"
+
+#define RULE_FIRES_ON_ORIGIN 'O'
+#define RULE_FIRES_ALWAYS 'A'
+#define RULE_FIRES_ON_REPLICA 'R'
+#define RULE_DISABLED 'D'
+
+extern ObjectAddress DefineRule(RuleStmt *stmt, const char *queryString);
+
+extern ObjectAddress DefineQueryRewrite(const char *rulename,
+ Oid event_relid,
+ Node *event_qual,
+ CmdType event_type,
+ bool is_instead,
+ bool replace,
+ List *action);
+
+extern ObjectAddress RenameRewriteRule(RangeVar *relation, const char *oldName,
+ const char *newName);
+
+extern void setRuleCheckAsUser(Node *node, Oid userid);
+
+extern void EnableDisableRule(Relation rel, const char *rulename,
+ char fires_when);
+
+#endif /* REWRITEDEFINE_H */
diff --git a/src/include/rewrite/rewriteHandler.h b/src/include/rewrite/rewriteHandler.h
new file mode 100644
index 0000000..a18211f
--- /dev/null
+++ b/src/include/rewrite/rewriteHandler.h
@@ -0,0 +1,40 @@
+/*-------------------------------------------------------------------------
+ *
+ * rewriteHandler.h
+ * External interface to query rewriter.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/rewrite/rewriteHandler.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef REWRITEHANDLER_H
+#define REWRITEHANDLER_H
+
+#include "nodes/parsenodes.h"
+#include "utils/relcache.h"
+
+extern List *QueryRewrite(Query *parsetree);
+extern void AcquireRewriteLocks(Query *parsetree,
+ bool forExecute,
+ bool forUpdatePushedDown);
+
+extern Node *build_column_default(Relation rel, int attrno);
+extern void rewriteTargetListUD(Query *parsetree, RangeTblEntry *target_rte,
+ Relation target_relation);
+
+extern void fill_extraUpdatedCols(RangeTblEntry *target_rte,
+ Relation target_relation);
+
+extern Query *get_view_query(Relation view);
+extern const char *view_query_is_auto_updatable(Query *viewquery,
+ bool check_cols);
+extern int relation_is_updatable(Oid reloid,
+ List *outer_reloids,
+ bool include_triggers,
+ Bitmapset *include_cols);
+
+#endif /* REWRITEHANDLER_H */
diff --git a/src/include/rewrite/rewriteManip.h b/src/include/rewrite/rewriteManip.h
new file mode 100644
index 0000000..5ece816
--- /dev/null
+++ b/src/include/rewrite/rewriteManip.h
@@ -0,0 +1,87 @@
+/*-------------------------------------------------------------------------
+ *
+ * rewriteManip.h
+ * Querytree manipulation subroutines for query rewriter.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/rewrite/rewriteManip.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef REWRITEMANIP_H
+#define REWRITEMANIP_H
+
+#include "nodes/parsenodes.h"
+
+struct AttrMap; /* avoid including attmap.h here */
+
+
+typedef struct replace_rte_variables_context replace_rte_variables_context;
+
+typedef Node *(*replace_rte_variables_callback) (Var *var,
+ replace_rte_variables_context *context);
+
+struct replace_rte_variables_context
+{
+ replace_rte_variables_callback callback; /* callback function */
+ void *callback_arg; /* context data for callback function */
+ int target_varno; /* RTE index to search for */
+ int sublevels_up; /* (current) nesting depth */
+ bool inserted_sublink; /* have we inserted a SubLink? */
+};
+
+typedef enum ReplaceVarsNoMatchOption
+{
+ REPLACEVARS_REPORT_ERROR, /* throw error if no match */
+ REPLACEVARS_CHANGE_VARNO, /* change the Var's varno, nothing else */
+ REPLACEVARS_SUBSTITUTE_NULL /* replace with a NULL Const */
+} ReplaceVarsNoMatchOption;
+
+
+extern void OffsetVarNodes(Node *node, int offset, int sublevels_up);
+extern void ChangeVarNodes(Node *node, int old_varno, int new_varno,
+ int sublevels_up);
+extern void IncrementVarSublevelsUp(Node *node, int delta_sublevels_up,
+ int min_sublevels_up);
+extern void IncrementVarSublevelsUp_rtable(List *rtable,
+ int delta_sublevels_up, int min_sublevels_up);
+
+extern bool rangeTableEntry_used(Node *node, int rt_index,
+ int sublevels_up);
+
+extern Query *getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr);
+
+extern void AddQual(Query *parsetree, Node *qual);
+extern void AddInvertedQual(Query *parsetree, Node *qual);
+
+extern bool contain_aggs_of_level(Node *node, int levelsup);
+extern int locate_agg_of_level(Node *node, int levelsup);
+extern bool contain_windowfuncs(Node *node);
+extern int locate_windowfunc(Node *node);
+extern bool checkExprHasSubLink(Node *node);
+
+extern Node *replace_rte_variables(Node *node,
+ int target_varno, int sublevels_up,
+ replace_rte_variables_callback callback,
+ void *callback_arg,
+ bool *outer_hasSubLinks);
+extern Node *replace_rte_variables_mutator(Node *node,
+ replace_rte_variables_context *context);
+
+extern Node *map_variable_attnos(Node *node,
+ int target_varno, int sublevels_up,
+ const struct AttrMap *attno_map,
+ Oid to_rowtype, bool *found_whole_row);
+
+extern Node *ReplaceVarsFromTargetList(Node *node,
+ int target_varno, int sublevels_up,
+ RangeTblEntry *target_rte,
+ List *targetlist,
+ ReplaceVarsNoMatchOption nomatch_option,
+ int nomatch_varno,
+ bool *outer_hasSubLinks);
+
+#endif /* REWRITEMANIP_H */
diff --git a/src/include/rewrite/rewriteRemove.h b/src/include/rewrite/rewriteRemove.h
new file mode 100644
index 0000000..f07896c
--- /dev/null
+++ b/src/include/rewrite/rewriteRemove.h
@@ -0,0 +1,21 @@
+/*-------------------------------------------------------------------------
+ *
+ * rewriteRemove.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/rewrite/rewriteRemove.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef REWRITEREMOVE_H
+#define REWRITEREMOVE_H
+
+#include "nodes/parsenodes.h"
+
+extern void RemoveRewriteRuleById(Oid ruleOid);
+
+#endif /* REWRITEREMOVE_H */
diff --git a/src/include/rewrite/rewriteSupport.h b/src/include/rewrite/rewriteSupport.h
new file mode 100644
index 0000000..f58f356
--- /dev/null
+++ b/src/include/rewrite/rewriteSupport.h
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ *
+ * rewriteSupport.h
+ *
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/rewrite/rewriteSupport.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef REWRITESUPPORT_H
+#define REWRITESUPPORT_H
+
+/* The ON SELECT rule of a view is always named this: */
+#define ViewSelectRuleName "_RETURN"
+
+extern bool IsDefinedRewriteRule(Oid owningRel, const char *ruleName);
+
+extern void SetRelationRuleStatus(Oid relationId, bool relHasRules);
+
+extern Oid get_rewrite_oid(Oid relid, const char *rulename, bool missing_ok);
+
+#endif /* REWRITESUPPORT_H */
diff --git a/src/include/rewrite/rowsecurity.h b/src/include/rewrite/rowsecurity.h
new file mode 100644
index 0000000..2e0bac5
--- /dev/null
+++ b/src/include/rewrite/rowsecurity.h
@@ -0,0 +1,49 @@
+/* -------------------------------------------------------------------------
+ *
+ * rowsecurity.h
+ *
+ * prototypes for rewrite/rowsecurity.c and the structures for managing
+ * the row security policies for relations in relcache.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * -------------------------------------------------------------------------
+ */
+#ifndef ROWSECURITY_H
+#define ROWSECURITY_H
+
+#include "nodes/parsenodes.h"
+#include "utils/array.h"
+#include "utils/relcache.h"
+
+typedef struct RowSecurityPolicy
+{
+ char *policy_name; /* Name of the policy */
+ char polcmd; /* Type of command policy is for */
+ ArrayType *roles; /* Array of roles policy is for */
+ bool permissive; /* restrictive or permissive policy */
+ Expr *qual; /* Expression to filter rows */
+ Expr *with_check_qual; /* Expression to limit rows allowed */
+ bool hassublinks; /* If either expression has sublinks */
+} RowSecurityPolicy;
+
+typedef struct RowSecurityDesc
+{
+ MemoryContext rscxt; /* row security memory context */
+ List *policies; /* list of row security policies */
+} RowSecurityDesc;
+
+typedef List *(*row_security_policy_hook_type) (CmdType cmdtype,
+ Relation relation);
+
+extern PGDLLIMPORT row_security_policy_hook_type row_security_policy_hook_permissive;
+
+extern PGDLLIMPORT row_security_policy_hook_type row_security_policy_hook_restrictive;
+
+extern void get_row_security_policies(Query *root,
+ RangeTblEntry *rte, int rt_index,
+ List **securityQuals, List **withCheckOptions,
+ bool *hasRowSecurity, bool *hasSubLinks);
+
+#endif /* ROWSECURITY_H */
diff --git a/src/include/rusagestub.h b/src/include/rusagestub.h
new file mode 100644
index 0000000..3a812a2
--- /dev/null
+++ b/src/include/rusagestub.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * rusagestub.h
+ * Stubs for getrusage(3).
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/rusagestub.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RUSAGESTUB_H
+#define RUSAGESTUB_H
+
+#include <sys/time.h> /* for struct timeval */
+#ifndef WIN32
+#include <sys/times.h> /* for struct tms */
+#endif
+#include <limits.h> /* for CLK_TCK */
+
+#define RUSAGE_SELF 0
+#define RUSAGE_CHILDREN (-1)
+
+struct rusage
+{
+ struct timeval ru_utime; /* user time used */
+ struct timeval ru_stime; /* system time used */
+};
+
+extern int getrusage(int who, struct rusage *rusage);
+
+#endif /* RUSAGESTUB_H */
diff --git a/src/include/snowball/header.h b/src/include/snowball/header.h
new file mode 100644
index 0000000..912e072
--- /dev/null
+++ b/src/include/snowball/header.h
@@ -0,0 +1,67 @@
+/*-------------------------------------------------------------------------
+ *
+ * header.h
+ * Replacement header file for Snowball stemmer modules
+ *
+ * The Snowball stemmer modules do #include "header.h", and think they
+ * are including snowball/libstemmer/header.h. We adjust the CPPFLAGS
+ * so that this file is found instead, and thereby we can modify the
+ * headers they see. The main point here is to ensure that pg_config.h
+ * is included before any system headers such as <stdio.h>; without that,
+ * we have portability issues on some platforms due to variation in
+ * largefile options across different modules in the backend.
+ *
+ * NOTE: this file should not be included into any non-snowball sources!
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ *
+ * src/include/snowball/header.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SNOWBALL_HEADR_H
+#define SNOWBALL_HEADR_H
+
+/*
+ * It's against Postgres coding conventions to include postgres.h in a
+ * header file, but we allow the violation here because the alternative is
+ * to modify the machine-generated .c files provided by the Snowball project.
+ */
+#include "postgres.h"
+
+/* Some platforms define MAXINT and/or MININT, causing conflicts */
+#ifdef MAXINT
+#undef MAXINT
+#endif
+#ifdef MININT
+#undef MININT
+#endif
+
+/* Now we can include the original Snowball header.h */
+#include "snowball/libstemmer/header.h" /* pgrminclude ignore */
+
+/*
+ * Redefine standard memory allocation interface to pgsql's one.
+ * This allows us to control where the Snowball code allocates stuff.
+ */
+#ifdef malloc
+#undef malloc
+#endif
+#define malloc(a) palloc(a)
+
+#ifdef calloc
+#undef calloc
+#endif
+#define calloc(a,b) palloc0((a) * (b))
+
+#ifdef realloc
+#undef realloc
+#endif
+#define realloc(a,b) repalloc(a,b)
+
+#ifdef free
+#undef free
+#endif
+#define free(a) pfree(a)
+
+#endif /* SNOWBALL_HEADR_H */
diff --git a/src/include/snowball/libstemmer/api.h b/src/include/snowball/libstemmer/api.h
new file mode 100644
index 0000000..7ed7995
--- /dev/null
+++ b/src/include/snowball/libstemmer/api.h
@@ -0,0 +1,33 @@
+
+typedef unsigned char symbol;
+
+/* Or replace 'char' above with 'short' for 16 bit characters.
+
+ More precisely, replace 'char' with whatever type guarantees the
+ character width you need. Note however that sizeof(symbol) should divide
+ HEAD, defined in header.h as 2*sizeof(int), without remainder, otherwise
+ there is an alignment problem. In the unlikely event of a problem here,
+ consult Martin Porter.
+
+*/
+
+struct SN_env {
+ symbol * p;
+ int c; int l; int lb; int bra; int ket;
+ symbol * * S;
+ int * I;
+ unsigned char * B;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * SN_create_env(int S_size, int I_size, int B_size);
+extern void SN_close_env(struct SN_env * z, int S_size);
+
+extern int SN_set_current(struct SN_env * z, int size, const symbol * s);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/include/snowball/libstemmer/header.h b/src/include/snowball/libstemmer/header.h
new file mode 100644
index 0000000..6bccf0f
--- /dev/null
+++ b/src/include/snowball/libstemmer/header.h
@@ -0,0 +1,60 @@
+
+#include <limits.h>
+
+#include "api.h"
+
+#define MAXINT INT_MAX
+#define MININT INT_MIN
+
+#define HEAD 2*sizeof(int)
+
+#define SIZE(p) ((int *)(p))[-1]
+#define SET_SIZE(p, n) ((int *)(p))[-1] = n
+#define CAPACITY(p) ((int *)(p))[-2]
+
+struct among
+{ int s_size; /* number of chars in string */
+ const symbol * s; /* search string */
+ int substring_i;/* index to longest matching substring */
+ int result; /* result of the lookup */
+ int (* function)(struct SN_env *);
+};
+
+extern symbol * create_s(void);
+extern void lose_s(symbol * p);
+
+extern int skip_utf8(const symbol * p, int c, int lb, int l, int n);
+
+extern int in_grouping_U(struct SN_env * z, const unsigned char * s, int min, int max, int repeat);
+extern int in_grouping_b_U(struct SN_env * z, const unsigned char * s, int min, int max, int repeat);
+extern int out_grouping_U(struct SN_env * z, const unsigned char * s, int min, int max, int repeat);
+extern int out_grouping_b_U(struct SN_env * z, const unsigned char * s, int min, int max, int repeat);
+
+extern int in_grouping(struct SN_env * z, const unsigned char * s, int min, int max, int repeat);
+extern int in_grouping_b(struct SN_env * z, const unsigned char * s, int min, int max, int repeat);
+extern int out_grouping(struct SN_env * z, const unsigned char * s, int min, int max, int repeat);
+extern int out_grouping_b(struct SN_env * z, const unsigned char * s, int min, int max, int repeat);
+
+extern int eq_s(struct SN_env * z, int s_size, const symbol * s);
+extern int eq_s_b(struct SN_env * z, int s_size, const symbol * s);
+extern int eq_v(struct SN_env * z, const symbol * p);
+extern int eq_v_b(struct SN_env * z, const symbol * p);
+
+extern int find_among(struct SN_env * z, const struct among * v, int v_size);
+extern int find_among_b(struct SN_env * z, const struct among * v, int v_size);
+
+extern int replace_s(struct SN_env * z, int c_bra, int c_ket, int s_size, const symbol * s, int * adjustment);
+extern int slice_from_s(struct SN_env * z, int s_size, const symbol * s);
+extern int slice_from_v(struct SN_env * z, const symbol * p);
+extern int slice_del(struct SN_env * z);
+
+extern int insert_s(struct SN_env * z, int bra, int ket, int s_size, const symbol * s);
+extern int insert_v(struct SN_env * z, int bra, int ket, const symbol * p);
+
+extern symbol * slice_to(struct SN_env * z, symbol * p);
+extern symbol * assign_to(struct SN_env * z, symbol * p);
+
+extern int len_utf8(const symbol * p);
+
+extern void debug(struct SN_env * z, int number, int line_count);
+
diff --git a/src/include/snowball/libstemmer/stem_ISO_8859_1_danish.h b/src/include/snowball/libstemmer/stem_ISO_8859_1_danish.h
new file mode 100644
index 0000000..57f16f8
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_ISO_8859_1_danish.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * danish_ISO_8859_1_create_env(void);
+extern void danish_ISO_8859_1_close_env(struct SN_env * z);
+
+extern int danish_ISO_8859_1_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_ISO_8859_1_dutch.h b/src/include/snowball/libstemmer/stem_ISO_8859_1_dutch.h
new file mode 100644
index 0000000..5423842
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_ISO_8859_1_dutch.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * dutch_ISO_8859_1_create_env(void);
+extern void dutch_ISO_8859_1_close_env(struct SN_env * z);
+
+extern int dutch_ISO_8859_1_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_ISO_8859_1_english.h b/src/include/snowball/libstemmer/stem_ISO_8859_1_english.h
new file mode 100644
index 0000000..d5a56a9
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_ISO_8859_1_english.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * english_ISO_8859_1_create_env(void);
+extern void english_ISO_8859_1_close_env(struct SN_env * z);
+
+extern int english_ISO_8859_1_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_ISO_8859_1_finnish.h b/src/include/snowball/libstemmer/stem_ISO_8859_1_finnish.h
new file mode 100644
index 0000000..ba197d8
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_ISO_8859_1_finnish.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * finnish_ISO_8859_1_create_env(void);
+extern void finnish_ISO_8859_1_close_env(struct SN_env * z);
+
+extern int finnish_ISO_8859_1_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_ISO_8859_1_french.h b/src/include/snowball/libstemmer/stem_ISO_8859_1_french.h
new file mode 100644
index 0000000..2932102
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_ISO_8859_1_french.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * french_ISO_8859_1_create_env(void);
+extern void french_ISO_8859_1_close_env(struct SN_env * z);
+
+extern int french_ISO_8859_1_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_ISO_8859_1_german.h b/src/include/snowball/libstemmer/stem_ISO_8859_1_german.h
new file mode 100644
index 0000000..0887ac8
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_ISO_8859_1_german.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * german_ISO_8859_1_create_env(void);
+extern void german_ISO_8859_1_close_env(struct SN_env * z);
+
+extern int german_ISO_8859_1_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_ISO_8859_1_indonesian.h b/src/include/snowball/libstemmer/stem_ISO_8859_1_indonesian.h
new file mode 100644
index 0000000..aac192c
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_ISO_8859_1_indonesian.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * indonesian_ISO_8859_1_create_env(void);
+extern void indonesian_ISO_8859_1_close_env(struct SN_env * z);
+
+extern int indonesian_ISO_8859_1_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_ISO_8859_1_irish.h b/src/include/snowball/libstemmer/stem_ISO_8859_1_irish.h
new file mode 100644
index 0000000..0e14637
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_ISO_8859_1_irish.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * irish_ISO_8859_1_create_env(void);
+extern void irish_ISO_8859_1_close_env(struct SN_env * z);
+
+extern int irish_ISO_8859_1_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_ISO_8859_1_italian.h b/src/include/snowball/libstemmer/stem_ISO_8859_1_italian.h
new file mode 100644
index 0000000..9e3fcf7
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_ISO_8859_1_italian.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * italian_ISO_8859_1_create_env(void);
+extern void italian_ISO_8859_1_close_env(struct SN_env * z);
+
+extern int italian_ISO_8859_1_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_ISO_8859_1_norwegian.h b/src/include/snowball/libstemmer/stem_ISO_8859_1_norwegian.h
new file mode 100644
index 0000000..424c8cd
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_ISO_8859_1_norwegian.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * norwegian_ISO_8859_1_create_env(void);
+extern void norwegian_ISO_8859_1_close_env(struct SN_env * z);
+
+extern int norwegian_ISO_8859_1_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_ISO_8859_1_porter.h b/src/include/snowball/libstemmer/stem_ISO_8859_1_porter.h
new file mode 100644
index 0000000..99bc54f
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_ISO_8859_1_porter.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * porter_ISO_8859_1_create_env(void);
+extern void porter_ISO_8859_1_close_env(struct SN_env * z);
+
+extern int porter_ISO_8859_1_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_ISO_8859_1_portuguese.h b/src/include/snowball/libstemmer/stem_ISO_8859_1_portuguese.h
new file mode 100644
index 0000000..e9abc0d
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_ISO_8859_1_portuguese.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * portuguese_ISO_8859_1_create_env(void);
+extern void portuguese_ISO_8859_1_close_env(struct SN_env * z);
+
+extern int portuguese_ISO_8859_1_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_ISO_8859_1_spanish.h b/src/include/snowball/libstemmer/stem_ISO_8859_1_spanish.h
new file mode 100644
index 0000000..1e661aa
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_ISO_8859_1_spanish.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * spanish_ISO_8859_1_create_env(void);
+extern void spanish_ISO_8859_1_close_env(struct SN_env * z);
+
+extern int spanish_ISO_8859_1_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_ISO_8859_1_swedish.h b/src/include/snowball/libstemmer/stem_ISO_8859_1_swedish.h
new file mode 100644
index 0000000..5e6f6ac
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_ISO_8859_1_swedish.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * swedish_ISO_8859_1_create_env(void);
+extern void swedish_ISO_8859_1_close_env(struct SN_env * z);
+
+extern int swedish_ISO_8859_1_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_ISO_8859_2_hungarian.h b/src/include/snowball/libstemmer/stem_ISO_8859_2_hungarian.h
new file mode 100644
index 0000000..c019a7d
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_ISO_8859_2_hungarian.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * hungarian_ISO_8859_2_create_env(void);
+extern void hungarian_ISO_8859_2_close_env(struct SN_env * z);
+
+extern int hungarian_ISO_8859_2_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_ISO_8859_2_romanian.h b/src/include/snowball/libstemmer/stem_ISO_8859_2_romanian.h
new file mode 100644
index 0000000..ef9bd3f
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_ISO_8859_2_romanian.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * romanian_ISO_8859_2_create_env(void);
+extern void romanian_ISO_8859_2_close_env(struct SN_env * z);
+
+extern int romanian_ISO_8859_2_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_KOI8_R_russian.h b/src/include/snowball/libstemmer/stem_KOI8_R_russian.h
new file mode 100644
index 0000000..cc58324
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_KOI8_R_russian.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * russian_KOI8_R_create_env(void);
+extern void russian_KOI8_R_close_env(struct SN_env * z);
+
+extern int russian_KOI8_R_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_arabic.h b/src/include/snowball/libstemmer/stem_UTF_8_arabic.h
new file mode 100644
index 0000000..5ef61a1
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_arabic.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * arabic_UTF_8_create_env(void);
+extern void arabic_UTF_8_close_env(struct SN_env * z);
+
+extern int arabic_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_danish.h b/src/include/snowball/libstemmer/stem_UTF_8_danish.h
new file mode 100644
index 0000000..71f9315
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_danish.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * danish_UTF_8_create_env(void);
+extern void danish_UTF_8_close_env(struct SN_env * z);
+
+extern int danish_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_dutch.h b/src/include/snowball/libstemmer/stem_UTF_8_dutch.h
new file mode 100644
index 0000000..6af7d0a
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_dutch.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * dutch_UTF_8_create_env(void);
+extern void dutch_UTF_8_close_env(struct SN_env * z);
+
+extern int dutch_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_english.h b/src/include/snowball/libstemmer/stem_UTF_8_english.h
new file mode 100644
index 0000000..d0ea10e
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_english.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * english_UTF_8_create_env(void);
+extern void english_UTF_8_close_env(struct SN_env * z);
+
+extern int english_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_finnish.h b/src/include/snowball/libstemmer/stem_UTF_8_finnish.h
new file mode 100644
index 0000000..7d07fba
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_finnish.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * finnish_UTF_8_create_env(void);
+extern void finnish_UTF_8_close_env(struct SN_env * z);
+
+extern int finnish_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_french.h b/src/include/snowball/libstemmer/stem_UTF_8_french.h
new file mode 100644
index 0000000..b19139e
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_french.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * french_UTF_8_create_env(void);
+extern void french_UTF_8_close_env(struct SN_env * z);
+
+extern int french_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_german.h b/src/include/snowball/libstemmer/stem_UTF_8_german.h
new file mode 100644
index 0000000..2a95132
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_german.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * german_UTF_8_create_env(void);
+extern void german_UTF_8_close_env(struct SN_env * z);
+
+extern int german_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_greek.h b/src/include/snowball/libstemmer/stem_UTF_8_greek.h
new file mode 100644
index 0000000..bf1cc6c
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_greek.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * greek_UTF_8_create_env(void);
+extern void greek_UTF_8_close_env(struct SN_env * z);
+
+extern int greek_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_hungarian.h b/src/include/snowball/libstemmer/stem_UTF_8_hungarian.h
new file mode 100644
index 0000000..d662a83
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_hungarian.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * hungarian_UTF_8_create_env(void);
+extern void hungarian_UTF_8_close_env(struct SN_env * z);
+
+extern int hungarian_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_indonesian.h b/src/include/snowball/libstemmer/stem_UTF_8_indonesian.h
new file mode 100644
index 0000000..7e07e73
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_indonesian.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * indonesian_UTF_8_create_env(void);
+extern void indonesian_UTF_8_close_env(struct SN_env * z);
+
+extern int indonesian_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_irish.h b/src/include/snowball/libstemmer/stem_UTF_8_irish.h
new file mode 100644
index 0000000..ea8b818
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_irish.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * irish_UTF_8_create_env(void);
+extern void irish_UTF_8_close_env(struct SN_env * z);
+
+extern int irish_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_italian.h b/src/include/snowball/libstemmer/stem_UTF_8_italian.h
new file mode 100644
index 0000000..4177c3e
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_italian.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * italian_UTF_8_create_env(void);
+extern void italian_UTF_8_close_env(struct SN_env * z);
+
+extern int italian_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_lithuanian.h b/src/include/snowball/libstemmer/stem_UTF_8_lithuanian.h
new file mode 100644
index 0000000..8a9b124
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_lithuanian.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * lithuanian_UTF_8_create_env(void);
+extern void lithuanian_UTF_8_close_env(struct SN_env * z);
+
+extern int lithuanian_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_nepali.h b/src/include/snowball/libstemmer/stem_UTF_8_nepali.h
new file mode 100644
index 0000000..20b2b91
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_nepali.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * nepali_UTF_8_create_env(void);
+extern void nepali_UTF_8_close_env(struct SN_env * z);
+
+extern int nepali_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_norwegian.h b/src/include/snowball/libstemmer/stem_UTF_8_norwegian.h
new file mode 100644
index 0000000..b155ebb
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_norwegian.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * norwegian_UTF_8_create_env(void);
+extern void norwegian_UTF_8_close_env(struct SN_env * z);
+
+extern int norwegian_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_porter.h b/src/include/snowball/libstemmer/stem_UTF_8_porter.h
new file mode 100644
index 0000000..54efb6f
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_porter.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * porter_UTF_8_create_env(void);
+extern void porter_UTF_8_close_env(struct SN_env * z);
+
+extern int porter_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_portuguese.h b/src/include/snowball/libstemmer/stem_UTF_8_portuguese.h
new file mode 100644
index 0000000..68dc255
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_portuguese.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * portuguese_UTF_8_create_env(void);
+extern void portuguese_UTF_8_close_env(struct SN_env * z);
+
+extern int portuguese_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_romanian.h b/src/include/snowball/libstemmer/stem_UTF_8_romanian.h
new file mode 100644
index 0000000..2cc1ad0
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_romanian.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * romanian_UTF_8_create_env(void);
+extern void romanian_UTF_8_close_env(struct SN_env * z);
+
+extern int romanian_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_russian.h b/src/include/snowball/libstemmer/stem_UTF_8_russian.h
new file mode 100644
index 0000000..2bc621b
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_russian.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * russian_UTF_8_create_env(void);
+extern void russian_UTF_8_close_env(struct SN_env * z);
+
+extern int russian_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_spanish.h b/src/include/snowball/libstemmer/stem_UTF_8_spanish.h
new file mode 100644
index 0000000..075ba87
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_spanish.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * spanish_UTF_8_create_env(void);
+extern void spanish_UTF_8_close_env(struct SN_env * z);
+
+extern int spanish_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_swedish.h b/src/include/snowball/libstemmer/stem_UTF_8_swedish.h
new file mode 100644
index 0000000..095623d
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_swedish.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * swedish_UTF_8_create_env(void);
+extern void swedish_UTF_8_close_env(struct SN_env * z);
+
+extern int swedish_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_tamil.h b/src/include/snowball/libstemmer/stem_UTF_8_tamil.h
new file mode 100644
index 0000000..65505dc
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_tamil.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * tamil_UTF_8_create_env(void);
+extern void tamil_UTF_8_close_env(struct SN_env * z);
+
+extern int tamil_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/snowball/libstemmer/stem_UTF_8_turkish.h b/src/include/snowball/libstemmer/stem_UTF_8_turkish.h
new file mode 100644
index 0000000..7d94a2f
--- /dev/null
+++ b/src/include/snowball/libstemmer/stem_UTF_8_turkish.h
@@ -0,0 +1,16 @@
+/* This file was generated automatically by the Snowball to ISO C compiler */
+/* http://snowballstem.org/ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct SN_env * turkish_UTF_8_create_env(void);
+extern void turkish_UTF_8_close_env(struct SN_env * z);
+
+extern int turkish_UTF_8_stem(struct SN_env * z);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/include/statistics/extended_stats_internal.h b/src/include/statistics/extended_stats_internal.h
new file mode 100644
index 0000000..61e6969
--- /dev/null
+++ b/src/include/statistics/extended_stats_internal.h
@@ -0,0 +1,112 @@
+/*-------------------------------------------------------------------------
+ *
+ * extended_stats_internal.h
+ * POSTGRES extended statistics internal declarations
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/statistics/extended_stats_internal.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef EXTENDED_STATS_INTERNAL_H
+#define EXTENDED_STATS_INTERNAL_H
+
+#include "statistics/statistics.h"
+#include "utils/sortsupport.h"
+
+typedef struct
+{
+ Oid eqopr; /* '=' operator for datatype, if any */
+ Oid eqfunc; /* and associated function */
+ Oid ltopr; /* '<' operator for datatype, if any */
+} StdAnalyzeData;
+
+typedef struct
+{
+ Datum value; /* a data value */
+ int tupno; /* position index for tuple it came from */
+} ScalarItem;
+
+/* (de)serialization info */
+typedef struct DimensionInfo
+{
+ int nvalues; /* number of deduplicated values */
+ int nbytes; /* number of bytes (serialized) */
+ int nbytes_aligned; /* size of deserialized data with alignment */
+ int typlen; /* pg_type.typlen */
+ bool typbyval; /* pg_type.typbyval */
+} DimensionInfo;
+
+/* multi-sort */
+typedef struct MultiSortSupportData
+{
+ int ndims; /* number of dimensions */
+ /* sort support data for each dimension: */
+ SortSupportData ssup[FLEXIBLE_ARRAY_MEMBER];
+} MultiSortSupportData;
+
+typedef MultiSortSupportData *MultiSortSupport;
+
+typedef struct SortItem
+{
+ Datum *values;
+ bool *isnull;
+ int count;
+} SortItem;
+
+extern MVNDistinct *statext_ndistinct_build(double totalrows,
+ int numrows, HeapTuple *rows,
+ Bitmapset *attrs, VacAttrStats **stats);
+extern bytea *statext_ndistinct_serialize(MVNDistinct *ndistinct);
+extern MVNDistinct *statext_ndistinct_deserialize(bytea *data);
+
+extern MVDependencies *statext_dependencies_build(int numrows, HeapTuple *rows,
+ Bitmapset *attrs, VacAttrStats **stats);
+extern bytea *statext_dependencies_serialize(MVDependencies *dependencies);
+extern MVDependencies *statext_dependencies_deserialize(bytea *data);
+
+extern MCVList *statext_mcv_build(int numrows, HeapTuple *rows,
+ Bitmapset *attrs, VacAttrStats **stats,
+ double totalrows, int stattarget);
+extern bytea *statext_mcv_serialize(MCVList *mcv, VacAttrStats **stats);
+extern MCVList *statext_mcv_deserialize(bytea *data);
+
+extern MultiSortSupport multi_sort_init(int ndims);
+extern void multi_sort_add_dimension(MultiSortSupport mss, int sortdim,
+ Oid oper, Oid collation);
+extern int multi_sort_compare(const void *a, const void *b, void *arg);
+extern int multi_sort_compare_dim(int dim, const SortItem *a,
+ const SortItem *b, MultiSortSupport mss);
+extern int multi_sort_compare_dims(int start, int end, const SortItem *a,
+ const SortItem *b, MultiSortSupport mss);
+extern int compare_scalars_simple(const void *a, const void *b, void *arg);
+extern int compare_datums_simple(Datum a, Datum b, SortSupport ssup);
+
+extern void *bsearch_arg(const void *key, const void *base,
+ size_t nmemb, size_t size,
+ int (*compar) (const void *, const void *, void *),
+ void *arg);
+
+extern AttrNumber *build_attnums_array(Bitmapset *attrs, int *numattrs);
+
+extern SortItem *build_sorted_items(int numrows, int *nitems, HeapTuple *rows,
+ TupleDesc tdesc, MultiSortSupport mss,
+ int numattrs, AttrNumber *attnums);
+
+extern bool examine_clause_args(List *args, Var **varp,
+ Const **cstp, bool *varonleftp);
+
+extern Selectivity mcv_clauselist_selectivity(PlannerInfo *root,
+ StatisticExtInfo *stat,
+ List *clauses,
+ int varRelid,
+ JoinType jointype,
+ SpecialJoinInfo *sjinfo,
+ RelOptInfo *rel,
+ Selectivity *basesel,
+ Selectivity *totalsel);
+
+#endif /* EXTENDED_STATS_INTERNAL_H */
diff --git a/src/include/statistics/statistics.h b/src/include/statistics/statistics.h
new file mode 100644
index 0000000..50fce49
--- /dev/null
+++ b/src/include/statistics/statistics.h
@@ -0,0 +1,125 @@
+/*-------------------------------------------------------------------------
+ *
+ * statistics.h
+ * Extended statistics and selectivity estimation functions.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/statistics/statistics.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef STATISTICS_H
+#define STATISTICS_H
+
+#include "commands/vacuum.h"
+#include "nodes/pathnodes.h"
+
+#define STATS_MAX_DIMENSIONS 8 /* max number of attributes */
+
+/* Multivariate distinct coefficients */
+#define STATS_NDISTINCT_MAGIC 0xA352BFA4 /* struct identifier */
+#define STATS_NDISTINCT_TYPE_BASIC 1 /* struct version */
+
+/* MVNDistinctItem represents a single combination of columns */
+typedef struct MVNDistinctItem
+{
+ double ndistinct; /* ndistinct value for this combination */
+ Bitmapset *attrs; /* attr numbers of items */
+} MVNDistinctItem;
+
+/* A MVNDistinct object, comprising all possible combinations of columns */
+typedef struct MVNDistinct
+{
+ uint32 magic; /* magic constant marker */
+ uint32 type; /* type of ndistinct (BASIC) */
+ uint32 nitems; /* number of items in the statistic */
+ MVNDistinctItem items[FLEXIBLE_ARRAY_MEMBER];
+} MVNDistinct;
+
+/* Multivariate functional dependencies */
+#define STATS_DEPS_MAGIC 0xB4549A2C /* marks serialized bytea */
+#define STATS_DEPS_TYPE_BASIC 1 /* basic dependencies type */
+
+/*
+ * Functional dependencies, tracking column-level relationships (values
+ * in one column determine values in another one).
+ */
+typedef struct MVDependency
+{
+ double degree; /* degree of validity (0-1) */
+ AttrNumber nattributes; /* number of attributes */
+ AttrNumber attributes[FLEXIBLE_ARRAY_MEMBER]; /* attribute numbers */
+} MVDependency;
+
+typedef struct MVDependencies
+{
+ uint32 magic; /* magic constant marker */
+ uint32 type; /* type of MV Dependencies (BASIC) */
+ uint32 ndeps; /* number of dependencies */
+ MVDependency *deps[FLEXIBLE_ARRAY_MEMBER]; /* dependencies */
+} MVDependencies;
+
+/* used to flag stats serialized to bytea */
+#define STATS_MCV_MAGIC 0xE1A651C2 /* marks serialized bytea */
+#define STATS_MCV_TYPE_BASIC 1 /* basic MCV list type */
+
+/* max items in MCV list (should be equal to max default_statistics_target) */
+#define STATS_MCVLIST_MAX_ITEMS 10000
+
+/*
+ * Multivariate MCV (most-common value) lists
+ *
+ * A straightforward extension of MCV items - i.e. a list (array) of
+ * combinations of attribute values, together with a frequency and null flags.
+ */
+typedef struct MCVItem
+{
+ double frequency; /* frequency of this combination */
+ double base_frequency; /* frequency if independent */
+ bool *isnull; /* NULL flags */
+ Datum *values; /* item values */
+} MCVItem;
+
+/* multivariate MCV list - essentially an array of MCV items */
+typedef struct MCVList
+{
+ uint32 magic; /* magic constant marker */
+ uint32 type; /* type of MCV list (BASIC) */
+ uint32 nitems; /* number of MCV items in the array */
+ AttrNumber ndimensions; /* number of dimensions */
+ Oid types[STATS_MAX_DIMENSIONS]; /* OIDs of data types */
+ MCVItem items[FLEXIBLE_ARRAY_MEMBER]; /* array of MCV items */
+} MCVList;
+
+extern MVNDistinct *statext_ndistinct_load(Oid mvoid);
+extern MVDependencies *statext_dependencies_load(Oid mvoid);
+extern MCVList *statext_mcv_load(Oid mvoid);
+
+extern void BuildRelationExtStatistics(Relation onerel, double totalrows,
+ int numrows, HeapTuple *rows,
+ int natts, VacAttrStats **vacattrstats);
+extern int ComputeExtStatisticsRows(Relation onerel,
+ int natts, VacAttrStats **stats);
+extern bool statext_is_kind_built(HeapTuple htup, char kind);
+extern Selectivity dependencies_clauselist_selectivity(PlannerInfo *root,
+ List *clauses,
+ int varRelid,
+ JoinType jointype,
+ SpecialJoinInfo *sjinfo,
+ RelOptInfo *rel,
+ Bitmapset **estimatedclauses);
+extern Selectivity statext_clauselist_selectivity(PlannerInfo *root,
+ List *clauses,
+ int varRelid,
+ JoinType jointype,
+ SpecialJoinInfo *sjinfo,
+ RelOptInfo *rel,
+ Bitmapset **estimatedclauses);
+extern bool has_stats_of_kind(List *stats, char requiredkind);
+extern StatisticExtInfo *choose_best_statistics(List *stats, char requiredkind,
+ Bitmapset **clause_attnums,
+ int nclauses);
+
+#endif /* STATISTICS_H */
diff --git a/src/include/storage/.gitignore b/src/include/storage/.gitignore
new file mode 100644
index 0000000..209c8be
--- /dev/null
+++ b/src/include/storage/.gitignore
@@ -0,0 +1 @@
+/lwlocknames.h
diff --git a/src/include/storage/backendid.h b/src/include/storage/backendid.h
new file mode 100644
index 0000000..0c776a3
--- /dev/null
+++ b/src/include/storage/backendid.h
@@ -0,0 +1,37 @@
+/*-------------------------------------------------------------------------
+ *
+ * backendid.h
+ * POSTGRES backend id communication definitions
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/backendid.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BACKENDID_H
+#define BACKENDID_H
+
+/* ----------------
+ * -cim 8/17/90
+ * ----------------
+ */
+typedef int BackendId; /* unique currently active backend identifier */
+
+#define InvalidBackendId (-1)
+
+extern PGDLLIMPORT BackendId MyBackendId; /* backend id of this backend */
+
+/* backend id of our parallel session leader, or InvalidBackendId if none */
+extern PGDLLIMPORT BackendId ParallelMasterBackendId;
+
+/*
+ * The BackendId to use for our session's temp relations is normally our own,
+ * but parallel workers should use their leader's ID.
+ */
+#define BackendIdForTempRelations() \
+ (ParallelMasterBackendId == InvalidBackendId ? MyBackendId : ParallelMasterBackendId)
+
+#endif /* BACKENDID_H */
diff --git a/src/include/storage/barrier.h b/src/include/storage/barrier.h
new file mode 100644
index 0000000..d71927c
--- /dev/null
+++ b/src/include/storage/barrier.h
@@ -0,0 +1,45 @@
+/*-------------------------------------------------------------------------
+ *
+ * barrier.h
+ * Barriers for synchronizing cooperating processes.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/barrier.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BARRIER_H
+#define BARRIER_H
+
+/*
+ * For the header previously known as "barrier.h", please include
+ * "port/atomics.h", which deals with atomics, compiler barriers and memory
+ * barriers.
+ */
+
+#include "storage/condition_variable.h"
+#include "storage/spin.h"
+
+typedef struct Barrier
+{
+ slock_t mutex;
+ int phase; /* phase counter */
+ int participants; /* the number of participants attached */
+ int arrived; /* the number of participants that have
+ * arrived */
+ int elected; /* highest phase elected */
+ bool static_party; /* used only for assertions */
+ ConditionVariable condition_variable;
+} Barrier;
+
+extern void BarrierInit(Barrier *barrier, int num_workers);
+extern bool BarrierArriveAndWait(Barrier *barrier, uint32 wait_event_info);
+extern bool BarrierArriveAndDetach(Barrier *barrier);
+extern int BarrierAttach(Barrier *barrier);
+extern bool BarrierDetach(Barrier *barrier);
+extern int BarrierPhase(Barrier *barrier);
+extern int BarrierParticipants(Barrier *barrier);
+
+#endif /* BARRIER_H */
diff --git a/src/include/storage/block.h b/src/include/storage/block.h
new file mode 100644
index 0000000..d73e393
--- /dev/null
+++ b/src/include/storage/block.h
@@ -0,0 +1,121 @@
+/*-------------------------------------------------------------------------
+ *
+ * block.h
+ * POSTGRES disk block definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/block.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BLOCK_H
+#define BLOCK_H
+
+/*
+ * BlockNumber:
+ *
+ * each data file (heap or index) is divided into postgres disk blocks
+ * (which may be thought of as the unit of i/o -- a postgres buffer
+ * contains exactly one disk block). the blocks are numbered
+ * sequentially, 0 to 0xFFFFFFFE.
+ *
+ * InvalidBlockNumber is the same thing as P_NEW in bufmgr.h.
+ *
+ * the access methods, the buffer manager and the storage manager are
+ * more or less the only pieces of code that should be accessing disk
+ * blocks directly.
+ */
+typedef uint32 BlockNumber;
+
+#define InvalidBlockNumber ((BlockNumber) 0xFFFFFFFF)
+
+#define MaxBlockNumber ((BlockNumber) 0xFFFFFFFE)
+
+/*
+ * BlockId:
+ *
+ * this is a storage type for BlockNumber. in other words, this type
+ * is used for on-disk structures (e.g., in HeapTupleData) whereas
+ * BlockNumber is the type on which calculations are performed (e.g.,
+ * in access method code).
+ *
+ * there doesn't appear to be any reason to have separate types except
+ * for the fact that BlockIds can be SHORTALIGN'd (and therefore any
+ * structures that contains them, such as ItemPointerData, can also be
+ * SHORTALIGN'd). this is an important consideration for reducing the
+ * space requirements of the line pointer (ItemIdData) array on each
+ * page and the header of each heap or index tuple, so it doesn't seem
+ * wise to change this without good reason.
+ */
+typedef struct BlockIdData
+{
+ uint16 bi_hi;
+ uint16 bi_lo;
+} BlockIdData;
+
+typedef BlockIdData *BlockId; /* block identifier */
+
+/* ----------------
+ * support macros
+ * ----------------
+ */
+
+/*
+ * BlockNumberIsValid
+ * True iff blockNumber is valid.
+ */
+#define BlockNumberIsValid(blockNumber) \
+ ((bool) ((BlockNumber) (blockNumber) != InvalidBlockNumber))
+
+/*
+ * BlockIdIsValid
+ * True iff the block identifier is valid.
+ */
+#define BlockIdIsValid(blockId) \
+ ((bool) PointerIsValid(blockId))
+
+/*
+ * BlockIdSet
+ * Sets a block identifier to the specified value.
+ */
+#define BlockIdSet(blockId, blockNumber) \
+( \
+ AssertMacro(PointerIsValid(blockId)), \
+ (blockId)->bi_hi = (blockNumber) >> 16, \
+ (blockId)->bi_lo = (blockNumber) & 0xffff \
+)
+
+/*
+ * BlockIdCopy
+ * Copy a block identifier.
+ */
+#define BlockIdCopy(toBlockId, fromBlockId) \
+( \
+ AssertMacro(PointerIsValid(toBlockId)), \
+ AssertMacro(PointerIsValid(fromBlockId)), \
+ (toBlockId)->bi_hi = (fromBlockId)->bi_hi, \
+ (toBlockId)->bi_lo = (fromBlockId)->bi_lo \
+)
+
+/*
+ * BlockIdEquals
+ * Check for block number equality.
+ */
+#define BlockIdEquals(blockId1, blockId2) \
+ ((blockId1)->bi_hi == (blockId2)->bi_hi && \
+ (blockId1)->bi_lo == (blockId2)->bi_lo)
+
+/*
+ * BlockIdGetBlockNumber
+ * Retrieve the block number from a block identifier.
+ */
+#define BlockIdGetBlockNumber(blockId) \
+( \
+ AssertMacro(BlockIdIsValid(blockId)), \
+ (BlockNumber) (((blockId)->bi_hi << 16) | ((uint16) (blockId)->bi_lo)) \
+)
+
+#endif /* BLOCK_H */
diff --git a/src/include/storage/buf.h b/src/include/storage/buf.h
new file mode 100644
index 0000000..dde87f8
--- /dev/null
+++ b/src/include/storage/buf.h
@@ -0,0 +1,46 @@
+/*-------------------------------------------------------------------------
+ *
+ * buf.h
+ * Basic buffer manager data types.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/buf.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BUF_H
+#define BUF_H
+
+/*
+ * Buffer identifiers.
+ *
+ * Zero is invalid, positive is the index of a shared buffer (1..NBuffers),
+ * negative is the index of a local buffer (-1 .. -NLocBuffer).
+ */
+typedef int Buffer;
+
+#define InvalidBuffer 0
+
+/*
+ * BufferIsInvalid
+ * True iff the buffer is invalid.
+ */
+#define BufferIsInvalid(buffer) ((buffer) == InvalidBuffer)
+
+/*
+ * BufferIsLocal
+ * True iff the buffer is local (not visible to other backends).
+ */
+#define BufferIsLocal(buffer) ((buffer) < 0)
+
+/*
+ * Buffer access strategy objects.
+ *
+ * BufferAccessStrategyData is private to freelist.c
+ */
+typedef struct BufferAccessStrategyData *BufferAccessStrategy;
+
+#endif /* BUF_H */
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
new file mode 100644
index 0000000..3377fa5
--- /dev/null
+++ b/src/include/storage/buf_internals.h
@@ -0,0 +1,341 @@
+/*-------------------------------------------------------------------------
+ *
+ * buf_internals.h
+ * Internal definitions for buffer manager and the buffer replacement
+ * strategy.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/buf_internals.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BUFMGR_INTERNALS_H
+#define BUFMGR_INTERNALS_H
+
+#include "port/atomics.h"
+#include "storage/buf.h"
+#include "storage/bufmgr.h"
+#include "storage/latch.h"
+#include "storage/lwlock.h"
+#include "storage/shmem.h"
+#include "storage/smgr.h"
+#include "storage/spin.h"
+#include "utils/relcache.h"
+
+/*
+ * Buffer state is a single 32-bit variable where following data is combined.
+ *
+ * - 18 bits refcount
+ * - 4 bits usage count
+ * - 10 bits of flags
+ *
+ * Combining these values allows to perform some operations without locking
+ * the buffer header, by modifying them together with a CAS loop.
+ *
+ * The definition of buffer state components is below.
+ */
+#define BUF_REFCOUNT_ONE 1
+#define BUF_REFCOUNT_MASK ((1U << 18) - 1)
+#define BUF_USAGECOUNT_MASK 0x003C0000U
+#define BUF_USAGECOUNT_ONE (1U << 18)
+#define BUF_USAGECOUNT_SHIFT 18
+#define BUF_FLAG_MASK 0xFFC00000U
+
+/* Get refcount and usagecount from buffer state */
+#define BUF_STATE_GET_REFCOUNT(state) ((state) & BUF_REFCOUNT_MASK)
+#define BUF_STATE_GET_USAGECOUNT(state) (((state) & BUF_USAGECOUNT_MASK) >> BUF_USAGECOUNT_SHIFT)
+
+/*
+ * Flags for buffer descriptors
+ *
+ * Note: BM_TAG_VALID essentially means that there is a buffer hashtable
+ * entry associated with the buffer's tag.
+ */
+#define BM_LOCKED (1U << 22) /* buffer header is locked */
+#define BM_DIRTY (1U << 23) /* data needs writing */
+#define BM_VALID (1U << 24) /* data is valid */
+#define BM_TAG_VALID (1U << 25) /* tag is assigned */
+#define BM_IO_IN_PROGRESS (1U << 26) /* read or write in progress */
+#define BM_IO_ERROR (1U << 27) /* previous I/O failed */
+#define BM_JUST_DIRTIED (1U << 28) /* dirtied since write started */
+#define BM_PIN_COUNT_WAITER (1U << 29) /* have waiter for sole pin */
+#define BM_CHECKPOINT_NEEDED (1U << 30) /* must write for checkpoint */
+#define BM_PERMANENT (1U << 31) /* permanent buffer (not unlogged,
+ * or init fork) */
+/*
+ * The maximum allowed value of usage_count represents a tradeoff between
+ * accuracy and speed of the clock-sweep buffer management algorithm. A
+ * large value (comparable to NBuffers) would approximate LRU semantics.
+ * But it can take as many as BM_MAX_USAGE_COUNT+1 complete cycles of
+ * clock sweeps to find a free buffer, so in practice we don't want the
+ * value to be very large.
+ */
+#define BM_MAX_USAGE_COUNT 5
+
+/*
+ * Buffer tag identifies which disk block the buffer contains.
+ *
+ * Note: the BufferTag data must be sufficient to determine where to write the
+ * block, without reference to pg_class or pg_tablespace entries. It's
+ * possible that the backend flushing the buffer doesn't even believe the
+ * relation is visible yet (its xact may have started before the xact that
+ * created the rel). The storage manager must be able to cope anyway.
+ *
+ * Note: if there's any pad bytes in the struct, INIT_BUFFERTAG will have
+ * to be fixed to zero them, since this struct is used as a hash key.
+ */
+typedef struct buftag
+{
+ RelFileNode rnode; /* physical relation identifier */
+ ForkNumber forkNum;
+ BlockNumber blockNum; /* blknum relative to begin of reln */
+} BufferTag;
+
+#define CLEAR_BUFFERTAG(a) \
+( \
+ (a).rnode.spcNode = InvalidOid, \
+ (a).rnode.dbNode = InvalidOid, \
+ (a).rnode.relNode = InvalidOid, \
+ (a).forkNum = InvalidForkNumber, \
+ (a).blockNum = InvalidBlockNumber \
+)
+
+#define INIT_BUFFERTAG(a,xx_rnode,xx_forkNum,xx_blockNum) \
+( \
+ (a).rnode = (xx_rnode), \
+ (a).forkNum = (xx_forkNum), \
+ (a).blockNum = (xx_blockNum) \
+)
+
+#define BUFFERTAGS_EQUAL(a,b) \
+( \
+ RelFileNodeEquals((a).rnode, (b).rnode) && \
+ (a).blockNum == (b).blockNum && \
+ (a).forkNum == (b).forkNum \
+)
+
+/*
+ * The shared buffer mapping table is partitioned to reduce contention.
+ * To determine which partition lock a given tag requires, compute the tag's
+ * hash code with BufTableHashCode(), then apply BufMappingPartitionLock().
+ * NB: NUM_BUFFER_PARTITIONS must be a power of 2!
+ */
+#define BufTableHashPartition(hashcode) \
+ ((hashcode) % NUM_BUFFER_PARTITIONS)
+#define BufMappingPartitionLock(hashcode) \
+ (&MainLWLockArray[BUFFER_MAPPING_LWLOCK_OFFSET + \
+ BufTableHashPartition(hashcode)].lock)
+#define BufMappingPartitionLockByIndex(i) \
+ (&MainLWLockArray[BUFFER_MAPPING_LWLOCK_OFFSET + (i)].lock)
+
+/*
+ * BufferDesc -- shared descriptor/state data for a single shared buffer.
+ *
+ * Note: Buffer header lock (BM_LOCKED flag) must be held to examine or change
+ * the tag, state or wait_backend_pid fields. In general, buffer header lock
+ * is a spinlock which is combined with flags, refcount and usagecount into
+ * single atomic variable. This layout allow us to do some operations in a
+ * single atomic operation, without actually acquiring and releasing spinlock;
+ * for instance, increase or decrease refcount. buf_id field never changes
+ * after initialization, so does not need locking. freeNext is protected by
+ * the buffer_strategy_lock not buffer header lock. The LWLock can take care
+ * of itself. The buffer header lock is *not* used to control access to the
+ * data in the buffer!
+ *
+ * It's assumed that nobody changes the state field while buffer header lock
+ * is held. Thus buffer header lock holder can do complex updates of the
+ * state variable in single write, simultaneously with lock release (cleaning
+ * BM_LOCKED flag). On the other hand, updating of state without holding
+ * buffer header lock is restricted to CAS, which insure that BM_LOCKED flag
+ * is not set. Atomic increment/decrement, OR/AND etc. are not allowed.
+ *
+ * An exception is that if we have the buffer pinned, its tag can't change
+ * underneath us, so we can examine the tag without locking the buffer header.
+ * Also, in places we do one-time reads of the flags without bothering to
+ * lock the buffer header; this is generally for situations where we don't
+ * expect the flag bit being tested to be changing.
+ *
+ * We can't physically remove items from a disk page if another backend has
+ * the buffer pinned. Hence, a backend may need to wait for all other pins
+ * to go away. This is signaled by storing its own PID into
+ * wait_backend_pid and setting flag bit BM_PIN_COUNT_WAITER. At present,
+ * there can be only one such waiter per buffer.
+ *
+ * We use this same struct for local buffer headers, but the locks are not
+ * used and not all of the flag bits are useful either. To avoid unnecessary
+ * overhead, manipulations of the state field should be done without actual
+ * atomic operations (i.e. only pg_atomic_read_u32() and
+ * pg_atomic_unlocked_write_u32()).
+ *
+ * Be careful to avoid increasing the size of the struct when adding or
+ * reordering members. Keeping it below 64 bytes (the most common CPU
+ * cache line size) is fairly important for performance.
+ */
+typedef struct BufferDesc
+{
+ BufferTag tag; /* ID of page contained in buffer */
+ int buf_id; /* buffer's index number (from 0) */
+
+ /* state of the tag, containing flags, refcount and usagecount */
+ pg_atomic_uint32 state;
+
+ int wait_backend_pid; /* backend PID of pin-count waiter */
+ int freeNext; /* link in freelist chain */
+
+ LWLock content_lock; /* to lock access to buffer contents */
+} BufferDesc;
+
+/*
+ * Concurrent access to buffer headers has proven to be more efficient if
+ * they're cache line aligned. So we force the start of the BufferDescriptors
+ * array to be on a cache line boundary and force the elements to be cache
+ * line sized.
+ *
+ * XXX: As this is primarily matters in highly concurrent workloads which
+ * probably all are 64bit these days, and the space wastage would be a bit
+ * more noticeable on 32bit systems, we don't force the stride to be cache
+ * line sized on those. If somebody does actual performance testing, we can
+ * reevaluate.
+ *
+ * Note that local buffer descriptors aren't forced to be aligned - as there's
+ * no concurrent access to those it's unlikely to be beneficial.
+ *
+ * We use a 64-byte cache line size here, because that's the most common
+ * size. Making it bigger would be a waste of memory. Even if running on a
+ * platform with either 32 or 128 byte line sizes, it's good to align to
+ * boundaries and avoid false sharing.
+ */
+#define BUFFERDESC_PAD_TO_SIZE (SIZEOF_VOID_P == 8 ? 64 : 1)
+
+typedef union BufferDescPadded
+{
+ BufferDesc bufferdesc;
+ char pad[BUFFERDESC_PAD_TO_SIZE];
+} BufferDescPadded;
+
+#define GetBufferDescriptor(id) (&BufferDescriptors[(id)].bufferdesc)
+#define GetLocalBufferDescriptor(id) (&LocalBufferDescriptors[(id)])
+
+#define BufferDescriptorGetBuffer(bdesc) ((bdesc)->buf_id + 1)
+
+#define BufferDescriptorGetIOLock(bdesc) \
+ (&(BufferIOLWLockArray[(bdesc)->buf_id]).lock)
+#define BufferDescriptorGetContentLock(bdesc) \
+ ((LWLock*) (&(bdesc)->content_lock))
+
+extern PGDLLIMPORT LWLockMinimallyPadded *BufferIOLWLockArray;
+
+/*
+ * The freeNext field is either the index of the next freelist entry,
+ * or one of these special values:
+ */
+#define FREENEXT_END_OF_LIST (-1)
+#define FREENEXT_NOT_IN_LIST (-2)
+
+/*
+ * Functions for acquiring/releasing a shared buffer header's spinlock. Do
+ * not apply these to local buffers!
+ */
+extern uint32 LockBufHdr(BufferDesc *desc);
+#define UnlockBufHdr(desc, s) \
+ do { \
+ pg_write_barrier(); \
+ pg_atomic_write_u32(&(desc)->state, (s) & (~BM_LOCKED)); \
+ } while (0)
+
+
+/*
+ * The PendingWriteback & WritebackContext structure are used to keep
+ * information about pending flush requests to be issued to the OS.
+ */
+typedef struct PendingWriteback
+{
+ /* could store different types of pending flushes here */
+ BufferTag tag;
+} PendingWriteback;
+
+/* struct forward declared in bufmgr.h */
+typedef struct WritebackContext
+{
+ /* pointer to the max number of writeback requests to coalesce */
+ int *max_pending;
+
+ /* current number of pending writeback requests */
+ int nr_pending;
+
+ /* pending requests */
+ PendingWriteback pending_writebacks[WRITEBACK_MAX_PENDING_FLUSHES];
+} WritebackContext;
+
+/* in buf_init.c */
+extern PGDLLIMPORT BufferDescPadded *BufferDescriptors;
+extern PGDLLIMPORT WritebackContext BackendWritebackContext;
+
+/* in localbuf.c */
+extern BufferDesc *LocalBufferDescriptors;
+
+/* in bufmgr.c */
+
+/*
+ * Structure to sort buffers per file on checkpoints.
+ *
+ * This structure is allocated per buffer in shared memory, so it should be
+ * kept as small as possible.
+ */
+typedef struct CkptSortItem
+{
+ Oid tsId;
+ Oid relNode;
+ ForkNumber forkNum;
+ BlockNumber blockNum;
+ int buf_id;
+} CkptSortItem;
+
+extern CkptSortItem *CkptBufferIds;
+
+/*
+ * Internal buffer management routines
+ */
+/* bufmgr.c */
+extern void WritebackContextInit(WritebackContext *context, int *max_pending);
+extern void IssuePendingWritebacks(WritebackContext *context);
+extern void ScheduleBufferTagForWriteback(WritebackContext *context, BufferTag *tag);
+
+/* freelist.c */
+extern BufferDesc *StrategyGetBuffer(BufferAccessStrategy strategy,
+ uint32 *buf_state);
+extern void StrategyFreeBuffer(BufferDesc *buf);
+extern bool StrategyRejectBuffer(BufferAccessStrategy strategy,
+ BufferDesc *buf);
+
+extern int StrategySyncStart(uint32 *complete_passes, uint32 *num_buf_alloc);
+extern void StrategyNotifyBgWriter(int bgwprocno);
+
+extern Size StrategyShmemSize(void);
+extern void StrategyInitialize(bool init);
+extern bool have_free_buffer(void);
+
+/* buf_table.c */
+extern Size BufTableShmemSize(int size);
+extern void InitBufTable(int size);
+extern uint32 BufTableHashCode(BufferTag *tagPtr);
+extern int BufTableLookup(BufferTag *tagPtr, uint32 hashcode);
+extern int BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id);
+extern void BufTableDelete(BufferTag *tagPtr, uint32 hashcode);
+
+/* localbuf.c */
+extern PrefetchBufferResult PrefetchLocalBuffer(SMgrRelation smgr,
+ ForkNumber forkNum,
+ BlockNumber blockNum);
+extern BufferDesc *LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum,
+ BlockNumber blockNum, bool *foundPtr);
+extern void MarkLocalBufferDirty(Buffer buffer);
+extern void DropRelFileNodeLocalBuffers(RelFileNode rnode, ForkNumber forkNum,
+ BlockNumber firstDelBlock);
+extern void DropRelFileNodeAllLocalBuffers(RelFileNode rnode);
+extern void AtEOXact_LocalBuffers(bool isCommit);
+
+#endif /* BUFMGR_INTERNALS_H */
diff --git a/src/include/storage/buffile.h b/src/include/storage/buffile.h
new file mode 100644
index 0000000..60433f3
--- /dev/null
+++ b/src/include/storage/buffile.h
@@ -0,0 +1,54 @@
+/*-------------------------------------------------------------------------
+ *
+ * buffile.h
+ * Management of large buffered temporary files.
+ *
+ * The BufFile routines provide a partial replacement for stdio atop
+ * virtual file descriptors managed by fd.c. Currently they only support
+ * buffered access to a virtual file, without any of stdio's formatting
+ * features. That's enough for immediate needs, but the set of facilities
+ * could be expanded if necessary.
+ *
+ * BufFile also supports working with temporary files that exceed the OS
+ * file size limit and/or the largest offset representable in an int.
+ * It might be better to split that out as a separately accessible module,
+ * but currently we have no need for oversize temp files without buffered
+ * access.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/buffile.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef BUFFILE_H
+#define BUFFILE_H
+
+#include "storage/sharedfileset.h"
+
+/* BufFile is an opaque type whose details are not known outside buffile.c. */
+
+typedef struct BufFile BufFile;
+
+/*
+ * prototypes for functions in buffile.c
+ */
+
+extern BufFile *BufFileCreateTemp(bool interXact);
+extern void BufFileClose(BufFile *file);
+extern size_t BufFileRead(BufFile *file, void *ptr, size_t size);
+extern size_t BufFileWrite(BufFile *file, void *ptr, size_t size);
+extern int BufFileSeek(BufFile *file, int fileno, off_t offset, int whence);
+extern void BufFileTell(BufFile *file, int *fileno, off_t *offset);
+extern int BufFileSeekBlock(BufFile *file, long blknum);
+extern int64 BufFileSize(BufFile *file);
+extern long BufFileAppend(BufFile *target, BufFile *source);
+
+extern BufFile *BufFileCreateShared(SharedFileSet *fileset, const char *name);
+extern void BufFileExportShared(BufFile *file);
+extern BufFile *BufFileOpenShared(SharedFileSet *fileset, const char *name);
+extern void BufFileDeleteShared(SharedFileSet *fileset, const char *name);
+
+#endif /* BUFFILE_H */
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
new file mode 100644
index 0000000..ee91b8f
--- /dev/null
+++ b/src/include/storage/bufmgr.h
@@ -0,0 +1,292 @@
+/*-------------------------------------------------------------------------
+ *
+ * bufmgr.h
+ * POSTGRES buffer manager definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/bufmgr.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BUFMGR_H
+#define BUFMGR_H
+
+#include "storage/block.h"
+#include "storage/buf.h"
+#include "storage/bufpage.h"
+#include "storage/relfilenode.h"
+#include "utils/relcache.h"
+#include "utils/snapmgr.h"
+
+typedef void *Block;
+
+/* Possible arguments for GetAccessStrategy() */
+typedef enum BufferAccessStrategyType
+{
+ BAS_NORMAL, /* Normal random access */
+ BAS_BULKREAD, /* Large read-only scan (hint bit updates are
+ * ok) */
+ BAS_BULKWRITE, /* Large multi-block write (e.g. COPY IN) */
+ BAS_VACUUM /* VACUUM */
+} BufferAccessStrategyType;
+
+/* Possible modes for ReadBufferExtended() */
+typedef enum
+{
+ RBM_NORMAL, /* Normal read */
+ RBM_ZERO_AND_LOCK, /* Don't read from disk, caller will
+ * initialize. Also locks the page. */
+ RBM_ZERO_AND_CLEANUP_LOCK, /* Like RBM_ZERO_AND_LOCK, but locks the page
+ * in "cleanup" mode */
+ RBM_ZERO_ON_ERROR, /* Read, but return an all-zeros page on error */
+ RBM_NORMAL_NO_LOG /* Don't log page as invalid during WAL
+ * replay; otherwise same as RBM_NORMAL */
+} ReadBufferMode;
+
+/*
+ * Type returned by PrefetchBuffer().
+ */
+typedef struct PrefetchBufferResult
+{
+ Buffer recent_buffer; /* If valid, a hit (recheck needed!) */
+ bool initiated_io; /* If true, a miss resulting in async I/O */
+} PrefetchBufferResult;
+
+/* forward declared, to avoid having to expose buf_internals.h here */
+struct WritebackContext;
+
+/* forward declared, to avoid including smgr.h here */
+struct SMgrRelationData;
+
+/* in globals.c ... this duplicates miscadmin.h */
+extern PGDLLIMPORT int NBuffers;
+
+/* in bufmgr.c */
+extern bool zero_damaged_pages;
+extern int bgwriter_lru_maxpages;
+extern double bgwriter_lru_multiplier;
+extern bool track_io_timing;
+extern int effective_io_concurrency;
+extern int maintenance_io_concurrency;
+
+extern int checkpoint_flush_after;
+extern int backend_flush_after;
+extern int bgwriter_flush_after;
+
+/* in buf_init.c */
+extern PGDLLIMPORT char *BufferBlocks;
+
+/* in localbuf.c */
+extern PGDLLIMPORT int NLocBuffer;
+extern PGDLLIMPORT Block *LocalBufferBlockPointers;
+extern PGDLLIMPORT int32 *LocalRefCount;
+
+/* upper limit for effective_io_concurrency */
+#define MAX_IO_CONCURRENCY 1000
+
+/* special block number for ReadBuffer() */
+#define P_NEW InvalidBlockNumber /* grow the file to get a new page */
+
+/*
+ * Buffer content lock modes (mode argument for LockBuffer())
+ */
+#define BUFFER_LOCK_UNLOCK 0
+#define BUFFER_LOCK_SHARE 1
+#define BUFFER_LOCK_EXCLUSIVE 2
+
+/*
+ * These routines are beaten on quite heavily, hence the macroization.
+ */
+
+/*
+ * BufferIsValid
+ * True iff the given buffer number is valid (either as a shared
+ * or local buffer).
+ *
+ * Note: For a long time this was defined the same as BufferIsPinned,
+ * that is it would say False if you didn't hold a pin on the buffer.
+ * I believe this was bogus and served only to mask logic errors.
+ * Code should always know whether it has a buffer reference,
+ * independently of the pin state.
+ *
+ * Note: For a further long time this was not quite the inverse of the
+ * BufferIsInvalid() macro, in that it also did sanity checks to verify
+ * that the buffer number was in range. Most likely, this macro was
+ * originally intended only to be used in assertions, but its use has
+ * since expanded quite a bit, and the overhead of making those checks
+ * even in non-assert-enabled builds can be significant. Thus, we've
+ * now demoted the range checks to assertions within the macro itself.
+ */
+#define BufferIsValid(bufnum) \
+( \
+ AssertMacro((bufnum) <= NBuffers && (bufnum) >= -NLocBuffer), \
+ (bufnum) != InvalidBuffer \
+)
+
+/*
+ * BufferGetBlock
+ * Returns a reference to a disk page image associated with a buffer.
+ *
+ * Note:
+ * Assumes buffer is valid.
+ */
+#define BufferGetBlock(buffer) \
+( \
+ AssertMacro(BufferIsValid(buffer)), \
+ BufferIsLocal(buffer) ? \
+ LocalBufferBlockPointers[-(buffer) - 1] \
+ : \
+ (Block) (BufferBlocks + ((Size) ((buffer) - 1)) * BLCKSZ) \
+)
+
+/*
+ * BufferGetPageSize
+ * Returns the page size within a buffer.
+ *
+ * Notes:
+ * Assumes buffer is valid.
+ *
+ * The buffer can be a raw disk block and need not contain a valid
+ * (formatted) disk page.
+ */
+/* XXX should dig out of buffer descriptor */
+#define BufferGetPageSize(buffer) \
+( \
+ AssertMacro(BufferIsValid(buffer)), \
+ (Size)BLCKSZ \
+)
+
+/*
+ * BufferGetPage
+ * Returns the page associated with a buffer.
+ *
+ * When this is called as part of a scan, there may be a need for a nearby
+ * call to TestForOldSnapshot(). See the definition of that for details.
+ */
+#define BufferGetPage(buffer) ((Page)BufferGetBlock(buffer))
+
+/*
+ * prototypes for functions in bufmgr.c
+ */
+extern PrefetchBufferResult PrefetchSharedBuffer(struct SMgrRelationData *smgr_reln,
+ ForkNumber forkNum,
+ BlockNumber blockNum);
+extern PrefetchBufferResult PrefetchBuffer(Relation reln, ForkNumber forkNum,
+ BlockNumber blockNum);
+extern Buffer ReadBuffer(Relation reln, BlockNumber blockNum);
+extern Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum,
+ BlockNumber blockNum, ReadBufferMode mode,
+ BufferAccessStrategy strategy);
+extern Buffer ReadBufferWithoutRelcache(RelFileNode rnode,
+ ForkNumber forkNum, BlockNumber blockNum,
+ ReadBufferMode mode, BufferAccessStrategy strategy);
+extern void ReleaseBuffer(Buffer buffer);
+extern void UnlockReleaseBuffer(Buffer buffer);
+extern void MarkBufferDirty(Buffer buffer);
+extern void IncrBufferRefCount(Buffer buffer);
+extern Buffer ReleaseAndReadBuffer(Buffer buffer, Relation relation,
+ BlockNumber blockNum);
+
+extern void InitBufferPool(void);
+extern void InitBufferPoolAccess(void);
+extern void InitBufferPoolBackend(void);
+extern void AtEOXact_Buffers(bool isCommit);
+extern void PrintBufferLeakWarning(Buffer buffer);
+extern void CheckPointBuffers(int flags);
+extern BlockNumber BufferGetBlockNumber(Buffer buffer);
+extern BlockNumber RelationGetNumberOfBlocksInFork(Relation relation,
+ ForkNumber forkNum);
+extern void FlushOneBuffer(Buffer buffer);
+extern void FlushRelationBuffers(Relation rel);
+extern void FlushRelationsAllBuffers(struct SMgrRelationData **smgrs, int nrels);
+extern void FlushDatabaseBuffers(Oid dbid);
+extern void DropRelFileNodeBuffers(RelFileNodeBackend rnode, ForkNumber *forkNum,
+ int nforks, BlockNumber *firstDelBlock);
+extern void DropRelFileNodesAllBuffers(RelFileNodeBackend *rnodes, int nnodes);
+extern void DropDatabaseBuffers(Oid dbid);
+
+#define RelationGetNumberOfBlocks(reln) \
+ RelationGetNumberOfBlocksInFork(reln, MAIN_FORKNUM)
+
+extern bool BufferIsPermanent(Buffer buffer);
+extern XLogRecPtr BufferGetLSNAtomic(Buffer buffer);
+
+#ifdef NOT_USED
+extern void PrintPinnedBufs(void);
+#endif
+extern Size BufferShmemSize(void);
+extern void BufferGetTag(Buffer buffer, RelFileNode *rnode,
+ ForkNumber *forknum, BlockNumber *blknum);
+
+extern void MarkBufferDirtyHint(Buffer buffer, bool buffer_std);
+
+extern void UnlockBuffers(void);
+extern void LockBuffer(Buffer buffer, int mode);
+extern bool ConditionalLockBuffer(Buffer buffer);
+extern void LockBufferForCleanup(Buffer buffer);
+extern bool ConditionalLockBufferForCleanup(Buffer buffer);
+extern bool IsBufferCleanupOK(Buffer buffer);
+extern bool HoldingBufferPinThatDelaysRecovery(void);
+
+extern void AbortBufferIO(void);
+
+extern void BufmgrCommit(void);
+extern bool BgBufferSync(struct WritebackContext *wb_context);
+
+extern void AtProcExit_LocalBuffers(void);
+
+extern void TestForOldSnapshot_impl(Snapshot snapshot, Relation relation);
+
+/* in freelist.c */
+extern BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype);
+extern void FreeAccessStrategy(BufferAccessStrategy strategy);
+
+
+/* inline functions */
+
+/*
+ * Although this header file is nominally backend-only, certain frontend
+ * programs like pg_waldump include it. For compilers that emit static
+ * inline functions even when they're unused, that leads to unsatisfied
+ * external references; hence hide these with #ifndef FRONTEND.
+ */
+
+#ifndef FRONTEND
+
+/*
+ * Check whether the given snapshot is too old to have safely read the given
+ * page from the given table. If so, throw a "snapshot too old" error.
+ *
+ * This test generally needs to be performed after every BufferGetPage() call
+ * that is executed as part of a scan. It is not needed for calls made for
+ * modifying the page (for example, to position to the right place to insert a
+ * new index tuple or for vacuuming). It may also be omitted where calls to
+ * lower-level functions will have already performed the test.
+ *
+ * Note that a NULL snapshot argument is allowed and causes a fast return
+ * without error; this is to support call sites which can be called from
+ * either scans or index modification areas.
+ *
+ * For best performance, keep the tests that are fastest and/or most likely to
+ * exclude a page from old snapshot testing near the front.
+ */
+static inline void
+TestForOldSnapshot(Snapshot snapshot, Relation relation, Page page)
+{
+ Assert(relation != NULL);
+
+ if (old_snapshot_threshold >= 0
+ && (snapshot) != NULL
+ && ((snapshot)->snapshot_type == SNAPSHOT_MVCC
+ || (snapshot)->snapshot_type == SNAPSHOT_TOAST)
+ && !XLogRecPtrIsInvalid((snapshot)->lsn)
+ && PageGetLSN(page) > (snapshot)->lsn)
+ TestForOldSnapshot_impl(snapshot, relation);
+}
+
+#endif /* FRONTEND */
+
+#endif /* BUFMGR_H */
diff --git a/src/include/storage/bufpage.h b/src/include/storage/bufpage.h
new file mode 100644
index 0000000..4d0ae4b
--- /dev/null
+++ b/src/include/storage/bufpage.h
@@ -0,0 +1,459 @@
+/*-------------------------------------------------------------------------
+ *
+ * bufpage.h
+ * Standard POSTGRES buffer page definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/bufpage.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef BUFPAGE_H
+#define BUFPAGE_H
+
+#include "access/xlogdefs.h"
+#include "storage/block.h"
+#include "storage/item.h"
+#include "storage/off.h"
+
+/*
+ * A postgres disk page is an abstraction layered on top of a postgres
+ * disk block (which is simply a unit of i/o, see block.h).
+ *
+ * specifically, while a disk block can be unformatted, a postgres
+ * disk page is always a slotted page of the form:
+ *
+ * +----------------+---------------------------------+
+ * | PageHeaderData | linp1 linp2 linp3 ... |
+ * +-----------+----+---------------------------------+
+ * | ... linpN | |
+ * +-----------+--------------------------------------+
+ * | ^ pd_lower |
+ * | |
+ * | v pd_upper |
+ * +-------------+------------------------------------+
+ * | | tupleN ... |
+ * +-------------+------------------+-----------------+
+ * | ... tuple3 tuple2 tuple1 | "special space" |
+ * +--------------------------------+-----------------+
+ * ^ pd_special
+ *
+ * a page is full when nothing can be added between pd_lower and
+ * pd_upper.
+ *
+ * all blocks written out by an access method must be disk pages.
+ *
+ * EXCEPTIONS:
+ *
+ * obviously, a page is not formatted before it is initialized by
+ * a call to PageInit.
+ *
+ * NOTES:
+ *
+ * linp1..N form an ItemId (line pointer) array. ItemPointers point
+ * to a physical block number and a logical offset (line pointer
+ * number) within that block/page. Note that OffsetNumbers
+ * conventionally start at 1, not 0.
+ *
+ * tuple1..N are added "backwards" on the page. Since an ItemPointer
+ * offset is used to access an ItemId entry rather than an actual
+ * byte-offset position, tuples can be physically shuffled on a page
+ * whenever the need arises. This indirection also keeps crash recovery
+ * relatively simple, because the low-level details of page space
+ * management can be controlled by standard buffer page code during
+ * logging, and during recovery.
+ *
+ * AM-generic per-page information is kept in PageHeaderData.
+ *
+ * AM-specific per-page data (if any) is kept in the area marked "special
+ * space"; each AM has an "opaque" structure defined somewhere that is
+ * stored as the page trailer. an access method should always
+ * initialize its pages with PageInit and then set its own opaque
+ * fields.
+ */
+
+typedef Pointer Page;
+
+
+/*
+ * location (byte offset) within a page.
+ *
+ * note that this is actually limited to 2^15 because we have limited
+ * ItemIdData.lp_off and ItemIdData.lp_len to 15 bits (see itemid.h).
+ */
+typedef uint16 LocationIndex;
+
+
+/*
+ * For historical reasons, the 64-bit LSN value is stored as two 32-bit
+ * values.
+ */
+typedef struct
+{
+ uint32 xlogid; /* high bits */
+ uint32 xrecoff; /* low bits */
+} PageXLogRecPtr;
+
+#define PageXLogRecPtrGet(val) \
+ ((uint64) (val).xlogid << 32 | (val).xrecoff)
+#define PageXLogRecPtrSet(ptr, lsn) \
+ ((ptr).xlogid = (uint32) ((lsn) >> 32), (ptr).xrecoff = (uint32) (lsn))
+
+/*
+ * disk page organization
+ *
+ * space management information generic to any page
+ *
+ * pd_lsn - identifies xlog record for last change to this page.
+ * pd_checksum - page checksum, if set.
+ * pd_flags - flag bits.
+ * pd_lower - offset to start of free space.
+ * pd_upper - offset to end of free space.
+ * pd_special - offset to start of special space.
+ * pd_pagesize_version - size in bytes and page layout version number.
+ * pd_prune_xid - oldest XID among potentially prunable tuples on page.
+ *
+ * The LSN is used by the buffer manager to enforce the basic rule of WAL:
+ * "thou shalt write xlog before data". A dirty buffer cannot be dumped
+ * to disk until xlog has been flushed at least as far as the page's LSN.
+ *
+ * pd_checksum stores the page checksum, if it has been set for this page;
+ * zero is a valid value for a checksum. If a checksum is not in use then
+ * we leave the field unset. This will typically mean the field is zero
+ * though non-zero values may also be present if databases have been
+ * pg_upgraded from releases prior to 9.3, when the same byte offset was
+ * used to store the current timelineid when the page was last updated.
+ * Note that there is no indication on a page as to whether the checksum
+ * is valid or not, a deliberate design choice which avoids the problem
+ * of relying on the page contents to decide whether to verify it. Hence
+ * there are no flag bits relating to checksums.
+ *
+ * pd_prune_xid is a hint field that helps determine whether pruning will be
+ * useful. It is currently unused in index pages.
+ *
+ * The page version number and page size are packed together into a single
+ * uint16 field. This is for historical reasons: before PostgreSQL 7.3,
+ * there was no concept of a page version number, and doing it this way
+ * lets us pretend that pre-7.3 databases have page version number zero.
+ * We constrain page sizes to be multiples of 256, leaving the low eight
+ * bits available for a version number.
+ *
+ * Minimum possible page size is perhaps 64B to fit page header, opaque space
+ * and a minimal tuple; of course, in reality you want it much bigger, so
+ * the constraint on pagesize mod 256 is not an important restriction.
+ * On the high end, we can only support pages up to 32KB because lp_off/lp_len
+ * are 15 bits.
+ */
+
+typedef struct PageHeaderData
+{
+ /* XXX LSN is member of *any* block, not only page-organized ones */
+ PageXLogRecPtr pd_lsn; /* LSN: next byte after last byte of xlog
+ * record for last change to this page */
+ uint16 pd_checksum; /* checksum */
+ uint16 pd_flags; /* flag bits, see below */
+ LocationIndex pd_lower; /* offset to start of free space */
+ LocationIndex pd_upper; /* offset to end of free space */
+ LocationIndex pd_special; /* offset to start of special space */
+ uint16 pd_pagesize_version;
+ TransactionId pd_prune_xid; /* oldest prunable XID, or zero if none */
+ ItemIdData pd_linp[FLEXIBLE_ARRAY_MEMBER]; /* line pointer array */
+} PageHeaderData;
+
+typedef PageHeaderData *PageHeader;
+
+/*
+ * pd_flags contains the following flag bits. Undefined bits are initialized
+ * to zero and may be used in the future.
+ *
+ * PD_HAS_FREE_LINES is set if there are any LP_UNUSED line pointers before
+ * pd_lower. This should be considered a hint rather than the truth, since
+ * changes to it are not WAL-logged.
+ *
+ * PD_PAGE_FULL is set if an UPDATE doesn't find enough free space in the
+ * page for its new tuple version; this suggests that a prune is needed.
+ * Again, this is just a hint.
+ */
+#define PD_HAS_FREE_LINES 0x0001 /* are there any unused line pointers? */
+#define PD_PAGE_FULL 0x0002 /* not enough free space for new tuple? */
+#define PD_ALL_VISIBLE 0x0004 /* all tuples on page are visible to
+ * everyone */
+
+#define PD_VALID_FLAG_BITS 0x0007 /* OR of all valid pd_flags bits */
+
+/*
+ * Page layout version number 0 is for pre-7.3 Postgres releases.
+ * Releases 7.3 and 7.4 use 1, denoting a new HeapTupleHeader layout.
+ * Release 8.0 uses 2; it changed the HeapTupleHeader layout again.
+ * Release 8.1 uses 3; it redefined HeapTupleHeader infomask bits.
+ * Release 8.3 uses 4; it changed the HeapTupleHeader layout again, and
+ * added the pd_flags field (by stealing some bits from pd_tli),
+ * as well as adding the pd_prune_xid field (which enlarges the header).
+ *
+ * As of Release 9.3, the checksum version must also be considered when
+ * handling pages.
+ */
+#define PG_PAGE_LAYOUT_VERSION 4
+#define PG_DATA_CHECKSUM_VERSION 1
+
+/* ----------------------------------------------------------------
+ * page support macros
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * PageIsValid
+ * True iff page is valid.
+ */
+#define PageIsValid(page) PointerIsValid(page)
+
+/*
+ * line pointer(s) do not count as part of header
+ */
+#define SizeOfPageHeaderData (offsetof(PageHeaderData, pd_linp))
+
+/*
+ * PageIsEmpty
+ * returns true iff no itemid has been allocated on the page
+ */
+#define PageIsEmpty(page) \
+ (((PageHeader) (page))->pd_lower <= SizeOfPageHeaderData)
+
+/*
+ * PageIsNew
+ * returns true iff page has not been initialized (by PageInit)
+ */
+#define PageIsNew(page) (((PageHeader) (page))->pd_upper == 0)
+
+/*
+ * PageGetItemId
+ * Returns an item identifier of a page.
+ */
+#define PageGetItemId(page, offsetNumber) \
+ ((ItemId) (&((PageHeader) (page))->pd_linp[(offsetNumber) - 1]))
+
+/*
+ * PageGetContents
+ * To be used in cases where the page does not contain line pointers.
+ *
+ * Note: prior to 8.3 this was not guaranteed to yield a MAXALIGN'd result.
+ * Now it is. Beware of old code that might think the offset to the contents
+ * is just SizeOfPageHeaderData rather than MAXALIGN(SizeOfPageHeaderData).
+ */
+#define PageGetContents(page) \
+ ((char *) (page) + MAXALIGN(SizeOfPageHeaderData))
+
+/* ----------------
+ * macros to access page size info
+ * ----------------
+ */
+
+/*
+ * PageSizeIsValid
+ * True iff the page size is valid.
+ */
+#define PageSizeIsValid(pageSize) ((pageSize) == BLCKSZ)
+
+/*
+ * PageGetPageSize
+ * Returns the page size of a page.
+ *
+ * this can only be called on a formatted page (unlike
+ * BufferGetPageSize, which can be called on an unformatted page).
+ * however, it can be called on a page that is not stored in a buffer.
+ */
+#define PageGetPageSize(page) \
+ ((Size) (((PageHeader) (page))->pd_pagesize_version & (uint16) 0xFF00))
+
+/*
+ * PageGetPageLayoutVersion
+ * Returns the page layout version of a page.
+ */
+#define PageGetPageLayoutVersion(page) \
+ (((PageHeader) (page))->pd_pagesize_version & 0x00FF)
+
+/*
+ * PageSetPageSizeAndVersion
+ * Sets the page size and page layout version number of a page.
+ *
+ * We could support setting these two values separately, but there's
+ * no real need for it at the moment.
+ */
+#define PageSetPageSizeAndVersion(page, size, version) \
+( \
+ AssertMacro(((size) & 0xFF00) == (size)), \
+ AssertMacro(((version) & 0x00FF) == (version)), \
+ ((PageHeader) (page))->pd_pagesize_version = (size) | (version) \
+)
+
+/* ----------------
+ * page special data macros
+ * ----------------
+ */
+/*
+ * PageGetSpecialSize
+ * Returns size of special space on a page.
+ */
+#define PageGetSpecialSize(page) \
+ ((uint16) (PageGetPageSize(page) - ((PageHeader)(page))->pd_special))
+
+/*
+ * Using assertions, validate that the page special pointer is OK.
+ *
+ * This is intended to catch use of the pointer before page initialization.
+ * It is implemented as a function due to the limitations of the MSVC
+ * compiler, which choked on doing all these tests within another macro. We
+ * return true so that AssertMacro() can be used while still getting the
+ * specifics from the macro failure within this function.
+ */
+static inline bool
+PageValidateSpecialPointer(Page page)
+{
+ Assert(PageIsValid(page));
+ Assert(((PageHeader) (page))->pd_special <= BLCKSZ);
+ Assert(((PageHeader) (page))->pd_special >= SizeOfPageHeaderData);
+
+ return true;
+}
+
+/*
+ * PageGetSpecialPointer
+ * Returns pointer to special space on a page.
+ */
+#define PageGetSpecialPointer(page) \
+( \
+ AssertMacro(PageValidateSpecialPointer(page)), \
+ (char *) ((char *) (page) + ((PageHeader) (page))->pd_special) \
+)
+
+/*
+ * PageGetItem
+ * Retrieves an item on the given page.
+ *
+ * Note:
+ * This does not change the status of any of the resources passed.
+ * The semantics may change in the future.
+ */
+#define PageGetItem(page, itemId) \
+( \
+ AssertMacro(PageIsValid(page)), \
+ AssertMacro(ItemIdHasStorage(itemId)), \
+ (Item)(((char *)(page)) + ItemIdGetOffset(itemId)) \
+)
+
+/*
+ * PageGetMaxOffsetNumber
+ * Returns the maximum offset number used by the given page.
+ * Since offset numbers are 1-based, this is also the number
+ * of items on the page.
+ *
+ * NOTE: if the page is not initialized (pd_lower == 0), we must
+ * return zero to ensure sane behavior. Accept double evaluation
+ * of the argument so that we can ensure this.
+ */
+#define PageGetMaxOffsetNumber(page) \
+ (((PageHeader) (page))->pd_lower <= SizeOfPageHeaderData ? 0 : \
+ ((((PageHeader) (page))->pd_lower - SizeOfPageHeaderData) \
+ / sizeof(ItemIdData)))
+
+/*
+ * Additional macros for access to page headers. (Beware multiple evaluation
+ * of the arguments!)
+ */
+#define PageGetLSN(page) \
+ PageXLogRecPtrGet(((PageHeader) (page))->pd_lsn)
+#define PageSetLSN(page, lsn) \
+ PageXLogRecPtrSet(((PageHeader) (page))->pd_lsn, lsn)
+
+#define PageHasFreeLinePointers(page) \
+ (((PageHeader) (page))->pd_flags & PD_HAS_FREE_LINES)
+#define PageSetHasFreeLinePointers(page) \
+ (((PageHeader) (page))->pd_flags |= PD_HAS_FREE_LINES)
+#define PageClearHasFreeLinePointers(page) \
+ (((PageHeader) (page))->pd_flags &= ~PD_HAS_FREE_LINES)
+
+#define PageIsFull(page) \
+ (((PageHeader) (page))->pd_flags & PD_PAGE_FULL)
+#define PageSetFull(page) \
+ (((PageHeader) (page))->pd_flags |= PD_PAGE_FULL)
+#define PageClearFull(page) \
+ (((PageHeader) (page))->pd_flags &= ~PD_PAGE_FULL)
+
+#define PageIsAllVisible(page) \
+ (((PageHeader) (page))->pd_flags & PD_ALL_VISIBLE)
+#define PageSetAllVisible(page) \
+ (((PageHeader) (page))->pd_flags |= PD_ALL_VISIBLE)
+#define PageClearAllVisible(page) \
+ (((PageHeader) (page))->pd_flags &= ~PD_ALL_VISIBLE)
+
+#define PageIsPrunable(page, oldestxmin) \
+( \
+ AssertMacro(TransactionIdIsNormal(oldestxmin)), \
+ TransactionIdIsValid(((PageHeader) (page))->pd_prune_xid) && \
+ TransactionIdPrecedes(((PageHeader) (page))->pd_prune_xid, oldestxmin) \
+)
+#define PageSetPrunable(page, xid) \
+do { \
+ Assert(TransactionIdIsNormal(xid)); \
+ if (!TransactionIdIsValid(((PageHeader) (page))->pd_prune_xid) || \
+ TransactionIdPrecedes(xid, ((PageHeader) (page))->pd_prune_xid)) \
+ ((PageHeader) (page))->pd_prune_xid = (xid); \
+} while (0)
+#define PageClearPrunable(page) \
+ (((PageHeader) (page))->pd_prune_xid = InvalidTransactionId)
+
+
+/* ----------------------------------------------------------------
+ * extern declarations
+ * ----------------------------------------------------------------
+ */
+
+/* flags for PageAddItemExtended() */
+#define PAI_OVERWRITE (1 << 0)
+#define PAI_IS_HEAP (1 << 1)
+
+/* flags for PageIsVerifiedExtended() */
+#define PIV_LOG_WARNING (1 << 0)
+#define PIV_REPORT_STAT (1 << 1)
+
+#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap) \
+ PageAddItemExtended(page, item, size, offsetNumber, \
+ ((overwrite) ? PAI_OVERWRITE : 0) | \
+ ((is_heap) ? PAI_IS_HEAP : 0))
+
+/*
+ * Check that BLCKSZ is a multiple of sizeof(size_t). In
+ * PageIsVerifiedExtended(), it is much faster to check if a page is
+ * full of zeroes using the native word size. Note that this assertion
+ * is kept within a header to make sure that StaticAssertDecl() works
+ * across various combinations of platforms and compilers.
+ */
+StaticAssertDecl(BLCKSZ == ((BLCKSZ / sizeof(size_t)) * sizeof(size_t)),
+ "BLCKSZ has to be a multiple of sizeof(size_t)");
+
+extern void PageInit(Page page, Size pageSize, Size specialSize);
+extern bool PageIsVerified(Page page, BlockNumber blkno);
+extern bool PageIsVerifiedExtended(Page page, BlockNumber blkno, int flags);
+extern OffsetNumber PageAddItemExtended(Page page, Item item, Size size,
+ OffsetNumber offsetNumber, int flags);
+extern Page PageGetTempPage(Page page);
+extern Page PageGetTempPageCopy(Page page);
+extern Page PageGetTempPageCopySpecial(Page page);
+extern void PageRestoreTempPage(Page tempPage, Page oldPage);
+extern void PageRepairFragmentation(Page page);
+extern Size PageGetFreeSpace(Page page);
+extern Size PageGetFreeSpaceForMultipleTuples(Page page, int ntups);
+extern Size PageGetExactFreeSpace(Page page);
+extern Size PageGetHeapFreeSpace(Page page);
+extern void PageIndexTupleDelete(Page page, OffsetNumber offset);
+extern void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems);
+extern void PageIndexTupleDeleteNoCompact(Page page, OffsetNumber offset);
+extern bool PageIndexTupleOverwrite(Page page, OffsetNumber offnum,
+ Item newtup, Size newsize);
+extern char *PageSetChecksumCopy(Page page, BlockNumber blkno);
+extern void PageSetChecksumInplace(Page page, BlockNumber blkno);
+
+#endif /* BUFPAGE_H */
diff --git a/src/include/storage/checksum.h b/src/include/storage/checksum.h
new file mode 100644
index 0000000..6e77744
--- /dev/null
+++ b/src/include/storage/checksum.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * checksum.h
+ * Checksum implementation for data pages.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/checksum.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef CHECKSUM_H
+#define CHECKSUM_H
+
+#include "storage/block.h"
+
+/*
+ * Compute the checksum for a Postgres page. The page must be aligned on a
+ * 4-byte boundary.
+ */
+extern uint16 pg_checksum_page(char *page, BlockNumber blkno);
+
+#endif /* CHECKSUM_H */
diff --git a/src/include/storage/checksum_impl.h b/src/include/storage/checksum_impl.h
new file mode 100644
index 0000000..364acfa
--- /dev/null
+++ b/src/include/storage/checksum_impl.h
@@ -0,0 +1,215 @@
+/*-------------------------------------------------------------------------
+ *
+ * checksum_impl.h
+ * Checksum implementation for data pages.
+ *
+ * This file exists for the benefit of external programs that may wish to
+ * check Postgres page checksums. They can #include this to get the code
+ * referenced by storage/checksum.h. (Note: you may need to redefine
+ * Assert() as empty to compile this successfully externally.)
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/checksum_impl.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/*
+ * The algorithm used to checksum pages is chosen for very fast calculation.
+ * Workloads where the database working set fits into OS file cache but not
+ * into shared buffers can read in pages at a very fast pace and the checksum
+ * algorithm itself can become the largest bottleneck.
+ *
+ * The checksum algorithm itself is based on the FNV-1a hash (FNV is shorthand
+ * for Fowler/Noll/Vo). The primitive of a plain FNV-1a hash folds in data 1
+ * byte at a time according to the formula:
+ *
+ * hash = (hash ^ value) * FNV_PRIME
+ *
+ * FNV-1a algorithm is described at http://www.isthe.com/chongo/tech/comp/fnv/
+ *
+ * PostgreSQL doesn't use FNV-1a hash directly because it has bad mixing of
+ * high bits - high order bits in input data only affect high order bits in
+ * output data. To resolve this we xor in the value prior to multiplication
+ * shifted right by 17 bits. The number 17 was chosen because it doesn't
+ * have common denominator with set bit positions in FNV_PRIME and empirically
+ * provides the fastest mixing for high order bits of final iterations quickly
+ * avalanche into lower positions. For performance reasons we choose to combine
+ * 4 bytes at a time. The actual hash formula used as the basis is:
+ *
+ * hash = (hash ^ value) * FNV_PRIME ^ ((hash ^ value) >> 17)
+ *
+ * The main bottleneck in this calculation is the multiplication latency. To
+ * hide the latency and to make use of SIMD parallelism multiple hash values
+ * are calculated in parallel. The page is treated as a 32 column two
+ * dimensional array of 32 bit values. Each column is aggregated separately
+ * into a partial checksum. Each partial checksum uses a different initial
+ * value (offset basis in FNV terminology). The initial values actually used
+ * were chosen randomly, as the values themselves don't matter as much as that
+ * they are different and don't match anything in real data. After initializing
+ * partial checksums each value in the column is aggregated according to the
+ * above formula. Finally two more iterations of the formula are performed with
+ * value 0 to mix the bits of the last value added.
+ *
+ * The partial checksums are then folded together using xor to form a single
+ * 32-bit checksum. The caller can safely reduce the value to 16 bits
+ * using modulo 2^16-1. That will cause a very slight bias towards lower
+ * values but this is not significant for the performance of the
+ * checksum.
+ *
+ * The algorithm choice was based on what instructions are available in SIMD
+ * instruction sets. This meant that a fast and good algorithm needed to use
+ * multiplication as the main mixing operator. The simplest multiplication
+ * based checksum primitive is the one used by FNV. The prime used is chosen
+ * for good dispersion of values. It has no known simple patterns that result
+ * in collisions. Test of 5-bit differentials of the primitive over 64bit keys
+ * reveals no differentials with 3 or more values out of 100000 random keys
+ * colliding. Avalanche test shows that only high order bits of the last word
+ * have a bias. Tests of 1-4 uncorrelated bit errors, stray 0 and 0xFF bytes,
+ * overwriting page from random position to end with 0 bytes, and overwriting
+ * random segments of page with 0x00, 0xFF and random data all show optimal
+ * 2e-16 false positive rate within margin of error.
+ *
+ * Vectorization of the algorithm requires 32bit x 32bit -> 32bit integer
+ * multiplication instruction. As of 2013 the corresponding instruction is
+ * available on x86 SSE4.1 extensions (pmulld) and ARM NEON (vmul.i32).
+ * Vectorization requires a compiler to do the vectorization for us. For recent
+ * GCC versions the flags -msse4.1 -funroll-loops -ftree-vectorize are enough
+ * to achieve vectorization.
+ *
+ * The optimal amount of parallelism to use depends on CPU specific instruction
+ * latency, SIMD instruction width, throughput and the amount of registers
+ * available to hold intermediate state. Generally, more parallelism is better
+ * up to the point that state doesn't fit in registers and extra load-store
+ * instructions are needed to swap values in/out. The number chosen is a fixed
+ * part of the algorithm because changing the parallelism changes the checksum
+ * result.
+ *
+ * The parallelism number 32 was chosen based on the fact that it is the
+ * largest state that fits into architecturally visible x86 SSE registers while
+ * leaving some free registers for intermediate values. For future processors
+ * with 256bit vector registers this will leave some performance on the table.
+ * When vectorization is not available it might be beneficial to restructure
+ * the computation to calculate a subset of the columns at a time and perform
+ * multiple passes to avoid register spilling. This optimization opportunity
+ * is not used. Current coding also assumes that the compiler has the ability
+ * to unroll the inner loop to avoid loop overhead and minimize register
+ * spilling. For less sophisticated compilers it might be beneficial to
+ * manually unroll the inner loop.
+ */
+
+#include "storage/bufpage.h"
+
+/* number of checksums to calculate in parallel */
+#define N_SUMS 32
+/* prime multiplier of FNV-1a hash */
+#define FNV_PRIME 16777619
+
+/* Use a union so that this code is valid under strict aliasing */
+typedef union
+{
+ PageHeaderData phdr;
+ uint32 data[BLCKSZ / (sizeof(uint32) * N_SUMS)][N_SUMS];
+} PGChecksummablePage;
+
+/*
+ * Base offsets to initialize each of the parallel FNV hashes into a
+ * different initial state.
+ */
+static const uint32 checksumBaseOffsets[N_SUMS] = {
+ 0x5B1F36E9, 0xB8525960, 0x02AB50AA, 0x1DE66D2A,
+ 0x79FF467A, 0x9BB9F8A3, 0x217E7CD2, 0x83E13D2C,
+ 0xF8D4474F, 0xE39EB970, 0x42C6AE16, 0x993216FA,
+ 0x7B093B5D, 0x98DAFF3C, 0xF718902A, 0x0B1C9CDB,
+ 0xE58F764B, 0x187636BC, 0x5D7B3BB1, 0xE73DE7DE,
+ 0x92BEC979, 0xCCA6C0B2, 0x304A0979, 0x85AA43D4,
+ 0x783125BB, 0x6CA8EAA2, 0xE407EAC6, 0x4B5CFC3E,
+ 0x9FBF8C76, 0x15CA20BE, 0xF2CA9FD3, 0x959BD756
+};
+
+/*
+ * Calculate one round of the checksum.
+ */
+#define CHECKSUM_COMP(checksum, value) \
+do { \
+ uint32 __tmp = (checksum) ^ (value); \
+ (checksum) = __tmp * FNV_PRIME ^ (__tmp >> 17); \
+} while (0)
+
+/*
+ * Block checksum algorithm. The page must be adequately aligned
+ * (at least on 4-byte boundary).
+ */
+static uint32
+pg_checksum_block(const PGChecksummablePage *page)
+{
+ uint32 sums[N_SUMS];
+ uint32 result = 0;
+ uint32 i,
+ j;
+
+ /* ensure that the size is compatible with the algorithm */
+ Assert(sizeof(PGChecksummablePage) == BLCKSZ);
+
+ /* initialize partial checksums to their corresponding offsets */
+ memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets));
+
+ /* main checksum calculation */
+ for (i = 0; i < (uint32) (BLCKSZ / (sizeof(uint32) * N_SUMS)); i++)
+ for (j = 0; j < N_SUMS; j++)
+ CHECKSUM_COMP(sums[j], page->data[i][j]);
+
+ /* finally add in two rounds of zeroes for additional mixing */
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < N_SUMS; j++)
+ CHECKSUM_COMP(sums[j], 0);
+
+ /* xor fold partial checksums together */
+ for (i = 0; i < N_SUMS; i++)
+ result ^= sums[i];
+
+ return result;
+}
+
+/*
+ * Compute the checksum for a Postgres page.
+ *
+ * The page must be adequately aligned (at least on a 4-byte boundary).
+ * Beware also that the checksum field of the page is transiently zeroed.
+ *
+ * The checksum includes the block number (to detect the case where a page is
+ * somehow moved to a different location), the page header (excluding the
+ * checksum itself), and the page data.
+ */
+uint16
+pg_checksum_page(char *page, BlockNumber blkno)
+{
+ PGChecksummablePage *cpage = (PGChecksummablePage *) page;
+ uint16 save_checksum;
+ uint32 checksum;
+
+ /* We only calculate the checksum for properly-initialized pages */
+ Assert(!PageIsNew(&cpage->phdr));
+
+ /*
+ * Save pd_checksum and temporarily set it to zero, so that the checksum
+ * calculation isn't affected by the old checksum stored on the page.
+ * Restore it after, because actually updating the checksum is NOT part of
+ * the API of this function.
+ */
+ save_checksum = cpage->phdr.pd_checksum;
+ cpage->phdr.pd_checksum = 0;
+ checksum = pg_checksum_block(cpage);
+ cpage->phdr.pd_checksum = save_checksum;
+
+ /* Mix in the block number to detect transposed pages */
+ checksum ^= blkno;
+
+ /*
+ * Reduce to a uint16 (to fit in the pd_checksum field) with an offset of
+ * one. That avoids checksums of zero, which seems like a good idea.
+ */
+ return (uint16) ((checksum % 65535) + 1);
+}
diff --git a/src/include/storage/condition_variable.h b/src/include/storage/condition_variable.h
new file mode 100644
index 0000000..c2be198
--- /dev/null
+++ b/src/include/storage/condition_variable.h
@@ -0,0 +1,62 @@
+/*-------------------------------------------------------------------------
+ *
+ * condition_variable.h
+ * Condition variables
+ *
+ * A condition variable is a method of waiting until a certain condition
+ * becomes true. Conventionally, a condition variable supports three
+ * operations: (1) sleep; (2) signal, which wakes up one process sleeping
+ * on the condition variable; and (3) broadcast, which wakes up every
+ * process sleeping on the condition variable. In our implementation,
+ * condition variables put a process into an interruptible sleep (so it
+ * can be canceled prior to the fulfillment of the condition) and do not
+ * use pointers internally (so that they are safe to use within DSMs).
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/condition_variable.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef CONDITION_VARIABLE_H
+#define CONDITION_VARIABLE_H
+
+#include "storage/proclist_types.h"
+#include "storage/s_lock.h"
+
+typedef struct
+{
+ slock_t mutex; /* spinlock protecting the wakeup list */
+ proclist_head wakeup; /* list of wake-able processes */
+} ConditionVariable;
+
+/* Initialize a condition variable. */
+extern void ConditionVariableInit(ConditionVariable *cv);
+
+/*
+ * To sleep on a condition variable, a process should use a loop which first
+ * checks the condition, exiting the loop if it is met, and then calls
+ * ConditionVariableSleep. Spurious wakeups are possible, but should be
+ * infrequent. After exiting the loop, ConditionVariableCancelSleep must
+ * be called to ensure that the process is no longer in the wait list for
+ * the condition variable.
+ */
+extern void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info);
+extern bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout,
+ uint32 wait_event_info);
+extern void ConditionVariableCancelSleep(void);
+
+/*
+ * Optionally, ConditionVariablePrepareToSleep can be called before entering
+ * the test-and-sleep loop described above. Doing so is more efficient if
+ * at least one sleep is needed, whereas not doing so is more efficient when
+ * no sleep is needed because the test condition is true the first time.
+ */
+extern void ConditionVariablePrepareToSleep(ConditionVariable *cv);
+
+/* Wake up a single waiter (via signal) or all waiters (via broadcast). */
+extern void ConditionVariableSignal(ConditionVariable *cv);
+extern void ConditionVariableBroadcast(ConditionVariable *cv);
+
+#endif /* CONDITION_VARIABLE_H */
diff --git a/src/include/storage/copydir.h b/src/include/storage/copydir.h
new file mode 100644
index 0000000..5d28f59
--- /dev/null
+++ b/src/include/storage/copydir.h
@@ -0,0 +1,19 @@
+/*-------------------------------------------------------------------------
+ *
+ * copydir.h
+ * Copy a directory.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/copydir.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef COPYDIR_H
+#define COPYDIR_H
+
+extern void copydir(char *fromdir, char *todir, bool recurse);
+extern void copy_file(char *fromfile, char *tofile);
+
+#endif /* COPYDIR_H */
diff --git a/src/include/storage/dsm.h b/src/include/storage/dsm.h
new file mode 100644
index 0000000..408c054
--- /dev/null
+++ b/src/include/storage/dsm.h
@@ -0,0 +1,61 @@
+/*-------------------------------------------------------------------------
+ *
+ * dsm.h
+ * manage dynamic shared memory segments
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/dsm.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DSM_H
+#define DSM_H
+
+#include "storage/dsm_impl.h"
+
+typedef struct dsm_segment dsm_segment;
+
+#define DSM_CREATE_NULL_IF_MAXSEGMENTS 0x0001
+
+/* A sentinel value for an invalid DSM handle. */
+#define DSM_HANDLE_INVALID 0
+
+/* Startup and shutdown functions. */
+struct PGShmemHeader; /* avoid including pg_shmem.h */
+extern void dsm_cleanup_using_control_segment(dsm_handle old_control_handle);
+extern void dsm_postmaster_startup(struct PGShmemHeader *);
+extern void dsm_backend_shutdown(void);
+extern void dsm_detach_all(void);
+
+#ifdef EXEC_BACKEND
+extern void dsm_set_control_handle(dsm_handle h);
+#endif
+
+/* Functions that create or remove mappings. */
+extern dsm_segment *dsm_create(Size size, int flags);
+extern dsm_segment *dsm_attach(dsm_handle h);
+extern void dsm_detach(dsm_segment *seg);
+
+/* Resource management functions. */
+extern void dsm_pin_mapping(dsm_segment *seg);
+extern void dsm_unpin_mapping(dsm_segment *seg);
+extern void dsm_pin_segment(dsm_segment *seg);
+extern void dsm_unpin_segment(dsm_handle h);
+extern dsm_segment *dsm_find_mapping(dsm_handle h);
+
+/* Informational functions. */
+extern void *dsm_segment_address(dsm_segment *seg);
+extern Size dsm_segment_map_length(dsm_segment *seg);
+extern dsm_handle dsm_segment_handle(dsm_segment *seg);
+
+/* Cleanup hooks. */
+typedef void (*on_dsm_detach_callback) (dsm_segment *, Datum arg);
+extern void on_dsm_detach(dsm_segment *seg,
+ on_dsm_detach_callback function, Datum arg);
+extern void cancel_on_dsm_detach(dsm_segment *seg,
+ on_dsm_detach_callback function, Datum arg);
+extern void reset_on_dsm_detach(void);
+
+#endif /* DSM_H */
diff --git a/src/include/storage/dsm_impl.h b/src/include/storage/dsm_impl.h
new file mode 100644
index 0000000..562cb78
--- /dev/null
+++ b/src/include/storage/dsm_impl.h
@@ -0,0 +1,75 @@
+/*-------------------------------------------------------------------------
+ *
+ * dsm_impl.h
+ * low-level dynamic shared memory primitives
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/dsm_impl.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DSM_IMPL_H
+#define DSM_IMPL_H
+
+/* Dynamic shared memory implementations. */
+#define DSM_IMPL_POSIX 1
+#define DSM_IMPL_SYSV 2
+#define DSM_IMPL_WINDOWS 3
+#define DSM_IMPL_MMAP 4
+
+/*
+ * Determine which dynamic shared memory implementations will be supported
+ * on this platform, and which one will be the default.
+ */
+#ifdef WIN32
+#define USE_DSM_WINDOWS
+#define DEFAULT_DYNAMIC_SHARED_MEMORY_TYPE DSM_IMPL_WINDOWS
+#else
+#ifdef HAVE_SHM_OPEN
+#define USE_DSM_POSIX
+#define DEFAULT_DYNAMIC_SHARED_MEMORY_TYPE DSM_IMPL_POSIX
+#endif
+#define USE_DSM_SYSV
+#ifndef DEFAULT_DYNAMIC_SHARED_MEMORY_TYPE
+#define DEFAULT_DYNAMIC_SHARED_MEMORY_TYPE DSM_IMPL_SYSV
+#endif
+#define USE_DSM_MMAP
+#endif
+
+/* GUC. */
+extern int dynamic_shared_memory_type;
+
+/*
+ * Directory for on-disk state.
+ *
+ * This is used by all implementations for crash recovery and by the mmap
+ * implementation for storage.
+ */
+#define PG_DYNSHMEM_DIR "pg_dynshmem"
+#define PG_DYNSHMEM_MMAP_FILE_PREFIX "mmap."
+
+/* A "name" for a dynamic shared memory segment. */
+typedef uint32 dsm_handle;
+
+/* All the shared-memory operations we know about. */
+typedef enum
+{
+ DSM_OP_CREATE,
+ DSM_OP_ATTACH,
+ DSM_OP_DETACH,
+ DSM_OP_DESTROY
+} dsm_op;
+
+/* Create, attach to, detach from, resize, or destroy a segment. */
+extern bool dsm_impl_op(dsm_op op, dsm_handle handle, Size request_size,
+ void **impl_private, void **mapped_address, Size *mapped_size,
+ int elevel);
+
+/* Implementation-dependent actions required to keep segment until shutdown. */
+extern void dsm_impl_pin_segment(dsm_handle handle, void *impl_private,
+ void **impl_private_pm_handle);
+extern void dsm_impl_unpin_segment(dsm_handle handle, void **impl_private);
+
+#endif /* DSM_IMPL_H */
diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h
new file mode 100644
index 0000000..8cd125d
--- /dev/null
+++ b/src/include/storage/fd.h
@@ -0,0 +1,168 @@
+/*-------------------------------------------------------------------------
+ *
+ * fd.h
+ * Virtual file descriptor definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/fd.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/*
+ * calls:
+ *
+ * File {Close, Read, Write, Size, Sync}
+ * {Path Name Open, Allocate, Free} File
+ *
+ * These are NOT JUST RENAMINGS OF THE UNIX ROUTINES.
+ * Use them for all file activity...
+ *
+ * File fd;
+ * fd = PathNameOpenFile("foo", O_RDONLY);
+ *
+ * AllocateFile();
+ * FreeFile();
+ *
+ * Use AllocateFile, not fopen, if you need a stdio file (FILE*); then
+ * use FreeFile, not fclose, to close it. AVOID using stdio for files
+ * that you intend to hold open for any length of time, since there is
+ * no way for them to share kernel file descriptors with other files.
+ *
+ * Likewise, use AllocateDir/FreeDir, not opendir/closedir, to allocate
+ * open directories (DIR*), and OpenTransientFile/CloseTransientFile for an
+ * unbuffered file descriptor.
+ *
+ * If you really can't use any of the above, at least call AcquireExternalFD
+ * or ReserveExternalFD to report any file descriptors that are held for any
+ * length of time. Failure to do so risks unnecessary EMFILE errors.
+ */
+#ifndef FD_H
+#define FD_H
+
+#include <dirent.h>
+
+
+typedef int File;
+
+
+/* GUC parameter */
+extern PGDLLIMPORT int max_files_per_process;
+extern PGDLLIMPORT bool data_sync_retry;
+
+/*
+ * This is private to fd.c, but exported for save/restore_backend_variables()
+ */
+extern int max_safe_fds;
+
+/*
+ * On Windows, we have to interpret EACCES as possibly meaning the same as
+ * ENOENT, because if a file is unlinked-but-not-yet-gone on that platform,
+ * that's what you get. Ugh. This code is designed so that we don't
+ * actually believe these cases are okay without further evidence (namely,
+ * a pending fsync request getting canceled ... see ProcessSyncRequests).
+ */
+#ifndef WIN32
+#define FILE_POSSIBLY_DELETED(err) ((err) == ENOENT)
+#else
+#define FILE_POSSIBLY_DELETED(err) ((err) == ENOENT || (err) == EACCES)
+#endif
+
+/*
+ * prototypes for functions in fd.c
+ */
+
+/* Operations on virtual Files --- equivalent to Unix kernel file ops */
+extern File PathNameOpenFile(const char *fileName, int fileFlags);
+extern File PathNameOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode);
+extern File OpenTemporaryFile(bool interXact);
+extern void FileClose(File file);
+extern int FilePrefetch(File file, off_t offset, int amount, uint32 wait_event_info);
+extern int FileRead(File file, char *buffer, int amount, off_t offset, uint32 wait_event_info);
+extern int FileWrite(File file, char *buffer, int amount, off_t offset, uint32 wait_event_info);
+extern int FileSync(File file, uint32 wait_event_info);
+extern off_t FileSize(File file);
+extern int FileTruncate(File file, off_t offset, uint32 wait_event_info);
+extern void FileWriteback(File file, off_t offset, off_t nbytes, uint32 wait_event_info);
+extern char *FilePathName(File file);
+extern int FileGetRawDesc(File file);
+extern int FileGetRawFlags(File file);
+extern mode_t FileGetRawMode(File file);
+
+/* Operations used for sharing named temporary files */
+extern File PathNameCreateTemporaryFile(const char *name, bool error_on_failure);
+extern File PathNameOpenTemporaryFile(const char *name);
+extern bool PathNameDeleteTemporaryFile(const char *name, bool error_on_failure);
+extern void PathNameCreateTemporaryDir(const char *base, const char *name);
+extern void PathNameDeleteTemporaryDir(const char *name);
+extern void TempTablespacePath(char *path, Oid tablespace);
+
+/* Operations that allow use of regular stdio --- USE WITH CAUTION */
+extern FILE *AllocateFile(const char *name, const char *mode);
+extern int FreeFile(FILE *file);
+
+/* Operations that allow use of pipe streams (popen/pclose) */
+extern FILE *OpenPipeStream(const char *command, const char *mode);
+extern int ClosePipeStream(FILE *file);
+
+/* Operations to allow use of the <dirent.h> library routines */
+extern DIR *AllocateDir(const char *dirname);
+extern struct dirent *ReadDir(DIR *dir, const char *dirname);
+extern struct dirent *ReadDirExtended(DIR *dir, const char *dirname,
+ int elevel);
+extern int FreeDir(DIR *dir);
+
+/* Operations to allow use of a plain kernel FD, with automatic cleanup */
+extern int OpenTransientFile(const char *fileName, int fileFlags);
+extern int OpenTransientFilePerm(const char *fileName, int fileFlags, mode_t fileMode);
+extern int CloseTransientFile(int fd);
+
+/* If you've really really gotta have a plain kernel FD, use this */
+extern int BasicOpenFile(const char *fileName, int fileFlags);
+extern int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode);
+
+/* Use these for other cases, and also for long-lived BasicOpenFile FDs */
+extern bool AcquireExternalFD(void);
+extern void ReserveExternalFD(void);
+extern void ReleaseExternalFD(void);
+
+/* Make a directory with default permissions */
+extern int MakePGDirectory(const char *directoryName);
+
+/* Miscellaneous support routines */
+extern void InitFileAccess(void);
+extern void set_max_safe_fds(void);
+extern void closeAllVfds(void);
+extern void SetTempTablespaces(Oid *tableSpaces, int numSpaces);
+extern bool TempTablespacesAreSet(void);
+extern int GetTempTablespaces(Oid *tableSpaces, int numSpaces);
+extern Oid GetNextTempTableSpace(void);
+extern void AtEOXact_Files(bool isCommit);
+extern void AtEOSubXact_Files(bool isCommit, SubTransactionId mySubid,
+ SubTransactionId parentSubid);
+extern void RemovePgTempFiles(void);
+extern void RemovePgTempFilesInDir(const char *tmpdirname, bool missing_ok,
+ bool unlink_all);
+extern bool looks_like_temp_rel_name(const char *name);
+
+extern int pg_fsync(int fd);
+extern int pg_fsync_no_writethrough(int fd);
+extern int pg_fsync_writethrough(int fd);
+extern int pg_fdatasync(int fd);
+extern void pg_flush_data(int fd, off_t offset, off_t amount);
+extern void fsync_fname(const char *fname, bool isdir);
+extern int fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel);
+extern int durable_rename(const char *oldfile, const char *newfile, int loglevel);
+extern int durable_unlink(const char *fname, int loglevel);
+extern int durable_rename_excl(const char *oldfile, const char *newfile, int loglevel);
+extern void SyncDataDirectory(void);
+extern int data_sync_elevel(int elevel);
+
+/* Filename components */
+#define PG_TEMP_FILES_DIR "pgsql_tmp"
+#define PG_TEMP_FILE_PREFIX "pgsql_tmp"
+
+#endif /* FD_H */
diff --git a/src/include/storage/freespace.h b/src/include/storage/freespace.h
new file mode 100644
index 0000000..81668ad
--- /dev/null
+++ b/src/include/storage/freespace.h
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * freespace.h
+ * POSTGRES free space map for quickly finding free space in relations
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/freespace.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FREESPACE_H_
+#define FREESPACE_H_
+
+#include "storage/block.h"
+#include "storage/relfilenode.h"
+#include "utils/relcache.h"
+
+/* prototypes for public functions in freespace.c */
+extern Size GetRecordedFreeSpace(Relation rel, BlockNumber heapBlk);
+extern BlockNumber GetPageWithFreeSpace(Relation rel, Size spaceNeeded);
+extern BlockNumber RecordAndGetPageWithFreeSpace(Relation rel,
+ BlockNumber oldPage,
+ Size oldSpaceAvail,
+ Size spaceNeeded);
+extern void RecordPageWithFreeSpace(Relation rel, BlockNumber heapBlk,
+ Size spaceAvail);
+extern void XLogRecordPageWithFreeSpace(RelFileNode rnode, BlockNumber heapBlk,
+ Size spaceAvail);
+
+extern BlockNumber FreeSpaceMapPrepareTruncateRel(Relation rel,
+ BlockNumber nblocks);
+extern void FreeSpaceMapVacuum(Relation rel);
+extern void FreeSpaceMapVacuumRange(Relation rel, BlockNumber start,
+ BlockNumber end);
+
+#endif /* FREESPACE_H_ */
diff --git a/src/include/storage/fsm_internals.h b/src/include/storage/fsm_internals.h
new file mode 100644
index 0000000..48d25a1
--- /dev/null
+++ b/src/include/storage/fsm_internals.h
@@ -0,0 +1,72 @@
+/*-------------------------------------------------------------------------
+ *
+ * fsm_internals.h
+ * internal functions for free space map
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/fsm_internals.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FSM_INTERNALS_H
+#define FSM_INTERNALS_H
+
+#include "storage/buf.h"
+#include "storage/bufpage.h"
+
+/*
+ * Structure of a FSM page. See src/backend/storage/freespace/README for
+ * details.
+ */
+typedef struct
+{
+ /*
+ * fsm_search_avail() tries to spread the load of multiple backends by
+ * returning different pages to different backends in a round-robin
+ * fashion. fp_next_slot points to the next slot to be returned (assuming
+ * there's enough space on it for the request). It's defined as an int,
+ * because it's updated without an exclusive lock. uint16 would be more
+ * appropriate, but int is more likely to be atomically
+ * fetchable/storable.
+ */
+ int fp_next_slot;
+
+ /*
+ * fp_nodes contains the binary tree, stored in array. The first
+ * NonLeafNodesPerPage elements are upper nodes, and the following
+ * LeafNodesPerPage elements are leaf nodes. Unused nodes are zero.
+ */
+ uint8 fp_nodes[FLEXIBLE_ARRAY_MEMBER];
+} FSMPageData;
+
+typedef FSMPageData *FSMPage;
+
+/*
+ * Number of non-leaf and leaf nodes, and nodes in total, on an FSM page.
+ * These definitions are internal to fsmpage.c.
+ */
+#define NodesPerPage (BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - \
+ offsetof(FSMPageData, fp_nodes))
+
+#define NonLeafNodesPerPage (BLCKSZ / 2 - 1)
+#define LeafNodesPerPage (NodesPerPage - NonLeafNodesPerPage)
+
+/*
+ * Number of FSM "slots" on a FSM page. This is what should be used
+ * outside fsmpage.c.
+ */
+#define SlotsPerFSMPage LeafNodesPerPage
+
+/* Prototypes for functions in fsmpage.c */
+extern int fsm_search_avail(Buffer buf, uint8 min_cat, bool advancenext,
+ bool exclusive_lock_held);
+extern uint8 fsm_get_avail(Page page, int slot);
+extern uint8 fsm_get_max_avail(Page page);
+extern bool fsm_set_avail(Page page, int slot, uint8 value);
+extern bool fsm_truncate_avail(Page page, int nslots);
+extern bool fsm_rebuild_page(Page page);
+
+#endif /* FSM_INTERNALS_H */
diff --git a/src/include/storage/indexfsm.h b/src/include/storage/indexfsm.h
new file mode 100644
index 0000000..fb896b4
--- /dev/null
+++ b/src/include/storage/indexfsm.h
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ *
+ * indexfsm.h
+ * POSTGRES free space map for quickly finding an unused page in index
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/indexfsm.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef INDEXFSM_H_
+#define INDEXFSM_H_
+
+#include "storage/block.h"
+#include "utils/relcache.h"
+
+extern BlockNumber GetFreeIndexPage(Relation rel);
+extern void RecordFreeIndexPage(Relation rel, BlockNumber page);
+extern void RecordUsedIndexPage(Relation rel, BlockNumber page);
+
+extern void IndexFreeSpaceMapVacuum(Relation rel);
+
+#endif /* INDEXFSM_H_ */
diff --git a/src/include/storage/ipc.h b/src/include/storage/ipc.h
new file mode 100644
index 0000000..462fe46
--- /dev/null
+++ b/src/include/storage/ipc.h
@@ -0,0 +1,81 @@
+/*-------------------------------------------------------------------------
+ *
+ * ipc.h
+ * POSTGRES inter-process communication definitions.
+ *
+ * This file is misnamed, as it no longer has much of anything directly
+ * to do with IPC. The functionality here is concerned with managing
+ * exit-time cleanup for either a postmaster or a backend.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/ipc.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef IPC_H
+#define IPC_H
+
+typedef void (*pg_on_exit_callback) (int code, Datum arg);
+typedef void (*shmem_startup_hook_type) (void);
+
+/*----------
+ * API for handling cleanup that must occur during either ereport(ERROR)
+ * or ereport(FATAL) exits from a block of code. (Typical examples are
+ * undoing transient changes to shared-memory state.)
+ *
+ * PG_ENSURE_ERROR_CLEANUP(cleanup_function, arg);
+ * {
+ * ... code that might throw ereport(ERROR) or ereport(FATAL) ...
+ * }
+ * PG_END_ENSURE_ERROR_CLEANUP(cleanup_function, arg);
+ *
+ * where the cleanup code is in a function declared per pg_on_exit_callback.
+ * The Datum value "arg" can carry any information the cleanup function
+ * needs.
+ *
+ * This construct ensures that cleanup_function() will be called during
+ * either ERROR or FATAL exits. It will not be called on successful
+ * exit from the controlled code. (If you want it to happen then too,
+ * call the function yourself from just after the construct.)
+ *
+ * Note: the macro arguments are multiply evaluated, so avoid side-effects.
+ *----------
+ */
+#define PG_ENSURE_ERROR_CLEANUP(cleanup_function, arg) \
+ do { \
+ before_shmem_exit(cleanup_function, arg); \
+ PG_TRY()
+
+#define PG_END_ENSURE_ERROR_CLEANUP(cleanup_function, arg) \
+ cancel_before_shmem_exit(cleanup_function, arg); \
+ PG_CATCH(); \
+ { \
+ cancel_before_shmem_exit(cleanup_function, arg); \
+ cleanup_function (0, arg); \
+ PG_RE_THROW(); \
+ } \
+ PG_END_TRY(); \
+ } while (0)
+
+
+/* ipc.c */
+extern PGDLLIMPORT bool proc_exit_inprogress;
+extern PGDLLIMPORT bool shmem_exit_inprogress;
+
+extern void proc_exit(int code) pg_attribute_noreturn();
+extern void shmem_exit(int code);
+extern void on_proc_exit(pg_on_exit_callback function, Datum arg);
+extern void on_shmem_exit(pg_on_exit_callback function, Datum arg);
+extern void before_shmem_exit(pg_on_exit_callback function, Datum arg);
+extern void cancel_before_shmem_exit(pg_on_exit_callback function, Datum arg);
+extern void on_exit_reset(void);
+
+/* ipci.c */
+extern PGDLLIMPORT shmem_startup_hook_type shmem_startup_hook;
+
+extern void CreateSharedMemoryAndSemaphores(void);
+
+#endif /* IPC_H */
diff --git a/src/include/storage/item.h b/src/include/storage/item.h
new file mode 100644
index 0000000..43a4726
--- /dev/null
+++ b/src/include/storage/item.h
@@ -0,0 +1,19 @@
+/*-------------------------------------------------------------------------
+ *
+ * item.h
+ * POSTGRES disk item definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/item.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ITEM_H
+#define ITEM_H
+
+typedef Pointer Item;
+
+#endif /* ITEM_H */
diff --git a/src/include/storage/itemid.h b/src/include/storage/itemid.h
new file mode 100644
index 0000000..5b0229b
--- /dev/null
+++ b/src/include/storage/itemid.h
@@ -0,0 +1,184 @@
+/*-------------------------------------------------------------------------
+ *
+ * itemid.h
+ * Standard POSTGRES buffer page item identifier/line pointer definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/itemid.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ITEMID_H
+#define ITEMID_H
+
+/*
+ * A line pointer on a buffer page. See buffer page definitions and comments
+ * for an explanation of how line pointers are used.
+ *
+ * In some cases a line pointer is "in use" but does not have any associated
+ * storage on the page. By convention, lp_len == 0 in every line pointer
+ * that does not have storage, independently of its lp_flags state.
+ */
+typedef struct ItemIdData
+{
+ unsigned lp_off:15, /* offset to tuple (from start of page) */
+ lp_flags:2, /* state of line pointer, see below */
+ lp_len:15; /* byte length of tuple */
+} ItemIdData;
+
+typedef ItemIdData *ItemId;
+
+/*
+ * lp_flags has these possible states. An UNUSED line pointer is available
+ * for immediate re-use, the other states are not.
+ */
+#define LP_UNUSED 0 /* unused (should always have lp_len=0) */
+#define LP_NORMAL 1 /* used (should always have lp_len>0) */
+#define LP_REDIRECT 2 /* HOT redirect (should have lp_len=0) */
+#define LP_DEAD 3 /* dead, may or may not have storage */
+
+/*
+ * Item offsets and lengths are represented by these types when
+ * they're not actually stored in an ItemIdData.
+ */
+typedef uint16 ItemOffset;
+typedef uint16 ItemLength;
+
+
+/* ----------------
+ * support macros
+ * ----------------
+ */
+
+/*
+ * ItemIdGetLength
+ */
+#define ItemIdGetLength(itemId) \
+ ((itemId)->lp_len)
+
+/*
+ * ItemIdGetOffset
+ */
+#define ItemIdGetOffset(itemId) \
+ ((itemId)->lp_off)
+
+/*
+ * ItemIdGetFlags
+ */
+#define ItemIdGetFlags(itemId) \
+ ((itemId)->lp_flags)
+
+/*
+ * ItemIdGetRedirect
+ * In a REDIRECT pointer, lp_off holds offset number for next line pointer
+ */
+#define ItemIdGetRedirect(itemId) \
+ ((itemId)->lp_off)
+
+/*
+ * ItemIdIsValid
+ * True iff item identifier is valid.
+ * This is a pretty weak test, probably useful only in Asserts.
+ */
+#define ItemIdIsValid(itemId) PointerIsValid(itemId)
+
+/*
+ * ItemIdIsUsed
+ * True iff item identifier is in use.
+ */
+#define ItemIdIsUsed(itemId) \
+ ((itemId)->lp_flags != LP_UNUSED)
+
+/*
+ * ItemIdIsNormal
+ * True iff item identifier is in state NORMAL.
+ */
+#define ItemIdIsNormal(itemId) \
+ ((itemId)->lp_flags == LP_NORMAL)
+
+/*
+ * ItemIdIsRedirected
+ * True iff item identifier is in state REDIRECT.
+ */
+#define ItemIdIsRedirected(itemId) \
+ ((itemId)->lp_flags == LP_REDIRECT)
+
+/*
+ * ItemIdIsDead
+ * True iff item identifier is in state DEAD.
+ */
+#define ItemIdIsDead(itemId) \
+ ((itemId)->lp_flags == LP_DEAD)
+
+/*
+ * ItemIdHasStorage
+ * True iff item identifier has associated storage.
+ */
+#define ItemIdHasStorage(itemId) \
+ ((itemId)->lp_len != 0)
+
+/*
+ * ItemIdSetUnused
+ * Set the item identifier to be UNUSED, with no storage.
+ * Beware of multiple evaluations of itemId!
+ */
+#define ItemIdSetUnused(itemId) \
+( \
+ (itemId)->lp_flags = LP_UNUSED, \
+ (itemId)->lp_off = 0, \
+ (itemId)->lp_len = 0 \
+)
+
+/*
+ * ItemIdSetNormal
+ * Set the item identifier to be NORMAL, with the specified storage.
+ * Beware of multiple evaluations of itemId!
+ */
+#define ItemIdSetNormal(itemId, off, len) \
+( \
+ (itemId)->lp_flags = LP_NORMAL, \
+ (itemId)->lp_off = (off), \
+ (itemId)->lp_len = (len) \
+)
+
+/*
+ * ItemIdSetRedirect
+ * Set the item identifier to be REDIRECT, with the specified link.
+ * Beware of multiple evaluations of itemId!
+ */
+#define ItemIdSetRedirect(itemId, link) \
+( \
+ (itemId)->lp_flags = LP_REDIRECT, \
+ (itemId)->lp_off = (link), \
+ (itemId)->lp_len = 0 \
+)
+
+/*
+ * ItemIdSetDead
+ * Set the item identifier to be DEAD, with no storage.
+ * Beware of multiple evaluations of itemId!
+ */
+#define ItemIdSetDead(itemId) \
+( \
+ (itemId)->lp_flags = LP_DEAD, \
+ (itemId)->lp_off = 0, \
+ (itemId)->lp_len = 0 \
+)
+
+/*
+ * ItemIdMarkDead
+ * Set the item identifier to be DEAD, keeping its existing storage.
+ *
+ * Note: in indexes, this is used as if it were a hint-bit mechanism;
+ * we trust that multiple processors can do this in parallel and get
+ * the same result.
+ */
+#define ItemIdMarkDead(itemId) \
+( \
+ (itemId)->lp_flags = LP_DEAD \
+)
+
+#endif /* ITEMID_H */
diff --git a/src/include/storage/itemptr.h b/src/include/storage/itemptr.h
new file mode 100644
index 0000000..944f6fe
--- /dev/null
+++ b/src/include/storage/itemptr.h
@@ -0,0 +1,206 @@
+/*-------------------------------------------------------------------------
+ *
+ * itemptr.h
+ * POSTGRES disk item pointer definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/itemptr.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ITEMPTR_H
+#define ITEMPTR_H
+
+#include "storage/block.h"
+#include "storage/off.h"
+
+/*
+ * ItemPointer:
+ *
+ * This is a pointer to an item within a disk page of a known file
+ * (for example, a cross-link from an index to its parent table).
+ * ip_blkid tells us which block, ip_posid tells us which entry in
+ * the linp (ItemIdData) array we want.
+ *
+ * Note: because there is an item pointer in each tuple header and index
+ * tuple header on disk, it's very important not to waste space with
+ * structure padding bytes. The struct is designed to be six bytes long
+ * (it contains three int16 fields) but a few compilers will pad it to
+ * eight bytes unless coerced. We apply appropriate persuasion where
+ * possible. If your compiler can't be made to play along, you'll waste
+ * lots of space.
+ */
+typedef struct ItemPointerData
+{
+ BlockIdData ip_blkid;
+ OffsetNumber ip_posid;
+}
+
+/* If compiler understands packed and aligned pragmas, use those */
+#if defined(pg_attribute_packed) && defined(pg_attribute_aligned)
+ pg_attribute_packed()
+ pg_attribute_aligned(2)
+#endif
+ItemPointerData;
+
+typedef ItemPointerData *ItemPointer;
+
+/* ----------------
+ * special values used in heap tuples (t_ctid)
+ * ----------------
+ */
+
+/*
+ * If a heap tuple holds a speculative insertion token rather than a real
+ * TID, ip_posid is set to SpecTokenOffsetNumber, and the token is stored in
+ * ip_blkid. SpecTokenOffsetNumber must be higher than MaxOffsetNumber, so
+ * that it can be distinguished from a valid offset number in a regular item
+ * pointer.
+ */
+#define SpecTokenOffsetNumber 0xfffe
+
+/*
+ * When a tuple is moved to a different partition by UPDATE, the t_ctid of
+ * the old tuple version is set to this magic value.
+ */
+#define MovedPartitionsOffsetNumber 0xfffd
+#define MovedPartitionsBlockNumber InvalidBlockNumber
+
+
+/* ----------------
+ * support macros
+ * ----------------
+ */
+
+/*
+ * ItemPointerIsValid
+ * True iff the disk item pointer is not NULL.
+ */
+#define ItemPointerIsValid(pointer) \
+ ((bool) (PointerIsValid(pointer) && ((pointer)->ip_posid != 0)))
+
+/*
+ * ItemPointerGetBlockNumberNoCheck
+ * Returns the block number of a disk item pointer.
+ */
+#define ItemPointerGetBlockNumberNoCheck(pointer) \
+( \
+ BlockIdGetBlockNumber(&(pointer)->ip_blkid) \
+)
+
+/*
+ * ItemPointerGetBlockNumber
+ * As above, but verifies that the item pointer looks valid.
+ */
+#define ItemPointerGetBlockNumber(pointer) \
+( \
+ AssertMacro(ItemPointerIsValid(pointer)), \
+ ItemPointerGetBlockNumberNoCheck(pointer) \
+)
+
+/*
+ * ItemPointerGetOffsetNumberNoCheck
+ * Returns the offset number of a disk item pointer.
+ */
+#define ItemPointerGetOffsetNumberNoCheck(pointer) \
+( \
+ (pointer)->ip_posid \
+)
+
+/*
+ * ItemPointerGetOffsetNumber
+ * As above, but verifies that the item pointer looks valid.
+ */
+#define ItemPointerGetOffsetNumber(pointer) \
+( \
+ AssertMacro(ItemPointerIsValid(pointer)), \
+ ItemPointerGetOffsetNumberNoCheck(pointer) \
+)
+
+/*
+ * ItemPointerSet
+ * Sets a disk item pointer to the specified block and offset.
+ */
+#define ItemPointerSet(pointer, blockNumber, offNum) \
+( \
+ AssertMacro(PointerIsValid(pointer)), \
+ BlockIdSet(&((pointer)->ip_blkid), blockNumber), \
+ (pointer)->ip_posid = offNum \
+)
+
+/*
+ * ItemPointerSetBlockNumber
+ * Sets a disk item pointer to the specified block.
+ */
+#define ItemPointerSetBlockNumber(pointer, blockNumber) \
+( \
+ AssertMacro(PointerIsValid(pointer)), \
+ BlockIdSet(&((pointer)->ip_blkid), blockNumber) \
+)
+
+/*
+ * ItemPointerSetOffsetNumber
+ * Sets a disk item pointer to the specified offset.
+ */
+#define ItemPointerSetOffsetNumber(pointer, offsetNumber) \
+( \
+ AssertMacro(PointerIsValid(pointer)), \
+ (pointer)->ip_posid = (offsetNumber) \
+)
+
+/*
+ * ItemPointerCopy
+ * Copies the contents of one disk item pointer to another.
+ *
+ * Should there ever be padding in an ItemPointer this would need to be handled
+ * differently as it's used as hash key.
+ */
+#define ItemPointerCopy(fromPointer, toPointer) \
+( \
+ AssertMacro(PointerIsValid(toPointer)), \
+ AssertMacro(PointerIsValid(fromPointer)), \
+ *(toPointer) = *(fromPointer) \
+)
+
+/*
+ * ItemPointerSetInvalid
+ * Sets a disk item pointer to be invalid.
+ */
+#define ItemPointerSetInvalid(pointer) \
+( \
+ AssertMacro(PointerIsValid(pointer)), \
+ BlockIdSet(&((pointer)->ip_blkid), InvalidBlockNumber), \
+ (pointer)->ip_posid = InvalidOffsetNumber \
+)
+
+/*
+ * ItemPointerIndicatesMovedPartitions
+ * True iff the block number indicates the tuple has moved to another
+ * partition.
+ */
+#define ItemPointerIndicatesMovedPartitions(pointer) \
+( \
+ ItemPointerGetOffsetNumber(pointer) == MovedPartitionsOffsetNumber && \
+ ItemPointerGetBlockNumberNoCheck(pointer) == MovedPartitionsBlockNumber \
+)
+
+/*
+ * ItemPointerSetMovedPartitions
+ * Indicate that the item referenced by the itempointer has moved into a
+ * different partition.
+ */
+#define ItemPointerSetMovedPartitions(pointer) \
+ ItemPointerSet((pointer), MovedPartitionsBlockNumber, MovedPartitionsOffsetNumber)
+
+/* ----------------
+ * externs
+ * ----------------
+ */
+
+extern bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2);
+extern int32 ItemPointerCompare(ItemPointer arg1, ItemPointer arg2);
+
+#endif /* ITEMPTR_H */
diff --git a/src/include/storage/large_object.h b/src/include/storage/large_object.h
new file mode 100644
index 0000000..2623d1a
--- /dev/null
+++ b/src/include/storage/large_object.h
@@ -0,0 +1,100 @@
+/*-------------------------------------------------------------------------
+ *
+ * large_object.h
+ * Declarations for PostgreSQL large objects. POSTGRES 4.2 supported
+ * zillions of large objects (internal, external, jaquith, inversion).
+ * Now we only support inversion.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/large_object.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LARGE_OBJECT_H
+#define LARGE_OBJECT_H
+
+#include "utils/snapshot.h"
+
+
+/*----------
+ * Data about a currently-open large object.
+ *
+ * id is the logical OID of the large object
+ * snapshot is the snapshot to use for read/write operations
+ * subid is the subtransaction that opened the desc (or currently owns it)
+ * offset is the current seek offset within the LO
+ * flags contains some flag bits
+ *
+ * NOTE: as of v11, permission checks are made when the large object is
+ * opened; therefore IFS_RDLOCK/IFS_WRLOCK indicate that read or write mode
+ * has been requested *and* the corresponding permission has been checked.
+ *
+ * NOTE: before 7.1, we also had to store references to the separate table
+ * and index of a specific large object. Now they all live in pg_largeobject
+ * and are accessed via a common relation descriptor.
+ *----------
+ */
+typedef struct LargeObjectDesc
+{
+ Oid id; /* LO's identifier */
+ Snapshot snapshot; /* snapshot to use */
+ SubTransactionId subid; /* owning subtransaction ID */
+ uint64 offset; /* current seek pointer */
+ int flags; /* see flag bits below */
+
+/* bits in flags: */
+#define IFS_RDLOCK (1 << 0) /* LO was opened for reading */
+#define IFS_WRLOCK (1 << 1) /* LO was opened for writing */
+
+} LargeObjectDesc;
+
+
+/*
+ * Each "page" (tuple) of a large object can hold this much data
+ *
+ * We could set this as high as BLCKSZ less some overhead, but it seems
+ * better to make it a smaller value, so that not as much space is used
+ * up when a page-tuple is updated. Note that the value is deliberately
+ * chosen large enough to trigger the tuple toaster, so that we will
+ * attempt to compress page tuples in-line. (But they won't be moved off
+ * unless the user creates a toast-table for pg_largeobject...)
+ *
+ * Also, it seems to be a smart move to make the page size be a power of 2,
+ * since clients will often be written to send data in power-of-2 blocks.
+ * This avoids unnecessary tuple updates caused by partial-page writes.
+ *
+ * NB: Changing LOBLKSIZE requires an initdb.
+ */
+#define LOBLKSIZE (BLCKSZ / 4)
+
+/*
+ * Maximum length in bytes for a large object. To make this larger, we'd
+ * have to widen pg_largeobject.pageno as well as various internal variables.
+ */
+#define MAX_LARGE_OBJECT_SIZE ((int64) INT_MAX * LOBLKSIZE)
+
+
+/*
+ * GUC: backwards-compatibility flag to suppress LO permission checks
+ */
+extern bool lo_compat_privileges;
+
+/*
+ * Function definitions...
+ */
+
+/* inversion stuff in inv_api.c */
+extern void close_lo_relation(bool isCommit);
+extern Oid inv_create(Oid lobjId);
+extern LargeObjectDesc *inv_open(Oid lobjId, int flags, MemoryContext mcxt);
+extern void inv_close(LargeObjectDesc *obj_desc);
+extern int inv_drop(Oid lobjId);
+extern int64 inv_seek(LargeObjectDesc *obj_desc, int64 offset, int whence);
+extern int64 inv_tell(LargeObjectDesc *obj_desc);
+extern int inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes);
+extern int inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes);
+extern void inv_truncate(LargeObjectDesc *obj_desc, int64 len);
+
+#endif /* LARGE_OBJECT_H */
diff --git a/src/include/storage/latch.h b/src/include/storage/latch.h
new file mode 100644
index 0000000..46ae56c
--- /dev/null
+++ b/src/include/storage/latch.h
@@ -0,0 +1,190 @@
+/*-------------------------------------------------------------------------
+ *
+ * latch.h
+ * Routines for interprocess latches
+ *
+ * A latch is a boolean variable, with operations that let processes sleep
+ * until it is set. A latch can be set from another process, or a signal
+ * handler within the same process.
+ *
+ * The latch interface is a reliable replacement for the common pattern of
+ * using pg_usleep() or select() to wait until a signal arrives, where the
+ * signal handler sets a flag variable. Because on some platforms an
+ * incoming signal doesn't interrupt sleep, and even on platforms where it
+ * does there is a race condition if the signal arrives just before
+ * entering the sleep, the common pattern must periodically wake up and
+ * poll the flag variable. The pselect() system call was invented to solve
+ * this problem, but it is not portable enough. Latches are designed to
+ * overcome these limitations, allowing you to sleep without polling and
+ * ensuring quick response to signals from other processes.
+ *
+ * There are two kinds of latches: local and shared. A local latch is
+ * initialized by InitLatch, and can only be set from the same process.
+ * A local latch can be used to wait for a signal to arrive, by calling
+ * SetLatch in the signal handler. A shared latch resides in shared memory,
+ * and must be initialized at postmaster startup by InitSharedLatch. Before
+ * a shared latch can be waited on, it must be associated with a process
+ * with OwnLatch. Only the process owning the latch can wait on it, but any
+ * process can set it.
+ *
+ * There are three basic operations on a latch:
+ *
+ * SetLatch - Sets the latch
+ * ResetLatch - Clears the latch, allowing it to be set again
+ * WaitLatch - Waits for the latch to become set
+ *
+ * WaitLatch includes a provision for timeouts (which should be avoided
+ * when possible, as they incur extra overhead) and a provision for
+ * postmaster child processes to wake up immediately on postmaster death.
+ * See latch.c for detailed specifications for the exported functions.
+ *
+ * The correct pattern to wait for event(s) is:
+ *
+ * for (;;)
+ * {
+ * ResetLatch();
+ * if (work to do)
+ * Do Stuff();
+ * WaitLatch();
+ * }
+ *
+ * It's important to reset the latch *before* checking if there's work to
+ * do. Otherwise, if someone sets the latch between the check and the
+ * ResetLatch call, you will miss it and Wait will incorrectly block.
+ *
+ * Another valid coding pattern looks like:
+ *
+ * for (;;)
+ * {
+ * if (work to do)
+ * Do Stuff(); // in particular, exit loop if some condition satisfied
+ * WaitLatch();
+ * ResetLatch();
+ * }
+ *
+ * This is useful to reduce latch traffic if it's expected that the loop's
+ * termination condition will often be satisfied in the first iteration;
+ * the cost is an extra loop iteration before blocking when it is not.
+ * What must be avoided is placing any checks for asynchronous events after
+ * WaitLatch and before ResetLatch, as that creates a race condition.
+ *
+ * To wake up the waiter, you must first set a global flag or something
+ * else that the wait loop tests in the "if (work to do)" part, and call
+ * SetLatch *after* that. SetLatch is designed to return quickly if the
+ * latch is already set.
+ *
+ * On some platforms, signals will not interrupt the latch wait primitive
+ * by themselves. Therefore, it is critical that any signal handler that
+ * is meant to terminate a WaitLatch wait calls SetLatch.
+ *
+ * Note that use of the process latch (PGPROC.procLatch) is generally better
+ * than an ad-hoc shared latch for signaling auxiliary processes. This is
+ * because generic signal handlers will call SetLatch on the process latch
+ * only, so using any latch other than the process latch effectively precludes
+ * use of any generic handler.
+ *
+ *
+ * WaitEventSets allow to wait for latches being set and additional events -
+ * postmaster dying and socket readiness of several sockets currently - at the
+ * same time. On many platforms using a long lived event set is more
+ * efficient than using WaitLatch or WaitLatchOrSocket.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/latch.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LATCH_H
+#define LATCH_H
+
+#include <signal.h>
+
+/*
+ * Latch structure should be treated as opaque and only accessed through
+ * the public functions. It is defined here to allow embedding Latches as
+ * part of bigger structs.
+ */
+typedef struct Latch
+{
+ sig_atomic_t is_set;
+ bool is_shared;
+ int owner_pid;
+#ifdef WIN32
+ HANDLE event;
+#endif
+} Latch;
+
+/*
+ * Bitmasks for events that may wake-up WaitLatch(), WaitLatchOrSocket(), or
+ * WaitEventSetWait().
+ */
+#define WL_LATCH_SET (1 << 0)
+#define WL_SOCKET_READABLE (1 << 1)
+#define WL_SOCKET_WRITEABLE (1 << 2)
+#define WL_TIMEOUT (1 << 3) /* not for WaitEventSetWait() */
+#define WL_POSTMASTER_DEATH (1 << 4)
+#define WL_EXIT_ON_PM_DEATH (1 << 5)
+#ifdef WIN32
+#define WL_SOCKET_CONNECTED (1 << 6)
+#else
+/* avoid having to deal with case on platforms not requiring it */
+#define WL_SOCKET_CONNECTED WL_SOCKET_WRITEABLE
+#endif
+
+#define WL_SOCKET_MASK (WL_SOCKET_READABLE | \
+ WL_SOCKET_WRITEABLE | \
+ WL_SOCKET_CONNECTED)
+
+typedef struct WaitEvent
+{
+ int pos; /* position in the event data structure */
+ uint32 events; /* triggered events */
+ pgsocket fd; /* socket fd associated with event */
+ void *user_data; /* pointer provided in AddWaitEventToSet */
+#ifdef WIN32
+ bool reset; /* Is reset of the event required? */
+#endif
+} WaitEvent;
+
+/* forward declaration to avoid exposing latch.c implementation details */
+typedef struct WaitEventSet WaitEventSet;
+
+/*
+ * prototypes for functions in latch.c
+ */
+extern void InitializeLatchSupport(void);
+extern void InitLatch(Latch *latch);
+extern void InitSharedLatch(Latch *latch);
+extern void OwnLatch(Latch *latch);
+extern void DisownLatch(Latch *latch);
+extern void SetLatch(Latch *latch);
+extern void ResetLatch(Latch *latch);
+
+extern WaitEventSet *CreateWaitEventSet(MemoryContext context, int nevents);
+extern void FreeWaitEventSet(WaitEventSet *set);
+extern int AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd,
+ Latch *latch, void *user_data);
+extern void ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch);
+
+extern int WaitEventSetWait(WaitEventSet *set, long timeout,
+ WaitEvent *occurred_events, int nevents,
+ uint32 wait_event_info);
+extern int WaitLatch(Latch *latch, int wakeEvents, long timeout,
+ uint32 wait_event_info);
+extern int WaitLatchOrSocket(Latch *latch, int wakeEvents,
+ pgsocket sock, long timeout, uint32 wait_event_info);
+
+/*
+ * Unix implementation uses SIGUSR1 for inter-process signaling.
+ * Win32 doesn't need this.
+ */
+#ifndef WIN32
+extern void latch_sigusr1_handler(void);
+#else
+#define latch_sigusr1_handler() ((void) 0)
+#endif
+
+#endif /* LATCH_H */
diff --git a/src/include/storage/lmgr.h b/src/include/storage/lmgr.h
new file mode 100644
index 0000000..f7cabcb
--- /dev/null
+++ b/src/include/storage/lmgr.h
@@ -0,0 +1,114 @@
+/*-------------------------------------------------------------------------
+ *
+ * lmgr.h
+ * POSTGRES lock manager definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/lmgr.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LMGR_H
+#define LMGR_H
+
+#include "lib/stringinfo.h"
+#include "storage/itemptr.h"
+#include "storage/lock.h"
+#include "utils/rel.h"
+
+
+/* XactLockTableWait operations */
+typedef enum XLTW_Oper
+{
+ XLTW_None,
+ XLTW_Update,
+ XLTW_Delete,
+ XLTW_Lock,
+ XLTW_LockUpdated,
+ XLTW_InsertIndex,
+ XLTW_InsertIndexUnique,
+ XLTW_FetchUpdated,
+ XLTW_RecheckExclusionConstr
+} XLTW_Oper;
+
+extern void RelationInitLockInfo(Relation relation);
+
+/* Lock a relation */
+extern void LockRelationOid(Oid relid, LOCKMODE lockmode);
+extern bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode);
+extern void UnlockRelationId(LockRelId *relid, LOCKMODE lockmode);
+extern void UnlockRelationOid(Oid relid, LOCKMODE lockmode);
+
+extern void LockRelation(Relation relation, LOCKMODE lockmode);
+extern bool ConditionalLockRelation(Relation relation, LOCKMODE lockmode);
+extern void UnlockRelation(Relation relation, LOCKMODE lockmode);
+extern bool CheckRelationLockedByMe(Relation relation, LOCKMODE lockmode,
+ bool orstronger);
+extern bool LockHasWaitersRelation(Relation relation, LOCKMODE lockmode);
+
+extern void LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode);
+extern void UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode);
+
+/* Lock a relation for extension */
+extern void LockRelationForExtension(Relation relation, LOCKMODE lockmode);
+extern void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode);
+extern bool ConditionalLockRelationForExtension(Relation relation,
+ LOCKMODE lockmode);
+extern int RelationExtensionLockWaiterCount(Relation relation);
+
+/* Lock to recompute pg_database.datfrozenxid in the current database */
+extern void LockDatabaseFrozenIds(LOCKMODE lockmode);
+
+/* Lock a page (currently only used within indexes) */
+extern void LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
+extern bool ConditionalLockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
+extern void UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
+
+/* Lock a tuple (see heap_lock_tuple before assuming you understand this) */
+extern void LockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode);
+extern bool ConditionalLockTuple(Relation relation, ItemPointer tid,
+ LOCKMODE lockmode);
+extern void UnlockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode);
+
+/* Lock an XID (used to wait for a transaction to finish) */
+extern void XactLockTableInsert(TransactionId xid);
+extern void XactLockTableDelete(TransactionId xid);
+extern void XactLockTableWait(TransactionId xid, Relation rel,
+ ItemPointer ctid, XLTW_Oper oper);
+extern bool ConditionalXactLockTableWait(TransactionId xid);
+
+/* Lock VXIDs, specified by conflicting locktags */
+extern void WaitForLockers(LOCKTAG heaplocktag, LOCKMODE lockmode, bool progress);
+extern void WaitForLockersMultiple(List *locktags, LOCKMODE lockmode, bool progress);
+
+/* Lock an XID for tuple insertion (used to wait for an insertion to finish) */
+extern uint32 SpeculativeInsertionLockAcquire(TransactionId xid);
+extern void SpeculativeInsertionLockRelease(TransactionId xid);
+extern void SpeculativeInsertionWait(TransactionId xid, uint32 token);
+
+/* Lock a general object (other than a relation) of the current database */
+extern void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
+ LOCKMODE lockmode);
+extern void UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
+ LOCKMODE lockmode);
+
+/* Lock a shared-across-databases object (other than a relation) */
+extern void LockSharedObject(Oid classid, Oid objid, uint16 objsubid,
+ LOCKMODE lockmode);
+extern void UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid,
+ LOCKMODE lockmode);
+
+extern void LockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid,
+ LOCKMODE lockmode);
+extern void UnlockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid,
+ LOCKMODE lockmode);
+
+/* Describe a locktag for error messages */
+extern void DescribeLockTag(StringInfo buf, const LOCKTAG *tag);
+
+extern const char *GetLockNameFromTagType(uint16 locktag_type);
+
+#endif /* LMGR_H */
diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h
new file mode 100644
index 0000000..2987c5e
--- /dev/null
+++ b/src/include/storage/lock.h
@@ -0,0 +1,612 @@
+/*-------------------------------------------------------------------------
+ *
+ * lock.h
+ * POSTGRES low-level lock mechanism
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/lock.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LOCK_H_
+#define LOCK_H_
+
+#ifdef FRONTEND
+#error "lock.h may not be included from frontend code"
+#endif
+
+#include "storage/backendid.h"
+#include "storage/lockdefs.h"
+#include "storage/lwlock.h"
+#include "storage/shmem.h"
+
+/* struct PGPROC is declared in proc.h, but must forward-reference it */
+typedef struct PGPROC PGPROC;
+
+typedef struct PROC_QUEUE
+{
+ SHM_QUEUE links; /* head of list of PGPROC objects */
+ int size; /* number of entries in list */
+} PROC_QUEUE;
+
+/* GUC variables */
+extern int max_locks_per_xact;
+
+#ifdef LOCK_DEBUG
+extern int Trace_lock_oidmin;
+extern bool Trace_locks;
+extern bool Trace_userlocks;
+extern int Trace_lock_table;
+extern bool Debug_deadlocks;
+#endif /* LOCK_DEBUG */
+
+
+/*
+ * Top-level transactions are identified by VirtualTransactionIDs comprising
+ * PGPROC fields backendId and lxid. For prepared transactions, the
+ * LocalTransactionId is an ordinary XID. These are guaranteed unique over
+ * the short term, but will be reused after a database restart or XID
+ * wraparound; hence they should never be stored on disk.
+ *
+ * Note that struct VirtualTransactionId can not be assumed to be atomically
+ * assignable as a whole. However, type LocalTransactionId is assumed to
+ * be atomically assignable, and the backend ID doesn't change often enough
+ * to be a problem, so we can fetch or assign the two fields separately.
+ * We deliberately refrain from using the struct within PGPROC, to prevent
+ * coding errors from trying to use struct assignment with it; instead use
+ * GET_VXID_FROM_PGPROC().
+ */
+typedef struct
+{
+ BackendId backendId; /* backendId from PGPROC */
+ LocalTransactionId localTransactionId; /* lxid from PGPROC */
+} VirtualTransactionId;
+
+#define InvalidLocalTransactionId 0
+#define LocalTransactionIdIsValid(lxid) ((lxid) != InvalidLocalTransactionId)
+#define VirtualTransactionIdIsValid(vxid) \
+ (LocalTransactionIdIsValid((vxid).localTransactionId))
+#define VirtualTransactionIdIsPreparedXact(vxid) \
+ ((vxid).backendId == InvalidBackendId)
+#define VirtualTransactionIdEquals(vxid1, vxid2) \
+ ((vxid1).backendId == (vxid2).backendId && \
+ (vxid1).localTransactionId == (vxid2).localTransactionId)
+#define SetInvalidVirtualTransactionId(vxid) \
+ ((vxid).backendId = InvalidBackendId, \
+ (vxid).localTransactionId = InvalidLocalTransactionId)
+#define GET_VXID_FROM_PGPROC(vxid, proc) \
+ ((vxid).backendId = (proc).backendId, \
+ (vxid).localTransactionId = (proc).lxid)
+
+/* MAX_LOCKMODES cannot be larger than the # of bits in LOCKMASK */
+#define MAX_LOCKMODES 10
+
+#define LOCKBIT_ON(lockmode) (1 << (lockmode))
+#define LOCKBIT_OFF(lockmode) (~(1 << (lockmode)))
+
+
+/*
+ * This data structure defines the locking semantics associated with a
+ * "lock method". The semantics specify the meaning of each lock mode
+ * (by defining which lock modes it conflicts with).
+ * All of this data is constant and is kept in const tables.
+ *
+ * numLockModes -- number of lock modes (READ,WRITE,etc) that
+ * are defined in this lock method. Must be less than MAX_LOCKMODES.
+ *
+ * conflictTab -- this is an array of bitmasks showing lock
+ * mode conflicts. conflictTab[i] is a mask with the j-th bit
+ * turned on if lock modes i and j conflict. Lock modes are
+ * numbered 1..numLockModes; conflictTab[0] is unused.
+ *
+ * lockModeNames -- ID strings for debug printouts.
+ *
+ * trace_flag -- pointer to GUC trace flag for this lock method. (The
+ * GUC variable is not constant, but we use "const" here to denote that
+ * it can't be changed through this reference.)
+ */
+typedef struct LockMethodData
+{
+ int numLockModes;
+ const LOCKMASK *conflictTab;
+ const char *const *lockModeNames;
+ const bool *trace_flag;
+} LockMethodData;
+
+typedef const LockMethodData *LockMethod;
+
+/*
+ * Lock methods are identified by LOCKMETHODID. (Despite the declaration as
+ * uint16, we are constrained to 256 lockmethods by the layout of LOCKTAG.)
+ */
+typedef uint16 LOCKMETHODID;
+
+/* These identify the known lock methods */
+#define DEFAULT_LOCKMETHOD 1
+#define USER_LOCKMETHOD 2
+
+/*
+ * LOCKTAG is the key information needed to look up a LOCK item in the
+ * lock hashtable. A LOCKTAG value uniquely identifies a lockable object.
+ *
+ * The LockTagType enum defines the different kinds of objects we can lock.
+ * We can handle up to 256 different LockTagTypes.
+ */
+typedef enum LockTagType
+{
+ LOCKTAG_RELATION, /* whole relation */
+ LOCKTAG_RELATION_EXTEND, /* the right to extend a relation */
+ LOCKTAG_DATABASE_FROZEN_IDS, /* pg_database.datfrozenxid */
+ LOCKTAG_PAGE, /* one page of a relation */
+ LOCKTAG_TUPLE, /* one physical tuple */
+ LOCKTAG_TRANSACTION, /* transaction (for waiting for xact done) */
+ LOCKTAG_VIRTUALTRANSACTION, /* virtual transaction (ditto) */
+ LOCKTAG_SPECULATIVE_TOKEN, /* speculative insertion Xid and token */
+ LOCKTAG_OBJECT, /* non-relation database object */
+ LOCKTAG_USERLOCK, /* reserved for old contrib/userlock code */
+ LOCKTAG_ADVISORY /* advisory user locks */
+} LockTagType;
+
+#define LOCKTAG_LAST_TYPE LOCKTAG_ADVISORY
+
+extern const char *const LockTagTypeNames[];
+
+/*
+ * The LOCKTAG struct is defined with malice aforethought to fit into 16
+ * bytes with no padding. Note that this would need adjustment if we were
+ * to widen Oid, BlockNumber, or TransactionId to more than 32 bits.
+ *
+ * We include lockmethodid in the locktag so that a single hash table in
+ * shared memory can store locks of different lockmethods.
+ */
+typedef struct LOCKTAG
+{
+ uint32 locktag_field1; /* a 32-bit ID field */
+ uint32 locktag_field2; /* a 32-bit ID field */
+ uint32 locktag_field3; /* a 32-bit ID field */
+ uint16 locktag_field4; /* a 16-bit ID field */
+ uint8 locktag_type; /* see enum LockTagType */
+ uint8 locktag_lockmethodid; /* lockmethod indicator */
+} LOCKTAG;
+
+/*
+ * These macros define how we map logical IDs of lockable objects into
+ * the physical fields of LOCKTAG. Use these to set up LOCKTAG values,
+ * rather than accessing the fields directly. Note multiple eval of target!
+ */
+
+/* ID info for a relation is DB OID + REL OID; DB OID = 0 if shared */
+#define SET_LOCKTAG_RELATION(locktag,dboid,reloid) \
+ ((locktag).locktag_field1 = (dboid), \
+ (locktag).locktag_field2 = (reloid), \
+ (locktag).locktag_field3 = 0, \
+ (locktag).locktag_field4 = 0, \
+ (locktag).locktag_type = LOCKTAG_RELATION, \
+ (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
+
+/* same ID info as RELATION */
+#define SET_LOCKTAG_RELATION_EXTEND(locktag,dboid,reloid) \
+ ((locktag).locktag_field1 = (dboid), \
+ (locktag).locktag_field2 = (reloid), \
+ (locktag).locktag_field3 = 0, \
+ (locktag).locktag_field4 = 0, \
+ (locktag).locktag_type = LOCKTAG_RELATION_EXTEND, \
+ (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
+
+/* ID info for frozen IDs is DB OID */
+#define SET_LOCKTAG_DATABASE_FROZEN_IDS(locktag,dboid) \
+ ((locktag).locktag_field1 = (dboid), \
+ (locktag).locktag_field2 = 0, \
+ (locktag).locktag_field3 = 0, \
+ (locktag).locktag_field4 = 0, \
+ (locktag).locktag_type = LOCKTAG_DATABASE_FROZEN_IDS, \
+ (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
+
+/* ID info for a page is RELATION info + BlockNumber */
+#define SET_LOCKTAG_PAGE(locktag,dboid,reloid,blocknum) \
+ ((locktag).locktag_field1 = (dboid), \
+ (locktag).locktag_field2 = (reloid), \
+ (locktag).locktag_field3 = (blocknum), \
+ (locktag).locktag_field4 = 0, \
+ (locktag).locktag_type = LOCKTAG_PAGE, \
+ (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
+
+/* ID info for a tuple is PAGE info + OffsetNumber */
+#define SET_LOCKTAG_TUPLE(locktag,dboid,reloid,blocknum,offnum) \
+ ((locktag).locktag_field1 = (dboid), \
+ (locktag).locktag_field2 = (reloid), \
+ (locktag).locktag_field3 = (blocknum), \
+ (locktag).locktag_field4 = (offnum), \
+ (locktag).locktag_type = LOCKTAG_TUPLE, \
+ (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
+
+/* ID info for a transaction is its TransactionId */
+#define SET_LOCKTAG_TRANSACTION(locktag,xid) \
+ ((locktag).locktag_field1 = (xid), \
+ (locktag).locktag_field2 = 0, \
+ (locktag).locktag_field3 = 0, \
+ (locktag).locktag_field4 = 0, \
+ (locktag).locktag_type = LOCKTAG_TRANSACTION, \
+ (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
+
+/* ID info for a virtual transaction is its VirtualTransactionId */
+#define SET_LOCKTAG_VIRTUALTRANSACTION(locktag,vxid) \
+ ((locktag).locktag_field1 = (vxid).backendId, \
+ (locktag).locktag_field2 = (vxid).localTransactionId, \
+ (locktag).locktag_field3 = 0, \
+ (locktag).locktag_field4 = 0, \
+ (locktag).locktag_type = LOCKTAG_VIRTUALTRANSACTION, \
+ (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
+
+/*
+ * ID info for a speculative insert is TRANSACTION info +
+ * its speculative insert counter.
+ */
+#define SET_LOCKTAG_SPECULATIVE_INSERTION(locktag,xid,token) \
+ ((locktag).locktag_field1 = (xid), \
+ (locktag).locktag_field2 = (token), \
+ (locktag).locktag_field3 = 0, \
+ (locktag).locktag_field4 = 0, \
+ (locktag).locktag_type = LOCKTAG_SPECULATIVE_TOKEN, \
+ (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
+
+/*
+ * ID info for an object is DB OID + CLASS OID + OBJECT OID + SUBID
+ *
+ * Note: object ID has same representation as in pg_depend and
+ * pg_description, but notice that we are constraining SUBID to 16 bits.
+ * Also, we use DB OID = 0 for shared objects such as tablespaces.
+ */
+#define SET_LOCKTAG_OBJECT(locktag,dboid,classoid,objoid,objsubid) \
+ ((locktag).locktag_field1 = (dboid), \
+ (locktag).locktag_field2 = (classoid), \
+ (locktag).locktag_field3 = (objoid), \
+ (locktag).locktag_field4 = (objsubid), \
+ (locktag).locktag_type = LOCKTAG_OBJECT, \
+ (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
+
+#define SET_LOCKTAG_ADVISORY(locktag,id1,id2,id3,id4) \
+ ((locktag).locktag_field1 = (id1), \
+ (locktag).locktag_field2 = (id2), \
+ (locktag).locktag_field3 = (id3), \
+ (locktag).locktag_field4 = (id4), \
+ (locktag).locktag_type = LOCKTAG_ADVISORY, \
+ (locktag).locktag_lockmethodid = USER_LOCKMETHOD)
+
+
+/*
+ * Per-locked-object lock information:
+ *
+ * tag -- uniquely identifies the object being locked
+ * grantMask -- bitmask for all lock types currently granted on this object.
+ * waitMask -- bitmask for all lock types currently awaited on this object.
+ * procLocks -- list of PROCLOCK objects for this lock.
+ * waitProcs -- queue of processes waiting for this lock.
+ * requested -- count of each lock type currently requested on the lock
+ * (includes requests already granted!!).
+ * nRequested -- total requested locks of all types.
+ * granted -- count of each lock type currently granted on the lock.
+ * nGranted -- total granted locks of all types.
+ *
+ * Note: these counts count 1 for each backend. Internally to a backend,
+ * there may be multiple grabs on a particular lock, but this is not reflected
+ * into shared memory.
+ */
+typedef struct LOCK
+{
+ /* hash key */
+ LOCKTAG tag; /* unique identifier of lockable object */
+
+ /* data */
+ LOCKMASK grantMask; /* bitmask for lock types already granted */
+ LOCKMASK waitMask; /* bitmask for lock types awaited */
+ SHM_QUEUE procLocks; /* list of PROCLOCK objects assoc. with lock */
+ PROC_QUEUE waitProcs; /* list of PGPROC objects waiting on lock */
+ int requested[MAX_LOCKMODES]; /* counts of requested locks */
+ int nRequested; /* total of requested[] array */
+ int granted[MAX_LOCKMODES]; /* counts of granted locks */
+ int nGranted; /* total of granted[] array */
+} LOCK;
+
+#define LOCK_LOCKMETHOD(lock) ((LOCKMETHODID) (lock).tag.locktag_lockmethodid)
+#define LOCK_LOCKTAG(lock) ((LockTagType) (lock).tag.locktag_type)
+
+
+/*
+ * We may have several different backends holding or awaiting locks
+ * on the same lockable object. We need to store some per-holder/waiter
+ * information for each such holder (or would-be holder). This is kept in
+ * a PROCLOCK struct.
+ *
+ * PROCLOCKTAG is the key information needed to look up a PROCLOCK item in the
+ * proclock hashtable. A PROCLOCKTAG value uniquely identifies the combination
+ * of a lockable object and a holder/waiter for that object. (We can use
+ * pointers here because the PROCLOCKTAG need only be unique for the lifespan
+ * of the PROCLOCK, and it will never outlive the lock or the proc.)
+ *
+ * Internally to a backend, it is possible for the same lock to be held
+ * for different purposes: the backend tracks transaction locks separately
+ * from session locks. However, this is not reflected in the shared-memory
+ * state: we only track which backend(s) hold the lock. This is OK since a
+ * backend can never block itself.
+ *
+ * The holdMask field shows the already-granted locks represented by this
+ * proclock. Note that there will be a proclock object, possibly with
+ * zero holdMask, for any lock that the process is currently waiting on.
+ * Otherwise, proclock objects whose holdMasks are zero are recycled
+ * as soon as convenient.
+ *
+ * releaseMask is workspace for LockReleaseAll(): it shows the locks due
+ * to be released during the current call. This must only be examined or
+ * set by the backend owning the PROCLOCK.
+ *
+ * Each PROCLOCK object is linked into lists for both the associated LOCK
+ * object and the owning PGPROC object. Note that the PROCLOCK is entered
+ * into these lists as soon as it is created, even if no lock has yet been
+ * granted. A PGPROC that is waiting for a lock to be granted will also be
+ * linked into the lock's waitProcs queue.
+ */
+typedef struct PROCLOCKTAG
+{
+ /* NB: we assume this struct contains no padding! */
+ LOCK *myLock; /* link to per-lockable-object information */
+ PGPROC *myProc; /* link to PGPROC of owning backend */
+} PROCLOCKTAG;
+
+typedef struct PROCLOCK
+{
+ /* tag */
+ PROCLOCKTAG tag; /* unique identifier of proclock object */
+
+ /* data */
+ PGPROC *groupLeader; /* proc's lock group leader, or proc itself */
+ LOCKMASK holdMask; /* bitmask for lock types currently held */
+ LOCKMASK releaseMask; /* bitmask for lock types to be released */
+ SHM_QUEUE lockLink; /* list link in LOCK's list of proclocks */
+ SHM_QUEUE procLink; /* list link in PGPROC's list of proclocks */
+} PROCLOCK;
+
+#define PROCLOCK_LOCKMETHOD(proclock) \
+ LOCK_LOCKMETHOD(*((proclock).tag.myLock))
+
+/*
+ * Each backend also maintains a local hash table with information about each
+ * lock it is currently interested in. In particular the local table counts
+ * the number of times that lock has been acquired. This allows multiple
+ * requests for the same lock to be executed without additional accesses to
+ * shared memory. We also track the number of lock acquisitions per
+ * ResourceOwner, so that we can release just those locks belonging to a
+ * particular ResourceOwner.
+ *
+ * When holding a lock taken "normally", the lock and proclock fields always
+ * point to the associated objects in shared memory. However, if we acquired
+ * the lock via the fast-path mechanism, the lock and proclock fields are set
+ * to NULL, since there probably aren't any such objects in shared memory.
+ * (If the lock later gets promoted to normal representation, we may eventually
+ * update our locallock's lock/proclock fields after finding the shared
+ * objects.)
+ *
+ * Caution: a locallock object can be left over from a failed lock acquisition
+ * attempt. In this case its lock/proclock fields are untrustworthy, since
+ * the shared lock object is neither held nor awaited, and hence is available
+ * to be reclaimed. If nLocks > 0 then these pointers must either be valid or
+ * NULL, but when nLocks == 0 they should be considered garbage.
+ */
+typedef struct LOCALLOCKTAG
+{
+ LOCKTAG lock; /* identifies the lockable object */
+ LOCKMODE mode; /* lock mode for this table entry */
+} LOCALLOCKTAG;
+
+typedef struct LOCALLOCKOWNER
+{
+ /*
+ * Note: if owner is NULL then the lock is held on behalf of the session;
+ * otherwise it is held on behalf of my current transaction.
+ *
+ * Must use a forward struct reference to avoid circularity.
+ */
+ struct ResourceOwnerData *owner;
+ int64 nLocks; /* # of times held by this owner */
+} LOCALLOCKOWNER;
+
+typedef struct LOCALLOCK
+{
+ /* tag */
+ LOCALLOCKTAG tag; /* unique identifier of locallock entry */
+
+ /* data */
+ uint32 hashcode; /* copy of LOCKTAG's hash value */
+ LOCK *lock; /* associated LOCK object, if any */
+ PROCLOCK *proclock; /* associated PROCLOCK object, if any */
+ int64 nLocks; /* total number of times lock is held */
+ int numLockOwners; /* # of relevant ResourceOwners */
+ int maxLockOwners; /* allocated size of array */
+ LOCALLOCKOWNER *lockOwners; /* dynamically resizable array */
+ bool holdsStrongLockCount; /* bumped FastPathStrongRelationLocks */
+ bool lockCleared; /* we read all sinval msgs for lock */
+} LOCALLOCK;
+
+#define LOCALLOCK_LOCKMETHOD(llock) ((llock).tag.lock.locktag_lockmethodid)
+#define LOCALLOCK_LOCKTAG(llock) ((LockTagType) (llock).tag.lock.locktag_type)
+
+
+/*
+ * These structures hold information passed from lmgr internals to the lock
+ * listing user-level functions (in lockfuncs.c).
+ */
+
+typedef struct LockInstanceData
+{
+ LOCKTAG locktag; /* tag for locked object */
+ LOCKMASK holdMask; /* locks held by this PGPROC */
+ LOCKMODE waitLockMode; /* lock awaited by this PGPROC, if any */
+ BackendId backend; /* backend ID of this PGPROC */
+ LocalTransactionId lxid; /* local transaction ID of this PGPROC */
+ int pid; /* pid of this PGPROC */
+ int leaderPid; /* pid of group leader; = pid if no group */
+ bool fastpath; /* taken via fastpath? */
+} LockInstanceData;
+
+typedef struct LockData
+{
+ int nelements; /* The length of the array */
+ LockInstanceData *locks; /* Array of per-PROCLOCK information */
+} LockData;
+
+typedef struct BlockedProcData
+{
+ int pid; /* pid of a blocked PGPROC */
+ /* Per-PROCLOCK information about PROCLOCKs of the lock the pid awaits */
+ /* (these fields refer to indexes in BlockedProcsData.locks[]) */
+ int first_lock; /* index of first relevant LockInstanceData */
+ int num_locks; /* number of relevant LockInstanceDatas */
+ /* PIDs of PGPROCs that are ahead of "pid" in the lock's wait queue */
+ /* (these fields refer to indexes in BlockedProcsData.waiter_pids[]) */
+ int first_waiter; /* index of first preceding waiter */
+ int num_waiters; /* number of preceding waiters */
+} BlockedProcData;
+
+typedef struct BlockedProcsData
+{
+ BlockedProcData *procs; /* Array of per-blocked-proc information */
+ LockInstanceData *locks; /* Array of per-PROCLOCK information */
+ int *waiter_pids; /* Array of PIDs of other blocked PGPROCs */
+ int nprocs; /* # of valid entries in procs[] array */
+ int maxprocs; /* Allocated length of procs[] array */
+ int nlocks; /* # of valid entries in locks[] array */
+ int maxlocks; /* Allocated length of locks[] array */
+ int npids; /* # of valid entries in waiter_pids[] array */
+ int maxpids; /* Allocated length of waiter_pids[] array */
+} BlockedProcsData;
+
+
+/* Result codes for LockAcquire() */
+typedef enum
+{
+ LOCKACQUIRE_NOT_AVAIL, /* lock not available, and dontWait=true */
+ LOCKACQUIRE_OK, /* lock successfully acquired */
+ LOCKACQUIRE_ALREADY_HELD, /* incremented count for lock already held */
+ LOCKACQUIRE_ALREADY_CLEAR /* incremented count for lock already clear */
+} LockAcquireResult;
+
+/* Deadlock states identified by DeadLockCheck() */
+typedef enum
+{
+ DS_NOT_YET_CHECKED, /* no deadlock check has run yet */
+ DS_NO_DEADLOCK, /* no deadlock detected */
+ DS_SOFT_DEADLOCK, /* deadlock avoided by queue rearrangement */
+ DS_HARD_DEADLOCK, /* deadlock, no way out but ERROR */
+ DS_BLOCKED_BY_AUTOVACUUM /* no deadlock; queue blocked by autovacuum
+ * worker */
+} DeadLockState;
+
+/*
+ * The lockmgr's shared hash tables are partitioned to reduce contention.
+ * To determine which partition a given locktag belongs to, compute the tag's
+ * hash code with LockTagHashCode(), then apply one of these macros.
+ * NB: NUM_LOCK_PARTITIONS must be a power of 2!
+ */
+#define LockHashPartition(hashcode) \
+ ((hashcode) % NUM_LOCK_PARTITIONS)
+#define LockHashPartitionLock(hashcode) \
+ (&MainLWLockArray[LOCK_MANAGER_LWLOCK_OFFSET + \
+ LockHashPartition(hashcode)].lock)
+#define LockHashPartitionLockByIndex(i) \
+ (&MainLWLockArray[LOCK_MANAGER_LWLOCK_OFFSET + (i)].lock)
+
+/*
+ * The deadlock detector needs to be able to access lockGroupLeader and
+ * related fields in the PGPROC, so we arrange for those fields to be protected
+ * by one of the lock hash partition locks. Since the deadlock detector
+ * acquires all such locks anyway, this makes it safe for it to access these
+ * fields without doing anything extra. To avoid contention as much as
+ * possible, we map different PGPROCs to different partition locks. The lock
+ * used for a given lock group is determined by the group leader's pgprocno.
+ */
+#define LockHashPartitionLockByProc(leader_pgproc) \
+ LockHashPartitionLock((leader_pgproc)->pgprocno)
+
+/*
+ * function prototypes
+ */
+extern void InitLocks(void);
+extern LockMethod GetLocksMethodTable(const LOCK *lock);
+extern LockMethod GetLockTagsMethodTable(const LOCKTAG *locktag);
+extern uint32 LockTagHashCode(const LOCKTAG *locktag);
+extern bool DoLockModesConflict(LOCKMODE mode1, LOCKMODE mode2);
+extern LockAcquireResult LockAcquire(const LOCKTAG *locktag,
+ LOCKMODE lockmode,
+ bool sessionLock,
+ bool dontWait);
+extern LockAcquireResult LockAcquireExtended(const LOCKTAG *locktag,
+ LOCKMODE lockmode,
+ bool sessionLock,
+ bool dontWait,
+ bool reportMemoryError,
+ LOCALLOCK **locallockp);
+extern void AbortStrongLockAcquire(void);
+extern void MarkLockClear(LOCALLOCK *locallock);
+extern bool LockRelease(const LOCKTAG *locktag,
+ LOCKMODE lockmode, bool sessionLock);
+extern void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks);
+extern void LockReleaseSession(LOCKMETHODID lockmethodid);
+extern void LockReleaseCurrentOwner(LOCALLOCK **locallocks, int nlocks);
+extern void LockReassignCurrentOwner(LOCALLOCK **locallocks, int nlocks);
+extern bool LockHeldByMe(const LOCKTAG *locktag, LOCKMODE lockmode);
+#ifdef USE_ASSERT_CHECKING
+extern HTAB *GetLockMethodLocalHash(void);
+#endif
+extern bool LockHasWaiters(const LOCKTAG *locktag,
+ LOCKMODE lockmode, bool sessionLock);
+extern VirtualTransactionId *GetLockConflicts(const LOCKTAG *locktag,
+ LOCKMODE lockmode, int *countp);
+extern void AtPrepare_Locks(void);
+extern void PostPrepare_Locks(TransactionId xid);
+extern bool LockCheckConflicts(LockMethod lockMethodTable,
+ LOCKMODE lockmode,
+ LOCK *lock, PROCLOCK *proclock);
+extern void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode);
+extern void GrantAwaitedLock(void);
+extern void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode);
+extern Size LockShmemSize(void);
+extern LockData *GetLockStatusData(void);
+extern BlockedProcsData *GetBlockerStatusData(int blocked_pid);
+
+extern xl_standby_lock *GetRunningTransactionLocks(int *nlocks);
+extern const char *GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode);
+
+extern void lock_twophase_recover(TransactionId xid, uint16 info,
+ void *recdata, uint32 len);
+extern void lock_twophase_postcommit(TransactionId xid, uint16 info,
+ void *recdata, uint32 len);
+extern void lock_twophase_postabort(TransactionId xid, uint16 info,
+ void *recdata, uint32 len);
+extern void lock_twophase_standby_recover(TransactionId xid, uint16 info,
+ void *recdata, uint32 len);
+
+extern DeadLockState DeadLockCheck(PGPROC *proc);
+extern PGPROC *GetBlockingAutoVacuumPgproc(void);
+extern void DeadLockReport(void) pg_attribute_noreturn();
+extern void RememberSimpleDeadLock(PGPROC *proc1,
+ LOCKMODE lockmode,
+ LOCK *lock,
+ PGPROC *proc2);
+extern void InitDeadLockChecking(void);
+
+extern int LockWaiterCount(const LOCKTAG *locktag);
+
+#ifdef LOCK_DEBUG
+extern void DumpLocks(PGPROC *proc);
+extern void DumpAllLocks(void);
+#endif
+
+/* Lock a VXID (used to wait for a transaction to finish) */
+extern void VirtualXactLockTableInsert(VirtualTransactionId vxid);
+extern void VirtualXactLockTableCleanup(void);
+extern bool VirtualXactLock(VirtualTransactionId vxid, bool wait);
+
+#endif /* LOCK_H_ */
diff --git a/src/include/storage/lockdefs.h b/src/include/storage/lockdefs.h
new file mode 100644
index 0000000..ef0daf7
--- /dev/null
+++ b/src/include/storage/lockdefs.h
@@ -0,0 +1,59 @@
+/*-------------------------------------------------------------------------
+ *
+ * lockdefs.h
+ * Frontend exposed parts of postgres' low level lock mechanism
+ *
+ * The split between lockdefs.h and lock.h is not very principled. This file
+ * contains definition that have to (indirectly) be available when included by
+ * FRONTEND code.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/lockdefs.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LOCKDEFS_H_
+#define LOCKDEFS_H_
+
+/*
+ * LOCKMODE is an integer (1..N) indicating a lock type. LOCKMASK is a bit
+ * mask indicating a set of held or requested lock types (the bit 1<<mode
+ * corresponds to a particular lock mode).
+ */
+typedef int LOCKMASK;
+typedef int LOCKMODE;
+
+/*
+ * These are the valid values of type LOCKMODE for all the standard lock
+ * methods (both DEFAULT and USER).
+ */
+
+/* NoLock is not a lock mode, but a flag value meaning "don't get a lock" */
+#define NoLock 0
+
+#define AccessShareLock 1 /* SELECT */
+#define RowShareLock 2 /* SELECT FOR UPDATE/FOR SHARE */
+#define RowExclusiveLock 3 /* INSERT, UPDATE, DELETE */
+#define ShareUpdateExclusiveLock 4 /* VACUUM (non-FULL),ANALYZE, CREATE INDEX
+ * CONCURRENTLY */
+#define ShareLock 5 /* CREATE INDEX (WITHOUT CONCURRENTLY) */
+#define ShareRowExclusiveLock 6 /* like EXCLUSIVE MODE, but allows ROW
+ * SHARE */
+#define ExclusiveLock 7 /* blocks ROW SHARE/SELECT...FOR UPDATE */
+#define AccessExclusiveLock 8 /* ALTER TABLE, DROP TABLE, VACUUM FULL,
+ * and unqualified LOCK TABLE */
+
+#define MaxLockMode 8
+
+
+/* WAL representation of an AccessExclusiveLock on a table */
+typedef struct xl_standby_lock
+{
+ TransactionId xid; /* xid of holder of AccessExclusiveLock */
+ Oid dbOid; /* DB containing table */
+ Oid relOid; /* OID of table */
+} xl_standby_lock;
+
+#endif /* LOCKDEFS_H_ */
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
new file mode 100644
index 0000000..c04ae97
--- /dev/null
+++ b/src/include/storage/lwlock.h
@@ -0,0 +1,232 @@
+/*-------------------------------------------------------------------------
+ *
+ * lwlock.h
+ * Lightweight lock manager
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/lwlock.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LWLOCK_H
+#define LWLOCK_H
+
+#ifdef FRONTEND
+#error "lwlock.h may not be included from frontend code"
+#endif
+
+#include "port/atomics.h"
+#include "storage/proclist_types.h"
+#include "storage/s_lock.h"
+
+struct PGPROC;
+
+/*
+ * Code outside of lwlock.c should not manipulate the contents of this
+ * structure directly, but we have to declare it here to allow LWLocks to be
+ * incorporated into other data structures.
+ */
+typedef struct LWLock
+{
+ uint16 tranche; /* tranche ID */
+ pg_atomic_uint32 state; /* state of exclusive/nonexclusive lockers */
+ proclist_head waiters; /* list of waiting PGPROCs */
+#ifdef LOCK_DEBUG
+ pg_atomic_uint32 nwaiters; /* number of waiters */
+ struct PGPROC *owner; /* last exclusive owner of the lock */
+#endif
+} LWLock;
+
+/*
+ * In most cases, it's desirable to force each tranche of LWLocks to be aligned
+ * on a cache line boundary and make the array stride a power of 2. This saves
+ * a few cycles in indexing, but more importantly ensures that individual
+ * LWLocks don't cross cache line boundaries. This reduces cache contention
+ * problems, especially on AMD Opterons. In some cases, it's useful to add
+ * even more padding so that each LWLock takes up an entire cache line; this is
+ * useful, for example, in the main LWLock array, where the overall number of
+ * locks is small but some are heavily contended.
+ *
+ * When allocating a tranche that contains data other than LWLocks, it is
+ * probably best to include a bare LWLock and then pad the resulting structure
+ * as necessary for performance. For an array that contains only LWLocks,
+ * LWLockMinimallyPadded can be used for cases where we just want to ensure
+ * that we don't cross cache line boundaries within a single lock, while
+ * LWLockPadded can be used for cases where we want each lock to be an entire
+ * cache line.
+ *
+ * An LWLockMinimallyPadded might contain more than the absolute minimum amount
+ * of padding required to keep a lock from crossing a cache line boundary,
+ * because an unpadded LWLock will normally fit into 16 bytes. We ignore that
+ * possibility when determining the minimal amount of padding. Older releases
+ * had larger LWLocks, so 32 really was the minimum, and packing them in
+ * tighter might hurt performance.
+ *
+ * LWLOCK_MINIMAL_SIZE should be 32 on basically all common platforms, but
+ * because pg_atomic_uint32 is more than 4 bytes on some obscure platforms, we
+ * allow for the possibility that it might be 64. Even on those platforms,
+ * we probably won't exceed 32 bytes unless LOCK_DEBUG is defined.
+ */
+#define LWLOCK_PADDED_SIZE PG_CACHE_LINE_SIZE
+#define LWLOCK_MINIMAL_SIZE (sizeof(LWLock) <= 32 ? 32 : 64)
+
+/* LWLock, padded to a full cache line size */
+typedef union LWLockPadded
+{
+ LWLock lock;
+ char pad[LWLOCK_PADDED_SIZE];
+} LWLockPadded;
+
+/* LWLock, minimally padded */
+typedef union LWLockMinimallyPadded
+{
+ LWLock lock;
+ char pad[LWLOCK_MINIMAL_SIZE];
+} LWLockMinimallyPadded;
+
+extern PGDLLIMPORT LWLockPadded *MainLWLockArray;
+
+/* struct for storing named tranche information */
+typedef struct NamedLWLockTranche
+{
+ int trancheId;
+ char *trancheName;
+} NamedLWLockTranche;
+
+extern PGDLLIMPORT NamedLWLockTranche *NamedLWLockTrancheArray;
+extern PGDLLIMPORT int NamedLWLockTrancheRequests;
+
+/* Names for fixed lwlocks */
+#include "storage/lwlocknames.h"
+
+/*
+ * It's a bit odd to declare NUM_BUFFER_PARTITIONS and NUM_LOCK_PARTITIONS
+ * here, but we need them to figure out offsets within MainLWLockArray, and
+ * having this file include lock.h or bufmgr.h would be backwards.
+ */
+
+/* Number of partitions of the shared buffer mapping hashtable */
+#define NUM_BUFFER_PARTITIONS 128
+
+/* Number of partitions the shared lock tables are divided into */
+#define LOG2_NUM_LOCK_PARTITIONS 4
+#define NUM_LOCK_PARTITIONS (1 << LOG2_NUM_LOCK_PARTITIONS)
+
+/* Number of partitions the shared predicate lock tables are divided into */
+#define LOG2_NUM_PREDICATELOCK_PARTITIONS 4
+#define NUM_PREDICATELOCK_PARTITIONS (1 << LOG2_NUM_PREDICATELOCK_PARTITIONS)
+
+/* Offsets for various chunks of preallocated lwlocks. */
+#define BUFFER_MAPPING_LWLOCK_OFFSET NUM_INDIVIDUAL_LWLOCKS
+#define LOCK_MANAGER_LWLOCK_OFFSET \
+ (BUFFER_MAPPING_LWLOCK_OFFSET + NUM_BUFFER_PARTITIONS)
+#define PREDICATELOCK_MANAGER_LWLOCK_OFFSET \
+ (LOCK_MANAGER_LWLOCK_OFFSET + NUM_LOCK_PARTITIONS)
+#define NUM_FIXED_LWLOCKS \
+ (PREDICATELOCK_MANAGER_LWLOCK_OFFSET + NUM_PREDICATELOCK_PARTITIONS)
+
+typedef enum LWLockMode
+{
+ LW_EXCLUSIVE,
+ LW_SHARED,
+ LW_WAIT_UNTIL_FREE /* A special mode used in PGPROC->lwWaitMode,
+ * when waiting for lock to become free. Not
+ * to be used as LWLockAcquire argument */
+} LWLockMode;
+
+
+#ifdef LOCK_DEBUG
+extern bool Trace_lwlocks;
+#endif
+
+extern bool LWLockAcquire(LWLock *lock, LWLockMode mode);
+extern bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode);
+extern bool LWLockAcquireOrWait(LWLock *lock, LWLockMode mode);
+extern void LWLockRelease(LWLock *lock);
+extern void LWLockReleaseClearVar(LWLock *lock, uint64 *valptr, uint64 val);
+extern void LWLockReleaseAll(void);
+extern bool LWLockHeldByMe(LWLock *lock);
+extern bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode);
+
+extern bool LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval);
+extern void LWLockUpdateVar(LWLock *lock, uint64 *valptr, uint64 value);
+
+extern Size LWLockShmemSize(void);
+extern void CreateLWLocks(void);
+extern void InitLWLockAccess(void);
+
+extern const char *GetLWLockIdentifier(uint32 classId, uint16 eventId);
+
+/*
+ * Extensions (or core code) can obtain an LWLocks by calling
+ * RequestNamedLWLockTranche() during postmaster startup. Subsequently,
+ * call GetNamedLWLockTranche() to obtain a pointer to an array containing
+ * the number of LWLocks requested.
+ */
+extern void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks);
+extern LWLockPadded *GetNamedLWLockTranche(const char *tranche_name);
+
+/*
+ * There is another, more flexible method of obtaining lwlocks. First, call
+ * LWLockNewTrancheId just once to obtain a tranche ID; this allocates from
+ * a shared counter. Next, each individual process using the tranche should
+ * call LWLockRegisterTranche() to associate that tranche ID with a name.
+ * Finally, LWLockInitialize should be called just once per lwlock, passing
+ * the tranche ID as an argument.
+ *
+ * It may seem strange that each process using the tranche must register it
+ * separately, but dynamic shared memory segments aren't guaranteed to be
+ * mapped at the same address in all coordinating backends, so storing the
+ * registration in the main shared memory segment wouldn't work for that case.
+ */
+extern int LWLockNewTrancheId(void);
+extern void LWLockRegisterTranche(int tranche_id, const char *tranche_name);
+extern void LWLockInitialize(LWLock *lock, int tranche_id);
+
+/*
+ * Every tranche ID less than NUM_INDIVIDUAL_LWLOCKS is reserved; also,
+ * we reserve additional tranche IDs for builtin tranches not included in
+ * the set of individual LWLocks. A call to LWLockNewTrancheId will never
+ * return a value less than LWTRANCHE_FIRST_USER_DEFINED.
+ */
+typedef enum BuiltinTrancheIds
+{
+ LWTRANCHE_XACT_BUFFER = NUM_INDIVIDUAL_LWLOCKS,
+ LWTRANCHE_COMMITTS_BUFFER,
+ LWTRANCHE_SUBTRANS_BUFFER,
+ LWTRANCHE_MULTIXACTOFFSET_BUFFER,
+ LWTRANCHE_MULTIXACTMEMBER_BUFFER,
+ LWTRANCHE_NOTIFY_BUFFER,
+ LWTRANCHE_SERIAL_BUFFER,
+ LWTRANCHE_WAL_INSERT,
+ LWTRANCHE_BUFFER_CONTENT,
+ LWTRANCHE_BUFFER_IO,
+ LWTRANCHE_REPLICATION_ORIGIN_STATE,
+ LWTRANCHE_REPLICATION_SLOT_IO,
+ LWTRANCHE_LOCK_FASTPATH,
+ LWTRANCHE_BUFFER_MAPPING,
+ LWTRANCHE_LOCK_MANAGER,
+ LWTRANCHE_PREDICATE_LOCK_MANAGER,
+ LWTRANCHE_PARALLEL_HASH_JOIN,
+ LWTRANCHE_PARALLEL_QUERY_DSA,
+ LWTRANCHE_PER_SESSION_DSA,
+ LWTRANCHE_PER_SESSION_RECORD_TYPE,
+ LWTRANCHE_PER_SESSION_RECORD_TYPMOD,
+ LWTRANCHE_SHARED_TUPLESTORE,
+ LWTRANCHE_SHARED_TIDBITMAP,
+ LWTRANCHE_PARALLEL_APPEND,
+ LWTRANCHE_PER_XACT_PREDICATE_LIST,
+ LWTRANCHE_FIRST_USER_DEFINED
+} BuiltinTrancheIds;
+
+/*
+ * Prior to PostgreSQL 9.4, we used an enum type called LWLockId to refer
+ * to LWLocks. New code should instead use LWLock *. However, for the
+ * convenience of third-party code, we include the following typedef.
+ */
+typedef LWLock *LWLockId;
+
+#endif /* LWLOCK_H */
diff --git a/src/include/storage/md.h b/src/include/storage/md.h
new file mode 100644
index 0000000..07fd1bb
--- /dev/null
+++ b/src/include/storage/md.h
@@ -0,0 +1,52 @@
+/*-------------------------------------------------------------------------
+ *
+ * md.h
+ * magnetic disk storage manager public interface declarations.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/md.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef MD_H
+#define MD_H
+
+#include "storage/block.h"
+#include "storage/relfilenode.h"
+#include "storage/smgr.h"
+#include "storage/sync.h"
+
+/* md storage manager functionality */
+extern void mdinit(void);
+extern void mdopen(SMgrRelation reln);
+extern void mdclose(SMgrRelation reln, ForkNumber forknum);
+extern void mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo);
+extern bool mdexists(SMgrRelation reln, ForkNumber forknum);
+extern void mdunlink(RelFileNodeBackend rnode, ForkNumber forknum, bool isRedo);
+extern void mdextend(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber blocknum, char *buffer, bool skipFsync);
+extern bool mdprefetch(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber blocknum);
+extern void mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
+ char *buffer);
+extern void mdwrite(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber blocknum, char *buffer, bool skipFsync);
+extern void mdwriteback(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber blocknum, BlockNumber nblocks);
+extern BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum);
+extern void mdtruncate(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber nblocks);
+extern void mdimmedsync(SMgrRelation reln, ForkNumber forknum);
+
+extern void ForgetDatabaseSyncRequests(Oid dbid);
+extern void DropRelationFiles(RelFileNode *delrels, int ndelrels, bool isRedo);
+
+/* md sync callbacks */
+extern int mdsyncfiletag(const FileTag *ftag, char *path);
+extern int mdunlinkfiletag(const FileTag *ftag, char *path);
+extern bool mdfiletagmatches(const FileTag *ftag, const FileTag *candidate);
+
+#endif /* MD_H */
diff --git a/src/include/storage/off.h b/src/include/storage/off.h
new file mode 100644
index 0000000..9bfdec8
--- /dev/null
+++ b/src/include/storage/off.h
@@ -0,0 +1,57 @@
+/*-------------------------------------------------------------------------
+ *
+ * off.h
+ * POSTGRES disk "offset" definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/off.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef OFF_H
+#define OFF_H
+
+#include "storage/itemid.h"
+/*
+ * OffsetNumber:
+ *
+ * this is a 1-based index into the linp (ItemIdData) array in the
+ * header of each disk page.
+ */
+typedef uint16 OffsetNumber;
+
+#define InvalidOffsetNumber ((OffsetNumber) 0)
+#define FirstOffsetNumber ((OffsetNumber) 1)
+#define MaxOffsetNumber ((OffsetNumber) (BLCKSZ / sizeof(ItemIdData)))
+
+/* ----------------
+ * support macros
+ * ----------------
+ */
+
+/*
+ * OffsetNumberIsValid
+ * True iff the offset number is valid.
+ */
+#define OffsetNumberIsValid(offsetNumber) \
+ ((bool) ((offsetNumber != InvalidOffsetNumber) && \
+ (offsetNumber <= MaxOffsetNumber)))
+
+/*
+ * OffsetNumberNext
+ * OffsetNumberPrev
+ * Increments/decrements the argument. These macros look pointless
+ * but they help us disambiguate the different manipulations on
+ * OffsetNumbers (e.g., sometimes we subtract one from an
+ * OffsetNumber to move back, and sometimes we do so to form a
+ * real C array index).
+ */
+#define OffsetNumberNext(offsetNumber) \
+ ((OffsetNumber) (1 + (offsetNumber)))
+#define OffsetNumberPrev(offsetNumber) \
+ ((OffsetNumber) (-1 + (offsetNumber)))
+
+#endif /* OFF_H */
diff --git a/src/include/storage/pg_sema.h b/src/include/storage/pg_sema.h
new file mode 100644
index 0000000..ef8a7b4
--- /dev/null
+++ b/src/include/storage/pg_sema.h
@@ -0,0 +1,61 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_sema.h
+ * Platform-independent API for semaphores.
+ *
+ * PostgreSQL requires counting semaphores (the kind that keep track of
+ * multiple unlock operations, and will allow an equal number of subsequent
+ * lock operations before blocking). The underlying implementation is
+ * not the same on every platform. This file defines the API that must
+ * be provided by each port.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/pg_sema.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_SEMA_H
+#define PG_SEMA_H
+
+/*
+ * struct PGSemaphoreData and pointer type PGSemaphore are the data structure
+ * representing an individual semaphore. The contents of PGSemaphoreData vary
+ * across implementations and must never be touched by platform-independent
+ * code; hence, PGSemaphoreData is declared as an opaque struct here.
+ *
+ * However, Windows is sufficiently unlike our other ports that it doesn't
+ * seem worth insisting on ABI compatibility for Windows too. Hence, on
+ * that platform just define PGSemaphore as HANDLE.
+ */
+#ifndef USE_WIN32_SEMAPHORES
+typedef struct PGSemaphoreData *PGSemaphore;
+#else
+typedef HANDLE PGSemaphore;
+#endif
+
+
+/* Report amount of shared memory needed */
+extern Size PGSemaphoreShmemSize(int maxSemas);
+
+/* Module initialization (called during postmaster start or shmem reinit) */
+extern void PGReserveSemaphores(int maxSemas);
+
+/* Allocate a PGSemaphore structure with initial count 1 */
+extern PGSemaphore PGSemaphoreCreate(void);
+
+/* Reset a previously-initialized PGSemaphore to have count 0 */
+extern void PGSemaphoreReset(PGSemaphore sema);
+
+/* Lock a semaphore (decrement count), blocking if count would be < 0 */
+extern void PGSemaphoreLock(PGSemaphore sema);
+
+/* Unlock a semaphore (increment count) */
+extern void PGSemaphoreUnlock(PGSemaphore sema);
+
+/* Lock a semaphore only if able to do so without blocking */
+extern bool PGSemaphoreTryLock(PGSemaphore sema);
+
+#endif /* PG_SEMA_H */
diff --git a/src/include/storage/pg_shmem.h b/src/include/storage/pg_shmem.h
new file mode 100644
index 0000000..0de26b3
--- /dev/null
+++ b/src/include/storage/pg_shmem.h
@@ -0,0 +1,90 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_shmem.h
+ * Platform-independent API for shared memory support.
+ *
+ * Every port is expected to support shared memory with approximately
+ * SysV-ish semantics; in particular, a memory block is not anonymous
+ * but has an ID, and we must be able to tell whether there are any
+ * remaining processes attached to a block of a specified ID.
+ *
+ * To simplify life for the SysV implementation, the ID is assumed to
+ * consist of two unsigned long values (these are key and ID in SysV
+ * terms). Other platforms may ignore the second value if they need
+ * only one ID number.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/pg_shmem.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_SHMEM_H
+#define PG_SHMEM_H
+
+#include "storage/dsm_impl.h"
+
+typedef struct PGShmemHeader /* standard header for all Postgres shmem */
+{
+ int32 magic; /* magic # to identify Postgres segments */
+#define PGShmemMagic 679834894
+ pid_t creatorPID; /* PID of creating process (set but unread) */
+ Size totalsize; /* total size of segment */
+ Size freeoffset; /* offset to first free space */
+ dsm_handle dsm_control; /* ID of dynamic shared memory control seg */
+ void *index; /* pointer to ShmemIndex table */
+#ifndef WIN32 /* Windows doesn't have useful inode#s */
+ dev_t device; /* device data directory is on */
+ ino_t inode; /* inode number of data directory */
+#endif
+} PGShmemHeader;
+
+/* GUC variables */
+extern int shared_memory_type;
+extern int huge_pages;
+
+/* Possible values for huge_pages */
+typedef enum
+{
+ HUGE_PAGES_OFF,
+ HUGE_PAGES_ON,
+ HUGE_PAGES_TRY
+} HugePagesType;
+
+/* Possible values for shared_memory_type */
+typedef enum
+{
+ SHMEM_TYPE_WINDOWS,
+ SHMEM_TYPE_SYSV,
+ SHMEM_TYPE_MMAP
+} PGShmemType;
+
+#ifndef WIN32
+extern unsigned long UsedShmemSegID;
+#else
+extern HANDLE UsedShmemSegID;
+extern void *ShmemProtectiveRegion;
+#endif
+extern void *UsedShmemSegAddr;
+
+#if !defined(WIN32) && !defined(EXEC_BACKEND)
+#define DEFAULT_SHARED_MEMORY_TYPE SHMEM_TYPE_MMAP
+#elif !defined(WIN32)
+#define DEFAULT_SHARED_MEMORY_TYPE SHMEM_TYPE_SYSV
+#else
+#define DEFAULT_SHARED_MEMORY_TYPE SHMEM_TYPE_WINDOWS
+#endif
+
+#ifdef EXEC_BACKEND
+extern void PGSharedMemoryReAttach(void);
+extern void PGSharedMemoryNoReAttach(void);
+#endif
+
+extern PGShmemHeader *PGSharedMemoryCreate(Size size,
+ PGShmemHeader **shim);
+extern bool PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2);
+extern void PGSharedMemoryDetach(void);
+
+#endif /* PG_SHMEM_H */
diff --git a/src/include/storage/pmsignal.h b/src/include/storage/pmsignal.h
new file mode 100644
index 0000000..56c5ec4
--- /dev/null
+++ b/src/include/storage/pmsignal.h
@@ -0,0 +1,94 @@
+/*-------------------------------------------------------------------------
+ *
+ * pmsignal.h
+ * routines for signaling the postmaster from its child processes
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/pmsignal.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PMSIGNAL_H
+#define PMSIGNAL_H
+
+#include <signal.h>
+
+#ifdef HAVE_SYS_PRCTL_H
+#include "sys/prctl.h"
+#endif
+
+#ifdef HAVE_SYS_PROCCTL_H
+#include "sys/procctl.h"
+#endif
+
+/*
+ * Reasons for signaling the postmaster. We can cope with simultaneous
+ * signals for different reasons. If the same reason is signaled multiple
+ * times in quick succession, however, the postmaster is likely to observe
+ * only one notification of it. This is okay for the present uses.
+ */
+typedef enum
+{
+ PMSIGNAL_RECOVERY_STARTED, /* recovery has started */
+ PMSIGNAL_BEGIN_HOT_STANDBY, /* begin Hot Standby */
+ PMSIGNAL_WAKEN_ARCHIVER, /* send a NOTIFY signal to xlog archiver */
+ PMSIGNAL_ROTATE_LOGFILE, /* send SIGUSR1 to syslogger to rotate logfile */
+ PMSIGNAL_START_AUTOVAC_LAUNCHER, /* start an autovacuum launcher */
+ PMSIGNAL_START_AUTOVAC_WORKER, /* start an autovacuum worker */
+ PMSIGNAL_BACKGROUND_WORKER_CHANGE, /* background worker state change */
+ PMSIGNAL_START_WALRECEIVER, /* start a walreceiver */
+ PMSIGNAL_ADVANCE_STATE_MACHINE, /* advance postmaster's state machine */
+
+ NUM_PMSIGNALS /* Must be last value of enum! */
+} PMSignalReason;
+
+/* PMSignalData is an opaque struct, details known only within pmsignal.c */
+typedef struct PMSignalData PMSignalData;
+
+/*
+ * prototypes for functions in pmsignal.c
+ */
+extern Size PMSignalShmemSize(void);
+extern void PMSignalShmemInit(void);
+extern void SendPostmasterSignal(PMSignalReason reason);
+extern bool CheckPostmasterSignal(PMSignalReason reason);
+extern int AssignPostmasterChildSlot(void);
+extern bool ReleasePostmasterChildSlot(int slot);
+extern bool IsPostmasterChildWalSender(int slot);
+extern void MarkPostmasterChildActive(void);
+extern void MarkPostmasterChildInactive(void);
+extern void MarkPostmasterChildWalSender(void);
+extern bool PostmasterIsAliveInternal(void);
+extern void PostmasterDeathSignalInit(void);
+
+
+/*
+ * Do we have a way to ask for a signal on parent death?
+ *
+ * If we do, pmsignal.c will set up a signal handler, that sets a flag when
+ * the parent dies. Checking the flag first makes PostmasterIsAlive() a lot
+ * cheaper in usual case that the postmaster is alive.
+ */
+#if (defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_PDEATHSIG)) || \
+ (defined(HAVE_SYS_PROCCTL_H) && defined(PROC_PDEATHSIG_CTL))
+#define USE_POSTMASTER_DEATH_SIGNAL
+#endif
+
+#ifdef USE_POSTMASTER_DEATH_SIGNAL
+extern volatile sig_atomic_t postmaster_possibly_dead;
+
+static inline bool
+PostmasterIsAlive(void)
+{
+ if (likely(!postmaster_possibly_dead))
+ return true;
+ return PostmasterIsAliveInternal();
+}
+#else
+#define PostmasterIsAlive() PostmasterIsAliveInternal()
+#endif
+
+#endif /* PMSIGNAL_H */
diff --git a/src/include/storage/predicate.h b/src/include/storage/predicate.h
new file mode 100644
index 0000000..86e756d
--- /dev/null
+++ b/src/include/storage/predicate.h
@@ -0,0 +1,87 @@
+/*-------------------------------------------------------------------------
+ *
+ * predicate.h
+ * POSTGRES public predicate locking definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/predicate.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PREDICATE_H
+#define PREDICATE_H
+
+#include "storage/lock.h"
+#include "utils/relcache.h"
+#include "utils/snapshot.h"
+
+
+/*
+ * GUC variables
+ */
+extern int max_predicate_locks_per_xact;
+extern int max_predicate_locks_per_relation;
+extern int max_predicate_locks_per_page;
+
+
+/* Number of SLRU buffers to use for Serial SLRU */
+#define NUM_SERIAL_BUFFERS 16
+
+/*
+ * A handle used for sharing SERIALIZABLEXACT objects between the participants
+ * in a parallel query.
+ */
+typedef void *SerializableXactHandle;
+
+/*
+ * function prototypes
+ */
+
+/* housekeeping for shared memory predicate lock structures */
+extern void InitPredicateLocks(void);
+extern Size PredicateLockShmemSize(void);
+
+extern void CheckPointPredicate(void);
+
+/* predicate lock reporting */
+extern bool PageIsPredicateLocked(Relation relation, BlockNumber blkno);
+
+/* predicate lock maintenance */
+extern Snapshot GetSerializableTransactionSnapshot(Snapshot snapshot);
+extern void SetSerializableTransactionSnapshot(Snapshot snapshot,
+ VirtualTransactionId *sourcevxid,
+ int sourcepid);
+extern void RegisterPredicateLockingXid(TransactionId xid);
+extern void PredicateLockRelation(Relation relation, Snapshot snapshot);
+extern void PredicateLockPage(Relation relation, BlockNumber blkno, Snapshot snapshot);
+extern void PredicateLockTID(Relation relation, ItemPointer tid, Snapshot snapshot,
+ TransactionId insert_xid);
+extern void PredicateLockPageSplit(Relation relation, BlockNumber oldblkno, BlockNumber newblkno);
+extern void PredicateLockPageCombine(Relation relation, BlockNumber oldblkno, BlockNumber newblkno);
+extern void TransferPredicateLocksToHeapRelation(Relation relation);
+extern void ReleasePredicateLocks(bool isCommit, bool isReadOnlySafe);
+
+/* conflict detection (may also trigger rollback) */
+extern bool CheckForSerializableConflictOutNeeded(Relation relation, Snapshot snapshot);
+extern void CheckForSerializableConflictOut(Relation relation, TransactionId xid, Snapshot snapshot);
+extern void CheckForSerializableConflictIn(Relation relation, ItemPointer tid, BlockNumber blkno);
+extern void CheckTableForSerializableConflictIn(Relation relation);
+
+/* final rollback checking */
+extern void PreCommit_CheckForSerializationFailure(void);
+
+/* two-phase commit support */
+extern void AtPrepare_PredicateLocks(void);
+extern void PostPrepare_PredicateLocks(TransactionId xid);
+extern void PredicateLockTwoPhaseFinish(TransactionId xid, bool isCommit);
+extern void predicatelock_twophase_recover(TransactionId xid, uint16 info,
+ void *recdata, uint32 len);
+
+/* parallel query support */
+extern SerializableXactHandle ShareSerializableXact(void);
+extern void AttachSerializableXact(SerializableXactHandle handle);
+
+#endif /* PREDICATE_H */
diff --git a/src/include/storage/predicate_internals.h b/src/include/storage/predicate_internals.h
new file mode 100644
index 0000000..cf9694d
--- /dev/null
+++ b/src/include/storage/predicate_internals.h
@@ -0,0 +1,493 @@
+/*-------------------------------------------------------------------------
+ *
+ * predicate_internals.h
+ * POSTGRES internal predicate locking definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/predicate_internals.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PREDICATE_INTERNALS_H
+#define PREDICATE_INTERNALS_H
+
+#include "storage/lock.h"
+#include "storage/lwlock.h"
+
+/*
+ * Commit number.
+ */
+typedef uint64 SerCommitSeqNo;
+
+/*
+ * Reserved commit sequence numbers:
+ * - 0 is reserved to indicate a non-existent SLRU entry; it cannot be
+ * used as a SerCommitSeqNo, even an invalid one
+ * - InvalidSerCommitSeqNo is used to indicate a transaction that
+ * hasn't committed yet, so use a number greater than all valid
+ * ones to make comparison do the expected thing
+ * - RecoverySerCommitSeqNo is used to refer to transactions that
+ * happened before a crash/recovery, since we restart the sequence
+ * at that point. It's earlier than all normal sequence numbers,
+ * and is only used by recovered prepared transactions
+ */
+#define InvalidSerCommitSeqNo ((SerCommitSeqNo) PG_UINT64_MAX)
+#define RecoverySerCommitSeqNo ((SerCommitSeqNo) 1)
+#define FirstNormalSerCommitSeqNo ((SerCommitSeqNo) 2)
+
+/*
+ * The SERIALIZABLEXACT struct contains information needed for each
+ * serializable database transaction to support SSI techniques.
+ *
+ * A home-grown list is maintained in shared memory to manage these.
+ * An entry is used when the serializable transaction acquires a snapshot.
+ * Unless the transaction is rolled back, this entry must generally remain
+ * until all concurrent transactions have completed. (There are special
+ * optimizations for READ ONLY transactions which often allow them to be
+ * cleaned up earlier.) A transaction which is rolled back is cleaned up
+ * as soon as possible.
+ *
+ * Eligibility for cleanup of committed transactions is generally determined
+ * by comparing the transaction's finishedBefore field to
+ * SxactGlobalXmin.
+ */
+typedef struct SERIALIZABLEXACT
+{
+ VirtualTransactionId vxid; /* The executing process always has one of
+ * these. */
+
+ /*
+ * We use two numbers to track the order that transactions commit. Before
+ * commit, a transaction is marked as prepared, and prepareSeqNo is set.
+ * Shortly after commit, it's marked as committed, and commitSeqNo is set.
+ * This doesn't give a strict commit order, but these two values together
+ * are good enough for us, as we can always err on the safe side and
+ * assume that there's a conflict, if we can't be sure of the exact
+ * ordering of two commits.
+ *
+ * Note that a transaction is marked as prepared for a short period during
+ * commit processing, even if two-phase commit is not used. But with
+ * two-phase commit, a transaction can stay in prepared state for some
+ * time.
+ */
+ SerCommitSeqNo prepareSeqNo;
+ SerCommitSeqNo commitSeqNo;
+
+ /* these values are not both interesting at the same time */
+ union
+ {
+ SerCommitSeqNo earliestOutConflictCommit; /* when committed with
+ * conflict out */
+ SerCommitSeqNo lastCommitBeforeSnapshot; /* when not committed or
+ * no conflict out */
+ } SeqNo;
+ SHM_QUEUE outConflicts; /* list of write transactions whose data we
+ * couldn't read. */
+ SHM_QUEUE inConflicts; /* list of read transactions which couldn't
+ * see our write. */
+ SHM_QUEUE predicateLocks; /* list of associated PREDICATELOCK objects */
+ SHM_QUEUE finishedLink; /* list link in
+ * FinishedSerializableTransactions */
+
+ /*
+ * perXactPredicateListLock is only used in parallel queries: it protects
+ * this SERIALIZABLEXACT's predicate lock list against other workers of
+ * the same session.
+ */
+ LWLock perXactPredicateListLock;
+
+ /*
+ * for r/o transactions: list of concurrent r/w transactions that we could
+ * potentially have conflicts with, and vice versa for r/w transactions
+ */
+ SHM_QUEUE possibleUnsafeConflicts;
+
+ TransactionId topXid; /* top level xid for the transaction, if one
+ * exists; else invalid */
+ TransactionId finishedBefore; /* invalid means still running; else the
+ * struct expires when no serializable
+ * xids are before this. */
+ TransactionId xmin; /* the transaction's snapshot xmin */
+ uint32 flags; /* OR'd combination of values defined below */
+ int pid; /* pid of associated process */
+} SERIALIZABLEXACT;
+
+#define SXACT_FLAG_COMMITTED 0x00000001 /* already committed */
+#define SXACT_FLAG_PREPARED 0x00000002 /* about to commit */
+#define SXACT_FLAG_ROLLED_BACK 0x00000004 /* already rolled back */
+#define SXACT_FLAG_DOOMED 0x00000008 /* will roll back */
+/*
+ * The following flag actually means that the flagged transaction has a
+ * conflict out *to a transaction which committed ahead of it*. It's hard
+ * to get that into a name of a reasonable length.
+ */
+#define SXACT_FLAG_CONFLICT_OUT 0x00000010
+#define SXACT_FLAG_READ_ONLY 0x00000020
+#define SXACT_FLAG_DEFERRABLE_WAITING 0x00000040
+#define SXACT_FLAG_RO_SAFE 0x00000080
+#define SXACT_FLAG_RO_UNSAFE 0x00000100
+#define SXACT_FLAG_SUMMARY_CONFLICT_IN 0x00000200
+#define SXACT_FLAG_SUMMARY_CONFLICT_OUT 0x00000400
+/*
+ * The following flag means the transaction has been partially released
+ * already, but is being preserved because parallel workers might have a
+ * reference to it. It'll be recycled by the leader at end-of-transaction.
+ */
+#define SXACT_FLAG_PARTIALLY_RELEASED 0x00000800
+
+/*
+ * The following types are used to provide an ad hoc list for holding
+ * SERIALIZABLEXACT objects. An HTAB is overkill, since there is no need to
+ * access these by key -- there are direct pointers to these objects where
+ * needed. If a shared memory list is created, these types can probably be
+ * eliminated in favor of using the general solution.
+ */
+typedef struct PredXactListElementData
+{
+ SHM_QUEUE link;
+ SERIALIZABLEXACT sxact;
+} PredXactListElementData;
+
+typedef struct PredXactListElementData *PredXactListElement;
+
+#define PredXactListElementDataSize \
+ ((Size)MAXALIGN(sizeof(PredXactListElementData)))
+
+typedef struct PredXactListData
+{
+ SHM_QUEUE availableList;
+ SHM_QUEUE activeList;
+
+ /*
+ * These global variables are maintained when registering and cleaning up
+ * serializable transactions. They must be global across all backends,
+ * but are not needed outside the predicate.c source file. Protected by
+ * SerializableXactHashLock.
+ */
+ TransactionId SxactGlobalXmin; /* global xmin for active serializable
+ * transactions */
+ int SxactGlobalXminCount; /* how many active serializable
+ * transactions have this xmin */
+ int WritableSxactCount; /* how many non-read-only serializable
+ * transactions are active */
+ SerCommitSeqNo LastSxactCommitSeqNo; /* a strictly monotonically
+ * increasing number for commits
+ * of serializable transactions */
+ /* Protected by SerializableXactHashLock. */
+ SerCommitSeqNo CanPartialClearThrough; /* can clear predicate locks and
+ * inConflicts for committed
+ * transactions through this seq
+ * no */
+ /* Protected by SerializableFinishedListLock. */
+ SerCommitSeqNo HavePartialClearedThrough; /* have cleared through this
+ * seq no */
+ SERIALIZABLEXACT *OldCommittedSxact; /* shared copy of dummy sxact */
+
+ PredXactListElement element;
+} PredXactListData;
+
+typedef struct PredXactListData *PredXactList;
+
+#define PredXactListDataSize \
+ ((Size)MAXALIGN(sizeof(PredXactListData)))
+
+
+/*
+ * The following types are used to provide lists of rw-conflicts between
+ * pairs of transactions. Since exactly the same information is needed,
+ * they are also used to record possible unsafe transaction relationships
+ * for purposes of identifying safe snapshots for read-only transactions.
+ *
+ * When a RWConflictData is not in use to record either type of relationship
+ * between a pair of transactions, it is kept on an "available" list. The
+ * outLink field is used for maintaining that list.
+ */
+typedef struct RWConflictData
+{
+ SHM_QUEUE outLink; /* link for list of conflicts out from a sxact */
+ SHM_QUEUE inLink; /* link for list of conflicts in to a sxact */
+ SERIALIZABLEXACT *sxactOut;
+ SERIALIZABLEXACT *sxactIn;
+} RWConflictData;
+
+typedef struct RWConflictData *RWConflict;
+
+#define RWConflictDataSize \
+ ((Size)MAXALIGN(sizeof(RWConflictData)))
+
+typedef struct RWConflictPoolHeaderData
+{
+ SHM_QUEUE availableList;
+ RWConflict element;
+} RWConflictPoolHeaderData;
+
+typedef struct RWConflictPoolHeaderData *RWConflictPoolHeader;
+
+#define RWConflictPoolHeaderDataSize \
+ ((Size)MAXALIGN(sizeof(RWConflictPoolHeaderData)))
+
+
+/*
+ * The SERIALIZABLEXIDTAG struct identifies an xid assigned to a serializable
+ * transaction or any of its subtransactions.
+ */
+typedef struct SERIALIZABLEXIDTAG
+{
+ TransactionId xid;
+} SERIALIZABLEXIDTAG;
+
+/*
+ * The SERIALIZABLEXID struct provides a link from a TransactionId for a
+ * serializable transaction to the related SERIALIZABLEXACT record, even if
+ * the transaction has completed and its connection has been closed.
+ *
+ * These are created as new top level transaction IDs are first assigned to
+ * transactions which are participating in predicate locking. This may
+ * never happen for a particular transaction if it doesn't write anything.
+ * They are removed with their related serializable transaction objects.
+ *
+ * The SubTransGetTopmostTransaction method is used where necessary to get
+ * from an XID which might be from a subtransaction to the top level XID.
+ */
+typedef struct SERIALIZABLEXID
+{
+ /* hash key */
+ SERIALIZABLEXIDTAG tag;
+
+ /* data */
+ SERIALIZABLEXACT *myXact; /* pointer to the top level transaction data */
+} SERIALIZABLEXID;
+
+
+/*
+ * The PREDICATELOCKTARGETTAG struct identifies a database object which can
+ * be the target of predicate locks.
+ *
+ * Note that the hash function being used doesn't properly respect tag
+ * length -- if the length of the structure isn't a multiple of four bytes it
+ * will go to a four byte boundary past the end of the tag. If you change
+ * this struct, make sure any slack space is initialized, so that any random
+ * bytes in the middle or at the end are not included in the hash.
+ *
+ * TODO SSI: If we always use the same fields for the same type of value, we
+ * should rename these. Holding off until it's clear there are no exceptions.
+ * Since indexes are relations with blocks and tuples, it's looking likely that
+ * the rename will be possible. If not, we may need to divide the last field
+ * and use part of it for a target type, so that we know how to interpret the
+ * data..
+ */
+typedef struct PREDICATELOCKTARGETTAG
+{
+ uint32 locktag_field1; /* a 32-bit ID field */
+ uint32 locktag_field2; /* a 32-bit ID field */
+ uint32 locktag_field3; /* a 32-bit ID field */
+ uint32 locktag_field4; /* a 32-bit ID field */
+} PREDICATELOCKTARGETTAG;
+
+/*
+ * The PREDICATELOCKTARGET struct represents a database object on which there
+ * are predicate locks.
+ *
+ * A hash list of these objects is maintained in shared memory. An entry is
+ * added when a predicate lock is requested on an object which doesn't
+ * already have one. An entry is removed when the last lock is removed from
+ * its list.
+ */
+typedef struct PREDICATELOCKTARGET
+{
+ /* hash key */
+ PREDICATELOCKTARGETTAG tag; /* unique identifier of lockable object */
+
+ /* data */
+ SHM_QUEUE predicateLocks; /* list of PREDICATELOCK objects assoc. with
+ * predicate lock target */
+} PREDICATELOCKTARGET;
+
+
+/*
+ * The PREDICATELOCKTAG struct identifies an individual predicate lock.
+ *
+ * It is the combination of predicate lock target (which is a lockable
+ * object) and a serializable transaction which has acquired a lock on that
+ * target.
+ */
+typedef struct PREDICATELOCKTAG
+{
+ PREDICATELOCKTARGET *myTarget;
+ SERIALIZABLEXACT *myXact;
+} PREDICATELOCKTAG;
+
+/*
+ * The PREDICATELOCK struct represents an individual lock.
+ *
+ * An entry can be created here when the related database object is read, or
+ * by promotion of multiple finer-grained targets. All entries related to a
+ * serializable transaction are removed when that serializable transaction is
+ * cleaned up. Entries can also be removed when they are combined into a
+ * single coarser-grained lock entry.
+ */
+typedef struct PREDICATELOCK
+{
+ /* hash key */
+ PREDICATELOCKTAG tag; /* unique identifier of lock */
+
+ /* data */
+ SHM_QUEUE targetLink; /* list link in PREDICATELOCKTARGET's list of
+ * predicate locks */
+ SHM_QUEUE xactLink; /* list link in SERIALIZABLEXACT's list of
+ * predicate locks */
+ SerCommitSeqNo commitSeqNo; /* only used for summarized predicate locks */
+} PREDICATELOCK;
+
+
+/*
+ * The LOCALPREDICATELOCK struct represents a local copy of data which is
+ * also present in the PREDICATELOCK table, organized for fast access without
+ * needing to acquire a LWLock. It is strictly for optimization.
+ *
+ * Each serializable transaction creates its own local hash table to hold a
+ * collection of these. This information is used to determine when a number
+ * of fine-grained locks should be promoted to a single coarser-grained lock.
+ * The information is maintained more-or-less in parallel to the
+ * PREDICATELOCK data, but because this data is not protected by locks and is
+ * only used in an optimization heuristic, it is allowed to drift in a few
+ * corner cases where maintaining exact data would be expensive.
+ *
+ * The hash table is created when the serializable transaction acquires its
+ * snapshot, and its memory is released upon completion of the transaction.
+ */
+typedef struct LOCALPREDICATELOCK
+{
+ /* hash key */
+ PREDICATELOCKTARGETTAG tag; /* unique identifier of lockable object */
+
+ /* data */
+ bool held; /* is lock held, or just its children? */
+ int childLocks; /* number of child locks currently held */
+} LOCALPREDICATELOCK;
+
+
+/*
+ * The types of predicate locks which can be acquired.
+ */
+typedef enum PredicateLockTargetType
+{
+ PREDLOCKTAG_RELATION,
+ PREDLOCKTAG_PAGE,
+ PREDLOCKTAG_TUPLE
+ /* TODO SSI: Other types may be needed for index locking */
+} PredicateLockTargetType;
+
+
+/*
+ * This structure is used to quickly capture a copy of all predicate
+ * locks. This is currently used only by the pg_lock_status function,
+ * which in turn is used by the pg_locks view.
+ */
+typedef struct PredicateLockData
+{
+ int nelements;
+ PREDICATELOCKTARGETTAG *locktags;
+ SERIALIZABLEXACT *xacts;
+} PredicateLockData;
+
+
+/*
+ * These macros define how we map logical IDs of lockable objects into the
+ * physical fields of PREDICATELOCKTARGETTAG. Use these to set up values,
+ * rather than accessing the fields directly. Note multiple eval of target!
+ */
+#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag,dboid,reloid) \
+ ((locktag).locktag_field1 = (dboid), \
+ (locktag).locktag_field2 = (reloid), \
+ (locktag).locktag_field3 = InvalidBlockNumber, \
+ (locktag).locktag_field4 = InvalidOffsetNumber)
+
+#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag,dboid,reloid,blocknum) \
+ ((locktag).locktag_field1 = (dboid), \
+ (locktag).locktag_field2 = (reloid), \
+ (locktag).locktag_field3 = (blocknum), \
+ (locktag).locktag_field4 = InvalidOffsetNumber)
+
+#define SET_PREDICATELOCKTARGETTAG_TUPLE(locktag,dboid,reloid,blocknum,offnum) \
+ ((locktag).locktag_field1 = (dboid), \
+ (locktag).locktag_field2 = (reloid), \
+ (locktag).locktag_field3 = (blocknum), \
+ (locktag).locktag_field4 = (offnum))
+
+#define GET_PREDICATELOCKTARGETTAG_DB(locktag) \
+ ((Oid) (locktag).locktag_field1)
+#define GET_PREDICATELOCKTARGETTAG_RELATION(locktag) \
+ ((Oid) (locktag).locktag_field2)
+#define GET_PREDICATELOCKTARGETTAG_PAGE(locktag) \
+ ((BlockNumber) (locktag).locktag_field3)
+#define GET_PREDICATELOCKTARGETTAG_OFFSET(locktag) \
+ ((OffsetNumber) (locktag).locktag_field4)
+#define GET_PREDICATELOCKTARGETTAG_TYPE(locktag) \
+ (((locktag).locktag_field4 != InvalidOffsetNumber) ? PREDLOCKTAG_TUPLE : \
+ (((locktag).locktag_field3 != InvalidBlockNumber) ? PREDLOCKTAG_PAGE : \
+ PREDLOCKTAG_RELATION))
+
+/*
+ * Two-phase commit statefile records. There are two types: for each
+ * transaction, we generate one per-transaction record and a variable
+ * number of per-predicate-lock records.
+ */
+typedef enum TwoPhasePredicateRecordType
+{
+ TWOPHASEPREDICATERECORD_XACT,
+ TWOPHASEPREDICATERECORD_LOCK
+} TwoPhasePredicateRecordType;
+
+/*
+ * Per-transaction information to reconstruct a SERIALIZABLEXACT. Not
+ * much is needed because most of it not meaningful for a recovered
+ * prepared transaction.
+ *
+ * In particular, we do not record the in and out conflict lists for a
+ * prepared transaction because the associated SERIALIZABLEXACTs will
+ * not be available after recovery. Instead, we simply record the
+ * existence of each type of conflict by setting the transaction's
+ * summary conflict in/out flag.
+ */
+typedef struct TwoPhasePredicateXactRecord
+{
+ TransactionId xmin;
+ uint32 flags;
+} TwoPhasePredicateXactRecord;
+
+/* Per-lock state */
+typedef struct TwoPhasePredicateLockRecord
+{
+ PREDICATELOCKTARGETTAG target;
+ uint32 filler; /* to avoid length change in back-patched fix */
+} TwoPhasePredicateLockRecord;
+
+typedef struct TwoPhasePredicateRecord
+{
+ TwoPhasePredicateRecordType type;
+ union
+ {
+ TwoPhasePredicateXactRecord xactRecord;
+ TwoPhasePredicateLockRecord lockRecord;
+ } data;
+} TwoPhasePredicateRecord;
+
+/*
+ * Define a macro to use for an "empty" SERIALIZABLEXACT reference.
+ */
+#define InvalidSerializableXact ((SERIALIZABLEXACT *) NULL)
+
+
+/*
+ * Function definitions for functions needing awareness of predicate
+ * locking internals.
+ */
+extern PredicateLockData *GetPredicateLockStatusData(void);
+extern int GetSafeSnapshotBlockingPids(int blocked_pid,
+ int *output, int output_size);
+
+#endif /* PREDICATE_INTERNALS_H */
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
new file mode 100644
index 0000000..1ee9000
--- /dev/null
+++ b/src/include/storage/proc.h
@@ -0,0 +1,333 @@
+/*-------------------------------------------------------------------------
+ *
+ * proc.h
+ * per-process shared memory data structures
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/proc.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _PROC_H_
+#define _PROC_H_
+
+#include "access/clog.h"
+#include "access/xlogdefs.h"
+#include "lib/ilist.h"
+#include "storage/latch.h"
+#include "storage/lock.h"
+#include "storage/pg_sema.h"
+#include "storage/proclist_types.h"
+
+/*
+ * Each backend advertises up to PGPROC_MAX_CACHED_SUBXIDS TransactionIds
+ * for non-aborted subtransactions of its current top transaction. These
+ * have to be treated as running XIDs by other backends.
+ *
+ * We also keep track of whether the cache overflowed (ie, the transaction has
+ * generated at least one subtransaction that didn't fit in the cache).
+ * If none of the caches have overflowed, we can assume that an XID that's not
+ * listed anywhere in the PGPROC array is not a running transaction. Else we
+ * have to look at pg_subtrans.
+ */
+#define PGPROC_MAX_CACHED_SUBXIDS 64 /* XXX guessed-at value */
+
+struct XidCache
+{
+ TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS];
+};
+
+/*
+ * Flags for PGXACT->vacuumFlags
+ *
+ * Note: If you modify these flags, you need to modify PROCARRAY_XXX flags
+ * in src/include/storage/procarray.h.
+ *
+ * PROC_RESERVED may later be assigned for use in vacuumFlags, but its value is
+ * used for PROCARRAY_SLOTS_XMIN in procarray.h, so GetOldestXmin won't be able
+ * to match and ignore processes with this flag set.
+ */
+#define PROC_IS_AUTOVACUUM 0x01 /* is it an autovac worker? */
+#define PROC_IN_VACUUM 0x02 /* currently running lazy vacuum */
+#define PROC_IN_ANALYZE 0x04 /* currently running analyze */
+#define PROC_VACUUM_FOR_WRAPAROUND 0x08 /* set by autovac only */
+#define PROC_IN_LOGICAL_DECODING 0x10 /* currently doing logical
+ * decoding outside xact */
+#define PROC_RESERVED 0x20 /* reserved for procarray */
+
+/* flags reset at EOXact */
+#define PROC_VACUUM_STATE_MASK \
+ (PROC_IN_VACUUM | PROC_IN_ANALYZE | PROC_VACUUM_FOR_WRAPAROUND)
+
+/*
+ * We allow a small number of "weak" relation locks (AccessShareLock,
+ * RowShareLock, RowExclusiveLock) to be recorded in the PGPROC structure
+ * rather than the main lock table. This eases contention on the lock
+ * manager LWLocks. See storage/lmgr/README for additional details.
+ */
+#define FP_LOCK_SLOTS_PER_BACKEND 16
+
+/*
+ * An invalid pgprocno. Must be larger than the maximum number of PGPROC
+ * structures we could possibly have. See comments for MAX_BACKENDS.
+ */
+#define INVALID_PGPROCNO PG_INT32_MAX
+
+/*
+ * Each backend has a PGPROC struct in shared memory. There is also a list of
+ * currently-unused PGPROC structs that will be reallocated to new backends.
+ *
+ * links: list link for any list the PGPROC is in. When waiting for a lock,
+ * the PGPROC is linked into that lock's waitProcs queue. A recycled PGPROC
+ * is linked into ProcGlobal's freeProcs list.
+ *
+ * Note: twophase.c also sets up a dummy PGPROC struct for each currently
+ * prepared transaction. These PGPROCs appear in the ProcArray data structure
+ * so that the prepared transactions appear to be still running and are
+ * correctly shown as holding locks. A prepared transaction PGPROC can be
+ * distinguished from a real one at need by the fact that it has pid == 0.
+ * The semaphore and lock-activity fields in a prepared-xact PGPROC are unused,
+ * but its myProcLocks[] lists are valid.
+ */
+struct PGPROC
+{
+ /* proc->links MUST BE FIRST IN STRUCT (see ProcSleep,ProcWakeup,etc) */
+ SHM_QUEUE links; /* list link if process is in a list */
+ PGPROC **procgloballist; /* procglobal list that owns this PGPROC */
+
+ PGSemaphore sem; /* ONE semaphore to sleep on */
+ int waitStatus; /* STATUS_WAITING, STATUS_OK or STATUS_ERROR */
+
+ Latch procLatch; /* generic latch for process */
+
+ LocalTransactionId lxid; /* local id of top-level transaction currently
+ * being executed by this proc, if running;
+ * else InvalidLocalTransactionId */
+ int pid; /* Backend's process ID; 0 if prepared xact */
+ int pgprocno;
+
+ /* These fields are zero while a backend is still starting up: */
+ BackendId backendId; /* This backend's backend ID (if assigned) */
+ Oid databaseId; /* OID of database this backend is using */
+ Oid roleId; /* OID of role using this backend */
+
+ Oid tempNamespaceId; /* OID of temp schema this backend is
+ * using */
+
+ bool isBackgroundWorker; /* true if background worker. */
+
+ /*
+ * While in hot standby mode, shows that a conflict signal has been sent
+ * for the current transaction. Set/cleared while holding ProcArrayLock,
+ * though not required. Accessed without lock, if needed.
+ */
+ bool recoveryConflictPending;
+
+ /* Info about LWLock the process is currently waiting for, if any. */
+ bool lwWaiting; /* true if waiting for an LW lock */
+ uint8 lwWaitMode; /* lwlock mode being waited for */
+ proclist_node lwWaitLink; /* position in LW lock wait list */
+
+ /* Support for condition variables. */
+ proclist_node cvWaitLink; /* position in CV wait list */
+
+ /* Info about lock the process is currently waiting for, if any. */
+ /* waitLock and waitProcLock are NULL if not currently waiting. */
+ LOCK *waitLock; /* Lock object we're sleeping on ... */
+ PROCLOCK *waitProcLock; /* Per-holder info for awaited lock */
+ LOCKMODE waitLockMode; /* type of lock we're waiting for */
+ LOCKMASK heldLocks; /* bitmask for lock types already held on this
+ * lock object by this backend */
+
+ bool delayChkpt; /* true if this proc delays checkpoint start */
+
+ /*
+ * Info to allow us to wait for synchronous replication, if needed.
+ * waitLSN is InvalidXLogRecPtr if not waiting; set only by user backend.
+ * syncRepState must not be touched except by owning process or WALSender.
+ * syncRepLinks used only while holding SyncRepLock.
+ */
+ XLogRecPtr waitLSN; /* waiting for this LSN or higher */
+ int syncRepState; /* wait state for sync rep */
+ SHM_QUEUE syncRepLinks; /* list link if process is in syncrep queue */
+
+ /*
+ * All PROCLOCK objects for locks held or awaited by this backend are
+ * linked into one of these lists, according to the partition number of
+ * their lock.
+ */
+ SHM_QUEUE myProcLocks[NUM_LOCK_PARTITIONS];
+
+ struct XidCache subxids; /* cache for subtransaction XIDs */
+
+ /* Support for group XID clearing. */
+ /* true, if member of ProcArray group waiting for XID clear */
+ bool procArrayGroupMember;
+ /* next ProcArray group member waiting for XID clear */
+ pg_atomic_uint32 procArrayGroupNext;
+
+ /*
+ * latest transaction id among the transaction's main XID and
+ * subtransactions
+ */
+ TransactionId procArrayGroupMemberXid;
+
+ uint32 wait_event_info; /* proc's wait information */
+
+ /* Support for group transaction status update. */
+ bool clogGroupMember; /* true, if member of clog group */
+ pg_atomic_uint32 clogGroupNext; /* next clog group member */
+ TransactionId clogGroupMemberXid; /* transaction id of clog group member */
+ XidStatus clogGroupMemberXidStatus; /* transaction status of clog
+ * group member */
+ int clogGroupMemberPage; /* clog page corresponding to
+ * transaction id of clog group member */
+ XLogRecPtr clogGroupMemberLsn; /* WAL location of commit record for clog
+ * group member */
+
+ /* Lock manager data, recording fast-path locks taken by this backend. */
+ LWLock fpInfoLock; /* protects per-backend fast-path state */
+ uint64 fpLockBits; /* lock modes held for each fast-path slot */
+ Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]; /* slots for rel oids */
+ bool fpVXIDLock; /* are we holding a fast-path VXID lock? */
+ LocalTransactionId fpLocalTransactionId; /* lxid for fast-path VXID
+ * lock */
+
+ /*
+ * Support for lock groups. Use LockHashPartitionLockByProc on the group
+ * leader to get the LWLock protecting these fields.
+ */
+ PGPROC *lockGroupLeader; /* lock group leader, if I'm a member */
+ dlist_head lockGroupMembers; /* list of members, if I'm a leader */
+ dlist_node lockGroupLink; /* my member link, if I'm a member */
+};
+
+/* NOTE: "typedef struct PGPROC PGPROC" appears in storage/lock.h. */
+
+
+extern PGDLLIMPORT PGPROC *MyProc;
+extern PGDLLIMPORT struct PGXACT *MyPgXact;
+
+/*
+ * Prior to PostgreSQL 9.2, the fields below were stored as part of the
+ * PGPROC. However, benchmarking revealed that packing these particular
+ * members into a separate array as tightly as possible sped up GetSnapshotData
+ * considerably on systems with many CPU cores, by reducing the number of
+ * cache lines needing to be fetched. Thus, think very carefully before adding
+ * anything else here.
+ */
+typedef struct PGXACT
+{
+ TransactionId xid; /* id of top-level transaction currently being
+ * executed by this proc, if running and XID
+ * is assigned; else InvalidTransactionId */
+
+ TransactionId xmin; /* minimal running XID as it was when we were
+ * starting our xact, excluding LAZY VACUUM:
+ * vacuum must not remove tuples deleted by
+ * xid >= xmin ! */
+
+ uint8 vacuumFlags; /* vacuum-related flags, see above */
+ bool overflowed;
+
+ uint8 nxids;
+} PGXACT;
+
+/*
+ * There is one ProcGlobal struct for the whole database cluster.
+ */
+typedef struct PROC_HDR
+{
+ /* Array of PGPROC structures (not including dummies for prepared txns) */
+ PGPROC *allProcs;
+ /* Array of PGXACT structures (not including dummies for prepared txns) */
+ PGXACT *allPgXact;
+ /* Length of allProcs array */
+ uint32 allProcCount;
+ /* Head of list of free PGPROC structures */
+ PGPROC *freeProcs;
+ /* Head of list of autovacuum's free PGPROC structures */
+ PGPROC *autovacFreeProcs;
+ /* Head of list of bgworker free PGPROC structures */
+ PGPROC *bgworkerFreeProcs;
+ /* Head of list of walsender free PGPROC structures */
+ PGPROC *walsenderFreeProcs;
+ /* First pgproc waiting for group XID clear */
+ pg_atomic_uint32 procArrayGroupFirst;
+ /* First pgproc waiting for group transaction status update */
+ pg_atomic_uint32 clogGroupFirst;
+ /* WALWriter process's latch */
+ Latch *walwriterLatch;
+ /* Checkpointer process's latch */
+ Latch *checkpointerLatch;
+ /* Current shared estimate of appropriate spins_per_delay value */
+ int spins_per_delay;
+ /* The proc of the Startup process, since not in ProcArray */
+ PGPROC *startupProc;
+ int startupProcPid;
+ /* Buffer id of the buffer that Startup process waits for pin on, or -1 */
+ int startupBufferPinWaitBufId;
+} PROC_HDR;
+
+extern PGDLLIMPORT PROC_HDR *ProcGlobal;
+
+extern PGPROC *PreparedXactProcs;
+
+/* Accessor for PGPROC given a pgprocno. */
+#define GetPGProcByNumber(n) (&ProcGlobal->allProcs[(n)])
+
+/*
+ * We set aside some extra PGPROC structures for auxiliary processes,
+ * ie things that aren't full-fledged backends but need shmem access.
+ *
+ * Background writer, checkpointer and WAL writer run during normal operation.
+ * Startup process and WAL receiver also consume 2 slots, but WAL writer is
+ * launched only after startup has exited, so we only need 4 slots.
+ */
+#define NUM_AUXILIARY_PROCS 4
+
+/* configurable options */
+extern PGDLLIMPORT int DeadlockTimeout;
+extern PGDLLIMPORT int StatementTimeout;
+extern PGDLLIMPORT int LockTimeout;
+extern PGDLLIMPORT int IdleInTransactionSessionTimeout;
+extern bool log_lock_waits;
+
+
+/*
+ * Function Prototypes
+ */
+extern int ProcGlobalSemas(void);
+extern Size ProcGlobalShmemSize(void);
+extern void InitProcGlobal(void);
+extern void InitProcess(void);
+extern void InitProcessPhase2(void);
+extern void InitAuxiliaryProcess(void);
+
+extern void PublishStartupProcessInformation(void);
+extern void SetStartupBufferPinWaitBufId(int bufid);
+extern int GetStartupBufferPinWaitBufId(void);
+
+extern bool HaveNFreeProcs(int n);
+extern void ProcReleaseLocks(bool isCommit);
+
+extern void ProcQueueInit(PROC_QUEUE *queue);
+extern int ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable);
+extern PGPROC *ProcWakeup(PGPROC *proc, int waitStatus);
+extern void ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock);
+extern void CheckDeadLockAlert(void);
+extern bool IsWaitingForLock(void);
+extern void LockErrorCleanup(void);
+
+extern void ProcWaitForSignal(uint32 wait_event_info);
+extern void ProcSendSignal(int pid);
+
+extern PGPROC *AuxiliaryPidGetProc(int pid);
+
+extern void BecomeLockGroupLeader(void);
+extern bool BecomeLockGroupMember(PGPROC *leader, int pid);
+
+#endif /* _PROC_H_ */
diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h
new file mode 100644
index 0000000..200ef8d
--- /dev/null
+++ b/src/include/storage/procarray.h
@@ -0,0 +1,130 @@
+/*-------------------------------------------------------------------------
+ *
+ * procarray.h
+ * POSTGRES process array definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/procarray.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PROCARRAY_H
+#define PROCARRAY_H
+
+#include "storage/lock.h"
+#include "storage/standby.h"
+#include "utils/relcache.h"
+#include "utils/snapshot.h"
+
+
+/*
+ * These are to implement PROCARRAY_FLAGS_XXX
+ *
+ * Note: These flags are cloned from PROC_XXX flags in src/include/storage/proc.h
+ * to avoid forcing to include proc.h when including procarray.h. So if you modify
+ * PROC_XXX flags, you need to modify these flags.
+ */
+#define PROCARRAY_VACUUM_FLAG 0x02 /* currently running lazy
+ * vacuum */
+#define PROCARRAY_ANALYZE_FLAG 0x04 /* currently running
+ * analyze */
+#define PROCARRAY_LOGICAL_DECODING_FLAG 0x10 /* currently doing logical
+ * decoding outside xact */
+
+#define PROCARRAY_SLOTS_XMIN 0x20 /* replication slot xmin,
+ * catalog_xmin */
+/*
+ * Only flags in PROCARRAY_PROC_FLAGS_MASK are considered when matching
+ * PGXACT->vacuumFlags. Other flags are used for different purposes and
+ * have no corresponding PROC flag equivalent.
+ */
+#define PROCARRAY_PROC_FLAGS_MASK (PROCARRAY_VACUUM_FLAG | \
+ PROCARRAY_ANALYZE_FLAG | \
+ PROCARRAY_LOGICAL_DECODING_FLAG)
+
+/* Use the following flags as an input "flags" to GetOldestXmin function */
+/* Consider all backends except for logical decoding ones which manage xmin separately */
+#define PROCARRAY_FLAGS_DEFAULT PROCARRAY_LOGICAL_DECODING_FLAG
+/* Ignore vacuum backends */
+#define PROCARRAY_FLAGS_VACUUM PROCARRAY_FLAGS_DEFAULT | PROCARRAY_VACUUM_FLAG
+/* Ignore analyze backends */
+#define PROCARRAY_FLAGS_ANALYZE PROCARRAY_FLAGS_DEFAULT | PROCARRAY_ANALYZE_FLAG
+/* Ignore both vacuum and analyze backends */
+#define PROCARRAY_FLAGS_VACUUM_ANALYZE PROCARRAY_FLAGS_DEFAULT | PROCARRAY_VACUUM_FLAG | PROCARRAY_ANALYZE_FLAG
+
+extern Size ProcArrayShmemSize(void);
+extern void CreateSharedProcArray(void);
+extern void ProcArrayAdd(PGPROC *proc);
+extern void ProcArrayRemove(PGPROC *proc, TransactionId latestXid);
+
+extern void ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid);
+extern void ProcArrayClearTransaction(PGPROC *proc);
+
+extern void ProcArrayInitRecovery(TransactionId initializedUptoXID);
+extern void ProcArrayApplyRecoveryInfo(RunningTransactions running);
+extern void ProcArrayApplyXidAssignment(TransactionId topxid,
+ int nsubxids, TransactionId *subxids);
+
+extern void RecordKnownAssignedTransactionIds(TransactionId xid);
+extern void ExpireTreeKnownAssignedTransactionIds(TransactionId xid,
+ int nsubxids, TransactionId *subxids,
+ TransactionId max_xid);
+extern void ExpireAllKnownAssignedTransactionIds(void);
+extern void ExpireOldKnownAssignedTransactionIds(TransactionId xid);
+
+extern int GetMaxSnapshotXidCount(void);
+extern int GetMaxSnapshotSubxidCount(void);
+
+extern Snapshot GetSnapshotData(Snapshot snapshot);
+
+extern bool ProcArrayInstallImportedXmin(TransactionId xmin,
+ VirtualTransactionId *sourcevxid);
+extern bool ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc);
+
+extern RunningTransactions GetRunningTransactionData(void);
+
+extern bool TransactionIdIsInProgress(TransactionId xid);
+extern bool TransactionIdIsActive(TransactionId xid);
+extern TransactionId GetOldestXmin(Relation rel, int flags);
+extern TransactionId GetOldestActiveTransactionId(void);
+extern TransactionId GetOldestSafeDecodingTransactionId(bool catalogOnly);
+
+extern VirtualTransactionId *GetVirtualXIDsDelayingChkpt(int *nvxids);
+extern bool HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids);
+
+extern PGPROC *BackendPidGetProc(int pid);
+extern PGPROC *BackendPidGetProcWithLock(int pid);
+extern int BackendXidGetPid(TransactionId xid);
+extern bool IsBackendPid(int pid);
+
+extern VirtualTransactionId *GetCurrentVirtualXIDs(TransactionId limitXmin,
+ bool excludeXmin0, bool allDbs, int excludeVacuum,
+ int *nvxids);
+extern VirtualTransactionId *GetConflictingVirtualXIDs(TransactionId limitXmin, Oid dbOid);
+extern pid_t CancelVirtualTransaction(VirtualTransactionId vxid, ProcSignalReason sigmode);
+extern pid_t SignalVirtualTransaction(VirtualTransactionId vxid, ProcSignalReason sigmode,
+ bool conflictPending);
+
+extern bool MinimumActiveBackends(int min);
+extern int CountDBBackends(Oid databaseid);
+extern int CountDBConnections(Oid databaseid);
+extern void CancelDBBackends(Oid databaseid, ProcSignalReason sigmode, bool conflictPending);
+extern int CountUserBackends(Oid roleid);
+extern bool CountOtherDBBackends(Oid databaseId,
+ int *nbackends, int *nprepared);
+extern void TerminateOtherDBBackends(Oid databaseId);
+
+extern void XidCacheRemoveRunningXids(TransactionId xid,
+ int nxids, const TransactionId *xids,
+ TransactionId latestXid);
+
+extern void ProcArraySetReplicationSlotXmin(TransactionId xmin,
+ TransactionId catalog_xmin, bool already_locked);
+
+extern void ProcArrayGetReplicationSlotXmin(TransactionId *xmin,
+ TransactionId *catalog_xmin);
+
+#endif /* PROCARRAY_H */
diff --git a/src/include/storage/proclist.h b/src/include/storage/proclist.h
new file mode 100644
index 0000000..9420091
--- /dev/null
+++ b/src/include/storage/proclist.h
@@ -0,0 +1,219 @@
+/*-------------------------------------------------------------------------
+ *
+ * proclist.h
+ * operations on doubly-linked lists of pgprocnos
+ *
+ * The interface is similar to dlist from ilist.h, but uses pgprocno instead
+ * of pointers. This allows proclist_head to be mapped at different addresses
+ * in different backends.
+ *
+ * See proclist_types.h for the structs that these functions operate on. They
+ * are separated to break a header dependency cycle with proc.h.
+ *
+ * Portions Copyright (c) 2016-2020, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/storage/proclist.h
+ *-------------------------------------------------------------------------
+ */
+#ifndef PROCLIST_H
+#define PROCLIST_H
+
+#include "storage/proc.h"
+#include "storage/proclist_types.h"
+
+/*
+ * Initialize a proclist.
+ */
+static inline void
+proclist_init(proclist_head *list)
+{
+ list->head = list->tail = INVALID_PGPROCNO;
+}
+
+/*
+ * Is the list empty?
+ */
+static inline bool
+proclist_is_empty(proclist_head *list)
+{
+ return list->head == INVALID_PGPROCNO;
+}
+
+/*
+ * Get a pointer to a proclist_node inside a given PGPROC, given a procno and
+ * the proclist_node field's offset within struct PGPROC.
+ */
+static inline proclist_node *
+proclist_node_get(int procno, size_t node_offset)
+{
+ char *entry = (char *) GetPGProcByNumber(procno);
+
+ return (proclist_node *) (entry + node_offset);
+}
+
+/*
+ * Insert a process at the beginning of a list.
+ */
+static inline void
+proclist_push_head_offset(proclist_head *list, int procno, size_t node_offset)
+{
+ proclist_node *node = proclist_node_get(procno, node_offset);
+
+ Assert(node->next == 0 && node->prev == 0);
+
+ if (list->head == INVALID_PGPROCNO)
+ {
+ Assert(list->tail == INVALID_PGPROCNO);
+ node->next = node->prev = INVALID_PGPROCNO;
+ list->head = list->tail = procno;
+ }
+ else
+ {
+ Assert(list->tail != INVALID_PGPROCNO);
+ Assert(list->head != procno);
+ Assert(list->tail != procno);
+ node->next = list->head;
+ proclist_node_get(node->next, node_offset)->prev = procno;
+ node->prev = INVALID_PGPROCNO;
+ list->head = procno;
+ }
+}
+
+/*
+ * Insert a process at the end of a list.
+ */
+static inline void
+proclist_push_tail_offset(proclist_head *list, int procno, size_t node_offset)
+{
+ proclist_node *node = proclist_node_get(procno, node_offset);
+
+ Assert(node->next == 0 && node->prev == 0);
+
+ if (list->tail == INVALID_PGPROCNO)
+ {
+ Assert(list->head == INVALID_PGPROCNO);
+ node->next = node->prev = INVALID_PGPROCNO;
+ list->head = list->tail = procno;
+ }
+ else
+ {
+ Assert(list->head != INVALID_PGPROCNO);
+ Assert(list->head != procno);
+ Assert(list->tail != procno);
+ node->prev = list->tail;
+ proclist_node_get(node->prev, node_offset)->next = procno;
+ node->next = INVALID_PGPROCNO;
+ list->tail = procno;
+ }
+}
+
+/*
+ * Delete a process from a list --- it must be in the list!
+ */
+static inline void
+proclist_delete_offset(proclist_head *list, int procno, size_t node_offset)
+{
+ proclist_node *node = proclist_node_get(procno, node_offset);
+
+ Assert(node->next != 0 || node->prev != 0);
+
+ if (node->prev == INVALID_PGPROCNO)
+ {
+ Assert(list->head == procno);
+ list->head = node->next;
+ }
+ else
+ proclist_node_get(node->prev, node_offset)->next = node->next;
+
+ if (node->next == INVALID_PGPROCNO)
+ {
+ Assert(list->tail == procno);
+ list->tail = node->prev;
+ }
+ else
+ proclist_node_get(node->next, node_offset)->prev = node->prev;
+
+ node->next = node->prev = 0;
+}
+
+/*
+ * Check if a process is currently in a list. It must be known that the
+ * process is not in any _other_ proclist that uses the same proclist_node,
+ * so that the only possibilities are that it is in this list or none.
+ */
+static inline bool
+proclist_contains_offset(proclist_head *list, int procno,
+ size_t node_offset)
+{
+ proclist_node *node = proclist_node_get(procno, node_offset);
+
+ /* If it's not in any list, it's definitely not in this one. */
+ if (node->prev == 0 && node->next == 0)
+ return false;
+
+ /*
+ * It must, in fact, be in this list. Ideally, in assert-enabled builds,
+ * we'd verify that. But since this function is typically used while
+ * holding a spinlock, crawling the whole list is unacceptable. However,
+ * we can verify matters in O(1) time when the node is a list head or
+ * tail, and that seems worth doing, since in practice that should often
+ * be enough to catch mistakes.
+ */
+ Assert(node->prev != INVALID_PGPROCNO || list->head == procno);
+ Assert(node->next != INVALID_PGPROCNO || list->tail == procno);
+
+ return true;
+}
+
+/*
+ * Remove and return the first process from a list (there must be one).
+ */
+static inline PGPROC *
+proclist_pop_head_node_offset(proclist_head *list, size_t node_offset)
+{
+ PGPROC *proc;
+
+ Assert(!proclist_is_empty(list));
+ proc = GetPGProcByNumber(list->head);
+ proclist_delete_offset(list, list->head, node_offset);
+ return proc;
+}
+
+/*
+ * Helper macros to avoid repetition of offsetof(PGPROC, <member>).
+ * 'link_member' is the name of a proclist_node member in PGPROC.
+ */
+#define proclist_delete(list, procno, link_member) \
+ proclist_delete_offset((list), (procno), offsetof(PGPROC, link_member))
+#define proclist_push_head(list, procno, link_member) \
+ proclist_push_head_offset((list), (procno), offsetof(PGPROC, link_member))
+#define proclist_push_tail(list, procno, link_member) \
+ proclist_push_tail_offset((list), (procno), offsetof(PGPROC, link_member))
+#define proclist_pop_head_node(list, link_member) \
+ proclist_pop_head_node_offset((list), offsetof(PGPROC, link_member))
+#define proclist_contains(list, procno, link_member) \
+ proclist_contains_offset((list), (procno), offsetof(PGPROC, link_member))
+
+/*
+ * Iterate through the list pointed at by 'lhead', storing the current
+ * position in 'iter'. 'link_member' is the name of a proclist_node member in
+ * PGPROC. Access the current position with iter.cur.
+ *
+ * The only list modification allowed while iterating is deleting the current
+ * node with proclist_delete(list, iter.cur, node_offset).
+ */
+#define proclist_foreach_modify(iter, lhead, link_member) \
+ for (AssertVariableIsOfTypeMacro(iter, proclist_mutable_iter), \
+ AssertVariableIsOfTypeMacro(lhead, proclist_head *), \
+ (iter).cur = (lhead)->head, \
+ (iter).next = (iter).cur == INVALID_PGPROCNO ? INVALID_PGPROCNO : \
+ proclist_node_get((iter).cur, \
+ offsetof(PGPROC, link_member))->next; \
+ (iter).cur != INVALID_PGPROCNO; \
+ (iter).cur = (iter).next, \
+ (iter).next = (iter).cur == INVALID_PGPROCNO ? INVALID_PGPROCNO : \
+ proclist_node_get((iter).cur, \
+ offsetof(PGPROC, link_member))->next)
+
+#endif /* PROCLIST_H */
diff --git a/src/include/storage/proclist_types.h b/src/include/storage/proclist_types.h
new file mode 100644
index 0000000..aba5578
--- /dev/null
+++ b/src/include/storage/proclist_types.h
@@ -0,0 +1,51 @@
+/*-------------------------------------------------------------------------
+ *
+ * proclist_types.h
+ * doubly-linked lists of pgprocnos
+ *
+ * See proclist.h for functions that operate on these types.
+ *
+ * Portions Copyright (c) 2016-2020, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/include/storage/proclist_types.h
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef PROCLIST_TYPES_H
+#define PROCLIST_TYPES_H
+
+/*
+ * A node in a doubly-linked list of processes. The link fields contain
+ * the 0-based PGPROC indexes of the next and previous process, or
+ * INVALID_PGPROCNO in the next-link of the last node and the prev-link
+ * of the first node. A node that is currently not in any list
+ * should have next == prev == 0; this is not a possible state for a node
+ * that is in a list, because we disallow circularity.
+ */
+typedef struct proclist_node
+{
+ int next; /* pgprocno of the next PGPROC */
+ int prev; /* pgprocno of the prev PGPROC */
+} proclist_node;
+
+/*
+ * Header of a doubly-linked list of PGPROCs, identified by pgprocno.
+ * An empty list is represented by head == tail == INVALID_PGPROCNO.
+ */
+typedef struct proclist_head
+{
+ int head; /* pgprocno of the head PGPROC */
+ int tail; /* pgprocno of the tail PGPROC */
+} proclist_head;
+
+/*
+ * List iterator allowing some modifications while iterating.
+ */
+typedef struct proclist_mutable_iter
+{
+ int cur; /* pgprocno of the current PGPROC */
+ int next; /* pgprocno of the next PGPROC */
+} proclist_mutable_iter;
+
+#endif /* PROCLIST_TYPES_H */
diff --git a/src/include/storage/procsignal.h b/src/include/storage/procsignal.h
new file mode 100644
index 0000000..5cb3969
--- /dev/null
+++ b/src/include/storage/procsignal.h
@@ -0,0 +1,75 @@
+/*-------------------------------------------------------------------------
+ *
+ * procsignal.h
+ * Routines for interprocess signaling
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/procsignal.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PROCSIGNAL_H
+#define PROCSIGNAL_H
+
+#include "storage/backendid.h"
+
+
+/*
+ * Reasons for signaling a Postgres child process (a backend or an auxiliary
+ * process, like checkpointer). We can cope with concurrent signals for different
+ * reasons. However, if the same reason is signaled multiple times in quick
+ * succession, the process is likely to observe only one notification of it.
+ * This is okay for the present uses.
+ *
+ * Also, because of race conditions, it's important that all the signals be
+ * defined so that no harm is done if a process mistakenly receives one.
+ */
+typedef enum
+{
+ PROCSIG_CATCHUP_INTERRUPT, /* sinval catchup interrupt */
+ PROCSIG_NOTIFY_INTERRUPT, /* listen/notify interrupt */
+ PROCSIG_PARALLEL_MESSAGE, /* message from cooperating parallel backend */
+ PROCSIG_WALSND_INIT_STOPPING, /* ask walsenders to prepare for shutdown */
+ PROCSIG_BARRIER, /* global barrier interrupt */
+
+ /* Recovery conflict reasons */
+ PROCSIG_RECOVERY_CONFLICT_DATABASE,
+ PROCSIG_RECOVERY_CONFLICT_TABLESPACE,
+ PROCSIG_RECOVERY_CONFLICT_LOCK,
+ PROCSIG_RECOVERY_CONFLICT_SNAPSHOT,
+ PROCSIG_RECOVERY_CONFLICT_BUFFERPIN,
+ PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK,
+
+ NUM_PROCSIGNALS /* Must be last! */
+} ProcSignalReason;
+
+typedef enum
+{
+ /*
+ * XXX. PROCSIGNAL_BARRIER_PLACEHOLDER should be replaced when the first
+ * real user of the ProcSignalBarrier mechanism is added. It's just here
+ * for now because we can't have an empty enum.
+ */
+ PROCSIGNAL_BARRIER_PLACEHOLDER = 0
+} ProcSignalBarrierType;
+
+/*
+ * prototypes for functions in procsignal.c
+ */
+extern Size ProcSignalShmemSize(void);
+extern void ProcSignalShmemInit(void);
+
+extern void ProcSignalInit(int pss_idx);
+extern int SendProcSignal(pid_t pid, ProcSignalReason reason,
+ BackendId backendId);
+
+extern uint64 EmitProcSignalBarrier(ProcSignalBarrierType type);
+extern void WaitForProcSignalBarrier(uint64 generation);
+extern void ProcessProcSignalBarrier(void);
+
+extern void procsignal_sigusr1_handler(SIGNAL_ARGS);
+
+#endif /* PROCSIGNAL_H */
diff --git a/src/include/storage/reinit.h b/src/include/storage/reinit.h
new file mode 100644
index 0000000..15d2e41
--- /dev/null
+++ b/src/include/storage/reinit.h
@@ -0,0 +1,28 @@
+/*-------------------------------------------------------------------------
+ *
+ * reinit.h
+ * Reinitialization of unlogged relations
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/reinit.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef REINIT_H
+#define REINIT_H
+
+#include "common/relpath.h"
+
+
+extern void ResetUnloggedRelations(int op);
+extern bool parse_filename_for_nontemp_relation(const char *name,
+ int *oidchars, ForkNumber *fork);
+
+#define UNLOGGED_RELATION_CLEANUP 0x0001
+#define UNLOGGED_RELATION_INIT 0x0002
+
+#endif /* REINIT_H */
diff --git a/src/include/storage/relfilenode.h b/src/include/storage/relfilenode.h
new file mode 100644
index 0000000..4de9fc1
--- /dev/null
+++ b/src/include/storage/relfilenode.h
@@ -0,0 +1,99 @@
+/*-------------------------------------------------------------------------
+ *
+ * relfilenode.h
+ * Physical access information for relations.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/relfilenode.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef RELFILENODE_H
+#define RELFILENODE_H
+
+#include "common/relpath.h"
+#include "storage/backendid.h"
+
+/*
+ * RelFileNode must provide all that we need to know to physically access
+ * a relation, with the exception of the backend ID, which can be provided
+ * separately. Note, however, that a "physical" relation is comprised of
+ * multiple files on the filesystem, as each fork is stored as a separate
+ * file, and each fork can be divided into multiple segments. See md.c.
+ *
+ * spcNode identifies the tablespace of the relation. It corresponds to
+ * pg_tablespace.oid.
+ *
+ * dbNode identifies the database of the relation. It is zero for
+ * "shared" relations (those common to all databases of a cluster).
+ * Nonzero dbNode values correspond to pg_database.oid.
+ *
+ * relNode identifies the specific relation. relNode corresponds to
+ * pg_class.relfilenode (NOT pg_class.oid, because we need to be able
+ * to assign new physical files to relations in some situations).
+ * Notice that relNode is only unique within a database in a particular
+ * tablespace.
+ *
+ * Note: spcNode must be GLOBALTABLESPACE_OID if and only if dbNode is
+ * zero. We support shared relations only in the "global" tablespace.
+ *
+ * Note: in pg_class we allow reltablespace == 0 to denote that the
+ * relation is stored in its database's "default" tablespace (as
+ * identified by pg_database.dattablespace). However this shorthand
+ * is NOT allowed in RelFileNode structs --- the real tablespace ID
+ * must be supplied when setting spcNode.
+ *
+ * Note: in pg_class, relfilenode can be zero to denote that the relation
+ * is a "mapped" relation, whose current true filenode number is available
+ * from relmapper.c. Again, this case is NOT allowed in RelFileNodes.
+ *
+ * Note: various places use RelFileNode in hashtable keys. Therefore,
+ * there *must not* be any unused padding bytes in this struct. That
+ * should be safe as long as all the fields are of type Oid.
+ */
+typedef struct RelFileNode
+{
+ Oid spcNode; /* tablespace */
+ Oid dbNode; /* database */
+ Oid relNode; /* relation */
+} RelFileNode;
+
+/*
+ * Augmenting a relfilenode with the backend ID provides all the information
+ * we need to locate the physical storage. The backend ID is InvalidBackendId
+ * for regular relations (those accessible to more than one backend), or the
+ * owning backend's ID for backend-local relations. Backend-local relations
+ * are always transient and removed in case of a database crash; they are
+ * never WAL-logged or fsync'd.
+ */
+typedef struct RelFileNodeBackend
+{
+ RelFileNode node;
+ BackendId backend;
+} RelFileNodeBackend;
+
+#define RelFileNodeBackendIsTemp(rnode) \
+ ((rnode).backend != InvalidBackendId)
+
+/*
+ * Note: RelFileNodeEquals and RelFileNodeBackendEquals compare relNode first
+ * since that is most likely to be different in two unequal RelFileNodes. It
+ * is probably redundant to compare spcNode if the other fields are found equal,
+ * but do it anyway to be sure. Likewise for checking the backend ID in
+ * RelFileNodeBackendEquals.
+ */
+#define RelFileNodeEquals(node1, node2) \
+ ((node1).relNode == (node2).relNode && \
+ (node1).dbNode == (node2).dbNode && \
+ (node1).spcNode == (node2).spcNode)
+
+#define RelFileNodeBackendEquals(node1, node2) \
+ ((node1).node.relNode == (node2).node.relNode && \
+ (node1).node.dbNode == (node2).node.dbNode && \
+ (node1).backend == (node2).backend && \
+ (node1).node.spcNode == (node2).node.spcNode)
+
+#endif /* RELFILENODE_H */
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
new file mode 100644
index 0000000..31a5ca6
--- /dev/null
+++ b/src/include/storage/s_lock.h
@@ -0,0 +1,1047 @@
+/*-------------------------------------------------------------------------
+ *
+ * s_lock.h
+ * Hardware-dependent implementation of spinlocks.
+ *
+ * NOTE: none of the macros in this file are intended to be called directly.
+ * Call them through the hardware-independent macros in spin.h.
+ *
+ * The following hardware-dependent macros must be provided for each
+ * supported platform:
+ *
+ * void S_INIT_LOCK(slock_t *lock)
+ * Initialize a spinlock (to the unlocked state).
+ *
+ * int S_LOCK(slock_t *lock)
+ * Acquire a spinlock, waiting if necessary.
+ * Time out and abort() if unable to acquire the lock in a
+ * "reasonable" amount of time --- typically ~ 1 minute.
+ * Should return number of "delays"; see s_lock.c
+ *
+ * void S_UNLOCK(slock_t *lock)
+ * Unlock a previously acquired lock.
+ *
+ * bool S_LOCK_FREE(slock_t *lock)
+ * Tests if the lock is free. Returns true if free, false if locked.
+ * This does *not* change the state of the lock.
+ *
+ * void SPIN_DELAY(void)
+ * Delay operation to occur inside spinlock wait loop.
+ *
+ * Note to implementors: there are default implementations for all these
+ * macros at the bottom of the file. Check if your platform can use
+ * these or needs to override them.
+ *
+ * Usually, S_LOCK() is implemented in terms of even lower-level macros
+ * TAS() and TAS_SPIN():
+ *
+ * int TAS(slock_t *lock)
+ * Atomic test-and-set instruction. Attempt to acquire the lock,
+ * but do *not* wait. Returns 0 if successful, nonzero if unable
+ * to acquire the lock.
+ *
+ * int TAS_SPIN(slock_t *lock)
+ * Like TAS(), but this version is used when waiting for a lock
+ * previously found to be contended. By default, this is the
+ * same as TAS(), but on some architectures it's better to poll a
+ * contended lock using an unlocked instruction and retry the
+ * atomic test-and-set only when it appears free.
+ *
+ * TAS() and TAS_SPIN() are NOT part of the API, and should never be called
+ * directly.
+ *
+ * CAUTION: on some platforms TAS() and/or TAS_SPIN() may sometimes report
+ * failure to acquire a lock even when the lock is not locked. For example,
+ * on Alpha TAS() will "fail" if interrupted. Therefore a retry loop must
+ * always be used, even if you are certain the lock is free.
+ *
+ * It is the responsibility of these macros to make sure that the compiler
+ * does not re-order accesses to shared memory to precede the actual lock
+ * acquisition, or follow the lock release. Prior to PostgreSQL 9.5, this
+ * was the caller's responsibility, which meant that callers had to use
+ * volatile-qualified pointers to refer to both the spinlock itself and the
+ * shared data being accessed within the spinlocked critical section. This
+ * was notationally awkward, easy to forget (and thus error-prone), and
+ * prevented some useful compiler optimizations. For these reasons, we
+ * now require that the macros themselves prevent compiler re-ordering,
+ * so that the caller doesn't need to take special precautions.
+ *
+ * On platforms with weak memory ordering, the TAS(), TAS_SPIN(), and
+ * S_UNLOCK() macros must further include hardware-level memory fence
+ * instructions to prevent similar re-ordering at the hardware level.
+ * TAS() and TAS_SPIN() must guarantee that loads and stores issued after
+ * the macro are not executed until the lock has been obtained. Conversely,
+ * S_UNLOCK() must guarantee that loads and stores issued before the macro
+ * have been executed before the lock is released.
+ *
+ * On most supported platforms, TAS() uses a tas() function written
+ * in assembly language to execute a hardware atomic-test-and-set
+ * instruction. Equivalent OS-supplied mutex routines could be used too.
+ *
+ * If no system-specific TAS() is available (ie, HAVE_SPINLOCKS is not
+ * defined), then we fall back on an emulation that uses SysV semaphores
+ * (see spin.c). This emulation will be MUCH MUCH slower than a proper TAS()
+ * implementation, because of the cost of a kernel call per lock or unlock.
+ * An old report is that Postgres spends around 40% of its time in semop(2)
+ * when using the SysV semaphore code.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/s_lock.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef S_LOCK_H
+#define S_LOCK_H
+
+#ifdef FRONTEND
+#error "s_lock.h may not be included from frontend code"
+#endif
+
+#ifdef HAVE_SPINLOCKS /* skip spinlocks if requested */
+
+#if defined(__GNUC__) || defined(__INTEL_COMPILER)
+/*************************************************************************
+ * All the gcc inlines
+ * Gcc consistently defines the CPU as __cpu__.
+ * Other compilers use __cpu or __cpu__ so we test for both in those cases.
+ */
+
+/*----------
+ * Standard gcc asm format (assuming "volatile slock_t *lock"):
+
+ __asm__ __volatile__(
+ " instruction \n"
+ " instruction \n"
+ " instruction \n"
+: "=r"(_res), "+m"(*lock) // return register, in/out lock value
+: "r"(lock) // lock pointer, in input register
+: "memory", "cc"); // show clobbered registers here
+
+ * The output-operands list (after first colon) should always include
+ * "+m"(*lock), whether or not the asm code actually refers to this
+ * operand directly. This ensures that gcc believes the value in the
+ * lock variable is used and set by the asm code. Also, the clobbers
+ * list (after third colon) should always include "memory"; this prevents
+ * gcc from thinking it can cache the values of shared-memory fields
+ * across the asm code. Add "cc" if your asm code changes the condition
+ * code register, and also list any temp registers the code uses.
+ *----------
+ */
+
+
+#ifdef __i386__ /* 32-bit i386 */
+#define HAS_TEST_AND_SET
+
+typedef unsigned char slock_t;
+
+#define TAS(lock) tas(lock)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+ register slock_t _res = 1;
+
+ /*
+ * Use a non-locking test before asserting the bus lock. Note that the
+ * extra test appears to be a small loss on some x86 platforms and a small
+ * win on others; it's by no means clear that we should keep it.
+ *
+ * When this was last tested, we didn't have separate TAS() and TAS_SPIN()
+ * macros. Nowadays it probably would be better to do a non-locking test
+ * in TAS_SPIN() but not in TAS(), like on x86_64, but no-one's done the
+ * testing to verify that. Without some empirical evidence, better to
+ * leave it alone.
+ */
+ __asm__ __volatile__(
+ " cmpb $0,%1 \n"
+ " jne 1f \n"
+ " lock \n"
+ " xchgb %0,%1 \n"
+ "1: \n"
+: "+q"(_res), "+m"(*lock)
+: /* no inputs */
+: "memory", "cc");
+ return (int) _res;
+}
+
+#define SPIN_DELAY() spin_delay()
+
+static __inline__ void
+spin_delay(void)
+{
+ /*
+ * This sequence is equivalent to the PAUSE instruction ("rep" is
+ * ignored by old IA32 processors if the following instruction is
+ * not a string operation); the IA-32 Architecture Software
+ * Developer's Manual, Vol. 3, Section 7.7.2 describes why using
+ * PAUSE in the inner loop of a spin lock is necessary for good
+ * performance:
+ *
+ * The PAUSE instruction improves the performance of IA-32
+ * processors supporting Hyper-Threading Technology when
+ * executing spin-wait loops and other routines where one
+ * thread is accessing a shared lock or semaphore in a tight
+ * polling loop. When executing a spin-wait loop, the
+ * processor can suffer a severe performance penalty when
+ * exiting the loop because it detects a possible memory order
+ * violation and flushes the core processor's pipeline. The
+ * PAUSE instruction provides a hint to the processor that the
+ * code sequence is a spin-wait loop. The processor uses this
+ * hint to avoid the memory order violation and prevent the
+ * pipeline flush. In addition, the PAUSE instruction
+ * de-pipelines the spin-wait loop to prevent it from
+ * consuming execution resources excessively.
+ */
+ __asm__ __volatile__(
+ " rep; nop \n");
+}
+
+#endif /* __i386__ */
+
+
+#ifdef __x86_64__ /* AMD Opteron, Intel EM64T */
+#define HAS_TEST_AND_SET
+
+typedef unsigned char slock_t;
+
+#define TAS(lock) tas(lock)
+
+/*
+ * On Intel EM64T, it's a win to use a non-locking test before the xchg proper,
+ * but only when spinning.
+ *
+ * See also Implementing Scalable Atomic Locks for Multi-Core Intel(tm) EM64T
+ * and IA32, by Michael Chynoweth and Mary R. Lee. As of this writing, it is
+ * available at:
+ * http://software.intel.com/en-us/articles/implementing-scalable-atomic-locks-for-multi-core-intel-em64t-and-ia32-architectures
+ */
+#define TAS_SPIN(lock) (*(lock) ? 1 : TAS(lock))
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+ register slock_t _res = 1;
+
+ __asm__ __volatile__(
+ " lock \n"
+ " xchgb %0,%1 \n"
+: "+q"(_res), "+m"(*lock)
+: /* no inputs */
+: "memory", "cc");
+ return (int) _res;
+}
+
+#define SPIN_DELAY() spin_delay()
+
+static __inline__ void
+spin_delay(void)
+{
+ /*
+ * Adding a PAUSE in the spin delay loop is demonstrably a no-op on
+ * Opteron, but it may be of some use on EM64T, so we keep it.
+ */
+ __asm__ __volatile__(
+ " rep; nop \n");
+}
+
+#endif /* __x86_64__ */
+
+
+#if defined(__ia64__) || defined(__ia64)
+/*
+ * Intel Itanium, gcc or Intel's compiler.
+ *
+ * Itanium has weak memory ordering, but we rely on the compiler to enforce
+ * strict ordering of accesses to volatile data. In particular, while the
+ * xchg instruction implicitly acts as a memory barrier with 'acquire'
+ * semantics, we do not have an explicit memory fence instruction in the
+ * S_UNLOCK macro. We use a regular assignment to clear the spinlock, and
+ * trust that the compiler marks the generated store instruction with the
+ * ".rel" opcode.
+ *
+ * Testing shows that assumption to hold on gcc, although I could not find
+ * any explicit statement on that in the gcc manual. In Intel's compiler,
+ * the -m[no-]serialize-volatile option controls that, and testing shows that
+ * it is enabled by default.
+ *
+ * While icc accepts gcc asm blocks on x86[_64], this is not true on ia64
+ * (at least not in icc versions before 12.x). So we have to carry a separate
+ * compiler-intrinsic-based implementation for it.
+ */
+#define HAS_TEST_AND_SET
+
+typedef unsigned int slock_t;
+
+#define TAS(lock) tas(lock)
+
+/* On IA64, it's a win to use a non-locking test before the xchg proper */
+#define TAS_SPIN(lock) (*(lock) ? 1 : TAS(lock))
+
+#ifndef __INTEL_COMPILER
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+ long int ret;
+
+ __asm__ __volatile__(
+ " xchg4 %0=%1,%2 \n"
+: "=r"(ret), "+m"(*lock)
+: "r"(1)
+: "memory");
+ return (int) ret;
+}
+
+#else /* __INTEL_COMPILER */
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+ int ret;
+
+ ret = _InterlockedExchange(lock,1); /* this is a xchg asm macro */
+
+ return ret;
+}
+
+/* icc can't use the regular gcc S_UNLOCK() macro either in this case */
+#define S_UNLOCK(lock) \
+ do { __memory_barrier(); *(lock) = 0; } while (0)
+
+#endif /* __INTEL_COMPILER */
+#endif /* __ia64__ || __ia64 */
+
+/*
+ * On ARM and ARM64, we use __sync_lock_test_and_set(int *, int) if available.
+ *
+ * We use the int-width variant of the builtin because it works on more chips
+ * than other widths.
+ */
+#if defined(__arm__) || defined(__arm) || defined(__aarch64__) || defined(__aarch64)
+#ifdef HAVE_GCC__SYNC_INT32_TAS
+#define HAS_TEST_AND_SET
+
+#define TAS(lock) tas(lock)
+
+typedef int slock_t;
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+ return __sync_lock_test_and_set(lock, 1);
+}
+
+#define S_UNLOCK(lock) __sync_lock_release(lock)
+
+#endif /* HAVE_GCC__SYNC_INT32_TAS */
+#endif /* __arm__ || __arm || __aarch64__ || __aarch64 */
+
+
+/* S/390 and S/390x Linux (32- and 64-bit zSeries) */
+#if defined(__s390__) || defined(__s390x__)
+#define HAS_TEST_AND_SET
+
+typedef unsigned int slock_t;
+
+#define TAS(lock) tas(lock)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+ int _res = 0;
+
+ __asm__ __volatile__(
+ " cs %0,%3,0(%2) \n"
+: "+d"(_res), "+m"(*lock)
+: "a"(lock), "d"(1)
+: "memory", "cc");
+ return _res;
+}
+
+#endif /* __s390__ || __s390x__ */
+
+
+#if defined(__sparc__) /* Sparc */
+/*
+ * Solaris has always run sparc processors in TSO (total store) mode, but
+ * linux didn't use to and the *BSDs still don't. So, be careful about
+ * acquire/release semantics. The CPU will treat superfluous membars as
+ * NOPs, so it's just code space.
+ */
+#define HAS_TEST_AND_SET
+
+typedef unsigned char slock_t;
+
+#define TAS(lock) tas(lock)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+ register slock_t _res;
+
+ /*
+ * See comment in src/backend/port/tas/sunstudio_sparc.s for why this
+ * uses "ldstub", and that file uses "cas". gcc currently generates
+ * sparcv7-targeted binaries, so "cas" use isn't possible.
+ */
+ __asm__ __volatile__(
+ " ldstub [%2], %0 \n"
+: "=r"(_res), "+m"(*lock)
+: "r"(lock)
+: "memory");
+#if defined(__sparcv7) || defined(__sparc_v7__)
+ /*
+ * No stbar or membar available, luckily no actually produced hardware
+ * requires a barrier.
+ */
+#elif defined(__sparcv8) || defined(__sparc_v8__)
+ /* stbar is available (and required for both PSO, RMO), membar isn't */
+ __asm__ __volatile__ ("stbar \n":::"memory");
+#else
+ /*
+ * #LoadStore (RMO) | #LoadLoad (RMO) together are the appropriate acquire
+ * barrier for sparcv8+ upwards.
+ */
+ __asm__ __volatile__ ("membar #LoadStore | #LoadLoad \n":::"memory");
+#endif
+ return (int) _res;
+}
+
+#if defined(__sparcv7) || defined(__sparc_v7__)
+/*
+ * No stbar or membar available, luckily no actually produced hardware
+ * requires a barrier. We fall through to the default gcc definition of
+ * S_UNLOCK in this case.
+ */
+#elif defined(__sparcv8) || defined(__sparc_v8__)
+/* stbar is available (and required for both PSO, RMO), membar isn't */
+#define S_UNLOCK(lock) \
+do \
+{ \
+ __asm__ __volatile__ ("stbar \n":::"memory"); \
+ *((volatile slock_t *) (lock)) = 0; \
+} while (0)
+#else
+/*
+ * #LoadStore (RMO) | #StoreStore (RMO, PSO) together are the appropriate
+ * release barrier for sparcv8+ upwards.
+ */
+#define S_UNLOCK(lock) \
+do \
+{ \
+ __asm__ __volatile__ ("membar #LoadStore | #StoreStore \n":::"memory"); \
+ *((volatile slock_t *) (lock)) = 0; \
+} while (0)
+#endif
+
+#endif /* __sparc__ */
+
+
+/* PowerPC */
+#if defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
+#define HAS_TEST_AND_SET
+
+typedef unsigned int slock_t;
+
+#define TAS(lock) tas(lock)
+
+/* On PPC, it's a win to use a non-locking test before the lwarx */
+#define TAS_SPIN(lock) (*(lock) ? 1 : TAS(lock))
+
+/*
+ * The second operand of addi can hold a constant zero or a register number,
+ * hence constraint "=&b" to avoid allocating r0. "b" stands for "address
+ * base register"; most operands having this register-or-zero property are
+ * address bases, e.g. the second operand of lwax.
+ *
+ * NOTE: per the Enhanced PowerPC Architecture manual, v1.0 dated 7-May-2002,
+ * an isync is a sufficient synchronization barrier after a lwarx/stwcx loop.
+ * On newer machines, we can use lwsync instead for better performance.
+ *
+ * Ordinarily, we'd code the branches here using GNU-style local symbols, that
+ * is "1f" referencing "1:" and so on. But some people run gcc on AIX with
+ * IBM's assembler as backend, and IBM's assembler doesn't do local symbols.
+ * So hand-code the branch offsets; fortunately, all PPC instructions are
+ * exactly 4 bytes each, so it's not too hard to count.
+ */
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+ slock_t _t;
+ int _res;
+
+ __asm__ __volatile__(
+#ifdef USE_PPC_LWARX_MUTEX_HINT
+" lwarx %0,0,%3,1 \n"
+#else
+" lwarx %0,0,%3 \n"
+#endif
+" cmpwi %0,0 \n"
+" bne $+16 \n" /* branch to li %1,1 */
+" addi %0,%0,1 \n"
+" stwcx. %0,0,%3 \n"
+" beq $+12 \n" /* branch to lwsync/isync */
+" li %1,1 \n"
+" b $+12 \n" /* branch to end of asm sequence */
+#ifdef USE_PPC_LWSYNC
+" lwsync \n"
+#else
+" isync \n"
+#endif
+" li %1,0 \n"
+
+: "=&b"(_t), "=r"(_res), "+m"(*lock)
+: "r"(lock)
+: "memory", "cc");
+ return _res;
+}
+
+/*
+ * PowerPC S_UNLOCK is almost standard but requires a "sync" instruction.
+ * On newer machines, we can use lwsync instead for better performance.
+ */
+#ifdef USE_PPC_LWSYNC
+#define S_UNLOCK(lock) \
+do \
+{ \
+ __asm__ __volatile__ (" lwsync \n" ::: "memory"); \
+ *((volatile slock_t *) (lock)) = 0; \
+} while (0)
+#else
+#define S_UNLOCK(lock) \
+do \
+{ \
+ __asm__ __volatile__ (" sync \n" ::: "memory"); \
+ *((volatile slock_t *) (lock)) = 0; \
+} while (0)
+#endif /* USE_PPC_LWSYNC */
+
+#endif /* powerpc */
+
+
+/* Linux Motorola 68k */
+#if (defined(__mc68000__) || defined(__m68k__)) && defined(__linux__)
+#define HAS_TEST_AND_SET
+
+typedef unsigned char slock_t;
+
+#define TAS(lock) tas(lock)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+ register int rv;
+
+ __asm__ __volatile__(
+ " clrl %0 \n"
+ " tas %1 \n"
+ " sne %0 \n"
+: "=d"(rv), "+m"(*lock)
+: /* no inputs */
+: "memory", "cc");
+ return rv;
+}
+
+#endif /* (__mc68000__ || __m68k__) && __linux__ */
+
+
+/* Motorola 88k */
+#if defined(__m88k__)
+#define HAS_TEST_AND_SET
+
+typedef unsigned int slock_t;
+
+#define TAS(lock) tas(lock)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+ register slock_t _res = 1;
+
+ __asm__ __volatile__(
+ " xmem %0, %2, %%r0 \n"
+: "+r"(_res), "+m"(*lock)
+: "r"(lock)
+: "memory");
+ return (int) _res;
+}
+
+#endif /* __m88k__ */
+
+
+/*
+ * VAXen -- even multiprocessor ones
+ * (thanks to Tom Ivar Helbekkmo)
+ */
+#if defined(__vax__)
+#define HAS_TEST_AND_SET
+
+typedef unsigned char slock_t;
+
+#define TAS(lock) tas(lock)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+ register int _res;
+
+ __asm__ __volatile__(
+ " movl $1, %0 \n"
+ " bbssi $0, (%2), 1f \n"
+ " clrl %0 \n"
+ "1: \n"
+: "=&r"(_res), "+m"(*lock)
+: "r"(lock)
+: "memory");
+ return _res;
+}
+
+#endif /* __vax__ */
+
+
+#if defined(__mips__) && !defined(__sgi) /* non-SGI MIPS */
+#define HAS_TEST_AND_SET
+
+typedef unsigned int slock_t;
+
+#define TAS(lock) tas(lock)
+
+/*
+ * Original MIPS-I processors lacked the LL/SC instructions, but if we are
+ * so unfortunate as to be running on one of those, we expect that the kernel
+ * will handle the illegal-instruction traps and emulate them for us. On
+ * anything newer (and really, MIPS-I is extinct) LL/SC is the only sane
+ * choice because any other synchronization method must involve a kernel
+ * call. Unfortunately, many toolchains still default to MIPS-I as the
+ * codegen target; if the symbol __mips shows that that's the case, we
+ * have to force the assembler to accept LL/SC.
+ *
+ * R10000 and up processors require a separate SYNC, which has the same
+ * issues as LL/SC.
+ */
+#if __mips < 2
+#define MIPS_SET_MIPS2 " .set mips2 \n"
+#else
+#define MIPS_SET_MIPS2
+#endif
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+ register volatile slock_t *_l = lock;
+ register int _res;
+ register int _tmp;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ MIPS_SET_MIPS2
+ " .set noreorder \n"
+ " .set nomacro \n"
+ " ll %0, %2 \n"
+ " or %1, %0, 1 \n"
+ " sc %1, %2 \n"
+ " xori %1, 1 \n"
+ " or %0, %0, %1 \n"
+ " sync \n"
+ " .set pop "
+: "=&r" (_res), "=&r" (_tmp), "+R" (*_l)
+: /* no inputs */
+: "memory");
+ return _res;
+}
+
+/* MIPS S_UNLOCK is almost standard but requires a "sync" instruction */
+#define S_UNLOCK(lock) \
+do \
+{ \
+ __asm__ __volatile__( \
+ " .set push \n" \
+ MIPS_SET_MIPS2 \
+ " .set noreorder \n" \
+ " .set nomacro \n" \
+ " sync \n" \
+ " .set pop " \
+: /* no outputs */ \
+: /* no inputs */ \
+: "memory"); \
+ *((volatile slock_t *) (lock)) = 0; \
+} while (0)
+
+#endif /* __mips__ && !__sgi */
+
+
+#if defined(__m32r__) && defined(HAVE_SYS_TAS_H) /* Renesas' M32R */
+#define HAS_TEST_AND_SET
+
+#include <sys/tas.h>
+
+typedef int slock_t;
+
+#define TAS(lock) tas(lock)
+
+#endif /* __m32r__ */
+
+
+#if defined(__sh__) /* Renesas' SuperH */
+#define HAS_TEST_AND_SET
+
+typedef unsigned char slock_t;
+
+#define TAS(lock) tas(lock)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+ register int _res;
+
+ /*
+ * This asm is coded as if %0 could be any register, but actually SuperH
+ * restricts the target of xor-immediate to be R0. That's handled by
+ * the "z" constraint on _res.
+ */
+ __asm__ __volatile__(
+ " tas.b @%2 \n"
+ " movt %0 \n"
+ " xor #1,%0 \n"
+: "=z"(_res), "+m"(*lock)
+: "r"(lock)
+: "memory", "t");
+ return _res;
+}
+
+#endif /* __sh__ */
+
+
+/* These live in s_lock.c, but only for gcc */
+
+
+#if defined(__m68k__) && !defined(__linux__) /* non-Linux Motorola 68k */
+#define HAS_TEST_AND_SET
+
+typedef unsigned char slock_t;
+#endif
+
+/*
+ * Default implementation of S_UNLOCK() for gcc/icc.
+ *
+ * Note that this implementation is unsafe for any platform that can reorder
+ * a memory access (either load or store) after a following store. That
+ * happens not to be possible on x86 and most legacy architectures (some are
+ * single-processor!), but many modern systems have weaker memory ordering.
+ * Those that do must define their own version of S_UNLOCK() rather than
+ * relying on this one.
+ */
+#if !defined(S_UNLOCK)
+#define S_UNLOCK(lock) \
+ do { __asm__ __volatile__("" : : : "memory"); *(lock) = 0; } while (0)
+#endif
+
+#endif /* defined(__GNUC__) || defined(__INTEL_COMPILER) */
+
+
+
+/*
+ * ---------------------------------------------------------------------
+ * Platforms that use non-gcc inline assembly:
+ * ---------------------------------------------------------------------
+ */
+
+#if !defined(HAS_TEST_AND_SET) /* We didn't trigger above, let's try here */
+
+
+#if defined(__hppa) || defined(__hppa__) /* HP PA-RISC, GCC and HP compilers */
+/*
+ * HP's PA-RISC
+ *
+ * See src/backend/port/hpux/tas.c.template for details about LDCWX. Because
+ * LDCWX requires a 16-byte-aligned address, we declare slock_t as a 16-byte
+ * struct. The active word in the struct is whichever has the aligned address;
+ * the other three words just sit at -1.
+ *
+ * When using gcc, we can inline the required assembly code.
+ */
+#define HAS_TEST_AND_SET
+
+typedef struct
+{
+ int sema[4];
+} slock_t;
+
+#define TAS_ACTIVE_WORD(lock) ((volatile int *) (((uintptr_t) (lock) + 15) & ~15))
+
+#if defined(__GNUC__)
+
+static __inline__ int
+tas(volatile slock_t *lock)
+{
+ volatile int *lockword = TAS_ACTIVE_WORD(lock);
+ register int lockval;
+
+ __asm__ __volatile__(
+ " ldcwx 0(0,%2),%0 \n"
+: "=r"(lockval), "+m"(*lockword)
+: "r"(lockword)
+: "memory");
+ return (lockval == 0);
+}
+
+/*
+ * The hppa implementation doesn't follow the rules of this files and provides
+ * a gcc specific implementation outside of the above defined(__GNUC__). It
+ * does so to avoid duplication between the HP compiler and gcc. So undefine
+ * the generic fallback S_UNLOCK from above.
+ */
+#ifdef S_UNLOCK
+#undef S_UNLOCK
+#endif
+#define S_UNLOCK(lock) \
+ do { \
+ __asm__ __volatile__("" : : : "memory"); \
+ *TAS_ACTIVE_WORD(lock) = -1; \
+ } while (0)
+
+#endif /* __GNUC__ */
+
+#define S_INIT_LOCK(lock) \
+ do { \
+ volatile slock_t *lock_ = (lock); \
+ lock_->sema[0] = -1; \
+ lock_->sema[1] = -1; \
+ lock_->sema[2] = -1; \
+ lock_->sema[3] = -1; \
+ } while (0)
+
+#define S_LOCK_FREE(lock) (*TAS_ACTIVE_WORD(lock) != 0)
+
+#endif /* __hppa || __hppa__ */
+
+
+#if defined(__hpux) && defined(__ia64) && !defined(__GNUC__)
+/*
+ * HP-UX on Itanium, non-gcc/icc compiler
+ *
+ * We assume that the compiler enforces strict ordering of loads/stores on
+ * volatile data (see comments on the gcc-version earlier in this file).
+ * Note that this assumption does *not* hold if you use the
+ * +Ovolatile=__unordered option on the HP-UX compiler, so don't do that.
+ *
+ * See also Implementing Spinlocks on the Intel Itanium Architecture and
+ * PA-RISC, by Tor Ekqvist and David Graves, for more information. As of
+ * this writing, version 1.0 of the manual is available at:
+ * http://h21007.www2.hp.com/portal/download/files/unprot/itanium/spinlocks.pdf
+ */
+#define HAS_TEST_AND_SET
+
+typedef unsigned int slock_t;
+
+#include <ia64/sys/inline.h>
+#define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE)
+/* On IA64, it's a win to use a non-locking test before the xchg proper */
+#define TAS_SPIN(lock) (*(lock) ? 1 : TAS(lock))
+#define S_UNLOCK(lock) \
+ do { _Asm_mf(); (*(lock)) = 0; } while (0)
+
+#endif /* HPUX on IA64, non gcc/icc */
+
+#if defined(_AIX) /* AIX */
+/*
+ * AIX (POWER)
+ */
+#define HAS_TEST_AND_SET
+
+#include <sys/atomic_op.h>
+
+typedef int slock_t;
+
+#define TAS(lock) _check_lock((slock_t *) (lock), 0, 1)
+#define S_UNLOCK(lock) _clear_lock((slock_t *) (lock), 0)
+#endif /* _AIX */
+
+
+/* These are in sunstudio_(sparc|x86).s */
+
+#if defined(__SUNPRO_C) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
+#define HAS_TEST_AND_SET
+
+#if defined(__i386) || defined(__x86_64__) || defined(__sparcv9) || defined(__sparcv8plus)
+typedef unsigned int slock_t;
+#else
+typedef unsigned char slock_t;
+#endif
+
+extern slock_t pg_atomic_cas(volatile slock_t *lock, slock_t with,
+ slock_t cmp);
+
+#define TAS(a) (pg_atomic_cas((a), 1, 0) != 0)
+#endif
+
+
+#ifdef _MSC_VER
+typedef LONG slock_t;
+
+#define HAS_TEST_AND_SET
+#define TAS(lock) (InterlockedCompareExchange(lock, 1, 0))
+
+#define SPIN_DELAY() spin_delay()
+
+/* If using Visual C++ on Win64, inline assembly is unavailable.
+ * Use a _mm_pause intrinsic instead of rep nop.
+ */
+#if defined(_WIN64)
+static __forceinline void
+spin_delay(void)
+{
+ _mm_pause();
+}
+#else
+static __forceinline void
+spin_delay(void)
+{
+ /* See comment for gcc code. Same code, MASM syntax */
+ __asm rep nop;
+}
+#endif
+
+#include <intrin.h>
+#pragma intrinsic(_ReadWriteBarrier)
+
+#define S_UNLOCK(lock) \
+ do { _ReadWriteBarrier(); (*(lock)) = 0; } while (0)
+
+#endif
+
+
+#endif /* !defined(HAS_TEST_AND_SET) */
+
+
+/* Blow up if we didn't have any way to do spinlocks */
+#ifndef HAS_TEST_AND_SET
+#error PostgreSQL does not have native spinlock support on this platform. To continue the compilation, rerun configure using --disable-spinlocks. However, performance will be poor. Please report this to pgsql-bugs@lists.postgresql.org.
+#endif
+
+
+#else /* !HAVE_SPINLOCKS */
+
+
+/*
+ * Fake spinlock implementation using semaphores --- slow and prone
+ * to fall foul of kernel limits on number of semaphores, so don't use this
+ * unless you must! The subroutines appear in spin.c.
+ */
+typedef int slock_t;
+
+extern bool s_lock_free_sema(volatile slock_t *lock);
+extern void s_unlock_sema(volatile slock_t *lock);
+extern void s_init_lock_sema(volatile slock_t *lock, bool nested);
+extern int tas_sema(volatile slock_t *lock);
+
+#define S_LOCK_FREE(lock) s_lock_free_sema(lock)
+#define S_UNLOCK(lock) s_unlock_sema(lock)
+#define S_INIT_LOCK(lock) s_init_lock_sema(lock, false)
+#define TAS(lock) tas_sema(lock)
+
+
+#endif /* HAVE_SPINLOCKS */
+
+
+/*
+ * Default Definitions - override these above as needed.
+ */
+
+#if !defined(S_LOCK)
+#define S_LOCK(lock) \
+ (TAS(lock) ? s_lock((lock), __FILE__, __LINE__, PG_FUNCNAME_MACRO) : 0)
+#endif /* S_LOCK */
+
+#if !defined(S_LOCK_FREE)
+#define S_LOCK_FREE(lock) (*(lock) == 0)
+#endif /* S_LOCK_FREE */
+
+#if !defined(S_UNLOCK)
+/*
+ * Our default implementation of S_UNLOCK is essentially *(lock) = 0. This
+ * is unsafe if the platform can reorder a memory access (either load or
+ * store) after a following store; platforms where this is possible must
+ * define their own S_UNLOCK. But CPU reordering is not the only concern:
+ * if we simply defined S_UNLOCK() as an inline macro, the compiler might
+ * reorder instructions from inside the critical section to occur after the
+ * lock release. Since the compiler probably can't know what the external
+ * function s_unlock is doing, putting the same logic there should be adequate.
+ * A sufficiently-smart globally optimizing compiler could break that
+ * assumption, though, and the cost of a function call for every spinlock
+ * release may hurt performance significantly, so we use this implementation
+ * only for platforms where we don't know of a suitable intrinsic. For the
+ * most part, those are relatively obscure platform/compiler combinations to
+ * which the PostgreSQL project does not have access.
+ */
+#define USE_DEFAULT_S_UNLOCK
+extern void s_unlock(volatile slock_t *lock);
+#define S_UNLOCK(lock) s_unlock(lock)
+#endif /* S_UNLOCK */
+
+#if !defined(S_INIT_LOCK)
+#define S_INIT_LOCK(lock) S_UNLOCK(lock)
+#endif /* S_INIT_LOCK */
+
+#if !defined(SPIN_DELAY)
+#define SPIN_DELAY() ((void) 0)
+#endif /* SPIN_DELAY */
+
+#if !defined(TAS)
+extern int tas(volatile slock_t *lock); /* in port/.../tas.s, or
+ * s_lock.c */
+
+#define TAS(lock) tas(lock)
+#endif /* TAS */
+
+#if !defined(TAS_SPIN)
+#define TAS_SPIN(lock) TAS(lock)
+#endif /* TAS_SPIN */
+
+extern slock_t dummy_spinlock;
+
+/*
+ * Platform-independent out-of-line support routines
+ */
+extern int s_lock(volatile slock_t *lock, const char *file, int line, const char *func);
+
+/* Support for dynamic adjustment of spins_per_delay */
+#define DEFAULT_SPINS_PER_DELAY 100
+
+extern void set_spins_per_delay(int shared_spins_per_delay);
+extern int update_spins_per_delay(int shared_spins_per_delay);
+
+/*
+ * Support for spin delay which is useful in various places where
+ * spinlock-like procedures take place.
+ */
+typedef struct
+{
+ int spins;
+ int delays;
+ int cur_delay;
+ const char *file;
+ int line;
+ const char *func;
+} SpinDelayStatus;
+
+static inline void
+init_spin_delay(SpinDelayStatus *status,
+ const char *file, int line, const char *func)
+{
+ status->spins = 0;
+ status->delays = 0;
+ status->cur_delay = 0;
+ status->file = file;
+ status->line = line;
+ status->func = func;
+}
+
+#define init_local_spin_delay(status) init_spin_delay(status, __FILE__, __LINE__, PG_FUNCNAME_MACRO)
+void perform_spin_delay(SpinDelayStatus *status);
+void finish_spin_delay(SpinDelayStatus *status);
+
+#endif /* S_LOCK_H */
diff --git a/src/include/storage/sharedfileset.h b/src/include/storage/sharedfileset.h
new file mode 100644
index 0000000..2d6cf07
--- /dev/null
+++ b/src/include/storage/sharedfileset.h
@@ -0,0 +1,45 @@
+/*-------------------------------------------------------------------------
+ *
+ * sharedfileset.h
+ * Shared temporary file management.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/sharedfileset.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef SHAREDFILESET_H
+#define SHAREDFILESET_H
+
+#include "storage/dsm.h"
+#include "storage/fd.h"
+#include "storage/spin.h"
+
+/*
+ * A set of temporary files that can be shared by multiple backends.
+ */
+typedef struct SharedFileSet
+{
+ pid_t creator_pid; /* PID of the creating process */
+ uint32 number; /* per-PID identifier */
+ slock_t mutex; /* mutex protecting the reference count */
+ int refcnt; /* number of attached backends */
+ int ntablespaces; /* number of tablespaces to use */
+ Oid tablespaces[8]; /* OIDs of tablespaces to use. Assumes that
+ * it's rare that there more than temp
+ * tablespaces. */
+} SharedFileSet;
+
+extern void SharedFileSetInit(SharedFileSet *fileset, dsm_segment *seg);
+extern void SharedFileSetAttach(SharedFileSet *fileset, dsm_segment *seg);
+extern File SharedFileSetCreate(SharedFileSet *fileset, const char *name);
+extern File SharedFileSetOpen(SharedFileSet *fileset, const char *name);
+extern bool SharedFileSetDelete(SharedFileSet *fileset, const char *name,
+ bool error_on_failure);
+extern void SharedFileSetDeleteAll(SharedFileSet *fileset);
+
+#endif
diff --git a/src/include/storage/shm_mq.h b/src/include/storage/shm_mq.h
new file mode 100644
index 0000000..5005f2c
--- /dev/null
+++ b/src/include/storage/shm_mq.h
@@ -0,0 +1,85 @@
+/*-------------------------------------------------------------------------
+ *
+ * shm_mq.h
+ * single-reader, single-writer shared memory message queue
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/shm_mq.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SHM_MQ_H
+#define SHM_MQ_H
+
+#include "postmaster/bgworker.h"
+#include "storage/dsm.h"
+#include "storage/proc.h"
+
+/* The queue itself, in shared memory. */
+struct shm_mq;
+typedef struct shm_mq shm_mq;
+
+/* Backend-private state. */
+struct shm_mq_handle;
+typedef struct shm_mq_handle shm_mq_handle;
+
+/* Descriptors for a single write spanning multiple locations. */
+typedef struct
+{
+ const char *data;
+ Size len;
+} shm_mq_iovec;
+
+/* Possible results of a send or receive operation. */
+typedef enum
+{
+ SHM_MQ_SUCCESS, /* Sent or received a message. */
+ SHM_MQ_WOULD_BLOCK, /* Not completed; retry later. */
+ SHM_MQ_DETACHED /* Other process has detached queue. */
+} shm_mq_result;
+
+/*
+ * Primitives to create a queue and set the sender and receiver.
+ *
+ * Both the sender and the receiver must be set before any messages are read
+ * or written, but they need not be set by the same process. Each must be
+ * set exactly once.
+ */
+extern shm_mq *shm_mq_create(void *address, Size size);
+extern void shm_mq_set_receiver(shm_mq *mq, PGPROC *);
+extern void shm_mq_set_sender(shm_mq *mq, PGPROC *);
+
+/* Accessor methods for sender and receiver. */
+extern PGPROC *shm_mq_get_receiver(shm_mq *);
+extern PGPROC *shm_mq_get_sender(shm_mq *);
+
+/* Set up backend-local queue state. */
+extern shm_mq_handle *shm_mq_attach(shm_mq *mq, dsm_segment *seg,
+ BackgroundWorkerHandle *handle);
+
+/* Associate worker handle with shm_mq. */
+extern void shm_mq_set_handle(shm_mq_handle *, BackgroundWorkerHandle *);
+
+/* Break connection, release handle resources. */
+extern void shm_mq_detach(shm_mq_handle *mqh);
+
+/* Get the shm_mq from handle. */
+extern shm_mq *shm_mq_get_queue(shm_mq_handle *mqh);
+
+/* Send or receive messages. */
+extern shm_mq_result shm_mq_send(shm_mq_handle *mqh,
+ Size nbytes, const void *data, bool nowait);
+extern shm_mq_result shm_mq_sendv(shm_mq_handle *mqh,
+ shm_mq_iovec *iov, int iovcnt, bool nowait);
+extern shm_mq_result shm_mq_receive(shm_mq_handle *mqh,
+ Size *nbytesp, void **datap, bool nowait);
+
+/* Wait for our counterparty to attach to the queue. */
+extern shm_mq_result shm_mq_wait_for_attach(shm_mq_handle *mqh);
+
+/* Smallest possible queue. */
+extern PGDLLIMPORT const Size shm_mq_minimum_size;
+
+#endif /* SHM_MQ_H */
diff --git a/src/include/storage/shm_toc.h b/src/include/storage/shm_toc.h
new file mode 100644
index 0000000..c3886d5
--- /dev/null
+++ b/src/include/storage/shm_toc.h
@@ -0,0 +1,58 @@
+/*-------------------------------------------------------------------------
+ *
+ * shm_toc.h
+ * shared memory segment table of contents
+ *
+ * This is intended to provide a simple way to divide a chunk of shared
+ * memory (probably dynamic shared memory allocated via dsm_create) into
+ * a number of regions and keep track of the addresses of those regions or
+ * key data structures within those regions. This is not intended to
+ * scale to a large number of keys and will perform poorly if used that
+ * way; if you need a large number of pointers, store them within some
+ * other data structure within the segment and only put the pointer to
+ * the data structure itself in the table of contents.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/shm_toc.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SHM_TOC_H
+#define SHM_TOC_H
+
+#include "storage/shmem.h" /* for add_size() */
+
+/* shm_toc is an opaque type known only within shm_toc.c */
+typedef struct shm_toc shm_toc;
+
+extern shm_toc *shm_toc_create(uint64 magic, void *address, Size nbytes);
+extern shm_toc *shm_toc_attach(uint64 magic, void *address);
+extern void *shm_toc_allocate(shm_toc *toc, Size nbytes);
+extern Size shm_toc_freespace(shm_toc *toc);
+extern void shm_toc_insert(shm_toc *toc, uint64 key, void *address);
+extern void *shm_toc_lookup(shm_toc *toc, uint64 key, bool noError);
+
+/*
+ * Tools for estimating how large a chunk of shared memory will be needed
+ * to store a TOC and its dependent objects. Note: we don't really support
+ * large numbers of keys, but it's convenient to declare number_of_keys
+ * as a Size anyway.
+ */
+typedef struct
+{
+ Size space_for_chunks;
+ Size number_of_keys;
+} shm_toc_estimator;
+
+#define shm_toc_initialize_estimator(e) \
+ ((e)->space_for_chunks = 0, (e)->number_of_keys = 0)
+#define shm_toc_estimate_chunk(e, sz) \
+ ((e)->space_for_chunks = add_size((e)->space_for_chunks, BUFFERALIGN(sz)))
+#define shm_toc_estimate_keys(e, cnt) \
+ ((e)->number_of_keys = add_size((e)->number_of_keys, cnt))
+
+extern Size shm_toc_estimate(shm_toc_estimator *e);
+
+#endif /* SHM_TOC_H */
diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h
new file mode 100644
index 0000000..e9e32ab
--- /dev/null
+++ b/src/include/storage/shmem.h
@@ -0,0 +1,81 @@
+/*-------------------------------------------------------------------------
+ *
+ * shmem.h
+ * shared memory management structures
+ *
+ * Historical note:
+ * A long time ago, Postgres' shared memory region was allowed to be mapped
+ * at a different address in each process, and shared memory "pointers" were
+ * passed around as offsets relative to the start of the shared memory region.
+ * That is no longer the case: each process must map the shared memory region
+ * at the same address. This means shared memory pointers can be passed
+ * around directly between different processes.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/shmem.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SHMEM_H
+#define SHMEM_H
+
+#include "utils/hsearch.h"
+
+
+/* shmqueue.c */
+typedef struct SHM_QUEUE
+{
+ struct SHM_QUEUE *prev;
+ struct SHM_QUEUE *next;
+} SHM_QUEUE;
+
+/* shmem.c */
+extern void InitShmemAccess(void *seghdr);
+extern void InitShmemAllocation(void);
+extern void *ShmemAlloc(Size size);
+extern void *ShmemAllocNoError(Size size);
+extern void *ShmemAllocUnlocked(Size size);
+extern bool ShmemAddrIsValid(const void *addr);
+extern void InitShmemIndex(void);
+extern HTAB *ShmemInitHash(const char *name, long init_size, long max_size,
+ HASHCTL *infoP, int hash_flags);
+extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr);
+extern Size add_size(Size s1, Size s2);
+extern Size mul_size(Size s1, Size s2);
+
+/* ipci.c */
+extern void RequestAddinShmemSpace(Size size);
+
+/* size constants for the shmem index table */
+ /* max size of data structure string name */
+#define SHMEM_INDEX_KEYSIZE (48)
+ /* estimated size of the shmem index table (not a hard limit) */
+#define SHMEM_INDEX_SIZE (64)
+
+/* this is a hash bucket in the shmem index table */
+typedef struct
+{
+ char key[SHMEM_INDEX_KEYSIZE]; /* string name */
+ void *location; /* location in shared mem */
+ Size size; /* # bytes requested for the structure */
+ Size allocated_size; /* # bytes actually allocated */
+} ShmemIndexEnt;
+
+/*
+ * prototypes for functions in shmqueue.c
+ */
+extern void SHMQueueInit(SHM_QUEUE *queue);
+extern void SHMQueueElemInit(SHM_QUEUE *queue);
+extern void SHMQueueDelete(SHM_QUEUE *queue);
+extern void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem);
+extern void SHMQueueInsertAfter(SHM_QUEUE *queue, SHM_QUEUE *elem);
+extern Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem,
+ Size linkOffset);
+extern Pointer SHMQueuePrev(const SHM_QUEUE *queue, const SHM_QUEUE *curElem,
+ Size linkOffset);
+extern bool SHMQueueEmpty(const SHM_QUEUE *queue);
+extern bool SHMQueueIsDetached(const SHM_QUEUE *queue);
+
+#endif /* SHMEM_H */
diff --git a/src/include/storage/sinval.h b/src/include/storage/sinval.h
new file mode 100644
index 0000000..903818b
--- /dev/null
+++ b/src/include/storage/sinval.h
@@ -0,0 +1,153 @@
+/*-------------------------------------------------------------------------
+ *
+ * sinval.h
+ * POSTGRES shared cache invalidation communication definitions.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/sinval.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SINVAL_H
+#define SINVAL_H
+
+#include <signal.h>
+
+#include "storage/relfilenode.h"
+
+/*
+ * We support several types of shared-invalidation messages:
+ * * invalidate a specific tuple in a specific catcache
+ * * invalidate all catcache entries from a given system catalog
+ * * invalidate a relcache entry for a specific logical relation
+ * * invalidate all relcache entries
+ * * invalidate an smgr cache entry for a specific physical relation
+ * * invalidate the mapped-relation mapping for a given database
+ * * invalidate any saved snapshot that might be used to scan a given relation
+ * More types could be added if needed. The message type is identified by
+ * the first "int8" field of the message struct. Zero or positive means a
+ * specific-catcache inval message (and also serves as the catcache ID field).
+ * Negative values identify the other message types, as per codes below.
+ *
+ * Catcache inval events are initially driven by detecting tuple inserts,
+ * updates and deletions in system catalogs (see CacheInvalidateHeapTuple).
+ * An update can generate two inval events, one for the old tuple and one for
+ * the new, but this is reduced to one event if the tuple's hash key doesn't
+ * change. Note that the inval events themselves don't actually say whether
+ * the tuple is being inserted or deleted. Also, since we transmit only a
+ * hash key, there is a small risk of unnecessary invalidations due to chance
+ * matches of hash keys.
+ *
+ * Note that some system catalogs have multiple caches on them (with different
+ * indexes). On detecting a tuple invalidation in such a catalog, separate
+ * catcache inval messages must be generated for each of its caches, since
+ * the hash keys will generally be different.
+ *
+ * Catcache, relcache, and snapshot invalidations are transactional, and so
+ * are sent to other backends upon commit. Internally to the generating
+ * backend, they are also processed at CommandCounterIncrement so that later
+ * commands in the same transaction see the new state. The generating backend
+ * also has to process them at abort, to flush out any cache state it's loaded
+ * from no-longer-valid entries.
+ *
+ * smgr and relation mapping invalidations are non-transactional: they are
+ * sent immediately when the underlying file change is made.
+ */
+
+typedef struct
+{
+ int8 id; /* cache ID --- must be first */
+ Oid dbId; /* database ID, or 0 if a shared relation */
+ uint32 hashValue; /* hash value of key for this catcache */
+} SharedInvalCatcacheMsg;
+
+#define SHAREDINVALCATALOG_ID (-1)
+
+typedef struct
+{
+ int8 id; /* type field --- must be first */
+ Oid dbId; /* database ID, or 0 if a shared catalog */
+ Oid catId; /* ID of catalog whose contents are invalid */
+} SharedInvalCatalogMsg;
+
+#define SHAREDINVALRELCACHE_ID (-2)
+
+typedef struct
+{
+ int8 id; /* type field --- must be first */
+ Oid dbId; /* database ID, or 0 if a shared relation */
+ Oid relId; /* relation ID, or 0 if whole relcache */
+} SharedInvalRelcacheMsg;
+
+#define SHAREDINVALSMGR_ID (-3)
+
+typedef struct
+{
+ /* note: field layout chosen to pack into 16 bytes */
+ int8 id; /* type field --- must be first */
+ int8 backend_hi; /* high bits of backend ID, if temprel */
+ uint16 backend_lo; /* low bits of backend ID, if temprel */
+ RelFileNode rnode; /* spcNode, dbNode, relNode */
+} SharedInvalSmgrMsg;
+
+#define SHAREDINVALRELMAP_ID (-4)
+
+typedef struct
+{
+ int8 id; /* type field --- must be first */
+ Oid dbId; /* database ID, or 0 for shared catalogs */
+} SharedInvalRelmapMsg;
+
+#define SHAREDINVALSNAPSHOT_ID (-5)
+
+typedef struct
+{
+ int8 id; /* type field --- must be first */
+ Oid dbId; /* database ID, or 0 if a shared relation */
+ Oid relId; /* relation ID */
+} SharedInvalSnapshotMsg;
+
+typedef union
+{
+ int8 id; /* type field --- must be first */
+ SharedInvalCatcacheMsg cc;
+ SharedInvalCatalogMsg cat;
+ SharedInvalRelcacheMsg rc;
+ SharedInvalSmgrMsg sm;
+ SharedInvalRelmapMsg rm;
+ SharedInvalSnapshotMsg sn;
+} SharedInvalidationMessage;
+
+
+/* Counter of messages processed; don't worry about overflow. */
+extern uint64 SharedInvalidMessageCounter;
+
+extern volatile sig_atomic_t catchupInterruptPending;
+
+extern void SendSharedInvalidMessages(const SharedInvalidationMessage *msgs,
+ int n);
+extern void ReceiveSharedInvalidMessages(void (*invalFunction) (SharedInvalidationMessage *msg),
+ void (*resetFunction) (void));
+
+/* signal handler for catchup events (PROCSIG_CATCHUP_INTERRUPT) */
+extern void HandleCatchupInterrupt(void);
+
+/*
+ * enable/disable processing of catchup events directly from signal handler.
+ * The enable routine first performs processing of any catchup events that
+ * have occurred since the last disable.
+ */
+extern void ProcessCatchupInterrupt(void);
+
+extern int xactGetCommittedInvalidationMessages(SharedInvalidationMessage **msgs,
+ bool *RelcacheInitFileInval);
+extern void ProcessCommittedInvalidationMessages(SharedInvalidationMessage *msgs,
+ int nmsgs, bool RelcacheInitFileInval,
+ Oid dbid, Oid tsid);
+
+extern void LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg);
+
+#endif /* SINVAL_H */
diff --git a/src/include/storage/sinvaladt.h b/src/include/storage/sinvaladt.h
new file mode 100644
index 0000000..426f547
--- /dev/null
+++ b/src/include/storage/sinvaladt.h
@@ -0,0 +1,43 @@
+/*-------------------------------------------------------------------------
+ *
+ * sinvaladt.h
+ * POSTGRES shared cache invalidation data manager.
+ *
+ * The shared cache invalidation manager is responsible for transmitting
+ * invalidation messages between backends. Any message sent by any backend
+ * must be delivered to all already-running backends before it can be
+ * forgotten. (If we run out of space, we instead deliver a "RESET"
+ * message to backends that have fallen too far behind.)
+ *
+ * The struct type SharedInvalidationMessage, defining the contents of
+ * a single message, is defined in sinval.h.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/sinvaladt.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SINVALADT_H
+#define SINVALADT_H
+
+#include "storage/lock.h"
+#include "storage/sinval.h"
+
+/*
+ * prototypes for functions in sinvaladt.c
+ */
+extern Size SInvalShmemSize(void);
+extern void CreateSharedInvalidationState(void);
+extern void SharedInvalBackendInit(bool sendOnly);
+extern PGPROC *BackendIdGetProc(int backendID);
+extern void BackendIdGetTransactionIds(int backendID, TransactionId *xid, TransactionId *xmin);
+
+extern void SIInsertDataEntries(const SharedInvalidationMessage *data, int n);
+extern int SIGetDataEntries(SharedInvalidationMessage *data, int datasize);
+extern void SICleanupQueue(bool callerHasWriteLock, int minFree);
+
+extern LocalTransactionId GetNextLocalTransactionId(void);
+
+#endif /* SINVALADT_H */
diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h
new file mode 100644
index 0000000..6566659
--- /dev/null
+++ b/src/include/storage/smgr.h
@@ -0,0 +1,109 @@
+/*-------------------------------------------------------------------------
+ *
+ * smgr.h
+ * storage manager switch public interface declarations.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/smgr.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SMGR_H
+#define SMGR_H
+
+#include "lib/ilist.h"
+#include "storage/block.h"
+#include "storage/relfilenode.h"
+
+/*
+ * smgr.c maintains a table of SMgrRelation objects, which are essentially
+ * cached file handles. An SMgrRelation is created (if not already present)
+ * by smgropen(), and destroyed by smgrclose(). Note that neither of these
+ * operations imply I/O, they just create or destroy a hashtable entry.
+ * (But smgrclose() may release associated resources, such as OS-level file
+ * descriptors.)
+ *
+ * An SMgrRelation may have an "owner", which is just a pointer to it from
+ * somewhere else; smgr.c will clear this pointer if the SMgrRelation is
+ * closed. We use this to avoid dangling pointers from relcache to smgr
+ * without having to make the smgr explicitly aware of relcache. There
+ * can't be more than one "owner" pointer per SMgrRelation, but that's
+ * all we need.
+ *
+ * SMgrRelations that do not have an "owner" are considered to be transient,
+ * and are deleted at end of transaction.
+ */
+typedef struct SMgrRelationData
+{
+ /* rnode is the hashtable lookup key, so it must be first! */
+ RelFileNodeBackend smgr_rnode; /* relation physical identifier */
+
+ /* pointer to owning pointer, or NULL if none */
+ struct SMgrRelationData **smgr_owner;
+
+ /*
+ * These next three fields are not actually used or manipulated by smgr,
+ * except that they are reset to InvalidBlockNumber upon a cache flush
+ * event (in particular, upon truncation of the relation). Higher levels
+ * store cached state here so that it will be reset when truncation
+ * happens. In all three cases, InvalidBlockNumber means "unknown".
+ */
+ BlockNumber smgr_targblock; /* current insertion target block */
+ BlockNumber smgr_fsm_nblocks; /* last known size of fsm fork */
+ BlockNumber smgr_vm_nblocks; /* last known size of vm fork */
+
+ /* additional public fields may someday exist here */
+
+ /*
+ * Fields below here are intended to be private to smgr.c and its
+ * submodules. Do not touch them from elsewhere.
+ */
+ int smgr_which; /* storage manager selector */
+
+ /*
+ * for md.c; per-fork arrays of the number of open segments
+ * (md_num_open_segs) and the segments themselves (md_seg_fds).
+ */
+ int md_num_open_segs[MAX_FORKNUM + 1];
+ struct _MdfdVec *md_seg_fds[MAX_FORKNUM + 1];
+
+ /* if unowned, list link in list of all unowned SMgrRelations */
+ dlist_node node;
+} SMgrRelationData;
+
+typedef SMgrRelationData *SMgrRelation;
+
+#define SmgrIsTemp(smgr) \
+ RelFileNodeBackendIsTemp((smgr)->smgr_rnode)
+
+extern void smgrinit(void);
+extern SMgrRelation smgropen(RelFileNode rnode, BackendId backend);
+extern bool smgrexists(SMgrRelation reln, ForkNumber forknum);
+extern void smgrsetowner(SMgrRelation *owner, SMgrRelation reln);
+extern void smgrclearowner(SMgrRelation *owner, SMgrRelation reln);
+extern void smgrclose(SMgrRelation reln);
+extern void smgrcloseall(void);
+extern void smgrclosenode(RelFileNodeBackend rnode);
+extern void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo);
+extern void smgrdosyncall(SMgrRelation *rels, int nrels);
+extern void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo);
+extern void smgrextend(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber blocknum, char *buffer, bool skipFsync);
+extern bool smgrprefetch(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber blocknum);
+extern void smgrread(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber blocknum, char *buffer);
+extern void smgrwrite(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber blocknum, char *buffer, bool skipFsync);
+extern void smgrwriteback(SMgrRelation reln, ForkNumber forknum,
+ BlockNumber blocknum, BlockNumber nblocks);
+extern BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum);
+extern void smgrtruncate(SMgrRelation reln, ForkNumber *forknum,
+ int nforks, BlockNumber *nblocks);
+extern void smgrimmedsync(SMgrRelation reln, ForkNumber forknum);
+extern void AtEOXact_SMgr(void);
+
+#endif /* SMGR_H */
diff --git a/src/include/storage/spin.h b/src/include/storage/spin.h
new file mode 100644
index 0000000..5ad25d0
--- /dev/null
+++ b/src/include/storage/spin.h
@@ -0,0 +1,77 @@
+/*-------------------------------------------------------------------------
+ *
+ * spin.h
+ * Hardware-independent implementation of spinlocks.
+ *
+ *
+ * The hardware-independent interface to spinlocks is defined by the
+ * typedef "slock_t" and these macros:
+ *
+ * void SpinLockInit(volatile slock_t *lock)
+ * Initialize a spinlock (to the unlocked state).
+ *
+ * void SpinLockAcquire(volatile slock_t *lock)
+ * Acquire a spinlock, waiting if necessary.
+ * Time out and abort() if unable to acquire the lock in a
+ * "reasonable" amount of time --- typically ~ 1 minute.
+ *
+ * void SpinLockRelease(volatile slock_t *lock)
+ * Unlock a previously acquired lock.
+ *
+ * bool SpinLockFree(slock_t *lock)
+ * Tests if the lock is free. Returns true if free, false if locked.
+ * This does *not* change the state of the lock.
+ *
+ * Callers must beware that the macro argument may be evaluated multiple
+ * times!
+ *
+ * Load and store operations in calling code are guaranteed not to be
+ * reordered with respect to these operations, because they include a
+ * compiler barrier. (Before PostgreSQL 9.5, callers needed to use a
+ * volatile qualifier to access data protected by spinlocks.)
+ *
+ * Keep in mind the coding rule that spinlocks must not be held for more
+ * than a few instructions. In particular, we assume it is not possible
+ * for a CHECK_FOR_INTERRUPTS() to occur while holding a spinlock, and so
+ * it is not necessary to do HOLD/RESUME_INTERRUPTS() in these macros.
+ *
+ * These macros are implemented in terms of hardware-dependent macros
+ * supplied by s_lock.h. There is not currently any extra functionality
+ * added by this header, but there has been in the past and may someday
+ * be again.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/spin.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SPIN_H
+#define SPIN_H
+
+#include "storage/s_lock.h"
+#ifndef HAVE_SPINLOCKS
+#include "storage/pg_sema.h"
+#endif
+
+
+#define SpinLockInit(lock) S_INIT_LOCK(lock)
+
+#define SpinLockAcquire(lock) S_LOCK(lock)
+
+#define SpinLockRelease(lock) S_UNLOCK(lock)
+
+#define SpinLockFree(lock) S_LOCK_FREE(lock)
+
+
+extern int SpinlockSemas(void);
+extern Size SpinlockSemaSize(void);
+
+#ifndef HAVE_SPINLOCKS
+extern void SpinlockSemaInit(void);
+extern PGSemaphore *SpinlockSemaArray;
+#endif
+
+#endif /* SPIN_H */
diff --git a/src/include/storage/standby.h b/src/include/storage/standby.h
new file mode 100644
index 0000000..cfbe426
--- /dev/null
+++ b/src/include/storage/standby.h
@@ -0,0 +1,91 @@
+/*-------------------------------------------------------------------------
+ *
+ * standby.h
+ * Definitions for hot standby mode.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/standby.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef STANDBY_H
+#define STANDBY_H
+
+#include "storage/lock.h"
+#include "storage/procsignal.h"
+#include "storage/relfilenode.h"
+#include "storage/standbydefs.h"
+
+/* User-settable GUC parameters */
+extern int vacuum_defer_cleanup_age;
+extern int max_standby_archive_delay;
+extern int max_standby_streaming_delay;
+
+extern void InitRecoveryTransactionEnvironment(void);
+extern void ShutdownRecoveryTransactionEnvironment(void);
+
+extern void ResolveRecoveryConflictWithSnapshot(TransactionId latestRemovedXid,
+ RelFileNode node);
+extern void ResolveRecoveryConflictWithTablespace(Oid tsid);
+extern void ResolveRecoveryConflictWithDatabase(Oid dbid);
+
+extern void ResolveRecoveryConflictWithLock(LOCKTAG locktag);
+extern void ResolveRecoveryConflictWithBufferPin(void);
+extern void CheckRecoveryConflictDeadlock(void);
+extern void StandbyDeadLockHandler(void);
+extern void StandbyTimeoutHandler(void);
+extern void StandbyLockTimeoutHandler(void);
+
+/*
+ * Standby Rmgr (RM_STANDBY_ID)
+ *
+ * Standby recovery manager exists to perform actions that are required
+ * to make hot standby work. That includes logging AccessExclusiveLocks taken
+ * by transactions and running-xacts snapshots.
+ */
+extern void StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid relOid);
+extern void StandbyReleaseLockTree(TransactionId xid,
+ int nsubxids, TransactionId *subxids);
+extern void StandbyReleaseAllLocks(void);
+extern void StandbyReleaseOldLocks(TransactionId oldxid);
+
+#define MinSizeOfXactRunningXacts offsetof(xl_running_xacts, xids)
+
+
+/*
+ * Declarations for GetRunningTransactionData(). Similar to Snapshots, but
+ * not quite. This has nothing at all to do with visibility on this server,
+ * so this is completely separate from snapmgr.c and snapmgr.h.
+ * This data is important for creating the initial snapshot state on a
+ * standby server. We need lots more information than a normal snapshot,
+ * hence we use a specific data structure for our needs. This data
+ * is written to WAL as a separate record immediately after each
+ * checkpoint. That means that wherever we start a standby from we will
+ * almost immediately see the data we need to begin executing queries.
+ */
+
+typedef struct RunningTransactionsData
+{
+ int xcnt; /* # of xact ids in xids[] */
+ int subxcnt; /* # of subxact ids in xids[] */
+ bool subxid_overflow; /* snapshot overflowed, subxids missing */
+ TransactionId nextXid; /* xid from ShmemVariableCache->nextFullXid */
+ TransactionId oldestRunningXid; /* *not* oldestXmin */
+ TransactionId latestCompletedXid; /* so we can set xmax */
+
+ TransactionId *xids; /* array of (sub)xids still running */
+} RunningTransactionsData;
+
+typedef RunningTransactionsData *RunningTransactions;
+
+extern void LogAccessExclusiveLock(Oid dbOid, Oid relOid);
+extern void LogAccessExclusiveLockPrepare(void);
+
+extern XLogRecPtr LogStandbySnapshot(void);
+extern void LogStandbyInvalidations(int nmsgs, SharedInvalidationMessage *msgs,
+ bool relcacheInitFileInval);
+
+#endif /* STANDBY_H */
diff --git a/src/include/storage/standbydefs.h b/src/include/storage/standbydefs.h
new file mode 100644
index 0000000..4876d2e
--- /dev/null
+++ b/src/include/storage/standbydefs.h
@@ -0,0 +1,74 @@
+/*-------------------------------------------------------------------------
+ *
+ * standbydefs.h
+ * Frontend exposed definitions for hot standby mode.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/standbydefs.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef STANDBYDEFS_H
+#define STANDBYDEFS_H
+
+#include "access/xlogreader.h"
+#include "lib/stringinfo.h"
+#include "storage/lockdefs.h"
+#include "storage/sinval.h"
+
+/* Recovery handlers for the Standby Rmgr (RM_STANDBY_ID) */
+extern void standby_redo(XLogReaderState *record);
+extern void standby_desc(StringInfo buf, XLogReaderState *record);
+extern const char *standby_identify(uint8 info);
+extern void standby_desc_invalidations(StringInfo buf,
+ int nmsgs, SharedInvalidationMessage *msgs,
+ Oid dbId, Oid tsId,
+ bool relcacheInitFileInval);
+
+/*
+ * XLOG message types
+ */
+#define XLOG_STANDBY_LOCK 0x00
+#define XLOG_RUNNING_XACTS 0x10
+#define XLOG_INVALIDATIONS 0x20
+
+typedef struct xl_standby_locks
+{
+ int nlocks; /* number of entries in locks array */
+ xl_standby_lock locks[FLEXIBLE_ARRAY_MEMBER];
+} xl_standby_locks;
+
+/*
+ * When we write running xact data to WAL, we use this structure.
+ */
+typedef struct xl_running_xacts
+{
+ int xcnt; /* # of xact ids in xids[] */
+ int subxcnt; /* # of subxact ids in xids[] */
+ bool subxid_overflow; /* snapshot overflowed, subxids missing */
+ TransactionId nextXid; /* xid from ShmemVariableCache->nextFullXid */
+ TransactionId oldestRunningXid; /* *not* oldestXmin */
+ TransactionId latestCompletedXid; /* so we can set xmax */
+
+ TransactionId xids[FLEXIBLE_ARRAY_MEMBER];
+} xl_running_xacts;
+
+/*
+ * Invalidations for standby, currently only when transactions without an
+ * assigned xid commit.
+ */
+typedef struct xl_invalidations
+{
+ Oid dbId; /* MyDatabaseId */
+ Oid tsId; /* MyDatabaseTableSpace */
+ bool relcacheInitFileInval; /* invalidate relcache init files */
+ int nmsgs; /* number of shared inval msgs */
+ SharedInvalidationMessage msgs[FLEXIBLE_ARRAY_MEMBER];
+} xl_invalidations;
+
+#define MinSizeOfInvalidations offsetof(xl_invalidations, msgs)
+
+#endif /* STANDBYDEFS_H */
diff --git a/src/include/storage/sync.h b/src/include/storage/sync.h
new file mode 100644
index 0000000..e16ab8e
--- /dev/null
+++ b/src/include/storage/sync.h
@@ -0,0 +1,62 @@
+/*-------------------------------------------------------------------------
+ *
+ * sync.h
+ * File synchronization management code.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/storage/sync.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SYNC_H
+#define SYNC_H
+
+#include "storage/relfilenode.h"
+
+/*
+ * Type of sync request. These are used to manage the set of pending
+ * requests to call a sync handler's sync or unlink functions at the next
+ * checkpoint.
+ */
+typedef enum SyncRequestType
+{
+ SYNC_REQUEST, /* schedule a call of sync function */
+ SYNC_UNLINK_REQUEST, /* schedule a call of unlink function */
+ SYNC_FORGET_REQUEST, /* forget all calls for a tag */
+ SYNC_FILTER_REQUEST /* forget all calls satisfying match fn */
+} SyncRequestType;
+
+/*
+ * Which set of functions to use to handle a given request. The values of
+ * the enumerators must match the indexes of the function table in sync.c.
+ */
+typedef enum SyncRequestHandler
+{
+ SYNC_HANDLER_MD = 0 /* md smgr */
+} SyncRequestHandler;
+
+/*
+ * A tag identifying a file. Currently it has the members required for md.c's
+ * usage, but sync.c has no knowledge of the internal structure, and it is
+ * liable to change as required by future handlers.
+ */
+typedef struct FileTag
+{
+ int16 handler; /* SyncRequestHandler value, saving space */
+ int16 forknum; /* ForkNumber, saving space */
+ RelFileNode rnode;
+ uint32 segno;
+} FileTag;
+
+extern void InitSync(void);
+extern void SyncPreCheckpoint(void);
+extern void SyncPostCheckpoint(void);
+extern void ProcessSyncRequests(void);
+extern void RememberSyncRequest(const FileTag *ftag, SyncRequestType type);
+extern void EnableSyncRequestForwarding(void);
+extern bool RegisterSyncRequest(const FileTag *ftag, SyncRequestType type,
+ bool retryOnError);
+
+#endif /* SYNC_H */
diff --git a/src/include/tcop/cmdtag.h b/src/include/tcop/cmdtag.h
new file mode 100644
index 0000000..f75a91e
--- /dev/null
+++ b/src/include/tcop/cmdtag.h
@@ -0,0 +1,58 @@
+/*-------------------------------------------------------------------------
+ *
+ * cmdtag.h
+ * Declarations for commandtag names and enumeration.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/tcop/cmdtag.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef CMDTAG_H
+#define CMDTAG_H
+
+
+#define PG_CMDTAG(tag, name, evtrgok, rwrok, rowcnt) \
+ tag,
+
+typedef enum CommandTag
+{
+#include "tcop/cmdtaglist.h"
+ COMMAND_TAG_NEXTTAG
+} CommandTag;
+
+#undef PG_CMDTAG
+
+typedef struct QueryCompletion
+{
+ CommandTag commandTag;
+ uint64 nprocessed;
+} QueryCompletion;
+
+
+static inline void
+SetQueryCompletion(QueryCompletion *qc, CommandTag commandTag,
+ uint64 nprocessed)
+{
+ qc->commandTag = commandTag;
+ qc->nprocessed = nprocessed;
+}
+
+static inline void
+CopyQueryCompletion(QueryCompletion *dst, const QueryCompletion *src)
+{
+ dst->commandTag = src->commandTag;
+ dst->nprocessed = src->nprocessed;
+}
+
+
+extern void InitializeQueryCompletion(QueryCompletion *qc);
+extern const char *GetCommandTagName(CommandTag commandTag);
+extern bool command_tag_display_rowcount(CommandTag commandTag);
+extern bool command_tag_event_trigger_ok(CommandTag commandTag);
+extern bool command_tag_table_rewrite_ok(CommandTag commandTag);
+extern CommandTag GetCommandTagEnum(const char *tagname);
+
+#endif /* CMDTAG_H */
diff --git a/src/include/tcop/cmdtaglist.h b/src/include/tcop/cmdtaglist.h
new file mode 100644
index 0000000..be94852
--- /dev/null
+++ b/src/include/tcop/cmdtaglist.h
@@ -0,0 +1,217 @@
+/*----------------------------------------------------------------------
+ *
+ * cmdtaglist.h
+ * Command tags
+ *
+ * The command tag list is kept in its own source file for possible use
+ * by automatic tools. The exact representation of a command tag is
+ * determined by the PG_CMDTAG macro, which is not defined in this file;
+ * it can be defined by the caller for special purposes.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/tcop/cmdtaglist.h
+ *
+ *----------------------------------------------------------------------
+ */
+
+/* there is deliberately not an #ifndef CMDTAGLIST_H here */
+
+/*
+ * List of command tags. The entries must be sorted alphabetically on their
+ * textual name, so that we can bsearch on it; see GetCommandTagEnum().
+ */
+
+/* symbol name, textual name, event_trigger_ok, table_rewrite_ok, rowcount */
+PG_CMDTAG(CMDTAG_UNKNOWN, "???", false, false, false)
+PG_CMDTAG(CMDTAG_ALTER_ACCESS_METHOD, "ALTER ACCESS METHOD", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_AGGREGATE, "ALTER AGGREGATE", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_CAST, "ALTER CAST", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_COLLATION, "ALTER COLLATION", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_CONSTRAINT, "ALTER CONSTRAINT", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_CONVERSION, "ALTER CONVERSION", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_DATABASE, "ALTER DATABASE", false, false, false)
+PG_CMDTAG(CMDTAG_ALTER_DEFAULT_PRIVILEGES, "ALTER DEFAULT PRIVILEGES", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_DOMAIN, "ALTER DOMAIN", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_EVENT_TRIGGER, "ALTER EVENT TRIGGER", false, false, false)
+PG_CMDTAG(CMDTAG_ALTER_EXTENSION, "ALTER EXTENSION", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_FOREIGN_DATA_WRAPPER, "ALTER FOREIGN DATA WRAPPER", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_FOREIGN_TABLE, "ALTER FOREIGN TABLE", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_FUNCTION, "ALTER FUNCTION", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_INDEX, "ALTER INDEX", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_LANGUAGE, "ALTER LANGUAGE", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_LARGE_OBJECT, "ALTER LARGE OBJECT", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_MATERIALIZED_VIEW, "ALTER MATERIALIZED VIEW", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_OPERATOR, "ALTER OPERATOR", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_OPERATOR_CLASS, "ALTER OPERATOR CLASS", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_OPERATOR_FAMILY, "ALTER OPERATOR FAMILY", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_POLICY, "ALTER POLICY", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_PROCEDURE, "ALTER PROCEDURE", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_PUBLICATION, "ALTER PUBLICATION", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_ROLE, "ALTER ROLE", false, false, false)
+PG_CMDTAG(CMDTAG_ALTER_ROUTINE, "ALTER ROUTINE", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_RULE, "ALTER RULE", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_SCHEMA, "ALTER SCHEMA", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_SEQUENCE, "ALTER SEQUENCE", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_SERVER, "ALTER SERVER", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_STATISTICS, "ALTER STATISTICS", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_SUBSCRIPTION, "ALTER SUBSCRIPTION", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_SYSTEM, "ALTER SYSTEM", false, false, false)
+PG_CMDTAG(CMDTAG_ALTER_TABLE, "ALTER TABLE", true, true, false)
+PG_CMDTAG(CMDTAG_ALTER_TABLESPACE, "ALTER TABLESPACE", false, false, false)
+PG_CMDTAG(CMDTAG_ALTER_TEXT_SEARCH_CONFIGURATION, "ALTER TEXT SEARCH CONFIGURATION", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_TEXT_SEARCH_DICTIONARY, "ALTER TEXT SEARCH DICTIONARY", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_TEXT_SEARCH_PARSER, "ALTER TEXT SEARCH PARSER", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_TEXT_SEARCH_TEMPLATE, "ALTER TEXT SEARCH TEMPLATE", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_TRANSFORM, "ALTER TRANSFORM", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_TRIGGER, "ALTER TRIGGER", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_TYPE, "ALTER TYPE", true, true, false)
+PG_CMDTAG(CMDTAG_ALTER_USER_MAPPING, "ALTER USER MAPPING", true, false, false)
+PG_CMDTAG(CMDTAG_ALTER_VIEW, "ALTER VIEW", true, false, false)
+PG_CMDTAG(CMDTAG_ANALYZE, "ANALYZE", false, false, false)
+PG_CMDTAG(CMDTAG_BEGIN, "BEGIN", false, false, false)
+PG_CMDTAG(CMDTAG_CALL, "CALL", false, false, false)
+PG_CMDTAG(CMDTAG_CHECKPOINT, "CHECKPOINT", false, false, false)
+PG_CMDTAG(CMDTAG_CLOSE, "CLOSE", false, false, false)
+PG_CMDTAG(CMDTAG_CLOSE_CURSOR, "CLOSE CURSOR", false, false, false)
+PG_CMDTAG(CMDTAG_CLOSE_CURSOR_ALL, "CLOSE CURSOR ALL", false, false, false)
+PG_CMDTAG(CMDTAG_CLUSTER, "CLUSTER", false, false, false)
+PG_CMDTAG(CMDTAG_COMMENT, "COMMENT", true, false, false)
+PG_CMDTAG(CMDTAG_COMMIT, "COMMIT", false, false, false)
+PG_CMDTAG(CMDTAG_COMMIT_PREPARED, "COMMIT PREPARED", false, false, false)
+PG_CMDTAG(CMDTAG_COPY, "COPY", false, false, true)
+PG_CMDTAG(CMDTAG_COPY_FROM, "COPY FROM", false, false, false)
+PG_CMDTAG(CMDTAG_CREATE_ACCESS_METHOD, "CREATE ACCESS METHOD", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_AGGREGATE, "CREATE AGGREGATE", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_CAST, "CREATE CAST", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_COLLATION, "CREATE COLLATION", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_CONSTRAINT, "CREATE CONSTRAINT", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_CONVERSION, "CREATE CONVERSION", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_DATABASE, "CREATE DATABASE", false, false, false)
+PG_CMDTAG(CMDTAG_CREATE_DOMAIN, "CREATE DOMAIN", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_EVENT_TRIGGER, "CREATE EVENT TRIGGER", false, false, false)
+PG_CMDTAG(CMDTAG_CREATE_EXTENSION, "CREATE EXTENSION", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_FOREIGN_DATA_WRAPPER, "CREATE FOREIGN DATA WRAPPER", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_FOREIGN_TABLE, "CREATE FOREIGN TABLE", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_FUNCTION, "CREATE FUNCTION", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_INDEX, "CREATE INDEX", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_LANGUAGE, "CREATE LANGUAGE", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_MATERIALIZED_VIEW, "CREATE MATERIALIZED VIEW", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_OPERATOR, "CREATE OPERATOR", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_OPERATOR_CLASS, "CREATE OPERATOR CLASS", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_OPERATOR_FAMILY, "CREATE OPERATOR FAMILY", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_POLICY, "CREATE POLICY", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_PROCEDURE, "CREATE PROCEDURE", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_PUBLICATION, "CREATE PUBLICATION", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_ROLE, "CREATE ROLE", false, false, false)
+PG_CMDTAG(CMDTAG_CREATE_ROUTINE, "CREATE ROUTINE", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_RULE, "CREATE RULE", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_SCHEMA, "CREATE SCHEMA", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_SEQUENCE, "CREATE SEQUENCE", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_SERVER, "CREATE SERVER", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_STATISTICS, "CREATE STATISTICS", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_SUBSCRIPTION, "CREATE SUBSCRIPTION", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_TABLE, "CREATE TABLE", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_TABLE_AS, "CREATE TABLE AS", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_TABLESPACE, "CREATE TABLESPACE", false, false, false)
+PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_CONFIGURATION, "CREATE TEXT SEARCH CONFIGURATION", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_DICTIONARY, "CREATE TEXT SEARCH DICTIONARY", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_PARSER, "CREATE TEXT SEARCH PARSER", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_TEMPLATE, "CREATE TEXT SEARCH TEMPLATE", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_TRANSFORM, "CREATE TRANSFORM", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_TRIGGER, "CREATE TRIGGER", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_TYPE, "CREATE TYPE", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_USER_MAPPING, "CREATE USER MAPPING", true, false, false)
+PG_CMDTAG(CMDTAG_CREATE_VIEW, "CREATE VIEW", true, false, false)
+PG_CMDTAG(CMDTAG_DEALLOCATE, "DEALLOCATE", false, false, false)
+PG_CMDTAG(CMDTAG_DEALLOCATE_ALL, "DEALLOCATE ALL", false, false, false)
+PG_CMDTAG(CMDTAG_DECLARE_CURSOR, "DECLARE CURSOR", false, false, false)
+PG_CMDTAG(CMDTAG_DELETE, "DELETE", false, false, true)
+PG_CMDTAG(CMDTAG_DISCARD, "DISCARD", false, false, false)
+PG_CMDTAG(CMDTAG_DISCARD_ALL, "DISCARD ALL", false, false, false)
+PG_CMDTAG(CMDTAG_DISCARD_PLANS, "DISCARD PLANS", false, false, false)
+PG_CMDTAG(CMDTAG_DISCARD_SEQUENCES, "DISCARD SEQUENCES", false, false, false)
+PG_CMDTAG(CMDTAG_DISCARD_TEMP, "DISCARD TEMP", false, false, false)
+PG_CMDTAG(CMDTAG_DO, "DO", false, false, false)
+PG_CMDTAG(CMDTAG_DROP_ACCESS_METHOD, "DROP ACCESS METHOD", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_AGGREGATE, "DROP AGGREGATE", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_CAST, "DROP CAST", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_COLLATION, "DROP COLLATION", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_CONSTRAINT, "DROP CONSTRAINT", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_CONVERSION, "DROP CONVERSION", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_DATABASE, "DROP DATABASE", false, false, false)
+PG_CMDTAG(CMDTAG_DROP_DOMAIN, "DROP DOMAIN", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_EVENT_TRIGGER, "DROP EVENT TRIGGER", false, false, false)
+PG_CMDTAG(CMDTAG_DROP_EXTENSION, "DROP EXTENSION", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_FOREIGN_DATA_WRAPPER, "DROP FOREIGN DATA WRAPPER", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_FOREIGN_TABLE, "DROP FOREIGN TABLE", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_FUNCTION, "DROP FUNCTION", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_INDEX, "DROP INDEX", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_LANGUAGE, "DROP LANGUAGE", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_MATERIALIZED_VIEW, "DROP MATERIALIZED VIEW", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_OPERATOR, "DROP OPERATOR", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_OPERATOR_CLASS, "DROP OPERATOR CLASS", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_OPERATOR_FAMILY, "DROP OPERATOR FAMILY", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_OWNED, "DROP OWNED", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_POLICY, "DROP POLICY", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_PROCEDURE, "DROP PROCEDURE", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_PUBLICATION, "DROP PUBLICATION", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_ROLE, "DROP ROLE", false, false, false)
+PG_CMDTAG(CMDTAG_DROP_ROUTINE, "DROP ROUTINE", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_RULE, "DROP RULE", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_SCHEMA, "DROP SCHEMA", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_SEQUENCE, "DROP SEQUENCE", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_SERVER, "DROP SERVER", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_STATISTICS, "DROP STATISTICS", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_SUBSCRIPTION, "DROP SUBSCRIPTION", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_TABLE, "DROP TABLE", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_TABLESPACE, "DROP TABLESPACE", false, false, false)
+PG_CMDTAG(CMDTAG_DROP_TEXT_SEARCH_CONFIGURATION, "DROP TEXT SEARCH CONFIGURATION", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_TEXT_SEARCH_DICTIONARY, "DROP TEXT SEARCH DICTIONARY", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_TEXT_SEARCH_PARSER, "DROP TEXT SEARCH PARSER", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_TEXT_SEARCH_TEMPLATE, "DROP TEXT SEARCH TEMPLATE", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_TRANSFORM, "DROP TRANSFORM", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_TRIGGER, "DROP TRIGGER", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_TYPE, "DROP TYPE", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_USER_MAPPING, "DROP USER MAPPING", true, false, false)
+PG_CMDTAG(CMDTAG_DROP_VIEW, "DROP VIEW", true, false, false)
+PG_CMDTAG(CMDTAG_EXECUTE, "EXECUTE", false, false, false)
+PG_CMDTAG(CMDTAG_EXPLAIN, "EXPLAIN", false, false, false)
+PG_CMDTAG(CMDTAG_FETCH, "FETCH", false, false, true)
+PG_CMDTAG(CMDTAG_GRANT, "GRANT", true, false, false)
+PG_CMDTAG(CMDTAG_GRANT_ROLE, "GRANT ROLE", false, false, false)
+PG_CMDTAG(CMDTAG_IMPORT_FOREIGN_SCHEMA, "IMPORT FOREIGN SCHEMA", true, false, false)
+PG_CMDTAG(CMDTAG_INSERT, "INSERT", false, false, true)
+PG_CMDTAG(CMDTAG_LISTEN, "LISTEN", false, false, false)
+PG_CMDTAG(CMDTAG_LOAD, "LOAD", false, false, false)
+PG_CMDTAG(CMDTAG_LOCK_TABLE, "LOCK TABLE", false, false, false)
+PG_CMDTAG(CMDTAG_MOVE, "MOVE", false, false, true)
+PG_CMDTAG(CMDTAG_NOTIFY, "NOTIFY", false, false, false)
+PG_CMDTAG(CMDTAG_PREPARE, "PREPARE", false, false, false)
+PG_CMDTAG(CMDTAG_PREPARE_TRANSACTION, "PREPARE TRANSACTION", false, false, false)
+PG_CMDTAG(CMDTAG_REASSIGN_OWNED, "REASSIGN OWNED", false, false, false)
+PG_CMDTAG(CMDTAG_REFRESH_MATERIALIZED_VIEW, "REFRESH MATERIALIZED VIEW", true, false, false)
+PG_CMDTAG(CMDTAG_REINDEX, "REINDEX", false, false, false)
+PG_CMDTAG(CMDTAG_RELEASE, "RELEASE", false, false, false)
+PG_CMDTAG(CMDTAG_RESET, "RESET", false, false, false)
+PG_CMDTAG(CMDTAG_REVOKE, "REVOKE", true, false, false)
+PG_CMDTAG(CMDTAG_REVOKE_ROLE, "REVOKE ROLE", false, false, false)
+PG_CMDTAG(CMDTAG_ROLLBACK, "ROLLBACK", false, false, false)
+PG_CMDTAG(CMDTAG_ROLLBACK_PREPARED, "ROLLBACK PREPARED", false, false, false)
+PG_CMDTAG(CMDTAG_SAVEPOINT, "SAVEPOINT", false, false, false)
+PG_CMDTAG(CMDTAG_SECURITY_LABEL, "SECURITY LABEL", true, false, false)
+PG_CMDTAG(CMDTAG_SELECT, "SELECT", false, false, true)
+PG_CMDTAG(CMDTAG_SELECT_FOR_KEY_SHARE, "SELECT FOR KEY SHARE", false, false, false)
+PG_CMDTAG(CMDTAG_SELECT_FOR_NO_KEY_UPDATE, "SELECT FOR NO KEY UPDATE", false, false, false)
+PG_CMDTAG(CMDTAG_SELECT_FOR_SHARE, "SELECT FOR SHARE", false, false, false)
+PG_CMDTAG(CMDTAG_SELECT_FOR_UPDATE, "SELECT FOR UPDATE", false, false, false)
+PG_CMDTAG(CMDTAG_SELECT_INTO, "SELECT INTO", true, false, false)
+PG_CMDTAG(CMDTAG_SET, "SET", false, false, false)
+PG_CMDTAG(CMDTAG_SET_CONSTRAINTS, "SET CONSTRAINTS", false, false, false)
+PG_CMDTAG(CMDTAG_SHOW, "SHOW", false, false, false)
+PG_CMDTAG(CMDTAG_START_TRANSACTION, "START TRANSACTION", false, false, false)
+PG_CMDTAG(CMDTAG_TRUNCATE_TABLE, "TRUNCATE TABLE", false, false, false)
+PG_CMDTAG(CMDTAG_UNLISTEN, "UNLISTEN", false, false, false)
+PG_CMDTAG(CMDTAG_UPDATE, "UPDATE", false, false, true)
+PG_CMDTAG(CMDTAG_VACUUM, "VACUUM", false, false, false)
diff --git a/src/include/tcop/deparse_utility.h b/src/include/tcop/deparse_utility.h
new file mode 100644
index 0000000..10c74ff
--- /dev/null
+++ b/src/include/tcop/deparse_utility.h
@@ -0,0 +1,108 @@
+/*-------------------------------------------------------------------------
+ *
+ * deparse_utility.h
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/tcop/deparse_utility.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DEPARSE_UTILITY_H
+#define DEPARSE_UTILITY_H
+
+#include "access/attnum.h"
+#include "catalog/objectaddress.h"
+#include "nodes/nodes.h"
+#include "utils/aclchk_internal.h"
+
+
+/*
+ * Support for keeping track of collected commands.
+ */
+typedef enum CollectedCommandType
+{
+ SCT_Simple,
+ SCT_AlterTable,
+ SCT_Grant,
+ SCT_AlterOpFamily,
+ SCT_AlterDefaultPrivileges,
+ SCT_CreateOpClass,
+ SCT_AlterTSConfig
+} CollectedCommandType;
+
+/*
+ * For ALTER TABLE commands, we keep a list of the subcommands therein.
+ */
+typedef struct CollectedATSubcmd
+{
+ ObjectAddress address; /* affected column, constraint, index, ... */
+ Node *parsetree;
+} CollectedATSubcmd;
+
+typedef struct CollectedCommand
+{
+ CollectedCommandType type;
+
+ bool in_extension;
+ Node *parsetree;
+
+ union
+ {
+ /* most commands */
+ struct
+ {
+ ObjectAddress address;
+ ObjectAddress secondaryObject;
+ } simple;
+
+ /* ALTER TABLE, and internal uses thereof */
+ struct
+ {
+ Oid objectId;
+ Oid classId;
+ List *subcmds;
+ } alterTable;
+
+ /* GRANT / REVOKE */
+ struct
+ {
+ InternalGrant *istmt;
+ } grant;
+
+ /* ALTER OPERATOR FAMILY */
+ struct
+ {
+ ObjectAddress address;
+ List *operators;
+ List *procedures;
+ } opfam;
+
+ /* CREATE OPERATOR CLASS */
+ struct
+ {
+ ObjectAddress address;
+ List *operators;
+ List *procedures;
+ } createopc;
+
+ /* ALTER TEXT SEARCH CONFIGURATION ADD/ALTER/DROP MAPPING */
+ struct
+ {
+ ObjectAddress address;
+ Oid *dictIds;
+ int ndicts;
+ } atscfg;
+
+ /* ALTER DEFAULT PRIVILEGES */
+ struct
+ {
+ ObjectType objtype;
+ } defprivs;
+ } d;
+
+ struct CollectedCommand *parent; /* when nested */
+} CollectedCommand;
+
+#endif /* DEPARSE_UTILITY_H */
diff --git a/src/include/tcop/dest.h b/src/include/tcop/dest.h
new file mode 100644
index 0000000..2e07f15
--- /dev/null
+++ b/src/include/tcop/dest.h
@@ -0,0 +1,149 @@
+/*-------------------------------------------------------------------------
+ *
+ * dest.h
+ * support for communication destinations
+ *
+ * Whenever the backend executes a query that returns tuples, the results
+ * have to go someplace. For example:
+ *
+ * - stdout is the destination only when we are running a
+ * standalone backend (no postmaster) and are returning results
+ * back to an interactive user.
+ *
+ * - a remote process is the destination when we are
+ * running a backend with a frontend and the frontend executes
+ * PQexec() or PQfn(). In this case, the results are sent
+ * to the frontend via the functions in backend/libpq.
+ *
+ * - DestNone is the destination when the system executes
+ * a query internally. The results are discarded.
+ *
+ * dest.c defines three functions that implement destination management:
+ *
+ * BeginCommand: initialize the destination at start of command.
+ * CreateDestReceiver: return a pointer to a struct of destination-specific
+ * receiver functions.
+ * EndCommand: clean up the destination at end of command.
+ *
+ * BeginCommand/EndCommand are executed once per received SQL query.
+ *
+ * CreateDestReceiver returns a receiver object appropriate to the specified
+ * destination. The executor, as well as utility statements that can return
+ * tuples, are passed the resulting DestReceiver* pointer. Each executor run
+ * or utility execution calls the receiver's rStartup method, then the
+ * receiveSlot method (zero or more times), then the rShutdown method.
+ * The same receiver object may be re-used multiple times; eventually it is
+ * destroyed by calling its rDestroy method.
+ *
+ * In some cases, receiver objects require additional parameters that must
+ * be passed to them after calling CreateDestReceiver. Since the set of
+ * parameters varies for different receiver types, this is not handled by
+ * this module, but by direct calls from the calling code to receiver type
+ * specific functions.
+ *
+ * The DestReceiver object returned by CreateDestReceiver may be a statically
+ * allocated object (for destination types that require no local state),
+ * in which case rDestroy is a no-op. Alternatively it can be a palloc'd
+ * object that has DestReceiver as its first field and contains additional
+ * fields (see printtup.c for an example). These additional fields are then
+ * accessible to the DestReceiver functions by casting the DestReceiver*
+ * pointer passed to them. The palloc'd object is pfree'd by the rDestroy
+ * method. Note that the caller of CreateDestReceiver should take care to
+ * do so in a memory context that is long-lived enough for the receiver
+ * object not to disappear while still needed.
+ *
+ * Special provision: None_Receiver is a permanently available receiver
+ * object for the DestNone destination. This avoids useless creation/destroy
+ * calls in portal and cursor manipulations.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/tcop/dest.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DEST_H
+#define DEST_H
+
+#include "executor/tuptable.h"
+#include "tcop/cmdtag.h"
+
+
+/* buffer size to use for command completion tags */
+#define COMPLETION_TAG_BUFSIZE 64
+
+
+/* ----------------
+ * CommandDest is a simplistic means of identifying the desired
+ * destination. Someday this will probably need to be improved.
+ *
+ * Note: only the values DestNone, DestDebug, DestRemote are legal for the
+ * global variable whereToSendOutput. The other values may be used
+ * as the destination for individual commands.
+ * ----------------
+ */
+typedef enum
+{
+ DestNone, /* results are discarded */
+ DestDebug, /* results go to debugging output */
+ DestRemote, /* results sent to frontend process */
+ DestRemoteExecute, /* sent to frontend, in Execute command */
+ DestRemoteSimple, /* sent to frontend, w/no catalog access */
+ DestSPI, /* results sent to SPI manager */
+ DestTuplestore, /* results sent to Tuplestore */
+ DestIntoRel, /* results sent to relation (SELECT INTO) */
+ DestCopyOut, /* results sent to COPY TO code */
+ DestSQLFunction, /* results sent to SQL-language func mgr */
+ DestTransientRel, /* results sent to transient relation */
+ DestTupleQueue /* results sent to tuple queue */
+} CommandDest;
+
+/* ----------------
+ * DestReceiver is a base type for destination-specific local state.
+ * In the simplest cases, there is no state info, just the function
+ * pointers that the executor must call.
+ *
+ * Note: the receiveSlot routine must be passed a slot containing a TupleDesc
+ * identical to the one given to the rStartup routine. It returns bool where
+ * a "true" value means "continue processing" and a "false" value means
+ * "stop early, just as if we'd reached the end of the scan".
+ * ----------------
+ */
+typedef struct _DestReceiver DestReceiver;
+
+struct _DestReceiver
+{
+ /* Called for each tuple to be output: */
+ bool (*receiveSlot) (TupleTableSlot *slot,
+ DestReceiver *self);
+ /* Per-executor-run initialization and shutdown: */
+ void (*rStartup) (DestReceiver *self,
+ int operation,
+ TupleDesc typeinfo);
+ void (*rShutdown) (DestReceiver *self);
+ /* Destroy the receiver object itself (if dynamically allocated) */
+ void (*rDestroy) (DestReceiver *self);
+ /* CommandDest code for this receiver */
+ CommandDest mydest;
+ /* Private fields might appear beyond this point... */
+};
+
+extern PGDLLIMPORT DestReceiver *None_Receiver; /* permanent receiver for
+ * DestNone */
+
+/* The primary destination management functions */
+
+extern void BeginCommand(CommandTag commandTag, CommandDest dest);
+extern DestReceiver *CreateDestReceiver(CommandDest dest);
+extern void EndCommand(const QueryCompletion *qc, CommandDest dest,
+ bool force_undecorated_output);
+extern void EndReplicationCommand(const char *commandTag);
+
+/* Additional functions that go with destination management, more or less. */
+
+extern void NullCommand(CommandDest dest);
+extern void ReadyForQuery(CommandDest dest);
+
+#endif /* DEST_H */
diff --git a/src/include/tcop/fastpath.h b/src/include/tcop/fastpath.h
new file mode 100644
index 0000000..3bb992c
--- /dev/null
+++ b/src/include/tcop/fastpath.h
@@ -0,0 +1,21 @@
+/*-------------------------------------------------------------------------
+ *
+ * fastpath.h
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/tcop/fastpath.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FASTPATH_H
+#define FASTPATH_H
+
+#include "lib/stringinfo.h"
+
+extern int GetOldFunctionMessage(StringInfo buf);
+extern void HandleFunctionRequest(StringInfo msgBuf);
+
+#endif /* FASTPATH_H */
diff --git a/src/include/tcop/pquery.h b/src/include/tcop/pquery.h
new file mode 100644
index 0000000..1385a00
--- /dev/null
+++ b/src/include/tcop/pquery.h
@@ -0,0 +1,51 @@
+/*-------------------------------------------------------------------------
+ *
+ * pquery.h
+ * prototypes for pquery.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/tcop/pquery.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PQUERY_H
+#define PQUERY_H
+
+#include "nodes/parsenodes.h"
+#include "utils/portal.h"
+
+struct PlannedStmt; /* avoid including plannodes.h here */
+
+
+extern PGDLLIMPORT Portal ActivePortal;
+
+
+extern PortalStrategy ChoosePortalStrategy(List *stmts);
+
+extern List *FetchPortalTargetList(Portal portal);
+
+extern List *FetchStatementTargetList(Node *stmt);
+
+extern void PortalStart(Portal portal, ParamListInfo params,
+ int eflags, Snapshot snapshot);
+
+extern void PortalSetResultFormat(Portal portal, int nFormats,
+ int16 *formats);
+
+extern bool PortalRun(Portal portal, long count, bool isTopLevel,
+ bool run_once, DestReceiver *dest, DestReceiver *altdest,
+ QueryCompletion *qc);
+
+extern uint64 PortalRunFetch(Portal portal,
+ FetchDirection fdirection,
+ long count,
+ DestReceiver *dest);
+
+extern bool PlannedStmtRequiresSnapshot(struct PlannedStmt *pstmt);
+
+extern void EnsurePortalSnapshotExists(void);
+
+#endif /* PQUERY_H */
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
new file mode 100644
index 0000000..bd30607
--- /dev/null
+++ b/src/include/tcop/tcopprot.h
@@ -0,0 +1,89 @@
+/*-------------------------------------------------------------------------
+ *
+ * tcopprot.h
+ * prototypes for postgres.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/tcop/tcopprot.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TCOPPROT_H
+#define TCOPPROT_H
+
+#include "nodes/params.h"
+#include "nodes/parsenodes.h"
+#include "nodes/plannodes.h"
+#include "storage/procsignal.h"
+#include "utils/guc.h"
+#include "utils/queryenvironment.h"
+
+
+/* Required daylight between max_stack_depth and the kernel limit, in bytes */
+#define STACK_DEPTH_SLOP (512 * 1024L)
+
+extern CommandDest whereToSendOutput;
+extern PGDLLIMPORT const char *debug_query_string;
+extern int max_stack_depth;
+extern int PostAuthDelay;
+
+/* GUC-configurable parameters */
+
+typedef enum
+{
+ LOGSTMT_NONE, /* log no statements */
+ LOGSTMT_DDL, /* log data definition statements */
+ LOGSTMT_MOD, /* log modification statements, plus DDL */
+ LOGSTMT_ALL /* log all statements */
+} LogStmtLevel;
+
+extern PGDLLIMPORT int log_statement;
+
+extern List *pg_parse_query(const char *query_string);
+extern List *pg_analyze_and_rewrite(RawStmt *parsetree,
+ const char *query_string,
+ Oid *paramTypes, int numParams,
+ QueryEnvironment *queryEnv);
+extern List *pg_analyze_and_rewrite_params(RawStmt *parsetree,
+ const char *query_string,
+ ParserSetupHook parserSetup,
+ void *parserSetupArg,
+ QueryEnvironment *queryEnv);
+extern PlannedStmt *pg_plan_query(Query *querytree, const char *query_string,
+ int cursorOptions,
+ ParamListInfo boundParams);
+extern List *pg_plan_queries(List *querytrees, const char *query_string,
+ int cursorOptions,
+ ParamListInfo boundParams);
+
+extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
+extern void assign_max_stack_depth(int newval, void *extra);
+
+extern void die(SIGNAL_ARGS);
+extern void quickdie(SIGNAL_ARGS) pg_attribute_noreturn();
+extern void StatementCancelHandler(SIGNAL_ARGS);
+extern void FloatExceptionHandler(SIGNAL_ARGS) pg_attribute_noreturn();
+extern void RecoveryConflictInterrupt(ProcSignalReason reason); /* called from SIGUSR1
+ * handler */
+extern void ProcessClientReadInterrupt(bool blocked);
+extern void ProcessClientWriteInterrupt(bool blocked);
+
+extern void process_postgres_switches(int argc, char *argv[],
+ GucContext ctx, const char **dbname);
+extern void PostgresMain(int argc, char *argv[],
+ const char *dbname,
+ const char *username) pg_attribute_noreturn();
+extern long get_stack_depth_rlimit(void);
+extern void ResetUsage(void);
+extern void ShowUsage(const char *title);
+extern int check_log_duration(char *msec_str, bool was_logged);
+extern void set_debug_options(int debug_flag,
+ GucContext context, GucSource source);
+extern bool set_plan_disabling_options(const char *arg,
+ GucContext context, GucSource source);
+extern const char *get_stats_option_name(const char *arg);
+
+#endif /* TCOPPROT_H */
diff --git a/src/include/tcop/utility.h b/src/include/tcop/utility.h
new file mode 100644
index 0000000..4aec19a
--- /dev/null
+++ b/src/include/tcop/utility.h
@@ -0,0 +1,108 @@
+/*-------------------------------------------------------------------------
+ *
+ * utility.h
+ * prototypes for utility.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/tcop/utility.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef UTILITY_H
+#define UTILITY_H
+
+#include "tcop/cmdtag.h"
+#include "tcop/tcopprot.h"
+
+typedef enum
+{
+ PROCESS_UTILITY_TOPLEVEL, /* toplevel interactive command */
+ PROCESS_UTILITY_QUERY, /* a complete query, but not toplevel */
+ PROCESS_UTILITY_QUERY_NONATOMIC, /* a complete query, nonatomic
+ * execution context */
+ PROCESS_UTILITY_SUBCOMMAND /* a portion of a query */
+} ProcessUtilityContext;
+
+/* Info needed when recursing from ALTER TABLE */
+typedef struct AlterTableUtilityContext
+{
+ PlannedStmt *pstmt; /* PlannedStmt for outer ALTER TABLE command */
+ const char *queryString; /* its query string */
+ Oid relid; /* OID of ALTER's target table */
+ ParamListInfo params; /* any parameters available to ALTER TABLE */
+ QueryEnvironment *queryEnv; /* execution environment for ALTER TABLE */
+} AlterTableUtilityContext;
+
+/*
+ * These constants are used to describe the extent to which a particular
+ * command is read-only.
+ *
+ * COMMAND_OK_IN_READ_ONLY_TXN means that the command is permissible even when
+ * XactReadOnly is set. This bit should be set for commands that don't change
+ * the state of the database (data or schema) in a way that would affect the
+ * output of pg_dump.
+ *
+ * COMMAND_OK_IN_PARALLEL_MODE means that the command is permissible even
+ * when in parallel mode. Writing tuples is forbidden, as is anything that
+ * might confuse cooperating processes.
+ *
+ * COMMAND_OK_IN_RECOVERY means that the command is permissible even when in
+ * recovery. It can't write WAL, nor can it do things that would imperil
+ * replay of future WAL received from the master.
+ */
+#define COMMAND_OK_IN_READ_ONLY_TXN 0x0001
+#define COMMAND_OK_IN_PARALLEL_MODE 0x0002
+#define COMMAND_OK_IN_RECOVERY 0x0004
+
+/*
+ * We say that a command is strictly read-only if it is sufficiently read-only
+ * for all purposes. For clarity, we also have a constant for commands that are
+ * in no way read-only.
+ */
+#define COMMAND_IS_STRICTLY_READ_ONLY \
+ (COMMAND_OK_IN_READ_ONLY_TXN | COMMAND_OK_IN_RECOVERY | \
+ COMMAND_OK_IN_PARALLEL_MODE)
+#define COMMAND_IS_NOT_READ_ONLY 0
+
+/* Hook for plugins to get control in ProcessUtility() */
+typedef void (*ProcessUtility_hook_type) (PlannedStmt *pstmt,
+ const char *queryString, ProcessUtilityContext context,
+ ParamListInfo params,
+ QueryEnvironment *queryEnv,
+ DestReceiver *dest, QueryCompletion *qc);
+extern PGDLLIMPORT ProcessUtility_hook_type ProcessUtility_hook;
+
+extern void ProcessUtility(PlannedStmt *pstmt, const char *queryString,
+ ProcessUtilityContext context, ParamListInfo params,
+ QueryEnvironment *queryEnv,
+ DestReceiver *dest, QueryCompletion *qc);
+extern void standard_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
+ ProcessUtilityContext context, ParamListInfo params,
+ QueryEnvironment *queryEnv,
+ DestReceiver *dest, QueryCompletion *qc);
+
+extern void ProcessUtilityForAlterTable(Node *stmt,
+ AlterTableUtilityContext *context);
+
+extern bool UtilityReturnsTuples(Node *parsetree);
+
+extern TupleDesc UtilityTupleDescriptor(Node *parsetree);
+
+extern Query *UtilityContainsQuery(Node *parsetree);
+
+extern CommandTag CreateCommandTag(Node *parsetree);
+
+static inline const char *
+CreateCommandName(Node *parsetree)
+{
+ return GetCommandTagName(CreateCommandTag(parsetree));
+}
+
+extern LogStmtLevel GetCommandLogLevel(Node *parsetree);
+
+extern bool CommandIsReadOnly(PlannedStmt *pstmt);
+
+#endif /* UTILITY_H */
diff --git a/src/include/tsearch/dicts/regis.h b/src/include/tsearch/dicts/regis.h
new file mode 100644
index 0000000..014a409
--- /dev/null
+++ b/src/include/tsearch/dicts/regis.h
@@ -0,0 +1,49 @@
+/*-------------------------------------------------------------------------
+ *
+ * regis.h
+ *
+ * Declarations for fast regex subset, used by ISpell
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ *
+ * src/include/tsearch/dicts/regis.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef __REGIS_H__
+#define __REGIS_H__
+
+typedef struct RegisNode
+{
+ uint32
+ type:2,
+ len:16,
+ unused:14;
+ struct RegisNode *next;
+ unsigned char data[FLEXIBLE_ARRAY_MEMBER];
+} RegisNode;
+
+#define RNHDRSZ (offsetof(RegisNode,data))
+
+#define RSF_ONEOF 1
+#define RSF_NONEOF 2
+
+typedef struct Regis
+{
+ RegisNode *node;
+ uint32
+ issuffix:1,
+ nchar:16,
+ unused:15;
+} Regis;
+
+bool RS_isRegis(const char *str);
+
+void RS_compile(Regis *r, bool issuffix, const char *str);
+void RS_free(Regis *r);
+
+/*returns true if matches */
+bool RS_execute(Regis *r, char *str);
+
+#endif
diff --git a/src/include/tsearch/dicts/spell.h b/src/include/tsearch/dicts/spell.h
new file mode 100644
index 0000000..9ec08be
--- /dev/null
+++ b/src/include/tsearch/dicts/spell.h
@@ -0,0 +1,247 @@
+/*-------------------------------------------------------------------------
+ *
+ * spell.h
+ *
+ * Declarations for ISpell dictionary
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ *
+ * src/include/tsearch/dicts/spell.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef __SPELL_H__
+#define __SPELL_H__
+
+#include "regex/regex.h"
+#include "tsearch/dicts/regis.h"
+#include "tsearch/ts_public.h"
+
+/*
+ * SPNode and SPNodeData are used to represent prefix tree (Trie) to store
+ * a words list.
+ */
+struct SPNode;
+
+typedef struct
+{
+ uint32 val:8,
+ isword:1,
+ /* Stores compound flags listed below */
+ compoundflag:4,
+ /* Reference to an entry of the AffixData field */
+ affix:19;
+ struct SPNode *node;
+} SPNodeData;
+
+/*
+ * Names of FF_ are correlated with Hunspell options in affix file
+ * http://hunspell.sourceforge.net/
+ */
+#define FF_COMPOUNDONLY 0x01
+#define FF_COMPOUNDBEGIN 0x02
+#define FF_COMPOUNDMIDDLE 0x04
+#define FF_COMPOUNDLAST 0x08
+#define FF_COMPOUNDFLAG ( FF_COMPOUNDBEGIN | FF_COMPOUNDMIDDLE | \
+ FF_COMPOUNDLAST )
+#define FF_COMPOUNDFLAGMASK 0x0f
+
+typedef struct SPNode
+{
+ uint32 length;
+ SPNodeData data[FLEXIBLE_ARRAY_MEMBER];
+} SPNode;
+
+#define SPNHDRSZ (offsetof(SPNode,data))
+
+/*
+ * Represents an entry in a words list.
+ */
+typedef struct spell_struct
+{
+ union
+ {
+ /*
+ * flag is filled in by NIImportDictionary(). After
+ * NISortDictionary(), d is used instead of flag.
+ */
+ char *flag;
+ /* d is used in mkSPNode() */
+ struct
+ {
+ /* Reference to an entry of the AffixData field */
+ int affix;
+ /* Length of the word */
+ int len;
+ } d;
+ } p;
+ char word[FLEXIBLE_ARRAY_MEMBER];
+} SPELL;
+
+#define SPELLHDRSZ (offsetof(SPELL, word))
+
+/*
+ * If an affix uses a regex, we have to store that separately in a struct
+ * that won't move around when arrays of affixes are enlarged or sorted.
+ * This is so that it can be found to be cleaned up at context destruction.
+ */
+typedef struct aff_regex_struct
+{
+ regex_t regex;
+ MemoryContextCallback mcallback;
+} aff_regex_struct;
+
+/*
+ * Represents an entry in an affix list.
+ */
+typedef struct aff_struct
+{
+ char *flag;
+ /* FF_SUFFIX or FF_PREFIX */
+ uint32 type:1,
+ flagflags:7,
+ issimple:1,
+ isregis:1,
+ replen:14;
+ char *find;
+ char *repl;
+ union
+ {
+ aff_regex_struct *pregex;
+ Regis regis;
+ } reg;
+} AFFIX;
+
+/*
+ * affixes use dictionary flags too
+ */
+#define FF_COMPOUNDPERMITFLAG 0x10
+#define FF_COMPOUNDFORBIDFLAG 0x20
+#define FF_CROSSPRODUCT 0x40
+
+/*
+ * Don't change the order of these. Initialization sorts by these,
+ * and expects prefixes to come first after sorting.
+ */
+#define FF_SUFFIX 1
+#define FF_PREFIX 0
+
+/*
+ * AffixNode and AffixNodeData are used to represent prefix tree (Trie) to store
+ * an affix list.
+ */
+struct AffixNode;
+
+typedef struct
+{
+ uint32 val:8,
+ naff:24;
+ AFFIX **aff;
+ struct AffixNode *node;
+} AffixNodeData;
+
+typedef struct AffixNode
+{
+ uint32 isvoid:1,
+ length:31;
+ AffixNodeData data[FLEXIBLE_ARRAY_MEMBER];
+} AffixNode;
+
+#define ANHRDSZ (offsetof(AffixNode, data))
+
+typedef struct
+{
+ char *affix;
+ int len;
+ bool issuffix;
+} CMPDAffix;
+
+/*
+ * Type of encoding affix flags in Hunspell dictionaries
+ */
+typedef enum
+{
+ FM_CHAR, /* one character (like ispell) */
+ FM_LONG, /* two characters */
+ FM_NUM /* number, >= 0 and < 65536 */
+} FlagMode;
+
+/*
+ * Structure to store Hunspell options. Flag representation depends on flag
+ * type. These flags are about support of compound words.
+ */
+typedef struct CompoundAffixFlag
+{
+ union
+ {
+ /* Flag name if flagMode is FM_CHAR or FM_LONG */
+ char *s;
+ /* Flag name if flagMode is FM_NUM */
+ uint32 i;
+ } flag;
+ /* we don't have a bsearch_arg version, so, copy FlagMode */
+ FlagMode flagMode;
+ uint32 value;
+} CompoundAffixFlag;
+
+#define FLAGNUM_MAXSIZE (1 << 16)
+
+typedef struct
+{
+ int maffixes;
+ int naffixes;
+ AFFIX *Affix;
+
+ AffixNode *Suffix;
+ AffixNode *Prefix;
+
+ SPNode *Dictionary;
+ /* Array of sets of affixes */
+ char **AffixData;
+ int lenAffixData;
+ int nAffixData;
+ bool useFlagAliases;
+
+ CMPDAffix *CompoundAffix;
+
+ bool usecompound;
+ FlagMode flagMode;
+
+ /*
+ * All follow fields are actually needed only for initialization
+ */
+
+ /* Array of Hunspell options in affix file */
+ CompoundAffixFlag *CompoundAffixFlags;
+ /* number of entries in CompoundAffixFlags array */
+ int nCompoundAffixFlag;
+ /* allocated length of CompoundAffixFlags array */
+ int mCompoundAffixFlag;
+
+ /*
+ * Remaining fields are only used during dictionary construction; they are
+ * set up by NIStartBuild and cleared by NIFinishBuild.
+ */
+ MemoryContext buildCxt; /* temp context for construction */
+
+ /* Temporary array of all words in the dict file */
+ SPELL **Spell;
+ int nspell; /* number of valid entries in Spell array */
+ int mspell; /* allocated length of Spell array */
+
+ /* These are used to allocate "compact" data without palloc overhead */
+ char *firstfree; /* first free address (always maxaligned) */
+ size_t avail; /* free space remaining at firstfree */
+} IspellDict;
+
+extern TSLexeme *NINormalizeWord(IspellDict *Conf, char *word);
+
+extern void NIStartBuild(IspellDict *Conf);
+extern void NIImportAffixes(IspellDict *Conf, const char *filename);
+extern void NIImportDictionary(IspellDict *Conf, const char *filename);
+extern void NISortDictionary(IspellDict *Conf);
+extern void NISortAffixes(IspellDict *Conf);
+extern void NIFinishBuild(IspellDict *Conf);
+
+#endif
diff --git a/src/include/tsearch/ts_cache.h b/src/include/tsearch/ts_cache.h
new file mode 100644
index 0000000..9149796
--- /dev/null
+++ b/src/include/tsearch/ts_cache.h
@@ -0,0 +1,98 @@
+/*-------------------------------------------------------------------------
+ *
+ * ts_cache.h
+ * Tsearch related object caches.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/tsearch/ts_cache.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TS_CACHE_H
+#define TS_CACHE_H
+
+#include "utils/guc.h"
+
+
+/*
+ * All TS*CacheEntry structs must share this common header
+ * (see InvalidateTSCacheCallBack)
+ */
+typedef struct TSAnyCacheEntry
+{
+ Oid objId;
+ bool isvalid;
+} TSAnyCacheEntry;
+
+
+typedef struct TSParserCacheEntry
+{
+ /* prsId is the hash lookup key and MUST BE FIRST */
+ Oid prsId; /* OID of the parser */
+ bool isvalid;
+
+ Oid startOid;
+ Oid tokenOid;
+ Oid endOid;
+ Oid headlineOid;
+ Oid lextypeOid;
+
+ /*
+ * Pre-set-up fmgr call of most needed parser's methods
+ */
+ FmgrInfo prsstart;
+ FmgrInfo prstoken;
+ FmgrInfo prsend;
+ FmgrInfo prsheadline;
+} TSParserCacheEntry;
+
+typedef struct TSDictionaryCacheEntry
+{
+ /* dictId is the hash lookup key and MUST BE FIRST */
+ Oid dictId;
+ bool isvalid;
+
+ /* most frequent fmgr call */
+ Oid lexizeOid;
+ FmgrInfo lexize;
+
+ MemoryContext dictCtx; /* memory context to store private data */
+ void *dictData;
+} TSDictionaryCacheEntry;
+
+typedef struct
+{
+ int len;
+ Oid *dictIds;
+} ListDictionary;
+
+typedef struct
+{
+ /* cfgId is the hash lookup key and MUST BE FIRST */
+ Oid cfgId;
+ bool isvalid;
+
+ Oid prsId;
+
+ int lenmap;
+ ListDictionary *map;
+} TSConfigCacheEntry;
+
+
+/*
+ * GUC variable for current configuration
+ */
+extern char *TSCurrentConfig;
+
+
+extern TSParserCacheEntry *lookup_ts_parser_cache(Oid prsId);
+extern TSDictionaryCacheEntry *lookup_ts_dictionary_cache(Oid dictId);
+extern TSConfigCacheEntry *lookup_ts_config_cache(Oid cfgId);
+
+extern Oid getTSCurrentConfig(bool emitError);
+extern bool check_TSCurrentConfig(char **newval, void **extra, GucSource source);
+extern void assign_TSCurrentConfig(const char *newval, void *extra);
+
+#endif /* TS_CACHE_H */
diff --git a/src/include/tsearch/ts_locale.h b/src/include/tsearch/ts_locale.h
new file mode 100644
index 0000000..cc4bd9a
--- /dev/null
+++ b/src/include/tsearch/ts_locale.h
@@ -0,0 +1,62 @@
+/*-------------------------------------------------------------------------
+ *
+ * ts_locale.h
+ * locale compatibility layer for tsearch
+ *
+ * Copyright (c) 1998-2020, PostgreSQL Global Development Group
+ *
+ * src/include/tsearch/ts_locale.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef __TSLOCALE_H__
+#define __TSLOCALE_H__
+
+#include <ctype.h>
+#include <limits.h>
+
+#include "mb/pg_wchar.h"
+#include "utils/pg_locale.h"
+
+/*
+ * towlower() and friends should be in <wctype.h>, but some pre-C99 systems
+ * declare them in <wchar.h>, so include that too.
+ */
+#include <wchar.h>
+#ifdef HAVE_WCTYPE_H
+#include <wctype.h>
+#endif
+
+/* working state for tsearch_readline (should be a local var in caller) */
+typedef struct
+{
+ FILE *fp;
+ const char *filename;
+ int lineno;
+ char *curline;
+ ErrorContextCallback cb;
+} tsearch_readline_state;
+
+#define TOUCHAR(x) (*((const unsigned char *) (x)))
+
+/* The second argument of t_iseq() must be a plain ASCII character */
+#define t_iseq(x,c) (TOUCHAR(x) == (unsigned char) (c))
+
+#define COPYCHAR(d,s) memcpy(d, s, pg_mblen(s))
+
+extern int t_isdigit(const char *ptr);
+extern int t_isspace(const char *ptr);
+extern int t_isalpha(const char *ptr);
+extern int t_isprint(const char *ptr);
+
+extern char *lowerstr(const char *str);
+extern char *lowerstr_with_len(const char *str, int len);
+
+extern bool tsearch_readline_begin(tsearch_readline_state *stp,
+ const char *filename);
+extern char *tsearch_readline(tsearch_readline_state *stp);
+extern void tsearch_readline_end(tsearch_readline_state *stp);
+
+extern char *t_readline(FILE *fp);
+
+#endif /* __TSLOCALE_H__ */
diff --git a/src/include/tsearch/ts_public.h b/src/include/tsearch/ts_public.h
new file mode 100644
index 0000000..63aca2b
--- /dev/null
+++ b/src/include/tsearch/ts_public.h
@@ -0,0 +1,132 @@
+/*-------------------------------------------------------------------------
+ *
+ * ts_public.h
+ * Public interface to various tsearch modules, such as
+ * parsers and dictionaries.
+ *
+ * Copyright (c) 1998-2020, PostgreSQL Global Development Group
+ *
+ * src/include/tsearch/ts_public.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _PG_TS_PUBLIC_H_
+#define _PG_TS_PUBLIC_H_
+
+#include "tsearch/ts_type.h"
+
+/*
+ * Parser's framework
+ */
+
+/*
+ * returning type for prslextype method of parser
+ */
+typedef struct
+{
+ int lexid;
+ char *alias;
+ char *descr;
+} LexDescr;
+
+/*
+ * Interface to headline generator
+ */
+typedef struct
+{
+ uint32 selected:1,
+ in:1,
+ replace:1,
+ repeated:1,
+ skip:1,
+ unused:3,
+ type:8,
+ len:16;
+ WordEntryPos pos;
+ char *word;
+ QueryOperand *item;
+} HeadlineWordEntry;
+
+typedef struct
+{
+ HeadlineWordEntry *words;
+ int32 lenwords;
+ int32 curwords;
+ int32 vectorpos; /* positions a-la tsvector */
+ char *startsel;
+ char *stopsel;
+ char *fragdelim;
+ int16 startsellen;
+ int16 stopsellen;
+ int16 fragdelimlen;
+} HeadlineParsedText;
+
+/*
+ * Common useful things for tsearch subsystem
+ */
+extern char *get_tsearch_config_filename(const char *basename,
+ const char *extension);
+
+/*
+ * Often useful stopword list management
+ */
+typedef struct
+{
+ int len;
+ char **stop;
+} StopList;
+
+extern void readstoplist(const char *fname, StopList *s,
+ char *(*wordop) (const char *));
+extern bool searchstoplist(StopList *s, char *key);
+
+/*
+ * Interface with dictionaries
+ */
+
+/* return struct for any lexize function */
+typedef struct
+{
+ /*----------
+ * Number of current variant of split word. For example the Norwegian
+ * word 'fotballklubber' has two variants to split: ( fotball, klubb )
+ * and ( fot, ball, klubb ). So, dictionary should return:
+ *
+ * nvariant lexeme
+ * 1 fotball
+ * 1 klubb
+ * 2 fot
+ * 2 ball
+ * 2 klubb
+ *
+ * In general, a TSLexeme will be considered to belong to the same split
+ * variant as the previous one if they have the same nvariant value.
+ * The exact values don't matter, only changes from one lexeme to next.
+ *----------
+ */
+ uint16 nvariant;
+
+ uint16 flags; /* See flag bits below */
+
+ char *lexeme; /* C string */
+} TSLexeme;
+
+/* Flag bits that can appear in TSLexeme.flags */
+#define TSL_ADDPOS 0x01
+#define TSL_PREFIX 0x02
+#define TSL_FILTER 0x04
+
+/*
+ * Struct for supporting complex dictionaries like thesaurus.
+ * 4th argument for dictlexize method is a pointer to this
+ */
+typedef struct
+{
+ bool isend; /* in: marks for lexize_info about text end is
+ * reached */
+ bool getnext; /* out: dict wants next lexeme */
+ void *private_state; /* internal dict state between calls with
+ * getnext == true */
+} DictSubState;
+
+#endif /* _PG_TS_PUBLIC_H_ */
diff --git a/src/include/tsearch/ts_type.h b/src/include/tsearch/ts_type.h
new file mode 100644
index 0000000..e7edca9
--- /dev/null
+++ b/src/include/tsearch/ts_type.h
@@ -0,0 +1,242 @@
+/*-------------------------------------------------------------------------
+ *
+ * ts_type.h
+ * Definitions for the tsvector and tsquery types
+ *
+ * Copyright (c) 1998-2020, PostgreSQL Global Development Group
+ *
+ * src/include/tsearch/ts_type.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _PG_TSTYPE_H_
+#define _PG_TSTYPE_H_
+
+#include "fmgr.h"
+#include "utils/memutils.h"
+
+
+/*
+ * TSVector type.
+ *
+ * Structure of tsvector datatype:
+ * 1) standard varlena header
+ * 2) int32 size - number of lexemes (WordEntry array entries)
+ * 3) Array of WordEntry - one per lexeme; must be sorted according to
+ * tsCompareString() (ie, memcmp of lexeme strings).
+ * WordEntry->pos gives the number of bytes from end of WordEntry
+ * array to start of lexeme's string, which is of length len.
+ * 4) Per-lexeme data storage:
+ * lexeme string (not null-terminated)
+ * if haspos is true:
+ * padding byte if necessary to make the position data 2-byte aligned
+ * uint16 number of positions that follow
+ * WordEntryPos[] positions
+ *
+ * The positions for each lexeme must be sorted.
+ *
+ * Note, tsvectorsend/recv believe that sizeof(WordEntry) == 4
+ */
+
+typedef struct
+{
+ uint32
+ haspos:1,
+ len:11, /* MAX 2Kb */
+ pos:20; /* MAX 1Mb */
+} WordEntry;
+
+#define MAXSTRLEN ( (1<<11) - 1)
+#define MAXSTRPOS ( (1<<20) - 1)
+
+extern int compareWordEntryPos(const void *a, const void *b);
+
+/*
+ * Equivalent to
+ * typedef struct {
+ * uint16
+ * weight:2,
+ * pos:14;
+ * }
+ */
+
+typedef uint16 WordEntryPos;
+
+typedef struct
+{
+ uint16 npos;
+ WordEntryPos pos[FLEXIBLE_ARRAY_MEMBER];
+} WordEntryPosVector;
+
+/* WordEntryPosVector with exactly 1 entry */
+typedef struct
+{
+ uint16 npos;
+ WordEntryPos pos[1];
+} WordEntryPosVector1;
+
+
+#define WEP_GETWEIGHT(x) ( (x) >> 14 )
+#define WEP_GETPOS(x) ( (x) & 0x3fff )
+
+#define WEP_SETWEIGHT(x,v) ( (x) = ( (v) << 14 ) | ( (x) & 0x3fff ) )
+#define WEP_SETPOS(x,v) ( (x) = ( (x) & 0xc000 ) | ( (v) & 0x3fff ) )
+
+#define MAXENTRYPOS (1<<14)
+#define MAXNUMPOS (256)
+#define LIMITPOS(x) ( ( (x) >= MAXENTRYPOS ) ? (MAXENTRYPOS-1) : (x) )
+
+/* This struct represents a complete tsvector datum */
+typedef struct
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ int32 size;
+ WordEntry entries[FLEXIBLE_ARRAY_MEMBER];
+ /* lexemes follow the entries[] array */
+} TSVectorData;
+
+typedef TSVectorData *TSVector;
+
+#define DATAHDRSIZE (offsetof(TSVectorData, entries))
+#define CALCDATASIZE(nentries, lenstr) (DATAHDRSIZE + (nentries) * sizeof(WordEntry) + (lenstr) )
+
+/* pointer to start of a tsvector's WordEntry array */
+#define ARRPTR(x) ( (x)->entries )
+
+/* pointer to start of a tsvector's lexeme storage */
+#define STRPTR(x) ( (char *) &(x)->entries[(x)->size] )
+
+#define _POSVECPTR(x, e) ((WordEntryPosVector *)(STRPTR(x) + SHORTALIGN((e)->pos + (e)->len)))
+#define POSDATALEN(x,e) ( ( (e)->haspos ) ? (_POSVECPTR(x,e)->npos) : 0 )
+#define POSDATAPTR(x,e) (_POSVECPTR(x,e)->pos)
+
+/*
+ * fmgr interface macros
+ */
+
+#define DatumGetTSVector(X) ((TSVector) PG_DETOAST_DATUM(X))
+#define DatumGetTSVectorCopy(X) ((TSVector) PG_DETOAST_DATUM_COPY(X))
+#define TSVectorGetDatum(X) PointerGetDatum(X)
+#define PG_GETARG_TSVECTOR(n) DatumGetTSVector(PG_GETARG_DATUM(n))
+#define PG_GETARG_TSVECTOR_COPY(n) DatumGetTSVectorCopy(PG_GETARG_DATUM(n))
+#define PG_RETURN_TSVECTOR(x) return TSVectorGetDatum(x)
+
+
+/*
+ * TSQuery
+ *
+ *
+ */
+
+typedef int8 QueryItemType;
+
+/* Valid values for QueryItemType: */
+#define QI_VAL 1
+#define QI_OPR 2
+#define QI_VALSTOP 3 /* This is only used in an intermediate stack
+ * representation in parse_tsquery. It's not a
+ * legal type elsewhere. */
+
+/*
+ * QueryItem is one node in tsquery - operator or operand.
+ */
+typedef struct
+{
+ QueryItemType type; /* operand or kind of operator (ts_tokentype) */
+ uint8 weight; /* weights of operand to search. It's a
+ * bitmask of allowed weights. if it =0 then
+ * any weight are allowed. Weights and bit
+ * map: A: 1<<3 B: 1<<2 C: 1<<1 D: 1<<0 */
+ bool prefix; /* true if it's a prefix search */
+ int32 valcrc; /* XXX: pg_crc32 would be a more appropriate
+ * data type, but we use comparisons to signed
+ * integers in the code. They would need to be
+ * changed as well. */
+
+ /* pointer to text value of operand, must correlate with WordEntry */
+ uint32
+ length:12,
+ distance:20;
+} QueryOperand;
+
+
+/*
+ * Legal values for QueryOperator.operator.
+ */
+#define OP_NOT 1
+#define OP_AND 2
+#define OP_OR 3
+#define OP_PHRASE 4 /* highest code, tsquery_cleanup.c */
+#define OP_COUNT 4
+
+extern const int tsearch_op_priority[OP_COUNT];
+
+/* get operation priority by its code*/
+#define OP_PRIORITY(x) ( tsearch_op_priority[(x) - 1] )
+/* get QueryOperator priority */
+#define QO_PRIORITY(x) OP_PRIORITY(((QueryOperator *) (x))->oper)
+
+typedef struct
+{
+ QueryItemType type;
+ int8 oper; /* see above */
+ int16 distance; /* distance between agrs for OP_PHRASE */
+ uint32 left; /* pointer to left operand. Right operand is
+ * item + 1, left operand is placed
+ * item+item->left */
+} QueryOperator;
+
+/*
+ * Note: TSQuery is 4-bytes aligned, so make sure there's no fields
+ * inside QueryItem requiring 8-byte alignment, like int64.
+ */
+typedef union
+{
+ QueryItemType type;
+ QueryOperator qoperator;
+ QueryOperand qoperand;
+} QueryItem;
+
+/*
+ * Storage:
+ * (len)(size)(array of QueryItem)(operands as '\0'-terminated c-strings)
+ */
+
+typedef struct
+{
+ int32 vl_len_; /* varlena header (do not touch directly!) */
+ int32 size; /* number of QueryItems */
+ char data[FLEXIBLE_ARRAY_MEMBER]; /* data starts here */
+} TSQueryData;
+
+typedef TSQueryData *TSQuery;
+
+#define HDRSIZETQ ( VARHDRSZ + sizeof(int32) )
+
+/* Computes the size of header and all QueryItems. size is the number of
+ * QueryItems, and lenofoperand is the total length of all operands
+ */
+#define COMPUTESIZE(size, lenofoperand) ( HDRSIZETQ + (size) * sizeof(QueryItem) + (lenofoperand) )
+#define TSQUERY_TOO_BIG(size, lenofoperand) \
+ ((size) > (MaxAllocSize - HDRSIZETQ - (lenofoperand)) / sizeof(QueryItem))
+
+/* Returns a pointer to the first QueryItem in a TSQuery */
+#define GETQUERY(x) ((QueryItem*)( (char*)(x)+HDRSIZETQ ))
+
+/* Returns a pointer to the beginning of operands in a TSQuery */
+#define GETOPERAND(x) ( (char*)GETQUERY(x) + ((TSQuery)(x))->size * sizeof(QueryItem) )
+
+/*
+ * fmgr interface macros
+ * Note, TSQuery type marked as plain storage, so it can't be toasted
+ * but PG_DETOAST_DATUM_COPY is used for simplicity
+ */
+
+#define DatumGetTSQuery(X) ((TSQuery) DatumGetPointer(X))
+#define DatumGetTSQueryCopy(X) ((TSQuery) PG_DETOAST_DATUM_COPY(X))
+#define TSQueryGetDatum(X) PointerGetDatum(X)
+#define PG_GETARG_TSQUERY(n) DatumGetTSQuery(PG_GETARG_DATUM(n))
+#define PG_GETARG_TSQUERY_COPY(n) DatumGetTSQueryCopy(PG_GETARG_DATUM(n))
+#define PG_RETURN_TSQUERY(x) return TSQueryGetDatum(x)
+
+#endif /* _PG_TSTYPE_H_ */
diff --git a/src/include/tsearch/ts_utils.h b/src/include/tsearch/ts_utils.h
new file mode 100644
index 0000000..a9b6f59
--- /dev/null
+++ b/src/include/tsearch/ts_utils.h
@@ -0,0 +1,266 @@
+/*-------------------------------------------------------------------------
+ *
+ * ts_utils.h
+ * helper utilities for tsearch
+ *
+ * Copyright (c) 1998-2020, PostgreSQL Global Development Group
+ *
+ * src/include/tsearch/ts_utils.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _PG_TS_UTILS_H_
+#define _PG_TS_UTILS_H_
+
+#include "nodes/pg_list.h"
+#include "tsearch/ts_public.h"
+#include "tsearch/ts_type.h"
+
+/*
+ * Common parse definitions for tsvector and tsquery
+ */
+
+/* tsvector parser support. */
+
+struct TSVectorParseStateData; /* opaque struct in tsvector_parser.c */
+typedef struct TSVectorParseStateData *TSVectorParseState;
+
+#define P_TSV_OPR_IS_DELIM (1 << 0)
+#define P_TSV_IS_TSQUERY (1 << 1)
+#define P_TSV_IS_WEB (1 << 2)
+
+extern TSVectorParseState init_tsvector_parser(char *input, int flags);
+extern void reset_tsvector_parser(TSVectorParseState state, char *input);
+extern bool gettoken_tsvector(TSVectorParseState state,
+ char **token, int *len,
+ WordEntryPos **pos, int *poslen,
+ char **endptr);
+extern void close_tsvector_parser(TSVectorParseState state);
+
+/* phrase operator begins with '<' */
+#define ISOPERATOR(x) \
+ ( pg_mblen(x) == 1 && ( *(x) == '!' || \
+ *(x) == '&' || \
+ *(x) == '|' || \
+ *(x) == '(' || \
+ *(x) == ')' || \
+ *(x) == '<' \
+ ) )
+
+/* parse_tsquery */
+
+struct TSQueryParserStateData; /* private in backend/utils/adt/tsquery.c */
+typedef struct TSQueryParserStateData *TSQueryParserState;
+
+typedef void (*PushFunction) (Datum opaque, TSQueryParserState state,
+ char *token, int tokenlen,
+ int16 tokenweights, /* bitmap as described in
+ * QueryOperand struct */
+ bool prefix);
+
+#define P_TSQ_PLAIN (1 << 0)
+#define P_TSQ_WEB (1 << 1)
+
+extern TSQuery parse_tsquery(char *buf,
+ PushFunction pushval,
+ Datum opaque,
+ int flags);
+
+/* Functions for use by PushFunction implementations */
+extern void pushValue(TSQueryParserState state,
+ char *strval, int lenval, int16 weight, bool prefix);
+extern void pushStop(TSQueryParserState state);
+extern void pushOperator(TSQueryParserState state, int8 oper, int16 distance);
+
+/*
+ * parse plain text and lexize words
+ */
+typedef struct
+{
+ uint16 len;
+ uint16 nvariant;
+ union
+ {
+ uint16 pos;
+
+ /*
+ * When apos array is used, apos[0] is the number of elements in the
+ * array (excluding apos[0]), and alen is the allocated size of the
+ * array.
+ */
+ uint16 *apos;
+ } pos;
+ uint16 flags; /* currently, only TSL_PREFIX */
+ char *word;
+ uint32 alen;
+} ParsedWord;
+
+typedef struct
+{
+ ParsedWord *words;
+ int32 lenwords;
+ int32 curwords;
+ int32 pos;
+} ParsedText;
+
+extern void parsetext(Oid cfgId, ParsedText *prs, char *buf, int32 buflen);
+
+/*
+ * headline framework, flow in common to generate:
+ * 1 parse text with hlparsetext
+ * 2 parser-specific function to find part
+ * 3 generateHeadline to generate result text
+ */
+
+extern void hlparsetext(Oid cfgId, HeadlineParsedText *prs, TSQuery query,
+ char *buf, int32 buflen);
+extern text *generateHeadline(HeadlineParsedText *prs);
+
+/*
+ * TSQuery execution support
+ *
+ * TS_execute() executes a tsquery against data that can be represented in
+ * various forms. The TSExecuteCallback callback function is called to check
+ * whether a given primitive tsquery value is matched in the data.
+ */
+
+/* TS_execute requires ternary logic to handle NOT with phrase matches */
+typedef enum
+{
+ TS_NO, /* definitely no match */
+ TS_YES, /* definitely does match */
+ TS_MAYBE /* can't verify match for lack of pos data */
+} TSTernaryValue;
+
+/*
+ * struct ExecPhraseData is passed to a TSExecuteCallback function if we need
+ * lexeme position data (because of a phrase-match operator in the tsquery).
+ * The callback should fill in position data when it returns TS_YES (success).
+ * If it cannot return position data, it should leave "data" unchanged and
+ * return TS_MAYBE. The caller of TS_execute() must then arrange for a later
+ * recheck with position data available.
+ *
+ * The reported lexeme positions must be sorted and unique. Callers must only
+ * consult the position bits of the pos array, ie, WEP_GETPOS(data->pos[i]).
+ * This allows the returned "pos" to point directly to the WordEntryPos
+ * portion of a tsvector value. If "allocated" is true then the pos array
+ * is palloc'd workspace and caller may free it when done.
+ *
+ * "negate" means that the pos array contains positions where the query does
+ * not match, rather than positions where it does. "width" is positive when
+ * the match is wider than one lexeme. Neither of these fields normally need
+ * to be touched by TSExecuteCallback functions; they are used for
+ * phrase-search processing within TS_execute.
+ *
+ * All fields of the ExecPhraseData struct are initially zeroed by caller.
+ */
+typedef struct ExecPhraseData
+{
+ int npos; /* number of positions reported */
+ bool allocated; /* pos points to palloc'd data? */
+ bool negate; /* positions are where query is NOT matched */
+ WordEntryPos *pos; /* ordered, non-duplicate lexeme positions */
+ int width; /* width of match in lexemes, less 1 */
+} ExecPhraseData;
+
+/*
+ * Signature for TSQuery lexeme check functions
+ *
+ * arg: opaque value passed through from caller of TS_execute
+ * val: lexeme to test for presence of
+ * data: to be filled with lexeme positions; NULL if position data not needed
+ *
+ * Return TS_YES if lexeme is present in data, TS_MAYBE if it might be
+ * present, TS_NO if it definitely is not present. If data is not NULL,
+ * it must be filled with lexeme positions if available. If position data
+ * is not available, leave *data as zeroes and return TS_MAYBE, never TS_YES.
+ */
+typedef TSTernaryValue (*TSExecuteCallback) (void *arg, QueryOperand *val,
+ ExecPhraseData *data);
+
+/*
+ * Flag bits for TS_execute
+ */
+#define TS_EXEC_EMPTY (0x00)
+/*
+ * If TS_EXEC_SKIP_NOT is set, then NOT sub-expressions are automatically
+ * evaluated to be true. This was formerly the default behavior. It's now
+ * deprecated because it tends to give silly answers, but some applications
+ * might still have a use for it.
+ */
+#define TS_EXEC_SKIP_NOT (0x01)
+/*
+ * If TS_EXEC_PHRASE_NO_POS is set, allow OP_PHRASE to be executed lossily
+ * in the absence of position information: a true result indicates that the
+ * phrase might be present. Without this flag, OP_PHRASE always returns
+ * false if lexeme position information is not available.
+ */
+#define TS_EXEC_PHRASE_NO_POS (0x02)
+
+extern bool TS_execute(QueryItem *curitem, void *arg, uint32 flags,
+ TSExecuteCallback chkcond);
+extern TSTernaryValue TS_execute_ternary(QueryItem *curitem, void *arg,
+ uint32 flags,
+ TSExecuteCallback chkcond);
+extern bool tsquery_requires_match(QueryItem *curitem);
+
+/*
+ * to_ts* - text transformation to tsvector, tsquery
+ */
+extern TSVector make_tsvector(ParsedText *prs);
+extern int32 tsCompareString(char *a, int lena, char *b, int lenb, bool prefix);
+
+/*
+ * Possible strategy numbers for indexes
+ * TSearchStrategyNumber - (tsvector|text) @@ tsquery
+ * TSearchWithClassStrategyNumber - tsvector @@@ tsquery
+ */
+#define TSearchStrategyNumber 1
+#define TSearchWithClassStrategyNumber 2
+
+/*
+ * TSQuery Utilities
+ */
+extern QueryItem *clean_NOT(QueryItem *ptr, int32 *len);
+extern TSQuery cleanup_tsquery_stopwords(TSQuery in);
+
+typedef struct QTNode
+{
+ QueryItem *valnode;
+ uint32 flags;
+ int32 nchild;
+ char *word;
+ uint32 sign;
+ struct QTNode **child;
+} QTNode;
+
+/* bits in QTNode.flags */
+#define QTN_NEEDFREE 0x01
+#define QTN_NOCHANGE 0x02
+#define QTN_WORDFREE 0x04
+
+typedef uint64 TSQuerySign;
+
+#define TSQS_SIGLEN (sizeof(TSQuerySign)*BITS_PER_BYTE)
+
+#define TSQuerySignGetDatum(X) Int64GetDatum((int64) (X))
+#define DatumGetTSQuerySign(X) ((TSQuerySign) DatumGetInt64(X))
+#define PG_RETURN_TSQUERYSIGN(X) return TSQuerySignGetDatum(X)
+#define PG_GETARG_TSQUERYSIGN(n) DatumGetTSQuerySign(PG_GETARG_DATUM(n))
+
+
+extern QTNode *QT2QTN(QueryItem *in, char *operand);
+extern TSQuery QTN2QT(QTNode *in);
+extern void QTNFree(QTNode *in);
+extern void QTNSort(QTNode *in);
+extern void QTNTernary(QTNode *in);
+extern void QTNBinary(QTNode *in);
+extern int QTNodeCompare(QTNode *an, QTNode *bn);
+extern QTNode *QTNCopy(QTNode *in);
+extern void QTNClearFlags(QTNode *in, uint32 flags);
+extern bool QTNEq(QTNode *a, QTNode *b);
+extern TSQuerySign makeTSQuerySign(TSQuery a);
+extern QTNode *findsubquery(QTNode *root, QTNode *ex, QTNode *subs,
+ bool *isfind);
+
+#endif /* _PG_TS_UTILS_H_ */
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 */
diff --git a/src/include/windowapi.h b/src/include/windowapi.h
new file mode 100644
index 0000000..e8c9fc5
--- /dev/null
+++ b/src/include/windowapi.h
@@ -0,0 +1,64 @@
+/*-------------------------------------------------------------------------
+ *
+ * windowapi.h
+ * API for window functions to extract data from their window
+ *
+ * A window function does not receive its arguments in the normal way
+ * (and therefore the concept of strictness is irrelevant). Instead it
+ * receives a "WindowObject", which it can fetch with PG_WINDOW_OBJECT()
+ * (note V1 calling convention must be used). Correct call context can
+ * be tested with WindowObjectIsValid(). Although argument values are
+ * not passed, the call is correctly set up so that PG_NARGS() can be
+ * used and argument type information can be obtained with
+ * get_fn_expr_argtype(), get_fn_expr_arg_stable(), etc.
+ *
+ * Operations on the WindowObject allow the window function to find out
+ * the current row number, total number of rows in the partition, etc
+ * and to evaluate its argument expression(s) at various rows in the
+ * window partition. See the header comments for each WindowObject API
+ * function in nodeWindowAgg.c for details.
+ *
+ *
+ * Portions Copyright (c) 2000-2020, PostgreSQL Global Development Group
+ *
+ * src/include/windowapi.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef WINDOWAPI_H
+#define WINDOWAPI_H
+
+/* values of "seektype" */
+#define WINDOW_SEEK_CURRENT 0
+#define WINDOW_SEEK_HEAD 1
+#define WINDOW_SEEK_TAIL 2
+
+/* this struct is private in nodeWindowAgg.c */
+typedef struct WindowObjectData *WindowObject;
+
+#define PG_WINDOW_OBJECT() ((WindowObject) fcinfo->context)
+
+#define WindowObjectIsValid(winobj) \
+ ((winobj) != NULL && IsA(winobj, WindowObjectData))
+
+extern void *WinGetPartitionLocalMemory(WindowObject winobj, Size sz);
+
+extern int64 WinGetCurrentPosition(WindowObject winobj);
+extern int64 WinGetPartitionRowCount(WindowObject winobj);
+
+extern void WinSetMarkPosition(WindowObject winobj, int64 markpos);
+
+extern bool WinRowsArePeers(WindowObject winobj, int64 pos1, int64 pos2);
+
+extern Datum WinGetFuncArgInPartition(WindowObject winobj, int argno,
+ int relpos, int seektype, bool set_mark,
+ bool *isnull, bool *isout);
+
+extern Datum WinGetFuncArgInFrame(WindowObject winobj, int argno,
+ int relpos, int seektype, bool set_mark,
+ bool *isnull, bool *isout);
+
+extern Datum WinGetFuncArgCurrent(WindowObject winobj, int argno,
+ bool *isnull);
+
+#endif /* WINDOWAPI_H */