PostgreSQL Source Code git master
collationcmds.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "access/xact.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_database.h"
#include "catalog/pg_namespace.h"
#include "commands/collationcmds.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "common/string.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/pg_locale.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Include dependency graph for collationcmds.c:

Go to the source code of this file.

Data Structures

struct  CollAliasData
 

Macros

#define READ_LOCALE_A_OUTPUT
 

Functions

ObjectAddress DefineCollation (ParseState *pstate, List *names, List *parameters, bool if_not_exists)
 
void IsThereCollationInNamespace (const char *collname, Oid nspOid)
 
ObjectAddress AlterCollation (AlterCollationStmt *stmt)
 
Datum pg_collation_actual_version (PG_FUNCTION_ARGS)
 
static bool normalize_libc_locale_name (char *new, const char *old)
 
static int cmpaliases (const void *a, const void *b)
 
 pg_attribute_unused () static int create_collation_from_locale(const char *locale
 
 if (!pg_is_ascii(locale))
 
 if (enc< 0)
 
 if (!PG_VALID_BE_ENCODING(enc))
 
 if (collid=CollationCreate(enc==PG_SQL_ASCII)
 
Datum pg_import_system_collations (PG_FUNCTION_ARGS)
 

Variables

int nspid
 
int int * nvalidp
 
int int int * ncreatedp
 
Oid collid
 
 enc = pg_get_encoding_from_locale(locale, false)
 

Macro Definition Documentation

◆ READ_LOCALE_A_OUTPUT

#define READ_LOCALE_A_OUTPUT

Definition at line 583 of file collationcmds.c.

Function Documentation

◆ AlterCollation()

ObjectAddress AlterCollation ( AlterCollationStmt stmt)

Definition at line 428 of file collationcmds.c.

429{
430 Relation rel;
431 Oid collOid;
432 HeapTuple tup;
433 Form_pg_collation collForm;
434 Datum datum;
435 bool isnull;
436 char *oldversion;
437 char *newversion;
438 ObjectAddress address;
439
440 rel = table_open(CollationRelationId, RowExclusiveLock);
441 collOid = get_collation_oid(stmt->collname, false);
442
443 if (collOid == DEFAULT_COLLATION_OID)
445 (errmsg("cannot refresh version of default collation"),
446 /* translator: %s is an SQL command */
447 errhint("Use %s instead.",
448 "ALTER DATABASE ... REFRESH COLLATION VERSION")));
449
450 if (!object_ownercheck(CollationRelationId, collOid, GetUserId()))
452 NameListToString(stmt->collname));
453
454 tup = SearchSysCacheCopy1(COLLOID, ObjectIdGetDatum(collOid));
455 if (!HeapTupleIsValid(tup))
456 elog(ERROR, "cache lookup failed for collation %u", collOid);
457
458 collForm = (Form_pg_collation) GETSTRUCT(tup);
459 datum = SysCacheGetAttr(COLLOID, tup, Anum_pg_collation_collversion, &isnull);
460 oldversion = isnull ? NULL : TextDatumGetCString(datum);
461
462 if (collForm->collprovider == COLLPROVIDER_LIBC)
463 datum = SysCacheGetAttrNotNull(COLLOID, tup, Anum_pg_collation_collcollate);
464 else
465 datum = SysCacheGetAttrNotNull(COLLOID, tup, Anum_pg_collation_colllocale);
466
467 newversion = get_collation_actual_version(collForm->collprovider,
468 TextDatumGetCString(datum));
469
470 /* cannot change from NULL to non-NULL or vice versa */
471 if ((!oldversion && newversion) || (oldversion && !newversion))
472 elog(ERROR, "invalid collation version change");
473 else if (oldversion && newversion && strcmp(newversion, oldversion) != 0)
474 {
475 bool nulls[Natts_pg_collation];
476 bool replaces[Natts_pg_collation];
477 Datum values[Natts_pg_collation];
478
480 (errmsg("changing version from %s to %s",
481 oldversion, newversion)));
482
483 memset(values, 0, sizeof(values));
484 memset(nulls, false, sizeof(nulls));
485 memset(replaces, false, sizeof(replaces));
486
487 values[Anum_pg_collation_collversion - 1] = CStringGetTextDatum(newversion);
488 replaces[Anum_pg_collation_collversion - 1] = true;
489
490 tup = heap_modify_tuple(tup, RelationGetDescr(rel),
491 values, nulls, replaces);
492 }
493 else
495 (errmsg("version has not changed")));
496
497 CatalogTupleUpdate(rel, &tup->t_self, tup);
498
499 InvokeObjectPostAlterHook(CollationRelationId, collOid, 0);
500
501 ObjectAddressSet(address, CollationRelationId, collOid);
502
503 heap_freetuple(tup);
504 table_close(rel, NoLock);
505
506 return address;
507}
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2654
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4090
static Datum values[MAXATTR]
Definition: bootstrap.c:155
#define CStringGetTextDatum(s)
Definition: builtins.h:97
#define TextDatumGetCString(d)
Definition: builtins.h:98
int errhint(const char *fmt,...)
Definition: elog.c:1330
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define NOTICE
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:150
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition: heaptuple.c:1210
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1435
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
#define stmt
Definition: indent_codes.h:59
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition: indexing.c:313
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
Oid GetUserId(void)
Definition: miscinit.c:469
char * NameListToString(const List *names)
Definition: namespace.c:3664
Oid get_collation_oid(List *collname, bool missing_ok)
Definition: namespace.c:4041
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
@ OBJECT_COLLATION
Definition: parsenodes.h:2359
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:58
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1247
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262
uint64_t Datum
Definition: postgres.h:70
unsigned int Oid
Definition: postgres_ext.h:32
#define RelationGetDescr(relation)
Definition: rel.h:541
ItemPointerData t_self
Definition: htup.h:65
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:595
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:625
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:91
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

References aclcheck_error(), ACLCHECK_NOT_OWNER, CatalogTupleUpdate(), CStringGetTextDatum, elog, ereport, errhint(), errmsg(), ERROR, get_collation_actual_version(), get_collation_oid(), GETSTRUCT(), GetUserId(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, InvokeObjectPostAlterHook, NameListToString(), NoLock, NOTICE, OBJECT_COLLATION, object_ownercheck(), ObjectAddressSet, ObjectIdGetDatum(), RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, stmt, SysCacheGetAttr(), SysCacheGetAttrNotNull(), HeapTupleData::t_self, table_close(), table_open(), TextDatumGetCString, and values.

Referenced by ProcessUtilitySlow().

◆ cmpaliases()

static int cmpaliases ( const void *  a,
const void *  b 
)
static

Definition at line 631 of file collationcmds.c.

632{
633 const CollAliasData *ca = (const CollAliasData *) a;
634 const CollAliasData *cb = (const CollAliasData *) b;
635
636 /* comparing localename is enough because other fields are derived */
637 return strcmp(ca->localename, cb->localename);
638}
int b
Definition: isn.c:74
int a
Definition: isn.c:73
char * localename
Definition: collationcmds.c:47

References a, b, and CollAliasData::localename.

Referenced by pg_import_system_collations().

◆ DefineCollation()

ObjectAddress DefineCollation ( ParseState pstate,
List names,
List parameters,
bool  if_not_exists 
)

Definition at line 57 of file collationcmds.c.

58{
59 char *collName;
60 Oid collNamespace;
61 AclResult aclresult;
62 ListCell *pl;
63 DefElem *fromEl = NULL;
64 DefElem *localeEl = NULL;
65 DefElem *lccollateEl = NULL;
66 DefElem *lcctypeEl = NULL;
67 DefElem *providerEl = NULL;
68 DefElem *deterministicEl = NULL;
69 DefElem *rulesEl = NULL;
70 DefElem *versionEl = NULL;
71 char *collcollate;
72 char *collctype;
73 const char *colllocale;
74 char *collicurules;
75 bool collisdeterministic;
76 int collencoding;
77 char collprovider;
78 char *collversion = NULL;
79 Oid newoid;
80 ObjectAddress address;
81
82 collNamespace = QualifiedNameGetCreationNamespace(names, &collName);
83
84 aclresult = object_aclcheck(NamespaceRelationId, collNamespace, GetUserId(), ACL_CREATE);
85 if (aclresult != ACLCHECK_OK)
87 get_namespace_name(collNamespace));
88
89 foreach(pl, parameters)
90 {
91 DefElem *defel = lfirst_node(DefElem, pl);
92 DefElem **defelp;
93
94 if (strcmp(defel->defname, "from") == 0)
95 defelp = &fromEl;
96 else if (strcmp(defel->defname, "locale") == 0)
97 defelp = &localeEl;
98 else if (strcmp(defel->defname, "lc_collate") == 0)
99 defelp = &lccollateEl;
100 else if (strcmp(defel->defname, "lc_ctype") == 0)
101 defelp = &lcctypeEl;
102 else if (strcmp(defel->defname, "provider") == 0)
103 defelp = &providerEl;
104 else if (strcmp(defel->defname, "deterministic") == 0)
105 defelp = &deterministicEl;
106 else if (strcmp(defel->defname, "rules") == 0)
107 defelp = &rulesEl;
108 else if (strcmp(defel->defname, "version") == 0)
109 defelp = &versionEl;
110 else
111 {
113 (errcode(ERRCODE_SYNTAX_ERROR),
114 errmsg("collation attribute \"%s\" not recognized",
115 defel->defname),
116 parser_errposition(pstate, defel->location)));
117 break;
118 }
119 if (*defelp != NULL)
120 errorConflictingDefElem(defel, pstate);
121 *defelp = defel;
122 }
123
124 if (localeEl && (lccollateEl || lcctypeEl))
126 errcode(ERRCODE_SYNTAX_ERROR),
127 errmsg("conflicting or redundant options"),
128 errdetail("LOCALE cannot be specified together with LC_COLLATE or LC_CTYPE."));
129
130 if (fromEl && list_length(parameters) != 1)
132 errcode(ERRCODE_SYNTAX_ERROR),
133 errmsg("conflicting or redundant options"),
134 errdetail("FROM cannot be specified together with any other options."));
135
136 if (fromEl)
137 {
138 Oid collid;
139 HeapTuple tp;
140 Datum datum;
141 bool isnull;
142
145 if (!HeapTupleIsValid(tp))
146 elog(ERROR, "cache lookup failed for collation %u", collid);
147
148 collprovider = ((Form_pg_collation) GETSTRUCT(tp))->collprovider;
149 collisdeterministic = ((Form_pg_collation) GETSTRUCT(tp))->collisdeterministic;
150 collencoding = ((Form_pg_collation) GETSTRUCT(tp))->collencoding;
151
152 datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collcollate, &isnull);
153 if (!isnull)
154 collcollate = TextDatumGetCString(datum);
155 else
156 collcollate = NULL;
157
158 datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collctype, &isnull);
159 if (!isnull)
160 collctype = TextDatumGetCString(datum);
161 else
162 collctype = NULL;
163
164 datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_colllocale, &isnull);
165 if (!isnull)
166 colllocale = TextDatumGetCString(datum);
167 else
168 colllocale = NULL;
169
170 /*
171 * When the ICU locale comes from an existing collation, do not
172 * canonicalize to a language tag.
173 */
174
175 datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collicurules, &isnull);
176 if (!isnull)
177 collicurules = TextDatumGetCString(datum);
178 else
179 collicurules = NULL;
180
181 ReleaseSysCache(tp);
182
183 /*
184 * Copying the "default" collation is not allowed because most code
185 * checks for DEFAULT_COLLATION_OID instead of COLLPROVIDER_DEFAULT,
186 * and so having a second collation with COLLPROVIDER_DEFAULT would
187 * not work and potentially confuse or crash some code. This could be
188 * fixed with some legwork.
189 */
190 if (collprovider == COLLPROVIDER_DEFAULT)
192 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
193 errmsg("collation \"default\" cannot be copied")));
194 }
195 else
196 {
197 char *collproviderstr = NULL;
198
199 collcollate = NULL;
200 collctype = NULL;
201 colllocale = NULL;
202 collicurules = NULL;
203
204 if (providerEl)
205 collproviderstr = defGetString(providerEl);
206
207 if (deterministicEl)
208 collisdeterministic = defGetBoolean(deterministicEl);
209 else
210 collisdeterministic = true;
211
212 if (rulesEl)
213 collicurules = defGetString(rulesEl);
214
215 if (versionEl)
216 collversion = defGetString(versionEl);
217
218 if (collproviderstr)
219 {
220 if (pg_strcasecmp(collproviderstr, "builtin") == 0)
221 collprovider = COLLPROVIDER_BUILTIN;
222 else if (pg_strcasecmp(collproviderstr, "icu") == 0)
223 collprovider = COLLPROVIDER_ICU;
224 else if (pg_strcasecmp(collproviderstr, "libc") == 0)
225 collprovider = COLLPROVIDER_LIBC;
226 else
228 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
229 errmsg("unrecognized collation provider: %s",
230 collproviderstr)));
231 }
232 else
233 collprovider = COLLPROVIDER_LIBC;
234
235 if (localeEl)
236 {
237 if (collprovider == COLLPROVIDER_LIBC)
238 {
239 collcollate = defGetString(localeEl);
240 collctype = defGetString(localeEl);
241 }
242 else
243 colllocale = defGetString(localeEl);
244 }
245
246 if (lccollateEl)
247 collcollate = defGetString(lccollateEl);
248
249 if (lcctypeEl)
250 collctype = defGetString(lcctypeEl);
251
252 if (collprovider == COLLPROVIDER_BUILTIN)
253 {
254 if (!colllocale)
256 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
257 errmsg("parameter \"%s\" must be specified",
258 "locale")));
259
261 colllocale);
262 }
263 else if (collprovider == COLLPROVIDER_LIBC)
264 {
265 if (!collcollate)
267 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
268 errmsg("parameter \"%s\" must be specified",
269 "lc_collate")));
270
271 if (!collctype)
273 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
274 errmsg("parameter \"%s\" must be specified",
275 "lc_ctype")));
276 }
277 else if (collprovider == COLLPROVIDER_ICU)
278 {
279 if (!colllocale)
281 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
282 errmsg("parameter \"%s\" must be specified",
283 "locale")));
284
285 /*
286 * During binary upgrade, preserve the locale string. Otherwise,
287 * canonicalize to a language tag.
288 */
289 if (!IsBinaryUpgrade)
290 {
291 char *langtag = icu_language_tag(colllocale,
293
294 if (langtag && strcmp(colllocale, langtag) != 0)
295 {
297 (errmsg("using standard form \"%s\" for ICU locale \"%s\"",
298 langtag, colllocale)));
299
300 colllocale = langtag;
301 }
302 }
303
304 icu_validate_locale(colllocale);
305 }
306
307 /*
308 * Nondeterministic collations are currently only supported with ICU
309 * because that's the only case where it can actually make a
310 * difference. So we can save writing the code for the other
311 * providers.
312 */
313 if (!collisdeterministic && collprovider != COLLPROVIDER_ICU)
315 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
316 errmsg("nondeterministic collations not supported with this provider")));
317
318 if (collicurules && collprovider != COLLPROVIDER_ICU)
320 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
321 errmsg("ICU rules cannot be specified unless locale provider is ICU")));
322
323 if (collprovider == COLLPROVIDER_BUILTIN)
324 {
325 collencoding = builtin_locale_encoding(colllocale);
326 }
327 else if (collprovider == COLLPROVIDER_ICU)
328 {
329#ifdef USE_ICU
330 /*
331 * We could create ICU collations with collencoding == database
332 * encoding, but it seems better to use -1 so that it matches the
333 * way initdb would create ICU collations. However, only allow
334 * one to be created when the current database's encoding is
335 * supported. Otherwise the collation is useless, plus we get
336 * surprising behaviors like not being able to drop the collation.
337 *
338 * Skip this test when !USE_ICU, because the error we want to
339 * throw for that isn't thrown till later.
340 */
343 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
344 errmsg("current database's encoding is not supported with this provider")));
345#endif
346 collencoding = -1;
347 }
348 else
349 {
350 collencoding = GetDatabaseEncoding();
351 check_encoding_locale_matches(collencoding, collcollate, collctype);
352 }
353 }
354
355 if (!collversion)
356 {
357 const char *locale;
358
359 if (collprovider == COLLPROVIDER_LIBC)
360 locale = collcollate;
361 else
362 locale = colllocale;
363
364 collversion = get_collation_actual_version(collprovider, locale);
365 }
366
367 newoid = CollationCreate(collName,
368 collNamespace,
369 GetUserId(),
370 collprovider,
371 collisdeterministic,
372 collencoding,
373 collcollate,
374 collctype,
375 colllocale,
376 collicurules,
377 collversion,
378 if_not_exists,
379 false); /* not quiet */
380
381 if (!OidIsValid(newoid))
383
384 /* Check that the locales can be loaded. */
386 (void) pg_newlocale_from_collation(newoid);
387
388 ObjectAddressSet(address, CollationRelationId, newoid);
389
390 return address;
391}
AclResult
Definition: acl.h:182
@ ACLCHECK_OK
Definition: acl.h:183
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3836
#define OidIsValid(objectId)
Definition: c.h:794
Oid collid
void check_encoding_locale_matches(int encoding, const char *collate, const char *ctype)
Definition: dbcommands.c:1597
char * defGetString(DefElem *def)
Definition: define.c:35
bool defGetBoolean(DefElem *def)
Definition: define.c:94
List * defGetQualifiedName(DefElem *def)
Definition: define.c:239
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:371
int errdetail(const char *fmt,...)
Definition: elog.c:1216
int errcode(int sqlerrcode)
Definition: elog.c:863
bool is_encoding_supported_by_icu(int encoding)
Definition: encnames.c:461
bool IsBinaryUpgrade
Definition: globals.c:121
static char * locale
Definition: initdb.c:140
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3516
int GetDatabaseEncoding(void)
Definition: mbutils.c:1264
Oid QualifiedNameGetCreationNamespace(const List *names, char **objname_p)
Definition: namespace.c:3557
const ObjectAddress InvalidObjectAddress
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
@ OBJECT_SCHEMA
Definition: parsenodes.h:2388
#define ACL_CREATE
Definition: parsenodes.h:85
Oid CollationCreate(const char *collname, Oid collnamespace, Oid collowner, char collprovider, bool collisdeterministic, int32 collencoding, const char *collcollate, const char *collctype, const char *colllocale, const char *collicurules, const char *collversion, bool if_not_exists, bool quiet)
Definition: pg_collation.c:42
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
int icu_validation_level
Definition: pg_locale.c:92
void icu_validate_locale(const char *loc_str)
Definition: pg_locale.c:1789
pg_locale_t pg_newlocale_from_collation(Oid collid)
Definition: pg_locale.c:1189
int builtin_locale_encoding(const char *locale)
Definition: pg_locale.c:1667
char * icu_language_tag(const char *loc_str, int elevel)
Definition: pg_locale.c:1731
const char * builtin_validate_locale(int encoding, const char *locale)
Definition: pg_locale.c:1691
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:32
char * defname
Definition: parsenodes.h:844
ParseLoc location
Definition: parsenodes.h:848
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:264
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:220
void CommandCounterIncrement(void)
Definition: xact.c:1101

References ACL_CREATE, aclcheck_error(), ACLCHECK_OK, builtin_locale_encoding(), builtin_validate_locale(), check_encoding_locale_matches(), CollationCreate(), collid, CommandCounterIncrement(), defGetBoolean(), defGetQualifiedName(), defGetString(), DefElem::defname, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, errorConflictingDefElem(), get_collation_actual_version(), get_collation_oid(), get_namespace_name(), GetDatabaseEncoding(), GETSTRUCT(), GetUserId(), HeapTupleIsValid, icu_language_tag(), icu_validate_locale(), icu_validation_level, InvalidObjectAddress, is_encoding_supported_by_icu(), IsBinaryUpgrade, lfirst_node, list_length(), locale, DefElem::location, NOTICE, object_aclcheck(), OBJECT_SCHEMA, ObjectAddressSet, ObjectIdGetDatum(), OidIsValid, parser_errposition(), pg_newlocale_from_collation(), pg_strcasecmp(), QualifiedNameGetCreationNamespace(), ReleaseSysCache(), SearchSysCache1(), SysCacheGetAttr(), and TextDatumGetCString.

Referenced by ProcessUtilitySlow().

◆ if() [1/4]

if ( pg_is_asciilocale)

Definition at line 712 of file collationcmds.c.

713 {
714 elog(DEBUG1, "skipping locale with non-ASCII name: \"%s\"", locale);
715 return -1;
716 }
#define DEBUG1
Definition: elog.h:30

References DEBUG1, elog, and locale.

◆ if() [2/4]

if ( PG_VALID_BE_ENCODINGenc)

Definition at line 724 of file collationcmds.c.

725 {
726 elog(DEBUG1, "skipping locale with client-only encoding: \"%s\"", locale);
727 return -1;
728 }

References DEBUG1, elog, and locale.

◆ if() [3/4]

if ( collid = CollationCreate enc = PG_SQL_ASCII)

Definition at line 729 of file collationcmds.c.

749 {
750 (*ncreatedp)++;
751
752 /* Must do CCI between inserts to handle duplicates correctly */
754 }

◆ if() [4/4]

if ( )

Definition at line 719 of file collationcmds.c.

720 {
721 elog(DEBUG1, "skipping locale with unrecognized encoding: \"%s\"", locale);
722 return -1;
723 }

References DEBUG1, elog, and locale.

◆ IsThereCollationInNamespace()

void IsThereCollationInNamespace ( const char *  collname,
Oid  nspOid 
)

Definition at line 400 of file collationcmds.c.

401{
402 /* make sure the name doesn't already exist in new schema */
403 if (SearchSysCacheExists3(COLLNAMEENCNSP,
404 CStringGetDatum(collname),
406 ObjectIdGetDatum(nspOid)))
409 errmsg("collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"",
410 collname, GetDatabaseEncodingName(),
411 get_namespace_name(nspOid))));
412
413 /* mustn't match an any-encoding entry, either */
414 if (SearchSysCacheExists3(COLLNAMEENCNSP,
415 CStringGetDatum(collname),
416 Int32GetDatum(-1),
417 ObjectIdGetDatum(nspOid)))
420 errmsg("collation \"%s\" already exists in schema \"%s\"",
421 collname, get_namespace_name(nspOid))));
422}
const char * GetDatabaseEncodingName(void)
Definition: mbutils.c:1270
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:380
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:222
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:104

References CStringGetDatum(), ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, get_namespace_name(), GetDatabaseEncoding(), GetDatabaseEncodingName(), Int32GetDatum(), ObjectIdGetDatum(), and SearchSysCacheExists3.

Referenced by AlterObjectNamespace_internal(), and AlterObjectRename_internal().

◆ normalize_libc_locale_name()

static bool normalize_libc_locale_name ( char *  new,
const char *  old 
)
static

Definition at line 600 of file collationcmds.c.

601{
602 char *n = new;
603 const char *o = old;
604 bool changed = false;
605
606 while (*o)
607 {
608 if (*o == '.')
609 {
610 /* skip over encoding tag such as ".utf8" or ".UTF-8" */
611 o++;
612 while ((*o >= 'A' && *o <= 'Z')
613 || (*o >= 'a' && *o <= 'z')
614 || (*o >= '0' && *o <= '9')
615 || (*o == '-'))
616 o++;
617 changed = true;
618 }
619 else
620 *n++ = *o++;
621 }
622 *n = '\0';
623
624 return changed;
625}

Referenced by pg_import_system_collations().

◆ pg_attribute_unused()

pg_attribute_unused ( ) const

◆ pg_collation_actual_version()

Datum pg_collation_actual_version ( PG_FUNCTION_ARGS  )

Definition at line 511 of file collationcmds.c.

512{
514 char provider;
515 char *locale;
516 char *version;
517 Datum datum;
518
519 if (collid == DEFAULT_COLLATION_OID)
520 {
521 /* retrieve from pg_database */
522
524
525 if (!HeapTupleIsValid(dbtup))
527 (errcode(ERRCODE_UNDEFINED_OBJECT),
528 errmsg("database with OID %u does not exist", MyDatabaseId)));
529
531
532 if (provider == COLLPROVIDER_LIBC)
533 {
534 datum = SysCacheGetAttrNotNull(DATABASEOID, dbtup, Anum_pg_database_datcollate);
536 }
537 else
538 {
539 datum = SysCacheGetAttrNotNull(DATABASEOID, dbtup, Anum_pg_database_datlocale);
541 }
542
543 ReleaseSysCache(dbtup);
544 }
545 else
546 {
547 /* retrieve from pg_collation */
548
550
551 if (!HeapTupleIsValid(colltp))
553 (errcode(ERRCODE_UNDEFINED_OBJECT),
554 errmsg("collation with OID %u does not exist", collid)));
555
556 provider = ((Form_pg_collation) GETSTRUCT(colltp))->collprovider;
557 Assert(provider != COLLPROVIDER_DEFAULT);
558
559 if (provider == COLLPROVIDER_LIBC)
560 {
561 datum = SysCacheGetAttrNotNull(COLLOID, colltp, Anum_pg_collation_collcollate);
563 }
564 else
565 {
566 datum = SysCacheGetAttrNotNull(COLLOID, colltp, Anum_pg_collation_colllocale);
568 }
569
570 ReleaseSysCache(colltp);
571 }
572
574 if (version)
576 else
578}
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_RETURN_NULL()
Definition: fmgr.h:346
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:374
Oid MyDatabaseId
Definition: globals.c:94
Assert(PointerIsAligned(start, uint64))
static JitProviderCallbacks provider
Definition: jit.c:43
char datlocprovider
Definition: pg_database.h:44
FormData_pg_database * Form_pg_database
Definition: pg_database.h:96
text * cstring_to_text(const char *s)
Definition: varlena.c:181

References Assert(), collid, cstring_to_text(), datlocprovider, ereport, errcode(), errmsg(), ERROR, get_collation_actual_version(), GETSTRUCT(), HeapTupleIsValid, locale, MyDatabaseId, ObjectIdGetDatum(), PG_GETARG_OID, PG_RETURN_NULL, PG_RETURN_TEXT_P, provider, ReleaseSysCache(), SearchSysCache1(), SysCacheGetAttrNotNull(), and TextDatumGetCString.

◆ pg_import_system_collations()

Datum pg_import_system_collations ( PG_FUNCTION_ARGS  )

Definition at line 840 of file collationcmds.c.

841{
843 int ncreated = 0;
844
845 if (!superuser())
847 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
848 errmsg("must be superuser to import system collations")));
849
850 if (!SearchSysCacheExists1(NAMESPACEOID, ObjectIdGetDatum(nspid)))
852 (errcode(ERRCODE_UNDEFINED_SCHEMA),
853 errmsg("schema with OID %u does not exist", nspid)));
854
855 /* Load collations known to libc, using "locale -a" to enumerate them */
856#ifdef READ_LOCALE_A_OUTPUT
857 {
858 FILE *locale_a_handle;
859 char localebuf[LOCALE_NAME_BUFLEN];
860 int nvalid = 0;
861 Oid collid;
862 CollAliasData *aliases;
863 int naliases,
864 maxaliases,
865 i;
866
867 /* expansible array of aliases */
868 maxaliases = 100;
869 aliases = (CollAliasData *) palloc(maxaliases * sizeof(CollAliasData));
870 naliases = 0;
871
872 locale_a_handle = OpenPipeStream("locale -a", "r");
873 if (locale_a_handle == NULL)
876 errmsg("could not execute command \"%s\": %m",
877 "locale -a")));
878
879 while (fgets(localebuf, sizeof(localebuf), locale_a_handle))
880 {
881 size_t len;
882 int enc;
883 char alias[LOCALE_NAME_BUFLEN];
884
885 len = strlen(localebuf);
886
887 if (len == 0 || localebuf[len - 1] != '\n')
888 {
889 elog(DEBUG1, "skipping locale with too-long name: \"%s\"", localebuf);
890 continue;
891 }
892 localebuf[len - 1] = '\0';
893
894 enc = create_collation_from_locale(localebuf, nspid, &nvalid, &ncreated);
895 if (enc < 0)
896 continue;
897
898 /*
899 * Generate aliases such as "en_US" in addition to "en_US.utf8"
900 * for ease of use. Note that collation names are unique per
901 * encoding only, so this doesn't clash with "en_US" for LATIN1,
902 * say.
903 *
904 * However, it might conflict with a name we'll see later in the
905 * "locale -a" output. So save up the aliases and try to add them
906 * after we've read all the output.
907 */
908 if (normalize_libc_locale_name(alias, localebuf))
909 {
910 if (naliases >= maxaliases)
911 {
912 maxaliases *= 2;
913 aliases = (CollAliasData *)
914 repalloc(aliases, maxaliases * sizeof(CollAliasData));
915 }
916 aliases[naliases].localename = pstrdup(localebuf);
917 aliases[naliases].alias = pstrdup(alias);
918 aliases[naliases].enc = enc;
919 naliases++;
920 }
921 }
922
923 /*
924 * We don't check the return value of this, because we want to support
925 * the case where there "locale" command does not exist. (This is
926 * unusual but can happen on minimalized Linux distributions, for
927 * example.) We will warn below if no locales could be found.
928 */
929 ClosePipeStream(locale_a_handle);
930
931 /*
932 * Before processing the aliases, sort them by locale name. The point
933 * here is that if "locale -a" gives us multiple locale names with the
934 * same encoding and base name, say "en_US.utf8" and "en_US.utf-8", we
935 * want to pick a deterministic one of them. First in ASCII sort
936 * order is a good enough rule. (Before PG 10, the code corresponding
937 * to this logic in initdb.c had an additional ordering rule, to
938 * prefer the locale name exactly matching the alias, if any. We
939 * don't need to consider that here, because we would have already
940 * created such a pg_collation entry above, and that one will win.)
941 */
942 if (naliases > 1)
943 qsort(aliases, naliases, sizeof(CollAliasData), cmpaliases);
944
945 /* Now add aliases, ignoring any that match pre-existing entries */
946 for (i = 0; i < naliases; i++)
947 {
948 char *locale = aliases[i].localename;
949 char *alias = aliases[i].alias;
950 int enc = aliases[i].enc;
951
953 COLLPROVIDER_LIBC, true, enc,
954 locale, locale, NULL, NULL,
955 get_collation_actual_version(COLLPROVIDER_LIBC, locale),
956 true, true);
957 if (OidIsValid(collid))
958 {
959 ncreated++;
960
962 }
963 }
964
965 /* Give a warning if "locale -a" seems to be malfunctioning */
966 if (nvalid == 0)
968 (errmsg("no usable system locales were found")));
969 }
970#endif /* READ_LOCALE_A_OUTPUT */
971
972 /*
973 * Load collations known to ICU
974 *
975 * We use uloc_countAvailable()/uloc_getAvailable() rather than
976 * ucol_countAvailable()/ucol_getAvailable(). The former returns a full
977 * set of language+region combinations, whereas the latter only returns
978 * language+region combinations if they are distinct from the language's
979 * base collation. So there might not be a de-DE or en-GB, which would be
980 * confusing.
981 */
982#ifdef USE_ICU
983 {
984 int i;
985
986 /*
987 * Start the loop at -1 to sneak in the root locale without too much
988 * code duplication.
989 */
990 for (i = -1; i < uloc_countAvailable(); i++)
991 {
992 const char *name;
993 char *langtag;
994 char *icucomment;
995 Oid collid;
996
997 if (i == -1)
998 name = ""; /* ICU root locale */
999 else
1000 name = uloc_getAvailable(i);
1001
1002 langtag = icu_language_tag(name, ERROR);
1003
1004 /*
1005 * Be paranoid about not allowing any non-ASCII strings into
1006 * pg_collation
1007 */
1008 if (!pg_is_ascii(langtag))
1009 continue;
1010
1011 collid = CollationCreate(psprintf("%s-x-icu", langtag),
1012 nspid, GetUserId(),
1013 COLLPROVIDER_ICU, true, -1,
1014 NULL, NULL, langtag, NULL,
1015 get_collation_actual_version(COLLPROVIDER_ICU, langtag),
1016 true, true);
1017 if (OidIsValid(collid))
1018 {
1019 ncreated++;
1020
1022
1023 icucomment = get_icu_locale_comment(name);
1024 if (icucomment)
1025 CreateComments(collid, CollationRelationId, 0,
1026 icucomment);
1027 }
1028 }
1029 }
1030#endif /* USE_ICU */
1031
1032 /* Load collations known to WIN32 */
1033#ifdef ENUM_SYSTEM_LOCALE
1034 {
1035 int nvalid = 0;
1036 CollParam param;
1037
1038 param.nspid = nspid;
1039 param.ncreatedp = &ncreated;
1040 param.nvalidp = &nvalid;
1041
1042 /*
1043 * Enumerate the locales that are either installed on or supported by
1044 * the OS.
1045 */
1046 if (!EnumSystemLocalesEx(win32_read_locale, LOCALE_ALL,
1047 (LPARAM) &param, NULL))
1048 _dosmaperr(GetLastError());
1049
1050 /* Give a warning if EnumSystemLocalesEx seems to be malfunctioning */
1051 if (nvalid == 0)
1053 (errmsg("no usable system locales were found")));
1054 }
1055#endif /* ENUM_SYSTEM_LOCALE */
1056
1057 PG_RETURN_INT32(ncreated);
1058}
static bool normalize_libc_locale_name(char *new, const char *old)
int nspid
static int cmpaliases(const void *a, const void *b)
enc
void CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment)
Definition: comment.c:143
int errcode_for_file_access(void)
Definition: elog.c:886
#define WARNING
Definition: elog.h:36
FILE * OpenPipeStream(const char *command, const char *mode)
Definition: fd.c:2727
int ClosePipeStream(FILE *file)
Definition: fd.c:3035
#define PG_RETURN_INT32(x)
Definition: fmgr.h:355
int i
Definition: isn.c:77
char * pstrdup(const char *in)
Definition: mcxt.c:1781
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1632
void * palloc(Size size)
Definition: mcxt.c:1387
const void size_t len
#define LOCALE_NAME_BUFLEN
Definition: pg_locale.h:18
#define qsort(a, b, c, d)
Definition: port.h:499
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
bool pg_is_ascii(const char *str)
Definition: string.c:132
bool superuser(void)
Definition: superuser.c:46
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:100
const char * name
void _dosmaperr(unsigned long)
Definition: win32error.c:177

References _dosmaperr(), CollAliasData::alias, ClosePipeStream(), cmpaliases(), CollationCreate(), collid, CommandCounterIncrement(), CreateComments(), DEBUG1, elog, CollAliasData::enc, enc, ereport, errcode(), errcode_for_file_access(), errmsg(), ERROR, get_collation_actual_version(), GetUserId(), i, icu_language_tag(), len, locale, LOCALE_NAME_BUFLEN, CollAliasData::localename, name, normalize_libc_locale_name(), nspid, ObjectIdGetDatum(), OidIsValid, OpenPipeStream(), palloc(), PG_GETARG_OID, pg_is_ascii(), PG_RETURN_INT32, psprintf(), pstrdup(), qsort, repalloc(), SearchSysCacheExists1, superuser(), and WARNING.

Variable Documentation

◆ collid

◆ enc

◆ ncreatedp

int int int* ncreatedp
Initial value:
{
int enc

Definition at line 701 of file collationcmds.c.

◆ nspid

◆ nvalidp

int int* nvalidp

Definition at line 701 of file collationcmds.c.