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

Commit 3aa2373

Browse files
committed
Refactor the code to create a pg_locale_t into new function.
Reviewed-by: Andreas Karlsson Discussion: https://postgr.es/m/59da7ee4-5e1a-4727-b464-a603c6ed84cd@proxel.se
1 parent 924e039 commit 3aa2373

File tree

1 file changed

+139
-157
lines changed

1 file changed

+139
-157
lines changed

src/backend/utils/adt/pg_locale.c

Lines changed: 139 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,42 +1215,135 @@ IsoLocaleName(const char *winlocname)
12151215

12161216

12171217
/*
1218-
* Cache mechanism for collation information.
1219-
*
1220-
* Note that we currently lack any way to flush the cache. Since we don't
1221-
* support ALTER COLLATION, this is OK. The worst case is that someone
1222-
* drops a collation, and a useless cache entry hangs around in existing
1223-
* backends.
1218+
* Create a new pg_locale_t struct for the given collation oid.
12241219
*/
1225-
static collation_cache_entry *
1226-
lookup_collation_cache(Oid collation)
1220+
static pg_locale_t
1221+
create_pg_locale(Oid collid, MemoryContext context)
12271222
{
1228-
collation_cache_entry *cache_entry;
1229-
bool found;
1223+
HeapTuple tp;
1224+
Form_pg_collation collform;
1225+
pg_locale_t result;
1226+
Datum datum;
1227+
bool isnull;
12301228

1231-
Assert(OidIsValid(collation));
1232-
Assert(collation != DEFAULT_COLLATION_OID);
1229+
result = MemoryContextAllocZero(context, sizeof(struct pg_locale_struct));
12331230

1234-
if (CollationCache == NULL)
1231+
tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
1232+
if (!HeapTupleIsValid(tp))
1233+
elog(ERROR, "cache lookup failed for collation %u", collid);
1234+
collform = (Form_pg_collation) GETSTRUCT(tp);
1235+
1236+
result->provider = collform->collprovider;
1237+
result->deterministic = collform->collisdeterministic;
1238+
1239+
if (collform->collprovider == COLLPROVIDER_BUILTIN)
12351240
{
1236-
CollationCacheContext = AllocSetContextCreate(TopMemoryContext,
1237-
"collation cache",
1238-
ALLOCSET_DEFAULT_SIZES);
1239-
CollationCache = collation_cache_create(CollationCacheContext,
1240-
16, NULL);
1241+
const char *locstr;
1242+
1243+
datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale);
1244+
locstr = TextDatumGetCString(datum);
1245+
1246+
result->collate_is_c = true;
1247+
result->ctype_is_c = (strcmp(locstr, "C") == 0);
1248+
1249+
builtin_validate_locale(GetDatabaseEncoding(), locstr);
1250+
1251+
result->info.builtin.locale = MemoryContextStrdup(context,
1252+
locstr);
12411253
}
1254+
else if (collform->collprovider == COLLPROVIDER_ICU)
1255+
{
1256+
#ifdef USE_ICU
1257+
const char *iculocstr;
1258+
const char *icurules;
12421259

1243-
cache_entry = collation_cache_insert(CollationCache, collation, &found);
1244-
if (!found)
1260+
datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale);
1261+
iculocstr = TextDatumGetCString(datum);
1262+
1263+
result->collate_is_c = false;
1264+
result->ctype_is_c = false;
1265+
1266+
datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collicurules, &isnull);
1267+
if (!isnull)
1268+
icurules = TextDatumGetCString(datum);
1269+
else
1270+
icurules = NULL;
1271+
1272+
result->info.icu.locale = MemoryContextStrdup(context, iculocstr);
1273+
result->info.icu.ucol = make_icu_collator(iculocstr, icurules);
1274+
#else
1275+
/* could get here if a collation was created by a build with ICU */
1276+
ereport(ERROR,
1277+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1278+
errmsg("ICU is not supported in this build")));
1279+
#endif
1280+
}
1281+
else if (collform->collprovider == COLLPROVIDER_LIBC)
12451282
{
1246-
/*
1247-
* Make sure cache entry is marked invalid, in case we fail before
1248-
* setting things.
1249-
*/
1250-
cache_entry->locale = 0;
1283+
const char *collcollate;
1284+
const char *collctype;
1285+
1286+
datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate);
1287+
collcollate = TextDatumGetCString(datum);
1288+
datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collctype);
1289+
collctype = TextDatumGetCString(datum);
1290+
1291+
result->collate_is_c = (strcmp(collcollate, "C") == 0) ||
1292+
(strcmp(collcollate, "POSIX") == 0);
1293+
result->ctype_is_c = (strcmp(collctype, "C") == 0) ||
1294+
(strcmp(collctype, "POSIX") == 0);
1295+
1296+
result->info.lt = make_libc_collator(collcollate, collctype);
1297+
}
1298+
else
1299+
/* shouldn't happen */
1300+
PGLOCALE_SUPPORT_ERROR(collform->collprovider);
1301+
1302+
datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion,
1303+
&isnull);
1304+
if (!isnull)
1305+
{
1306+
char *actual_versionstr;
1307+
char *collversionstr;
1308+
1309+
collversionstr = TextDatumGetCString(datum);
1310+
1311+
if (collform->collprovider == COLLPROVIDER_LIBC)
1312+
datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate);
1313+
else
1314+
datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale);
1315+
1316+
actual_versionstr = get_collation_actual_version(collform->collprovider,
1317+
TextDatumGetCString(datum));
1318+
if (!actual_versionstr)
1319+
{
1320+
/*
1321+
* This could happen when specifying a version in CREATE COLLATION
1322+
* but the provider does not support versioning, or manually
1323+
* creating a mess in the catalogs.
1324+
*/
1325+
ereport(ERROR,
1326+
(errmsg("collation \"%s\" has no actual version, but a version was recorded",
1327+
NameStr(collform->collname))));
1328+
}
1329+
1330+
if (strcmp(actual_versionstr, collversionstr) != 0)
1331+
ereport(WARNING,
1332+
(errmsg("collation \"%s\" has version mismatch",
1333+
NameStr(collform->collname)),
1334+
errdetail("The collation in the database was created using version %s, "
1335+
"but the operating system provides version %s.",
1336+
collversionstr, actual_versionstr),
1337+
errhint("Rebuild all objects affected by this collation and run "
1338+
"ALTER COLLATION %s REFRESH VERSION, "
1339+
"or build PostgreSQL with the right library version.",
1340+
quote_qualified_identifier(get_namespace_name(collform->collnamespace),
1341+
NameStr(collform->collname)))));
12511342
}
12521343

1253-
return cache_entry;
1344+
ReleaseSysCache(tp);
1345+
1346+
return result;
12541347
}
12551348

12561349
/*
@@ -1358,6 +1451,7 @@ pg_locale_t
13581451
pg_newlocale_from_collation(Oid collid)
13591452
{
13601453
collation_cache_entry *cache_entry;
1454+
bool found;
13611455

13621456
if (collid == DEFAULT_COLLATION_OID)
13631457
return &default_locale;
@@ -1368,140 +1462,28 @@ pg_newlocale_from_collation(Oid collid)
13681462
if (last_collation_cache_oid == collid)
13691463
return last_collation_cache_locale;
13701464

1371-
cache_entry = lookup_collation_cache(collid);
1372-
1373-
if (cache_entry->locale == 0)
1465+
if (CollationCache == NULL)
13741466
{
1375-
/* We haven't computed this yet in this session, so do it */
1376-
HeapTuple tp;
1377-
Form_pg_collation collform;
1378-
struct pg_locale_struct result;
1379-
pg_locale_t resultp;
1380-
Datum datum;
1381-
bool isnull;
1382-
1383-
tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
1384-
if (!HeapTupleIsValid(tp))
1385-
elog(ERROR, "cache lookup failed for collation %u", collid);
1386-
collform = (Form_pg_collation) GETSTRUCT(tp);
1387-
1388-
/* We'll fill in the result struct locally before allocating memory */
1389-
memset(&result, 0, sizeof(result));
1390-
result.provider = collform->collprovider;
1391-
result.deterministic = collform->collisdeterministic;
1392-
1393-
if (collform->collprovider == COLLPROVIDER_BUILTIN)
1394-
{
1395-
const char *locstr;
1396-
1397-
datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale);
1398-
locstr = TextDatumGetCString(datum);
1399-
1400-
result.collate_is_c = true;
1401-
result.ctype_is_c = (strcmp(locstr, "C") == 0);
1402-
1403-
builtin_validate_locale(GetDatabaseEncoding(), locstr);
1404-
1405-
result.info.builtin.locale = MemoryContextStrdup(TopMemoryContext,
1406-
locstr);
1407-
}
1408-
else if (collform->collprovider == COLLPROVIDER_ICU)
1409-
{
1410-
#ifdef USE_ICU
1411-
const char *iculocstr;
1412-
const char *icurules;
1413-
1414-
datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale);
1415-
iculocstr = TextDatumGetCString(datum);
1416-
1417-
result.collate_is_c = false;
1418-
result.ctype_is_c = false;
1419-
1420-
datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collicurules, &isnull);
1421-
if (!isnull)
1422-
icurules = TextDatumGetCString(datum);
1423-
else
1424-
icurules = NULL;
1425-
1426-
result.info.icu.locale = MemoryContextStrdup(TopMemoryContext, iculocstr);
1427-
result.info.icu.ucol = make_icu_collator(iculocstr, icurules);
1428-
#else
1429-
/* could get here if a collation was created by a build with ICU */
1430-
ereport(ERROR,
1431-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1432-
errmsg("ICU is not supported in this build")));
1433-
#endif
1434-
}
1435-
else if (collform->collprovider == COLLPROVIDER_LIBC)
1436-
{
1437-
const char *collcollate;
1438-
const char *collctype;
1439-
1440-
datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate);
1441-
collcollate = TextDatumGetCString(datum);
1442-
datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collctype);
1443-
collctype = TextDatumGetCString(datum);
1444-
1445-
result.collate_is_c = (strcmp(collcollate, "C") == 0) ||
1446-
(strcmp(collcollate, "POSIX") == 0);
1447-
result.ctype_is_c = (strcmp(collctype, "C") == 0) ||
1448-
(strcmp(collctype, "POSIX") == 0);
1449-
1450-
result.info.lt = make_libc_collator(collcollate, collctype);
1451-
}
1452-
else
1453-
/* shouldn't happen */
1454-
PGLOCALE_SUPPORT_ERROR(collform->collprovider);
1455-
1456-
datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion,
1457-
&isnull);
1458-
if (!isnull)
1459-
{
1460-
char *actual_versionstr;
1461-
char *collversionstr;
1462-
1463-
collversionstr = TextDatumGetCString(datum);
1464-
1465-
if (collform->collprovider == COLLPROVIDER_LIBC)
1466-
datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_collcollate);
1467-
else
1468-
datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale);
1469-
1470-
actual_versionstr = get_collation_actual_version(collform->collprovider,
1471-
TextDatumGetCString(datum));
1472-
if (!actual_versionstr)
1473-
{
1474-
/*
1475-
* This could happen when specifying a version in CREATE
1476-
* COLLATION but the provider does not support versioning, or
1477-
* manually creating a mess in the catalogs.
1478-
*/
1479-
ereport(ERROR,
1480-
(errmsg("collation \"%s\" has no actual version, but a version was recorded",
1481-
NameStr(collform->collname))));
1482-
}
1483-
1484-
if (strcmp(actual_versionstr, collversionstr) != 0)
1485-
ereport(WARNING,
1486-
(errmsg("collation \"%s\" has version mismatch",
1487-
NameStr(collform->collname)),
1488-
errdetail("The collation in the database was created using version %s, "
1489-
"but the operating system provides version %s.",
1490-
collversionstr, actual_versionstr),
1491-
errhint("Rebuild all objects affected by this collation and run "
1492-
"ALTER COLLATION %s REFRESH VERSION, "
1493-
"or build PostgreSQL with the right library version.",
1494-
quote_qualified_identifier(get_namespace_name(collform->collnamespace),
1495-
NameStr(collform->collname)))));
1496-
}
1497-
1498-
ReleaseSysCache(tp);
1467+
CollationCacheContext = AllocSetContextCreate(TopMemoryContext,
1468+
"collation cache",
1469+
ALLOCSET_DEFAULT_SIZES);
1470+
CollationCache = collation_cache_create(CollationCacheContext,
1471+
16, NULL);
1472+
}
14991473

1500-
/* We'll keep the pg_locale_t structures in TopMemoryContext */
1501-
resultp = MemoryContextAlloc(TopMemoryContext, sizeof(*resultp));
1502-
*resultp = result;
1474+
cache_entry = collation_cache_insert(CollationCache, collid, &found);
1475+
if (!found)
1476+
{
1477+
/*
1478+
* Make sure cache entry is marked invalid, in case we fail before
1479+
* setting things.
1480+
*/
1481+
cache_entry->locale = 0;
1482+
}
15031483

1504-
cache_entry->locale = resultp;
1484+
if (cache_entry->locale == 0)
1485+
{
1486+
cache_entry->locale = create_pg_locale(collid, CollationCacheContext);
15051487
}
15061488

15071489
last_collation_cache_oid = collid;

0 commit comments

Comments
 (0)