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

Reply via email to