From c5d94a34fbd732762106b4056823bde6969fdfd8 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Tue, 7 Sep 2010 14:10:30 +0000 Subject: [PATCH] Modify pg_upgrade to set/restore all environment variables related to collation/encoding to match English when reading controldata. This now matches the English variable setting used by pg_regress.c. Backpatch to 9.0.X. --- contrib/pg_upgrade/controldata.c | 126 ++++++++++++++++++++++++------- src/port/unsetenv.c | 3 +- 2 files changed, 102 insertions(+), 27 deletions(-) diff --git a/contrib/pg_upgrade/controldata.c b/contrib/pg_upgrade/controldata.c index 18c1e89f4b..cb0b01994e 100644 --- a/contrib/pg_upgrade/controldata.c +++ b/contrib/pg_upgrade/controldata.c @@ -4,13 +4,14 @@ * controldata functions * * Copyright (c) 2010, PostgreSQL Global Development Group - * $PostgreSQL: pgsql/contrib/pg_upgrade/controldata.c,v 1.9 2010/07/06 19:18:55 momjian Exp $ + * $PostgreSQL: pgsql/contrib/pg_upgrade/controldata.c,v 1.10 2010/09/07 14:10:30 momjian Exp $ */ #include "pg_upgrade.h" #include +static void putenv2(migratorContext *ctx, const char *var, const char *val); /* * get_control_data() @@ -51,19 +52,55 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check) bool got_toast = false; bool got_date_is_int = false; bool got_float8_pass_by_value = false; + char *lc_collate = NULL; + char *lc_ctype = NULL; + char *lc_monetary = NULL; + char *lc_numeric = NULL; + char *lc_time = NULL; char *lang = NULL; + char *language = NULL; + char *lc_all = NULL; + char *lc_messages = NULL; /* - * Because we test the pg_resetxlog output strings, it has to be in - * English. + * Because we test the pg_resetxlog output as strings, it has to be in + * English. Copied from pg_regress.c. */ + if (getenv("LC_COLLATE")) + lc_collate = pg_strdup(ctx, getenv("LC_COLLATE")); + if (getenv("LC_CTYPE")) + lc_ctype = pg_strdup(ctx, getenv("LC_CTYPE")); + if (getenv("LC_MONETARY")) + lc_monetary = pg_strdup(ctx, getenv("LC_MONETARY")); + if (getenv("LC_NUMERIC")) + lc_numeric = pg_strdup(ctx, getenv("LC_NUMERIC")); + if (getenv("LC_TIME")) + lc_time = pg_strdup(ctx, getenv("LC_TIME")); if (getenv("LANG")) lang = pg_strdup(ctx, getenv("LANG")); + if (getenv("LANGUAGE")) + language = pg_strdup(ctx, getenv("LANGUAGE")); + if (getenv("LC_ALL")) + lc_all = pg_strdup(ctx, getenv("LC_ALL")); + if (getenv("LC_MESSAGES")) + lc_messages = pg_strdup(ctx, getenv("LC_MESSAGES")); + + putenv2(ctx, "LC_COLLATE", NULL); + putenv2(ctx, "LC_CTYPE", NULL); + putenv2(ctx, "LC_MONETARY", NULL); + putenv2(ctx, "LC_NUMERIC", NULL); + putenv2(ctx, "LC_TIME", NULL); + putenv2(ctx, "LANG", #ifndef WIN32 - putenv(pg_strdup(ctx, "LANG=C")); + NULL); #else - SetEnvironmentVariableA("LANG", "C"); + /* On Windows the default locale cannot be English, so force it */ + "en"); #endif + putenv2(ctx, "LANGUAGE", NULL); + putenv2(ctx, "LC_ALL", NULL); + putenv2(ctx, "LC_MESSAGES", "C"); + snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "\"%s/%s \"%s\"" SYSTEMQUOTE, cluster->bindir, live_check ? "pg_controldata\"" : "pg_resetxlog\" -n", @@ -334,28 +371,29 @@ get_control_data(migratorContext *ctx, ClusterInfo *cluster, bool live_check) if (output) pclose(output); - /* restore LANG */ - if (lang) - { -#ifndef WIN32 - char *envstr = (char *) pg_malloc(ctx, strlen(lang) + 6); - - sprintf(envstr, "LANG=%s", lang); - putenv(envstr); -#else - SetEnvironmentVariableA("LANG", lang); -#endif - pg_free(lang); - } - else - { -#ifndef WIN32 - unsetenv("LANG"); -#else - SetEnvironmentVariableA("LANG", ""); -#endif - } + /* + * Restore environment variables + */ + putenv2(ctx, "LC_COLLATE", lc_collate); + putenv2(ctx, "LC_CTYPE", lc_ctype); + putenv2(ctx, "LC_MONETARY", lc_monetary); + putenv2(ctx, "LC_NUMERIC", lc_numeric); + putenv2(ctx, "LC_TIME", lc_time); + putenv2(ctx, "LANG", lang); + putenv2(ctx, "LANGUAGE", language); + putenv2(ctx, "LC_ALL", lc_all); + putenv2(ctx, "LC_MESSAGES", lc_messages); + pg_free(lc_collate); + pg_free(lc_ctype); + pg_free(lc_monetary); + pg_free(lc_numeric); + pg_free(lc_time); + pg_free(lang); + pg_free(language); + pg_free(lc_all); + pg_free(lc_messages); + /* verify that we got all the mandatory pg_control data */ if (!got_xid || !got_oid || (!live_check && !got_log_id) || @@ -492,3 +530,39 @@ rename_old_pg_control(migratorContext *ctx) pg_log(ctx, PG_FATAL, "Unable to rename %s to %s.\n", old_path, new_path); check_ok(ctx); } + + +/* + * putenv2() + * + * This is like putenv(), but takes two arguments. + * It also does unsetenv() if val is NULL. + */ +static void +putenv2(migratorContext *ctx, const char *var, const char *val) +{ + if (val) + { +#ifndef WIN32 + char *envstr = (char *) pg_malloc(ctx, strlen(var) + + strlen(val) + 1); + + sprintf(envstr, "%s=%s", var, val); + putenv(envstr); + /* + * Do not free envstr because it becomes part of the environment + * on some operating systems. See port/unsetenv.c::unsetenv. + */ +#else + SetEnvironmentVariableA(var, val); +#endif + } + else + { +#ifndef WIN32 + unsetenv(var); +#else + SetEnvironmentVariableA(var, ""); +#endif + } +} diff --git a/src/port/unsetenv.c b/src/port/unsetenv.c index df8bda5633..2110123694 100644 --- a/src/port/unsetenv.c +++ b/src/port/unsetenv.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/port/unsetenv.c,v 1.11 2010/01/02 16:58:13 momjian Exp $ + * $PostgreSQL: pgsql/src/port/unsetenv.c,v 1.12 2010/09/07 14:10:30 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -32,6 +32,7 @@ unsetenv(const char *name) * implementations (notably recent BSDs) that do not obey SUS but copy the * presented string. This method fails on such platforms. Hopefully all * such platforms have unsetenv() and thus won't be using this hack. + * See: http://www.greenend.org.uk/rjk/2008/putenv.html * * Note that repeatedly setting and unsetting a var using this code will * leak memory.