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

From Hiroshi Inoue
Subject Re: trouble with to_char('L')
Date
Msg-id 49EF8DA0.90008@tpf.co.jp
Whole thread Raw
In response to Re: trouble with to_char('L')  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: trouble with to_char('L')
List pgsql-general
Tom Lane wrote:
> Alvaro Herrera <alvherre@commandprompt.com> writes:
>> Does this imply that we shouldn't allow UTF8 database on Windows at all?
>
> That would be pretty unfortunate :-(
>
> I think what this suggests is that there probably needs to be some
> encoding conversion logic near the places we examine localeconv()
> output.

Attached is a patch to the current CVS.
It uses a similar way like LC_TIME stuff does.

regards,
Hiroshi Inoue
Index: pg_locale.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v
retrieving revision 1.49
diff -c -c -r1.49 pg_locale.c
*** pg_locale.c    1 Apr 2009 09:17:32 -0000    1.49
--- pg_locale.c    22 Apr 2009 21:08:33 -0000
***************
*** 386,391 ****
--- 386,449 ----
          free(s->positive_sign);
  }

+ #ifdef    WIN32
+ #define    MAX_BYTES_PER_CHARACTER    4
+ static char *dbstr_win32(bool matchenc, const char *str)
+ {
+     int    encoding = GetDatabaseEncoding();
+     bool    is_ascii = true;
+     size_t    len, ilen, wclen, dstlen;
+     wchar_t    *wbuf;
+     char    *dst, *ibuf;
+
+     if (matchenc)
+         return strdup(str);
+     /* Is the str an ascii string ? */
+     for (ibuf = str; *ibuf; ibuf++)
+     {
+         if (!isascii(*ibuf))
+         {
+             is_ascii = false;
+             break;
+         }
+     }
+     /* Simply returns the strdup()ed ascii string */
+     if (is_ascii)
+         return strdup(str);
+
+     ilen = strlen(str) + 1;
+     wclen = ilen * sizeof(wchar_t);
+     wbuf = (wchar_t *) palloc(wclen);
+     len = mbstowcs(wbuf, str, ilen);
+     if (len == -1)
+         elog(ERROR,
+             "could not convert string to Wide characters:error %lu", GetLastError());
+
+     dstlen = len * MAX_BYTES_PER_CHARACTER + 1;
+     dst = malloc(dstlen);
+
+     len = WideCharToMultiByte(CP_UTF8, 0, wbuf, len, dst, dstlen, NULL, NULL);
+     pfree(wbuf);
+     if (len == 0)
+         elog(ERROR,
+             "could not convert string to UTF-8:error %lu", GetLastError());
+
+     dst[len] = '\0';
+     if (encoding != PG_UTF8)
+     {
+         char *convstr = pg_do_encoding_conversion(dst, len, PG_UTF8, encoding);
+         if (dst != convstr)
+         {
+             strlcpy(dst, convstr, dstlen);
+             pfree(convstr);
+         }
+     }
+
+     return dst;
+ }
+
+ #define    strdup(str)    dbstr_win32(is_encoding_match, str)
+ #endif /* WIN32 */

  /*
   * Return the POSIX lconv struct (contains number/money formatting
***************
*** 398,403 ****
--- 456,466 ----
      struct lconv *extlconv;
      char       *save_lc_monetary;
      char       *save_lc_numeric;
+ #ifdef    WIN32
+     char       *save_lc_ctype = NULL;
+     bool    lc_ctype_change = false, is_encoding_match;
+ #endif /* WIN32 */
+

      /* Did we do it already? */
      if (CurrentLocaleConvValid)
***************
*** 413,418 ****
--- 476,492 ----
      if (save_lc_numeric)
          save_lc_numeric = pstrdup(save_lc_numeric);

+ #ifdef    WIN32
+     save_lc_ctype = setlocale(LC_CTYPE, NULL);
+     if (save_lc_ctype && stricmp(locale_monetary, save_lc_ctype) != 0)
+     {
+         lc_ctype_change = true;
+         save_lc_ctype = pstrdup(save_lc_ctype);
+         setlocale(LC_CTYPE, locale_monetary);
+     }
+     is_encoding_match = (pg_get_encoding_from_locale(locale_monetary) == GetDatabaseEncoding());
+ #endif
+
      setlocale(LC_MONETARY, locale_monetary);
      setlocale(LC_NUMERIC, locale_numeric);

***************
*** 437,442 ****
--- 511,524 ----
      CurrentLocaleConv.n_sign_posn = extlconv->n_sign_posn;

      /* Try to restore internal settings */
+ #ifdef    WIN32
+ #undef    strdup
+     if (lc_ctype_change)
+     {
+         setlocale(LC_CTYPE, save_lc_ctype);
+         pfree(save_lc_ctype);
+     }
+ #endif /* WIN32 */
      if (save_lc_monetary)
      {
          setlocale(LC_MONETARY, save_lc_monetary);

pgsql-general by date:

Previous
From: Filip Rembiałkowski
Date:
Subject: Re: Help request to improve function performance
Next
From: zach cruise
Date:
Subject: how to search for relation by name?