Re: ECPG support for string pseudo-type
От | Boszormenyi Zoltan |
---|---|
Тема | Re: ECPG support for string pseudo-type |
Дата | |
Msg-id | 4A4F7090.6080200@cybertec.at обсуждение исходный текст |
Ответ на | Re: ECPG support for string pseudo-type (Tom Lane <tgl@sss.pgh.pa.us>) |
Ответы |
Re: ECPG support for string pseudo-type
(Michael Meskes <meskes@postgresql.org>)
|
Список | pgsql-hackers |
Hi, Tom Lane írta: > Boszormenyi Zoltan <zb@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) {
В списке pgsql-hackers по дате отправления: