PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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/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/lsyscache.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 331 of file schemacmds.c.

332{
333 Oid nspOid;
335 Relation rel;
336 ObjectAddress address;
338
340
342 if (!HeapTupleIsValid(tup))
345 errmsg("schema \"%s\" does not exist", name)));
346
348 nspOid = nspform->oid;
349
351
353
355
357
358 return address;
359}
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
#define RowExclusiveLock
Definition lockdefs.h:38
#define ObjectAddressSet(addr, class_id, object_id)
FormData_pg_namespace * Form_pg_namespace
static Datum CStringGetDatum(const char *X)
Definition postgres.h:380
unsigned int Oid
static int fb(int x)
static void AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId)
Definition schemacmds.c:362
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition syscache.c:220
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, fb(), 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 362 of file schemacmds.c.

363{
365
366 Assert(tup->t_tableOid == NamespaceRelationId);
368
370
371 /*
372 * If the new owner is the same as the existing owner, consider the
373 * command to have succeeded. This is for dump restoration purposes.
374 */
375 if (nspForm->nspowner != newOwnerId)
376 {
380 Acl *newAcl;
382 bool isNull;
383 HeapTuple newtuple;
385
386 /* Otherwise, must be owner of the existing object */
389 NameStr(nspForm->nspname));
390
391 /* Must be able to become new owner */
393
394 /*
395 * must have create-schema rights
396 *
397 * NOTE: This is different from other alter-owner checks in that the
398 * current user is checked for create privileges instead of the
399 * destination owner. This is consistent with the CREATE case for
400 * schemas. Because superusers will always have this right, we need
401 * no special case for them.
402 */
404 ACL_CREATE);
405 if (aclresult != ACLCHECK_OK)
408
409 memset(repl_null, false, sizeof(repl_null));
410 memset(repl_repl, false, sizeof(repl_repl));
411
414
415 /*
416 * Determine the modified ACL for the new owner. This is only
417 * necessary when the ACL is non-null.
418 */
421 &isNull);
422 if (!isNull)
423 {
425 nspForm->nspowner, newOwnerId);
428 }
429
431
432 CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
433
434 heap_freetuple(newtuple);
435
436 /* Update owner dependency reference */
438 newOwnerId);
439 }
440
442 nspForm->oid, 0);
443}
Acl * aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
Definition acl.c:1119
void check_can_set_role(Oid member, Oid role)
Definition acl.c:5341
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:2654
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition aclchk.c:3836
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition aclchk.c:4090
#define NameStr(name)
Definition c.h:765
#define Assert(condition)
Definition c.h:873
Oid MyDatabaseId
Definition globals.c:94
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, const ItemPointerData *otid, HeapTuple tup)
Definition indexing.c:313
char * get_database_name(Oid dbid)
Definition lsyscache.c:1242
Oid GetUserId(void)
Definition miscinit.c:469
#define InvokeObjectPostAlterHook(classId, objectId, subId)
@ OBJECT_SCHEMA
@ OBJECT_DATABASE
#define ACL_CREATE
Definition parsenodes.h:85
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
static Datum PointerGetDatum(const void *X)
Definition postgres.h:352
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
uint64_t Datum
Definition postgres.h:70
#define RelationGetRelid(relation)
Definition rel.h:514
#define RelationGetDescr(relation)
Definition rel.h:540
ItemPointerData t_self
Definition htup.h:65
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:595

References ACL_CREATE, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, aclnewowner(), Assert, CatalogTupleUpdate(), changeDependencyOnOwner(), check_can_set_role(), DatumGetAclP, fb(), 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(), and HeapTupleData::t_self.

Referenced by AlterSchemaOwner(), and AlterSchemaOwner_oid().

◆ AlterSchemaOwner_oid()

void AlterSchemaOwner_oid ( Oid  schemaoid,
Oid  newOwnerId 
)

