aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/catalog/aclchk.c230
-rw-r--r--src/backend/catalog/heap.c4
-rw-r--r--src/backend/catalog/pg_proc.c4
-rw-r--r--src/backend/catalog/pg_shdepend.c159
-rw-r--r--src/include/catalog/dependency.h4
5 files changed, 248 insertions, 153 deletions
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 5151d7bbcea..f61add142aa 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.164 2010/03/06 23:10:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.165 2010/04/05 01:09:52 tgl Exp $
*
* NOTES
* See acl.h.
@@ -1142,7 +1142,16 @@ SetDefaultACL(InternalDefaultACL *iacls)
isNew = true;
}
- if (old_acl == NULL)
+ if (old_acl != NULL)
+ {
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information. Collect data before
+ * merge_acl_with_grant throws away old_acl.
+ */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
+ else
{
/*
* If we are creating a global entry, start with the hard-wired
@@ -1154,14 +1163,11 @@ SetDefaultACL(InternalDefaultACL *iacls)
old_acl = acldefault(iacls->objtype, iacls->roleid);
else
old_acl = make_empty_acl();
- }
- /*
- * We need the members of both old and new ACLs so we can correct the
- * shared dependency information. Collect data before
- * merge_acl_with_grant throws away old_acl.
- */
- noldmembers = aclmembers(old_acl, &oldmembers);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
/*
* Generate new ACL. Grantor of rights is always the same as the target
@@ -1236,7 +1242,7 @@ SetDefaultACL(InternalDefaultACL *iacls)
nnewmembers = aclmembers(new_acl, &newmembers);
updateAclDependencies(DefaultAclRelationId, HeapTupleGetOid(newtuple), 0,
- iacls->roleid, iacls->is_grant,
+ iacls->roleid,
noldmembers, oldmembers,
nnewmembers, newmembers);
@@ -1526,9 +1532,18 @@ ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname,
aclDatum = SysCacheGetAttr(ATTNUM, attr_tuple, Anum_pg_attribute_attacl,
&isNull);
if (isNull)
+ {
old_acl = acldefault(ACL_OBJECT_COLUMN, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
else
+ {
old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
/*
* In select_best_grantor we should consider existing table-level ACL bits
@@ -1563,18 +1578,17 @@ ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname,
/*
* Generate new ACL.
- *
- * 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, istmt->is_grant,
istmt->grant_option,
istmt->behavior, istmt->grantees,
col_privileges, grantorId,
ownerId);
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
@@ -1613,7 +1627,7 @@ ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname,
/* Update the shared dependency ACL info */
updateAclDependencies(RelationRelationId, relOid, attnum,
- ownerId, istmt->is_grant,
+ ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
}
@@ -1648,6 +1662,8 @@ ExecGrant_Relation(InternalGrant *istmt)
bool have_col_privileges;
Acl *old_acl;
Acl *old_rel_acl;
+ int noldmembers;
+ Oid *oldmembers;
Oid ownerId;
HeapTuple tuple;
ListCell *cell_colprivs;
@@ -1770,11 +1786,20 @@ ExecGrant_Relation(InternalGrant *istmt)
aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
&isNull);
if (isNull)
+ {
old_acl = acldefault(pg_class_tuple->relkind == RELKIND_SEQUENCE ?
ACL_OBJECT_SEQUENCE : ACL_OBJECT_RELATION,
ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
else
+ {
old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
/* Need an extra copy of original rel ACL for column handling */
old_rel_acl = aclcopy(old_acl);
@@ -1791,9 +1816,7 @@ ExecGrant_Relation(InternalGrant *istmt)
Datum values[Natts_pg_class];
bool nulls[Natts_pg_class];
bool replaces[Natts_pg_class];
- int noldmembers;
int nnewmembers;
- Oid *oldmembers;
Oid *newmembers;
/* Determine ID to do the grant as, and available grant options */
@@ -1816,12 +1839,7 @@ ExecGrant_Relation(InternalGrant *istmt)
/*
* Generate new ACL.
- *
- * 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,
istmt->is_grant,
istmt->grant_option,
@@ -1831,6 +1849,10 @@ ExecGrant_Relation(InternalGrant *istmt)
grantorId,
ownerId);
+ /*
+ * We need the members of both old and new ACLs so we can correct
+ * the shared dependency information.
+ */
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
@@ -1851,7 +1873,7 @@ ExecGrant_Relation(InternalGrant *istmt)
/* Update the shared dependency ACL info */
updateAclDependencies(RelationRelationId, relOid, 0,
- ownerId, istmt->is_grant,
+ ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
@@ -1980,9 +2002,18 @@ ExecGrant_Database(InternalGrant *istmt)
aclDatum = heap_getattr(tuple, Anum_pg_database_datacl,
RelationGetDescr(relation), &isNull);
if (isNull)
+ {
old_acl = acldefault(ACL_OBJECT_DATABASE, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
else
+ {
old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
@@ -2002,17 +2033,16 @@ ExecGrant_Database(InternalGrant *istmt)
/*
* Generate new ACL.
- *
- * 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, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
@@ -2033,7 +2063,7 @@ ExecGrant_Database(InternalGrant *istmt)
/* Update the shared dependency ACL info */
updateAclDependencies(DatabaseRelationId, HeapTupleGetOid(tuple), 0,
- ownerId, istmt->is_grant,
+ ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
@@ -2097,9 +2127,18 @@ ExecGrant_Fdw(InternalGrant *istmt)
Anum_pg_foreign_data_wrapper_fdwacl,
&isNull);
if (isNull)
+ {
old_acl = acldefault(ACL_OBJECT_FDW, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
else
+ {
old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
@@ -2119,17 +2158,16 @@ ExecGrant_Fdw(InternalGrant *istmt)
/*
* Generate new ACL.
- *
- * 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, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
@@ -2151,7 +2189,7 @@ ExecGrant_Fdw(InternalGrant *istmt)
/* Update the shared dependency ACL info */
updateAclDependencies(ForeignDataWrapperRelationId,
HeapTupleGetOid(tuple), 0,
- ownerId, istmt->is_grant,
+ ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
@@ -2214,9 +2252,18 @@ ExecGrant_ForeignServer(InternalGrant *istmt)
Anum_pg_foreign_server_srvacl,
&isNull);
if (isNull)
+ {
old_acl = acldefault(ACL_OBJECT_FOREIGN_SERVER, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
else
+ {
old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
@@ -2236,17 +2283,16 @@ ExecGrant_ForeignServer(InternalGrant *istmt)
/*
* Generate new ACL.
- *
- * 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, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
@@ -2268,7 +2314,7 @@ ExecGrant_ForeignServer(InternalGrant *istmt)
/* Update the shared dependency ACL info */
updateAclDependencies(ForeignServerRelationId,
HeapTupleGetOid(tuple), 0,
- ownerId, istmt->is_grant,
+ ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
@@ -2330,9 +2376,18 @@ ExecGrant_Function(InternalGrant *istmt)
aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
&isNull);
if (isNull)
+ {
old_acl = acldefault(ACL_OBJECT_FUNCTION, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
else
+ {
old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
@@ -2352,17 +2407,16 @@ ExecGrant_Function(InternalGrant *istmt)
/*
* Generate new ACL.
- *
- * 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, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
@@ -2383,7 +2437,7 @@ ExecGrant_Function(InternalGrant *istmt)
/* Update the shared dependency ACL info */
updateAclDependencies(ProcedureRelationId, funcId, 0,
- ownerId, istmt->is_grant,
+ ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
@@ -2452,9 +2506,18 @@ ExecGrant_Language(InternalGrant *istmt)
aclDatum = SysCacheGetAttr(LANGNAME, tuple, Anum_pg_language_lanacl,
&isNull);
if (isNull)
+ {
old_acl = acldefault(ACL_OBJECT_LANGUAGE, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
else
+ {
old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
@@ -2474,17 +2537,16 @@ ExecGrant_Language(InternalGrant *istmt)
/*
* Generate new ACL.
- *
- * 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, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
@@ -2505,7 +2567,7 @@ ExecGrant_Language(InternalGrant *istmt)
/* Update the shared dependency ACL info */
updateAclDependencies(LanguageRelationId, HeapTupleGetOid(tuple), 0,
- ownerId, istmt->is_grant,
+ ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
@@ -2582,9 +2644,18 @@ ExecGrant_Largeobject(InternalGrant *istmt)
Anum_pg_largeobject_metadata_lomacl,
RelationGetDescr(relation), &isNull);
if (isNull)
+ {
old_acl = acldefault(ACL_OBJECT_LARGEOBJECT, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
else
+ {
old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
@@ -2604,17 +2675,16 @@ ExecGrant_Largeobject(InternalGrant *istmt)
/*
* Generate new ACL.
- *
- * 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, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
@@ -2637,7 +2707,7 @@ ExecGrant_Largeobject(InternalGrant *istmt)
/* Update the shared dependency ACL info */
updateAclDependencies(LargeObjectRelationId,
HeapTupleGetOid(tuple), 0,
- ownerId, istmt->is_grant,
+ ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
@@ -2700,9 +2770,18 @@ ExecGrant_Namespace(InternalGrant *istmt)
Anum_pg_namespace_nspacl,
&isNull);
if (isNull)
+ {
old_acl = acldefault(ACL_OBJECT_NAMESPACE, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
else
+ {
old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
@@ -2722,17 +2801,16 @@ ExecGrant_Namespace(InternalGrant *istmt)
/*
* Generate new ACL.
- *
- * 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, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
@@ -2753,7 +2831,7 @@ ExecGrant_Namespace(InternalGrant *istmt)
/* Update the shared dependency ACL info */
updateAclDependencies(NamespaceRelationId, HeapTupleGetOid(tuple), 0,
- ownerId, istmt->is_grant,
+ ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
@@ -2816,9 +2894,18 @@ ExecGrant_Tablespace(InternalGrant *istmt)
aclDatum = heap_getattr(tuple, Anum_pg_tablespace_spcacl,
RelationGetDescr(relation), &isNull);
if (isNull)
+ {
old_acl = acldefault(ACL_OBJECT_TABLESPACE, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
else
+ {
old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
@@ -2838,17 +2925,16 @@ ExecGrant_Tablespace(InternalGrant *istmt)
/*
* Generate new ACL.
- *
- * 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, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
@@ -2869,7 +2955,7 @@ ExecGrant_Tablespace(InternalGrant *istmt)
/* Update the shared dependency ACL info */
updateAclDependencies(TableSpaceRelationId, tblId, 0,
- ownerId, istmt->is_grant,
+ ownerId,
noldmembers, oldmembers,
nnewmembers, newmembers);
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 39aec680c08..47e0c9b9cf5 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.372 2010/02/26 02:00:36 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.373 2010/04/05 01:09:52 tgl Exp $
*
*
* INTERFACE ROUTINES
@@ -1160,7 +1160,7 @@ heap_create_with_catalog(const char *relname,
nnewmembers = aclmembers(relacl, &newmembers);
updateAclDependencies(RelationRelationId, relid, 0,
- ownerid, true,
+ ownerid,
0, NULL,
nnewmembers, newmembers);
}
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index f97641d5555..64b88727063 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.173 2010/03/19 22:54:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.174 2010/04/05 01:09:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -609,7 +609,7 @@ ProcedureCreate(const char *procedureName,
nnewmembers = aclmembers(proacl, &newmembers);
updateAclDependencies(ProcedureRelationId, retval, 0,
- proowner, true,
+ proowner,
0, NULL,
nnewmembers, newmembers);
}
diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c
index df65e1086ee..c7a5e86c583 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.40 2010/02/26 02:00:37 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.41 2010/04/05 01:09:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -54,8 +54,7 @@ typedef enum
REMOTE_OBJECT
} objectType;
-static int getOidListDiff(Oid *list1, int nlist1, Oid *list2, int nlist2,
- Oid **diff);
+static void getOidListDiff(Oid *list1, int *nlist1, Oid *list2, int *nlist2);
static Oid classIdGetDbId(Oid classId);
static void shdepChangeDep(Relation sdepRel,
Oid classid, Oid objid, int32 objsubid,
@@ -328,57 +327,53 @@ changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
* getOidListDiff
* Helper for updateAclDependencies.
*
- * Takes two Oid arrays and returns elements from the first not found in the
- * second. We assume both arrays are sorted and de-duped, and that the
- * second array does not contain any values not found in the first.
- *
- * NOTE: Both input arrays are pfreed.
+ * Takes two Oid arrays and removes elements that are common to both arrays,
+ * leaving just those that are in one input but not the other.
+ * We assume both arrays have been sorted and de-duped.
*/
-static int
-getOidListDiff(Oid *list1, int nlist1, Oid *list2, int nlist2, Oid **diff)
+static void
+getOidListDiff(Oid *list1, int *nlist1, Oid *list2, int *nlist2)
{
- Oid *result;
- int i,
- j,
- k = 0;
-
- AssertArg(nlist1 >= nlist2 && nlist2 >= 0);
+ int in1,
+ in2,
+ out1,
+ out2;
- result = palloc(sizeof(Oid) * (nlist1 - nlist2));
- *diff = result;
-
- for (i = 0, j = 0; i < nlist1 && j < nlist2;)
+ in1 = in2 = out1 = out2 = 0;
+ while (in1 < *nlist1 && in2 < *nlist2)
{
- if (list1[i] == list2[j])
+ if (list1[in1] == list2[in2])
{
- i++;
- j++;
+ /* skip over duplicates */
+ in1++;
+ in2++;
}
- else if (list1[i] < list2[j])
+ else if (list1[in1] < list2[in2])
{
- result[k++] = list1[i];
- i++;
+ /* list1[in1] is not in list2 */
+ list1[out1++] = list1[in1++];
}
else
{
- /* can't happen */
- elog(WARNING, "invalid element %u in shorter list", list2[j]);
- j++;
+ /* list2[in2] is not in list1 */
+ list2[out2++] = list2[in2++];
}
}
- for (; i < nlist1; i++)
- result[k++] = list1[i];
-
- /* We should have copied the exact number of elements */
- AssertState(k == (nlist1 - nlist2));
+ /* any remaining list1 entries are not in list2 */
+ while (in1 < *nlist1)
+ {
+ list1[out1++] = list1[in1++];
+ }
- if (list1)
- pfree(list1);
- if (list2)
- pfree(list2);
+ /* any remaining list2 entries are not in list1 */
+ while (in2 < *nlist2)
+ {
+ list2[out2++] = list2[in2++];
+ }
- return k;
+ *nlist1 = out1;
+ *nlist2 = out2;
}
/*
@@ -387,52 +382,50 @@ getOidListDiff(Oid *list1, int nlist1, Oid *list2, int nlist2, Oid **diff)
*
* classId, objectId, objsubId: identify the object whose ACL this is
* ownerId: role owning the object
- * isGrant: are we adding or removing ACL entries?
* noldmembers, oldmembers: array of roleids appearing in old ACL
* nnewmembers, newmembers: array of roleids appearing in new ACL
*
- * We calculate the difference between the new and old lists of roles,
- * and then insert (if it's a grant) or delete (if it's a revoke) from
- * pg_shdepend as appropiate.
+ * We calculate the differences between the new and old lists of roles,
+ * and then insert or delete from pg_shdepend as appropiate.
*
- * Note that we can't insert blindly at grant, because we would end up with
- * duplicate registered dependencies. We could check for existence of the
- * tuple before inserting, but that seems to be more expensive than what we are
- * doing now. On the other hand, we can't just delete the tuples blindly at
- * revoke, because the user may still have other privileges.
+ * Note that we can't just insert all referenced roles blindly during GRANT,
+ * because we would end up with duplicate registered dependencies. We could
+ * check for existence of the tuples before inserting, but that seems to be
+ * more expensive than what we are doing here. Likewise we can't just delete
+ * blindly during REVOKE, because the user may still have other privileges.
+ * It is also possible that REVOKE actually adds dependencies, due to
+ * instantiation of a formerly implicit default ACL (although at present,
+ * all such dependencies should be for the owning role, which we ignore here).
*
- * NOTE: Both input arrays must be sorted and de-duped. They are pfreed
- * before return.
+ * NOTE: Both input arrays must be sorted and de-duped. (Typically they
+ * are extracted from an ACL array by aclmembers(), which takes care of
+ * both requirements.) The arrays are pfreed before return.
*/
void
updateAclDependencies(Oid classId, Oid objectId, int32 objsubId,
- Oid ownerId, bool isGrant,
+ Oid ownerId,
int noldmembers, Oid *oldmembers,
int nnewmembers, Oid *newmembers)
{
Relation sdepRel;
- Oid *diff;
- int ndiff,
- i;
+ int i;
/*
- * Calculate the differences between the old and new lists.
+ * Remove entries that are common to both lists; those represent
+ * existing dependencies we don't need to change.
+ *
+ * OK to overwrite the inputs since we'll pfree them anyway.
*/
- if (isGrant)
- ndiff = getOidListDiff(newmembers, nnewmembers,
- oldmembers, noldmembers, &diff);
- else
- ndiff = getOidListDiff(oldmembers, noldmembers,
- newmembers, nnewmembers, &diff);
+ getOidListDiff(oldmembers, &noldmembers, newmembers, &nnewmembers);
- if (ndiff > 0)
+ if (noldmembers > 0 || nnewmembers > 0)
{
sdepRel = heap_open(SharedDependRelationId, RowExclusiveLock);
- /* Add or drop the respective dependency */
- for (i = 0; i < ndiff; i++)
+ /* Add new dependencies that weren't already present */
+ for (i = 0; i < nnewmembers; i++)
{
- Oid roleid = diff[i];
+ Oid roleid = newmembers[i];
/*
* Skip the owner: he has an OWNER shdep entry instead. (This is
@@ -442,25 +435,41 @@ updateAclDependencies(Oid classId, Oid objectId, int32 objsubId,
if (roleid == ownerId)
continue;
+ /* Skip pinned roles; they don't need dependency entries */
+ if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
+ continue;
+
+ shdepAddDependency(sdepRel, classId, objectId, objsubId,
+ AuthIdRelationId, roleid,
+ SHARED_DEPENDENCY_ACL);
+ }
+
+ /* Drop no-longer-used old dependencies */
+ for (i = 0; i < noldmembers; i++)
+ {
+ Oid roleid = oldmembers[i];
+
+ /* Skip the owner, same as above */
+ if (roleid == ownerId)
+ continue;
+
/* Skip pinned roles */
if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
continue;
- if (isGrant)
- shdepAddDependency(sdepRel, classId, objectId, objsubId,
- AuthIdRelationId, roleid,
- SHARED_DEPENDENCY_ACL);
- else
- shdepDropDependency(sdepRel, classId, objectId, objsubId,
- false, /* exact match on objsubId */
- AuthIdRelationId, roleid,
- SHARED_DEPENDENCY_ACL);
+ shdepDropDependency(sdepRel, classId, objectId, objsubId,
+ false, /* exact match on objsubId */
+ AuthIdRelationId, roleid,
+ SHARED_DEPENDENCY_ACL);
}
heap_close(sdepRel, RowExclusiveLock);
}
- pfree(diff);
+ if (oldmembers)
+ pfree(oldmembers);
+ if (newmembers)
+ pfree(newmembers);
}
/*
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
index 6d39ecee507..d8a0e0aa639 100644
--- a/src/include/catalog/dependency.h
+++ b/src/include/catalog/dependency.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.44 2010/01/02 16:58:01 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.45 2010/04/05 01:09:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -232,7 +232,7 @@ extern void changeDependencyOnOwner(Oid classId, Oid objectId,
Oid newOwnerId);
extern void updateAclDependencies(Oid classId, Oid objectId, int32 objectSubId,
- Oid ownerId, bool isGrant,
+ Oid ownerId,
int noldmembers, Oid *oldmembers,
int nnewmembers, Oid *newmembers);