Index: contrib/txid/Makefile =================================================================== RCS file: /projects/cvsroot/pgsql/contrib/txid/Makefile,v retrieving revision 1.1 diff -p -u -c -r1.1 Makefile *** contrib/txid/Makefile 7 Oct 2007 23:32:19 -0000 1.1 --- contrib/txid/Makefile 11 Oct 2007 12:30:51 -0000 *************** include $(top_builddir)/src/Makefile.glo *** 17,26 **** include $(top_srcdir)/contrib/contrib-global.mk endif - - test: install - $(MAKE) installcheck || { less regression.diffs; exit 1; } - - ack: - cp results/* expected/ - --- 17,19 ---- Index: contrib/txid/txid.c =================================================================== RCS file: /projects/cvsroot/pgsql/contrib/txid/txid.c,v retrieving revision 1.3 diff -p -u -c -r1.3 txid.c *** contrib/txid/txid.c 8 Oct 2007 22:07:16 -0000 1.3 --- contrib/txid/txid.c 11 Oct 2007 12:30:51 -0000 *************** *** 15,20 **** --- 15,21 ---- #include "access/transam.h" #include "access/xact.h" #include "funcapi.h" + #include "libpq/pqformat.h" #ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; *************** typedef struct { *** 71,76 **** --- 72,79 ---- /* public functions */ Datum txid_snapshot_in(PG_FUNCTION_ARGS); Datum txid_snapshot_out(PG_FUNCTION_ARGS); + Datum txid_snapshot_recv(PG_FUNCTION_ARGS); + Datum txid_snapshot_send(PG_FUNCTION_ARGS); Datum txid_current(PG_FUNCTION_ARGS); Datum txid_current_snapshot(PG_FUNCTION_ARGS); Datum txid_snapshot_xmin(PG_FUNCTION_ARGS); *************** Datum txid_visible_in_snapshot(PG_ *** 81,86 **** --- 84,91 ---- /* public function tags */ PG_FUNCTION_INFO_V1(txid_snapshot_in); PG_FUNCTION_INFO_V1(txid_snapshot_out); + PG_FUNCTION_INFO_V1(txid_snapshot_recv); + PG_FUNCTION_INFO_V1(txid_snapshot_send); PG_FUNCTION_INFO_V1(txid_current); PG_FUNCTION_INFO_V1(txid_current_snapshot); PG_FUNCTION_INFO_V1(txid_snapshot_xmin); *************** bad_format: *** 319,325 **** } /* ! * Public functions */ /* --- 324,341 ---- } /* ! * 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_snapshot(PG_FUNCTION_ARGS) *** 353,361 **** TxidEpoch state; Snapshot cur; ! cur = SerializableSnapshot; if (cur == NULL) ! elog(ERROR, "get_current_snapshot: SerializableSnapshot == NULL"); load_xid_epoch(&state); --- 369,377 ---- TxidEpoch state; Snapshot cur; ! cur = ActiveSnapshot; if (cur == NULL) ! elog(ERROR, "txid_current_snapshot: ActiveSnapshot == NULL"); load_xid_epoch(&state); *************** txid_snapshot_out(PG_FUNCTION_ARGS) *** 425,430 **** --- 441,526 ---- 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 Index: contrib/txid/txid.sql.in =================================================================== RCS file: /projects/cvsroot/pgsql/contrib/txid/txid.sql.in,v retrieving revision 1.1 diff -p -u -c -r1.1 txid.sql.in *** contrib/txid/txid.sql.in 7 Oct 2007 23:32:19 -0000 1.1 --- contrib/txid/txid.sql.in 11 Oct 2007 12:30:52 -0000 *************** CREATE OR REPLACE FUNCTION txid_snapshot *** 20,25 **** --- 20,33 ---- RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + CREATE OR REPLACE FUNCTION txid_snapshot_recv(internal) + RETURNS txid_snapshot + AS 'MODULE_PATHNAME' LANGUAGE C + IMMUTABLE STRICT; + CREATE OR REPLACE FUNCTION txid_snapshot_send(txid_snapshot) + RETURNS bytea + AS 'MODULE_PATHNAME' LANGUAGE C + IMMUTABLE STRICT; -- -- The data type itself *************** CREATE OR REPLACE FUNCTION txid_snapshot *** 27,32 **** --- 35,42 ---- CREATE TYPE txid_snapshot ( INPUT = txid_snapshot_in, OUTPUT = txid_snapshot_out, + RECEIVE = txid_snapshot_recv, + SEND = txid_snapshot_send, INTERNALLENGTH = variable, STORAGE = extended, ALIGNMENT = double