PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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 "storage/fd.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 intnvalidp
 
int int intncreatedp
 
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 584 of file collationcmds.c.

Function Documentation

◆ AlterCollation()

ObjectAddress AlterCollation ( AlterCollationStmt stmt)

Definition at line 429 of file collationcmds.c.

430{
431 Relation rel;
432 Oid collOid;
435 Datum datum;
436 bool isnull;
437 char *oldversion;
438 char *newversion;
439 ObjectAddress address;
440
442 collOid = get_collation_oid(stmt->collname, false);
443
444 if (collOid == DEFAULT_COLLATION_OID)
446 (errmsg("cannot refresh version of default collation"),
447 /* translator: %s is an SQL command */
448 errhint("Use %s instead.",
449 "ALTER DATABASE ... REFRESH COLLATION VERSION")));
450
453 NameListToString(stmt->collname));
454
456 if (!HeapTupleIsValid(tup))
457 elog(ERROR, "cache lookup failed for collation %u", collOid);
458
461 oldversion = isnull ? NULL : TextDatumGetCString(datum);
462
463 if (collForm->collprovider == COLLPROVIDER_LIBC)
465 else
467
469 TextDatumGetCString(datum));
470
471 /* cannot change from NULL to non-NULL or vice versa */
472 if ((!oldversion && newversion) || (oldversion && !newversion))
473 elog(ERROR, "invalid collation version change");
474 else if (oldversion && newversion && strcmp(newversion, oldversion) != 0)
475 {
476 bool nulls[Natts_pg_collation];
479
481 (errmsg("changing version from %s to %s",
483
484 memset(values, 0, sizeof(values));
485 memset(nulls, false, sizeof(nulls));
486 memset(replaces, false, sizeof(replaces));
487
490
492 values, nulls, replaces);
493 }
494 else
496 (errmsg("version has not changed")));
497
498 CatalogTupleUpdate(rel, &tup->t_self, tup);
499
501
502 ObjectAddressSet(address, CollationRelationId, collOid);
503
505 table_close(rel, NoLock);
506
507 return address;
508}
@ 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)
#define stmt
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)
#define ObjectAddressSet(addr, class_id, object_id)
@ OBJECT_COLLATION
FormData_pg_collation * Form_pg_collation
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
static int fb(int x)
#define RelationGetDescr(relation)
Definition rel.h:540
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, fb(), 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(), table_close(), table_open(), TextDatumGetCString, and values.

Referenced by ProcessUtilitySlow().

◆ cmpaliases()

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

Definition at line 632 of file collationcmds.c.

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

References a, b, fb(), 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 58 of file collationcmds.c.

59{
60 char *collName;
63 ListCell *pl;
72 char *collcollate;
73 char *collctype;
74 const char *colllocale;
75 char *collicurules;
77 int collencoding;
78 char collprovider;
79 char *collversion = NULL;
80 Oid newoid;
81 ObjectAddress address;
82
84
89
90 foreach(pl, parameters)
91 {
94
95 if (strcmp(defel->defname, "from") == 0)
96 defelp = &fromEl;
97 else if (strcmp(defel->defname, "locale") == 0)
99 else if (strcmp(defel->defname, "lc_collate") == 0)
101 else if (strcmp(defel->defname, "lc_ctype") == 0)
102 defelp = &lcctypeEl;
103 else if (strcmp(defel->defname, "provider") == 0)
105 else if (strcmp(defel->defname, "deterministic") == 0)
107 else if (strcmp(defel->defname, "rules") == 0)
108 defelp = &rulesEl;
109 else if (strcmp(defel->defname, "version") == 0)
110 defelp = &versionEl;
111 else
112 {
115 errmsg("collation attribute \"%s\" not recognized",
116 defel->defname),
117 parser_errposition(pstate, defel->location)));
118 break;
119 }
120 if (*defelp != NULL)
122 *defelp = defel;
123 }
124
125 if (localeEl && (lccollateEl || lcctypeEl))
128 errmsg("conflicting or redundant options"),
129 errdetail("LOCALE cannot be specified together with LC_COLLATE or LC_CTYPE."));
130
131 if (fromEl && list_length(parameters) != 1)
134 errmsg("conflicting or redundant options"),
135 errdetail("FROM cannot be specified together with any other options."));
136
137 if (fromEl)
138 {
139 Oid collid;
140 HeapTuple tp;
141 Datum datum;
142 bool isnull;
143
146 if (!HeapTupleIsValid(tp))
147 elog(ERROR, "cache lookup failed for collation %u", collid);
148
151 collencoding = ((Form_pg_collation) GETSTRUCT(tp))->collencoding;
152
154 if (!isnull)
156 else
158
160 if (!isnull)
162 else
163 collctype = NULL;
164
166 if (!isnull)
168 else
170
171 /*
172 * When the ICU locale comes from an existing collation, do not
173 * canonicalize to a language tag.
174 */
175
177 if (!isnull)
179 else
181
182 ReleaseSysCache(tp);
183
184 /*
185 * Copying the "default" collation is not allowed because most code
186 * checks for DEFAULT_COLLATION_OID instead of COLLPROVIDER_DEFAULT,
187 * and so having a second collation with COLLPROVIDER_DEFAULT would
188 * not work and potentially confuse or crash some code. This could be
189 * fixed with some legwork.
190 */
194 errmsg("collation \"default\" cannot be copied")));
195 }
196 else
197 {
198 char *collproviderstr = NULL;
199
201 collctype = NULL;
204
205 if (providerEl)
207
208 if (deterministicEl)
210 else
211 collisdeterministic = true;
212
213 if (rulesEl)
215
216 if (versionEl)
218
219 if (collproviderstr)
220 {
221 if (pg_strcasecmp(collproviderstr, "builtin") == 0)
223 else if (pg_strcasecmp(collproviderstr, "icu") == 0)
225 else if (pg_strcasecmp(collproviderstr, "libc") == 0)
227 else
230 errmsg("unrecognized collation provider: %s",
232 }
233 else
235
236 if (localeEl)
237 {
239 {
242 }
243 else
245 }
246
247 if (lccollateEl)
249
250 if (lcctypeEl)
252
254 {
255 if (!colllocale)
258 errmsg("parameter \"%s\" must be specified",
259 "locale")));
260
262 colllocale);
263 }
265 {
266 if (!collcollate)
269 errmsg("parameter \"%s\" must be specified",
270 "lc_collate")));
271
272 if (!collctype)
275 errmsg("parameter \"%s\" must be specified",
276 "lc_ctype")));
277 }
278 else if (collprovider == COLLPROVIDER_ICU)
279 {
280 if (!colllocale)
283 errmsg("parameter \"%s\" must be specified",
284 "locale")));
285
286 /*
287 * During binary upgrade, preserve the locale string. Otherwise,
288 * canonicalize to a language tag.
289 */
290 if (!IsBinaryUpgrade)
291 {
294
295 if (langtag && strcmp(colllocale, langtag) != 0)
296 {
298 (errmsg("using standard form \"%s\" for ICU locale \"%s\"",
300
302 }
303 }
304
306 }
307
308 /*
309 * Nondeterministic collations are currently only supported with ICU
310 * because that's the only case where it can actually make a
311 * difference. So we can save writing the code for the other
312 * providers.
313 */
317 errmsg("nondeterministic collations not supported with this provider")));
318
322 errmsg("ICU rules cannot be specified unless locale provider is ICU")));
323
325 {
326 collencoding = builtin_locale_encoding(colllocale);
327 }
328 else if (collprovider == COLLPROVIDER_ICU)
329 {
330#ifdef USE_ICU
331 /*
332 * We could create ICU collations with collencoding == database
333 * encoding, but it seems better to use -1 so that it matches the
334 * way initdb would create ICU collations. However, only allow
335 * one to be created when the current database's encoding is
336 * supported. Otherwise the collation is useless, plus we get
337 * surprising behaviors like not being able to drop the collation.
338 *
339 * Skip this test when !USE_ICU, because the error we want to
340 * throw for that isn't thrown till later.
341 */
345 errmsg("current database's encoding is not supported with this provider")));
346#endif
347 collencoding = -1;
348 }
349 else
350 {
351 collencoding = GetDatabaseEncoding();
353 }
354 }
355
356 if (!collversion)
357 {
358 const char *locale;
359
361 locale = collcollate;
362 else
363 locale = colllocale;
364
366 }
367
370 GetUserId(),
373 collencoding,
375 collctype,
379 if_not_exists,
380 false); /* not quiet */
381
382 if (!OidIsValid(newoid))
384
385 /* Check that the locales can be loaded. */
388
390
391 return address;
392}
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:788
Oid collid
void check_encoding_locale_matches(int encoding, const char *collate, const char *ctype)
char * defGetString(DefElem *def)
Definition define.c:34
bool defGetBoolean(DefElem *def)
Definition define.c:93
List * defGetQualifiedName(DefElem *def)
Definition define.c:238
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition define.c:370
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
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
#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)
#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)
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(), elog, ereport, errcode(), errdetail(), errmsg(), ERROR, errorConflictingDefElem(), fb(), 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(), 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 713 of file collationcmds.c.

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

References DEBUG1, and elog.

◆ if() [2/4]

if ( PG_VALID_BE_ENCODINGenc)

Definition at line 725 of file collationcmds.c.

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

References DEBUG1, and elog.

◆ if() [3/4]

if ( collid = CollationCreate enc = PG_SQL_ASCII)

Definition at line 730 of file collationcmds.c.

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

◆ if() [4/4]

if ( )

Definition at line 720 of file collationcmds.c.

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

References DEBUG1, and elog.

◆ IsThereCollationInNamespace()

void IsThereCollationInNamespace ( const char collname,
Oid  nspOid 
)

Definition at line 401 of file collationcmds.c.

402{
403 /* make sure the name doesn't already exist in new schema */
405 CStringGetDatum(collname),
410 errmsg("collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"",
411 collname, GetDatabaseEncodingName(),
413
414 /* mustn't match an any-encoding entry, either */
416 CStringGetDatum(collname),
417 Int32GetDatum(-1),
421 errmsg("collation \"%s\" already exists in schema \"%s\"",
422 collname, get_namespace_name(nspOid))));
423}
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, fb(), 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 601 of file collationcmds.c.

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

References fb().

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 512 of file collationcmds.c.

513{
515 char provider;
516 char *locale;
517 char *version;
518 Datum datum;
519
521 {
522 /* retrieve from pg_database */
523
525
529 errmsg("database with OID %u does not exist", MyDatabaseId)));
530
532
534 {
536 locale = TextDatumGetCString(datum);
537 }
538 else
539 {
541 locale = TextDatumGetCString(datum);
542 }
543
545 }
546 else
547 {
548 /* retrieve from pg_collation */
549
551
555 errmsg("collation with OID %u does not exist", collid)));
556
559
561 {
563 locale = TextDatumGetCString(datum);
564 }
565 else
566 {
568 locale = TextDatumGetCString(datum);
569 }
570
572 }
573
574 version = get_collation_actual_version(provider, locale);
575 if (version)
577 else
579}
#define Assert(condition)
Definition c.h:873
#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
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, fb(), get_collation_actual_version(), GETSTRUCT(), HeapTupleIsValid, MyDatabaseId, ObjectIdGetDatum(), PG_GETARG_OID, PG_RETURN_NULL, PG_RETURN_TEXT_P, ReleaseSysCache(), SearchSysCache1(), SysCacheGetAttrNotNull(), and TextDatumGetCString.

◆ pg_import_system_collations()

Datum pg_import_system_collations ( PG_FUNCTION_ARGS  )

Definition at line 841 of file collationcmds.c.

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

Oid collid

Definition at line 705 of file collationcmds.c.

Referenced by add_column_collation_dependency(), bpchar_sortsupport(), bpchareq(), bpcharne(), btnamesortsupport(), bttextsortsupport(), btvarstrequalimage(), check_collation_set(), check_collation_set(), citextcmp(), CollationGetCollid(), CollationIsVisible(), CollationIsVisibleExt(), convert_string_datum(), convert_to_scalar(), create_pg_locale(), create_pg_locale_builtin(), create_pg_locale_icu(), create_pg_locale_libc(), datetime_to_char_body(), DCH_from_char(), DCH_to_char(), DefineCollation(), do_to_timestamp(), DoubleMetaphone(), ExecBuildGroupingEqual(), ExecBuildParamSetEqual(), executeDateTimeMethod(), find_expr_references_walker(), from_char_seq_search(), generate_collation_name(), get_atttypetypmodcoll(), hashbpchar(), hashbpcharextended(), hashtext(), hashtextextended(), lookup_collation(), MakeUpper(), mcv_get_match_bitmap(), mcv_match_expression(), namecmp(), nameeqtext(), namenetext(), ndistinct_for_combination(), parse_datetime(), pg_collation_actual_version(), pg_collation_for(), pg_import_system_collations(), pg_newlocale_from_collation(), ri_CompareWithCast(), seq_search_localized(), str_casefold(), str_initcap(), str_initcap_z(), str_tolower(), str_tolower_z(), str_toupper(), str_toupper_z(), t_starts_with(), text_cmp(), text_isequal(), text_position(), text_position_setup(), text_starts_with(), texteq(), texteqname(), textne(), textnename(), to_date(), to_timestamp(), varstr_cmp(), and varstr_sortsupport().

◆ enc

◆ ncreatedp

int int int* ncreatedp
Initial value:
{
int enc

Definition at line 702 of file collationcmds.c.

◆ nspid

◆ nvalidp

int int* nvalidp

Definition at line 702 of file collationcmds.c.