]> granicus.if.org Git - postgresql/commitdiff
Allow 'Infinity' and '-Infinity' as input to the float4 and float8
authorNeil Conway <neilc@samurai.com>
Fri, 12 Mar 2004 00:25:43 +0000 (00:25 +0000)
committerNeil Conway <neilc@samurai.com>
Fri, 12 Mar 2004 00:25:43 +0000 (00:25 +0000)
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.

doc/src/sgml/syntax.sgml
src/backend/utils/adt/float.c
src/include/pg_config_manual.h
src/test/regress/expected/float4.out
src/test/regress/expected/float8.out
src/test/regress/sql/float4.sql
src/test/regress/sql/float8.sql

index 5f82a7848512047544941bb0b79662cce4a77299..c6093b846377f5babb6e6d965e9d82ab054c8490 100644 (file)
@@ -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">
@@ -359,6 +359,23 @@ SELECT 'foo'      'bar';
 </literallayout>
     </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>
      <indexterm><primary>integer</primary></indexterm>
      <indexterm><primary>bigint</primary></indexterm>
index 2707c83fd62a43c487bdd7ba5a18943059d78437..aed643d862b858bf1d63c1255a73f3e8a186fbbd 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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
- * the FLOAT4_MIN, FLOAT4_MAX bounds.
+ * check to see if a float4 val is outside of the FLOAT4_MIN,
+ * FLOAT4_MAX bounds.
  *
- * raise an ereport warning if it is
-*/
+ * raise an ereport() error if it is
+ */
 static void
 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)
                ereport(ERROR,
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
@@ -137,27 +130,17 @@ CheckFloat4Val(double val)
                ereport(ERROR,
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                 errmsg("type \"real\" value out of range: underflow")));
-
-       return;
-#endif   /* UNSAFE_FLOATS */
 }
 
 /*
- * check to see if a float8 val is outside of
- * the FLOAT8_MIN, FLOAT8_MAX bounds.
+ * check to see if a float8 val is outside of the FLOAT8_MIN,
+ * FLOAT8_MAX bounds.
  *
- * raise an ereport error if it is
+ * raise an ereport() error if it is
  */
 static void
 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)
                ereport(ERROR,
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
@@ -166,7 +149,6 @@ CheckFloat8Val(double val)
                ereport(ERROR,
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                 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
                 * is deprecated. In 7.6+, the warning should be replaced by
                 * 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')
                {
@@ -217,6 +195,10 @@ float4in(PG_FUNCTION_ARGS)
                }
                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),
@@ -239,7 +221,8 @@ float4in(PG_FUNCTION_ARGS)
         * if we get here, we have a legal double, still need to check to see
         * if it's a legal float
         */
-       CheckFloat4Val(val);
+       if (!isinf(val))
+               CheckFloat4Val(val);
 
        PG_RETURN_FLOAT4((float4) val);
 }
@@ -364,7 +347,8 @@ float8in(PG_FUNCTION_ARGS)
                                 errmsg("invalid input syntax for type double precision: \"%s\"",
                                                num)));
 
-       CheckFloat8Val(val);
+       if (!isinf(val))
+               CheckFloat8Val(val);
 
        PG_RETURN_FLOAT8(val);
 }
index 8226c6d5cf72114d6f80e0106fd3eb7a83e428d0..6fcf38ec7b1cc44d5f18a65ecb1b6758cc96d5ec 100644 (file)
@@ -6,7 +6,7 @@
  * for developers.     If you edit any of these, be sure to do a *full*
  * 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 $
  *------------------------------------------------------------------------
  */
 
  */
 #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
  * MAX_RANDOM_VALUE.  Currently, all known implementations yield
index 124b7c378c69fdf78c0c0fd7ea601a4412bd6a3c..e4d460359fefd6150e7c8441f27b048d88dd4aee 100644 (file)
@@ -50,9 +50,39 @@ SELECT '   NAN  '::float4;
     NaN
 (1 row)
 
+SELECT 'infinity'::float4;
+  float4  
+----------
+ Infinity
+(1 row)
+
+SELECT '          -INFINiTY   '::float4;
+  float4   
+-----------
+ -Infinity
+(1 row)
+
 -- bad special inputs
 SELECT 'N A N'::float4;
 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.*;
  five |     f1      
 ------+-------------
index 89e2bbf90256977c90487c92669a29d9f476ee81..798a67c04fe4fc4ef2909aecd1799d3c9346931b 100644 (file)
@@ -50,9 +50,39 @@ SELECT '   NAN  '::float8;
     NaN
 (1 row)
 
+SELECT 'infinity'::float8;
+  float8  
+----------
+ Infinity
+(1 row)
+
+SELECT '          -INFINiTY   '::float8;
+  float8   
+-----------
+ -Infinity
+(1 row)
+
 -- bad special inputs
 SELECT 'N A N'::float8;
 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.*;
  five |          f1          
 ------+----------------------
index b7b64f2e50ea835730442634864beed4ed0064c3..a7147409ec98c6ab72fd885b82401b79311933a7 100644 (file)
@@ -29,8 +29,17 @@ INSERT INTO FLOAT4_TBL(f1) VALUES ('123            5');
 SELECT 'NaN'::float4;
 SELECT 'nan'::float4;
 SELECT '   NAN  '::float4;
+SELECT 'infinity'::float4;
+SELECT '          -INFINiTY   '::float4;
 -- bad special inputs
 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.*;
 
index 1e5e8ad4302278b66f7c0ae4c3332e79bee61c0d..593df68a326d9e3ba35486d2eac983d3b3fab837 100644 (file)
@@ -29,8 +29,16 @@ INSERT INTO FLOAT8_TBL(f1) VALUES ('123           5');
 SELECT 'NaN'::float8;
 SELECT 'nan'::float8;
 SELECT '   NAN  '::float8;
+SELECT 'infinity'::float8;
+SELECT '          -INFINiTY   '::float8;
 -- bad special inputs
 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.*;