Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit33f5bf9

Browse files
committed
ALTER TABLE OWNER must change the ownership of the table's rowtype too.
This was not especially critical before, but it is now that we trackownership dependencies --- the dependency for the rowtype *must* shiftto the new owner. Spotted by Bernd Helmle.Also fix a problem introduced by recent change to allow non-superusersto do ALTER OWNER in some cases: if the table had a toast table, ALTEROWNER failed *even for superusers*, because the test being applied wouldconclude that the new would-be owner had no create rights on pg_toast.A side-effect of the fix is to disallow changing the ownership of indexesor toast tables separately from their parent table, which seems a goodidea on the whole.
1 parente48b28b commit33f5bf9

File tree

6 files changed

+104
-34
lines changed

6 files changed

+104
-34
lines changed

‎doc/src/sgml/ref/alter_table.sgml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/ref/alter_table.sgml,v 1.78 2005/08/01 16:11:14 tgl Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/ref/alter_table.sgml,v 1.79 2005/08/04 01:09:27 tgl Exp $
33
PostgreSQL documentation
44
-->
55

@@ -235,7 +235,7 @@ where <replaceable class="PARAMETER">action</replaceable> is one of:
235235
<term><literal>OWNER</literal></term>
236236
<listitem>
237237
<para>
238-
This form changes the owner of the table,index,sequence, or view to the
238+
This form changes the owner of the table, sequence, or view to the
239239
specified user.
240240
</para>
241241
</listitem>

‎src/backend/commands/tablecmds.c

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* 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 $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -238,7 +238,7 @@ static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
238238
constchar*colName,TypeName*typename);
239239
staticvoidATPostAlterTypeCleanup(List**wqueue,AlteredTableInfo*tab);
240240
staticvoidATPostAlterTypeParse(char*cmd,List**wqueue);
241-
staticvoidATExecChangeOwner(OidrelationOid,OidnewOwnerId);
241+
staticvoidATExecChangeOwner(OidrelationOid,OidnewOwnerId,boolrecursing);
242242
staticvoidchange_owner_recurse_to_sequences(OidrelationOid,
243243
OidnewOwnerId);
244244
staticvoidATExecClusterOn(Relationrel,constchar*indexName);
@@ -2141,7 +2141,8 @@ ATExecCmd(AlteredTableInfo *tab, Relation rel, AlterTableCmd *cmd)
21412141
break;
21422142
caseAT_ChangeOwner:/* ALTER OWNER */
21432143
ATExecChangeOwner(RelationGetRelid(rel),
2144-
get_roleid_checked(cmd->name));
2144+
get_roleid_checked(cmd->name),
2145+
false);
21452146
break;
21462147
caseAT_ClusterOn:/* CLUSTER ON */
21472148
ATExecClusterOn(rel,cmd->name);
@@ -5238,9 +5239,15 @@ ATPostAlterTypeParse(char *cmd, List **wqueue)
52385239

52395240
/*
52405241
* 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).
52415248
*/
52425249
staticvoid
5243-
ATExecChangeOwner(OidrelationOid,OidnewOwnerId)
5250+
ATExecChangeOwner(OidrelationOid,OidnewOwnerId,boolrecursing)
52445251
{
52455252
Relationtarget_rel;
52465253
Relationclass_rel;
@@ -5267,16 +5274,19 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId)
52675274
switch (tuple_class->relkind)
52685275
{
52695276
caseRELKIND_RELATION:
5270-
caseRELKIND_INDEX:
52715277
caseRELKIND_VIEW:
52725278
caseRELKIND_SEQUENCE:
5273-
caseRELKIND_TOASTVALUE:
52745279
/* ok to change owner */
52755280
break;
5281+
caseRELKIND_INDEX:
5282+
caseRELKIND_TOASTVALUE:
5283+
if (recursing)
5284+
break;
5285+
/* FALL THRU */
52765286
default:
52775287
ereport(ERROR,
52785288
(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",
52805290
NameStr(tuple_class->relname))));
52815291
}
52825292

@@ -5293,23 +5303,28 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId)
52935303
DatumaclDatum;
52945304
boolisNull;
52955305
HeapTuplenewtuple;
5296-
OidnamespaceOid=tuple_class->relnamespace;
5297-
AclResultaclresult;
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));
53035306

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+
OidnamespaceOid=tuple_class->relnamespace;
5311+
AclResultaclresult;
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+
}
53135328

53145329
memset(repl_null,' ',sizeof(repl_null));
53155330
memset(repl_repl,' ',sizeof(repl_repl));
@@ -5342,6 +5357,12 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId)
53425357
/* Update owner dependency reference */
53435358
changeDependencyOnOwner(RelationRelationId,relationOid,newOwnerId);
53445359

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+
53455366
/*
53465367
* If we are operating on a table, also change the ownership of
53475368
* any indexes and sequences that belong to the table, as well as
@@ -5358,7 +5379,7 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId)
53585379

53595380
/* For each index, recursively change its ownership */
53605381
foreach(i,index_oid_list)
5361-
ATExecChangeOwner(lfirst_oid(i),newOwnerId);
5382+
ATExecChangeOwner(lfirst_oid(i),newOwnerId, true);
53625383

53635384
list_free(index_oid_list);
53645385
}
@@ -5367,7 +5388,8 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId)
53675388
{
53685389
/* If it has a toast table, recurse to change its ownership */
53695390
if (tuple_class->reltoastrelid!=InvalidOid)
5370-
ATExecChangeOwner(tuple_class->reltoastrelid,newOwnerId);
5391+
ATExecChangeOwner(tuple_class->reltoastrelid,newOwnerId,
5392+
true);
53715393

53725394
/* If it has dependent sequences, recurse to change them too */
53735395
change_owner_recurse_to_sequences(relationOid,newOwnerId);
@@ -5437,7 +5459,7 @@ change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId)
54375459
}
54385460

54395461
/* We don't need to close the sequence while we alter it. */
5440-
ATExecChangeOwner(depForm->objid,newOwnerId);
5462+
ATExecChangeOwner(depForm->objid,newOwnerId, false);
54415463

54425464
/* Now we can close it. Keep the lock till end of transaction. */
54435465
relation_close(seqRel,NoLock);

‎src/backend/commands/typecmds.c

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.77 2005/08/01 04:03:55 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.78 2005/08/04 01:09:28 tgl Exp $
1212
*
1313
* DESCRIPTION
1414
* The "DefineFoo" routines take the parse tree and pick out the
@@ -2057,7 +2057,8 @@ AlterTypeOwner(List *names, Oid newOwnerId)
20572057
* free-standing composite type, and not a table's underlying type. We
20582058
* want people to use ALTER TABLE not ALTER TYPE for that case.
20592059
*/
2060-
if (typTup->typtype=='c'&&get_rel_relkind(typTup->typrelid)!='c')
2060+
if (typTup->typtype=='c'&&
2061+
get_rel_relkind(typTup->typrelid)!=RELKIND_COMPOSITE_TYPE)
20612062
ereport(ERROR,
20622063
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
20632064
errmsg("\"%s\" is a table's row type",
@@ -2102,6 +2103,45 @@ AlterTypeOwner(List *names, Oid newOwnerId)
21022103
heap_close(rel,RowExclusiveLock);
21032104
}
21042105

2106+
/*
2107+
* AlterTypeOwnerInternal - change type owner unconditionally
2108+
*
2109+
* This is currently only used to propagate ALTER TABLE OWNER to the
2110+
* table's rowtype. It assumes the caller has done all needed checks.
2111+
*/
2112+
void
2113+
AlterTypeOwnerInternal(OidtypeOid,OidnewOwnerId)
2114+
{
2115+
Relationrel;
2116+
HeapTupletup;
2117+
Form_pg_typetypTup;
2118+
2119+
rel=heap_open(TypeRelationId,RowExclusiveLock);
2120+
2121+
tup=SearchSysCacheCopy(TYPEOID,
2122+
ObjectIdGetDatum(typeOid),
2123+
0,0,0);
2124+
if (!HeapTupleIsValid(tup))
2125+
elog(ERROR,"cache lookup failed for type %u",typeOid);
2126+
typTup= (Form_pg_type)GETSTRUCT(tup);
2127+
2128+
/*
2129+
* Modify the owner --- okay to scribble on typTup because it's a
2130+
* copy
2131+
*/
2132+
typTup->typowner=newOwnerId;
2133+
2134+
simple_heap_update(rel,&tup->t_self,tup);
2135+
2136+
CatalogUpdateIndexes(rel,tup);
2137+
2138+
/* Update owner dependency reference */
2139+
changeDependencyOnOwner(TypeRelationId,typeOid,newOwnerId);
2140+
2141+
/* Clean up */
2142+
heap_close(rel,RowExclusiveLock);
2143+
}
2144+
21052145
/*
21062146
* Execute ALTER TYPE SET SCHEMA
21072147
*/

‎src/include/commands/typecmds.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/commands/typecmds.h,v 1.12 2005/08/01 04:03:58 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/commands/typecmds.h,v 1.13 2005/08/04 01:09:29 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -35,6 +35,7 @@ extern void AlterDomainDropConstraint(List *names, const char *constrName,
3535
externList*GetDomainConstraints(OidtypeOid);
3636

3737
externvoidAlterTypeOwner(List*names,OidnewOwnerId);
38+
externvoidAlterTypeOwnerInternal(OidtypeOid,OidnewOwnerId);
3839
externvoidAlterTypeNamespace(List*names,constchar*newschema);
3940
externvoidAlterTypeNamespaceInternal(OidtypeOid,OidnspOid,
4041
boolerrorOnTableType);

‎src/test/regress/expected/dependency.out

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ CREATE USER regression_user;
55
CREATE USER regression_user2;
66
CREATE USER regression_user3;
77
CREATE GROUP regression_group;
8-
CREATE TABLE deptest ();
8+
CREATE TABLE deptest (f1 serial primary key, f2 text);
9+
NOTICE: CREATE TABLE will create implicit sequence "deptest_f1_seq" for serial column "deptest.f1"
10+
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "deptest_pkey" for table "deptest"
911
GRANT SELECT ON TABLE deptest TO GROUP regression_group;
1012
GRANT ALL ON TABLE deptest TO regression_user, regression_user2;
1113
-- can't drop neither because they have privileges somewhere
@@ -30,10 +32,12 @@ DROP USER regression_user;
3032
REVOKE ALL ON deptest FROM regression_user2;
3133
DROP USER regression_user2;
3234
-- can't drop the owner of an object
35+
-- the error message detail here would include a pg_toast_nnn name that
36+
-- is not constant, so suppress it
37+
\set VERBOSITY terse
3338
ALTER TABLE deptest OWNER TO regression_user3;
3439
DROP USER regression_user3;
3540
ERROR: role "regression_user3" cannot be dropped because some objects depend on it
36-
DETAIL: owner of table deptest
3741
-- if we drop the object, we can drop the user too
3842
DROP TABLE deptest;
3943
DROP USER regression_user3;

‎src/test/regress/sql/dependency.sql

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ CREATE USER regression_user2;
77
CREATEUSERregression_user3;
88
CREATEGROUPregression_group;
99

10-
CREATETABLEdeptest ();
10+
CREATETABLEdeptest (f1serialprimary key, f2text);
1111

1212
GRANTSELECTON TABLE deptest TO GROUP regression_group;
1313
GRANT ALLON TABLE deptest TO regression_user, regression_user2;
@@ -33,6 +33,9 @@ REVOKE ALL ON deptest FROM regression_user2;
3333
DROPUSER regression_user2;
3434

3535
-- can't drop the owner of an object
36+
-- the error message detail here would include a pg_toast_nnn name that
37+
-- is not constant, so suppress it
38+
\set VERBOSITY terse
3639
ALTERTABLE deptest OWNER TO regression_user3;
3740
DROPUSER regression_user3;
3841

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp