PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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_database.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 "parser/scansup.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 schemaoid, Oid newOwnerId)
 
ObjectAddress AlterSchemaOwner (const char *name, Oid newOwnerId)
 

Function Documentation

◆ AlterSchemaOwner()

ObjectAddress AlterSchemaOwner ( const char *  name,
Oid  newOwnerId 
)

Definition at line 330 of file schemacmds.c.

331{
332 Oid nspOid;
333 HeapTuple tup;
334 Relation rel;
335 ObjectAddress address;
336 Form_pg_namespace nspform;
337
338 rel = table_open(NamespaceRelationId, RowExclusiveLock);
339
340 tup = SearchSysCache1(NAMESPACENAME, CStringGetDatum(name));
341 if (!HeapTupleIsValid(tup))
343 (errcode(ERRCODE_UNDEFINED_SCHEMA),
344 errmsg("schema \"%s\" does not exist", name)));
345
346 nspform = (Form_pg_namespace) GETSTRUCT(tup);
347 nspOid = nspform->oid;
348
349 AlterSchemaOwner_internal(tup, rel, newOwnerId);
350
351 ObjectAddressSet(address, NamespaceRelationId, nspOid);
352
353 ReleaseSysCache(tup);
354
356
357 return address;
358}
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
FormData_pg_namespace * Form_pg_namespace
Definition: pg_namespace.h:52
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
unsigned int Oid
Definition: postgres_ext.h:31
static void AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId)
Definition: schemacmds.c:361
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
const char * name

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

Referenced by ExecAlterOwnerStmt().

◆ AlterSchemaOwner_internal()

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

Definition at line 361 of file schemacmds.c.

362{
363 Form_pg_namespace nspForm;
364
365 Assert(tup->t_tableOid == NamespaceRelationId);
366 Assert(RelationGetRelid(rel) == NamespaceRelationId);
367
368 nspForm = (Form_pg_namespace) GETSTRUCT(tup);
369
370 /*
371 * If the new owner is the same as the existing owner, consider the
372 * command to have succeeded. This is for dump restoration purposes.
373 */
374 if (nspForm->nspowner != newOwnerId)
375 {
376 Datum repl_val[Natts_pg_namespace];
377 bool repl_null[Natts_pg_namespace];
378 bool repl_repl[Natts_pg_namespace];
379 Acl *newAcl;
380 Datum aclDatum;
381 bool isNull;
382 HeapTuple newtuple;
383 AclResult aclresult;
384
385 /* Otherwise, must be owner of the existing object */
386 if (!object_ownercheck(NamespaceRelationId, nspForm->oid, GetUserId()))
388 NameStr(nspForm->nspname));
389
390 /* Must be able to become new owner */
391 check_can_set_role(GetUserId(), newOwnerId);
392
393 /*
394 * must have create-schema rights
395 *
396 * NOTE: This is different from other alter-owner checks in that the
397 * current user is checked for create privileges instead of the
398 * destination owner. This is consistent with the CREATE case for
399 * schemas. Because superusers will always have this right, we need
400 * no special case for them.
401 */
402 aclresult = object_aclcheck(DatabaseRelationId, MyDatabaseId, GetUserId(),
403 ACL_CREATE);
404 if (aclresult != ACLCHECK_OK)
407
408 memset(repl_null, false, sizeof(repl_null));
409 memset(repl_repl, false, sizeof(repl_repl));
410
411 repl_repl[Anum_pg_namespace_nspowner - 1] = true;
412 repl_val[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(newOwnerId);
413
414 /*
415 * Determine the modified ACL for the new owner. This is only
416 * necessary when the ACL is non-null.
417 */
418 aclDatum = SysCacheGetAttr(NAMESPACENAME, tup,
419 Anum_pg_namespace_nspacl,
420 &isNull);
421 if (!isNull)
422 {
423 newAcl = aclnewowner(DatumGetAclP(aclDatum),
424 nspForm->nspowner, newOwnerId);
425 repl_repl[Anum_pg_namespace_nspacl - 1] = true;
426 repl_val[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(newAcl);
427 }
428
429 newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null, repl_repl);
430
431 CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
432
433 heap_freetuple(newtuple);
434
435 /* Update owner dependency reference */
436 changeDependencyOnOwner(NamespaceRelationId, nspForm->oid,
437 newOwnerId);
438 }
439
440 InvokeObjectPostAlterHook(NamespaceRelationId,
441 nspForm->oid, 0);
442}
Acl * aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
Definition: acl.c:1103
void check_can_set_role(Oid member, Oid role)
Definition: acl.c:5325
AclResult
Definition: acl.h:182
@ ACLCHECK_OK
Definition: acl.h:183
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
#define DatumGetAclP(X)
Definition: acl.h:120
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2622
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3810
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4064
#define NameStr(name)
Definition: c.h:700
#define Assert(condition)
Definition: c.h:812
char * get_database_name(Oid dbid)
Definition: dbcommands.c:3187
Oid MyDatabaseId
Definition: globals.c:93
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition: heaptuple.c:1210
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1435
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
Oid GetUserId(void)
Definition: miscinit.c:517
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
@ OBJECT_SCHEMA
Definition: parsenodes.h:2304
@ OBJECT_DATABASE
Definition: parsenodes.h:2277
#define ACL_CREATE
Definition: parsenodes.h:85
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
Definition: pg_shdepend.c:316
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
#define RelationGetRelid(relation)
Definition: rel.h:505
#define RelationGetDescr(relation)
Definition: rel.h:531
ItemPointerData t_self
Definition: htup.h:65
Oid t_tableOid
Definition: htup.h:66
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:600

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

