8989
9090#define MAX_L10N_DATA 80
9191
92+ /* pg_locale_builtin.c */
93+ extern pg_locale_t create_pg_locale_builtin (Oid collid ,MemoryContext context );
94+
9295/* pg_locale_icu.c */
9396#ifdef USE_ICU
9497extern UCollator * pg_ucol_open (const char * loc_str );
95- extern UCollator * make_icu_collator (const char * iculocstr ,
96- const char * icurules );
9798extern int strncoll_icu (const char * arg1 ,ssize_t len1 ,
9899const char * arg2 ,ssize_t len2 ,
99100pg_locale_t locale );
@@ -104,10 +105,10 @@ extern size_t strnxfrm_prefix_icu(char *dest, size_t destsize,
104105const char * src ,ssize_t srclen ,
105106pg_locale_t locale );
106107#endif
108+ extern pg_locale_t create_pg_locale_icu (Oid collid ,MemoryContext context );
107109
108110/* pg_locale_libc.c */
109- extern locale_t make_libc_collator (const char * collate ,
110- const char * ctype );
111+ extern pg_locale_t create_pg_locale_libc (Oid collid ,MemoryContext context );
111112extern int strncoll_libc (const char * arg1 ,ssize_t len1 ,
112113const char * arg2 ,ssize_t len2 ,
113114pg_locale_t locale );
@@ -138,7 +139,7 @@ char *localized_full_months[12 + 1];
138139/* is the databases's LC_CTYPE the C locale? */
139140bool database_ctype_is_c = false;
140141
141- static struct pg_locale_struct default_locale ;
142+ static pg_locale_t default_locale = NULL ;
142143
143144/* indicates whether locale information cache is valid */
144145static bool CurrentLocaleConvValid = false;
@@ -1194,7 +1195,6 @@ IsoLocaleName(const char *winlocname)
11941195
11951196#endif /* WIN32 && LC_MESSAGES */
11961197
1197-
11981198/*
11991199 * Create a new pg_locale_t struct for the given collation oid.
12001200 */
@@ -1207,80 +1207,23 @@ create_pg_locale(Oid collid, MemoryContext context)
12071207Datum datum ;
12081208bool isnull ;
12091209
1210- result = MemoryContextAllocZero (context ,sizeof (struct pg_locale_struct ));
1211-
12121210tp = SearchSysCache1 (COLLOID ,ObjectIdGetDatum (collid ));
12131211if (!HeapTupleIsValid (tp ))
12141212elog (ERROR ,"cache lookup failed for collation %u" ,collid );
12151213collform = (Form_pg_collation )GETSTRUCT (tp );
12161214
1217- result -> provider = collform -> collprovider ;
1218- result -> deterministic = collform -> collisdeterministic ;
1219- result -> is_default = false;
1220-
12211215if (collform -> collprovider == COLLPROVIDER_BUILTIN )
1222- {
1223- const char * locstr ;
1224-
1225- datum = SysCacheGetAttrNotNull (COLLOID ,tp ,Anum_pg_collation_colllocale );
1226- locstr = TextDatumGetCString (datum );
1227-
1228- result -> collate_is_c = true;
1229- result -> ctype_is_c = (strcmp (locstr ,"C" )== 0 );
1230-
1231- builtin_validate_locale (GetDatabaseEncoding (),locstr );
1232-
1233- result -> info .builtin .locale = MemoryContextStrdup (context ,
1234- locstr );
1235- }
1216+ result = create_pg_locale_builtin (collid ,context );
12361217else if (collform -> collprovider == COLLPROVIDER_ICU )
1237- {
1238- #ifdef USE_ICU
1239- const char * iculocstr ;
1240- const char * icurules ;
1241-
1242- datum = SysCacheGetAttrNotNull (COLLOID ,tp ,Anum_pg_collation_colllocale );
1243- iculocstr = TextDatumGetCString (datum );
1244-
1245- result -> collate_is_c = false;
1246- result -> ctype_is_c = false;
1247-
1248- datum = SysCacheGetAttr (COLLOID ,tp ,Anum_pg_collation_collicurules ,& isnull );
1249- if (!isnull )
1250- icurules = TextDatumGetCString (datum );
1251- else
1252- icurules = NULL ;
1253-
1254- result -> info .icu .locale = MemoryContextStrdup (context ,iculocstr );
1255- result -> info .icu .ucol = make_icu_collator (iculocstr ,icurules );
1256- #else
1257- /* could get here if a collation was created by a build with ICU */
1258- ereport (ERROR ,
1259- (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
1260- errmsg ("ICU is not supported in this build" )));
1261- #endif
1262- }
1218+ result = create_pg_locale_icu (collid ,context );
12631219else if (collform -> collprovider == COLLPROVIDER_LIBC )
1264- {
1265- const char * collcollate ;
1266- const char * collctype ;
1267-
1268- datum = SysCacheGetAttrNotNull (COLLOID ,tp ,Anum_pg_collation_collcollate );
1269- collcollate = TextDatumGetCString (datum );
1270- datum = SysCacheGetAttrNotNull (COLLOID ,tp ,Anum_pg_collation_collctype );
1271- collctype = TextDatumGetCString (datum );
1272-
1273- result -> collate_is_c = (strcmp (collcollate ,"C" )== 0 )||
1274- (strcmp (collcollate ,"POSIX" )== 0 );
1275- result -> ctype_is_c = (strcmp (collctype ,"C" )== 0 )||
1276- (strcmp (collctype ,"POSIX" )== 0 );
1277-
1278- result -> info .lt = make_libc_collator (collcollate ,collctype );
1279- }
1220+ result = create_pg_locale_libc (collid ,context );
12801221else
12811222/* shouldn't happen */
12821223PGLOCALE_SUPPORT_ERROR (collform -> collprovider );
12831224
1225+ result -> is_default = false;
1226+
12841227datum = SysCacheGetAttr (COLLOID ,tp ,Anum_pg_collation_collversion ,
12851228& isnull );
12861229if (!isnull )
@@ -1336,7 +1279,9 @@ init_database_collation(void)
13361279{
13371280HeapTuple tup ;
13381281Form_pg_database dbform ;
1339- Datum datum ;
1282+ pg_locale_t result ;
1283+
1284+ Assert (default_locale == NULL );
13401285
13411286/* Fetch our pg_database row normally, via syscache */
13421287tup = SearchSysCache1 (DATABASEOID ,ObjectIdGetDatum (MyDatabaseId ));
@@ -1345,81 +1290,22 @@ init_database_collation(void)
13451290dbform = (Form_pg_database )GETSTRUCT (tup );
13461291
13471292if (dbform -> datlocprovider == COLLPROVIDER_BUILTIN )
1348- {
1349- char * datlocale ;
1350-
1351- datum = SysCacheGetAttrNotNull (DATABASEOID ,tup ,Anum_pg_database_datlocale );
1352- datlocale = TextDatumGetCString (datum );
1353-
1354- builtin_validate_locale (dbform -> encoding ,datlocale );
1355-
1356- default_locale .collate_is_c = true;
1357- default_locale .ctype_is_c = (strcmp (datlocale ,"C" )== 0 );
1358-
1359- default_locale .info .builtin .locale = MemoryContextStrdup (TopMemoryContext ,
1360- datlocale );
1361- }
1293+ result = create_pg_locale_builtin (DEFAULT_COLLATION_OID ,
1294+ TopMemoryContext );
13621295else if (dbform -> datlocprovider == COLLPROVIDER_ICU )
1363- {
1364- #ifdef USE_ICU
1365- char * datlocale ;
1366- char * icurules ;
1367- bool isnull ;
1368-
1369- datum = SysCacheGetAttrNotNull (DATABASEOID ,tup ,Anum_pg_database_datlocale );
1370- datlocale = TextDatumGetCString (datum );
1371-
1372- default_locale .collate_is_c = false;
1373- default_locale .ctype_is_c = false;
1374-
1375- datum = SysCacheGetAttr (DATABASEOID ,tup ,Anum_pg_database_daticurules ,& isnull );
1376- if (!isnull )
1377- icurules = TextDatumGetCString (datum );
1378- else
1379- icurules = NULL ;
1380-
1381- default_locale .info .icu .locale = MemoryContextStrdup (TopMemoryContext ,datlocale );
1382- default_locale .info .icu .ucol = make_icu_collator (datlocale ,icurules );
1383- #else
1384- /* could get here if a collation was created by a build with ICU */
1385- ereport (ERROR ,
1386- (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
1387- errmsg ("ICU is not supported in this build" )));
1388- #endif
1389- }
1296+ result = create_pg_locale_icu (DEFAULT_COLLATION_OID ,
1297+ TopMemoryContext );
13901298else if (dbform -> datlocprovider == COLLPROVIDER_LIBC )
1391- {
1392- const char * datcollate ;
1393- const char * datctype ;
1394-
1395- datum = SysCacheGetAttrNotNull (DATABASEOID ,tup ,Anum_pg_database_datcollate );
1396- datcollate = TextDatumGetCString (datum );
1397- datum = SysCacheGetAttrNotNull (DATABASEOID ,tup ,Anum_pg_database_datctype );
1398- datctype = TextDatumGetCString (datum );
1399-
1400- default_locale .collate_is_c = (strcmp (datcollate ,"C" )== 0 )||
1401- (strcmp (datcollate ,"POSIX" )== 0 );
1402- default_locale .ctype_is_c = (strcmp (datctype ,"C" )== 0 )||
1403- (strcmp (datctype ,"POSIX" )== 0 );
1404-
1405- default_locale .info .lt = make_libc_collator (datcollate ,datctype );
1406- }
1299+ result = create_pg_locale_libc (DEFAULT_COLLATION_OID ,
1300+ TopMemoryContext );
14071301else
14081302/* shouldn't happen */
14091303PGLOCALE_SUPPORT_ERROR (dbform -> datlocprovider );
14101304
1411-
1412- default_locale .provider = dbform -> datlocprovider ;
1413- default_locale .is_default = true;
1414-
1415- /*
1416- * Default locale is currently always deterministic. Nondeterministic
1417- * locales currently don't support pattern matching, which would break a
1418- * lot of things if applied globally.
1419- */
1420- default_locale .deterministic = true;
1421-
1305+ result -> is_default = true;
14221306ReleaseSysCache (tup );
1307+
1308+ default_locale = result ;
14231309}
14241310
14251311/*
@@ -1437,7 +1323,7 @@ pg_newlocale_from_collation(Oid collid)
14371323bool found ;
14381324
14391325if (collid == DEFAULT_COLLATION_OID )
1440- return & default_locale ;
1326+ return default_locale ;
14411327
14421328if (!OidIsValid (collid ))
14431329elog (ERROR ,"cache lookup failed for collation %u" ,collid );