Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc7cea26

Browse files
committed
Replace empty locale name with implied value in CREATE DATABASE and initdb.
setlocale() accepts locale name "" as meaning "the locale specified by theprocess's environment variables". Historically we've accepted that forPostgres' locale settings, too. However, it's fairly unsafe to store anempty string in a new database's pg_database.datcollate or datctype fields,because then the interpretation could vary across postmaster restarts,possibly resulting in index corruption and other unpleasantness.Instead, we should expand "" to whatever it means at the moment of callingCREATE DATABASE, which we can do by saving the value returned bysetlocale().For consistency, make initdb set up the initial lc_xxx parameter values thesame way. initdb was already doing the right thing for empty locale names,but it did not replace non-empty names with setlocale results. On aplatform where setlocale chooses to canonicalize the spellings of localenames, this would result in annoying inconsistency. (It seems that popularimplementations of setlocale don't do such canonicalization, which is apity, but the POSIX spec certainly allows it to be done.) The same riskof inconsistency leads me to not venture back-patching this, although itcould certainly be seen as a longstanding bug.Per report from Jeff Davis, though this is not his proposed patch.
1 parent8279eb4 commitc7cea26

File tree

4 files changed

+90
-41
lines changed

4 files changed

+90
-41
lines changed

‎src/backend/commands/dbcommands.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ createdb(const CreatedbStmt *stmt)
123123
constchar*dbtemplate=NULL;
124124
char*dbcollate=NULL;
125125
char*dbctype=NULL;
126+
char*canonname;
126127
intencoding=-1;
127128
intdbconnlimit=-1;
128129
intnotherbackends;
@@ -318,15 +319,17 @@ createdb(const CreatedbStmt *stmt)
318319
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
319320
errmsg("invalid server encoding %d",encoding)));
320321

321-
/* Check that the chosen locales are valid */
322-
if (!check_locale(LC_COLLATE,dbcollate))
322+
/* Check that the chosen locales are valid, and get canonical spellings */
323+
if (!check_locale(LC_COLLATE,dbcollate,&canonname))
323324
ereport(ERROR,
324325
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
325326
errmsg("invalid locale name %s",dbcollate)));
326-
if (!check_locale(LC_CTYPE,dbctype))
327+
dbcollate=canonname;
328+
if (!check_locale(LC_CTYPE,dbctype,&canonname))
327329
ereport(ERROR,
328330
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
329331
errmsg("invalid locale name %s",dbctype)));
332+
dbctype=canonname;
330333

331334
check_encoding_locale_matches(encoding,dbcollate,dbctype);
332335

‎src/backend/utils/adt/pg_locale.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -222,29 +222,43 @@ pg_perm_setlocale(int category, const char *locale)
222222

223223
/*
224224
* Is the locale name valid for the locale category?
225+
*
226+
* If successful, and canonname isn't NULL, a palloc'd copy of the locale's
227+
* canonical name is stored there. This is especially useful for figuring out
228+
* what locale name "" means (ie, the server environment value). (Actually,
229+
* it seems that on most implementations that's the only thing it's good for;
230+
* we could wish that setlocale gave back a canonically spelled version of
231+
* the locale name, but typically it doesn't.)
225232
*/
226233
bool
227-
check_locale(intcategory,constchar*value)
234+
check_locale(intcategory,constchar*locale,char**canonname)
228235
{
229236
char*save;
230-
boolret;
237+
char*res;
238+
239+
if (canonname)
240+
*canonname=NULL;/* in case of failure */
231241

232242
save=setlocale(category,NULL);
233243
if (!save)
234244
return false;/* won't happen, we hope */
235245

236-
/* save may be pointing at a modifiable scratch variable, see above */
246+
/* save may be pointing at a modifiable scratch variable, see above. */
237247
save=pstrdup(save);
238248

239249
/* set the locale with setlocale, to see if it accepts it. */
240-
ret= (setlocale(category,value)!=NULL);
250+
res=setlocale(category,locale);
251+
252+
/* save canonical name if requested. */
253+
if (res&&canonname)
254+
*canonname=pstrdup(res);
241255

242256
/* restore old value. */
243257
if (!setlocale(category,save))
244-
elog(WARNING,"failed to restore old locale");
258+
elog(WARNING,"failed to restore old locale \"%s\"",save);
245259
pfree(save);
246260

247-
returnret;
261+
return(res!=NULL);
248262
}
249263

250264

@@ -262,7 +276,7 @@ check_locale(int category, const char *value)
262276
bool
263277
check_locale_monetary(char**newval,void**extra,GucSourcesource)
264278
{
265-
returncheck_locale(LC_MONETARY,*newval);
279+
returncheck_locale(LC_MONETARY,*newval,NULL);
266280
}
267281

268282
void
@@ -274,7 +288,7 @@ assign_locale_monetary(const char *newval, void *extra)
274288
bool
275289
check_locale_numeric(char**newval,void**extra,GucSourcesource)
276290
{
277-
returncheck_locale(LC_NUMERIC,*newval);
291+
returncheck_locale(LC_NUMERIC,*newval,NULL);
278292
}
279293

280294
void
@@ -286,7 +300,7 @@ assign_locale_numeric(const char *newval, void *extra)
286300
bool
287301
check_locale_time(char**newval,void**extra,GucSourcesource)
288302
{
289-
returncheck_locale(LC_TIME,*newval);
303+
returncheck_locale(LC_TIME,*newval,NULL);
290304
}
291305

292306
void
@@ -322,7 +336,7 @@ check_locale_messages(char **newval, void **extra, GucSource source)
322336
* On Windows, we can't even check the value, so accept blindly
323337
*/
324338
#if defined(LC_MESSAGES)&& !defined(WIN32)
325-
returncheck_locale(LC_MESSAGES,*newval);
339+
returncheck_locale(LC_MESSAGES,*newval,NULL);
326340
#else
327341
return true;
328342
#endif

‎src/bin/initdb/initdb.c

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,8 @@ static void trapsig(int signum);
213213
staticvoidcheck_ok(void);
214214
staticchar*escape_quotes(constchar*src);
215215
staticintlocale_date_order(constchar*locale);
216-
staticboolcheck_locale_name(constchar*locale);
216+
staticboolcheck_locale_name(intcategory,constchar*locale,
217+
char**canonname);
217218
staticboolcheck_locale_encoding(constchar*locale,intencoding);
218219
staticvoidsetlocales(void);
219220
staticvoidusage(constchar*progname);
@@ -2240,33 +2241,52 @@ locale_date_order(const char *locale)
22402241
}
22412242

22422243
/*
2243-
*check if given string is a valid localespecifier
2244+
*Is the locale name valid for the localecategory?
22442245
*
2245-
* this should match the backend check_locale() function
2246+
* If successful, and canonname isn't NULL, a malloc'd copy of the locale's
2247+
* canonical name is stored there. This is especially useful for figuring out
2248+
* what locale name "" means (ie, the environment value). (Actually,
2249+
* it seems that on most implementations that's the only thing it's good for;
2250+
* we could wish that setlocale gave back a canonically spelled version of
2251+
* the locale name, but typically it doesn't.)
2252+
*
2253+
* this should match the backend's check_locale() function
22462254
*/
22472255
staticbool
2248-
check_locale_name(constchar*locale)
2256+
check_locale_name(intcategory,constchar*locale,char**canonname)
22492257
{
2250-
boolret;
2251-
intcategory=LC_CTYPE;
22522258
char*save;
2259+
char*res;
2260+
2261+
if (canonname)
2262+
*canonname=NULL;/* in case of failure */
22532263

22542264
save=setlocale(category,NULL);
22552265
if (!save)
2256-
return false;/*should nothappen; */
2266+
return false;/*won'thappen, we hope */
22572267

2268+
/* save may be pointing at a modifiable scratch variable, so copy it. */
22582269
save=xstrdup(save);
22592270

2260-
ret= (setlocale(category,locale)!=NULL);
2271+
/* set the locale with setlocale, to see if it accepts it. */
2272+
res=setlocale(category,locale);
22612273

2262-
setlocale(category,save);
2274+
/* save canonical name if requested. */
2275+
if (res&&canonname)
2276+
*canonname=xstrdup(res);
2277+
2278+
/* restore old value. */
2279+
if (!setlocale(category,save))
2280+
fprintf(stderr,_("%s: failed to restore old locale \"%s\"\n"),
2281+
progname,save);
22632282
free(save);
22642283

22652284
/* should we exit here? */
2266-
if (!ret)
2267-
fprintf(stderr,_("%s: invalid locale name \"%s\"\n"),progname,locale);
2285+
if (res==NULL)
2286+
fprintf(stderr,_("%s: invalid locale name \"%s\"\n"),
2287+
progname,locale);
22682288

2269-
returnret;
2289+
return(res!=NULL);
22702290
}
22712291

22722292
/*
@@ -2308,11 +2328,13 @@ check_locale_encoding(const char *locale, int user_enc)
23082328
/*
23092329
* set up the locale variables
23102330
*
2311-
* assumes we have called setlocale(LC_ALL,"")
2331+
* assumes we have called setlocale(LC_ALL,"") -- see set_pglocale_pgservice
23122332
*/
23132333
staticvoid
23142334
setlocales(void)
23152335
{
2336+
char*canonname;
2337+
23162338
/* set empty lc_* values to locale config if set */
23172339

23182340
if (strlen(locale)>0)
@@ -2332,32 +2354,42 @@ setlocales(void)
23322354
}
23332355

23342356
/*
2335-
* override absent/invalid config settings from initdb's locale settings
2357+
* canonicalize locale names, and override any missing/invalid values from
2358+
* our current environment
23362359
*/
23372360

2338-
if (strlen(lc_ctype)==0|| !check_locale_name(lc_ctype))
2361+
if (check_locale_name(LC_CTYPE,lc_ctype,&canonname))
2362+
lc_ctype=canonname;
2363+
else
23392364
lc_ctype=xstrdup(setlocale(LC_CTYPE,NULL));
2340-
if (strlen(lc_collate)==0|| !check_locale_name(lc_collate))
2365+
if (check_locale_name(LC_COLLATE,lc_collate,&canonname))
2366+
lc_collate=canonname;
2367+
else
23412368
lc_collate=xstrdup(setlocale(LC_COLLATE,NULL));
2342-
if (strlen(lc_numeric)==0|| !check_locale_name(lc_numeric))
2369+
if (check_locale_name(LC_NUMERIC,lc_numeric,&canonname))
2370+
lc_numeric=canonname;
2371+
else
23432372
lc_numeric=xstrdup(setlocale(LC_NUMERIC,NULL));
2344-
if (strlen(lc_time)==0|| !check_locale_name(lc_time))
2373+
if (check_locale_name(LC_TIME,lc_time,&canonname))
2374+
lc_time=canonname;
2375+
else
23452376
lc_time=xstrdup(setlocale(LC_TIME,NULL));
2346-
if (strlen(lc_monetary)==0|| !check_locale_name(lc_monetary))
2377+
if (check_locale_name(LC_MONETARY,lc_monetary,&canonname))
2378+
lc_monetary=canonname;
2379+
else
23472380
lc_monetary=xstrdup(setlocale(LC_MONETARY,NULL));
2348-
if (strlen(lc_messages)==0|| !check_locale_name(lc_messages))
23492381
#if defined(LC_MESSAGES)&& !defined(WIN32)
2350-
{
2351-
/* when available get the current locale setting */
2382+
if (check_locale_name(LC_MESSAGES,lc_messages,&canonname))
2383+
lc_messages=canonname;
2384+
else
23522385
lc_messages=xstrdup(setlocale(LC_MESSAGES,NULL));
2353-
}
23542386
#else
2355-
{
2356-
/* when not available, get the CTYPE setting */
2387+
/* when LC_MESSAGES is not available, use the LC_CTYPE setting */
2388+
if (check_locale_name(LC_CTYPE,lc_messages,&canonname))
2389+
lc_messages=canonname;
2390+
else
23572391
lc_messages=xstrdup(setlocale(LC_CTYPE,NULL));
2358-
}
23592392
#endif
2360-
23612393
}
23622394

23632395
#ifdefWIN32

‎src/include/utils/pg_locale.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ extern void assign_locale_numeric(const char *newval, void *extra);
4242
externboolcheck_locale_time(char**newval,void**extra,GucSourcesource);
4343
externvoidassign_locale_time(constchar*newval,void*extra);
4444

45-
externboolcheck_locale(intcategory,constchar*locale);
45+
externboolcheck_locale(intcategory,constchar*locale,char**canonname);
4646
externchar*pg_perm_setlocale(intcategory,constchar*locale);
4747

4848
externboollc_collate_is_c(Oidcollation);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp