diff -dcrpN pgsql85dev.3describe/doc/src/sgml/ecpg.sgml pgsql85dev.4string/doc/src/sgml/ecpg.sgml *** pgsql85dev.3describe/doc/src/sgml/ecpg.sgml 2009-07-13 15:16:28.469424632 +0200 --- pgsql85dev.4string/doc/src/sgml/ecpg.sgml 2009-07-14 22:30:24.345801171 +0200 *************** void PGTYPESdecimal_free(decimal *var); *** 2418,2423 **** --- 2418,2428 ---- know about ranges like for example YEAR TO MINUTE so you won't find support in ecpg for that either. + + The Informix-special "string" data type for storing right-trimmed character string data is now + supported in Informix-mode without using typedef. In fact, in Informix-mode, + ECPG refuses to process source files that contain typedef sometype string; + Additional embedded SQL statements diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/data.c pgsql85dev.4string/src/interfaces/ecpg/ecpglib/data.c *** pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/data.c 2009-01-16 11:45:04.000000000 +0100 --- pgsql85dev.4string/src/interfaces/ecpg/ecpglib/data.c 2009-07-14 21:36:58.576800146 +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 pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/descriptor.c pgsql85dev.4string/src/interfaces/ecpg/ecpglib/descriptor.c *** pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/descriptor.c 2009-07-14 21:21:46.526800064 +0200 --- pgsql85dev.4string/src/interfaces/ecpg/ecpglib/descriptor.c 2009-07-14 21:36:58.577803765 +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 pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/execute.c pgsql85dev.4string/src/interfaces/ecpg/ecpglib/execute.c *** pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/execute.c 2009-07-14 21:25:02.120803120 +0200 --- pgsql85dev.4string/src/interfaces/ecpg/ecpglib/execute.c 2009-07-14 21:36:58.582803006 +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 pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/misc.c pgsql85dev.4string/src/interfaces/ecpg/ecpglib/misc.c *** pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/misc.c 2009-06-13 18:25:05.000000000 +0200 --- pgsql85dev.4string/src/interfaces/ecpg/ecpglib/misc.c 2009-07-14 21:36:58.583801667 +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 pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/typename.c pgsql85dev.4string/src/interfaces/ecpg/ecpglib/typename.c *** pgsql85dev.3describe/src/interfaces/ecpg/ecpglib/typename.c 2009-07-14 21:25:45.229800483 +0200 --- pgsql85dev.4string/src/interfaces/ecpg/ecpglib/typename.c 2009-07-14 21:36:58.584800118 +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 pgsql85dev.3describe/src/interfaces/ecpg/include/ecpgtype.h pgsql85dev.4string/src/interfaces/ecpg/include/ecpgtype.h *** pgsql85dev.3describe/src/interfaces/ecpg/include/ecpgtype.h 2009-07-14 20:28:50.644801933 +0200 --- pgsql85dev.4string/src/interfaces/ecpg/include/ecpgtype.h 2009-07-14 21:36:58.584800118 +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 pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.addons pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.addons *** pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.addons 2009-07-14 21:26:31.594800717 +0200 --- pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.addons 2009-07-14 21:36:58.585801153 +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", FALSE); + 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 pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.header pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.header *** pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.header 2009-06-13 18:25:05.000000000 +0200 --- pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.header 2009-07-15 11:19:06.423546668 +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 *** 343,348 **** --- 343,350 ---- type_enum == ECPGt_union) && initializer == 1) mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in type definition"); + else if (INFORMIX_MODE && strcmp(name, "string") == 0) + mmerror(PARSE_ERROR, ET_ERROR, "type name \"string\" is reserved in Informix mode"); else { for (ptr = types; ptr != NULL; ptr = ptr->next) *************** add_typedef(char *name, char * dimension *** 371,376 **** --- 373,379 ---- 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 pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.tokens pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.tokens *** pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.tokens 2008-11-14 11:03:33.000000000 +0100 --- pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.tokens 2009-07-14 21:36:58.596799901 +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 pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.trailer pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.trailer *** pgsql85dev.3describe/src/interfaces/ecpg/preproc/ecpg.trailer 2009-07-14 21:27:26.131801570 +0200 --- pgsql85dev.4string/src/interfaces/ecpg/preproc/ecpg.trailer 2009-07-14 21:36:58.598800505 +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 *** 596,613 **** else { /* this is for typedef'ed types */ ! struct typedefs *this = get_typedef($1); ! $$.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); } } | s_struct_union_symbol --- 597,630 ---- else { /* this is for typedef'ed types */ ! struct typedefs *this = get_typedef($1, FALSE); ! if (this == NULL) ! { ! if ((strcmp($1, "string") == 0) && INFORMIX_MODE) ! { ! $$.type_enum = ECPGt_string; ! $$.type_str = make_str("char"); ! $$.type_dimension = make_str("-1"); ! $$.type_index = make_str("-1"); ! $$.type_sizeof = NULL; ! } ! else ! mmerror(PARSE_ERROR, ET_FATAL, "type \"%s\" is not defined", $1); ! } ! 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); ! } } } | s_struct_union_symbol *************** var_type: simple_type *** 623,629 **** { /* No */ ! this = get_typedef(name); $$.type_str = mm_strdup(this->name); $$.type_enum = this->type->type_enum; $$.type_dimension = this->type->type_dimension; --- 640,646 ---- { /* No */ ! this = get_typedef(name, TRUE); $$.type_str = mm_strdup(this->name); $$.type_enum = this->type->type_enum; $$.type_dimension = this->type->type_dimension; *************** signed_type: SQL_SHORT { $$ = ECPGt_s *** 795,800 **** --- 812,818 ---- } | SQL_BOOL { $$ = ECPGt_bool; } | CHAR_P { $$ = ECPGt_char; } + | STRING_P { $$ = ECPGt_string; } | DOUBLE_P { $$ = ECPGt_double; } ; *************** variable: opt_pointer ECPGColLabel opt_a *** 855,860 **** --- 873,879 ---- case ECPGt_char: case ECPGt_unsigned_char: + case ECPGt_string: if (atoi(dimension) == -1) { int i = strlen($5); *************** ECPGVar: SQL_VAR *** 1332,1337 **** --- 1351,1357 ---- 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; } *** 2018,2023 **** --- 2038,2044 ---- | 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 pgsql85dev.3describe/src/interfaces/ecpg/preproc/extern.h pgsql85dev.4string/src/interfaces/ecpg/preproc/extern.h *** pgsql85dev.3describe/src/interfaces/ecpg/preproc/extern.h 2009-07-14 20:59:04.846801587 +0200 --- pgsql85dev.4string/src/interfaces/ecpg/preproc/extern.h 2009-07-14 21:36:58.598800505 +0200 *************** extern void add_variable_to_head(struct *** 94,100 **** extern void add_variable_to_tail(struct arguments **, struct variable *, struct variable *); extern void remove_variable_from_list(struct arguments ** list, struct variable * var); extern void dump_variables(struct arguments *, int); ! extern struct typedefs *get_typedef(char *); extern void adjust_array(enum ECPGttype, char **, char **, char *, char *, int, bool); extern void reset_variables(void); extern void check_indicator(struct ECPGtype *); --- 94,100 ---- extern void add_variable_to_tail(struct arguments **, struct variable *, struct variable *); extern void remove_variable_from_list(struct arguments ** list, struct variable * var); extern void dump_variables(struct arguments *, int); ! extern struct typedefs *get_typedef(char *, int); extern void adjust_array(enum ECPGttype, char **, char **, char *, char *, int, bool); extern void reset_variables(void); extern void check_indicator(struct ECPGtype *); diff -dcrpN pgsql85dev.3describe/src/interfaces/ecpg/preproc/type.c pgsql85dev.4string/src/interfaces/ecpg/preproc/type.c *** pgsql85dev.3describe/src/interfaces/ecpg/preproc/type.c 2009-07-14 20:59:41.644799341 +0200 --- pgsql85dev.4string/src/interfaces/ecpg/preproc/type.c 2009-07-14 21:36:58.599800842 +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 pgsql85dev.3describe/src/interfaces/ecpg/preproc/variable.c pgsql85dev.4string/src/interfaces/ecpg/preproc/variable.c *** pgsql85dev.3describe/src/interfaces/ecpg/preproc/variable.c 2009-07-14 16:40:53.576682685 +0200 --- pgsql85dev.4string/src/interfaces/ecpg/preproc/variable.c 2009-07-14 21:36:58.600799922 +0200 *************** check_indicator(struct ECPGtype * var) *** 486,497 **** } struct typedefs * ! get_typedef(char *name) { struct typedefs *this; for (this = types; this && strcmp(this->name, name); this = this->next); ! if (!this) mmerror(PARSE_ERROR, ET_FATAL, "unrecognized data type name \"%s\"", name); return (this); --- 486,497 ---- } struct typedefs * ! get_typedef(char *name, int error) { struct typedefs *this; for (this = types; this && strcmp(this->name, name); this = this->next); ! if (!this && error) mmerror(PARSE_ERROR, ET_FATAL, "unrecognized data type name \"%s\"", name); return (this); *************** 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) {