Referenced by AlterSchemaOwner(), and AlterSchemaOwner_oid().

◆ AlterSchemaOwner_oid()

void AlterSchemaOwner_oid ( Oid  schemaoid,
Oid  newOwnerId 
)

Definition at line 307 of file schemacmds.c.

308{
309 HeapTuple tup;
310 Relation rel;
311
312 rel = table_open(NamespaceRelationId, RowExclusiveLock);
313
314 tup = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(schemaoid));
315 if (!HeapTupleIsValid(tup))
316 elog(ERROR, "cache lookup failed for schema %u", schemaoid);
317
318 AlterSchemaOwner_internal(tup, rel, newOwnerId);
319
320 ReleaseSysCache(tup);
321
323}
#define elog(elevel,...)
Definition: elog.h:225

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

Referenced by shdepReassignOwned_Owner().

◆ CreateSchemaCommand()

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

Definition at line 52 of file schemacmds.c.

54{
55 const char *schemaName = stmt->schemaname;
56 Oid namespaceId;
57 List *parsetree_list;
58 ListCell *parsetree_item;
59 Oid owner_uid;
60 Oid saved_uid;
61 int save_sec_context;
62 int save_nestlevel;
63 char *nsp = namespace_search_path;
64 AclResult aclresult;
65 ObjectAddress address;
66 StringInfoData pathbuf;
67
68 GetUserIdAndSecContext(&saved_uid, &save_sec_context);
69
70 /*
71 * Who is supposed to own the new schema?
72 */
73 if (stmt->authrole)
74 owner_uid = get_rolespec_oid(stmt->authrole, false);
75 else
76 owner_uid = saved_uid;
77
78 /* fill schema name with the user name if not specified */
79 if (!schemaName)
80 {
81 HeapTuple tuple;
82
83 tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(owner_uid));
84 if (!HeapTupleIsValid(tuple))
85 elog(ERROR, "cache lookup failed for role %u", owner_uid);
86 schemaName =
88 ReleaseSysCache(tuple);
89 }
90
91 /*
92 * To create a schema, must have schema-create privilege on the current
93 * database and must be able to become the target role (this does not
94 * imply that the target role itself must have create-schema privilege).
95 * The latter provision guards against "giveaway" attacks. Note that a
96 * superuser will always have both of these privileges a fortiori.
97 */
98 aclresult = object_aclcheck(DatabaseRelationId, MyDatabaseId, saved_uid, ACL_CREATE);
99 if (aclresult != ACLCHECK_OK)
102
103 check_can_set_role(saved_uid, owner_uid);
104
105 /* Additional check to protect reserved schema names */
106 if (!allowSystemTableMods && IsReservedName(schemaName))
108 (errcode(ERRCODE_RESERVED_NAME),
109 errmsg("unacceptable schema name \"%s\"", schemaName),
110 errdetail("The prefix \"pg_\" is reserved for system schemas.")));
111
112 /*
113 * If if_not_exists was given and the schema already exists, bail out.
114 * (Note: we needn't check this when not if_not_exists, because
115 * NamespaceCreate will complain anyway.) We could do this before making
116 * the permissions checks, but since CREATE TABLE IF NOT EXISTS makes its
117 * creation-permission check first, we do likewise.
118 */
119 if (stmt->if_not_exists)
120 {
121 namespaceId = get_namespace_oid(schemaName, true);
122 if (OidIsValid(namespaceId))
123 {
124 /*
125 * If we are in an extension script, insist that the pre-existing
126 * object be a member of the extension, to avoid security risks.
127 */
128 ObjectAddressSet(address, NamespaceRelationId, namespaceId);
130
131 /* OK to skip */
133 (errcode(ERRCODE_DUPLICATE_SCHEMA),
134 errmsg("schema \"%s\" already exists, skipping",
135 schemaName)));
136 return InvalidOid;
137 }
138 }
139
140 /*
141 * If the requested authorization is different from the current user,
142 * temporarily set the current user so that the object(s) will be created
143 * with the correct ownership.
144 *
145 * (The setting will be restored at the end of this routine, or in case of
146 * error, transaction abort will clean things up.)
147 */
148 if (saved_uid != owner_uid)
149 SetUserIdAndSecContext(owner_uid,
150 save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
151
152 /* Create the schema's namespace */
153 namespaceId = NamespaceCreate(schemaName, owner_uid, false);
154
155 /* Advance cmd counter to make the namespace visible */
157
158 /*
159 * Prepend the new schema to the current search path.
160 *
161 * We use the equivalent of a function SET option to allow the setting to
162 * persist for exactly the duration of the schema creation. guc.c also
163 * takes care of undoing the setting on error.
164 */
165 save_nestlevel = NewGUCNestLevel();
166
167 initStringInfo(&pathbuf);
168 appendStringInfoString(&pathbuf, quote_identifier(schemaName));
169
170 while (scanner_isspace(*nsp))
171 nsp++;
172
173 if (*nsp != '\0')
174 appendStringInfo(&pathbuf, ", %s", nsp);
175
176 (void) set_config_option("search_path", pathbuf.data,
178 GUC_ACTION_SAVE, true, 0, false);
179
180 /*
181 * Report the new schema to possibly interested event triggers. Note we
182 * must do this here and not in ProcessUtilitySlow because otherwise the
183 * objects created below are reported before the schema, which would be
184 * wrong.
185 */
186 ObjectAddressSet(address, NamespaceRelationId, namespaceId);
188 (Node *) stmt);
189
190 /*
191 * Examine the list of commands embedded in the CREATE SCHEMA command, and
192 * reorganize them into a sequentially executable order with no forward
193 * references. Note that the result is still a list of raw parsetrees ---
194 * we cannot, in general, run parse analysis on one statement until we
195 * have actually executed the prior ones.
196 */
197 parsetree_list = transformCreateSchemaStmtElements(stmt->schemaElts,
198 schemaName);
199
200 /*
201 * Execute each command contained in the CREATE SCHEMA. Since the grammar
202 * allows only utility commands in CREATE SCHEMA, there is no need to pass
203 * them through parse_analyze_*() or the rewriter; we can just hand them
204 * straight to ProcessUtility.
205 */
206 foreach(parsetree_item, parsetree_list)
207 {
208 Node *stmt = (Node *) lfirst(parsetree_item);
209 PlannedStmt *wrapper;
210
211 /* need to make a wrapper PlannedStmt */
212 wrapper = makeNode(PlannedStmt);
213 wrapper->commandType = CMD_UTILITY;
214 wrapper->canSetTag = false;
215 wrapper->utilityStmt = stmt;
216 wrapper->stmt_location = stmt_location;
217 wrapper->stmt_len = stmt_len;
218
219 /* do this step */
220 ProcessUtility(wrapper,
221 queryString,
222 false,
224 NULL,
225 NULL,
227 NULL);
228
229 /* make sure later steps can see the object created here */
231 }
232
233 /*
234 * Restore the GUC variable search_path we set above.
235 */
236 AtEOXact_GUC(true, save_nestlevel);
237
238 /* Reset current user and security context */
239 SetUserIdAndSecContext(saved_uid, save_sec_context);
240
241 return namespaceId;
242}
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5588
#define OidIsValid(objectId)
Definition: c.h:729
bool IsReservedName(const char *name)
Definition: catalog.c:247
DestReceiver * None_Receiver
Definition: dest.c:96
int errdetail(const char *fmt,...)
Definition: elog.c:1203
#define NOTICE
Definition: elog.h:35
void EventTriggerCollectSimpleCommand(ObjectAddress address, ObjectAddress secondaryObject, Node *parsetree)
bool allowSystemTableMods
Definition: globals.c:129
int NewGUCNestLevel(void)
Definition: guc.c:2235
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition: guc.c:2262
int set_config_option(const char *name, const char *value, GucContext context, GucSource source, GucAction action, bool changeVal, int elevel, bool is_reload)
Definition: guc.c:3342
@ GUC_ACTION_SAVE
Definition: guc.h:201
@ PGC_S_SESSION
Definition: guc.h:122
@ PGC_USERSET
Definition: guc.h:75
#define stmt
Definition: indent_codes.h:59
char * pstrdup(const char *in)
Definition: mcxt.c:1696
#define SECURITY_LOCAL_USERID_CHANGE
Definition: miscadmin.h:317
void GetUserIdAndSecContext(Oid *userid, int *sec_context)
Definition: miscinit.c:660
void SetUserIdAndSecContext(Oid userid, int sec_context)
Definition: miscinit.c:667
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition: namespace.c:3535
char * namespace_search_path
Definition: namespace.c:211
@ CMD_UTILITY
Definition: nodes.h:270
#define makeNode(_type_)
Definition: nodes.h:155
const ObjectAddress InvalidObjectAddress
List * transformCreateSchemaStmtElements(List *schemaElts, const char *schemaName)
NameData rolname
Definition: pg_authid.h:34
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
void checkMembershipInCurrentExtension(const ObjectAddress *object)
Definition: pg_depend.c:258
#define lfirst(lc)
Definition: pg_list.h:172
Oid NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
Definition: pg_namespace.c:43
#define InvalidOid
Definition: postgres_ext.h:36
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:12870
bool scanner_isspace(char ch)
Definition: scansup.c:117
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:94
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:179
void initStringInfo(StringInfo str)
Definition: stringinfo.c:56
Definition: pg_list.h:54
Definition: nodes.h:129
bool canSetTag
Definition: plannodes.h:60
ParseLoc stmt_len
Definition: plannodes.h:99
ParseLoc stmt_location
Definition: plannodes.h:98
CmdType commandType
Definition: plannodes.h:52
Node * utilityStmt
Definition: plannodes.h:95
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
Definition: utility.c:499
@ PROCESS_UTILITY_SUBCOMMAND
Definition: utility.h:26
void CommandCounterIncrement(void)
Definition: xact.c:1099

References ACL_CREATE, aclcheck_error(), ACLCHECK_OK, allowSystemTableMods, appendStringInfo(), appendStringInfoString(), AtEOXact_GUC(), PlannedStmt::canSetTag, check_can_set_role(), checkMembershipInCurrentExtension(), CMD_UTILITY, CommandCounterIncrement(), PlannedStmt::commandType, StringInfoData::data, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, EventTriggerCollectSimpleCommand(), get_database_name(), get_namespace_oid(), get_rolespec_oid(), GETSTRUCT, GetUserIdAndSecContext(), GUC_ACTION_SAVE, HeapTupleIsValid, initStringInfo(), InvalidObjectAddress, InvalidOid, IsReservedName(), lfirst, makeNode, MyDatabaseId, namespace_search_path, NamespaceCreate(), NameStr, NewGUCNestLevel(), None_Receiver, NOTICE, object_aclcheck(), OBJECT_DATABASE, ObjectAddressSet, ObjectIdGetDatum(), OidIsValid, PGC_S_SESSION, PGC_USERSET, PROCESS_UTILITY_SUBCOMMAND, ProcessUtility(), pstrdup(), quote_identifier(), ReleaseSysCache(), rolname, scanner_isspace(), SearchSysCache1(), SECURITY_LOCAL_USERID_CHANGE, set_config_option(), SetUserIdAndSecContext(), stmt, PlannedStmt::stmt_len, PlannedStmt::stmt_location, transformCreateSchemaStmtElements(), and PlannedStmt::utilityStmt.

