From aa6ac352215d435b277711f85985d00a07a5c590 Mon Sep 17 00:00:00 2001 From: Michael Meskes Date: Tue, 26 Jan 2010 09:07:32 +0000 Subject: [PATCH] Applied patch by Boszormenyi Zoltan to add out-of-scope cursor support to native mode. --- src/interfaces/ecpg/compatlib/informix.c | 47 +---- src/interfaces/ecpg/ecpglib/exports.txt | 6 +- src/interfaces/ecpg/ecpglib/misc.c | 54 +++++- src/interfaces/ecpg/include/ecpglib.h | 5 +- src/interfaces/ecpg/preproc/descriptor.c | 4 +- src/interfaces/ecpg/preproc/ecpg.addons | 25 +-- src/interfaces/ecpg/preproc/ecpg.c | 6 +- src/interfaces/ecpg/preproc/ecpg.header | 166 +++++++++++++----- src/interfaces/ecpg/preproc/ecpg.trailer | 43 ++++- src/interfaces/ecpg/preproc/extern.h | 5 +- src/interfaces/ecpg/preproc/pgc.l | 23 ++- src/interfaces/ecpg/preproc/type.c | 10 +- src/interfaces/ecpg/preproc/type.h | 8 +- src/interfaces/ecpg/preproc/variable.c | 8 +- src/interfaces/ecpg/test/ecpg_schedule | 1 + src/interfaces/ecpg/test/ecpg_schedule_tcp | 1 + .../expected/compat_informix-test_informix.c | 4 +- .../ecpg/test/expected/preproc-cursor.c | 14 +- .../ecpg/test/expected/sql-binary.c | 9 +- src/interfaces/ecpg/test/preproc/Makefile | 1 + 20 files changed, 298 insertions(+), 142 deletions(-) diff --git a/src/interfaces/ecpg/compatlib/informix.c b/src/interfaces/ecpg/compatlib/informix.c index c4f1f18822..24906ab487 100644 --- a/src/interfaces/ecpg/compatlib/informix.c +++ b/src/interfaces/ecpg/compatlib/informix.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/compatlib/informix.c,v 1.62 2009/10/01 18:03:54 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/compatlib/informix.c,v 1.63 2010/01/26 09:07:31 meskes Exp $ */ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" @@ -1004,57 +1004,16 @@ rtypwidth(int sqltype, int sqllen) return 0; } -static struct var_list -{ - int number; - void *pointer; - struct var_list *next; -} *ivlist = NULL; - void ECPG_informix_set_var(int number, void *pointer, int lineno) { - struct var_list *ptr; - - for (ptr = ivlist; ptr != NULL; ptr = ptr->next) - { - if (ptr->number == number) - { - /* already known => just change pointer value */ - ptr->pointer = pointer; - return; - } - } - - /* a new one has to be added */ - ptr = (struct var_list *) calloc(1L, sizeof(struct var_list)); - if (!ptr) - { - struct sqlca_t *sqlca = ECPGget_sqlca(); - - sqlca->sqlcode = ECPG_OUT_OF_MEMORY; - strncpy(sqlca->sqlstate, "YE001", sizeof("YE001")); - snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "out of memory on line %d", lineno); - sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc); - /* free all memory we have allocated for the user */ - ECPGfree_auto_mem(); - } - else - { - ptr->number = number; - ptr->pointer = pointer; - ptr->next = ivlist; - ivlist = ptr; - } + ECPGset_var(number, pointer, lineno); } void * ECPG_informix_get_var(int number) { - struct var_list *ptr; - - for (ptr = ivlist; ptr != NULL && ptr->number != number; ptr = ptr->next); - return (ptr) ? ptr->pointer : NULL; + return ECPGget_var(number); } void diff --git a/src/interfaces/ecpg/ecpglib/exports.txt b/src/interfaces/ecpg/ecpglib/exports.txt index c63994ff11..5b4144a178 100644 --- a/src/interfaces/ecpg/ecpglib/exports.txt +++ b/src/interfaces/ecpg/ecpglib/exports.txt @@ -1,4 +1,4 @@ -# $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/exports.txt,v 1.6 2009/09/18 13:13:32 meskes Exp $ +# $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/exports.txt,v 1.7 2010/01/26 09:07:31 meskes Exp $ # Functions to be exported by ecpglib DLL ECPGallocate_desc 1 ECPGconnect 2 @@ -26,4 +26,6 @@ ECPGstatus 23 ECPGtrans 24 sqlprint 25 ECPGget_PGconn 26 -ECPGtransactionStatus 27 +ECPGtransactionStatus 27 +ECPGset_var 28 +ECPGget_var 29 diff --git a/src/interfaces/ecpg/ecpglib/misc.c b/src/interfaces/ecpg/ecpglib/misc.c index c779cc1a7b..d5f7107440 100644 --- a/src/interfaces/ecpg/ecpglib/misc.c +++ b/src/interfaces/ecpg/ecpglib/misc.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.53 2009/11/24 16:30:31 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.54 2010/01/26 09:07:31 meskes Exp $ */ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" @@ -505,3 +505,55 @@ ecpg_gettext(const char *msgid) } #endif /* ENABLE_NLS */ + +static struct var_list +{ + int number; + void *pointer; + struct var_list *next; +} *ivlist = NULL; + +void +ECPGset_var(int number, void *pointer, int lineno) +{ + struct var_list *ptr; + + for (ptr = ivlist; ptr != NULL; ptr = ptr->next) + { + if (ptr->number == number) + { + /* already known => just change pointer value */ + ptr->pointer = pointer; + return; + } + } + + /* a new one has to be added */ + ptr = (struct var_list *) calloc(1L, sizeof(struct var_list)); + if (!ptr) + { + struct sqlca_t *sqlca = ECPGget_sqlca(); + sqlca->sqlcode = ECPG_OUT_OF_MEMORY; + strncpy(sqlca->sqlstate, "YE001", sizeof("YE001")); + snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc), "out of memory on line %d", lineno); + sqlca->sqlerrm.sqlerrml = strlen(sqlca->sqlerrm.sqlerrmc); + /* free all memory we have allocated for the user */ + ECPGfree_auto_mem(); + } + else + { + ptr->number = number; + ptr->pointer = pointer; + ptr->next = ivlist; + ivlist = ptr; + } +} + +void * +ECPGget_var(int number) +{ + struct var_list *ptr; + + for (ptr = ivlist; ptr != NULL && ptr->number != number; ptr = ptr->next); + return (ptr) ? ptr->pointer : NULL; +} diff --git a/src/interfaces/ecpg/include/ecpglib.h b/src/interfaces/ecpg/include/ecpglib.h index f301de986a..775fe7a6e2 100644 --- a/src/interfaces/ecpg/include/ecpglib.h +++ b/src/interfaces/ecpg/include/ecpglib.h @@ -1,7 +1,7 @@ /* * this is a small part of c.h since we don't want to leak all postgres * definitions into ecpg programs - * $PostgreSQL: pgsql/src/interfaces/ecpg/include/ecpglib.h,v 1.81 2010/01/15 10:44:36 meskes Exp $ + * $PostgreSQL: pgsql/src/interfaces/ecpg/include/ecpglib.h,v 1.82 2010/01/26 09:07:31 meskes Exp $ */ #ifndef _ECPGLIB_H @@ -85,6 +85,9 @@ void ECPGset_noind_null(enum ECPGttype, void *); bool ECPGis_noind_null(enum ECPGttype, void *); bool ECPGdescribe(int, int, bool, const char *, const char *, ...); +void ECPGset_var(int, void *, int); +void *ECPGget_var(int number); + /* dynamic result allocation */ void ECPGfree_auto_mem(void); diff --git a/src/interfaces/ecpg/preproc/descriptor.c b/src/interfaces/ecpg/preproc/descriptor.c index 983c8cf414..6762aa4e0e 100644 --- a/src/interfaces/ecpg/preproc/descriptor.c +++ b/src/interfaces/ecpg/preproc/descriptor.c @@ -1,7 +1,7 @@ /* * functions needed for descriptor handling * - * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/descriptor.c,v 1.29 2010/01/05 16:38:23 meskes Exp $ + * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/descriptor.c,v 1.30 2010/01/26 09:07:31 meskes Exp $ * * since descriptor might be either a string constant or a string var * we need to check for a constant if we expect a constant @@ -317,7 +317,7 @@ struct variable * descriptor_variable(const char *name, int input) { static char descriptor_names[2][MAX_DESCRIPTOR_NAMELEN]; - static const struct ECPGtype descriptor_type = {ECPGt_descriptor, NULL, NULL, {NULL}, 0}; + static const struct ECPGtype descriptor_type = {ECPGt_descriptor, NULL, NULL, NULL, {NULL}, 0}; static const struct variable varspace[2] = { {descriptor_names[0], (struct ECPGtype *) & descriptor_type, 0, NULL}, {descriptor_names[1], (struct ECPGtype *) & descriptor_type, 0, NULL} diff --git a/src/interfaces/ecpg/preproc/ecpg.addons b/src/interfaces/ecpg/preproc/ecpg.addons index 2838267991..6c5889ec6b 100644 --- a/src/interfaces/ecpg/preproc/ecpg.addons +++ b/src/interfaces/ecpg/preproc/ecpg.addons @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.addons,v 1.14 2010/01/15 10:44:37 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.addons,v 1.15 2010/01/26 09:07:31 meskes Exp $ */ ECPG: stmtClosePortalStmt block { if (INFORMIX_MODE) @@ -310,11 +310,14 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt this->next = cur; this->name = $2; + this->function = (current_function ? mm_strdup(current_function) : NULL); this->connection = connection; this->opened = false; this->command = cat_str(7, make_str("declare"), cursor_marker, $3, make_str("cursor"), $5, make_str("for"), $7); this->argsinsert = argsinsert; + this->argsinsert_oos = NULL; this->argsresult = argsresult; + this->argsresult_oos = NULL; argsinsert = argsresult = NULL; cur = this; @@ -327,17 +330,17 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt } comment = cat_str(3, make_str("/*"), c1, make_str("*/")); - if (INFORMIX_MODE) - { - if (braces_open > 0) /* we're in a function */ - { - $$ = cat_str(4, adjust_informix(this->argsinsert), adjust_informix(this->argsresult), make_str("ECPG_informix_reset_sqlca();"), comment); - } - else - $$ = cat_str(3, adjust_informix(this->argsinsert), adjust_informix(this->argsresult), comment); - } + 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 - $$ = comment; + $$ = cat_str(3, + adjust_outofscope_cursor_vars(this, true), + adjust_outofscope_cursor_vars(this, false), + comment); } ECPG: ClosePortalStmtCLOSEcursor_name block { diff --git a/src/interfaces/ecpg/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c index 060d060332..25ba08e519 100644 --- a/src/interfaces/ecpg/preproc/ecpg.c +++ b/src/interfaces/ecpg/preproc/ecpg.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.112 2010/01/02 16:58:11 momjian Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.113 2010/01/26 09:07:31 meskes Exp $ */ /* Main for ecpg, the PostgreSQL embedded SQL precompiler. */ /* Copyright (c) 1996-2010, PostgreSQL Global Development Group */ @@ -419,8 +419,8 @@ main(int argc, char *const argv[]) /* and structure member lists */ memset(struct_member_list, 0, sizeof(struct_member_list)); - /* and our variable counter for Informix compatibility */ - ecpg_informix_var = 0; + /* and our variable counter for out of scope cursors' variables */ + ecpg_internal_var = 0; /* finally the actual connection */ connection = NULL; diff --git a/src/interfaces/ecpg/preproc/ecpg.header b/src/interfaces/ecpg/preproc/ecpg.header index fbf0bd05b5..f60105560c 100644 --- a/src/interfaces/ecpg/preproc/ecpg.header +++ b/src/interfaces/ecpg/preproc/ecpg.header @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.header,v 1.10 2009/11/05 23:24:27 tgl Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.header,v 1.11 2010/01/26 09:07:31 meskes Exp $ */ /* Copyright comment */ %{ @@ -33,7 +33,8 @@ */ int struct_level = 0; int braces_open; /* brace level counter */ -int ecpg_informix_var = 0; +char *current_function; +int ecpg_internal_var = 0; char *connection = NULL; char *input_filename = NULL; @@ -53,10 +54,10 @@ static char *ECPGstruct_sizeof = NULL; /* for forward declarations we have to store some data as well */ static char *forward_name = NULL; -struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, NULL, NULL, {NULL}, 0}; +struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, NULL, NULL, NULL, {NULL}, 0}; struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL}; -struct ECPGtype ecpg_query = {ECPGt_char_variable, NULL, NULL, {NULL}, 0}; +struct ECPGtype ecpg_query = {ECPGt_char_variable, NULL, NULL, NULL, {NULL}, 0}; /* * Handle parsing errors and warnings @@ -226,76 +227,153 @@ create_questionmarks(char *name, bool array) } static char * -adjust_informix(struct arguments *list) +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 variables in a function, and then subsequently use them - * { - * declare_vars(); - * exec sql ... which uses vars declared in the above function + * For instance you can DECLARE a cursor in one function, and OPEN/FETCH/CLOSE + * it in other functions. This is very useful for e.g. event-driver programming, + * but may also lead to dangerous programming. The limitation when this is allowed + * and doesn's cause problems have to be documented, like the allocated variables + * must not be realloc()'ed. * - * This breaks standard and leads to some very dangerous programming. - * Since they do, we have to work around and accept their syntax as well. - * But we will do so ONLY in Informix mode. - * We have to change the variables to our own struct and just store the pointer instead of the variable + * We have to change the variables to our own struct and just store the pointer + * instead of the variable. Do it only for local variables, not for globals. */ - struct arguments *ptr; - char *result = make_str(""); + struct arguments *list; + struct arguments *ptr; + struct arguments *newlist = NULL; + struct variable *newvar, *newind; + char *result = make_str(""); - for (ptr = list; ptr != NULL; ptr = ptr->next) - { - char temp[20]; /* this should be sufficient unless you have 8 byte integers */ + 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 "ECPG_informix_get_var()" */ + /* change variable name to "ECPGget_var()" */ original_var = ptr->variable->name; - sprintf(temp, "%d))", ecpg_informix_var); + sprintf(temp, "%d))", ecpg_internal_var); - 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) + /* 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")))) { - ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)), make_str(" *)(ECPG_informix_get_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_informix_var++); + 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) { - ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->lineno), 0); - sprintf(temp, "%d, (", ecpg_informix_var++); + 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 { - ptr->variable = new_variable(cat_str(4, make_str("*("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->lineno), 0); - sprintf(temp, "%d, &(", ecpg_informix_var++); + 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 "ECPG_informix_set_var(, . )" */ - result = cat_str(5, result, make_str("ECPG_informix_set_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n")); + /* create call to "ECPGset_var(, . )" */ + 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 */ - if (ptr->indicator->type->type != ECPGt_NO_INDICATOR) + /* 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 "ECPG_informix_get_var()" */ + /* change variable name to "ECPGget_var()" */ original_var = ptr->indicator->name; - sprintf(temp, "%d))", ecpg_informix_var); + sprintf(temp, "%d))", ecpg_internal_var); - /* create call to "ECPG_informix_set_var(, . )" */ - if (atoi(ptr->indicator->type->size) > 1) + 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) { - ptr->indicator = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->indicator->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->lineno), 0); - sprintf(temp, "%d, (", ecpg_informix_var++); + 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 { - ptr->indicator = new_variable(cat_str(4, make_str("*("), mm_strdup(ecpg_type_name(ptr->indicator->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->lineno), 0); - sprintf(temp, "%d, &(", ecpg_informix_var++); + 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++); } - result = cat_str(5, result, make_str("ECPG_informix_set_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n")); + + /* create call to "ECPGset_var(, . )" */ + result = cat_str(5, result, make_str("ECPGset_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n")); } - } - return result; + add_variable_to_tail(&newlist, newvar, newind); + } + + if (insert) + cur->argsinsert_oos = newlist; + else + cur->argsresult_oos = newlist; + + return result; } +/* This tests whether the cursor was declared and opened in the same function. */ +#define SAMEFUNC(cur) \ + ((cur->function == NULL) || \ + (cur->function != NULL && !strcmp(cur->function, current_function))) + static struct cursor * add_additional_variables(char *name, bool insert) { @@ -318,12 +396,12 @@ add_additional_variables(char *name, bool insert) { /* add all those input variables that were given earlier * note that we have to append here but have to keep the existing order */ - for (p = ptr->argsinsert; p; p = p->next) + for (p = (SAMEFUNC(ptr) ? ptr->argsinsert : ptr->argsinsert_oos); p; p = p->next) add_variable_to_tail(&argsinsert, p->variable, p->indicator); } /* add all those output variables that were given earlier */ - for (p = ptr->argsresult; p; p = p->next) + for (p = (SAMEFUNC(ptr) ? ptr->argsresult : ptr->argsresult_oos); p; p = p->next) add_variable_to_tail(&argsresult, p->variable, p->indicator); return ptr; diff --git a/src/interfaces/ecpg/preproc/ecpg.trailer b/src/interfaces/ecpg/preproc/ecpg.trailer index f372c7dcd8..30af0b068c 100644 --- a/src/interfaces/ecpg/preproc/ecpg.trailer +++ b/src/interfaces/ecpg/preproc/ecpg.trailer @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.trailer,v 1.18 2010/01/15 10:44:37 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.trailer,v 1.19 2010/01/26 09:07:31 meskes Exp $ */ statements: /*EMPTY*/ | statements statement @@ -16,7 +16,17 @@ statement: ecpgstart at stmt ';' { connection = NULL; } | c_thing { fprintf(yyout, "%s", $1); free($1); } | CPP_LINE { fprintf(yyout, "%s", $1); free($1); } | '{' { braces_open++; fputs("{", yyout); } - | '}' { remove_typedefs(braces_open); remove_variables(braces_open--); fputs("}", yyout); } + | '}' + { + remove_typedefs(braces_open); + remove_variables(braces_open--); + if (braces_open == 0) + { + free(current_function); + current_function = NULL; + } + fputs("}", yyout); + } ; CreateAsStmt: CREATE OptTemp TABLE create_as_target AS {FoundInto = 0;} SelectStmt opt_with_data @@ -281,6 +291,7 @@ ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared 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) { @@ -294,9 +305,11 @@ ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared /* initial definition */ this->next = cur; this->name = $2; + this->function = (current_function ? mm_strdup(current_function) : NULL); this->connection = connection; this->command = cat_str(6, make_str("declare"), cursor_marker, $3, make_str("cursor"), $5, make_str("for $1")); this->argsresult = NULL; + this->argsresult_oos = NULL; thisquery->type = &ecpg_query; thisquery->brace_level = 0; @@ -305,6 +318,7 @@ ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared sprintf(thisquery->name, "ECPGprepared_statement(%s, %s, __LINE__)", con, $7); this->argsinsert = NULL; + this->argsinsert_oos = NULL; if ($2[0] == ':') { struct variable *var = find_variable($2 + 1); @@ -315,10 +329,19 @@ ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared cur = this; - if (INFORMIX_MODE && braces_open > 0) /* we're in a function */ - $$ = cat_str(4, make_str("ECPG_informix_reset_sqlca();"), make_str("/*"), mm_strdup(this->command), make_str("*/")); + 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, make_str("/*"), mm_strdup(this->command), make_str("*/")); + $$ = cat_str(3, + adjust_outofscope_cursor_vars(this, true), + adjust_outofscope_cursor_vars(this, false), + comment); } ; @@ -402,6 +425,7 @@ var_declaration: storage_declaration var_type { actual_type[struct_level].type_enum = $2.type_enum; + actual_type[struct_level].type_str = $2.type_str; actual_type[struct_level].type_dimension = $2.type_dimension; actual_type[struct_level].type_index = $2.type_index; actual_type[struct_level].type_sizeof = $2.type_sizeof; @@ -415,6 +439,7 @@ var_declaration: storage_declaration | var_type { actual_type[struct_level].type_enum = $1.type_enum; + actual_type[struct_level].type_str = $1.type_str; actual_type[struct_level].type_dimension = $1.type_dimension; actual_type[struct_level].type_index = $1.type_index; actual_type[struct_level].type_sizeof = $1.type_sizeof; @@ -826,9 +851,9 @@ variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initialize case ECPGt_struct: case ECPGt_union: if (atoi(dimension) < 0) - type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_sizeof); + type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_str, actual_type[struct_level].type_sizeof); else - type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_sizeof), dimension); + type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_str, actual_type[struct_level].type_sizeof), dimension); $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5); break; @@ -1303,9 +1328,9 @@ ECPGVar: SQL_VAR case ECPGt_struct: case ECPGt_union: if (atoi(dimension) < 0) - type = ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_sizeof); + type = ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_str, $5.type_sizeof); else - type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum,$5.type_sizeof), dimension); + type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_str, $5.type_sizeof), dimension); break; case ECPGt_varchar: diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h index 2d53b76dc0..25972b0c85 100644 --- a/src/interfaces/ecpg/preproc/extern.h +++ b/src/interfaces/ecpg/preproc/extern.h @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/extern.h,v 1.77 2010/01/05 16:38:23 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/extern.h,v 1.78 2010/01/26 09:07:31 meskes Exp $ */ #ifndef _ECPG_PREPROC_EXTERN_H #define _ECPG_PREPROC_EXTERN_H @@ -26,9 +26,10 @@ extern int braces_open, questionmarks, ret_value, struct_level, - ecpg_informix_var, + ecpg_internal_var, regression_mode, auto_prepare; +extern char *current_function; extern char *descriptor_index; extern char *descriptor_name; extern char *connection; diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l index bb8f8d43aa..7a61b0f49f 100644 --- a/src/interfaces/ecpg/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.171 2010/01/02 16:58:11 momjian Exp $ + * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.172 2010/01/26 09:07:31 meskes Exp $ * *------------------------------------------------------------------------- */ @@ -41,6 +41,9 @@ static char *literalbuf = NULL; /* expandable buffer */ static int literallen; /* actual current length */ static int literalalloc; /* current allocated buffer size */ +/* Used for detecting global state together with braces_open */ +static int parenths_open; + #define startlit() (literalbuf[0] = '\0', literallen = 0) static void addlit(char *ytext, int yleng); static void addlitchar (unsigned char); @@ -788,7 +791,17 @@ cppline {space}*#(.*\\{space})*.*{newline} } {identifier} { const ScanKeyword *keyword; - + + /* + * Try to detect a function name: + * look for identifiers at the global scope + * keep the last identifier before the first '(' and '{' */ + if (braces_open == 0 && parenths_open == 0) + { + if (current_function) + free(current_function); + current_function = mm_strdup(yytext); + } /* Informix uses SQL defines only in SQL space */ /* however, some defines have to be taken care of for compatibility */ if ((!INFORMIX_MODE || !isinformixdefine()) && !isdefine()) @@ -811,8 +824,8 @@ cppline {space}*#(.*\\{space})*.*{newline} "/" { return('/'); } "+" { return('+'); } "-" { return('-'); } -"(" { return('('); } -")" { return(')'); } +"(" { parenths_open++; return('('); } +")" { parenths_open--; return(')'); } {space} { ECHO; } \{ { return('{'); } \} { return('}'); } @@ -1178,6 +1191,8 @@ void lex_init(void) { braces_open = 0; + parenths_open = 0; + current_function = NULL; preproc_tos = 0; yylineno = 1; diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c index 40043896fc..4eb65e4eb9 100644 --- a/src/interfaces/ecpg/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/type.c,v 1.86 2010/01/05 16:38:23 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/type.c,v 1.87 2010/01/26 09:07:31 meskes Exp $ */ #include "postgres_fe.h" @@ -46,7 +46,7 @@ ECPGstruct_member_dup(struct ECPGstruct_member * rm) { case ECPGt_struct: case ECPGt_union: - type = ECPGmake_struct_type(rm->type->u.members, rm->type->type, rm->type->struct_sizeof); + type = ECPGmake_struct_type(rm->type->u.members, rm->type->type, rm->type->type_name, rm->type->struct_sizeof); break; case ECPGt_array: @@ -55,7 +55,7 @@ ECPGstruct_member_dup(struct ECPGstruct_member * rm) * create the struct too */ if (rm->type->u.element->type == ECPGt_struct) - type = ECPGmake_struct_type(rm->type->u.element->u.members, rm->type->u.element->type, rm->type->u.element->struct_sizeof); + type = ECPGmake_struct_type(rm->type->u.element->u.members, rm->type->u.element->type, rm->type->u.element->type_name, rm->type->u.element->struct_sizeof); else type = ECPGmake_array_type(ECPGmake_simple_type(rm->type->u.element->type, rm->type->u.element->size, rm->type->u.element->lineno), rm->type->size); break; @@ -98,6 +98,7 @@ ECPGmake_simple_type(enum ECPGttype type, char *size, int lineno) struct ECPGtype *ne = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype)); ne->type = type; + ne->type_name = NULL; ne->size = size; ne->u.element = NULL; ne->struct_sizeof = NULL; @@ -117,10 +118,11 @@ ECPGmake_array_type(struct ECPGtype * type, char *size) } struct ECPGtype * -ECPGmake_struct_type(struct ECPGstruct_member * rm, enum ECPGttype type, char *struct_sizeof) +ECPGmake_struct_type(struct ECPGstruct_member * rm, enum ECPGttype type, char *type_name, char *struct_sizeof) { struct ECPGtype *ne = ECPGmake_simple_type(type, make_str("1"), 0); + ne->type_name = mm_strdup(type_name); ne->u.members = ECPGstruct_member_dup(rm); ne->struct_sizeof = struct_sizeof; diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h index 45fd8cca61..a36e4518a2 100644 --- a/src/interfaces/ecpg/preproc/type.h +++ b/src/interfaces/ecpg/preproc/type.h @@ -1,5 +1,5 @@ /* - * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/type.h,v 1.51 2009/06/11 14:49:13 momjian Exp $ + * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/type.h,v 1.52 2010/01/26 09:07:31 meskes Exp $ */ #ifndef _ECPG_PREPROC_TYPE_H #define _ECPG_PREPROC_TYPE_H @@ -17,6 +17,7 @@ struct ECPGstruct_member struct ECPGtype { enum ECPGttype type; + char *type_name; /* For struct and union types it is the struct name */ char *size; /* For array it is the number of elements. For * varchar it is the maxsize of the area. */ char *struct_sizeof; /* For a struct this is the sizeof() type as @@ -36,7 +37,7 @@ void ECPGmake_struct_member(char *, struct ECPGtype *, struct ECPGstruct_member struct ECPGtype *ECPGmake_simple_type(enum ECPGttype, char *, int); struct ECPGtype *ECPGmake_varchar_type(enum ECPGttype, long); struct ECPGtype *ECPGmake_array_type(struct ECPGtype *, char *); -struct ECPGtype *ECPGmake_struct_type(struct ECPGstruct_member *, enum ECPGttype, char *); +struct ECPGtype *ECPGmake_struct_type(struct ECPGstruct_member *, enum ECPGttype, char *, char *); struct ECPGstruct_member *ECPGstruct_member_dup(struct ECPGstruct_member *); /* Frees a type. */ @@ -123,11 +124,14 @@ struct _include_path struct cursor { char *name; + char *function; char *command; char *connection; bool opened; struct arguments *argsinsert; + struct arguments *argsinsert_oos; struct arguments *argsresult; + struct arguments *argsresult_oos; struct cursor *next; }; diff --git a/src/interfaces/ecpg/preproc/variable.c b/src/interfaces/ecpg/preproc/variable.c index ce3b950621..728bc360dc 100644 --- a/src/interfaces/ecpg/preproc/variable.c +++ b/src/interfaces/ecpg/preproc/variable.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/variable.c,v 1.51 2009/11/26 15:06:47 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/variable.c,v 1.52 2010/01/26 09:07:31 meskes Exp $ */ #include "postgres_fe.h" @@ -47,7 +47,7 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member * members, in return (new_variable(name, ECPGmake_array_type(ECPGmake_simple_type(members->type->u.element->type, members->type->u.element->size, members->type->u.element->lineno), members->type->size), brace_level)); case ECPGt_struct: case ECPGt_union: - return (new_variable(name, ECPGmake_struct_type(members->type->u.members, members->type->type, members->type->struct_sizeof), brace_level)); + return (new_variable(name, ECPGmake_struct_type(members->type->u.members, members->type->type, members->type->type_name, members->type->struct_sizeof), brace_level)); default: return (new_variable(name, ECPGmake_simple_type(members->type->type, members->type->size, members->type->lineno), brace_level)); } @@ -94,7 +94,7 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member * members, in return (new_variable(name, ECPGmake_array_type(ECPGmake_simple_type(members->type->u.element->u.element->type, members->type->u.element->u.element->size, members->type->u.element->u.element->lineno), members->type->u.element->size), brace_level)); case ECPGt_struct: case ECPGt_union: - return (new_variable(name, ECPGmake_struct_type(members->type->u.element->u.members, members->type->u.element->type, members->type->u.element->struct_sizeof), brace_level)); + return (new_variable(name, ECPGmake_struct_type(members->type->u.element->u.members, members->type->u.element->type, members->type->u.element->type_name, members->type->u.element->struct_sizeof), brace_level)); default: return (new_variable(name, ECPGmake_simple_type(members->type->u.element->type, members->type->u.element->size, members->type->u.element->lineno), brace_level)); } @@ -235,7 +235,7 @@ find_variable(char *name) return (new_variable(name, ECPGmake_array_type(ECPGmake_simple_type(p->type->u.element->u.element->type, p->type->u.element->u.element->size, p->type->u.element->u.element->lineno), p->type->u.element->size), p->brace_level)); case ECPGt_struct: case ECPGt_union: - return (new_variable(name, ECPGmake_struct_type(p->type->u.element->u.members, p->type->u.element->type, p->type->u.element->struct_sizeof), p->brace_level)); + return (new_variable(name, ECPGmake_struct_type(p->type->u.element->u.members, p->type->u.element->type, p->type->u.element->type_name, p->type->u.element->struct_sizeof), p->brace_level)); default: return (new_variable(name, ECPGmake_simple_type(p->type->u.element->type, p->type->u.element->size, p->type->u.element->lineno), p->brace_level)); } diff --git a/src/interfaces/ecpg/test/ecpg_schedule b/src/interfaces/ecpg/test/ecpg_schedule index 2bf1e0243e..e71452484d 100644 --- a/src/interfaces/ecpg/test/ecpg_schedule +++ b/src/interfaces/ecpg/test/ecpg_schedule @@ -24,6 +24,7 @@ test: preproc/init test: preproc/strings test: preproc/type test: preproc/variable +test: preproc/outofscope test: preproc/whenever test: sql/array test: sql/binary diff --git a/src/interfaces/ecpg/test/ecpg_schedule_tcp b/src/interfaces/ecpg/test/ecpg_schedule_tcp index 9df75aba21..64125e65ea 100644 --- a/src/interfaces/ecpg/test/ecpg_schedule_tcp +++ b/src/interfaces/ecpg/test/ecpg_schedule_tcp @@ -24,6 +24,7 @@ test: preproc/init test: preproc/strings test: preproc/type test: preproc/variable +test: preproc/outofscope test: preproc/whenever test: sql/array test: sql/binary diff --git a/src/interfaces/ecpg/test/expected/compat_informix-test_informix.c b/src/interfaces/ecpg/test/expected/compat_informix-test_informix.c index 0dc8c7f08a..c19c2e5aff 100644 --- a/src/interfaces/ecpg/test/expected/compat_informix-test_informix.c +++ b/src/interfaces/ecpg/test/expected/compat_informix-test_informix.c @@ -147,7 +147,7 @@ if (sqlca.sqlcode < 0) dosqlprint ( );} sqlca.sqlcode = 100; - ECPG_informix_set_var( 0, &( i ), __LINE__);\ + ECPGset_var( 0, &( i ), __LINE__);\ ECPG_informix_reset_sqlca(); /* declare c cursor for select * from test where i <= $1 */ #line 49 "test_informix.pgc" @@ -245,7 +245,7 @@ if (sqlca.sqlcode < 0) dosqlprint ( );} static void openit(void) { { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "declare c cursor for select * from test where i <= $1 ", - ECPGt_int,&(*( int *)(ECPG_informix_get_var( 0))),(long)1,(long)1,sizeof(int), + ECPGt_int,&(*( int *)(ECPGget_var( 0))),(long)1,(long)1,sizeof(int), ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT); #line 95 "test_informix.pgc" diff --git a/src/interfaces/ecpg/test/expected/preproc-cursor.c b/src/interfaces/ecpg/test/expected/preproc-cursor.c index b9bf5410a2..2373475271 100644 --- a/src/interfaces/ecpg/test/expected/preproc-cursor.c +++ b/src/interfaces/ecpg/test/expected/preproc-cursor.c @@ -153,7 +153,8 @@ if (sqlca.sqlcode < 0) exit (1);} /* Dynamic cursorname test with INTO list in FETCH stmts */ strcpy(msg, "declare"); - /* declare $0 cursor for select id , t from t1 */ + ECPGset_var( 0, &( curname1 ), __LINE__);\ + /* declare $0 cursor for select id , t from t1 */ #line 59 "cursor.pgc" @@ -286,7 +287,10 @@ if (sqlca.sqlcode < 0) exit (1);} /* Dynamic cursorname test with INTO list in DECLARE stmt */ strcpy(msg, "declare"); - /* declare $0 cursor for select id , t from t1 */ + 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" @@ -435,7 +439,8 @@ if (sqlca.sqlcode < 0) exit (1);} strcpy(msg, "declare"); - /* declare $0 cursor for $1 */ + ECPGset_var( 4, &( curname3 ), __LINE__);\ + /* declare $0 cursor for $1 */ #line 143 "cursor.pgc" @@ -590,7 +595,8 @@ if (sqlca.sqlcode < 0) exit (1);} strcpy(msg, "declare"); - /* declare $0 cursor for $1 */ + ECPGset_var( 5, &( curname4 ), __LINE__);\ + /* declare $0 cursor for $1 */ #line 193 "cursor.pgc" diff --git a/src/interfaces/ecpg/test/expected/sql-binary.c b/src/interfaces/ecpg/test/expected/sql-binary.c index 00fd70224e..64497b6a72 100644 --- a/src/interfaces/ecpg/test/expected/sql-binary.c +++ b/src/interfaces/ecpg/test/expected/sql-binary.c @@ -107,7 +107,8 @@ main (void) exit (sqlca.sqlcode); } - /* declare C cursor for select name , accs , byte from empl where idnum = $1 */ + ECPGset_var( 0, &( empl.idnum ), __LINE__);\ + /* declare C cursor for select name , accs , byte from empl where idnum = $1 */ #line 58 "binary.pgc" { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare C cursor for select name , accs , byte from empl where idnum = $1 ", @@ -133,7 +134,8 @@ main (void) printf ("name=%s, accs=%d byte=%s\n", empl.name, empl.accs, empl.byte); memset(empl.name, 0, 21L); - /* declare B binary cursor for select name , accs , byte from empl where idnum = $1 */ + ECPGset_var( 1, &( empl.idnum ), __LINE__);\ + /* declare B binary cursor for select name , accs , byte from empl where idnum = $1 */ #line 70 "binary.pgc" { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare B binary cursor for select name , accs , byte from empl where idnum = $1 ", @@ -166,7 +168,8 @@ main (void) printf("(%o)", (unsigned char)empl.byte[i]); printf("\n"); - /* declare A binary cursor for select byte from empl where idnum = $1 */ + ECPGset_var( 2, &( empl.idnum ), __LINE__);\ + /* declare A binary cursor for select byte from empl where idnum = $1 */ #line 87 "binary.pgc" { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare A binary cursor for select byte from empl where idnum = $1 ", diff --git a/src/interfaces/ecpg/test/preproc/Makefile b/src/interfaces/ecpg/test/preproc/Makefile index ed3243214e..6d1d6294f5 100644 --- a/src/interfaces/ecpg/test/preproc/Makefile +++ b/src/interfaces/ecpg/test/preproc/Makefile @@ -11,6 +11,7 @@ TESTS = array_of_struct array_of_struct.c \ define define.c \ init init.c \ strings strings.c \ + outofscope outofscope.c \ type type.c \ variable variable.c \ whenever whenever.c -- 2.40.0