diff options
author | Peter Eisentraut | 2019-06-30 08:15:25 +0000 |
---|---|---|
committer | Peter Eisentraut | 2019-06-30 08:27:43 +0000 |
commit | 21f428ebde39339487c271a830fed135d6032d73 (patch) | |
tree | 0a69ab528a79a31f3306a1d60c190c09a1fca085 /src/backend/utils/adt/pg_lsn.c | |
parent | 666cbae16da46b833f57ef8b12ff0bf215684d9c (diff) |
Don't call data type input functions in GUC check hooks
Instead of calling pg_lsn_in() in check_recovery_target_lsn and
timestamptz_in() in check_recovery_target_time, reorganize the
respective code so that we don't raise any errors in the check hooks.
The previous code tried to use PG_TRY/PG_CATCH to handle errors in a
way that is not safe, so now the code contains no ereport() calls and
can operate safely within the GUC error handling system.
Moreover, since the interpretation of the recovery_target_time string
may depend on the time zone, we cannot do the final processing of that
string until all the GUC processing is done. Instead,
check_recovery_target_time() now does some parsing for syntax
checking, but the actual conversion to a timestamptz value is done
later in the recovery code that uses it.
Reported-by: Andres Freund <[email protected]>
Reviewed-by: Michael Paquier <[email protected]>
Discussion: https://www.postgresql.org/message-id/flat/20190611061115.njjwkagvxp4qujhp%40alap3.anarazel.de
Diffstat (limited to 'src/backend/utils/adt/pg_lsn.c')
-rw-r--r-- | src/backend/utils/adt/pg_lsn.c | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/src/backend/utils/adt/pg_lsn.c b/src/backend/utils/adt/pg_lsn.c index 7242d3cfed4..eb586851529 100644 --- a/src/backend/utils/adt/pg_lsn.c +++ b/src/backend/utils/adt/pg_lsn.c @@ -25,10 +25,9 @@ * Formatting and conversion routines. *---------------------------------------------------------*/ -Datum -pg_lsn_in(PG_FUNCTION_ARGS) +XLogRecPtr +pg_lsn_in_internal(const char *str, bool *have_error) { - char *str = PG_GETARG_CSTRING(0); int len1, len2; uint32 id, @@ -38,16 +37,16 @@ pg_lsn_in(PG_FUNCTION_ARGS) /* 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 type %s: \"%s\"", - "pg_lsn", str))); + { + *have_error = true; + return InvalidXLogRecPtr; + } 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 type %s: \"%s\"", - "pg_lsn", str))); + { + *have_error = true; + return InvalidXLogRecPtr; + } /* Decode result. */ id = (uint32) strtoul(str, NULL, 16); @@ -58,6 +57,23 @@ pg_lsn_in(PG_FUNCTION_ARGS) } Datum +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) + ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s: \"%s\"", + "pg_lsn", str))); + + PG_RETURN_LSN(result); +} + +Datum pg_lsn_out(PG_FUNCTION_ARGS) { XLogRecPtr lsn = PG_GETARG_LSN(0); |