diff -crN pgsql.orig/doc/src/sgml/datatype.sgml pgsql/doc/src/sgml/datatype.sgml *** pgsql.orig/doc/src/sgml/datatype.sgml 2007-08-31 07:52:29.000000000 +0300 --- pgsql/doc/src/sgml/datatype.sgml 2007-10-11 16:29:07.000000000 +0300 *************** *** 247,252 **** --- 247,258 ---- + txid_snapshot + + user-level transaction id snapshot + + + uuid universally unique identifier diff -crN pgsql.orig/doc/src/sgml/func.sgml pgsql/doc/src/sgml/func.sgml *** pgsql.orig/doc/src/sgml/func.sgml 2007-09-24 04:29:27.000000000 +0300 --- pgsql/doc/src/sgml/func.sgml 2007-10-11 17:37:04.000000000 +0300 *************** *** 12048,12054 **** databases within each cluster and their descriptions are stored globally as well. ! System Administration Functions --- 12048,12126 ---- databases within each cluster and their descriptions are stored globally as well. ! ! ! ! txid_current ! ! ! ! txid_current_snapshot ! ! ! ! txid_snapshot_xmin ! ! ! ! txid_snapshot_xmax ! ! ! ! txid_snapshot_xip ! ! ! ! txid_visible_in_snapshot ! ! ! ! The functions shown in ! export backend internal transaction info to user level. ! ! ! ! Transaction IDs and snapshots ! ! ! Name Return Type Description ! ! ! ! ! txid_current() ! int8 ! get current transaction id ! ! ! txid_current_snapshot() ! txid_snapshot ! get current snapshot ! ! ! txid_snapshot_xmin(txid_snapshot) ! int8 ! get xmin of snapshot ! ! ! txid_snapshot_xmax(txid_snapshot) ! int8 ! get xmax of snapshot ! ! ! txid_snapshot_xip(txid_snapshot) ! setof int8 ! get in-progress transaction ids in snapshot ! ! ! txid_visible_in_snapshot(int8, txid_snapshot) ! bool ! check if transaction id is visible in snapshot ! ! ! !
!
System Administration Functions diff -crN pgsql.orig/src/backend/utils/adt/Makefile pgsql/src/backend/utils/adt/Makefile *** pgsql.orig/src/backend/utils/adt/Makefile 2007-09-07 18:09:56.000000000 +0300 --- pgsql/src/backend/utils/adt/Makefile 2007-10-11 16:47:59.000000000 +0300 *************** *** 29,35 **** 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 like.o: like.c like_match.c --- 29,35 ---- 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 txid.o xml.o like.o: like.c like_match.c diff -crN pgsql.orig/src/backend/utils/adt/txid.c pgsql/src/backend/utils/adt/txid.c *** pgsql.orig/src/backend/utils/adt/txid.c 1970-01-01 02:00:00.000000000 +0200 --- pgsql/src/backend/utils/adt/txid.c 2007-10-11 16:02:57.000000000 +0300 *************** *** 0 **** --- 1,581 ---- + /*------------------------------------------------------------------------- + * txid.c + * + * Export backend internal tranasction id's to user level. + * + * Copyright (c) 2003-2007, PostgreSQL Global Development Group + * Author: Jan Wieck, Afilias USA INC. + * + * 64-bit txids: Marko Kreen, Skype Technologies + *------------------------------------------------------------------------- + */ + + #include "postgres.h" + + #include "access/transam.h" + #include "access/xact.h" + #include "funcapi.h" + #include "libpq/pqformat.h" + #include "utils/builtins.h" + + #ifdef INT64_IS_BUSTED + #error txid needs working int64 + #endif + + /* txid will be signed int8 in database */ + #define MAX_TXID UINT64CONST(0x7FFFFFFFFFFFFFFF) + + /* + * If defined, use bsearch() function for searching + * txid's inside snapshots that have more than given values. + */ + #define USE_BSEARCH_IF_NXIP_GREATER 30 + + /* format code for uint64 to appendStringInfo */ + #define TXID_FMT UINT64_FORMAT + + /* Use unsigned variant internally */ + typedef uint64 txid; + + /* + * Snapshot for 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 */ + } TxidSnapshot; + + #define TXID_SNAPSHOT_SIZE(nxip) (offsetof(TxidSnapshot, xip) + sizeof(txid) * (nxip)) + + /* + * Epoch values from backend. + */ + typedef struct { + uint64 last_value; + uint64 epoch; + } TxidEpoch; + + /* + * do a TransactionId -> txid conversion + */ + static txid + convert_xid(TransactionId xid, const TxidEpoch *state) + { + uint64 epoch; + + /* return special xid's as-is */ + if (xid < FirstNormalTransactionId) + return xid; + + /* xid can on both sides on wrap-around */ + epoch = state->epoch; + if (TransactionIdPrecedes(xid, state->last_value)) { + if (xid > state->last_value) + epoch--; + } else if (TransactionIdFollows(xid, state->last_value)) { + if (xid < state->last_value) + epoch++; + } + return (epoch << 32) | xid; + } + + /* + * Fetch epoch data from backend. + */ + static void + load_xid_epoch(TxidEpoch *state) + { + TransactionId xid; + uint32 epoch; + + GetNextXidAndEpoch(&xid, &epoch); + + state->epoch = epoch; + state->last_value = xid; + } + + /* + * compare txid in memory. + */ + static int + cmp_txid(const void *aa, const void *bb) + { + const uint64 *a = aa; + const uint64 *b = bb; + if (*a < *b) + return -1; + if (*a > *b) + return 1; + return 0; + } + + /* + * order txids, for bsearch(). + */ + 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); + return (res) ? false : true; + } + #endif + else + { + int 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 it 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 backend xid machinery. All the others work on data + * returned by them. + * + * So they define what an external transaction will be and their + * definitions must match. Eg. if one returns subtransactions ids + * then other must also. + * + * Currently only top-level transaction id's are tracked, so they use + * GetTopTransactionId() and ActiveSnapshot->xip respectively. + */ + + /* + * txid_current() returns int8 + * + * Return the current transaction ID + */ + 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 + */ + Datum + txid_current_snapshot(PG_FUNCTION_ARGS) + { + TxidSnapshot *snap; + unsigned 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 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) + { + TxidSnapshot *snap; + char *str = PG_GETARG_CSTRING(0); + + 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; + StringInfoData str; + int i; + + snap = (TxidSnapshot *) PG_GETARG_VARLENA_P(0); + + initStringInfo(&str); + + appendStringInfo(&str, TXID_FMT ":", snap->xmin); + appendStringInfo(&str, TXID_FMT ":", snap->xmax); + + for (i = 0; i < snap->nxip; i++) + { + appendStringInfo(&str, "%s" TXID_FMT, + ((i > 0) ? "," : ""), + snap->xip[i]); + } + + PG_FREE_IF_COPY(snap, 0); + + 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; + StringInfoData buf; + int i; + + snap = (TxidSnapshot *)PG_GETARG_VARLENA_P(0); + + 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); + int res; + + res = is_visible_txid(value, snap) ? true : false; + + PG_FREE_IF_COPY(snap, 1); + PG_RETURN_BOOL(res); + } + + /* + * 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); + txid res = snap->xmin; + PG_FREE_IF_COPY(snap, 0); + PG_RETURN_INT64(res); + } + + /* + * 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); + txid res = snap->xmax; + PG_FREE_IF_COPY(snap, 0); + PG_RETURN_INT64(res); + } + + /* + * 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; + + fctx = SRF_FIRSTCALL_INIT(); + + /* make a copy of user snapshot */ + arg = (TxidSnapshot *) PG_GETARG_VARLENA_P(0); + snap = MemoryContextAlloc(fctx->multi_call_memory_ctx, VARSIZE(arg)); + memcpy(snap, arg, VARSIZE(arg)); + PG_FREE_IF_COPY(arg, 0); + + 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); + } + } + diff -crN pgsql.orig/src/include/catalog/pg_proc.h pgsql/src/include/catalog/pg_proc.h *** pgsql.orig/src/include/catalog/pg_proc.h 2007-09-25 23:03:38.000000000 +0300 --- pgsql/src/include/catalog/pg_proc.h 2007-10-11 16:21:36.000000000 +0300 *************** *** 4400,4405 **** --- 4400,4426 ---- DESCR("I/O"); + 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 top 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 the 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 the 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 list 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("check if txid is visible in snapshot"); + /* * Symbolic values for provolatile column: these indicate whether the result * of a function is dependent *only* on the values of its explicit arguments, diff -crN pgsql.orig/src/include/catalog/pg_type.h pgsql/src/include/catalog/pg_type.h *** pgsql.orig/src/include/catalog/pg_type.h 2007-09-03 05:30:45.000000000 +0300 --- pgsql/src/include/catalog/pg_type.h 2007-10-11 16:21:36.000000000 +0300 *************** *** 566,571 **** --- 566,579 ---- DESCR("registered text search dictionary"); #define REGDICTIONARYOID 3769 + DATA(insert OID = 2970 ( txid_snapshot PGNSP PGUID -1 f b t \054 0 0 0 txid_snapshot_in txid_snapshot_out txid_snapshot_recv txid_snapshot_send - - - d x f 0 -1 0 _null_ _null_ )); + DESCR("txid snapshot type"); + #define TXIDSNAPSHOTOID 2970 + DATA(insert OID = 2034 ( _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_ )); + DESCR("txid snapshot array type"); + #define TXIDSNAPSHOTARRAYOID 2034 + + DATA(insert OID = 3643 ( _tsvector PGNSP PGUID -1 f b t \054 0 3614 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); DATA(insert OID = 3644 ( _gtsvector PGNSP PGUID -1 f b t \054 0 3642 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); DATA(insert OID = 3645 ( _tsquery PGNSP PGUID -1 f b t \054 0 3615 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); diff -crN pgsql.orig/src/include/utils/builtins.h pgsql/src/include/utils/builtins.h *** pgsql.orig/src/include/utils/builtins.h 2007-09-24 04:29:30.000000000 +0300 --- pgsql/src/include/utils/builtins.h 2007-10-11 16:21:36.000000000 +0300 *************** *** 961,964 **** --- 961,976 ---- extern Datum uuid_cmp(PG_FUNCTION_ARGS); extern Datum uuid_hash(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); + #endif /* BUILTINS_H */ diff -crN pgsql.orig/src/test/regress/expected/sanity_check.out pgsql/src/test/regress/expected/sanity_check.out *** pgsql.orig/src/test/regress/expected/sanity_check.out 2007-08-21 04:11:31.000000000 +0300 --- pgsql/src/test/regress/expected/sanity_check.out 2007-10-11 16:21:36.000000000 +0300 *************** *** 129,134 **** --- 129,135 ---- road | t shighway | t slow_emp4000 | f + snapshot_test | t sql_features | f sql_implementation_info | f sql_languages | f *************** *** 148,154 **** timetz_tbl | f tinterval_tbl | f varchar_tbl | f ! (137 rows) -- -- another sanity check: every system catalog that has OIDs should have --- 149,155 ---- timetz_tbl | f tinterval_tbl | f varchar_tbl | f ! (138 rows) -- -- another sanity check: every system catalog that has OIDs should have diff -crN pgsql.orig/src/test/regress/expected/txid.out pgsql/src/test/regress/expected/txid.out *** pgsql.orig/src/test/regress/expected/txid.out 1970-01-01 02:00:00.000000000 +0200 --- pgsql/src/test/regress/expected/txid.out 2007-10-10 17:55:20.000000000 +0300 *************** *** 0 **** --- 1,220 ---- + -- i/o + select '12:13:'::txid_snapshot; + txid_snapshot + --------------- + 12:13: + (1 row) + + select '12:13:1,2'::txid_snapshot; + ERROR: invalid input for txid_snapshot: "12:13:1,2" + -- 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 table snapshot_test ( + nr integer not null primary key, + snap txid_snapshot not null + ); + NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "snapshot_test_pkey" for table "snapshot_test" + 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) + + /* due to lazy xid alloc in 8.3 those are different in 8.2 and 8.3 + select txid_current() < txid_snapshot_xmax(txid_current_snapshot()); + + select txid_visible_in_snapshot(txid_current(), txid_current_snapshot()); + */ + -- 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" diff -crN pgsql.orig/src/test/regress/output/misc.source pgsql/src/test/regress/output/misc.source *** pgsql.orig/src/test/regress/output/misc.source 2007-08-21 04:11:31.000000000 +0300 --- pgsql/src/test/regress/output/misc.source 2007-10-11 16:21:36.000000000 +0300 *************** *** 650,655 **** --- 650,656 ---- road shighway slow_emp4000 + snapshot_test street stud_emp student *************** *** 666,672 **** toyemp varchar_tbl xacttest ! (100 rows) SELECT name(equipment(hobby_construct(text 'skywalking', text 'mer'))); name --- 667,673 ---- toyemp varchar_tbl xacttest ! (101 rows) SELECT name(equipment(hobby_construct(text 'skywalking', text 'mer'))); name diff -crN pgsql.orig/src/test/regress/parallel_schedule pgsql/src/test/regress/parallel_schedule *** pgsql.orig/src/test/regress/parallel_schedule 2007-09-11 14:54:42.000000000 +0300 --- pgsql/src/test/regress/parallel_schedule 2007-10-11 16:21:36.000000000 +0300 *************** *** 8,14 **** # ---------- # The first group of parallel tests # ---------- ! test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric uuid enum # Depends on things setup during char, varchar and text test: strings --- 8,14 ---- # ---------- # The first group of parallel tests # ---------- ! test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric uuid enum txid # Depends on things setup during char, varchar and text test: strings diff -crN pgsql.orig/src/test/regress/sql/txid.sql pgsql/src/test/regress/sql/txid.sql *** pgsql.orig/src/test/regress/sql/txid.sql 1970-01-01 02:00:00.000000000 +0200 --- pgsql/src/test/regress/sql/txid.sql 2007-10-10 17:48:52.000000000 +0300 *************** *** 0 **** --- 1,56 ---- + + -- i/o + select '12:13:'::txid_snapshot; + select '12:13:1,2'::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 table snapshot_test ( + nr integer not null primary key, + snap txid_snapshot not null + ); + + 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()); + + /* due to lazy xid alloc in 8.3 those are different in 8.2 and 8.3 + select txid_current() < txid_snapshot_xmax(txid_current_snapshot()); + + 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'; +