@@ -163,17 +163,35 @@ Datum
163
163
float4in (PG_FUNCTION_ARGS )
164
164
{
165
165
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
+ {
168
186
float val ;
169
187
char * endptr ;
170
188
171
189
/*
172
190
* 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
174
193
* string.
175
194
*/
176
- orig_num = num ;
177
195
178
196
/* skip leading whitespace */
179
197
while (* num != '\0' && isspace ((unsigned char ) * num ))
@@ -184,10 +202,10 @@ float4in(PG_FUNCTION_ARGS)
184
202
* strtod() on different platforms.
185
203
*/
186
204
if (* num == '\0' )
187
- ereturn (escontext , ( Datum ) 0 ,
205
+ ereturn (escontext , 0 ,
188
206
(errcode (ERRCODE_INVALID_TEXT_REPRESENTATION ),
189
207
errmsg ("invalid input syntax for type %s: \"%s\"" ,
190
- "real" , orig_num )));
208
+ type_name , orig_string )));
191
209
192
210
errno = 0 ;
193
211
val = strtof (num , & endptr );
@@ -258,30 +276,39 @@ float4in(PG_FUNCTION_ARGS)
258
276
(val >= HUGE_VALF || val <= - HUGE_VALF )
259
277
#endif
260
278
)
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 ,
262
286
(errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
263
287
errmsg ("\"%s\" is out of range for type real" ,
264
- orig_num )));
288
+ errnumber )));
289
+ }
265
290
}
266
291
else
267
- ereturn (escontext , ( Datum ) 0 ,
292
+ ereturn (escontext , 0 ,
268
293
(errcode (ERRCODE_INVALID_TEXT_REPRESENTATION ),
269
294
errmsg ("invalid input syntax for type %s: \"%s\"" ,
270
- "real" , orig_num )));
295
+ type_name , orig_string )));
271
296
}
272
297
273
298
/* skip trailing whitespace */
274
299
while (* endptr != '\0' && isspace ((unsigned char ) * endptr ))
275
300
endptr ++ ;
276
301
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 ,
280
307
(errcode (ERRCODE_INVALID_TEXT_REPRESENTATION ),
281
308
errmsg ("invalid input syntax for type %s: \"%s\"" ,
282
- "real" , orig_num )));
309
+ type_name , orig_string )));
283
310
284
- PG_RETURN_FLOAT4 ( val ) ;
311
+ return val ;
285
312
}
286
313
287
314
/*
0 commit comments