Hi, here's another patch that aims to fix auto-prepare.
The reason is, that in the project porting from Informix, a small test case that used a cursor and two small SELECTs issued for every record retrieved by the cursor showed that for this case, the ESQL compiled binary finished about 60% faster then the ECPG compiled counterpart running against PostgreSQL. The cursor retrieved a little over 60'000 records. We have modified the test code to prepare the two SELECTs and now the new test code was faster then the ESQL/Informix code, parsing and planning the two small SELECTs had such an accumulated runtime effect. Then we looked at ECPG and discovered that it already has the auto-prepare feature, and tried it using "ecpg -r prepare". However, it turned out that the auto-prepare feature is over-zealous, it tries to prepare statements that are rejected by the server, returning -400 (ECPG_PGSQL). One example is char *sqlstr = "SELECT ..."; EXEC SQL PREPARE stmt1 FROM :sqlstr; EXEC SQL DECLARE cur1 CURSOR FOR stmt1; The attached patch is an attempt to make the preprocessor only pass ECPGst_prepnormal when it's definitely appropriate, i.e. only for DELETE, INSERT, UPDATE and SELECT(-like) statements in the grammar. Comments? 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.4.1/src/interfaces/ecpg/preproc/ecpg.addons pgsql.6/src/interfaces/ecpg/preproc/ecpg.addons *** pgsql.4.1/src/interfaces/ecpg/preproc/ecpg.addons 2009-12-15 12:15:49.000000000 +0100 --- pgsql.6/src/interfaces/ecpg/preproc/ecpg.addons 2009-12-15 13:18:05.000000000 +0100 *************** ECPG: stmtClosePortalStmt block *** 15,21 **** } } ! output_statement($1, 0, ECPGst_normal); } ECPG: stmtDeallocateStmt block { --- 15,21 ---- } } ! output_statement($1, 0, ECPGst_normal, false); } ECPG: stmtDeallocateStmt block { *************** ECPG: stmtDeallocateStmt block *** 26,46 **** } ECPG: stmtDeclareCursorStmt block { output_simple_statement($1); } - ECPG: stmtDeleteStmt block ECPG: stmtDiscardStmt block ECPG: stmtFetchStmt block ECPG: stmtInsertStmt block ECPG: stmtSelectStmt block ECPG: stmtUpdateStmt block ! { output_statement($1, 1, ECPGst_normal); } ECPG: stmtExecuteStmt block ! { output_statement($1, 1, ECPGst_execute); } ECPG: stmtPrepareStmt block { if ($1.type == NULL || strlen($1.type) == 0) output_prepare_statement($1.name, $1.stmt); ! else ! output_statement(cat_str(5, make_str("prepare"), $1.name, $1.type, make_str("as"), $1.stmt), 0, ECPGst_normal); } ECPG: stmtTransactionStmt block { --- 26,47 ---- } ECPG: stmtDeclareCursorStmt block { output_simple_statement($1); } ECPG: stmtDiscardStmt block ECPG: stmtFetchStmt block + { output_statement($1, 1, ECPGst_normal, false); } + ECPG: stmtDeleteStmt block ECPG: stmtInsertStmt block ECPG: stmtSelectStmt block ECPG: stmtUpdateStmt block ! { output_statement($1, 1, ECPGst_normal, auto_prepare); } ECPG: stmtExecuteStmt block ! { output_statement($1, 1, ECPGst_execute, false); } ECPG: stmtPrepareStmt block { if ($1.type == NULL || strlen($1.type) == 0) output_prepare_statement($1.name, $1.stmt); ! else ! output_statement(cat_str(5, make_str("prepare"), $1.name, $1.type, make_str("as"), $1.stmt), 0, ECPGst_normal, false); } ECPG: stmtTransactionStmt block { *************** ECPG: stmtViewStmt rule *** 101,107 **** whenever_action(2); free($1); } ! | ECPGExecuteImmediateStmt { output_statement($1, 0, ECPGst_exec_immediate); } | ECPGFree { const char *con = connection ? connection : "NULL"; --- 102,108 ---- whenever_action(2); free($1); } ! | ECPGExecuteImmediateStmt { output_statement($1, 0, ECPGst_exec_immediate, false); } | ECPGFree { const char *con = connection ? connection : "NULL"; *************** ECPG: stmtViewStmt rule *** 133,139 **** if ((ptr = add_additional_variables($1, true)) != NULL) { connection = ptr->connection ? mm_strdup(ptr->connection) : NULL; ! output_statement(mm_strdup(ptr->command), 0, 0); ptr->opened = true; } } --- 134,140 ---- if ((ptr = add_additional_variables($1, true)) != NULL) { connection = ptr->connection ? mm_strdup(ptr->connection) : NULL; ! output_statement(mm_strdup(ptr->command), 0, ECPGst_normal, false); ptr->opened = true; } } diff -dcrpN pgsql.4.1/src/interfaces/ecpg/preproc/extern.h pgsql.6/src/interfaces/ecpg/preproc/extern.h *** pgsql.4.1/src/interfaces/ecpg/preproc/extern.h 2009-12-15 12:07:20.000000000 +0100 --- pgsql.6/src/interfaces/ecpg/preproc/extern.h 2009-12-15 13:46:55.000000000 +0100 *************** extern const char *get_dtype(enum ECPGdt *** 64,70 **** extern void lex_init(void); extern char *make_str(const char *); extern void output_line_number(void); ! extern void output_statement(char *, int, enum ECPG_statement_type); extern void output_prepare_statement(char *, char *); extern void output_deallocate_prepare_statement(char *); extern void output_simple_statement(char *); --- 64,70 ---- extern void lex_init(void); extern char *make_str(const char *); extern void output_line_number(void); ! extern void output_statement(char *, int, enum ECPG_statement_type, int); extern void output_prepare_statement(char *, char *); extern void output_deallocate_prepare_statement(char *); extern void output_simple_statement(char *); diff -dcrpN pgsql.4.1/src/interfaces/ecpg/preproc/output.c pgsql.6/src/interfaces/ecpg/preproc/output.c *** pgsql.4.1/src/interfaces/ecpg/preproc/output.c 2009-06-13 18:25:05.000000000 +0200 --- pgsql.6/src/interfaces/ecpg/preproc/output.c 2009-12-15 13:12:37.000000000 +0100 *************** hashline_number(void) *** 106,112 **** } void ! output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st) { fprintf(yyout, "{ ECPGdo(__LINE__, %d, %d, %s, %d, ", compat, force_indicator, connection ? connection : "NULL", questionmarks); --- 106,112 ---- } void ! output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st, int auto_prepare) { fprintf(yyout, "{ ECPGdo(__LINE__, %d, %d, %s, %d, ", compat, force_indicator, connection ? connection : "NULL", questionmarks); diff -dcrpN pgsql.4.1/src/interfaces/ecpg/preproc/parse.pl pgsql.6/src/interfaces/ecpg/preproc/parse.pl *** pgsql.4.1/src/interfaces/ecpg/preproc/parse.pl 2009-11-26 18:57:00.000000000 +0100 --- pgsql.6/src/interfaces/ecpg/preproc/parse.pl 2009-12-15 13:23:06.000000000 +0100 *************** sub dump_fields { *** 441,447 **** # we're in the stmt: rule if ($len) { # or just the statement ... ! &add_to_buffer('rules', " { output_statement(\$1, 0, ECPGst_normal); }"); } else { &add_to_buffer('rules', " { \$\$ = NULL; }"); --- 441,447 ---- # we're in the stmt: rule if ($len) { # or just the statement ... ! &add_to_buffer('rules', " { output_statement(\$1, 0, ECPGst_normal, false); }"); } else { &add_to_buffer('rules', " { \$\$ = NULL; }"); diff -dcrpN pgsql.4.1/src/interfaces/ecpg/test/expected/preproc-autoprep.c pgsql.6/src/interfaces/ecpg/test/expected/preproc-autoprep.c *** pgsql.4.1/src/interfaces/ecpg/test/expected/preproc-autoprep.c 2009-05-25 12:08:49.000000000 +0200 --- pgsql.6/src/interfaces/ecpg/test/expected/preproc-autoprep.c 2009-12-15 13:43:11.000000000 +0100 *************** *** 26,143 **** int main() { /* exec sql begin declare section */ #line 10 "autoprep.pgc" int item [ 4 ] , ind [ 4 ] , i = 1 ; ! /* exec sql end declare section */ #line 11 "autoprep.pgc" ECPGdebug(1, stderr); { ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , NULL, 0); } ! #line 14 "autoprep.pgc" /* exec sql whenever sql_warning sqlprint ; */ ! #line 16 "autoprep.pgc" /* exec sql whenever sqlerror sqlprint ; */ ! #line 17 "autoprep.pgc" ! { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_prepnormal, "create table T ( Item1 int , Item2 int )", ECPGt_EOIT, ECPGt_EORT); ! #line 19 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); ! #line 19 "autoprep.pgc" if (sqlca.sqlcode < 0) sqlprint();} ! #line 19 "autoprep.pgc" { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_prepnormal, "insert into T values ( 1 , null )", ECPGt_EOIT, ECPGt_EORT); ! #line 21 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); ! #line 21 "autoprep.pgc" if (sqlca.sqlcode < 0) sqlprint();} ! #line 21 "autoprep.pgc" { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_prepnormal, "insert into T values ( 1 , $1 )", ECPGt_int,&(i),(long)1,(long)1,sizeof(int), ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT); ! #line 22 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); ! #line 22 "autoprep.pgc" if (sqlca.sqlcode < 0) sqlprint();} ! #line 22 "autoprep.pgc" i++; { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_prepnormal, "insert into T values ( 1 , $1 )", ECPGt_int,&(i),(long)1,(long)1,sizeof(int), ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT); ! #line 24 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); ! #line 24 "autoprep.pgc" if (sqlca.sqlcode < 0) sqlprint();} ! #line 24 "autoprep.pgc" { ECPGprepare(__LINE__, NULL, 0, "i", " insert into T values ( 1 , 2 ) "); ! #line 25 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); ! #line 25 "autoprep.pgc" if (sqlca.sqlcode < 0) sqlprint();} ! #line 25 "autoprep.pgc" { ECPGdo(__LINE__, 0, 1, NULL, 0, 1, "i", ECPGt_EOIT, ECPGt_EORT); ! #line 26 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); ! #line 26 "autoprep.pgc" if (sqlca.sqlcode < 0) sqlprint();} ! #line 26 "autoprep.pgc" { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_prepnormal, "select Item2 from T order by Item2 nulls last", ECPGt_EOIT, ECPGt_int,(item),(long)1,(long)4,sizeof(int), ECPGt_int,(ind),(long)1,(long)4,sizeof(int), ECPGt_EORT); ! #line 28 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); ! #line 28 "autoprep.pgc" if (sqlca.sqlcode < 0) sqlprint();} ! #line 28 "autoprep.pgc" for (i=0; i<4; i++) printf("item[%d] = %d\n", i, ind[i] ? -1 : item[i]); /* declare C cursor for select Item1 from T */ - #line 33 "autoprep.pgc" - - - { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_prepnormal, "declare C cursor for select Item1 from T", ECPGt_EOIT, ECPGt_EORT); - #line 35 "autoprep.pgc" - - if (sqlca.sqlwarn[0] == 'W') sqlprint(); #line 35 "autoprep.pgc" - if (sqlca.sqlcode < 0) sqlprint();} - #line 35 "autoprep.pgc" ! ! { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_prepnormal, "fetch 1 in C", ECPGt_EOIT, ! ECPGt_int,&(i),(long)1,(long)1,sizeof(int), ! ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); #line 37 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); --- 26,139 ---- int main() { /* exec sql begin declare section */ + + #line 10 "autoprep.pgc" int item [ 4 ] , ind [ 4 ] , i = 1 ; ! #line 11 "autoprep.pgc" + int item1 , ind1 ; + + #line 12 "autoprep.pgc" + char sqlstr [ 64 ] = "SELECT item2 FROM T ORDER BY item2 NULLS LAST" ; + /* exec sql end declare section */ + #line 13 "autoprep.pgc" ECPGdebug(1, stderr); { ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , NULL, 0); } ! #line 16 "autoprep.pgc" /* exec sql whenever sql_warning sqlprint ; */ ! #line 18 "autoprep.pgc" /* exec sql whenever sqlerror sqlprint ; */ ! #line 19 "autoprep.pgc" ! { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table T ( Item1 int , Item2 int )", ECPGt_EOIT, ECPGt_EORT); ! #line 21 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); ! #line 21 "autoprep.pgc" if (sqlca.sqlcode < 0) sqlprint();} ! #line 21 "autoprep.pgc" { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_prepnormal, "insert into T values ( 1 , null )", ECPGt_EOIT, ECPGt_EORT); ! #line 23 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); ! #line 23 "autoprep.pgc" if (sqlca.sqlcode < 0) sqlprint();} ! #line 23 "autoprep.pgc" { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_prepnormal, "insert into T values ( 1 , $1 )", ECPGt_int,&(i),(long)1,(long)1,sizeof(int), ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT); ! #line 24 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); ! #line 24 "autoprep.pgc" if (sqlca.sqlcode < 0) sqlprint();} ! #line 24 "autoprep.pgc" i++; { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_prepnormal, "insert into T values ( 1 , $1 )", ECPGt_int,&(i),(long)1,(long)1,sizeof(int), ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT); ! #line 26 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); ! #line 26 "autoprep.pgc" if (sqlca.sqlcode < 0) sqlprint();} ! #line 26 "autoprep.pgc" { ECPGprepare(__LINE__, NULL, 0, "i", " insert into T values ( 1 , 2 ) "); ! #line 27 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); ! #line 27 "autoprep.pgc" if (sqlca.sqlcode < 0) sqlprint();} ! #line 27 "autoprep.pgc" { ECPGdo(__LINE__, 0, 1, NULL, 0, 1, "i", ECPGt_EOIT, ECPGt_EORT); ! #line 28 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); ! #line 28 "autoprep.pgc" if (sqlca.sqlcode < 0) sqlprint();} ! #line 28 "autoprep.pgc" { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_prepnormal, "select Item2 from T order by Item2 nulls last", ECPGt_EOIT, ECPGt_int,(item),(long)1,(long)4,sizeof(int), ECPGt_int,(ind),(long)1,(long)4,sizeof(int), ECPGt_EORT); ! #line 30 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); ! #line 30 "autoprep.pgc" if (sqlca.sqlcode < 0) sqlprint();} ! #line 30 "autoprep.pgc" for (i=0; i<4; i++) printf("item[%d] = %d\n", i, ind[i] ? -1 : item[i]); /* declare C cursor for select Item1 from T */ #line 35 "autoprep.pgc" ! { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare C cursor for select Item1 from T", ECPGt_EOIT, ECPGt_EORT); #line 37 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); *************** if (sqlca.sqlwarn[0] == 'W') sqlprint(); *** 146,164 **** if (sqlca.sqlcode < 0) sqlprint();} #line 37 "autoprep.pgc" - printf("i = %d\n", i); ! { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_prepnormal, "close C", ECPGt_EOIT, ECPGt_EORT); ! #line 40 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); ! #line 40 "autoprep.pgc" if (sqlca.sqlcode < 0) sqlprint();} ! #line 40 "autoprep.pgc" ! { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_prepnormal, "drop table T", ECPGt_EOIT, ECPGt_EORT); #line 42 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); --- 142,162 ---- if (sqlca.sqlcode < 0) sqlprint();} #line 37 "autoprep.pgc" ! { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch 1 in C", ECPGt_EOIT, ! ECPGt_int,&(i),(long)1,(long)1,sizeof(int), ! ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); ! #line 39 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); ! #line 39 "autoprep.pgc" if (sqlca.sqlcode < 0) sqlprint();} ! #line 39 "autoprep.pgc" + printf("i = %d\n", i); ! { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close C", ECPGt_EOIT, ECPGt_EORT); #line 42 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); *************** if (sqlca.sqlcode < 0) sqlprint();} *** 168,174 **** #line 42 "autoprep.pgc" ! { ECPGdisconnect(__LINE__, "ALL"); #line 44 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); --- 166,172 ---- #line 42 "autoprep.pgc" ! { ECPGprepare(__LINE__, NULL, 0, "stmt1", sqlstr); #line 44 "autoprep.pgc" if (sqlca.sqlwarn[0] == 'W') sqlprint(); *************** if (sqlca.sqlcode < 0) sqlprint();} *** 178,182 **** --- 176,251 ---- #line 44 "autoprep.pgc" + /* declare cur1 cursor for $1 */ + #line 46 "autoprep.pgc" + + + { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare cur1 cursor for $1", + ECPGt_char_variable,(ECPGprepared_statement(NULL, "stmt1", __LINE__)),(long)1,(long)1,(1)*sizeof(char), + ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT); + #line 48 "autoprep.pgc" + + if (sqlca.sqlwarn[0] == 'W') sqlprint(); + #line 48 "autoprep.pgc" + + if (sqlca.sqlcode < 0) sqlprint();} + #line 48 "autoprep.pgc" + + + /* exec sql whenever not found break ; */ + #line 50 "autoprep.pgc" + + + i = 0; + while (1) + { + { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch cur1", ECPGt_EOIT, + ECPGt_int,&(item1),(long)1,(long)1,sizeof(int), + ECPGt_int,&(ind1),(long)1,(long)1,sizeof(int), ECPGt_EORT); + #line 55 "autoprep.pgc" + + if (sqlca.sqlcode == ECPG_NOT_FOUND) break; + #line 55 "autoprep.pgc" + + if (sqlca.sqlwarn[0] == 'W') sqlprint(); + #line 55 "autoprep.pgc" + + if (sqlca.sqlcode < 0) sqlprint();} + #line 55 "autoprep.pgc" + + printf("item[%d] = %d\n", i, ind1 ? -1 : item1); + i++; + } + + { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close cur1", ECPGt_EOIT, ECPGt_EORT); + #line 60 "autoprep.pgc" + + if (sqlca.sqlwarn[0] == 'W') sqlprint(); + #line 60 "autoprep.pgc" + + if (sqlca.sqlcode < 0) sqlprint();} + #line 60 "autoprep.pgc" + + + { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table T", ECPGt_EOIT, ECPGt_EORT); + #line 62 "autoprep.pgc" + + if (sqlca.sqlwarn[0] == 'W') sqlprint(); + #line 62 "autoprep.pgc" + + if (sqlca.sqlcode < 0) sqlprint();} + #line 62 "autoprep.pgc" + + + { ECPGdisconnect(__LINE__, "ALL"); + #line 64 "autoprep.pgc" + + if (sqlca.sqlwarn[0] == 'W') sqlprint(); + #line 64 "autoprep.pgc" + + if (sqlca.sqlcode < 0) sqlprint();} + #line 64 "autoprep.pgc" + + return 0; } diff -dcrpN pgsql.4.1/src/interfaces/ecpg/test/expected/preproc-autoprep.stderr pgsql.6/src/interfaces/ecpg/test/expected/preproc-autoprep.stderr *** pgsql.4.1/src/interfaces/ecpg/test/expected/preproc-autoprep.stderr 2008-12-30 15:28:02.000000000 +0100 --- pgsql.6/src/interfaces/ecpg/test/expected/preproc-autoprep.stderr 2009-12-15 13:43:21.000000000 +0100 *************** *** 2,131 **** [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_auto_prepare on line 19: statement not in cache; inserting [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGprepare on line 19: name ecpg1; query: "create table T ( Item1 int , Item2 int )" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 19: query: create table T ( Item1 int , Item2 int ); with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 19: using PQexecPrepared for "create table T ( Item1 int , Item2 int )" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 19: OK: CREATE TABLE [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_auto_prepare on line 21: statement not in cache; inserting [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGprepare on line 21: name ecpg2; query: "insert into T values ( 1 , null )" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 21: query: insert into T values ( 1 , null ); with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 21: using PQexecPrepared for "insert into T values ( 1 , null )" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 21: OK: INSERT 0 1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_auto_prepare on line 22: statement not in cache; inserting [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGprepare on line 22: name ecpg3; query: "insert into T values ( 1 , $1 )" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 22: query: insert into T values ( 1 , $1 ); with 1 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 22: using PQexecPrepared for "insert into T values ( 1 , $1 )" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: free_params on line 22: parameter 1 = 1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 22: OK: INSERT 0 1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_auto_prepare on line 24: statement found in cache; entry 1640 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 24: query: insert into T values ( 1 , $1 ); with 1 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 24: using PQexecPrepared for "insert into T values ( 1 , $1 )" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: free_params on line 24: parameter 1 = 2 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 24: OK: INSERT 0 1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGprepare on line 25: name i; query: " insert into T values ( 1 , 2 ) " [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 26: query: insert into T values ( 1 , 2 ) ; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 26: using PQexecPrepared for " insert into T values ( 1 , 2 ) " [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 26: OK: INSERT 0 1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_auto_prepare on line 28: statement not in cache; inserting [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGprepare on line 28: name ecpg4; query: "select Item2 from T order by Item2 nulls last" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 28: query: select Item2 from T order by Item2 nulls last; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 28: using PQexecPrepared for "select Item2 from T order by Item2 nulls last" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 28: correctly got 4 tuples with 1 fields [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_get_data on line 28: RESULT: 1 offset: -1; array: yes [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_get_data on line 28: RESULT: 2 offset: -1; array: yes [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_get_data on line 28: RESULT: 2 offset: -1; array: yes [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_get_data on line 28: RESULT: offset: -1; array: yes [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_auto_prepare on line 35: statement not in cache; inserting [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGprepare on line 35: name ecpg5; query: "declare C cursor for select Item1 from T" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 35: query: declare C cursor for select Item1 from T; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 35: using PQexecPrepared for "declare C cursor for select Item1 from T" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 35: OK: DECLARE CURSOR [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_auto_prepare on line 37: statement not in cache; inserting [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGprepare on line 37: name ecpg6; query: "fetch 1 in C" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 37: query: fetch 1 in C; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 37: using PQexecPrepared for "fetch 1 in C" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 37: correctly got 1 tuples with 1 fields [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_get_data on line 37: RESULT: 1 offset: -1; array: yes [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_auto_prepare on line 40: statement not in cache; inserting [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGprepare on line 40: name ecpg7; query: "close C" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 40: query: close C; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 40: using PQexecPrepared for "close C" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 40: OK: CLOSE CURSOR [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_auto_prepare on line 42: statement not in cache; inserting [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGprepare on line 42: name ecpg8; query: "drop table T" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 42: query: drop table T; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 42: using PQexecPrepared for "drop table T" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 42: OK: DROP TABLE [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGdeallocate on line 0: name ecpg8 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGdeallocate on line 0: name ecpg7 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGdeallocate on line 0: name ecpg6 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGdeallocate on line 0: name ecpg5 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGdeallocate on line 0: name ecpg4 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGdeallocate on line 0: name i [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ECPGdeallocate on line 0: name ecpg3 [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ECPGdeallocate on line 0: name ecpg2 [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ECPGdeallocate on line 0: name ecpg1 --- 2,157 ---- [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 21: query: create table T ( Item1 int , Item2 int ); with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 21: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 21: OK: CREATE TABLE [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_auto_prepare on line 23: statement not in cache; inserting [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGprepare on line 23: name ecpg1; query: "insert into T values ( 1 , null )" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 23: query: insert into T values ( 1 , null ); with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 23: using PQexecPrepared for "insert into T values ( 1 , null )" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 23: OK: INSERT 0 1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_auto_prepare on line 24: statement not in cache; inserting [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGprepare on line 24: name ecpg2; query: "insert into T values ( 1 , $1 )" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 24: query: insert into T values ( 1 , $1 ); with 1 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 24: using PQexecPrepared for "insert into T values ( 1 , $1 )" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: free_params on line 24: parameter 1 = 1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 24: OK: INSERT 0 1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_auto_prepare on line 26: statement found in cache; entry 1640 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 26: query: insert into T values ( 1 , $1 ); with 1 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 26: using PQexecPrepared for "insert into T values ( 1 , $1 )" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: free_params on line 26: parameter 1 = 2 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 26: OK: INSERT 0 1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGprepare on line 27: name i; query: " insert into T values ( 1 , 2 ) " [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 28: query: insert into T values ( 1 , 2 ) ; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 28: using PQexecPrepared for " insert into T values ( 1 , 2 ) " [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 28: OK: INSERT 0 1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_auto_prepare on line 30: statement not in cache; inserting [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGprepare on line 30: name ecpg3; query: "select Item2 from T order by Item2 nulls last" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 30: query: select Item2 from T order by Item2 nulls last; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 30: using PQexecPrepared for "select Item2 from T order by Item2 nulls last" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 30: correctly got 4 tuples with 1 fields [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_get_data on line 30: RESULT: 1 offset: -1; array: yes [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_get_data on line 30: RESULT: 2 offset: -1; array: yes [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_get_data on line 30: RESULT: 2 offset: -1; array: yes [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_get_data on line 30: RESULT: offset: -1; array: yes [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 37: query: declare C cursor for select Item1 from T; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 37: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 37: OK: DECLARE CURSOR [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 39: query: fetch 1 in C; 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: correctly got 1 tuples with 1 fields [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_get_data on line 39: RESULT: 1 offset: -1; array: yes [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 42: query: close C; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 42: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 42: OK: CLOSE CURSOR [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGprepare on line 44: name stmt1; query: "SELECT item2 FROM T ORDER BY item2 NULLS LAST" [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 48: query: declare cur1 cursor for SELECT item2 FROM T ORDER BY item2 NULLS LAST; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 48: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 48: OK: DECLARE CURSOR [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 55: query: fetch cur1; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 55: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 55: correctly got 1 tuples with 1 fields [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_get_data on line 55: RESULT: 1 offset: -1; array: yes [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 55: query: fetch cur1; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 55: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 55: correctly got 1 tuples with 1 fields [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_get_data on line 55: RESULT: 2 offset: -1; array: yes [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 55: query: fetch cur1; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 55: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 55: correctly got 1 tuples with 1 fields [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_get_data on line 55: RESULT: 2 offset: -1; array: yes [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 55: query: fetch cur1; with 0 parameter(s) on connection regress1 [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 55: using PQexec [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 55: correctly got 1 tuples with 1 fields ! [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_get_data on line 55: RESULT: offset: -1; array: yes ! [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 55: query: fetch cur1; with 0 parameter(s) on connection regress1 ! [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 55: using PQexec ! [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 55: correctly got 0 tuples with 1 fields ! [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: raising sqlcode 100 on line 55: no data found on line 55 ! [NO_PID]: sqlca: code: 100, state: 02000 ! [NO_PID]: ecpg_execute on line 60: query: close cur1; with 0 parameter(s) on connection regress1 ! [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 60: using PQexec ! [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 60: OK: CLOSE CURSOR ! [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 62: query: drop table T; with 0 parameter(s) on connection regress1 ! [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 62: using PQexec ! [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ecpg_execute on line 62: OK: DROP TABLE ! [NO_PID]: sqlca: code: 0, state: 00000 ! [NO_PID]: ECPGdeallocate on line 0: name stmt1 [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ECPGdeallocate on line 0: name ecpg3 [NO_PID]: sqlca: code: 0, state: 00000 + [NO_PID]: ECPGdeallocate on line 0: name i + [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ECPGdeallocate on line 0: name ecpg2 [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ECPGdeallocate on line 0: name ecpg1 diff -dcrpN pgsql.4.1/src/interfaces/ecpg/test/expected/preproc-autoprep.stdout pgsql.6/src/interfaces/ecpg/test/expected/preproc-autoprep.stdout *** pgsql.4.1/src/interfaces/ecpg/test/expected/preproc-autoprep.stdout 2007-08-14 12:01:53.000000000 +0200 --- pgsql.6/src/interfaces/ecpg/test/expected/preproc-autoprep.stdout 2009-12-15 13:43:22.000000000 +0100 *************** item[1] = 2 *** 3,5 **** --- 3,9 ---- item[2] = 2 item[3] = -1 i = 1 + item[0] = 1 + item[1] = 2 + item[2] = 2 + item[3] = -1 diff -dcrpN pgsql.4.1/src/interfaces/ecpg/test/preproc/autoprep.pgc pgsql.6/src/interfaces/ecpg/test/preproc/autoprep.pgc *** pgsql.4.1/src/interfaces/ecpg/test/preproc/autoprep.pgc 2009-05-25 12:08:49.000000000 +0200 --- pgsql.6/src/interfaces/ecpg/test/preproc/autoprep.pgc 2009-12-15 13:38:55.000000000 +0100 *************** EXEC SQL INCLUDE ../regression; *** 8,13 **** --- 8,15 ---- int main() { EXEC SQL BEGIN DECLARE SECTION; int item[4], ind[4], i = 1; + int item1, ind1; + char sqlstr[64] = "SELECT item2 FROM T ORDER BY item2 NULLS LAST"; EXEC SQL END DECLARE SECTION; ECPGdebug(1, stderr); *************** int main() { *** 39,44 **** --- 41,64 ---- EXEC SQL CLOSE C; + EXEC SQL PREPARE stmt1 FROM :sqlstr; + + EXEC SQL DECLARE cur1 CURSOR FOR stmt1; + + EXEC SQL OPEN cur1; + + EXEC SQL WHENEVER NOT FOUND DO BREAK; + + i = 0; + while (1) + { + EXEC SQL FETCH cur1 INTO :item1:ind1; + printf("item[%d] = %d\n", i, ind1 ? -1 : item1); + i++; + } + + EXEC SQL CLOSE cur1; + EXEC SQL DROP TABLE T; EXEC SQL DISCONNECT ALL;
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers