summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Dunstan2022-12-21 13:37:17 +0000
committerAndrew Dunstan2022-12-21 21:55:52 +0000
commit33dd895ef3316bd1896def6882e9075359d7e9af (patch)
treeebb480514853daab160668252c8baf4f0d9fbd4c
parenteb706fde8302c32267518663032905556db21f57 (diff)
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/[email protected]
-rw-r--r--src/backend/utils/adt/float.c57
-rw-r--r--src/include/utils/float.h3
2 files changed, 45 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;
}
/*
diff --git a/src/include/utils/float.h b/src/include/utils/float.h
index f92860b4a46..60e897be755 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);