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

Commit756e7b4

Browse files
committed
Rework internals of changing a type's ownership
This is necessary so that REASSIGN OWNED does the right thing withcomposite types, to wit, that it also alters ownership of the type'spg_class entry -- previously, the pg_class entry remained owned by theoriginal user, which caused later other failures such as the new owner'sinability to use ALTER TYPE to rename an attribute of the affectedcomposite. Also, if the original owner is later dropped, the pg_classentry becomes owned by a non-existant user which is bogus.To fix, create a new routine AlterTypeOwner_oid which knows whether topass the request to ATExecChangeOwner or deal with it directly, and usethat in shdepReassignOwner rather than calling AlterTypeOwnerInternaldirectly. AlterTypeOwnerInternal is now simpler in that it onlymodifies the pg_type entry and recurses to handle a possible array type;higher-level tasks are handled by either AlterTypeOwner directly orAlterTypeOwner_oid.I took the opportunity to add a few more objects to the test rig forREASSIGN OWNED, so that more cases are exercised. Additional ones couldbe added for superuser-only-ownable objects (such as FDWs and eventtriggers) but I didn't want to push my luck by adding a new superuser tothe tests on a backpatchable bug fix.Per bug #13666 reported by Chris Pacejo.Backpatch to 9.5.(I would back-patch this all the way back, except that it doesn't applycleanly in 9.4 and earlier because59367fd wasn't backpatched. If wedecide that we need this in earlier branches too, we should backpatchboth.)
1 parent2ec477d commit756e7b4

File tree

6 files changed

+102
-76
lines changed

6 files changed

+102
-76
lines changed

‎src/backend/catalog/pg_shdepend.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1365,7 +1365,7 @@ shdepReassignOwned(List *roleids, Oid newrole)
13651365
switch (sdepForm->classid)
13661366
{
13671367
caseTypeRelationId:
1368-
AlterTypeOwnerInternal(sdepForm->objid,newrole, true);
1368+
AlterTypeOwner_oid(sdepForm->objid,newrole, true);
13691369
break;
13701370

13711371
caseNamespaceRelationId:

‎src/backend/commands/tablecmds.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9081,8 +9081,7 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
90819081
* Also change the ownership of the table's row type, if it has one
90829082
*/
90839083
if (tuple_class->relkind!=RELKIND_INDEX)
9084-
AlterTypeOwnerInternal(tuple_class->reltype,newOwnerId,
9085-
tuple_class->relkind==RELKIND_COMPOSITE_TYPE);
9084+
AlterTypeOwnerInternal(tuple_class->reltype,newOwnerId);
90869085

90879086
/*
90889087
* If we are operating on a table or materialized view, also change

‎src/backend/commands/typecmds.c

Lines changed: 50 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -3273,57 +3273,7 @@ AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype)
32733273
get_namespace_name(typTup->typnamespace));
32743274
}
32753275

3276-
/*
3277-
* If it's a composite type, invoke ATExecChangeOwner so that we fix
3278-
* up the pg_class entry properly. That will call back to
3279-
* AlterTypeOwnerInternal to take care of the pg_type entry(s).
3280-
*/
3281-
if (typTup->typtype==TYPTYPE_COMPOSITE)
3282-
ATExecChangeOwner(typTup->typrelid,newOwnerId, true,AccessExclusiveLock);
3283-
else
3284-
{
3285-
Datumrepl_val[Natts_pg_type];
3286-
boolrepl_null[Natts_pg_type];
3287-
boolrepl_repl[Natts_pg_type];
3288-
Acl*newAcl;
3289-
DatumaclDatum;
3290-
boolisNull;
3291-
3292-
memset(repl_null, false,sizeof(repl_null));
3293-
memset(repl_repl, false,sizeof(repl_repl));
3294-
3295-
repl_repl[Anum_pg_type_typowner-1]= true;
3296-
repl_val[Anum_pg_type_typowner-1]=ObjectIdGetDatum(newOwnerId);
3297-
3298-
aclDatum=heap_getattr(tup,
3299-
Anum_pg_type_typacl,
3300-
RelationGetDescr(rel),
3301-
&isNull);
3302-
/* Null ACLs do not require changes */
3303-
if (!isNull)
3304-
{
3305-
newAcl=aclnewowner(DatumGetAclP(aclDatum),
3306-
typTup->typowner,newOwnerId);
3307-
repl_repl[Anum_pg_type_typacl-1]= true;
3308-
repl_val[Anum_pg_type_typacl-1]=PointerGetDatum(newAcl);
3309-
}
3310-
3311-
tup=heap_modify_tuple(tup,RelationGetDescr(rel),repl_val,repl_null,
3312-
repl_repl);
3313-
3314-
simple_heap_update(rel,&tup->t_self,tup);
3315-
3316-
CatalogUpdateIndexes(rel,tup);
3317-
3318-
/* Update owner dependency reference */
3319-
changeDependencyOnOwner(TypeRelationId,typeOid,newOwnerId);
3320-
3321-
InvokeObjectPostAlterHook(TypeRelationId,typeOid,0);
3322-
3323-
/* If it has an array type, update that too */
3324-
if (OidIsValid(typTup->typarray))
3325-
AlterTypeOwnerInternal(typTup->typarray,newOwnerId, false);
3326-
}
3276+
AlterTypeOwner_oid(typeOid,newOwnerId, true);
33273277
}
33283278

