PostgreSQL Source Code  git master
collationcmds.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "access/xact.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_database.h"
#include "catalog/pg_namespace.h"
#include "commands/alter.h"
#include "commands/collationcmds.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "common/string.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "utils/acl.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.

Data Structures

struct  CollAliasData
 

Functions

ObjectAddress DefineCollation (ParseState *pstate, List *names, List *parameters, bool if_not_exists)
 
void IsThereCollationInNamespace (const char *collname, Oid nspOid)
 
ObjectAddress AlterCollation (AlterCollationStmt *stmt)
 
Datum pg_collation_actual_version (PG_FUNCTION_ARGS)
 
 pg_attribute_unused () static int create_collation_from_locale(const char *locale
 
 if (!pg_is_ascii(locale))
 
 if (enc< 0)
 
 if (!PG_VALID_BE_ENCODING(enc))
 
 if (collid=CollationCreate(enc==PG_SQL_ASCII)
 
Datum pg_import_system_collations (PG_FUNCTION_ARGS)
 

Variables

int nspid
 
int int * nvalidp
 
int int int * ncreatedp
 
Oid collid
 
 enc = pg_get_encoding_from_locale(locale, false)
 

Function Documentation

◆ AlterCollation()

ObjectAddress AlterCollation ( AlterCollationStmt stmt)

Definition at line 375 of file collationcmds.c.

376 {
377  Relation rel;
378  Oid collOid;
379  HeapTuple tup;
380  Form_pg_collation collForm;
381  Datum datum;
382  bool isnull;
383  char *oldversion;
384  char *newversion;
385  ObjectAddress address;
386 
387  rel = table_open(CollationRelationId, RowExclusiveLock);
388  collOid = get_collation_oid(stmt->collname, false);
389 
390  if (collOid == DEFAULT_COLLATION_OID)
391  ereport(ERROR,
392  (errmsg("cannot refresh version of default collation"),
393  errhint("Use ALTER DATABASE ... REFRESH COLLATION VERSION instead.")));
394 
395  if (!object_ownercheck(CollationRelationId, collOid, GetUserId()))
397  NameListToString(stmt->collname));
398 
400  if (!HeapTupleIsValid(tup))
401  elog(ERROR, "cache lookup failed for collation %u", collOid);
402 
403  collForm = (Form_pg_collation) GETSTRUCT(tup);
404  datum = SysCacheGetAttr(COLLOID, tup, Anum_pg_collation_collversion, &isnull);
405  oldversion = isnull ? NULL : TextDatumGetCString(datum);
406 
407  datum = SysCacheGetAttr(COLLOID, tup, collForm->collprovider == COLLPROVIDER_ICU ? Anum_pg_collation_colliculocale : Anum_pg_collation_collcollate, &isnull);
408  if (isnull)
409  elog(ERROR, "unexpected null in pg_collation");
410  newversion = get_collation_actual_version(collForm->collprovider, TextDatumGetCString(datum));
411 
412  /* cannot change from NULL to non-NULL or vice versa */
413  if ((!oldversion && newversion) || (oldversion && !newversion))
414  elog(ERROR, "invalid collation version change");
415  else if (oldversion && newversion && strcmp(newversion, oldversion) != 0)
416  {
417  bool nulls[Natts_pg_collation];
418  bool replaces[Natts_pg_collation];
419  Datum values[Natts_pg_collation];
420 
421  ereport(NOTICE,
422  (errmsg("changing version from %s to %s",
423  oldversion, newversion)));
424 
425  memset(values, 0, sizeof(values));
426  memset(nulls, false, sizeof(nulls));
427  memset(replaces, false, sizeof(replaces));
428 
429  values[Anum_pg_collation_collversion - 1] = CStringGetTextDatum(newversion);
430  replaces[Anum_pg_collation_collversion - 1] = true;
431 
432  tup = heap_modify_tuple(tup, RelationGetDescr(rel),
433  values, nulls, replaces);
434  }
435  else
436  ereport(NOTICE,
437  (errmsg("version has not changed")));
438 
439  CatalogTupleUpdate(rel, &tup->t_self, tup);
440 
441  InvokeObjectPostAlterHook(CollationRelationId, collOid, 0);
442 
443  ObjectAddressSet(address, CollationRelationId, collOid);
444 
445  heap_freetuple(tup);
446  table_close(rel, NoLock);
447 
448  return address;
449 }
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2679
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:3984
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define CStringGetTextDatum(s)
Definition: builtins.h:94
#define TextDatumGetCString(d)
Definition: builtins.h:95
int errhint(const char *fmt,...)
Definition: elog.c:1316
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define NOTICE
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:149
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
#define stmt
Definition: indent_codes.h:59
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
Oid GetUserId(void)
Definition: miscinit.c:510
Oid get_collation_oid(List *collname, bool missing_ok)
Definition: namespace.c:3644
char * NameListToString(List *names)
Definition: namespace.c:3145
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
@ OBJECT_COLLATION
Definition: parsenodes.h:1982
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:58
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1717
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetDescr(relation)
Definition: rel.h:527
ItemPointerData t_self
Definition: htup.h:65
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1078
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:179
@ COLLOID
Definition: syscache.h:50
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

References aclcheck_error(), ACLCHECK_NOT_OWNER, CatalogTupleUpdate(), COLLOID, CStringGetTextDatum, elog(), ereport, errhint(), errmsg(), ERROR, get_collation_actual_version(), get_collation_oid(), GETSTRUCT, GetUserId(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, InvokeObjectPostAlterHook, NameListToString(), NoLock, NOTICE, OBJECT_COLLATION, object_ownercheck(), ObjectAddressSet, ObjectIdGetDatum(), RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, stmt, SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), TextDatumGetCString, and values.

Referenced by ProcessUtilitySlow().

◆ DefineCollation()

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

Definition at line 55 of file collationcmds.c.

56 {
57  char *collName;
58  Oid collNamespace;
59  AclResult aclresult;
60  ListCell *pl;
61  DefElem *fromEl = NULL;
62  DefElem *localeEl = NULL;
63  DefElem *lccollateEl = NULL;
64  DefElem *lcctypeEl = NULL;
65  DefElem *providerEl = NULL;
66  DefElem *deterministicEl = NULL;
67  DefElem *rulesEl = NULL;
68  DefElem *versionEl = NULL;
69  char *collcollate;
70  char *collctype;
71  char *colliculocale;
72  char *collicurules;
73  bool collisdeterministic;
74  int collencoding;
75  char collprovider;
76  char *collversion = NULL;
77  Oid newoid;
78  ObjectAddress address;
79 
80  collNamespace = QualifiedNameGetCreationNamespace(names, &collName);
81 
82  aclresult = object_aclcheck(NamespaceRelationId, collNamespace, GetUserId(), ACL_CREATE);
83  if (aclresult != ACLCHECK_OK)
84  aclcheck_error(aclresult, OBJECT_SCHEMA,
85  get_namespace_name(collNamespace));
86 
87  foreach(pl, parameters)
88  {
89  DefElem *defel = lfirst_node(DefElem, pl);
90  DefElem **defelp;
91 
92  if (strcmp(defel->defname, "from") == 0)
93  defelp = &fromEl;
94  else if (strcmp(defel->defname, "locale") == 0)
95  defelp = &localeEl;
96  else if (strcmp(defel->defname, "lc_collate") == 0)
97  defelp = &lccollateEl;
98  else if (strcmp(defel->defname, "lc_ctype") == 0)
99  defelp = &lcctypeEl;
100  else if (strcmp(defel->defname, "provider") == 0)
101  defelp = &providerEl;
102  else if (strcmp(defel->defname, "deterministic") == 0)
103  defelp = &deterministicEl;
104  else if (strcmp(defel->defname, "rules") == 0)
105  defelp = &rulesEl;
106  else if (strcmp(defel->defname, "version") == 0)
107  defelp = &versionEl;
108  else
109  {
110  ereport(ERROR,
111  (errcode(ERRCODE_SYNTAX_ERROR),
112  errmsg("collation attribute \"%s\" not recognized",
113  defel->defname),
114  parser_errposition(pstate, defel->location)));
115  break;
116  }
117  if (*defelp != NULL)
118  errorConflictingDefElem(defel, pstate);
119  *defelp = defel;
120  }
121 
122  if (localeEl && (lccollateEl || lcctypeEl))
123  ereport(ERROR,
124  errcode(ERRCODE_SYNTAX_ERROR),
125  errmsg("conflicting or redundant options"),
126  errdetail("LOCALE cannot be specified together with LC_COLLATE or LC_CTYPE."));
127 
128  if (fromEl && list_length(parameters) != 1)
129  ereport(ERROR,
130  errcode(ERRCODE_SYNTAX_ERROR),
131  errmsg("conflicting or redundant options"),
132  errdetail("FROM cannot be specified together with any other options."));
133 
134  if (fromEl)
135  {
136  Oid collid;
137  HeapTuple tp;
138  Datum datum;
139  bool isnull;
140 
141  collid = get_collation_oid(defGetQualifiedName(fromEl), false);
143  if (!HeapTupleIsValid(tp))
144  elog(ERROR, "cache lookup failed for collation %u", collid);
145 
146  collprovider = ((Form_pg_collation) GETSTRUCT(tp))->collprovider;
147  collisdeterministic = ((Form_pg_collation) GETSTRUCT(tp))->collisdeterministic;
148  collencoding = ((Form_pg_collation) GETSTRUCT(tp))->collencoding;
149 
150  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collcollate, &isnull);
151  if (!isnull)
152  collcollate = TextDatumGetCString(datum);
153  else
154  collcollate = NULL;
155 
156  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collctype, &isnull);
157  if (!isnull)
158  collctype = TextDatumGetCString(datum);
159  else
160  collctype = NULL;
161 
162  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_colliculocale, &isnull);
163  if (!isnull)
164  colliculocale = TextDatumGetCString(datum);
165  else
166  colliculocale = NULL;
167 
168  datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collicurules, &isnull);
169  if (!isnull)
170  collicurules = TextDatumGetCString(datum);
171  else
172  collicurules = NULL;
173 
174  ReleaseSysCache(tp);
175 
176  /*
177  * Copying the "default" collation is not allowed because most code
178  * checks for DEFAULT_COLLATION_OID instead of COLLPROVIDER_DEFAULT,
179  * and so having a second collation with COLLPROVIDER_DEFAULT would
180  * not work and potentially confuse or crash some code. This could be
181  * fixed with some legwork.
182  */
183  if (collprovider == COLLPROVIDER_DEFAULT)
184  ereport(ERROR,
185  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
186  errmsg("collation \"default\" cannot be copied")));
187  }
188  else
189  {
190  char *collproviderstr = NULL;
191 
192  collcollate = NULL;
193  collctype = NULL;
194  colliculocale = NULL;
195  collicurules = NULL;
196 
197  if (providerEl)
198  collproviderstr = defGetString(providerEl);
199 
200  if (deterministicEl)
201  collisdeterministic = defGetBoolean(deterministicEl);
202  else
203  collisdeterministic = true;
204 
205  if (rulesEl)
206  collicurules = defGetString(rulesEl);
207 
208  if (versionEl)
209  collversion = defGetString(versionEl);
210 
211  if (collproviderstr)
212  {
213  if (pg_strcasecmp(collproviderstr, "icu") == 0)
214  collprovider = COLLPROVIDER_ICU;
215  else if (pg_strcasecmp(collproviderstr, "libc") == 0)
216  collprovider = COLLPROVIDER_LIBC;
217  else
218  ereport(ERROR,
219  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
220  errmsg("unrecognized collation provider: %s",
221  collproviderstr)));
222  }
223  else
224  collprovider = COLLPROVIDER_LIBC;
225 
226  if (localeEl)
227  {
228  if (collprovider == COLLPROVIDER_LIBC)
229  {
230  collcollate = defGetString(localeEl);
231  collctype = defGetString(localeEl);
232  }
233  else
234  colliculocale = defGetString(localeEl);
235  }
236 
237  if (lccollateEl)
238  collcollate = defGetString(lccollateEl);
239 
240  if (lcctypeEl)
241  collctype = defGetString(lcctypeEl);
242 
243  if (collprovider == COLLPROVIDER_LIBC)
244  {
245  if (!collcollate)
246  ereport(ERROR,
247  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
248  errmsg("parameter \"lc_collate\" must be specified")));
249 
250  if (!collctype)
251  ereport(ERROR,
252  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
253  errmsg("parameter \"lc_ctype\" must be specified")));
254  }
255  else if (collprovider == COLLPROVIDER_ICU)
256  {
257  if (!colliculocale)
258  ereport(ERROR,
259  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
260  errmsg("parameter \"locale\" must be specified")));
261  }
262 
263  /*
264  * Nondeterministic collations are currently only supported with ICU
265  * because that's the only case where it can actually make a
266  * difference. So we can save writing the code for the other
267  * providers.
268  */
269  if (!collisdeterministic && collprovider != COLLPROVIDER_ICU)
270  ereport(ERROR,
271  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
272  errmsg("nondeterministic collations not supported with this provider")));
273 
274  if (collicurules && collprovider != COLLPROVIDER_ICU)
275  ereport(ERROR,
276  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
277  errmsg("ICU rules cannot be specified unless locale provider is ICU")));
278 
279  if (collprovider == COLLPROVIDER_ICU)
280  {
281 #ifdef USE_ICU
282  /*
283  * We could create ICU collations with collencoding == database
284  * encoding, but it seems better to use -1 so that it matches the
285  * way initdb would create ICU collations. However, only allow
286  * one to be created when the current database's encoding is
287  * supported. Otherwise the collation is useless, plus we get
288  * surprising behaviors like not being able to drop the collation.
289  *
290  * Skip this test when !USE_ICU, because the error we want to
291  * throw for that isn't thrown till later.
292  */
294  ereport(ERROR,
295  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
296  errmsg("current database's encoding is not supported with this provider")));
297 #endif
298  collencoding = -1;
299  }
300  else
301  {
302  collencoding = GetDatabaseEncoding();
303  check_encoding_locale_matches(collencoding, collcollate, collctype);
304  }
305  }
306 
307  if (!collversion)
308  collversion = get_collation_actual_version(collprovider, collprovider == COLLPROVIDER_ICU ? colliculocale : collcollate);
309 
310  newoid = CollationCreate(collName,
311  collNamespace,
312  GetUserId(),
313  collprovider,
314  collisdeterministic,
315  collencoding,
316  collcollate,
317  collctype,
318  colliculocale,
319  collicurules,
320  collversion,
321  if_not_exists,
322  false); /* not quiet */
323 
324  if (!OidIsValid(newoid))
325  return InvalidObjectAddress;
326 
327  /*
328  * Check that the locales can be loaded. NB: pg_newlocale_from_collation
329  * is only supposed to be called on non-C-equivalent locales.
330  */
332  if (!lc_collate_is_c(newoid) || !lc_ctype_is_c(newoid))
333  (void) pg_newlocale_from_collation(newoid);
334 
335  ObjectAddressSet(address, CollationRelationId, newoid);
336 
337  return address;
338 }
AclResult
Definition: acl.h:182
@ ACLCHECK_OK
Definition: acl.h:183
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3783
#define OidIsValid(objectId)
Definition: c.h:759
Oid collid
void check_encoding_locale_matches(int encoding, const char *collate, const char *ctype)
Definition: dbcommands.c:1469
bool defGetBoolean(DefElem *def)
Definition: define.c:108
List * defGetQualifiedName(DefElem *def)
Definition: define.c:253
char * defGetString(DefElem *def)
Definition: define.c:49
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:385
int errdetail(const char *fmt,...)
Definition: elog.c:1202
int errcode(int sqlerrcode)
Definition: elog.c:858
bool is_encoding_supported_by_icu(int encoding)
Definition: encnames.c:462
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3331
int GetDatabaseEncoding(void)
Definition: mbutils.c:1268
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:3038
const ObjectAddress InvalidObjectAddress
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
@ OBJECT_SCHEMA
Definition: parsenodes.h:2011
#define ACL_CREATE
Definition: parsenodes.h:92
Oid CollationCreate(const char *collname, Oid collnamespace, Oid collowner, char collprovider, bool collisdeterministic, int32 collencoding, const char *collcollate, const char *collctype, const char *colliculocale, const char *collicurules, const char *collversion, bool if_not_exists, bool quiet)
Definition: pg_collation.c:46
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
bool lc_collate_is_c(Oid collation)
Definition: pg_locale.c:1322
pg_locale_t pg_newlocale_from_collation(Oid collid)
Definition: pg_locale.c:1543
bool lc_ctype_is_c(Oid collation)
Definition: pg_locale.c:1375
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
char * defname
Definition: parsenodes.h:810
int location
Definition: parsenodes.h:814
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:865
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:817
void CommandCounterIncrement(void)
Definition: xact.c:1078

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

Referenced by ProcessUtilitySlow().

◆ if() [1/4]

if ( pg_is_asciilocale)

Definition at line 669 of file collationcmds.c.

670  {
671  elog(DEBUG1, "skipping locale with non-ASCII name: \"%s\"", locale);
672  return -1;
673  }
#define DEBUG1
Definition: elog.h:30
static char * locale
Definition: initdb.c:132

References DEBUG1, elog(), and locale.

◆ if() [2/4]

if ( PG_VALID_BE_ENCODINGenc)

Definition at line 681 of file collationcmds.c.

682  {
683  elog(DEBUG1, "skipping locale with client-only encoding: \"%s\"", locale);
684  return -1;
685  }

References DEBUG1, elog(), and locale.

◆ if() [3/4]

if ( collid = CollationCreate enc = PG_SQL_ASCII)

Definition at line 686 of file collationcmds.c.

707  {
708  (*ncreatedp)++;
709 
710  /* Must do CCI between inserts to handle duplicates correctly */
712  }

◆ if() [4/4]

if ( )

Definition at line 676 of file collationcmds.c.

677  {
678  elog(DEBUG1, "skipping locale with unrecognized encoding: \"%s\"", locale);
679  return -1;
680  }

References DEBUG1, elog(), and locale.

◆ IsThereCollationInNamespace()

