From a88b6e4cfbff9802906dd400ef334ffa49e7f286 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Thu, 1 Sep 2011 11:08:32 +0300 Subject: setlocale() on Windows doesn't work correctly if the locale name contains dots. I previously worked around this in initdb, mapping the known problematic locale names to aliases that work, but Hiroshi Inoue pointed out that that's not enough because even if you use one of the aliases, like "Chinese_HKG", setlocale(LC_CTYPE, NULL) returns back the long form, ie. "Chinese_Hong Kong S.A.R.". When we try to restore an old locale value by passing that value back to setlocale(), it fails. Note that you are affected by this bug also if you use one of those short-form names manually, so just reverting the hack in initdb won't fix it. To work around that, move the locale name mapping from initdb to a wrapper around setlocale(), so that the mapping is invoked on every setlocale() call. Also, add a few checks for failed setlocale() calls in the backend. These calls shouldn't fail, and if they do there isn't much we can do about it, but at least you'll get a warning. Backpatch to 9.1, where the initdb hack was introduced. The Windows bug affects older versions too if you set locale manually to one of the aliases, but given the lack of complaints from the field, I'm hesitent to backpatch. --- src/backend/utils/adt/pg_locale.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'src/backend/utils/adt/pg_locale.c') diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c index 4a2fd28f475..7112dea0e1e 100644 --- a/src/backend/utils/adt/pg_locale.c +++ b/src/backend/utils/adt/pg_locale.c @@ -239,7 +239,9 @@ check_locale(int category, const char *value) /* set the locale with setlocale, to see if it accepts it. */ ret = (setlocale(category, value) != NULL); - setlocale(category, save); /* assume this won't fail */ + /* restore old value. */ + if (!setlocale(category, save)) + elog(WARNING, "failed to restore old locale"); pfree(save); return ret; @@ -499,13 +501,15 @@ PGLC_localeconv(void) /* Try to restore internal settings */ if (save_lc_monetary) { - setlocale(LC_MONETARY, save_lc_monetary); + if (!setlocale(LC_MONETARY, save_lc_monetary)) + elog(WARNING, "failed to restore old locale"); pfree(save_lc_monetary); } if (save_lc_numeric) { - setlocale(LC_NUMERIC, save_lc_numeric); + if (!setlocale(LC_NUMERIC, save_lc_numeric)) + elog(WARNING, "failed to restore old locale"); pfree(save_lc_numeric); } @@ -513,7 +517,8 @@ PGLC_localeconv(void) /* Try to restore internal ctype settings */ if (save_lc_ctype) { - setlocale(LC_CTYPE, save_lc_ctype); + if (!setlocale(LC_CTYPE, save_lc_ctype)) + elog(WARNING, "failed to restore old locale"); pfree(save_lc_ctype); } #endif @@ -674,7 +679,8 @@ cache_locale_time(void) /* try to restore internal settings */ if (save_lc_time) { - setlocale(LC_TIME, save_lc_time); + if (!setlocale(LC_TIME, save_lc_time)) + elog(WARNING, "failed to restore old locale"); pfree(save_lc_time); } @@ -682,7 +688,8 @@ cache_locale_time(void) /* try to restore internal ctype settings */ if (save_lc_ctype) { - setlocale(LC_CTYPE, save_lc_ctype); + if (!setlocale(LC_CTYPE, save_lc_ctype)) + elog(WARNING, "failed to restore old locale"); pfree(save_lc_ctype); } #endif -- cgit v1.2.3