From: Michael Paquier Date: Wed, 7 Jan 2026 02:37:00 +0000 (+0900) Subject: Add data type oid8, 64-bit unsigned identifier X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b139bd3b6ef000ab5d00dd47128e366a726da5f9;p=thirdparty%2Fpostgresql.git Add data type oid8, 64-bit unsigned identifier 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 Reviewed-by: Greg Burd Reviewed-by: Nikhil Kumar Veldanda Discussion: https://postgr.es/m/1891064.1754681536@sss.pgh.pa.us --- diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index e5267a8e4be..e51423c0111 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -4724,6 +4724,10 @@ INSERT INTO mytable VALUES(-1); -- fails oid + + oid8 + + regclass @@ -4807,8 +4811,16 @@ INSERT INTO mytable VALUES(-1); -- fails - The oid 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 oid8 can be used. + It is implemented as an unsigned eight-byte integer. Unlike its + oid counterpart, it can ensure uniqueness in large + individual tables. + + + + The oid and oid8 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.) diff --git a/doc/src/sgml/func/func-aggregate.sgml b/doc/src/sgml/func/func-aggregate.sgml index 8031cde2c96..8b5eaeb2e94 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 bytea, inet, interval, - money, oid, pg_lsn, - tid, xid8, + money, oid, oid8, + pg_lsn, tid, xid8, and also arrays and composite types containing sortable data types. Yes @@ -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 bytea, inet, interval, - money, oid, pg_lsn, - tid, xid8, + money, oid, oid8, + pg_lsn, tid, xid8, and also arrays and composite types containing sortable data types. Yes diff --git a/src/backend/access/nbtree/nbtcompare.c b/src/backend/access/nbtree/nbtcompare.c index bffc4b7709c..8425805a292 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 832b33839b6..dd57624b4f9 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 ba40ada11ca..a8fd680589f 100644 --- a/src/backend/utils/adt/Makefile +++ b/src/backend/utils/adt/Makefile @@ -77,6 +77,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 d4509206217..37d34685b93 100644 --- a/src/backend/utils/adt/int8.c +++ b/src/backend/utils/adt/int8.c @@ -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 */ diff --git a/src/backend/utils/adt/meson.build b/src/backend/utils/adt/meson.build index 9d0566910c2..fb8294d7e4a 100644 --- a/src/backend/utils/adt/meson.build +++ b/src/backend/utils/adt/meson.build @@ -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 index 00000000000..cfebcb13428 --- /dev/null +++ b/src/backend/utils/adt/oid8.c @@ -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); +} diff --git a/src/fe_utils/print.c b/src/fe_utils/print.c index d46c7c38ffa..ef52cdee9b7 100644 --- a/src/fe_utils/print.c +++ b/src/fe_utils/print.c @@ -3821,6 +3821,7 @@ column_type_alignment(Oid ftype) case FLOAT8OID: case NUMERICOID: case OIDOID: + case OID8OID: case XIDOID: case XID8OID: case CIDOID: diff --git a/src/include/c.h b/src/include/c.h index 5c4d769d451..335af3352d1 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -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) diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 4eb435eb1ec..0ebaba0867e 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -57,6 +57,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202601041 +#define CATALOG_VERSION_NO 202601071 #endif diff --git a/src/include/catalog/pg_aggregate.dat b/src/include/catalog/pg_aggregate.dat index 631fc29a92b..75d4604a0b2 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 d1bd641db3a..8d5a0004a47 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 75cbaea7a02..4a1efdbc899 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 1b718a15044..9b1cfb1b590 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 6af8699652f..0eddd0298f8 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 1f064d8ea16..1465f13120a 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 47098fdf35a..7a027c4810e 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 7f481687afe..2ac69bf2df5 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' }, @@ -12619,4 +12628,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 058785d66a4..a1a753d1797 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 22dd6526169..eabbc78b280 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 9268e6832cc..7d93fbce709 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/test/regress/expected/hash_func.out b/src/test/regress/expected/hash_func.out index 2d625a247bb..6bc14f57a6b 100644 --- a/src/test/regress/expected/hash_func.out +++ b/src/test/regress/expected/hash_func.out @@ -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 index 00000000000..3689d21e7c5 --- /dev/null +++ b/src/test/regress/expected/oid8.out @@ -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; diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index a357e1d0c0e..6ff4d7ee901 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 943e56506bf..9ddcacec6bf 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 905f9bca959..021d57f66bb 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 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 diff --git a/src/test/regress/sql/hash_func.sql b/src/test/regress/sql/hash_func.sql index 33756bd288f..ce38da72c0b 100644 --- a/src/test/regress/sql/hash_func.sql +++ b/src/test/regress/sql/hash_func.sql @@ -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 index 00000000000..8bfaff01f12 --- /dev/null +++ b/src/test/regress/sql/oid8.sql @@ -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; diff --git a/src/test/regress/sql/type_sanity.sql b/src/test/regress/sql/type_sanity.sql index df795759bb4..c2496823d90 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,