PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
collationcmds.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/xact.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_collation_fn.h"
#include "commands/alter.h"
#include "commands/collationcmds.h"
#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/pg_locale.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Include dependency graph for collationcmds.c:

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)
 
 pg_attribute_unused ()
 
Datum pg_import_system_collations (PG_FUNCTION_ARGS)
 

Function Documentation

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

Definition at line 40 of file collationcmds.c.

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

Referenced by ProcessUtilitySlow().

41 {
42  char *collName;
43  Oid collNamespace;
44  AclResult aclresult;
45  ListCell *pl;
46  DefElem *fromEl = NULL;
47  DefElem *localeEl = NULL;
48  DefElem *lccollateEl = NULL;
49  DefElem *lcctypeEl = NULL;
50  char *collcollate = NULL;
51  char *collctype = NULL;
52  Oid newoid;
53  ObjectAddress address;
54 
55  collNamespace = QualifiedNameGetCreationNamespace(names, &collName);
56 
57  aclresult = pg_namespace_aclcheck(collNamespace, GetUserId(), ACL_CREATE);
58  if (aclresult != ACLCHECK_OK)
60  get_namespace_name(collNamespace));
61 
62  foreach(pl, parameters)
63  {
64  DefElem *defel = castNode(DefElem, lfirst(pl));
65  DefElem **defelp;
66 
67  if (pg_strcasecmp(defel->defname, "from") == 0)
68  defelp = &fromEl;
69  else if (pg_strcasecmp(defel->defname, "locale") == 0)
70  defelp = &localeEl;
71  else if (pg_strcasecmp(defel->defname, "lc_collate") == 0)
72  defelp = &lccollateEl;
73  else if (pg_strcasecmp(defel->defname, "lc_ctype") == 0)
74  defelp = &lcctypeEl;
75  else
76  {
77  ereport(ERROR,
78  (errcode(ERRCODE_SYNTAX_ERROR),
79  errmsg("collation attribute \"%s\" not recognized",
80  defel->defname),
81  parser_errposition(pstate, defel->location)));
82  break;
83  }
84 
85  *defelp = defel;
86  }
87 
88  if ((localeEl && (lccollateEl || lcctypeEl))
89  || (fromEl && list_length(parameters) != 1))
90  ereport(ERROR,
91  (errcode(ERRCODE_SYNTAX_ERROR),
92  errmsg("conflicting or redundant options")));
93 
94  if (fromEl)
95  {
96  Oid collid;
97  HeapTuple tp;
98 
99  collid = get_collation_oid(defGetQualifiedName(fromEl), false);
101  if (!HeapTupleIsValid(tp))
102  elog(ERROR, "cache lookup failed for collation %u", collid);
103 
104  collcollate = pstrdup(NameStr(((Form_pg_collation) GETSTRUCT(tp))->collcollate));
105  collctype = pstrdup(NameStr(((Form_pg_collation) GETSTRUCT(tp))->collctype));
106 
107  ReleaseSysCache(tp);
108  }
109 
110  if (localeEl)
111  {
112  collcollate = defGetString(localeEl);
113  collctype = defGetString(localeEl);
114  }
115 
116  if (lccollateEl)
117  collcollate = defGetString(lccollateEl);
118 
119  if (lcctypeEl)
120  collctype = defGetString(lcctypeEl);
121 
122  if (!collcollate)
123  ereport(ERROR,
124  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
125  errmsg("parameter \"lc_collate\" must be specified")));
126 
127  if (!collctype)
128  ereport(ERROR,
129  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
130  errmsg("parameter \"lc_ctype\" must be specified")));
131 
132  check_encoding_locale_matches(GetDatabaseEncoding(), collcollate, collctype);
133 
134  newoid = CollationCreate(collName,
135  collNamespace,
136  GetUserId(),
138  collcollate,
139  collctype,
140  if_not_exists);
141 
142  if (!OidIsValid(newoid))
143  return InvalidObjectAddress;
144 
145  ObjectAddressSet(address, CollationRelationId, newoid);
146 
147  /* check that the locales can be loaded */
149  (void) pg_newlocale_from_collation(newoid);
150 
151  return address;
152 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
void check_encoding_locale_matches(int encoding, const char *collate, const char *ctype)
Definition: dbcommands.c:723
Oid GetUserId(void)
Definition: miscinit.c:283
#define castNode(_type_, nodeptr)
Definition: nodes.h:577
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2790
char * pstrdup(const char *in)
Definition: mcxt.c:1165
int errcode(int sqlerrcode)
Definition: elog.c:575
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
unsigned int Oid
Definition: postgres_ext.h:31
Oid CollationCreate(const char *collname, Oid collnamespace, Oid collowner, int32 collencoding, const char *collcollate, const char *collctype, bool if_not_exists)
Definition: pg_collation.c:41
#define OidIsValid(objectId)
Definition: c.h:534
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4459
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:75
char * defGetString(DefElem *def)
Definition: define.c:49
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3378
int location
Definition: parsenodes.h:678
#define ereport(elevel, rest)
Definition: elog.h:122
pg_locale_t pg_newlocale_from_collation(Oid collid)
Definition: pg_locale.c:1260
AclResult
Definition: acl.h:170
void CommandCounterIncrement(void)
Definition: xact.c:921
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
int GetDatabaseEncoding(void)
Definition: mbutils.c:1015
#define CollationRelationId
Definition: pg_collation.h:30
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
static int list_length(const List *l)
Definition: pg_list.h:89
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:109
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:797
#define NameStr(name)
Definition: c.h:495
char * defname
Definition: parsenodes.h:675
#define elog
Definition: elog.h:219
Oid get_collation_oid(List *name, bool missing_ok)
Definition: namespace.c:3324
void IsThereCollationInNamespace ( const char *  collname,
Oid  nspOid 
)

Definition at line 161 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().

162 {
163  /* make sure the name doesn't already exist in new schema */
165  CStringGetDatum(collname),
167  ObjectIdGetDatum(nspOid)))
168  ereport(ERROR,
170  errmsg("collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"",
171  collname, GetDatabaseEncodingName(),
172  get_namespace_name(nspOid))));
173 
174  /* mustn't match an any-encoding entry, either */
176  CStringGetDatum(collname),
177  Int32GetDatum(-1),
178  ObjectIdGetDatum(nspOid)))
179  ereport(ERROR,
181  errmsg("collation \"%s\" already exists in schema \"%s\"",
182  collname, get_namespace_name(nspOid))));
183 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:171
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
#define CStringGetDatum(X)
Definition: postgres.h:586
#define ereport(elevel, rest)
Definition: elog.h:122
int GetDatabaseEncoding(void)
Definition: mbutils.c:1015
const char * GetDatabaseEncodingName(void)
Definition: mbutils.c:1021
#define Int32GetDatum(X)
Definition: postgres.h:487
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:34
pg_attribute_unused ( )

Definition at line 192 of file collationcmds.c.

195 {
196  char *n = new;
197  const char *o = old;
198  bool changed = false;
199 
200  while (*o)
201  {
202  if (*o == '.')
203  {
204  /* skip over encoding tag such as ".utf8" or ".UTF-8" */
205  o++;
206  while ((*o >= 'A' && *o <= 'Z')
207  || (*o >= 'a' && *o <= 'z')
208  || (*o >= '0' && *o <= '9')
209  || (*o == '-'))
210  o++;
211  changed = true;
212  }
213  else
214  *n++ = *o++;
215  }
216  *n = '\0';
217 
218  return changed;
219 }
Datum pg_import_system_collations ( PG_FUNCTION_ARGS  )

Definition at line 223 of file collationcmds.c.

References ClosePipeStream(), CollationCreate(), CommandCounterIncrement(), DEBUG1, elog, enc, enclist, ereport, errcode(), errcode_for_file_access(), errmsg(), ERROR, forthree, GetUserId(), i, IS_HIGHBIT_SET, lappend(), lappend_int(), lca(), lfirst, lfirst_int, locale, NAMEDATALEN, NIL, NULL, OpenPipeStream(), pg_get_encoding_from_locale(), PG_GETARG_BOOL, PG_GETARG_OID, PG_RETURN_VOID, PG_SQL_ASCII, PG_VALID_BE_ENCODING, pstrdup(), skip(), superuser(), and WARNING.

224 {
225 #if defined(HAVE_LOCALE_T) && !defined(WIN32)
226  bool if_not_exists = PG_GETARG_BOOL(0);
227  Oid nspid = PG_GETARG_OID(1);
228 
229  FILE *locale_a_handle;
230  char localebuf[NAMEDATALEN]; /* we assume ASCII so this is fine */
231  int count = 0;
232  List *aliaslist = NIL;
233  List *localelist = NIL;
234  List *enclist = NIL;
235  ListCell *lca,
236  *lcl,
237  *lce;
238 #endif
239 
240  if (!superuser())
241  ereport(ERROR,
242  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
243  (errmsg("must be superuser to import system collations"))));
244 
245 #if defined(HAVE_LOCALE_T) && !defined(WIN32)
246  locale_a_handle = OpenPipeStream("locale -a", "r");
247  if (locale_a_handle == NULL)
248  ereport(ERROR,
250  errmsg("could not execute command \"%s\": %m",
251  "locale -a")));
252 
253  while (fgets(localebuf, sizeof(localebuf), locale_a_handle))
254  {
255  int i;
256  size_t len;
257  int enc;
258  bool skip;
259  char alias[NAMEDATALEN];
260 
261  len = strlen(localebuf);
262 
263  if (len == 0 || localebuf[len - 1] != '\n')
264  {
265  elog(DEBUG1, "locale name too long, skipped: \"%s\"", localebuf);
266  continue;
267  }
268  localebuf[len - 1] = '\0';
269 
270  /*
271  * Some systems have locale names that don't consist entirely of ASCII
272  * letters (such as "bokm&aring;l" or "fran&ccedil;ais"). This is
273  * pretty silly, since we need the locale itself to interpret the
274  * non-ASCII characters. We can't do much with those, so we filter
275  * them out.
276  */
277  skip = false;
278  for (i = 0; i < len; i++)
279  {
280  if (IS_HIGHBIT_SET(localebuf[i]))
281  {
282  skip = true;
283  break;
284  }
285  }
286  if (skip)
287  {
288  elog(DEBUG1, "locale name has non-ASCII characters, skipped: \"%s\"", localebuf);
289  continue;
290  }
291 
292  enc = pg_get_encoding_from_locale(localebuf, false);
293  if (enc < 0)
294  {
295  /* error message printed by pg_get_encoding_from_locale() */
296  continue;
297  }
298  if (!PG_VALID_BE_ENCODING(enc))
299  continue; /* ignore locales for client-only encodings */
300  if (enc == PG_SQL_ASCII)
301  continue; /* C/POSIX are already in the catalog */
302 
303  count++;
304 
305  CollationCreate(localebuf, nspid, GetUserId(), enc,
306  localebuf, localebuf, if_not_exists);
307 
309 
310  /*
311  * Generate aliases such as "en_US" in addition to "en_US.utf8" for
312  * ease of use. Note that collation names are unique per encoding
313  * only, so this doesn't clash with "en_US" for LATIN1, say.
314  *
315  * However, it might conflict with a name we'll see later in the
316  * "locale -a" output. So save up the aliases and try to add them
317  * after we've read all the output.
318  */
319  if (normalize_locale_name(alias, localebuf))
320  {
321  aliaslist = lappend(aliaslist, pstrdup(alias));
322  localelist = lappend(localelist, pstrdup(localebuf));
323  enclist = lappend_int(enclist, enc);
324  }
325  }
326 
327  ClosePipeStream(locale_a_handle);
328 
329  /* Now try to add any aliases we created */
330  forthree(lca, aliaslist, lcl, localelist, lce, enclist)
331  {
332  char *alias = (char *) lfirst(lca);
333  char *locale = (char *) lfirst(lcl);
334  int enc = lfirst_int(lce);
335 
336  CollationCreate(alias, nspid, GetUserId(), enc,
337  locale, locale, true);
339  }
340 
341  if (count == 0)
343  (errmsg("no usable system locales were found")));
344 #endif /* not HAVE_LOCALE_T && not WIN32 */
345 
346  PG_RETURN_VOID();
347 }
#define NIL
Definition: pg_list.h:69
static void skip(struct vars *v)
Definition: regc_lex.c:1109
#define DEBUG1
Definition: elog.h:25
Oid GetUserId(void)
Definition: miscinit.c:283
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:183
char * pstrdup(const char *in)
Definition: mcxt.c:1165
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:230
unsigned int Oid
Definition: postgres_ext.h:31
Oid CollationCreate(const char *collname, Oid collnamespace, Oid collowner, int32 collencoding, const char *collcollate, const char *collctype, bool if_not_exists)
Definition: pg_collation.c:41
int ClosePipeStream(FILE *file)
Definition: fd.c:2419
#define NAMEDATALEN
#define IS_HIGHBIT_SET(ch)
Definition: c.h:969
#define ERROR
Definition: elog.h:43
struct pg_encoding enc
Definition: encode.c:522
#define lfirst_int(lc)
Definition: pg_list.h:107
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
int errcode_for_file_access(void)
Definition: elog.c:598
static const struct @26 enclist[]
FILE * OpenPipeStream(const char *command, const char *mode)
Definition: fd.c:2133
#define ereport(elevel, rest)
Definition: elog.h:122
List * lappend_int(List *list, int datum)
Definition: list.c:146
List * lappend(List *list, void *datum)
Definition: list.c:128
#define WARNING
Definition: elog.h:40
void CommandCounterIncrement(void)
Definition: xact.c:921
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:438
#define PG_RETURN_VOID()
Definition: fmgr.h:293
#define PG_VALID_BE_ENCODING(_enc)
Definition: pg_wchar.h:293
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
Datum lca(PG_FUNCTION_ARGS)
Definition: ltree_op.c:471
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
static char * locale
Definition: initdb.c:122
#define elog
Definition: elog.h:219
Definition: pg_list.h:45