Hi, Boszormenyi Zoltan írta: > I think the best would be to delete the NAN test from outofscope.pgc > and fix the double/numeric NaN/Inf/-Inf problem separately and have > their own test case. >
the attached patch attempts to fix NaN/Infinity problems in ECPG for float/double/numeric/decimal. I had to introduce a new NUMERIC_NULL value for the numeric sign to still be able to use risnull()/rsetnull(). Best regards, Zoltán Böszörményi -- Bible has answers for everything. Proof: "But let your communication be, Yea, yea; Nay, nay: for whatsoever is more than these cometh of evil." (Matthew 5:37) - basics of digital technology. "May your kingdom come" - superficial description of plate tectonics ---------------------------------- Zoltán Böszörményi Cybertec Schönig & Schönig GmbH http://www.postgresql.at/
diff -dcrpN pgsql.orig/src/interfaces/ecpg/ecpglib/data.c pgsql/src/interfaces/ecpg/ecpglib/data.c *** pgsql.orig/src/interfaces/ecpg/ecpglib/data.c 2010-01-01 14:11:38.000000000 +0100 --- pgsql/src/interfaces/ecpg/ecpglib/data.c 2010-01-28 21:36:16.000000000 +0100 *************** *** 5,10 **** --- 5,11 ---- #include <stdlib.h> #include <string.h> + #include <math.h> #include "ecpgtype.h" #include "ecpglib.h" *************** garbage_left(enum ARRAY_TYPE isarray, ch *** 38,43 **** --- 39,96 ---- 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, *************** ecpg_get_data(const PGresult *results, i *** 300,307 **** case ECPGt_float: case ECPGt_double: if (isarray && *pval == '"') ! dres = strtod(pval + 1, &scan_length); ! else dres = strtod(pval, &scan_length); if (isarray && *scan_length == '"') --- 353,361 ---- case ECPGt_float: case ECPGt_double: if (isarray && *pval == '"') ! pval++; ! ! if (!check_special_value(pval, &dres, &scan_length)) dres = strtod(pval, &scan_length); if (isarray && *scan_length == '"') diff -dcrpN pgsql.orig/src/interfaces/ecpg/ecpglib/misc.c pgsql/src/interfaces/ecpg/ecpglib/misc.c *** pgsql.orig/src/interfaces/ecpg/ecpglib/misc.c 2010-01-26 10:09:40.000000000 +0100 --- pgsql/src/interfaces/ecpg/ecpglib/misc.c 2010-01-28 21:53:44.000000000 +0100 *************** ECPGset_noind_null(enum ECPGttype type, *** 344,354 **** break; case ECPGt_decimal: memset((char *) ptr, 0, sizeof(decimal)); ! ((decimal *) ptr)->sign = NUMERIC_NAN; break; case ECPGt_numeric: memset((char *) ptr, 0, sizeof(numeric)); ! ((numeric *) ptr)->sign = NUMERIC_NAN; break; case ECPGt_interval: memset((char *) ptr, 0xff, sizeof(interval)); --- 344,354 ---- break; case ECPGt_decimal: memset((char *) ptr, 0, sizeof(decimal)); ! ((decimal *) ptr)->sign = NUMERIC_NULL; break; case ECPGt_numeric: memset((char *) ptr, 0, sizeof(numeric)); ! ((numeric *) ptr)->sign = NUMERIC_NULL; break; case ECPGt_interval: memset((char *) ptr, 0xff, sizeof(interval)); *************** ECPGis_noind_null(enum ECPGttype type, v *** 416,426 **** return true; break; case ECPGt_decimal: ! if (((decimal *) ptr)->sign == NUMERIC_NAN) return true; break; case ECPGt_numeric: ! if (((numeric *) ptr)->sign == NUMERIC_NAN) return true; break; case ECPGt_interval: --- 416,426 ---- return true; break; case ECPGt_decimal: ! if (((decimal *) ptr)->sign == NUMERIC_NULL) return true; break; case ECPGt_numeric: ! if (((numeric *) ptr)->sign == NUMERIC_NULL) return true; break; case ECPGt_interval: diff -dcrpN pgsql.orig/src/interfaces/ecpg/include/pgtypes_numeric.h pgsql/src/interfaces/ecpg/include/pgtypes_numeric.h *** pgsql.orig/src/interfaces/ecpg/include/pgtypes_numeric.h 2010-01-06 08:43:28.000000000 +0100 --- pgsql/src/interfaces/ecpg/include/pgtypes_numeric.h 2010-01-28 22:01:00.000000000 +0100 *************** *** 4,9 **** --- 4,10 ---- #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 -dcrpN pgsql.orig/src/interfaces/ecpg/pgtypeslib/numeric.c pgsql/src/interfaces/ecpg/pgtypeslib/numeric.c *** pgsql.orig/src/interfaces/ecpg/pgtypeslib/numeric.c 2009-09-03 12:25:47.000000000 +0200 --- pgsql/src/interfaces/ecpg/pgtypeslib/numeric.c 2010-01-28 22:32:31.000000000 +0100 *************** set_var_from_str(char *str, char **ptr, *** 173,178 **** --- 173,197 ---- (*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; *************** get_str_from_var(numeric *var, int dscal *** 296,301 **** --- 315,329 ---- 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 -dcrpN pgsql.orig/src/interfaces/ecpg/test/ecpg_schedule pgsql/src/interfaces/ecpg/test/ecpg_schedule *** pgsql.orig/src/interfaces/ecpg/test/ecpg_schedule 2010-01-26 10:09:40.000000000 +0100 --- pgsql/src/interfaces/ecpg/test/ecpg_schedule 2010-01-28 21:24:11.000000000 +0100 *************** test: pgtypeslib/dt_test *** 15,20 **** --- 15,21 ---- 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 -dcrpN pgsql.orig/src/interfaces/ecpg/test/ecpg_schedule_tcp pgsql/src/interfaces/ecpg/test/ecpg_schedule_tcp *** pgsql.orig/src/interfaces/ecpg/test/ecpg_schedule_tcp 2010-01-26 10:09:40.000000000 +0100 --- pgsql/src/interfaces/ecpg/test/ecpg_schedule_tcp 2010-01-28 21:24:19.000000000 +0100 *************** test: pgtypeslib/dt_test *** 15,20 **** --- 15,21 ---- 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 -dcrpN pgsql.orig/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.c pgsql/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.c *** pgsql.orig/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.c 1970-01-01 01:00:00.000000000 +0100 --- pgsql/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.c 2010-01-28 22:23:40.000000000 +0100 *************** *** 0 **** --- 1,157 ---- + /* 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, "close cur", ECPGt_EOIT, ECPGt_EORT); + #line 39 "nan_test.pgc" + + if (sqlca.sqlcode < 0) sqlprint ( );} + #line 39 "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 43 "nan_test.pgc" + + if (sqlca.sqlcode < 0) sqlprint ( );} + #line 43 "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 44 "nan_test.pgc" + + if (sqlca.sqlcode < 0) sqlprint ( );} + #line 44 "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 46 "nan_test.pgc" + + if (sqlca.sqlcode < 0) sqlprint ( );} + #line 46 "nan_test.pgc" + + + printf("%d %s '%s'\n", id, (num->sign == NUMERIC_NAN ? "NaN" : "not NaN"), val); + + { ECPGtrans(__LINE__, NULL, "rollback"); + #line 50 "nan_test.pgc" + + if (sqlca.sqlcode < 0) sqlprint ( );} + #line 50 "nan_test.pgc" + + { ECPGdisconnect(__LINE__, "CURRENT"); + #line 51 "nan_test.pgc" + + if (sqlca.sqlcode < 0) sqlprint ( );} + #line 51 "nan_test.pgc" + + + return (0); + } diff -dcrpN pgsql.orig/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stderr pgsql/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stderr *** pgsql.orig/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stderr 1970-01-01 01:00:00.000000000 +0100 --- pgsql/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stderr 2010-01-28 22:22:53.000000000 +0100 *************** *** 0 **** --- 1,100 ---- + [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 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 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 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 39: query: close cur; with 0 parameter(s) on connection regress1 + [NO_PID]: sqlca: code: 0, state: 00000 + [NO_PID]: ecpg_execute on line 39: using PQexec + [NO_PID]: sqlca: code: 0, state: 00000 + [NO_PID]: ecpg_execute on line 39: OK: CLOSE CURSOR + [NO_PID]: sqlca: code: 0, state: 00000 + [NO_PID]: ecpg_execute on line 43: 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 43: using PQexec + [NO_PID]: sqlca: code: 0, state: 00000 + [NO_PID]: ecpg_execute on line 43: OK: CREATE TABLE + [NO_PID]: sqlca: code: 0, state: 00000 + [NO_PID]: ecpg_execute on line 44: 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 44: using PQexec + [NO_PID]: sqlca: code: 0, state: 00000 + [NO_PID]: ecpg_execute on line 44: OK: INSERT 0 1 + [NO_PID]: sqlca: code: 0, state: 00000 + [NO_PID]: ecpg_execute on line 46: 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 46: using PQexec + [NO_PID]: sqlca: code: 0, state: 00000 + [NO_PID]: ecpg_execute on line 46: correctly got 1 tuples with 3 fields + [NO_PID]: sqlca: code: 0, state: 00000 + [NO_PID]: ecpg_get_data on line 46: RESULT: 4 offset: -1; array: yes + [NO_PID]: sqlca: code: 0, state: 00000 + [NO_PID]: ecpg_get_data on line 46: RESULT: NaN offset: -1; array: yes + [NO_PID]: sqlca: code: 0, state: 00000 + [NO_PID]: ecpg_get_data on line 46: RESULT: NaN offset: -1; array: yes + [NO_PID]: sqlca: code: 0, state: 00000 + [NO_PID]: ECPGtrans on line 50: 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 -dcrpN pgsql.orig/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stdout pgsql/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stdout *** pgsql.orig/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stdout 1970-01-01 01:00:00.000000000 +0100 --- pgsql/src/interfaces/ecpg/test/expected/pgtypeslib-nan_test.stdout 2010-01-28 22:23:45.000000000 +0100 *************** *** 0 **** --- 1,4 ---- + 1 NaN 'NaN' + 2 +Inf 'Infinity' + 3 -Inf '-Infinity' + 4 NaN 'NaN' diff -dcrpN pgsql.orig/src/interfaces/ecpg/test/expected/preproc-outofscope.c pgsql/src/interfaces/ecpg/test/expected/preproc-outofscope.c *** pgsql.orig/src/interfaces/ecpg/test/expected/preproc-outofscope.c 2010-01-26 11:31:14.000000000 +0100 --- pgsql/src/interfaces/ecpg/test/expected/preproc-outofscope.c 2010-01-28 22:41:06.000000000 +0100 *************** *** 31,36 **** --- 31,37 ---- #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 -dcrpN pgsql.orig/src/interfaces/ecpg/test/expected/sql-sqlda.c pgsql/src/interfaces/ecpg/test/expected/sql-sqlda.c *** pgsql.orig/src/interfaces/ecpg/test/expected/sql-sqlda.c 2010-01-06 19:06:44.000000000 +0100 --- pgsql/src/interfaces/ecpg/test/expected/sql-sqlda.c 2010-01-28 22:41:07.000000000 +0100 *************** typedef struct sqlda_struct sqlda_t; *** 53,58 **** --- 53,59 ---- #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 -dcrpN pgsql.orig/src/interfaces/ecpg/test/pgtypeslib/Makefile pgsql/src/interfaces/ecpg/test/pgtypeslib/Makefile *** pgsql.orig/src/interfaces/ecpg/test/pgtypeslib/Makefile 2006-08-13 12:18:31.000000000 +0200 --- pgsql/src/interfaces/ecpg/test/pgtypeslib/Makefile 2010-01-28 21:23:46.000000000 +0100 *************** include $(top_srcdir)/$(subdir)/../Makef *** 6,12 **** TESTS = dt_test dt_test.c \ dt_test2 dt_test2.c \ num_test num_test.c \ ! num_test2 num_test2.c all: $(TESTS) --- 6,13 ---- TESTS = dt_test dt_test.c \ dt_test2 dt_test2.c \ num_test num_test.c \ ! num_test2 num_test2.c \ ! nan_test nan_test.c all: $(TESTS) diff -dcrpN pgsql.orig/src/interfaces/ecpg/test/pgtypeslib/nan_test.pgc pgsql/src/interfaces/ecpg/test/pgtypeslib/nan_test.pgc *** pgsql.orig/src/interfaces/ecpg/test/pgtypeslib/nan_test.pgc 1970-01-01 01:00:00.000000000 +0100 --- pgsql/src/interfaces/ecpg/test/pgtypeslib/nan_test.pgc 2010-01-28 22:22:20.000000000 +0100 *************** *** 0 **** --- 1,54 ---- + #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 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 rollback; + exec sql disconnect; + + return (0); + }
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers