PostgreSQL Source Code  git master
schemacmds.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "access/xact.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_namespace.h"
#include "commands/dbcommands.h"
#include "commands/event_trigger.h"
#include "commands/schemacmds.h"
#include "miscadmin.h"
#include "parser/parse_utilcmd.h"
#include "tcop/utility.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Include dependency graph for schemacmds.c:

Go to the source code of this file.

Functions

static void AlterSchemaOwner_internal (HeapTuple tup, Relation rel, Oid newOwnerId)
 
Oid CreateSchemaCommand (CreateSchemaStmt *stmt, const char *queryString, int stmt_location, int stmt_len)
 
ObjectAddress RenameSchema (const char *oldname, const char *newname)
 
void AlterSchemaOwner_oid (Oid oid, Oid newOwnerId)
 
ObjectAddress AlterSchemaOwner (const char *name, Oid newOwnerId)
 

Function Documentation

◆ AlterSchemaOwner()

ObjectAddress AlterSchemaOwner ( const char *  name,
Oid  newOwnerId 
)

Definition at line 299 of file schemacmds.c.

References AlterSchemaOwner_internal(), CStringGetDatum, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, NAMESPACENAME, ObjectAddressSet, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), table_close(), and table_open().

Referenced by ExecAlterOwnerStmt().

300 {
301  Oid nspOid;
302  HeapTuple tup;
303  Relation rel;
304  ObjectAddress address;
305  Form_pg_namespace nspform;
306 
307  rel = table_open(NamespaceRelationId, RowExclusiveLock);
308 
310  if (!HeapTupleIsValid(tup))
311  ereport(ERROR,
312  (errcode(ERRCODE_UNDEFINED_SCHEMA),
313  errmsg("schema \"%s\" does not exist", name)));
314 
315  nspform = (Form_pg_namespace) GETSTRUCT(tup);
316  nspOid = nspform->oid;
317 
318  AlterSchemaOwner_internal(tup, rel, newOwnerId);
319 
320  ObjectAddressSet(address, NamespaceRelationId, nspOid);
321 
322  ReleaseSysCache(tup);
323 
325 
326  return address;
327 }
static void AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId)
Definition: schemacmds.c:330
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
FormData_pg_namespace * Form_pg_namespace
Definition: pg_namespace.h:52
int errcode(int sqlerrcode)
Definition: elog.c:610
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define ereport(elevel,...)
Definition: elog.h:144
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
const char * name
Definition: encode.c:561
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
int errmsg(const char *fmt,...)
Definition: elog.c:824
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ AlterSchemaOwner_internal()

static void AlterSchemaOwner_internal ( HeapTuple  tup,
Relation  rel,
Oid  newOwnerId 
)
static

Definition at line 330 of file schemacmds.c.

References ACL_CREATE, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, aclnewowner(), Assert, CatalogTupleUpdate(), changeDependencyOnOwner(), check_is_member_of_role(), DatumGetAclP, get_database_name(), GETSTRUCT, GetUserId(), heap_freetuple(), heap_modify_tuple(), InvokeObjectPostAlterHook, MyDatabaseId, NAMESPACENAME, NameStr, OBJECT_DATABASE, OBJECT_SCHEMA, ObjectIdGetDatum, pg_database_aclcheck(), pg_namespace_ownercheck(), PointerGetDatum, RelationGetDescr, RelationGetRelid, SysCacheGetAttr(), HeapTupleData::t_self, and HeapTupleData::t_tableOid.

Referenced by AlterSchemaOwner(), and AlterSchemaOwner_oid().

331 {
332  Form_pg_namespace nspForm;
333 
334  Assert(tup->t_tableOid == NamespaceRelationId);
335  Assert(RelationGetRelid(rel) == NamespaceRelationId);
336 
337  nspForm = (Form_pg_namespace) GETSTRUCT(tup);
338 
339  /*
340  * If the new owner is the same as the existing owner, consider the
341  * command to have succeeded. This is for dump restoration purposes.
342  */
343  if (nspForm->nspowner != newOwnerId)
344  {
345  Datum repl_val[Natts_pg_namespace];
346  bool repl_null[Natts_pg_namespace];
347  bool repl_repl[Natts_pg_namespace];
348  Acl *newAcl;
349  Datum aclDatum;
350  bool isNull;
351  HeapTuple newtuple;
352  AclResult aclresult;
353 
354  /* Otherwise, must be owner of the existing object */
355  if (!pg_namespace_ownercheck(nspForm->oid, GetUserId()))
357  NameStr(nspForm->nspname));
358 
359  /* Must be able to become new owner */
360  check_is_member_of_role(GetUserId(), newOwnerId);
361 
362  /*
363  * must have create-schema rights
364  *
365  * NOTE: This is different from other alter-owner checks in that the
366  * current user is checked for create privileges instead of the
367  * destination owner. This is consistent with the CREATE case for
368  * schemas. Because superusers will always have this right, we need
369  * no special case for them.
370  */
372  ACL_CREATE);
373  if (aclresult != ACLCHECK_OK)
374  aclcheck_error(aclresult, OBJECT_DATABASE,
376 
377  memset(repl_null, false, sizeof(repl_null));
378  memset(repl_repl, false, sizeof(repl_repl));
379 
380  repl_repl[Anum_pg_namespace_nspowner - 1] = true;
381  repl_val[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(newOwnerId);
382 
383  /*
384  * Determine the modified ACL for the new owner. This is only
385  * necessary when the ACL is non-null.
386  */
387  aclDatum = SysCacheGetAttr(NAMESPACENAME, tup,
388  Anum_pg_namespace_nspacl,
389  &isNull);
390  if (!isNull)
391  {
392  newAcl = aclnewowner(DatumGetAclP(aclDatum),
393  nspForm->nspowner, newOwnerId);
394  repl_repl[Anum_pg_namespace_nspacl - 1] = true;
395  repl_val[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(newAcl);
396  }
397 
398  newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null, repl_repl);
399 
400  CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
401 
402  heap_freetuple(newtuple);
403 
404  /* Update owner dependency reference */
405  changeDependencyOnOwner(NamespaceRelationId, nspForm->oid,
406  newOwnerId);
407  }
408 
409  InvokeObjectPostAlterHook(NamespaceRelationId,
410  nspForm->oid, 0);
411 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
FormData_pg_namespace * Form_pg_namespace
Definition: pg_namespace.h:52
#define RelationGetDescr(relation)
Definition: rel.h:482
Oid GetUserId(void)
Definition: miscinit.c:450
#define DatumGetAclP(X)
Definition: acl.h:120
#define PointerGetDatum(X)
Definition: postgres.h:556
bool pg_namespace_ownercheck(Oid nsp_oid, Oid roleid)
Definition: aclchk.c:4863
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
Definition: pg_shdepend.c:309
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ACL_CREATE
Definition: parsenodes.h:84
ItemPointerData t_self
Definition: htup.h:65
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2155
Oid t_tableOid
Definition: htup.h:66
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4938
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
Oid MyDatabaseId
Definition: globals.c:85
AclResult pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4575
#define Assert(condition)
Definition: c.h:745
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define NameStr(name)
Definition: c.h:622
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
Acl * aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
Definition: acl.c:1044
#define RelationGetRelid(relation)
Definition: rel.h:456

◆ AlterSchemaOwner_oid()

void AlterSchemaOwner_oid ( Oid  oid,
Oid  newOwnerId 
)

Definition at line 276 of file schemacmds.c.

References AlterSchemaOwner_internal(), elog, ERROR, HeapTupleIsValid, NAMESPACEOID, ObjectIdGetDatum, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), table_close(), and table_open().

Referenced by shdepReassignOwned().

277 {
278  HeapTuple tup;
279  Relation rel;
280 
281  rel = table_open(NamespaceRelationId, RowExclusiveLock);
282 
284  if (!HeapTupleIsValid(tup))
285  elog(ERROR, "cache lookup failed for schema %u", oid);
286 
287  AlterSchemaOwner_internal(tup, rel, newOwnerId);
288 
289  ReleaseSysCache(tup);
290 
292 }
static void AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId)
Definition: schemacmds.c:330
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:214
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ CreateSchemaCommand()

Oid CreateSchemaCommand ( CreateSchemaStmt stmt,
const char *  queryString,
int  stmt_location,
int  stmt_len 
)

Definition at line 50 of file schemacmds.c.

References ACL_CREATE, aclcheck_error(), ACLCHECK_OK, allowSystemTableMods, AUTHOID, CreateSchemaStmt::authrole, PlannedStmt::canSetTag, check_is_member_of_role(), CMD_UTILITY, CommandCounterIncrement(), PlannedStmt::commandType, CurrentMemoryContext, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, EventTriggerCollectSimpleCommand(), get_database_name(), get_rolespec_oid(), GetOverrideSearchPath(), GETSTRUCT, GetUserIdAndSecContext(), HeapTupleIsValid, CreateSchemaStmt::if_not_exists, InvalidObjectAddress, InvalidOid, IsReservedName(), lcons_oid(), lfirst, makeNode, MyDatabaseId, NamespaceCreate(), NAMESPACENAME, NameStr, None_Receiver, NOTICE, OBJECT_DATABASE, ObjectAddressSet, ObjectIdGetDatum, pg_database_aclcheck(), PointerGetDatum, PopOverrideSearchPath(), PROCESS_UTILITY_SUBCOMMAND, ProcessUtility(), pstrdup(), PushOverrideSearchPath(), ReleaseSysCache(), rolname, CreateSchemaStmt::schemaname, OverrideSearchPath::schemas, SearchSysCache1(), SearchSysCacheExists1, SECURITY_LOCAL_USERID_CHANGE, SetUserIdAndSecContext(), prepared_statement::stmt, PlannedStmt::stmt_len, PlannedStmt::stmt_location, transformCreateSchemaStmt(), and PlannedStmt::utilityStmt.

Referenced by CreateExtensionInternal(), and ProcessUtilitySlow().

52 {
53  const char *schemaName = stmt->schemaname;
54  Oid namespaceId;
55  OverrideSearchPath *overridePath;
56  List *parsetree_list;
57  ListCell *parsetree_item;
58  Oid owner_uid;
59  Oid saved_uid;
60  int save_sec_context;
61  AclResult aclresult;
62  ObjectAddress address;
63 
64  GetUserIdAndSecContext(&saved_uid, &save_sec_context);
65 
66  /*
67  * Who is supposed to own the new schema?
68  */
69  if (stmt->authrole)
70  owner_uid = get_rolespec_oid(stmt->authrole, false);
71  else
72  owner_uid = saved_uid;
73 
74  /* fill schema name with the user name if not specified */
75  if (!schemaName)
76  {
77  HeapTuple tuple;
78 
79  tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(owner_uid));
80  if (!HeapTupleIsValid(tuple))
81  elog(ERROR, "cache lookup failed for role %u", owner_uid);
82  schemaName =
84  ReleaseSysCache(tuple);
85  }
86 
87  /*
88  * To create a schema, must have schema-create privilege on the current
89  * database and must be able to become the target role (this does not
90  * imply that the target role itself must have create-schema privilege).
91  * The latter provision guards against "giveaway" attacks. Note that a
92  * superuser will always have both of these privileges a fortiori.
93  */
94  aclresult = pg_database_aclcheck(MyDatabaseId, saved_uid, ACL_CREATE);
95  if (aclresult != ACLCHECK_OK)
98 
99  check_is_member_of_role(saved_uid, owner_uid);
100 
101  /* Additional check to protect reserved schema names */
102  if (!allowSystemTableMods && IsReservedName(schemaName))
103  ereport(ERROR,
104  (errcode(ERRCODE_RESERVED_NAME),
105  errmsg("unacceptable schema name \"%s\"", schemaName),
106  errdetail("The prefix \"pg_\" is reserved for system schemas.")));
107 
108  /*
109  * If if_not_exists was given and the schema already exists, bail out.
110  * (Note: we needn't check this when not if_not_exists, because
111  * NamespaceCreate will complain anyway.) We could do this before making
112  * the permissions checks, but since CREATE TABLE IF NOT EXISTS makes its
113  * creation-permission check first, we do likewise.
114  */
115  if (stmt->if_not_exists &&
117  {
118  ereport(NOTICE,
119  (errcode(ERRCODE_DUPLICATE_SCHEMA),
120  errmsg("schema \"%s\" already exists, skipping",
121  schemaName)));
122  return InvalidOid;
123  }
124 
125  /*
126  * If the requested authorization is different from the current user,
127  * temporarily set the current user so that the object(s) will be created
128  * with the correct ownership.
129  *
130  * (The setting will be restored at the end of this routine, or in case of
131  * error, transaction abort will clean things up.)
132  */
133  if (saved_uid != owner_uid)
134  SetUserIdAndSecContext(owner_uid,
135  save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
136 
137  /* Create the schema's namespace */
138  namespaceId = NamespaceCreate(schemaName, owner_uid, false);
139 
140  /* Advance cmd counter to make the namespace visible */
142 
143  /*
144  * Temporarily make the new namespace be the front of the search path, as
145  * well as the default creation target namespace. This will be undone at
146  * the end of this routine, or upon error.
147  */
149  overridePath->schemas = lcons_oid(namespaceId, overridePath->schemas);
150  /* XXX should we clear overridePath->useTemp? */
151  PushOverrideSearchPath(overridePath);
152 
153  /*
154  * Report the new schema to possibly interested event triggers. Note we
155  * must do this here and not in ProcessUtilitySlow because otherwise the
156  * objects created below are reported before the schema, which would be
157  * wrong.
158  */
159  ObjectAddressSet(address, NamespaceRelationId, namespaceId);
161  (Node *) stmt);
162 
163  /*
164  * Examine the list of commands embedded in the CREATE SCHEMA command, and
165  * reorganize them into a sequentially executable order with no forward
166  * references. Note that the result is still a list of raw parsetrees ---
167  * we cannot, in general, run parse analysis on one statement until we
168  * have actually executed the prior ones.
169  */
170  parsetree_list = transformCreateSchemaStmt(stmt);
171 
172  /*
173  * Execute each command contained in the CREATE SCHEMA. Since the grammar
174  * allows only utility commands in CREATE SCHEMA, there is no need to pass
175  * them through parse_analyze() or the rewriter; we can just hand them
176  * straight to ProcessUtility.
177  */
178  foreach(parsetree_item, parsetree_list)
179  {
180  Node *stmt = (Node *) lfirst(parsetree_item);
181  PlannedStmt *wrapper;
182 
183  /* need to make a wrapper PlannedStmt */
184  wrapper = makeNode(PlannedStmt);
185  wrapper->commandType = CMD_UTILITY;
186  wrapper->canSetTag = false;
187  wrapper->utilityStmt = stmt;
188  wrapper->stmt_location = stmt_location;
189  wrapper->stmt_len = stmt_len;
190 
191  /* do this step */
192  ProcessUtility(wrapper,
193  queryString,
195  NULL,
196  NULL,
198  NULL);
199 
200  /* make sure later steps can see the object created here */
202  }
203 
204  /* Reset search path to normal state */
206 
207  /* Reset current user and security context */
208  SetUserIdAndSecContext(saved_uid, save_sec_context);
209 
210  return namespaceId;
211 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void SetUserIdAndSecContext(Oid userid, int sec_context)
Definition: miscinit.c:562
NameData rolname
Definition: pg_authid.h:34
#define PointerGetDatum(X)
Definition: postgres.h:556
char * pstrdup(const char *in)
Definition: mcxt.c:1186
void PushOverrideSearchPath(OverrideSearchPath *newpath)
Definition: namespace.c:3490
Definition: nodes.h:529
int errcode(int sqlerrcode)
Definition: elog.c:610
List * lcons_oid(Oid datum, List *list)
Definition: list.c:489
unsigned int Oid
Definition: postgres_ext.h:31
bool IsReservedName(const char *name)
Definition: catalog.c:212
DestReceiver * None_Receiver
Definition: dest.c:96
int stmt_len
Definition: plannodes.h:96
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:183
RoleSpec * authrole
Definition: parsenodes.h:1759
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:84
OverrideSearchPath * GetOverrideSearchPath(MemoryContext context)
Definition: namespace.c:3360
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2155
int stmt_location
Definition: plannodes.h:95
void GetUserIdAndSecContext(Oid *userid, int *sec_context)
Definition: miscinit.c:555
int errdetail(const char *fmt,...)
Definition: elog.c:957
Node * utilityStmt
Definition: plannodes.h:92
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4938
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void PopOverrideSearchPath(void)
Definition: namespace.c:3557
bool canSetTag
Definition: plannodes.h:54
AclResult
Definition: acl.h:177
CmdType commandType
Definition: plannodes.h:46
void CommandCounterIncrement(void)
Definition: xact.c:1021
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
Oid MyDatabaseId
Definition: globals.c:85
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5209
#define SECURITY_LOCAL_USERID_CHANGE
Definition: miscadmin.h:298
bool allowSystemTableMods
Definition: globals.c:120
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:144
#define NOTICE
Definition: elog.h:37
#define makeNode(_type_)
Definition: nodes.h:577
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
AclResult pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4575
#define lfirst(lc)
Definition: pg_list.h:190
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
List * transformCreateSchemaStmt(CreateSchemaStmt *stmt)
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
#define NameStr(name)
Definition: c.h:622
void EventTriggerCollectSimpleCommand(ObjectAddress address, ObjectAddress secondaryObject, Node *parsetree)
Definition: pg_list.h:50
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
Definition: utility.c:501
Oid NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
Definition: pg_namespace.c:43

◆ RenameSchema()

ObjectAddress RenameSchema ( const char *  oldname,
const char *  newname 
)

Definition at line 218 of file schemacmds.c.

References ACL_CREATE, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, allowSystemTableMods, CatalogTupleUpdate(), CStringGetDatum, ereport, errcode(), errdetail(), errmsg(), ERROR, get_database_name(), get_namespace_oid(), GETSTRUCT, GetUserId(), heap_freetuple(), HeapTupleIsValid, InvokeObjectPostAlterHook, IsReservedName(), MyDatabaseId, NAMESPACENAME, namestrcpy(), NoLock, OBJECT_DATABASE, OBJECT_SCHEMA, ObjectAddressSet, OidIsValid, pg_database_aclcheck(), pg_namespace_ownercheck(), RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, table_close(), and table_open().

Referenced by ExecRenameStmt().

219 {
220  Oid nspOid;
221  HeapTuple tup;
222  Relation rel;
223  AclResult aclresult;
224  ObjectAddress address;
225  Form_pg_namespace nspform;
226 
227  rel = table_open(NamespaceRelationId, RowExclusiveLock);
228 
230  if (!HeapTupleIsValid(tup))
231  ereport(ERROR,
232  (errcode(ERRCODE_UNDEFINED_SCHEMA),
233  errmsg("schema \"%s\" does not exist", oldname)));
234 
235  nspform = (Form_pg_namespace) GETSTRUCT(tup);
236  nspOid = nspform->oid;
237 
238  /* make sure the new name doesn't exist */
239  if (OidIsValid(get_namespace_oid(newname, true)))
240  ereport(ERROR,
241  (errcode(ERRCODE_DUPLICATE_SCHEMA),
242  errmsg("schema \"%s\" already exists", newname)));
243 
244  /* must be owner */
245  if (!pg_namespace_ownercheck(nspOid, GetUserId()))
247  oldname);
248 
249  /* must have CREATE privilege on database */
251  if (aclresult != ACLCHECK_OK)
252  aclcheck_error(aclresult, OBJECT_DATABASE,
254 
255  if (!allowSystemTableMods && IsReservedName(newname))
256  ereport(ERROR,
257  (errcode(ERRCODE_RESERVED_NAME),
258  errmsg("unacceptable schema name \"%s\"", newname),
259  errdetail("The prefix \"pg_\" is reserved for system schemas.")));
260 
261  /* rename */
262  namestrcpy(&nspform->nspname, newname);
263  CatalogTupleUpdate(rel, &tup->t_self, tup);
264 
265  InvokeObjectPostAlterHook(NamespaceRelationId, nspOid, 0);
266 
267  ObjectAddressSet(address, NamespaceRelationId, nspOid);
268 
269  table_close(rel, NoLock);
270  heap_freetuple(tup);
271 
272  return address;
273 }
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition: namespace.c:3043
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
FormData_pg_namespace * Form_pg_namespace
Definition: pg_namespace.h:52
Oid GetUserId(void)
Definition: miscinit.c:450
void namestrcpy(Name name, const char *str)
Definition: name.c:233
int errcode(int sqlerrcode)
Definition: elog.c:610
bool pg_namespace_ownercheck(Oid nsp_oid, Oid roleid)
Definition: aclchk.c:4863
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
bool IsReservedName(const char *name)
Definition: catalog.c:212
#define OidIsValid(objectId)
Definition: c.h:651
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:84
ItemPointerData t_self
Definition: htup.h:65
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2155
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:957
#define CStringGetDatum(X)
Definition: postgres.h:578
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
AclResult
Definition: acl.h:177
Oid MyDatabaseId
Definition: globals.c:85
bool allowSystemTableMods
Definition: globals.c:120
#define ereport(elevel,...)
Definition: elog.h:144
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
AclResult pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4575
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
int errmsg(const char *fmt,...)
Definition: elog.c:824
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39