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.
This commit is contained in:
parent
c52795d18a
commit
cec3b0a9e6
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.66 2005/07/29 15:13:11 momjian Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.67 2005/11/21 12:49:30 alvherre Exp $
|
||||
PostgreSQL documentation
|
||||
Complete list of usable sgml source files in this directory.
|
||||
-->
|
||||
@ -70,6 +70,7 @@ Complete list of usable sgml source files in this directory.
|
||||
<!entity dropLanguage system "drop_language.sgml">
|
||||
<!entity dropOperator system "drop_operator.sgml">
|
||||
<!entity dropOperatorClass system "drop_opclass.sgml">
|
||||
<!entity dropOwned system "drop_owned.sgml">
|
||||
<!entity dropRole system "drop_role.sgml">
|
||||
<!entity dropRule system "drop_rule.sgml">
|
||||
<!entity dropSchema system "drop_schema.sgml">
|
||||
@ -93,6 +94,7 @@ Complete list of usable sgml source files in this directory.
|
||||
<!entity notify system "notify.sgml">
|
||||
<!entity prepare system "prepare.sgml">
|
||||
<!entity prepareTransaction system "prepare_transaction.sgml">
|
||||
<!entity reassignOwned system "reassign_owned.sgml">
|
||||
<!entity reindex system "reindex.sgml">
|
||||
<!entity releaseSavepoint system "release_savepoint.sgml">
|
||||
<!entity reset system "reset.sgml">
|
||||
|
99
doc/src/sgml/ref/drop_owned.sgml
Normal file
99
doc/src/sgml/ref/drop_owned.sgml
Normal file
@ -0,0 +1,99 @@
|
||||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/ref/drop_owned.sgml,v 1.1 2005/11/21 12:49:30 alvherre Exp $
|
||||
PostgreSQL documentation
|
||||
-->
|
||||
|
||||
<refentry id="SQL-DROP-OWNED">
|
||||
<refmeta>
|
||||
<refentrytitle id="SQL-DROP-OWNED-TITLE">DROP OWNED</refentrytitle>
|
||||
<refmiscinfo>SQL - Language Statements</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>DROP OWNED</refname>
|
||||
<refpurpose>remove database objects owned by a database role</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<indexterm zone="sql-drop-owned">
|
||||
<primary>DROP OWNED</primary>
|
||||
</indexterm>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<synopsis>
|
||||
DROP OWNED <replaceable class="PARAMETER">name</replaceable> [, ...] [ RESTRICT | CASCADE ]
|
||||
</synopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>
|
||||
The <command>DROP OWNED</command> instructs the system to drop those
|
||||
database objects owned by one of the given roles which reside on the
|
||||
current database. All privileges granted to the given roles will also be
|
||||
revoked.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If <literal>CASCADE</> is specified, <command>DROP OWNED</command>
|
||||
will behave like a <command>DROP ... CASCADE</command> was issued
|
||||
for each object, that is, objects dependent on the ones owned by the
|
||||
given users will be dropped as well.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Notes</title>
|
||||
<para>
|
||||
The <command>DROP OWNED</command> command is mostly used in preparation to
|
||||
drop the roles. It may be necessary to issue the command in more than one
|
||||
database.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Using the <literal>CASCADE</literal> option may make the command recurse to
|
||||
objects owned by other users.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
See the <command>REASSIGN OWNED</command> command for an alternative that
|
||||
gives the objects away to another role.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Compatibility</title>
|
||||
|
||||
<para>
|
||||
The <command>DROP OWNED</command> statement is a
|
||||
<productname>PostgreSQL</productname> extension.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
|
||||
<simplelist type="inline">
|
||||
<member><xref linkend="sql-reassign-owned" endterm="sql-reassign-owned-title"></member>
|
||||
<member><xref linkend="sql-droprole" endterm="sql-droprole-title"></member>
|
||||
</simplelist>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
|
||||
<!-- Keep this comment at the end of the file
|
||||
Local variables:
|
||||
mode: sgml
|
||||
sgml-omittag:nil
|
||||
sgml-shorttag:t
|
||||
sgml-minimize-attributes:nil
|
||||
sgml-always-quote-attributes:t
|
||||
sgml-indent-step:1
|
||||
sgml-indent-data:t
|
||||
sgml-parent-document:nil
|
||||
sgml-default-dtd-file:"../reference.ced"
|
||||
sgml-exposed-tags:nil
|
||||
sgml-local-catalogs:"/usr/lib/sgml/catalog"
|
||||
sgml-local-ecat-files:nil
|
||||
End:
|
||||
-->
|
89
doc/src/sgml/ref/reassign_owned.sgml
Normal file
89
doc/src/sgml/ref/reassign_owned.sgml
Normal file
@ -0,0 +1,89 @@
|
||||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/ref/reassign_owned.sgml,v 1.1 2005/11/21 12:49:30 alvherre Exp $
|
||||
PostgreSQL documentation
|
||||
-->
|
||||
|
||||
<refentry id="SQL-REASSIGN-OWNED">
|
||||
<refmeta>
|
||||
<refentrytitle id="SQL-REASSIGN-OWNED-TITLE">REASSIGN OWNED</refentrytitle>
|
||||
<refmiscinfo>SQL - Language Statements</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>REASSIGN OWNED</refname>
|
||||
<refpurpose>change ownership of database objects owned by a database role</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<indexterm zone="sql-reassign-owned">
|
||||
<primary>REASSIGN OWNED</primary>
|
||||
</indexterm>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<synopsis>
|
||||
REASSIGN OWNED <replaceable class="PARAMETER">old_role</replaceable> [, ...] TO <replaceable class="PARAMETER">new_role</replaceable>
|
||||
</synopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>
|
||||
The <command>REASSIGN OWNED</command> instructs the system to change
|
||||
the ownership of the database objects owned by one of the old_roles,
|
||||
to new_role.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Notes</title>
|
||||
|
||||
<para>
|
||||
The <command>REASSIGN OWNED</command> command is mostly used in preparation to
|
||||
drop the roles. See the <command>DROP OWNED</command> command for an
|
||||
alternative that drops the objects.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <command>REASSIGN OWNED</command> command does not affect the privileges
|
||||
granted to the old_roles in objects not owned by them. Use
|
||||
<command>DROP OWNED</command> to remove them.
|
||||
</para>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Compatibility</title>
|
||||
|
||||
<para>
|
||||
The <command>REASSIGN OWNED</command> statement is a
|
||||
<productname>PostgreSQL</productname> extension.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
|
||||
<simplelist type="inline">
|
||||
<member><xref linkend="sql-drop-owned" endterm="sql-drop-owned-title"></member>
|
||||
<member><xref linkend="sql-droprole" endterm="sql-droprole-title"></member>
|
||||
</simplelist>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
|
||||
<!-- Keep this comment at the end of the file
|
||||
Local variables:
|
||||
mode: sgml
|
||||
sgml-omittag:nil
|
||||
sgml-shorttag:t
|
||||
sgml-minimize-attributes:nil
|
||||
sgml-always-quote-attributes:t
|
||||
sgml-indent-step:1
|
||||
sgml-indent-data:t
|
||||
sgml-parent-document:nil
|
||||
sgml-default-dtd-file:"../reference.ced"
|
||||
sgml-exposed-tags:nil
|
||||
sgml-local-catalogs:"/usr/lib/sgml/catalog"
|
||||
sgml-local-ecat-files:nil
|
||||
End:
|
||||
-->
|
@ -1,5 +1,5 @@
|
||||
<!-- reference.sgml
|
||||
$PostgreSQL: pgsql/doc/src/sgml/reference.sgml,v 1.56 2005/07/29 15:13:11 momjian Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/reference.sgml,v 1.57 2005/11/21 12:49:30 alvherre Exp $
|
||||
|
||||
PostgreSQL Reference Manual
|
||||
-->
|
||||
@ -102,6 +102,7 @@ PostgreSQL Reference Manual
|
||||
&dropLanguage;
|
||||
&dropOperator;
|
||||
&dropOperatorClass;
|
||||
&dropOwned;
|
||||
&dropRole;
|
||||
&dropRule;
|
||||
&dropSchema;
|
||||
@ -125,6 +126,7 @@ PostgreSQL Reference Manual
|
||||
¬ify;
|
||||
&prepare;
|
||||
&prepareTransaction;
|
||||
&reassignOwned;
|
||||
&reindex;
|
||||
&releaseSavepoint;
|
||||
&reset;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_depend.c,v 1.15 2005/10/15 02:49:14 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_depend.c,v 1.16 2005/11/21 12:49:30 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -162,6 +162,58 @@ deleteDependencyRecordsFor(Oid classId, Oid objectId)
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* objectIsInternalDependency -- return whether the specified object
|
||||
* is listed as an internal dependency for some other object.
|
||||
*
|
||||
* This is used to implement DROP/REASSIGN OWNED. We cannot invoke
|
||||
* performDeletion blindly, because it may try to drop or modify an internal-
|
||||
* dependent object before the "main" object, so we need to skip the first
|
||||
* object and expect it to be automatically dropped when the main object is
|
||||
* dropped.
|
||||
*/
|
||||
bool
|
||||
objectIsInternalDependency(Oid classId, Oid objectId)
|
||||
{
|
||||
Relation depRel;
|
||||
ScanKeyData key[2];
|
||||
SysScanDesc scan;
|
||||
HeapTuple tup;
|
||||
bool isdep = false;
|
||||
|
||||
depRel = heap_open(DependRelationId, AccessShareLock);
|
||||
|
||||
ScanKeyInit(&key[0],
|
||||
Anum_pg_depend_classid,
|
||||
BTEqualStrategyNumber, F_OIDEQ,
|
||||
ObjectIdGetDatum(classId));
|
||||
ScanKeyInit(&key[1],
|
||||
Anum_pg_depend_objid,
|
||||
BTEqualStrategyNumber, F_OIDEQ,
|
||||
ObjectIdGetDatum(objectId));
|
||||
|
||||
scan = systable_beginscan(depRel, DependDependerIndexId, true,
|
||||
SnapshotNow, 2, key);
|
||||
|
||||
while (HeapTupleIsValid(tup = systable_getnext(scan)))
|
||||
{
|
||||
Form_pg_depend depForm = (Form_pg_depend) GETSTRUCT(tup);
|
||||
|
||||
if (depForm->deptype == DEPENDENCY_INTERNAL)
|
||||
{
|
||||
/* No need to keep scanning */
|
||||
isdep = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
systable_endscan(scan);
|
||||
|
||||
heap_close(depRel, AccessShareLock);
|
||||
|
||||
return isdep;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust dependency record(s) to point to a different object of the same type
|
||||
*
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.3 2005/10/15 02:49:14 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.4 2005/11/21 12:49:30 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -16,11 +16,24 @@
|
||||
|
||||
#include "access/genam.h"
|
||||
#include "access/heapam.h"
|
||||
#include "utils/acl.h"
|
||||
#include "catalog/dependency.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/pg_authid.h"
|
||||
#include "catalog/pg_conversion.h"
|
||||
#include "catalog/pg_database.h"
|
||||
#include "catalog/pg_language.h"
|
||||
#include "catalog/pg_namespace.h"
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_shdepend.h"
|
||||
#include "catalog/pg_tablespace.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "commands/conversioncmds.h"
|
||||
#include "commands/defrem.h"
|
||||
#include "commands/schemacmds.h"
|
||||
#include "commands/tablecmds.h"
|
||||
#include "commands/typecmds.h"
|
||||
#include "lib/stringinfo.h"
|
||||
#include "miscadmin.h"
|
||||
#include "utils/fmgroids.h"
|
||||
@ -1042,3 +1055,251 @@ isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* shdepDropOwned
|
||||
*
|
||||
* Drop the objects owned by any one of the given RoleIds. If a role has
|
||||
* access to an object, the grant will be removed as well (but the object
|
||||
* will not, of course.)
|
||||
*/
|
||||
void
|
||||
shdepDropOwned(List *roleids, DropBehavior behavior)
|
||||
{
|
||||
Relation sdepRel;
|
||||
ListCell *cell;
|
||||
|
||||
sdepRel = heap_open(SharedDependRelationId, AccessExclusiveLock);
|
||||
|
||||
/*
|
||||
* For each role, find the dependent objects and drop them using the
|
||||
* regular (non-shared) dependency management.
|
||||
*/
|
||||
foreach(cell, roleids)
|
||||
{
|
||||
Oid roleid = lfirst_oid(cell);
|
||||
ScanKeyData key[2];
|
||||
SysScanDesc scan;
|
||||
HeapTuple tuple;
|
||||
|
||||
/* Doesn't work for pinned objects */
|
||||
if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
|
||||
{
|
||||
ObjectAddress obj;
|
||||
|
||||
obj.classId = AuthIdRelationId;
|
||||
obj.objectId = roleid;
|
||||
obj.objectSubId = 0;
|
||||
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
|
||||
errmsg("cannot drop objects owned by %s because they are "
|
||||
"required by the database system",
|
||||
getObjectDescription(&obj))));
|
||||
}
|
||||
|
||||
ScanKeyInit(&key[0],
|
||||
Anum_pg_shdepend_refclassid,
|
||||
BTEqualStrategyNumber, F_OIDEQ,
|
||||
ObjectIdGetDatum(AuthIdRelationId));
|
||||
ScanKeyInit(&key[1],
|
||||
Anum_pg_shdepend_refobjid,
|
||||
BTEqualStrategyNumber, F_OIDEQ,
|
||||
ObjectIdGetDatum(roleid));
|
||||
|
||||
scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
|
||||
SnapshotNow, 2, key);
|
||||
|
||||
while ((tuple = systable_getnext(scan)) != NULL)
|
||||
{
|
||||
Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
|
||||
|
||||
/* We only operate on objects on the current database */
|
||||
if (sdepForm->dbid != MyDatabaseId)
|
||||
continue;
|
||||
|
||||
switch (sdepForm->deptype)
|
||||
{
|
||||
ObjectAddress obj;
|
||||
GrantObjectType objtype;
|
||||
|
||||
/* Shouldn't happen */
|
||||
case SHARED_DEPENDENCY_PIN:
|
||||
case SHARED_DEPENDENCY_INVALID:
|
||||
elog(ERROR, "unexpected dependency type");
|
||||
break;
|
||||
case SHARED_DEPENDENCY_ACL:
|
||||
switch (sdepForm->classid)
|
||||
{
|
||||
case RelationRelationId:
|
||||
objtype = ACL_OBJECT_RELATION;
|
||||
break;
|
||||
case DatabaseRelationId:
|
||||
objtype = ACL_OBJECT_DATABASE;
|
||||
break;
|
||||
case ProcedureRelationId:
|
||||
objtype = ACL_OBJECT_FUNCTION;
|
||||
break;
|
||||
case LanguageRelationId:
|
||||
objtype = ACL_OBJECT_LANGUAGE;
|
||||
break;
|
||||
case NamespaceRelationId:
|
||||
objtype = ACL_OBJECT_NAMESPACE;
|
||||
break;
|
||||
case TableSpaceRelationId:
|
||||
objtype = ACL_OBJECT_TABLESPACE;
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "unexpected object type %d",
|
||||
sdepForm->classid);
|
||||
/* keep compiler quiet */
|
||||
objtype = (GrantObjectType) 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ExecGrantStmt_oids(false, objtype,
|
||||
list_make1_oid(sdepForm->objid), true,
|
||||
ACL_NO_RIGHTS, list_make1_oid(roleid),
|
||||
false, DROP_CASCADE);
|
||||
break;
|
||||
case SHARED_DEPENDENCY_OWNER:
|
||||
/*
|
||||
* If there's a regular (non-shared) dependency on this
|
||||
* object marked with DEPENDENCY_INTERNAL, skip this
|
||||
* object. We will drop the referencer object instead.
|
||||
*/
|
||||
if (objectIsInternalDependency(sdepForm->classid, sdepForm->objid))
|
||||
continue;
|
||||
|
||||
/* Drop the object */
|
||||
obj.classId = sdepForm->classid;
|
||||
obj.objectId = sdepForm->objid;
|
||||
obj.objectSubId = 0;
|
||||
performDeletion(&obj, behavior);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
systable_endscan(scan);
|
||||
}
|
||||
|
||||
heap_close(sdepRel, AccessExclusiveLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* shdepReassignOwned
|
||||
*
|
||||
* Change the owner of objects owned by any of the roles in roleids to
|
||||
* newrole. Grants are not touched.
|
||||
*/
|
||||
void
|
||||
shdepReassignOwned(List *roleids, Oid newrole)
|
||||
{
|
||||
Relation sdepRel;
|
||||
ListCell *cell;
|
||||
|
||||
sdepRel = heap_open(SharedDependRelationId, AccessShareLock);
|
||||
|
||||
foreach(cell, roleids)
|
||||
{
|
||||
SysScanDesc scan;
|
||||
ScanKeyData key[2];
|
||||
HeapTuple tuple;
|
||||
Oid roleid = lfirst_oid(cell);
|
||||
|
||||
/* Refuse to work on pinned roles */
|
||||
if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
|
||||
{
|
||||
ObjectAddress obj;
|
||||
|
||||
obj.classId = AuthIdRelationId;
|
||||
obj.objectId = roleid;
|
||||
obj.objectSubId = 0;
|
||||
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
|
||||
errmsg("cannot drop objects owned by %s because they are "
|
||||
"required by the database system",
|
||||
getObjectDescription(&obj))));
|
||||
/*
|
||||
* There's no need to tell the whole truth, which is that we
|
||||
* didn't track these dependencies at all ...
|
||||
*/
|
||||
}
|
||||
|
||||
ScanKeyInit(&key[0],
|
||||
Anum_pg_shdepend_refclassid,
|
||||
BTEqualStrategyNumber, F_OIDEQ,
|
||||
ObjectIdGetDatum(AuthIdRelationId));
|
||||
ScanKeyInit(&key[1],
|
||||
Anum_pg_shdepend_refobjid,
|
||||
BTEqualStrategyNumber, F_OIDEQ,
|
||||
ObjectIdGetDatum(roleid));
|
||||
|
||||
scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
|
||||
SnapshotNow, 2, key);
|
||||
|
||||
while ((tuple = systable_getnext(scan)) != NULL)
|
||||
{
|
||||
Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
|
||||
|
||||
/* We only operate on objects on the current database */
|
||||
if (sdepForm->dbid != MyDatabaseId)
|
||||
continue;
|
||||
|
||||
/* Unexpected because we checked for pins above */
|
||||
if (sdepForm->deptype == SHARED_DEPENDENCY_PIN)
|
||||
elog(ERROR, "unexpected shared pin");
|
||||
|
||||
/* We leave non-owner dependencies alone */
|
||||
if (sdepForm->deptype != SHARED_DEPENDENCY_OWNER)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If there's a regular (non-shared) dependency on this
|
||||
* object marked with DEPENDENCY_INTERNAL, skip this
|
||||
* object. We will alter the referencer object instead.
|
||||
*/
|
||||
if (objectIsInternalDependency(sdepForm->classid, sdepForm->objid))
|
||||
continue;
|
||||
|
||||
/* Issue the appropiate ALTER OWNER call */
|
||||
switch (sdepForm->classid)
|
||||
{
|
||||
case ConversionRelationId:
|
||||
AlterConversionOwner_oid(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
||||
case TypeRelationId:
|
||||
AlterTypeOwnerInternal(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
||||
case OperatorRelationId:
|
||||
AlterOperatorOwner_oid(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
||||
case NamespaceRelationId:
|
||||
AlterSchemaOwner_oid(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
||||
case RelationRelationId:
|
||||
ATExecChangeOwner(sdepForm->objid, newrole, false);
|
||||
break;
|
||||
|
||||
case ProcedureRelationId:
|
||||
AlterFunctionOwner_oid(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "unexpected classid %d", sdepForm->classid);
|
||||
break;
|
||||
}
|
||||
/* Make sure the next iteration will see my changes */
|
||||
CommandCounterIncrement();
|
||||
}
|
||||
|
||||
systable_endscan(scan);
|
||||
}
|
||||
|
||||
heap_close(sdepRel, AccessShareLock);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -1118,6 +1118,67 @@ GrantRole(GrantRoleStmt *stmt)
|
||||
auth_file_update_needed();
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
|
@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.318 2005/11/20 23:24:12 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.319 2005/11/21 12:49:31 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -2595,6 +2595,27 @@ _copyDeallocateStmt(DeallocateStmt *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static DropOwnedStmt *
|
||||
_copyDropOwnedStmt(DropOwnedStmt *from)
|
||||
{
|
||||
DropOwnedStmt *newnode = makeNode(DropOwnedStmt);
|
||||
|
||||
COPY_NODE_FIELD(roles);
|
||||
COPY_SCALAR_FIELD(behavior);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static ReassignOwnedStmt *
|
||||
_copyReassignOwnedStmt(ReassignOwnedStmt *from)
|
||||
{
|
||||
ReassignOwnedStmt *newnode = makeNode(ReassignOwnedStmt);
|
||||
|
||||
COPY_NODE_FIELD(roles);
|
||||
COPY_SCALAR_FIELD(newrole);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/* ****************************************************************
|
||||
* pg_list.h copy functions
|
||||
@ -3146,6 +3167,12 @@ copyObject(void *from)
|
||||
case T_DeallocateStmt:
|
||||
retval = _copyDeallocateStmt(from);
|
||||
break;
|
||||
case T_DropOwnedStmt:
|
||||
retval = _copyDropOwnedStmt(from);
|
||||
break;
|
||||
case T_ReassignOwnedStmt:
|
||||
retval = _copyReassignOwnedStmt(from);
|
||||
break;
|
||||
|
||||
case T_A_Expr:
|
||||
retval = _copyAExpr(from);
|
||||
|
@ -18,7 +18,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.255 2005/11/20 23:24:12 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.256 2005/11/21 12:49:31 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -1469,10 +1469,23 @@ _equalDeallocateStmt(DeallocateStmt *a, DeallocateStmt *b)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalDropOwnedStmt(DropOwnedStmt *a, DropOwnedStmt *b)
|
||||
{
|
||||
COMPARE_NODE_FIELD(roles);
|
||||
COMPARE_SCALAR_FIELD(behavior);
|
||||
|
||||
/*
|
||||
* stuff from parsenodes.h
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalReassignOwnedStmt(ReassignOwnedStmt *a, ReassignOwnedStmt *b)
|
||||
{
|
||||
COMPARE_NODE_FIELD(roles);
|
||||
COMPARE_NODE_FIELD(newrole);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalAExpr(A_Expr *a, A_Expr *b)
|
||||
@ -2188,6 +2201,13 @@ equal(void *a, void *b)
|
||||
case T_DeallocateStmt:
|
||||
retval = _equalDeallocateStmt(a, b);
|
||||
break;
|
||||
case T_DropOwnedStmt:
|
||||
retval = _equalDropOwnedStmt(a, b);
|
||||
break;
|
||||
|
||||
case T_ReassignOwnedStmt:
|
||||
retval = _equalReassignOwnedStmt(a, b);
|
||||
break;
|
||||
|
||||
case T_A_Expr:
|
||||
retval = _equalAExpr(a, b);
|
||||
|
@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.513 2005/11/19 17:39:44 adunstan Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.514 2005/11/21 12:49:31 alvherre Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@ -153,6 +153,7 @@ static void doNegateFloat(Value *v);
|
||||
VariableResetStmt VariableSetStmt VariableShowStmt
|
||||
ViewStmt CheckPointStmt CreateConversionStmt
|
||||
DeallocateStmt PrepareStmt ExecuteStmt
|
||||
DropOwnedStmt ReassignOwnedStmt
|
||||
|
||||
%type <node> select_no_parens select_with_parens select_clause
|
||||
simple_select
|
||||
@ -382,7 +383,7 @@ static void doNegateFloat(Value *v);
|
||||
NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NUMERIC
|
||||
|
||||
OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OR
|
||||
ORDER OUT_P OUTER_P OVERLAPS OVERLAY OWNER
|
||||
ORDER OUT_P OUTER_P OVERLAPS OVERLAY OWNED OWNER
|
||||
|
||||
PARTIAL PASSWORD PLACING POSITION
|
||||
PRECISION PRESERVE PREPARE PREPARED PRIMARY
|
||||
@ -390,7 +391,7 @@ static void doNegateFloat(Value *v);
|
||||
|
||||
QUOTE
|
||||
|
||||
READ REAL RECHECK REFERENCES REINDEX RELATIVE_P RELEASE RENAME
|
||||
READ REAL REASSIGN RECHECK REFERENCES REINDEX RELATIVE_P RELEASE RENAME
|
||||
REPEATABLE REPLACE RESET RESTART RESTRICT RETURNS REVOKE RIGHT
|
||||
ROLE ROLLBACK ROW ROWS RULE
|
||||
|
||||
@ -533,6 +534,7 @@ stmt :
|
||||
| DropCastStmt
|
||||
| DropGroupStmt
|
||||
| DropOpClassStmt
|
||||
| DropOwnedStmt
|
||||
| DropPLangStmt
|
||||
| DropRuleStmt
|
||||
| DropStmt
|
||||
@ -553,6 +555,7 @@ stmt :
|
||||
| LockStmt
|
||||
| NotifyStmt
|
||||
| PrepareStmt
|
||||
| ReassignOwnedStmt
|
||||
| ReindexStmt
|
||||
| RemoveAggrStmt
|
||||
| RemoveFuncStmt
|
||||
@ -2813,6 +2816,33 @@ DropOpClassStmt:
|
||||
}
|
||||
;
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* QUERY:
|
||||
*
|
||||
* DROP OWNED BY username [, username ...] [ RESTRICT | CASCADE ]
|
||||
* REASSIGN OWNED BY username [, username ...] TO username
|
||||
*
|
||||
*****************************************************************************/
|
||||
DropOwnedStmt:
|
||||
DROP OWNED BY name_list opt_drop_behavior
|
||||
{
|
||||
DropOwnedStmt *n = makeNode(DropOwnedStmt);
|
||||
n->roles = $4;
|
||||
n->behavior = $5;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
;
|
||||
|
||||
ReassignOwnedStmt:
|
||||
REASSIGN OWNED BY name_list TO name
|
||||
{
|
||||
ReassignOwnedStmt *n = makeNode(ReassignOwnedStmt);
|
||||
n->roles = $4;
|
||||
n->newrole = $6;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
;
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
@ -8222,6 +8252,7 @@ unreserved_keyword:
|
||||
| OIDS
|
||||
| OPERATOR
|
||||
| OPTION
|
||||
| OWNED
|
||||
| OWNER
|
||||
| PARTIAL
|
||||
| PASSWORD
|
||||
@ -8234,6 +8265,7 @@ unreserved_keyword:
|
||||
| PROCEDURE
|
||||
| QUOTE
|
||||
| READ
|
||||
| REASSIGN
|
||||
| RECHECK
|
||||
| REINDEX
|
||||
| RELATIVE_P
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.167 2005/11/19 17:39:44 adunstan Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.168 2005/11/21 12:49:32 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -252,6 +252,7 @@ static const ScanKeyword ScanKeywords[] = {
|
||||
{"outer", OUTER_P},
|
||||
{"overlaps", OVERLAPS},
|
||||
{"overlay", OVERLAY},
|
||||
{"owned", OWNED},
|
||||
{"owner", OWNER},
|
||||
{"partial", PARTIAL},
|
||||
{"password", PASSWORD},
|
||||
@ -269,6 +270,7 @@ static const ScanKeyword ScanKeywords[] = {
|
||||
{"quote", QUOTE},
|
||||
{"read", READ},
|
||||
{"real", REAL},
|
||||
{"reassign", REASSIGN},
|
||||
{"recheck", RECHECK},
|
||||
{"references", REFERENCES},
|
||||
{"reindex", REINDEX},
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.246 2005/11/19 17:39:45 adunstan Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.247 2005/11/21 12:49:32 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -347,6 +347,8 @@ check_xact_readonly(Node *parsetree)
|
||||
case T_GrantStmt:
|
||||
case T_GrantRoleStmt:
|
||||
case T_TruncateStmt:
|
||||
case T_DropOwnedStmt:
|
||||
case T_ReassignOwnedStmt:
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
|
||||
errmsg("transaction is read-only")));
|
||||
@ -725,8 +727,7 @@ ProcessUtility(Node *parsetree,
|
||||
break;
|
||||
|
||||
/*
|
||||
* ******************************** object creation / destruction ********************************
|
||||
*
|
||||
* **************** object creation / destruction ******************
|
||||
*/
|
||||
case T_DefineStmt:
|
||||
{
|
||||
@ -1019,6 +1020,14 @@ ProcessUtility(Node *parsetree,
|
||||
DropRole((DropRoleStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_DropOwnedStmt:
|
||||
DropOwnedObjects((DropOwnedStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_ReassignOwnedStmt:
|
||||
ReassignOwnedObjects((ReassignOwnedStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_LockStmt:
|
||||
LockTableCommand((LockStmt *) parsetree);
|
||||
break;
|
||||
@ -1677,6 +1686,14 @@ CreateCommandTag(Node *parsetree)
|
||||
tag = "DROP ROLE";
|
||||
break;
|
||||
|
||||
case T_DropOwnedStmt:
|
||||
tag = "DROP OWNED";
|
||||
break;
|
||||
|
||||
case T_ReassignOwnedStmt:
|
||||
tag = "REASSIGN OWNED";
|
||||
break;
|
||||
|
||||
case T_LockStmt:
|
||||
tag = "LOCK TABLE";
|
||||
break;
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.17 2005/10/15 02:49:42 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.18 2005/11/21 12:49:32 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -177,6 +177,8 @@ extern long changeDependencyFor(Oid classId, Oid objectId,
|
||||
Oid refClassId, Oid oldRefObjectId,
|
||||
Oid newRefObjectId);
|
||||
|
||||
extern bool objectIsInternalDependency(Oid classId, Oid objectId);
|
||||
|
||||
/* in pg_shdepend.c */
|
||||
|
||||
extern void recordSharedDependencyOn(ObjectAddress *depender,
|
||||
@ -201,4 +203,8 @@ extern void copyTemplateDependencies(Oid templateDbId, Oid newDbId);
|
||||
|
||||
extern void dropDatabaseDependencies(Oid databaseId);
|
||||
|
||||
extern void shdepDropOwned(List *relids, DropBehavior behavior);
|
||||
|
||||
extern void shdepReassignOwned(List *relids, Oid newrole);
|
||||
|
||||
#endif /* DEPENDENCY_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/commands/conversioncmds.h,v 1.11 2005/11/19 17:39:45 adunstan Exp $
|
||||
* $PostgreSQL: pgsql/src/include/commands/conversioncmds.h,v 1.12 2005/11/21 12:49:32 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -22,5 +22,6 @@ extern void DropConversionCommand(List *conversion_name,
|
||||
DropBehavior behavior, bool missing_ok);
|
||||
extern void RenameConversion(List *name, const char *newname);
|
||||
extern void AlterConversionOwner(List *name, Oid newOwnerId);
|
||||
extern void AlterConversionOwner_oid(Oid conversionOid, Oid newOwnerId);
|
||||
|
||||
#endif /* CONVERSIONCMDS_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.68 2005/10/15 02:49:44 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.69 2005/11/21 12:49:32 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -51,6 +51,7 @@ extern void SetFunctionReturnType(Oid funcOid, Oid newRetType);
|
||||
extern void SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType);
|
||||
extern void RenameFunction(List *name, List *argtypes, const char *newname);
|
||||
extern void AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId);
|
||||
extern void AlterFunctionOwner_oid(Oid procOid, Oid newOwnerId);
|
||||
extern void AlterFunction(AlterFunctionStmt *stmt);
|
||||
extern void CreateCast(CreateCastStmt *stmt);
|
||||
extern void DropCast(DropCastStmt *stmt);
|
||||
@ -64,6 +65,7 @@ extern void RemoveOperator(RemoveOperStmt *stmt);
|
||||
extern void RemoveOperatorById(Oid operOid);
|
||||
extern void AlterOperatorOwner(List *name, TypeName *typeName1,
|
||||
TypeName *typename2, Oid newOwnerId);
|
||||
extern void AlterOperatorOwner_oid(Oid operOid, Oid newOwnerId);
|
||||
|
||||
/* commands/aggregatecmds.c */
|
||||
extern void DefineAggregate(List *names, List *parameters);
|
||||
@ -77,6 +79,7 @@ extern void RemoveOpClass(RemoveOpClassStmt *stmt);
|
||||
extern void RemoveOpClassById(Oid opclassOid);
|
||||
extern void RenameOpClass(List *name, const char *access_method, const char *newname);
|
||||
extern void AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId);
|
||||
extern void AlterOpClassOwner_oid(Oid opcOid, Oid newOwnerId);
|
||||
|
||||
/* support routines in commands/define.c */
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/commands/schemacmds.h,v 1.11 2005/11/19 17:39:45 adunstan Exp $
|
||||
* $PostgreSQL: pgsql/src/include/commands/schemacmds.h,v 1.12 2005/11/21 12:49:32 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -24,5 +24,6 @@ extern void RemoveSchemaById(Oid schemaOid);
|
||||
|
||||
extern void RenameSchema(const char *oldname, const char *newname);
|
||||
extern void AlterSchemaOwner(const char *name, Oid newOwnerId);
|
||||
extern void AlterSchemaOwner_oid(const Oid schemaOid, Oid newOwnerId);
|
||||
|
||||
#endif /* SCHEMACMDS_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/commands/tablecmds.h,v 1.24 2005/10/15 02:49:44 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/commands/tablecmds.h,v 1.25 2005/11/21 12:49:32 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -24,6 +24,8 @@ extern void RemoveRelation(const RangeVar *relation, DropBehavior behavior);
|
||||
|
||||
extern void AlterTable(AlterTableStmt *stmt);
|
||||
|
||||
extern void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing);
|
||||
|
||||
extern void AlterTableInternal(Oid relid, List *cmds, bool recurse);
|
||||
|
||||
extern void AlterTableCreateToastTable(Oid relOid, bool silent);
|
||||
|
@ -4,7 +4,7 @@
|
||||
* Commands for manipulating roles (formerly called users).
|
||||
*
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/commands/user.h,v 1.27 2005/06/28 05:09:12 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/commands/user.h,v 1.28 2005/11/21 12:49:32 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -20,5 +20,7 @@ extern void AlterRoleSet(AlterRoleSetStmt *stmt);
|
||||
extern void DropRole(DropRoleStmt *stmt);
|
||||
extern void GrantRole(GrantRoleStmt *stmt);
|
||||
extern void RenameRole(const char *oldname, const char *newname);
|
||||
extern void DropOwnedObjects(DropOwnedStmt *stmt);
|
||||
extern void ReassignOwnedObjects(ReassignOwnedStmt *stmt);
|
||||
|
||||
#endif /* USER_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.176 2005/10/15 02:49:45 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.177 2005/11/21 12:49:32 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -286,6 +286,8 @@ typedef enum NodeTag
|
||||
T_DropTableSpaceStmt,
|
||||
T_AlterObjectSchemaStmt,
|
||||
T_AlterOwnerStmt,
|
||||
T_DropOwnedStmt,
|
||||
T_ReassignOwnedStmt,
|
||||
|
||||
T_A_Expr = 800,
|
||||
T_ColumnRef,
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.293 2005/11/19 17:39:45 adunstan Exp $
|
||||
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.294 2005/11/21 12:49:32 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -1875,4 +1875,24 @@ typedef struct DeallocateStmt
|
||||
char *name; /* The name of the plan to remove */
|
||||
} DeallocateStmt;
|
||||
|
||||
/*
|
||||
* DROP OWNED statement
|
||||
*/
|
||||
typedef struct DropOwnedStmt
|
||||
{
|
||||
NodeTag type;
|
||||
List *roles;
|
||||
DropBehavior behavior;
|
||||
} DropOwnedStmt;
|
||||
|
||||
/*
|
||||
* REASSIGN OWNED statement
|
||||
*/
|
||||
typedef struct ReassignOwnedStmt
|
||||
{
|
||||
NodeTag type;
|
||||
List *roles;
|
||||
char *newrole;
|
||||
} ReassignOwnedStmt;
|
||||
|
||||
#endif /* PARSENODES_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.88 2005/11/18 02:38:24 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.89 2005/11/21 12:49:33 alvherre Exp $
|
||||
*
|
||||
* NOTES
|
||||
* An ACL array is simply an array of AclItems, representing the union
|
||||
@ -221,6 +221,9 @@ extern Datum hash_aclitem(PG_FUNCTION_ARGS);
|
||||
* prototypes for functions in aclchk.c
|
||||
*/
|
||||
extern void ExecuteGrantStmt(GrantStmt *stmt);
|
||||
extern void ExecGrantStmt_oids(bool is_grant, GrantObjectType objtype,
|
||||
List *objects, bool all_privs, AclMode privileges,
|
||||
List *grantees, bool grant_option, DropBehavior behavior);
|
||||
|
||||
extern AclMode pg_class_aclmask(Oid table_oid, Oid roleid,
|
||||
AclMode mask, AclMaskHow how);
|
||||
|
@ -38,6 +38,76 @@ DROP USER regression_user2;
|
||||
ALTER TABLE deptest OWNER TO regression_user3;
|
||||
DROP USER regression_user3;
|
||||
ERROR: role "regression_user3" cannot be dropped because some objects depend on it
|
||||
\set VERBOSITY default
|
||||
-- if we drop the object, we can drop the user too
|
||||
DROP TABLE deptest;
|
||||
DROP USER regression_user3;
|
||||
-- Test DROP OWNED
|
||||
CREATE USER regression_user0;
|
||||
CREATE USER regression_user1;
|
||||
CREATE USER regression_user2;
|
||||
SET SESSION AUTHORIZATION regression_user0;
|
||||
-- permission denied
|
||||
DROP OWNED BY regression_user1;
|
||||
ERROR: permission denied to drop objects
|
||||
DROP OWNED BY regression_user0, regression_user2;
|
||||
ERROR: permission denied to drop objects
|
||||
REASSIGN OWNED BY regression_user0 TO regression_user1;
|
||||
ERROR: permission denied to reassign objects
|
||||
REASSIGN OWNED BY regression_user1 TO regression_user0;
|
||||
ERROR: permission denied to reassign objects
|
||||
-- this one is allowed
|
||||
DROP OWNED BY regression_user0;
|
||||
CREATE TABLE deptest1 ();
|
||||
GRANT ALL ON deptest1 TO regression_user1 WITH GRANT OPTION;
|
||||
SET SESSION AUTHORIZATION regression_user1;
|
||||
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"
|
||||
GRANT ALL ON deptest1 TO regression_user2;
|
||||
RESET SESSION AUTHORIZATION;
|
||||
\z deptest1
|
||||
Access privileges for database "regression"
|
||||
Schema | Name | Type | Access privileges
|
||||
--------+----------+-------+----------------------------------------------------------------------------------------------------------------------------------------
|
||||
public | deptest1 | table | {regression_user0=arwdRxt/regression_user0,regression_user1=a*r*w*d*R*x*t*/regression_user0,regression_user2=arwdRxt/regression_user1}
|
||||
(1 row)
|
||||
|
||||
DROP OWNED BY regression_user1;
|
||||
-- all grants revoked
|
||||
\z deptest1
|
||||
Access privileges for database "regression"
|
||||
Schema | Name | Type | Access privileges
|
||||
--------+----------+-------+---------------------------------------------
|
||||
public | deptest1 | table | {regression_user0=arwdRxt/regression_user0}
|
||||
(1 row)
|
||||
|
||||
-- table was dropped
|
||||
\d deptest
|
||||
-- Test REASSIGN OWNED
|
||||
GRANT ALL ON deptest1 TO regression_user1;
|
||||
SET SESSION AUTHORIZATION regression_user1;
|
||||
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"
|
||||
RESET SESSION AUTHORIZATION;
|
||||
REASSIGN OWNED BY regression_user1 TO regression_user2;
|
||||
\dt deptest
|
||||
List of relations
|
||||
Schema | Name | Type | Owner
|
||||
--------+---------+-------+------------------
|
||||
public | deptest | table | regression_user2
|
||||
(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: access to table deptest1
|
||||
DROP OWNED BY regression_user1;
|
||||
DROP USER regression_user1;
|
||||
\set VERBOSITY terse
|
||||
DROP USER regression_user2;
|
||||
ERROR: role "regression_user2" cannot be dropped because some objects depend on it
|
||||
DROP OWNED BY regression_user2, regression_user0;
|
||||
DROP USER regression_user2;
|
||||
DROP USER regression_user0;
|
||||
|
@ -39,6 +39,55 @@ DROP USER regression_user2;
|
||||
ALTER TABLE deptest OWNER TO regression_user3;
|
||||
DROP USER regression_user3;
|
||||
|
||||
\set VERBOSITY default
|
||||
-- if we drop the object, we can drop the user too
|
||||
DROP TABLE deptest;
|
||||
DROP USER regression_user3;
|
||||
|
||||
-- Test DROP OWNED
|
||||
CREATE USER regression_user0;
|
||||
CREATE USER regression_user1;
|
||||
CREATE USER regression_user2;
|
||||
SET SESSION AUTHORIZATION regression_user0;
|
||||
-- permission denied
|
||||
DROP OWNED BY regression_user1;
|
||||
DROP OWNED BY regression_user0, regression_user2;
|
||||
REASSIGN OWNED BY regression_user0 TO regression_user1;
|
||||
REASSIGN OWNED BY regression_user1 TO regression_user0;
|
||||
-- this one is allowed
|
||||
DROP OWNED BY regression_user0;
|
||||
|
||||
CREATE TABLE deptest1 ();
|
||||
GRANT ALL ON deptest1 TO regression_user1 WITH GRANT OPTION;
|
||||
|
||||
SET SESSION AUTHORIZATION regression_user1;
|
||||
CREATE TABLE deptest (a serial primary key, b text);
|
||||
GRANT ALL ON deptest1 TO regression_user2;
|
||||
RESET SESSION AUTHORIZATION;
|
||||
\z deptest1
|
||||
|
||||
DROP OWNED BY regression_user1;
|
||||
-- all grants revoked
|
||||
\z deptest1
|
||||
-- table was dropped
|
||||
\d deptest
|
||||
|
||||
-- Test REASSIGN OWNED
|
||||
GRANT ALL ON deptest1 TO regression_user1;
|
||||
|
||||
SET SESSION AUTHORIZATION regression_user1;
|
||||
CREATE TABLE deptest (a serial primary key, b text);
|
||||
RESET SESSION AUTHORIZATION;
|
||||
|
||||
REASSIGN OWNED BY regression_user1 TO regression_user2;
|
||||
\dt deptest
|
||||
-- doesn't work: grant still exists
|
||||
DROP USER regression_user1;
|
||||
DROP OWNED BY regression_user1;
|
||||
DROP USER regression_user1;
|
||||
|
||||
\set VERBOSITY terse
|
||||
DROP USER regression_user2;
|
||||
DROP OWNED BY regression_user2, regression_user0;
|
||||
DROP USER regression_user2;
|
||||
DROP USER regression_user0;
|
||||
|
Loading…
Reference in New Issue
Block a user