aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/catalog/pg_shdepend.c2
-rw-r--r--src/backend/commands/tablecmds.c3
-rw-r--r--src/backend/commands/typecmds.c119
-rw-r--r--src/include/commands/typecmds.h6
-rw-r--r--src/test/regress/expected/dependency.out29
-rw-r--r--src/test/regress/sql/dependency.sql19
6 files changed, 102 insertions, 76 deletions
diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c
index cfd43a8ddfc..c3cce67a8b6 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -1365,7 +1365,7 @@ shdepReassignOwned(List *roleids, Oid newrole)
switch (sdepForm->classid)
{
case TypeRelationId:
- AlterTypeOwnerInternal(sdepForm->objid, newrole, true);
+ AlterTypeOwner_oid(sdepForm->objid, newrole, true);
break;
case NamespaceRelationId:
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 6df493932e0..56fed4d87cd 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -9081,8 +9081,7 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
* Also change the ownership of the table's row type, if it has one
*/
if (tuple_class->relkind != RELKIND_INDEX)
- AlterTypeOwnerInternal(tuple_class->reltype, newOwnerId,
- tuple_class->relkind == RELKIND_COMPOSITE_TYPE);
+ AlterTypeOwnerInternal(tuple_class->reltype, newOwnerId);
/*
* If we are operating on a table or materialized view, also change
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index a126e666d88..8d8731d3490 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -3273,57 +3273,7 @@ AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype)
get_namespace_name(typTup->typnamespace));
}
- /*
- * If it's a composite type, invoke ATExecChangeOwner so that we fix
- * up the pg_class entry properly. That will call back to
- * AlterTypeOwnerInternal to take care of the pg_type entry(s).
- */
- if (typTup->typtype == TYPTYPE_COMPOSITE)
- ATExecChangeOwner(typTup->typrelid, newOwnerId, true, AccessExclusiveLock);
- else
- {
- Datum repl_val[Natts_pg_type];
- bool repl_null[Natts_pg_type];
- bool repl_repl[Natts_pg_type];
- Acl *newAcl;
- Datum aclDatum;
- bool isNull;
-
- memset(repl_null, false, sizeof(repl_null));
- memset(repl_repl, false, sizeof(repl_repl));
-
- repl_repl[Anum_pg_type_typowner - 1] = true;
- repl_val[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(newOwnerId);
-
- aclDatum = heap_getattr(tup,
- Anum_pg_type_typacl,
- RelationGetDescr(rel),
- &isNull);
- /* Null ACLs do not require changes */
- if (!isNull)
- {
- newAcl = aclnewowner(DatumGetAclP(aclDatum),
- typTup->typowner, newOwnerId);
- repl_repl[Anum_pg_type_typacl - 1] = true;
- repl_val[Anum_pg_type_typacl - 1] = PointerGetDatum(newAcl);
- }
-
- tup = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null,
- repl_repl);
-
- simple_heap_update(rel, &tup->t_self, tup);
-
- CatalogUpdateIndexes(rel, tup);
-
- /* Update owner dependency reference */
- changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId);
-
- InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
-
- /* If it has an array type, update that too */
- if (OidIsValid(typTup->typarray))
- AlterTypeOwnerInternal(typTup->typarray, newOwnerId, false);
- }
+ AlterTypeOwner_oid(typeOid, newOwnerId, true);
}
ObjectAddressSet(address, TypeRelationId, typeOid);
@@ -3335,21 +3285,58 @@ AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype)
}
/*
- * AlterTypeOwnerInternal - change type owner unconditionally
+ * AlterTypeOwner_oid - change type owner unconditionally
+ *
+ * This function recurses to handle a pg_class entry, if necessary. It
+ * invokes any necessary access object hooks. If hasDependEntry is TRUE, this
+ * function modifies the pg_shdepend entry appropriately (this should be
+ * passed as FALSE only for table rowtypes and array types).
*
- * This is currently only used to propagate ALTER TABLE/TYPE OWNER to a
- * table's rowtype or an array type, and to implement REASSIGN OWNED BY.
- * It assumes the caller has done all needed checks. The function will
- * automatically recurse to an array type if the type has one.
+ * This is used by ALTER TABLE/TYPE OWNER commands, as well as by REASSIGN
+ * OWNED BY. It assumes the caller has done all needed check.
+ */
+void
+AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry)
+{
+ Relation rel;
+ HeapTuple tup;
+ Form_pg_type typTup;
+
+ rel = heap_open(TypeRelationId, RowExclusiveLock);
+
+ tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for type %u", typeOid);
+ typTup = (Form_pg_type) GETSTRUCT(tup);
+
+ /*
+ * If it's a composite type, invoke ATExecChangeOwner so that we fix up the
+ * pg_class entry properly. That will call back to AlterTypeOwnerInternal
+ * to take care of the pg_type entry(s).
+ */
+ if (typTup->typtype == TYPTYPE_COMPOSITE)
+ ATExecChangeOwner(typTup->typrelid, newOwnerId, true, AccessExclusiveLock);
+ else
+ AlterTypeOwnerInternal(typeOid, newOwnerId);
+
+ /* Update owner dependency reference */
+ if (hasDependEntry)
+ changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId);
+
+ InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
+
+ ReleaseSysCache(tup);
+ heap_close(rel, RowExclusiveLock);
+}
+
+/*
+ * AlterTypeOwnerInternal - bare-bones type owner change.
*
- * hasDependEntry should be TRUE if type is expected to have a pg_shdepend
- * entry (ie, it's not a table rowtype nor an array type).
- * is_primary_ops should be TRUE if this function is invoked with user's
- * direct operation (e.g, shdepReassignOwned). Elsewhere,
+ * This routine simply modifies the owner of a pg_type entry, and recurses
+ * to handle a possible array type.
*/
void
-AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId,
- bool hasDependEntry)
+AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
{
Relation rel;
HeapTuple tup;
@@ -3394,15 +3381,9 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId,
CatalogUpdateIndexes(rel, tup);
- /* Update owner dependency reference, if it has one */
- if (hasDependEntry)
- changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId);
-
/* If it has an array type, update that too */
if (OidIsValid(typTup->typarray))
- AlterTypeOwnerInternal(typTup->typarray, newOwnerId, false);
-
- InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
+ AlterTypeOwnerInternal(typTup->typarray, newOwnerId);
/* Clean up */
heap_close(rel, RowExclusiveLock);
diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h
index ef4b41b5a55..44bc5e70cdd 100644
--- a/src/include/commands/typecmds.h
+++ b/src/include/commands/typecmds.h
@@ -41,9 +41,11 @@ extern ObjectAddress AlterDomainDropConstraint(List *names, const char *constrNa
extern void checkDomainOwner(HeapTuple tup);
extern ObjectAddress RenameType(RenameStmt *stmt);
+
extern ObjectAddress AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype);
-extern void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId,
- bool hasDependEntry);
+extern void AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry);
+extern void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId);
+
extern ObjectAddress AlterTypeNamespace(List *names, const char *newschema,
ObjectType objecttype, Oid *oldschema);
extern Oid AlterTypeNamespace_oid(Oid typeOid, Oid nspOid, ObjectAddresses *objsMoved);
diff --git a/src/test/regress/expected/dependency.out b/src/test/regress/expected/dependency.out
index 09b02127f94..caba88f89b3 100644
--- a/src/test/regress/expected/dependency.out
+++ b/src/test/regress/expected/dependency.out
@@ -84,13 +84,31 @@ DROP OWNED BY regression_user1;
\d deptest
-- Test REASSIGN OWNED
GRANT ALL ON deptest1 TO regression_user1;
+GRANT CREATE ON DATABASE regression TO regression_user1;
SET SESSION AUTHORIZATION regression_user1;
+CREATE SCHEMA deptest;
CREATE TABLE deptest (a serial primary key, b text);
+ALTER DEFAULT PRIVILEGES FOR ROLE regression_user1 IN SCHEMA deptest
+ GRANT ALL ON TABLES TO regression_user2;
+CREATE FUNCTION deptest_func() RETURNS void LANGUAGE plpgsql
+ AS $$ BEGIN END; $$;
+CREATE TYPE deptest_enum AS ENUM ('red');
+CREATE TYPE deptest_range AS RANGE (SUBTYPE = int4);
CREATE TABLE deptest2 (f1 int);
-- make a serial column the hard way
CREATE SEQUENCE ss1;
ALTER TABLE deptest2 ALTER f1 SET DEFAULT nextval('ss1');
ALTER SEQUENCE ss1 OWNED BY deptest2.f1;
+-- When reassigning ownership of a composite type, its pg_class entry
+-- should match
+CREATE TYPE deptest_t AS (a int);
+SELECT typowner = relowner
+FROM pg_type JOIN pg_class c ON typrelid = c.oid WHERE typname = 'deptest_t';
+ ?column?
+----------
+ t
+(1 row)
+
RESET SESSION AUTHORIZATION;
REASSIGN OWNED BY regression_user1 TO regression_user2;
\dt deptest
@@ -100,10 +118,19 @@ REASSIGN OWNED BY regression_user1 TO regression_user2;
public | deptest | table | regression_user2
(1 row)
+SELECT typowner = relowner
+FROM pg_type JOIN pg_class c ON typrelid = c.oid WHERE typname = 'deptest_t';
+ ?column?
+----------
+ t
+(1 row)
+
-- doesn't work: grant still exists
DROP USER regression_user1;
ERROR: role "regression_user1" cannot be dropped because some objects depend on it
-DETAIL: privileges for table deptest1
+DETAIL: owner of default privileges on new relations belonging to role regression_user1 in schema deptest
+privileges for database regression
+privileges for table deptest1
DROP OWNED BY regression_user1;
DROP USER regression_user1;
\set VERBOSITY terse
diff --git a/src/test/regress/sql/dependency.sql b/src/test/regress/sql/dependency.sql
index c1d81569c69..599a359b4fe 100644
--- a/src/test/regress/sql/dependency.sql
+++ b/src/test/regress/sql/dependency.sql
@@ -74,20 +74,37 @@ DROP OWNED BY regression_user1;
-- Test REASSIGN OWNED
GRANT ALL ON deptest1 TO regression_user1;
+GRANT CREATE ON DATABASE regression TO regression_user1;
SET SESSION AUTHORIZATION regression_user1;
+CREATE SCHEMA deptest;
CREATE TABLE deptest (a serial primary key, b text);
+ALTER DEFAULT PRIVILEGES FOR ROLE regression_user1 IN SCHEMA deptest
+ GRANT ALL ON TABLES TO regression_user2;
+CREATE FUNCTION deptest_func() RETURNS void LANGUAGE plpgsql
+ AS $$ BEGIN END; $$;
+CREATE TYPE deptest_enum AS ENUM ('red');
+CREATE TYPE deptest_range AS RANGE (SUBTYPE = int4);
CREATE TABLE deptest2 (f1 int);
-- make a serial column the hard way
CREATE SEQUENCE ss1;
ALTER TABLE deptest2 ALTER f1 SET DEFAULT nextval('ss1');
ALTER SEQUENCE ss1 OWNED BY deptest2.f1;
-RESET SESSION AUTHORIZATION;
+-- When reassigning ownership of a composite type, its pg_class entry
+-- should match
+CREATE TYPE deptest_t AS (a int);
+SELECT typowner = relowner
+FROM pg_type JOIN pg_class c ON typrelid = c.oid WHERE typname = 'deptest_t';
+
+RESET SESSION AUTHORIZATION;
REASSIGN OWNED BY regression_user1 TO regression_user2;
\dt deptest
+SELECT typowner = relowner
+FROM pg_type JOIN pg_class c ON typrelid = c.oid WHERE typname = 'deptest_t';
+
-- doesn't work: grant still exists
DROP USER regression_user1;
DROP OWNED BY regression_user1;