64 DefElem *deterministicEl = NULL;
69 const char *colllocale;
71 bool collisdeterministic;
74 char *collversion = NULL;
85 foreach(pl, parameters)
90 if (strcmp(defel->
defname,
"from") == 0)
92 else if (strcmp(defel->
defname,
"locale") == 0)
94 else if (strcmp(defel->
defname,
"lc_collate") == 0)
95 defelp = &lccollateEl;
96 else if (strcmp(defel->
defname,
"lc_ctype") == 0)
98 else if (strcmp(defel->
defname,
"provider") == 0)
100 else if (strcmp(defel->
defname,
"deterministic") == 0)
101 defelp = &deterministicEl;
102 else if (strcmp(defel->
defname,
"rules") == 0)
104 else if (strcmp(defel->
defname,
"version") == 0)
109 (
errcode(ERRCODE_SYNTAX_ERROR),
110 errmsg(
"collation attribute \"%s\" not recognized",
120 if (localeEl && (lccollateEl || lcctypeEl))
123 errmsg(
"conflicting or redundant options"),
124 errdetail(
"LOCALE cannot be specified together with LC_COLLATE or LC_CTYPE."));
129 errmsg(
"conflicting or redundant options"),
130 errdetail(
"FROM cannot be specified together with any other options."));
148 datum =
SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collcollate, &isnull);
154 datum =
SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collctype, &isnull);
160 datum =
SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_colllocale, &isnull);
171 datum =
SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collicurules, &isnull);
186 if (collprovider == COLLPROVIDER_DEFAULT)
188 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
189 errmsg(
"collation \"default\" cannot be copied")));
193 char *collproviderstr = NULL;
206 collisdeterministic =
true;
217 collprovider = COLLPROVIDER_BUILTIN;
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_BUILTIN)
252 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
253 errmsg(
"parameter \"%s\" must be specified",
259 else if (collprovider == COLLPROVIDER_LIBC)
263 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
264 errmsg(
"parameter \"%s\" must be specified",
269 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
270 errmsg(
"parameter \"%s\" must be specified",
273 else if (collprovider == COLLPROVIDER_ICU)
277 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
278 errmsg(
"parameter \"%s\" must be specified",
290 if (langtag && strcmp(colllocale, langtag) != 0)
293 (
errmsg(
"using standard form \"%s\" for ICU locale \"%s\"",
294 langtag, colllocale)));
296 colllocale = langtag;
309 if (!collisdeterministic && collprovider != COLLPROVIDER_ICU)
311 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
312 errmsg(
"nondeterministic collations not supported with this provider")));
314 if (collicurules && collprovider != COLLPROVIDER_ICU)
316 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
317 errmsg(
"ICU rules cannot be specified unless locale provider is ICU")));
319 if (collprovider == COLLPROVIDER_BUILTIN)
323 else if (collprovider == COLLPROVIDER_ICU)
339 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
340 errmsg(
"current database's encoding is not supported with this provider")));
355 if (collprovider == COLLPROVIDER_LIBC)
405 errmsg(
"collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"",
416 errmsg(
"collation \"%s\" already exists in schema \"%s\"",
439 if (collOid == DEFAULT_COLLATION_OID)
441 (
errmsg(
"cannot refresh version of default collation"),
444 "ALTER DATABASE ... REFRESH COLLATION VERSION")));
452 elog(
ERROR,
"cache lookup failed for collation %u", collOid);
455 datum =
SysCacheGetAttr(COLLOID, tup, Anum_pg_collation_collversion, &isnull);
458 if (collForm->collprovider == COLLPROVIDER_LIBC)
467 if ((!oldversion && newversion) || (oldversion && !newversion))
468 elog(
ERROR,
"invalid collation version change");
469 else if (oldversion && newversion && strcmp(newversion, oldversion) != 0)
471 bool nulls[Natts_pg_collation];
472 bool replaces[Natts_pg_collation];
476 (
errmsg(
"changing version from %s to %s",
477 oldversion, newversion)));
480 memset(nulls,
false,
sizeof(nulls));
481 memset(replaces,
false,
sizeof(replaces));
484 replaces[Anum_pg_collation_collversion - 1] =
true;
491 (
errmsg(
"version has not changed")));
515 if (
collid == DEFAULT_COLLATION_OID)
523 (
errcode(ERRCODE_UNDEFINED_OBJECT),
549 (
errcode(ERRCODE_UNDEFINED_OBJECT),
550 errmsg(
"collation with OID %u does not exist",
collid)));
579#define READ_LOCALE_A_OUTPUT
584#define ENUM_SYSTEM_LOCALE
588#ifdef READ_LOCALE_A_OUTPUT
600 bool changed =
false;
608 while ((*o >=
'A' && *o <=
'Z')
609 || (*o >=
'a' && *o <=
'z')
610 || (*o >=
'0' && *o <=
'9')
646get_icu_locale_comment(
const char *localename)
649 UChar displayname[128];
654 status = U_ZERO_ERROR;
655 len_uchar = uloc_getDisplayName(localename,
"en",
658 if (U_FAILURE(status))
662 for (
i = 0;
i < len_uchar;
i++)
664 if (displayname[
i] > 127)
669 result =
palloc(len_uchar + 1);
670 for (
i = 0;
i < len_uchar;
i++)
671 result[
i] = displayname[
i];
672 result[len_uchar] =
'\0';
740 COLLPROVIDER_LIBC,
true,
enc,
756#ifdef ENUM_SYSTEM_LOCALE
774win32_read_locale(LPWSTR pStr, DWORD dwFlags, LPARAM lparam)
776 CollParam *param = (CollParam *) lparam;
783 result = WideCharToMultiByte(CP_ACP, 0, pStr, -1, localebuf,
NAMEDATALEN,
788 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
789 elog(
DEBUG1,
"skipping locale with too-long name: \"%s\"", localebuf);
792 if (localebuf[0] ==
'\0')
795 enc = create_collation_from_locale(localebuf, param->nspid,
796 param->nvalidp, param->ncreatedp);
804 if (strchr(localebuf,
'-'))
809 strcpy(alias, localebuf);
810 for (
char *p = alias; *p; p++)
815 COLLPROVIDER_LIBC,
true,
enc,
816 localebuf, localebuf, NULL, NULL,
821 (*param->ncreatedp)++;
843 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
844 errmsg(
"must be superuser to import system collations")));
848 (
errcode(ERRCODE_UNDEFINED_SCHEMA),
849 errmsg(
"schema with OID %u does not exist",
nspid)));
852#ifdef READ_LOCALE_A_OUTPUT
854 FILE *locale_a_handle;
869 if (locale_a_handle == NULL)
872 errmsg(
"could not execute command \"%s\": %m",
875 while (fgets(localebuf,
sizeof(localebuf), locale_a_handle))
881 len = strlen(localebuf);
883 if (
len == 0 || localebuf[
len - 1] !=
'\n')
885 elog(
DEBUG1,
"skipping locale with too-long name: \"%s\"", localebuf);
888 localebuf[
len - 1] =
'\0';
890 enc = create_collation_from_locale(localebuf,
nspid, &nvalid, &ncreated);
906 if (naliases >= maxaliases)
914 aliases[naliases].
enc =
enc;
942 for (
i = 0;
i < naliases;
i++)
945 char *alias = aliases[
i].
alias;
949 COLLPROVIDER_LIBC,
true,
enc,
964 (
errmsg(
"no usable system locales were found")));
986 for (
i = -1;
i < uloc_countAvailable();
i++)
996 name = uloc_getAvailable(
i);
1009 COLLPROVIDER_ICU,
true, -1,
1010 NULL, NULL, langtag, NULL,
1019 icucomment = get_icu_locale_comment(
name);
1029#ifdef ENUM_SYSTEM_LOCALE
1034 param.nspid =
nspid;
1035 param.ncreatedp = &ncreated;
1036 param.nvalidp = &nvalid;
1042 if (!EnumSystemLocalesEx(win32_read_locale, LOCALE_ALL,
1043 (LPARAM) ¶m, NULL))
1049 (
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 Assert(condition)
#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)
char * defGetString(DefElem *def)
bool defGetBoolean(DefElem *def)
List * defGetQualifiedName(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)
FILE * OpenPipeStream(const char *command, const char *mode)
int ClosePipeStream(FILE *file)
#define PG_RETURN_TEXT_P(x)
#define PG_RETURN_INT32(x)
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
void heap_freetuple(HeapTuple htup)
#define HeapTupleIsValid(tuple)
static void * GETSTRUCT(const HeapTupleData *tuple)
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
static JitProviderCallbacks provider
char * get_namespace_name(Oid nspid)
int GetDatabaseEncoding(void)
const char * GetDatabaseEncodingName(void)
char * pstrdup(const char *in)
void * repalloc(void *pointer, Size size)
char * NameListToString(const List *names)
Oid QualifiedNameGetCreationNamespace(const List *names, char **objname_p)
Oid get_collation_oid(List *collname, bool missing_ok)
#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 *colllocale, 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)
void icu_validate_locale(const char *loc_str)
char * get_collation_actual_version(char collprovider, const char *collcollate)
pg_locale_t pg_newlocale_from_collation(Oid collid)
int builtin_locale_encoding(const char *locale)
char * icu_language_tag(const char *loc_str, int elevel)
const char * builtin_validate_locale(int encoding, const char *locale)
#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)