Hi,

Tom Lane írta:
> Boszormenyi Zoltan <z...@cybertec.at> writes:
>   
>> in a continued effort for better Informix ESQL/C compatibility,
>> we added the "string" pseudo-type handling to ECPG.
>> ...
>> - "string" has become a type name, reserved word in ECPG.
>>     
>
> This seems like a sufficient reason to reject the patch.  Who knows
> what that will break?  (I observe that it already broke a few of the
> ecpg regression tests, suggesting that using "string" as a variable
> name is hardly uncommon.)
>
>                       regards, tom lane
>   

OK, let me retry. This version treats "string" as a non-reserved word,
and also discovers whether the PGC contains this construct below,
as in ecpg/tests/preproc/type.pgc:

exec sql type string is char[11];
typedef char string[11];

Now all regression tests pass unchanged and ECPG also accepts
    string *string;
and
    string string[N];
without typedef, replacing "string" with "char".

I think it's acceptable.

Thanks in advance,
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 -dcrpN postgresql-8.4.0-sqlda/src/interfaces/ecpg/ecpglib/data.c postgresql-8.4.0-string/src/interfaces/ecpg/ecpglib/data.c
*** postgresql-8.4.0-sqlda/src/interfaces/ecpg/ecpglib/data.c	2009-01-15 12:52:55.000000000 +0100
--- postgresql-8.4.0-string/src/interfaces/ecpg/ecpglib/data.c	2009-07-04 12:27:57.000000000 +0200
*************** ecpg_get_data(const PGresult *results, i
*** 138,143 ****
--- 138,144 ----
  			case ECPGt_char:
  			case ECPGt_unsigned_char:
  			case ECPGt_varchar:
+ 			case ECPGt_string:
  				break;
  
  			default:
*************** ecpg_get_data(const PGresult *results, i
*** 389,394 ****
--- 390,396 ----
  
  				case ECPGt_char:
  				case ECPGt_unsigned_char:
+ 				case ECPGt_string:
  					if (pval)
  					{
  						if (varcharsize == 0 || varcharsize > size)
*************** ecpg_get_data(const PGresult *results, i
*** 426,431 ****
--- 428,454 ----
  								sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W';
  							}
  						}
+ 						/* Do the rtrim() */
+ 						if (type == ECPGt_string)
+ 						{
+ 							char	*str = (char *) ((long) var + offset * act_tuple);
+ 							char	*last;
+ 							int	len = strlen(str);
+ 
+ 							last = str + len;
+ 							while (last > str)
+ 							{
+ 								if (*last == '\0')
+ 									last--;
+ 								else if (*last == ' ')
+ 								{
+ 									*last = '\0';
+ 									last--;
+ 								}
+ 								else
+ 									break;
+ 							}
+ 						}
  						pval += size;
  					}
  					break;
diff -dcrpN postgresql-8.4.0-sqlda/src/interfaces/ecpg/ecpglib/descriptor.c postgresql-8.4.0-string/src/interfaces/ecpg/ecpglib/descriptor.c
*** postgresql-8.4.0-sqlda/src/interfaces/ecpg/ecpglib/descriptor.c	2009-07-04 10:42:50.000000000 +0200
--- postgresql-8.4.0-string/src/interfaces/ecpg/ecpglib/descriptor.c	2009-07-04 12:12:02.000000000 +0200
*************** get_char_item(int lineno, void *var, enu
*** 201,206 ****
--- 201,207 ----
  	{
  		case ECPGt_char:
  		case ECPGt_unsigned_char:
+ 		case ECPGt_string:
  			strncpy((char *) var, value, varcharsize);
  			break;
  		case ECPGt_varchar:
diff -dcrpN postgresql-8.4.0-sqlda/src/interfaces/ecpg/ecpglib/execute.c postgresql-8.4.0-string/src/interfaces/ecpg/ecpglib/execute.c
*** postgresql-8.4.0-sqlda/src/interfaces/ecpg/ecpglib/execute.c	2009-07-04 10:42:50.000000000 +0200
--- postgresql-8.4.0-string/src/interfaces/ecpg/ecpglib/execute.c	2009-07-04 12:12:02.000000000 +0200
*************** ecpg_store_result(const PGresult *result
*** 360,365 ****
--- 360,366 ----
  			{
  				case ECPGt_char:
  				case ECPGt_unsigned_char:
+ 				case ECPGt_string:
  					if (!var->varcharsize && !var->arrsize)
  					{
  						/* special mode for handling char**foo=0 */
*************** ecpg_store_result(const PGresult *result
*** 419,425 ****
  
  	/* fill the variable with the tuple(s) */
  	if (!var->varcharsize && !var->arrsize &&
! 		(var->type == ECPGt_char || var->type == ECPGt_unsigned_char))
  	{
  		/* special mode for handling char**foo=0 */
  
--- 420,426 ----
  
  	/* fill the variable with the tuple(s) */
  	if (!var->varcharsize && !var->arrsize &&
! 		(var->type == ECPGt_char || var->type == ECPGt_unsigned_char || var->type == ECPGt_string))
  	{
  		/* special mode for handling char**foo=0 */
  
*************** ecpg_store_input(const int lineno, const
*** 758,763 ****
--- 759,765 ----
  
  			case ECPGt_char:
  			case ECPGt_unsigned_char:
+ 			case ECPGt_string:
  				{
  					/* set slen to string length if type is char * */
  					int			slen = (var->varcharsize == 0) ? strlen((char *) var->value) : (unsigned int) var->varcharsize;
*************** ecpg_execute(struct statement * stmt)
*** 1196,1201 ****
--- 1198,1204 ----
  					{
  						case ECPGt_char:
  						case ECPGt_varchar:
+ 						case ECPGt_string:
  							desc_inlist.varcharsize = strlen(sqlda->sqlvar[i].sqldata);
  							break;
  						default:
diff -dcrpN postgresql-8.4.0-sqlda/src/interfaces/ecpg/ecpglib/misc.c postgresql-8.4.0-string/src/interfaces/ecpg/ecpglib/misc.c
*** postgresql-8.4.0-sqlda/src/interfaces/ecpg/ecpglib/misc.c	2009-06-11 16:49:13.000000000 +0200
--- postgresql-8.4.0-string/src/interfaces/ecpg/ecpglib/misc.c	2009-07-04 12:12:02.000000000 +0200
*************** ECPGset_noind_null(enum ECPGttype type, 
*** 295,300 ****
--- 295,301 ----
  	{
  		case ECPGt_char:
  		case ECPGt_unsigned_char:
+ 		case ECPGt_string:
  			*((char *) ptr) = '\0';
  			break;
  		case ECPGt_short:
*************** ECPGis_noind_null(enum ECPGttype type, v
*** 361,366 ****
--- 362,368 ----
  	{
  		case ECPGt_char:
  		case ECPGt_unsigned_char:
+ 		case ECPGt_string:
  			if (*((char *) ptr) == '\0')
  				return true;
  			break;
diff -dcrpN postgresql-8.4.0-sqlda/src/interfaces/ecpg/ecpglib/typename.c postgresql-8.4.0-string/src/interfaces/ecpg/ecpglib/typename.c
*** postgresql-8.4.0-sqlda/src/interfaces/ecpg/ecpglib/typename.c	2009-07-04 10:42:50.000000000 +0200
--- postgresql-8.4.0-string/src/interfaces/ecpg/ecpglib/typename.c	2009-07-04 12:12:02.000000000 +0200
*************** ecpg_type_name(enum ECPGttype typ)
*** 20,25 ****
--- 20,26 ----
  	switch (typ)
  	{
  		case ECPGt_char:
+ 		case ECPGt_string:
  			return "char";
  		case ECPGt_unsigned_char:
  			return "unsigned char";
diff -dcrpN postgresql-8.4.0-sqlda/src/interfaces/ecpg/include/ecpgtype.h postgresql-8.4.0-string/src/interfaces/ecpg/include/ecpgtype.h
*** postgresql-8.4.0-sqlda/src/interfaces/ecpg/include/ecpgtype.h	2009-07-04 10:42:50.000000000 +0200
--- postgresql-8.4.0-string/src/interfaces/ecpg/include/ecpgtype.h	2009-07-04 12:06:05.000000000 +0200
*************** enum ECPGttype
*** 62,68 ****
  	ECPGt_EOIT,					/* End of insert types. */
  	ECPGt_EORT,					/* End of result types. */
  	ECPGt_NO_INDICATOR,			/* no indicator */
! 	ECPGt_sqlda				/* INFORMIX-compatible sqlda_t descriptor */
  };
  
   /* descriptor items */
--- 62,69 ----
  	ECPGt_EOIT,					/* End of insert types. */
  	ECPGt_EORT,					/* End of result types. */
  	ECPGt_NO_INDICATOR,			/* no indicator */
! 	ECPGt_sqlda,				/* INFORMIX-compatible sqlda_t descriptor */
! 	ECPGt_string				/* trimmed (char *) type */
  };
  
   /* descriptor items */
*************** enum ECPGdtype
*** 87,93 ****
  	ECPGd_cardinality
  };
  
! #define IS_SIMPLE_TYPE(type) ((type) >= ECPGt_char && (type) <= ECPGt_interval)
  
  /* we also have to handle different statement types */
  enum ECPG_statement_type
--- 88,94 ----
  	ECPGd_cardinality
  };
  
! #define IS_SIMPLE_TYPE(type) (((type) >= ECPGt_char && (type) <= ECPGt_interval) || ((type) == ECPGt_string))
  
  /* we also have to handle different statement types */
  enum ECPG_statement_type
diff -dcrpN postgresql-8.4.0-sqlda/src/interfaces/ecpg/preproc/ecpg.addons postgresql-8.4.0-string/src/interfaces/ecpg/preproc/ecpg.addons
*** postgresql-8.4.0-sqlda/src/interfaces/ecpg/preproc/ecpg.addons	2009-07-04 10:42:50.000000000 +0200
--- postgresql-8.4.0-string/src/interfaces/ecpg/preproc/ecpg.addons	2009-07-04 16:49:28.000000000 +0200
*************** ECPG: ColIdcol_name_keyword rule
*** 331,336 ****
--- 331,344 ----
  	| ECPGKeywords                  { $$ = $1; }
  	| ECPGCKeywords                 { $$ = $1; }
  	| CHAR_P                        { $$ = make_str("char"); }
+ 	| STRING_P
+ 	{
+ 		struct typedefs *this = get_typedef("string");
+ 		if (this)
+ 			$$ = make_str("string");
+ 		else
+ 			$$ = make_str("char");
+ 	}
  	| VALUES                        { $$ = make_str("values"); }
  ECPG: type_function_nametype_func_name_keyword rule
  	| ECPGKeywords                          { $$ = $1; }
diff -dcrpN postgresql-8.4.0-sqlda/src/interfaces/ecpg/preproc/ecpg.header postgresql-8.4.0-string/src/interfaces/ecpg/preproc/ecpg.header
*** postgresql-8.4.0-sqlda/src/interfaces/ecpg/preproc/ecpg.header	2009-06-11 01:11:52.000000000 +0200
--- postgresql-8.4.0-string/src/interfaces/ecpg/preproc/ecpg.header	2009-07-04 11:49:50.000000000 +0200
*************** adjust_informix(struct arguments *list)
*** 256,267 ****
  		original_var = ptr->variable->name;
  		sprintf(temp, "%d))", ecpg_informix_var);
  
! 		if ((ptr->variable->type->type != ECPGt_varchar && ptr->variable->type->type != ECPGt_char && ptr->variable->type->type != ECPGt_unsigned_char) && 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++);
  		}
! 		else if ((ptr->variable->type->type == ECPGt_varchar || ptr->variable->type->type == ECPGt_char || ptr->variable->type->type == ECPGt_unsigned_char) && 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++);
--- 256,267 ----
  		original_var = ptr->variable->name;
  		sprintf(temp, "%d))", ecpg_informix_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)
  		{
  			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++);
  		}
! 		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++);
*************** add_typedef(char *name, char * dimension
*** 371,376 ****
--- 371,377 ----
  		if (type_enum != ECPGt_varchar &&
  			type_enum != ECPGt_char &&
  			type_enum != ECPGt_unsigned_char &&
+ 			type_enum != ECPGt_string &&
  			atoi(this->type->type_index) >= 0)
  			mmerror(PARSE_ERROR, ET_ERROR, "multidimensional arrays for simple data types are not supported");
  
diff -dcrpN postgresql-8.4.0-sqlda/src/interfaces/ecpg/preproc/ecpg.tokens postgresql-8.4.0-string/src/interfaces/ecpg/preproc/ecpg.tokens
*** postgresql-8.4.0-sqlda/src/interfaces/ecpg/preproc/ecpg.tokens	2008-11-14 11:03:33.000000000 +0100
--- postgresql-8.4.0-string/src/interfaces/ecpg/preproc/ecpg.tokens	2009-07-04 10:59:43.000000000 +0200
***************
*** 25,28 ****
  %token TYPECAST
  %token CSTRING CVARIABLE CPP_LINE IP 
  %token DOLCONST ECONST NCONST UCONST UIDENT
! 
--- 25,28 ----
  %token TYPECAST
  %token CSTRING CVARIABLE CPP_LINE IP 
  %token DOLCONST ECONST NCONST UCONST UIDENT
! %token STRING_P
diff -dcrpN postgresql-8.4.0-sqlda/src/interfaces/ecpg/preproc/ecpg.trailer postgresql-8.4.0-string/src/interfaces/ecpg/preproc/ecpg.trailer
*** postgresql-8.4.0-sqlda/src/interfaces/ecpg/preproc/ecpg.trailer	2009-07-04 10:42:50.000000000 +0200
--- postgresql-8.4.0-string/src/interfaces/ecpg/preproc/ecpg.trailer	2009-07-04 17:02:20.000000000 +0200
*************** char_variable: cvariable
*** 213,218 ****
--- 213,219 ----
  				{
  					case ECPGt_char:
  					case ECPGt_unsigned_char:
+ 					case ECPGt_string:
  						$$ = $1;
  						break;
  					case ECPGt_varchar:
*************** var_type:	simple_type
*** 529,534 ****
--- 530,560 ----
  				$$.type_index = make_str("-1");
  				$$.type_sizeof = NULL;
  			}
+ 			else if (strcmp($1, "string") == 0)
+ 			{
+ 				struct typedefs *this = get_typedef($1);
+ 				if (this == NULL)
+ 				{
+ 					$$.type_enum = ECPGt_string;
+ 					$$.type_str = make_str("char");
+ 					$$.type_dimension = make_str("-1");
+ 					$$.type_index = make_str("-1");
+ 					$$.type_sizeof = NULL;
+ 				}
+ 				else
+ 				{
+ 					$$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
+ 					$$.type_enum = this->type->type_enum;
+ 					$$.type_dimension = this->type->type_dimension;
+ 					$$.type_index = this->type->type_index;
+ 					if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0)
+ 						$$.type_sizeof = this->type->type_sizeof;
+ 					else 
+ 						$$.type_sizeof = cat_str(3, make_str("sizeof("), mm_strdup(this->name), make_str(")"));
+ 
+ 					struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
+ 				}
+ 			}
  			else if (strcmp($1, "float") == 0)
  			{
  				$$.type_enum = ECPGt_float;
*************** signed_type: SQL_SHORT				{ $$ = ECPGt_s
*** 795,800 ****
--- 821,827 ----
  		}
  		| SQL_BOOL					{ $$ = ECPGt_bool; }
  		| CHAR_P					{ $$ = ECPGt_char; }
+ 		| STRING_P					{ $$ = ECPGt_string; }
  		| DOUBLE_P					{ $$ = ECPGt_double; }
  		;
  
*************** variable: opt_pointer ECPGColLabel opt_a
*** 855,860 ****
--- 882,888 ----
  
  				case ECPGt_char:
  				case ECPGt_unsigned_char:
+ 				case ECPGt_string:
  					if (atoi(dimension) == -1)
  					{
  						int i = strlen($5);
*************** ECPGVar: SQL_VAR
*** 1331,1336 ****
--- 1359,1365 ----
  
  					case ECPGt_char:
  					case ECPGt_unsigned_char:
+ 					case ECPGt_string:
  						if (atoi(dimension) == -1)
  							type = ECPGmake_simple_type($5.type_enum, length, 0);
  						else
*************** c_anything:  ecpg_ident				{ $$ = $1; }
*** 2017,2022 ****
--- 2046,2052 ----
  		| SQL_UNSIGNED			{ $$ = make_str("unsigned"); }
  		| YEAR_P			{ $$ = make_str("year"); }
  		| CHAR_P			{ $$ = make_str("char"); }
+ 		| STRING_P			{ $$ = make_str("string"); }
  		| FLOAT_P			{ $$ = make_str("float"); }
  		| TO				{ $$ = make_str("to"); }
  		| UNION				{ $$ = make_str("union"); }
diff -dcrpN postgresql-8.4.0-sqlda/src/interfaces/ecpg/preproc/type.c postgresql-8.4.0-string/src/interfaces/ecpg/preproc/type.c
*** postgresql-8.4.0-sqlda/src/interfaces/ecpg/preproc/type.c	2009-07-04 10:42:50.000000000 +0200
--- postgresql-8.4.0-string/src/interfaces/ecpg/preproc/type.c	2009-07-04 14:12:07.000000000 +0200
*************** get_type(enum ECPGttype type)
*** 200,205 ****
--- 200,208 ----
  		case ECPGt_timestamp:
  			return ("ECPGt_timestamp");
  			break;
+ 		case ECPGt_string:
+ 			return ("ECPGt_string");
+ 			break;
  		default:
  			mmerror(PARSE_ERROR, ET_ERROR, "unrecognized variable type code %d", type);
  	}
*************** ECPGdump_a_simple(FILE *o, const char *n
*** 368,373 ****
--- 371,377 ----
  			case ECPGt_char:
  			case ECPGt_unsigned_char:
  			case ECPGt_char_variable:
+ 			case ECPGt_string:
  
  				/*
  				 * we have to use the pointer except for arrays with given
diff -dcrpN postgresql-8.4.0-sqlda/src/interfaces/ecpg/preproc/variable.c postgresql-8.4.0-string/src/interfaces/ecpg/preproc/variable.c
*** postgresql-8.4.0-sqlda/src/interfaces/ecpg/preproc/variable.c	2009-07-04 10:42:50.000000000 +0200
--- postgresql-8.4.0-string/src/interfaces/ecpg/preproc/variable.c	2009-07-04 11:45:25.000000000 +0200
*************** adjust_array(enum ECPGttype type_enum, c
*** 524,530 ****
  												"multilevel pointers (more than 2 levels) are not supported; found %d levels", pointer_len),
  				pointer_len);
  
! 	if (pointer_len > 1 && type_enum != ECPGt_char && type_enum != ECPGt_unsigned_char)
  		mmerror(PARSE_ERROR, ET_FATAL, "pointer to pointer is not supported for this data type");
  
  	if (pointer_len > 1 && (atoi(*length) >= 0 || atoi(*dimension) >= 0))
--- 524,530 ----
  												"multilevel pointers (more than 2 levels) are not supported; found %d levels", pointer_len),
  				pointer_len);
  
! 	if (pointer_len > 1 && type_enum != ECPGt_char && type_enum != ECPGt_unsigned_char && type_enum != ECPGt_string)
  		mmerror(PARSE_ERROR, ET_FATAL, "pointer to pointer is not supported for this data type");
  
  	if (pointer_len > 1 && (atoi(*length) >= 0 || atoi(*dimension) >= 0))
*************** adjust_array(enum ECPGttype type_enum, c
*** 563,568 ****
--- 563,569 ----
  			break;
  		case ECPGt_char:
  		case ECPGt_unsigned_char:
+ 		case ECPGt_string:
  			/* char ** */
  			if (pointer_len == 2)
  			{
-- 
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