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 по дате отправления:

Предыдущее
От: Tom Lane
Дата:
Сообщение: Re: ECPG support for string pseudo-type
Следующее
От: Pavel Stehule
Дата:
Сообщение: problem with varlena and extended type