Fix connection handling for DEALLOCATE and DESCRIBE statements

After binding a statement to a connection with DECLARE STATEMENT the connection
was still not used for DEALLOCATE and DESCRIBE statements. This patch fixes
that, adds a missing warning and cleans up the code.

Author: Hayato Kuroda
Reviewed-by: Kyotaro Horiguchi, Michael Paquier
Discussion: https://postgr.es/m/TYAPR01MB5866BA57688DF2770E2F95C6F5069%40TYAPR01MB5866.jpnprd01.prod.outlook.com
This commit is contained in:
Michael Meskes 2021-08-13 10:34:04 +02:00
parent ffff00a355
commit a945f55273
11 changed files with 258 additions and 75 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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"); }
;

View File

@ -10,7 +10,6 @@
%type <str> ECPGDeclaration
%type <str> ECPGDeclare
%type <str> ECPGDeclareStmt
%type <str> ECPGDescribe
%type <str> ECPGDisconnect
%type <str> ECPGExecuteImmediateStmt
%type <str> ECPGFree
@ -143,3 +142,5 @@
%type <type> var_type
%type <action> action
%type <describe> ECPGDescribe

View File

@ -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

View File

@ -207,4 +207,10 @@ struct fetch_desc
char *name;
};
struct describe
{
int input;
char *stmt_name;
};
#endif /* _ECPG_PREPROC_TYPE_H */

View File

@ -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"
}

View File

@ -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

View File

@ -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

View File

@ -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()