? 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);