LCOV - code coverage report
Current view: top level - src/backend/commands - alter.c (source / functions) Hit Total Coverage
Test: PostgreSQL 16beta1 Lines: 311 355 87.6 %
Date: 2023-05-30 17:15:13 Functions: 10 10 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * alter.c
       4             :  *    Drivers for generic alter commands
       5             :  *
       6             :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/commands/alter.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #include "postgres.h"
      16             : 
      17             : #include "access/htup_details.h"
      18             : #include "access/relation.h"
      19             : #include "access/sysattr.h"
      20             : #include "access/table.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_collation.h"
      26             : #include "catalog/pg_conversion.h"
      27             : #include "catalog/pg_database_d.h"
      28             : #include "catalog/pg_event_trigger.h"
      29             : #include "catalog/pg_foreign_data_wrapper.h"
      30             : #include "catalog/pg_foreign_server.h"
      31             : #include "catalog/pg_language.h"
      32             : #include "catalog/pg_largeobject.h"
      33             : #include "catalog/pg_largeobject_metadata.h"
      34             : #include "catalog/pg_namespace.h"
      35             : #include "catalog/pg_opclass.h"
      36             : #include "catalog/pg_opfamily.h"
      37             : #include "catalog/pg_proc.h"
      38             : #include "catalog/pg_statistic_ext.h"
      39             : #include "catalog/pg_subscription.h"
      40             : #include "catalog/pg_ts_config.h"
      41             : #include "catalog/pg_ts_dict.h"
      42             : #include "catalog/pg_ts_parser.h"
      43             : #include "catalog/pg_ts_template.h"
      44             : #include "commands/alter.h"
      45             : #include "commands/collationcmds.h"
      46             : #include "commands/conversioncmds.h"
      47             : #include "commands/dbcommands.h"
      48             : #include "commands/defrem.h"
      49             : #include "commands/event_trigger.h"
      50             : #include "commands/extension.h"
      51             : #include "commands/policy.h"
      52             : #include "commands/proclang.h"
      53             : #include "commands/publicationcmds.h"
      54             : #include "commands/schemacmds.h"
      55             : #include "commands/subscriptioncmds.h"
      56             : #include "commands/tablecmds.h"
      57             : #include "commands/tablespace.h"
      58             : #include "commands/trigger.h"
      59             : #include "commands/typecmds.h"
      60             : #include "commands/user.h"
      61             : #include "miscadmin.h"
      62             : #include "parser/parse_func.h"
      63             : #include "replication/logicalworker.h"
      64             : #include "rewrite/rewriteDefine.h"
      65             : #include "tcop/utility.h"
      66             : #include "utils/builtins.h"
      67             : #include "utils/fmgroids.h"
      68             : #include "utils/lsyscache.h"
      69             : #include "utils/rel.h"
      70             : #include "utils/syscache.h"
      71             : 
      72             : static Oid  AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid);
      73             : 
      74             : /*
      75             :  * Raise an error to the effect that an object of the given name is already
      76             :  * present in the given namespace.
      77             :  */
      78             : static void
      79          24 : report_name_conflict(Oid classId, const char *name)
      80             : {
      81             :     char       *msgfmt;
      82             : 
      83          24 :     switch (classId)
      84             :     {
      85           6 :         case EventTriggerRelationId:
      86           6 :             msgfmt = gettext_noop("event trigger \"%s\" already exists");
      87           6 :             break;
      88           6 :         case ForeignDataWrapperRelationId:
      89           6 :             msgfmt = gettext_noop("foreign-data wrapper \"%s\" already exists");
      90           6 :             break;
      91           6 :         case ForeignServerRelationId:
      92           6 :             msgfmt = gettext_noop("server \"%s\" already exists");
      93           6 :             break;
      94           6 :         case LanguageRelationId:
      95           6 :             msgfmt = gettext_noop("language \"%s\" already exists");
      96           6 :             break;
      97           0 :         case PublicationRelationId:
      98           0 :             msgfmt = gettext_noop("publication \"%s\" already exists");
      99           0 :             break;
     100           0 :         case SubscriptionRelationId:
     101           0 :             msgfmt = gettext_noop("subscription \"%s\" already exists");
     102           0 :             break;
     103           0 :         default:
     104           0 :             elog(ERROR, "unsupported object class: %u", classId);
     105             :             break;
     106             :     }
     107             : 
     108          24 :     ereport(ERROR,
     109             :             (errcode(ERRCODE_DUPLICATE_OBJECT),
     110             :              errmsg(msgfmt, name)));
     111             : }
     112             : 
     113             : static void
     114          72 : report_namespace_conflict(Oid classId, const char *name, Oid nspOid)
     115             : {
     116             :     char       *msgfmt;
     117             : 
     118             :     Assert(OidIsValid(nspOid));
     119             : 
     120          72 :     switch (classId)
     121             :     {
     122          12 :         case ConversionRelationId:
     123             :             Assert(OidIsValid(nspOid));
     124          12 :             msgfmt = gettext_noop("conversion \"%s\" already exists in schema \"%s\"");
     125          12 :             break;
     126          12 :         case StatisticExtRelationId:
     127             :             Assert(OidIsValid(nspOid));
     128          12 :             msgfmt = gettext_noop("statistics object \"%s\" already exists in schema \"%s\"");
     129          12 :             break;
     130          12 :         case TSParserRelationId:
     131             :             Assert(OidIsValid(nspOid));
     132          12 :             msgfmt = gettext_noop("text search parser \"%s\" already exists in schema \"%s\"");
     133          12 :             break;
     134          12 :         case TSDictionaryRelationId:
     135             :             Assert(OidIsValid(nspOid));
     136          12 :             msgfmt = gettext_noop("text search dictionary \"%s\" already exists in schema \"%s\"");
     137          12 :             break;
     138          12 :         case TSTemplateRelationId:
     139             :             Assert(OidIsValid(nspOid));
     140          12 :             msgfmt = gettext_noop("text search template \"%s\" already exists in schema \"%s\"");
     141          12 :             break;
     142          12 :         case TSConfigRelationId:
     143             :             Assert(OidIsValid(nspOid));
     144          12 :             msgfmt = gettext_noop("text search configuration \"%s\" already exists in schema \"%s\"");
     145          12 :             break;
     146           0 :         default:
     147           0 :             elog(ERROR, "unsupported object class: %u", classId);
     148             :             break;
     149             :     }
     150             : 
     151          72 :     ereport(ERROR,
     152             :             (errcode(ERRCODE_DUPLICATE_OBJECT),
     153             :              errmsg(msgfmt, name, get_namespace_name(nspOid))));
     154             : }
     155             : 
     156             : /*
     157             :  * AlterObjectRename_internal
     158             :  *
     159             :  * Generic function to rename the given object, for simple cases (won't
     160             :  * work for tables, nor other cases where we need to do more than change
     161             :  * the name column of a single catalog entry).
     162             :  *
     163             :  * rel: catalog relation containing object (RowExclusiveLock'd by caller)
     164             :  * objectId: OID of object to be renamed
     165             :  * new_name: CString representation of new name
     166             :  */
     167             : static void
     168         404 : AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
     169             : {
     170         404 :     Oid         classId = RelationGetRelid(rel);
     171         404 :     int         oidCacheId = get_object_catcache_oid(classId);
     172         404 :     int         nameCacheId = get_object_catcache_name(classId);
     173         404 :     AttrNumber  Anum_name = get_object_attnum_name(classId);
     174         404 :     AttrNumber  Anum_namespace = get_object_attnum_namespace(classId);
     175         404 :     AttrNumber  Anum_owner = get_object_attnum_owner(classId);
     176             :     HeapTuple   oldtup;
     177             :     HeapTuple   newtup;
     178             :     Datum       datum;
     179             :     bool        isnull;
     180             :     Oid         namespaceId;
     181             :     Oid         ownerId;
     182             :     char       *old_name;
     183             :     AclResult   aclresult;
     184             :     Datum      *values;
     185             :     bool       *nulls;
     186             :     bool       *replaces;
     187             :     NameData    nameattrdata;
     188             : 
     189         404 :     oldtup = SearchSysCache1(oidCacheId, ObjectIdGetDatum(objectId));
     190         404 :     if (!HeapTupleIsValid(oldtup))
     191           0 :         elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"",
     192             :              objectId, RelationGetRelationName(rel));
     193             : 
     194         404 :     datum = heap_getattr(oldtup, Anum_name,
     195             :                          RelationGetDescr(rel), &isnull);
     196             :     Assert(!isnull);
     197         404 :     old_name = NameStr(*(DatumGetName(datum)));
     198             : 
     199             :     /* Get OID of namespace */
     200         404 :     if (Anum_namespace > 0)
     201             :     {
     202         270 :         datum = heap_getattr(oldtup, Anum_namespace,
     203             :                              RelationGetDescr(rel), &isnull);
     204             :         Assert(!isnull);
     205         270 :         namespaceId = DatumGetObjectId(datum);
     206             :     }
     207             :     else
     208         134 :         namespaceId = InvalidOid;
     209             : 
     210             :     /* Permission checks ... superusers can always do it */
     211         404 :     if (!superuser())
     212             :     {
     213             :         /* Fail if object does not have an explicit owner */
     214         246 :         if (Anum_owner <= 0)
     215           0 :             ereport(ERROR,
     216             :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
     217             :                      errmsg("must be superuser to rename %s",
     218             :                             getObjectDescriptionOids(classId, objectId))));
     219             : 
     220             :         /* Otherwise, must be owner of the existing object */
     221         246 :         datum = heap_getattr(oldtup, Anum_owner,
     222             :                              RelationGetDescr(rel), &isnull);
     223             :         Assert(!isnull);
     224         246 :         ownerId = DatumGetObjectId(datum);
     225             : 
     226         246 :         if (!has_privs_of_role(GetUserId(), DatumGetObjectId(ownerId)))
     227          72 :             aclcheck_error(ACLCHECK_NOT_OWNER, get_object_type(classId, objectId),
     228             :                            old_name);
     229             : 
     230             :         /* User must have CREATE privilege on the namespace */
     231         174 :         if (OidIsValid(namespaceId))
     232             :         {
     233         144 :             aclresult = object_aclcheck(NamespaceRelationId, namespaceId, GetUserId(),
     234             :                                         ACL_CREATE);
     235         144 :             if (aclresult != ACLCHECK_OK)
     236           0 :                 aclcheck_error(aclresult, OBJECT_SCHEMA,
     237           0 :                                get_namespace_name(namespaceId));
     238             :         }
     239             : 
     240         174 :         if (classId == SubscriptionRelationId)
     241             :         {
     242             :             Form_pg_subscription form;
     243             : 
     244             :             /* must have CREATE privilege on database */
     245          18 :             aclresult = object_aclcheck(DatabaseRelationId, MyDatabaseId,
     246             :                                         GetUserId(), ACL_CREATE);
     247          18 :             if (aclresult != ACLCHECK_OK)
     248           6 :                 aclcheck_error(aclresult, OBJECT_DATABASE,
     249           6 :                                get_database_name(MyDatabaseId));
     250             : 
     251             :             /*
     252             :              * Don't allow non-superuser modification of a subscription with
     253             :              * password_required=false.
     254             :              */
     255          12 :             form = (Form_pg_subscription) GETSTRUCT(oldtup);
     256          12 :             if (!form->subpasswordrequired && !superuser())
     257           0 :                 ereport(ERROR,
     258             :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
     259             :                          errmsg("password_required=false is superuser-only"),
     260             :                          errhint("Subscriptions with the password_required option set to false may only be created or modified by the superuser.")));
     261             :         }
     262             :     }
     263             : 
     264             :     /*
     265             :      * Check for duplicate name (more friendly than unique-index failure).
     266             :      * Since this is just a friendliness check, we can just skip it in cases
     267             :      * where there isn't suitable support.
     268             :      */
     269         326 :     if (classId == ProcedureRelationId)
     270             :     {
     271          72 :         Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(oldtup);
     272             : 
     273          72 :         IsThereFunctionInNamespace(new_name, proc->pronargs,
     274             :                                    &proc->proargtypes, proc->pronamespace);
     275             :     }
     276         254 :     else if (classId == CollationRelationId)
     277             :     {
     278          12 :         Form_pg_collation coll = (Form_pg_collation) GETSTRUCT(oldtup);
     279             : 
     280          12 :         IsThereCollationInNamespace(new_name, coll->collnamespace);
     281             :     }
     282         242 :     else if (classId == OperatorClassRelationId)
     283             :     {
     284          18 :         Form_pg_opclass opc = (Form_pg_opclass) GETSTRUCT(oldtup);
     285             : 
     286          18 :         IsThereOpClassInNamespace(new_name, opc->opcmethod,
     287             :                                   opc->opcnamespace);
     288             :     }
     289         224 :     else if (classId == OperatorFamilyRelationId)
     290             :     {
     291          18 :         Form_pg_opfamily opf = (Form_pg_opfamily) GETSTRUCT(oldtup);
     292             : 
     293          18 :         IsThereOpFamilyInNamespace(new_name, opf->opfmethod,
     294             :                                    opf->opfnamespace);
     295             :     }
     296         206 :     else if (classId == SubscriptionRelationId)
     297             :     {
     298          26 :         if (SearchSysCacheExists2(SUBSCRIPTIONNAME, MyDatabaseId,
     299             :                                   CStringGetDatum(new_name)))
     300           0 :             report_name_conflict(classId, new_name);
     301             : 
     302             :         /* Also enforce regression testing naming rules, if enabled */
     303             : #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
     304             :         if (strncmp(new_name, "regress_", 8) != 0)
     305             :             elog(WARNING, "subscriptions created by regression test cases should have names starting with \"regress_\"");
     306             : #endif
     307             : 
     308             :         /* Wake up related replication workers to handle this change quickly */
     309          26 :         LogicalRepWorkersWakeupAtCommit(objectId);
     310             :     }
     311         180 :     else if (nameCacheId >= 0)
     312             :     {
     313         180 :         if (OidIsValid(namespaceId))
     314             :         {
     315          96 :             if (SearchSysCacheExists2(nameCacheId,
     316             :                                       CStringGetDatum(new_name),
     317             :                                       ObjectIdGetDatum(namespaceId)))
     318          36 :                 report_namespace_conflict(classId, new_name, namespaceId);
     319             :         }
     320             :         else
     321             :         {
     322          84 :             if (SearchSysCacheExists1(nameCacheId,
     323             :                                       CStringGetDatum(new_name)))
     324          24 :                 report_name_conflict(classId, new_name);
     325             :         }
     326             :     }
     327             : 
     328             :     /* Build modified tuple */
     329         236 :     values = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(Datum));
     330         236 :     nulls = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
     331         236 :     replaces = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
     332         236 :     namestrcpy(&nameattrdata, new_name);
     333         236 :     values[Anum_name - 1] = NameGetDatum(&nameattrdata);
     334         236 :     replaces[Anum_name - 1] = true;
     335         236 :     newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel),
     336             :                                values, nulls, replaces);
     337             : 
     338             :     /* Perform actual update */
     339         236 :     CatalogTupleUpdate(rel, &oldtup->t_self, newtup);
     340             : 
     341         236 :     InvokeObjectPostAlterHook(classId, objectId, 0);
     342             : 
     343             :     /* Release memory */
     344         236 :     pfree(values);
     345         236 :     pfree(nulls);
     346         236 :     pfree(replaces);
     347         236 :     heap_freetuple(newtup);
     348             : 
     349         236 :     ReleaseSysCache(oldtup);
     350         236 : }
     351             : 
     352             : /*
     353             :  * Executes an ALTER OBJECT / RENAME TO statement.  Based on the object
     354             :  * type, the function appropriate to that type is executed.
     355             :  *
     356             :  * Return value is the address of the renamed object.
     357             :  */
     358             : ObjectAddress
     359        1482 : ExecRenameStmt(RenameStmt *stmt)
     360             : {
     361        1482 :     switch (stmt->renameType)
     362             :     {
     363          78 :         case OBJECT_TABCONSTRAINT:
     364             :         case OBJECT_DOMCONSTRAINT:
     365          78 :             return RenameConstraint(stmt);
     366             : 
     367           0 :         case OBJECT_DATABASE:
     368           0 :             return RenameDatabase(stmt->subname, stmt->newname);
     369             : 
     370          30 :         case OBJECT_ROLE:
     371          30 :             return RenameRole(stmt->subname, stmt->newname);
     372             : 
     373          20 :         case OBJECT_SCHEMA:
     374          20 :             return RenameSchema(stmt->subname, stmt->newname);
     375             : 
     376           6 :         case OBJECT_TABLESPACE:
     377           6 :             return RenameTableSpace(stmt->subname, stmt->newname);
     378             : 
     379         510 :         case OBJECT_TABLE:
     380             :         case OBJECT_SEQUENCE:
     381             :         case OBJECT_VIEW:
     382             :         case OBJECT_MATVIEW:
     383             :         case OBJECT_INDEX:
     384             :         case OBJECT_FOREIGN_TABLE:
     385         510 :             return RenameRelation(stmt);
     386             : 
     387         298 :         case OBJECT_COLUMN:
     388             :         case OBJECT_ATTRIBUTE:
     389         298 :             return renameatt(stmt);
     390             : 
     391          34 :         case OBJECT_RULE:
     392          34 :             return RenameRewriteRule(stmt->relation, stmt->subname,
     393          34 :                                      stmt->newname);
     394             : 
     395          40 :         case OBJECT_TRIGGER:
     396          40 :             return renametrig(stmt);
     397             : 
     398          18 :         case OBJECT_POLICY:
     399          18 :             return rename_policy(stmt);
     400             : 
     401          32 :         case OBJECT_DOMAIN:
     402             :         case OBJECT_TYPE:
     403          32 :             return RenameType(stmt);
     404             : 
     405         416 :         case OBJECT_AGGREGATE:
     406             :         case OBJECT_COLLATION:
     407             :         case OBJECT_CONVERSION:
     408             :         case OBJECT_EVENT_TRIGGER:
     409             :         case OBJECT_FDW:
     410             :         case OBJECT_FOREIGN_SERVER:
     411             :         case OBJECT_FUNCTION:
     412             :         case OBJECT_OPCLASS:
     413             :         case OBJECT_OPFAMILY:
     414             :         case OBJECT_LANGUAGE:
     415             :         case OBJECT_PROCEDURE:
     416             :         case OBJECT_ROUTINE:
     417             :         case OBJECT_STATISTIC_EXT:
     418             :         case OBJECT_TSCONFIGURATION:
     419             :         case OBJECT_TSDICTIONARY:
     420             :         case OBJECT_TSPARSER:
     421             :         case OBJECT_TSTEMPLATE:
     422             :         case OBJECT_PUBLICATION:
     423             :         case OBJECT_SUBSCRIPTION:
     424             :             {
     425             :                 ObjectAddress address;
     426             :                 Relation    catalog;
     427             :                 Relation    relation;
     428             : 
     429         416 :                 address = get_object_address(stmt->renameType,
     430             :                                              stmt->object,
     431             :                                              &relation,
     432             :                                              AccessExclusiveLock, false);
     433             :                 Assert(relation == NULL);
     434             : 
     435         404 :                 catalog = table_open(address.classId, RowExclusiveLock);
     436         404 :                 AlterObjectRename_internal(catalog,
     437             :                                            address.objectId,
     438         404 :                                            stmt->newname);
     439         236 :                 table_close(catalog, RowExclusiveLock);
     440             : 
     441         236 :                 return address;
     442             :             }
     443             : 
     444           0 :         default:
     445           0 :             elog(ERROR, "unrecognized rename stmt type: %d",
     446             :                  (int) stmt->renameType);
     447             :             return InvalidObjectAddress;    /* keep compiler happy */
     448             :     }
     449             : }
     450             : 
     451             : /*
     452             :  * Executes an ALTER OBJECT / [NO] DEPENDS ON EXTENSION statement.
     453             :  *
     454             :  * Return value is the address of the altered object.  refAddress is an output
     455             :  * argument which, if not null, receives the address of the object that the
     456             :  * altered object now depends on.
     457             :  */
     458             : ObjectAddress
     459          46 : ExecAlterObjectDependsStmt(AlterObjectDependsStmt *stmt, ObjectAddress *refAddress)
     460             : {
     461             :     ObjectAddress address;
     462             :     ObjectAddress refAddr;
     463             :     Relation    rel;
     464             : 
     465             :     address =
     466          46 :         get_object_address_rv(stmt->objectType, stmt->relation, (List *) stmt->object,
     467             :                               &rel, AccessExclusiveLock, false);
     468             : 
     469             :     /*
     470             :      * Verify that the user is entitled to run the command.
     471             :      *
     472             :      * We don't check any privileges on the extension, because that's not
     473             :      * needed.  The object owner is stipulating, by running this command, that
     474             :      * the extension owner can drop the object whenever they feel like it,
     475             :      * which is not considered a problem.
     476             :      */
     477          46 :     check_object_ownership(GetUserId(),
     478             :                            stmt->objectType, address, stmt->object, rel);
     479             : 
     480             :     /*
     481             :      * If a relation was involved, it would have been opened and locked. We
     482             :      * don't need the relation here, but we'll retain the lock until commit.
     483             :      */
     484          46 :     if (rel)
     485          34 :         table_close(rel, NoLock);
     486             : 
     487          46 :     refAddr = get_object_address(OBJECT_EXTENSION, (Node *) stmt->extname,
     488             :                                  &rel, AccessExclusiveLock, false);
     489             :     Assert(rel == NULL);
     490          46 :     if (refAddress)
     491          46 :         *refAddress = refAddr;
     492             : 
     493          46 :     if (stmt->remove)
     494             :     {
     495           8 :         deleteDependencyRecordsForSpecific(address.classId, address.objectId,
     496             :                                            DEPENDENCY_AUTO_EXTENSION,
     497             :                                            refAddr.classId, refAddr.objectId);
     498             :     }
     499             :     else
     500             :     {
     501             :         List       *currexts;
     502             : 
     503             :         /* Avoid duplicates */
     504          38 :         currexts = getAutoExtensionsOfObject(address.classId,
     505             :                                              address.objectId);
     506          38 :         if (!list_member_oid(currexts, refAddr.objectId))
     507          36 :             recordDependencyOn(&address, &refAddr, DEPENDENCY_AUTO_EXTENSION);
     508             :     }
     509             : 
     510          46 :     return address;
     511             : }
     512             : 
     513             : /*
     514             :  * Executes an ALTER OBJECT / SET SCHEMA statement.  Based on the object
     515             :  * type, the function appropriate to that type is executed.
     516             :  *
     517             :  * Return value is that of the altered object.
     518             :  *
     519             :  * oldSchemaAddr is an output argument which, if not NULL, is set to the object
     520             :  * address of the original schema.
     521             :  */
     522             : ObjectAddress
     523         382 : ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt,
     524             :                           ObjectAddress *oldSchemaAddr)
     525             : {
     526             :     ObjectAddress address;
     527             :     Oid         oldNspOid;
     528             : 
     529         382 :     switch (stmt->objectType)
     530             :     {
     531           6 :         case OBJECT_EXTENSION:
     532           6 :             address = AlterExtensionNamespace(strVal(stmt->object), stmt->newschema,
     533             :                                               oldSchemaAddr ? &oldNspOid : NULL);
     534           4 :             break;
     535             : 
     536          98 :         case OBJECT_FOREIGN_TABLE:
     537             :         case OBJECT_SEQUENCE:
     538             :         case OBJECT_TABLE:
     539             :         case OBJECT_VIEW:
     540             :         case OBJECT_MATVIEW:
     541          98 :             address = AlterTableNamespace(stmt,
     542             :                                           oldSchemaAddr ? &oldNspOid : NULL);
     543          96 :             break;
     544             : 
     545          18 :         case OBJECT_DOMAIN:
     546             :         case OBJECT_TYPE:
     547          18 :             address = AlterTypeNamespace(castNode(List, stmt->object), stmt->newschema,
     548             :                                          stmt->objectType,
     549             :                                          oldSchemaAddr ? &oldNspOid : NULL);
     550          18 :             break;
     551             : 
     552             :             /* generic code path */
     553         260 :         case OBJECT_AGGREGATE:
     554             :         case OBJECT_COLLATION:
     555             :         case OBJECT_CONVERSION:
     556             :         case OBJECT_FUNCTION:
     557             :         case OBJECT_OPERATOR:
     558             :         case OBJECT_OPCLASS:
     559             :         case OBJECT_OPFAMILY:
     560             :         case OBJECT_PROCEDURE:
     561             :         case OBJECT_ROUTINE:
     562             :         case OBJECT_STATISTIC_EXT:
     563             :         case OBJECT_TSCONFIGURATION:
     564             :         case OBJECT_TSDICTIONARY:
     565             :         case OBJECT_TSPARSER:
     566             :         case OBJECT_TSTEMPLATE:
     567             :             {
     568             :                 Relation    catalog;
     569             :                 Relation    relation;
     570             :                 Oid         classId;
     571             :                 Oid         nspOid;
     572             : 
     573         260 :                 address = get_object_address(stmt->objectType,
     574             :                                              stmt->object,
     575             :                                              &relation,
     576             :                                              AccessExclusiveLock,
     577             :                                              false);
     578             :                 Assert(relation == NULL);
     579         254 :                 classId = address.classId;
     580         254 :                 catalog = table_open(classId, RowExclusiveLock);
     581         254 :                 nspOid = LookupCreationNamespace(stmt->newschema);
     582             : 
     583         254 :                 oldNspOid = AlterObjectNamespace_internal(catalog, address.objectId,
     584             :                                                           nspOid);
     585         140 :                 table_close(catalog, RowExclusiveLock);
     586             :             }
     587         140 :             break;
     588             : 
     589           0 :         default:
     590           0 :             elog(ERROR, "unrecognized AlterObjectSchemaStmt type: %d",
     591             :                  (int) stmt->objectType);
     592             :             return InvalidObjectAddress;    /* keep compiler happy */
     593             :     }
     594             : 
     595         258 :     if (oldSchemaAddr)
     596         258 :         ObjectAddressSet(*oldSchemaAddr, NamespaceRelationId, oldNspOid);
     597             : 
     598         258 :     return address;
     599             : }
     600             : 
     601             : /*
     602             :  * Change an object's namespace given its classOid and object Oid.
     603             :  *
     604             :  * Objects that don't have a namespace should be ignored.
     605             :  *
     606             :  * This function is currently used only by ALTER EXTENSION SET SCHEMA,
     607             :  * so it only needs to cover object types that can be members of an
     608             :  * extension, and it doesn't have to deal with certain special cases
     609             :  * such as not wanting to process array types --- those should never
     610             :  * be direct members of an extension anyway.  Nonetheless, we insist
     611             :  * on listing all OCLASS types in the switch.
     612             :  *
     613             :  * Returns the OID of the object's previous namespace, or InvalidOid if
     614             :  * object doesn't have a schema.
     615             :  */
     616             : Oid
     617           6 : AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid,
     618             :                          ObjectAddresses *objsMoved)
     619             : {
     620           6 :     Oid         oldNspOid = InvalidOid;
     621             :     ObjectAddress dep;
     622             : 
     623           6 :     dep.classId = classId;
     624           6 :     dep.objectId = objid;
     625           6 :     dep.objectSubId = 0;
     626             : 
     627           6 :     switch (getObjectClass(&dep))
     628             :     {
     629           0 :         case OCLASS_CLASS:
     630             :             {
     631             :                 Relation    rel;
     632             : 
     633           0 :                 rel = relation_open(objid, AccessExclusiveLock);
     634           0 :                 oldNspOid = RelationGetNamespace(rel);
     635             : 
     636           0 :                 AlterTableNamespaceInternal(rel, oldNspOid, nspOid, objsMoved);
     637             : 
     638           0 :                 relation_close(rel, NoLock);
     639           0 :                 break;
     640             :             }
     641             : 
     642           0 :         case OCLASS_TYPE:
     643           0 :             oldNspOid = AlterTypeNamespace_oid(objid, nspOid, objsMoved);
     644           0 :             break;
     645             : 
     646           6 :         case OCLASS_PROC:
     647             :         case OCLASS_COLLATION:
     648             :         case OCLASS_CONVERSION:
     649             :         case OCLASS_OPERATOR:
     650             :         case OCLASS_OPCLASS:
     651             :         case OCLASS_OPFAMILY:
     652             :         case OCLASS_STATISTIC_EXT:
     653             :         case OCLASS_TSPARSER:
     654             :         case OCLASS_TSDICT:
     655             :         case OCLASS_TSTEMPLATE:
     656             :         case OCLASS_TSCONFIG:
     657             :             {
     658             :                 Relation    catalog;
     659             : 
     660           6 :                 catalog = table_open(classId, RowExclusiveLock);
     661             : 
     662           6 :                 oldNspOid = AlterObjectNamespace_internal(catalog, objid,
     663             :                                                           nspOid);
     664             : 
     665           6 :                 table_close(catalog, RowExclusiveLock);
     666             :             }
     667           6 :             break;
     668             : 
     669           0 :         case OCLASS_CAST:
     670             :         case OCLASS_CONSTRAINT:
     671             :         case OCLASS_DEFAULT:
     672             :         case OCLASS_LANGUAGE:
     673             :         case OCLASS_LARGEOBJECT:
     674             :         case OCLASS_AM:
     675             :         case OCLASS_AMOP:
     676             :         case OCLASS_AMPROC:
     677             :         case OCLASS_REWRITE:
     678             :         case OCLASS_TRIGGER:
     679             :         case OCLASS_SCHEMA:
     680             :         case OCLASS_ROLE:
     681             :         case OCLASS_ROLE_MEMBERSHIP:
     682             :         case OCLASS_DATABASE:
     683             :         case OCLASS_TBLSPACE:
     684             :         case OCLASS_FDW:
     685             :         case OCLASS_FOREIGN_SERVER:
     686             :         case OCLASS_USER_MAPPING:
     687             :         case OCLASS_DEFACL:
     688             :         case OCLASS_EXTENSION:
     689             :         case OCLASS_EVENT_TRIGGER:
     690             :         case OCLASS_PARAMETER_ACL:
     691             :         case OCLASS_POLICY:
     692             :         case OCLASS_PUBLICATION:
     693             :         case OCLASS_PUBLICATION_NAMESPACE:
     694             :         case OCLASS_PUBLICATION_REL:
     695             :         case OCLASS_SUBSCRIPTION:
     696             :         case OCLASS_TRANSFORM:
     697             :             /* ignore object types that don't have schema-qualified names */
     698           0 :             break;
     699             : 
     700             :             /*
     701             :              * There's intentionally no default: case here; we want the
     702             :              * compiler to warn if a new OCLASS hasn't been handled above.
     703             :              */
     704             :     }
     705             : 
     706           6 :     return oldNspOid;
     707             : }
     708             : 
     709             : /*
     710             :  * Generic function to change the namespace of a given object, for simple
     711             :  * cases (won't work for tables, nor other cases where we need to do more
     712             :  * than change the namespace column of a single catalog entry).
     713             :  *
     714             :  * rel: catalog relation containing object (RowExclusiveLock'd by caller)
     715             :  * objid: OID of object to change the namespace of
     716             :  * nspOid: OID of new namespace
     717             :  *
     718             :  * Returns the OID of the object's previous namespace.
     719             :  */
     720             : static Oid
     721         260 : AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid)
     722             : {
     723         260 :     Oid         classId = RelationGetRelid(rel);
     724         260 :     int         oidCacheId = get_object_catcache_oid(classId);
     725         260 :     int         nameCacheId = get_object_catcache_name(classId);
     726         260 :     AttrNumber  Anum_name = get_object_attnum_name(classId);
     727         260 :     AttrNumber  Anum_namespace = get_object_attnum_namespace(classId);
     728         260 :     AttrNumber  Anum_owner = get_object_attnum_owner(classId);
     729             :     Oid         oldNspOid;
     730             :     Datum       name,
     731             :                 namespace;
     732             :     bool        isnull;
     733             :     HeapTuple   tup,
     734             :                 newtup;
     735             :     Datum      *values;
     736             :     bool       *nulls;
     737             :     bool       *replaces;
     738             : 
     739         260 :     tup = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objid));
     740         260 :     if (!HeapTupleIsValid(tup)) /* should not happen */
     741           0 :         elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"",
     742             :              objid, RelationGetRelationName(rel));
     743             : 
     744         260 :     name = heap_getattr(tup, Anum_name, RelationGetDescr(rel), &isnull);
     745             :     Assert(!isnull);
     746         260 :     namespace = heap_getattr(tup, Anum_namespace, RelationGetDescr(rel),
     747             :                              &isnull);
     748             :     Assert(!isnull);
     749         260 :     oldNspOid = DatumGetObjectId(namespace);
     750             : 
     751             :     /*
     752             :      * If the object is already in the correct namespace, we don't need to do
     753             :      * anything except fire the object access hook.
     754             :      */
     755         260 :     if (oldNspOid == nspOid)
     756             :     {
     757           6 :         InvokeObjectPostAlterHook(classId, objid, 0);
     758           6 :         return oldNspOid;
     759             :     }
     760             : 
     761             :     /* Check basic namespace related issues */
     762         254 :     CheckSetNamespace(oldNspOid, nspOid);
     763             : 
     764             :     /* Permission checks ... superusers can always do it */
     765         254 :     if (!superuser())
     766             :     {
     767             :         Datum       owner;
     768             :         Oid         ownerId;
     769             :         AclResult   aclresult;
     770             : 
     771             :         /* Fail if object does not have an explicit owner */
     772         156 :         if (Anum_owner <= 0)
     773           0 :             ereport(ERROR,
     774             :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
     775             :                      errmsg("must be superuser to set schema of %s",
     776             :                             getObjectDescriptionOids(classId, objid))));
     777             : 
     778             :         /* Otherwise, must be owner of the existing object */
     779         156 :         owner = heap_getattr(tup, Anum_owner, RelationGetDescr(rel), &isnull);
     780             :         Assert(!isnull);
     781         156 :         ownerId = DatumGetObjectId(owner);
     782             : 
     783         156 :         if (!has_privs_of_role(GetUserId(), ownerId))
     784          54 :             aclcheck_error(ACLCHECK_NOT_OWNER, get_object_type(classId, objid),
     785          54 :                            NameStr(*(DatumGetName(name))));
     786             : 
     787             :         /* User must have CREATE privilege on new namespace */
     788         102 :         aclresult = object_aclcheck(NamespaceRelationId, nspOid, GetUserId(), ACL_CREATE);
     789         102 :         if (aclresult != ACLCHECK_OK)
     790           0 :             aclcheck_error(aclresult, OBJECT_SCHEMA,
     791           0 :                            get_namespace_name(nspOid));
     792             :     }
     793             : 
     794             :     /*
     795             :      * Check for duplicate name (more friendly than unique-index failure).
     796             :      * Since this is just a friendliness check, we can just skip it in cases
     797             :      * where there isn't suitable support.
     798             :      */
     799         200 :     if (classId == ProcedureRelationId)
     800             :     {
     801          44 :         Form_pg_proc proc = (Form_pg_proc) GETSTRUCT(tup);
     802             : 
     803          44 :         IsThereFunctionInNamespace(NameStr(proc->proname), proc->pronargs,
     804             :                                    &proc->proargtypes, nspOid);
     805             :     }
     806         156 :     else if (classId == CollationRelationId)
     807             :     {
     808           6 :         Form_pg_collation coll = (Form_pg_collation) GETSTRUCT(tup);
     809             : 
     810           6 :         IsThereCollationInNamespace(NameStr(coll->collname), nspOid);
     811             :     }
     812         150 :     else if (classId == OperatorClassRelationId)
     813             :     {
     814          18 :         Form_pg_opclass opc = (Form_pg_opclass) GETSTRUCT(tup);
     815             : 
     816          18 :         IsThereOpClassInNamespace(NameStr(opc->opcname),
     817             :                                   opc->opcmethod, nspOid);
     818             :     }
     819         132 :     else if (classId == OperatorFamilyRelationId)
     820             :     {
     821          18 :         Form_pg_opfamily opf = (Form_pg_opfamily) GETSTRUCT(tup);
     822             : 
     823          18 :         IsThereOpFamilyInNamespace(NameStr(opf->opfname),
     824             :                                    opf->opfmethod, nspOid);
     825             :     }
     826         216 :     else if (nameCacheId >= 0 &&
     827         102 :              SearchSysCacheExists2(nameCacheId, name,
     828             :                                    ObjectIdGetDatum(nspOid)))
     829          36 :         report_namespace_conflict(classId,
     830          36 :                                   NameStr(*(DatumGetName(name))),
     831             :                                   nspOid);
     832             : 
     833             :     /* Build modified tuple */
     834         140 :     values = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(Datum));
     835         140 :     nulls = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
     836         140 :     replaces = palloc0(RelationGetNumberOfAttributes(rel) * sizeof(bool));
     837         140 :     values[Anum_namespace - 1] = ObjectIdGetDatum(nspOid);
     838         140 :     replaces[Anum_namespace - 1] = true;
     839         140 :     newtup = heap_modify_tuple(tup, RelationGetDescr(rel),
     840             :                                values, nulls, replaces);
     841             : 
     842             :     /* Perform actual update */
     843         140 :     CatalogTupleUpdate(rel, &tup->t_self, newtup);
     844             : 
     845             :     /* Release memory */
     846         140 :     pfree(values);
     847         140 :     pfree(nulls);
     848         140 :     pfree(replaces);
     849             : 
     850             :     /* update dependencies to point to the new schema */
     851         140 :     changeDependencyFor(classId, objid,
     852             :                         NamespaceRelationId, oldNspOid, nspOid);
     853             : 
     854         140 :     InvokeObjectPostAlterHook(classId, objid, 0);
     855             : 
     856         140 :     return oldNspOid;
     857             : }
     858             : 
     859             : /*
     860             :  * Executes an ALTER OBJECT / OWNER TO statement.  Based on the object
     861             :  * type, the function appropriate to that type is executed.
     862             :  */
     863             : ObjectAddress
     864        2012 : ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
     865             : {
     866        2012 :     Oid         newowner = get_rolespec_oid(stmt->newowner, false);
     867             : 
     868        2000 :     switch (stmt->objectType)
     869             :     {
     870          36 :         case OBJECT_DATABASE:
     871          36 :             return AlterDatabaseOwner(strVal(stmt->object), newowner);
     872             : 
     873          52 :         case OBJECT_SCHEMA:
     874          52 :             return AlterSchemaOwner(strVal(stmt->object), newowner);
     875             : 
     876          96 :         case OBJECT_TYPE:
     877             :         case OBJECT_DOMAIN:     /* same as TYPE */
     878          96 :             return AlterTypeOwner(castNode(List, stmt->object), newowner, stmt->objectType);
     879             :             break;
     880             : 
     881          20 :         case OBJECT_FDW:
     882          20 :             return AlterForeignDataWrapperOwner(strVal(stmt->object),
     883             :                                                 newowner);
     884             : 
     885          68 :         case OBJECT_FOREIGN_SERVER:
     886          68 :             return AlterForeignServerOwner(strVal(stmt->object),
     887             :                                            newowner);
     888             : 
     889          12 :         case OBJECT_EVENT_TRIGGER:
     890          12 :             return AlterEventTriggerOwner(strVal(stmt->object),
     891             :                                           newowner);
     892             : 
     893          24 :         case OBJECT_PUBLICATION:
     894          24 :             return AlterPublicationOwner(strVal(stmt->object),
     895             :                                          newowner);
     896             : 
     897          12 :         case OBJECT_SUBSCRIPTION:
     898          12 :             return AlterSubscriptionOwner(strVal(stmt->object),
     899             :                                           newowner);
     900             : 
     901             :             /* Generic cases */
     902        1680 :         case OBJECT_AGGREGATE:
     903             :         case OBJECT_COLLATION:
     904             :         case OBJECT_CONVERSION:
     905             :         case OBJECT_FUNCTION:
     906             :         case OBJECT_LANGUAGE:
     907             :         case OBJECT_LARGEOBJECT:
     908             :         case OBJECT_OPERATOR:
     909             :         case OBJECT_OPCLASS:
     910             :         case OBJECT_OPFAMILY:
     911             :         case OBJECT_PROCEDURE:
     912             :         case OBJECT_ROUTINE:
     913             :         case OBJECT_STATISTIC_EXT:
     914             :         case OBJECT_TABLESPACE:
     915             :         case OBJECT_TSDICTIONARY:
     916             :         case OBJECT_TSCONFIGURATION:
     917             :             {
     918             :                 Relation    catalog;
     919             :                 Relation    relation;
     920             :                 Oid         classId;
     921             :                 ObjectAddress address;
     922             : 
     923        1680 :                 address = get_object_address(stmt->objectType,
     924             :                                              stmt->object,
     925             :                                              &relation,
     926             :                                              AccessExclusiveLock,
     927             :                                              false);
     928             :                 Assert(relation == NULL);
     929        1672 :                 classId = address.classId;
     930             : 
     931             :                 /*
     932             :                  * XXX - get_object_address returns Oid of pg_largeobject
     933             :                  * catalog for OBJECT_LARGEOBJECT because of historical
     934             :                  * reasons.  Fix up it here.
     935             :                  */
     936        1672 :                 if (classId == LargeObjectRelationId)
     937          12 :                     classId = LargeObjectMetadataRelationId;
     938             : 
     939        1672 :                 catalog = table_open(classId, RowExclusiveLock);
     940             : 
     941        1672 :                 AlterObjectOwner_internal(catalog, address.objectId, newowner);
     942        1498 :                 table_close(catalog, RowExclusiveLock);
     943             : 
     944        1498 :                 return address;
     945             :             }
     946             :             break;
     947             : 
     948           0 :         default:
     949           0 :             elog(ERROR, "unrecognized AlterOwnerStmt type: %d",
     950             :                  (int) stmt->objectType);
     951             :             return InvalidObjectAddress;    /* keep compiler happy */
     952             :     }
     953             : }
     954             : 
     955             : /*
     956             :  * Generic function to change the ownership of a given object, for simple
     957             :  * cases (won't work for tables, nor other cases where we need to do more than
     958             :  * change the ownership column of a single catalog entry).
     959             :  *
     960             :  * rel: catalog relation containing object (RowExclusiveLock'd by caller)
     961             :  * objectId: OID of object to change the ownership of
     962             :  * new_ownerId: OID of new object owner
     963             :  */
     964             : void
     965        1678 : AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
     966             : {
     967        1678 :     Oid         classId = RelationGetRelid(rel);
     968        1678 :     AttrNumber  Anum_oid = get_object_attnum_oid(classId);
     969        1678 :     AttrNumber  Anum_owner = get_object_attnum_owner(classId);
     970        1678 :     AttrNumber  Anum_namespace = get_object_attnum_namespace(classId);
     971        1678 :     AttrNumber  Anum_acl = get_object_attnum_acl(classId);
     972        1678 :     AttrNumber  Anum_name = get_object_attnum_name(classId);
     973             :     HeapTuple   oldtup;
     974             :     Datum       datum;
     975             :     bool        isnull;
     976             :     Oid         old_ownerId;
     977        1678 :     Oid         namespaceId = InvalidOid;
     978             : 
     979        1678 :     oldtup = get_catalog_object_by_oid(rel, Anum_oid, objectId);
     980        1678 :     if (oldtup == NULL)
     981           0 :         elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"",
     982             :              objectId, RelationGetRelationName(rel));
     983             : 
     984        1678 :     datum = heap_getattr(oldtup, Anum_owner,
     985             :                          RelationGetDescr(rel), &isnull);
     986             :     Assert(!isnull);
     987        1678 :     old_ownerId = DatumGetObjectId(datum);
     988             : 
     989        1678 :     if (Anum_namespace != InvalidAttrNumber)
     990             :     {
     991        1012 :         datum = heap_getattr(oldtup, Anum_namespace,
     992             :                              RelationGetDescr(rel), &isnull);
     993             :         Assert(!isnull);
     994        1012 :         namespaceId = DatumGetObjectId(datum);
     995             :     }
     996             : 
     997        1678 :     if (old_ownerId != new_ownerId)
     998             :     {
     999             :         AttrNumber  nattrs;
    1000             :         HeapTuple   newtup;
    1001             :         Datum      *values;
    1002             :         bool       *nulls;
    1003             :         bool       *replaces;
    1004             : 
    1005             :         /* Superusers can bypass permission checks */
    1006         352 :         if (!superuser())
    1007             :         {
    1008             :             /* must be owner */
    1009         234 :             if (!has_privs_of_role(GetUserId(), old_ownerId))
    1010             :             {
    1011             :                 char       *objname;
    1012             :                 char        namebuf[NAMEDATALEN];
    1013             : 
    1014          60 :                 if (Anum_name != InvalidAttrNumber)
    1015             :                 {
    1016          60 :                     datum = heap_getattr(oldtup, Anum_name,
    1017             :                                          RelationGetDescr(rel), &isnull);
    1018             :                     Assert(!isnull);
    1019          60 :                     objname = NameStr(*DatumGetName(datum));
    1020             :                 }
    1021             :                 else
    1022             :                 {
    1023           0 :                     snprintf(namebuf, sizeof(namebuf), "%u", objectId);
    1024           0 :                     objname = namebuf;
    1025             :                 }
    1026          60 :                 aclcheck_error(ACLCHECK_NOT_OWNER, get_object_type(classId, objectId),
    1027             :                                objname);
    1028             :             }
    1029             :             /* Must be able to become new owner */
    1030         174 :             check_can_set_role(GetUserId(), new_ownerId);
    1031             : 
    1032             :             /* New owner must have CREATE privilege on namespace */
    1033          60 :             if (OidIsValid(namespaceId))
    1034             :             {
    1035             :                 AclResult   aclresult;
    1036             : 
    1037          54 :                 aclresult = object_aclcheck(NamespaceRelationId, namespaceId, new_ownerId,
    1038             :                                             ACL_CREATE);
    1039          54 :                 if (aclresult != ACLCHECK_OK)
    1040           0 :                     aclcheck_error(aclresult, OBJECT_SCHEMA,
    1041           0 :                                    get_namespace_name(namespaceId));
    1042             :             }
    1043             :         }
    1044             : 
    1045             :         /* Build a modified tuple */
    1046         178 :         nattrs = RelationGetNumberOfAttributes(rel);
    1047         178 :         values = palloc0(nattrs * sizeof(Datum));
    1048         178 :         nulls = palloc0(nattrs * sizeof(bool));
    1049         178 :         replaces = palloc0(nattrs * sizeof(bool));
    1050         178 :         values[Anum_owner - 1] = ObjectIdGetDatum(new_ownerId);
    1051         178 :         replaces[Anum_owner - 1] = true;
    1052             : 
    1053             :         /*
    1054             :          * Determine the modified ACL for the new owner.  This is only
    1055             :          * necessary when the ACL is non-null.
    1056             :          */
    1057         178 :         if (Anum_acl != InvalidAttrNumber)
    1058             :         {
    1059          82 :             datum = heap_getattr(oldtup,
    1060             :                                  Anum_acl, RelationGetDescr(rel), &isnull);
    1061          82 :             if (!isnull)
    1062             :             {
    1063             :                 Acl        *newAcl;
    1064             : 
    1065           2 :                 newAcl = aclnewowner(DatumGetAclP(datum),
    1066             :                                      old_ownerId, new_ownerId);
    1067           2 :                 values[Anum_acl - 1] = PointerGetDatum(newAcl);
    1068           2 :                 replaces[Anum_acl - 1] = true;
    1069             :             }
    1070             :         }
    1071             : 
    1072         178 :         newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel),
    1073             :                                    values, nulls, replaces);
    1074             : 
    1075             :         /* Perform actual update */
    1076         178 :         CatalogTupleUpdate(rel, &newtup->t_self, newtup);
    1077             : 
    1078             :         /* Update owner dependency reference */
    1079         178 :         if (classId == LargeObjectMetadataRelationId)
    1080           6 :             classId = LargeObjectRelationId;
    1081         178 :         changeDependencyOnOwner(classId, objectId, new_ownerId);
    1082             : 
    1083             :         /* Release memory */
    1084         178 :         pfree(values);
    1085         178 :         pfree(nulls);
    1086         178 :         pfree(replaces);
    1087             :     }
    1088             : 
    1089        1504 :     InvokeObjectPostAlterHook(classId, objectId, 0);
    1090        1504 : }

Generated by: LCOV version 1.14