]> granicus.if.org Git - postgresql/commitdiff
Fixed NaN/Infinity problems in ECPG for float/double/numeric/decimal by making it...
authorMichael Meskes <meskes@postgresql.org>
Tue, 2 Feb 2010 16:09:12 +0000 (16:09 +0000)
committerMichael Meskes <meskes@postgresql.org>
Tue, 2 Feb 2010 16:09:12 +0000 (16:09 +0000)
Patch done by Zoltán Böszörményi.

14 files changed:
src/interfaces/ecpg/ecpglib/data.c
src/interfaces/ecpg/ecpglib/execute.c
src/interfaces/ecpg/ecpglib/misc.c
src/interfaces/ecpg/include/pgtypes_numeric.h
src/interfaces/ecpg/pgtypeslib/numeric.c
src/interfaces/ecpg/test/ecpg_schedule
src/interfaces/ecpg/test/ecpg_schedule_tcp
src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.c [new file with mode: 0644]
src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stderr [new file with mode: 0644]
src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stdout [new file with mode: 0644]
src/interfaces/ecpg/test/expected/preproc-outofscope.c
src/interfaces/ecpg/test/expected/sql-sqlda.c
src/interfaces/ecpg/test/pgtypeslib/Makefile
src/interfaces/ecpg/test/pgtypeslib/nan_test.pgc [new file with mode: 0644]

index f30fe8ba1e0bb8d808a9e6454fb167d4fb55997c..d816ff4b3b22d220c0ca71028a7e25a8c837410d 100644 (file)
@@ -1,10 +1,11 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.47 2009/12/31 19:41:36 tgl Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.48 2010/02/02 16:09:11 meskes Exp $ */
 
 #define POSTGRES_ECPG_INTERNAL
 #include "postgres_fe.h"
 
 #include <stdlib.h>
 #include <string.h>
+#include <math.h>
 
 #include "ecpgtype.h"
 #include "ecpglib.h"
@@ -38,6 +39,58 @@ garbage_left(enum ARRAY_TYPE isarray, char *scan_length, enum COMPAT_MODE compat
        return false;
 }
 
+/* stolen code from src/backend/utils/adt/float.c */
+#if defined(WIN32) && !defined(NAN)
+static const uint32 nan[2] = {0xffffffff, 0x7fffffff};
+
+#define NAN (*(const double *) nan)
+#endif
+
+static double
+get_float8_infinity(void)
+{
+#ifdef INFINITY
+       return (double) INFINITY;
+#else
+       return (double) (HUGE_VAL * HUGE_VAL);
+#endif
+}
+
+static double
+get_float8_nan(void)
+{
+#ifdef NAN
+       return (double) NAN;  
+#else
+       return (double) (0.0 / 0.0);
+#endif
+}
+
+static bool
+check_special_value(char *ptr, double *retval, char **endptr)
+{
+       if (!pg_strncasecmp(ptr, "NaN", 3))
+       {
+               *retval = get_float8_nan();
+               *endptr = ptr + 3;
+               return true;
+       }
+       else if (!pg_strncasecmp(ptr, "Infinity", 8))
+       {
+               *retval = get_float8_infinity();
+               *endptr = ptr + 8;
+               return true;
+       }
+       else if (!pg_strncasecmp(ptr, "-Infinity", 9))
+       {
+               *retval = -get_float8_infinity();
+               *endptr = ptr + 9;
+               return true;
+       }
+
+       return false;
+}
+
 bool
 ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
                          enum ECPGttype type, enum ECPGttype ind_type,
@@ -300,8 +353,9 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
                                case ECPGt_float:
                                case ECPGt_double:
                                        if (isarray && *pval == '"')
-                                               dres = strtod(pval + 1, &scan_length);
-                                       else
+                                               pval++;
+
+                                       if (!check_special_value(pval, &dres, &scan_length))
                                                dres = strtod(pval, &scan_length);
 
                                        if (isarray && *scan_length == '"')
index 71b32a8128c8ae7dbe8be56db8d7cab6d29fbb68..48b38dab1e4b46d1fc6902731381131d1ac89767 100644 (file)
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.90 2010/01/29 15:57:01 meskes Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.91 2010/02/02 16:09:11 meskes Exp $ */
 
 /*
  * The aim is to get a simpler inteface to the database routines.
@@ -17,6 +17,7 @@
 #include "postgres_fe.h"
 
 #include <locale.h>
+#include <math.h>
 
 #include "pg_type.h"
 
@@ -463,6 +464,38 @@ ecpg_store_result(const PGresult *results, int act_field,
        return status;
 }
 
+static void
+sprintf_double_value(char *ptr, double value, const char *delim)
+{
+       if (isinf(value))
+       {
+               if (value < 0)
+                       sprintf(ptr, "%s%s", "-Infinity", delim);
+               else
+                       sprintf(ptr, "%s%s", "Infinity", delim);
+       }
+       else if (isnan(value))
+               sprintf(ptr, "%s%s", "NaN", delim);
+       else
+               sprintf(ptr, "%.14g%s", value, delim);
+}
+
+static void
+sprintf_float_value(char *ptr, float value, const char *delim)
+{
+       if (isinf(value))
+       {
+               if (value < 0)
+                       sprintf(ptr, "%s%s", "-Infinity", delim);
+               else
+                       sprintf(ptr, "%s%s", "Infinity", delim);
+       }
+       else if (isnan(value))
+               sprintf(ptr, "%s%s", "NaN", delim);
+       else
+               sprintf(ptr, "%.14g%s", value, delim);
+}
+
 bool
 ecpg_store_input(const int lineno, const bool force_indicator, const struct variable * var,
                                 char **tobeinserted_p, bool quote)
@@ -693,12 +726,12 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
                                        strcpy(mallocedval, "array [");
 
                                        for (element = 0; element < asize; element++)
-                                               sprintf(mallocedval + strlen(mallocedval), "%.14g,", ((float *) var->value)[element]);
+                                               sprintf_float_value(mallocedval + strlen(mallocedval), ((float *) var->value)[element], ",");
 
                                        strcpy(mallocedval + strlen(mallocedval) - 1, "]");
                                }
                                else
-                                       sprintf(mallocedval, "%.14g", *((float *) var->value));
+                                       sprintf_float_value(mallocedval, *((float *) var->value), "");
 
                                *tobeinserted_p = mallocedval;
                                break;
@@ -712,12 +745,12 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
                                        strcpy(mallocedval, "array [");
 
                                        for (element = 0; element < asize; element++)
-                                               sprintf(mallocedval + strlen(mallocedval), "%.14g,", ((double *) var->value)[element]);
+                                               sprintf_double_value(mallocedval + strlen(mallocedval), ((double *) var->value)[element], ",");
 
                                        strcpy(mallocedval + strlen(mallocedval) - 1, "]");
                                }
                                else
-                                       sprintf(mallocedval, "%.14g", *((double *) var->value));
+                                       sprintf_double_value(mallocedval, *((double *) var->value), "");
 
                                *tobeinserted_p = mallocedval;
                                break;
index d5f7107440a9a331f2c478ef7d7fce20afd8a738..11d69ac04c44d895625ae5de5f15d703db85da42 100644 (file)
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.54 2010/01/26 09:07:31 meskes Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.55 2010/02/02 16:09:11 meskes Exp $ */
 
 #define POSTGRES_ECPG_INTERNAL
 #include "postgres_fe.h"
@@ -344,11 +344,11 @@ ECPGset_noind_null(enum ECPGttype type, void *ptr)
                        break;
                case ECPGt_decimal:
                        memset((char *) ptr, 0, sizeof(decimal));
-                       ((decimal *) ptr)->sign = NUMERIC_NAN;
+                       ((decimal *) ptr)->sign = NUMERIC_NULL;
                        break;
                case ECPGt_numeric:
                        memset((char *) ptr, 0, sizeof(numeric));
-                       ((numeric *) ptr)->sign = NUMERIC_NAN;
+                       ((numeric *) ptr)->sign = NUMERIC_NULL;
                        break;
                case ECPGt_interval:
                        memset((char *) ptr, 0xff, sizeof(interval));
@@ -416,11 +416,11 @@ ECPGis_noind_null(enum ECPGttype type, void *ptr)
                                return true;
                        break;
                case ECPGt_decimal:
-                       if (((decimal *) ptr)->sign == NUMERIC_NAN)
+                       if (((decimal *) ptr)->sign == NUMERIC_NULL)
                                return true;
                        break;
                case ECPGt_numeric:
-                       if (((numeric *) ptr)->sign == NUMERIC_NAN)
+                       if (((numeric *) ptr)->sign == NUMERIC_NULL)
                                return true;
                        break;
                case ECPGt_interval:
index 207b5f37ba49503e5f60d8b5ee011c12541d0283..1b9e4c35e436c62265e0c288d85baeba07d9a704 100644 (file)
@@ -4,6 +4,7 @@
 #define NUMERIC_POS                                            0x0000
 #define NUMERIC_NEG                                            0x4000
 #define NUMERIC_NAN                                            0xC000
+#define NUMERIC_NULL                                           0xF000
 #define NUMERIC_MAX_PRECISION                  1000
 #define NUMERIC_MAX_DISPLAY_SCALE              NUMERIC_MAX_PRECISION
 #define NUMERIC_MIN_DISPLAY_SCALE              0
index 1feac9b76e398d3334c9f679b3fc19281ecc4370..3d123489e60f7263f8579c73cf320d5d92469681 100644 (file)
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/numeric.c,v 1.34 2009/09/03 09:59:20 meskes Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/numeric.c,v 1.35 2010/02/02 16:09:12 meskes Exp $ */
 
 #include "postgres_fe.h"
 #include <ctype.h>
@@ -173,6 +173,25 @@ set_var_from_str(char *str, char **ptr, numeric *dest)
                (*ptr)++;
        }
 
+       if (pg_strncasecmp(*ptr, "NaN", 3) == 0)
+       {
+               *ptr += 3;
+               dest->sign = NUMERIC_NAN;
+
+               /* Should be nothing left but spaces */
+               while (*(*ptr))
+               {
+                       if (!isspace((unsigned char) *(*ptr)))
+                       {
+                               errno = PGTYPES_NUM_BAD_NUMERIC;
+                               return -1;
+                       }
+                       (*ptr)++;
+               }
+
+               return 0;
+       }
+
        if (alloc_var(dest, strlen((*ptr))) < 0)
                return -1;
        dest->weight = -1;
@@ -296,6 +315,15 @@ get_str_from_var(numeric *var, int dscale)
        int                     i;
        int                     d;
 
+       if (var->sign == NUMERIC_NAN)
+       {
+               str = (char *) pgtypes_alloc(4);
+               if (str == NULL)
+                       return NULL;
+               sprintf(str, "NaN");
+               return str;
+       }
+
        /*
         * Check if we must round up before printing the value and do so.
         */
index e71452484d91eb8196228659bbf7c6a5ab8eba1b..c07ea9359c2216a312a0f9f94deadc171f43f710 100644 (file)
@@ -15,6 +15,7 @@ test: pgtypeslib/dt_test
 test: pgtypeslib/dt_test2
 test: pgtypeslib/num_test
 test: pgtypeslib/num_test2
+test: pgtypeslib/nan_test
 test: preproc/array_of_struct
 test: preproc/autoprep
 test: preproc/comment
index 64125e65eaeef8f836804a39e1ca1c1417cdf693..5214d251ac0f5e58e0d3cc8f08ac755f5650aaf0 100644 (file)
@@ -15,6 +15,7 @@ test: pgtypeslib/dt_test
 test: pgtypeslib/dt_test2
 test: pgtypeslib/num_test
 test: pgtypeslib/num_test2
+test: pgtypeslib/nan_test
 test: preproc/array_of_struct
 test: preproc/autoprep
 test: preproc/comment
diff --git a/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.c b/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.c
new file mode 100644 (file)
index 0000000..f42fea3
--- /dev/null
@@ -0,0 +1,263 @@
+/* Processed by ecpg (regression mode) */
+/* These include files are added by the preprocessor */
+#include <ecpglib.h>
+#include <ecpgerrno.h>
+#include <sqlca.h>
+/* End of automatic include section */
+#define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y))
+
+#line 1 "nan_test.pgc"
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <pgtypes_numeric.h>
+#include <decimal.h>
+
+
+#line 1 "regression.h"
+
+
+
+
+
+
+#line 7 "nan_test.pgc"
+
+
+int
+main(void)
+{
+       /* exec sql begin declare section */
+               
+               
+               
+               
+       
+#line 13 "nan_test.pgc"
+ int id ;
+#line 14 "nan_test.pgc"
+ double d ;
+#line 15 "nan_test.pgc"
+ numeric * num ;
+#line 16 "nan_test.pgc"
+ char val [ 16 ] ;
+/* exec sql end declare section */
+#line 17 "nan_test.pgc"
+
+
+       ECPGdebug(1, stderr);
+       /* exec sql whenever sqlerror  do sqlprint ( ) ; */
+#line 20 "nan_test.pgc"
+
+
+       { ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , NULL, 0); 
+#line 22 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 22 "nan_test.pgc"
+
+
+       { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table nantest1 ( id int4 , d float8 )", ECPGt_EOIT, ECPGt_EORT);
+#line 24 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 24 "nan_test.pgc"
+
+       { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into nantest1 ( id , d ) values ( 1 , 'nan' :: float8 ) , ( 2 , 'inf' :: float8 ) , ( 3 , '-inf' :: float8 )", ECPGt_EOIT, ECPGt_EORT);
+#line 25 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 25 "nan_test.pgc"
+
+
+       /* declare cur cursor for select id , d , d from nantest1 */
+#line 27 "nan_test.pgc"
+
+       { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare cur cursor for select id , d , d from nantest1", ECPGt_EOIT, ECPGt_EORT);
+#line 28 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 28 "nan_test.pgc"
+
+       while (1)
+       {
+               { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch from cur", ECPGt_EOIT, 
+       ECPGt_int,&(id),(long)1,(long)1,sizeof(int), 
+       ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+       ECPGt_double,&(d),(long)1,(long)1,sizeof(double), 
+       ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+       ECPGt_char,(val),(long)16,(long)1,(16)*sizeof(char), 
+       ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+#line 31 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 31 "nan_test.pgc"
+
+               if (sqlca.sqlcode)
+                       break;
+               if (isinf(d))
+                       printf("%d %sInf '%s'\n", id, (d < 0 ? "-" : "+"), val);
+               if (isnan(d))
+                       printf("%d  NaN '%s'\n", id, val);
+
+               { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into nantest1 ( id , d ) values ( $1  + 3 , $2  )", 
+       ECPGt_int,&(id),(long)1,(long)1,sizeof(int), 
+       ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+       ECPGt_double,&(d),(long)1,(long)1,sizeof(double), 
+       ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+#line 39 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 39 "nan_test.pgc"
+
+               { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into nantest1 ( id , d ) values ( $1  + 6 , $2  )", 
+       ECPGt_int,&(id),(long)1,(long)1,sizeof(int), 
+       ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+       ECPGt_char,(val),(long)16,(long)1,(16)*sizeof(char), 
+       ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+#line 40 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 40 "nan_test.pgc"
+
+       }
+       { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close cur", ECPGt_EOIT, ECPGt_EORT);
+#line 42 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 42 "nan_test.pgc"
+
+
+       { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare cur cursor for select id , d , d from nantest1", ECPGt_EOIT, ECPGt_EORT);
+#line 44 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 44 "nan_test.pgc"
+
+       while (1)
+       {
+               { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch from cur", ECPGt_EOIT, 
+       ECPGt_int,&(id),(long)1,(long)1,sizeof(int), 
+       ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+       ECPGt_double,&(d),(long)1,(long)1,sizeof(double), 
+       ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+       ECPGt_char,(val),(long)16,(long)1,(16)*sizeof(char), 
+       ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+#line 47 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 47 "nan_test.pgc"
+
+               if (sqlca.sqlcode)
+                       break;
+               if (isinf(d))
+                       printf("%d %sInf '%s'\n", id, (d < 0 ? "-" : "+"), val);
+               if (isnan(d))
+                       printf("%d  NaN '%s'\n", id, val);
+       }
+       { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close cur", ECPGt_EOIT, ECPGt_EORT);
+#line 55 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 55 "nan_test.pgc"
+
+
+       num = PGTYPESnumeric_new();
+
+       { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table nantest2 ( id int4 , d numeric )", ECPGt_EOIT, ECPGt_EORT);
+#line 59 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 59 "nan_test.pgc"
+
+       { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into nantest2 ( id , d ) values ( 4 , 'nan' :: numeric )", ECPGt_EOIT, ECPGt_EORT);
+#line 60 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 60 "nan_test.pgc"
+
+
+       { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select id , d , d from nantest2 where id = 4", ECPGt_EOIT, 
+       ECPGt_int,&(id),(long)1,(long)1,sizeof(int), 
+       ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+       ECPGt_numeric,&(num),(long)1,(long)0,sizeof(numeric), 
+       ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+       ECPGt_char,(val),(long)16,(long)1,(16)*sizeof(char), 
+       ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+#line 62 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 62 "nan_test.pgc"
+
+
+       printf("%d %s '%s'\n", id, (num->sign == NUMERIC_NAN ? "NaN" : "not NaN"), val);
+
+       { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into nantest2 ( id , d ) values ( 5 , $1  )", 
+       ECPGt_numeric,&(num),(long)1,(long)0,sizeof(numeric), 
+       ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+#line 66 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 66 "nan_test.pgc"
+
+       { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into nantest2 ( id , d ) values ( 6 , $1  )", 
+       ECPGt_char,(val),(long)16,(long)1,(16)*sizeof(char), 
+       ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+#line 67 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 67 "nan_test.pgc"
+
+
+       /* declare cur1 cursor for select id , d , d from nantest2 */
+#line 69 "nan_test.pgc"
+
+       { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare cur1 cursor for select id , d , d from nantest2", ECPGt_EOIT, ECPGt_EORT);
+#line 70 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 70 "nan_test.pgc"
+
+       while (1)
+       {
+               { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch from cur1", ECPGt_EOIT, 
+       ECPGt_int,&(id),(long)1,(long)1,sizeof(int), 
+       ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+       ECPGt_numeric,&(num),(long)1,(long)0,sizeof(numeric), 
+       ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, 
+       ECPGt_char,(val),(long)16,(long)1,(16)*sizeof(char), 
+       ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+#line 73 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 73 "nan_test.pgc"
+
+               if (sqlca.sqlcode)
+                       break;
+               printf("%d %s '%s'\n", id, (num->sign == NUMERIC_NAN ? "NaN" : "not NaN"), val);
+       }
+       { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close cur1", ECPGt_EOIT, ECPGt_EORT);
+#line 78 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 78 "nan_test.pgc"
+
+
+       { ECPGtrans(__LINE__, NULL, "rollback");
+#line 80 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 80 "nan_test.pgc"
+
+       { ECPGdisconnect(__LINE__, "CURRENT");
+#line 81 "nan_test.pgc"
+
+if (sqlca.sqlcode < 0) sqlprint ( );}
+#line 81 "nan_test.pgc"
+
+
+       return (0);
+}
diff --git a/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stderr b/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stderr
new file mode 100644 (file)
index 0000000..cb87b53
--- /dev/null
@@ -0,0 +1,360 @@
+[NO_PID]: ECPGdebug: set to 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ECPGconnect: opening database regress1 on <DEFAULT> port <DEFAULT>  
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 24: query: create table nantest1 ( id int4 , d float8 ); with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 24: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 24: OK: CREATE TABLE
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 25: query: insert into nantest1 ( id , d ) values ( 1 , 'nan' :: float8 ) , ( 2 , 'inf' :: float8 ) , ( 3 , '-inf' :: float8 ); with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 25: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 25: OK: INSERT 0 3
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 28: query: declare cur cursor for select id , d , d from nantest1; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 28: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 28: OK: DECLARE CURSOR
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: query: fetch from cur; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 31: RESULT: 1 offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 31: RESULT: NaN offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 31: RESULT: NaN offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 39: query: insert into nantest1 ( id , d ) values ( $1  + 3 , $2  ); with 2 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 39: using PQexecParams
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: free_params on line 39: parameter 1 = 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: free_params on line 39: parameter 2 = NaN
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 39: OK: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 40: query: insert into nantest1 ( id , d ) values ( $1  + 6 , $2  ); with 2 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 40: using PQexecParams
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: free_params on line 40: parameter 1 = 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: free_params on line 40: parameter 2 = NaN
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 40: OK: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: query: fetch from cur; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 31: RESULT: 2 offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 31: RESULT: Infinity offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 31: RESULT: Infinity offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 39: query: insert into nantest1 ( id , d ) values ( $1  + 3 , $2  ); with 2 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 39: using PQexecParams
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: free_params on line 39: parameter 1 = 2
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: free_params on line 39: parameter 2 = Infinity
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 39: OK: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 40: query: insert into nantest1 ( id , d ) values ( $1  + 6 , $2  ); with 2 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 40: using PQexecParams
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: free_params on line 40: parameter 1 = 2
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: free_params on line 40: parameter 2 = Infinity
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 40: OK: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: query: fetch from cur; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 31: RESULT: 3 offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 31: RESULT: -Infinity offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 31: RESULT: -Infinity offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 39: query: insert into nantest1 ( id , d ) values ( $1  + 3 , $2  ); with 2 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 39: using PQexecParams
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: free_params on line 39: parameter 1 = 3
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: free_params on line 39: parameter 2 = -Infinity
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 39: OK: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 40: query: insert into nantest1 ( id , d ) values ( $1  + 6 , $2  ); with 2 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 40: using PQexecParams
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: free_params on line 40: parameter 1 = 3
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: free_params on line 40: parameter 2 = -Infinity
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 40: OK: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: query: fetch from cur; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: correctly got 0 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: raising sqlcode 100 on line 31: no data found on line 31
+[NO_PID]: sqlca: code: 100, state: 02000
+[NO_PID]: ecpg_execute on line 42: query: close cur; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 42: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 42: OK: CLOSE CURSOR
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 44: query: declare cur cursor for select id , d , d from nantest1; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 44: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 44: OK: DECLARE CURSOR
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: query: fetch from cur; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: 1 offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: NaN offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: NaN offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: query: fetch from cur; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: 2 offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: Infinity offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: Infinity offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: query: fetch from cur; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: 3 offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: -Infinity offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: -Infinity offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: query: fetch from cur; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: 4 offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: NaN offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: NaN offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: query: fetch from cur; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: 7 offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: NaN offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: NaN offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: query: fetch from cur; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: 5 offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: Infinity offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: Infinity offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: query: fetch from cur; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: 8 offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: Infinity offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: Infinity offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: query: fetch from cur; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: 6 offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: -Infinity offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: -Infinity offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: query: fetch from cur; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: 9 offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: -Infinity offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 47: RESULT: -Infinity offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: query: fetch from cur; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 47: correctly got 0 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: raising sqlcode 100 on line 47: no data found on line 47
+[NO_PID]: sqlca: code: 100, state: 02000
+[NO_PID]: ecpg_execute on line 55: query: close cur; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 55: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 55: OK: CLOSE CURSOR
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 59: query: create table nantest2 ( id int4 , d numeric ); with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 59: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 59: OK: CREATE TABLE
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 60: query: insert into nantest2 ( id , d ) values ( 4 , 'nan' :: numeric ); with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 60: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 60: OK: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 62: query: select id , d , d from nantest2 where id = 4; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 62: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 62: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 62: RESULT: 4 offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 62: RESULT: NaN offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 62: RESULT: NaN offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 66: query: insert into nantest2 ( id , d ) values ( 5 , $1  ); with 1 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 66: using PQexecParams
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: free_params on line 66: parameter 1 = NaN
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 66: OK: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 67: query: insert into nantest2 ( id , d ) values ( 6 , $1  ); with 1 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 67: using PQexecParams
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: free_params on line 67: parameter 1 = NaN
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 67: OK: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 70: query: declare cur1 cursor for select id , d , d from nantest2; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 70: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 70: OK: DECLARE CURSOR
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 73: query: fetch from cur1; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 73: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 73: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 73: RESULT: 4 offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 73: RESULT: NaN offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 73: RESULT: NaN offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 73: query: fetch from cur1; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 73: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 73: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 73: RESULT: 5 offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 73: RESULT: NaN offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 73: RESULT: NaN offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 73: query: fetch from cur1; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 73: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 73: correctly got 1 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 73: RESULT: 6 offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 73: RESULT: NaN offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_get_data on line 73: RESULT: NaN offset: -1; array: yes
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 73: query: fetch from cur1; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 73: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 73: correctly got 0 tuples with 3 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: raising sqlcode 100 on line 73: no data found on line 73
+[NO_PID]: sqlca: code: 100, state: 02000
+[NO_PID]: ecpg_execute on line 78: query: close cur1; with 0 parameter(s) on connection regress1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 78: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 78: OK: CLOSE CURSOR
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ECPGtrans on line 80: action "rollback"; connection "regress1"
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_finish: connection regress1 closed
+[NO_PID]: sqlca: code: 0, state: 00000
diff --git a/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stdout b/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stdout
new file mode 100644 (file)
index 0000000..635ab23
--- /dev/null
@@ -0,0 +1,16 @@
+1  NaN 'NaN'
+2 +Inf 'Infinity'
+3 -Inf '-Infinity'
+1  NaN 'NaN'
+2 +Inf 'Infinity'
+3 -Inf '-Infinity'
+4  NaN 'NaN'
+7  NaN 'NaN'
+5 +Inf 'Infinity'
+8 +Inf 'Infinity'
+6 -Inf '-Infinity'
+9 -Inf '-Infinity'
+4 NaN 'NaN'
+4 NaN 'NaN'
+5 NaN 'NaN'
+6 NaN 'NaN'
index aa98ff4ba3e4c175bd1544bbc4b46a39986ef9d0..d510eb0e03bf417628c5177ce77fe338ba219c44 100644 (file)
@@ -31,6 +31,7 @@
 #define NUMERIC_POS                                            0x0000
 #define NUMERIC_NEG                                            0x4000
 #define NUMERIC_NAN                                            0xC000
+#define NUMERIC_NULL                                           0xF000
 #define NUMERIC_MAX_PRECISION                  1000
 #define NUMERIC_MAX_DISPLAY_SCALE              NUMERIC_MAX_PRECISION
 #define NUMERIC_MIN_DISPLAY_SCALE              0
index f85cf392b8171d3a21340f0e7b6d959d5fab8e84..c177ad3f803491e98f85b26a287468f394d9539a 100644 (file)
@@ -53,6 +53,7 @@ typedef struct sqlda_struct   sqlda_t;
 #define NUMERIC_POS                                            0x0000
 #define NUMERIC_NEG                                            0x4000
 #define NUMERIC_NAN                                            0xC000
+#define NUMERIC_NULL                                           0xF000
 #define NUMERIC_MAX_PRECISION                  1000
 #define NUMERIC_MAX_DISPLAY_SCALE              NUMERIC_MAX_PRECISION
 #define NUMERIC_MIN_DISPLAY_SCALE              0
index 6776b706a1b5c63b9b3d4a5760ae65b870ab5a54..5392323da12e714a93c5edb853ea471ccdb37e4f 100644 (file)
@@ -6,7 +6,8 @@ include $(top_srcdir)/$(subdir)/../Makefile.regress
 TESTS = dt_test dt_test.c \
         dt_test2 dt_test2.c \
         num_test num_test.c \
-        num_test2 num_test2.c
+        num_test2 num_test2.c \
+        nan_test nan_test.c
 
 all: $(TESTS)
 
diff --git a/src/interfaces/ecpg/test/pgtypeslib/nan_test.pgc b/src/interfaces/ecpg/test/pgtypeslib/nan_test.pgc
new file mode 100644 (file)
index 0000000..d1793ef
--- /dev/null
@@ -0,0 +1,84 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <pgtypes_numeric.h>
+#include <decimal.h>
+
+exec sql include ../regression;
+
+int
+main(void)
+{
+       exec sql begin declare section;
+       int     id;
+       double  d;
+       numeric *num;
+       char    val[16];
+       exec sql end declare section;
+
+       ECPGdebug(1, stderr);
+       exec sql whenever sqlerror do sqlprint();
+
+       exec sql connect to REGRESSDB1;
+
+       exec sql create table nantest1 (id int4, d float8);
+       exec sql insert into nantest1 (id, d) values (1, 'nan'::float8), (2, 'inf'::float8), (3, '-inf'::float8);
+
+       exec sql declare cur cursor for select id, d, d from nantest1;
+       exec sql open cur;
+       while (1)
+       {
+               exec sql fetch from cur into :id, :d, :val;
+               if (sqlca.sqlcode)
+                       break;
+               if (isinf(d))
+                       printf("%d %sInf '%s'\n", id, (d < 0 ? "-" : "+"), val);
+               if (isnan(d))
+                       printf("%d  NaN '%s'\n", id, val);
+
+               exec sql insert into nantest1 (id, d) values (:id + 3, :d);
+               exec sql insert into nantest1 (id, d) values (:id + 6, :val);
+       }
+       exec sql close cur;
+
+       exec sql open cur;
+       while (1)
+       {
+               exec sql fetch from cur into :id, :d, :val;
+               if (sqlca.sqlcode)
+                       break;
+               if (isinf(d))
+                       printf("%d %sInf '%s'\n", id, (d < 0 ? "-" : "+"), val);
+               if (isnan(d))
+                       printf("%d  NaN '%s'\n", id, val);
+       }
+       exec sql close cur;
+
+       num = PGTYPESnumeric_new();
+
+       exec sql create table nantest2 (id int4, d numeric);
+       exec sql insert into nantest2 (id, d) values (4, 'nan'::numeric);
+
+       exec sql select id, d, d into :id, :num, :val from nantest2 where id = 4;
+
+       printf("%d %s '%s'\n", id, (num->sign == NUMERIC_NAN ? "NaN" : "not NaN"), val);
+
+       exec sql insert into nantest2 (id, d) values (5, :num);
+       exec sql insert into nantest2 (id, d) values (6, :val);
+
+       exec sql declare cur1 cursor for select id, d, d from nantest2;
+       exec sql open cur1;
+       while (1)
+       {
+               exec sql fetch from cur1 into :id, :num, :val;
+               if (sqlca.sqlcode)
+                       break;
+               printf("%d %s '%s'\n", id, (num->sign == NUMERIC_NAN ? "NaN" : "not NaN"), val);
+       }
+       exec sql close cur1;
+
+       exec sql rollback;
+       exec sql disconnect;
+
+       return (0);
+}