PostgreSQL Source Code  git master
collationcmds.h File Reference
Include dependency graph for collationcmds.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

ObjectAddress DefineCollation (ParseState *pstate, List *names, List *parameters, bool if_not_exists)
 
void IsThereCollationInNamespace (const char *collname, Oid nspOid)
 

Function Documentation

◆ DefineCollation()

ObjectAddress DefineCollation ( ParseState pstate,
List names,
List parameters,
bool  if_not_exists 
)

Definition at line 53 of file collationcmds.c.

References ACL_CREATE, aclcheck_error(), ACLCHECK_OK, check_encoding_locale_matches(), CollationCreate(), COLLOID, CommandCounterIncrement(), defGetBoolean(), defGetQualifiedName(), defGetString(), DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, get_collation_oid(), get_namespace_name(), GetDatabaseEncoding(), GETSTRUCT, GetUserId(), HeapTupleIsValid, InvalidObjectAddress, lc_collate_is_c(), lc_ctype_is_c(), lfirst_node, list_length(), DefElem::location, NameStr, OBJECT_SCHEMA, ObjectAddressSet, ObjectIdGetDatum, OidIsValid, parser_errposition(), pg_namespace_aclcheck(), pg_newlocale_from_collation(), pg_strcasecmp(), pstrdup(), QualifiedNameGetCreationNamespace(), ReleaseSysCache(), and SearchSysCache1().

Referenced by ProcessUtilitySlow().

54 {
55  char *collName;
56  Oid collNamespace;
57  AclResult aclresult;
58  ListCell *pl;
59  DefElem *fromEl = NULL;
60  DefElem *localeEl = NULL;
61  DefElem *lccollateEl = NULL;
62  DefElem *lcctypeEl = NULL;
63  DefElem *providerEl = NULL;
64  DefElem *deterministicEl = NULL;
65  char *collcollate = NULL;
66  char *collctype = NULL;
67  char *collproviderstr = NULL;
68  bool collisdeterministic = true;
69  int collencoding = 0;
70  char collprovider = 0;
71  Oid newoid;
72  ObjectAddress address;
73 
74  collNamespace = QualifiedNameGetCreationNamespace(names, &collName);
75 
76  aclresult = pg_namespace_aclcheck(collNamespace, GetUserId(), ACL_CREATE);
77  if (aclresult != ACLCHECK_OK)
78  aclcheck_error(aclresult, OBJECT_SCHEMA,
79  get_namespace_name(collNamespace));
80 
81  foreach(pl, parameters)
82  {
83  DefElem *defel = lfirst_node(DefElem, pl);
84  DefElem **defelp;
85 
86  if (strcmp(defel->defname, "from") == 0)
87  defelp = &fromEl;
88  else if (strcmp(defel->defname, "locale") == 0)
89  defelp = &localeEl;
90  else if (strcmp(defel->defname, "lc_collate") == 0)
91  defelp = &lccollateEl;
92  else if (strcmp(defel->defname, "lc_ctype") == 0)
93  defelp = &lcctypeEl;
94  else if (strcmp(defel->defname, "provider") == 0)
95  defelp = &providerEl;
96  else if (strcmp(defel->defname, "deterministic") == 0)
97  defelp = &deterministicEl;
98  else
99  {
100  ereport(ERROR,
101  (errcode(ERRCODE_SYNTAX_ERROR),
102  errmsg("collation attribute \"%s\" not recognized",
103  defel->defname),
104  parser_errposition(pstate, defel->location)));
105  break;
106  }
107 
108  *defelp = defel;
109  }
110 
111  if ((localeEl && (lccollateEl || lcctypeEl))
112  || (fromEl && list_length(parameters) != 1))
113  ereport(ERROR,
114  (errcode(ERRCODE_SYNTAX_ERROR),
115  errmsg("conflicting or redundant options")));
116 
117  if (fromEl)
118  {
119  Oid collid;
120  HeapTuple tp;
121 
122  collid = get_collation_oid(defGetQualifiedName(fromEl), false);
124  if (!HeapTupleIsValid(tp))
125  elog(ERROR, "cache lookup failed for collation %u", collid);
126 
127  collcollate = pstrdup(NameStr(((Form_pg_collation) GETSTRUCT(tp))->collcollate));
128  collctype = pstrdup(NameStr(((Form_pg_collation) GETSTRUCT(tp))->collctype));
129  collprovider = ((Form_pg_collation) GETSTRUCT(tp))->collprovider;
130  collisdeterministic = ((Form_pg_collation) GETSTRUCT(tp))->collisdeterministic;
131  collencoding = ((Form_pg_collation) GETSTRUCT(tp))->collencoding;
132 
133  ReleaseSysCache(tp);
134 
135  /*
136  * Copying the "default" collation is not allowed because most code
137  * checks for DEFAULT_COLLATION_OID instead of COLLPROVIDER_DEFAULT,
138  * and so having a second collation with COLLPROVIDER_DEFAULT would
139  * not work and potentially confuse or crash some code. This could be
140  * fixed with some legwork.
141  */
142  if (collprovider == COLLPROVIDER_DEFAULT)
143  ereport(ERROR,
144  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
145  errmsg("collation \"default\" cannot be copied")));
146  }
147 
148  if (localeEl)
149  {
150  collcollate = defGetString(localeEl);
151  collctype = defGetString(localeEl);
152  }
153 
154  if (lccollateEl)
155  collcollate = defGetString(lccollateEl);
156 
157  if (lcctypeEl)
158  collctype = defGetString(lcctypeEl);
159 
160  if (providerEl)
161  collproviderstr = defGetString(providerEl);
162 
163  if (deterministicEl)
164  collisdeterministic = defGetBoolean(deterministicEl);
165 
166  if (collproviderstr)
167  {
168  if (pg_strcasecmp(collproviderstr, "icu") == 0)
169  collprovider = COLLPROVIDER_ICU;
170  else if (pg_strcasecmp(collproviderstr, "libc") == 0)
171  collprovider = COLLPROVIDER_LIBC;
172  else
173  ereport(ERROR,
174  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
175  errmsg("unrecognized collation provider: %s",
176  collproviderstr)));
177  }
178  else if (!fromEl)
179  collprovider = COLLPROVIDER_LIBC;
180 
181  if (!collcollate)
182  ereport(ERROR,
183  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
184  errmsg("parameter \"lc_collate\" must be specified")));
185 
186  if (!collctype)
187  ereport(ERROR,
188  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
189  errmsg("parameter \"lc_ctype\" must be specified")));
190 
191  /*
192  * Nondeterministic collations are currently only supported with ICU
193  * because that's the only case where it can actually make a difference.
194  * So we can save writing the code for the other providers.
195  */
196  if (!collisdeterministic && collprovider != COLLPROVIDER_ICU)
197  ereport(ERROR,
198  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
199  errmsg("nondeterministic collations not supported with this provider")));
200 
201  if (!fromEl)
202  {
203  if (collprovider == COLLPROVIDER_ICU)
204  collencoding = -1;
205  else
206  {
207  collencoding = GetDatabaseEncoding();
208  check_encoding_locale_matches(collencoding, collcollate, collctype);
209  }
210  }
211 
212  newoid = CollationCreate(collName,
213  collNamespace,
214  GetUserId(),
215  collprovider,
216  collisdeterministic,
217  collencoding,
218  collcollate,
219  collctype,
220  if_not_exists,
221  false); /* not quiet */
222 
223  if (!OidIsValid(newoid))
224  return InvalidObjectAddress;
225 
226  /*
227  * Check that the locales can be loaded. NB: pg_newlocale_from_collation
228  * is only supposed to be called on non-C-equivalent locales.
229  */
231  if (!lc_collate_is_c(newoid) || !lc_ctype_is_c(newoid))
232  (void) pg_newlocale_from_collation(newoid);
233 
234  ObjectAddressSet(address, CollationRelationId, newoid);
235 
236  return address;
237 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void check_encoding_locale_matches(int encoding, const char *collate, const char *ctype)
Definition: dbcommands.c:755
Oid GetUserId(void)
Definition: miscinit.c:476
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2994
char * pstrdup(const char *in)
Definition: mcxt.c:1187
Oid CollationCreate(const char *collname, Oid collnamespace, Oid collowner, char collprovider, bool collisdeterministic, int32 collencoding, const char *collcollate, const char *collctype, bool if_not_exists, bool quiet)
Definition: pg_collation.c:46
int errcode(int sqlerrcode)
Definition: elog.c:704
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:698
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4628
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3297
bool defGetBoolean(DefElem *def)
Definition: define.c:111
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
#define ACL_CREATE
Definition: parsenodes.h:84
bool lc_collate_is_c(Oid collation)
Definition: pg_locale.c:1326
char * defGetString(DefElem *def)
Definition: define.c:49
#define lfirst_node(type, lc)
Definition: pg_list.h:172
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3289
int location
Definition: parsenodes.h:736
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
pg_locale_t pg_newlocale_from_collation(Oid collid)
Definition: pg_locale.c:1473
AclResult
Definition: acl.h:177
void CommandCounterIncrement(void)
Definition: xact.c:1021
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
int GetDatabaseEncoding(void)
Definition: mbutils.c:1151
#define ereport(elevel,...)
Definition: elog.h:155
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
static int list_length(const List *l)
Definition: pg_list.h:149
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:47
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:915
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:669
char * defname
Definition: parsenodes.h:733
bool lc_ctype_is_c(Oid collation)
Definition: pg_locale.c:1376
Oid get_collation_oid(List *name, bool missing_ok)
Definition: namespace.c:3600

