Re: trouble with to_char('L') - Mailing list pgsql-general

From Hiroshi Inoue
Subject Re: trouble with to_char('L')
Date
Msg-id 4B8853F7.6030908@tpf.co.jp
Whole thread Raw
In response to Re: trouble with to_char('L')  (Bruce Momjian <bruce@momjian.us>)
Responses Re: trouble with to_char('L')
List pgsql-general
Bruce Momjian wrote:
> Hiroshi Inoue wrote:
>> Bruce Momjian wrote:
>>> Where are we on this issue?
>> Oops I forgot it completely.
>> I have a little improved version and would post it tonight.
>
> Ah, very good.  Thanks.

Attached is an improved version.

regards,
Hiroshi Inoue
? formatting.patch
? pg_locale.patch
? pg_locale_20081221.patch
? pg_locale_20090120.patch
? pg_locale_20090422.patch
? pg_locale_20090423.patch
? pg_locale_20090427.patch
? pg_locale_20090608.patch
? pg_locale_20090901.patch
? pg_locale_with_debug.c
Index: pg_locale.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v
retrieving revision 1.51
diff -c -c -r1.51 pg_locale.c
*** pg_locale.c    2 Jan 2010 16:57:54 -0000    1.51
--- pg_locale.c    26 Feb 2010 22:43:52 -0000
***************
*** 386,391 ****
--- 386,449 ----
          free(s->positive_sign);
  }

+ #ifdef    WIN32
+ static char *db_strdup(const char *item, const char *str)
+ {
+     int    encoding = GetDatabaseEncoding();
+     size_t    wchars, ilen, wclen, dstlen;
+     int    utflen, bytes_per_char;
+     wchar_t    *wbuf;
+     char    *dst;
+
+     if (!str[0])
+         return strdup(str);
+     ilen = strlen(str) + 1;
+     wclen = ilen * sizeof(wchar_t);
+     wbuf = (wchar_t *) palloc(wclen);
+     wchars = mbstowcs(wbuf, str, ilen);
+     if (wchars == (size_t) -1)
+         elog(ERROR,
+             "could not convert string to Wide characters:error %lu", GetLastError());
+
+     bytes_per_char = pg_encoding_max_length(PG_UTF8);
+     if (pg_encoding_max_length(encoding) > bytes_per_char)
+         bytes_per_char = pg_encoding_max_length(encoding);
+     dstlen = wchars * bytes_per_char + 1;
+     dst = malloc(dstlen);
+     if (dst == NULL)
+         elog(ERROR, "could not allocate a destination buffer");
+
+     utflen = WideCharToMultiByte(CP_UTF8, 0, wbuf, wchars, dst, dstlen, NULL, NULL);
+     if (utflen == 0)
+         elog(ERROR,
+             "could not convert string %04x to UTF-8:error %lu", wbuf[0], GetLastError());
+     pfree(wbuf);
+
+     dst[utflen] = '\0';
+     if (encoding != PG_UTF8)
+     {
+         PG_TRY();
+         {
+             char *convstr = pg_do_encoding_conversion(dst, utflen, PG_UTF8, encoding);
+             if (dst != convstr)
+             {
+                 strlcpy(dst, convstr, dstlen);
+                 pfree(convstr);
+             }
+         }
+         PG_CATCH();
+         {
+             FlushErrorState();
+             dst[0] = '\0';
+         }
+         PG_END_TRY();
+     }
+
+     return dst;
+ }
+ #else
+ static char *db_strdup(const char *item, const char *str)    {return strdup(str);}
+ #endif /* WIN32 */

  /*
   * Return the POSIX lconv struct (contains number/money formatting
***************
*** 398,403 ****
--- 456,463 ----
      struct lconv *extlconv;
      char       *save_lc_monetary;
      char       *save_lc_numeric;
+     bool    change_lc_ctype = false, is_same_locale = true;
+     char    *save_lc_ctype = NULL;

      /* Did we do it already? */
      if (CurrentLocaleConvValid)
***************
*** 413,422 ****
      if (save_lc_numeric)
          save_lc_numeric = pstrdup(save_lc_numeric);

      setlocale(LC_MONETARY, locale_monetary);
!     setlocale(LC_NUMERIC, locale_numeric);

