diff options
Diffstat (limited to 'src/backend/utils/adt/pg_lsn.c')
-rw-r--r-- | src/backend/utils/adt/pg_lsn.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/backend/utils/adt/pg_lsn.c b/src/backend/utils/adt/pg_lsn.c index d9754a7778c..ad0a7bd869d 100644 --- a/src/backend/utils/adt/pg_lsn.c +++ b/src/backend/utils/adt/pg_lsn.c @@ -16,6 +16,7 @@ #include "funcapi.h" #include "libpq/pqformat.h" #include "utils/builtins.h" +#include "utils/numeric.h" #include "utils/pg_lsn.h" #define MAXPG_LSNLEN 17 @@ -248,3 +249,71 @@ pg_lsn_mi(PG_FUNCTION_ARGS) return result; } + +/* + * Add the number of bytes to pg_lsn, giving a new pg_lsn. + * Must handle both positive and negative numbers of bytes. + */ +Datum +pg_lsn_pli(PG_FUNCTION_ARGS) +{ + XLogRecPtr lsn = PG_GETARG_LSN(0); + Numeric nbytes = PG_GETARG_NUMERIC(1); + Datum num; + Datum res; + char buf[32]; + + if (numeric_is_nan(nbytes)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot add NaN to pg_lsn"))); + + /* Convert to numeric */ + snprintf(buf, sizeof(buf), UINT64_FORMAT, lsn); + num = DirectFunctionCall3(numeric_in, + CStringGetDatum(buf), + ObjectIdGetDatum(0), + Int32GetDatum(-1)); + + /* Add two numerics */ + res = DirectFunctionCall2(numeric_add, + NumericGetDatum(num), + NumericGetDatum(nbytes)); + + /* Convert to pg_lsn */ + return DirectFunctionCall1(numeric_pg_lsn, res); +} + +/* + * Subtract the number of bytes from pg_lsn, giving a new pg_lsn. + * Must handle both positive and negative numbers of bytes. + */ +Datum +pg_lsn_mii(PG_FUNCTION_ARGS) +{ + XLogRecPtr lsn = PG_GETARG_LSN(0); + Numeric nbytes = PG_GETARG_NUMERIC(1); + Datum num; + Datum res; + char buf[32]; + + if (numeric_is_nan(nbytes)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot subtract NaN from pg_lsn"))); + + /* Convert to numeric */ + snprintf(buf, sizeof(buf), UINT64_FORMAT, lsn); + num = DirectFunctionCall3(numeric_in, + CStringGetDatum(buf), + ObjectIdGetDatum(0), + Int32GetDatum(-1)); + + /* Subtract two numerics */ + res = DirectFunctionCall2(numeric_sub, + NumericGetDatum(num), + NumericGetDatum(nbytes)); + + /* Convert to pg_lsn */ + return DirectFunctionCall1(numeric_pg_lsn, res); +} |