aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2012-10-02 11:42:34 -0400
committerBruce Momjian <bruce@momjian.us>2012-10-02 11:42:34 -0400
commitb61837a49f4b4ea12e7ced8e3039ae98908c7c0b (patch)
tree392c6feba56a8e47a1cde30e16c695eb0ea77d79
parent2a4bbed7b80283200216244e98f7f004ad4d735a (diff)
downloadpostgresql-b61837a49f4b4ea12e7ced8e3039ae98908c7c0b.tar.gz
postgresql-b61837a49f4b4ea12e7ced8e3039ae98908c7c0b.zip
In pg_upgrade, try to convert the locale names to canonical form before
comparison; also report the old/new values if they don't match. Backpatch to 9.2.
-rw-r--r--contrib/pg_upgrade/check.c72
1 files changed, 66 insertions, 6 deletions
diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c
index bed10f8fb45..e4fec34195e 100644
--- a/contrib/pg_upgrade/check.c
+++ b/contrib/pg_upgrade/check.c
@@ -21,6 +21,7 @@ static void check_for_prepared_transactions(ClusterInfo *cluster);
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster);
static void check_for_reg_data_type_usage(ClusterInfo *cluster);
static void get_bin_version(ClusterInfo *cluster);
+static char *get_canonical_locale_name(int category, const char *locale);
/*
@@ -359,8 +360,23 @@ set_locale_and_encoding(ClusterInfo *cluster)
i_datcollate = PQfnumber(res, "datcollate");
i_datctype = PQfnumber(res, "datctype");
- ctrl->lc_collate = pg_strdup(PQgetvalue(res, 0, i_datcollate));
- ctrl->lc_ctype = pg_strdup(PQgetvalue(res, 0, i_datctype));
+ if (GET_MAJOR_VERSION(cluster->major_version) < 902)
+ {
+ /*
+ * Pre-9.2 did not canonicalize the supplied locale names
+ * to match what the system returns, while 9.2+ does, so
+ * convert pre-9.2 to match.
+ */
+ ctrl->lc_collate = get_canonical_locale_name(LC_COLLATE,
+ pg_strdup(PQgetvalue(res, 0, i_datcollate)));
+ ctrl->lc_ctype = get_canonical_locale_name(LC_CTYPE,
+ pg_strdup(PQgetvalue(res, 0, i_datctype)));
+ }
+ else
+ {
+ ctrl->lc_collate = pg_strdup(PQgetvalue(res, 0, i_datcollate));
+ ctrl->lc_ctype = pg_strdup(PQgetvalue(res, 0, i_datctype));
+ }
PQclear(res);
}
@@ -390,16 +406,23 @@ static void
check_locale_and_encoding(ControlData *oldctrl,
ControlData *newctrl)
{
- /* These are often defined with inconsistent case, so use pg_strcasecmp(). */
+ /*
+ * These are often defined with inconsistent case, so use pg_strcasecmp().
+ * They also often use inconsistent hyphenation, which we cannot fix, e.g.
+ * UTF-8 vs. UTF8, so at least we display the mismatching values.
+ */
if (pg_strcasecmp(oldctrl->lc_collate, newctrl->lc_collate) != 0)
pg_log(PG_FATAL,
- "old and new cluster lc_collate values do not match\n");
+ "lc_collate cluster values do not match: old \"%s\", new \"%s\"\n",
+ oldctrl->lc_collate, newctrl->lc_collate);
if (pg_strcasecmp(oldctrl->lc_ctype, newctrl->lc_ctype) != 0)
pg_log(PG_FATAL,
- "old and new cluster lc_ctype values do not match\n");
+ "lc_ctype cluster values do not match: old \"%s\", new \"%s\"\n",
+ oldctrl->lc_ctype, newctrl->lc_ctype);
if (pg_strcasecmp(oldctrl->encoding, newctrl->encoding) != 0)
pg_log(PG_FATAL,
- "old and new cluster encoding values do not match\n");
+ "encoding cluster values do not match: old \"%s\", new \"%s\"\n",
+ oldctrl->encoding, newctrl->encoding);
}
@@ -931,3 +954,40 @@ get_bin_version(ClusterInfo *cluster)
cluster->bin_version = (pre_dot * 100 + post_dot) * 100;
}
+
+
+/*
+ * get_canonical_locale_name
+ *
+ * Send the locale name to the system, and hope we get back a canonical
+ * version. This should match the backend's check_locale() function.
+ */
+static char *
+get_canonical_locale_name(int category, const char *locale)
+{
+ char *save;
+ char *res;
+
+ save = setlocale(category, NULL);
+ if (!save)
+ pg_log(PG_FATAL, "failed to get the current locale\n");
+
+ /* 'save' may be pointing at a modifiable scratch variable, so copy it. */
+ save = pg_strdup(save);
+
+ /* set the locale with setlocale, to see if it accepts it. */
+ res = setlocale(category, locale);
+
+ if (!res)
+ pg_log(PG_FATAL, "failed to get system local name for \"%s\"\n", res);
+
+ res = pg_strdup(res);
+
+ /* restore old value. */
+ if (!setlocale(category, save))
+ pg_log(PG_FATAL, "failed to restore old locale \"%s\"\n", save);
+
+ free(save);
+
+ return res;
+}