mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-06 15:24:56 +08:00
Migrate the former contrib/txid module into core. This will make it easier
for Slony and Skytools to depend on it. Per discussion.
This commit is contained in:
parent
17333b6d09
commit
18e3fcc31e
@ -1,4 +1,4 @@
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.209 2007/08/31 04:52:29 momjian Exp $ -->
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.210 2007/10/13 23:06:26 tgl Exp $ -->
|
||||
|
||||
<chapter id="datatype">
|
||||
<title id="datatype-title">Data Types</title>
|
||||
@ -246,6 +246,12 @@
|
||||
<entry>full text search document</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><type>txid_snapshot</type></entry>
|
||||
<entry></entry>
|
||||
<entry>user-level transaction ID snapshot</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry><type>uuid</type></entry>
|
||||
<entry></entry>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.400 2007/10/11 02:43:55 momjian Exp $ -->
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.401 2007/10/13 23:06:26 tgl Exp $ -->
|
||||
|
||||
<chapter id="functions">
|
||||
<title>Functions and Operators</title>
|
||||
@ -12048,6 +12048,84 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
|
||||
databases within each cluster and their descriptions are stored globally
|
||||
as well.
|
||||
</para>
|
||||
|
||||
<indexterm>
|
||||
<primary>txid_current</primary>
|
||||
</indexterm>
|
||||
|
||||
<indexterm>
|
||||
<primary>txid_current_snapshot</primary>
|
||||
</indexterm>
|
||||
|
||||
<indexterm>
|
||||
<primary>txid_snapshot_xmin</primary>
|
||||
</indexterm>
|
||||
|
||||
<indexterm>
|
||||
<primary>txid_snapshot_xmax</primary>
|
||||
</indexterm>
|
||||
|
||||
<indexterm>
|
||||
<primary>txid_snapshot_xip</primary>
|
||||
</indexterm>
|
||||
|
||||
<indexterm>
|
||||
<primary>txid_visible_in_snapshot</primary>
|
||||
</indexterm>
|
||||
|
||||
<para>
|
||||
The functions shown in <xref linkend="functions-txid-snapshot">
|
||||
export server internal transaction info to user level.
|
||||
</para>
|
||||
|
||||
<table id="functions-txid-snapshot">
|
||||
<title>Transaction IDs and snapshots</title>
|
||||
<tgroup cols="3">
|
||||
<thead>
|
||||
<row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><literal><function>txid_current</function>()</literal></entry>
|
||||
<entry><type>bigint</type></entry>
|
||||
<entry>get current transaction ID</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><function>txid_current_snapshot</function>()</literal></entry>
|
||||
<entry><type>txid_snapshot</type></entry>
|
||||
<entry>get current snapshot</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><function>txid_snapshot_xmin</function>(<parameter>txid_snapshot</parameter>)</literal></entry>
|
||||
<entry><type>bigint</type></entry>
|
||||
<entry>get xmin of snapshot</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><function>txid_snapshot_xmax</function>(<parameter>txid_snapshot</parameter>)</literal></entry>
|
||||
<entry><type>bigint</type></entry>
|
||||
<entry>get xmax of snapshot</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><function>txid_snapshot_xip</function>(<parameter>txid_snapshot</parameter>)</literal></entry>
|
||||
<entry><type>setof bigint</type></entry>
|
||||
<entry>get in-progress transaction IDs in snapshot</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><function>txid_visible_in_snapshot</function>(<parameter>bigint</parameter>, <parameter>txid_snapshot</parameter>)</literal></entry>
|
||||
<entry><type>boolean</type></entry>
|
||||
<entry>is transaction ID visible in snapshot?</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<para>
|
||||
The internal transaction ID type (<type>xid</>) is 32 bits wide and so
|
||||
it wraps around every 4 billion transactions. However, these functions
|
||||
export a 64-bit format that is extended with an <quote>epoch</> counter
|
||||
so that it will not wrap around for the life of an installation.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="functions-admin">
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Makefile for utils/adt
|
||||
#
|
||||
# $PostgreSQL: pgsql/src/backend/utils/adt/Makefile,v 1.67 2007/09/07 15:09:56 teodor Exp $
|
||||
# $PostgreSQL: pgsql/src/backend/utils/adt/Makefile,v 1.68 2007/10/13 23:06:26 tgl Exp $
|
||||
#
|
||||
|
||||
subdir = src/backend/utils/adt
|
||||
@ -28,8 +28,8 @@ OBJS = acl.o arrayfuncs.o array_userfuncs.o arrayutils.o bool.o \
|
||||
ascii.o quote.o pgstatfuncs.o encode.o dbsize.o genfile.o \
|
||||
tsginidx.o tsgistidx.o tsquery.o tsquery_cleanup.o tsquery_gist.o \
|
||||
tsquery_op.o tsquery_rewrite.o tsquery_util.o tsrank.o \
|
||||
tsvector.o tsvector_op.o tsvector_parser.o\
|
||||
uuid.o xml.o
|
||||
tsvector.o tsvector_op.o tsvector_parser.o \
|
||||
txid.o uuid.o xml.o
|
||||
|
||||
like.o: like.c like_match.c
|
||||
|
||||
|
583
src/backend/utils/adt/txid.c
Normal file
583
src/backend/utils/adt/txid.c
Normal file
@ -0,0 +1,583 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
* txid.c
|
||||
*
|
||||
* Export internal transaction IDs to user level.
|
||||
*
|
||||
* Note that only top-level transaction IDs are ever converted to TXID.
|
||||
* This is important because TXIDs frequently persist beyond the global
|
||||
* xmin horizon, or may even be shipped to other machines, so we cannot
|
||||
* rely on being able to correlate subtransaction IDs with their parents
|
||||
* via functions such as SubTransGetTopmostTransaction().
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003-2007, PostgreSQL Global Development Group
|
||||
* Author: Jan Wieck, Afilias USA INC.
|
||||
* 64-bit txids: Marko Kreen, Skype Technologies
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/txid.c,v 1.1 2007/10/13 23:06:26 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/transam.h"
|
||||
#include "access/xact.h"
|
||||
#include "funcapi.h"
|
||||
#include "libpq/pqformat.h"
|
||||
#include "utils/builtins.h"
|
||||
|
||||
|
||||
#ifndef INT64_IS_BUSTED
|
||||
/* txid will be signed int8 in database, so must limit to 63 bits */
|
||||
#define MAX_TXID UINT64CONST(0x7FFFFFFFFFFFFFFF)
|
||||
#else
|
||||
/* we only really have 32 bits to work with :-( */
|
||||
#define MAX_TXID UINT64CONST(0x7FFFFFFF)
|
||||
#endif
|
||||
|
||||
/* Use unsigned variant internally */
|
||||
typedef uint64 txid;
|
||||
|
||||
/* sprintf format code for uint64 */
|
||||
#define TXID_FMT UINT64_FORMAT
|
||||
|
||||
/*
|
||||
* If defined, use bsearch() function for searching for txids in snapshots
|
||||
* that have more than the specified number of values.
|
||||
*/
|
||||
#define USE_BSEARCH_IF_NXIP_GREATER 30
|
||||
|
||||
|
||||
/*
|
||||
* Snapshot containing 8byte txids.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/*
|
||||
* 4-byte length hdr, should not be touched directly.
|
||||
*
|
||||
* Explicit embedding is ok as we want always correct
|
||||
* alignment anyway.
|
||||
*/
|
||||
int32 __varsz;
|
||||
|
||||
uint32 nxip; /* number of txids in xip array */
|
||||
txid xmin;
|
||||
txid xmax;
|
||||
txid xip[1]; /* in-progress txids, xmin <= xip[i] < xmax */
|
||||
} TxidSnapshot;
|
||||
|
||||
#define TXID_SNAPSHOT_SIZE(nxip) \
|
||||
(offsetof(TxidSnapshot, xip) + sizeof(txid) * (nxip))
|
||||
|
||||
/*
|
||||
* Epoch values from xact.c
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
TransactionId last_xid;
|
||||
uint32 epoch;
|
||||
} TxidEpoch;
|
||||
|
||||
|
||||
/*
|
||||
* Fetch epoch data from xact.c.
|
||||
*/
|
||||
static void
|
||||
load_xid_epoch(TxidEpoch *state)
|
||||
{
|
||||
GetNextXidAndEpoch(&state->last_xid, &state->epoch);
|
||||
}
|
||||
|
||||
/*
|
||||
* do a TransactionId -> txid conversion for an XID near the given epoch
|
||||
*/
|
||||
static txid
|
||||
convert_xid(TransactionId xid, const TxidEpoch *state)
|
||||
{
|
||||
#ifndef INT64_IS_BUSTED
|
||||
uint64 epoch;
|
||||
|
||||
/* return special xid's as-is */
|
||||
if (!TransactionIdIsNormal(xid))
|
||||
return (txid) xid;
|
||||
|
||||
/* xid can be on either side when near wrap-around */
|
||||
epoch = (uint64) state->epoch;
|
||||
if (xid > state->last_xid &&
|
||||
TransactionIdPrecedes(xid, state->last_xid))
|
||||
epoch--;
|
||||
else if (xid < state->last_xid &&
|
||||
TransactionIdFollows(xid, state->last_xid))
|
||||
epoch++;
|
||||
|
||||
return (epoch << 32) | xid;
|
||||
#else /* INT64_IS_BUSTED */
|
||||
/* we can't do anything with the epoch, so ignore it */
|
||||
return (txid) xid & MAX_TXID;
|
||||
#endif /* INT64_IS_BUSTED */
|
||||
}
|
||||
|
||||
/*
|
||||
* txid comparator for qsort/bsearch
|
||||
*/
|
||||
static int
|
||||
cmp_txid(const void *aa, const void *bb)
|
||||
{
|
||||
txid a = *(const txid *) aa;
|
||||
txid b = *(const txid *) bb;
|
||||
|
||||
if (a < b)
|
||||
return -1;
|
||||
if (a > b)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* sort a snapshot's txids, so we can use bsearch() later.
|
||||
*
|
||||
* For consistency of on-disk representation, we always sort even if bsearch
|
||||
* will not be used.
|
||||
*/
|
||||
static void
|
||||
sort_snapshot(TxidSnapshot *snap)
|
||||
{
|
||||
if (snap->nxip > 1)
|
||||
qsort(snap->xip, snap->nxip, sizeof(txid), cmp_txid);
|
||||
}
|
||||
|
||||
/*
|
||||
* check txid visibility.
|
||||
*/
|
||||
static bool
|
||||
is_visible_txid(txid value, const TxidSnapshot *snap)
|
||||
{
|
||||
if (value < snap->xmin)
|
||||
return true;
|
||||
else if (value >= snap->xmax)
|
||||
return false;
|
||||
#ifdef USE_BSEARCH_IF_NXIP_GREATER
|
||||
else if (snap->nxip > USE_BSEARCH_IF_NXIP_GREATER)
|
||||
{
|
||||
void *res;
|
||||
|
||||
res = bsearch(&value, snap->xip, snap->nxip, sizeof(txid), cmp_txid);
|
||||
/* if found, transaction is still in progress */
|
||||
return (res) ? false : true;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
for (i = 0; i < snap->nxip; i++)
|
||||
{
|
||||
if (value == snap->xip[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* helper functions to use StringInfo for TxidSnapshot creation.
|
||||
*/
|
||||
|
||||
static StringInfo
|
||||
buf_init(txid xmin, txid xmax)
|
||||
{
|
||||
TxidSnapshot snap;
|
||||
StringInfo buf;
|
||||
|
||||
snap.xmin = xmin;
|
||||
snap.xmax = xmax;
|
||||
snap.nxip = 0;
|
||||
|
||||
buf = makeStringInfo();
|
||||
appendBinaryStringInfo(buf, (char *)&snap, TXID_SNAPSHOT_SIZE(0));
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void
|
||||
buf_add_txid(StringInfo buf, txid xid)
|
||||
{
|
||||
TxidSnapshot *snap = (TxidSnapshot *)buf->data;
|
||||
|
||||
/* do this before possible realloc */
|
||||
snap->nxip++;
|
||||
|
||||
appendBinaryStringInfo(buf, (char *)&xid, sizeof(xid));
|
||||
}
|
||||
|
||||
static TxidSnapshot *
|
||||
buf_finalize(StringInfo buf)
|
||||
{
|
||||
TxidSnapshot *snap = (TxidSnapshot *)buf->data;
|
||||
|
||||
SET_VARSIZE(snap, buf->len);
|
||||
|
||||
/* buf is not needed anymore */
|
||||
buf->data = NULL;
|
||||
pfree(buf);
|
||||
|
||||
return snap;
|
||||
}
|
||||
|
||||
/*
|
||||
* simple number parser.
|
||||
*
|
||||
* We return 0 on error, which is invalid value for txid.
|
||||
*/
|
||||
static txid
|
||||
str2txid(const char *s, const char **endp)
|
||||
{
|
||||
txid val = 0;
|
||||
txid cutoff = MAX_TXID / 10;
|
||||
txid cutlim = MAX_TXID % 10;
|
||||
|
||||
for (; *s; s++)
|
||||
{
|
||||
unsigned d;
|
||||
|
||||
if (*s < '0' || *s > '9')
|
||||
break;
|
||||
d = *s - '0';
|
||||
|
||||
/*
|
||||
* check for overflow
|
||||
*/
|
||||
if (val > cutoff || (val == cutoff && d > cutlim))
|
||||
{
|
||||
val = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
val = val * 10 + d;
|
||||
}
|
||||
if (endp)
|
||||
*endp = s;
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* parse snapshot from cstring
|
||||
*/
|
||||
static TxidSnapshot *
|
||||
parse_snapshot(const char *str)
|
||||
{
|
||||
txid xmin;
|
||||
txid xmax;
|
||||
txid last_val = 0, val;
|
||||
const char *str_start = str;
|
||||
const char *endp;
|
||||
StringInfo buf;
|
||||
|
||||
xmin = str2txid(str, &endp);
|
||||
if (*endp != ':')
|
||||
goto bad_format;
|
||||
str = endp + 1;
|
||||
|
||||
xmax = str2txid(str, &endp);
|
||||
if (*endp != ':')
|
||||
goto bad_format;
|
||||
str = endp + 1;
|
||||
|
||||
/* it should look sane */
|
||||
if (xmin == 0 || xmax == 0 || xmin > xmax)
|
||||
goto bad_format;
|
||||
|
||||
/* allocate buffer */
|
||||
buf = buf_init(xmin, xmax);
|
||||
|
||||
/* loop over values */
|
||||
while (*str != '\0')
|
||||
{
|
||||
/* read next value */
|
||||
val = str2txid(str, &endp);
|
||||
str = endp;
|
||||
|
||||
/* require the input to be in order */
|
||||
if (val < xmin || val >= xmax || val <= last_val)
|
||||
goto bad_format;
|
||||
|
||||
buf_add_txid(buf, val);
|
||||
last_val = val;
|
||||
|
||||
if (*str == ',')
|
||||
str++;
|
||||
else if (*str != '\0')
|
||||
goto bad_format;
|
||||
}
|
||||
|
||||
return buf_finalize(buf);
|
||||
|
||||
bad_format:
|
||||
elog(ERROR, "invalid input for txid_snapshot: \"%s\"", str_start);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Public functions.
|
||||
*
|
||||
* txid_current() and txid_current_snapshot() are the only ones that
|
||||
* communicate with core xid machinery. All the others work on data
|
||||
* returned by them.
|
||||
*/
|
||||
|
||||
/*
|
||||
* txid_current() returns int8
|
||||
*
|
||||
* Return the current toplevel transaction ID as TXID
|
||||
*/
|
||||
Datum
|
||||
txid_current(PG_FUNCTION_ARGS)
|
||||
{
|
||||
txid val;
|
||||
TxidEpoch state;
|
||||
|
||||
load_xid_epoch(&state);
|
||||
|
||||
val = convert_xid(GetTopTransactionId(), &state);
|
||||
|
||||
PG_RETURN_INT64(val);
|
||||
}
|
||||
|
||||
/*
|
||||
* txid_current_snapshot() returns txid_snapshot
|
||||
*
|
||||
* Return current snapshot in TXID format
|
||||
*
|
||||
* Note that only top-transaction XIDs are included in the snapshot.
|
||||
*/
|
||||
Datum
|
||||
txid_current_snapshot(PG_FUNCTION_ARGS)
|
||||
{
|
||||
TxidSnapshot *snap;
|
||||
uint32 nxip, i, size;
|
||||
TxidEpoch state;
|
||||
Snapshot cur;
|
||||
|
||||
cur = ActiveSnapshot;
|
||||
if (cur == NULL)
|
||||
elog(ERROR, "txid_current_snapshot: ActiveSnapshot == NULL");
|
||||
|
||||
load_xid_epoch(&state);
|
||||
|
||||
/* allocate */
|
||||
nxip = cur->xcnt;
|
||||
size = TXID_SNAPSHOT_SIZE(nxip);
|
||||
snap = palloc(size);
|
||||
SET_VARSIZE(snap, size);
|
||||
|
||||
/* fill */
|
||||
snap->xmin = convert_xid(cur->xmin, &state);
|
||||
snap->xmax = convert_xid(cur->xmax, &state);
|
||||
snap->nxip = nxip;
|
||||
for (i = 0; i < nxip; i++)
|
||||
snap->xip[i] = convert_xid(cur->xip[i], &state);
|
||||
|
||||
/* we want them guaranteed to be in ascending order */
|
||||
sort_snapshot(snap);
|
||||
|
||||
PG_RETURN_POINTER(snap);
|
||||
}
|
||||
|
||||
/*
|
||||
* txid_snapshot_in(cstring) returns txid_snapshot
|
||||
*
|
||||
* input function for type txid_snapshot
|
||||
*/
|
||||
Datum
|
||||
txid_snapshot_in(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *str = PG_GETARG_CSTRING(0);
|
||||
TxidSnapshot *snap;
|
||||
|
||||
snap = parse_snapshot(str);
|
||||
|
||||
PG_RETURN_POINTER(snap);
|
||||
}
|
||||
|
||||
/*
|
||||
* txid_snapshot_out(txid_snapshot) returns cstring
|
||||
*
|
||||
* output function for type txid_snapshot
|
||||
*/
|
||||
Datum
|
||||
txid_snapshot_out(PG_FUNCTION_ARGS)
|
||||
{
|
||||
TxidSnapshot *snap = (TxidSnapshot *) PG_GETARG_VARLENA_P(0);
|
||||
StringInfoData str;
|
||||
uint32 i;
|
||||
|
||||
initStringInfo(&str);
|
||||
|
||||
appendStringInfo(&str, TXID_FMT ":", snap->xmin);
|
||||
appendStringInfo(&str, TXID_FMT ":", snap->xmax);
|
||||
|
||||
for (i = 0; i < snap->nxip; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
appendStringInfoChar(&str, ',');
|
||||
appendStringInfo(&str, TXID_FMT, snap->xip[i]);
|
||||
}
|
||||
|
||||
PG_RETURN_CSTRING(str.data);
|
||||
}
|
||||
|
||||
/*
|
||||
* txid_snapshot_recv(internal) returns txid_snapshot
|
||||
*
|
||||
* binary input function for type txid_snapshot
|
||||
*
|
||||
* format: int4 nxip, int8 xmin, int8 xmax, int8 xip
|
||||
*/
|
||||
Datum
|
||||
txid_snapshot_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
TxidSnapshot *snap;
|
||||
txid last = 0;
|
||||
int nxip;
|
||||
int i;
|
||||
int avail;
|
||||
int expect;
|
||||
txid xmin, xmax;
|
||||
|
||||
/*
|
||||
* load nxip and check for nonsense.
|
||||
*
|
||||
* (nxip > avail) check is against int overflows in 'expect'.
|
||||
*/
|
||||
nxip = pq_getmsgint(buf, 4);
|
||||
avail = buf->len - buf->cursor;
|
||||
expect = 8 + 8 + nxip * 8;
|
||||
if (nxip < 0 || nxip > avail || expect > avail)
|
||||
goto bad_format;
|
||||
|
||||
xmin = pq_getmsgint64(buf);
|
||||
xmax = pq_getmsgint64(buf);
|
||||
if (xmin == 0 || xmax == 0 || xmin > xmax || xmax > MAX_TXID)
|
||||
goto bad_format;
|
||||
|
||||
snap = palloc(TXID_SNAPSHOT_SIZE(nxip));
|
||||
snap->xmin = xmin;
|
||||
snap->xmax = xmax;
|
||||
snap->nxip = nxip;
|
||||
SET_VARSIZE(snap, TXID_SNAPSHOT_SIZE(nxip));
|
||||
|
||||
for (i = 0; i < nxip; i++)
|
||||
{
|
||||
txid cur = pq_getmsgint64(buf);
|
||||
if (cur <= last || cur < xmin || cur >= xmax)
|
||||
goto bad_format;
|
||||
snap->xip[i] = cur;
|
||||
last = cur;
|
||||
}
|
||||
PG_RETURN_POINTER(snap);
|
||||
|
||||
bad_format:
|
||||
elog(ERROR, "invalid snapshot data");
|
||||
return (Datum)NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* txid_snapshot_send(txid_snapshot) returns bytea
|
||||
*
|
||||
* binary output function for type txid_snapshot
|
||||
*
|
||||
* format: int4 nxip, int8 xmin, int8 xmax, int8 xip
|
||||
*/
|
||||
Datum
|
||||
txid_snapshot_send(PG_FUNCTION_ARGS)
|
||||
{
|
||||
TxidSnapshot *snap = (TxidSnapshot *)PG_GETARG_VARLENA_P(0);
|
||||
StringInfoData buf;
|
||||
uint32 i;
|
||||
|
||||
pq_begintypsend(&buf);
|
||||
pq_sendint(&buf, snap->nxip, 4);
|
||||
pq_sendint64(&buf, snap->xmin);
|
||||
pq_sendint64(&buf, snap->xmax);
|
||||
for (i = 0; i < snap->nxip; i++)
|
||||
pq_sendint64(&buf, snap->xip[i]);
|
||||
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
||||
}
|
||||
|
||||
/*
|
||||
* txid_visible_in_snapshot(int8, txid_snapshot) returns bool
|
||||
*
|
||||
* is txid visible in snapshot ?
|
||||
*/
|
||||
Datum
|
||||
txid_visible_in_snapshot(PG_FUNCTION_ARGS)
|
||||
{
|
||||
txid value = PG_GETARG_INT64(0);
|
||||
TxidSnapshot *snap = (TxidSnapshot *) PG_GETARG_VARLENA_P(1);
|
||||
|
||||
PG_RETURN_BOOL(is_visible_txid(value, snap));
|
||||
}
|
||||
|
||||
/*
|
||||
* txid_snapshot_xmin(txid_snapshot) returns int8
|
||||
*
|
||||
* return snapshot's xmin
|
||||
*/
|
||||
Datum
|
||||
txid_snapshot_xmin(PG_FUNCTION_ARGS)
|
||||
{
|
||||
TxidSnapshot *snap = (TxidSnapshot *) PG_GETARG_VARLENA_P(0);
|
||||
|
||||
PG_RETURN_INT64(snap->xmin);
|
||||
}
|
||||
|
||||
/*
|
||||
* txid_snapshot_xmax(txid_snapshot) returns int8
|
||||
*
|
||||
* return snapshot's xmax
|
||||
*/
|
||||
Datum
|
||||
txid_snapshot_xmax(PG_FUNCTION_ARGS)
|
||||
{
|
||||
TxidSnapshot *snap = (TxidSnapshot *) PG_GETARG_VARLENA_P(0);
|
||||
|
||||
PG_RETURN_INT64(snap->xmax);
|
||||
}
|
||||
|
||||
/*
|
||||
* txid_snapshot_xip(txid_snapshot) returns setof int8
|
||||
*
|
||||
* return in-progress TXIDs in snapshot.
|
||||
*/
|
||||
Datum
|
||||
txid_snapshot_xip(PG_FUNCTION_ARGS)
|
||||
{
|
||||
FuncCallContext *fctx;
|
||||
TxidSnapshot *snap;
|
||||
txid value;
|
||||
|
||||
/* on first call initialize snap_state and get copy of snapshot */
|
||||
if (SRF_IS_FIRSTCALL()) {
|
||||
TxidSnapshot *arg = (TxidSnapshot *) PG_GETARG_VARLENA_P(0);
|
||||
|
||||
fctx = SRF_FIRSTCALL_INIT();
|
||||
|
||||
/* make a copy of user snapshot */
|
||||
snap = MemoryContextAlloc(fctx->multi_call_memory_ctx, VARSIZE(arg));
|
||||
memcpy(snap, arg, VARSIZE(arg));
|
||||
|
||||
fctx->user_fctx = snap;
|
||||
}
|
||||
|
||||
/* return values one-by-one */
|
||||
fctx = SRF_PERCALL_SETUP();
|
||||
snap = fctx->user_fctx;
|
||||
if (fctx->call_cntr < snap->nxip) {
|
||||
value = snap->xip[fctx->call_cntr];
|
||||
SRF_RETURN_NEXT(fctx, Int64GetDatum(value));
|
||||
} else {
|
||||
SRF_RETURN_DONE(fctx);
|
||||
}
|
||||
}
|
@ -37,7 +37,7 @@
|
||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.431 2007/10/13 20:18:41 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.432 2007/10/13 23:06:26 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -53,6 +53,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 200710131
|
||||
#define CATALOG_VERSION_NO 200710141
|
||||
|
||||
#endif
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.473 2007/09/25 20:03:38 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.474 2007/10/13 23:06:26 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* The script catalog/genbki.sh reads this file and generates .bki
|
||||
@ -4399,6 +4399,28 @@ DESCR("I/O");
|
||||
DATA(insert OID = 3774 ( regdictionarysend PGNSP PGUID 12 1 0 f f t f i 1 17 "3769" _null_ _null_ _null_ regdictionarysend - _null_ _null_ ));
|
||||
DESCR("I/O");
|
||||
|
||||
/* txid */
|
||||
DATA(insert OID = 2939 ( txid_snapshot_in PGNSP PGUID 12 1 0 f f t f i 1 2970 "2275" _null_ _null_ _null_ txid_snapshot_in - _null_ _null_ ));
|
||||
DESCR("I/O");
|
||||
DATA(insert OID = 2940 ( txid_snapshot_out PGNSP PGUID 12 1 0 f f t f i 1 2275 "2970" _null_ _null_ _null_ txid_snapshot_out - _null_ _null_ ));
|
||||
DESCR("I/O");
|
||||
DATA(insert OID = 2941 ( txid_snapshot_recv PGNSP PGUID 12 1 0 f f t f i 1 2970 "2281" _null_ _null_ _null_ txid_snapshot_recv - _null_ _null_ ));
|
||||
DESCR("I/O");
|
||||
DATA(insert OID = 2942 ( txid_snapshot_send PGNSP PGUID 12 1 0 f f t f i 1 17 "2970" _null_ _null_ _null_ txid_snapshot_send - _null_ _null_ ));
|
||||
DESCR("I/O");
|
||||
DATA(insert OID = 2943 ( txid_current PGNSP PGUID 12 1 0 f f t f s 0 20 "" _null_ _null_ _null_ txid_current - _null_ _null_ ));
|
||||
DESCR("get current transaction ID");
|
||||
DATA(insert OID = 2944 ( txid_current_snapshot PGNSP PGUID 12 1 0 f f t f s 0 2970 "" _null_ _null_ _null_ txid_current_snapshot - _null_ _null_ ));
|
||||
DESCR("get current snapshot");
|
||||
DATA(insert OID = 2945 ( txid_snapshot_xmin PGNSP PGUID 12 1 0 f f t f i 1 20 "2970" _null_ _null_ _null_ txid_snapshot_xmin - _null_ _null_ ));
|
||||
DESCR("get xmin of snapshot");
|
||||
DATA(insert OID = 2946 ( txid_snapshot_xmax PGNSP PGUID 12 1 0 f f t f i 1 20 "2970" _null_ _null_ _null_ txid_snapshot_xmax - _null_ _null_ ));
|
||||
DESCR("get xmax of snapshot");
|
||||
DATA(insert OID = 2947 ( txid_snapshot_xip PGNSP PGUID 12 1 50 f f t t i 1 20 "2970" _null_ _null_ _null_ txid_snapshot_xip - _null_ _null_ ));
|
||||
DESCR("get set of in-progress txids in snapshot");
|
||||
DATA(insert OID = 2948 ( txid_visible_in_snapshot PGNSP PGUID 12 1 0 f f t f i 2 16 "20 2970" _null_ _null_ _null_ txid_visible_in_snapshot - _null_ _null_ ));
|
||||
DESCR("is txid visible in snapshot?");
|
||||
|
||||
|
||||
/*
|
||||
* Symbolic values for provolatile column: these indicate whether the result
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.188 2007/09/03 02:30:45 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.189 2007/10/13 23:06:27 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* the genbki.sh script reads this file and generates .bki
|
||||
@ -572,6 +572,10 @@ DATA(insert OID = 3645 ( _tsquery PGNSP PGUID -1 f b t \054 0 3615 0 array_in a
|
||||
DATA(insert OID = 3735 ( _regconfig PGNSP PGUID -1 f b t \054 0 3734 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
|
||||
DATA(insert OID = 3770 ( _regdictionary PGNSP PGUID -1 f b t \054 0 3769 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
|
||||
|
||||
DATA(insert OID = 2970 ( txid_snapshot PGNSP PGUID -1 f b t \054 0 0 2949 txid_snapshot_in txid_snapshot_out txid_snapshot_recv txid_snapshot_send - - - d x f 0 -1 0 _null_ _null_ ));
|
||||
DESCR("txid snapshot");
|
||||
DATA(insert OID = 2949 ( _txid_snapshot PGNSP PGUID -1 f b t \054 0 2970 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ ));
|
||||
|
||||
/*
|
||||
* pseudo-types
|
||||
*
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.304 2007/09/24 01:29:30 adunstan Exp $
|
||||
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.305 2007/10/13 23:06:27 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -938,14 +938,17 @@ extern Datum pg_advisory_unlock_int4(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_advisory_unlock_shared_int4(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_advisory_unlock_all(PG_FUNCTION_ARGS);
|
||||
|
||||
/* access/transam/twophase.c */
|
||||
extern Datum pg_prepared_xact(PG_FUNCTION_ARGS);
|
||||
|
||||
/* commands/prepare.c */
|
||||
extern Datum pg_prepared_statement(PG_FUNCTION_ARGS);
|
||||
|
||||
/* utils/mmgr/portalmem.c */
|
||||
extern Datum pg_cursor(PG_FUNCTION_ARGS);
|
||||
/* txid.c */
|
||||
extern Datum txid_snapshot_in(PG_FUNCTION_ARGS);
|
||||
extern Datum txid_snapshot_out(PG_FUNCTION_ARGS);
|
||||
extern Datum txid_snapshot_recv(PG_FUNCTION_ARGS);
|
||||
extern Datum txid_snapshot_send(PG_FUNCTION_ARGS);
|
||||
extern Datum txid_current(PG_FUNCTION_ARGS);
|
||||
extern Datum txid_current_snapshot(PG_FUNCTION_ARGS);
|
||||
extern Datum txid_snapshot_xmin(PG_FUNCTION_ARGS);
|
||||
extern Datum txid_snapshot_xmax(PG_FUNCTION_ARGS);
|
||||
extern Datum txid_snapshot_xip(PG_FUNCTION_ARGS);
|
||||
extern Datum txid_visible_in_snapshot(PG_FUNCTION_ARGS);
|
||||
|
||||
/* uuid.c */
|
||||
extern Datum uuid_in(PG_FUNCTION_ARGS);
|
||||
@ -961,4 +964,13 @@ extern Datum uuid_ne(PG_FUNCTION_ARGS);
|
||||
extern Datum uuid_cmp(PG_FUNCTION_ARGS);
|
||||
extern Datum uuid_hash(PG_FUNCTION_ARGS);
|
||||
|
||||
/* access/transam/twophase.c */
|
||||
extern Datum pg_prepared_xact(PG_FUNCTION_ARGS);
|
||||
|
||||
/* commands/prepare.c */
|
||||
extern Datum pg_prepared_statement(PG_FUNCTION_ARGS);
|
||||
|
||||
/* utils/mmgr/portalmem.c */
|
||||
extern Datum pg_cursor(PG_FUNCTION_ARGS);
|
||||
|
||||
#endif /* BUILTINS_H */
|
||||
|
226
src/test/regress/expected/txid.out
Normal file
226
src/test/regress/expected/txid.out
Normal file
@ -0,0 +1,226 @@
|
||||
-- txid_snapshot data type and related functions
|
||||
-- i/o
|
||||
select '12:13:'::txid_snapshot;
|
||||
txid_snapshot
|
||||
---------------
|
||||
12:13:
|
||||
(1 row)
|
||||
|
||||
select '12:18:14,16'::txid_snapshot;
|
||||
txid_snapshot
|
||||
---------------
|
||||
12:18:14,16
|
||||
(1 row)
|
||||
|
||||
-- errors
|
||||
select '31:12:'::txid_snapshot;
|
||||
ERROR: invalid input for txid_snapshot: "31:12:"
|
||||
select '0:1:'::txid_snapshot;
|
||||
ERROR: invalid input for txid_snapshot: "0:1:"
|
||||
select '12:13:0'::txid_snapshot;
|
||||
ERROR: invalid input for txid_snapshot: "12:13:0"
|
||||
select '12:16:14,13'::txid_snapshot;
|
||||
ERROR: invalid input for txid_snapshot: "12:16:14,13"
|
||||
select '12:16:14,14'::txid_snapshot;
|
||||
ERROR: invalid input for txid_snapshot: "12:16:14,14"
|
||||
create temp table snapshot_test (
|
||||
nr integer,
|
||||
snap txid_snapshot
|
||||
);
|
||||
insert into snapshot_test values (1, '12:13:');
|
||||
insert into snapshot_test values (2, '12:20:13,15,18');
|
||||
insert into snapshot_test values (3, '100001:100009:100005,100007,100008');
|
||||
insert into snapshot_test values (4, '100:150:101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131');
|
||||
select snap from snapshot_test order by nr;
|
||||
snap
|
||||
-------------------------------------------------------------------------------------------------------------------------------------
|
||||
12:13:
|
||||
12:20:13,15,18
|
||||
100001:100009:100005,100007,100008
|
||||
100:150:101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131
|
||||
(4 rows)
|
||||
|
||||
select txid_snapshot_xmin(snap),
|
||||
txid_snapshot_xmax(snap),
|
||||
txid_snapshot_xip(snap)
|
||||
from snapshot_test order by nr;
|
||||
txid_snapshot_xmin | txid_snapshot_xmax | txid_snapshot_xip
|
||||
--------------------+--------------------+-------------------
|
||||
12 | 20 | 13
|
||||
12 | 20 | 15
|
||||
12 | 20 | 18
|
||||
100001 | 100009 | 100005
|
||||
100001 | 100009 | 100007
|
||||
100001 | 100009 | 100008
|
||||
100 | 150 | 101
|
||||
100 | 150 | 102
|
||||
100 | 150 | 103
|
||||
100 | 150 | 104
|
||||
100 | 150 | 105
|
||||
100 | 150 | 106
|
||||
100 | 150 | 107
|
||||
100 | 150 | 108
|
||||
100 | 150 | 109
|
||||
100 | 150 | 110
|
||||
100 | 150 | 111
|
||||
100 | 150 | 112
|
||||
100 | 150 | 113
|
||||
100 | 150 | 114
|
||||
100 | 150 | 115
|
||||
100 | 150 | 116
|
||||
100 | 150 | 117
|
||||
100 | 150 | 118
|
||||
100 | 150 | 119
|
||||
100 | 150 | 120
|
||||
100 | 150 | 121
|
||||
100 | 150 | 122
|
||||
100 | 150 | 123
|
||||
100 | 150 | 124
|
||||
100 | 150 | 125
|
||||
100 | 150 | 126
|
||||
100 | 150 | 127
|
||||
100 | 150 | 128
|
||||
100 | 150 | 129
|
||||
100 | 150 | 130
|
||||
100 | 150 | 131
|
||||
(37 rows)
|
||||
|
||||
select id, txid_visible_in_snapshot(id, snap)
|
||||
from snapshot_test, generate_series(11, 21) id
|
||||
where nr = 2;
|
||||
id | txid_visible_in_snapshot
|
||||
----+--------------------------
|
||||
11 | t
|
||||
12 | t
|
||||
13 | f
|
||||
14 | t
|
||||
15 | f
|
||||
16 | t
|
||||
17 | t
|
||||
18 | f
|
||||
19 | t
|
||||
20 | f
|
||||
21 | f
|
||||
(11 rows)
|
||||
|
||||
-- test bsearch
|
||||
select id, txid_visible_in_snapshot(id, snap)
|
||||
from snapshot_test, generate_series(90, 160) id
|
||||
where nr = 4;
|
||||
id | txid_visible_in_snapshot
|
||||
-----+--------------------------
|
||||
90 | t
|
||||
91 | t
|
||||
92 | t
|
||||
93 | t
|
||||
94 | t
|
||||
95 | t
|
||||
96 | t
|
||||
97 | t
|
||||
98 | t
|
||||
99 | t
|
||||
100 | t
|
||||
101 | f
|
||||
102 | f
|
||||
103 | f
|
||||
104 | f
|
||||
105 | f
|
||||
106 | f
|
||||
107 | f
|
||||
108 | f
|
||||
109 | f
|
||||
110 | f
|
||||
111 | f
|
||||
112 | f
|
||||
113 | f
|
||||
114 | f
|
||||
115 | f
|
||||
116 | f
|
||||
117 | f
|
||||
118 | f
|
||||
119 | f
|
||||
120 | f
|
||||
121 | f
|
||||
122 | f
|
||||
123 | f
|
||||
124 | f
|
||||
125 | f
|
||||
126 | f
|
||||
127 | f
|
||||
128 | f
|
||||
129 | f
|
||||
130 | f
|
||||
131 | f
|
||||
132 | t
|
||||
133 | t
|
||||
134 | t
|
||||
135 | t
|
||||
136 | t
|
||||
137 | t
|
||||
138 | t
|
||||
139 | t
|
||||
140 | t
|
||||
141 | t
|
||||
142 | t
|
||||
143 | t
|
||||
144 | t
|
||||
145 | t
|
||||
146 | t
|
||||
147 | t
|
||||
148 | t
|
||||
149 | t
|
||||
150 | f
|
||||
151 | f
|
||||
152 | f
|
||||
153 | f
|
||||
154 | f
|
||||
155 | f
|
||||
156 | f
|
||||
157 | f
|
||||
158 | f
|
||||
159 | f
|
||||
160 | f
|
||||
(71 rows)
|
||||
|
||||
-- test current values also
|
||||
select txid_current() >= txid_snapshot_xmin(txid_current_snapshot());
|
||||
?column?
|
||||
----------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
-- we can't assume current is always less than xmax, however
|
||||
select txid_visible_in_snapshot(txid_current(), txid_current_snapshot());
|
||||
txid_visible_in_snapshot
|
||||
--------------------------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
-- test 64bitness
|
||||
select txid_snapshot '1000100010001000:1000100010001100:1000100010001012,1000100010001013';
|
||||
txid_snapshot
|
||||
---------------------------------------------------------------------
|
||||
1000100010001000:1000100010001100:1000100010001012,1000100010001013
|
||||
(1 row)
|
||||
|
||||
select txid_visible_in_snapshot('1000100010001012', '1000100010001000:1000100010001100:1000100010001012,1000100010001013');
|
||||
txid_visible_in_snapshot
|
||||
--------------------------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
select txid_visible_in_snapshot('1000100010001015', '1000100010001000:1000100010001100:1000100010001012,1000100010001013');
|
||||
txid_visible_in_snapshot
|
||||
--------------------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
-- test 64bit overflow
|
||||
SELECT txid_snapshot '1:9223372036854775807:3';
|
||||
txid_snapshot
|
||||
-------------------------
|
||||
1:9223372036854775807:3
|
||||
(1 row)
|
||||
|
||||
SELECT txid_snapshot '1:9223372036854775808:3';
|
||||
ERROR: invalid input for txid_snapshot: "1:9223372036854775808:3"
|
@ -1,5 +1,5 @@
|
||||
# ----------
|
||||
# $PostgreSQL: pgsql/src/test/regress/parallel_schedule,v 1.44 2007/09/11 11:54:42 teodor Exp $
|
||||
# $PostgreSQL: pgsql/src/test/regress/parallel_schedule,v 1.45 2007/10/13 23:06:27 tgl Exp $
|
||||
#
|
||||
# By convention, we put no more than twenty tests in any one parallel group;
|
||||
# this limits the number of connections needed to run the tests.
|
||||
@ -8,7 +8,7 @@
|
||||
# ----------
|
||||
# The first group of parallel tests
|
||||
# ----------
|
||||
test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric uuid enum
|
||||
test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric txid uuid enum
|
||||
|
||||
# Depends on things setup during char, varchar and text
|
||||
test: strings
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $PostgreSQL: pgsql/src/test/regress/serial_schedule,v 1.41 2007/09/11 11:54:42 teodor Exp $
|
||||
# $PostgreSQL: pgsql/src/test/regress/serial_schedule,v 1.42 2007/10/13 23:06:27 tgl Exp $
|
||||
# This should probably be in an order similar to parallel_schedule.
|
||||
test: boolean
|
||||
test: char
|
||||
@ -13,6 +13,7 @@ test: float4
|
||||
test: float8
|
||||
test: bit
|
||||
test: numeric
|
||||
test: txid
|
||||
test: uuid
|
||||
test: enum
|
||||
test: strings
|
||||
|
54
src/test/regress/sql/txid.sql
Normal file
54
src/test/regress/sql/txid.sql
Normal file
@ -0,0 +1,54 @@
|
||||
-- txid_snapshot data type and related functions
|
||||
|
||||
-- i/o
|
||||
select '12:13:'::txid_snapshot;
|
||||
select '12:18:14,16'::txid_snapshot;
|
||||
|
||||
-- errors
|
||||
select '31:12:'::txid_snapshot;
|
||||
select '0:1:'::txid_snapshot;
|
||||
select '12:13:0'::txid_snapshot;
|
||||
select '12:16:14,13'::txid_snapshot;
|
||||
select '12:16:14,14'::txid_snapshot;
|
||||
|
||||
create temp table snapshot_test (
|
||||
nr integer,
|
||||
snap txid_snapshot
|
||||
);
|
||||
|
||||
insert into snapshot_test values (1, '12:13:');
|
||||
insert into snapshot_test values (2, '12:20:13,15,18');
|
||||
insert into snapshot_test values (3, '100001:100009:100005,100007,100008');
|
||||
insert into snapshot_test values (4, '100:150:101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131');
|
||||
select snap from snapshot_test order by nr;
|
||||
|
||||
select txid_snapshot_xmin(snap),
|
||||
txid_snapshot_xmax(snap),
|
||||
txid_snapshot_xip(snap)
|
||||
from snapshot_test order by nr;
|
||||
|
||||
select id, txid_visible_in_snapshot(id, snap)
|
||||
from snapshot_test, generate_series(11, 21) id
|
||||
where nr = 2;
|
||||
|
||||
-- test bsearch
|
||||
select id, txid_visible_in_snapshot(id, snap)
|
||||
from snapshot_test, generate_series(90, 160) id
|
||||
where nr = 4;
|
||||
|
||||
-- test current values also
|
||||
select txid_current() >= txid_snapshot_xmin(txid_current_snapshot());
|
||||
|
||||
-- we can't assume current is always less than xmax, however
|
||||
|
||||
select txid_visible_in_snapshot(txid_current(), txid_current_snapshot());
|
||||
|
||||
-- test 64bitness
|
||||
|
||||
select txid_snapshot '1000100010001000:1000100010001100:1000100010001012,1000100010001013';
|
||||
select txid_visible_in_snapshot('1000100010001012', '1000100010001000:1000100010001100:1000100010001012,1000100010001013');
|
||||
select txid_visible_in_snapshot('1000100010001015', '1000100010001000:1000100010001100:1000100010001012,1000100010001013');
|
||||
|
||||
-- test 64bit overflow
|
||||
SELECT txid_snapshot '1:9223372036854775807:3';
|
||||
SELECT txid_snapshot '1:9223372036854775808:3';
|
Loading…
Reference in New Issue
Block a user