33293279
ObjectAddressSet(address,TypeRelationId,typeOid);
@@ -3335,21 +3285,58 @@ AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype)
33353285
}
33363286

33373287
/*
3338-
* AlterTypeOwnerInternal - change type owner unconditionally
3288+
* AlterTypeOwner_oid - change type owner unconditionally
3289+
*
3290+
* This function recurses to handle a pg_class entry, if necessary. It
3291+
* invokes any necessary access object hooks. If hasDependEntry is TRUE, this
3292+
* function modifies the pg_shdepend entry appropriately (this should be
3293+
* passed as FALSE only for table rowtypes and array types).
33393294
*
3340-
* This is currently only used to propagate ALTER TABLE/TYPE OWNER to a
3341-
* table's rowtype or an array type, and to implement REASSIGN OWNED BY.
3342-
* It assumes the caller has done all needed checks. The function will
3343-
* automatically recurse to an array type if the type has one.
3295+
* This is used by ALTER TABLE/TYPE OWNER commands, as well as by REASSIGN
3296+
* OWNED BY. It assumes the caller has done all needed check.
3297+
*/
3298+
void
3299+
AlterTypeOwner_oid(OidtypeOid,OidnewOwnerId,boolhasDependEntry)
3300+
{
3301+
Relationrel;
3302+
HeapTupletup;
3303+
Form_pg_typetypTup;
3304+
3305+
rel=heap_open(TypeRelationId,RowExclusiveLock);
3306+
3307+
tup=SearchSysCache1(TYPEOID,ObjectIdGetDatum(typeOid));
3308+
if (!HeapTupleIsValid(tup))
3309+
elog(ERROR,"cache lookup failed for type %u",typeOid);
3310+
typTup= (Form_pg_type)GETSTRUCT(tup);
3311+
3312+
/*
3313+
* If it's a composite type, invoke ATExecChangeOwner so that we fix up the
3314+
* pg_class entry properly. That will call back to AlterTypeOwnerInternal
3315+
* to take care of the pg_type entry(s).
3316+
*/
3317+
if (typTup->typtype==TYPTYPE_COMPOSITE)
3318+
ATExecChangeOwner(typTup->typrelid,newOwnerId, true,AccessExclusiveLock);
3319+
else
3320+
AlterTypeOwnerInternal(typeOid,newOwnerId);
3321+
3322+
/* Update owner dependency reference */
3323+
if (hasDependEntry)
3324+
changeDependencyOnOwner(TypeRelationId,typeOid,newOwnerId);
3325+
3326+
InvokeObjectPostAlterHook(TypeRelationId,typeOid,0);
3327+
3328+
ReleaseSysCache(tup);
3329+
heap_close(rel,RowExclusiveLock);
3330+
}
3331+
3332+
/*
3333+
* AlterTypeOwnerInternal - bare-bones type owner change.
33443334
*
3345-
* hasDependEntry should be TRUE if type is expected to have a pg_shdepend
3346-
* entry (ie, it's not a table rowtype nor an array type).
3347-
* is_primary_ops should be TRUE if this function is invoked with user's
3348-
* direct operation (e.g, shdepReassignOwned). Elsewhere,
3335+
* This routine simply modifies the owner of a pg_type entry, and recurses
3336+
* to handle a possible array type.
33493337
*/
33503338
void
3351-
AlterTypeOwnerInternal(OidtypeOid,OidnewOwnerId,
3352-
boolhasDependEntry)
3339+
AlterTypeOwnerInternal(OidtypeOid,OidnewOwnerId)
33533340
{
33543341
Relationrel;
33553342
HeapTupletup;
@@ -3394,15 +3381,9 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId,
33943381

33953382
CatalogUpdateIndexes(rel,tup);
33963383

3397-
/* Update owner dependency reference, if it has one */
3398-
if (hasDependEntry)
3399-
changeDependencyOnOwner(TypeRelationId,typeOid,newOwnerId);
3400-
34013384
/* If it has an array type, update that too */
34023385
if (OidIsValid(typTup->typarray))
3403-
AlterTypeOwnerInternal(typTup->typarray,newOwnerId, false);
3404-
3405-
InvokeObjectPostAlterHook(TypeRelationId,typeOid,0);
3386+
AlterTypeOwnerInternal(typTup->typarray,newOwnerId);
34063387

34073388
/* Clean up */
34083389
heap_close(rel,RowExclusiveLock);

‎src/include/commands/typecmds.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@ extern ObjectAddress AlterDomainDropConstraint(List *names, const char *constrNa
4141
externvoidcheckDomainOwner(HeapTupletup);
4242

4343
externObjectAddressRenameType(RenameStmt*stmt);
44+
4445
externObjectAddressAlterTypeOwner(List*names,OidnewOwnerId,ObjectTypeobjecttype);
45-
externvoidAlterTypeOwnerInternal(OidtypeOid,OidnewOwnerId,
46-
boolhasDependEntry);
46+
externvoidAlterTypeOwner_oid(OidtypeOid,OidnewOwnerId,boolhasDependEntry);
47+
externvoidAlterTypeOwnerInternal(OidtypeOid,OidnewOwnerId);
48+
4749
externObjectAddressAlterTypeNamespace(List*names,constchar*newschema,
4850
ObjectTypeobjecttype,Oid*oldschema);
4951
externOidAlterTypeNamespace_oid(OidtypeOid,OidnspOid,ObjectAddresses*objsMoved);

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

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,31 @@ DROP OWNED BY regression_user1;
8484
\d deptest
8585
-- Test REASSIGN OWNED
8686
GRANT ALL ON deptest1 TO regression_user1;
87+
GRANT CREATE ON DATABASE regression TO regression_user1;
8788
SET SESSION AUTHORIZATION regression_user1;
89+
CREATE SCHEMA deptest;
8890
CREATE TABLE deptest (a serial primary key, b text);
91+
ALTER DEFAULT PRIVILEGES FOR ROLE regression_user1 IN SCHEMA deptest
92+
GRANT ALL ON TABLES TO regression_user2;
93+
CREATE FUNCTION deptest_func() RETURNS void LANGUAGE plpgsql
94+
AS $$ BEGIN END; $$;
95+
CREATE TYPE deptest_enum AS ENUM ('red');
96+
CREATE TYPE deptest_range AS RANGE (SUBTYPE = int4);
8997
CREATE TABLE deptest2 (f1 int);
9098
-- make a serial column the hard way
9199
CREATE SEQUENCE ss1;
92100
ALTER TABLE deptest2 ALTER f1 SET DEFAULT nextval('ss1');
93101
ALTER SEQUENCE ss1 OWNED BY deptest2.f1;
102+
-- When reassigning ownership of a composite type, its pg_class entry
103+
-- should match
104+
CREATE TYPE deptest_t AS (a int);
105+
SELECT typowner = relowner
106+
FROM pg_type JOIN pg_class c ON typrelid = c.oid WHERE typname = 'deptest_t';
107+
?column?
108+
----------
109+
t
110+
(1 row)
111+
94112
RESET SESSION AUTHORIZATION;
95113
REASSIGN OWNED BY regression_user1 TO regression_user2;
96114
\dt deptest
@@ -100,10 +118,19 @@ REASSIGN OWNED BY regression_user1 TO regression_user2;
100118
public | deptest | table | regression_user2
101119
(1 row)
102120

121+
SELECT typowner = relowner
122+
FROM pg_type JOIN pg_class c ON typrelid = c.oid WHERE typname = 'deptest_t';
123+
?column?
124+
----------
125+
t
126+
(1 row)
127+
103128
-- doesn't work: grant still exists
104129
DROP USER regression_user1;
105130
ERROR: role "regression_user1" cannot be dropped because some objects depend on it
106-
DETAIL: privileges for table deptest1
131+
DETAIL: owner of default privileges on new relations belonging to role regression_user1 in schema deptest
132+
privileges for database regression
133+
privileges for table deptest1
107134
DROP OWNED BY regression_user1;
108135
DROP USER regression_user1;
109136
\set VERBOSITY terse

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,20 +74,37 @@ DROP OWNED BY regression_user1;
7474

7575
-- Test REASSIGN OWNED
7676
GRANT ALLON deptest1 TO regression_user1;
77+
GRANT CREATEON DATABASE regression TO regression_user1;
7778

7879
SET SESSION AUTHORIZATION regression_user1;
80+
CREATESCHEMAdeptest;
7981
CREATETABLEdeptest (aserialprimary key, btext);
82+
ALTER DEFAULT PRIVILEGES FOR ROLE regression_user1IN SCHEMA deptest
83+
GRANT ALLON TABLES TO regression_user2;
84+
CREATEFUNCTIONdeptest_func() RETURNS void LANGUAGE plpgsql
85+
AS $$BEGIN END; $$;
86+
CREATETYPEdeptest_enumAS ENUM ('red');
87+
CREATETYPEdeptest_rangeAS RANGE (SUBTYPE= int4);
8088

8189
CREATETABLEdeptest2 (f1int);
8290
-- make a serial column the hard way
8391
CREATESEQUENCEss1;
8492
ALTERTABLE deptest2 ALTER f1SET DEFAULT nextval('ss1');
8593
ALTERSEQUENCE ss1 OWNED BYdeptest2.f1;
86-
RESET SESSION AUTHORIZATION;
8794

95+
-- When reassigning ownership of a composite type, its pg_class entry
96+
-- should match
97+
CREATETYPEdeptest_tAS (aint);
98+
SELECT typowner= relowner
99+
FROM pg_typeJOIN pg_class cON typrelid=c.oidWHERE typname='deptest_t';
100+
101+
RESET SESSION AUTHORIZATION;
88102
REASSIGN OWNED BY regression_user1 TO regression_user2;
89103
\dt deptest
90104

105+
SELECT typowner= relowner
106+
FROM pg_typeJOIN pg_class cON typrelid=c.oidWHERE typname='deptest_t';
107+
91108
-- doesn't work: grant still exists
92109
DROPUSER regression_user1;
93110
DROP OWNED BY regression_user1;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp