Allow 'Infinity' and '-Infinity' as input to the float4 and float8
types. Update the regression tests and the documentation to reflect this. Remove the UNSAFE_FLOATS #ifdef. This is only half the story: we still unconditionally reject floating point operations that result in +/- infinity. See recent thread on -hackers for more information.
This commit is contained in:
parent
fe6e922136
commit
bfd6f52b0e
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$PostgreSQL: pgsql/doc/src/sgml/syntax.sgml,v 1.89 2003/11/29 19:51:37 pgsql Exp $
|
$PostgreSQL: pgsql/doc/src/sgml/syntax.sgml,v 1.90 2004/03/12 00:25:40 neilc Exp $
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<chapter id="sql-syntax">
|
<chapter id="sql-syntax">
|
||||||
@ -359,6 +359,23 @@ SELECT 'foo' 'bar';
|
|||||||
</literallayout>
|
</literallayout>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
In addition, there are several special constant values that are
|
||||||
|
accepted as numeric constants. The <type>float4</type> and
|
||||||
|
<type>float8</type> types allow the following special constants:
|
||||||
|
<literallayout>
|
||||||
|
Infinity
|
||||||
|
-Infinity
|
||||||
|
NaN
|
||||||
|
</literallayout>
|
||||||
|
These represent the IEEE 754 special values
|
||||||
|
<quote>infinity</quote>, <quote>negative infinity</quote>, and
|
||||||
|
<quote>not-a-number</quote>, respectively. The
|
||||||
|
<type>numeric</type> type only allows <literal>NaN</>, whereas
|
||||||
|
the integral types do not allow any of these constants. Note that
|
||||||
|
these constants are recognized in a case-insensitive manner.
|
||||||
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<indexterm><primary>integer</primary></indexterm>
|
<indexterm><primary>integer</primary></indexterm>
|
||||||
<indexterm><primary>bigint</primary></indexterm>
|
<indexterm><primary>bigint</primary></indexterm>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.98 2004/03/11 02:11:13 neilc Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.99 2004/03/12 00:25:40 neilc Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -114,21 +114,14 @@ static int float8_cmp_internal(float8 a, float8 b);
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* check to see if a float4 val is outside of
|
* check to see if a float4 val is outside of the FLOAT4_MIN,
|
||||||
* the FLOAT4_MIN, FLOAT4_MAX bounds.
|
* FLOAT4_MAX bounds.
|
||||||
*
|
*
|
||||||
* raise an ereport warning if it is
|
* raise an ereport() error if it is
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
CheckFloat4Val(double val)
|
CheckFloat4Val(double val)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* defining unsafe floats's will make float4 and float8 ops faster at
|
|
||||||
* the cost of safety, of course!
|
|
||||||
*/
|
|
||||||
#ifdef UNSAFE_FLOATS
|
|
||||||
return;
|
|
||||||
#else
|
|
||||||
if (fabs(val) > FLOAT4_MAX)
|
if (fabs(val) > FLOAT4_MAX)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||||
@ -137,27 +130,17 @@ CheckFloat4Val(double val)
|
|||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||||
errmsg("type \"real\" value out of range: underflow")));
|
errmsg("type \"real\" value out of range: underflow")));
|
||||||
|
|
||||||
return;
|
|
||||||
#endif /* UNSAFE_FLOATS */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* check to see if a float8 val is outside of
|
* check to see if a float8 val is outside of the FLOAT8_MIN,
|
||||||
* the FLOAT8_MIN, FLOAT8_MAX bounds.
|
* FLOAT8_MAX bounds.
|
||||||
*
|
*
|
||||||
* raise an ereport error if it is
|
* raise an ereport() error if it is
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
CheckFloat8Val(double val)
|
CheckFloat8Val(double val)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* defining unsafe floats's will make float4 and float8 ops faster at
|
|
||||||
* the cost of safety, of course!
|
|
||||||
*/
|
|
||||||
#ifdef UNSAFE_FLOATS
|
|
||||||
return;
|
|
||||||
#else
|
|
||||||
if (fabs(val) > FLOAT8_MAX)
|
if (fabs(val) > FLOAT8_MAX)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||||
@ -166,7 +149,6 @@ CheckFloat8Val(double val)
|
|||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||||
errmsg("type \"double precision\" value out of range: underflow")));
|
errmsg("type \"double precision\" value out of range: underflow")));
|
||||||
#endif /* UNSAFE_FLOATS */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -201,10 +183,6 @@ float4in(PG_FUNCTION_ARGS)
|
|||||||
* empty strings, but emit a warning noting that the feature
|
* empty strings, but emit a warning noting that the feature
|
||||||
* is deprecated. In 7.6+, the warning should be replaced by
|
* is deprecated. In 7.6+, the warning should be replaced by
|
||||||
* an error.
|
* an error.
|
||||||
*
|
|
||||||
* XXX we should accept "Infinity" and "-Infinity" too, but
|
|
||||||
* what are the correct values to assign? HUGE_VAL will
|
|
||||||
* provoke an error from CheckFloat4Val.
|
|
||||||
*/
|
*/
|
||||||
if (*num == '\0')
|
if (*num == '\0')
|
||||||
{
|
{
|
||||||
@ -217,6 +195,10 @@ float4in(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
else if (strcasecmp(num, "NaN") == 0)
|
else if (strcasecmp(num, "NaN") == 0)
|
||||||
val = NAN;
|
val = NAN;
|
||||||
|
else if (strcasecmp(num, "Infinity") == 0)
|
||||||
|
val = HUGE_VAL;
|
||||||
|
else if (strcasecmp(num, "-Infinity") == 0)
|
||||||
|
val = -HUGE_VAL;
|
||||||
else
|
else
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
@ -239,7 +221,8 @@ float4in(PG_FUNCTION_ARGS)
|
|||||||
* if we get here, we have a legal double, still need to check to see
|
* if we get here, we have a legal double, still need to check to see
|
||||||
* if it's a legal float
|
* if it's a legal float
|
||||||
*/
|
*/
|
||||||
CheckFloat4Val(val);
|
if (!isinf(val))
|
||||||
|
CheckFloat4Val(val);
|
||||||
|
|
||||||
PG_RETURN_FLOAT4((float4) val);
|
PG_RETURN_FLOAT4((float4) val);
|
||||||
}
|
}
|
||||||
@ -364,7 +347,8 @@ float8in(PG_FUNCTION_ARGS)
|
|||||||
errmsg("invalid input syntax for type double precision: \"%s\"",
|
errmsg("invalid input syntax for type double precision: \"%s\"",
|
||||||
num)));
|
num)));
|
||||||
|
|
||||||
CheckFloat8Val(val);
|
if (!isinf(val))
|
||||||
|
CheckFloat8Val(val);
|
||||||
|
|
||||||
PG_RETURN_FLOAT8(val);
|
PG_RETURN_FLOAT8(val);
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* for developers. If you edit any of these, be sure to do a *full*
|
* for developers. If you edit any of these, be sure to do a *full*
|
||||||
* rebuild (and an initdb if noted).
|
* rebuild (and an initdb if noted).
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/pg_config_manual.h,v 1.10 2004/02/11 22:55:26 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/pg_config_manual.h,v 1.11 2004/03/12 00:25:40 neilc Exp $
|
||||||
*------------------------------------------------------------------------
|
*------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -175,12 +175,6 @@
|
|||||||
*/
|
*/
|
||||||
#define DEFAULT_PGSOCKET_DIR "/tmp"
|
#define DEFAULT_PGSOCKET_DIR "/tmp"
|
||||||
|
|
||||||
/*
|
|
||||||
* Defining this will make float4 and float8 operations faster by
|
|
||||||
* suppressing overflow/underflow checks.
|
|
||||||
*/
|
|
||||||
/* #define UNSAFE_FLOATS */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The random() function is expected to yield values between 0 and
|
* The random() function is expected to yield values between 0 and
|
||||||
* MAX_RANDOM_VALUE. Currently, all known implementations yield
|
* MAX_RANDOM_VALUE. Currently, all known implementations yield
|
||||||
|
@ -50,9 +50,39 @@ SELECT ' NAN '::float4;
|
|||||||
NaN
|
NaN
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 'infinity'::float4;
|
||||||
|
float4
|
||||||
|
----------
|
||||||
|
Infinity
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT ' -INFINiTY '::float4;
|
||||||
|
float4
|
||||||
|
-----------
|
||||||
|
-Infinity
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- bad special inputs
|
-- bad special inputs
|
||||||
SELECT 'N A N'::float4;
|
SELECT 'N A N'::float4;
|
||||||
ERROR: invalid input syntax for type real: "N A N"
|
ERROR: invalid input syntax for type real: "N A N"
|
||||||
|
SELECT 'NaN x'::float4;
|
||||||
|
ERROR: invalid input syntax for type real: "NaN x"
|
||||||
|
SELECT ' INFINITY x'::float4;
|
||||||
|
ERROR: invalid input syntax for type real: " INFINITY x"
|
||||||
|
SELECT 'Infinity'::float4 + 100.0;
|
||||||
|
ERROR: type "double precision" value out of range: overflow
|
||||||
|
SELECT 'Infinity'::float4 / 'Infinity'::float4;
|
||||||
|
?column?
|
||||||
|
----------
|
||||||
|
NaN
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 'nan'::float4 / 'nan'::float4;
|
||||||
|
?column?
|
||||||
|
----------
|
||||||
|
NaN
|
||||||
|
(1 row)
|
||||||
|
|
||||||
SELECT '' AS five, FLOAT4_TBL.*;
|
SELECT '' AS five, FLOAT4_TBL.*;
|
||||||
five | f1
|
five | f1
|
||||||
------+-------------
|
------+-------------
|
||||||
|
@ -50,9 +50,39 @@ SELECT ' NAN '::float8;
|
|||||||
NaN
|
NaN
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 'infinity'::float8;
|
||||||
|
float8
|
||||||
|
----------
|
||||||
|
Infinity
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT ' -INFINiTY '::float8;
|
||||||
|
float8
|
||||||
|
-----------
|
||||||
|
-Infinity
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- bad special inputs
|
-- bad special inputs
|
||||||
SELECT 'N A N'::float8;
|
SELECT 'N A N'::float8;
|
||||||
ERROR: invalid input syntax for type double precision: "N A N"
|
ERROR: invalid input syntax for type double precision: "N A N"
|
||||||
|
SELECT 'NaN x'::float8;
|
||||||
|
ERROR: invalid input syntax for type double precision: "NaN x"
|
||||||
|
SELECT ' INFINITY x'::float8;
|
||||||
|
ERROR: invalid input syntax for type double precision: " INFINITY x"
|
||||||
|
SELECT 'Infinity'::float8 + 100.0;
|
||||||
|
ERROR: type "double precision" value out of range: overflow
|
||||||
|
SELECT 'Infinity'::float8 / 'Infinity'::float8;
|
||||||
|
?column?
|
||||||
|
----------
|
||||||
|
NaN
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 'nan'::float8 / 'nan'::float8;
|
||||||
|
?column?
|
||||||
|
----------
|
||||||
|
NaN
|
||||||
|
(1 row)
|
||||||
|
|
||||||
SELECT '' AS five, FLOAT8_TBL.*;
|
SELECT '' AS five, FLOAT8_TBL.*;
|
||||||
five | f1
|
five | f1
|
||||||
------+----------------------
|
------+----------------------
|
||||||
|
@ -29,8 +29,17 @@ INSERT INTO FLOAT4_TBL(f1) VALUES ('123 5');
|
|||||||
SELECT 'NaN'::float4;
|
SELECT 'NaN'::float4;
|
||||||
SELECT 'nan'::float4;
|
SELECT 'nan'::float4;
|
||||||
SELECT ' NAN '::float4;
|
SELECT ' NAN '::float4;
|
||||||
|
SELECT 'infinity'::float4;
|
||||||
|
SELECT ' -INFINiTY '::float4;
|
||||||
-- bad special inputs
|
-- bad special inputs
|
||||||
SELECT 'N A N'::float4;
|
SELECT 'N A N'::float4;
|
||||||
|
SELECT 'NaN x'::float4;
|
||||||
|
SELECT ' INFINITY x'::float4;
|
||||||
|
|
||||||
|
SELECT 'Infinity'::float4 + 100.0;
|
||||||
|
SELECT 'Infinity'::float4 / 'Infinity'::float4;
|
||||||
|
SELECT 'nan'::float4 / 'nan'::float4;
|
||||||
|
|
||||||
|
|
||||||
SELECT '' AS five, FLOAT4_TBL.*;
|
SELECT '' AS five, FLOAT4_TBL.*;
|
||||||
|
|
||||||
|
@ -29,8 +29,16 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('123 5');
|
|||||||
SELECT 'NaN'::float8;
|
SELECT 'NaN'::float8;
|
||||||
SELECT 'nan'::float8;
|
SELECT 'nan'::float8;
|
||||||
SELECT ' NAN '::float8;
|
SELECT ' NAN '::float8;
|
||||||
|
SELECT 'infinity'::float8;
|
||||||
|
SELECT ' -INFINiTY '::float8;
|
||||||
-- bad special inputs
|
-- bad special inputs
|
||||||
SELECT 'N A N'::float8;
|
SELECT 'N A N'::float8;
|
||||||
|
SELECT 'NaN x'::float8;
|
||||||
|
SELECT ' INFINITY x'::float8;
|
||||||
|
|
||||||
|
SELECT 'Infinity'::float8 + 100.0;
|
||||||
|
SELECT 'Infinity'::float8 / 'Infinity'::float8;
|
||||||
|
SELECT 'nan'::float8 / 'nan'::float8;
|
||||||
|
|
||||||
SELECT '' AS five, FLOAT8_TBL.*;
|
SELECT '' AS five, FLOAT8_TBL.*;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user