diff options
author | Robert Haas <rhaas@postgresql.org> | 2014-02-19 08:35:23 -0500 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2014-02-19 08:35:23 -0500 |
commit | 7d03a83f4d0736ba869fa6f93973f7623a27038a (patch) | |
tree | d1d7f36c742fcea38edbbf7eb623cca2a52c1378 /src/backend/utils/adt/pg_lsn.c | |
parent | a222f7fda6a04ab8ec655cd5a9de5ff70ff916c3 (diff) | |
download | postgresql-7d03a83f4d0736ba869fa6f93973f7623a27038a.tar.gz postgresql-7d03a83f4d0736ba869fa6f93973f7623a27038a.zip |
Add a pg_lsn data type, to represent an LSN.
Robert Haas and Michael Paquier
Diffstat (limited to 'src/backend/utils/adt/pg_lsn.c')
-rw-r--r-- | src/backend/utils/adt/pg_lsn.c | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/src/backend/utils/adt/pg_lsn.c b/src/backend/utils/adt/pg_lsn.c new file mode 100644 index 00000000000..39e22931362 --- /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; +} |