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

Commit 76fdf7a

Browse files
author
Marina Polyakova
committed
ICU: fix the use of locale names in Windows for ICU functions 3
Return the function _create_locale because although it returns different locales for the same locale names, these locales have the same Language Code Identifier (LCID). Therefore use LCID to get the canonical name of the ICU locale. Return the ability to use language and country strings in locale names e.g. "Russian_Russia[.encoding]" or "English_United States[.encoding]".
1 parent a093ea7 commit 76fdf7a

File tree

6 files changed

+142
-241
lines changed

6 files changed

+142
-241
lines changed

src/backend/commands/dbcommands.c

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,6 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
152152
char *icu_wincollate = NULL;
153153
char *langtag = NULL;
154154
const char *collate;
155-
#ifdef WIN32
156-
char *dbcollate_original;
157-
char *dbctype_original;
158-
#endif
159155

160156
/* Extract options from the statement node tree */
161157
foreach(option, stmt->options)
@@ -398,11 +394,6 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
398394

399395
/* Check that the chosen locales are valid, and get canonical spellings */
400396

401-
#ifdef WIN32
402-
dbcollate_original = dbcollate;
403-
dbctype_original = dbctype;
404-
#endif
405-
406397
if (!check_locale(LC_CTYPE, dbctype, &canonname, '\0'))
407398
ereport(ERROR,
408399
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
@@ -439,15 +430,6 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
439430
/* check lc_collate and lc_ctype for icu if we need it */
440431
if (dbcollprovider == COLLPROVIDER_ICU)
441432
{
442-
#ifdef WIN32
443-
/* set the libc canonnames for dbcollate and dbctype */
444-
445-
check_winlocale(dbcollate_original, &canonname, NULL);
446-
dbcollate = canonname;
447-
448-
check_winlocale(dbctype_original, &canonname, NULL);
449-
dbctype = canonname;
450-
#endif
451433
if (!check_locale(LC_COLLATE, dbcollate, NULL, dbcollprovider))
452434
ereport(ERROR,
453435
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
@@ -467,20 +449,19 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
467449
#ifdef USE_ICU
468450
if (dbcollprovider == COLLPROVIDER_ICU)
469451
{
452+
collate = (const char *) dbcollate;
470453
#ifdef WIN32
471-
if (!locale_is_c(dbcollate))
454+
if (!locale_is_c(collate))
472455
{
473-
check_winlocale(dbcollate, NULL, &icu_wincollate);
456+
icu_wincollate = check_icu_winlocale(collate);
474457
collate = (const char *) icu_wincollate;
475458
}
476-
#else /* not WIN32 */
477-
collate = (const char *) dbcollate;
478-
#endif /* not WIN32 */
459+
#endif /* WIN32 */
479460
langtag = get_icu_language_tag(collate);
480461
collate = get_icu_collate(collate, langtag);
481462
}
482463
else
483-
#endif
464+
#endif /* USE_ICU */
484465
{
485466
/* COLLPROVIDER_LIBC */
486467
collate = (const char *) dbcollate;

src/backend/utils/adt/pg_locale.c

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1836,9 +1836,6 @@ char2wchar(wchar_t *to, size_t tolen, const char *from, size_t fromlen,
18361836
* If locale is "" return the environment value from setlocale().
18371837
*
18381838
* Otherwise return a malloc'd copy of locale if it is not NULL.
1839-
*
1840-
* In Windows, check that the name is not long (for example,
1841-
* "English_United States[.encoding]").
18421839
*/
18431840
static char *
18441841
check_icu_locale(const char *locale)
@@ -1847,19 +1844,20 @@ check_icu_locale(const char *locale)
18471844
char *winlocale = NULL;
18481845
char *result;
18491846

1847+
/* Windows locales can be in the format ".codepage" */
1848+
if (locale && (strlen(locale) == 0 || locale[0] == '.'))
1849+
{
1850+
check_locale(LC_COLLATE, locale, &canonname, COLLPROVIDER_LIBC);
1851+
locale = (const char *) canonname;
1852+
}
1853+
18501854
#ifdef WIN32
18511855
if (!locale_is_c(locale))
18521856
{
1853-
check_winlocale(locale, NULL, &winlocale);
1857+
winlocale = check_icu_winlocale(locale);
18541858
locale = (const char *) winlocale;
18551859
}
1856-
#else /* not WIN32 */
1857-
if (locale && strlen(locale) == 0)
1858-
{
1859-
check_locale(LC_COLLATE, locale, &canonname, COLLPROVIDER_LIBC);
1860-
locale = (const char *) canonname;
1861-
}
1862-
#endif /* not WIN32 */
1860+
#endif
18631861

18641862
result = locale ? pstrdup(locale) : NULL;
18651863

src/backend/utils/init/postinit.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,15 +442,15 @@ CheckMyDatabase(const char *name, bool am_superuser)
442442
#ifdef WIN32
443443
if (!locale_is_c(collcollate))
444444
{
445-
check_winlocale(collcollate, NULL, &wincollate);
445+
wincollate = check_icu_winlocale(collcollate);
446446
collcollate = (const char *) wincollate;
447447
}
448448
#endif /* WIN32 */
449449
langtag = get_icu_language_tag(collcollate);
450450
collcollate = get_icu_collate(collcollate, langtag);
451451
}
452452
else
453-
#endif
453+
#endif /* USE_ICU */
454454
{
455455
/* COLLPROVIDER_LIBC */
456456
collcollate = (const char *) collate;

src/bin/initdb/initdb.c

Lines changed: 19 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2357,10 +2357,6 @@ static void
23572357
setlocales(void)
23582358
{
23592359
char *canonname;
2360-
#ifdef WIN32
2361-
char *lc_collate_original;
2362-
char *lc_ctype_original;
2363-
#endif
23642360

23652361
/*
23662362
* Set up the collation provider if possible and canonicalize the locale
@@ -2409,11 +2405,6 @@ setlocales(void)
24092405
* current environment
24102406
*/
24112407

2412-
#ifdef WIN32
2413-
lc_collate_original = pstrdup(lc_collate);
2414-
lc_ctype_original = pstrdup(lc_ctype);
2415-
#endif
2416-
24172408
check_locale_name(LC_CTYPE, lc_ctype, &canonname, '\0');
24182409
lc_ctype = canonname;
24192410

@@ -2442,23 +2433,6 @@ setlocales(void)
24422433
/* check lc_collate and lc_ctype for icu if we need it */
24432434
if (collprovider == COLLPROVIDER_ICU)
24442435
{
2445-
#ifdef WIN32
2446-
/* set the libc canonnames for lc_collate and lc_ctype */
2447-
2448-
check_winlocale(lc_collate_original, &canonname, NULL);
2449-
if (canonname == NULL && lc_collate_original != NULL)
2450-
exit(1); /* check_winlocale printed the error */
2451-
2452-
pfree(lc_collate);
2453-
lc_collate = canonname;
2454-
2455-
check_winlocale(lc_ctype_original, &canonname, NULL);
2456-
if (canonname == NULL && lc_ctype_original != NULL)
2457-
exit(1); /* check_winlocale printed the error */
2458-
2459-
pfree(lc_ctype);
2460-
lc_ctype = canonname;
2461-
#endif
24622436
check_locale_name(LC_COLLATE, lc_collate, NULL, collprovider);
24632437
if (strcmp(lc_collate, lc_ctype) != 0)
24642438
{
@@ -2485,11 +2459,6 @@ setlocales(void)
24852459
#endif
24862460

24872461
set_collation_version();
2488-
2489-
#ifdef WIN32
2490-
free(lc_collate_original);
2491-
free(lc_ctype_original);
2492-
#endif
24932462
}
24942463

24952464
/*
@@ -3505,9 +3474,6 @@ main(int argc, char *argv[])
35053474
*
35063475
* Otherwise return a malloc'd copy of locale if it is not NULL.
35073476
*
3508-
* In Windows, check that the name is not long (for example,
3509-
* "English_United States[.encoding]").
3510-
*
35113477
* This should match the backend's check_icu_locale() function.
35123478
*/
35133479
static char *
@@ -3517,23 +3483,24 @@ check_icu_locale_name(const char *locale)
35173483
char *winlocale = NULL;
35183484
char *result;
35193485

3486+
/* Windows locales can be in the format ".codepage" */
3487+
if (locale && (strlen(locale) == 0 || locale[0] == '.'))
3488+
{
3489+
check_locale_name(LC_COLLATE, locale, &canonname, COLLPROVIDER_LIBC);
3490+
locale = (const char *) canonname;
3491+
}
3492+
35203493
#ifdef WIN32
35213494
if (!locale_is_c(locale))
35223495
{
3523-
check_winlocale(locale, NULL, &winlocale);
3496+
winlocale = check_icu_winlocale(locale);
35243497

35253498
if (winlocale == NULL && locale != NULL)
3526-
exit(1); /* check_winlocale printed the error */
3499+
exit(1); /* check_icu_winlocale printed the error */
35273500
else
35283501
locale = winlocale;
35293502
}
3530-
#else /* not WIN32 */
3531-
if (locale && strlen(locale) == 0)
3532-
{
3533-
check_locale_name(LC_COLLATE, locale, &canonname, COLLPROVIDER_LIBC);
3534-
locale = (const char *) canonname;
3535-
}
3536-
#endif /* not WIN32 */
3503+
#endif
35373504

35383505
result = locale ? pstrdup(locale) : NULL;
35393506

@@ -3562,19 +3529,19 @@ set_collation_version(void)
35623529
if (collprovider == COLLPROVIDER_ICU)
35633530
{
35643531
#ifdef USE_ICU
3532+
collate = (const char *) lc_collate;
3533+
35653534
#ifdef WIN32
3566-
if (!locale_is_c(lc_collate))
3535+
if (!locale_is_c(collate))
35673536
{
3568-
check_winlocale(lc_collate, NULL, &wincollate);
3537+
wincollate = check_icu_winlocale(collate);
35693538

3570-
if (wincollate == NULL && lc_collate != NULL)
3571-
exit(1); /* check_winlocale printed the error */
3539+
if (wincollate == NULL && collate != NULL)
3540+
exit(1); /* check_icu_winlocale printed the error */
35723541
else
35733542
collate = (const char *) wincollate;
35743543
}
3575-
#else /* not WIN32 */
3576-
collate = (const char *) lc_collate;
3577-
#endif /* not WIN32 */
3544+
#endif /* WIN32 */
35783545

35793546
langtag = get_icu_language_tag(collate);
35803547
if (!langtag)
@@ -3585,13 +3552,13 @@ set_collation_version(void)
35853552
exit(1);
35863553
}
35873554
collate = get_icu_collate(collate, langtag);
3588-
#else
3555+
#else /* not USE_ICU */
35893556
fprintf(stderr,
35903557
_("%s: ICU is not supported in this build\n"
35913558
"You need to rebuild PostgreSQL using --with-icu.\n"),
35923559
progname);
35933560
exit(1);
3594-
#endif
3561+
#endif /* not USE_ICU */
35953562
}
35963563
else
35973564
{

src/include/port.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,8 +491,7 @@ extern UCollator *open_collator(const char *collate);
491491
extern char * get_icu_language_tag(const char *localename);
492492
extern const char *get_icu_collate(const char *locale, const char *langtag);
493493
#ifdef WIN32
494-
extern void check_winlocale(const char *winlocale, char **libc_canononame,
495-
char **icu_canonname);
494+
extern char * check_icu_winlocale(const char *winlocale);
496495
#endif /* WIN32 */
497496
#endif /* USE_ICU */
498497

0 commit comments

Comments
 (0)