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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy