]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Add data type oid8, 64-bit unsigned identifier
authorMichael Paquier <michael@paquier.xyz>
Wed, 7 Jan 2026 02:37:00 +0000 (11:37 +0900)
committerMichael Paquier <michael@paquier.xyz>
Wed, 7 Jan 2026 02:37:00 +0000 (11:37 +0900)
This new identifier type provides support for 64-bit unsigned values,
to be used in catalogs, like OIDs.  An advantage of a new data type is
that it becomes easier to grep for it in the code when assigning this
type to a catalog attribute, linking it to dedicated APIs and internal
structures.

The following operators are added in this commit, with dedicated tests:
- Casts with integer types and OID.
- btree and hash operators
- min/max functions.
- C type with related macros and defines, named around "Oid8".

This has been mentioned as useful on its own on the thread to add
support for 64-bit TOAST values, so as it becomes possible to attach
this data type to the TOAST code and catalog definitions.  However, as
this concept can apply to many more areas, it is implemented as its own
independent change.  This is based on a discussion with Andres Freund
and Tom Lane.

Bump catalog version.

Author: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Greg Burd <greg@burd.me>
Reviewed-by: Nikhil Kumar Veldanda <veldanda.nikhilkumar17@gmail.com>
Discussion: https://postgr.es/m/1891064.1754681536@sss.pgh.pa.us

30 files changed:
doc/src/sgml/datatype.sgml
doc/src/sgml/func/func-aggregate.sgml
src/backend/access/nbtree/nbtcompare.c
src/backend/bootstrap/bootstrap.c
src/backend/utils/adt/Makefile
src/backend/utils/adt/int8.c
src/backend/utils/adt/meson.build
src/backend/utils/adt/oid8.c [new file with mode: 0644]
src/fe_utils/print.c
src/include/c.h
src/include/catalog/catversion.h
src/include/catalog/pg_aggregate.dat
src/include/catalog/pg_amop.dat
src/include/catalog/pg_amproc.dat
src/include/catalog/pg_cast.dat
src/include/catalog/pg_opclass.dat
src/include/catalog/pg_operator.dat
src/include/catalog/pg_opfamily.dat
src/include/catalog/pg_proc.dat
src/include/catalog/pg_type.dat
src/include/fmgr.h
src/include/postgres.h
src/test/regress/expected/hash_func.out
src/test/regress/expected/oid8.out [new file with mode: 0644]
src/test/regress/expected/opr_sanity.out
src/test/regress/expected/type_sanity.out
src/test/regress/parallel_schedule
src/test/regress/sql/hash_func.sql
src/test/regress/sql/oid8.sql [new file with mode: 0644]
src/test/regress/sql/type_sanity.sql

index e5267a8e4be61573c8cd9ff9f396ef7de56203a1..e51423c011155fd263f6af51af07eaa2c2c84006 100644 (file)
@@ -4724,6 +4724,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>
@@ -4807,8 +4811,16 @@ INSERT INTO mytable VALUES(-1);  -- fails
    </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
+    In some contexts, a 64-bit variant <type>oid8</type> can be 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> and <type>oid8</type> types themselves have
+    few operations beyond comparison.
+    they can be cast to integer, however, and then manipulated using the
     standard integer operators.  (Beware of possible
     signed-versus-unsigned confusion if you do this.)
    </para>
index 8031cde2c96c8394a9903636a05e01286df690b6..8b5eaeb2e94b636c8d5bf226ee2dfb01b84f4cd0 100644 (file)
         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>
         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>
index bffc4b7709cca3ac60207ce48525645b3677ceea..8425805a292956751a712fa0eb3a2cc031280192 100644 (file)
@@ -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)
 {
index 832b33839b68fda2281d26d98ae61829ae0880b6..dd57624b4f9c6106f75d5db12855f1608553924c 100644 (file)
@@ -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,
index ba40ada11cafa72613ba4ffdc080041ca6d5b508..a8fd680589f72e91841a4fd2c575acc3d5452f57 100644 (file)
@@ -77,6 +77,7 @@ OBJS = \
        numeric.o \
        numutils.o \
        oid.o \
+       oid8.o \
        oracle_compat.o \
        orderedsetaggs.o \
        partitionfuncs.o \
index d4509206217314ffe655aefa5b132cd42cd62ebb..37d34685b93254d90b41e0dc7ff2ea8c13e95b5d 100644 (file)
@@ -1370,6 +1370,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
  */
index 9d0566910c26572ab5cbd0871c2898c6341d7394..fb8294d7e4a3e911d127d6681490f81e55aaf96a 100644 (file)
@@ -73,6 +73,7 @@ backend_sources += files(
   'network_spgist.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 (file)
index 0000000..cfebcb1
--- /dev/null
@@ -0,0 +1,168 @@
+/*-------------------------------------------------------------------------
+ *
+ * oid8.c
+ *       Functions for the built-in type Oid8
+ *
+ * Portions Copyright (c) 1996-2026, 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 "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);
+}
index d46c7c38ffa947ffa0f57d4cc35007fe90cae015..ef52cdee9b7ee751d208f30da2e55e6ee4a3d156 100644 (file)
@@ -3821,6 +3821,7 @@ column_type_alignment(Oid ftype)
                case FLOAT8OID:
                case NUMERICOID:
                case OIDOID:
+               case OID8OID:
                case XIDOID:
                case XID8OID:
                case CIDOID:
index 5c4d769d451af4c3ee784b860cce95084be3c30b..335af3352d1a32bc2fbbccad8b03345638cc6713 100644 (file)
@@ -569,6 +569,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
@@ -655,7 +656,7 @@ typedef double float8;
 #define FLOAT8PASSBYVAL true
 
 /*
- * Oid, RegProcedure, TransactionId, SubTransactionId, MultiXactId,
+ * Oid, Oid8, RegProcedure, TransactionId, SubTransactionId, MultiXactId,
  * CommandId
  */
 
@@ -687,6 +688,11 @@ 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
 
 /* ----------------
  *             Variable-length datatypes all share the 'struct varlena' header.
@@ -787,6 +793,8 @@ typedef NameData *Name;
 
 #define OidIsValid(objectId)  ((bool) ((objectId) != InvalidOid))
 
+#define Oid8IsValid(objectId)  ((bool) ((objectId) != InvalidOid8))
+
 #define RegProcedureIsValid(p) OidIsValid(p)
 
 
index 4eb435eb1ecfc4167018065254e099dc858053b6..0ebaba0867ee424ee9c1e273309aa1ac65212764 100644 (file)
@@ -57,6 +57,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     202601041
+#define CATALOG_VERSION_NO     202601071
 
 #endif
index 631fc29a92b1e22065e4a0a747b0513e9b94d7a5..75d4604a0b212e82cf1938095e4d36d3ab3362dd 100644 (file)
 { 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' },
 { 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' },
index d1bd641db3a0cd6fccdb012f5b29cf6b600efa1a..8d5a0004a478a93bff433026753c10d60bd12635 100644 (file)
 { 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',
 { 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',
index 75cbaea7a0287b8d19636bc1f0db1f45d3e04809..4a1efdbc8998625cbe4e3a90cb1e1dcff275ab5d 100644 (file)
   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' },
   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',
index 1b718a1504428cfdadaccea3067d0613f3bf0ba8..9b1cfb1b59063511bdf0fec45e2709128585fce3 100644 (file)
 { 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' },
index 6af8699652f3f301319d5064d840821b94c0f58d..0eddd0298f83cecb78f3814599a586ee210a9856 100644 (file)
   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',
index 1f064d8ea160121214e7c2aa8ff9a1d67089e585..1465f13120ac5261af38b9e12e4b983ae8effcef 100644 (file)
   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' },
+
 ]
index 47098fdf35a296922d89518cb3b1813a01f738a2..7a027c4810ee0a8563224b0cc13fc9a824b385a3 100644 (file)
   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',
index 7f481687afebf9d0226646bc8d3e48b5b055d78f..2ac69bf2df55ae0148cc5822b12f02f99fa54110 100644 (file)
 { 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' },
   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' },
+
 ]
index 058785d66a40b9203734b42512adc8f07e9914a7..a1a753d17978c0c74889e9d9cb2edaa4f8169d49 100644 (file)
   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' },
 ]
index 22dd6526169e9f5a2799b9560d32dbf3cb8875a7..eabbc78b2801fd3f572a68eed91990414cfecc90 100644 (file)
@@ -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)
index 9268e6832ccb78d1fed5ea755928375f2c567d1b..7d93fbce7094a1a6db3aac5479f5e7ec1d4c7558 100644 (file)
@@ -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.
index 2d625a247bb91ca1b7eeed79032cb604e76117fe..6bc14f57a6bf4d982dd16fd231c12b3327288488 100644 (file)
@@ -65,6 +65,16 @@ WHERE  hashoid(v)::bit(32) != hashoidextended(v, 0)::bit(32)
 -------+----------+-----------+-----------
 (0 rows)
 
+SELECT v as value, hashoid8(v)::bit(32) as standard,
+       hashoid8extended(v, 0)::bit(32) as extended0,
+       hashoid8extended(v, 1)::bit(32) as extended1
+FROM   (VALUES (0), (1), (17), (42), (550273), (207112489)) x(v)
+WHERE  hashoid8(v)::bit(32) != hashoid8extended(v, 0)::bit(32)
+       OR hashoid8(v)::bit(32) = hashoid8extended(v, 1)::bit(32);
+ value | standard | extended0 | extended1 
+-------+----------+-----------+-----------
+(0 rows)
+
 SELECT v as value, hashchar(v)::bit(32) as standard,
        hashcharextended(v, 0)::bit(32) as extended0,
        hashcharextended(v, 1)::bit(32) as extended1
diff --git a/src/test/regress/expected/oid8.out b/src/test/regress/expected/oid8.out
new file mode 100644 (file)
index 0000000..3689d21
--- /dev/null
@@ -0,0 +1,368 @@
+--
+-- 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  ');
+INSERT INTO OID8_TBL(f1) VALUES ('123456789012345678');
+-- UINT64_MAX
+INSERT INTO OID8_TBL(f1) VALUES ('18446744073709551615');
+-- 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...
+                                         ^
+-- UINT64_MAX + 1
+INSERT INTO OID8_TBL(f1) VALUES ('18446744073709551616');
+ERROR:  value "18446744073709551616" is out of range for type oid8
+LINE 1: INSERT INTO OID8_TBL(f1) VALUES ('18446744073709551616');
+                                         ^
+SELECT * FROM OID8_TBL;
+          f1          
+----------------------
+                 1234
+                 1235
+                  987
+ 18446744073709550576
+             99999999
+                    5
+                   10
+   123456789012345678
+ 18446744073709551615
+                   15
+(10 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
+   123456789012345678
+ 18446744073709551615
+                   15
+(9 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
+   123456789012345678
+ 18446744073709551615
+(6 rows)
+
+SELECT o.* FROM OID8_TBL o WHERE o.f1 > '1234';
+          f1          
+----------------------
+                 1235
+ 18446744073709550576
+             99999999
+   123456789012345678
+ 18446744073709551615
+(5 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 | 18446744073709551615
+(1 row)
+
+-- Check btree and hash opclasses
+EXPLAIN (COSTS OFF)
+SELECT DISTINCT (i || '000000000000' || j)::oid8 f
+  FROM generate_series(1, 10) i,
+       generate_series(1, 10) j,
+       generate_series(1, 5) k
+  WHERE i <= 10 AND j > 0 AND j <= 10
+  ORDER BY f;
+                                    QUERY PLAN                                     
+-----------------------------------------------------------------------------------
+ Sort
+   Sort Key: (((((i.i)::text || '000000000000'::text) || (j.j)::text))::oid8)
+   ->  HashAggregate
+         Group Key: ((((i.i)::text || '000000000000'::text) || (j.j)::text))::oid8
+         ->  Nested Loop
+               ->  Function Scan on generate_series k
+               ->  Materialize
+                     ->  Nested Loop
+                           ->  Function Scan on generate_series j
+                                 Filter: ((j > 0) AND (j <= 10))
+                           ->  Function Scan on generate_series i
+                                 Filter: (i <= 10)
+(12 rows)
+
+SELECT DISTINCT (i || '000000000000' || j)::oid8 f
+  FROM generate_series(1, 10) i,
+       generate_series(1, 10) j,
+       generate_series(1, 5) k
+  WHERE i <= 10 AND j > 0 AND j <= 10
+  ORDER BY f;
+        f         
+------------------
+   10000000000001
+   10000000000002
+   10000000000003
+   10000000000004
+   10000000000005
+   10000000000006
+   10000000000007
+   10000000000008
+   10000000000009
+   20000000000001
+   20000000000002
+   20000000000003
+   20000000000004
+   20000000000005
+   20000000000006
+   20000000000007
+   20000000000008
+   20000000000009
+   30000000000001
+   30000000000002
+   30000000000003
+   30000000000004
+   30000000000005
+   30000000000006
+   30000000000007
+   30000000000008
+   30000000000009
+   40000000000001
+   40000000000002
+   40000000000003
+   40000000000004
+   40000000000005
+   40000000000006
+   40000000000007
+   40000000000008
+   40000000000009
+   50000000000001
+   50000000000002
+   50000000000003
+   50000000000004
+   50000000000005
+   50000000000006
+   50000000000007
+   50000000000008
+   50000000000009
+   60000000000001
+   60000000000002
+   60000000000003
+   60000000000004
+   60000000000005
+   60000000000006
+   60000000000007
+   60000000000008
+   60000000000009
+   70000000000001
+   70000000000002
+   70000000000003
+   70000000000004
+   70000000000005
+   70000000000006
+   70000000000007
+   70000000000008
+   70000000000009
+   80000000000001
+   80000000000002
+   80000000000003
+   80000000000004
+   80000000000005
+   80000000000006
+   80000000000007
+   80000000000008
+   80000000000009
+   90000000000001
+   90000000000002
+   90000000000003
+   90000000000004
+   90000000000005
+   90000000000006
+   90000000000007
+   90000000000008
+   90000000000009
+  100000000000001
+  100000000000002
+  100000000000003
+  100000000000004
+  100000000000005
+  100000000000006
+  100000000000007
+  100000000000008
+  100000000000009
+  100000000000010
+  200000000000010
+  300000000000010
+  400000000000010
+  500000000000010
+  600000000000010
+  700000000000010
+  800000000000010
+  900000000000010
+ 1000000000000010
+(100 rows)
+
+-- 3-way compare for btrees
+SELECT btoid8cmp(1::oid8, 2::oid8);
+ btoid8cmp 
+-----------
+        -1
+(1 row)
+
+SELECT btoid8cmp(2::oid8, 2::oid8);
+ btoid8cmp 
+-----------
+         0
+(1 row)
+
+SELECT btoid8cmp(2::oid8, 1::oid8);
+ btoid8cmp 
+-----------
+         1
+(1 row)
+
+-- oid8 has btree and hash opclasses
+CREATE INDEX on OID8_TBL USING btree(f1);
+CREATE INDEX ON OID8_TBL USING hash(f1);
+DROP TABLE OID8_TBL;
index a357e1d0c0e1842f95974a6ab26d063d80174d69..6ff4d7ee90145a1b9d776bac07bcb6bc3d8d839c 100644 (file)
@@ -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
index 943e56506bf1bec6bcdce8b634a16a75f5345863..9ddcacec6bf46bd23d0dd27a3563f3e7f48f1c02 100644 (file)
@@ -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,
index 905f9bca95987fa93fbf361b9684c38188dceba3..021d57f66bbd19858a2ccc2067ceec47a6be8e41 100644 (file)
@@ -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 pg_ndistinct pg_dependencies
+test: geometry horology tstypes regex type_sanity opr_sanity misc_sanity comments expressions unicode xid mvcc database stats_import pg_ndistinct pg_dependencies oid8
 
 # ----------
 # Load huge amounts of data
index 33756bd288ff3f517d3d8537ae422fea1d6c29dd..ce38da72c0bddf5b69bbc7de16a2b90ddd6579cd 100644 (file)
@@ -48,6 +48,13 @@ FROM   (VALUES (0), (1), (17), (42), (550273), (207112489)) x(v)
 WHERE  hashoid(v)::bit(32) != hashoidextended(v, 0)::bit(32)
        OR hashoid(v)::bit(32) = hashoidextended(v, 1)::bit(32);
 
+SELECT v as value, hashoid8(v)::bit(32) as standard,
+       hashoid8extended(v, 0)::bit(32) as extended0,
+       hashoid8extended(v, 1)::bit(32) as extended1
+FROM   (VALUES (0), (1), (17), (42), (550273), (207112489)) x(v)
+WHERE  hashoid8(v)::bit(32) != hashoid8extended(v, 0)::bit(32)
+       OR hashoid8(v)::bit(32) = hashoid8extended(v, 1)::bit(32);
+
 SELECT v as value, hashchar(v)::bit(32) as standard,
        hashcharextended(v, 0)::bit(32) as extended0,
        hashcharextended(v, 1)::bit(32) as extended1
diff --git a/src/test/regress/sql/oid8.sql b/src/test/regress/sql/oid8.sql
new file mode 100644 (file)
index 0000000..8bfaff0
--- /dev/null
@@ -0,0 +1,87 @@
+--
+-- 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  ');
+INSERT INTO OID8_TBL(f1) VALUES ('123456789012345678');
+-- UINT64_MAX
+INSERT INTO OID8_TBL(f1) VALUES ('18446744073709551615');
+-- 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');
+-- UINT64_MAX + 1
+INSERT INTO OID8_TBL(f1) VALUES ('18446744073709551616');
+
+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;
+
+-- Check btree and hash opclasses
+EXPLAIN (COSTS OFF)
+SELECT DISTINCT (i || '000000000000' || j)::oid8 f
+  FROM generate_series(1, 10) i,
+       generate_series(1, 10) j,
+       generate_series(1, 5) k
+  WHERE i <= 10 AND j > 0 AND j <= 10
+  ORDER BY f;
+
+SELECT DISTINCT (i || '000000000000' || j)::oid8 f
+  FROM generate_series(1, 10) i,
+       generate_series(1, 10) j,
+       generate_series(1, 5) k
+  WHERE i <= 10 AND j > 0 AND j <= 10
+  ORDER BY f;
+
+-- 3-way compare for btrees
+SELECT btoid8cmp(1::oid8, 2::oid8);
+SELECT btoid8cmp(2::oid8, 2::oid8);
+SELECT btoid8cmp(2::oid8, 1::oid8);
+
+-- oid8 has btree and hash opclasses
+CREATE INDEX on OID8_TBL USING btree(f1);
+CREATE INDEX ON OID8_TBL USING hash(f1);
+
+DROP TABLE OID8_TBL;
index df795759bb4cbfa83748cc8f086b406d6e86bc03..c2496823d90eb6262d10b1792d4027b56c89f76c 100644 (file)
@@ -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,