void IsThereCollationInNamespace ( const char *  collname,
Oid  nspOid 
)

Definition at line 347 of file collationcmds.c.

348 {
349  /* make sure the name doesn't already exist in new schema */
351  CStringGetDatum(collname),
353  ObjectIdGetDatum(nspOid)))
354  ereport(ERROR,
356  errmsg("collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"",
357  collname, GetDatabaseEncodingName(),
358  get_namespace_name(nspOid))));
359 
360  /* mustn't match an any-encoding entry, either */
362  CStringGetDatum(collname),
363  Int32GetDatum(-1),
364  ObjectIdGetDatum(nspOid)))
365  ereport(ERROR,
367  errmsg("collation \"%s\" already exists in schema \"%s\"",
368  collname, get_namespace_name(nspOid))));
369 }
const char * GetDatabaseEncodingName(void)
Definition: mbutils.c:1274
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
@ COLLNAMEENCNSP
Definition: syscache.h:49
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:192

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().

◆ pg_attribute_unused()

pg_attribute_unused ( ) const

◆ pg_collation_actual_version()

Datum pg_collation_actual_version ( PG_FUNCTION_ARGS  )

Definition at line 453 of file collationcmds.c.

454 {
455  Oid collid = PG_GETARG_OID(0);
456  char provider;
457  char *locale;
458  char *version;
459  Datum datum;
460  bool isnull;
461 
462  if (collid == DEFAULT_COLLATION_OID)
463  {
464  /* retrieve from pg_database */
465 
467  if (!HeapTupleIsValid(dbtup))
468  ereport(ERROR,
469  (errcode(ERRCODE_UNDEFINED_OBJECT),
470  errmsg("database with OID %u does not exist", MyDatabaseId)));
471 
473 
474  datum = SysCacheGetAttr(DATABASEOID, dbtup,
475  provider == COLLPROVIDER_ICU ?
476  Anum_pg_database_daticulocale : Anum_pg_database_datcollate,
477  &isnull);
478  if (isnull)
479  elog(ERROR, "unexpected null in pg_database");
480 
481  locale = TextDatumGetCString(datum);
482 
483  ReleaseSysCache(dbtup);
484  }
485  else
486  {
487  /* retrieve from pg_collation */
488 
490  if (!HeapTupleIsValid(colltp))
491  ereport(ERROR,
492  (errcode(ERRCODE_UNDEFINED_OBJECT),
493  errmsg("collation with OID %u does not exist", collid)));
494 
495  provider = ((Form_pg_collation) GETSTRUCT(colltp))->collprovider;
496  Assert(provider != COLLPROVIDER_DEFAULT);
497  datum = SysCacheGetAttr(COLLOID, colltp,
498  provider == COLLPROVIDER_ICU ?
499  Anum_pg_collation_colliculocale : Anum_pg_collation_collcollate,
500  &isnull);
501  if (isnull)
502  elog(ERROR, "unexpected null in pg_collation");
503 
504  locale = TextDatumGetCString(datum);
505 
506  ReleaseSysCache(colltp);
507  }
508 
510  if (version)
512  else
513  PG_RETURN_NULL();
514 }
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
Oid MyDatabaseId
Definition: globals.c:89
static JitProviderCallbacks provider
Definition: jit.c:43
Assert(fmt[strlen(fmt) - 1] !='\n')
char datlocprovider
Definition: pg_database.h:44
FormData_pg_database * Form_pg_database
Definition: pg_database.h:90
@ DATABASEOID
Definition: syscache.h:55
text * cstring_to_text(const char *s)
Definition: varlena.c:182

References Assert(), collid, COLLOID, cstring_to_text(), DATABASEOID, datlocprovider, elog(), ereport, errcode(), errmsg(), ERROR, get_collation_actual_version(), GETSTRUCT, HeapTupleIsValid, locale, MyDatabaseId, ObjectIdGetDatum(), PG_GETARG_OID, PG_RETURN_NULL, PG_RETURN_TEXT_P, provider, ReleaseSysCache(), SearchSysCache1(), SysCacheGetAttr(), and TextDatumGetCString.

◆ pg_import_system_collations()

Datum pg_import_system_collations ( PG_FUNCTION_ARGS  )

Definition at line 798 of file collationcmds.c.

799 {
800  Oid nspid = PG_GETARG_OID(0);
801  int ncreated = 0;
802 
803  if (!superuser())
804  ereport(ERROR,
805  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
806  errmsg("must be superuser to import system collations")));
807 
809  ereport(ERROR,
810  (errcode(ERRCODE_UNDEFINED_SCHEMA),
811  errmsg("schema with OID %u does not exist", nspid)));
812 
813  /* Load collations known to libc, using "locale -a" to enumerate them */
814 #ifdef READ_LOCALE_A_OUTPUT
815  {
816  FILE *locale_a_handle;
817  char localebuf[LOCALE_NAME_BUFLEN];
818  int nvalid = 0;
819  Oid collid;
820  CollAliasData *aliases;
821  int naliases,
822  maxaliases,
823  i;
824 
825  /* expansible array of aliases */
826  maxaliases = 100;
827  aliases = (CollAliasData *) palloc(maxaliases * sizeof(CollAliasData));
828  naliases = 0;
829 
830  locale_a_handle = OpenPipeStream("locale -a", "r");
831  if (locale_a_handle == NULL)
832  ereport(ERROR,
834  errmsg("could not execute command \"%s\": %m",
835  "locale -a")));
836 
837  while (fgets(localebuf, sizeof(localebuf), locale_a_handle))
838  {
839  size_t len;
840  int enc;
841  char alias[LOCALE_NAME_BUFLEN];
842 
843  len = strlen(localebuf);
844 
845  if (len == 0 || localebuf[len - 1] != '\n')
846  {
847  elog(DEBUG1, "skipping locale with too-long name: \"%s\"", localebuf);
848  continue;
849  }
850  localebuf[len - 1] = '\0';
851 
852  enc = create_collation_from_locale(localebuf, nspid, &nvalid, &ncreated);
853  if (enc < 0)
854  continue;
855 
856  /*
857  * Generate aliases such as "en_US" in addition to "en_US.utf8"
858  * for ease of use. Note that collation names are unique per
859  * encoding only, so this doesn't clash with "en_US" for LATIN1,
860  * say.
861  *
862  * However, it might conflict with a name we'll see later in the
863  * "locale -a" output. So save up the aliases and try to add them
864  * after we've read all the output.
865  */
866  if (normalize_libc_locale_name(alias, localebuf))
867  {
868  if (naliases >= maxaliases)
869  {
870  maxaliases *= 2;
871  aliases = (CollAliasData *)
872  repalloc(aliases, maxaliases * sizeof(CollAliasData));
873  }
874  aliases[naliases].localename = pstrdup(localebuf);
875  aliases[naliases].alias = pstrdup(alias);
876  aliases[naliases].enc = enc;
877  naliases++;
878  }
879  }
880 
881  /*
882  * We don't check the return value of this, because we want to support
883  * the case where there "locale" command does not exist. (This is
884  * unusual but can happen on minimalized Linux distributions, for
885  * example.) We will warn below if no locales could be found.
886  */
887  ClosePipeStream(locale_a_handle);
888 
889  /*
890  * Before processing the aliases, sort them by locale name. The point
891  * here is that if "locale -a" gives us multiple locale names with the
892  * same encoding and base name, say "en_US.utf8" and "en_US.utf-8", we
893  * want to pick a deterministic one of them. First in ASCII sort
894  * order is a good enough rule. (Before PG 10, the code corresponding
895  * to this logic in initdb.c had an additional ordering rule, to
896  * prefer the locale name exactly matching the alias, if any. We
897  * don't need to consider that here, because we would have already
898  * created such a pg_collation entry above, and that one will win.)
899  */
900  if (naliases > 1)
901  qsort(aliases, naliases, sizeof(CollAliasData), cmpaliases);
902 
903  /* Now add aliases, ignoring any that match pre-existing entries */
904  for (i = 0; i < naliases; i++)
905  {
906  char *locale = aliases[i].localename;
907  char *alias = aliases[i].alias;
908  int enc = aliases[i].enc;
909 
911  COLLPROVIDER_LIBC, true, enc,
912  locale, locale, NULL, NULL,
913  get_collation_actual_version(COLLPROVIDER_LIBC, locale),
914  true, true);
915  if (OidIsValid(collid))
916  {
917  ncreated++;
918 
920  }
921  }
922 
923  /* Give a warning if "locale -a" seems to be malfunctioning */
924  if (nvalid == 0)
926  (errmsg("no usable system locales were found")));
927  }
928 #endif /* READ_LOCALE_A_OUTPUT */
929 
930  /*
931  * Load collations known to ICU
932  *
933  * We use uloc_countAvailable()/uloc_getAvailable() rather than
934  * ucol_countAvailable()/ucol_getAvailable(). The former returns a full
935  * set of language+region combinations, whereas the latter only returns
936  * language+region combinations if they are distinct from the language's
937  * base collation. So there might not be a de-DE or en-GB, which would be
938  * confusing.
939  */
940 #ifdef USE_ICU
941  {
942  int i;
943 
944  /*
945  * Start the loop at -1 to sneak in the root locale without too much
946  * code duplication.
947  */
948  for (i = -1; i < uloc_countAvailable(); i++)
949  {
950  const char *name;
951  char *langtag;
952  char *icucomment;
953  const char *iculocstr;
954  Oid collid;
955 
956  if (i == -1)
957  name = ""; /* ICU root locale */
958  else
959  name = uloc_getAvailable(i);
960 
961  langtag = get_icu_language_tag(name);
962  iculocstr = U_ICU_VERSION_MAJOR_NUM >= 54 ? langtag : name;
963 
964  /*
965  * Be paranoid about not allowing any non-ASCII strings into
966  * pg_collation
967  */
968  if (!pg_is_ascii(langtag) || !pg_is_ascii(iculocstr))
969  continue;
970 
971  collid = CollationCreate(psprintf("%s-x-icu", langtag),
972  nspid, GetUserId(),
973  COLLPROVIDER_ICU, true, -1,
974  NULL, NULL, iculocstr, NULL,
975  get_collation_actual_version(COLLPROVIDER_ICU, iculocstr),
976  true, true);
977  if (OidIsValid(collid))
978  {
979  ncreated++;
980 
982 
983  icucomment = get_icu_locale_comment(name);
984  if (icucomment)
985  CreateComments(collid, CollationRelationId, 0,
986  icucomment);
987  }
988  }
989  }
990 #endif /* USE_ICU */
991 
992  /* Load collations known to WIN32 */
993 #ifdef ENUM_SYSTEM_LOCALE
994  {
995  int nvalid = 0;
996  CollParam param;
997 
998  param.nspid = nspid;
999  param.ncreatedp = &ncreated;
1000  param.nvalidp = &nvalid;
1001 
1002  /*
1003  * Enumerate the locales that are either installed on or supported
1004  * by the OS.
1005  */
1006  if (!EnumSystemLocalesEx(win32_read_locale, LOCALE_ALL,
1007  (LPARAM) &param, NULL))
1008  _dosmaperr(GetLastError());
1009 
1010  /* Give a warning if EnumSystemLocalesEx seems to be malfunctioning */
1011  if (nvalid == 0)
1012  ereport(WARNING,
1013  (errmsg("no usable system locales were found")));
1014  }
1015 #endif /* ENUM_SYSTEM_LOCALE */
1016 
1017  PG_RETURN_INT32(ncreated);
1018 }
int nspid
enc
void CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment)
Definition: comment.c:143
int errcode_for_file_access(void)
Definition: elog.c:881
#define WARNING
Definition: elog.h:36
const char * name
Definition: encode.c:571
int ClosePipeStream(FILE *file)
Definition: fd.c:2792
FILE * OpenPipeStream(const char *command, const char *mode)
Definition: fd.c:2487
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
int i
Definition: isn.c:73
char * pstrdup(const char *in)
Definition: mcxt.c:1624
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1456
void * palloc(Size size)
Definition: mcxt.c:1210
const void size_t len
#define LOCALE_NAME_BUFLEN
Definition: pg_locale.h:36
#define qsort(a, b, c, d)
Definition: port.h:445
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
bool pg_is_ascii(const char *str)
Definition: string.c:133
char * localename
Definition: collationcmds.c:45
bool superuser(void)
Definition: superuser.c:46
@ NAMESPACEOID
Definition: syscache.h:70
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:188
void _dosmaperr(unsigned long)
Definition: win32error.c:177

References _dosmaperr(), CollAliasData::alias, ClosePipeStream(), CollationCreate(), collid, CommandCounterIncrement(), CreateComments(), DEBUG1, elog(), CollAliasData::enc, enc, ereport, errcode(), errcode_for_file_access(), errmsg(), ERROR, get_collation_actual_version(), GetUserId(), i, len, locale, LOCALE_NAME_BUFLEN, CollAliasData::localename, name, NAMESPACEOID, nspid, ObjectIdGetDatum(), OidIsValid, OpenPipeStream(), palloc(), PG_GETARG_OID, pg_is_ascii(), PG_RETURN_INT32, psprintf(), pstrdup(), qsort, repalloc(), SearchSysCacheExists1, superuser(), and WARNING.

Variable Documentation

◆ collid

◆ enc

◆ ncreatedp

int int int* ncreatedp
Initial value:
{
int enc

Definition at line 657 of file collationcmds.c.

◆ nspid

◆ nvalidp

int int* nvalidp

Definition at line 657 of file collationcmds.c.