PostgreSQL Source Code  git master
collationcmds.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * collationcmds.c
4  * collation-related commands support code
5  *
6  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/commands/collationcmds.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include "access/htup_details.h"
18 #include "access/table.h"
19 #include "access/xact.h"
20 #include "catalog/dependency.h"
21 #include "catalog/indexing.h"
22 #include "catalog/namespace.h"
23 #include "catalog/objectaccess.h"
24 #include "catalog/pg_collation.h"
25 #include "commands/alter.h"
26 #include "commands/collationcmds.h"
27 #include "commands/comment.h"
28 #include "commands/dbcommands.h"
29 #include "commands/defrem.h"
30 #include "common/string.h"
31 #include "mb/pg_wchar.h"
32 #include "miscadmin.h"
33 #include "utils/acl.h"
34 #include "utils/builtins.h"
35 #include "utils/lsyscache.h"
36 #include "utils/pg_locale.h"
37 #include "utils/rel.h"
38 #include "utils/syscache.h"
39 
40 
41 typedef struct
42 {
43  char *localename; /* name of locale, as per "locale -a" */
44  char *alias; /* shortened alias for same */
45  int enc; /* encoding */
47 
48 
49 /*
50  * CREATE COLLATION
51  */
53 DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_exists)
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  DefElem *versionEl = NULL;
66  char *collcollate = NULL;
67  char *collctype = NULL;
68  char *collproviderstr = NULL;
69  bool collisdeterministic = true;
70  int collencoding = 0;
71  char collprovider = 0;
72  char *collversion = NULL;
73  Oid newoid;
74  ObjectAddress address;
75 
76  collNamespace = QualifiedNameGetCreationNamespace(names, &collName);
77 
78  aclresult = pg_namespace_aclcheck(collNamespace, GetUserId(), ACL_CREATE);
79  if (aclresult != ACLCHECK_OK)
80  aclcheck_error(aclresult, OBJECT_SCHEMA,
81  get_namespace_name(collNamespace));
82 
83  foreach(pl, parameters)
84  {
85  DefElem *defel = lfirst_node(DefElem, pl);
86  DefElem **defelp;
87 
88  if (strcmp(defel->defname, "from") == 0)
89  defelp = &fromEl;
90  else if (strcmp(defel->defname, "locale") == 0)
91  defelp = &localeEl;
92  else if (strcmp(defel->defname, "lc_collate") == 0)
93  defelp = &lccollateEl;
94  else if (strcmp(defel->defname, "lc_ctype") == 0)
95  defelp = &lcctypeEl;
96  else if (strcmp(defel->defname, "provider") == 0)
97  defelp = &providerEl;
98  else if (strcmp(defel->defname, "deterministic") == 0)
99  defelp = &deterministicEl;
100  else if (strcmp(defel->defname, "version") == 0)
101  defelp = &versionEl;
102  else
103  {
104  ereport(ERROR,
105  (errcode(ERRCODE_SYNTAX_ERROR),
106  errmsg("collation attribute \"%s\" not recognized",
107  defel->defname),
108  parser_errposition(pstate, defel->location)));
109  break;
110  }
111 
112  *defelp = defel;
113  }
114 
115  if ((localeEl && (lccollateEl || lcctypeEl))
116  || (fromEl && list_length(parameters) != 1))
117  ereport(ERROR,
118  (errcode(ERRCODE_SYNTAX_ERROR),
119  errmsg("conflicting or redundant options")));
120 
121  if (fromEl)
122  {
123  Oid collid;
124  HeapTuple tp;
125 
126  collid = get_collation_oid(defGetQualifiedName(fromEl), false);
128  if (!HeapTupleIsValid(tp))
129  elog(ERROR, "cache lookup failed for collation %u", collid);
130 
131  collcollate = pstrdup(NameStr(((Form_pg_collation) GETSTRUCT(tp))->collcollate));
132  collctype = pstrdup(NameStr(((Form_pg_collation) GETSTRUCT(tp))->collctype));
133  collprovider = ((Form_pg_collation) GETSTRUCT(tp))->collprovider;
134  collisdeterministic = ((Form_pg_collation) GETSTRUCT(tp))->collisdeterministic;
135  collencoding = ((Form_pg_collation) GETSTRUCT(tp))->collencoding;
136 
137  ReleaseSysCache(tp);
138 
139  /*
140  * Copying the "default" collation is not allowed because most code
141  * checks for DEFAULT_COLLATION_OID instead of COLLPROVIDER_DEFAULT,
142  * and so having a second collation with COLLPROVIDER_DEFAULT would
143  * not work and potentially confuse or crash some code. This could be
144  * fixed with some legwork.
145  */
146  if (collprovider == COLLPROVIDER_DEFAULT)
147  ereport(ERROR,
148  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
149  errmsg("collation \"default\" cannot be copied")));
150  }
151 
152  if (localeEl)
153  {
154  collcollate = defGetString(localeEl);
155  collctype = defGetString(localeEl);
156  }
157 
158  if (lccollateEl)
159  collcollate = defGetString(lccollateEl);
160 
161  if (lcctypeEl)
162  collctype = defGetString(lcctypeEl);
163 
164  if (providerEl)
165  collproviderstr = defGetString(providerEl);
166 
167  if (deterministicEl)
168  collisdeterministic = defGetBoolean(deterministicEl);
169 
170  if (versionEl)
171  collversion = defGetString(versionEl);
172 
173  if (collproviderstr)
174  {
175  if (pg_strcasecmp(collproviderstr, "icu") == 0)
176  collprovider = COLLPROVIDER_ICU;
177  else if (pg_strcasecmp(collproviderstr, "libc") == 0)
178  collprovider = COLLPROVIDER_LIBC;
179  else
180  ereport(ERROR,
181  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
182  errmsg("unrecognized collation provider: %s",
183  collproviderstr)));
184  }
185  else if (!fromEl)
186  collprovider = COLLPROVIDER_LIBC;
187 
188  if (!collcollate)
189  ereport(ERROR,
190  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
191  errmsg("parameter \"lc_collate\" must be specified")));
192 
193  if (!collctype)
194  ereport(ERROR,
195  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
196  errmsg("parameter \"lc_ctype\" must be specified")));
197 
198  /*
199  * Nondeterministic collations are currently only supported with ICU
200  * because that's the only case where it can actually make a difference.
201  * So we can save writing the code for the other providers.
202  */
203  if (!collisdeterministic && collprovider != COLLPROVIDER_ICU)
204  ereport(ERROR,
205  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
206  errmsg("nondeterministic collations not supported with this provider")));
207 
208  if (!fromEl)
209  {
210  if (collprovider == COLLPROVIDER_ICU)
211  collencoding = -1;
212  else
213  {
214  collencoding = GetDatabaseEncoding();
215  check_encoding_locale_matches(collencoding, collcollate, collctype);
216  }
217  }
218 
219  if (!collversion)
220  collversion = get_collation_actual_version(collprovider, collcollate);
221 
222  newoid = CollationCreate(collName,
223  collNamespace,
224  GetUserId(),
225  collprovider,
226  collisdeterministic,
227  collencoding,
228  collcollate,
229  collctype,
230  collversion,
231  if_not_exists,
232  false); /* not quiet */
233 
234  if (!OidIsValid(newoid))
235  return InvalidObjectAddress;
236 
237  /*
238  * Check that the locales can be loaded. NB: pg_newlocale_from_collation
239  * is only supposed to be called on non-C-equivalent locales.
240  */
242  if (!lc_collate_is_c(newoid) || !lc_ctype_is_c(newoid))
243  (void) pg_newlocale_from_collation(newoid);
244 
245  ObjectAddressSet(address, CollationRelationId, newoid);
246 
247  return address;
248 }
249 
250 /*
251  * Subroutine for ALTER COLLATION SET SCHEMA and RENAME
252  *
253  * Is there a collation with the same name of the given collation already in
254  * the given namespace? If so, raise an appropriate error message.
255  */
256 void
257 IsThereCollationInNamespace(const char *collname, Oid nspOid)
258 {
259  /* make sure the name doesn't already exist in new schema */
261  CStringGetDatum(collname),
263  ObjectIdGetDatum(nspOid)))
264  ereport(ERROR,
266  errmsg("collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"",
267  collname, GetDatabaseEncodingName(),
268  get_namespace_name(nspOid))));
269 
270  /* mustn't match an any-encoding entry, either */
272  CStringGetDatum(collname),
273  Int32GetDatum(-1),
274  ObjectIdGetDatum(nspOid)))
275  ereport(ERROR,
277  errmsg("collation \"%s\" already exists in schema \"%s\"",
278  collname, get_namespace_name(nspOid))));
279 }
280 
281 /*
282  * ALTER COLLATION
283  */
286 {
287  Relation rel;
288  Oid collOid;
289  HeapTuple tup;
290  Form_pg_collation collForm;
291  Datum collversion;
292  bool isnull;
293  char *oldversion;
294  char *newversion;
295  ObjectAddress address;
296 
297  rel = table_open(CollationRelationId, RowExclusiveLock);
298  collOid = get_collation_oid(stmt->collname, false);
299 
300  if (!pg_collation_ownercheck(collOid, GetUserId()))
302  NameListToString(stmt->collname));
303 
305  if (!HeapTupleIsValid(tup))
306  elog(ERROR, "cache lookup failed for collation %u", collOid);
307 
308  collForm = (Form_pg_collation) GETSTRUCT(tup);
309  collversion = SysCacheGetAttr(COLLOID, tup, Anum_pg_collation_collversion,
310  &isnull);
311  oldversion = isnull ? NULL : TextDatumGetCString(collversion);
312 
313  newversion = get_collation_actual_version(collForm->collprovider, NameStr(collForm->collcollate));
314 
315  /* cannot change from NULL to non-NULL or vice versa */
316  if ((!oldversion && newversion) || (oldversion && !newversion))
317  elog(ERROR, "invalid collation version change");
318  else if (oldversion && newversion && strcmp(newversion, oldversion) != 0)
319  {
320  bool nulls[Natts_pg_collation];
321  bool replaces[Natts_pg_collation];
322  Datum values[Natts_pg_collation];
323 
324  ereport(NOTICE,
325  (errmsg("changing version from %s to %s",
326  oldversion, newversion)));
327 
328  memset(values, 0, sizeof(values));
329  memset(nulls, false, sizeof(nulls));
330  memset(replaces, false, sizeof(replaces));
331 
332  values[Anum_pg_collation_collversion - 1] = CStringGetTextDatum(newversion);
333  replaces[Anum_pg_collation_collversion - 1] = true;
334 
335  tup = heap_modify_tuple(tup, RelationGetDescr(rel),
336  values, nulls, replaces);
337  }
338  else
339  ereport(NOTICE,
340  (errmsg("version has not changed")));
341 
342  CatalogTupleUpdate(rel, &tup->t_self, tup);
343 
344  InvokeObjectPostAlterHook(CollationRelationId, collOid, 0);
345 
346  ObjectAddressSet(address, CollationRelationId, collOid);
347 
348  heap_freetuple(tup);
349  table_close(rel, NoLock);
350 
351  return address;
352 }
353 
354 
355 Datum
357 {
358  Oid collid = PG_GETARG_OID(0);
359  HeapTuple tp;
360  char *collcollate;
361  char collprovider;
362  char *version;
363 
365  if (!HeapTupleIsValid(tp))
366  ereport(ERROR,
367  (errcode(ERRCODE_UNDEFINED_OBJECT),
368  errmsg("collation with OID %u does not exist", collid)));
369 
370  collcollate = pstrdup(NameStr(((Form_pg_collation) GETSTRUCT(tp))->collcollate));
371  collprovider = ((Form_pg_collation) GETSTRUCT(tp))->collprovider;
372 
373  ReleaseSysCache(tp);
374 
375  version = get_collation_actual_version(collprovider, collcollate);
376 
377  if (version)
379  else
380  PG_RETURN_NULL();
381 }
382 
383 
384 /* will we use "locale -a" in pg_import_system_collations? */
385 #if defined(HAVE_LOCALE_T) && !defined(WIN32)
386 #define READ_LOCALE_A_OUTPUT
387 #endif
388 
389 #ifdef READ_LOCALE_A_OUTPUT
390 /*
391  * "Normalize" a libc locale name, stripping off encoding tags such as
392  * ".utf8" (e.g., "en_US.utf8" -> "en_US", but "br_FR.iso885915@euro"
393  * -> "br_FR@euro"). Return true if a new, different name was
394  * generated.
395  */
396 static bool
397 normalize_libc_locale_name(char *new, const char *old)
398 {
399  char *n = new;
400  const char *o = old;
401  bool changed = false;
402 
403  while (*o)
404  {
405  if (*o == '.')
406  {
407  /* skip over encoding tag such as ".utf8" or ".UTF-8" */
408  o++;
409  while ((*o >= 'A' && *o <= 'Z')
410  || (*o >= 'a' && *o <= 'z')
411  || (*o >= '0' && *o <= '9')
412  || (*o == '-'))
413  o++;
414  changed = true;
415  }
416  else
417  *n++ = *o++;
418  }
419  *n = '\0';
420 
421  return changed;
422 }
423 
424 /*
425  * qsort comparator for CollAliasData items
426  */
427 static int
428 cmpaliases(const void *a, const void *b)
429 {
430  const CollAliasData *ca = (const CollAliasData *) a;
431  const CollAliasData *cb = (const CollAliasData *) b;
432 
433  /* comparing localename is enough because other fields are derived */
434  return strcmp(ca->localename, cb->localename);
435 }
436 #endif /* READ_LOCALE_A_OUTPUT */
437 
438 
439 #ifdef USE_ICU
440 /*
441  * Get the ICU language tag for a locale name.
442  * The result is a palloc'd string.
443  */
444 static char *
445 get_icu_language_tag(const char *localename)
446 {
447  char buf[ULOC_FULLNAME_CAPACITY];
448  UErrorCode status;
449 
450  status = U_ZERO_ERROR;
451  uloc_toLanguageTag(localename, buf, sizeof(buf), true, &status);
452  if (U_FAILURE(status))
453  ereport(ERROR,
454  (errmsg("could not convert locale name \"%s\" to language tag: %s",
455  localename, u_errorName(status))));
456 
457  return pstrdup(buf);
458 }
459 
460 /*
461  * Get a comment (specifically, the display name) for an ICU locale.
462  * The result is a palloc'd string, or NULL if we can't get a comment
463  * or find that it's not all ASCII. (We can *not* accept non-ASCII
464  * comments, because the contents of template0 must be encoding-agnostic.)
465  */
466 static char *
467 get_icu_locale_comment(const char *localename)
468 {
469  UErrorCode status;
470  UChar displayname[128];
471  int32 len_uchar;
472  int32 i;
473  char *result;
474 
475  status = U_ZERO_ERROR;
476  len_uchar = uloc_getDisplayName(localename, "en",
477  displayname, lengthof(displayname),
478  &status);
479  if (U_FAILURE(status))
480  return NULL; /* no good reason to raise an error */
481 
482  /* Check for non-ASCII comment (can't use pg_is_ascii for this) */
483  for (i = 0; i < len_uchar; i++)
484  {
485  if (displayname[i] > 127)
486  return NULL;
487  }
488 
489  /* OK, transcribe */
490  result = palloc(len_uchar + 1);
491  for (i = 0; i < len_uchar; i++)
492  result[i] = displayname[i];
493  result[len_uchar] = '\0';
494 
495  return result;
496 }
497 #endif /* USE_ICU */
498 
499 
500 /*
501  * pg_import_system_collations: add known system collations to pg_collation
502  */
503 Datum
505 {
506  Oid nspid = PG_GETARG_OID(0);
507  int ncreated = 0;
508 
509  if (!superuser())
510  ereport(ERROR,
511  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
512  errmsg("must be superuser to import system collations")));
513 
515  ereport(ERROR,
516  (errcode(ERRCODE_UNDEFINED_SCHEMA),
517  errmsg("schema with OID %u does not exist", nspid)));
518 
519  /* Load collations known to libc, using "locale -a" to enumerate them */
520 #ifdef READ_LOCALE_A_OUTPUT
521  {
522  FILE *locale_a_handle;
523  char localebuf[NAMEDATALEN]; /* we assume ASCII so this is fine */
524  int nvalid = 0;
525  Oid collid;
526  CollAliasData *aliases;
527  int naliases,
528  maxaliases,
529  i;
530 
531  /* expansible array of aliases */
532  maxaliases = 100;
533  aliases = (CollAliasData *) palloc(maxaliases * sizeof(CollAliasData));
534  naliases = 0;
535 
536  locale_a_handle = OpenPipeStream("locale -a", "r");
537  if (locale_a_handle == NULL)
538  ereport(ERROR,
540  errmsg("could not execute command \"%s\": %m",
541  "locale -a")));
542 
543  while (fgets(localebuf, sizeof(localebuf), locale_a_handle))
544  {
545  size_t len;
546  int enc;
547  char alias[NAMEDATALEN];
548 
549  len = strlen(localebuf);
550 
551  if (len == 0 || localebuf[len - 1] != '\n')
552  {
553  elog(DEBUG1, "locale name too long, skipped: \"%s\"", localebuf);
554  continue;
555  }
556  localebuf[len - 1] = '\0';
557 
558  /*
559  * Some systems have locale names that don't consist entirely of
560  * ASCII letters (such as "bokm&aring;l" or "fran&ccedil;ais").
561  * This is pretty silly, since we need the locale itself to
562  * interpret the non-ASCII characters. We can't do much with
563  * those, so we filter them out.
564  */
565  if (!pg_is_ascii(localebuf))
566  {
567  elog(DEBUG1, "locale name has non-ASCII characters, skipped: \"%s\"", localebuf);
568  continue;
569  }
570 
571  enc = pg_get_encoding_from_locale(localebuf, false);
572  if (enc < 0)
573  {
574  /* error message printed by pg_get_encoding_from_locale() */
575  continue;
576  }
577  if (!PG_VALID_BE_ENCODING(enc))
578  continue; /* ignore locales for client-only encodings */
579  if (enc == PG_SQL_ASCII)
580  continue; /* C/POSIX are already in the catalog */
581 
582  /* count valid locales found in operating system */
583  nvalid++;
584 
585  /*
586  * Create a collation named the same as the locale, but quietly
587  * doing nothing if it already exists. This is the behavior we
588  * need even at initdb time, because some versions of "locale -a"
589  * can report the same locale name more than once. And it's
590  * convenient for later import runs, too, since you just about
591  * always want to add on new locales without a lot of chatter
592  * about existing ones.
593  */
594  collid = CollationCreate(localebuf, nspid, GetUserId(),
595  COLLPROVIDER_LIBC, true, enc,
596  localebuf, localebuf,
597  get_collation_actual_version(COLLPROVIDER_LIBC, localebuf),
598  true, true);
599  if (OidIsValid(collid))
600  {
601  ncreated++;
602 
603  /* Must do CCI between inserts to handle duplicates correctly */
605  }
606 
607  /*
608  * Generate aliases such as "en_US" in addition to "en_US.utf8"
609  * for ease of use. Note that collation names are unique per
610  * encoding only, so this doesn't clash with "en_US" for LATIN1,
611  * say.
612  *
613  * However, it might conflict with a name we'll see later in the
614  * "locale -a" output. So save up the aliases and try to add them
615  * after we've read all the output.
616  */
617  if (normalize_libc_locale_name(alias, localebuf))
618  {
619  if (naliases >= maxaliases)
620  {
621  maxaliases *= 2;
622  aliases = (CollAliasData *)
623  repalloc(aliases, maxaliases * sizeof(CollAliasData));
624  }
625  aliases[naliases].localename = pstrdup(localebuf);
626  aliases[naliases].alias = pstrdup(alias);
627  aliases[naliases].enc = enc;
628  naliases++;
629  }
630  }
631 
632  ClosePipeStream(locale_a_handle);
633 
634  /*
635  * Before processing the aliases, sort them by locale name. The point
636  * here is that if "locale -a" gives us multiple locale names with the
637  * same encoding and base name, say "en_US.utf8" and "en_US.utf-8", we
638  * want to pick a deterministic one of them. First in ASCII sort
639  * order is a good enough rule. (Before PG 10, the code corresponding
640  * to this logic in initdb.c had an additional ordering rule, to
641  * prefer the locale name exactly matching the alias, if any. We
642  * don't need to consider that here, because we would have already
643  * created such a pg_collation entry above, and that one will win.)
644  */
645  if (naliases > 1)
646  qsort((void *) aliases, naliases, sizeof(CollAliasData), cmpaliases);
647 
648  /* Now add aliases, ignoring any that match pre-existing entries */
649  for (i = 0; i < naliases; i++)
650  {
651  char *locale = aliases[i].localename;
652  char *alias = aliases[i].alias;
653  int enc = aliases[i].enc;
654 
655  collid = CollationCreate(alias, nspid, GetUserId(),
656  COLLPROVIDER_LIBC, true, enc,
657  locale, locale,
658  get_collation_actual_version(COLLPROVIDER_LIBC, locale),
659  true, true);
660  if (OidIsValid(collid))
661  {
662  ncreated++;
663 
665  }
666  }
667 
668  /* Give a warning if "locale -a" seems to be malfunctioning */
669  if (nvalid == 0)
671  (errmsg("no usable system locales were found")));
672  }
673 #endif /* READ_LOCALE_A_OUTPUT */
674 
675  /*
676  * Load collations known to ICU
677  *
678  * We use uloc_countAvailable()/uloc_getAvailable() rather than
679  * ucol_countAvailable()/ucol_getAvailable(). The former returns a full
680  * set of language+region combinations, whereas the latter only returns
681  * language+region combinations if they are distinct from the language's
682  * base collation. So there might not be a de-DE or en-GB, which would be
683  * confusing.
684  */
685 #ifdef USE_ICU
686  {
687  int i;
688 
689  /*
690  * Start the loop at -1 to sneak in the root locale without too much
691  * code duplication.
692  */
693  for (i = -1; i < uloc_countAvailable(); i++)
694  {
695  const char *name;
696  char *langtag;
697  char *icucomment;
698  const char *collcollate;
699  Oid collid;
700 
701  if (i == -1)
702  name = ""; /* ICU root locale */
703  else
704  name = uloc_getAvailable(i);
705 
706  langtag = get_icu_language_tag(name);
707  collcollate = U_ICU_VERSION_MAJOR_NUM >= 54 ? langtag : name;
708 
709  /*
710  * Be paranoid about not allowing any non-ASCII strings into
711  * pg_collation
712  */
713  if (!pg_is_ascii(langtag) || !pg_is_ascii(collcollate))
714  continue;
715 
716  collid = CollationCreate(psprintf("%s-x-icu", langtag),
717  nspid, GetUserId(),
718  COLLPROVIDER_ICU, true, -1,
719  collcollate, collcollate,
720  get_collation_actual_version(COLLPROVIDER_ICU, collcollate),
721  true, true);
722  if (OidIsValid(collid))
723  {
724  ncreated++;
725 
727 
728  icucomment = get_icu_locale_comment(name);
729  if (icucomment)
730  CreateComments(collid, CollationRelationId, 0,
731  icucomment);
732  }
733  }
734  }
735 #endif /* USE_ICU */
736 
737  PG_RETURN_INT32(ncreated);
738 }
bool pg_collation_ownercheck(Oid coll_oid, Oid roleid)
Definition: aclchk.c:5267
void CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment)
Definition: comment.c:142
#define DEBUG1
Definition: elog.h:25
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
void check_encoding_locale_matches(int encoding, const char *collate, const char *ctype)
Definition: dbcommands.c:755
#define RelationGetDescr(relation)
Definition: rel.h:495
Oid GetUserId(void)
Definition: miscinit.c:478
char * localename
Definition: collationcmds.c:43
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2994
char * pstrdup(const char *in)
Definition: mcxt.c:1299
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define lengthof(array)
Definition: c.h:734
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4761
bool pg_is_ascii(const char *str)
Definition: string.c:99
signed int int32
Definition: c.h:429
int ClosePipeStream(FILE *file)
Definition: fd.c:2782
#define NAMEDATALEN
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3313
bool defGetBoolean(DefElem *def)
Definition: define.c:111
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:184
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define ACL_CREATE
Definition: parsenodes.h:92
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:188
bool lc_collate_is_c(Oid collation)
Definition: pg_locale.c:1321
struct pg_encoding enc
Definition: encode.c:516
char * defGetString(DefElem *def)
Definition: define.c:49
ItemPointerData t_self
Definition: htup.h:65
#define lfirst_node(type, lc)
Definition: pg_list.h:172
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
#define NoLock
Definition: lockdefs.h:34
static char * buf
Definition: pg_test_fsync.c:68
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
int location
Definition: parsenodes.h:749
#define RowExclusiveLock
Definition: lockdefs.h:38
int errcode_for_file_access(void)
Definition: elog.c:721
#define CStringGetDatum(X)
Definition: postgres.h:622
void IsThereCollationInNamespace(const char *collname, Oid nspOid)
FILE * OpenPipeStream(const char *command, const char *mode)
Definition: fd.c:2476
Datum pg_collation_actual_version(PG_FUNCTION_ARGS)
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
char * NameListToString(List *names)
Definition: namespace.c:3101
pg_locale_t pg_newlocale_from_collation(Oid collid)
Definition: pg_locale.c:1468
#define TextDatumGetCString(d)
Definition: builtins.h:83
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1021
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
int GetDatabaseEncoding(void)
Definition: mbutils.c:1210
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
ObjectAddress DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_exists)
Definition: collationcmds.c:53
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:452
#define ereport(elevel,...)
Definition: elog.h:157
#define NOTICE
Definition: elog.h:37
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
text * cstring_to_text(const char *s)
Definition: varlena.c:190
#define PG_VALID_BE_ENCODING(_enc)
Definition: pg_wchar.h:295
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
const char * GetDatabaseEncodingName(void)
Definition: mbutils.c:1216
List * defGetQualifiedName(DefElem *def)
Definition: define.c:223
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
static int list_length(const List *l)
Definition: pg_list.h:149
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
Oid CollationCreate(const char *collname, Oid collnamespace, Oid collowner, char collprovider, bool collisdeterministic, int32 collencoding, const char *collcollate, const char *collctype, const char *collversion, bool if_not_exists, bool quiet)
Definition: pg_collation.c:46
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
const char * name
Definition: encode.c:515
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:56
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:175
#define Int32GetDatum(X)
Definition: postgres.h:523
const ObjectAddress InvalidObjectAddress
Datum pg_import_system_collations(PG_FUNCTION_ARGS)
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
ObjectAddress AlterCollation(AlterCollationStmt *stmt)
int i
#define NameStr(name)
Definition: c.h:681
static char * locale
Definition: initdb.c:126
#define CStringGetTextDatum(s)
Definition: builtins.h:82
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
char * defname
Definition: parsenodes.h:746
bool lc_ctype_is_c(Oid collation)
Definition: pg_locale.c:1371
#define qsort(a, b, c, d)
Definition: port.h:504
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
Oid get_collation_oid(List *name, bool missing_ok)
Definition: namespace.c:3600
Definition: pg_list.h:50
#define PG_RETURN_NULL()
Definition: fmgr.h:345
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1645