diff options
author | Alexander Korotkov <akorotkov@postgresql.org> | 2019-03-16 12:21:19 +0300 |
---|---|---|
committer | Alexander Korotkov <akorotkov@postgresql.org> | 2019-03-16 12:21:19 +0300 |
commit | 16d489b0fe058e527619f5e9d92fd7ca3c6c2994 (patch) | |
tree | d0f82a4250a33db045574fc69137eb32d52d04f9 /src/backend/utils/adt/float.c | |
parent | 72b6460336e86ad5cafd3426af6013c7d8457367 (diff) | |
download | postgresql-16d489b0fe058e527619f5e9d92fd7ca3c6c2994.tar.gz postgresql-16d489b0fe058e527619f5e9d92fd7ca3c6c2994.zip |
Numeric error suppression in jsonpath
Add support of numeric error suppression to jsonpath as it's required by
standard. This commit doesn't use PG_TRY()/PG_CATCH() in order to implement
that. Instead, it provides internal versions of numeric functions used, which
support error suppression.
Discussion: https://postgr.es/m/fcc6fc6a-b497-f39a-923d-aa34d0c588e8%402ndQuadrant.com
Author: Alexander Korotkov, Nikita Glukhov
Reviewed-by: Tomas Vondra
Diffstat (limited to 'src/backend/utils/adt/float.c')
-rw-r--r-- | src/backend/utils/adt/float.c | 68 |
1 files changed, 49 insertions, 19 deletions
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index 8e16d755b04..23649c10000 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -336,8 +336,19 @@ float8in(PG_FUNCTION_ARGS) PG_RETURN_FLOAT8(float8in_internal(num, NULL, "double precision", num)); } +/* Convenience macro: set *have_error flag (if provided) or throw error */ +#define RETURN_ERROR(throw_error) \ +do { \ + if (have_error) { \ + *have_error = true; \ + return 0.0; \ + } else { \ + throw_error; \ + } \ +} while (0) + /* - * float8in_internal - guts of float8in() + * float8in_internal_opt_error - guts of float8in() * * This is exposed for use by functions that want a reasonably * platform-independent way of inputting doubles. The behavior is @@ -353,10 +364,14 @@ float8in(PG_FUNCTION_ARGS) * * "num" could validly be declared "const char *", but that results in an * unreasonable amount of extra casting both here and in callers, so we don't. + * + * When "*have_error" flag is provided, it's set instead of throwing an + * error. This is helpful when caller need to handle errors by itself. */ double -float8in_internal(char *num, char **endptr_p, - const char *type_name, const char *orig_string) +float8in_internal_opt_error(char *num, char **endptr_p, + const char *type_name, const char *orig_string, + bool *have_error) { double val; char *endptr; @@ -370,10 +385,10 @@ float8in_internal(char *num, char **endptr_p, * strtod() on different platforms. */ if (*num == '\0') - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s: \"%s\"", - type_name, orig_string))); + RETURN_ERROR(ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type %s: \"%s\"", + type_name, orig_string)))); errno = 0; val = strtod(num, &endptr); @@ -446,17 +461,19 @@ float8in_internal(char *num, char **endptr_p, char *errnumber = pstrdup(num); errnumber[endptr - num] = '\0'; - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("\"%s\" is out of range for type double precision", - errnumber))); + RETURN_ERROR(ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("\"%s\" is out of range for " + "type double precision", + errnumber)))); } } else - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s: \"%s\"", - type_name, orig_string))); + RETURN_ERROR(ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type " + "%s: \"%s\"", + type_name, orig_string)))); } #ifdef HAVE_BUGGY_SOLARIS_STRTOD else @@ -479,15 +496,28 @@ float8in_internal(char *num, char **endptr_p, if (endptr_p) *endptr_p = endptr; else if (*endptr != '\0') - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for type %s: \"%s\"", - type_name, orig_string))); + RETURN_ERROR(ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for type " + "%s: \"%s\"", + type_name, orig_string)))); return val; } /* + * Interfact to float8in_internal_opt_error() without "have_error" argument. + */ +double +float8in_internal(char *num, char **endptr_p, + const char *type_name, const char *orig_string) +{ + return float8in_internal_opt_error(num, endptr_p, type_name, + orig_string, NULL); +} + + +/* * float8out - converts float8 number to a string * using a standard output format */ |