Referenced by CreateExtensionInternal(), and ProcessUtilitySlow().

◆ RenameSchema()

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

Definition at line 249 of file schemacmds.c.

250{
251 Oid nspOid;
252 HeapTuple tup;
253 Relation rel;
254 AclResult aclresult;
255 ObjectAddress address;
256 Form_pg_namespace nspform;
257
258 rel = table_open(NamespaceRelationId, RowExclusiveLock);
259
260 tup = SearchSysCacheCopy1(NAMESPACENAME, CStringGetDatum(oldname));
261 if (!HeapTupleIsValid(tup))
263 (errcode(ERRCODE_UNDEFINED_SCHEMA),
264 errmsg("schema \"%s\" does not exist", oldname)));
265
266 nspform = (Form_pg_namespace) GETSTRUCT(tup);
267 nspOid = nspform->oid;
268
269 /* make sure the new name doesn't exist */
270 if (OidIsValid(get_namespace_oid(newname, true)))
272 (errcode(ERRCODE_DUPLICATE_SCHEMA),
273 errmsg("schema \"%s\" already exists", newname)));
274
275 /* must be owner */
276 if (!object_ownercheck(NamespaceRelationId, nspOid, GetUserId()))
278 oldname);
279
280 /* must have CREATE privilege on database */
281 aclresult = object_aclcheck(DatabaseRelationId, MyDatabaseId, GetUserId(), ACL_CREATE);
282 if (aclresult != ACLCHECK_OK)
285
286 if (!allowSystemTableMods && IsReservedName(newname))
288 (errcode(ERRCODE_RESERVED_NAME),
289 errmsg("unacceptable schema name \"%s\"", newname),
290 errdetail("The prefix \"pg_\" is reserved for system schemas.")));
291
292 /* rename */
293 namestrcpy(&nspform->nspname, newname);
294 CatalogTupleUpdate(rel, &tup->t_self, tup);
295
296 InvokeObjectPostAlterHook(NamespaceRelationId, nspOid, 0);
297
298 ObjectAddressSet(address, NamespaceRelationId, nspOid);
299
300 table_close(rel, NoLock);
301 heap_freetuple(tup);
302
303 return address;
304}
#define NoLock
Definition: lockdefs.h:34
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:91

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, namestrcpy(), NoLock, object_aclcheck(), OBJECT_DATABASE, object_ownercheck(), OBJECT_SCHEMA, ObjectAddressSet, OidIsValid, RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, table_close(), and table_open().

Referenced by ExecRenameStmt().