*** a/doc/src/sgml/datatype.sgml
--- b/doc/src/sgml/datatype.sgml
***************
*** 181,186 ****
--- 181,192 ----
+ pg_lsn
+
+ PostgreSQL Log Sequence Number
+
+
+
point
geometric point on a plane
***************
*** 4502,4507 **** SELECT * FROM pg_attribute
--- 4508,4528 ----
+
+ PG_LSN Type
+
+
+ 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.
+
+
+
Pseudo-Types
*** a/src/backend/utils/adt/Makefile
--- b/src/backend/utils/adt/Makefile
***************
*** 21,27 **** OBJS = acl.o arrayfuncs.o array_selfuncs.o array_typanalyze.o \
enum.o float.o format_type.o \
geo_ops.o geo_selfuncs.o int.o int8.o json.o jsonfuncs.o like.o \
lockfuncs.o misc.o nabstime.o name.o numeric.o numutils.o \
! oid.o oracle_compat.o orderedsetaggs.o \
pseudotypes.o rangetypes.o rangetypes_gist.o \
rowtypes.o regexp.o regproc.o ruleutils.o selfuncs.o \
tid.o timestamp.o varbit.o varchar.o varlena.o version.o xid.o \
--- 21,27 ----
enum.o float.o format_type.o \
geo_ops.o geo_selfuncs.o int.o int8.o json.o jsonfuncs.o like.o \
lockfuncs.o misc.o nabstime.o name.o numeric.o numutils.o \
! oid.o oracle_compat.o orderedsetaggs.o pg_lsn.o \
pseudotypes.o rangetypes.o rangetypes_gist.o \
rowtypes.o regexp.o regproc.o ruleutils.o selfuncs.o \
tid.o timestamp.o varbit.o varchar.o varlena.o version.o xid.o \
*** /dev/null
--- b/src/backend/utils/adt/pg_lsn.c
***************
*** 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;
+
+ sprintf(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. */
+ sprintf(buf, UINT64_FORMAT, lsn1 - lsn2);
+ result = DirectFunctionCall3(numeric_in,
+ CStringGetDatum(buf),
+ ObjectIdGetDatum(0),
+ Int32GetDatum(-1));
+
+ return result;
+ }
*** a/src/include/catalog/pg_operator.h
--- b/src/include/catalog/pg_operator.h
***************
*** 1592,1597 **** DESCR("less than or equal");
--- 1592,1613 ----
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");
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
***************
*** 4212,4217 **** DESCR("I/O");
--- 4212,4234 ----
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");
*** a/src/include/catalog/pg_type.h
--- b/src/include/catalog/pg_type.h
***************
*** 577,582 **** DESCR("UUID datatype");
--- 577,587 ----
#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");
*** a/src/include/fmgr.h
--- b/src/include/fmgr.h
***************
*** 230,235 **** extern struct varlena *pg_detoast_datum_packed(struct varlena * datum);
--- 230,236 ----
#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,307 **** extern struct varlena *pg_detoast_datum_packed(struct varlena * datum);
--- 303,309 ----
#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)
*** a/src/include/postgres.h
--- b/src/include/postgres.h
***************
*** 484,489 **** typedef Datum *DatumPtr;
--- 484,503 ----
#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.
*/
*** /dev/null
--- b/src/include/utils/pg_lsn.h
***************
*** 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 */
*** /dev/null
--- b/src/test/regress/expected/pg_lsn.out
***************
*** 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 pg_lsn_eq('0/16AE7F8', '0/16AE7F8'); -- true
+ pg_lsn_eq
+ ----------
+ t
+ (1 row)
+
+ SELECT pg_lsn_ne('0/16AE7F8', '0/16AE7F7'); -- true
+ pg_lsn_ne
+ ----------
+ t
+ (1 row)
+
+ SELECT pg_lsn_lt('0/16AE7F7', '0/16AE7F8'); -- true
+ pg_lsn_lt
+ ----------
+ t
+ (1 row)
+
+ SELECT pg_lsn_gt('0/16AE7F8', '0/16AE7F7'); -- true
+ pg_lsn_gt
+ ----------
+ t
+ (1 row)
+
+ SELECT pg_lsn_mi('0/16AE7F7', '0/16AE7F8'); -- No negative results
+ ERROR: transaction log location out of range
+ SELECT pg_lsn_mi('0/16AE7F8', '0/16AE7F7'); -- correct
+ pg_lsn_mi
+ ----------
+ 1
+ (1 row)
+
*** a/src/test/regress/parallel_schedule
--- b/src/test/regress/parallel_schedule
***************
*** 13,19 **** 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
# Depends on things setup during char, varchar and text
test: strings
--- 13,19 ----
# ----------
# 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 pg_lsn
# Depends on things setup during char, varchar and text
test: strings
*** a/src/test/regress/serial_schedule
--- b/src/test/regress/serial_schedule
***************
*** 19,24 **** test: uuid
--- 19,25 ----
test: enum
test: money
test: rangetypes
+ test: pg_lsn
test: strings
test: numerology
test: point
*** /dev/null
--- b/src/test/regress/sql/pg_lsn.sql
***************
*** 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 pg_lsn_eq('0/16AE7F8', '0/16AE7F8'); -- true
+ SELECT pg_lsn_ne('0/16AE7F8', '0/16AE7F7'); -- true
+ SELECT pg_lsn_lt('0/16AE7F7', '0/16AE7F8'); -- true
+ SELECT pg_lsn_gt('0/16AE7F8', '0/16AE7F7'); -- true
+ SELECT pg_lsn_mi('0/16AE7F7', '0/16AE7F8'); -- No negative results
+ SELECT pg_lsn_mi('0/16AE7F8', '0/16AE7F7'); -- correct