v5-0001-Implement-oid8-data-type.patch
text/x-diff
Filename: v5-0001-Implement-oid8-data-type.patch
Type: text/x-diff
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v5-0001
Subject: Implement oid8 data type
| File | + | − |
|---|---|---|
| doc/src/sgml/datatype.sgml | 11 | 0 |
| doc/src/sgml/func/func-aggregate.sgml | 4 | 4 |
| src/backend/access/nbtree/nbtcompare.c | 82 | 0 |
| src/backend/bootstrap/bootstrap.c | 2 | 0 |
| src/backend/utils/adt/int8.c | 8 | 0 |
| src/backend/utils/adt/Makefile | 1 | 0 |
| src/backend/utils/adt/meson.build | 1 | 0 |
| src/backend/utils/adt/oid8.c | 171 | 0 |
| src/fe_utils/print.c | 1 | 0 |
| src/include/catalog/pg_aggregate.dat | 6 | 0 |
| src/include/catalog/pg_amop.dat | 23 | 0 |
| src/include/catalog/pg_amproc.dat | 12 | 0 |
| src/include/catalog/pg_cast.dat | 14 | 0 |
| src/include/catalog/pg_opclass.dat | 4 | 0 |
| src/include/catalog/pg_operator.dat | 26 | 0 |
| src/include/catalog/pg_opfamily.dat | 4 | 0 |
| src/include/catalog/pg_proc.dat | 64 | 0 |
| src/include/catalog/pg_type.dat | 5 | 0 |
| src/include/c.h | 10 | 1 |
| src/include/fmgr.h | 2 | 0 |
| src/include/postgres_ext.h | 0 | 1 |
| src/include/postgres.h | 20 | 0 |
| src/test/regress/expected/oid8.out | 196 | 0 |
| src/test/regress/expected/oid8.sql | 0 | 0 |
| src/test/regress/expected/opr_sanity.out | 7 | 0 |
| src/test/regress/expected/type_sanity.out | 1 | 0 |
| src/test/regress/parallel_schedule | 1 | 1 |
| src/test/regress/sql/oid8.sql | 57 | 0 |
| src/test/regress/sql/type_sanity.sql | 1 | 0 |
From 03ee1e96425f885348617f244037c1e9e9a4675b Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Thu, 14 Aug 2025 11:03:17 +0900
Subject: [PATCH v5 01/15] Implement oid8 data type
This new identifier type will be used for 8-byte TOAST values, and can
be useful for other purposes, not yet defined as of writing this patch.
The following operators are added for this data type:
- Casts with integer types and OID.
- btree and hash operators
- min/max functions.
- Tests and documentation.
XXX: Requires catversion bump.
---
src/include/c.h | 11 +-
src/include/catalog/pg_aggregate.dat | 6 +
src/include/catalog/pg_amop.dat | 23 +++
src/include/catalog/pg_amproc.dat | 12 ++
src/include/catalog/pg_cast.dat | 14 ++
src/include/catalog/pg_opclass.dat | 4 +
src/include/catalog/pg_operator.dat | 26 +++
src/include/catalog/pg_opfamily.dat | 4 +
src/include/catalog/pg_proc.dat | 64 +++++++
src/include/catalog/pg_type.dat | 5 +
src/include/fmgr.h | 2 +
src/include/postgres.h | 20 +++
src/include/postgres_ext.h | 1 -
src/backend/access/nbtree/nbtcompare.c | 82 +++++++++
src/backend/bootstrap/bootstrap.c | 2 +
src/backend/utils/adt/Makefile | 1 +
src/backend/utils/adt/int8.c | 8 +
src/backend/utils/adt/meson.build | 1 +
src/backend/utils/adt/oid8.c | 171 +++++++++++++++++++
src/fe_utils/print.c | 1 +
src/test/regress/expected/oid8.out | 196 ++++++++++++++++++++++
src/test/regress/expected/oid8.sql | 0
src/test/regress/expected/opr_sanity.out | 7 +
src/test/regress/expected/type_sanity.out | 1 +
src/test/regress/parallel_schedule | 2 +-
src/test/regress/sql/oid8.sql | 57 +++++++
src/test/regress/sql/type_sanity.sql | 1 +
doc/src/sgml/datatype.sgml | 11 ++
doc/src/sgml/func/func-aggregate.sgml | 8 +-
29 files changed, 734 insertions(+), 7 deletions(-)
create mode 100644 src/backend/utils/adt/oid8.c
create mode 100644 src/test/regress/expected/oid8.out
create mode 100644 src/test/regress/expected/oid8.sql
create mode 100644 src/test/regress/sql/oid8.sql
diff --git a/src/include/c.h b/src/include/c.h
index 39022f8a9dd7..ea2d5d4a1640 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -530,6 +530,7 @@ typedef uint32 bits32; /* >= 32 bits */
/* snprintf format strings to use for 64-bit integers */
#define INT64_FORMAT "%" PRId64
#define UINT64_FORMAT "%" PRIu64
+#define OID8_FORMAT "%" PRIu64
/*
* 128-bit signed and unsigned integers
@@ -616,7 +617,7 @@ typedef double float8;
#define FLOAT8PASSBYVAL true
/*
- * Oid, RegProcedure, TransactionId, SubTransactionId, MultiXactId,
+ * Oid, Oid8, RegProcedure, TransactionId, SubTransactionId, MultiXactId,
* CommandId
*/
@@ -648,6 +649,12 @@ typedef uint32 CommandId;
#define FirstCommandId ((CommandId) 0)
#define InvalidCommandId (~(CommandId)0)
+/* 8-byte Object ID */
+typedef uint64 Oid8;
+
+#define InvalidOid8 ((Oid8) 0)
+#define OID8_MAX UINT64_MAX
+#define atooid8(x) ((Oid8) strtou64((x), NULL, 10))
/* ----------------
* Variable-length datatypes all share the 'struct varlena' header.
@@ -754,6 +761,8 @@ typedef NameData *Name;
#define OidIsValid(objectId) ((bool) ((objectId) != InvalidOid))
+#define Oid8IsValid(objectId) ((bool) ((objectId) != InvalidOid8))
+
#define RegProcedureIsValid(p) OidIsValid(p)
diff --git a/src/include/catalog/pg_aggregate.dat b/src/include/catalog/pg_aggregate.dat
index d6aa1f6ec478..75acf4ef96cd 100644
--- a/src/include/catalog/pg_aggregate.dat
+++ b/src/include/catalog/pg_aggregate.dat
@@ -104,6 +104,9 @@
{ aggfnoid => 'max(oid)', aggtransfn => 'oidlarger',
aggcombinefn => 'oidlarger', aggsortop => '>(oid,oid)',
aggtranstype => 'oid' },
+{ aggfnoid => 'max(oid8)', aggtransfn => 'oid8larger',
+ aggcombinefn => 'oid8larger', aggsortop => '>(oid8,oid8)',
+ aggtranstype => 'oid8' },
{ aggfnoid => 'max(float4)', aggtransfn => 'float4larger',
aggcombinefn => 'float4larger', aggsortop => '>(float4,float4)',
aggtranstype => 'float4' },
@@ -178,6 +181,9 @@
{ aggfnoid => 'min(oid)', aggtransfn => 'oidsmaller',
aggcombinefn => 'oidsmaller', aggsortop => '<(oid,oid)',
aggtranstype => 'oid' },
+{ aggfnoid => 'min(oid8)', aggtransfn => 'oid8smaller',
+ aggcombinefn => 'oid8smaller', aggsortop => '<(oid8,oid8)',
+ aggtranstype => 'oid8' },
{ aggfnoid => 'min(float4)', aggtransfn => 'float4smaller',
aggcombinefn => 'float4smaller', aggsortop => '<(float4,float4)',
aggtranstype => 'float4' },
diff --git a/src/include/catalog/pg_amop.dat b/src/include/catalog/pg_amop.dat
index 2a693cfc31c6..2c3004d53611 100644
--- a/src/include/catalog/pg_amop.dat
+++ b/src/include/catalog/pg_amop.dat
@@ -180,6 +180,24 @@
{ amopfamily => 'btree/oid_ops', amoplefttype => 'oid', amoprighttype => 'oid',
amopstrategy => '5', amopopr => '>(oid,oid)', amopmethod => 'btree' },
+# btree oid8_ops
+
+{ amopfamily => 'btree/oid8_ops', amoplefttype => 'oid8',
+ amoprighttype => 'oid8', amopstrategy => '1', amopopr => '<(oid8,oid8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/oid8_ops', amoplefttype => 'oid8',
+ amoprighttype => 'oid8', amopstrategy => '2', amopopr => '<=(oid8,oid8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/oid8_ops', amoplefttype => 'oid8',
+ amoprighttype => 'oid8', amopstrategy => '3', amopopr => '=(oid8,oid8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/oid8_ops', amoplefttype => 'oid8',
+ amoprighttype => 'oid8', amopstrategy => '4', amopopr => '>=(oid8,oid8)',
+ amopmethod => 'btree' },
+{ amopfamily => 'btree/oid8_ops', amoplefttype => 'oid8',
+ amoprighttype => 'oid8', amopstrategy => '5', amopopr => '>(oid8,oid8)',
+ amopmethod => 'btree' },
+
# btree xid8_ops
{ amopfamily => 'btree/xid8_ops', amoplefttype => 'xid8',
@@ -974,6 +992,11 @@
{ amopfamily => 'hash/oid_ops', amoplefttype => 'oid', amoprighttype => 'oid',
amopstrategy => '1', amopopr => '=(oid,oid)', amopmethod => 'hash' },
+# oid8_ops
+{ amopfamily => 'hash/oid8_ops', amoplefttype => 'oid8',
+ amoprighttype => 'oid8', amopstrategy => '1', amopopr => '=(oid8,oid8)',
+ amopmethod => 'hash' },
+
# oidvector_ops
{ amopfamily => 'hash/oidvector_ops', amoplefttype => 'oidvector',
amoprighttype => 'oidvector', amopstrategy => '1',
diff --git a/src/include/catalog/pg_amproc.dat b/src/include/catalog/pg_amproc.dat
index e3477500baa7..d3719b3610c4 100644
--- a/src/include/catalog/pg_amproc.dat
+++ b/src/include/catalog/pg_amproc.dat
@@ -213,6 +213,14 @@
amprocrighttype => 'oid', amprocnum => '4', amproc => 'btequalimage' },
{ amprocfamily => 'btree/oid_ops', amproclefttype => 'oid',
amprocrighttype => 'oid', amprocnum => '6', amproc => 'btoidskipsupport' },
+{ amprocfamily => 'btree/oid8_ops', amproclefttype => 'oid8',
+ amprocrighttype => 'oid8', amprocnum => '1', amproc => 'btoid8cmp' },
+{ amprocfamily => 'btree/oid8_ops', amproclefttype => 'oid8',
+ amprocrighttype => 'oid8', amprocnum => '2', amproc => 'btoid8sortsupport' },
+{ amprocfamily => 'btree/oid8_ops', amproclefttype => 'oid8',
+ amprocrighttype => 'oid8', amprocnum => '4', amproc => 'btequalimage' },
+{ amprocfamily => 'btree/oid8_ops', amproclefttype => 'oid8',
+ amprocrighttype => 'oid8', amprocnum => '6', amproc => 'btoid8skipsupport' },
{ amprocfamily => 'btree/oidvector_ops', amproclefttype => 'oidvector',
amprocrighttype => 'oidvector', amprocnum => '1',
amproc => 'btoidvectorcmp' },
@@ -432,6 +440,10 @@
amprocrighttype => 'xid8', amprocnum => '1', amproc => 'hashxid8' },
{ amprocfamily => 'hash/xid8_ops', amproclefttype => 'xid8',
amprocrighttype => 'xid8', amprocnum => '2', amproc => 'hashxid8extended' },
+{ amprocfamily => 'hash/oid8_ops', amproclefttype => 'oid8',
+ amprocrighttype => 'oid8', amprocnum => '1', amproc => 'hashoid8' },
+{ amprocfamily => 'hash/oid8_ops', amproclefttype => 'oid8',
+ amprocrighttype => 'oid8', amprocnum => '2', amproc => 'hashoid8extended' },
{ amprocfamily => 'hash/cid_ops', amproclefttype => 'cid',
amprocrighttype => 'cid', amprocnum => '1', amproc => 'hashcid' },
{ amprocfamily => 'hash/cid_ops', amproclefttype => 'cid',
diff --git a/src/include/catalog/pg_cast.dat b/src/include/catalog/pg_cast.dat
index fbfd669587f0..695f6b2a5e73 100644
--- a/src/include/catalog/pg_cast.dat
+++ b/src/include/catalog/pg_cast.dat
@@ -296,6 +296,20 @@
{ castsource => 'regdatabase', casttarget => 'int4', castfunc => '0',
castcontext => 'a', castmethod => 'b' },
+# OID8 category: allow implicit conversion from any integral type (including
+# int8), as well as assignment coercion to int8.
+{ castsource => 'int8', casttarget => 'oid8', castfunc => '0',
+ castcontext => 'i', castmethod => 'b' },
+{ castsource => 'int2', casttarget => 'oid8', castfunc => 'int8(int2)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'int4', casttarget => 'oid8', castfunc => 'int8(int4)',
+ castcontext => 'i', castmethod => 'f' },
+{ castsource => 'oid8', casttarget => 'int8', castfunc => '0',
+ castcontext => 'a', castmethod => 'b' },
+# Assignment coercion from oid to oid8.
+{ castsource => 'oid', casttarget => 'oid8', castfunc => 'oid8(oid)',
+ castcontext => 'a', castmethod => 'f' },
+
# String category
{ castsource => 'text', casttarget => 'bpchar', castfunc => '0',
castcontext => 'i', castmethod => 'b' },
diff --git a/src/include/catalog/pg_opclass.dat b/src/include/catalog/pg_opclass.dat
index 4a9624802aa5..c0de88fabc49 100644
--- a/src/include/catalog/pg_opclass.dat
+++ b/src/include/catalog/pg_opclass.dat
@@ -177,6 +177,10 @@
opcintype => 'xid8' },
{ opcmethod => 'btree', opcname => 'xid8_ops', opcfamily => 'btree/xid8_ops',
opcintype => 'xid8' },
+{ opcmethod => 'hash', opcname => 'oid8_ops', opcfamily => 'hash/oid8_ops',
+ opcintype => 'oid8' },
+{ opcmethod => 'btree', opcname => 'oid8_ops', opcfamily => 'btree/oid8_ops',
+ opcintype => 'oid8' },
{ opcmethod => 'hash', opcname => 'cid_ops', opcfamily => 'hash/cid_ops',
opcintype => 'cid' },
{ opcmethod => 'hash', opcname => 'tid_ops', opcfamily => 'hash/tid_ops',
diff --git a/src/include/catalog/pg_operator.dat b/src/include/catalog/pg_operator.dat
index 6d9dc1528d6e..87a7255490a7 100644
--- a/src/include/catalog/pg_operator.dat
+++ b/src/include/catalog/pg_operator.dat
@@ -3460,4 +3460,30 @@
oprcode => 'multirange_after_multirange', oprrest => 'multirangesel',
oprjoin => 'scalargtjoinsel' },
+{ oid => '8262', descr => 'equal',
+ oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'oid8',
+ oprright => 'oid8', oprresult => 'bool', oprcom => '=(oid8,oid8)',
+ oprnegate => '<>(oid8,oid8)', oprcode => 'oid8eq', oprrest => 'eqsel',
+ oprjoin => 'eqjoinsel' },
+{ oid => '8263', descr => 'not equal',
+ oprname => '<>', oprleft => 'oid8', oprright => 'oid8', oprresult => 'bool',
+ oprcom => '<>(oid8,oid8)', oprnegate => '=(oid8,oid8)', oprcode => 'oid8ne',
+ oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
+{ oid => '8264', descr => 'less than',
+ oprname => '<', oprleft => 'oid8', oprright => 'oid8', oprresult => 'bool',
+ oprcom => '>(oid8,oid8)', oprnegate => '>=(oid8,oid8)', oprcode => 'oid8lt',
+ oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
+{ oid => '8265', descr => 'greater than',
+ oprname => '>', oprleft => 'oid8', oprright => 'oid8', oprresult => 'bool',
+ oprcom => '<(oid8,oid8)', oprnegate => '<=(oid8,oid8)', oprcode => 'oid8gt',
+ oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
+{ oid => '8266', descr => 'less than or equal',
+ oprname => '<=', oprleft => 'oid8', oprright => 'oid8', oprresult => 'bool',
+ oprcom => '>=(oid8,oid8)', oprnegate => '>(oid8,oid8)', oprcode => 'oid8le',
+ oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
+{ oid => '8267', descr => 'greater than or equal',
+ oprname => '>=', oprleft => 'oid8', oprright => 'oid8', oprresult => 'bool',
+ oprcom => '<=(oid8,oid8)', oprnegate => '<(oid8,oid8)', oprcode => 'oid8ge',
+ oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
+
]
diff --git a/src/include/catalog/pg_opfamily.dat b/src/include/catalog/pg_opfamily.dat
index f7dcb96b43ce..54472ce97dcd 100644
--- a/src/include/catalog/pg_opfamily.dat
+++ b/src/include/catalog/pg_opfamily.dat
@@ -116,6 +116,10 @@
opfmethod => 'hash', opfname => 'xid8_ops' },
{ oid => '5067',
opfmethod => 'btree', opfname => 'xid8_ops' },
+{ oid => '8278',
+ opfmethod => 'hash', opfname => 'oid8_ops' },
+{ oid => '8279',
+ opfmethod => 'btree', opfname => 'oid8_ops' },
{ oid => '2226',
opfmethod => 'hash', opfname => 'cid_ops' },
{ oid => '2227',
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 118d6da1ace0..b78508e83b9b 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -1046,6 +1046,15 @@
{ oid => '6405', descr => 'skip support',
proname => 'btoidskipsupport', prorettype => 'void',
proargtypes => 'internal', prosrc => 'btoidskipsupport' },
+{ oid => '8282', descr => 'less-equal-greater',
+ proname => 'btoid8cmp', proleakproof => 't', prorettype => 'int4',
+ proargtypes => 'oid8 oid8', prosrc => 'btoid8cmp' },
+{ oid => '8283', descr => 'sort support',
+ proname => 'btoid8sortsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'btoid8sortsupport' },
+{ oid => '8284', descr => 'skip support',
+ proname => 'btoid8skipsupport', prorettype => 'void',
+ proargtypes => 'internal', prosrc => 'btoid8skipsupport' },
{ oid => '404', descr => 'less-equal-greater',
proname => 'btoidvectorcmp', proleakproof => 't', prorettype => 'int4',
proargtypes => 'oidvector oidvector', prosrc => 'btoidvectorcmp' },
@@ -12576,4 +12585,59 @@
proargnames => '{pid,io_id,io_generation,state,operation,off,length,target,handle_data_len,raw_result,result,target_desc,f_sync,f_localmem,f_buffered}',
prosrc => 'pg_get_aios' },
+# oid8 related functions
+{ oid => '8255', descr => 'convert oid to oid8',
+ proname => 'oid8', prorettype => 'oid8', proargtypes => 'oid',
+ prosrc => 'oidtooid8' },
+{ oid => '8257', descr => 'I/O',
+ proname => 'oid8in', prorettype => 'oid8', proargtypes => 'cstring',
+ prosrc => 'oid8in' },
+{ oid => '8258', descr => 'I/O',
+ proname => 'oid8out', prorettype => 'cstring', proargtypes => 'oid8',
+ prosrc => 'oid8out' },
+{ oid => '8259', descr => 'I/O',
+ proname => 'oid8recv', prorettype => 'oid8', proargtypes => 'internal',
+ prosrc => 'oid8recv' },
+{ oid => '8260', descr => 'I/O',
+ proname => 'oid8send', prorettype => 'bytea', proargtypes => 'oid8',
+ prosrc => 'oid8send' },
+# Comparators
+{ oid => '8268',
+ proname => 'oid8eq', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'oid8 oid8', prosrc => 'oid8eq' },
+{ oid => '8269',
+ proname => 'oid8ne', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'oid8 oid8', prosrc => 'oid8ne' },
+{ oid => '8270',
+ proname => 'oid8lt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'oid8 oid8', prosrc => 'oid8lt' },
+{ oid => '8271',
+ proname => 'oid8le', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'oid8 oid8', prosrc => 'oid8le' },
+{ oid => '8272',
+ proname => 'oid8gt', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'oid8 oid8', prosrc => 'oid8gt' },
+{ oid => '8273',
+ proname => 'oid8ge', proleakproof => 't', prorettype => 'bool',
+ proargtypes => 'oid8 oid8', prosrc => 'oid8ge' },
+# Aggregates
+{ oid => '8274', descr => 'larger of two',
+ proname => 'oid8larger', prorettype => 'oid8', proargtypes => 'oid8 oid8',
+ prosrc => 'oid8larger' },
+{ oid => '8275', descr => 'smaller of two',
+ proname => 'oid8smaller', prorettype => 'oid8', proargtypes => 'oid8 oid8',
+ prosrc => 'oid8smaller' },
+{ oid => '8276', descr => 'maximum value of all oid8 input values',
+ proname => 'max', prokind => 'a', proisstrict => 'f', prorettype => 'oid8',
+ proargtypes => 'oid8', prosrc => 'aggregate_dummy' },
+{ oid => '8277', descr => 'minimum value of all oid8 input values',
+ proname => 'min', prokind => 'a', proisstrict => 'f', prorettype => 'oid8',
+ proargtypes => 'oid8', prosrc => 'aggregate_dummy' },
+{ oid => '8280', descr => 'hash',
+ proname => 'hashoid8', prorettype => 'int4', proargtypes => 'oid8',
+ prosrc => 'hashoid8' },
+{ oid => '8281', descr => 'hash',
+ proname => 'hashoid8extended', prorettype => 'int8',
+ proargtypes => 'oid8 int8', prosrc => 'hashoid8extended' },
+
]
diff --git a/src/include/catalog/pg_type.dat b/src/include/catalog/pg_type.dat
index cb730aeac864..704f2890cb28 100644
--- a/src/include/catalog/pg_type.dat
+++ b/src/include/catalog/pg_type.dat
@@ -700,4 +700,9 @@
typreceive => 'brin_minmax_multi_summary_recv',
typsend => 'brin_minmax_multi_summary_send', typalign => 'i',
typstorage => 'x', typcollation => 'default' },
+{ oid => '8256', array_type_oid => '8261',
+ descr => 'object identifier(oid8), 8 bytes',
+ typname => 'oid8', typlen => '8', typbyval => 't',
+ typcategory => 'N', typinput => 'oid8in', typoutput => 'oid8out',
+ typreceive => 'oid8recv', typsend => 'oid8send', typalign => 'd' },
]
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index c7236e429724..111588f75c86 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -273,6 +273,7 @@ extern struct varlena *pg_detoast_datum_packed(struct varlena *datum);
#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_OID8(n) DatumGetObjectId8(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))
@@ -358,6 +359,7 @@ extern struct varlena *pg_detoast_datum_packed(struct varlena *datum);
#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_OID8(x) return ObjectId8GetDatum(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)
diff --git a/src/include/postgres.h b/src/include/postgres.h
index 357cbd6fd961..a5a0e3b7cbfa 100644
--- a/src/include/postgres.h
+++ b/src/include/postgres.h
@@ -264,6 +264,26 @@ ObjectIdGetDatum(Oid X)
return (Datum) X;
}
+/*
+ * DatumGetObjectId8
+ * Returns 8-byte object identifier value of a datum.
+ */
+static inline Oid8
+DatumGetObjectId8(Datum X)
+{
+ return (Oid8) X;
+}
+
+/*
+ * ObjectId8GetDatum
+ * Returns datum representation for an 8-byte object identifier
+ */
+static inline Datum
+ObjectId8GetDatum(Oid8 X)
+{
+ return (Datum) X;
+}
+
/*
* DatumGetTransactionId
* Returns transaction identifier value of a datum.
diff --git a/src/include/postgres_ext.h b/src/include/postgres_ext.h
index bf45c50dcf31..c80b195bf235 100644
--- a/src/include/postgres_ext.h
+++ b/src/include/postgres_ext.h
@@ -41,7 +41,6 @@ typedef unsigned int Oid;
#define atooid(x) ((Oid) strtoul((x), NULL, 10))
/* the above needs <stdlib.h> */
-
/*
* Identifiers of error message fields. Kept here to keep common
* between frontend and backend, and also to export them to libpq
diff --git a/src/backend/access/nbtree/nbtcompare.c b/src/backend/access/nbtree/nbtcompare.c
index 188c27b4925f..3f59ba3f1ad0 100644
--- a/src/backend/access/nbtree/nbtcompare.c
+++ b/src/backend/access/nbtree/nbtcompare.c
@@ -498,6 +498,88 @@ btoidskipsupport(PG_FUNCTION_ARGS)
PG_RETURN_VOID();
}
+Datum
+btoid8cmp(PG_FUNCTION_ARGS)
+{
+ Oid8 a = PG_GETARG_OID8(0);
+ Oid8 b = PG_GETARG_OID8(1);
+
+ if (a > b)
+ PG_RETURN_INT32(A_GREATER_THAN_B);
+ else if (a == b)
+ PG_RETURN_INT32(0);
+ else
+ PG_RETURN_INT32(A_LESS_THAN_B);
+}
+
+static int
+btoid8fastcmp(Datum x, Datum y, SortSupport ssup)
+{
+ Oid8 a = DatumGetObjectId8(x);
+ Oid8 b = DatumGetObjectId8(y);
+
+ if (a > b)
+ return A_GREATER_THAN_B;
+ else if (a == b)
+ return 0;
+ else
+ return A_LESS_THAN_B;
+}
+
+Datum
+btoid8sortsupport(PG_FUNCTION_ARGS)
+{
+ SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
+
+ ssup->comparator = btoid8fastcmp;
+ PG_RETURN_VOID();
+}
+
+static Datum
+oid8_decrement(Relation rel, Datum existing, bool *underflow)
+{
+ Oid8 oexisting = DatumGetObjectId8(existing);
+
+ if (oexisting == InvalidOid8)
+ {
+ /* return value is undefined */
+ *underflow = true;
+ return (Datum) 0;
+ }
+
+ *underflow = false;
+ return ObjectId8GetDatum(oexisting - 1);
+}
+
+static Datum
+oid8_increment(Relation rel, Datum existing, bool *overflow)
+{
+ Oid8 oexisting = DatumGetObjectId8(existing);
+
+ if (oexisting == OID8_MAX)
+ {
+ /* return value is undefined */
+ *overflow = true;
+ return (Datum) 0;
+ }
+
+ *overflow = false;
+ return ObjectId8GetDatum(oexisting + 1);
+}
+
+Datum
+btoid8skipsupport(PG_FUNCTION_ARGS)
+{
+ SkipSupport sksup = (SkipSupport) PG_GETARG_POINTER(0);
+
+ sksup->decrement = oid8_decrement;
+ sksup->increment = oid8_increment;
+ sksup->low_elem = ObjectId8GetDatum(InvalidOid8);
+ sksup->high_elem = ObjectId8GetDatum(OID8_MAX);
+
+ PG_RETURN_VOID();
+}
+
Datum
btoidvectorcmp(PG_FUNCTION_ARGS)
{
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index fc8638c1b61b..48e6966e6b48 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -115,6 +115,8 @@ static const struct typinfo TypInfo[] = {
F_TEXTIN, F_TEXTOUT},
{"oid", OIDOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
F_OIDIN, F_OIDOUT},
+ {"oid8", OID8OID, 0, 8, true, TYPALIGN_DOUBLE, TYPSTORAGE_PLAIN, InvalidOid,
+ F_OID8IN, F_OID8OUT},
{"tid", TIDOID, 0, 6, false, TYPALIGN_SHORT, TYPSTORAGE_PLAIN, InvalidOid,
F_TIDIN, F_TIDOUT},
{"xid", XIDOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
diff --git a/src/backend/utils/adt/Makefile b/src/backend/utils/adt/Makefile
index ffeacf2b819f..42d7e1db2433 100644
--- a/src/backend/utils/adt/Makefile
+++ b/src/backend/utils/adt/Makefile
@@ -76,6 +76,7 @@ OBJS = \
numeric.o \
numutils.o \
oid.o \
+ oid8.o \
oracle_compat.o \
orderedsetaggs.o \
partitionfuncs.o \
diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c
index bdea490202a6..9f7466e47b79 100644
--- a/src/backend/utils/adt/int8.c
+++ b/src/backend/utils/adt/int8.c
@@ -1323,6 +1323,14 @@ oidtoi8(PG_FUNCTION_ARGS)
PG_RETURN_INT64((int64) arg);
}
+Datum
+oidtooid8(PG_FUNCTION_ARGS)
+{
+ Oid arg = PG_GETARG_OID(0);
+
+ PG_RETURN_OID8((Oid8) arg);
+}
+
/*
* non-persistent numeric series generator
*/
diff --git a/src/backend/utils/adt/meson.build b/src/backend/utils/adt/meson.build
index ed9bbd7b9266..74926c32321b 100644
--- a/src/backend/utils/adt/meson.build
+++ b/src/backend/utils/adt/meson.build
@@ -63,6 +63,7 @@ backend_sources += files(
'numeric.c',
'numutils.c',
'oid.c',
+ 'oid8.c',
'oracle_compat.c',
'orderedsetaggs.c',
'partitionfuncs.c',
diff --git a/src/backend/utils/adt/oid8.c b/src/backend/utils/adt/oid8.c
new file mode 100644
index 000000000000..6e9ffd96303f
--- /dev/null
+++ b/src/backend/utils/adt/oid8.c
@@ -0,0 +1,171 @@
+/*-------------------------------------------------------------------------
+ *
+ * oid8.c
+ * Functions for the built-in type Oid8
+ *
+ * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/utils/adt/oid8.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include <ctype.h>
+#include <limits.h>
+
+#include "catalog/pg_type.h"
+#include "libpq/pqformat.h"
+#include "utils/builtins.h"
+
+#define MAXOID8LEN 20
+
+/*****************************************************************************
+ * USER I/O ROUTINES *
+ *****************************************************************************/
+
+Datum
+oid8in(PG_FUNCTION_ARGS)
+{
+ char *s = PG_GETARG_CSTRING(0);
+ Oid8 result;
+
+ result = uint64in_subr(s, NULL, "oid8", fcinfo->context);
+ PG_RETURN_OID8(result);
+}
+
+Datum
+oid8out(PG_FUNCTION_ARGS)
+{
+ Oid8 val = PG_GETARG_OID8(0);
+ char buf[MAXOID8LEN + 1];
+ char *result;
+ int len;
+
+ len = pg_ulltoa_n(val, buf) + 1;
+ buf[len - 1] = '\0';
+
+ /*
+ * Since the length is already known, we do a manual palloc() and memcpy()
+ * to avoid the strlen() call that would otherwise be done in pstrdup().
+ */
+ result = palloc(len);
+ memcpy(result, buf, len);
+ PG_RETURN_CSTRING(result);
+}
+
+/*
+ * oid8recv - converts external binary format to oid8
+ */
+Datum
+oid8recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+
+ PG_RETURN_OID8(pq_getmsgint64(buf));
+}
+
+/*
+ * oid8send - converts oid8 to binary format
+ */
+Datum
+oid8send(PG_FUNCTION_ARGS)
+{
+ Oid8 arg1 = PG_GETARG_OID8(0);
+ StringInfoData buf;
+
+ pq_begintypsend(&buf);
+ pq_sendint64(&buf, arg1);
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
+/*****************************************************************************
+ * PUBLIC ROUTINES *
+ *****************************************************************************/
+
+Datum
+oid8eq(PG_FUNCTION_ARGS)
+{
+ Oid8 arg1 = PG_GETARG_OID8(0);
+ Oid8 arg2 = PG_GETARG_OID8(1);
+
+ PG_RETURN_BOOL(arg1 == arg2);
+}
+
+Datum
+oid8ne(PG_FUNCTION_ARGS)
+{
+ Oid8 arg1 = PG_GETARG_OID8(0);
+ Oid8 arg2 = PG_GETARG_OID8(1);
+
+ PG_RETURN_BOOL(arg1 != arg2);
+}
+
+Datum
+oid8lt(PG_FUNCTION_ARGS)
+{
+ Oid8 arg1 = PG_GETARG_OID8(0);
+ Oid8 arg2 = PG_GETARG_OID8(1);
+
+ PG_RETURN_BOOL(arg1 < arg2);
+}
+
+Datum
+oid8le(PG_FUNCTION_ARGS)
+{
+ Oid8 arg1 = PG_GETARG_OID8(0);
+ Oid8 arg2 = PG_GETARG_OID8(1);
+
+ PG_RETURN_BOOL(arg1 <= arg2);
+}
+
+Datum
+oid8ge(PG_FUNCTION_ARGS)
+{
+ Oid8 arg1 = PG_GETARG_OID8(0);
+ Oid8 arg2 = PG_GETARG_OID8(1);
+
+ PG_RETURN_BOOL(arg1 >= arg2);
+}
+
+Datum
+oid8gt(PG_FUNCTION_ARGS)
+{
+ Oid8 arg1 = PG_GETARG_OID8(0);
+ Oid8 arg2 = PG_GETARG_OID8(1);
+
+ PG_RETURN_BOOL(arg1 > arg2);
+}
+
+Datum
+hashoid8(PG_FUNCTION_ARGS)
+{
+ return hashint8(fcinfo);
+}
+
+Datum
+hashoid8extended(PG_FUNCTION_ARGS)
+{
+ return hashint8extended(fcinfo);
+}
+
+Datum
+oid8larger(PG_FUNCTION_ARGS)
+{
+ Oid8 arg1 = PG_GETARG_OID8(0);
+ Oid8 arg2 = PG_GETARG_OID8(1);
+
+ PG_RETURN_OID8((arg1 > arg2) ? arg1 : arg2);
+}
+
+Datum
+oid8smaller(PG_FUNCTION_ARGS)
+{
+ Oid8 arg1 = PG_GETARG_OID8(0);
+ Oid8 arg2 = PG_GETARG_OID8(1);
+
+ PG_RETURN_OID8((arg1 < arg2) ? arg1 : arg2);
+}
diff --git a/src/fe_utils/print.c b/src/fe_utils/print.c
index 4af0f32f2fc0..221624707892 100644
--- a/src/fe_utils/print.c
+++ b/src/fe_utils/print.c
@@ -3624,6 +3624,7 @@ column_type_alignment(Oid ftype)
case FLOAT8OID:
case NUMERICOID:
case OIDOID:
+ case OID8OID:
case XIDOID:
case XID8OID:
case CIDOID:
diff --git a/src/test/regress/expected/oid8.out b/src/test/regress/expected/oid8.out
new file mode 100644
index 000000000000..80529214ca53
--- /dev/null
+++ b/src/test/regress/expected/oid8.out
@@ -0,0 +1,196 @@
+--
+-- OID8
+--
+CREATE TABLE OID8_TBL(f1 oid8);
+INSERT INTO OID8_TBL(f1) VALUES ('1234');
+INSERT INTO OID8_TBL(f1) VALUES ('1235');
+INSERT INTO OID8_TBL(f1) VALUES ('987');
+INSERT INTO OID8_TBL(f1) VALUES ('-1040');
+INSERT INTO OID8_TBL(f1) VALUES ('99999999');
+INSERT INTO OID8_TBL(f1) VALUES ('5 ');
+INSERT INTO OID8_TBL(f1) VALUES (' 10 ');
+-- leading/trailing hard tab is also allowed
+INSERT INTO OID8_TBL(f1) VALUES (' 15 ');
+-- bad inputs
+INSERT INTO OID8_TBL(f1) VALUES ('');
+ERROR: invalid input syntax for type oid8: ""
+LINE 1: INSERT INTO OID8_TBL(f1) VALUES ('');
+ ^
+INSERT INTO OID8_TBL(f1) VALUES (' ');
+ERROR: invalid input syntax for type oid8: " "
+LINE 1: INSERT INTO OID8_TBL(f1) VALUES (' ');
+ ^
+INSERT INTO OID8_TBL(f1) VALUES ('asdfasd');
+ERROR: invalid input syntax for type oid8: "asdfasd"
+LINE 1: INSERT INTO OID8_TBL(f1) VALUES ('asdfasd');
+ ^
+INSERT INTO OID8_TBL(f1) VALUES ('99asdfasd');
+ERROR: invalid input syntax for type oid8: "99asdfasd"
+LINE 1: INSERT INTO OID8_TBL(f1) VALUES ('99asdfasd');
+ ^
+INSERT INTO OID8_TBL(f1) VALUES ('5 d');
+ERROR: invalid input syntax for type oid8: "5 d"
+LINE 1: INSERT INTO OID8_TBL(f1) VALUES ('5 d');
+ ^
+INSERT INTO OID8_TBL(f1) VALUES (' 5d');
+ERROR: invalid input syntax for type oid8: " 5d"
+LINE 1: INSERT INTO OID8_TBL(f1) VALUES (' 5d');
+ ^
+INSERT INTO OID8_TBL(f1) VALUES ('5 5');
+ERROR: invalid input syntax for type oid8: "5 5"
+LINE 1: INSERT INTO OID8_TBL(f1) VALUES ('5 5');
+ ^
+INSERT INTO OID8_TBL(f1) VALUES (' - 500');
+ERROR: invalid input syntax for type oid8: " - 500"
+LINE 1: INSERT INTO OID8_TBL(f1) VALUES (' - 500');
+ ^
+INSERT INTO OID8_TBL(f1) VALUES ('3908203590239580293850293850329485');
+ERROR: value "3908203590239580293850293850329485" is out of range for type oid8
+LINE 1: INSERT INTO OID8_TBL(f1) VALUES ('39082035902395802938502938...
+ ^
+INSERT INTO OID8_TBL(f1) VALUES ('-1204982019841029840928340329840934');
+ERROR: value "-1204982019841029840928340329840934" is out of range for type oid8
+LINE 1: INSERT INTO OID8_TBL(f1) VALUES ('-1204982019841029840928340...
+ ^
+SELECT * FROM OID8_TBL;
+ f1
+----------------------
+ 1234
+ 1235
+ 987
+ 18446744073709550576
+ 99999999
+ 5
+ 10
+ 15
+(8 rows)
+
+-- Also try it with non-error-throwing API
+SELECT pg_input_is_valid('1234', 'oid8');
+ pg_input_is_valid
+-------------------
+ t
+(1 row)
+
+SELECT pg_input_is_valid('01XYZ', 'oid8');
+ pg_input_is_valid
+-------------------
+ f
+(1 row)
+
+SELECT * FROM pg_input_error_info('01XYZ', 'oid8');
+ message | detail | hint | sql_error_code
+---------------------------------------------+--------+------+----------------
+ invalid input syntax for type oid8: "01XYZ" | | | 22P02
+(1 row)
+
+SELECT pg_input_is_valid('3908203590239580293850293850329485', 'oid8');
+ pg_input_is_valid
+-------------------
+ f
+(1 row)
+
+SELECT * FROM pg_input_error_info('-1204982019841029840928340329840934', 'oid8');
+ message | detail | hint | sql_error_code
+---------------------------------------------------------------------------+--------+------+----------------
+ value "-1204982019841029840928340329840934" is out of range for type oid8 | | | 22003
+(1 row)
+
+-- Operators
+SELECT o.* FROM OID8_TBL o WHERE o.f1 = 1234;
+ f1
+------
+ 1234
+(1 row)
+
+SELECT o.* FROM OID8_TBL o WHERE o.f1 <> '1234';
+ f1
+----------------------
+ 1235
+ 987
+ 18446744073709550576
+ 99999999
+ 5
+ 10
+ 15
+(7 rows)
+
+SELECT o.* FROM OID8_TBL o WHERE o.f1 <= '1234';
+ f1
+------
+ 1234
+ 987
+ 5
+ 10
+ 15
+(5 rows)
+
+SELECT o.* FROM OID8_TBL o WHERE o.f1 < '1234';
+ f1
+-----
+ 987
+ 5
+ 10
+ 15
+(4 rows)
+
+SELECT o.* FROM OID8_TBL o WHERE o.f1 >= '1234';
+ f1
+----------------------
+ 1234
+ 1235
+ 18446744073709550576
+ 99999999
+(4 rows)
+
+SELECT o.* FROM OID8_TBL o WHERE o.f1 > '1234';
+ f1
+----------------------
+ 1235
+ 18446744073709550576
+ 99999999
+(3 rows)
+
+-- Casts
+SELECT 1::int2::oid8;
+ oid8
+------
+ 1
+(1 row)
+
+SELECT 1::int4::oid8;
+ oid8
+------
+ 1
+(1 row)
+
+SELECT 1::int8::oid8;
+ oid8
+------
+ 1
+(1 row)
+
+SELECT 1::oid8::int8;
+ int8
+------
+ 1
+(1 row)
+
+SELECT 1::oid::oid8; -- ok
+ oid8
+------
+ 1
+(1 row)
+
+SELECT 1::oid8::oid; -- not ok
+ERROR: cannot cast type oid8 to oid
+LINE 1: SELECT 1::oid8::oid;
+ ^
+-- Aggregates
+SELECT min(f1), max(f1) FROM OID8_TBL;
+ min | max
+-----+----------------------
+ 5 | 18446744073709550576
+(1 row)
+
+DROP TABLE OID8_TBL;
diff --git a/src/test/regress/expected/oid8.sql b/src/test/regress/expected/oid8.sql
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index 20bf9ea9cdf7..1b2a1641029d 100644
--- a/src/test/regress/expected/opr_sanity.out
+++ b/src/test/regress/expected/opr_sanity.out
@@ -880,6 +880,13 @@ bytea(integer)
bytea(bigint)
bytea_larger(bytea,bytea)
bytea_smaller(bytea,bytea)
+oid8eq(oid8,oid8)
+oid8ne(oid8,oid8)
+oid8lt(oid8,oid8)
+oid8le(oid8,oid8)
+oid8gt(oid8,oid8)
+oid8ge(oid8,oid8)
+btoid8cmp(oid8,oid8)
-- Check that functions without argument are not marked as leakproof.
SELECT p1.oid::regprocedure
FROM pg_proc p1 JOIN pg_namespace pn
diff --git a/src/test/regress/expected/type_sanity.out b/src/test/regress/expected/type_sanity.out
index 943e56506bf1..9ddcacec6bf4 100644
--- a/src/test/regress/expected/type_sanity.out
+++ b/src/test/regress/expected/type_sanity.out
@@ -702,6 +702,7 @@ CREATE TABLE tab_core_types AS SELECT
'abc'::refcursor,
'1 2'::int2vector,
'1 2'::oidvector,
+ '1234'::oid8,
format('%I=UC/%I', USER, USER)::aclitem AS aclitem,
'a fat cat sat on a mat and ate a fat rat'::tsvector,
'fat & rat'::tsquery,
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index fbffc67ae601..56e129ce4aa0 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -28,7 +28,7 @@ test: strings md5 numerology point lseg line box path polygon circle date time t
# geometry depends on point, lseg, line, box, path, polygon, circle
# horology depends on date, time, timetz, timestamp, timestamptz, interval
# ----------
-test: geometry horology tstypes regex type_sanity opr_sanity misc_sanity comments expressions unicode xid mvcc database stats_import
+test: geometry horology tstypes regex type_sanity opr_sanity misc_sanity comments expressions unicode xid mvcc database stats_import oid8
# ----------
# Load huge amounts of data
diff --git a/src/test/regress/sql/oid8.sql b/src/test/regress/sql/oid8.sql
new file mode 100644
index 000000000000..c4f2ae6a2e57
--- /dev/null
+++ b/src/test/regress/sql/oid8.sql
@@ -0,0 +1,57 @@
+--
+-- OID8
+--
+
+CREATE TABLE OID8_TBL(f1 oid8);
+
+INSERT INTO OID8_TBL(f1) VALUES ('1234');
+INSERT INTO OID8_TBL(f1) VALUES ('1235');
+INSERT INTO OID8_TBL(f1) VALUES ('987');
+INSERT INTO OID8_TBL(f1) VALUES ('-1040');
+INSERT INTO OID8_TBL(f1) VALUES ('99999999');
+INSERT INTO OID8_TBL(f1) VALUES ('5 ');
+INSERT INTO OID8_TBL(f1) VALUES (' 10 ');
+-- leading/trailing hard tab is also allowed
+INSERT INTO OID8_TBL(f1) VALUES (' 15 ');
+
+-- bad inputs
+INSERT INTO OID8_TBL(f1) VALUES ('');
+INSERT INTO OID8_TBL(f1) VALUES (' ');
+INSERT INTO OID8_TBL(f1) VALUES ('asdfasd');
+INSERT INTO OID8_TBL(f1) VALUES ('99asdfasd');
+INSERT INTO OID8_TBL(f1) VALUES ('5 d');
+INSERT INTO OID8_TBL(f1) VALUES (' 5d');
+INSERT INTO OID8_TBL(f1) VALUES ('5 5');
+INSERT INTO OID8_TBL(f1) VALUES (' - 500');
+INSERT INTO OID8_TBL(f1) VALUES ('3908203590239580293850293850329485');
+INSERT INTO OID8_TBL(f1) VALUES ('-1204982019841029840928340329840934');
+
+SELECT * FROM OID8_TBL;
+
+-- Also try it with non-error-throwing API
+SELECT pg_input_is_valid('1234', 'oid8');
+SELECT pg_input_is_valid('01XYZ', 'oid8');
+SELECT * FROM pg_input_error_info('01XYZ', 'oid8');
+SELECT pg_input_is_valid('3908203590239580293850293850329485', 'oid8');
+SELECT * FROM pg_input_error_info('-1204982019841029840928340329840934', 'oid8');
+
+-- Operators
+SELECT o.* FROM OID8_TBL o WHERE o.f1 = 1234;
+SELECT o.* FROM OID8_TBL o WHERE o.f1 <> '1234';
+SELECT o.* FROM OID8_TBL o WHERE o.f1 <= '1234';
+SELECT o.* FROM OID8_TBL o WHERE o.f1 < '1234';
+SELECT o.* FROM OID8_TBL o WHERE o.f1 >= '1234';
+SELECT o.* FROM OID8_TBL o WHERE o.f1 > '1234';
+
+-- Casts
+SELECT 1::int2::oid8;
+SELECT 1::int4::oid8;
+SELECT 1::int8::oid8;
+SELECT 1::oid8::int8;
+SELECT 1::oid::oid8; -- ok
+SELECT 1::oid8::oid; -- not ok
+
+-- Aggregates
+SELECT min(f1), max(f1) FROM OID8_TBL;
+
+DROP TABLE OID8_TBL;
diff --git a/src/test/regress/sql/type_sanity.sql b/src/test/regress/sql/type_sanity.sql
index df795759bb4c..c2496823d90e 100644
--- a/src/test/regress/sql/type_sanity.sql
+++ b/src/test/regress/sql/type_sanity.sql
@@ -530,6 +530,7 @@ CREATE TABLE tab_core_types AS SELECT
'abc'::refcursor,
'1 2'::int2vector,
'1 2'::oidvector,
+ '1234'::oid8,
format('%I=UC/%I', USER, USER)::aclitem AS aclitem,
'a fat cat sat on a mat and ate a fat rat'::tsvector,
'fat & rat'::tsquery,
diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index b81d89e26080..66c6aa7f349a 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -4723,6 +4723,10 @@ INSERT INTO mytable VALUES(-1); -- fails
<primary>oid</primary>
</indexterm>
+ <indexterm zone="datatype-oid">
+ <primary>oid8</primary>
+ </indexterm>
+
<indexterm zone="datatype-oid">
<primary>regclass</primary>
</indexterm>
@@ -4805,6 +4809,13 @@ INSERT INTO mytable VALUES(-1); -- fails
individual tables.
</para>
+ <para>
+ In some contexts, a 64-bit variant <type>oid8</type> is used.
+ It is implemented as an unsigned eight-byte integer. Unlike its
+ <type>oid</type> counterpart, it can ensure uniqueness in large
+ individual tables.
+ </para>
+
<para>
The <type>oid</type> type itself has few operations beyond comparison.
It can be cast to integer, however, and then manipulated using the
diff --git a/doc/src/sgml/func/func-aggregate.sgml b/doc/src/sgml/func/func-aggregate.sgml
index f50b692516b6..a5396048adf3 100644
--- a/doc/src/sgml/func/func-aggregate.sgml
+++ b/doc/src/sgml/func/func-aggregate.sgml
@@ -508,8 +508,8 @@
Computes the maximum of the non-null input
values. Available for any numeric, string, date/time, or enum type,
as well as <type>bytea</type>, <type>inet</type>, <type>interval</type>,
- <type>money</type>, <type>oid</type>, <type>pg_lsn</type>,
- <type>tid</type>, <type>xid8</type>,
+ <type>money</type>, <type>oid</type>, <type>oid8</type>,
+ <type>pg_lsn</type>, <type>tid</type>, <type>xid8</type>,
and also arrays and composite types containing sortable data types.
</para></entry>
<entry>Yes</entry>
@@ -527,8 +527,8 @@
Computes the minimum of the non-null input
values. Available for any numeric, string, date/time, or enum type,
as well as <type>bytea</type>, <type>inet</type>, <type>interval</type>,
- <type>money</type>, <type>oid</type>, <type>pg_lsn</type>,
- <type>tid</type>, <type>xid8</type>,
+ <type>money</type>, <type>oid</type>, <type>oid8</type>,
+ <type>pg_lsn</type>, <type>tid</type>, <type>xid8</type>,
and also arrays and composite types containing sortable data types.
</para></entry>
<entry>Yes</entry>
--
2.50.0