|
|
|
@ -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 *list; |
|
|
|
|
struct arguments *ptr; |
|
|
|
|
struct arguments *newlist = NULL; |
|
|
|
|
struct variable *newvar, *newind; |
|
|
|
|
char *result = make_str(""); |
|
|
|
|
|
|
|
|
|
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(<counter>)" */ |
|
|
|
|
/* change variable name to "ECPGget_var(<counter>)" */ |
|
|
|
|
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")))) |
|
|
|
|
{ |
|
|
|
|
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) |
|
|
|
|
{ |
|
|
|
|
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 = 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(<counter>, <pointer>. <linen number>)" */ |
|
|
|
|
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(<counter>, <pointer>. <linen number>)" */ |
|
|
|
|
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)) |
|
|
|
|
{ |
|
|
|
|
/* change variable name to "ECPG_informix_get_var(<counter>)" */ |
|
|
|
|
newind = ptr->indicator; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
/* change variable name to "ECPGget_var(<counter>)" */ |
|
|
|
|
original_var = ptr->indicator->name; |
|
|
|
|
sprintf(temp, "%d))", ecpg_informix_var); |
|
|
|
|
sprintf(temp, "%d))", ecpg_internal_var); |
|
|
|
|
|
|
|
|
|
/* create call to "ECPG_informix_set_var(<counter>, <pointer>. <linen number>)" */ |
|
|
|
|
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(<counter>, <pointer>. <linen number>)" */ |
|
|
|
|
result = cat_str(5, result, make_str("ECPGset_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|