00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include "access/heapam.h"
00018 #include "access/htup_details.h"
00019 #include "access/xact.h"
00020 #include "catalog/dependency.h"
00021 #include "catalog/indexing.h"
00022 #include "catalog/namespace.h"
00023 #include "catalog/pg_collation.h"
00024 #include "catalog/pg_collation_fn.h"
00025 #include "commands/alter.h"
00026 #include "commands/collationcmds.h"
00027 #include "commands/dbcommands.h"
00028 #include "commands/defrem.h"
00029 #include "mb/pg_wchar.h"
00030 #include "miscadmin.h"
00031 #include "utils/builtins.h"
00032 #include "utils/lsyscache.h"
00033 #include "utils/pg_locale.h"
00034 #include "utils/rel.h"
00035 #include "utils/syscache.h"
00036
00037
00038
00039
00040 Oid
00041 DefineCollation(List *names, List *parameters)
00042 {
00043 char *collName;
00044 Oid collNamespace;
00045 AclResult aclresult;
00046 ListCell *pl;
00047 DefElem *fromEl = NULL;
00048 DefElem *localeEl = NULL;
00049 DefElem *lccollateEl = NULL;
00050 DefElem *lcctypeEl = NULL;
00051 char *collcollate = NULL;
00052 char *collctype = NULL;
00053 Oid newoid;
00054
00055 collNamespace = QualifiedNameGetCreationNamespace(names, &collName);
00056
00057 aclresult = pg_namespace_aclcheck(collNamespace, GetUserId(), ACL_CREATE);
00058 if (aclresult != ACLCHECK_OK)
00059 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
00060 get_namespace_name(collNamespace));
00061
00062 foreach(pl, parameters)
00063 {
00064 DefElem *defel = (DefElem *) lfirst(pl);
00065 DefElem **defelp;
00066
00067 if (pg_strcasecmp(defel->defname, "from") == 0)
00068 defelp = &fromEl;
00069 else if (pg_strcasecmp(defel->defname, "locale") == 0)
00070 defelp = &localeEl;
00071 else if (pg_strcasecmp(defel->defname, "lc_collate") == 0)
00072 defelp = &lccollateEl;
00073 else if (pg_strcasecmp(defel->defname, "lc_ctype") == 0)
00074 defelp = &lcctypeEl;
00075 else
00076 {
00077 ereport(ERROR,
00078 (errcode(ERRCODE_SYNTAX_ERROR),
00079 errmsg("collation attribute \"%s\" not recognized",
00080 defel->defname)));
00081 break;
00082 }
00083
00084 *defelp = defel;
00085 }
00086
00087 if ((localeEl && (lccollateEl || lcctypeEl))
00088 || (fromEl && list_length(parameters) != 1))
00089 ereport(ERROR,
00090 (errcode(ERRCODE_SYNTAX_ERROR),
00091 errmsg("conflicting or redundant options")));
00092
00093 if (fromEl)
00094 {
00095 Oid collid;
00096 HeapTuple tp;
00097
00098 collid = get_collation_oid(defGetQualifiedName(fromEl), false);
00099 tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
00100 if (!HeapTupleIsValid(tp))
00101 elog(ERROR, "cache lookup failed for collation %u", collid);
00102
00103 collcollate = pstrdup(NameStr(((Form_pg_collation) GETSTRUCT(tp))->collcollate));
00104 collctype = pstrdup(NameStr(((Form_pg_collation) GETSTRUCT(tp))->collctype));
00105
00106 ReleaseSysCache(tp);
00107 }
00108
00109 if (localeEl)
00110 {
00111 collcollate = defGetString(localeEl);
00112 collctype = defGetString(localeEl);
00113 }
00114
00115 if (lccollateEl)
00116 collcollate = defGetString(lccollateEl);
00117
00118 if (lcctypeEl)
00119 collctype = defGetString(lcctypeEl);
00120
00121 if (!collcollate)
00122 ereport(ERROR,
00123 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
00124 errmsg("parameter \"lc_collate\" must be specified")));
00125
00126 if (!collctype)
00127 ereport(ERROR,
00128 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
00129 errmsg("parameter \"lc_ctype\" must be specified")));
00130
00131 check_encoding_locale_matches(GetDatabaseEncoding(), collcollate, collctype);
00132
00133 newoid = CollationCreate(collName,
00134 collNamespace,
00135 GetUserId(),
00136 GetDatabaseEncoding(),
00137 collcollate,
00138 collctype);
00139
00140
00141 CommandCounterIncrement();
00142 (void) pg_newlocale_from_collation(newoid);
00143
00144 return newoid;
00145 }
00146
00147
00148
00149
00150
00151
00152
00153 void
00154 IsThereCollationInNamespace(const char *collname, Oid nspOid)
00155 {
00156
00157 if (SearchSysCacheExists3(COLLNAMEENCNSP,
00158 CStringGetDatum(collname),
00159 Int32GetDatum(GetDatabaseEncoding()),
00160 ObjectIdGetDatum(nspOid)))
00161 ereport(ERROR,
00162 (errcode(ERRCODE_DUPLICATE_OBJECT),
00163 errmsg("collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"",
00164 collname, GetDatabaseEncodingName(),
00165 get_namespace_name(nspOid))));
00166
00167
00168 if (SearchSysCacheExists3(COLLNAMEENCNSP,
00169 CStringGetDatum(collname),
00170 Int32GetDatum(-1),
00171 ObjectIdGetDatum(nspOid)))
00172 ereport(ERROR,
00173 (errcode(ERRCODE_DUPLICATE_OBJECT),
00174 errmsg("collation \"%s\" already exists in schema \"%s\"",
00175 collname, get_namespace_name(nspOid))));
00176 }