summaryrefslogtreecommitdiff
path: root/src/backend/commands
diff options
context:
space:
mode:
authorAlvaro Herrera2005-11-21 12:49:33 +0000
committerAlvaro Herrera2005-11-21 12:49:33 +0000
commitcec3b0a9e63fd94b05dac894cca8bfa51358afec (patch)
tree464377c39a1b3f42b4d2ab82a261e9a603fa1220 /src/backend/commands
parentc52795d18a698d25b9cd7cd1ca9318a42b08fdb9 (diff)
Implement DROP OWNED and REASSIGN OWNED. These new commands facilitate the
process of dropping roles by dropping objects owned by them and privileges granted to them, or giving the owned objects to someone else, through the use of the data stored in the new pg_shdepend catalog. Some refactoring of the GRANT/REVOKE code was needed, as well as ALTER OWNER code. Further cleanup of code duplication in the GRANT code seems necessary. Implemented by me after an idea from Tom Lane, who also provided various kind of implementation advice. Regression tests pass. Some tests for the new functionality are also added, as well as rudimentary documentation.
Diffstat (limited to 'src/backend/commands')
-rw-r--r--src/backend/commands/conversioncmds.c48
-rw-r--r--src/backend/commands/functioncmds.c57
-rw-r--r--src/backend/commands/opclasscmds.c77
-rw-r--r--src/backend/commands/operatorcmds.c37
-rw-r--r--src/backend/commands/schemacmds.c47
-rw-r--r--src/backend/commands/tablecmds.c5
-rw-r--r--src/backend/commands/typecmds.c5
-rw-r--r--src/backend/commands/user.c63
8 files changed, 287 insertions, 52 deletions
diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c
index 97abc9fc774..42bb0853a10 100644
--- a/src/backend/commands/conversioncmds.c
+++ b/src/backend/commands/conversioncmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.24 2005/11/19 17:39:44 adunstan Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.25 2005/11/21 12:49:30 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
@@ -30,6 +30,8 @@
#include "utils/lsyscache.h"
#include "utils/syscache.h"
+static void AlterConversionOwner_internal(Relation rel, Oid conversionOid,
+ Oid newOwnerId);
/*
* CREATE CONVERSION
@@ -185,16 +187,13 @@ RenameConversion(List *name, const char *newname)
}
/*
- * Change conversion owner
+ * Change conversion owner, by name
*/
void
AlterConversionOwner(List *name, Oid newOwnerId)
{
Oid conversionOid;
- HeapTuple tup;
Relation rel;
- Form_pg_conversion convForm;
- AclResult aclresult;
rel = heap_open(ConversionRelationId, RowExclusiveLock);
@@ -205,6 +204,40 @@ AlterConversionOwner(List *name, Oid newOwnerId)
errmsg("conversion \"%s\" does not exist",
NameListToString(name))));
+ AlterConversionOwner_internal(rel, conversionOid, newOwnerId);
+
+ heap_close(rel, NoLock);
+}
+
+/*
+ * Change conversion owner, by oid
+ */
+void
+AlterConversionOwner_oid(Oid conversionOid, Oid newOwnerId)
+{
+ Relation rel;
+
+ rel = heap_open(ConversionRelationId, RowExclusiveLock);
+
+ AlterConversionOwner_internal(rel, conversionOid, newOwnerId);
+
+ heap_close(rel, NoLock);
+}
+
+/*
+ * AlterConversionOwner_internal
+ *
+ * Internal routine for changing the owner. rel must be pg_conversion, already
+ * open and suitably locked; it will not be closed.
+ */
+static void
+AlterConversionOwner_internal(Relation rel, Oid conversionOid, Oid newOwnerId)
+{
+ Form_pg_conversion convForm;
+ HeapTuple tup;
+
+ Assert(RelationGetRelid(rel) == ConversionRelationId);
+
tup = SearchSysCacheCopy(CONOID,
ObjectIdGetDatum(conversionOid),
0, 0, 0);
@@ -219,13 +252,15 @@ AlterConversionOwner(List *name, Oid newOwnerId)
*/
if (convForm->conowner != newOwnerId)
{
+ AclResult aclresult;
+
/* Superusers can always do it */
if (!superuser())
{
/* Otherwise, must be owner of the existing object */
if (!pg_conversion_ownercheck(HeapTupleGetOid(tup), GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
- NameListToString(name));
+ NameStr(convForm->conname));
/* Must be able to become new owner */
check_is_member_of_role(GetUserId(), newOwnerId);
@@ -253,6 +288,5 @@ AlterConversionOwner(List *name, Oid newOwnerId)
newOwnerId);
}
- heap_close(rel, NoLock);
heap_freetuple(tup);
}
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index f4d6164775e..77f892fe501 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.69 2005/10/15 02:49:15 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.70 2005/11/21 12:49:31 alvherre Exp $
*
* DESCRIPTION
* These routines take the parse tree and pick out the
@@ -55,6 +55,7 @@
#include "utils/lsyscache.h"
#include "utils/syscache.h"
+static void AlterFunctionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId);
/*
* Examine the RETURNS clause of the CREATE FUNCTION statement
@@ -853,16 +854,14 @@ RenameFunction(List *name, List *argtypes, const char *newname)
}
/*
- * Change function owner
+ * Change function owner by name and args
*/
void
AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId)
{
+ Relation rel;
Oid procOid;
HeapTuple tup;
- Form_pg_proc procForm;
- Relation rel;
- AclResult aclresult;
rel = heap_open(ProcedureRelationId, RowExclusiveLock);
@@ -873,15 +872,53 @@ AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId)
0, 0, 0);
if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for function %u", procOid);
- procForm = (Form_pg_proc) GETSTRUCT(tup);
- if (procForm->proisagg)
+ if (((Form_pg_proc) GETSTRUCT(tup))->proisagg)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is an aggregate function",
NameListToString(name)),
errhint("Use ALTER AGGREGATE to change owner of aggregate functions.")));
+ AlterFunctionOwner_internal(rel, tup, newOwnerId);
+
+ heap_close(rel, NoLock);
+}
+
+/*
+ * Change function owner by Oid
+ */
+void
+AlterFunctionOwner_oid(Oid procOid, Oid newOwnerId)
+{
+ Relation rel;
+ HeapTuple tup;
+
+ rel = heap_open(ProcedureRelationId, RowExclusiveLock);
+
+ tup = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(procOid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "cache lookup failed for function %u", procOid);
+ AlterFunctionOwner_internal(rel, tup, newOwnerId);
+
+ heap_close(rel, NoLock);
+}
+
+static void
+AlterFunctionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
+{
+ Form_pg_proc procForm;
+ AclResult aclresult;
+ Oid procOid;
+
+ Assert(RelationGetRelid(rel) == ProcedureRelationId);
+ Assert(tup->t_tableOid == ProcedureRelationId);
+
+ procForm = (Form_pg_proc) GETSTRUCT(tup);
+ procOid = HeapTupleGetOid(tup);
+
/*
* If the new owner is the same as the existing owner, consider the
* command to have succeeded. This is for dump restoration purposes.
@@ -902,7 +939,7 @@ AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId)
/* Otherwise, must be owner of the existing object */
if (!pg_proc_ownercheck(procOid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
- NameListToString(name));
+ NameStr(procForm->proname));
/* Must be able to become new owner */
check_is_member_of_role(GetUserId(), newOwnerId);
@@ -937,7 +974,8 @@ AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId)
repl_val[Anum_pg_proc_proacl - 1] = PointerGetDatum(newAcl);
}
- newtuple = heap_modifytuple(tup, RelationGetDescr(rel), repl_val, repl_null, repl_repl);
+ newtuple = heap_modifytuple(tup, RelationGetDescr(rel), repl_val,
+ repl_null, repl_repl);
simple_heap_update(rel, &newtuple->t_self, newtuple);
CatalogUpdateIndexes(rel, newtuple);
@@ -949,7 +987,6 @@ AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId)
}
ReleaseSysCache(tup);
- heap_close(rel, NoLock);
}
/*
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index ea8afcfccbf..10745032de2 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.38 2005/10/15 02:49:15 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.39 2005/11/21 12:49:31 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
@@ -58,6 +58,8 @@ static Oid assignProcSubtype(Oid amoid, Oid typeoid, Oid procOid);
static void addClassMember(List **list, OpClassMember *member, bool isProc);
static void storeOperators(Oid opclassoid, List *operators);
static void storeProcedures(Oid opclassoid, List *procedures);
+static void AlterOpClassOwner_internal(Relation rel, HeapTuple tuple,
+ Oid newOwnerId);
/*
@@ -879,20 +881,39 @@ RenameOpClass(List *name, const char *access_method, const char *newname)
}
/*
- * Change opclass owner
+ * Change opclass owner by oid
+ */
+void
+AlterOpClassOwner_oid(Oid opcOid, Oid newOwnerId)
+{
+ Relation rel;
+ HeapTuple tup;
+
+ rel = heap_open(OperatorClassRelationId, RowExclusiveLock);
+
+ tup = SearchSysCacheCopy(CLAOID,
+ ObjectIdGetDatum(opcOid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup)) /* shouldn't happen */
+ elog(ERROR, "cache lookup failed for opclass %u", opcOid);
+
+ AlterOpClassOwner_internal(rel, tup, newOwnerId);
+
+ heap_freetuple(tup);
+ heap_close(rel, NoLock);
+}
+
+/*
+ * Change opclass owner by name
*/
void
AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId)
{
- Oid opcOid;
Oid amOid;
- Oid namespaceOid;
- char *schemaname;
- char *opcname;
- HeapTuple tup;
Relation rel;
- AclResult aclresult;
- Form_pg_opclass opcForm;
+ HeapTuple tup;
+ char *opcname;
+ char *schemaname;
amOid = GetSysCacheOid(AMNAME,
CStringGetDatum(access_method),
@@ -912,6 +933,8 @@ AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId)
if (schemaname)
{
+ Oid namespaceOid;
+
namespaceOid = LookupExplicitNamespace(schemaname);
tup = SearchSysCacheCopy(CLAAMNAMENSP,
@@ -924,11 +947,11 @@ AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId)
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("operator class \"%s\" does not exist for access method \"%s\"",
opcname, access_method)));
-
- opcOid = HeapTupleGetOid(tup);
}
else
{
+ Oid opcOid;
+
opcOid = OpclassnameGetOpcid(amOid, opcname);
if (!OidIsValid(opcOid))
ereport(ERROR,
@@ -941,10 +964,32 @@ AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId)
0, 0, 0);
if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for opclass %u", opcOid);
- namespaceOid = ((Form_pg_opclass) GETSTRUCT(tup))->opcnamespace;
}
+
+ AlterOpClassOwner_internal(rel, tup, newOwnerId);
+
+ heap_freetuple(tup);
+ heap_close(rel, NoLock);
+}
+
+/*
+ * The first parameter is pg_opclass, opened and suitably locked. The second
+ * parameter is the tuple from pg_opclass we want to modify.
+ */
+static void
+AlterOpClassOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
+{
+ Oid namespaceOid;
+ AclResult aclresult;
+ Form_pg_opclass opcForm;
+
+ Assert(tup->t_tableOid == OperatorClassRelationId);
+ Assert(RelationGetRelid(rel) == OperatorClassRelationId);
+
opcForm = (Form_pg_opclass) GETSTRUCT(tup);
+ namespaceOid = opcForm->opcnamespace;
+
/*
* If the new owner is the same as the existing owner, consider the
* command to have succeeded. This is for dump restoration purposes.
@@ -957,7 +1002,7 @@ AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId)
/* Otherwise, must be owner of the existing object */
if (!pg_opclass_ownercheck(HeapTupleGetOid(tup), GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS,
- NameListToString(name));
+ NameStr(opcForm->opcname));
/* Must be able to become new owner */
check_is_member_of_role(GetUserId(), newOwnerId);
@@ -980,9 +1025,7 @@ AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId)
CatalogUpdateIndexes(rel, tup);
/* Update owner dependency reference */
- changeDependencyOnOwner(OperatorClassRelationId, opcOid, newOwnerId);
+ changeDependencyOnOwner(OperatorClassRelationId, HeapTupleGetOid(tup),
+ newOwnerId);
}
-
- heap_close(rel, NoLock);
- heap_freetuple(tup);
}
diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c
index 07877962e3f..bcc2abe5fb7 100644
--- a/src/backend/commands/operatorcmds.c
+++ b/src/backend/commands/operatorcmds.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.26 2005/10/15 02:49:15 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.27 2005/11/21 12:49:31 alvherre Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -48,6 +48,8 @@
#include "utils/syscache.h"
+static void AlterOperatorOwner_internal(Relation rel, Oid operOid, Oid newOwnerId);
+
/*
* DefineOperator
* this function extracts all the information from the
@@ -260,6 +262,18 @@ RemoveOperatorById(Oid operOid)
heap_close(relation, RowExclusiveLock);
}
+void
+AlterOperatorOwner_oid(Oid operOid, Oid newOwnerId)
+{
+ Relation rel;
+
+ rel = heap_open(OperatorRelationId, RowExclusiveLock);
+
+ AlterOperatorOwner_internal(rel, operOid, newOwnerId);
+
+ heap_close(rel, NoLock);
+}
+
/*
* change operator owner
*/
@@ -268,16 +282,27 @@ AlterOperatorOwner(List *name, TypeName *typeName1, TypeName *typeName2,
Oid newOwnerId)
{
Oid operOid;
- HeapTuple tup;
Relation rel;
- AclResult aclresult;
- Form_pg_operator oprForm;
rel = heap_open(OperatorRelationId, RowExclusiveLock);
operOid = LookupOperNameTypeNames(name, typeName1, typeName2,
false);
+ AlterOperatorOwner_internal(rel, operOid, newOwnerId);
+
+ heap_close(rel, NoLock);
+}
+
+static void
+AlterOperatorOwner_internal(Relation rel, Oid operOid, Oid newOwnerId)
+{
+ HeapTuple tup;
+ AclResult aclresult;
+ Form_pg_operator oprForm;
+
+ Assert(RelationGetRelid(rel) == OperatorRelationId);
+
tup = SearchSysCacheCopy(OPEROID,
ObjectIdGetDatum(operOid),
0, 0, 0);
@@ -298,7 +323,7 @@ AlterOperatorOwner(List *name, TypeName *typeName1, TypeName *typeName2,
/* Otherwise, must be owner of the existing object */
if (!pg_oper_ownercheck(operOid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER,
- NameListToString(name));
+ NameStr(oprForm->oprname));
/* Must be able to become new owner */
check_is_member_of_role(GetUserId(), newOwnerId);
@@ -325,7 +350,5 @@ AlterOperatorOwner(List *name, TypeName *typeName1, TypeName *typeName2,
changeDependencyOnOwner(OperatorRelationId, operOid, newOwnerId);
}
- heap_close(rel, NoLock);
heap_freetuple(tup);
-
}
diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
index caa336d2c45..7a7b930ce05 100644
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.36 2005/11/19 17:39:44 adunstan Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.37 2005/11/21 12:49:31 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
@@ -31,6 +31,8 @@
#include "utils/syscache.h"
+static void AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId);
+
/*
* CREATE SCHEMA
*/
@@ -277,6 +279,28 @@ RenameSchema(const char *oldname, const char *newname)
heap_freetuple(tup);
}
+void
+AlterSchemaOwner_oid(Oid oid, Oid newOwnerId)
+{
+ HeapTuple tup;
+ Relation rel;
+
+ rel = heap_open(NamespaceRelationId, RowExclusiveLock);
+
+ tup = SearchSysCache(NAMESPACEOID,
+ ObjectIdGetDatum(oid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for schema %u", oid);
+
+ AlterSchemaOwner_internal(tup, rel, newOwnerId);
+
+ ReleaseSysCache(tup);
+
+ heap_close(rel, RowExclusiveLock);
+}
+
+
/*
* Change schema owner
*/
@@ -285,7 +309,6 @@ AlterSchemaOwner(const char *name, Oid newOwnerId)
{
HeapTuple tup;
Relation rel;
- Form_pg_namespace nspForm;
rel = heap_open(NamespaceRelationId, RowExclusiveLock);
@@ -296,6 +319,22 @@ AlterSchemaOwner(const char *name, Oid newOwnerId)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_SCHEMA),
errmsg("schema \"%s\" does not exist", name)));
+
+ AlterSchemaOwner_internal(tup, rel, newOwnerId);
+
+ ReleaseSysCache(tup);
+
+ heap_close(rel, RowExclusiveLock);
+}
+
+static void
+AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId)
+{
+ Form_pg_namespace nspForm;
+
+ Assert(tup->t_tableOid == NamespaceRelationId);
+ Assert(RelationGetRelid(rel) == NamespaceRelationId);
+
nspForm = (Form_pg_namespace) GETSTRUCT(tup);
/*
@@ -316,7 +355,7 @@ AlterSchemaOwner(const char *name, Oid newOwnerId)
/* Otherwise, must be owner of the existing object */
if (!pg_namespace_ownercheck(HeapTupleGetOid(tup), GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE,
- name);
+ NameStr(nspForm->nspname));
/* Must be able to become new owner */
check_is_member_of_role(GetUserId(), newOwnerId);
@@ -369,6 +408,4 @@ AlterSchemaOwner(const char *name, Oid newOwnerId)
newOwnerId);
}
- ReleaseSysCache(tup);
- heap_close(rel, NoLock);
}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index abec1a835d1..09161e0d4b9 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.174 2005/10/15 02:49:15 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.175 2005/11/21 12:49:31 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
@@ -236,7 +236,6 @@ static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
const char *colName, TypeName *typename);
static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab);
static void ATPostAlterTypeParse(char *cmd, List **wqueue);
-static void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing);
static void change_owner_recurse_to_sequences(Oid relationOid,
Oid newOwnerId);
static void ATExecClusterOn(Relation rel, const char *indexName);
@@ -5264,7 +5263,7 @@ ATPostAlterTypeParse(char *cmd, List **wqueue)
* checks (this is necessary not just an optimization, else we'd fail to
* handle toast tables properly).
*/
-static void
+void
ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing)
{
Relation target_rel;
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 475c251b2fc..30044f10bf1 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.83 2005/11/19 17:39:44 adunstan Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.84 2005/11/21 12:49:31 alvherre Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -2122,7 +2122,8 @@ AlterTypeOwner(List *names, Oid newOwnerId)
* AlterTypeOwnerInternal - change type owner unconditionally
*
* This is currently only used to propagate ALTER TABLE OWNER to the
- * table's rowtype. It assumes the caller has done all needed checks.
+ * table's rowtype, and to implement REASSIGN OWNED BY. It assumes the
+ * caller has done all needed checks.
*/
void
AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 91befbc6aba..9ac3c8a97ef 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.164 2005/11/04 17:25:15 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.165 2005/11/21 12:49:31 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1119,6 +1119,67 @@ GrantRole(GrantRoleStmt *stmt)
}
/*
+ * DropOwnedObjects
+ *
+ * Drop the objects owned by a given list of roles.
+ */
+void
+DropOwnedObjects(DropOwnedStmt *stmt)
+{
+ List *role_ids = roleNamesToIds(stmt->roles);
+ ListCell *cell;
+
+ /* Check privileges */
+ foreach (cell, role_ids)
+ {
+ Oid roleid = lfirst_oid(cell);
+
+ if (!has_privs_of_role(GetUserId(), roleid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied to drop objects")));
+ }
+
+ /* Ok, do it */
+ shdepDropOwned(role_ids, stmt->behavior);
+}
+
+/*
+ * ReassignOwnedObjects
+ *
+ * Give the objects owned by a given list of roles away to another user.
+ */
+void
+ReassignOwnedObjects(ReassignOwnedStmt *stmt)
+{
+ List *role_ids = roleNamesToIds(stmt->roles);
+ ListCell *cell;
+ Oid newrole;
+
+ /* Check privileges */
+ foreach (cell, role_ids)
+ {
+ Oid roleid = lfirst_oid(cell);
+
+ if (!has_privs_of_role(GetUserId(), roleid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied to reassign objects")));
+ }
+
+ /* Must have privileges on the receiving side too */
+ newrole = get_roleid_checked(stmt->newrole);
+
+ if (!has_privs_of_role(GetUserId(), newrole))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied to reassign objects")));
+
+ /* Ok, do it */
+ shdepReassignOwned(role_ids, newrole);
+}
+
+/*
* roleNamesToIds
*
* Given a list of role names (as String nodes), generate a list of role OIDs