The attached patch factors out the guts of float4in so that the new float4in_internal function is callable without going through the fmgr call sequence. This will make adjusting the seg module's input function to handle soft errors simpler. A similar operation was done for float8in some years ago in commit 50861cd683e. The new function has an identical argument structure to float8in_internal.
We could probably call these two internal functions directly in numeric_float4() and numeric_float8() - not sure if it's worth it rght now but we might end up wanting something like that for error-safe casts. cheers andrew -- Andrew Dunstan EDB: https://www.enterprisedb.com
From be571575e54c1b24617c54dbcd3daa3826d7e15a Mon Sep 17 00:00:00 2001 From: Andrew Dunstan <and...@dunslane.net> Date: Wed, 21 Dec 2022 08:37:17 -0500 Subject: [PATCH] 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. --- src/backend/utils/adt/float.c | 52 ++++++++++++++++++++++++----------- src/include/utils/float.h | 3 ++ 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index b02a19be24..5a9b7fbe5b 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,32 @@ float4in(PG_FUNCTION_ARGS) (val >= HUGE_VALF || val <= -HUGE_VALF) #endif ) - ereturn(escontext, (Datum) 0, + ereturn(escontext, 0, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("\"%s\" is out of range for type real", - orig_num))); + errmsg("\"%s\" is out of range for type %s", + orig_string, type_name))); } 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; } /* diff --git a/src/include/utils/float.h b/src/include/utils/float.h index f92860b4a4..60e897be75 100644 --- a/src/include/utils/float.h +++ b/src/include/utils/float.h @@ -44,6 +44,9 @@ extern int is_infinite(float8 val); extern float8 float8in_internal(char *num, char **endptr_p, const char *type_name, const char *orig_string, struct Node *escontext); +extern float4 float4in_internal(char *num, char **endptr_p, + const char *type_name, const char *orig_string, + struct Node *escontext); extern char *float8out_internal(float8 num); extern int float4_cmp_internal(float4 a, float4 b); extern int float8_cmp_internal(float8 a, float8 b); -- 2.34.1