8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.165 2005/08/01 04:03:55 tgl Exp $
11
+ * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.166 2005/08/04 01:09:28 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -238,7 +238,7 @@ static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
238
238
const char * colName , TypeName * typename );
239
239
static void ATPostAlterTypeCleanup (List * * wqueue , AlteredTableInfo * tab );
240
240
static void ATPostAlterTypeParse (char * cmd , List * * wqueue );
241
- static void ATExecChangeOwner (Oid relationOid , Oid newOwnerId );
241
+ static void ATExecChangeOwner (Oid relationOid , Oid newOwnerId , bool recursing );
242
242
static void change_owner_recurse_to_sequences (Oid relationOid ,
243
243
Oid newOwnerId );
244
244
static void ATExecClusterOn (Relation rel , const char * indexName );
@@ -2141,7 +2141,8 @@ ATExecCmd(AlteredTableInfo *tab, Relation rel, AlterTableCmd *cmd)
2141
2141
break ;
2142
2142
case AT_ChangeOwner : /* ALTER OWNER */
2143
2143
ATExecChangeOwner (RelationGetRelid (rel ),
2144
- get_roleid_checked (cmd -> name ));
2144
+ get_roleid_checked (cmd -> name ),
2145
+ false);
2145
2146
break ;
2146
2147
case AT_ClusterOn : /* CLUSTER ON */
2147
2148
ATExecClusterOn (rel , cmd -> name );
@@ -5238,9 +5239,15 @@ ATPostAlterTypeParse(char *cmd, List **wqueue)
5238
5239
5239
5240
/*
5240
5241
* ALTER TABLE OWNER
5242
+ *
5243
+ * recursing is true if we are recursing from a table to its indexes or
5244
+ * toast table. We don't allow the ownership of those things to be
5245
+ * changed separately from the parent table. Also, we can skip permission
5246
+ * checks (this is necessary not just an optimization, else we'd fail to
5247
+ * handle toast tables properly).
5241
5248
*/
5242
5249
static void
5243
- ATExecChangeOwner (Oid relationOid , Oid newOwnerId )
5250
+ ATExecChangeOwner (Oid relationOid , Oid newOwnerId , bool recursing )
5244
5251
{
5245
5252
Relation target_rel ;
5246
5253
Relation class_rel ;
@@ -5267,16 +5274,19 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId)
5267
5274
switch (tuple_class -> relkind )
5268
5275
{
5269
5276
case RELKIND_RELATION :
5270
- case RELKIND_INDEX :
5271
5277
case RELKIND_VIEW :
5272
5278
case RELKIND_SEQUENCE :
5273
- case RELKIND_TOASTVALUE :
5274
5279
/* ok to change owner */
5275
5280
break ;
5281
+ case RELKIND_INDEX :
5282
+ case RELKIND_TOASTVALUE :
5283
+ if (recursing )
5284
+ break ;
5285
+ /* FALL THRU */
5276
5286
default :
5277
5287
ereport (ERROR ,
5278
5288
(errcode (ERRCODE_WRONG_OBJECT_TYPE ),
5279
- errmsg ("\"%s\" is not a table, TOAST table, index, view, or sequence" ,
5289
+ errmsg ("\"%s\" is not a table, view, or sequence" ,
5280
5290
NameStr (tuple_class -> relname ))));
5281
5291
}
5282
5292
@@ -5293,23 +5303,28 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId)
5293
5303
Datum aclDatum ;
5294
5304
bool isNull ;
5295
5305
HeapTuple newtuple ;
5296
- Oid namespaceOid = tuple_class -> relnamespace ;
5297
- AclResult aclresult ;
5298
-
5299
- /* Otherwise, must be owner of the existing object */
5300
- if (!pg_class_ownercheck (relationOid ,GetUserId ()))
5301
- aclcheck_error (ACLCHECK_NOT_OWNER , ACL_KIND_CLASS ,
5302
- RelationGetRelationName (target_rel ));
5303
5306
5304
- /* Must be able to become new owner */
5305
- check_is_member_of_role (GetUserId (), newOwnerId );
5306
-
5307
- /* New owner must have CREATE privilege on namespace */
5308
- aclresult = pg_namespace_aclcheck (namespaceOid , newOwnerId ,
5309
- ACL_CREATE );
5310
- if (aclresult != ACLCHECK_OK )
5311
- aclcheck_error (aclresult , ACL_KIND_NAMESPACE ,
5312
- get_namespace_name (namespaceOid ));
5307
+ /* skip permission checks when recursing to index or toast table */
5308
+ if (!recursing )
5309
+ {
5310
+ Oid namespaceOid = tuple_class -> relnamespace ;
5311
+ AclResult aclresult ;
5312
+
5313
+ /* Otherwise, must be owner of the existing object */
5314
+ if (!pg_class_ownercheck (relationOid ,GetUserId ()))
5315
+ aclcheck_error (ACLCHECK_NOT_OWNER , ACL_KIND_CLASS ,
5316
+ RelationGetRelationName (target_rel ));
5317
+
5318
+ /* Must be able to become new owner */
5319
+ check_is_member_of_role (GetUserId (), newOwnerId );
5320
+
5321
+ /* New owner must have CREATE privilege on namespace */
5322
+ aclresult = pg_namespace_aclcheck (namespaceOid , newOwnerId ,
5323
+ ACL_CREATE );
5324
+ if (aclresult != ACLCHECK_OK )
5325
+ aclcheck_error (aclresult , ACL_KIND_NAMESPACE ,
5326
+ get_namespace_name (namespaceOid ));
5327
+ }
5313
5328
5314
5329
memset (repl_null , ' ' , sizeof (repl_null ));
5315
5330
memset (repl_repl , ' ' , sizeof (repl_repl ));
@@ -5342,6 +5357,12 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId)
5342
5357
/* Update owner dependency reference */
5343
5358
changeDependencyOnOwner (RelationRelationId , relationOid , newOwnerId );
5344
5359
5360
+ /*
5361
+ * Also change the ownership of the table's rowtype, if it has one
5362
+ */
5363
+ if (tuple_class -> relkind != RELKIND_INDEX )
5364
+ AlterTypeOwnerInternal (tuple_class -> reltype , newOwnerId );
5365
+
5345
5366
/*
5346
5367
* If we are operating on a table, also change the ownership of
5347
5368
* any indexes and sequences that belong to the table, as well as
@@ -5358,7 +5379,7 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId)
5358
5379
5359
5380
/* For each index, recursively change its ownership */
5360
5381
foreach (i , index_oid_list )
5361
- ATExecChangeOwner (lfirst_oid (i ), newOwnerId );
5382
+ ATExecChangeOwner (lfirst_oid (i ), newOwnerId , true );
5362
5383
5363
5384
list_free (index_oid_list );
5364
5385
}
@@ -5367,7 +5388,8 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId)
5367
5388
{
5368
5389
/* If it has a toast table, recurse to change its ownership */
5369
5390
if (tuple_class -> reltoastrelid != InvalidOid )
5370
- ATExecChangeOwner (tuple_class -> reltoastrelid , newOwnerId );
5391
+ ATExecChangeOwner (tuple_class -> reltoastrelid , newOwnerId ,
5392
+ true);
5371
5393
5372
5394
/* If it has dependent sequences, recurse to change them too */
5373
5395
change_owner_recurse_to_sequences (relationOid , newOwnerId );
@@ -5437,7 +5459,7 @@ change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId)
5437
5459
}
5438
5460
5439
5461
/* We don't need to close the sequence while we alter it. */
5440
- ATExecChangeOwner (depForm -> objid , newOwnerId );
5462
+ ATExecChangeOwner (depForm -> objid , newOwnerId , false );
5441
5463
5442
5464
/* Now we can close it. Keep the lock till end of transaction. */
5443
5465
relation_close (seqRel , NoLock );
0 commit comments