Skip to content

Commit 31a2632

Browse files
committed
Make initdb throw error for bad locale values.
Historically we've printed a complaint for a bad locale setting, but then fallen back to the environment default. Per discussion, this is not such a great idea, because rectifying an erroneous locale choice post-initdb (perhaps long after data has been loaded) could be enormously expensive. Better to complain and give the user a chance to double-check things. The behavior was particularly bad if the bad setting came from environment variables rather than a bogus command-line switch: in that case not only was there a fallback to C/SQL_ASCII, but the printed complaint was quite unhelpful. It's hard to be entirely sure what variables setlocale looked at, but we can at least give a hint where the problem might be. Per a complaint from Tomas Vondra.
1 parent eb6144b commit 31a2632

File tree

1 file changed

+47
-39
lines changed

1 file changed

+47
-39
lines changed

src/bin/initdb/initdb.c

Lines changed: 47 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ static void trapsig(int signum);
252252
static void check_ok(void);
253253
static char *escape_quotes(const char *src);
254254
static int locale_date_order(const char *locale);
255-
static bool check_locale_name(int category, const char *locale,
255+
static void check_locale_name(int category, const char *locale,
256256
char **canonname);
257257
static bool check_locale_encoding(const char *locale, int encoding);
258258
static void setlocales(void);
@@ -2529,7 +2529,7 @@ locale_date_order(const char *locale)
25292529
}
25302530

25312531
/*
2532-
* Is the locale name valid for the locale category?
2532+
* Verify that locale name is valid for the locale category.
25332533
*
25342534
* If successful, and canonname isn't NULL, a malloc'd copy of the locale's
25352535
* canonical name is stored there. This is especially useful for figuring out
@@ -2540,7 +2540,7 @@ locale_date_order(const char *locale)
25402540
*
25412541
* this should match the backend's check_locale() function
25422542
*/
2543-
static bool
2543+
static void
25442544
check_locale_name(int category, const char *locale, char **canonname)
25452545
{
25462546
char *save;
@@ -2551,7 +2551,11 @@ check_locale_name(int category, const char *locale, char **canonname)
25512551

25522552
save = setlocale(category, NULL);
25532553
if (!save)
2554-
return false; /* won't happen, we hope */
2554+
{
2555+
fprintf(stderr, _("%s: setlocale failed\n"),
2556+
progname);
2557+
exit(1);
2558+
}
25552559

25562560
/* save may be pointing at a modifiable scratch variable, so copy it. */
25572561
save = pg_strdup(save);
@@ -2565,16 +2569,34 @@ check_locale_name(int category, const char *locale, char **canonname)
25652569

25662570
/* restore old value. */
25672571
if (!setlocale(category, save))
2572+
{
25682573
fprintf(stderr, _("%s: failed to restore old locale \"%s\"\n"),
25692574
progname, save);
2575+
exit(1);
2576+
}
25702577
free(save);
25712578

2572-
/* should we exit here? */
2579+
/* complain if locale wasn't valid */
25732580
if (res == NULL)
2574-
fprintf(stderr, _("%s: invalid locale name \"%s\"\n"),
2575-
progname, locale);
2576-
2577-
return (res != NULL);
2581+
{
2582+
if (*locale)
2583+
fprintf(stderr, _("%s: invalid locale name \"%s\"\n"),
2584+
progname, locale);
2585+
else
2586+
{
2587+
/*
2588+
* If no relevant switch was given on command line, locale is an
2589+
* empty string, which is not too helpful to report. Presumably
2590+
* setlocale() found something it did not like in the environment.
2591+
* Ideally we'd report the bad environment variable, but since
2592+
* setlocale's behavior is implementation-specific, it's hard to
2593+
* be sure what it didn't like. Print a safe generic message.
2594+
*/
2595+
fprintf(stderr, _("%s: invalid locale settings; check LANG and LC_* environment variables\n"),
2596+
progname);
2597+
}
2598+
exit(1);
2599+
}
25782600
}
25792601

25802602
/*
@@ -2642,41 +2664,27 @@ setlocales(void)
26422664
}
26432665

26442666
/*
2645-
* canonicalize locale names, and override any missing/invalid values from
2646-
* our current environment
2667+
* canonicalize locale names, and obtain any missing values from our
2668+
* current environment
26472669
*/
26482670

2649-
if (check_locale_name(LC_CTYPE, lc_ctype, &canonname))
2650-
lc_ctype = canonname;
2651-
else
2652-
lc_ctype = pg_strdup(setlocale(LC_CTYPE, NULL));
2653-
if (check_locale_name(LC_COLLATE, lc_collate, &canonname))
2654-
lc_collate = canonname;
2655-
else
2656-
lc_collate = pg_strdup(setlocale(LC_COLLATE, NULL));
2657-
if (check_locale_name(LC_NUMERIC, lc_numeric, &canonname))
2658-
lc_numeric = canonname;
2659-
else
2660-
lc_numeric = pg_strdup(setlocale(LC_NUMERIC, NULL));
2661-
if (check_locale_name(LC_TIME, lc_time, &canonname))
2662-
lc_time = canonname;
2663-
else
2664-
lc_time = pg_strdup(setlocale(LC_TIME, NULL));
2665-
if (check_locale_name(LC_MONETARY, lc_monetary, &canonname))
2666-
lc_monetary = canonname;
2667-
else
2668-
lc_monetary = pg_strdup(setlocale(LC_MONETARY, NULL));
2671+
check_locale_name(LC_CTYPE, lc_ctype, &canonname);
2672+
lc_ctype = canonname;
2673+
check_locale_name(LC_COLLATE, lc_collate, &canonname);
2674+
lc_collate = canonname;
2675+
check_locale_name(LC_NUMERIC, lc_numeric, &canonname);
2676+
lc_numeric = canonname;
2677+
check_locale_name(LC_TIME, lc_time, &canonname);
2678+
lc_time = canonname;
2679+
check_locale_name(LC_MONETARY, lc_monetary, &canonname);
2680+
lc_monetary = canonname;
26692681
#if defined(LC_MESSAGES) && !defined(WIN32)
2670-
if (check_locale_name(LC_MESSAGES, lc_messages, &canonname))
2671-
lc_messages = canonname;
2672-
else
2673-
lc_messages = pg_strdup(setlocale(LC_MESSAGES, NULL));
2682+
check_locale_name(LC_MESSAGES, lc_messages, &canonname);
2683+
lc_messages = canonname;
26742684
#else
26752685
/* when LC_MESSAGES is not available, use the LC_CTYPE setting */
2676-
if (check_locale_name(LC_CTYPE, lc_messages, &canonname))
2677-
lc_messages = canonname;
2678-
else
2679-
lc_messages = pg_strdup(setlocale(LC_CTYPE, NULL));
2686+
check_locale_name(LC_CTYPE, lc_messages, &canonname);
2687+
lc_messages = canonname;
26802688
#endif
26812689
}
26822690

0 commit comments

Comments
 (0)