ECPGset_var
Zoltan, could you please look into this:
http://pgbuildfarm.org/cgi-bin/show_log.pl?nm=dugong&dt=2010-01-26%2011:05:01 ?
Apparently dugong creates the ECPGset_var statements in a different order than
the other archs.
Michael
--
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ 179140304, AIM/Yahoo/Skype michaelmeskes, Jabber meskes@jabber.org
VfL Borussia! Força Barça! Go SF 49ers! Use Debian GNU/Linux, PostgreSQL
Hi,
Michael Meskes írta:
Zoltan, could you please look into this:
http://pgbuildfarm.org/cgi-bin/show_log.pl?nm=dugong&dt=2010-01-26%2011:05:01 ?
Apparently dugong creates the ECPGset_var statements in a different order than
the other archs.Michael
It seems mongoose also fails the same way,
the common factor seems to be ICC, other machines
with various GCC versions are green . I'll look into it.
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/
Boszormenyi Zoltan <zb@cybertec.at> writes:
Michael Meskes írta:
Zoltan, could you please look into this:
http://pgbuildfarm.org/cgi-bin/show_log.pl?nm=dugong&dt=2010-01-26%2011:05:01 ?
Apparently dugong creates the ECPGset_var statements in a different order than
the other archs.
It seems mongoose also fails the same way,
the common factor seems to be ICC, other machines
with various GCC versions are green . I'll look into it.
The problem is you've got calls like this:
$$ = cat_str(4,
adjust_outofscope_cursor_vars(this, true),
adjust_outofscope_cursor_vars(this, false),
make_str("ECPG_informix_reset_sqlca();"),
comment);
in which the order of evaluation of cat_str's parameters is unspecified,
but adjust_outofscope_cursor_vars has got order-dependent side effects.
regards, tom lane
Tom Lane �rta:
Boszormenyi Zoltan <zb@cybertec.at> writes:
Michael Meskes Ărta:
Zoltan, could you please look into this:
http://pgbuildfarm.org/cgi-bin/show_log.pl?nm=dugong&dt=2010-01-26%2011:05:01 ?
Apparently dugong creates the ECPGset_var statements in a different order than
the other archs.It seems mongoose also fails the same way,
the common factor seems to be ICC, other machines
with various GCC versions are green . I'll look into it.The problem is you've got calls like this:
$$ = cat_str(4,
adjust_outofscope_cursor_vars(this, true),
adjust_outofscope_cursor_vars(this, false),
make_str("ECPG_informix_reset_sqlca();"),
comment);in which the order of evaluation of cat_str's parameters is unspecified,
but adjust_outofscope_cursor_vars has got order-dependent side effects.regards, tom lane
Thanks for analyzing it, patch is attached. I downloaded
and installed ICC, so I could reproduce the difference.
Also, another "bug" is fixed in one regression test,
it seems NaN is different across platforms, so
we must not test for it either.
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/
Attachments:
pg85-fix-ooscope-cur-1-ctxdiff.patchtext/x-patch; name=pg85-fix-ooscope-cur-1-ctxdiff.patchDownload
diff -dcrpN pgsql.orig/src/interfaces/ecpg/preproc/ecpg.addons pgsql/src/interfaces/ecpg/preproc/ecpg.addons
*** pgsql.orig/src/interfaces/ecpg/preproc/ecpg.addons 2010-01-26 10:09:40.000000000 +0100
--- pgsql/src/interfaces/ecpg/preproc/ecpg.addons 2010-01-26 18:58:18.000000000 +0100
*************** ECPG: DeclareCursorStmtDECLAREcursor_nam
*** 298,304 ****
{
struct cursor *ptr, *this;
char *cursor_marker = $2[0] == ':' ? make_str("$0") : mm_strdup($2);
! char *comment, *c1, *c2;
for (ptr = cur; ptr != NULL; ptr = ptr->next)
{
--- 298,304 ----
{
struct cursor *ptr, *this;
char *cursor_marker = $2[0] == ':' ? make_str("$0") : mm_strdup($2);
! char *comment, *c1, *c2, *oo1, *oo2;
for (ptr = cur; ptr != NULL; ptr = ptr->next)
{
*************** ECPG: DeclareCursorStmtDECLAREcursor_nam
*** 330,346 ****
}
comment = cat_str(3, make_str("/*"), c1, make_str("*/"));
if ((braces_open > 0) && INFORMIX_MODE) /* we're in a function */
! $$ = cat_str(4,
! adjust_outofscope_cursor_vars(this, true),
! adjust_outofscope_cursor_vars(this, false),
make_str("ECPG_informix_reset_sqlca();"),
comment);
else
! $$ = cat_str(3,
! adjust_outofscope_cursor_vars(this, true),
! adjust_outofscope_cursor_vars(this, false),
! comment);
}
ECPG: ClosePortalStmtCLOSEcursor_name block
{
--- 330,344 ----
}
comment = cat_str(3, make_str("/*"), c1, make_str("*/"));
+ oo1 = adjust_outofscope_cursor_vars(this, true);
+ oo2 = adjust_outofscope_cursor_vars(this, false);
+
if ((braces_open > 0) && INFORMIX_MODE) /* we're in a function */
! $$ = cat_str(4, oo1, oo2,
make_str("ECPG_informix_reset_sqlca();"),
comment);
else
! $$ = cat_str(3, oo1, oo2, comment);
}
ECPG: ClosePortalStmtCLOSEcursor_name block
{
diff -dcrpN pgsql.orig/src/interfaces/ecpg/preproc/ecpg.trailer pgsql/src/interfaces/ecpg/preproc/ecpg.trailer
*** pgsql.orig/src/interfaces/ecpg/preproc/ecpg.trailer 2010-01-26 10:09:40.000000000 +0100
--- pgsql/src/interfaces/ecpg/preproc/ecpg.trailer 2010-01-26 18:58:20.000000000 +0100
*************** ECPGCursorStmt: DECLARE cursor_name cur
*** 291,297 ****
char *cursor_marker = $2[0] == ':' ? make_str("$0") : mm_strdup($2);
struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
const char *con = connection ? connection : "NULL";
! char *comment;
for (ptr = cur; ptr != NULL; ptr = ptr->next)
{
--- 291,297 ----
char *cursor_marker = $2[0] == ':' ? make_str("$0") : mm_strdup($2);
struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
const char *con = connection ? connection : "NULL";
! char *comment, *oo1, *oo2;
for (ptr = cur; ptr != NULL; ptr = ptr->next)
{
*************** ECPGCursorStmt: DECLARE cursor_name cur
*** 331,347 ****
comment = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
if ((braces_open > 0) && INFORMIX_MODE) /* we're in a function */
! $$ = cat_str(4,
! adjust_outofscope_cursor_vars(this, true),
! adjust_outofscope_cursor_vars(this, false),
make_str("ECPG_informix_reset_sqlca();"),
comment);
else
! $$ = cat_str(3,
! adjust_outofscope_cursor_vars(this, true),
! adjust_outofscope_cursor_vars(this, false),
! comment);
}
;
--- 331,345 ----
comment = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
+ oo1 = adjust_outofscope_cursor_vars(this, true);
+ oo2 = adjust_outofscope_cursor_vars(this, false);
+
if ((braces_open > 0) && INFORMIX_MODE) /* we're in a function */
! $$ = cat_str(4, oo1, oo2,
make_str("ECPG_informix_reset_sqlca();"),
comment);
else
! $$ = cat_str(3, oo1, oo2, comment);
}
;
diff -dcrpN pgsql.orig/src/interfaces/ecpg/test/expected/preproc-cursor.c pgsql/src/interfaces/ecpg/test/expected/preproc-cursor.c
*** pgsql.orig/src/interfaces/ecpg/test/expected/preproc-cursor.c 2010-01-26 10:09:40.000000000 +0100
--- pgsql/src/interfaces/ecpg/test/expected/preproc-cursor.c 2010-01-26 19:01:18.000000000 +0100
*************** if (sqlca.sqlcode < 0) exit (1);}
*** 287,295 ****
/* Dynamic cursorname test with INTO list in DECLARE stmt */
strcpy(msg, "declare");
! ECPGset_var( 3, &( curname2 ), __LINE__);\
! ECPGset_var( 1, ( t ), __LINE__);\
! ECPGset_var( 2, &( id ), __LINE__);\
/* declare $0 cursor for select id , t from t1 */
#line 100 "cursor.pgc"
--- 287,295 ----
/* Dynamic cursorname test with INTO list in DECLARE stmt */
strcpy(msg, "declare");
! ECPGset_var( 1, &( curname2 ), __LINE__);\
! ECPGset_var( 2, ( t ), __LINE__);\
! ECPGset_var( 3, &( id ), __LINE__);\
/* declare $0 cursor for select id , t from t1 */
#line 100 "cursor.pgc"
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-26 15:25:31.000000000 +0100
*************** if (sqlca.sqlcode < 0) exit (1);}
*** 305,329 ****
if (sqlca.sqlcode < 0) exit (1);}
#line 85 "outofscope.pgc"
! { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default , '\"a\"' , - 1.0 , 'nan' :: float8 , 'a' )", ECPGt_EOIT, ECPGt_EORT);
#line 86 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
#line 86 "outofscope.pgc"
- { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default , 'b' , 2.0 , 3 , 'b' )", ECPGt_EOIT, ECPGt_EORT);
- #line 87 "outofscope.pgc"
-
- if (sqlca.sqlcode < 0) exit (1);}
- #line 87 "outofscope.pgc"
-
strcpy(msg, "commit");
{ ECPGtrans(__LINE__, NULL, "commit");
! #line 90 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
! #line 90 "outofscope.pgc"
/* Test out-of-scope DECLARE/OPEN/FETCH/CLOSE */
--- 305,323 ----
if (sqlca.sqlcode < 0) exit (1);}
#line 85 "outofscope.pgc"
! { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default , 'b' , 2.0 , 3 , 'b' )", ECPGt_EOIT, ECPGt_EORT);
#line 86 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
#line 86 "outofscope.pgc"
strcpy(msg, "commit");
{ ECPGtrans(__LINE__, NULL, "commit");
! #line 89 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
! #line 89 "outofscope.pgc"
/* Test out-of-scope DECLARE/OPEN/FETCH/CLOSE */
*************** if (sqlca.sqlcode < 0) exit (1);}
*** 332,338 ****
open_cur1();
/* exec sql whenever not found break ; */
! #line 97 "outofscope.pgc"
while (1)
--- 326,332 ----
open_cur1();
/* exec sql whenever not found break ; */
! #line 96 "outofscope.pgc"
while (1)
*************** if (sqlca.sqlcode < 0) exit (1);}
*** 353,378 ****
strcpy(msg, "drop");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table a1", ECPGt_EOIT, ECPGt_EORT);
! #line 116 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
! #line 116 "outofscope.pgc"
strcpy(msg, "commit");
{ ECPGtrans(__LINE__, NULL, "commit");
! #line 119 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
! #line 119 "outofscope.pgc"
strcpy(msg, "disconnect");
{ ECPGdisconnect(__LINE__, "CURRENT");
! #line 122 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
! #line 122 "outofscope.pgc"
return (0);
--- 347,372 ----
strcpy(msg, "drop");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table a1", ECPGt_EOIT, ECPGt_EORT);
! #line 115 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
! #line 115 "outofscope.pgc"
strcpy(msg, "commit");
{ ECPGtrans(__LINE__, NULL, "commit");
! #line 118 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
! #line 118 "outofscope.pgc"
strcpy(msg, "disconnect");
{ ECPGdisconnect(__LINE__, "CURRENT");
! #line 121 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
! #line 121 "outofscope.pgc"
return (0);
diff -dcrpN pgsql.orig/src/interfaces/ecpg/test/expected/preproc-outofscope.stderr pgsql/src/interfaces/ecpg/test/expected/preproc-outofscope.stderr
*** pgsql.orig/src/interfaces/ecpg/test/expected/preproc-outofscope.stderr 2010-01-26 11:31:14.000000000 +0100
--- pgsql/src/interfaces/ecpg/test/expected/preproc-outofscope.stderr 2010-01-26 15:25:32.000000000 +0100
***************
*** 26,44 ****
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 85: OK: INSERT 0 1
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 86: query: insert into a1 ( id , t , d1 , d2 , c ) values ( default , '"a"' , - 1.0 , 'nan' :: float8 , 'a' ); with 0 parameter(s) on connection regress1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 86: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 86: OK: INSERT 0 1
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 87: query: insert into a1 ( id , t , d1 , d2 , c ) values ( default , 'b' , 2.0 , 3 , 'b' ); with 0 parameter(s) on connection regress1
! [NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 87: using PQexec
! [NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 87: OK: INSERT 0 1
! [NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ECPGtrans on line 90: action "commit"; connection "regress1"
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 40: query: declare mycur cursor for select * from a1; with 0 parameter(s) on connection regress1
[NO_PID]: sqlca: code: 0, state: 00000
--- 26,38 ----
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 85: OK: INSERT 0 1
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 86: query: insert into a1 ( id , t , d1 , d2 , c ) values ( default , 'b' , 2.0 , 3 , 'b' ); with 0 parameter(s) on connection regress1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 86: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 86: OK: INSERT 0 1
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ECPGtrans on line 89: action "commit"; connection "regress1"
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 40: query: declare mycur cursor for select * from a1; with 0 parameter(s) on connection regress1
[NO_PID]: sqlca: code: 0, state: 00000
***************
*** 86,107 ****
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 49: RESULT: 3 offset: -1; array: yes
[NO_PID]: sqlca: code: 0, state: 00000
- [NO_PID]: ecpg_get_data on line 49: RESULT: "a" offset: -1; array: yes
- [NO_PID]: sqlca: code: 0, state: 00000
- [NO_PID]: ecpg_get_data on line 49: RESULT: -1.0 offset: -1; array: yes
- [NO_PID]: sqlca: code: 0, state: 00000
- [NO_PID]: ecpg_get_data on line 49: RESULT: NaN offset: -1; array: yes
- [NO_PID]: sqlca: code: 0, state: 00000
- [NO_PID]: ecpg_get_data on line 49: RESULT: a offset: -1; array: yes
- [NO_PID]: sqlca: code: 0, state: 00000
- [NO_PID]: ecpg_execute on line 49: query: fetch mycur; with 0 parameter(s) on connection regress1
- [NO_PID]: sqlca: code: 0, state: 00000
- [NO_PID]: ecpg_execute on line 49: using PQexec
- [NO_PID]: sqlca: code: 0, state: 00000
- [NO_PID]: ecpg_execute on line 49: correctly got 1 tuples with 5 fields
- [NO_PID]: sqlca: code: 0, state: 00000
- [NO_PID]: ecpg_get_data on line 49: RESULT: 4 offset: -1; array: yes
- [NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 49: RESULT: b offset: -1; array: yes
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 49: RESULT: 2.0 offset: -1; array: yes
--- 80,85 ----
***************
*** 124,136 ****
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 58: OK: CLOSE CURSOR
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 116: query: drop table a1; with 0 parameter(s) on connection regress1
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 116: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 116: OK: DROP TABLE
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ECPGtrans on line 119: action "commit"; connection "regress1"
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_finish: connection regress1 closed
[NO_PID]: sqlca: code: 0, state: 00000
--- 102,114 ----
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 58: OK: CLOSE CURSOR
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 115: query: drop table a1; with 0 parameter(s) on connection regress1
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 115: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 115: OK: DROP TABLE
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ECPGtrans on line 118: action "commit"; 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/preproc-outofscope.stdout pgsql/src/interfaces/ecpg/test/expected/preproc-outofscope.stdout
*** pgsql.orig/src/interfaces/ecpg/test/expected/preproc-outofscope.stdout 2010-01-26 11:31:14.000000000 +0100
--- pgsql/src/interfaces/ecpg/test/expected/preproc-outofscope.stdout 2010-01-26 15:25:32.000000000 +0100
***************
*** 1,4 ****
id=1 t='a' d1=1.000000 d2=2.000000 c = 'a '
id=2 t='' (NULL) d1=0.000000 (NULL) d2=0.000000 (NULL) c = '' (NULL)
! id=3 t='"a"' d1=-1.000000 d2=nan c = 'a '
! id=4 t='b' d1=2.000000 d2=3.000000 c = 'b '
--- 1,3 ----
id=1 t='a' d1=1.000000 d2=2.000000 c = 'a '
id=2 t='' (NULL) d1=0.000000 (NULL) d2=0.000000 (NULL) c = '' (NULL)
! id=3 t='b' d1=2.000000 d2=3.000000 c = 'b '
diff -dcrpN pgsql.orig/src/interfaces/ecpg/test/preproc/outofscope.pgc pgsql/src/interfaces/ecpg/test/preproc/outofscope.pgc
*** pgsql.orig/src/interfaces/ecpg/test/preproc/outofscope.pgc 2010-01-26 11:31:14.000000000 +0100
--- pgsql/src/interfaces/ecpg/test/preproc/outofscope.pgc 2010-01-26 15:23:51.000000000 +0100
*************** main (void)
*** 83,89 ****
strcpy(msg, "insert");
exec sql insert into a1(id, t, d1, d2, c) values (default, 'a', 1.0, 2, 'a');
exec sql insert into a1(id, t, d1, d2, c) values (default, null, null, null, null);
- exec sql insert into a1(id, t, d1, d2, c) values (default, '"a"', -1.0, 'nan'::float8, 'a');
exec sql insert into a1(id, t, d1, d2, c) values (default, 'b', 2.0, 3, 'b');
strcpy(msg, "commit");
--- 83,88 ----
Boszormenyi Zoltan wrote:
Thanks for analyzing it, patch is attached. I downloaded
and installed ICC, so I could reproduce the difference.
Why not have a single function that does both things in a single call?
It doesn't look like there's any place that calls the function with only
one value for "insert" ...
I happened to notice this misleading comment:
char temp[20]; /* this should be sufficient unless you have 8 byte integers */
--
Alvaro Herrera http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.
Alvaro Herrera �rta:
Boszormenyi Zoltan wrote:
Thanks for analyzing it, patch is attached. I downloaded
and installed ICC, so I could reproduce the difference.Why not have a single function that does both things in a single call?
It doesn't look like there's any place that calls the function with only
one value for "insert" ...
Okay, I tried this approach, patch is attached.
This way it doesn't depend on the evaluation order
of function parameters.
I happened to notice this misleading comment:
char temp[20]; /* this should be sufficient unless you have 8 byte integers */
That comment was there before I touched that function, I deleted it now.
There will be other problems before reaching 2^31-1 internal variables,
like compiling the monster C file without the compiler going OOM...
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/
Attachments:
pg85-fix-ooscope-cur-2-ctxdiff.patchtext/x-patch; name=pg85-fix-ooscope-cur-2-ctxdiff.patchDownload
diff -dcrpN pgsql.orig/src/interfaces/ecpg/preproc/ecpg.addons pgsql/src/interfaces/ecpg/preproc/ecpg.addons
*** pgsql.orig/src/interfaces/ecpg/preproc/ecpg.addons 2010-01-26 10:09:40.000000000 +0100
--- pgsql/src/interfaces/ecpg/preproc/ecpg.addons 2010-01-26 20:11:53.000000000 +0100
*************** ECPG: DeclareCursorStmtDECLAREcursor_nam
*** 331,346 ****
comment = cat_str(3, make_str("/*"), c1, make_str("*/"));
if ((braces_open > 0) && INFORMIX_MODE) /* we're in a function */
! $$ = cat_str(4,
! adjust_outofscope_cursor_vars(this, true),
! adjust_outofscope_cursor_vars(this, false),
make_str("ECPG_informix_reset_sqlca();"),
comment);
else
! $$ = cat_str(3,
! adjust_outofscope_cursor_vars(this, true),
! adjust_outofscope_cursor_vars(this, false),
! comment);
}
ECPG: ClosePortalStmtCLOSEcursor_name block
{
--- 331,341 ----
comment = cat_str(3, make_str("/*"), c1, make_str("*/"));
if ((braces_open > 0) && INFORMIX_MODE) /* we're in a function */
! $$ = cat_str(3, adjust_outofscope_cursor_vars(this),
make_str("ECPG_informix_reset_sqlca();"),
comment);
else
! $$ = cat2_str(adjust_outofscope_cursor_vars(this), comment);
}
ECPG: ClosePortalStmtCLOSEcursor_name block
{
diff -dcrpN pgsql.orig/src/interfaces/ecpg/preproc/ecpg.header pgsql/src/interfaces/ecpg/preproc/ecpg.header
*** pgsql.orig/src/interfaces/ecpg/preproc/ecpg.header 2010-01-26 10:09:40.000000000 +0100
--- pgsql/src/interfaces/ecpg/preproc/ecpg.header 2010-01-26 20:25:06.000000000 +0100
*************** create_questionmarks(char *name, bool ar
*** 227,233 ****
}
static char *
! adjust_outofscope_cursor_vars(struct cursor *cur, bool insert)
{
/* Informix accepts DECLARE with variables that are out of scope when OPEN is called.
* For instance you can DECLARE a cursor in one function, and OPEN/FETCH/CLOSE
--- 227,233 ----
}
static char *
! adjust_outofscope_cursor_vars(struct cursor *cur)
{
/* Informix accepts DECLARE with variables that are out of scope when OPEN is called.
* For instance you can DECLARE a cursor in one function, and OPEN/FETCH/CLOSE
*************** adjust_outofscope_cursor_vars(struct cur
*** 240,371 ****
* instead of the variable. Do it only for local variables, not for globals.
*/
- struct arguments *list;
- struct arguments *ptr;
- struct arguments *newlist = NULL;
- struct variable *newvar, *newind;
char *result = make_str("");
! list = (insert ? cur->argsinsert : cur->argsresult);
!
! for (ptr = list; ptr != NULL; ptr = ptr->next)
{
! char temp[20]; /* this should be sufficient unless you have 8 byte integers */
! char *original_var;
! bool skip_set_var = false;
! /* change variable name to "ECPGget_var(<counter>)" */
! original_var = ptr->variable->name;
! sprintf(temp, "%d))", ecpg_internal_var);
! /* Don't emit ECPGset_var() calls for global variables */
! if (ptr->variable->brace_level == 0)
! {
! newvar = ptr->variable;
! skip_set_var = true;
! }
! else if ((ptr->variable->type->type == ECPGt_char_variable) && (!strncmp(ptr->variable->name, "ECPGprepared_statement", strlen("ECPGprepared_statement"))))
! {
! newvar = ptr->variable;
! skip_set_var = true;
! }
! else if ((ptr->variable->type->type != ECPGt_varchar && ptr->variable->type->type != ECPGt_char && ptr->variable->type->type != ECPGt_unsigned_char && ptr->variable->type->type != ECPGt_string) && atoi(ptr->variable->type->size) > 1)
! {
! newvar = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, make_str("1"), ptr->variable->type->u.element->lineno), ptr->variable->type->size), 0);
! sprintf(temp, "%d, (", ecpg_internal_var++);
! }
! else if ((ptr->variable->type->type == ECPGt_varchar || ptr->variable->type->type == ECPGt_char || ptr->variable->type->type == ECPGt_unsigned_char || ptr->variable->type->type == ECPGt_string) && atoi(ptr->variable->type->size) > 1)
! {
! newvar = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->lineno), 0);
! if (ptr->variable->type->type == ECPGt_varchar)
! sprintf(temp, "%d, &(", ecpg_internal_var++);
! else
! sprintf(temp, "%d, (", ecpg_internal_var++);
! }
! else if (ptr->variable->type->type == ECPGt_struct || ptr->variable->type->type == ECPGt_union)
! {
! sprintf(temp, "%d)))", ecpg_internal_var);
! newvar = new_variable(cat_str(4, make_str("(*("), mm_strdup(ptr->variable->type->type_name), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_struct_type(ptr->variable->type->u.members, ptr->variable->type->type, ptr->variable->type->type_name, ptr->variable->type->struct_sizeof), 0);
! sprintf(temp, "%d, &(", ecpg_internal_var++);
! }
! else if (ptr->variable->type->type == ECPGt_array)
{
! if (ptr->variable->type->u.element->type == ECPGt_struct || ptr->variable->type->u.element->type == ECPGt_union)
{
! sprintf(temp, "%d)))", ecpg_internal_var);
! newvar = new_variable(cat_str(4, make_str("(*("), mm_strdup(ptr->variable->type->u.element->type_name), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_struct_type(ptr->variable->type->u.element->u.members, ptr->variable->type->u.element->type, ptr->variable->type->u.element->type_name, ptr->variable->type->u.element->struct_sizeof), 0);
sprintf(temp, "%d, (", ecpg_internal_var++);
}
! else
{
! newvar = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, ptr->variable->type->u.element->size, ptr->variable->type->u.element->lineno), ptr->variable->type->size), 0);
! sprintf(temp, "%d, &(", ecpg_internal_var++);
}
! }
! else
! {
! newvar = new_variable(cat_str(4, make_str("*("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->lineno), 0);
! sprintf(temp, "%d, &(", ecpg_internal_var++);
! }
!
! /* create call to "ECPGset_var(<counter>, <pointer>. <linen number>)" */
! if (!skip_set_var)
! result = cat_str(5, result, make_str("ECPGset_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n"));
!
! /* now the indicator if there is one and it's not a global variable */
! if ((ptr->indicator->type->type == ECPGt_NO_INDICATOR) || (ptr->indicator->brace_level == 0))
! {
! newind = ptr->indicator;
! }
! else
! {
! /* change variable name to "ECPGget_var(<counter>)" */
! original_var = ptr->indicator->name;
! sprintf(temp, "%d))", ecpg_internal_var);
!
! if (ptr->indicator->type->type == ECPGt_struct || ptr->indicator->type->type == ECPGt_union)
{
sprintf(temp, "%d)))", ecpg_internal_var);
! newind = new_variable(cat_str(4, make_str("(*("), mm_strdup(ptr->indicator->type->type_name), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_struct_type(ptr->indicator->type->u.members, ptr->indicator->type->type, ptr->indicator->type->type_name, ptr->indicator->type->struct_sizeof), 0);
sprintf(temp, "%d, &(", ecpg_internal_var++);
}
! else if (ptr->indicator->type->type == ECPGt_array)
{
! if (ptr->indicator->type->u.element->type == ECPGt_struct || ptr->indicator->type->u.element->type == ECPGt_union)
{
sprintf(temp, "%d)))", ecpg_internal_var);
! newind = new_variable(cat_str(4, make_str("(*("), mm_strdup(ptr->indicator->type->u.element->type_name), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_struct_type(ptr->indicator->type->u.element->u.members, ptr->indicator->type->u.element->type, ptr->indicator->type->u.element->type_name, ptr->indicator->type->u.element->struct_sizeof), 0);
sprintf(temp, "%d, (", ecpg_internal_var++);
}
else
{
! newind = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->indicator->type->u.element->type)), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_array_type(ECPGmake_simple_type(ptr->indicator->type->u.element->type, ptr->indicator->type->u.element->size, ptr->indicator->type->u.element->lineno), ptr->indicator->type->size), 0);
sprintf(temp, "%d, &(", ecpg_internal_var++);
}
}
- else if (atoi(ptr->indicator->type->size) > 1)
- {
- newind = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->indicator->type->type)), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->lineno), 0);
- sprintf(temp, "%d, (", ecpg_internal_var++);
- }
else
{
! newind = new_variable(cat_str(4, make_str("*("), mm_strdup(ecpg_type_name(ptr->indicator->type->type)), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->lineno), 0);
sprintf(temp, "%d, &(", ecpg_internal_var++);
}
/* create call to "ECPGset_var(<counter>, <pointer>. <linen number>)" */
! result = cat_str(5, result, make_str("ECPGset_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n"));
}
! add_variable_to_tail(&newlist, newvar, newind);
}
- if (insert)
- cur->argsinsert_oos = newlist;
- else
- cur->argsresult_oos = newlist;
-
return result;
}
--- 240,376 ----
* instead of the variable. Do it only for local variables, not for globals.
*/
char *result = make_str("");
+ int insert;
! for (insert = 1; insert >= 0; insert--)
{
! struct arguments *list;
! struct arguments *ptr;
! struct arguments *newlist = NULL;
! struct variable *newvar, *newind;
! list = (insert ? cur->argsinsert : cur->argsresult);
! for (ptr = list; ptr != NULL; ptr = ptr->next)
{
! char temp[20];
! char *original_var;
! bool skip_set_var = false;
!
! /* change variable name to "ECPGget_var(<counter>)" */
! original_var = ptr->variable->name;
! sprintf(temp, "%d))", ecpg_internal_var);
!
! /* Don't emit ECPGset_var() calls for global variables */
! if (ptr->variable->brace_level == 0)
{
! newvar = ptr->variable;
! skip_set_var = true;
! }
! else if ((ptr->variable->type->type == ECPGt_char_variable) && (!strncmp(ptr->variable->name, "ECPGprepared_statement", strlen("ECPGprepared_statement"))))
! {
! newvar = ptr->variable;
! skip_set_var = true;
! }
! else if ((ptr->variable->type->type != ECPGt_varchar && ptr->variable->type->type != ECPGt_char && ptr->variable->type->type != ECPGt_unsigned_char && ptr->variable->type->type != ECPGt_string) && atoi(ptr->variable->type->size) > 1)
! {
! newvar = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, make_str("1"), ptr->variable->type->u.element->lineno), ptr->variable->type->size), 0);
sprintf(temp, "%d, (", ecpg_internal_var++);
}
! else if ((ptr->variable->type->type == ECPGt_varchar || ptr->variable->type->type == ECPGt_char || ptr->variable->type->type == ECPGt_unsigned_char || ptr->variable->type->type == ECPGt_string) && atoi(ptr->variable->type->size) > 1)
{
! newvar = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->lineno), 0);
! if (ptr->variable->type->type == ECPGt_varchar)
! sprintf(temp, "%d, &(", ecpg_internal_var++);
! else
! sprintf(temp, "%d, (", ecpg_internal_var++);
}
! else if (ptr->variable->type->type == ECPGt_struct || ptr->variable->type->type == ECPGt_union)
{
sprintf(temp, "%d)))", ecpg_internal_var);
! newvar = new_variable(cat_str(4, make_str("(*("), mm_strdup(ptr->variable->type->type_name), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_struct_type(ptr->variable->type->u.members, ptr->variable->type->type, ptr->variable->type->type_name, ptr->variable->type->struct_sizeof), 0);
sprintf(temp, "%d, &(", ecpg_internal_var++);
}
! else if (ptr->variable->type->type == ECPGt_array)
{
! if (ptr->variable->type->u.element->type == ECPGt_struct || ptr->variable->type->u.element->type == ECPGt_union)
{
sprintf(temp, "%d)))", ecpg_internal_var);
! newvar = new_variable(cat_str(4, make_str("(*("), mm_strdup(ptr->variable->type->u.element->type_name), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_struct_type(ptr->variable->type->u.element->u.members, ptr->variable->type->u.element->type, ptr->variable->type->u.element->type_name, ptr->variable->type->u.element->struct_sizeof), 0);
sprintf(temp, "%d, (", ecpg_internal_var++);
}
else
{
! newvar = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, ptr->variable->type->u.element->size, ptr->variable->type->u.element->lineno), ptr->variable->type->size), 0);
sprintf(temp, "%d, &(", ecpg_internal_var++);
}
}
else
{
! newvar = new_variable(cat_str(4, make_str("*("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->lineno), 0);
sprintf(temp, "%d, &(", ecpg_internal_var++);
}
/* create call to "ECPGset_var(<counter>, <pointer>. <linen number>)" */
! if (!skip_set_var)
! result = cat_str(5, result, make_str("ECPGset_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n"));
!
! /* now the indicator if there is one and it's not a global variable */
! if ((ptr->indicator->type->type == ECPGt_NO_INDICATOR) || (ptr->indicator->brace_level == 0))
! {
! newind = ptr->indicator;
! }
! else
! {
! /* change variable name to "ECPGget_var(<counter>)" */
! original_var = ptr->indicator->name;
! sprintf(temp, "%d))", ecpg_internal_var);
!
! if (ptr->indicator->type->type == ECPGt_struct || ptr->indicator->type->type == ECPGt_union)
! {
! sprintf(temp, "%d)))", ecpg_internal_var);
! newind = new_variable(cat_str(4, make_str("(*("), mm_strdup(ptr->indicator->type->type_name), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_struct_type(ptr->indicator->type->u.members, ptr->indicator->type->type, ptr->indicator->type->type_name, ptr->indicator->type->struct_sizeof), 0);
! sprintf(temp, "%d, &(", ecpg_internal_var++);
! }
! else if (ptr->indicator->type->type == ECPGt_array)
! {
! if (ptr->indicator->type->u.element->type == ECPGt_struct || ptr->indicator->type->u.element->type == ECPGt_union)
! {
! sprintf(temp, "%d)))", ecpg_internal_var);
! newind = new_variable(cat_str(4, make_str("(*("), mm_strdup(ptr->indicator->type->u.element->type_name), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_struct_type(ptr->indicator->type->u.element->u.members, ptr->indicator->type->u.element->type, ptr->indicator->type->u.element->type_name, ptr->indicator->type->u.element->struct_sizeof), 0);
! sprintf(temp, "%d, (", ecpg_internal_var++);
! }
! else
! {
! newind = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->indicator->type->u.element->type)), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_array_type(ECPGmake_simple_type(ptr->indicator->type->u.element->type, ptr->indicator->type->u.element->size, ptr->indicator->type->u.element->lineno), ptr->indicator->type->size), 0);
! sprintf(temp, "%d, &(", ecpg_internal_var++);
! }
! }
! else if (atoi(ptr->indicator->type->size) > 1)
! {
! newind = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->indicator->type->type)), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->lineno), 0);
! sprintf(temp, "%d, (", ecpg_internal_var++);
! }
! else
! {
! newind = new_variable(cat_str(4, make_str("*("), mm_strdup(ecpg_type_name(ptr->indicator->type->type)), make_str(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->lineno), 0);
! sprintf(temp, "%d, &(", ecpg_internal_var++);
! }
!
! /* create call to "ECPGset_var(<counter>, <pointer>. <linen number>)" */
! result = cat_str(5, result, make_str("ECPGset_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n"));
! }
!
! add_variable_to_tail(&newlist, newvar, newind);
}
! if (insert)
! cur->argsinsert_oos = newlist;
! else
! cur->argsresult_oos = newlist;
}
return result;
}
diff -dcrpN pgsql.orig/src/interfaces/ecpg/preproc/ecpg.trailer pgsql/src/interfaces/ecpg/preproc/ecpg.trailer
*** pgsql.orig/src/interfaces/ecpg/preproc/ecpg.trailer 2010-01-26 10:09:40.000000000 +0100
--- pgsql/src/interfaces/ecpg/preproc/ecpg.trailer 2010-01-26 20:11:45.000000000 +0100
*************** ECPGCursorStmt: DECLARE cursor_name cur
*** 332,347 ****
comment = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
if ((braces_open > 0) && INFORMIX_MODE) /* we're in a function */
! $$ = cat_str(4,
! adjust_outofscope_cursor_vars(this, true),
! adjust_outofscope_cursor_vars(this, false),
make_str("ECPG_informix_reset_sqlca();"),
comment);
else
! $$ = cat_str(3,
! adjust_outofscope_cursor_vars(this, true),
! adjust_outofscope_cursor_vars(this, false),
! comment);
}
;
--- 332,342 ----
comment = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
if ((braces_open > 0) && INFORMIX_MODE) /* we're in a function */
! $$ = cat_str(3, adjust_outofscope_cursor_vars(this),
make_str("ECPG_informix_reset_sqlca();"),
comment);
else
! $$ = cat2_str(adjust_outofscope_cursor_vars(this), comment);
}
;
diff -dcrpN pgsql.orig/src/interfaces/ecpg/test/expected/preproc-cursor.c pgsql/src/interfaces/ecpg/test/expected/preproc-cursor.c
*** pgsql.orig/src/interfaces/ecpg/test/expected/preproc-cursor.c 2010-01-26 10:09:40.000000000 +0100
--- pgsql/src/interfaces/ecpg/test/expected/preproc-cursor.c 2010-01-26 19:01:18.000000000 +0100
*************** if (sqlca.sqlcode < 0) exit (1);}
*** 287,295 ****
/* Dynamic cursorname test with INTO list in DECLARE stmt */
strcpy(msg, "declare");
! ECPGset_var( 3, &( curname2 ), __LINE__);\
! ECPGset_var( 1, ( t ), __LINE__);\
! ECPGset_var( 2, &( id ), __LINE__);\
/* declare $0 cursor for select id , t from t1 */
#line 100 "cursor.pgc"
--- 287,295 ----
/* Dynamic cursorname test with INTO list in DECLARE stmt */
strcpy(msg, "declare");
! ECPGset_var( 1, &( curname2 ), __LINE__);\
! ECPGset_var( 2, ( t ), __LINE__);\
! ECPGset_var( 3, &( id ), __LINE__);\
/* declare $0 cursor for select id , t from t1 */
#line 100 "cursor.pgc"
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-26 15:25:31.000000000 +0100
*************** if (sqlca.sqlcode < 0) exit (1);}
*** 305,329 ****
if (sqlca.sqlcode < 0) exit (1);}
#line 85 "outofscope.pgc"
! { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default , '\"a\"' , - 1.0 , 'nan' :: float8 , 'a' )", ECPGt_EOIT, ECPGt_EORT);
#line 86 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
#line 86 "outofscope.pgc"
- { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default , 'b' , 2.0 , 3 , 'b' )", ECPGt_EOIT, ECPGt_EORT);
- #line 87 "outofscope.pgc"
-
- if (sqlca.sqlcode < 0) exit (1);}
- #line 87 "outofscope.pgc"
-
strcpy(msg, "commit");
{ ECPGtrans(__LINE__, NULL, "commit");
! #line 90 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
! #line 90 "outofscope.pgc"
/* Test out-of-scope DECLARE/OPEN/FETCH/CLOSE */
--- 305,323 ----
if (sqlca.sqlcode < 0) exit (1);}
#line 85 "outofscope.pgc"
! { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default , 'b' , 2.0 , 3 , 'b' )", ECPGt_EOIT, ECPGt_EORT);
#line 86 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
#line 86 "outofscope.pgc"
strcpy(msg, "commit");
{ ECPGtrans(__LINE__, NULL, "commit");
! #line 89 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
! #line 89 "outofscope.pgc"
/* Test out-of-scope DECLARE/OPEN/FETCH/CLOSE */
*************** if (sqlca.sqlcode < 0) exit (1);}
*** 332,338 ****
open_cur1();
/* exec sql whenever not found break ; */
! #line 97 "outofscope.pgc"
while (1)
--- 326,332 ----
open_cur1();
/* exec sql whenever not found break ; */
! #line 96 "outofscope.pgc"
while (1)
*************** if (sqlca.sqlcode < 0) exit (1);}
*** 353,378 ****
strcpy(msg, "drop");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table a1", ECPGt_EOIT, ECPGt_EORT);
! #line 116 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
! #line 116 "outofscope.pgc"
strcpy(msg, "commit");
{ ECPGtrans(__LINE__, NULL, "commit");
! #line 119 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
! #line 119 "outofscope.pgc"
strcpy(msg, "disconnect");
{ ECPGdisconnect(__LINE__, "CURRENT");
! #line 122 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
! #line 122 "outofscope.pgc"
return (0);
--- 347,372 ----
strcpy(msg, "drop");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table a1", ECPGt_EOIT, ECPGt_EORT);
! #line 115 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
! #line 115 "outofscope.pgc"
strcpy(msg, "commit");
{ ECPGtrans(__LINE__, NULL, "commit");
! #line 118 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
! #line 118 "outofscope.pgc"
strcpy(msg, "disconnect");
{ ECPGdisconnect(__LINE__, "CURRENT");
! #line 121 "outofscope.pgc"
if (sqlca.sqlcode < 0) exit (1);}
! #line 121 "outofscope.pgc"
return (0);
diff -dcrpN pgsql.orig/src/interfaces/ecpg/test/expected/preproc-outofscope.stderr pgsql/src/interfaces/ecpg/test/expected/preproc-outofscope.stderr
*** pgsql.orig/src/interfaces/ecpg/test/expected/preproc-outofscope.stderr 2010-01-26 11:31:14.000000000 +0100
--- pgsql/src/interfaces/ecpg/test/expected/preproc-outofscope.stderr 2010-01-26 15:25:32.000000000 +0100
***************
*** 26,44 ****
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 85: OK: INSERT 0 1
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 86: query: insert into a1 ( id , t , d1 , d2 , c ) values ( default , '"a"' , - 1.0 , 'nan' :: float8 , 'a' ); with 0 parameter(s) on connection regress1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 86: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 86: OK: INSERT 0 1
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 87: query: insert into a1 ( id , t , d1 , d2 , c ) values ( default , 'b' , 2.0 , 3 , 'b' ); with 0 parameter(s) on connection regress1
! [NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 87: using PQexec
! [NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 87: OK: INSERT 0 1
! [NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ECPGtrans on line 90: action "commit"; connection "regress1"
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 40: query: declare mycur cursor for select * from a1; with 0 parameter(s) on connection regress1
[NO_PID]: sqlca: code: 0, state: 00000
--- 26,38 ----
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 85: OK: INSERT 0 1
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 86: query: insert into a1 ( id , t , d1 , d2 , c ) values ( default , 'b' , 2.0 , 3 , 'b' ); with 0 parameter(s) on connection regress1
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 86: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 86: OK: INSERT 0 1
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ECPGtrans on line 89: action "commit"; connection "regress1"
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 40: query: declare mycur cursor for select * from a1; with 0 parameter(s) on connection regress1
[NO_PID]: sqlca: code: 0, state: 00000
***************
*** 86,107 ****
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 49: RESULT: 3 offset: -1; array: yes
[NO_PID]: sqlca: code: 0, state: 00000
- [NO_PID]: ecpg_get_data on line 49: RESULT: "a" offset: -1; array: yes
- [NO_PID]: sqlca: code: 0, state: 00000
- [NO_PID]: ecpg_get_data on line 49: RESULT: -1.0 offset: -1; array: yes
- [NO_PID]: sqlca: code: 0, state: 00000
- [NO_PID]: ecpg_get_data on line 49: RESULT: NaN offset: -1; array: yes
- [NO_PID]: sqlca: code: 0, state: 00000
- [NO_PID]: ecpg_get_data on line 49: RESULT: a offset: -1; array: yes
- [NO_PID]: sqlca: code: 0, state: 00000
- [NO_PID]: ecpg_execute on line 49: query: fetch mycur; with 0 parameter(s) on connection regress1
- [NO_PID]: sqlca: code: 0, state: 00000
- [NO_PID]: ecpg_execute on line 49: using PQexec
- [NO_PID]: sqlca: code: 0, state: 00000
- [NO_PID]: ecpg_execute on line 49: correctly got 1 tuples with 5 fields
- [NO_PID]: sqlca: code: 0, state: 00000
- [NO_PID]: ecpg_get_data on line 49: RESULT: 4 offset: -1; array: yes
- [NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 49: RESULT: b offset: -1; array: yes
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 49: RESULT: 2.0 offset: -1; array: yes
--- 80,85 ----
***************
*** 124,136 ****
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 58: OK: CLOSE CURSOR
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 116: query: drop table a1; with 0 parameter(s) on connection regress1
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 116: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 116: OK: DROP TABLE
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ECPGtrans on line 119: action "commit"; connection "regress1"
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_finish: connection regress1 closed
[NO_PID]: sqlca: code: 0, state: 00000
--- 102,114 ----
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_execute on line 58: OK: CLOSE CURSOR
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 115: query: drop table a1; with 0 parameter(s) on connection regress1
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 115: using PQexec
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 115: OK: DROP TABLE
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ECPGtrans on line 118: action "commit"; 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/preproc-outofscope.stdout pgsql/src/interfaces/ecpg/test/expected/preproc-outofscope.stdout
*** pgsql.orig/src/interfaces/ecpg/test/expected/preproc-outofscope.stdout 2010-01-26 11:31:14.000000000 +0100
--- pgsql/src/interfaces/ecpg/test/expected/preproc-outofscope.stdout 2010-01-26 15:25:32.000000000 +0100
***************
*** 1,4 ****
id=1 t='a' d1=1.000000 d2=2.000000 c = 'a '
id=2 t='' (NULL) d1=0.000000 (NULL) d2=0.000000 (NULL) c = '' (NULL)
! id=3 t='"a"' d1=-1.000000 d2=nan c = 'a '
! id=4 t='b' d1=2.000000 d2=3.000000 c = 'b '
--- 1,3 ----
id=1 t='a' d1=1.000000 d2=2.000000 c = 'a '
id=2 t='' (NULL) d1=0.000000 (NULL) d2=0.000000 (NULL) c = '' (NULL)
! id=3 t='b' d1=2.000000 d2=3.000000 c = 'b '
diff -dcrpN pgsql.orig/src/interfaces/ecpg/test/preproc/outofscope.pgc pgsql/src/interfaces/ecpg/test/preproc/outofscope.pgc
*** pgsql.orig/src/interfaces/ecpg/test/preproc/outofscope.pgc 2010-01-26 11:31:14.000000000 +0100
--- pgsql/src/interfaces/ecpg/test/preproc/outofscope.pgc 2010-01-26 15:23:51.000000000 +0100
*************** main (void)
*** 83,89 ****
strcpy(msg, "insert");
exec sql insert into a1(id, t, d1, d2, c) values (default, 'a', 1.0, 2, 'a');
exec sql insert into a1(id, t, d1, d2, c) values (default, null, null, null, null);
- exec sql insert into a1(id, t, d1, d2, c) values (default, '"a"', -1.0, 'nan'::float8, 'a');
exec sql insert into a1(id, t, d1, d2, c) values (default, 'b', 2.0, 3, 'b');
strcpy(msg, "commit");
--- 83,88 ----
Boszormenyi Zoltan wrote:
Alvaro Herrera �rta:
I happened to notice this misleading comment:
char temp[20]; /* this should be sufficient unless you have 8 byte integers */
That comment was there before I touched that function, I deleted it now.
There will be other problems before reaching 2^31-1 internal variables,
like compiling the monster C file without the compiler going OOM...
No, I meant
alvherre=# select length((2^32)::text), length((2^64)::text);
length | length
--------+--------
10 | 20
(1 fila)
--
Alvaro Herrera http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.
Boszormenyi Zoltan <zb@cybertec.at> writes:
Also, another "bug" is fixed in one regression test,
it seems NaN is different across platforms, so
we must not test for it either.
Really? The main regression tests have several test cases for NaN,
and no provision that I can see for platform dependence of the
result.
-- special inputs
SELECT 'NaN'::float8;
float8
--------
NaN
(1 row)
If ecpg isn't handling this maybe you have a real bug to deal with.
regards, tom lane
Tom Lane �rta:
Boszormenyi Zoltan <zb@cybertec.at> writes:
Also, another "bug" is fixed in one regression test,
it seems NaN is different across platforms, so
we must not test for it either.Really? The main regression tests have several test cases for NaN,
and no provision that I can see for platform dependence of the
result.-- special inputs
SELECT 'NaN'::float8;
float8
--------
NaN
(1 row)If ecpg isn't handling this maybe you have a real bug to deal with.
regards, tom lane
I meant this, e.g. from "gypsy_moth":
===================================
*** /export/home/tmp/pg-test/build-suncc/HEAD/pgsql.11494/src/interfaces/ecpg/test/expected/preproc-outofscope.stdout Tue Jan 26 13:51:59 2010
--- /export/home/tmp/pg-test/build-suncc/HEAD/pgsql.11494/src/interfaces/ecpg/test/results/preproc-outofscope.stdout Tue Jan 26 14:14:58 2010
***************
*** 1,4 ****
id=1 t='a' d1=1.000000 d2=2.000000 c = 'a '
id=2 t='' (NULL) d1=0.000000 (NULL) d2=0.000000 (NULL) c = '' (NULL)
! id=3 t='"a"' d1=-1.000000 d2=nan c = 'a '
id=4 t='b' d1=2.000000 d2=3.000000 c = 'b '
--- 1,4 ----
id=1 t='a' d1=1.000000 d2=2.000000 c = 'a '
id=2 t='' (NULL) d1=0.000000 (NULL) d2=0.000000 (NULL) c = '' (NULL)
! id=3 t='"a"' d1=-1.000000 d2=NaN c = 'a '
id=4 t='b' d1=2.000000 d2=3.000000 c = 'b '
===================================
This is the result of a printf(). My Fedora 9 writes out "nan",
every Sparc machine in the buildfarm writes out "NaN".
This is not an ECPG parser bug, only a difference in the
system libc.
However, on "mastodon", a Windows Server 2003 machine:
===================================
--- 92,96 ----
[NO_PID]: sqlca: code: 0, state: 00000
[NO_PID]: ecpg_get_data on line 49: RESULT: NaN offset: -1; array: yes
[NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: raising sqlcode -206 on line 49: invalid input syntax for floating-point type: "NaN", on line 49
! [NO_PID]: sqlca: code: -206, state: 42804
===================================
This comes from this code in data.c, in ecpg_get_data():
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 == '"')
scan_length++;
if (garbage_left(isarray,
scan_length, compat))
{
ecpg_raise(lineno,
ECPG_FLOAT_FORMAT,
ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
return (false);
}
It seems Windows doesn't accept "NaN" in strtod(). Is it really the case?
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/
Boszormenyi Zoltan <zb@cybertec.at> writes:
Tom Lane �rta:
Really? The main regression tests have several test cases for NaN,
and no provision that I can see for platform dependence of the
result.
I meant this, e.g. from "gypsy_moth":
*** 1,4 **** id=1 t='a' d1=1.000000 d2=2.000000 c = 'a ' id=2 t='' (NULL) d1=0.000000 (NULL) d2=0.000000 (NULL) c = '' (NULL) ! id=3 t='"a"' d1=-1.000000 d2=nan c = 'a ' id=4 t='b' d1=2.000000 d2=3.000000 c = 'b ' --- 1,4 ---- id=1 t='a' d1=1.000000 d2=2.000000 c = 'a ' id=2 t='' (NULL) d1=0.000000 (NULL) d2=0.000000 (NULL) c = '' (NULL) ! id=3 t='"a"' d1=-1.000000 d2=NaN c = 'a ' id=4 t='b' d1=2.000000 d2=3.000000 c = 'b '
Hmm. The backend gets around this by testing isnan() rather than
relying on what sprintf will do with a NaN. I'm not sure if it's
possible/practical for ecpg to do likewise. Even if it's not, it
might be better to carry a variant result file instead of not testing
NaN behavior at all. I'll leave it to Michael to make that decision
though ...
It seems Windows doesn't accept "NaN" in strtod(). Is it really the case?
Again, see the backend (float8in).
regards, tom lane
Tom Lane �rta:
Boszormenyi Zoltan <zb@cybertec.at> writes:
Tom Lane �rta:
Really? The main regression tests have several test cases for NaN,
and no provision that I can see for platform dependence of the
result.I meant this, e.g. from "gypsy_moth":
*** 1,4 **** id=1 t='a' d1=1.000000 d2=2.000000 c = 'a ' id=2 t='' (NULL) d1=0.000000 (NULL) d2=0.000000 (NULL) c = '' (NULL) ! id=3 t='"a"' d1=-1.000000 d2=nan c = 'a ' id=4 t='b' d1=2.000000 d2=3.000000 c = 'b ' --- 1,4 ---- id=1 t='a' d1=1.000000 d2=2.000000 c = 'a ' id=2 t='' (NULL) d1=0.000000 (NULL) d2=0.000000 (NULL) c = '' (NULL) ! id=3 t='"a"' d1=-1.000000 d2=NaN c = 'a ' id=4 t='b' d1=2.000000 d2=3.000000 c = 'b 'Hmm. The backend gets around this by testing isnan() rather than
relying on what sprintf will do with a NaN. I'm not sure if it's
possible/practical for ecpg to do likewise. Even if it's not, it
might be better to carry a variant result file instead of not testing
NaN behavior at all. I'll leave it to Michael to make that decision
though ...It seems Windows doesn't accept "NaN" in strtod(). Is it really the case?
Again, see the backend (float8in).
Yes, I saw it and also looked at numeric_in() and compared
them with ecpg/pgtypeslib/numeric.c and NUMERIC_NAN
is not set anywhere. Also tested 'nan'::numeric and getting it into
a "numeric" variable gave me this:
! [NO_PID]: ecpg_get_data on line 49: RESULT NaN; errno 302
[NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: raising sqlcode -207 on line 49: SQL error -207 on line 49
+ [NO_PID]: sqlca: code: -207, state: 42804
errno == 302 (PGTYPES_NUM_BAD_NUMERIC) is set by pgtypeslib
and the subsequent error (-207 == ECPG_NUMERIC_FORMAT) has
a documentation bug at
http://www.postgresql.org/docs/8.4/interactive/ecpg-errors.html
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.
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/
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/
Attachments:
pg85-ecpg-fix-nan-inf-2-ctxdiff.patchtext/x-patch; name=pg85-ecpg-fix-nan-inf-2-ctxdiff.patchDownload
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);
+ }