From 7d03a83f4d0736ba869fa6f93973f7623a27038a Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Wed, 19 Feb 2014 08:35:23 -0500 Subject: [PATCH] Add a pg_lsn data type, to represent an LSN. Robert Haas and Michael Paquier --- doc/src/sgml/datatype.sgml | 32 +++++ src/backend/utils/adt/Makefile | 2 +- src/backend/utils/adt/pg_lsn.c | 180 +++++++++++++++++++++++++++ src/include/catalog/catversion.h | 2 +- src/include/catalog/pg_operator.h | 16 +++ src/include/catalog/pg_proc.h | 17 +++ src/include/catalog/pg_type.h | 5 + src/include/fmgr.h | 2 + src/include/postgres.h | 14 +++ src/include/utils/pg_lsn.h | 34 +++++ src/test/regress/expected/pg_lsn.out | 62 +++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/serial_schedule | 1 + src/test/regress/sql/pg_lsn.sql | 25 ++++ 14 files changed, 391 insertions(+), 3 deletions(-) create mode 100644 src/backend/utils/adt/pg_lsn.c create mode 100644 src/include/utils/pg_lsn.h create mode 100644 src/test/regress/expected/pg_lsn.out create mode 100644 src/test/regress/sql/pg_lsn.sql diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index 30fd9bb598..00ccbe1bb5 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -180,6 +180,12 @@ geometric path on a plane + + pg_lsn + + PostgreSQL Log Sequence Number + + point @@ -4504,6 +4510,32 @@ SELECT * FROM pg_attribute + + <acronym>pg_lsn Type</acronym> + + + pg_lsn + + + + The pg_lsn data type can be used to store LSN (Log Sequence + Number) data which is a pointer to a location in the XLOG. This type is a + representation of XLogRecPtr and an internal system type of + PostgreSQL. + + + + Internally, an LSN is a 64-bit integer, representing a byte position in + the write-ahead log stream. It is printed as two hexadecimal numbers of + up to 8 digits each, separated by a slash; for example, + 16/B374D848. The pg_lsn type supports the + standard comparison operators, like = and + >. Two LSNs can be subtracted using the + - operator; the result is the number of bytes separating + those write-ahead log positions. + + + Pseudo-Types diff --git a/src/backend/utils/adt/Makefile b/src/backend/utils/adt/Makefile index 51355754d5..644687954b 100644 --- a/src/backend/utils/adt/Makefile +++ b/src/backend/utils/adt/Makefile @@ -24,7 +24,7 @@ OBJS = acl.o arrayfuncs.o array_selfuncs.o array_typanalyze.o \ int8.o json.o jsonfuncs.o like.o \ lockfuncs.o mac.o misc.o nabstime.o name.o network.o numeric.o \ numutils.o oid.o oracle_compat.o orderedsetaggs.o \ - pg_lzcompress.o pg_locale.o pgstatfuncs.o \ + pg_lzcompress.o pg_locale.o pg_lsn.o pgstatfuncs.o \ pseudotypes.o quote.o rangetypes.o rangetypes_gist.o \ rangetypes_selfuncs.o rangetypes_spgist.o rangetypes_typanalyze.o \ regexp.o regproc.o ri_triggers.o rowtypes.o ruleutils.o \ diff --git a/src/backend/utils/adt/pg_lsn.c b/src/backend/utils/adt/pg_lsn.c new file mode 100644 index 0000000000..39e2293136 --- /dev/null +++ b/src/backend/utils/adt/pg_lsn.c @@ -0,0 +1,180 @@ +/*------------------------------------------------------------------------- + * + * pg_lsn.c + * Internal PostgreSQL LSN operations + * + * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/utils/adt/pg_lsn.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "funcapi.h" +#include "libpq/pqformat.h" +#include "utils/builtins.h" +#include "utils/pg_lsn.h" + +#define MAXPG_LSNLEN 17 +#define MAXPG_LSNCOMPONENT 8 + +/*---------------------------------------------------------- + * Formatting and conversion routines. + *---------------------------------------------------------*/ + +Datum +pg_lsn_in(PG_FUNCTION_ARGS) +{ + char *str = PG_GETARG_CSTRING(0); + int len1, len2; + uint32 id, off; + XLogRecPtr result; + + /* Sanity check input format. */ + len1 = strspn(str, "0123456789abcdefABCDEF"); + if (len1 < 1 || len1 > MAXPG_LSNCOMPONENT || str[len1] != '/') + ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for transaction log location: \"%s\"", str))); + len2 = strspn(str + len1 + 1, "0123456789abcdefABCDEF"); + if (len2 < 1 || len2 > MAXPG_LSNCOMPONENT || str[len1 + 1 + len2] != '\0') + ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for transaction log location: \"%s\"", str))); + + /* Decode result. */ + id = (uint32) strtoul(str, NULL, 16); + off = (uint32) strtoul(str + len1 + 1, NULL, 16); + result = (XLogRecPtr) ((uint64) id << 32) | off; + + PG_RETURN_PG_LSN(result); +} + +Datum +pg_lsn_out(PG_FUNCTION_ARGS) +{ + XLogRecPtr lsn = (XLogRecPtr) PG_GETARG_PG_LSN(0); + char buf[MAXPG_LSNLEN + 1]; + char *result; + uint32 id, off; + + /* Decode ID and offset */ + id = (uint32) (lsn >> 32); + off = (uint32) lsn; + + snprintf(buf, sizeof buf, "%X/%X", id, off); + result = pstrdup(buf); + PG_RETURN_CSTRING(result); +} + +Datum +pg_lsn_recv(PG_FUNCTION_ARGS) +{ + StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); + XLogRecPtr result; + + result = pq_getmsgint64(buf); + PG_RETURN_PG_LSN(result); +} + +Datum +pg_lsn_send(PG_FUNCTION_ARGS) +{ + XLogRecPtr lsn = (XLogRecPtr) PG_GETARG_PG_LSN(0); + StringInfoData buf; + + pq_begintypsend(&buf); + pq_sendint64(&buf, lsn); + PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); +} + + +/*---------------------------------------------------------- + * Operators for PostgreSQL LSNs + *---------------------------------------------------------*/ + +Datum +pg_lsn_eq(PG_FUNCTION_ARGS) +{ + XLogRecPtr lsn1 = (XLogRecPtr) PG_GETARG_PG_LSN(0); + XLogRecPtr lsn2 = (XLogRecPtr) PG_GETARG_PG_LSN(1); + + PG_RETURN_BOOL(lsn1 == lsn2); +} + +Datum +pg_lsn_ne(PG_FUNCTION_ARGS) +{ + XLogRecPtr lsn1 = (XLogRecPtr) PG_GETARG_PG_LSN(0); + XLogRecPtr lsn2 = (XLogRecPtr) PG_GETARG_PG_LSN(1); + + PG_RETURN_BOOL(lsn1 != lsn2); +} + +Datum +pg_lsn_lt(PG_FUNCTION_ARGS) +{ + XLogRecPtr lsn1 = (XLogRecPtr) PG_GETARG_PG_LSN(0); + XLogRecPtr lsn2 = (XLogRecPtr) PG_GETARG_PG_LSN(1); + + PG_RETURN_BOOL(lsn1 < lsn2); +} + +Datum +pg_lsn_gt(PG_FUNCTION_ARGS) +{ + XLogRecPtr lsn1 = (XLogRecPtr) PG_GETARG_PG_LSN(0); + XLogRecPtr lsn2 = (XLogRecPtr) PG_GETARG_PG_LSN(1); + + PG_RETURN_BOOL(lsn1 > lsn2); +} + +Datum +pg_lsn_le(PG_FUNCTION_ARGS) +{ + XLogRecPtr lsn1 = (XLogRecPtr) PG_GETARG_PG_LSN(0); + XLogRecPtr lsn2 = (XLogRecPtr) PG_GETARG_PG_LSN(1); + + PG_RETURN_BOOL(lsn1 <= lsn2); +} + +Datum +pg_lsn_ge(PG_FUNCTION_ARGS) +{ + XLogRecPtr lsn1 = (XLogRecPtr) PG_GETARG_PG_LSN(0); + XLogRecPtr lsn2 = (XLogRecPtr) PG_GETARG_PG_LSN(1); + + PG_RETURN_BOOL(lsn1 >= lsn2); +} + + +/*---------------------------------------------------------- + * Arithmetic operators on PostgreSQL LSNs. + *---------------------------------------------------------*/ + +Datum +pg_lsn_mi(PG_FUNCTION_ARGS) +{ + XLogRecPtr lsn1 = (XLogRecPtr) PG_GETARG_PG_LSN(0); + XLogRecPtr lsn2 = (XLogRecPtr) PG_GETARG_PG_LSN(1); + char buf[256]; + Datum result; + + /* Negative results are not allowed. */ + if (lsn1 < lsn2) + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("transaction log location out of range"))); + + /* Convert to numeric. */ + snprintf(buf, sizeof buf, UINT64_FORMAT, lsn1 - lsn2); + result = DirectFunctionCall3(numeric_in, + CStringGetDatum(buf), + ObjectIdGetDatum(0), + Int32GetDatum(-1)); + + return result; +} diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 9263b0df7a..cd1afc842d 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201402031 +#define CATALOG_VERSION_NO 201402191 #endif diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h index 6aa4890782..e07d6d9ef9 100644 --- a/src/include/catalog/pg_operator.h +++ b/src/include/catalog/pg_operator.h @@ -1592,6 +1592,22 @@ DESCR("less than or equal"); DATA(insert OID = 2977 ( ">=" PGNSP PGUID b f f 2950 2950 16 2976 2974 uuid_ge scalargtsel scalargtjoinsel )); DESCR("greater than or equal"); +/* pg_lsn operators */ +DATA(insert OID = 3222 ( "=" PGNSP PGUID b f f 3220 3220 16 3222 3223 pg_lsn_eq eqsel eqjoinsel )); +DESCR("equal"); +DATA(insert OID = 3223 ( "<>" PGNSP PGUID b f f 3220 3220 16 3223 3222 pg_lsn_ne neqsel neqjoinsel )); +DESCR("not equal"); +DATA(insert OID = 3224 ( "<" PGNSP PGUID b f f 3220 3220 16 3225 3227 pg_lsn_lt scalarltsel scalarltjoinsel )); +DESCR("less than"); +DATA(insert OID = 3225 ( ">" PGNSP PGUID b f f 3220 3220 16 3224 3226 pg_lsn_gt scalargtsel scalargtjoinsel )); +DESCR("greater than"); +DATA(insert OID = 3226 ( "<=" PGNSP PGUID b f f 3220 3220 16 3227 3225 pg_lsn_le scalarltsel scalarltjoinsel )); +DESCR("less than or equal"); +DATA(insert OID = 3227 ( ">=" PGNSP PGUID b f f 3220 3220 16 3226 3224 pg_lsn_ge scalargtsel scalargtjoinsel )); +DESCR("greater than or equal"); +DATA(insert OID = 3228 ( "-" PGNSP PGUID b f f 3220 3220 1700 0 0 pg_lsn_mi - - )); +DESCR("minus"); + /* enum operators */ DATA(insert OID = 3516 ( "=" PGNSP PGUID b t t 3500 3500 16 3516 3517 enum_eq eqsel eqjoinsel )); DESCR("equal"); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index e6713a6106..ac726462e4 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -4212,6 +4212,23 @@ DESCR("I/O"); DATA(insert OID = 2963 ( uuid_hash PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 23 "2950" _null_ _null_ _null_ _null_ uuid_hash _null_ _null_ _null_ )); DESCR("hash"); +/* pg_lsn */ +DATA(insert OID = 3229 ( pg_lsn_in PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 3220 "2275" _null_ _null_ _null_ _null_ pg_lsn_in _null_ _null_ _null_ )); +DESCR("I/O"); +DATA(insert OID = 3230 ( pg_lsn_out PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "3220" _null_ _null_ _null_ _null_ pg_lsn_out _null_ _null_ _null_ )); +DESCR("I/O"); +DATA(insert OID = 3231 ( pg_lsn_lt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "3220 3220" _null_ _null_ _null_ _null_ pg_lsn_lt _null_ _null_ _null_ )); +DATA(insert OID = 3232 ( pg_lsn_le PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "3220 3220" _null_ _null_ _null_ _null_ pg_lsn_le _null_ _null_ _null_ )); +DATA(insert OID = 3233 ( pg_lsn_eq PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "3220 3220" _null_ _null_ _null_ _null_ pg_lsn_eq _null_ _null_ _null_ )); +DATA(insert OID = 3234 ( pg_lsn_ge PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "3220 3220" _null_ _null_ _null_ _null_ pg_lsn_ge _null_ _null_ _null_ )); +DATA(insert OID = 3235 ( pg_lsn_gt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "3220 3220" _null_ _null_ _null_ _null_ pg_lsn_gt _null_ _null_ _null_ )); +DATA(insert OID = 3236 ( pg_lsn_ne PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "3220 3220" _null_ _null_ _null_ _null_ pg_lsn_ne _null_ _null_ _null_ )); +DATA(insert OID = 3237 ( pg_lsn_mi PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1700 "3220 3220" _null_ _null_ _null_ _null_ pg_lsn_mi _null_ _null_ _null_ )); +DATA(insert OID = 3238 ( pg_lsn_recv PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 3220 "2281" _null_ _null_ _null_ _null_ pg_lsn_recv _null_ _null_ _null_ )); +DESCR("I/O"); +DATA(insert OID = 3239 ( pg_lsn_send PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 17 "3220" _null_ _null_ _null_ _null_ pg_lsn_send _null_ _null_ _null_ )); +DESCR("I/O"); + /* enum related procs */ DATA(insert OID = 3504 ( anyenum_in PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 3500 "2275" _null_ _null_ _null_ _null_ anyenum_in _null_ _null_ _null_ )); DESCR("I/O"); diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index 3fc20c6a8d..db18a23bf6 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -577,6 +577,11 @@ DESCR("UUID datatype"); #define UUIDOID 2950 DATA(insert OID = 2951 ( _uuid PGNSP PGUID -1 f b A f t \054 0 2950 0 array_in array_out array_recv array_send - - array_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ )); +/* pg_lsn */ +DATA(insert OID = 3220 ( pg_lsn PGNSP PGUID 8 t b U t t \054 0 0 3221 pg_lsn_in pg_lsn_out pg_lsn_recv pg_lsn_send - - - d p f 0 -1 0 0 _null_ _null_ _null_ )); +DESCR("PostgreSQL LSN datatype"); +DATA(insert OID = 3221 ( _pg_lsn PGNSP PGUID -1 f b A f t \054 0 3220 0 array_in array_out array_recv array_send - - array_typanalyze d x f 0 -1 0 0 _null_ _null_ _null_ )); + /* text search */ DATA(insert OID = 3614 ( tsvector PGNSP PGUID -1 f b U f t \054 0 0 3643 tsvectorin tsvectorout tsvectorrecv tsvectorsend - - ts_typanalyze i x f 0 -1 0 0 _null_ _null_ _null_ )); DESCR("text representation for text search"); diff --git a/src/include/fmgr.h b/src/include/fmgr.h index aed81cdc26..700435b548 100644 --- a/src/include/fmgr.h +++ b/src/include/fmgr.h @@ -230,6 +230,7 @@ extern struct varlena *pg_detoast_datum_packed(struct varlena * datum); #define PG_GETARG_CHAR(n) DatumGetChar(PG_GETARG_DATUM(n)) #define PG_GETARG_BOOL(n) DatumGetBool(PG_GETARG_DATUM(n)) #define PG_GETARG_OID(n) DatumGetObjectId(PG_GETARG_DATUM(n)) +#define PG_GETARG_PG_LSN(n) DatumGetPgLsn(PG_GETARG_DATUM(n)) #define PG_GETARG_POINTER(n) DatumGetPointer(PG_GETARG_DATUM(n)) #define PG_GETARG_CSTRING(n) DatumGetCString(PG_GETARG_DATUM(n)) #define PG_GETARG_NAME(n) DatumGetName(PG_GETARG_DATUM(n)) @@ -302,6 +303,7 @@ extern struct varlena *pg_detoast_datum_packed(struct varlena * datum); #define PG_RETURN_CHAR(x) return CharGetDatum(x) #define PG_RETURN_BOOL(x) return BoolGetDatum(x) #define PG_RETURN_OID(x) return ObjectIdGetDatum(x) +#define PG_RETURN_PG_LSN(x) return PgLsnGetDatum(x) #define PG_RETURN_POINTER(x) return PointerGetDatum(x) #define PG_RETURN_CSTRING(x) return CStringGetDatum(x) #define PG_RETURN_NAME(x) return NameGetDatum(x) diff --git a/src/include/postgres.h b/src/include/postgres.h index a8a206d988..e72d5fca2b 100644 --- a/src/include/postgres.h +++ b/src/include/postgres.h @@ -483,6 +483,20 @@ typedef Datum *DatumPtr; #define ObjectIdGetDatum(X) ((Datum) SET_4_BYTES(X)) +/* + * DatumGetPgLsn + * Returns PostgreSQL log sequence number of a datum. + */ + +#define DatumGetPgLsn(X) ((XLogRecPtr) GET_8_BYTES(X)) + +/* + * PG_LSNGetDatum + * Returns datum representation for a PostgreSQL log sequence number. + */ + +#define PgLsnGetDatum(X) ((Datum) SET_8_BYTES(X)) + /* * DatumGetTransactionId * Returns transaction identifier value of a datum. diff --git a/src/include/utils/pg_lsn.h b/src/include/utils/pg_lsn.h new file mode 100644 index 0000000000..dc2193006e --- /dev/null +++ b/src/include/utils/pg_lsn.h @@ -0,0 +1,34 @@ +/*------------------------------------------------------------------------- + * + * pg_lsn.h + * Declarations for operations on log sequence numbers (LSNs) of + * PostgreSQL. + * + * + * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/utils/pg_lsn.h + * + *------------------------------------------------------------------------- + */ +#ifndef PG_LSN_H +#define PG_LSN_H + +#include "fmgr.h" + +extern Datum pg_lsn_in(PG_FUNCTION_ARGS); +extern Datum pg_lsn_out(PG_FUNCTION_ARGS); +extern Datum pg_lsn_recv(PG_FUNCTION_ARGS); +extern Datum pg_lsn_send(PG_FUNCTION_ARGS); + +extern Datum pg_lsn_eq(PG_FUNCTION_ARGS); +extern Datum pg_lsn_ne(PG_FUNCTION_ARGS); +extern Datum pg_lsn_lt(PG_FUNCTION_ARGS); +extern Datum pg_lsn_gt(PG_FUNCTION_ARGS); +extern Datum pg_lsn_le(PG_FUNCTION_ARGS); +extern Datum pg_lsn_ge(PG_FUNCTION_ARGS); + +extern Datum pg_lsn_mi(PG_FUNCTION_ARGS); + +#endif /* PG_LSN_H */ diff --git a/src/test/regress/expected/pg_lsn.out b/src/test/regress/expected/pg_lsn.out new file mode 100644 index 0000000000..50258f7ef1 --- /dev/null +++ b/src/test/regress/expected/pg_lsn.out @@ -0,0 +1,62 @@ +-- +-- PG_LSN +-- +CREATE TABLE PG_LSN_TBL (f1 pg_lsn); +-- Largest and smallest input +INSERT INTO PG_LSN_TBL VALUES ('0/0'); +INSERT INTO PG_LSN_TBL VALUES ('FFFFFFFF/FFFFFFFF'); +-- Incorrect input +INSERT INTO PG_LSN_TBL VALUES ('G/0'); +ERROR: invalid input syntax for transaction log location: "G/0" +LINE 1: INSERT INTO PG_LSN_TBL VALUES ('G/0'); + ^ +INSERT INTO PG_LSN_TBL VALUES ('-1/0'); +ERROR: invalid input syntax for transaction log location: "-1/0" +LINE 1: INSERT INTO PG_LSN_TBL VALUES ('-1/0'); + ^ +INSERT INTO PG_LSN_TBL VALUES (' 0/12345678'); +ERROR: invalid input syntax for transaction log location: " 0/12345678" +LINE 1: INSERT INTO PG_LSN_TBL VALUES (' 0/12345678'); + ^ +INSERT INTO PG_LSN_TBL VALUES ('ABCD/'); +ERROR: invalid input syntax for transaction log location: "ABCD/" +LINE 1: INSERT INTO PG_LSN_TBL VALUES ('ABCD/'); + ^ +INSERT INTO PG_LSN_TBL VALUES ('/ABCD'); +ERROR: invalid input syntax for transaction log location: "/ABCD" +LINE 1: INSERT INTO PG_LSN_TBL VALUES ('/ABCD'); + ^ +DROP TABLE PG_LSN_TBL; +-- Operators +SELECT '0/16AE7F8' = '0/16AE7F8'::pg_lsn; + ?column? +---------- + t +(1 row) + +SELECT '0/16AE7F8'::pg_lsn != '0/16AE7F7'; + ?column? +---------- + t +(1 row) + +SELECT '0/16AE7F7' < '0/16AE7F8'::pg_lsn; + ?column? +---------- + t +(1 row) + +SELECT '0/16AE7F8' > pg_lsn '0/16AE7F7'; + ?column? +---------- + t +(1 row) + +SELECT '0/16AE7F7'::pg_lsn - '0/16AE7F8'::pg_lsn; -- No negative results +ERROR: transaction log location out of range +SELECT '0/16AE7F8'::pg_lsn - '0/16AE7F7'::pg_lsn; -- correct + ?column? +---------- + 1 +(1 row) + diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 5758b07fa4..2e3eba83de 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -13,7 +13,7 @@ test: tablespace # ---------- # The first group of parallel tests # ---------- -test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric txid uuid enum money rangetypes +test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric txid uuid enum money rangetypes pg_lsn # Depends on things setup during char, varchar and text test: strings diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule index 78348f5f86..4f1dedec2b 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -19,6 +19,7 @@ test: uuid test: enum test: money test: rangetypes +test: pg_lsn test: strings test: numerology test: point diff --git a/src/test/regress/sql/pg_lsn.sql b/src/test/regress/sql/pg_lsn.sql new file mode 100644 index 0000000000..dddafb32f7 --- /dev/null +++ b/src/test/regress/sql/pg_lsn.sql @@ -0,0 +1,25 @@ +-- +-- PG_LSN +-- + +CREATE TABLE PG_LSN_TBL (f1 pg_lsn); + +-- Largest and smallest input +INSERT INTO PG_LSN_TBL VALUES ('0/0'); +INSERT INTO PG_LSN_TBL VALUES ('FFFFFFFF/FFFFFFFF'); + +-- Incorrect input +INSERT INTO PG_LSN_TBL VALUES ('G/0'); +INSERT INTO PG_LSN_TBL VALUES ('-1/0'); +INSERT INTO PG_LSN_TBL VALUES (' 0/12345678'); +INSERT INTO PG_LSN_TBL VALUES ('ABCD/'); +INSERT INTO PG_LSN_TBL VALUES ('/ABCD'); +DROP TABLE PG_LSN_TBL; + +-- Operators +SELECT '0/16AE7F8' = '0/16AE7F8'::pg_lsn; +SELECT '0/16AE7F8'::pg_lsn != '0/16AE7F7'; +SELECT '0/16AE7F7' < '0/16AE7F8'::pg_lsn; +SELECT '0/16AE7F8' > pg_lsn '0/16AE7F7'; +SELECT '0/16AE7F7'::pg_lsn - '0/16AE7F8'::pg_lsn; -- No negative results +SELECT '0/16AE7F8'::pg_lsn - '0/16AE7F7'::pg_lsn; -- correct -- 2.40.0