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: