PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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)
 
ObjectAddress AlterCollation (AlterCollationStmt *stmt)
 

Function Documentation

ObjectAddress AlterCollation ( AlterCollationStmt stmt)

Definition at line 236 of file collationcmds.c.

References ACL_KIND_COLLATION, aclcheck_error(), ACLCHECK_NOT_OWNER, Anum_pg_collation_collversion, CatalogTupleUpdate(), CollationRelationId, AlterCollationStmt::collname, COLLOID, CStringGetTextDatum, elog, ereport, errmsg(), ERROR, get_collation_actual_version(), get_collation_oid(), GETSTRUCT, GetUserId(), heap_close, heap_freetuple(), heap_modify_tuple(), heap_open(), HeapTupleIsValid, InvokeObjectPostAlterHook, NameListToString(), NameStr, Natts_pg_collation, NoLock, NOTICE, NULL, ObjectAddressSet, ObjectIdGetDatum, pg_collation_ownercheck(), RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy1, SysCacheGetAttr(), HeapTupleData::t_self, TextDatumGetCString, and values.

Referenced by ProcessUtilitySlow().

237 {
238  Relation rel;
239  Oid collOid;
240  HeapTuple tup;
241  Form_pg_collation collForm;
242  Datum collversion;
243  bool isnull;
244  char *oldversion;
245  char *newversion;
246  ObjectAddress address;
247 
249  collOid = get_collation_oid(stmt->collname, false);
250 
251  if (!pg_collation_ownercheck(collOid, GetUserId()))
253  NameListToString(stmt->collname));
254 
256  if (!HeapTupleIsValid(tup))
257  elog(ERROR, "cache lookup failed for collation %u", collOid);
258 
259  collForm = (Form_pg_collation) GETSTRUCT(tup);
261  &isnull);
262  oldversion = isnull ? NULL : TextDatumGetCString(collversion);
263 
264  newversion = get_collation_actual_version(collForm->collprovider, NameStr(collForm->collcollate));
265 
266  /* cannot change from NULL to non-NULL or vice versa */
267  if ((!oldversion && newversion) || (oldversion && !newversion))
268  elog(ERROR, "invalid collation version change");
269  else if (oldversion && newversion && strcmp(newversion, oldversion) != 0)
270  {
271  bool nulls[Natts_pg_collation];
272  bool replaces[Natts_pg_collation];
274 
275  ereport(NOTICE,
276  (errmsg("changing version from %s to %s",
277  oldversion, newversion)));
278 
279  memset(values, 0, sizeof(values));
280  memset(nulls, false, sizeof(nulls));
281  memset(replaces, false, sizeof(replaces));
282 
283  values[Anum_pg_collation_collversion - 1] = CStringGetTextDatum(newversion);
284  replaces[Anum_pg_collation_collversion - 1] = true;
285 
286  tup = heap_modify_tuple(tup, RelationGetDescr(rel),
287  values, nulls, replaces);
288  }
289  else
290  ereport(NOTICE,
291  (errmsg("version has not changed")));
292 
293  CatalogTupleUpdate(rel, &tup->t_self, tup);
294 
296 
297  ObjectAddressSet(address, CollationRelationId, collOid);
298 
299  heap_freetuple(tup);
300  heap_close(rel, NoLock);
301 
302  return address;
303 }
bool pg_collation_ownercheck(Oid coll_oid, Oid roleid)
Definition: aclchk.c:4990
#define Anum_pg_collation_collversion
Definition: pg_collation.h:65
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define RelationGetDescr(relation)
Definition: rel.h:429
Oid GetUserId(void)
Definition: miscinit.c:283
#define Natts_pg_collation
Definition: pg_collation.h:57
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
char * NameListToString(List *names)
Definition: namespace.c:2953
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1278
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define CollationRelationId
Definition: pg_collation.h:30
#define NOTICE
Definition: elog.h:37
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:51
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
static Datum values[MAXATTR]
Definition: bootstrap.c:163
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:161
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:499
#define CStringGetTextDatum(s)
Definition: builtins.h:91
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:793
Oid get_collation_oid(List *name, bool missing_ok)
Definition: namespace.c:3380
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1423
ObjectAddress DefineCollation ( ParseState pstate,
List names,
List parameters,
bool  if_not_exists 
)

