Change pg_lsn_in_internal() to use soft error reporting

pg_lsn includes pg_lsn_in_internal() for the purpose of parsing a LSN
position for the GUC recovery_target_lsn (21f428ebde).  It relies on a
boolean called "have_error" that would be set when the LSN parsing
fails, then let its callers handle any errors.

d9f7f5d32f has added support for soft error reporting.  This commit
removes some boilerplate code and switches the routine to use soft error
reporting directly, giving to the callers of pg_lsn_in_internal()
the possibility to be fed the error message generated on failure.

pg_lsn_in_internal() routine is renamed to pg_lsn_in_safe(), for
consistency with other similar routines that are given an escontext.

Author: Amul Sul <sulamul@gmail.com>
Reviewed-by: Dean Rasheed <dean.a.rasheed@gmail.com>
Discussion: https://postgr.es/m/CAAJ_b96No5h5tRuR+KhcC44YcYUCw8WAHuLoqqyyop8_k3+JDQ@mail.gmail.com
master
Michael Paquier 6 days ago
parent d814d7fc3d
commit ae45312008
  1. 6
      src/backend/access/transam/xlogrecovery.c
  2. 35
      src/backend/utils/adt/pg_lsn.c
  3. 5
      src/include/utils/pg_lsn.h

@ -4834,10 +4834,10 @@ check_recovery_target_lsn(char **newval, void **extra, GucSource source)
{
XLogRecPtr lsn;
XLogRecPtr *myextra;
bool have_error = false;
ErrorSaveContext escontext = {T_ErrorSaveContext};
lsn = pg_lsn_in_internal(*newval, &have_error);
if (have_error)
lsn = pg_lsn_in_safe(*newval, (Node *) &escontext);
if (escontext.error_occurred)
return false;
myextra = (XLogRecPtr *) guc_malloc(LOG, sizeof(XLogRecPtr));

@ -25,8 +25,11 @@
* Formatting and conversion routines.
*---------------------------------------------------------*/
/*
* Internal version of pg_lsn_in() with support for soft error reporting.
*/
XLogRecPtr
pg_lsn_in_internal(const char *str, bool *have_error)
pg_lsn_in_safe(const char *str, Node *escontext)
{
int len1,
len2;
@ -34,22 +37,14 @@ pg_lsn_in_internal(const char *str, bool *have_error)
off;
XLogRecPtr result;
Assert(have_error != NULL);
*have_error = false;
/* Sanity check input format. */
len1 = strspn(str, "0123456789abcdefABCDEF");
if (len1 < 1 || len1 > MAXPG_LSNCOMPONENT || str[len1] != '/')
{
*have_error = true;
return InvalidXLogRecPtr;
}
goto syntax_error;
len2 = strspn(str + len1 + 1, "0123456789abcdefABCDEF");
if (len2 < 1 || len2 > MAXPG_LSNCOMPONENT || str[len1 + 1 + len2] != '\0')
{
*have_error = true;
return InvalidXLogRecPtr;
}
goto syntax_error;
/* Decode result. */
id = (uint32) strtoul(str, NULL, 16);
@ -57,6 +52,12 @@ pg_lsn_in_internal(const char *str, bool *have_error)
result = ((uint64) id << 32) | off;
return result;
syntax_error:
ereturn(escontext, InvalidXLogRecPtr,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type %s: \"%s\"",
"pg_lsn", str)));
}
Datum
@ -64,14 +65,8 @@ pg_lsn_in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
XLogRecPtr result;
bool have_error = false;
result = pg_lsn_in_internal(str, &have_error);
if (have_error)
ereturn(fcinfo->context, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type %s: \"%s\"",
"pg_lsn", str)));
result = pg_lsn_in_safe(str, fcinfo->context);
PG_RETURN_LSN(result);
}

@ -18,6 +18,9 @@
#include "access/xlogdefs.h"
#include "fmgr.h"
/* forward declaration to avoid node.h include */
typedef struct Node Node;
static inline XLogRecPtr
DatumGetLSN(Datum X)
{
@ -33,6 +36,6 @@ LSNGetDatum(XLogRecPtr X)
#define PG_GETARG_LSN(n) DatumGetLSN(PG_GETARG_DATUM(n))
#define PG_RETURN_LSN(x) return LSNGetDatum(x)
extern XLogRecPtr pg_lsn_in_internal(const char *str, bool *have_error);
extern XLogRecPtr pg_lsn_in_safe(const char *str, Node *escontext);
#endif /* PG_LSN_H */

Loading…
Cancel
Save