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;
188 if (collprovider == COLLPROVIDER_DEFAULT)
190 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
191 errmsg(
"collation \"default\" cannot be copied")));
195 char *collproviderstr = NULL;
199 colliculocale = NULL;
208 collisdeterministic =
true;
219 collprovider = COLLPROVIDER_ICU;
221 collprovider = COLLPROVIDER_LIBC;
224 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
225 errmsg(
"unrecognized collation provider: %s",
229 collprovider = COLLPROVIDER_LIBC;
233 if (collprovider == COLLPROVIDER_LIBC)
248 if (collprovider == COLLPROVIDER_LIBC)
252 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
253 errmsg(
"parameter \"lc_collate\" must be specified")));
257 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
258 errmsg(
"parameter \"lc_ctype\" must be specified")));
260 else if (collprovider == COLLPROVIDER_ICU)
264 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
265 errmsg(
"parameter \"locale\" must be specified")));
276 if (langtag && strcmp(colliculocale, langtag) != 0)
279 (
errmsg(
"using standard form \"%s\" for ICU locale \"%s\"",
280 langtag, colliculocale)));
282 colliculocale = langtag;
295 if (!collisdeterministic && collprovider != COLLPROVIDER_ICU)
297 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
298 errmsg(
"nondeterministic collations not supported with this provider")));
300 if (collicurules && collprovider != COLLPROVIDER_ICU)
302 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
303 errmsg(
"ICU rules cannot be specified unless locale provider is ICU")));
305 if (collprovider == COLLPROVIDER_ICU)
321 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
322 errmsg(
"current database's encoding is not supported with this provider")));
382 errmsg(
"collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"",
393 errmsg(
"collation \"%s\" already exists in schema \"%s\"",
416 if (collOid == DEFAULT_COLLATION_OID)
418 (
errmsg(
"cannot refresh version of default collation"),
419 errhint(
"Use ALTER DATABASE ... REFRESH COLLATION VERSION instead.")));
427 elog(
ERROR,
"cache lookup failed for collation %u", collOid);
433 datum =
SysCacheGetAttrNotNull(
COLLOID, tup, collForm->collprovider == COLLPROVIDER_ICU ? Anum_pg_collation_colliculocale : Anum_pg_collation_collcollate);
437 if ((!oldversion && newversion) || (oldversion && !newversion))
438 elog(
ERROR,
"invalid collation version change");
439 else if (oldversion && newversion && strcmp(newversion, oldversion) != 0)
441 bool nulls[Natts_pg_collation];
442 bool replaces[Natts_pg_collation];
446 (
errmsg(
"changing version from %s to %s",
447 oldversion, newversion)));
450 memset(nulls,
false,
sizeof(nulls));
451 memset(replaces,
false,
sizeof(replaces));
454 replaces[Anum_pg_collation_collversion - 1] =
true;
461 (
errmsg(
"version has not changed")));
485 if (
collid == DEFAULT_COLLATION_OID)
493 (
errcode(ERRCODE_UNDEFINED_OBJECT),
500 Anum_pg_database_daticulocale : Anum_pg_database_datcollate);
514 (
errcode(ERRCODE_UNDEFINED_OBJECT),
515 errmsg(
"collation with OID %u does not exist",
collid)));
521 Anum_pg_collation_colliculocale : Anum_pg_collation_collcollate);
538 #define READ_LOCALE_A_OUTPUT
543 #define ENUM_SYSTEM_LOCALE
547 #ifdef READ_LOCALE_A_OUTPUT
559 bool changed =
false;
567 while ((*o >=
'A' && *o <=
'Z')
568 || (*o >=
'a' && *o <=
'z')
569 || (*o >=
'0' && *o <=
'9')
605 get_icu_locale_comment(
const char *localename)
608 UChar displayname[128];
613 status = U_ZERO_ERROR;
614 len_uchar = uloc_getDisplayName(localename,
"en",
617 if (U_FAILURE(status))
621 for (
i = 0;
i < len_uchar;
i++)
623 if (displayname[
i] > 127)
628 result =
palloc(len_uchar + 1);
629 for (
i = 0;
i < len_uchar;
i++)
630 result[
i] = displayname[
i];
631 result[len_uchar] =
'\0';
699 COLLPROVIDER_LIBC,
true,
enc,
715 #ifdef ENUM_SYSTEM_LOCALE
733 win32_read_locale(LPWSTR pStr, DWORD dwFlags, LPARAM lparam)
735 CollParam *param = (CollParam *) lparam;
742 result = WideCharToMultiByte(CP_ACP, 0, pStr, -1, localebuf,
NAMEDATALEN,
747 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
748 elog(
DEBUG1,
"skipping locale with too-long name: \"%s\"", localebuf);
751 if (localebuf[0] ==
'\0')
754 enc = create_collation_from_locale(localebuf, param->nspid,
755 param->nvalidp, param->ncreatedp);
763 if (strchr(localebuf,
'-'))
768 strcpy(alias, localebuf);
769 for (
char *p = alias; *p; p++)
774 COLLPROVIDER_LIBC,
true,
enc,
775 localebuf, localebuf, NULL, NULL,
780 (*param->ncreatedp)++;
802 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
803 errmsg(
"must be superuser to import system collations")));
807 (
errcode(ERRCODE_UNDEFINED_SCHEMA),
808 errmsg(
"schema with OID %u does not exist",
nspid)));
811 #ifdef READ_LOCALE_A_OUTPUT
813 FILE *locale_a_handle;
828 if (locale_a_handle == NULL)
831 errmsg(
"could not execute command \"%s\": %m",
834 while (fgets(localebuf,
sizeof(localebuf), locale_a_handle))
840 len = strlen(localebuf);
842 if (
len == 0 || localebuf[
len - 1] !=
'\n')
844 elog(
DEBUG1,
"skipping locale with too-long name: \"%s\"", localebuf);
847 localebuf[
len - 1] =
'\0';
849 enc = create_collation_from_locale(localebuf,
nspid, &nvalid, &ncreated);
865 if (naliases >= maxaliases)
873 aliases[naliases].
enc =
enc;
901 for (
i = 0;
i < naliases;
i++)
904 char *alias = aliases[
i].
alias;
908 COLLPROVIDER_LIBC,
true,
enc,
923 (
errmsg(
"no usable system locales were found")));
945 for (
i = -1;
i < uloc_countAvailable();
i++)
955 name = uloc_getAvailable(
i);
968 COLLPROVIDER_ICU,
true, -1,
969 NULL, NULL, langtag, NULL,
978 icucomment = get_icu_locale_comment(
name);
988 #ifdef ENUM_SYSTEM_LOCALE
994 param.ncreatedp = &ncreated;
995 param.nvalidp = &nvalid;
1001 if (!EnumSystemLocalesEx(win32_read_locale, LOCALE_ALL,
1002 (LPARAM) ¶m, NULL))
1008 (
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)
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
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(const List *names, char **objname_p)
Oid get_collation_oid(List *collname, bool missing_ok)
char * NameListToString(const 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)
void icu_validate_locale(const char *loc_str)
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)
char * icu_language_tag(const char *loc_str, int elevel)
#define LOCALE_NAME_BUFLEN
#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)
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
#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)