Bruce Momjian [EMAIL PROTECTED] writes:
I am seeing the following regression failure for current CVS. On my
OS, BSD/OS 4.3, it seems once you hit Infinity, you can't negate it.
Actually, I suspect the problem is that isinf() on your platform
returns 1 for any infinity (rather than -1 for negative infinity and 1
for positive infinity). Some existing code in float4out() and
float8out() assumed that a positive return from isinf() indicated a
positive infinity, which is not per C99.
Anyway, Tom and I worked through this issue, and a couple other
portability problems with the recent float changes, via private
email. The current patch is attached -- Tom hasn't yet gotten back to
me on whether this fixes the problem for him on HPUX, but it fixes my
OS X box.
-Neil
Index: src/backend/utils/adt/float.c
===
RCS file: /var/lib/cvs/pgsql-server/src/backend/utils/adt/float.c,v
retrieving revision 1.99
diff -c -r1.99 float.c
*** a/src/backend/utils/adt/float.c 12 Mar 2004 00:25:40 - 1.99
--- b/src/backend/utils/adt/float.c 14 Mar 2004 01:07:21 -
***
*** 109,117
--- 109,138
static void CheckFloat4Val(double val);
static void CheckFloat8Val(double val);
+ static int is_infinite(double val);
static int float4_cmp_internal(float4 a, float4 b);
static int float8_cmp_internal(float8 a, float8 b);
+ /*
+ * Returns -1 if 'val' represents negative infinity, 1 if 'val'
+ * represents (positive) infinity, and 0 otherwise. On same platforms,
+ * this is equivalent to the isinf() macro, but not everywhere: C99
+ * does not specify that isinf() needs to distinguish between positive
+ * and negative infinity.
+ */
+ static int
+ is_infinite(double val)
+ {
+ int inf = isinf(val);
+
+ if (inf == 0)
+ return 0;
+
+ if (val 0)
+ return 1;
+
+ return -1;
+ }
/*
* check to see if a float4 val is outside of the FLOAT4_MIN,
***
*** 154,160
/*
* float4in - converts num to float
* restricted syntax:
! * {sp} [+|-] {digit} [.{digit}] [exp]
* where sp is a space, digit is 0-9,
* exp is e or E followed by an integer.
*/
--- 175,182
/*
* float4in - converts num to float
* restricted syntax:
! *
! {sp} [+|-] {digit} [.{digit}] [exp]
* where sp is a space, digit is 0-9,
* exp is e or E followed by an integer.
*/
***
*** 162,209
float4in(PG_FUNCTION_ARGS)
{
char *num = PG_GETARG_CSTRING(0);
double val;
char *endptr;
errno = 0;
val = strtod(num, endptr);
if (errno == ERANGE)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
! errmsg(\%s\ is out of range for type real, num)));
if (num == endptr)
{
/*
! * We didn't find anything that looks like a float in the input
! *
! * In releases prior to 7.5, we accepted an empty string as
! * valid input (yielding a float8 of 0). In 7.5, we accept
! * empty strings, but emit a warning noting that the feature
! * is deprecated. In 7.6+, the warning should be replaced by
! * an error.
*/
! if (*num == '\0')
{
- ereport(WARNING,
- (errcode(ERRCODE_WARNING_DEPRECATED_FEATURE),
- errmsg(deprecated input syntax for type real: \\),
- errdetail(This input will be rejected in
- a future release of PostgreSQL.)));
- Assert(val == 0.0);
- }
- else if (strcasecmp(num, NaN) == 0)
val = NAN;
! else if (strcasecmp(num, Infinity) == 0)
val = HUGE_VAL;
! else if (strcasecmp(num, -Infinity) == 0)
val = -HUGE_VAL;
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg(invalid input syntax for type real: \%s\,
! num)));
}
/* skip trailing whitespace */
--- 184,261
float4in(PG_FUNCTION_ARGS)
{
char *num = PG_GETARG_CSTRING(0);
+ char *orig_num;
double 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 string.
+ */
+ orig_num = num;
+
+ /*
+ * Check for an empty-string input to begin with, to avoid
+ * the vagaries of strtod() on different platforms.
+ *
+ * In releases prior to 7.5, we accepted an empty string as valid
+ * input (yielding a float4 of 0). In 7.5, we accept empty
+ * strings, but emit a warning noting that the feature is
+ * deprecated. In 7.6+, the warning should be replaced by an
+ * error.
+ */
+ if (*num == '\0')
+ {
+ ereport(WARNING,
+ (errcode(ERRCODE_WARNING_DEPRECATED_FEATURE),
+ errmsg(deprecated input syntax for type real: \\),
+ errdetail(This input will be rejected in
+ a future release of PostgreSQL.)));
+ PG_RETURN_FLOAT4((float4) 0.0);
+ }
+
+ /* skip leading whitespace */
+ while (*num !=