66 DefElem *deterministicEl = NULL;
73 bool collisdeterministic;
76 char *collversion = NULL;
87 foreach(pl, parameters)
92 if (strcmp(defel->
defname,
"from") == 0)
94 else if (strcmp(defel->
defname,
"locale") == 0)
96 else if (strcmp(defel->
defname,
"lc_collate") == 0)
97 defelp = &lccollateEl;
98 else if (strcmp(defel->
defname,
"lc_ctype") == 0)
100 else if (strcmp(defel->
defname,
"provider") == 0)
101 defelp = &providerEl;
102 else if (strcmp(defel->
defname,
"deterministic") == 0)
103 defelp = &deterministicEl;
104 else if (strcmp(defel->
defname,
"rules") == 0)
106 else if (strcmp(defel->
defname,
"version") == 0)
111 (
errcode(ERRCODE_SYNTAX_ERROR),
112 errmsg(
"collation attribute \"%s\" not recognized",
122 if (localeEl && (lccollateEl || lcctypeEl))
125 errmsg(
"conflicting or redundant options"),
126 errdetail(
"LOCALE cannot be specified together with LC_COLLATE or LC_CTYPE."));
131 errmsg(
"conflicting or redundant options"),
132 errdetail(
"FROM cannot be specified together with any other options."));
166 colliculocale = NULL;
183 if (collprovider == COLLPROVIDER_DEFAULT)
185 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
186 errmsg(
"collation \"default\" cannot be copied")));
190 char *collproviderstr = NULL;
194 colliculocale = NULL;
203 collisdeterministic =
true;
214 collprovider = COLLPROVIDER_ICU;
216 collprovider = COLLPROVIDER_LIBC;
219 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
220 errmsg(
"unrecognized collation provider: %s",
224 collprovider = COLLPROVIDER_LIBC;
228 if (collprovider == COLLPROVIDER_LIBC)
243 if (collprovider == COLLPROVIDER_LIBC)
247 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
248 errmsg(
"parameter \"lc_collate\" must be specified")));
252 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
253 errmsg(
"parameter \"lc_ctype\" must be specified")));
255 else if (collprovider == COLLPROVIDER_ICU)
259 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
260 errmsg(
"parameter \"locale\" must be specified")));
269 if (!collisdeterministic && collprovider != COLLPROVIDER_ICU)
271 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
272 errmsg(
"nondeterministic collations not supported with this provider")));
274 if (collicurules && collprovider != COLLPROVIDER_ICU)
276 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
277 errmsg(
"ICU rules cannot be specified unless locale provider is ICU")));
279 if (collprovider == COLLPROVIDER_ICU)
295 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
296 errmsg(
"current database's encoding is not supported with this provider")));
356 errmsg(
"collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"",
367 errmsg(
"collation \"%s\" already exists in schema \"%s\"",
390 if (collOid == DEFAULT_COLLATION_OID)
392 (
errmsg(
"cannot refresh version of default collation"),
393 errhint(
"Use ALTER DATABASE ... REFRESH COLLATION VERSION instead.")));
401 elog(
ERROR,
"cache lookup failed for collation %u", collOid);
407 datum =
SysCacheGetAttr(
COLLOID, tup, collForm->collprovider == COLLPROVIDER_ICU ? Anum_pg_collation_colliculocale : Anum_pg_collation_collcollate, &isnull);
409 elog(
ERROR,
"unexpected null in pg_collation");
413 if ((!oldversion && newversion) || (oldversion && !newversion))
414 elog(
ERROR,
"invalid collation version change");
415 else if (oldversion && newversion && strcmp(newversion, oldversion) != 0)
417 bool nulls[Natts_pg_collation];
418 bool replaces[Natts_pg_collation];
422 (
errmsg(
"changing version from %s to %s",
423 oldversion, newversion)));
426 memset(nulls,
false,
sizeof(nulls));
427 memset(replaces,
false,
sizeof(replaces));
430 replaces[Anum_pg_collation_collversion - 1] =
true;
437 (
errmsg(
"version has not changed")));
462 if (
collid == DEFAULT_COLLATION_OID)
469 (
errcode(ERRCODE_UNDEFINED_OBJECT),
476 Anum_pg_database_daticulocale : Anum_pg_database_datcollate,
479 elog(
ERROR,
"unexpected null in pg_database");
492 (
errcode(ERRCODE_UNDEFINED_OBJECT),
493 errmsg(
"collation with OID %u does not exist",
collid)));
499 Anum_pg_collation_colliculocale : Anum_pg_collation_collcollate,
502 elog(
ERROR,
"unexpected null in pg_collation");
518 #if defined(HAVE_LOCALE_T) && !defined(WIN32)
519 #define READ_LOCALE_A_OUTPUT
524 #define ENUM_SYSTEM_LOCALE
528 #ifdef READ_LOCALE_A_OUTPUT
536 normalize_libc_locale_name(
char *
new,
const char *old)
540 bool changed =
false;
548 while ((*o >=
'A' && *o <=
'Z')
549 || (*o >=
'a' && *o <=
'z')
550 || (*o >=
'0' && *o <=
'9')
567 cmpaliases(
const void *
a,
const void *
b)
584 get_icu_language_tag(
const char *localename)
586 char buf[ULOC_FULLNAME_CAPACITY];
590 uloc_toLanguageTag(localename,
buf,
sizeof(
buf),
true, &
status);
593 (
errmsg(
"could not convert locale name \"%s\" to language tag: %s",
594 localename, u_errorName(
status))));
606 get_icu_locale_comment(
const char *localename)
609 UChar displayname[128];
615 len_uchar = uloc_getDisplayName(localename,
"en",
622 for (
i = 0;
i < len_uchar;
i++)
624 if (displayname[
i] > 127)
629 result =
palloc(len_uchar + 1);
630 for (
i = 0;
i < len_uchar;
i++)
631 result[
i] = displayname[
i];
632 result[len_uchar] =
'\0';
702 COLLPROVIDER_LIBC,
true,
enc,
718 #ifdef ENUM_SYSTEM_LOCALE
736 win32_read_locale(LPWSTR pStr, DWORD dwFlags, LPARAM lparam)
738 CollParam *param = (CollParam *) lparam;
745 result = WideCharToMultiByte(CP_ACP, 0, pStr, -1, localebuf,
NAMEDATALEN,
750 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
751 elog(
DEBUG1,
"skipping locale with too-long name: \"%s\"", localebuf);
754 if (localebuf[0] ==
'\0')
757 enc = create_collation_from_locale(localebuf, param->nspid,
758 param->nvalidp, param->ncreatedp);
766 if (strchr(localebuf,
'-'))
771 strcpy(alias, localebuf);
772 for (
char *p = alias; *p; p++)
777 COLLPROVIDER_LIBC,
true,
enc,
778 localebuf, localebuf, NULL, NULL,
783 (*param->ncreatedp)++;
805 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
806 errmsg(
"must be superuser to import system collations")));
810 (
errcode(ERRCODE_UNDEFINED_SCHEMA),
811 errmsg(
"schema with OID %u does not exist",
nspid)));
814 #ifdef READ_LOCALE_A_OUTPUT
816 FILE *locale_a_handle;
831 if (locale_a_handle == NULL)
834 errmsg(
"could not execute command \"%s\": %m",
837 while (fgets(localebuf,
sizeof(localebuf), locale_a_handle))
843 len = strlen(localebuf);
845 if (
len == 0 || localebuf[
len - 1] !=
'\n')
847 elog(
DEBUG1,
"skipping locale with too-long name: \"%s\"", localebuf);
850 localebuf[
len - 1] =
'\0';
852 enc = create_collation_from_locale(localebuf,
nspid, &nvalid, &ncreated);
866 if (normalize_libc_locale_name(alias, localebuf))
868 if (naliases >= maxaliases)
876 aliases[naliases].
enc =
enc;
904 for (
i = 0;
i < naliases;
i++)
907 char *alias = aliases[
i].
alias;
911 COLLPROVIDER_LIBC,
true,
enc,
926 (
errmsg(
"no usable system locales were found")));
948 for (
i = -1;
i < uloc_countAvailable();
i++)
953 const char *iculocstr;
959 name = uloc_getAvailable(
i);
961 langtag = get_icu_language_tag(
name);
962 iculocstr = U_ICU_VERSION_MAJOR_NUM >= 54 ? langtag :
name;
973 COLLPROVIDER_ICU,
true, -1,
974 NULL, NULL, iculocstr, NULL,
983 icucomment = get_icu_locale_comment(
name);
993 #ifdef ENUM_SYSTEM_LOCALE
999 param.ncreatedp = &ncreated;
1000 param.nvalidp = &nvalid;
1006 if (!EnumSystemLocalesEx(win32_read_locale, LOCALE_ALL,
1007 (LPARAM) ¶m, NULL))
1013 (
errmsg(
"no usable system locales were found")));
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
static Datum values[MAXATTR]
#define CStringGetTextDatum(s)
#define TextDatumGetCString(d)
#define OidIsValid(objectId)
Datum pg_collation_actual_version(PG_FUNCTION_ARGS)
pg_attribute_unused() static int create_collation_from_locale(const char *locale
ObjectAddress AlterCollation(AlterCollationStmt *stmt)
void IsThereCollationInNamespace(const char *collname, Oid nspOid)
Datum pg_import_system_collations(PG_FUNCTION_ARGS)
ObjectAddress DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_exists)
void check_encoding_locale_matches(int encoding, const char *collate, const char *ctype)
elog(ERROR, "%s: %s", p2, msg)
bool defGetBoolean(DefElem *def)
List * defGetQualifiedName(DefElem *def)
char * defGetString(DefElem *def)
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
int errcode_for_file_access(void)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
bool is_encoding_supported_by_icu(int encoding)
int ClosePipeStream(FILE *file)
FILE * OpenPipeStream(const char *command, const char *mode)
#define PG_RETURN_TEXT_P(x)
#define PG_RETURN_INT32(x)
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
void heap_freetuple(HeapTuple htup)
#define HeapTupleIsValid(tuple)
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
static JitProviderCallbacks provider
Assert(fmt[strlen(fmt) - 1] !='\n')
char * get_namespace_name(Oid nspid)
int GetDatabaseEncoding(void)
const char * GetDatabaseEncodingName(void)
char * pstrdup(const char *in)
void * repalloc(void *pointer, Size size)
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Oid get_collation_oid(List *collname, bool missing_ok)
char * NameListToString(List *names)
#define InvokeObjectPostAlterHook(classId, objectId, subId)
const ObjectAddress InvalidObjectAddress
#define ObjectAddressSet(addr, class_id, object_id)
int parser_errposition(ParseState *pstate, int location)
Oid CollationCreate(const char *collname, Oid collnamespace, Oid collowner, char collprovider, bool collisdeterministic, int32 collencoding, const char *collcollate, const char *collctype, const char *colliculocale, const char *collicurules, const char *collversion, bool if_not_exists, bool quiet)
FormData_pg_collation * Form_pg_collation
FormData_pg_database * Form_pg_database
#define lfirst_node(type, lc)
static int list_length(const List *l)
bool lc_collate_is_c(Oid collation)
pg_locale_t pg_newlocale_from_collation(Oid collid)
bool lc_ctype_is_c(Oid collation)
char * get_collation_actual_version(char collprovider, const char *collcollate)
#define LOCALE_NAME_BUFLEN
static void static void status(const char *fmt,...) pg_attribute_printf(1
#define PG_VALID_BE_ENCODING(_enc)
int pg_strcasecmp(const char *s1, const char *s2)
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
#define qsort(a, b, c, d)
static Datum ObjectIdGetDatum(Oid X)
static Datum CStringGetDatum(const char *X)
static Datum Int32GetDatum(int32 X)
char * psprintf(const char *fmt,...)
#define RelationGetDescr(relation)
#define ERRCODE_DUPLICATE_OBJECT
bool pg_is_ascii(const char *str)
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
#define SearchSysCacheCopy1(cacheId, key1)
#define SearchSysCacheExists1(cacheId, key1)
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
text * cstring_to_text(const char *s)
void _dosmaperr(unsigned long)
void CommandCounterIncrement(void)