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,