Commit aeec457d authored by Thomas Munro's avatar Thomas Munro

Add SQL type xid8 to expose FullTransactionId to users.

Similar to xid, but 64 bits wide.  This new type is suitable for use in
various system views and administration functions.
Reviewed-by: default avatarFujii Masao <masao.fujii@oss.nttdata.com>
Reviewed-by: default avatarTakao Fujii <btfujiitkp@oss.nttdata.com>
Reviewed-by: default avatarYoshikazu Imai <imai.yoshikazu@fujitsu.com>
Reviewed-by: default avatarMark Dilger <mark.dilger@enterprisedb.com>
Discussion: https://postgr.es/m/20190725000636.666m5mad25wfbrri%40alap3.anarazel.de
parent 4bea576b
...@@ -4516,6 +4516,10 @@ INSERT INTO mytable VALUES(-1); -- fails ...@@ -4516,6 +4516,10 @@ INSERT INTO mytable VALUES(-1); -- fails
<primary>regtype</primary> <primary>regtype</primary>
</indexterm> </indexterm>
<indexterm zone="datatype-oid">
<primary>xid8</primary>
</indexterm>
<indexterm zone="datatype-oid"> <indexterm zone="datatype-oid">
<primary>cid</primary> <primary>cid</primary>
</indexterm> </indexterm>
...@@ -4719,6 +4723,9 @@ SELECT * FROM pg_attribute ...@@ -4719,6 +4723,9 @@ SELECT * FROM pg_attribute
Another identifier type used by the system is <type>xid</type>, or transaction Another identifier type used by the system is <type>xid</type>, or transaction
(abbreviated <abbrev>xact</abbrev>) identifier. This is the data type of the system columns (abbreviated <abbrev>xact</abbrev>) identifier. This is the data type of the system columns
<structfield>xmin</structfield> and <structfield>xmax</structfield>. Transaction identifiers are 32-bit quantities. <structfield>xmin</structfield> and <structfield>xmax</structfield>. Transaction identifiers are 32-bit quantities.
In some contexts, a 64-bit variant <type>xid8</type> is used. Unlike
<type>xid</type> values, <type>xid8</type> values increase strictly
monotonically and cannot be reused in the lifetime of a database cluster.
</para> </para>
<para> <para>
......
...@@ -317,6 +317,9 @@ check_hash_func_signature(Oid funcid, int16 amprocnum, Oid argtype) ...@@ -317,6 +317,9 @@ check_hash_func_signature(Oid funcid, int16 amprocnum, Oid argtype)
(argtype == DATEOID || (argtype == DATEOID ||
argtype == XIDOID || argtype == CIDOID)) argtype == XIDOID || argtype == CIDOID))
/* okay, allowed use of hashint4() */ ; /* okay, allowed use of hashint4() */ ;
else if ((funcid == F_HASHINT8 || funcid == F_HASHINT8EXTENDED) &&
(argtype == XID8OID))
/* okay, allowed use of hashint8() */ ;
else if ((funcid == F_TIMESTAMP_HASH || else if ((funcid == F_TIMESTAMP_HASH ||
funcid == F_TIMESTAMP_HASH_EXTENDED) && funcid == F_TIMESTAMP_HASH_EXTENDED) &&
argtype == TIMESTAMPTZOID) argtype == TIMESTAMPTZOID)
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "access/xact.h" #include "access/xact.h"
#include "libpq/pqformat.h" #include "libpq/pqformat.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/xid8.h"
#define PG_GETARG_TRANSACTIONID(n) DatumGetTransactionId(PG_GETARG_DATUM(n)) #define PG_GETARG_TRANSACTIONID(n) DatumGetTransactionId(PG_GETARG_DATUM(n))
#define PG_RETURN_TRANSACTIONID(x) return TransactionIdGetDatum(x) #define PG_RETURN_TRANSACTIONID(x) return TransactionIdGetDatum(x)
...@@ -147,6 +148,121 @@ xidComparator(const void *arg1, const void *arg2) ...@@ -147,6 +148,121 @@ xidComparator(const void *arg1, const void *arg2)
return 0; return 0;
} }
Datum
xid8toxid(PG_FUNCTION_ARGS)
{
FullTransactionId fxid = PG_GETARG_FULLTRANSACTIONID(0);
PG_RETURN_TRANSACTIONID(XidFromFullTransactionId(fxid));
}
Datum
xid8in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
PG_RETURN_FULLTRANSACTIONID(FullTransactionIdFromU64(pg_strtouint64(str, NULL, 0)));
}
Datum
xid8out(PG_FUNCTION_ARGS)
{
FullTransactionId fxid = PG_GETARG_FULLTRANSACTIONID(0);
char *result = (char *) palloc(21);
snprintf(result, 21, UINT64_FORMAT, U64FromFullTransactionId(fxid));
PG_RETURN_CSTRING(result);
}
Datum
xid8recv(PG_FUNCTION_ARGS)
{
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
uint64 value;
value = (uint64) pq_getmsgint64(buf);
PG_RETURN_FULLTRANSACTIONID(FullTransactionIdFromU64(value));
}
Datum
xid8send(PG_FUNCTION_ARGS)
{
FullTransactionId arg1 = PG_GETARG_FULLTRANSACTIONID(0);
StringInfoData buf;
pq_begintypsend(&buf);
pq_sendint64(&buf, (uint64) U64FromFullTransactionId(arg1));
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
Datum
xid8eq(PG_FUNCTION_ARGS)
{
FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
PG_RETURN_BOOL(FullTransactionIdEquals(fxid1, fxid2));
}
Datum
xid8ne(PG_FUNCTION_ARGS)
{
FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
PG_RETURN_BOOL(!FullTransactionIdEquals(fxid1, fxid2));
}
Datum
xid8lt(PG_FUNCTION_ARGS)
{
FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
PG_RETURN_BOOL(FullTransactionIdPrecedes(fxid1, fxid2));
}
Datum
xid8gt(PG_FUNCTION_ARGS)
{
FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
PG_RETURN_BOOL(FullTransactionIdFollows(fxid1, fxid2));
}
Datum
xid8le(PG_FUNCTION_ARGS)
{
FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
PG_RETURN_BOOL(FullTransactionIdPrecedesOrEquals(fxid1, fxid2));
}
Datum
xid8ge(PG_FUNCTION_ARGS)
{
FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
PG_RETURN_BOOL(FullTransactionIdFollowsOrEquals(fxid1, fxid2));
}
Datum
xid8cmp(PG_FUNCTION_ARGS)
{
FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
if (FullTransactionIdFollows(fxid1, fxid2))
PG_RETURN_INT32(1);
else if (FullTransactionIdEquals(fxid1, fxid2))
PG_RETURN_INT32(0);
else
PG_RETURN_INT32(-1);
}
/***************************************************************************** /*****************************************************************************
* COMMAND IDENTIFIER ROUTINES * * COMMAND IDENTIFIER ROUTINES *
*****************************************************************************/ *****************************************************************************/
......
...@@ -3509,6 +3509,7 @@ column_type_alignment(Oid ftype) ...@@ -3509,6 +3509,7 @@ column_type_alignment(Oid ftype)
case NUMERICOID: case NUMERICOID:
case OIDOID: case OIDOID:
case XIDOID: case XIDOID:
case XID8OID:
case CIDOID: case CIDOID:
case CASHOID: case CASHOID:
align = 'r'; align = 'r';
......
...@@ -47,7 +47,11 @@ ...@@ -47,7 +47,11 @@
#define EpochFromFullTransactionId(x) ((uint32) ((x).value >> 32)) #define EpochFromFullTransactionId(x) ((uint32) ((x).value >> 32))
#define XidFromFullTransactionId(x) ((uint32) (x).value) #define XidFromFullTransactionId(x) ((uint32) (x).value)
#define U64FromFullTransactionId(x) ((x).value) #define U64FromFullTransactionId(x) ((x).value)
#define FullTransactionIdEquals(a, b) ((a).value == (b).value)
#define FullTransactionIdPrecedes(a, b) ((a).value < (b).value) #define FullTransactionIdPrecedes(a, b) ((a).value < (b).value)
#define FullTransactionIdPrecedesOrEquals(a, b) ((a).value <= (b).value)
#define FullTransactionIdFollows(a, b) ((a).value > (b).value)
#define FullTransactionIdFollowsOrEquals(a, b) ((a).value >= (b).value)
#define FullTransactionIdIsValid(x) TransactionIdIsValid(XidFromFullTransactionId(x)) #define FullTransactionIdIsValid(x) TransactionIdIsValid(XidFromFullTransactionId(x))
#define InvalidFullTransactionId FullTransactionIdFromEpochAndXid(0, InvalidTransactionId) #define InvalidFullTransactionId FullTransactionIdFromEpochAndXid(0, InvalidTransactionId)
...@@ -71,6 +75,16 @@ FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid) ...@@ -71,6 +75,16 @@ FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
return result; return result;
} }
static inline FullTransactionId
FullTransactionIdFromU64(uint64 value)
{
FullTransactionId result;
result.value = value;
return result;
}
/* advance a transaction ID variable, handling wraparound correctly */ /* advance a transaction ID variable, handling wraparound correctly */
#define TransactionIdAdvance(dest) \ #define TransactionIdAdvance(dest) \
do { \ do { \
......
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 202004022 #define CATALOG_VERSION_NO 202004061
#endif #endif
...@@ -180,6 +180,24 @@ ...@@ -180,6 +180,24 @@
{ amopfamily => 'btree/oid_ops', amoplefttype => 'oid', amoprighttype => 'oid', { amopfamily => 'btree/oid_ops', amoplefttype => 'oid', amoprighttype => 'oid',
amopstrategy => '5', amopopr => '>(oid,oid)', amopmethod => 'btree' }, amopstrategy => '5', amopopr => '>(oid,oid)', amopmethod => 'btree' },
# btree xid8_ops
{ amopfamily => 'btree/xid8_ops', amoplefttype => 'xid8',
amoprighttype => 'xid8', amopstrategy => '1', amopopr => '<(xid8,xid8)',
amopmethod => 'btree' },
{ amopfamily => 'btree/xid8_ops', amoplefttype => 'xid8',
amoprighttype => 'xid8', amopstrategy => '2', amopopr => '<=(xid8,xid8)',
amopmethod => 'btree' },
{ amopfamily => 'btree/xid8_ops', amoplefttype => 'xid8',
amoprighttype => 'xid8', amopstrategy => '3', amopopr => '=(xid8,xid8)',
amopmethod => 'btree' },
{ amopfamily => 'btree/xid8_ops', amoplefttype => 'xid8',
amoprighttype => 'xid8', amopstrategy => '4', amopopr => '>=(xid8,xid8)',
amopmethod => 'btree' },
{ amopfamily => 'btree/xid8_ops', amoplefttype => 'xid8',
amoprighttype => 'xid8', amopstrategy => '5', amopopr => '>(xid8,xid8)',
amopmethod => 'btree' },
# btree tid_ops # btree tid_ops
{ amopfamily => 'btree/tid_ops', amoplefttype => 'tid', amoprighttype => 'tid', { amopfamily => 'btree/tid_ops', amoplefttype => 'tid', amoprighttype => 'tid',
...@@ -1009,6 +1027,10 @@ ...@@ -1009,6 +1027,10 @@
{ amopfamily => 'hash/xid_ops', amoplefttype => 'xid', amoprighttype => 'xid', { amopfamily => 'hash/xid_ops', amoplefttype => 'xid', amoprighttype => 'xid',
amopstrategy => '1', amopopr => '=(xid,xid)', amopmethod => 'hash' }, amopstrategy => '1', amopopr => '=(xid,xid)', amopmethod => 'hash' },
# xid8_ops
{ amopfamily => 'hash/xid8_ops', amoplefttype => 'xid8', amoprighttype => 'xid8',
amopstrategy => '1', amopopr => '=(xid8,xid8)', amopmethod => 'hash' },
# cid_ops # cid_ops
{ amopfamily => 'hash/cid_ops', amoplefttype => 'cid', amoprighttype => 'cid', { amopfamily => 'hash/cid_ops', amoplefttype => 'cid', amoprighttype => 'cid',
amopstrategy => '1', amopopr => '=(cid,cid)', amopmethod => 'hash' }, amopstrategy => '1', amopopr => '=(cid,cid)', amopmethod => 'hash' },
......
...@@ -287,6 +287,10 @@ ...@@ -287,6 +287,10 @@
amprocrighttype => 'anyrange', amprocnum => '1', amproc => 'range_cmp' }, amprocrighttype => 'anyrange', amprocnum => '1', amproc => 'range_cmp' },
{ amprocfamily => 'btree/jsonb_ops', amproclefttype => 'jsonb', { amprocfamily => 'btree/jsonb_ops', amproclefttype => 'jsonb',
amprocrighttype => 'jsonb', amprocnum => '1', amproc => 'jsonb_cmp' }, amprocrighttype => 'jsonb', amprocnum => '1', amproc => 'jsonb_cmp' },
{ amprocfamily => 'btree/xid8_ops', amproclefttype => 'xid8',
amprocrighttype => 'xid8', amprocnum => '1', amproc => 'xid8cmp' },
{ amprocfamily => 'btree/xid8_ops', amproclefttype => 'xid8',
amprocrighttype => 'xid8', amprocnum => '4', amproc => 'btequalimage' },
# hash # hash
{ amprocfamily => 'hash/bpchar_ops', amproclefttype => 'bpchar', { amprocfamily => 'hash/bpchar_ops', amproclefttype => 'bpchar',
...@@ -399,6 +403,10 @@ ...@@ -399,6 +403,10 @@
amprocrighttype => 'xid', amprocnum => '1', amproc => 'hashint4' }, amprocrighttype => 'xid', amprocnum => '1', amproc => 'hashint4' },
{ amprocfamily => 'hash/xid_ops', amproclefttype => 'xid', { amprocfamily => 'hash/xid_ops', amproclefttype => 'xid',
amprocrighttype => 'xid', amprocnum => '2', amproc => 'hashint4extended' }, amprocrighttype => 'xid', amprocnum => '2', amproc => 'hashint4extended' },
{ amprocfamily => 'hash/xid8_ops', amproclefttype => 'xid8',
amprocrighttype => 'xid8', amprocnum => '1', amproc => 'hashint8' },
{ amprocfamily => 'hash/xid8_ops', amproclefttype => 'xid8',
amprocrighttype => 'xid8', amprocnum => '2', amproc => 'hashint8extended' },
{ amprocfamily => 'hash/cid_ops', amproclefttype => 'cid', { amprocfamily => 'hash/cid_ops', amproclefttype => 'cid',
amprocrighttype => 'cid', amprocnum => '1', amproc => 'hashint4' }, amprocrighttype => 'cid', amprocnum => '1', amproc => 'hashint4' },
{ amprocfamily => 'hash/cid_ops', amproclefttype => 'cid', { amprocfamily => 'hash/cid_ops', amproclefttype => 'cid',
......
...@@ -93,6 +93,10 @@ ...@@ -93,6 +93,10 @@
{ castsource => 'bool', casttarget => 'int4', castfunc => 'int4(bool)', { castsource => 'bool', casttarget => 'int4', castfunc => 'int4(bool)',
castcontext => 'e', castmethod => 'f' }, castcontext => 'e', castmethod => 'f' },
# Allow explicit coercions between xid8 and xid
{ castsource => 'xid8', casttarget => 'xid', castfunc => 'xid(xid8)',
castcontext => 'e', castmethod => 'f' },
# OID category: allow implicit conversion from any integral type (including # OID category: allow implicit conversion from any integral type (including
# int8, to support OID literals > 2G) to OID, as well as assignment coercion # int8, to support OID literals > 2G) to OID, as well as assignment coercion
# from OID to int4 or int8. Similarly for each OID-alias type. Also allow # from OID to int4 or int8. Similarly for each OID-alias type. Also allow
......
...@@ -168,6 +168,10 @@ ...@@ -168,6 +168,10 @@
opcintype => 'tid' }, opcintype => 'tid' },
{ opcmethod => 'hash', opcname => 'xid_ops', opcfamily => 'hash/xid_ops', { opcmethod => 'hash', opcname => 'xid_ops', opcfamily => 'hash/xid_ops',
opcintype => 'xid' }, opcintype => 'xid' },
{ opcmethod => 'hash', opcname => 'xid8_ops', opcfamily => 'hash/xid8_ops',
opcintype => 'xid8' },
{ opcmethod => 'btree', opcname => 'xid8_ops', opcfamily => 'btree/xid8_ops',
opcintype => 'xid8' },
{ opcmethod => 'hash', opcname => 'cid_ops', opcfamily => 'hash/cid_ops', { opcmethod => 'hash', opcname => 'cid_ops', opcfamily => 'hash/cid_ops',
opcintype => 'cid' }, opcintype => 'cid' },
{ opcmethod => 'hash', opcname => 'tid_ops', opcfamily => 'hash/tid_ops', { opcmethod => 'hash', opcname => 'tid_ops', opcfamily => 'hash/tid_ops',
......
...@@ -193,6 +193,31 @@ ...@@ -193,6 +193,31 @@
oprname => '<>', oprleft => 'xid', oprright => 'int4', oprresult => 'bool', oprname => '<>', oprleft => 'xid', oprright => 'int4', oprresult => 'bool',
oprnegate => '=(xid,int4)', oprcode => 'xidneqint4', oprrest => 'neqsel', oprnegate => '=(xid,int4)', oprcode => 'xidneqint4', oprrest => 'neqsel',
oprjoin => 'neqjoinsel' }, oprjoin => 'neqjoinsel' },
{ oid => '9418', descr => 'equal',
oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'xid8',
oprright => 'xid8', oprresult => 'bool', oprcom => '=(xid8,xid8)',
oprnegate => '<>(xid8,xid8)', oprcode => 'xid8eq', oprrest => 'eqsel',
oprjoin => 'eqjoinsel' },
{ oid => '9422', descr => 'not equal',
oprname => '<>', oprleft => 'xid8', oprright => 'xid8',
oprresult => 'bool', oprcom => '<>(xid8,xid8)', oprnegate => '=(xid8,xid8)',
oprcode => 'xid8ne', oprrest => 'neqsel', oprjoin => 'neqjoinsel' },
{ oid => '9432', descr => 'less than',
oprname => '<', oprleft => 'xid8', oprright => 'xid8', oprresult => 'bool',
oprcom => '>(xid8,xid8)', oprnegate => '>=(xid8,xid8)', oprcode => 'xid8lt',
oprrest => 'scalarltsel', oprjoin => 'scalarltjoinsel' },
{ oid => '9433', descr => 'greater than',
oprname => '>', oprleft => 'xid8', oprright => 'xid8', oprresult => 'bool',
oprcom => '<(xid8,xid8)', oprnegate => '<=(xid8,xid8)', oprcode => 'xid8gt',
oprrest => 'scalargtsel', oprjoin => 'scalargtjoinsel' },
{ oid => '9434', descr => 'less than or equal',
oprname => '<=', oprleft => 'xid8', oprright => 'xid8', oprresult => 'bool',
oprcom => '>=(xid8,xid8)', oprnegate => '>(xid8,xid8)', oprcode => 'xid8le',
oprrest => 'scalarlesel', oprjoin => 'scalarlejoinsel' },
{ oid => '9435', descr => 'greater than or equal',
oprname => '>=', oprleft => 'xid8', oprright => 'xid8', oprresult => 'bool',
oprcom => '<=(xid8,xid8)', oprnegate => '<(xid8,xid8)', oprcode => 'xid8ge',
oprrest => 'scalargesel', oprjoin => 'scalargejoinsel' },
{ oid => '388', descr => 'factorial', { oid => '388', descr => 'factorial',
oprname => '!', oprkind => 'r', oprleft => 'int8', oprright => '0', oprname => '!', oprkind => 'r', oprleft => 'int8', oprright => '0',
oprresult => 'numeric', oprcode => 'numeric_fac' }, oprresult => 'numeric', oprcode => 'numeric_fac' },
......
...@@ -110,6 +110,10 @@ ...@@ -110,6 +110,10 @@
opfmethod => 'btree', opfname => 'tid_ops' }, opfmethod => 'btree', opfname => 'tid_ops' },
{ oid => '2225', { oid => '2225',
opfmethod => 'hash', opfname => 'xid_ops' }, opfmethod => 'hash', opfname => 'xid_ops' },
{ oid => '8164',
opfmethod => 'hash', opfname => 'xid8_ops' },
{ oid => '9322',
opfmethod => 'btree', opfname => 'xid8_ops' },
{ oid => '2226', { oid => '2226',
opfmethod => 'hash', opfname => 'cid_ops' }, opfmethod => 'hash', opfname => 'cid_ops' },
{ oid => '2227', { oid => '2227',
......
...@@ -112,6 +112,18 @@ ...@@ -112,6 +112,18 @@
{ oid => '51', descr => 'I/O', { oid => '51', descr => 'I/O',
proname => 'xidout', prorettype => 'cstring', proargtypes => 'xid', proname => 'xidout', prorettype => 'cstring', proargtypes => 'xid',
prosrc => 'xidout' }, prosrc => 'xidout' },
{ oid => '9420', descr => 'I/O',
proname => 'xid8in', prorettype => 'xid8', proargtypes => 'cstring',
prosrc => 'xid8in' },
{ oid => '9554', descr => 'I/O',
proname => 'xid8out', prorettype => 'cstring', proargtypes => 'xid8',
prosrc => 'xid8out' },
{ oid => '9555', descr => 'I/O',
proname => 'xid8recv', prorettype => 'xid8', proargtypes => 'internal',
prosrc => 'xid8recv' },
{ oid => '9556', descr => 'I/O',
proname => 'xid8send', prorettype => 'bytea', proargtypes => 'xid8',
prosrc => 'xid8send' },
{ oid => '52', descr => 'I/O', { oid => '52', descr => 'I/O',
proname => 'cidin', prorettype => 'cid', proargtypes => 'cstring', proname => 'cidin', prorettype => 'cid', proargtypes => 'cstring',
prosrc => 'cidin' }, prosrc => 'cidin' },
...@@ -163,6 +175,30 @@ ...@@ -163,6 +175,30 @@
{ oid => '3308', { oid => '3308',
proname => 'xidneq', proleakproof => 't', prorettype => 'bool', proname => 'xidneq', proleakproof => 't', prorettype => 'bool',
proargtypes => 'xid xid', prosrc => 'xidneq' }, proargtypes => 'xid xid', prosrc => 'xidneq' },
{ oid => '9557',
proname => 'xid8eq', proleakproof => 't', prorettype => 'bool',
proargtypes => 'xid8 xid8', prosrc => 'xid8eq' },
{ oid => '9558',
proname => 'xid8ne', proleakproof => 't', prorettype => 'bool',
proargtypes => 'xid8 xid8', prosrc => 'xid8ne' },
{ oid => '8295',
proname => 'xid8lt', proleakproof => 't', prorettype => 'bool',
proargtypes => 'xid8 xid8', prosrc => 'xid8lt' },
{ oid => '8296',
proname => 'xid8gt', proleakproof => 't', prorettype => 'bool',
proargtypes => 'xid8 xid8', prosrc => 'xid8gt' },
{ oid => '8297',
proname => 'xid8le', proleakproof => 't', prorettype => 'bool',
proargtypes => 'xid8 xid8', prosrc => 'xid8le' },
{ oid => '8298',
proname => 'xid8ge', proleakproof => 't', prorettype => 'bool',
proargtypes => 'xid8 xid8', prosrc => 'xid8ge' },
{ oid => '9912', descr => 'less-equal-greater',
proname => 'xid8cmp', proleakproof => 't', prorettype => 'int4',
proargtypes => 'xid8 xid8', prosrc => 'xid8cmp' },
{ oid => '9421', descr => 'convert xid8 to xid',
proname => 'xid', prorettype => 'xid', proargtypes => 'xid8',
prosrc => 'xid8toxid' },
{ oid => '69', { oid => '69',
proname => 'cideq', proleakproof => 't', prorettype => 'bool', proname => 'cideq', proleakproof => 't', prorettype => 'bool',
proargtypes => 'cid cid', prosrc => 'cideq' }, proargtypes => 'cid cid', prosrc => 'cideq' },
......
...@@ -177,6 +177,10 @@ ...@@ -177,6 +177,10 @@
typtype => 'p', typcategory => 'P', typinput => 'pg_ddl_command_in', typtype => 'p', typcategory => 'P', typinput => 'pg_ddl_command_in',
typoutput => 'pg_ddl_command_out', typreceive => 'pg_ddl_command_recv', typoutput => 'pg_ddl_command_out', typreceive => 'pg_ddl_command_recv',
typsend => 'pg_ddl_command_send', typalign => 'ALIGNOF_POINTER' }, typsend => 'pg_ddl_command_send', typalign => 'ALIGNOF_POINTER' },
{ oid => '9419', array_type_oid => '271', descr => 'full transaction id',
typname => 'xid8', typlen => '8', typbyval => 'FLOAT8PASSBYVAL',
typcategory => 'U', typinput => 'xid8in', typoutput => 'xid8out',
typreceive => 'xid8recv', typsend => 'xid8send', typalign => 'd' },
# OIDS 600 - 699 # OIDS 600 - 699
......
/*-------------------------------------------------------------------------
*
* xid8.h
* Header file for the "xid8" ADT.
*
* Copyright (c) 2020, PostgreSQL Global Development Group
*
* src/include/utils/xid8.h
*
*-------------------------------------------------------------------------
*/
#ifndef XID8_H
#define XID8_H
#include "access/transam.h"
#define DatumGetFullTransactionId(X) (FullTransactionIdFromU64(DatumGetUInt64(X)))
#define FullTransactionIdGetDatum(X) (UInt64GetDatum(U64FromFullTransactionId(X)))
#define PG_GETARG_FULLTRANSACTIONID(X) DatumGetFullTransactionId(PG_GETARG_DATUM(X))
#define PG_RETURN_FULLTRANSACTIONID(X) return FullTransactionIdGetDatum(X)
#endif /* XID8_H */
...@@ -832,6 +832,13 @@ macaddr8_gt(macaddr8,macaddr8) ...@@ -832,6 +832,13 @@ macaddr8_gt(macaddr8,macaddr8)
macaddr8_ge(macaddr8,macaddr8) macaddr8_ge(macaddr8,macaddr8)
macaddr8_ne(macaddr8,macaddr8) macaddr8_ne(macaddr8,macaddr8)
macaddr8_cmp(macaddr8,macaddr8) macaddr8_cmp(macaddr8,macaddr8)
xid8lt(xid8,xid8)
xid8gt(xid8,xid8)
xid8le(xid8,xid8)
xid8ge(xid8,xid8)
xid8eq(xid8,xid8)
xid8ne(xid8,xid8)
xid8cmp(xid8,xid8)
-- restore normal output mode -- restore normal output mode
\a\t \a\t
-- List of functions used by libpq's fe-lobj.c -- List of functions used by libpq's fe-lobj.c
......
-- xid and xid8
-- values in range, in octal, decimal, hex
select '010'::xid,
'42'::xid,
'0xffffffff'::xid,
'-1'::xid,
'010'::xid8,
'42'::xid8,
'0xffffffffffffffff'::xid8,
'-1'::xid8;
xid | xid | xid | xid | xid8 | xid8 | xid8 | xid8
-----+-----+------------+------------+------+------+----------------------+----------------------
8 | 42 | 4294967295 | 4294967295 | 8 | 42 | 18446744073709551615 | 18446744073709551615
(1 row)
-- garbage values are not yet rejected (perhaps they should be)
select ''::xid;
xid
-----
0
(1 row)
select 'asdf'::xid;
xid
-----
0
(1 row)
select ''::xid8;
xid8
------
0
(1 row)
select 'asdf'::xid8;
xid8
------
0
(1 row)
-- equality
select '1'::xid = '1'::xid;
?column?
----------
t
(1 row)
select '1'::xid != '1'::xid;
?column?
----------
f
(1 row)
select '1'::xid8 = '1'::xid8;
?column?
----------
t
(1 row)
select '1'::xid8 != '1'::xid8;
?column?
----------
f
(1 row)
-- conversion
select '1'::xid = '1'::xid8::xid;
?column?
----------
t
(1 row)
select '1'::xid != '1'::xid8::xid;
?column?
----------
f
(1 row)
-- we don't want relational operators for xid, due to use of modular arithmetic
select '1'::xid < '2'::xid;
ERROR: operator does not exist: xid < xid
LINE 1: select '1'::xid < '2'::xid;
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
select '1'::xid <= '2'::xid;
ERROR: operator does not exist: xid <= xid
LINE 1: select '1'::xid <= '2'::xid;
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
select '1'::xid > '2'::xid;
ERROR: operator does not exist: xid > xid
LINE 1: select '1'::xid > '2'::xid;
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
select '1'::xid >= '2'::xid;
ERROR: operator does not exist: xid >= xid
LINE 1: select '1'::xid >= '2'::xid;
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
-- we want them for xid8 though
select '1'::xid8 < '2'::xid8, '2'::xid8 < '2'::xid8, '2'::xid8 < '1'::xid8;
?column? | ?column? | ?column?
----------+----------+----------
t | f | f
(1 row)
select '1'::xid8 <= '2'::xid8, '2'::xid8 <= '2'::xid8, '2'::xid8 <= '1'::xid8;
?column? | ?column? | ?column?
----------+----------+----------
t | t | f
(1 row)
select '1'::xid8 > '2'::xid8, '2'::xid8 > '2'::xid8, '2'::xid8 > '1'::xid8;
?column? | ?column? | ?column?
----------+----------+----------
f | f | t
(1 row)
select '1'::xid8 >= '2'::xid8, '2'::xid8 >= '2'::xid8, '2'::xid8 >= '1'::xid8;
?column? | ?column? | ?column?
----------+----------+----------
f | t | t
(1 row)
-- we also have a 3way compare for btrees
select xid8cmp('1', '2'), xid8cmp('2', '2'), xid8cmp('2', '1');
xid8cmp | xid8cmp | xid8cmp
---------+---------+---------
-1 | 0 | 1
(1 row)
-- xid8 has btree and hash opclasses
create table xid8_t1 (x xid8);
create index on xid8_t1 using btree(x);
create index on xid8_t1 using hash(x);
drop table xid8_t1;
...@@ -20,7 +20,7 @@ test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeri ...@@ -20,7 +20,7 @@ test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeri
# strings depends on char, varchar and text # strings depends on char, varchar and text
# numerology depends on int2, int4, int8, float4, float8 # numerology depends on int2, int4, int8, float4, float8
# ---------- # ----------
test: strings numerology point lseg line box path polygon circle date time timetz timestamp timestamptz interval inet macaddr macaddr8 tstypes test: strings numerology point lseg line box path polygon circle date time timetz timestamp timestamptz interval inet macaddr macaddr8 tstypes xid
# ---------- # ----------
# Another group of parallel tests # Another group of parallel tests
......
...@@ -10,6 +10,7 @@ test: int2 ...@@ -10,6 +10,7 @@ test: int2
test: int4 test: int4
test: int8 test: int8
test: oid test: oid
test: xid
test: float4 test: float4
test: float8 test: float8
test: bit test: bit
......
-- xid and xid8
-- values in range, in octal, decimal, hex
select '010'::xid,
'42'::xid,
'0xffffffff'::xid,
'-1'::xid,
'010'::xid8,
'42'::xid8,
'0xffffffffffffffff'::xid8,
'-1'::xid8;
-- garbage values are not yet rejected (perhaps they should be)
select ''::xid;
select 'asdf'::xid;
select ''::xid8;
select 'asdf'::xid8;
-- equality
select '1'::xid = '1'::xid;
select '1'::xid != '1'::xid;
select '1'::xid8 = '1'::xid8;
select '1'::xid8 != '1'::xid8;
-- conversion
select '1'::xid = '1'::xid8::xid;
select '1'::xid != '1'::xid8::xid;
-- we don't want relational operators for xid, due to use of modular arithmetic
select '1'::xid < '2'::xid;
select '1'::xid <= '2'::xid;
select '1'::xid > '2'::xid;
select '1'::xid >= '2'::xid;
-- we want them for xid8 though
select '1'::xid8 < '2'::xid8, '2'::xid8 < '2'::xid8, '2'::xid8 < '1'::xid8;
select '1'::xid8 <= '2'::xid8, '2'::xid8 <= '2'::xid8, '2'::xid8 <= '1'::xid8;
select '1'::xid8 > '2'::xid8, '2'::xid8 > '2'::xid8, '2'::xid8 > '1'::xid8;
select '1'::xid8 >= '2'::xid8, '2'::xid8 >= '2'::xid8, '2'::xid8 >= '1'::xid8;
-- we also have a 3way compare for btrees
select xid8cmp('1', '2'), xid8cmp('2', '2'), xid8cmp('2', '1');
-- xid8 has btree and hash opclasses
create table xid8_t1 (x xid8);
create index on xid8_t1 using btree(x);
create index on xid8_t1 using hash(x);
drop table xid8_t1;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment