Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b61837a

Browse files
committed
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.
1 parent 2a4bbed commit b61837a

File tree

1 file changed

+66
-6
lines changed

1 file changed

+66
-6
lines changed

contrib/pg_upgrade/check.c

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ static void check_for_prepared_transactions(ClusterInfo *cluster);
2121
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster);
2222
static void check_for_reg_data_type_usage(ClusterInfo *cluster);
2323
static void get_bin_version(ClusterInfo *cluster);
24+
static char *get_canonical_locale_name(int category, const char *locale);
2425

2526

2627
/*
@@ -359,8 +360,23 @@ set_locale_and_encoding(ClusterInfo *cluster)
359360
i_datcollate = PQfnumber(res, "datcollate");
360361
i_datctype = PQfnumber(res, "datctype");
361362

362-
ctrl->lc_collate = pg_strdup(PQgetvalue(res, 0, i_datcollate));
363-
ctrl->lc_ctype = pg_strdup(PQgetvalue(res, 0, i_datctype));
363+
if (GET_MAJOR_VERSION(cluster->major_version) < 902)
364+
{
365+
/*
366+
* Pre-9.2 did not canonicalize the supplied locale names
367+
* to match what the system returns, while 9.2+ does, so
368+
* convert pre-9.2 to match.
369+
*/
370+
ctrl->lc_collate = get_canonical_locale_name(LC_COLLATE,
371+
pg_strdup(PQgetvalue(res, 0, i_datcollate)));
372+
ctrl->lc_ctype = get_canonical_locale_name(LC_CTYPE,
373+
pg_strdup(PQgetvalue(res, 0, i_datctype)));
374+
}
375+
else
376+
{
377+
ctrl->lc_collate = pg_strdup(PQgetvalue(res, 0, i_datcollate));
378+
ctrl->lc_ctype = pg_strdup(PQgetvalue(res, 0, i_datctype));
379+
}
364380

365381
PQclear(res);
366382
}
@@ -390,16 +406,23 @@ static void
390406
check_locale_and_encoding(ControlData *oldctrl,
391407
ControlData *newctrl)
392408
{
393-
/* These are often defined with inconsistent case, so use pg_strcasecmp(). */
409+
/*
410+
* These are often defined with inconsistent case, so use pg_strcasecmp().
411+
* They also often use inconsistent hyphenation, which we cannot fix, e.g.
412+
* UTF-8 vs. UTF8, so at least we display the mismatching values.
413+
*/
394414
if (pg_strcasecmp(oldctrl->lc_collate, newctrl->lc_collate) != 0)
395415
pg_log(PG_FATAL,
396-
"old and new cluster lc_collate values do not match\n");
416+
"lc_collate cluster values do not match: old \"%s\", new \"%s\"\n",
417+
oldctrl->lc_collate, newctrl->lc_collate);
397418
if (pg_strcasecmp(oldctrl->lc_ctype, newctrl->lc_ctype) != 0)
398419
pg_log(PG_FATAL,
399-
"old and new cluster lc_ctype values do not match\n");
420+
"lc_ctype cluster values do not match: old \"%s\", new \"%s\"\n",
421+
oldctrl->lc_ctype, newctrl->lc_ctype);
400422
if (pg_strcasecmp(oldctrl->encoding, newctrl->encoding) != 0)
401423
pg_log(PG_FATAL,
402-
"old and new cluster encoding values do not match\n");
424+
"encoding cluster values do not match: old \"%s\", new \"%s\"\n",
425+
oldctrl->encoding, newctrl->encoding);
403426
}
404427

405428

@@ -931,3 +954,40 @@ get_bin_version(ClusterInfo *cluster)
931954

932955
cluster->bin_version = (pre_dot * 100 + post_dot) * 100;
933956
}
957+
958+
959+
/*
960+
* get_canonical_locale_name
961+
*
962+
* Send the locale name to the system, and hope we get back a canonical
963+
* version. This should match the backend's check_locale() function.
964+
*/
965+
static char *
966+
get_canonical_locale_name(int category, const char *locale)
967+
{
968+
char *save;
969+
char *res;
970+
971+
save = setlocale(category, NULL);
972+
if (!save)
973+
pg_log(PG_FATAL, "failed to get the current locale\n");
974+
975+
/* 'save' may be pointing at a modifiable scratch variable, so copy it. */
976+
save = pg_strdup(save);
977+
978+
/* set the locale with setlocale, to see if it accepts it. */
979+
res = setlocale(category, locale);
980+
981+
if (!res)
982+
pg_log(PG_FATAL, "failed to get system local name for \"%s\"\n", res);
983+
984+
res = pg_strdup(res);
985+
986+
/* restore old value. */
987+
if (!setlocale(category, save))
988+
pg_log(PG_FATAL, "failed to restore old locale \"%s\"\n", save);
989+
990+
free(save);
991+
992+
return res;
993+
}

0 commit comments

Comments
 (0)