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)
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