Hi, here's a little beautified patch: - more logical parameter order in ECPGdump_a_type() - use mm_strdup() instead of strdup() (I notoriously forget this) - actually bail out with ET_FATAL if the local variable is of a different type than the global variable that was used in the DECLARE in the global scope
Although with this patch we can only detect variables under DECLARE SECTIONs, so we can't detect the scenario in the attached test case. Should we? This test code would be a good candidate for the Underhanded C Contest. :-) Best regards, Zoltán Böszörményi -- Bible has answers for everything. Proof: "But let your communication be, Yea, yea; Nay, nay: for whatsoever is more than these cometh of evil." (Matthew 5:37) - basics of digital technology. "May your kingdom come" - superficial description of plate tectonics ---------------------------------- Zoltán Böszörményi Cybertec Schönig & Schönig GmbH http://www.postgresql.at/
diff -dcrp pgsql.orig/src/interfaces/ecpg/preproc/descriptor.c pgsql/src/interfaces/ecpg/preproc/descriptor.c *** pgsql.orig/src/interfaces/ecpg/preproc/descriptor.c 2010-03-10 14:31:49.000000000 +0100 --- pgsql/src/interfaces/ecpg/preproc/descriptor.c 2010-04-01 09:48:48.000000000 +0200 *************** output_get_descr(char *desc_name, char * *** 188,194 **** break; } fprintf(yyout, "%s,", get_dtype(results->value)); ! ECPGdump_a_type(yyout, v->name, v->type, NULL, NULL, NULL, NULL, make_str("0"), NULL, NULL); } drop_assignments(); fputs("ECPGd_EODT);\n", yyout); --- 188,194 ---- break; } fprintf(yyout, "%s,", get_dtype(results->value)); ! ECPGdump_a_type(yyout, v->name, v->type, v->brace_level, NULL, NULL, -1, NULL, NULL, make_str("0"), NULL, NULL); } drop_assignments(); fputs("ECPGd_EODT);\n", yyout); *************** output_set_descr(char *desc_name, char * *** 293,299 **** case ECPGd_length: case ECPGd_type: fprintf(yyout, "%s,", get_dtype(results->value)); ! ECPGdump_a_type(yyout, v->name, v->type, NULL, NULL, NULL, NULL, make_str("0"), NULL, NULL); break; default: --- 293,299 ---- case ECPGd_length: case ECPGd_type: fprintf(yyout, "%s,", get_dtype(results->value)); ! ECPGdump_a_type(yyout, v->name, v->type, v->brace_level, NULL, NULL, -1, NULL, NULL, make_str("0"), NULL, NULL); break; default: diff -dcrp pgsql.orig/src/interfaces/ecpg/preproc/type.c pgsql/src/interfaces/ecpg/preproc/type.c *** pgsql.orig/src/interfaces/ecpg/preproc/type.c 2010-03-31 12:44:07.000000000 +0200 --- pgsql/src/interfaces/ecpg/preproc/type.c 2010-04-01 10:03:00.000000000 +0200 *************** ECPGstruct_member_dup(struct ECPGstruct_ *** 54,60 **** * if this array does contain a struct again, we have to * 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->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->counter), rm->type->size); --- 54,60 ---- * if this array does contain a struct again, we have to * create the struct too */ ! if (rm->type->u.element->type == ECPGt_struct || rm->type->u.element->type == ECPGt_union) 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->counter), rm->type->size); *************** static void ECPGdump_a_struct(FILE *o, c *** 236,247 **** struct ECPGtype * type, struct ECPGtype * ind_type, const char *prefix, const char *ind_prefix); void ! ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type, ! const char *ind_name, struct ECPGtype * ind_type, const char *prefix, const char *ind_prefix, char *arr_str_siz, const char *struct_sizeof, const char *ind_struct_sizeof) { switch (type->type) { case ECPGt_array: --- 236,282 ---- struct ECPGtype * type, struct ECPGtype * ind_type, const char *prefix, const char *ind_prefix); void ! ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type, const int brace_level, ! const char *ind_name, struct ECPGtype * ind_type, const int ind_brace_level, const char *prefix, const char *ind_prefix, char *arr_str_siz, const char *struct_sizeof, const char *ind_struct_sizeof) { + struct variable *var; + + if (type->type != ECPGt_descriptor && type->type != ECPGt_sqlda && + type->type != ECPGt_char_variable && + brace_level >= 0) + { + char *str; + + str = mm_strdup(name); + var = find_variable(str); + free(str); + + if ((var->type->type != type->type) || + (var->type->type_name && !type->type_name) || + (!var->type->type_name && type->type_name) || + (var->type->type_name && type->type_name && strcmp(var->type->type_name, type->type_name))) + mmerror(PARSE_ERROR, ET_FATAL, "variable (%s) is hidden by a local variable of a different type", name); + else if (var->brace_level != brace_level) + mmerror(PARSE_ERROR, ET_WARNING, "variable (%s) is hidden by a local variable", name); + + if (ind_name && ind_type && ind_type->type != ECPGt_NO_INDICATOR && ind_brace_level >= 0) + { + str = mm_strdup(ind_name); + var = find_variable(str); + free(str); + if ((var->type->type != ind_type->type) || + (var->type->type_name && !ind_type->type_name) || + (!var->type->type_name && ind_type->type_name) || + (var->type->type_name && ind_type->type_name && strcmp(var->type->type_name, ind_type->type_name))) + mmerror(PARSE_ERROR, ET_FATAL, "indicator variable (%s) is hidden by a local variable of a different type", ind_name); + else if (var->brace_level != ind_brace_level) + mmerror(PARSE_ERROR, ET_WARNING, "indicator variable (%s) is hidden by a local variable", ind_name); + } + } + switch (type->type) { case ECPGt_array: *************** ECPGdump_a_struct(FILE *o, const char *n *** 499,507 **** for (p = type->u.members; p; p = p->next) { ! ECPGdump_a_type(o, p->name, p->type, (ind_p != NULL) ? ind_p->name : NULL, (ind_p != NULL) ? ind_p->type : NULL, prefix, ind_prefix, arrsiz, type->struct_sizeof, (ind_p != NULL) ? ind_type->struct_sizeof : NULL); if (ind_p != NULL && ind_p != &struct_no_indicator) --- 534,543 ---- for (p = type->u.members; p; p = p->next) { ! ECPGdump_a_type(o, p->name, p->type, -1, (ind_p != NULL) ? ind_p->name : NULL, (ind_p != NULL) ? ind_p->type : NULL, + -1, prefix, ind_prefix, arrsiz, type->struct_sizeof, (ind_p != NULL) ? ind_type->struct_sizeof : NULL); if (ind_p != NULL && ind_p != &struct_no_indicator) diff -dcrp pgsql.orig/src/interfaces/ecpg/preproc/type.h pgsql/src/interfaces/ecpg/preproc/type.h *** pgsql.orig/src/interfaces/ecpg/preproc/type.h 2010-03-10 14:31:49.000000000 +0100 --- pgsql/src/interfaces/ecpg/preproc/type.h 2010-04-01 09:44:37.000000000 +0200 *************** void ECPGfree_type(struct ECPGtype *); *** 55,63 **** size is the maxsize in case it is a varchar. Otherwise it is the size of the variable (required to do array fetches of structs). */ ! void ECPGdump_a_type(FILE *, const char *, struct ECPGtype *, ! const char *, struct ECPGtype *, const char *, ! const char *, char *, const char *, const char *); /* A simple struct to keep a variable and its type. */ struct ECPGtemp_type --- 55,64 ---- size is the maxsize in case it is a varchar. Otherwise it is the size of the variable (required to do array fetches of structs). */ ! void ECPGdump_a_type(FILE *, const char *, struct ECPGtype *, const int, ! const char *, struct ECPGtype *, const int, ! const char *, const char *, char *, ! const char *, const char *); /* A simple struct to keep a variable and its type. */ struct ECPGtemp_type diff -dcrp pgsql.orig/src/interfaces/ecpg/preproc/variable.c pgsql/src/interfaces/ecpg/preproc/variable.c *** pgsql.orig/src/interfaces/ecpg/preproc/variable.c 2010-03-10 14:31:49.000000000 +0100 --- pgsql/src/interfaces/ecpg/preproc/variable.c 2010-04-01 09:49:49.000000000 +0200 *************** dump_variables(struct arguments * list, *** 444,451 **** dump_variables(list->next, mode); /* Then the current element and its indicator */ ! ECPGdump_a_type(yyout, list->variable->name, list->variable->type, ! list->indicator->name, list->indicator->type, NULL, NULL, make_str("0"), NULL, NULL); /* Then release the list element. */ --- 444,451 ---- dump_variables(list->next, mode); /* Then the current element and its indicator */ ! ECPGdump_a_type(yyout, list->variable->name, list->variable->type, list->variable->brace_level, ! list->indicator->name, list->indicator->type, list->indicator->brace_level, NULL, NULL, make_str("0"), NULL, NULL); /* Then release the list element. */
EXEC SQL BEGIN DECLARE SECTION; int id; char t[256]; EXEC SQL END DECLARE SECTION; EXEC SQL DECLARE mycur CURSOR FOR SELECT * INTO :id,:t FROM t1; int main(void) { int id; int t; EXEC SQL CONNECT TO test; EXEC SQL OPEN mycur; EXEC SQL FETCH mycur; EXEC SQL CLOSE mycur; EXEC SQL DISCONNECT ALL; return 0; }
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers