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

Commit8240401

Browse files
committed
Do not return NULL from pg_newlocale_from_collation().
Previously, pg_newlocale_from_collation() returned NULL as a specialcase for the DEFAULT_COLLATION_OID if the provider was libc. In thatcase the behavior would depend on the last call to setlocale().Now, consistent with the other providers, it will return a pointer todefault_locale, which is not dependent on setlocale().Note: for the C and POSIX locales, the locale_t structure within thepg_locale_t will still be zero, because those locales are implementedwith internal logic and do not use libc at all.lc_collate_is_c() and lc_ctype_is_c() still depend on setlocale() todetermine the current locale, which will be removed in a subsequentcommit.Discussion:https://postgr.es/m/cfd9eb85-c52a-4ec9-a90e-a5e4de56e57d@eisentraut.orgReviewed-by: Peter Eisentraut, Andreas Karlsson
1 parent6a1d8ce commit8240401

File tree

1 file changed

+110
-81
lines changed

1 file changed

+110
-81
lines changed

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

Lines changed: 110 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,103 @@ lc_ctype_is_c(Oid collation)
14611461
return (lookup_collation_cache(collation, true))->ctype_is_c;
14621462
}
14631463

1464+
/* simple subroutine for reporting errors from newlocale() */
1465+
staticvoid
1466+
report_newlocale_failure(constchar*localename)
1467+
{
1468+
intsave_errno;
1469+
1470+
/*
1471+
* Windows doesn't provide any useful error indication from
1472+
* _create_locale(), and BSD-derived platforms don't seem to feel they
1473+
* need to set errno either (even though POSIX is pretty clear that
1474+
* newlocale should do so). So, if errno hasn't been set, assume ENOENT
1475+
* is what to report.
1476+
*/
1477+
if (errno==0)
1478+
errno=ENOENT;
1479+
1480+
/*
1481+
* ENOENT means "no such locale", not "no such file", so clarify that
1482+
* errno with an errdetail message.
1483+
*/
1484+
save_errno=errno;/* auxiliary funcs might change errno */
1485+
ereport(ERROR,
1486+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1487+
errmsg("could not create locale \"%s\": %m",
1488+
localename),
1489+
(save_errno==ENOENT ?
1490+
errdetail("The operating system could not find any locale data for the locale name \"%s\".",
1491+
localename) :0)));
1492+
}
1493+
1494+
/*
1495+
* Initialize the locale_t field.
1496+
*
1497+
* The "C" and "POSIX" locales are not actually handled by libc, so set the
1498+
* locale_t to zero in that case.
1499+
*/
1500+
staticvoid
1501+
make_libc_collator(constchar*collate,constchar*ctype,
1502+
pg_locale_tresult)
1503+
{
1504+
locale_tloc=0;
1505+
1506+
if (strcmp(collate,ctype)==0)
1507+
{
1508+
if (strcmp(ctype,"C")!=0&&strcmp(ctype,"POSIX")!=0)
1509+
{
1510+
/* Normal case where they're the same */
1511+
errno=0;
1512+
#ifndefWIN32
1513+
loc=newlocale(LC_COLLATE_MASK |LC_CTYPE_MASK,collate,
1514+
NULL);
1515+
#else
1516+
loc=_create_locale(LC_ALL,collate);
1517+
#endif
1518+
if (!loc)
1519+
report_newlocale_failure(collate);
1520+
}
1521+
}
1522+
else
1523+
{
1524+
#ifndefWIN32
1525+
/* We need two newlocale() steps */
1526+
locale_tloc1=0;
1527+
1528+
if (strcmp(collate,"C")!=0&&strcmp(collate,"POSIX")!=0)
1529+
{
1530+
errno=0;
1531+
loc1=newlocale(LC_COLLATE_MASK,collate,NULL);
1532+
if (!loc1)
1533+
report_newlocale_failure(collate);
1534+
}
1535+
1536+
if (strcmp(ctype,"C")!=0&&strcmp(ctype,"POSIX")!=0)
1537+
{
1538+
errno=0;
1539+
loc=newlocale(LC_CTYPE_MASK,ctype,loc1);
1540+
if (!loc)
1541+
report_newlocale_failure(ctype);
1542+
}
1543+
else
1544+
loc=loc1;
1545+
#else
1546+
1547+
/*
1548+
* XXX The _create_locale() API doesn't appear to support this. Could
1549+
* perhaps be worked around by changing pg_locale_t to contain two
1550+
* separate fields.
1551+
*/
1552+
ereport(ERROR,
1553+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1554+
errmsg("collations with different collate and ctype values are not supported on this platform")));
1555+
#endif
1556+
}
1557+
1558+
result->info.lt=loc;
1559+
}
1560+
14641561
void
14651562
make_icu_collator(constchar*iculocstr,
14661563
constchar*icurules,
@@ -1514,36 +1611,6 @@ make_icu_collator(const char *iculocstr,
15141611
}
15151612

15161613

1517-
/* simple subroutine for reporting errors from newlocale() */
1518-
staticvoid
1519-
report_newlocale_failure(constchar*localename)
1520-
{
1521-
intsave_errno;
1522-
1523-
/*
1524-
* Windows doesn't provide any useful error indication from
1525-
* _create_locale(), and BSD-derived platforms don't seem to feel they
1526-
* need to set errno either (even though POSIX is pretty clear that
1527-
* newlocale should do so). So, if errno hasn't been set, assume ENOENT
1528-
* is what to report.
1529-
*/
1530-
if (errno==0)
1531-
errno=ENOENT;
1532-
1533-
/*
1534-
* ENOENT means "no such locale", not "no such file", so clarify that
1535-
* errno with an errdetail message.
1536-
*/
1537-
save_errno=errno;/* auxiliary funcs might change errno */
1538-
ereport(ERROR,
1539-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1540-
errmsg("could not create locale \"%s\": %m",
1541-
localename),
1542-
(save_errno==ENOENT ?
1543-
errdetail("The operating system could not find any locale data for the locale name \"%s\".",
1544-
localename) :0)));
1545-
}
1546-
15471614
bool
15481615
pg_locale_deterministic(pg_locale_tlocale)
15491616
{
@@ -1601,7 +1668,17 @@ init_database_collation(void)
16011668
}
16021669
else
16031670
{
1671+
constchar*datcollate;
1672+
constchar*datctype;
1673+
16041674
Assert(dbform->datlocprovider==COLLPROVIDER_LIBC);
1675+
1676+
datum=SysCacheGetAttrNotNull(DATABASEOID,tup,Anum_pg_database_datcollate);
1677+
datcollate=TextDatumGetCString(datum);
1678+
datum=SysCacheGetAttrNotNull(DATABASEOID,tup,Anum_pg_database_datctype);
1679+
datctype=TextDatumGetCString(datum);
1680+
1681+
make_libc_collator(datcollate,datctype,&default_locale);
16051682
}
16061683

