diff --git a/src/interfaces/ecpg/preproc/descriptor.c b/src/interfaces/ecpg/preproc/descriptor.c index a29f530327..35d94711d5 100644 --- a/src/interfaces/ecpg/preproc/descriptor.c +++ b/src/interfaces/ecpg/preproc/descriptor.c @@ -121,7 +121,10 @@ drop_descriptor(char *name, char *connection) } } } - mmerror(PARSE_ERROR, ET_WARNING, "descriptor \"%s\" does not exist", name); + if (connection) + mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to connection %s does not exist", name, connection); + else + mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to the default connection does not exist", name); } struct descriptor @@ -141,9 +144,18 @@ lookup_descriptor(char *name, char *connection) || (connection && i->connection && strcmp(connection, i->connection) == 0)) return i; + if (connection && !i->connection) + { + /* overwrite descriptor's connection */ + i->connection = mm_strdup(connection); + return i; + } } } - mmerror(PARSE_ERROR, ET_WARNING, "descriptor \"%s\" does not exist", name); + if (connection) + mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to connection %s does not exist", name, connection); + else + mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to the default connection does not exist", name); return NULL; } diff --git a/src/interfaces/ecpg/preproc/ecpg.addons b/src/interfaces/ecpg/preproc/ecpg.addons index b6e3412cef..94f7d4a3ec 100644 --- a/src/interfaces/ecpg/preproc/ecpg.addons +++ b/src/interfaces/ecpg/preproc/ecpg.addons @@ -132,13 +132,15 @@ ECPG: stmtViewStmt rule } | ECPGDescribe { - fprintf(base_yyout, "{ ECPGdescribe(__LINE__, %d, %s,", compat, $1); + check_declared_list($1.stmt_name); + + fprintf(base_yyout, "{ ECPGdescribe(__LINE__, %d, %d, %s, %s,", compat, $1.input, connection ? connection : "NULL", $1.stmt_name); dump_variables(argsresult, 1); fputs("ECPGt_EORT);", base_yyout); fprintf(base_yyout, "}"); output_line_number(); - free($1); + free($1.stmt_name); } | ECPGDisconnect { @@ -397,7 +399,7 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt this->next = cur; this->name = $2; this->function = (current_function ? mm_strdup(current_function) : NULL); - this->connection = connection; + this->connection = connection ? mm_strdup(connection) : NULL; this->opened = false; this->command = cat_str(7, mm_strdup("declare"), cursor_marker, $3, mm_strdup("cursor"), $5, mm_strdup("for"), $7); this->argsinsert = argsinsert; diff --git a/src/interfaces/ecpg/preproc/ecpg.header b/src/interfaces/ecpg/preproc/ecpg.header index 5263df2b6e..067c9cf8e7 100644 --- a/src/interfaces/ecpg/preproc/ecpg.header +++ b/src/interfaces/ecpg/preproc/ecpg.header @@ -590,13 +590,14 @@ check_declared_list(const char *name) struct declared_list *ptr = NULL; for (ptr = g_declared_list; ptr != NULL; ptr = ptr -> next) { + if (!ptr->connection) + continue; if (strcmp(name, ptr -> name) == 0) { - if (ptr -> connection) - { - connection = mm_strdup(ptr -> connection); - return true; - } + if (connection) + mmerror(PARSE_ERROR, ET_WARNING, "connection %s is overwritten to %s.", connection, ptr->connection); + connection = mm_strdup(ptr -> connection); + return true; } } return false; @@ -621,4 +622,5 @@ check_declared_list(const char *name) struct su_symbol struct_union; struct prep prep; struct exec exec; + struct describe describe; } diff --git a/src/interfaces/ecpg/preproc/ecpg.trailer b/src/interfaces/ecpg/preproc/ecpg.trailer index 96c55349e8..daf979a8e8 100644 --- a/src/interfaces/ecpg/preproc/ecpg.trailer +++ b/src/interfaces/ecpg/preproc/ecpg.trailer @@ -4,8 +4,18 @@ statements: /*EMPTY*/ | statements statement ; -statement: ecpgstart at toplevel_stmt ';' { connection = NULL; } +statement: ecpgstart at toplevel_stmt ';' + { + if (connection) + free(connection); + connection = NULL; + } | ecpgstart toplevel_stmt ';' + { + if (connection) + free(connection); + connection = NULL; + } | ecpgstart ECPGVarDeclaration { fprintf(base_yyout, "%s", $2); @@ -1101,41 +1111,33 @@ UsingConst: Iconst { $$ = $1; } */ ECPGDescribe: SQL_DESCRIBE INPUT_P prepared_name using_descriptor { - const char *con = connection ? connection : "NULL"; - mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement"); - $$ = (char *) mm_alloc(sizeof("1, , ") + strlen(con) + strlen($3)); - sprintf($$, "1, %s, %s", con, $3); + $$.input = 1; + $$.stmt_name = $3; } | SQL_DESCRIBE opt_output prepared_name using_descriptor { - const char *con = connection ? connection : "NULL"; struct variable *var; - var = argsinsert->variable; remove_variable_from_list(&argsinsert, var); add_variable_to_head(&argsresult, var, &no_indicator); - $$ = (char *) mm_alloc(sizeof("0, , ") + strlen(con) + strlen($3)); - sprintf($$, "0, %s, %s", con, $3); + $$.input = 0; + $$.stmt_name = $3; } | SQL_DESCRIBE opt_output prepared_name into_descriptor { - const char *con = connection ? connection : "NULL"; - $$ = (char *) mm_alloc(sizeof("0, , ") + strlen(con) + strlen($3)); - sprintf($$, "0, %s, %s", con, $3); + $$.input = 0; + $$.stmt_name = $3; } | SQL_DESCRIBE INPUT_P prepared_name into_sqlda { - const char *con = connection ? connection : "NULL"; - mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement"); - $$ = (char *) mm_alloc(sizeof("1, , ") + strlen(con) + strlen($3)); - sprintf($$, "1, %s, %s", con, $3); + $$.input = 1; + $$.stmt_name = $3; } | SQL_DESCRIBE opt_output prepared_name into_sqlda { - const char *con = connection ? connection : "NULL"; - $$ = (char *) mm_alloc(sizeof("0, , ") + strlen(con) + strlen($3)); - sprintf($$, "0, %s, %s", con, $3); + $$.input = 0; + $$.stmt_name = $3; } ; @@ -1862,8 +1864,8 @@ c_anything: ecpg_ident { $$ = $1; } | ':' { $$ = mm_strdup(":"); } ; -DeallocateStmt: DEALLOCATE prepared_name { $$ = $2; } - | DEALLOCATE PREPARE prepared_name { $$ = $3; } +DeallocateStmt: DEALLOCATE prepared_name { check_declared_list($2); $$ = $2; } + | DEALLOCATE PREPARE prepared_name { check_declared_list($3); $$ = $3; } | DEALLOCATE ALL { $$ = mm_strdup("all"); } | DEALLOCATE PREPARE ALL { $$ = mm_strdup("all"); } ; diff --git a/src/interfaces/ecpg/preproc/ecpg.type b/src/interfaces/ecpg/preproc/ecpg.type index e8c36119ed..e4b77fa065 100644 --- a/src/interfaces/ecpg/preproc/ecpg.type +++ b/src/interfaces/ecpg/preproc/ecpg.type @@ -10,7 +10,6 @@ %type ECPGDeclaration %type ECPGDeclare %type ECPGDeclareStmt -%type ECPGDescribe %type ECPGDisconnect %type ECPGExecuteImmediateStmt %type ECPGFree @@ -143,3 +142,5 @@ %type var_type %type action + +%type ECPGDescribe \ No newline at end of file diff --git a/src/interfaces/ecpg/preproc/output.c b/src/interfaces/ecpg/preproc/output.c index 65d06d5794..cf8aadd0b1 100644 --- a/src/interfaces/ecpg/preproc/output.c +++ b/src/interfaces/ecpg/preproc/output.c @@ -164,9 +164,6 @@ output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st) whenever_action(whenever_mode | 2); free(stmt); - if (connection != NULL) - free(connection); - connection = NULL; } void @@ -179,9 +176,6 @@ output_prepare_statement(char *name, char *stmt) fputs(");", base_yyout); whenever_action(2); free(name); - if (connection != NULL) - free(connection); - connection = NULL; } void @@ -200,9 +194,6 @@ output_deallocate_prepare_statement(char *name) whenever_action(2); free(name); - if (connection != NULL) - free(connection); - connection = NULL; } static void diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h index 01ccb74fdc..fb20be53e0 100644 --- a/src/interfaces/ecpg/preproc/type.h +++ b/src/interfaces/ecpg/preproc/type.h @@ -207,4 +207,10 @@ struct fetch_desc char *name; }; +struct describe +{ + int input; + char *stmt_name; +}; + #endif /* _ECPG_PREPROC_TYPE_H */ diff --git a/src/interfaces/ecpg/test/expected/sql-declare.c b/src/interfaces/ecpg/test/expected/sql-declare.c index 7ca540df28..cff928204e 100644 --- a/src/interfaces/ecpg/test/expected/sql-declare.c +++ b/src/interfaces/ecpg/test/expected/sql-declare.c @@ -97,7 +97,7 @@ struct sqlca_t *ECPGget_sqlca(void); #line 8 "declare.pgc" -#define ARRAY_SZIE 20 +#define ARRAY_SIZE 2 void execute_test(void); void commitTable(void); @@ -110,13 +110,13 @@ void printResult(char *tc_name, int loop); #line 18 "declare.pgc" - int f1 [ ARRAY_SZIE ] ; + int f1 [ ARRAY_SIZE ] ; #line 19 "declare.pgc" - int f2 [ ARRAY_SZIE ] ; + int f2 [ ARRAY_SIZE ] ; #line 20 "declare.pgc" - char f3 [ ARRAY_SZIE ] [ 20 ] ; + char f3 [ ARRAY_SIZE ] [ 20 ] ; /* exec sql end declare section */ #line 21 "declare.pgc" @@ -216,11 +216,11 @@ if (sqlca.sqlcode < 0) sqlprint();} void execute_test(void) { /* exec sql begin declare section */ - + #line 63 "declare.pgc" - int i ; + int i , count , length ; #line 64 "declare.pgc" char * selectString = "SELECT f1,f2,f3 FROM source" ; @@ -353,7 +353,7 @@ if (sqlca.sqlcode < 0) sqlprint();} if (sqlca.sqlcode < 0) sqlprint();} #line 110 "declare.pgc" - { ECPGdeallocate(__LINE__, 0, NULL, "stmt_2"); + { ECPGdeallocate(__LINE__, 0, "con1", "stmt_2"); #line 111 "declare.pgc" if (sqlca.sqlcode < 0) sqlprint();} @@ -421,7 +421,7 @@ if (sqlca.sqlcode < 0) sqlprint();} if (sqlca.sqlcode < 0) sqlprint();} #line 134 "declare.pgc" - { ECPGdeallocate(__LINE__, 0, "con2", "stmt_3"); + { ECPGdeallocate(__LINE__, 0, "con1", "stmt_3"); #line 135 "declare.pgc" if (sqlca.sqlcode < 0) sqlprint();} @@ -518,11 +518,11 @@ if (sqlca.sqlcode < 0) sqlprint();} #line 172 "declare.pgc" { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_execute, "stmt_5", ECPGt_EOIT, - ECPGt_int,(f1),(long)1,(long)ARRAY_SZIE,sizeof(int), + ECPGt_int,(f1),(long)1,(long)ARRAY_SIZE,sizeof(int), ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, - ECPGt_int,(f2),(long)1,(long)ARRAY_SZIE,sizeof(int), + ECPGt_int,(f2),(long)1,(long)ARRAY_SIZE,sizeof(int), ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, - ECPGt_char,(f3),(long)20,(long)ARRAY_SZIE,(20)*sizeof(char), + ECPGt_char,(f3),(long)20,(long)ARRAY_SIZE,(20)*sizeof(char), ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); #line 173 "declare.pgc" @@ -538,21 +538,128 @@ if (sqlca.sqlcode < 0) sqlprint();} printResult("testcase5", 2); + + /* + * DESCRIBE statement is also supported. + */ + /* declare \"stmt_desc\" as an SQL identifier */ +#line 182 "declare.pgc" + + { ECPGprepare(__LINE__, "con1", 0, "stmt_desc", selectString); +#line 183 "declare.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 183 "declare.pgc" + + /* declare cur_desc cursor for $1 */ +#line 184 "declare.pgc" + + { ECPGdo(__LINE__, 0, 1, "con1", 0, ECPGst_normal, "declare cur_desc cursor for $1", + ECPGt_char_variable,(ECPGprepared_statement("con1", "stmt_desc", __LINE__)),(long)1,(long)1,(1)*sizeof(char), + ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT); +#line 185 "declare.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 185 "declare.pgc" + + + /* descriptor can be used for describe statement */ + ECPGallocate_desc(__LINE__, "desc_for_describe"); +#line 188 "declare.pgc" + +if (sqlca.sqlcode < 0) sqlprint(); +#line 188 "declare.pgc" + + { ECPGdescribe(__LINE__, 0, 0, "con1", "stmt_desc", + ECPGt_descriptor, "desc_for_describe", 1L, 1L, 1L, + ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);} +#line 189 "declare.pgc" + + + { ECPGget_desc_header(__LINE__, "desc_for_describe", &(count)); + +#line 191 "declare.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 191 "declare.pgc" + + { ECPGget_desc(__LINE__, "desc_for_describe", 3,ECPGd_length, + ECPGt_int,&(length),(long)1,(long)1,sizeof(int), ECPGd_EODT); + +#line 192 "declare.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 192 "declare.pgc" + + + ECPGdeallocate_desc(__LINE__, "desc_for_describe"); +#line 194 "declare.pgc" + +if (sqlca.sqlcode < 0) sqlprint(); +#line 194 "declare.pgc" + + + /* for fetch statement */ + ECPGallocate_desc(__LINE__, "desc_for_fetch"); +#line 197 "declare.pgc" + +if (sqlca.sqlcode < 0) sqlprint(); +#line 197 "declare.pgc" + + { ECPGdo(__LINE__, 0, 1, "con1", 0, ECPGst_normal, "fetch cur_desc", ECPGt_EOIT, + ECPGt_descriptor, "desc_for_fetch", 1L, 1L, 1L, + ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); +#line 198 "declare.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 198 "declare.pgc" + + + { ECPGget_desc(__LINE__, "desc_for_fetch", 3,ECPGd_data, + ECPGt_char,(f3[0]),(long)20,(long)1,(20)*sizeof(char), ECPGd_EODT); + +#line 200 "declare.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 200 "declare.pgc" + + + ECPGdeallocate_desc(__LINE__, "desc_for_fetch"); +#line 202 "declare.pgc" + +if (sqlca.sqlcode < 0) sqlprint(); +#line 202 "declare.pgc" + + { ECPGdo(__LINE__, 0, 1, "con1", 0, ECPGst_normal, "close cur_desc", ECPGt_EOIT, ECPGt_EORT); +#line 203 "declare.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 203 "declare.pgc" + + { ECPGdeallocate(__LINE__, 0, "con1", "stmt_desc"); +#line 204 "declare.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 204 "declare.pgc" + + + printf("****descriptor results****\n"); + printf("count: %d, length: %d, data: %s\n", count, length, f3[0]); } void commitTable() { { ECPGtrans(__LINE__, "con1", "commit"); -#line 182 "declare.pgc" +#line 212 "declare.pgc" if (sqlca.sqlcode < 0) sqlprint();} -#line 182 "declare.pgc" +#line 212 "declare.pgc" { ECPGtrans(__LINE__, "con2", "commit"); -#line 183 "declare.pgc" +#line 213 "declare.pgc" if (sqlca.sqlcode < 0) sqlprint();} -#line 183 "declare.pgc" +#line 213 "declare.pgc" } diff --git a/src/interfaces/ecpg/test/expected/sql-declare.stderr b/src/interfaces/ecpg/test/expected/sql-declare.stderr index 71aa21ece4..29d0b828e7 100644 --- a/src/interfaces/ecpg/test/expected/sql-declare.stderr +++ b/src/interfaces/ecpg/test/expected/sql-declare.stderr @@ -40,9 +40,9 @@ [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_process_output on line 39: OK: INSERT 0 1 [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGtrans on line 182: action "commit"; connection "con1" +[NO_PID]: ECPGtrans on line 212: action "commit"; connection "con1" [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGtrans on line 183: action "commit"; connection "con2" +[NO_PID]: ECPGtrans on line 213: action "commit"; connection "con2" [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: prepare_common on line 74: name stmt_1; query: "SELECT f1,f2,f3 FROM source" [NO_PID]: sqlca: code: 0, state: 00000 @@ -138,9 +138,8 @@ [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_process_output on line 110: OK: CLOSE CURSOR [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: raising sqlcode -230 on line 111: invalid statement name "stmt_2" on line 111 -[NO_PID]: sqlca: code: -230, state: 26000 -SQL error: invalid statement name "stmt_2" on line 111 +[NO_PID]: deallocate_one on line 111: name stmt_2 +[NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: prepare_common on line 123: name stmt_3; query: "SELECT f1,f2,f3 FROM source" [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_execute on line 125: query: declare cur_3 cursor for SELECT f1,f2,f3 FROM source; with 0 parameter(s) on connection con1 @@ -187,9 +186,8 @@ SQL error: invalid statement name "stmt_2" on line 111 [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_process_output on line 134: OK: CLOSE CURSOR [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: raising sqlcode -230 on line 135: invalid statement name "stmt_3" on line 135 -[NO_PID]: sqlca: code: -230, state: 26000 -SQL error: invalid statement name "stmt_3" on line 135 +[NO_PID]: deallocate_one on line 135: name stmt_3 +[NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: prepare_common on line 148: name stmt_4; query: "SELECT f1,f2,f3 FROM source" [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_execute on line 150: query: declare cur_4 cursor for SELECT f1,f2,f3 FROM source; with 0 parameter(s) on connection con2 @@ -260,6 +258,40 @@ SQL error: invalid statement name "stmt_3" on line 135 [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: deallocate_one on line 175: name stmt_5 [NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: prepare_common on line 183: name stmt_desc; query: "SELECT f1,f2,f3 FROM source" +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 185: query: declare cur_desc cursor for SELECT f1,f2,f3 FROM source; with 0 parameter(s) on connection con1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 185: using PQexec +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_process_output on line 185: OK: DECLARE CURSOR +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGget_desc_header: found 3 attributes +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGget_desc: reading items for tuple 3 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGget_desc: LENGTH = 20 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 198: query: fetch cur_desc; with 0 parameter(s) on connection con1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 198: using PQexec +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_process_output on line 198: correctly got 1 tuples with 3 fields +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_process_output on line 198: putting result (1 tuples) into descriptor desc_for_fetch +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGget_desc: reading items for tuple 3 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_get_data on line 200: RESULT: db on con1 offset: -1; array: no +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 203: query: close cur_desc; with 0 parameter(s) on connection con1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_execute on line 203: using PQexec +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_process_output on line 203: OK: CLOSE CURSOR +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: deallocate_one on line 204: name stmt_desc +[NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_execute on line 45: query: drop table if exists source; with 0 parameter(s) on connection con1 [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_execute on line 45: using PQexec @@ -272,15 +304,11 @@ SQL error: invalid statement name "stmt_3" on line 135 [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_process_output on line 46: OK: DROP TABLE [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGtrans on line 182: action "commit"; connection "con1" +[NO_PID]: ECPGtrans on line 212: action "commit"; connection "con1" [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGtrans on line 183: action "commit"; connection "con2" +[NO_PID]: ECPGtrans on line 213: action "commit"; connection "con2" [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: connection con2 closed [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: deallocate_one on line 0: name stmt_3 -[NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: deallocate_one on line 0: name stmt_2 -[NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: connection con1 closed [NO_PID]: sqlca: code: 0, state: 00000 diff --git a/src/interfaces/ecpg/test/expected/sql-declare.stdout b/src/interfaces/ecpg/test/expected/sql-declare.stdout index 3352d47cc4..d32ba4b6a4 100644 --- a/src/interfaces/ecpg/test/expected/sql-declare.stdout +++ b/src/interfaces/ecpg/test/expected/sql-declare.stdout @@ -18,3 +18,5 @@ f1=2, f2=20, f3=db on con2 f1=1, f2=10, f3=db on con2 f1=2, f2=20, f3=db on con2 +****descriptor results**** +count: 3, length: 20, data: db on con1 diff --git a/src/interfaces/ecpg/test/sql/declare.pgc b/src/interfaces/ecpg/test/sql/declare.pgc index f9ef468741..b6a0723dd4 100644 --- a/src/interfaces/ecpg/test/sql/declare.pgc +++ b/src/interfaces/ecpg/test/sql/declare.pgc @@ -7,7 +7,7 @@ EXEC SQL WHENEVER SQLERROR SQLPRINT; EXEC SQL INCLUDE sqlca; EXEC SQL INCLUDE ../regression; -#define ARRAY_SZIE 20 +#define ARRAY_SIZE 2 void execute_test(void); void commitTable(void); @@ -15,9 +15,9 @@ void reset(void); void printResult(char *tc_name, int loop); EXEC SQL BEGIN DECLARE SECTION; -int f1[ARRAY_SZIE]; -int f2[ARRAY_SZIE]; -char f3[ARRAY_SZIE][20]; +int f1[ARRAY_SIZE]; +int f2[ARRAY_SIZE]; +char f3[ARRAY_SIZE][20]; EXEC SQL END DECLARE SECTION; int main(void) @@ -60,7 +60,7 @@ int main(void) void execute_test(void) { EXEC SQL BEGIN DECLARE SECTION; - int i; + int i, count, length; char *selectString = "SELECT f1,f2,f3 FROM source"; EXEC SQL END DECLARE SECTION; @@ -175,6 +175,36 @@ void execute_test(void) EXEC SQL DEALLOCATE PREPARE stmt_5; printResult("testcase5", 2); + + /* + * DESCRIBE statement is also supported. + */ + EXEC SQL AT con1 DECLARE stmt_desc STATEMENT; + EXEC SQL PREPARE stmt_desc FROM :selectString; + EXEC SQL DECLARE cur_desc CURSOR FOR stmt_desc; + EXEC SQL OPEN cur_desc; + + /* descriptor can be used for describe statement */ + EXEC SQL AT con1 ALLOCATE DESCRIPTOR desc_for_describe; + EXEC SQL DESCRIBE stmt_desc INTO SQL DESCRIPTOR desc_for_describe; + + EXEC SQL AT con1 GET DESCRIPTOR desc_for_describe :count = COUNT; + EXEC SQL AT con1 GET DESCRIPTOR desc_for_describe VALUE 3 :length = LENGTH; + + EXEC SQL AT con1 DEALLOCATE DESCRIPTOR desc_for_describe; + + /* for fetch statement */ + EXEC SQL AT con1 ALLOCATE DESCRIPTOR desc_for_fetch; + EXEC SQL FETCH cur_desc INTO SQL DESCRIPTOR desc_for_fetch; + + EXEC SQL AT con1 GET DESCRIPTOR desc_for_fetch VALUE 3 :f3[0] = DATA; + + EXEC SQL AT con1 DEALLOCATE DESCRIPTOR desc_for_fetch; + EXEC SQL CLOSE cur_desc; + EXEC SQL DEALLOCATE stmt_desc; + + printf("****descriptor results****\n"); + printf("count: %d, length: %d, data: %s\n", count, length, f3[0]); } void commitTable()