aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/catalog/pg_shdepend.c2
-rw-r--r--src/backend/commands/tablecmds.c3
-rw-r--r--src/backend/commands/typecmds.c87
-rw-r--r--src/include/commands/typecmds.h4
-rw-r--r--src/test/regress/expected/dependency.out28
-rw-r--r--src/test/regress/sql/dependency.sql18
6 files changed, 95 insertions, 47 deletions
diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c
index fd9651fce27..67c4fcfc406 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -1349,7 +1349,7 @@ shdepReassignOwned(List *roleids, Oid newrole)
break;
case TypeRelationId:
- AlterTypeOwnerInternal(sdepForm->objid, newrole, true);
+ AlterTypeOwner_oid(sdepForm->objid, newrole, true);
break;
case OperatorRelationId:
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index eac7e5d71b1..d7698a10789 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7567,8 +7567,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, also change the ownership of any
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 9a717d01211..01e014d6e1c 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -2717,53 +2717,64 @@ AlterTypeOwner(List *names, Oid newOwnerId)
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
- {
- /*
- * We can just apply the modification directly.
- *
- * okay to scribble on typTup because it's a copy
- */
- typTup->typowner = newOwnerId;
+ AlterTypeOwner_oid(typeOid, newOwnerId, true);
+ }
+
+ /* Clean up */
+ heap_close(rel, RowExclusiveLock);
+}
+
+/*
+ * 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 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;
- simple_heap_update(rel, &tup->t_self, tup);
+ rel = heap_open(TypeRelationId, RowExclusiveLock);
- CatalogUpdateIndexes(rel, tup);
+ tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for type %u", typeOid);
+ typTup = (Form_pg_type) GETSTRUCT(tup);
- /* Update owner dependency reference */
- changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId);
+ /*
+ * 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);
- /* If it has an array type, update that too */
- if (OidIsValid(typTup->typarray))
- AlterTypeOwnerInternal(typTup->typarray, newOwnerId, false);
- }
- }
+ /* Update owner dependency reference */
+ if (hasDependEntry)
+ changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId);
- /* Clean up */
+ ReleaseSysCache(tup);
heap_close(rel, RowExclusiveLock);
}
/*
- * AlterTypeOwnerInternal - change type owner unconditionally
- *
- * 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.
+ * 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).
+ * 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;
@@ -2785,13 +2796,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);
+ 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 e22a699657d..c12cbf0ff18 100644
--- a/src/include/commands/typecmds.h
+++ b/src/include/commands/typecmds.h
@@ -39,8 +39,8 @@ extern List *GetDomainConstraints(Oid typeOid);
extern void RenameType(List *names, const char *newTypeName);
extern void AlterTypeOwner(List *names, Oid newOwnerId);
-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 void AlterTypeNamespace(List *names, const char *newschema);
extern Oid AlterTypeNamespace_oid(Oid typeOid, Oid nspOid, ObjectAddresses *objsMoved);
extern Oid AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid,
diff --git a/src/test/regress/expected/dependency.out b/src/test/regress/expected/dependency.out
index 700def75b1f..cb2e4659322 100644
--- a/src/test/regress/expected/dependency.out
+++ b/src/test/regress/expected/dependency.out
@@ -89,15 +89,32 @@ 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);
NOTICE: CREATE TABLE will create implicit sequence "deptest_a_seq" for serial column "deptest.a"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "deptest_pkey" for table "deptest"
+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 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
@@ -107,10 +124,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..a0836a7121d 100644
--- a/src/test/regress/sql/dependency.sql
+++ b/src/test/regress/sql/dependency.sql
@@ -74,20 +74,36 @@ 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 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;