18#include <unicode/uloc.h>
68 DefElem *deterministicEl = NULL;
73 const char *colllocale;
75 bool collisdeterministic;
78 char *collversion = NULL;
89 foreach(pl, parameters)
94 if (strcmp(defel->
defname,
"from") == 0)
96 else if (strcmp(defel->
defname,
"locale") == 0)
98 else if (strcmp(defel->
defname,
"lc_collate") == 0)
99 defelp = &lccollateEl;
100 else if (strcmp(defel->
defname,
"lc_ctype") == 0)
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)
108 else if (strcmp(defel->
defname,
"version") == 0)
113 (
errcode(ERRCODE_SYNTAX_ERROR),
114 errmsg(
"collation attribute \"%s\" not recognized",
124 if (localeEl && (lccollateEl || lcctypeEl))
127 errmsg(
"conflicting or redundant options"),
128 errdetail(
"LOCALE cannot be specified together with LC_COLLATE or LC_CTYPE."));
133 errmsg(
"conflicting or redundant options"),
134 errdetail(
"FROM cannot be specified together with any other options."));
152 datum =
SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collcollate, &isnull);
158 datum =
SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collctype, &isnull);
164 datum =
SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_colllocale, &isnull);
175 datum =
SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collicurules, &isnull);
190 if (collprovider == COLLPROVIDER_DEFAULT)
192 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
193 errmsg(
"collation \"default\" cannot be copied")));
197 char *collproviderstr = NULL;
210 collisdeterministic =
true;
221 collprovider = COLLPROVIDER_BUILTIN;
223 collprovider = COLLPROVIDER_ICU;
225 collprovider = COLLPROVIDER_LIBC;
228 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
229 errmsg(
"unrecognized collation provider: %s",
233 collprovider = COLLPROVIDER_LIBC;
237 if (collprovider == COLLPROVIDER_LIBC)
252 if (collprovider == COLLPROVIDER_BUILTIN)
256 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
257 errmsg(
"parameter \"%s\" must be specified",
263 else if (collprovider == COLLPROVIDER_LIBC)
267 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
268 errmsg(
"parameter \"%s\" must be specified",
273 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
274 errmsg(
"parameter \"%s\" must be specified",
277 else if (collprovider == COLLPROVIDER_ICU)
281 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
282 errmsg(
"parameter \"%s\" must be specified",
294 if (langtag && strcmp(colllocale, langtag) != 0)
297 (
errmsg(
"using standard form \"%s\" for ICU locale \"%s\"",
298 langtag, colllocale)));
300 colllocale = langtag;
313 if (!collisdeterministic && collprovider != COLLPROVIDER_ICU)
315 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
316 errmsg(
"nondeterministic collations not supported with this provider")));
318 if (collicurules && collprovider != COLLPROVIDER_ICU)
320 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
321 errmsg(
"ICU rules cannot be specified unless locale provider is ICU")));
323 if (collprovider == COLLPROVIDER_BUILTIN)
327 else if (collprovider == COLLPROVIDER_ICU)
343 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
344 errmsg(
"current database's encoding is not supported with this provider")));
359 if (collprovider == COLLPROVIDER_LIBC)
409 errmsg(
"collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"",
420 errmsg(
"collation \"%s\" already exists in schema \"%s\"",
443 if (collOid == DEFAULT_COLLATION_OID)
445 (
errmsg(
"cannot refresh version of default collation"),
448 "ALTER DATABASE ... REFRESH COLLATION VERSION")));
456 elog(
ERROR,
"cache lookup failed for collation %u", collOid);
459 datum =
SysCacheGetAttr(COLLOID, tup, Anum_pg_collation_collversion, &isnull);
462 if (collForm->collprovider == COLLPROVIDER_LIBC)
471 if ((!oldversion && newversion) || (oldversion && !newversion))
472 elog(
ERROR,
"invalid collation version change");
473 else if (oldversion && newversion && strcmp(newversion, oldversion) != 0)
475 bool nulls[Natts_pg_collation];
476 bool replaces[Natts_pg_collation];
480 (
errmsg(
"changing version from %s to %s",
481 oldversion, newversion)));
484 memset(nulls,
false,
sizeof(nulls));
485 memset(replaces,
false,
sizeof(replaces));
488 replaces[Anum_pg_collation_collversion - 1] =
true;
495 (
errmsg(
"version has not changed")));
519 if (
collid == DEFAULT_COLLATION_OID)
527 (
errcode(ERRCODE_UNDEFINED_OBJECT),
553 (
errcode(ERRCODE_UNDEFINED_OBJECT),
554 errmsg(
"collation with OID %u does not exist",
collid)));
583#define READ_LOCALE_A_OUTPUT
588#define ENUM_SYSTEM_LOCALE
592#ifdef READ_LOCALE_A_OUTPUT
604 bool changed =
false;
612 while ((*o >=
'A' && *o <=
'Z')
613 || (*o >=
'a' && *o <=
'z')
614 || (*o >=
'0' && *o <=
'9')
650get_icu_locale_comment(
const char *localename)
653 UChar displayname[128];
658 status = U_ZERO_ERROR;
659 len_uchar = uloc_getDisplayName(localename,
"en",
662 if (U_FAILURE(status))
666 for (
i = 0;
i < len_uchar;
i++)
668 if (displayname[
i] > 127)
673 result =
palloc(len_uchar + 1);
674 for (
i = 0;
i < len_uchar;
i++)
675 result[
i] = displayname[
i];
676 result[len_uchar] =
'\0';
744 COLLPROVIDER_LIBC,
true,
enc,
760#ifdef ENUM_SYSTEM_LOCALE
778win32_read_locale(LPWSTR pStr, DWORD dwFlags, LPARAM lparam)
780 CollParam *param = (CollParam *) lparam;
787 result = WideCharToMultiByte(CP_ACP, 0, pStr, -1, localebuf,
NAMEDATALEN,
792 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
793 elog(
DEBUG1,
"skipping locale with too-long name: \"%s\"", localebuf);
796 if (localebuf[0] ==
'\0')
799 enc = create_collation_from_locale(localebuf, param->nspid,
800 param->nvalidp, param->ncreatedp);
808 if (strchr(localebuf,
'-'))
813 strcpy(alias, localebuf);
814 for (
char *p = alias; *p; p++)
819 COLLPROVIDER_LIBC,
true,
enc,
820 localebuf, localebuf, NULL, NULL,
825 (*param->ncreatedp)++;
847 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
848 errmsg(
"must be superuser to import system collations")));
852 (
errcode(ERRCODE_UNDEFINED_SCHEMA),
853 errmsg(
"schema with OID %u does not exist",
nspid)));
856#ifdef READ_LOCALE_A_OUTPUT
858 FILE *locale_a_handle;
873 if (locale_a_handle == NULL)
876 errmsg(
"could not execute command \"%s\": %m",
879 while (fgets(localebuf,
sizeof(localebuf), locale_a_handle))
885 len = strlen(localebuf);
887 if (
len == 0 || localebuf[
len - 1] !=
'\n')
889 elog(
DEBUG1,
"skipping locale with too-long name: \"%s\"", localebuf);
892 localebuf[
len - 1] =
'\0';
894 enc = create_collation_from_locale(localebuf,
nspid, &nvalid, &ncreated);
910 if (naliases >= maxaliases)
918 aliases[naliases].
enc =
enc;
946 for (
i = 0;
i < naliases;
i++)
949 char *alias = aliases[
i].
alias;
953 COLLPROVIDER_LIBC,
true,
enc,
968 (
errmsg(
"no usable system locales were found")));
990 for (
i = -1;
i < uloc_countAvailable();
i++)
1000 name = uloc_getAvailable(
i);
1013 COLLPROVIDER_ICU,
true, -1,
1014 NULL, NULL, langtag, NULL,
1023 icucomment = get_icu_locale_comment(
name);
1033#ifdef ENUM_SYSTEM_LOCALE
1038 param.nspid =
nspid;
1039 param.ncreatedp = &ncreated;
1040 param.nvalidp = &nvalid;
1046 if (!EnumSystemLocalesEx(win32_read_locale, LOCALE_ALL,
1047 (LPARAM) ¶m, NULL))
1053 (
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)
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)
Assert(PointerIsAligned(start, uint64))
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, const ItemPointerData *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)