◆ IsThereCollationInNamespace()

void IsThereCollationInNamespace ( const char *  collname,
Oid  nspOid 
)

Definition at line 246 of file collationcmds.c.

References COLLNAMEENCNSP, CStringGetDatum, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, get_namespace_name(), GetDatabaseEncoding(), GetDatabaseEncodingName(), Int32GetDatum, ObjectIdGetDatum, and SearchSysCacheExists3.

Referenced by AlterObjectNamespace_internal(), and AlterObjectRename_internal().

247 {
248  /* make sure the name doesn't already exist in new schema */
250  CStringGetDatum(collname),
252  ObjectIdGetDatum(nspOid)))
253  ereport(ERROR,
255  errmsg("collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"",
256  collname, GetDatabaseEncodingName(),
257  get_namespace_name(nspOid))));
258 
259  /* mustn't match an any-encoding entry, either */
261  CStringGetDatum(collname),
262  Int32GetDatum(-1),
263  ObjectIdGetDatum(nspOid)))
264  ereport(ERROR,
266  errmsg("collation \"%s\" already exists in schema \"%s\"",
267  collname, get_namespace_name(nspOid))));
268 }
int errcode(int sqlerrcode)
Definition: elog.c:704
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:188
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3289
#define CStringGetDatum(X)
Definition: postgres.h:578
int GetDatabaseEncoding(void)
Definition: mbutils.c:1151
#define ereport(elevel,...)
Definition: elog.h:155
const char * GetDatabaseEncodingName(void)
Definition: mbutils.c:1157
#define Int32GetDatum(X)
Definition: postgres.h:479
int errmsg(const char *fmt,...)
Definition: elog.c:915
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32