Definition at line 44 of file collationcmds.c.

References ACL_CREATE, ACL_KIND_NAMESPACE, aclcheck_error(), ACLCHECK_OK, check_encoding_locale_matches(), CollationCreate(), CollationRelationId, COLLOID, COLLPROVIDER_ICU, COLLPROVIDER_LIBC, CommandCounterIncrement(), defGetQualifiedName(), defGetString(), DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, get_collation_actual_version(), get_collation_oid(), get_namespace_name(), GetDatabaseEncoding(), GETSTRUCT, GetUserId(), HeapTupleIsValid, InvalidObjectAddress, lfirst_node, 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().

45 {
46  char *collName;
47  Oid collNamespace;
48  AclResult aclresult;
49  ListCell *pl;
50  DefElem *fromEl = NULL;
51  DefElem *localeEl = NULL;
52  DefElem *lccollateEl = NULL;
53  DefElem *lcctypeEl = NULL;
54  DefElem *providerEl = NULL;
55  DefElem *versionEl = NULL;
56  char *collcollate = NULL;
57  char *collctype = NULL;
58  char *collproviderstr = NULL;
59  int collencoding;
60  char collprovider = 0;
61  char *collversion = NULL;
62  Oid newoid;
63  ObjectAddress address;
64 
65  collNamespace = QualifiedNameGetCreationNamespace(names, &collName);
66 
67  aclresult = pg_namespace_aclcheck(collNamespace, GetUserId(), ACL_CREATE);
68  if (aclresult != ACLCHECK_OK)
70  get_namespace_name(collNamespace));
71 
72  foreach(pl, parameters)
73  {
74  DefElem *defel = lfirst_node(DefElem, pl);
75  DefElem **defelp;
76 
77  if (pg_strcasecmp(defel->defname, "from") == 0)
78  defelp = &fromEl;
79  else if (pg_strcasecmp(defel->defname, "locale") == 0)
80  defelp = &localeEl;
81  else if (pg_strcasecmp(defel->defname, "lc_collate") == 0)
82  defelp = &lccollateEl;
83  else if (pg_strcasecmp(defel->defname, "lc_ctype") == 0)
84  defelp = &lcctypeEl;
85  else if (pg_strcasecmp(defel->defname, "provider") == 0)
86  defelp = &providerEl;
87  else if (pg_strcasecmp(defel->defname, "version") == 0)
88  defelp = &versionEl;
89  else
90  {
91  ereport(ERROR,
92  (errcode(ERRCODE_SYNTAX_ERROR),
93  errmsg("collation attribute \"%s\" not recognized",
94  defel->defname),
95  parser_errposition(pstate, defel->location)));
96  break;
97  }
98 
99  *defelp = defel;
100  }
101 
102  if ((localeEl && (lccollateEl || lcctypeEl))
103  || (fromEl && list_length(parameters) != 1))
104  ereport(ERROR,
105  (errcode(ERRCODE_SYNTAX_ERROR),
106  errmsg("conflicting or redundant options")));
107 
108  if (fromEl)
109  {
110  Oid collid;
111  HeapTuple tp;
112 
113  collid = get_collation_oid(defGetQualifiedName(fromEl), false);
115  if (!HeapTupleIsValid(tp))
116  elog(ERROR, "cache lookup failed for collation %u", collid);
117 
118  collcollate = pstrdup(NameStr(((Form_pg_collation) GETSTRUCT(tp))->collcollate));
119  collctype = pstrdup(NameStr(((Form_pg_collation) GETSTRUCT(tp))->collctype));
120  collprovider = ((Form_pg_collation) GETSTRUCT(tp))->collprovider;
121 
122  ReleaseSysCache(tp);
123  }
124 
125  if (localeEl)
126  {
127  collcollate = defGetString(localeEl);
128  collctype = defGetString(localeEl);
129  }
130 
131  if (lccollateEl)
132  collcollate = defGetString(lccollateEl);
133 
134  if (lcctypeEl)
135  collctype = defGetString(lcctypeEl);
136 
137  if (providerEl)
138  collproviderstr = defGetString(providerEl);
139 
140  if (versionEl)
141  collversion = defGetString(versionEl);
142 
143  if (collproviderstr)
144  {
145  if (pg_strcasecmp(collproviderstr, "icu") == 0)
146  collprovider = COLLPROVIDER_ICU;
147  else if (pg_strcasecmp(collproviderstr, "libc") == 0)
148  collprovider = COLLPROVIDER_LIBC;
149  else
150  ereport(ERROR,
151  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
152  errmsg("unrecognized collation provider: %s",
153  collproviderstr)));
154  }
155  else if (!fromEl)
156  collprovider = COLLPROVIDER_LIBC;
157 
158  if (!collcollate)
159  ereport(ERROR,
160  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
161  errmsg("parameter \"lc_collate\" must be specified")));
162 
163  if (!collctype)
164  ereport(ERROR,
165  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
166  errmsg("parameter \"lc_ctype\" must be specified")));
167 
168  if (collprovider == COLLPROVIDER_ICU)
169  collencoding = -1;
170  else
171  {
172  collencoding = GetDatabaseEncoding();
173  check_encoding_locale_matches(collencoding, collcollate, collctype);
174  }
175 
176  if (!collversion)
177  collversion = get_collation_actual_version(collprovider, collcollate);
178 
179  newoid = CollationCreate(collName,
180  collNamespace,
181  GetUserId(),
182  collprovider,
183  collencoding,
184  collcollate,
185  collctype,
186  collversion,
187  if_not_exists);
188 
189  if (!OidIsValid(newoid))
190  return InvalidObjectAddress;
191 
192  ObjectAddressSet(address, CollationRelationId, newoid);
193 
194  /* check that the locales can be loaded */
196  (void) pg_newlocale_from_collation(newoid);
197 
198  return address;
199 }
#define COLLPROVIDER_ICU
Definition: pg_collation.h:84
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid CollationCreate(const char *collname, Oid collnamespace, Oid collowner, char collprovider, int32 collencoding, const char *collcollate, const char *collctype, const char *collversion, bool if_not_exists)
Definition: pg_collation.c:42
void check_encoding_locale_matches(int encoding, const char *collate, const char *ctype)
Definition: dbcommands.c:722
Oid GetUserId(void)
Definition: miscinit.c:283
Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p)
Definition: namespace.c:2846
char * pstrdup(const char *in)
Definition: mcxt.c:1077
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
#define OidIsValid(objectId)
Definition: c.h:538
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4484
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:82
char * defGetString(DefElem *def)
Definition: define.c:49
#define lfirst_node(type, lc)
Definition: pg_list.h:109
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3038
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
int location
Definition: parsenodes.h:722
#define ereport(elevel, rest)
Definition: elog.h:122
pg_locale_t pg_newlocale_from_collation(Oid collid)
Definition: pg_locale.c:1265
AclResult
Definition: acl.h:170
void CommandCounterIncrement(void)
Definition: xact.c:922
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
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:229
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:111
FormData_pg_collation * Form_pg_collation
Definition: pg_collation.h:51
#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:499
char * defname
Definition: parsenodes.h:719
#define elog
Definition: elog.h:219
Oid get_collation_oid(List *name, bool missing_ok)
Definition: namespace.c:3380
#define COLLPROVIDER_LIBC
Definition: pg_collation.h:85
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1423
void IsThereCollationInNamespace ( const char *  collname,
Oid  nspOid 
)

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

209 {
210  /* make sure the name doesn't already exist in new schema */
212  CStringGetDatum(collname),
214  ObjectIdGetDatum(nspOid)))
215  ereport(ERROR,
217  errmsg("collation \"%s\" for encoding \"%s\" already exists in schema \"%s\"",
218  collname, GetDatabaseEncodingName(),
219  get_namespace_name(nspOid))));
220 
221  /* mustn't match an any-encoding entry, either */
223  CStringGetDatum(collname),
224  Int32GetDatum(-1),
225  ObjectIdGetDatum(nspOid)))
226  ereport(ERROR,
228  errmsg("collation \"%s\" already exists in schema \"%s\"",
229  collname, get_namespace_name(nspOid))));
230 }
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define SearchSysCacheExists3(cacheId, key1, key2, key3)
Definition: syscache.h:174
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3038
#define CStringGetDatum(X)
Definition: postgres.h:584
#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:485
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31