OSDN Git Service

Modify pg_upgrade to set/restore all environment variables related to
authorBruce Momjian <bruce@momjian.us>
Tue, 7 Sep 2010 14:10:39 +0000 (14:10 +0000)
committerBruce Momjian <bruce@momjian.us>
Tue, 7 Sep 2010 14:10:39 +0000 (14:10 +0000)
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
src/port/unsetenv.c

index 18c1e89..fe1b396 100644 (file)
@@ -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.9.2.1 2010/09/07 14:10:38 momjian Exp $
  */
 
 #include "pg_upgrade.h"
 
 #include <ctype.h>
 
+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
+       }
+}
index df8bda5..1e4c626 100644 (file)
@@ -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.11.6.1 2010/09/07 14:10:39 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.