16071684
default_locale.provider=dbform->datlocprovider;
@@ -1620,8 +1697,6 @@ init_database_collation(void)
16201697
* Create a pg_locale_t from a collation OID. Results are cached for the
16211698
* lifetime of the backend. Thus, do not free the result with freelocale().
16221699
*
1623-
* As a special optimization, the default/database collation returns 0.
1624-
*
16251700
* For simplicity, we always generate COLLATE + CTYPE even though we
16261701
* might only need one of them. Since this is called only once per session,
16271702
* it shouldn't cost much.
@@ -1635,12 +1710,7 @@ pg_newlocale_from_collation(Oid collid)
16351710
Assert(OidIsValid(collid));
16361711

16371712
if (collid==DEFAULT_COLLATION_OID)
1638-
{
1639-
if (default_locale.provider==COLLPROVIDER_LIBC)
1640-
return (pg_locale_t)0;
1641-
else
1642-
return&default_locale;
1643-
}
1713+
return&default_locale;
16441714

16451715
cache_entry=lookup_collation_cache(collid, false);
16461716

@@ -1679,55 +1749,14 @@ pg_newlocale_from_collation(Oid collid)
16791749
elseif (collform->collprovider==COLLPROVIDER_LIBC)
16801750
{
16811751
constchar*collcollate;
1682-
constchar*collctypepg_attribute_unused();
1683-
locale_tloc;
1752+
constchar*collctype;
16841753

16851754
datum=SysCacheGetAttrNotNull(COLLOID,tp,Anum_pg_collation_collcollate);
16861755
collcollate=TextDatumGetCString(datum);
16871756
datum=SysCacheGetAttrNotNull(COLLOID,tp,Anum_pg_collation_collctype);
16881757
collctype=TextDatumGetCString(datum);
16891758

1690-
if (strcmp(collcollate,collctype)==0)
1691-
{
1692-
/* Normal case where they're the same */
1693-
errno=0;
1694-
#ifndefWIN32
1695-
loc=newlocale(LC_COLLATE_MASK |LC_CTYPE_MASK,collcollate,
1696-
NULL);
1697-
#else
1698-
loc=_create_locale(LC_ALL,collcollate);
1699-
#endif
1700-
if (!loc)
1701-
report_newlocale_failure(collcollate);
1702-
}
1703-
else
1704-
{
1705-
#ifndefWIN32
1706-
/* We need two newlocale() steps */
1707-
locale_tloc1;
1708-
1709-
errno=0;
1710-
loc1=newlocale(LC_COLLATE_MASK,collcollate,NULL);
1711-
if (!loc1)
1712-
report_newlocale_failure(collcollate);
1713-
errno=0;
1714-
loc=newlocale(LC_CTYPE_MASK,collctype,loc1);
1715-
if (!loc)
1716-
report_newlocale_failure(collctype);
1717-
#else
1718-
1719-
/*
1720-
* XXX The _create_locale() API doesn't appear to support
1721-
* this. Could perhaps be worked around by changing
1722-
* pg_locale_t to contain two separate fields.
1723-
*/
1724-
ereport(ERROR,
1725-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1726-
errmsg("collations with different collate and ctype values are not supported on this platform")));
1727-
#endif
1728-
}
1729-
1730-
result.info.lt=loc;
1759+
make_libc_collator(collcollate,collctype,&result);
17311760
}
17321761
elseif (collform->collprovider==COLLPROVIDER_ICU)
17331762
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp