From cedae130173c8a023cbc2bad39e2301b24aeb027 Mon Sep 17 00:00:00 2001 From: Michael Meskes Date: Tue, 2 Feb 2010 16:09:12 +0000 Subject: [PATCH] Fixed NaN/Infinity problems in ECPG for float/double/numeric/decimal by making it OS independant. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Patch done by Zoltán Böszörményi. --- src/interfaces/ecpg/ecpglib/data.c | 60 +++- src/interfaces/ecpg/ecpglib/execute.c | 43 ++- src/interfaces/ecpg/ecpglib/misc.c | 10 +- src/interfaces/ecpg/include/pgtypes_numeric.h | 1 + src/interfaces/ecpg/pgtypeslib/numeric.c | 30 +- src/interfaces/ecpg/test/ecpg_schedule | 1 + src/interfaces/ecpg/test/ecpg_schedule_tcp | 1 + .../ecpg/test/expected/pgtypeslib-nan_test.c | 263 +++++++++++++++ .../ecpg/test/expected/pgtypeslib-nan_test.stderr | 360 +++++++++++++++++++++ .../ecpg/test/expected/pgtypeslib-nan_test.stdout | 16 + .../ecpg/test/expected/preproc-outofscope.c | 1 + src/interfaces/ecpg/test/expected/sql-sqlda.c | 1 + src/interfaces/ecpg/test/pgtypeslib/Makefile | 3 +- src/interfaces/ecpg/test/pgtypeslib/nan_test.pgc | 84 +++++ 14 files changed, 859 insertions(+), 15 deletions(-) create mode 100644 src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.c create mode 100644 src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stderr create mode 100644 src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stdout create mode 100644 src/interfaces/ecpg/test/pgtypeslib/nan_test.pgc diff --git a/src/interfaces/ecpg/ecpglib/data.c b/src/interfaces/ecpg/ecpglib/data.c index f30fe8ba1e..d816ff4b3b 100644 --- a/src/interfaces/ecpg/ecpglib/data.c +++ b/src/interfaces/ecpg/ecpglib/data.c @@ -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 #include +#include #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 == '"') diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c index 71b32a8128..48b38dab1e 100644 --- a/src/interfaces/ecpg/ecpglib/execute.c +++ b/src/interfaces/ecpg/ecpglib/execute.c @@ -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 +#include #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; diff --git a/src/interfaces/ecpg/ecpglib/misc.c b/src/interfaces/ecpg/ecpglib/misc.c index d5f7107440..11d69ac04c 100644 --- a/src/interfaces/ecpg/ecpglib/misc.c +++ b/src/interfaces/ecpg/ecpglib/misc.c @@ -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: diff --git a/src/interfaces/ecpg/include/pgtypes_numeric.h b/src/interfaces/ecpg/include/pgtypes_numeric.h index 207b5f37ba..1b9e4c35e4 100644 --- a/src/interfaces/ecpg/include/pgtypes_numeric.h +++ b/src/interfaces/ecpg/include/pgtypes_numeric.h @@ -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 diff --git a/src/interfaces/ecpg/pgtypeslib/numeric.c b/src/interfaces/ecpg/pgtypeslib/numeric.c index 1feac9b76e..3d123489e6 100644 --- a/src/interfaces/ecpg/pgtypeslib/numeric.c +++ b/src/interfaces/ecpg/pgtypeslib/numeric.c @@ -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 @@ -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. */ diff --git a/src/interfaces/ecpg/test/ecpg_schedule b/src/interfaces/ecpg/test/ecpg_schedule index e71452484d..c07ea9359c 100644 --- a/src/interfaces/ecpg/test/ecpg_schedule +++ b/src/interfaces/ecpg/test/ecpg_schedule @@ -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/ecpg_schedule_tcp b/src/interfaces/ecpg/test/ecpg_schedule_tcp index 64125e65ea..5214d251ac 100644 --- a/src/interfaces/ecpg/test/ecpg_schedule_tcp +++ b/src/interfaces/ecpg/test/ecpg_schedule_tcp @@ -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 index 0000000000..f42fea3a35 --- /dev/null +++ b/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.c @@ -0,0 +1,263 @@ +/* Processed by ecpg (regression mode) */ +/* These include files are added by the preprocessor */ +#include +#include +#include +/* End of automatic include section */ +#define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y)) + +#line 1 "nan_test.pgc" +#include +#include +#include +#include +#include + + +#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 index 0000000000..cb87b53f76 --- /dev/null +++ b/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stderr @@ -0,0 +1,360 @@ +[NO_PID]: ECPGdebug: set to 1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGconnect: opening database regress1 on port +[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 index 0000000000..635ab23de0 --- /dev/null +++ b/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stdout @@ -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' diff --git a/src/interfaces/ecpg/test/expected/preproc-outofscope.c b/src/interfaces/ecpg/test/expected/preproc-outofscope.c index aa98ff4ba3..d510eb0e03 100644 --- a/src/interfaces/ecpg/test/expected/preproc-outofscope.c +++ b/src/interfaces/ecpg/test/expected/preproc-outofscope.c @@ -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 diff --git a/src/interfaces/ecpg/test/expected/sql-sqlda.c b/src/interfaces/ecpg/test/expected/sql-sqlda.c index f85cf392b8..c177ad3f80 100644 --- a/src/interfaces/ecpg/test/expected/sql-sqlda.c +++ b/src/interfaces/ecpg/test/expected/sql-sqlda.c @@ -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 diff --git a/src/interfaces/ecpg/test/pgtypeslib/Makefile b/src/interfaces/ecpg/test/pgtypeslib/Makefile index 6776b706a1..5392323da1 100644 --- a/src/interfaces/ecpg/test/pgtypeslib/Makefile +++ b/src/interfaces/ecpg/test/pgtypeslib/Makefile @@ -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 index 0000000000..d1793ef42d --- /dev/null +++ b/src/interfaces/ecpg/test/pgtypeslib/nan_test.pgc @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include + +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); +} -- 2.11.0