diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index 888dd73bc84..e6d8a0098e0 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -1834,6 +1834,13 @@ Wed Jun 30 16:56:32 CEST 2004 Sun Jul 4 16:53:53 CEST 2004 - Made sure SET DESCRIPTOR accepts all data types including constants. + - Some code cleanup. + +Mon, 5 Jul 2004 10:41:54 +0200 + + - Fixed indicator in SET DESCRIPTOR. + - Added special handling of descriptor header information. + - More code cleanup. - Set pgtypes library version to 1.2. - Set ecpg version to 3.2.0. - Set compat library version to 1.2. diff --git a/src/interfaces/ecpg/ecpglib/descriptor.c b/src/interfaces/ecpg/ecpglib/descriptor.c index e653203f89b..bc56b0222bc 100644 --- a/src/interfaces/ecpg/ecpglib/descriptor.c +++ b/src/interfaces/ecpg/ecpglib/descriptor.c @@ -1,6 +1,6 @@ /* dynamic SQL support routines * - * $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.10 2004/07/04 15:02:22 meskes Exp $ + * $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.11 2004/07/05 09:45:53 meskes Exp $ */ #define POSTGRES_ECPG_INTERNAL @@ -430,6 +430,27 @@ ECPGget_desc(int lineno, char *desc_name, int index,...) return (true); } +bool +ECPGset_desc_header(int lineno, char *desc_name, int count) +{ + struct descriptor *desc; + + for (desc = all_descriptors; desc; desc = desc->next) + { + if (strcmp(desc_name, desc->name)==0) + break; + } + + if (desc == NULL) + { + ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, desc_name); + return false; + } + + desc->count = count; + return true; +} + bool ECPGset_desc(int lineno, char *desc_name, int index,...) { @@ -581,6 +602,7 @@ ECPGallocate_desc(int line, const char *name) ECPGfree(new); return false; } + new->count = -1; new->items = NULL; new->result = PQmakeEmptyPGresult(NULL, 0); if (!new->result) diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c index 6464ecb4b32..a3a601aed52 100644 --- a/src/interfaces/ecpg/ecpglib/execute.c +++ b/src/interfaces/ecpg/ecpglib/execute.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.36 2004/07/04 15:02:22 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.37 2004/07/05 09:45:53 meskes Exp $ */ /* * The aim is to get a simpler inteface to the database routines. @@ -1080,6 +1080,7 @@ ECPGexecute(struct statement * stmt) int hostvarl = 0; tobeinserted = NULL; + /* A descriptor is a special case since it contains many variables but is listed only once. */ if (var->type == ECPGt_descriptor) { @@ -1100,28 +1101,43 @@ ECPGexecute(struct statement * stmt) } desc_counter++; - for (desc_item = desc->items; desc_item; desc_item = desc_item->next) + if (desc->count < 0 || desc->count >= desc_counter) { - if (desc_item->num == desc_counter) + for (desc_item = desc->items; desc_item; desc_item = desc_item->next) { - desc_inlist.type = ECPGt_char; - desc_inlist.value = desc_item->data; - desc_inlist.pointer = &(desc_item->data); - desc_inlist.varcharsize = strlen(desc_item->data); - desc_inlist.arrsize = 1; - desc_inlist.offset = 0; - desc_inlist.ind_type = ECPGt_NO_INDICATOR; - desc_inlist.ind_value = desc_inlist.ind_pointer = NULL; - desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0; - - if (!ECPGstore_input(stmt->lineno, stmt->force_indicator, &desc_inlist, &tobeinserted, &malloced)) - return false; - - break; + if (desc_item->num == desc_counter) + { + desc_inlist.type = ECPGt_char; + desc_inlist.value = desc_item->data; + desc_inlist.pointer = &(desc_item->data); + desc_inlist.varcharsize = strlen(desc_item->data); + desc_inlist.arrsize = 1; + desc_inlist.offset = 0; + if (!desc_item->indicator) + { + desc_inlist.ind_type = ECPGt_NO_INDICATOR; + desc_inlist.ind_value = desc_inlist.ind_pointer = NULL; + desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0; + } + else + { + desc_inlist.ind_type = ECPGt_int; + desc_inlist.ind_value = &(desc_item->indicator); + desc_inlist.ind_pointer = &(desc_inlist.ind_value); + desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = 1; + desc_inlist.ind_offset = 0; + } + if (!ECPGstore_input(stmt->lineno, stmt->force_indicator, &desc_inlist, &tobeinserted, &malloced)) + return false; + + break; + } } - } - if (!desc_item) /* no more entries found in descriptor */ + if (!desc_item) /* no more entries found in descriptor */ + desc_counter = 0; + } + else desc_counter = 0; } else @@ -1129,6 +1145,7 @@ ECPGexecute(struct statement * stmt) if (!ECPGstore_input(stmt->lineno, stmt->force_indicator, var, &tobeinserted, &malloced)) return false; } + if (tobeinserted) { /* diff --git a/src/interfaces/ecpg/include/ecpglib.h b/src/interfaces/ecpg/include/ecpglib.h index 778104a27b2..6145e79cb4d 100644 --- a/src/interfaces/ecpg/include/ecpglib.h +++ b/src/interfaces/ecpg/include/ecpglib.h @@ -77,7 +77,7 @@ void ECPGraise(int line, int code, const char *sqlstate, const char *str); void ECPGraise_backend(int line, PGresult *result, PGconn *conn, int compat); bool ECPGget_desc_header(int, char *, int *); bool ECPGget_desc(int, char *, int,...); -bool ECPGset_desc_header(int, char *, int *); +bool ECPGset_desc_header(int, char *, int); bool ECPGset_desc(int, char *, int,...); void ECPGset_noind_null(enum ECPGttype, void *); diff --git a/src/interfaces/ecpg/preproc/descriptor.c b/src/interfaces/ecpg/preproc/descriptor.c index 6861a91dc7f..43193364b47 100644 --- a/src/interfaces/ecpg/preproc/descriptor.c +++ b/src/interfaces/ecpg/preproc/descriptor.c @@ -55,6 +55,7 @@ ECPGnumeric_lvalue(FILE *f, char *name) case ECPGt_unsigned_int: case ECPGt_unsigned_long: case ECPGt_unsigned_long_long: + case ECPGt_const: fputs(name, yyout); break; default: @@ -198,7 +199,7 @@ output_set_descr_header(char *desc_name) { struct assignment *results; - fprintf(yyout, "{ ECPGset_desc_header(__LINE__, %s, &(", desc_name); + fprintf(yyout, "{ ECPGset_desc_header(__LINE__, %s, (int)(", desc_name); for (results = assignments; results != NULL; results = results->next) { if (results->value == ECPGd_count) diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index e1dab2b72e8..3c10072f686 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.291 2004/07/04 15:02:23 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.292 2004/07/05 09:45:53 meskes Exp $ */ /* Copyright comment */ %{ @@ -522,7 +522,7 @@ add_additional_variables(char *name, bool insert) %type select_limit opt_for_update_clause CheckPointStmt %type OptSchemaName OptSchemaEltList schema_stmt opt_drop_behavior %type handler_name any_name_list any_name opt_as insert_column_list -%type columnref function_name insert_target_el +%type columnref function_name insert_target_el AllConstVar %type insert_target_list insert_column_item DropRuleStmt %type createfunc_opt_item set_rest var_list_or_default %type CreateFunctionStmt createfunc_opt_list func_table @@ -4207,7 +4207,7 @@ IntConst: PosIntConst { $$ = $1; } IntConstVar: Iconst { char *length = mm_alloc(32); - + sprintf(length, "%d", (int) strlen($1)); new_variable($1, ECPGmake_simple_type(ECPGt_const, length), 0); $$ = $1; @@ -4215,6 +4215,45 @@ IntConstVar: Iconst | cvariable { $$ = $1; } ; +AllConstVar: Fconst + { + char *length = mm_alloc(32); + + sprintf(length, "%d", (int) strlen($1)); + new_variable($1, ECPGmake_simple_type(ECPGt_const, length), 0); + $$ = $1; + } + | IntConstVar { $$ = $1; } + | '-' Fconst + { + char *length = mm_alloc(32); + char *var = cat2_str(make_str("-"), $2); + + sprintf(length, "%d", (int) strlen(var)); + new_variable(var, ECPGmake_simple_type(ECPGt_const, length), 0); + $$ = var; + } + | '-' Iconst + { + char *length = mm_alloc(32); + char *var = cat2_str(make_str("-"), $2); + + sprintf(length, "%d", (int) strlen(var)); + new_variable(var, ECPGmake_simple_type(ECPGt_const, length), 0); + $$ = var; + } + | Sconst + { + char *length = mm_alloc(32); + char *var = $1 + 1; + + var[strlen(var) - 1] = '\0'; + sprintf(length, "%d", (int) strlen(var)); + new_variable(var, ECPGmake_simple_type(ECPGt_const, length), 0); + $$ = var; + } + ; + StringConst: Sconst { $$ = $1; } | civar { $$ = $1; } ; @@ -5375,7 +5414,7 @@ ECPGSetDescItems: ECPGSetDescItem | ECPGSetDescItems ',' ECPGSetDescItem ; -ECPGSetDescItem: descriptor_item '=' IntConstVar +ECPGSetDescItem: descriptor_item '=' AllConstVar { push_assignment($3, $1); } diff --git a/src/interfaces/ecpg/test/test_desc.pgc b/src/interfaces/ecpg/test/test_desc.pgc index aee30bc59f3..7d4854cfdf2 100644 --- a/src/interfaces/ecpg/test/test_desc.pgc +++ b/src/interfaces/ecpg/test/test_desc.pgc @@ -6,11 +6,12 @@ main() EXEC SQL BEGIN DECLARE SECTION; char *stmt1 = "INSERT INTO test1 VALUES (?, ?)"; char *stmt2 = "SELECT * from test1 where a = ? and b = ?"; + char *stmt3 = "SELECT * from test1 where a = ?"; int val1 = 1; char val2[] = "one", val2output[] = "AAA"; int val1output = 2, val2i = 0; - int val2null = 1; + int val2null = -1; EXEC SQL END DECLARE SECTION; FILE *dbgs; @@ -28,6 +29,7 @@ main() EXEC SQL CREATE TABLE test1 (a int, b text); EXEC SQL PREPARE foo1 FROM :stmt1; EXEC SQL PREPARE foo2 FROM :stmt2; + EXEC SQL PREPARE foo3 FROM :stmt3; EXEC SQL EXECUTE foo1 USING DESCRIPTOR indesc; @@ -44,16 +46,27 @@ main() EXEC SQL GET DESCRIPTOR outdesc VALUE 1 :val2output = DATA; printf("output = %s\n", val2output); - EXEC SQL DECLARE c CURSOR FOR foo2; - EXEC SQL OPEN c USING DESCRIPTOR indesc; + EXEC SQL DECLARE c1 CURSOR FOR foo2; + EXEC SQL OPEN c1 USING DESCRIPTOR indesc; - EXEC SQL FETCH next FROM c INTO :val1output, :val2output; + EXEC SQL FETCH next FROM c1 INTO :val1output, :val2output; printf("val1=%d val2=%s\n", val1output, val2output); - EXEC SQL CLOSE c; + EXEC SQL CLOSE c1; + + EXEC SQL SET DESCRIPTOR indesc COUNT = 1; + EXEC SQL SET DESCRIPTOR indesc VALUE 1 DATA = 2; - EXEC SQL SELECT * INTO :val1output, :val2output FROM test1 where a = 2; - printf("val1=%d val2=%s\n", val1output, val2output); + EXEC SQL DECLARE c2 CURSOR FOR foo3; + EXEC SQL OPEN c2 USING DESCRIPTOR indesc; + + EXEC SQL FETCH next FROM c2 INTO :val1output, :val2output :val2i; + printf("val1=%d val2=%s\n", val1output, val2i ? "null" : val2output); + + EXEC SQL CLOSE c2; + + EXEC SQL SELECT * INTO :val1output, :val2output :val2i FROM test1 where a = 2; + printf("val1=%d val2=%s\n", val1output, val2i ? "null" : val2output); EXEC SQL DROP TABLE test1; EXEC SQL DISCONNECT;