Skip to content

Commit 33dd895

Browse files
committed
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 50861cd. Reviewed by Tom Lane Discussion: https://postgr.es/m/cee4e426-d014-c0b7-aa22-a659f2cd9130@dunslane.net
1 parent eb706fd commit 33dd895

File tree

2 files changed

+45
-15
lines changed

2 files changed

+45
-15
lines changed

src/backend/utils/adt/float.c

+42-15
Original file line numberDiff line numberDiff line change
@@ -163,17 +163,35 @@ Datum
163163
float4in(PG_FUNCTION_ARGS)
164164
{
165165
char *num = PG_GETARG_CSTRING(0);
166-
Node *escontext = fcinfo->context;
167-
char *orig_num;
166+
167+
PG_RETURN_FLOAT4(float4in_internal(num, NULL, "real", num,
168+
fcinfo->context));
169+
}
170+
171+
/*
172+
* float4in_internal - guts of float4in()
173+
*
174+
* This is exposed for use by functions that want a reasonably
175+
* platform-independent way of inputting floats. The behavior is
176+
* essentially like strtof + ereturn on error.
177+
*
178+
* Uses the same API as float8in_internal below, so most of its
179+
* comments also apply here, except regarding use in geometric types.
180+
*/
181+
float4
182+
float4in_internal(char *num, char **endptr_p,
183+
const char *type_name, const char *orig_string,
184+
struct Node *escontext)
185+
{
168186
float val;
169187
char *endptr;
170188

171189
/*
172190
* endptr points to the first character _after_ the sequence we recognized
173-
* as a valid floating point number. orig_num points to the original input
191+
* as a valid floating point number. orig_string points to the original
192+
* input
174193
* string.
175194
*/
176-
orig_num = num;
177195

178196
/* skip leading whitespace */
179197
while (*num != '\0' && isspace((unsigned char) *num))
@@ -184,10 +202,10 @@ float4in(PG_FUNCTION_ARGS)
184202
* strtod() on different platforms.
185203
*/
186204
if (*num == '\0')
187-
ereturn(escontext, (Datum) 0,
205+
ereturn(escontext, 0,
188206
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
189207
errmsg("invalid input syntax for type %s: \"%s\"",
190-
"real", orig_num)));
208+
type_name, orig_string)));
191209

192210
errno = 0;
193211
val = strtof(num, &endptr);
@@ -258,30 +276,39 @@ float4in(PG_FUNCTION_ARGS)
258276
(val >= HUGE_VALF || val <= -HUGE_VALF)
259277
#endif
260278
)
261-
ereturn(escontext, (Datum) 0,
279+
{
280+
/* see comments in float8in_internal for rationale */
281+
char *errnumber = pstrdup(num);
282+
283+
errnumber[endptr - num] = '\0';
284+
285+
ereturn(escontext, 0,
262286
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
263287
errmsg("\"%s\" is out of range for type real",
264-
orig_num)));
288+
errnumber)));
289+
}
265290
}
266291
else
267-
ereturn(escontext, (Datum) 0,
292+
ereturn(escontext, 0,
268293
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
269294
errmsg("invalid input syntax for type %s: \"%s\"",
270-
"real", orig_num)));
295+
type_name, orig_string)));
271296
}
272297

273298
/* skip trailing whitespace */
274299
while (*endptr != '\0' && isspace((unsigned char) *endptr))
275300
endptr++;
276301

277-
/* if there is any junk left at the end of the string, bail out */
278-
if (*endptr != '\0')
279-
ereturn(escontext, (Datum) 0,
302+
/* report stopping point if wanted, else complain if not end of string */
303+
if (endptr_p)
304+
*endptr_p = endptr;
305+
else if (*endptr != '\0')
306+
ereturn(escontext, 0,
280307
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
281308
errmsg("invalid input syntax for type %s: \"%s\"",
282-
"real", orig_num)));
309+
type_name, orig_string)));
283310

284-
PG_RETURN_FLOAT4(val);
311+
return val;
285312
}
286313

287314
/*

src/include/utils/float.h

+3
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ extern int is_infinite(float8 val);
4444
extern float8 float8in_internal(char *num, char **endptr_p,
4545
const char *type_name, const char *orig_string,
4646
struct Node *escontext);
47+
extern float4 float4in_internal(char *num, char **endptr_p,
48+
const char *type_name, const char *orig_string,
49+
struct Node *escontext);
4750
extern char *float8out_internal(float8 num);
4851
extern int float4_cmp_internal(float4 a, float4 b);
4952
extern int float8_cmp_internal(float8 a, float8 b);

0 commit comments

Comments
 (0)