Header And Logo

PostgreSQL
| The world's most advanced open source database.

Functions

schemacmds.h File Reference

#include "nodes/parsenodes.h"
Include dependency graph for schemacmds.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

Oid CreateSchemaCommand (CreateSchemaStmt *parsetree, const char *queryString)
void RemoveSchemaById (Oid schemaOid)
Oid RenameSchema (const char *oldname, const char *newname)
Oid AlterSchemaOwner (const char *name, Oid newOwnerId)
void AlterSchemaOwner_oid (Oid schemaOid, Oid newOwnerId)

Function Documentation

Oid AlterSchemaOwner ( const char *  name,
Oid  newOwnerId 
)
void AlterSchemaOwner_oid ( Oid  schemaOid,
Oid  newOwnerId 
)
Oid CreateSchemaCommand ( CreateSchemaStmt parsetree,
const char *  queryString 
)

Definition at line 43 of file schemacmds.c.

References ACL_CREATE, ACL_KIND_DATABASE, aclcheck_error(), ACLCHECK_OK, allowSystemTableMods, CreateSchemaStmt::authid, check_is_member_of_role(), CommandCounterIncrement(), CurrentMemoryContext, ereport, errcode(), errdetail(), errmsg(), ERROR, get_database_name(), get_role_oid(), GetOverrideSearchPath(), GetUserIdAndSecContext(), CreateSchemaStmt::if_not_exists, IsReservedName(), lcons_oid(), lfirst, MyDatabaseId, NamespaceCreate(), NAMESPACENAME, None_Receiver, NOTICE, NULL, pg_database_aclcheck(), PointerGetDatum, PopOverrideSearchPath(), PROCESS_UTILITY_SUBCOMMAND, ProcessUtility(), PushOverrideSearchPath(), CreateSchemaStmt::schemaname, OverrideSearchPath::schemas, SearchSysCacheExists1, SECURITY_LOCAL_USERID_CHANGE, SetUserIdAndSecContext(), and transformCreateSchemaStmt().

Referenced by CreateExtension(), and ProcessUtilitySlow().

{
    const char *schemaName = stmt->schemaname;
    const char *authId = stmt->authid;
    Oid         namespaceId;
    OverrideSearchPath *overridePath;
    List       *parsetree_list;
    ListCell   *parsetree_item;
    Oid         owner_uid;
    Oid         saved_uid;
    int         save_sec_context;
    AclResult   aclresult;

    GetUserIdAndSecContext(&saved_uid, &save_sec_context);

    /*
     * Who is supposed to own the new schema?
     */
    if (authId)
        owner_uid = get_role_oid(authId, false);
    else
        owner_uid = saved_uid;

    /*
     * To create a schema, must have schema-create privilege on the current
     * database and must be able to become the target role (this does not
     * imply that the target role itself must have create-schema privilege).
     * The latter provision guards against "giveaway" attacks.  Note that a
     * superuser will always have both of these privileges a fortiori.
     */
    aclresult = pg_database_aclcheck(MyDatabaseId, saved_uid, ACL_CREATE);
    if (aclresult != ACLCHECK_OK)
        aclcheck_error(aclresult, ACL_KIND_DATABASE,
                       get_database_name(MyDatabaseId));

    check_is_member_of_role(saved_uid, owner_uid);

    /* Additional check to protect reserved schema names */
    if (!allowSystemTableMods && IsReservedName(schemaName))
        ereport(ERROR,
                (errcode(ERRCODE_RESERVED_NAME),
                 errmsg("unacceptable schema name \"%s\"", schemaName),
           errdetail("The prefix \"pg_\" is reserved for system schemas.")));

    /*
     * If if_not_exists was given and the schema already exists, bail out.
     * (Note: we needn't check this when not if_not_exists, because
     * NamespaceCreate will complain anyway.)  We could do this before making
     * the permissions checks, but since CREATE TABLE IF NOT EXISTS makes its
     * creation-permission check first, we do likewise.
     */
    if (stmt->if_not_exists &&
        SearchSysCacheExists1(NAMESPACENAME, PointerGetDatum(schemaName)))
    {
        ereport(NOTICE,
                (errcode(ERRCODE_DUPLICATE_SCHEMA),
                 errmsg("schema \"%s\" already exists, skipping",
                        schemaName)));
        return InvalidOid;
    }

    /*
     * If the requested authorization is different from the current user,
     * temporarily set the current user so that the object(s) will be created
     * with the correct ownership.
     *
     * (The setting will be restored at the end of this routine, or in case of
     * error, transaction abort will clean things up.)
     */
    if (saved_uid != owner_uid)
        SetUserIdAndSecContext(owner_uid,
                            save_sec_context | SECURITY_LOCAL_USERID_CHANGE);

    /* Create the schema's namespace */
    namespaceId = NamespaceCreate(schemaName, owner_uid, false);

    /* Advance cmd counter to make the namespace visible */
    CommandCounterIncrement();

    /*
     * Temporarily make the new namespace be the front of the search path, as
     * well as the default creation target namespace.  This will be undone at
     * the end of this routine, or upon error.
     */
    overridePath = GetOverrideSearchPath(CurrentMemoryContext);
    overridePath->schemas = lcons_oid(namespaceId, overridePath->schemas);
    /* XXX should we clear overridePath->useTemp? */
    PushOverrideSearchPath(overridePath);

    /*
     * Examine the list of commands embedded in the CREATE SCHEMA command, and
     * reorganize them into a sequentially executable order with no forward
     * references.  Note that the result is still a list of raw parsetrees ---
     * we cannot, in general, run parse analysis on one statement until we
     * have actually executed the prior ones.
     */
    parsetree_list = transformCreateSchemaStmt(stmt);

    /*
     * Execute each command contained in the CREATE SCHEMA.  Since the grammar
     * allows only utility commands in CREATE SCHEMA, there is no need to pass
     * them through parse_analyze() or the rewriter; we can just hand them
     * straight to ProcessUtility.
     */
    foreach(parsetree_item, parsetree_list)
    {
        Node       *stmt = (Node *) lfirst(parsetree_item);

        /* do this step */
        ProcessUtility(stmt,
                       queryString,
                       PROCESS_UTILITY_SUBCOMMAND,
                       NULL,
                       None_Receiver,
                       NULL);
        /* make sure later steps can see the object created here */
        CommandCounterIncrement();
    }

    /* Reset search path to normal state */
    PopOverrideSearchPath();

    /* Reset current user and security context */
    SetUserIdAndSecContext(saved_uid, save_sec_context);

    return namespaceId;
}

void RemoveSchemaById ( Oid  schemaOid  ) 

Definition at line 175 of file schemacmds.c.

References elog, ERROR, heap_close, heap_open(), HeapTupleIsValid, NAMESPACEOID, NamespaceRelationId, ObjectIdGetDatum, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1, simple_heap_delete(), and HeapTupleData::t_self.

Referenced by doDeletion().

{
    Relation    relation;
    HeapTuple   tup;

    relation = heap_open(NamespaceRelationId, RowExclusiveLock);

    tup = SearchSysCache1(NAMESPACEOID,
                          ObjectIdGetDatum(schemaOid));
    if (!HeapTupleIsValid(tup)) /* should not happen */
        elog(ERROR, "cache lookup failed for namespace %u", schemaOid);

    simple_heap_delete(relation, &tup->t_self);

    ReleaseSysCache(tup);

    heap_close(relation, RowExclusiveLock);
}

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

Definition at line 199 of file schemacmds.c.

References ACL_CREATE, ACL_KIND_DATABASE, ACL_KIND_NAMESPACE, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, allowSystemTableMods, CatalogUpdateIndexes(), CStringGetDatum, ereport, errcode(), errdetail(), errmsg(), ERROR, get_database_name(), get_namespace_oid(), GETSTRUCT, GetUserId(), heap_close, heap_freetuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, InvokeObjectPostAlterHook, IsReservedName(), MyDatabaseId, NAMESPACENAME, NamespaceRelationId, namestrcpy(), NoLock, OidIsValid, pg_database_aclcheck(), pg_namespace_ownercheck(), RowExclusiveLock, SearchSysCacheCopy1, simple_heap_update(), and HeapTupleData::t_self.

Referenced by ExecRenameStmt().

{
    Oid         nspOid;
    HeapTuple   tup;
    Relation    rel;
    AclResult   aclresult;

    rel = heap_open(NamespaceRelationId, RowExclusiveLock);

    tup = SearchSysCacheCopy1(NAMESPACENAME, CStringGetDatum(oldname));
    if (!HeapTupleIsValid(tup))
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_SCHEMA),
                 errmsg("schema \"%s\" does not exist", oldname)));

    nspOid = HeapTupleGetOid(tup);

    /* make sure the new name doesn't exist */
    if (OidIsValid(get_namespace_oid(newname, true)))
        ereport(ERROR,
                (errcode(ERRCODE_DUPLICATE_SCHEMA),
                 errmsg("schema \"%s\" already exists", newname)));

    /* must be owner */
    if (!pg_namespace_ownercheck(HeapTupleGetOid(tup), GetUserId()))
        aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE,
                       oldname);

    /* must have CREATE privilege on database */
    aclresult = pg_database_aclcheck(MyDatabaseId, GetUserId(), ACL_CREATE);
    if (aclresult != ACLCHECK_OK)
        aclcheck_error(aclresult, ACL_KIND_DATABASE,
                       get_database_name(MyDatabaseId));

    if (!allowSystemTableMods && IsReservedName(newname))
        ereport(ERROR,
                (errcode(ERRCODE_RESERVED_NAME),
                 errmsg("unacceptable schema name \"%s\"", newname),
           errdetail("The prefix \"pg_\" is reserved for system schemas.")));

    /* rename */
    namestrcpy(&(((Form_pg_namespace) GETSTRUCT(tup))->nspname), newname);
    simple_heap_update(rel, &tup->t_self, tup);
    CatalogUpdateIndexes(rel, tup);

    InvokeObjectPostAlterHook(NamespaceRelationId, HeapTupleGetOid(tup), 0);

    heap_close(rel, NoLock);
    heap_freetuple(tup);

    return nspOid;
}