Re: trouble with to_char('L')

From: Bruce Momjian <bruce(at)momjian(dot)us>
To: Hiroshi Inoue <inoue(at)tpf(dot)co(dot)jp>
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Alvaro Herrera <alvherre(at)commandprompt(dot)com>, Mikko <mhannesy(at)gmail(dot)com>, pgsql-general(at)postgresql(dot)org
Subject: Re: trouble with to_char('L')
Date: 2010-02-25 23:21:58
Message-ID: 201002252321.o1PNLw603637@momjian.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general pgsql-hackers


Where are we on this issue?

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

Hiroshi Inoue wrote:
> Tom Lane wrote:
> > Alvaro Herrera <alvherre(at)commandprompt(dot)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(at)postgresql(dot)org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-general

--
Bruce Momjian <bruce(at)momjian(dot)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. +

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Tom Lane 2010-02-25 23:32:05 Re: trouble with to_char('L')
Previous Message Bruce Momjian 2010-02-25 22:24:47 Re: After each row trigger NOT seeing data changes?

Browse pgsql-hackers by date

  From Date Subject
Next Message David Fetter 2010-02-25 23:29:02 Re: strict version of version_stamp.pl
Previous Message Bruce Momjian 2010-02-25 22:39:10 Re: strict version of version_stamp.pl