LCOV - differential code coverage report
Current view: top level - src/backend/commands - schemacmds.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 88.3 % 128 113 15 113
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 5 5 5
Baseline: 16@8cea358b128 Branches: 61.8 % 76 47 29 47
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (240..) days: 88.3 % 128 113 15 113
Function coverage date bins:
(240..) days: 100.0 % 5 5 5
Branch coverage date bins:
(240..) days: 61.8 % 76 47 29 47

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * schemacmds.c
                                  4                 :                :  *    schema creation/manipulation commands
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  *
                                 10                 :                :  * IDENTIFICATION
                                 11                 :                :  *    src/backend/commands/schemacmds.c
                                 12                 :                :  *
                                 13                 :                :  *-------------------------------------------------------------------------
                                 14                 :                :  */
                                 15                 :                : #include "postgres.h"
                                 16                 :                : 
                                 17                 :                : #include "access/htup_details.h"
                                 18                 :                : #include "access/table.h"
                                 19                 :                : #include "access/xact.h"
                                 20                 :                : #include "catalog/catalog.h"
                                 21                 :                : #include "catalog/dependency.h"
                                 22                 :                : #include "catalog/indexing.h"
                                 23                 :                : #include "catalog/namespace.h"
                                 24                 :                : #include "catalog/objectaccess.h"
                                 25                 :                : #include "catalog/pg_authid.h"
                                 26                 :                : #include "catalog/pg_database.h"
                                 27                 :                : #include "catalog/pg_namespace.h"
                                 28                 :                : #include "commands/dbcommands.h"
                                 29                 :                : #include "commands/event_trigger.h"
                                 30                 :                : #include "commands/schemacmds.h"
                                 31                 :                : #include "miscadmin.h"
                                 32                 :                : #include "parser/parse_utilcmd.h"
                                 33                 :                : #include "parser/scansup.h"
                                 34                 :                : #include "tcop/utility.h"
                                 35                 :                : #include "utils/acl.h"
                                 36                 :                : #include "utils/builtins.h"
                                 37                 :                : #include "utils/rel.h"
                                 38                 :                : #include "utils/syscache.h"
                                 39                 :                : 
                                 40                 :                : static void AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId);
                                 41                 :                : 
                                 42                 :                : /*
                                 43                 :                :  * CREATE SCHEMA
                                 44                 :                :  *
                                 45                 :                :  * Note: caller should pass in location information for the whole
                                 46                 :                :  * CREATE SCHEMA statement, which in turn we pass down as the location
                                 47                 :                :  * of the component commands.  This comports with our general plan of
                                 48                 :                :  * reporting location/len for the whole command even when executing
                                 49                 :                :  * a subquery.
                                 50                 :                :  */
                                 51                 :                : Oid
 2647 tgl@sss.pgh.pa.us          52                 :CBC         493 : CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString,
                                 53                 :                :                     int stmt_location, int stmt_len)
                                 54                 :                : {
 3249 bruce@momjian.us           55                 :            493 :     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;
  342 noah@leadboat.com          63                 :            493 :     char       *nsp = namespace_search_path;
                                 64                 :                :     AclResult   aclresult;
                                 65                 :                :     ObjectAddress address;
                                 66                 :                :     StringInfoData pathbuf;
                                 67                 :                : 
 5240 tgl@sss.pgh.pa.us          68                 :            493 :     GetUserIdAndSecContext(&saved_uid, &save_sec_context);
                                 69                 :                : 
                                 70                 :                :     /*
                                 71                 :                :      * Who is supposed to own the new schema?
                                 72                 :                :      */
 3324 alvherre@alvh.no-ip.       73         [ +  + ]:            493 :     if (stmt->authrole)
                                 74                 :             88 :         owner_uid = get_rolespec_oid(stmt->authrole, false);
                                 75                 :                :     else
 6865 tgl@sss.pgh.pa.us          76                 :            405 :         owner_uid = saved_uid;
                                 77                 :                : 
                                 78                 :                :     /* fill schema name with the user name if not specified */
 3324 alvherre@alvh.no-ip.       79         [ +  + ]:            487 :     if (!schemaName)
                                 80                 :                :     {
                                 81                 :                :         HeapTuple   tuple;
                                 82                 :                : 
                                 83                 :             36 :         tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(owner_uid));
                                 84         [ -  + ]:             36 :         if (!HeapTupleIsValid(tuple))
 3324 alvherre@alvh.no-ip.       85         [ #  # ]:UBC           0 :             elog(ERROR, "cache lookup failed for role %u", owner_uid);
                                 86                 :                :         schemaName =
 3324 alvherre@alvh.no-ip.       87                 :CBC          36 :             pstrdup(NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname));
                                 88                 :             36 :         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                 :                :      */
  518 peter@eisentraut.org       98                 :            487 :     aclresult = object_aclcheck(DatabaseRelationId, MyDatabaseId, saved_uid, ACL_CREATE);
 8023 tgl@sss.pgh.pa.us          99         [ -  + ]:            487 :     if (aclresult != ACLCHECK_OK)
 2325 peter_e@gmx.net           100                 :UBC           0 :         aclcheck_error(aclresult, OBJECT_DATABASE,
 7562 tgl@sss.pgh.pa.us         101                 :              0 :                        get_database_name(MyDatabaseId));
                                102                 :                : 
  513 rhaas@postgresql.org      103                 :CBC         487 :     check_can_set_role(saved_uid, owner_uid);
                                104                 :                : 
                                105                 :                :     /* Additional check to protect reserved schema names */
 8035 tgl@sss.pgh.pa.us         106   [ +  +  +  + ]:            484 :     if (!allowSystemTableMods && IsReservedName(schemaName))
 7576                           107         [ +  - ]:              1 :         ereport(ERROR,
                                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                 :                :      */
  615                           119         [ +  + ]:            483 :     if (stmt->if_not_exists)
                                120                 :                :     {
                                121                 :             17 :         namespaceId = get_namespace_oid(schemaName, true);
                                122         [ +  + ]:             17 :         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                 :             12 :             ObjectAddressSet(address, NamespaceRelationId, namespaceId);
                                129                 :             12 :             checkMembershipInCurrentExtension(&address);
                                130                 :                : 
                                131                 :                :             /* OK to skip */
                                132         [ +  + ]:             11 :             ereport(NOTICE,
                                133                 :                :                     (errcode(ERRCODE_DUPLICATE_SCHEMA),
                                134                 :                :                      errmsg("schema \"%s\" already exists, skipping",
                                135                 :                :                             schemaName)));
                                136                 :             11 :             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                 :                :      */
 6849                           148         [ +  + ]:            471 :     if (saved_uid != owner_uid)
 5240                           149                 :             35 :         SetUserIdAndSecContext(owner_uid,
                                150                 :                :                                save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
                                151                 :                : 
                                152                 :                :     /* Create the schema's namespace */
 4420                           153                 :            471 :     namespaceId = NamespaceCreate(schemaName, owner_uid, false);
                                154                 :                : 
                                155                 :                :     /* Advance cmd counter to make the namespace visible */
 8035                           156                 :            468 :     CommandCounterIncrement();
                                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                 :                :      */
  342 noah@leadboat.com         165                 :            468 :     save_nestlevel = NewGUCNestLevel();
                                166                 :                : 
                                167                 :            468 :     initStringInfo(&pathbuf);
                                168                 :            468 :     appendStringInfoString(&pathbuf, quote_identifier(schemaName));
                                169                 :                : 
                                170         [ +  + ]:            471 :     while (scanner_isspace(*nsp))
                                171                 :              3 :         nsp++;
                                172                 :                : 
                                173         [ +  + ]:            468 :     if (*nsp != '\0')
                                174                 :            456 :         appendStringInfo(&pathbuf, ", %s", nsp);
                                175                 :                : 
                                176                 :            468 :     (void) set_config_option("search_path", pathbuf.data,
                                177                 :                :                              PGC_USERSET, PGC_S_SESSION,
                                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                 :                :      */
 3261 alvherre@alvh.no-ip.      186                 :            468 :     ObjectAddressSet(address, NamespaceRelationId, namespaceId);
                                187                 :            468 :     EventTriggerCollectSimpleCommand(address, InvalidObjectAddress,
                                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                 :                :      */
  352 michael@paquier.xyz       197                 :            468 :     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                 :                :      */
 8035 tgl@sss.pgh.pa.us         206   [ +  +  +  +  :            623 :     foreach(parsetree_item, parsetree_list)
                                              +  + ]
                                207                 :                :     {
 6140                           208                 :            206 :         Node       *stmt = (Node *) lfirst(parsetree_item);
                                209                 :                :         PlannedStmt *wrapper;
                                210                 :                : 
                                211                 :                :         /* need to make a wrapper PlannedStmt */
 2647                           212                 :            206 :         wrapper = makeNode(PlannedStmt);
                                213                 :            206 :         wrapper->commandType = CMD_UTILITY;
                                214                 :            206 :         wrapper->canSetTag = false;
                                215                 :            206 :         wrapper->utilityStmt = stmt;
                                216                 :            206 :         wrapper->stmt_location = stmt_location;
                                217                 :            206 :         wrapper->stmt_len = stmt_len;
                                218                 :                : 
                                219                 :                :         /* do this step */
                                220                 :            206 :         ProcessUtility(wrapper,
                                221                 :                :                        queryString,
                                222                 :                :                        false,
                                223                 :                :                        PROCESS_UTILITY_SUBCOMMAND,
                                224                 :                :                        NULL,
                                225                 :                :                        NULL,
                                226                 :                :                        None_Receiver,
                                227                 :                :                        NULL);
                                228                 :                : 
                                229                 :                :         /* make sure later steps can see the object created here */
 6140                           230                 :            200 :         CommandCounterIncrement();
                                231                 :                :     }
                                232                 :                : 
                                233                 :                :     /*
                                234                 :                :      * Restore the GUC variable search_path we set above.
                                235                 :                :      */
  342 noah@leadboat.com         236                 :            417 :     AtEOXact_GUC(true, save_nestlevel);
                                237                 :                : 
                                238                 :                :     /* Reset current user and security context */
 5240 tgl@sss.pgh.pa.us         239                 :            417 :     SetUserIdAndSecContext(saved_uid, save_sec_context);
                                240                 :                : 
 4130 rhaas@postgresql.org      241                 :            417 :     return namespaceId;
                                242                 :                : }
                                243                 :                : 
                                244                 :                : 
                                245                 :                : /*
                                246                 :                :  * Rename schema
                                247                 :                :  */
                                248                 :                : ObjectAddress
 7597 peter_e@gmx.net           249                 :             10 : RenameSchema(const char *oldname, const char *newname)
                                250                 :                : {
                                251                 :                :     Oid         nspOid;
                                252                 :                :     HeapTuple   tup;
                                253                 :                :     Relation    rel;
                                254                 :                :     AclResult   aclresult;
                                255                 :                :     ObjectAddress address;
                                256                 :                :     Form_pg_namespace nspform;
                                257                 :                : 
 1910 andres@anarazel.de        258                 :             10 :     rel = table_open(NamespaceRelationId, RowExclusiveLock);
                                259                 :                : 
 5173 rhaas@postgresql.org      260                 :             10 :     tup = SearchSysCacheCopy1(NAMESPACENAME, CStringGetDatum(oldname));
 7597 peter_e@gmx.net           261         [ -  + ]:             10 :     if (!HeapTupleIsValid(tup))
 7597 peter_e@gmx.net           262         [ #  # ]:UBC           0 :         ereport(ERROR,
                                263                 :                :                 (errcode(ERRCODE_UNDEFINED_SCHEMA),
                                264                 :                :                  errmsg("schema \"%s\" does not exist", oldname)));
                                265                 :                : 
 1972 andres@anarazel.de        266                 :CBC          10 :     nspform = (Form_pg_namespace) GETSTRUCT(tup);
                                267                 :             10 :     nspOid = nspform->oid;
                                268                 :                : 
                                269                 :                :     /* make sure the new name doesn't exist */
 5001 rhaas@postgresql.org      270         [ -  + ]:             10 :     if (OidIsValid(get_namespace_oid(newname, true)))
 7597 peter_e@gmx.net           271         [ #  # ]:UBC           0 :         ereport(ERROR,
                                272                 :                :                 (errcode(ERRCODE_DUPLICATE_SCHEMA),
                                273                 :                :                  errmsg("schema \"%s\" already exists", newname)));
                                274                 :                : 
                                275                 :                :     /* must be owner */
  518 peter@eisentraut.org      276         [ -  + ]:CBC          10 :     if (!object_ownercheck(NamespaceRelationId, nspOid, GetUserId()))
 2325 peter_e@gmx.net           277                 :UBC           0 :         aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SCHEMA,
                                278                 :                :                        oldname);
                                279                 :                : 
                                280                 :                :     /* must have CREATE privilege on database */
  518 peter@eisentraut.org      281                 :CBC          10 :     aclresult = object_aclcheck(DatabaseRelationId, MyDatabaseId, GetUserId(), ACL_CREATE);
 7597 peter_e@gmx.net           282         [ -  + ]:             10 :     if (aclresult != ACLCHECK_OK)
 2325 peter_e@gmx.net           283                 :UBC           0 :         aclcheck_error(aclresult, OBJECT_DATABASE,
 7562 tgl@sss.pgh.pa.us         284                 :              0 :                        get_database_name(MyDatabaseId));
                                285                 :                : 
 7597 peter_e@gmx.net           286   [ +  -  -  + ]:CBC          10 :     if (!allowSystemTableMods && IsReservedName(newname))
 7576 tgl@sss.pgh.pa.us         287         [ #  # ]:UBC           0 :         ereport(ERROR,
                                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 */
 1972 andres@anarazel.de        293                 :CBC          10 :     namestrcpy(&nspform->nspname, newname);
 2630 alvherre@alvh.no-ip.      294                 :             10 :     CatalogTupleUpdate(rel, &tup->t_self, tup);
                                295                 :                : 
 1972 andres@anarazel.de        296         [ -  + ]:             10 :     InvokeObjectPostAlterHook(NamespaceRelationId, nspOid, 0);
                                297                 :                : 
 3330 alvherre@alvh.no-ip.      298                 :             10 :     ObjectAddressSet(address, NamespaceRelationId, nspOid);
                                299                 :                : 
 1910 andres@anarazel.de        300                 :             10 :     table_close(rel, NoLock);
 7597 peter_e@gmx.net           301                 :             10 :     heap_freetuple(tup);
                                302                 :                : 
 3330 alvherre@alvh.no-ip.      303                 :             10 :     return address;
                                304                 :                : }
                                305                 :                : 
                                306                 :                : void
  572 pg@bowt.ie                307                 :              3 : AlterSchemaOwner_oid(Oid schemaoid, Oid newOwnerId)
                                308                 :                : {
                                309                 :                :     HeapTuple   tup;
                                310                 :                :     Relation    rel;
                                311                 :                : 
 1910 andres@anarazel.de        312                 :              3 :     rel = table_open(NamespaceRelationId, RowExclusiveLock);
                                313                 :                : 
  572 pg@bowt.ie                314                 :              3 :     tup = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(schemaoid));
 6719 alvherre@alvh.no-ip.      315         [ -  + ]:              3 :     if (!HeapTupleIsValid(tup))
  572 pg@bowt.ie                316         [ #  # ]:UBC           0 :         elog(ERROR, "cache lookup failed for schema %u", schemaoid);
                                317                 :                : 
 6719 alvherre@alvh.no-ip.      318                 :CBC           3 :     AlterSchemaOwner_internal(tup, rel, newOwnerId);
                                319                 :                : 
                                320                 :              3 :     ReleaseSysCache(tup);
                                321                 :                : 
 1910 andres@anarazel.de        322                 :              3 :     table_close(rel, RowExclusiveLock);
 6719 alvherre@alvh.no-ip.      323                 :              3 : }
                                324                 :                : 
                                325                 :                : 
                                326                 :                : /*
                                327                 :                :  * Change schema owner
                                328                 :                :  */
                                329                 :                : ObjectAddress
 6865 tgl@sss.pgh.pa.us         330                 :             26 : AlterSchemaOwner(const char *name, Oid newOwnerId)
                                331                 :                : {
                                332                 :                :     Oid         nspOid;
                                333                 :                :     HeapTuple   tup;
                                334                 :                :     Relation    rel;
                                335                 :                :     ObjectAddress address;
                                336                 :                :     Form_pg_namespace nspform;
                                337                 :                : 
 1910 andres@anarazel.de        338                 :             26 :     rel = table_open(NamespaceRelationId, RowExclusiveLock);
                                339                 :                : 
 5173 rhaas@postgresql.org      340                 :             26 :     tup = SearchSysCache1(NAMESPACENAME, CStringGetDatum(name));
 7233 tgl@sss.pgh.pa.us         341         [ -  + ]:             26 :     if (!HeapTupleIsValid(tup))
 7233 tgl@sss.pgh.pa.us         342         [ #  # ]:UBC           0 :         ereport(ERROR,
                                343                 :                :                 (errcode(ERRCODE_UNDEFINED_SCHEMA),
                                344                 :                :                  errmsg("schema \"%s\" does not exist", name)));
                                345                 :                : 
 1972 andres@anarazel.de        346                 :CBC          26 :     nspform = (Form_pg_namespace) GETSTRUCT(tup);
                                347                 :             26 :     nspOid = nspform->oid;
                                348                 :                : 
 6719 alvherre@alvh.no-ip.      349                 :             26 :     AlterSchemaOwner_internal(tup, rel, newOwnerId);
                                350                 :                : 
 3330                           351                 :             26 :     ObjectAddressSet(address, NamespaceRelationId, nspOid);
                                352                 :                : 
 6719                           353                 :             26 :     ReleaseSysCache(tup);
                                354                 :                : 
 1910 andres@anarazel.de        355                 :             26 :     table_close(rel, RowExclusiveLock);
                                356                 :                : 
 3330 alvherre@alvh.no-ip.      357                 :             26 :     return address;
                                358                 :                : }
                                359                 :                : 
                                360                 :                : static void
 6719                           361                 :             29 : AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId)
                                362                 :                : {
                                363                 :                :     Form_pg_namespace nspForm;
                                364                 :                : 
                                365         [ -  + ]:             29 :     Assert(tup->t_tableOid == NamespaceRelationId);
                                366         [ -  + ]:             29 :     Assert(RelationGetRelid(rel) == NamespaceRelationId);
                                367                 :                : 
 7233 tgl@sss.pgh.pa.us         368                 :             29 :     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                 :                :      */
 6865                           374         [ +  + ]:             29 :     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 */
  518 peter@eisentraut.org      386         [ -  + ]:             20 :         if (!object_ownercheck(NamespaceRelationId, nspForm->oid, GetUserId()))
 2325 peter_e@gmx.net           387                 :UBC           0 :             aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SCHEMA,
 6719 alvherre@alvh.no-ip.      388                 :              0 :                            NameStr(nspForm->nspname));
                                389                 :                : 
                                390                 :                :         /* Must be able to become new owner */
  513 rhaas@postgresql.org      391                 :CBC          20 :         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                 :                :          */
  518 peter@eisentraut.org      402                 :             20 :         aclresult = object_aclcheck(DatabaseRelationId, MyDatabaseId, GetUserId(),
                                403                 :                :                                     ACL_CREATE);
 6849 tgl@sss.pgh.pa.us         404         [ -  + ]:             20 :         if (aclresult != ACLCHECK_OK)
 2325 peter_e@gmx.net           405                 :UBC           0 :             aclcheck_error(aclresult, OBJECT_DATABASE,
 6849 tgl@sss.pgh.pa.us         406                 :              0 :                            get_database_name(MyDatabaseId));
                                407                 :                : 
 5642 tgl@sss.pgh.pa.us         408                 :CBC          20 :         memset(repl_null, false, sizeof(repl_null));
                                409                 :             20 :         memset(repl_repl, false, sizeof(repl_repl));
                                410                 :                : 
                                411                 :             20 :         repl_repl[Anum_pg_namespace_nspowner - 1] = true;
 6865                           412                 :             20 :         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                 :                :          */
 7196                           418                 :             20 :         aclDatum = SysCacheGetAttr(NAMESPACENAME, tup,
                                419                 :                :                                    Anum_pg_namespace_nspacl,
                                420                 :                :                                    &isNull);
                                421         [ +  + ]:             20 :         if (!isNull)
                                422                 :                :         {
                                423                 :              2 :             newAcl = aclnewowner(DatumGetAclP(aclDatum),
                                424                 :                :                                  nspForm->nspowner, newOwnerId);
 5642                           425                 :              2 :             repl_repl[Anum_pg_namespace_nspacl - 1] = true;
 7196                           426                 :              2 :             repl_val[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(newAcl);
                                427                 :                :         }
                                428                 :                : 
 5642                           429                 :             20 :         newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null, repl_repl);
                                430                 :                : 
 2630 alvherre@alvh.no-ip.      431                 :             20 :         CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
                                432                 :                : 
 7196 tgl@sss.pgh.pa.us         433                 :             20 :         heap_freetuple(newtuple);
                                434                 :                : 
                                435                 :                :         /* Update owner dependency reference */
 1972 andres@anarazel.de        436                 :             20 :         changeDependencyOnOwner(NamespaceRelationId, nspForm->oid,
                                437                 :                :                                 newOwnerId);
                                438                 :                :     }
                                439                 :                : 
 4046 rhaas@postgresql.org      440         [ -  + ]:             29 :     InvokeObjectPostAlterHook(NamespaceRelationId,
                                441                 :                :                               nspForm->oid, 0);
 7233 tgl@sss.pgh.pa.us         442                 :             29 : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622