!     /* Get formatting information */
      extlconv = localeconv();

      /*
--- 473,496 ----
      if (save_lc_numeric)
          save_lc_numeric = pstrdup(save_lc_numeric);

+ #ifdef    WIN32
+     is_same_locale = (stricmp(locale_monetary, locale_numeric) == 0);
+     save_lc_ctype = setlocale(LC_CTYPE, NULL);
+     if (!is_same_locale || save_lc_ctype == NULL || stricmp(locale_monetary, save_lc_ctype) != 0)
+         change_lc_ctype = true;
+     if (change_lc_ctype && save_lc_ctype)
+         save_lc_ctype = pstrdup(save_lc_ctype);
+     else
+         save_lc_ctype = NULL;
+ #endif
+
+     if (change_lc_ctype)
+         setlocale(LC_CTYPE, locale_monetary);
      setlocale(LC_MONETARY, locale_monetary);
!     if (is_same_locale)
!         setlocale(LC_NUMERIC, locale_numeric);

!     /* Get formatting information for LC_MONETARY( and LC_NUMERIC when they are the same) */
      extlconv = localeconv();

      /*
***************
*** 424,442 ****
       * localeconv()'s results.
       */
      CurrentLocaleConv = *extlconv;
!     CurrentLocaleConv.currency_symbol = strdup(extlconv->currency_symbol);
!     CurrentLocaleConv.decimal_point = strdup(extlconv->decimal_point);
!     CurrentLocaleConv.grouping = strdup(extlconv->grouping);
!     CurrentLocaleConv.thousands_sep = strdup(extlconv->thousands_sep);
!     CurrentLocaleConv.int_curr_symbol = strdup(extlconv->int_curr_symbol);
!     CurrentLocaleConv.mon_decimal_point = strdup(extlconv->mon_decimal_point);
      CurrentLocaleConv.mon_grouping = strdup(extlconv->mon_grouping);
!     CurrentLocaleConv.mon_thousands_sep = strdup(extlconv->mon_thousands_sep);
!     CurrentLocaleConv.negative_sign = strdup(extlconv->negative_sign);
!     CurrentLocaleConv.positive_sign = strdup(extlconv->positive_sign);
      CurrentLocaleConv.n_sign_posn = extlconv->n_sign_posn;

      /* Try to restore internal settings */
      if (save_lc_monetary)
      {
          setlocale(LC_MONETARY, save_lc_monetary);
--- 498,528 ----
       * localeconv()'s results.
       */
      CurrentLocaleConv = *extlconv;
!     CurrentLocaleConv.currency_symbol = db_strdup("currency_symbol", extlconv->currency_symbol);
!     CurrentLocaleConv.int_curr_symbol = db_strdup("int_curr_symbol", extlconv->int_curr_symbol);
!     CurrentLocaleConv.mon_decimal_point = db_strdup("mon_decimal_point", extlconv->mon_decimal_point);
      CurrentLocaleConv.mon_grouping = strdup(extlconv->mon_grouping);
!     CurrentLocaleConv.mon_thousands_sep = db_strdup("mon_thousands_sep", extlconv->mon_thousands_sep);
!     CurrentLocaleConv.negative_sign = db_strdup("nagative_sign", extlconv->negative_sign);
!     CurrentLocaleConv.positive_sign = db_strdup("positive_sign", extlconv->positive_sign);
      CurrentLocaleConv.n_sign_posn = extlconv->n_sign_posn;

+     if (!is_same_locale)
+     {
+         setlocale(LC_CTYPE, locale_numeric);
+         setlocale(LC_NUMERIC, locale_numeric);
+         /* Get formatting information for LC_NUMERIC */
+         extlconv = localeconv();
+     }
+     CurrentLocaleConv.decimal_point = db_strdup("decimal_point", extlconv->decimal_point);
+     CurrentLocaleConv.grouping = strdup(extlconv->grouping);
+     CurrentLocaleConv.thousands_sep = db_strdup("thousands_sep", extlconv->thousands_sep);
      /* Try to restore internal settings */
+     if (save_lc_ctype)
+     {
+         setlocale(LC_CTYPE, save_lc_ctype);
+         pfree(save_lc_ctype);
+     }
      if (save_lc_monetary)
      {
          setlocale(LC_MONETARY, save_lc_monetary);

pgsql-general by date:

Previous
From: Scott Marlowe
Date:
Subject: Re: select issue with order v8.1
Next
From: Bill Karwin
Date:
Subject: Automatic index advisor?