◆ 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;
61 int save_sec_context;
62 int save_nestlevel;
65 ObjectAddress address;
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
77
78 /* fill schema name with the user name if not specified */
79 if (!schemaName)
80 {
81 HeapTuple tuple;
82
84 if (!HeapTupleIsValid(tuple))
85 elog(ERROR, "cache lookup failed for role %u", owner_uid);
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 */
102
104
105 /* Additional check to protect reserved schema names */
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 {
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 */
130
131 /* OK to skip */
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)
150 save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
151
152 /* Create the schema's namespace */
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
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 */
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 */
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 */
207 {
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;
219
220 /* do this step */
221 ProcessUtility(wrapper,
222 queryString,
223 false,
225 NULL,
226 NULL,
228 NULL);
229
230 /* make sure later steps can see the object created here */
232 }
233
234 /*
235 * Restore the GUC variable search_path we set above.
236 */
237 AtEOXact_GUC(true, save_nestlevel);
238
239 /* Reset current user and security context */
240 SetUserIdAndSecContext(saved_uid, save_sec_context);
241
242 return namespaceId;
243}
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition acl.c:5586
#define OidIsValid(objectId)
Definition c.h:788
bool IsReservedName(const char *name)
Definition catalog.c:278
DestReceiver * None_Receiver
Definition dest.c:96
int errdetail(const char *fmt,...)
Definition elog.c:1216
#define NOTICE
Definition elog.h:35
void EventTriggerCollectSimpleCommand(ObjectAddress address, ObjectAddress secondaryObject, Node *parsetree)
bool allowSystemTableMods
Definition globals.c:130
int NewGUCNestLevel(void)
Definition guc.c:2110
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition guc.c:2137
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:3216
@ GUC_ACTION_SAVE
Definition guc.h:205
@ PGC_S_SESSION
Definition guc.h:126
@ PGC_USERSET
Definition guc.h:79
#define stmt
char * pstrdup(const char *in)
Definition mcxt.c:1781
#define SECURITY_LOCAL_USERID_CHANGE
Definition miscadmin.h:318
void GetUserIdAndSecContext(Oid *userid, int *sec_context)
Definition miscinit.c:612
void SetUserIdAndSecContext(Oid userid, int sec_context)
Definition miscinit.c:619
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition namespace.c:3605
char * namespace_search_path
Definition namespace.c:210
@ CMD_UTILITY
Definition nodes.h:280
#define makeNode(_type_)
Definition nodes.h:161
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)
@ PLAN_STMT_INTERNAL
Definition plannodes.h:40
#define InvalidOid
const char * quote_identifier(const char *ident)
bool scanner_isspace(char ch)
Definition scansup.c:105
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
Definition pg_list.h:54
Definition nodes.h:135
bool canSetTag
Definition plannodes.h:86
ParseLoc stmt_len
Definition plannodes.h:165
PlannedStmtOrigin planOrigin
Definition plannodes.h:77
ParseLoc stmt_location
Definition plannodes.h:163
CmdType commandType
Definition plannodes.h:68
Node * utilityStmt
Definition plannodes.h:150
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
Definition utility.c:501
@ PROCESS_UTILITY_SUBCOMMAND
Definition utility.h:26
void CommandCounterIncrement(void)
Definition xact.c:1101

References ACL_CREATE, aclcheck_error(), ACLCHECK_OK, allowSystemTableMods, appendStringInfo(), appendStringInfoString(), AtEOXact_GUC(), PlannedStmt::canSetTag, check_can_set_role(), checkMembershipInCurrentExtension(), CMD_UTILITY, CommandCounterIncrement(), PlannedStmt::commandType, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, EventTriggerCollectSimpleCommand(), fb(), 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, PLAN_STMT_INTERNAL, PlannedStmt::planOrigin, 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 250 of file schemacmds.c.

251{
252 Oid nspOid;
254 Relation rel;
256 ObjectAddress address;
258
260
262 if (!HeapTupleIsValid(tup))
265 errmsg("schema \"%s\" does not exist", oldname)));
266
268 nspOid = nspform->oid;
269
270 /* make sure the new name doesn't exist */
271 if (OidIsValid(get_namespace_oid(newname, true)))
274 errmsg("schema \"%s\" already exists", newname)));
275
276 /* must be owner */
279 oldname);
280
281 /* must have CREATE privilege on database */
283 if (aclresult != ACLCHECK_OK)
286
287 if (!allowSystemTableMods && IsReservedName(newname))
290 errmsg("unacceptable schema name \"%s\"", newname),
291 errdetail("The prefix \"pg_\" is reserved for system schemas.")));
292
293 /* rename */
294 namestrcpy(&nspform->nspname, newname);
295 CatalogTupleUpdate(rel, &tup->t_self, tup);
296
298
300
301 table_close(rel, NoLock);
303
304 return address;
305}
#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, fb(), 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, table_close(), and table_open().

Referenced by ExecRenameStmt().