diff options
author | Andrew Dunstan <andrew@dunslane.net> | 2022-12-21 08:37:17 -0500 |
---|---|---|
committer | Andrew Dunstan <andrew@dunslane.net> | 2022-12-21 16:55:52 -0500 |
commit | 33dd895ef3316bd1896def6882e9075359d7e9af (patch) | |
tree | ebb480514853daab160668252c8baf4f0d9fbd4c /src/backend/utils/adt/float.c | |
parent | eb706fde8302c32267518663032905556db21f57 (diff) | |
download | postgresql-33dd895ef3316bd1896def6882e9075359d7e9af.tar.gz postgresql-33dd895ef3316bd1896def6882e9075359d7e9af.zip |
Introduce float4in_internal
This is the guts of float4in, callable as a routine to input floats,
which will be useful in an upcoming patch for allowing soft errors in
the seg module's input function.
A similar operation was performed some years ago for float8in in
commit 50861cd683e.
Reviewed by Tom Lane
Discussion: https://postgr.es/m/cee4e426-d014-c0b7-aa22-a659f2cd9130@dunslane.net
Diffstat (limited to 'src/backend/utils/adt/float.c')
-rw-r--r-- | src/backend/utils/adt/float.c | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index b02a19be24d..23e371c4130 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -163,17 +163,35 @@ Datum float4in(PG_FUNCTION_ARGS) { char *num = PG_GETARG_CSTRING(0); - Node *escontext = fcinfo->context; - char *orig_num; + + PG_RETURN_FLOAT4(float4in_internal(num, NULL, "real", num, + fcinfo->context)); +} + +/* + * float4in_internal - guts of float4in() + * + * This is exposed for use by functions that want a reasonably + * platform-independent way of inputting floats. The behavior is + * essentially like strtof + ereturn on error. + * + * Uses the same API as float8in_internal below, so most of its + * comments also apply here, except regarding use in geometric types. + */ +float4 +float4in_internal(char *num, char **endptr_p, + const char *type_name, const char *orig_string, + struct Node *escontext) +{ float val; char *endptr; /* * endptr points to the first character _after_ the sequence we recognized - * as a valid floating point number. orig_num points to the original input + * as a valid floating point number. orig_string points to the original + * input * string. */ - orig_num = num; /* skip leading whitespace */ while (*num != '\0' && isspace((unsigned char) *num)) @@ -184,10 +202,10 @@ float4in(PG_FUNCTION_ARGS) * strtod() on different platforms. */ if (*num == '\0') - ereturn(escontext, (Datum) 0, + ereturn(escontext, 0, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for type %s: \"%s\"", - "real", orig_num))); + type_name, orig_string))); errno = 0; val = strtof(num, &endptr); @@ -258,30 +276,39 @@ float4in(PG_FUNCTION_ARGS) (val >= HUGE_VALF || val <= -HUGE_VALF) #endif ) - ereturn(escontext, (Datum) 0, + { + /* see comments in float8in_internal for rationale */ + char *errnumber = pstrdup(num); + + errnumber[endptr - num] = '\0'; + + ereturn(escontext, 0, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("\"%s\" is out of range for type real", - orig_num))); + errnumber))); + } } else - ereturn(escontext, (Datum) 0, + ereturn(escontext, 0, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for type %s: \"%s\"", - "real", orig_num))); + type_name, orig_string))); } /* skip trailing whitespace */ while (*endptr != '\0' && isspace((unsigned char) *endptr)) endptr++; - /* if there is any junk left at the end of the string, bail out */ - if (*endptr != '\0') - ereturn(escontext, (Datum) 0, + /* report stopping point if wanted, else complain if not end of string */ + if (endptr_p) + *endptr_p = endptr; + else if (*endptr != '\0') + ereturn(escontext, 0, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg("invalid input syntax for type %s: \"%s\"", - "real", orig_num))); + type_name, orig_string))); - PG_RETURN_FLOAT4(val); + return val; } /* |