Re: trouble with to_char('L')

Поиск
Список
Период
Сортировка
От Bruce Momjian
Тема Re: trouble with to_char('L')
Дата
Msg-id 201002252321.o1PNLw603637@momjian.us
обсуждение исходный текст
Ответ на Re: trouble with to_char('L')  (Hiroshi Inoue <inoue@tpf.co.jp>)
Ответы Re: trouble with to_char('L')  (Tom Lane <tgl@sss.pgh.pa.us>)
Re: trouble with to_char('L')  (Hiroshi Inoue <inoue@tpf.co.jp>)
Список pgsql-general
Where are we on this issue?

---------------------------------------------------------------------------

Hiroshi Inoue wrote:
> 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);
>
>
> --
> Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-general

--
  Bruce Momjian  <bruce@momjian.us>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com
  PG East:  http://www.enterprisedb.com/community/nav-pg-east-2010.do
  + If your life is a hard drive, Christ can be your backup. +

В списке pgsql-general по дате отправления:

Предыдущее
От: Bruce Momjian
Дата:
Сообщение: Re: After each row trigger NOT seeing data changes?
Следующее
От: Tom Lane
Дата:
Сообщение: Re: trouble with to_char('L')