mirror of
https://github.com/postgres/postgres.git
synced 2025-11-09 06:21:09 +03:00
Track dependencies on shared objects (which is to say, roles; we already
have adequate mechanisms for tracking the contents of databases and tablespaces). This solves the longstanding problem that you can drop a user who still owns objects and/or has access permissions. Alvaro Herrera, with some kibitzing from Tom Lane.
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Makefile for backend/catalog
|
||||
#
|
||||
# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.54 2005/06/28 05:08:52 tgl Exp $
|
||||
# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.55 2005/07/07 20:39:57 tgl Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@@ -12,7 +12,8 @@ include $(top_builddir)/src/Makefile.global
|
||||
|
||||
OBJS = catalog.o dependency.o heap.o index.o indexing.o namespace.o aclchk.o \
|
||||
pg_aggregate.o pg_constraint.o pg_conversion.o pg_depend.o \
|
||||
pg_largeobject.o pg_namespace.o pg_operator.o pg_proc.o pg_type.o
|
||||
pg_largeobject.o pg_namespace.o pg_operator.o pg_proc.o pg_shdepend.o \
|
||||
pg_type.o
|
||||
|
||||
BKIFILES = postgres.bki postgres.description
|
||||
|
||||
@@ -31,7 +32,7 @@ POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\
|
||||
pg_operator.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
|
||||
pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \
|
||||
pg_rewrite.h pg_trigger.h pg_listener.h pg_description.h pg_cast.h \
|
||||
pg_namespace.h pg_conversion.h pg_database.h \
|
||||
pg_namespace.h pg_conversion.h pg_database.h pg_shdepend.h \
|
||||
pg_authid.h pg_auth_members.h pg_tablespace.h pg_depend.h \
|
||||
indexing.h \
|
||||
)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.114 2005/06/28 19:51:21 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.115 2005/07/07 20:39:57 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* See acl.h.
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/catalog.h"
|
||||
#include "catalog/dependency.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/namespace.h"
|
||||
#include "catalog/pg_auth_members.h"
|
||||
@@ -252,6 +253,10 @@ ExecuteGrantStmt_Relation(GrantStmt *stmt)
|
||||
Datum values[Natts_pg_class];
|
||||
char nulls[Natts_pg_class];
|
||||
char replaces[Natts_pg_class];
|
||||
int noldmembers;
|
||||
int nnewmembers;
|
||||
Oid *oldmembers;
|
||||
Oid *newmembers;
|
||||
|
||||
/* open pg_class */
|
||||
relation = heap_open(RelationRelationId, RowExclusiveLock);
|
||||
@@ -344,11 +349,19 @@ ExecuteGrantStmt_Relation(GrantStmt *stmt)
|
||||
/* get a detoasted copy of the ACL */
|
||||
old_acl = DatumGetAclPCopy(aclDatum);
|
||||
|
||||
/*
|
||||
* We need the members of both old and new ACLs so we can correct
|
||||
* the shared dependency information.
|
||||
*/
|
||||
noldmembers = aclmembers(old_acl, &oldmembers);
|
||||
|
||||
new_acl = merge_acl_with_grant(old_acl, stmt->is_grant,
|
||||
stmt->grant_option, stmt->behavior,
|
||||
stmt->grantees, this_privileges,
|
||||
grantorId, ownerId);
|
||||
|
||||
nnewmembers = aclmembers(new_acl, &newmembers);
|
||||
|
||||
/* finished building new ACL value, now insert it */
|
||||
MemSet(values, 0, sizeof(values));
|
||||
MemSet(nulls, ' ', sizeof(nulls));
|
||||
@@ -359,13 +372,19 @@ ExecuteGrantStmt_Relation(GrantStmt *stmt)
|
||||
|
||||
newtuple = heap_modifytuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
simple_heap_update(relation, &newtuple->t_self, newtuple);
|
||||
|
||||
/* keep the catalog indexes up to date */
|
||||
CatalogUpdateIndexes(relation, newtuple);
|
||||
|
||||
/* Update the shared dependency ACL info */
|
||||
updateAclDependencies(RelationRelationId, relOid,
|
||||
ownerId, stmt->is_grant,
|
||||
noldmembers, oldmembers,
|
||||
nnewmembers, newmembers);
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
pfree(new_acl);
|
||||
|
||||
heap_close(relation, RowExclusiveLock);
|
||||
@@ -422,6 +441,10 @@ ExecuteGrantStmt_Database(GrantStmt *stmt)
|
||||
Datum values[Natts_pg_database];
|
||||
char nulls[Natts_pg_database];
|
||||
char replaces[Natts_pg_database];
|
||||
int noldmembers;
|
||||
int nnewmembers;
|
||||
Oid *oldmembers;
|
||||
Oid *newmembers;
|
||||
|
||||
relation = heap_open(DatabaseRelationId, RowExclusiveLock);
|
||||
ScanKeyInit(&entry[0],
|
||||
@@ -503,11 +526,19 @@ ExecuteGrantStmt_Database(GrantStmt *stmt)
|
||||
/* get a detoasted copy of the ACL */
|
||||
old_acl = DatumGetAclPCopy(aclDatum);
|
||||
|
||||
/*
|
||||
* We need the members of both old and new ACLs so we can correct
|
||||
* the shared dependency information.
|
||||
*/
|
||||
noldmembers = aclmembers(old_acl, &oldmembers);
|
||||
|
||||
new_acl = merge_acl_with_grant(old_acl, stmt->is_grant,
|
||||
stmt->grant_option, stmt->behavior,
|
||||
stmt->grantees, this_privileges,
|
||||
grantorId, ownerId);
|
||||
|
||||
nnewmembers = aclmembers(new_acl, &newmembers);
|
||||
|
||||
/* finished building new ACL value, now insert it */
|
||||
MemSet(values, 0, sizeof(values));
|
||||
MemSet(nulls, ' ', sizeof(nulls));
|
||||
@@ -523,6 +554,12 @@ ExecuteGrantStmt_Database(GrantStmt *stmt)
|
||||
/* keep the catalog indexes up to date */
|
||||
CatalogUpdateIndexes(relation, newtuple);
|
||||
|
||||
/* Update the shared dependency ACL info */
|
||||
updateAclDependencies(DatabaseRelationId, HeapTupleGetOid(tuple),
|
||||
ownerId, stmt->is_grant,
|
||||
noldmembers, oldmembers,
|
||||
nnewmembers, newmembers);
|
||||
|
||||
pfree(new_acl);
|
||||
|
||||
heap_endscan(scan);
|
||||
@@ -580,6 +617,10 @@ ExecuteGrantStmt_Function(GrantStmt *stmt)
|
||||
Datum values[Natts_pg_proc];
|
||||
char nulls[Natts_pg_proc];
|
||||
char replaces[Natts_pg_proc];
|
||||
int noldmembers;
|
||||
int nnewmembers;
|
||||
Oid *oldmembers;
|
||||
Oid *newmembers;
|
||||
|
||||
oid = LookupFuncNameTypeNames(func->funcname, func->funcargs, false);
|
||||
|
||||
@@ -658,11 +699,19 @@ ExecuteGrantStmt_Function(GrantStmt *stmt)
|
||||
/* get a detoasted copy of the ACL */
|
||||
old_acl = DatumGetAclPCopy(aclDatum);
|
||||
|
||||
/*
|
||||
* We need the members of both old and new ACLs so we can correct
|
||||
* the shared dependency information.
|
||||
*/
|
||||
noldmembers = aclmembers(old_acl, &oldmembers);
|
||||
|
||||
new_acl = merge_acl_with_grant(old_acl, stmt->is_grant,
|
||||
stmt->grant_option, stmt->behavior,
|
||||
stmt->grantees, this_privileges,
|
||||
grantorId, ownerId);
|
||||
|
||||
nnewmembers = aclmembers(new_acl, &newmembers);
|
||||
|
||||
/* finished building new ACL value, now insert it */
|
||||
MemSet(values, 0, sizeof(values));
|
||||
MemSet(nulls, ' ', sizeof(nulls));
|
||||
@@ -673,13 +722,19 @@ ExecuteGrantStmt_Function(GrantStmt *stmt)
|
||||
|
||||
newtuple = heap_modifytuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
simple_heap_update(relation, &newtuple->t_self, newtuple);
|
||||
|
||||
/* keep the catalog indexes up to date */
|
||||
CatalogUpdateIndexes(relation, newtuple);
|
||||
|
||||
/* Update the shared dependency ACL info */
|
||||
updateAclDependencies(ProcedureRelationId, oid,
|
||||
ownerId, stmt->is_grant,
|
||||
noldmembers, oldmembers,
|
||||
nnewmembers, newmembers);
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
pfree(new_acl);
|
||||
|
||||
heap_close(relation, RowExclusiveLock);
|
||||
@@ -734,6 +789,10 @@ ExecuteGrantStmt_Language(GrantStmt *stmt)
|
||||
Datum values[Natts_pg_language];
|
||||
char nulls[Natts_pg_language];
|
||||
char replaces[Natts_pg_language];
|
||||
int noldmembers;
|
||||
int nnewmembers;
|
||||
Oid *oldmembers;
|
||||
Oid *newmembers;
|
||||
|
||||
relation = heap_open(LanguageRelationId, RowExclusiveLock);
|
||||
tuple = SearchSysCache(LANGNAME,
|
||||
@@ -822,11 +881,19 @@ ExecuteGrantStmt_Language(GrantStmt *stmt)
|
||||
/* get a detoasted copy of the ACL */
|
||||
old_acl = DatumGetAclPCopy(aclDatum);
|
||||
|
||||
/*
|
||||
* We need the members of both old and new ACLs so we can correct
|
||||
* the shared dependency information.
|
||||
*/
|
||||
noldmembers = aclmembers(old_acl, &oldmembers);
|
||||
|
||||
new_acl = merge_acl_with_grant(old_acl, stmt->is_grant,
|
||||
stmt->grant_option, stmt->behavior,
|
||||
stmt->grantees, this_privileges,
|
||||
grantorId, ownerId);
|
||||
|
||||
nnewmembers = aclmembers(new_acl, &newmembers);
|
||||
|
||||
/* finished building new ACL value, now insert it */
|
||||
MemSet(values, 0, sizeof(values));
|
||||
MemSet(nulls, ' ', sizeof(nulls));
|
||||
@@ -837,13 +904,19 @@ ExecuteGrantStmt_Language(GrantStmt *stmt)
|
||||
|
||||
newtuple = heap_modifytuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
simple_heap_update(relation, &newtuple->t_self, newtuple);
|
||||
|
||||
/* keep the catalog indexes up to date */
|
||||
CatalogUpdateIndexes(relation, newtuple);
|
||||
|
||||
/* Update the shared dependency ACL info */
|
||||
updateAclDependencies(LanguageRelationId, HeapTupleGetOid(tuple),
|
||||
ownerId, stmt->is_grant,
|
||||
noldmembers, oldmembers,
|
||||
nnewmembers, newmembers);
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
pfree(new_acl);
|
||||
|
||||
heap_close(relation, RowExclusiveLock);
|
||||
@@ -898,6 +971,10 @@ ExecuteGrantStmt_Namespace(GrantStmt *stmt)
|
||||
Datum values[Natts_pg_namespace];
|
||||
char nulls[Natts_pg_namespace];
|
||||
char replaces[Natts_pg_namespace];
|
||||
int noldmembers;
|
||||
int nnewmembers;
|
||||
Oid *oldmembers;
|
||||
Oid *newmembers;
|
||||
|
||||
relation = heap_open(NamespaceRelationId, RowExclusiveLock);
|
||||
tuple = SearchSysCache(NAMESPACENAME,
|
||||
@@ -977,11 +1054,19 @@ ExecuteGrantStmt_Namespace(GrantStmt *stmt)
|
||||
/* get a detoasted copy of the ACL */
|
||||
old_acl = DatumGetAclPCopy(aclDatum);
|
||||
|
||||
/*
|
||||
* We need the members of both old and new ACLs so we can correct
|
||||
* the shared dependency information.
|
||||
*/
|
||||
noldmembers = aclmembers(old_acl, &oldmembers);
|
||||
|
||||
new_acl = merge_acl_with_grant(old_acl, stmt->is_grant,
|
||||
stmt->grant_option, stmt->behavior,
|
||||
stmt->grantees, this_privileges,
|
||||
grantorId, ownerId);
|
||||
|
||||
nnewmembers = aclmembers(new_acl, &newmembers);
|
||||
|
||||
/* finished building new ACL value, now insert it */
|
||||
MemSet(values, 0, sizeof(values));
|
||||
MemSet(nulls, ' ', sizeof(nulls));
|
||||
@@ -992,13 +1077,19 @@ ExecuteGrantStmt_Namespace(GrantStmt *stmt)
|
||||
|
||||
newtuple = heap_modifytuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
simple_heap_update(relation, &newtuple->t_self, newtuple);
|
||||
|
||||
/* keep the catalog indexes up to date */
|
||||
CatalogUpdateIndexes(relation, newtuple);
|
||||
|
||||
/* Update the shared dependency ACL info */
|
||||
updateAclDependencies(NamespaceRelationId, HeapTupleGetOid(tuple),
|
||||
ownerId, stmt->is_grant,
|
||||
noldmembers, oldmembers,
|
||||
nnewmembers, newmembers);
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
pfree(new_acl);
|
||||
|
||||
heap_close(relation, RowExclusiveLock);
|
||||
@@ -1055,6 +1146,10 @@ ExecuteGrantStmt_Tablespace(GrantStmt *stmt)
|
||||
Datum values[Natts_pg_tablespace];
|
||||
char nulls[Natts_pg_tablespace];
|
||||
char replaces[Natts_pg_tablespace];
|
||||
int noldmembers;
|
||||
int nnewmembers;
|
||||
Oid *oldmembers;
|
||||
Oid *newmembers;
|
||||
|
||||
relation = heap_open(TableSpaceRelationId, RowExclusiveLock);
|
||||
ScanKeyInit(&entry[0],
|
||||
@@ -1136,11 +1231,19 @@ ExecuteGrantStmt_Tablespace(GrantStmt *stmt)
|
||||
/* get a detoasted copy of the ACL */
|
||||
old_acl = DatumGetAclPCopy(aclDatum);
|
||||
|
||||
/*
|
||||
* We need the members of both old and new ACLs so we can correct
|
||||
* the shared dependency information.
|
||||
*/
|
||||
noldmembers = aclmembers(old_acl, &oldmembers);
|
||||
|
||||
new_acl = merge_acl_with_grant(old_acl, stmt->is_grant,
|
||||
stmt->grant_option, stmt->behavior,
|
||||
stmt->grantees, this_privileges,
|
||||
grantorId, ownerId);
|
||||
|
||||
nnewmembers = aclmembers(new_acl, &newmembers);
|
||||
|
||||
/* finished building new ACL value, now insert it */
|
||||
MemSet(values, 0, sizeof(values));
|
||||
MemSet(nulls, ' ', sizeof(nulls));
|
||||
@@ -1156,6 +1259,12 @@ ExecuteGrantStmt_Tablespace(GrantStmt *stmt)
|
||||
/* keep the catalog indexes up to date */
|
||||
CatalogUpdateIndexes(relation, newtuple);
|
||||
|
||||
/* Update the shared dependency ACL info */
|
||||
updateAclDependencies(TableSpaceRelationId, HeapTupleGetOid(tuple),
|
||||
ownerId, stmt->is_grant,
|
||||
noldmembers, oldmembers,
|
||||
nnewmembers, newmembers);
|
||||
|
||||
pfree(new_acl);
|
||||
|
||||
heap_endscan(scan);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.44 2005/04/14 20:03:23 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.45 2005/07/07 20:39:57 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -22,9 +22,11 @@
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/namespace.h"
|
||||
#include "catalog/pg_attrdef.h"
|
||||
#include "catalog/pg_authid.h"
|
||||
#include "catalog/pg_cast.h"
|
||||
#include "catalog/pg_constraint.h"
|
||||
#include "catalog/pg_conversion.h"
|
||||
#include "catalog/pg_database.h"
|
||||
#include "catalog/pg_depend.h"
|
||||
#include "catalog/pg_language.h"
|
||||
#include "catalog/pg_namespace.h"
|
||||
@@ -32,12 +34,15 @@
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_rewrite.h"
|
||||
#include "catalog/pg_tablespace.h"
|
||||
#include "catalog/pg_trigger.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "commands/comment.h"
|
||||
#include "commands/dbcommands.h"
|
||||
#include "commands/defrem.h"
|
||||
#include "commands/proclang.h"
|
||||
#include "commands/schemacmds.h"
|
||||
#include "commands/tablespace.h"
|
||||
#include "commands/trigger.h"
|
||||
#include "commands/typecmds.h"
|
||||
#include "lib/stringinfo.h"
|
||||
@@ -509,6 +514,7 @@ recursiveDeletion(const ObjectAddress *object,
|
||||
break;
|
||||
}
|
||||
|
||||
/* delete the pg_depend tuple */
|
||||
simple_heap_delete(depRel, &tup->t_self);
|
||||
}
|
||||
|
||||
@@ -584,6 +590,14 @@ recursiveDeletion(const ObjectAddress *object,
|
||||
*/
|
||||
DeleteComments(object->objectId, object->classId, object->objectSubId);
|
||||
|
||||
/*
|
||||
* Delete shared dependency references related to this object.
|
||||
* Sub-objects (columns) don't have dependencies on global objects,
|
||||
* so skip them.
|
||||
*/
|
||||
if (object->objectSubId == 0)
|
||||
deleteSharedDependencyRecordsFor(object->classId, object->objectId);
|
||||
|
||||
/*
|
||||
* CommandCounterIncrement here to ensure that preceding changes are
|
||||
* all visible.
|
||||
@@ -1365,6 +1379,18 @@ getObjectClass(const ObjectAddress *object)
|
||||
case NamespaceRelationId:
|
||||
Assert(object->objectSubId == 0);
|
||||
return OCLASS_SCHEMA;
|
||||
|
||||
case AuthIdRelationId:
|
||||
Assert(object->objectSubId == 0);
|
||||
return OCLASS_ROLE;
|
||||
|
||||
case DatabaseRelationId:
|
||||
Assert(object->objectSubId == 0);
|
||||
return OCLASS_DATABASE;
|
||||
|
||||
case TableSpaceRelationId:
|
||||
Assert(object->objectSubId == 0);
|
||||
return OCLASS_TBLSPACE;
|
||||
}
|
||||
|
||||
/* shouldn't get here */
|
||||
@@ -1680,6 +1706,37 @@ getObjectDescription(const ObjectAddress *object)
|
||||
break;
|
||||
}
|
||||
|
||||
case OCLASS_ROLE:
|
||||
{
|
||||
appendStringInfo(&buffer, _("role %s"),
|
||||
GetUserNameFromId(object->objectId));
|
||||
break;
|
||||
}
|
||||
|
||||
case OCLASS_DATABASE:
|
||||
{
|
||||
char *datname;
|
||||
|
||||
datname = get_database_name(object->objectId);
|
||||
if (!datname)
|
||||
elog(ERROR, "cache lookup failed for database %u",
|
||||
object->objectId);
|
||||
appendStringInfo(&buffer, _("database %s"), datname);
|
||||
break;
|
||||
}
|
||||
|
||||
case OCLASS_TBLSPACE:
|
||||
{
|
||||
char *tblspace;
|
||||
|
||||
tblspace = get_tablespace_name(object->objectId);
|
||||
if (!tblspace)
|
||||
elog(ERROR, "cache lookup failed for tablespace %u",
|
||||
object->objectId);
|
||||
appendStringInfo(&buffer, _("tablespace %s"), tblspace);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
appendStringInfo(&buffer, "unrecognized object %u %u %d",
|
||||
object->classId,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.285 2005/06/05 00:38:07 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.286 2005/07/07 20:39:57 tgl Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@@ -755,6 +755,8 @@ heap_create_with_catalog(const char *relname,
|
||||
* make a dependency link to force the relation to be deleted if its
|
||||
* namespace is. Skip this in bootstrap mode, since we don't make
|
||||
* dependencies while bootstrapping.
|
||||
*
|
||||
* Also make a dependency link to its owner.
|
||||
*/
|
||||
if (!IsBootstrapProcessingMode())
|
||||
{
|
||||
@@ -768,6 +770,8 @@ heap_create_with_catalog(const char *relname,
|
||||
referenced.objectId = relnamespace;
|
||||
referenced.objectSubId = 0;
|
||||
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
||||
|
||||
recordDependencyOnOwner(RelationRelationId, new_rel_oid, GetUserId());
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_conversion.c,v 1.24 2005/06/28 05:08:52 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_conversion.c,v 1.25 2005/07/07 20:39:57 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -120,6 +120,10 @@ ConversionCreate(const char *conname, Oid connamespace,
|
||||
referenced.objectSubId = 0;
|
||||
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
||||
|
||||
/* create dependency on owner */
|
||||
recordDependencyOnOwner(ConversionRelationId, HeapTupleGetOid(tup),
|
||||
conowner);
|
||||
|
||||
heap_freetuple(tup);
|
||||
heap_close(rel, RowExclusiveLock);
|
||||
|
||||
|
||||
@@ -8,13 +8,14 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_namespace.c,v 1.14 2005/06/28 05:08:52 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_namespace.c,v 1.15 2005/07/07 20:39:57 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/dependency.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/pg_namespace.h"
|
||||
#include "utils/builtins.h"
|
||||
@@ -72,5 +73,8 @@ NamespaceCreate(const char *nspName, Oid ownerId)
|
||||
|
||||
heap_close(nspdesc, RowExclusiveLock);
|
||||
|
||||
/* Record dependency on owner */
|
||||
recordDependencyOnOwner(NamespaceRelationId, nspoid, ownerId);
|
||||
|
||||
return nspoid;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_operator.c,v 1.92 2005/06/28 05:08:52 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_operator.c,v 1.93 2005/07/07 20:39:57 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* these routines moved here from commands/define.c and somewhat cleaned up.
|
||||
@@ -889,6 +889,7 @@ makeOperatorDependencies(HeapTuple tuple)
|
||||
|
||||
/* In case we are updating a shell, delete any existing entries */
|
||||
deleteDependencyRecordsFor(myself.classId, myself.objectId);
|
||||
deleteSharedDependencyRecordsFor(myself.classId, myself.objectId);
|
||||
|
||||
/* Dependency on namespace */
|
||||
if (OidIsValid(oper->oprnamespace))
|
||||
@@ -962,4 +963,8 @@ makeOperatorDependencies(HeapTuple tuple)
|
||||
referenced.objectSubId = 0;
|
||||
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
||||
}
|
||||
|
||||
/* Dependency on owner */
|
||||
recordDependencyOnOwner(OperatorRelationId, HeapTupleGetOid(tuple),
|
||||
oper->oprowner);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.131 2005/06/28 19:51:21 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.132 2005/07/07 20:39:57 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -349,7 +349,10 @@ ProcedureCreate(const char *procedureName,
|
||||
* existing function, first delete any existing pg_depend entries.
|
||||
*/
|
||||
if (is_update)
|
||||
{
|
||||
deleteDependencyRecordsFor(ProcedureRelationId, retval);
|
||||
deleteSharedDependencyRecordsFor(ProcedureRelationId, retval);
|
||||
}
|
||||
|
||||
myself.classId = ProcedureRelationId;
|
||||
myself.objectId = retval;
|
||||
@@ -382,6 +385,9 @@ ProcedureCreate(const char *procedureName,
|
||||
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
||||
}
|
||||
|
||||
/* dependency on owner */
|
||||
recordDependencyOnOwner(ProcedureRelationId, retval, GetUserId());
|
||||
|
||||
heap_freetuple(tup);
|
||||
|
||||
heap_close(rel, RowExclusiveLock);
|
||||
|
||||
1042
src/backend/catalog/pg_shdepend.c
Normal file
1042
src/backend/catalog/pg_shdepend.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.101 2005/06/28 05:08:52 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.102 2005/07/07 20:39:57 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -75,7 +75,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace)
|
||||
namestrcpy(&name, typeName);
|
||||
values[i++] = NameGetDatum(&name); /* typname */
|
||||
values[i++] = ObjectIdGetDatum(typeNamespace); /* typnamespace */
|
||||
values[i++] = ObjectIdGetDatum(InvalidOid); /* typowner */
|
||||
values[i++] = ObjectIdGetDatum(GetUserId()); /* typowner */
|
||||
values[i++] = Int16GetDatum(0); /* typlen */
|
||||
values[i++] = BoolGetDatum(false); /* typbyval */
|
||||
values[i++] = CharGetDatum(0); /* typtype */
|
||||
@@ -117,6 +117,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace)
|
||||
typoid,
|
||||
InvalidOid,
|
||||
0,
|
||||
GetUserId(),
|
||||
InvalidOid,
|
||||
InvalidOid,
|
||||
InvalidOid,
|
||||
@@ -330,6 +331,7 @@ TypeCreate(const char *typeName,
|
||||
typeObjectId,
|
||||
relationOid,
|
||||
relationKind,
|
||||
GetUserId(),
|
||||
inputProcedure,
|
||||
outputProcedure,
|
||||
receiveProcedure,
|
||||
@@ -365,6 +367,7 @@ GenerateTypeDependencies(Oid typeNamespace,
|
||||
Oid relationOid, /* only for 'c'atalog
|
||||
* types */
|
||||
char relationKind, /* ditto */
|
||||
Oid owner,
|
||||
Oid inputProcedure,
|
||||
Oid outputProcedure,
|
||||
Oid receiveProcedure,
|
||||
@@ -379,7 +382,10 @@ GenerateTypeDependencies(Oid typeNamespace,
|
||||
referenced;
|
||||
|
||||
if (rebuild)
|
||||
{
|
||||
deleteDependencyRecordsFor(TypeRelationId, typeObjectId);
|
||||
deleteSharedDependencyRecordsFor(TypeRelationId, typeObjectId);
|
||||
}
|
||||
|
||||
myself.classId = TypeRelationId;
|
||||
myself.objectId = typeObjectId;
|
||||
@@ -485,6 +491,9 @@ GenerateTypeDependencies(Oid typeNamespace,
|
||||
/* Normal dependency on the default expression. */
|
||||
if (defaultExpr)
|
||||
recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL);
|
||||
|
||||
/* Shared dependency on owner. */
|
||||
recordDependencyOnOwner(TypeRelationId, typeObjectId, owner);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.19 2005/06/28 05:08:53 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.20 2005/07/07 20:39:58 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "catalog/pg_conversion.h"
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/catalog.h"
|
||||
#include "catalog/dependency.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/namespace.h"
|
||||
#include "catalog/pg_type.h"
|
||||
@@ -220,6 +221,10 @@ AlterConversionOwner(List *name, Oid newOwnerId)
|
||||
simple_heap_update(rel, &tup->t_self, tup);
|
||||
|
||||
CatalogUpdateIndexes(rel, tup);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(ConversionRelationId, conversionOid,
|
||||
newOwnerId);
|
||||
}
|
||||
|
||||
heap_close(rel, NoLock);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.164 2005/06/30 00:00:50 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.165 2005/07/07 20:39:58 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "access/genam.h"
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/catalog.h"
|
||||
#include "catalog/dependency.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/pg_authid.h"
|
||||
#include "catalog/pg_database.h"
|
||||
@@ -511,6 +512,12 @@ createdb(const CreatedbStmt *stmt)
|
||||
/* Update indexes */
|
||||
CatalogUpdateIndexes(pg_database_rel, tuple);
|
||||
|
||||
/* Register owner dependency */
|
||||
recordDependencyOnOwner(DatabaseRelationId, dboid, datdba);
|
||||
|
||||
/* Create pg_shdepend entries for objects within database */
|
||||
copyTemplateDependencies(src_dboid, dboid);
|
||||
|
||||
/* Close pg_database, but keep exclusive lock till commit */
|
||||
heap_close(pg_database_rel, NoLock);
|
||||
|
||||
@@ -679,6 +686,11 @@ dropdb(const char *dbname)
|
||||
/* Close pg_database, but keep exclusive lock till commit */
|
||||
heap_close(pgdbrel, NoLock);
|
||||
|
||||
/*
|
||||
* Remove shared dependency references for the database.
|
||||
*/
|
||||
dropDatabaseDependencies(db_id);
|
||||
|
||||
/*
|
||||
* Set flag to update flat database file at commit.
|
||||
*/
|
||||
@@ -951,6 +963,10 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId)
|
||||
CatalogUpdateIndexes(rel, newtuple);
|
||||
|
||||
heap_freetuple(newtuple);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(DatabaseRelationId, HeapTupleGetOid(tuple),
|
||||
newOwnerId);
|
||||
}
|
||||
|
||||
systable_endscan(scan);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.62 2005/06/28 05:08:53 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.63 2005/07/07 20:39:58 tgl Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* These routines take the parse tree and pick out the
|
||||
@@ -925,6 +925,9 @@ AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId)
|
||||
CatalogUpdateIndexes(rel, newtuple);
|
||||
|
||||
heap_freetuple(newtuple);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(ProcedureRelationId, procOid, newOwnerId);
|
||||
}
|
||||
|
||||
ReleaseSysCache(tup);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.33 2005/06/28 05:08:53 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.34 2005/07/07 20:39:58 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -392,6 +392,9 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
||||
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
||||
}
|
||||
|
||||
/* dependency on owner */
|
||||
recordDependencyOnOwner(OperatorClassRelationId, opclassoid, GetUserId());
|
||||
|
||||
heap_close(rel, RowExclusiveLock);
|
||||
}
|
||||
|
||||
@@ -962,6 +965,9 @@ AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId)
|
||||
simple_heap_update(rel, &tup->t_self, tup);
|
||||
|
||||
CatalogUpdateIndexes(rel, tup);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(OperatorClassRelationId, amOid, newOwnerId);
|
||||
}
|
||||
|
||||
heap_close(rel, NoLock);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.22 2005/06/28 05:08:54 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.23 2005/07/07 20:39:58 tgl Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The "DefineFoo" routines take the parse tree and pick out the
|
||||
@@ -310,6 +310,9 @@ AlterOperatorOwner(List *name, TypeName *typeName1, TypeName *typeName2,
|
||||
simple_heap_update(rel, &tup->t_self, tup);
|
||||
|
||||
CatalogUpdateIndexes(rel, tup);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(OperatorRelationId, operOid, newOwnerId);
|
||||
}
|
||||
|
||||
heap_close(rel, NoLock);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.31 2005/06/28 05:08:54 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.32 2005/07/07 20:39:58 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -342,6 +342,10 @@ AlterSchemaOwner(const char *name, Oid newOwnerId)
|
||||
CatalogUpdateIndexes(rel, newtuple);
|
||||
|
||||
heap_freetuple(newtuple);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(NamespaceRelationId, HeapTupleGetOid(tup),
|
||||
newOwnerId);
|
||||
}
|
||||
|
||||
ReleaseSysCache(tup);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.162 2005/06/28 05:08:54 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.163 2005/07/07 20:39:58 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -5321,6 +5321,9 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId)
|
||||
|
||||
heap_freetuple(newtuple);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(RelationRelationId, relationOid, newOwnerId);
|
||||
|
||||
/*
|
||||
* If we are operating on a table, also change the ownership of
|
||||
* any indexes and sequences that belong to the table, as well as
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.24 2005/07/04 04:51:46 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.25 2005/07/07 20:39:58 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -50,6 +50,7 @@
|
||||
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/catalog.h"
|
||||
#include "catalog/dependency.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/pg_namespace.h"
|
||||
#include "catalog/pg_tablespace.h"
|
||||
@@ -307,6 +308,9 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
|
||||
|
||||
heap_freetuple(tuple);
|
||||
|
||||
/* Record dependency on owner */
|
||||
recordDependencyOnOwner(TableSpaceRelationId, tablespaceoid, ownerId);
|
||||
|
||||
/*
|
||||
* Attempt to coerce target directory to safe permissions. If this
|
||||
* fails, it doesn't exist or has the wrong owner.
|
||||
@@ -818,6 +822,10 @@ AlterTableSpaceOwner(const char *name, Oid newOwnerId)
|
||||
CatalogUpdateIndexes(rel, newtuple);
|
||||
|
||||
heap_freetuple(newtuple);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(TableSpaceRelationId, HeapTupleGetOid(tup),
|
||||
newOwnerId);
|
||||
}
|
||||
|
||||
heap_endscan(scandesc);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.73 2005/06/28 05:08:54 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.74 2005/07/07 20:39:58 tgl Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The "DefineFoo" routines take the parse tree and pick out the
|
||||
@@ -1208,6 +1208,7 @@ AlterDomainDefault(List *names, Node *defaultRaw)
|
||||
domainoid,
|
||||
typTup->typrelid,
|
||||
0, /* relation kind is n/a */
|
||||
typTup->typowner,
|
||||
typTup->typinput,
|
||||
typTup->typoutput,
|
||||
typTup->typreceive,
|
||||
@@ -2080,6 +2081,9 @@ AlterTypeOwner(List *names, Oid newOwnerId)
|
||||
simple_heap_update(rel, &tup->t_self, tup);
|
||||
|
||||
CatalogUpdateIndexes(rel, tup);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId);
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
|
||||
@@ -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.155 2005/06/29 20:34:13 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.156 2005/07/07 20:39:58 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -14,10 +14,10 @@
|
||||
|
||||
#include "access/genam.h"
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/dependency.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/pg_auth_members.h"
|
||||
#include "catalog/pg_authid.h"
|
||||
#include "catalog/pg_database.h"
|
||||
#include "commands/user.h"
|
||||
#include "libpq/crypt.h"
|
||||
#include "miscadmin.h"
|
||||
@@ -742,10 +742,8 @@ DropRole(DropRoleStmt *stmt)
|
||||
const char *role = strVal(lfirst(item));
|
||||
HeapTuple tuple,
|
||||
tmp_tuple;
|
||||
Relation pg_rel;
|
||||
TupleDesc pg_dsc;
|
||||
ScanKeyData scankey;
|
||||
HeapScanDesc scan;
|
||||
ScanKeyData scankey;
|
||||
char *detail;
|
||||
SysScanDesc sscan;
|
||||
Oid roleid;
|
||||
|
||||
@@ -780,42 +778,18 @@ DropRole(DropRoleStmt *stmt)
|
||||
errmsg("must be superuser to drop superusers")));
|
||||
|
||||
/*
|
||||
* Check if role still owns a database. If so, error out.
|
||||
*
|
||||
* (It used to be that this function would drop the database
|
||||
* automatically. This is not only very dangerous for people that
|
||||
* don't read the manual, it doesn't seem to be the behaviour one
|
||||
* would expect either.) -- petere 2000/01/14)
|
||||
*/
|
||||
pg_rel = heap_open(DatabaseRelationId, AccessShareLock);
|
||||
pg_dsc = RelationGetDescr(pg_rel);
|
||||
* Lock the role, so nobody can add dependencies to her while we drop
|
||||
* her. We keep the lock until the end of transaction.
|
||||
*/
|
||||
LockSharedObject(AuthIdRelationId, roleid, 0, AccessExclusiveLock);
|
||||
|
||||
ScanKeyInit(&scankey,
|
||||
Anum_pg_database_datdba,
|
||||
BTEqualStrategyNumber, F_OIDEQ,
|
||||
roleid);
|
||||
|
||||
scan = heap_beginscan(pg_rel, SnapshotNow, 1, &scankey);
|
||||
|
||||
if ((tmp_tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
|
||||
{
|
||||
char *dbname;
|
||||
|
||||
dbname = NameStr(((Form_pg_database) GETSTRUCT(tmp_tuple))->datname);
|
||||
/* Check for pg_shdepend entries depending on this role */
|
||||
if ((detail = checkSharedDependencies(AuthIdRelationId, roleid)) != NULL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OBJECT_IN_USE),
|
||||
errmsg("role \"%s\" cannot be dropped", role),
|
||||
errdetail("The role owns database \"%s\".", dbname)));
|
||||
}
|
||||
|
||||
heap_endscan(scan);
|
||||
heap_close(pg_rel, AccessShareLock);
|
||||
|
||||
/*
|
||||
* Somehow we'd have to check for tables, views, etc. owned by the
|
||||
* role as well, but those could be spread out over all sorts of
|
||||
* databases which we don't have access to (easily).
|
||||
*/
|
||||
(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
|
||||
errmsg("role \"%s\" cannot be dropped because some objects depend on it",
|
||||
role),
|
||||
errdetail("%s", detail)));
|
||||
|
||||
/*
|
||||
* Remove the role from the pg_authid table
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.117 2005/06/29 20:34:14 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.118 2005/07/07 20:39:58 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -59,6 +59,7 @@ static void check_circularity(const Acl *old_acl, const AclItem *mod_aip,
|
||||
Oid ownerId);
|
||||
static Acl *recursive_revoke(Acl *acl, Oid grantee, AclMode revoke_privs,
|
||||
Oid ownerId, DropBehavior behavior);
|
||||
static int oidComparator(const void *arg1, const void *arg2);
|
||||
|
||||
static AclMode convert_priv_string(text *priv_type_text);
|
||||
|
||||
@@ -1052,6 +1053,86 @@ aclmask(const Acl *acl, Oid roleid, Oid ownerId,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* aclmembers
|
||||
* Find out all the roleids mentioned in an Acl.
|
||||
* Note that we do not distinguish grantors from grantees.
|
||||
*
|
||||
* *roleids is set to point to a palloc'd array containing distinct OIDs
|
||||
* in sorted order. The length of the array is the function result.
|
||||
*/
|
||||
int
|
||||
aclmembers(const Acl *acl, Oid **roleids)
|
||||
{
|
||||
Oid *list;
|
||||
const AclItem *acldat;
|
||||
int i,
|
||||
j,
|
||||
k;
|
||||
|
||||
if (acl == NULL || ACL_NUM(acl) == 0)
|
||||
{
|
||||
*roleids = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Allocate the worst-case space requirement */
|
||||
list = palloc(ACL_NUM(acl) * 2 * sizeof(Oid));
|
||||
acldat = ACL_DAT(acl);
|
||||
|
||||
/*
|
||||
* Walk the ACL collecting mentioned RoleIds.
|
||||
*/
|
||||
j = 0;
|
||||
for (i = 0; i < ACL_NUM(acl); i++)
|
||||
{
|
||||
const AclItem *ai = &acldat[i];
|
||||
|
||||
if (ai->ai_grantee != ACL_ID_PUBLIC)
|
||||
list[j++] = ai->ai_grantee;
|
||||
/* grantor is currently never PUBLIC, but let's check anyway */
|
||||
if (ai->ai_grantor != ACL_ID_PUBLIC)
|
||||
list[j++] = ai->ai_grantor;
|
||||
}
|
||||
|
||||
/* Sort the array */
|
||||
qsort(list, j, sizeof(Oid), oidComparator);
|
||||
|
||||
/* Remove duplicates from the array */
|
||||
k = 0;
|
||||
for (i = 1; i < j; i++)
|
||||
{
|
||||
if (list[k] != list[i])
|
||||
list[++k] = list[i];
|
||||
}
|
||||
|
||||
/*
|
||||
* We could repalloc the array down to minimum size, but it's hardly
|
||||
* worth it since it's only transient memory.
|
||||
*/
|
||||
*roleids = list;
|
||||
|
||||
return k + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* oidComparator
|
||||
* qsort comparison function for Oids
|
||||
*/
|
||||
static int
|
||||
oidComparator(const void *arg1, const void *arg2)
|
||||
{
|
||||
Oid oid1 = * (const Oid *) arg1;
|
||||
Oid oid2 = * (const Oid *) arg2;
|
||||
|
||||
if (oid1 > oid2)
|
||||
return 1;
|
||||
if (oid1 < oid2)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* aclinsert (exported function)
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user