Index: contrib/userlock/user_locks.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/contrib/userlock/user_locks.c,v
retrieving revision 1.14
diff -c -r1.14 user_locks.c
*** contrib/userlock/user_locks.c 27 Aug 2004 17:07:41 -0000 1.14
--- contrib/userlock/user_locks.c 19 Dec 2004 21:35:12 -0000
***************
*** 25,32 ****
memset(&tag, 0, sizeof(LOCKTAG));
tag.dbId = MyDatabaseId;
! tag.relId = 0;
! tag.objId.blkno = (BlockNumber) id2;
tag.offnum = (OffsetNumber) (id1 & 0xffff);
return LockAcquire(USER_LOCKMETHOD, &tag, InvalidTransactionId,
--- 25,33 ----
memset(&tag, 0, sizeof(LOCKTAG));
tag.dbId = MyDatabaseId;
! tag.classId = InvalidOid;
! tag.objId = InvalidOid;
! tag.objsubId.blkno = (BlockNumber) id2;
tag.offnum = (OffsetNumber) (id1 & 0xffff);
return LockAcquire(USER_LOCKMETHOD, &tag, InvalidTransactionId,
***************
*** 40,47 ****
memset(&tag, 0, sizeof(LOCKTAG));
tag.dbId = MyDatabaseId;
! tag.relId = 0;
! tag.objId.blkno = (BlockNumber) id2;
tag.offnum = (OffsetNumber) (id1 & 0xffff);
return LockRelease(USER_LOCKMETHOD, &tag, InvalidTransactionId, lockmode);
--- 41,49 ----
memset(&tag, 0, sizeof(LOCKTAG));
tag.dbId = MyDatabaseId;
! tag.classId = InvalidOid;
! tag.objId = InvalidOid;
! tag.objsubId.blkno = (BlockNumber) id2;
tag.offnum = (OffsetNumber) (id1 & 0xffff);
return LockRelease(USER_LOCKMETHOD, &tag, InvalidTransactionId, lockmode);
Index: doc/src/sgml/catalogs.sgml
===================================================================
RCS file: /home/alvherre/cvs/pgsql/doc/src/sgml/catalogs.sgml,v
retrieving revision 2.95
diff -c -r2.95 catalogs.sgml
*** doc/src/sgml/catalogs.sgml 5 Jan 2005 23:42:03 -0000 2.95
--- doc/src/sgml/catalogs.sgml 11 Jan 2005 00:00:29 -0000
***************
*** 174,179 ****
--- 174,183 ----
+ pg_shdepend
+ cross-database dependencies between objects
+
+ pg_statisticplanner statistics
***************
*** 3139,3144 ****
--- 3143,3219 ----
+
+ pg_shdepend
+
+
+ pg_shdepend
+
+
+
+ The shared catalog pg_shdepend records the
+ dependency relationships between database objects and global objects,
+ such as users, groups and tablespaces. This information allows
+ DROP USER, DROP GROUP and
+ DROP TABLESPACE to ensure that those objects are
+ unreferenced before attempting to delete them.
+
+
+
+ pg_shdepend> Columns
+
+
+
+
+ Name
+ Type
+ References
+ Description
+
+
+
+
+
+ dbid
+ oid
+ pg_database.oid
+ The OID of the database the dependent object is in
+
+
+
+ classid
+ oid
+ pg_class.oid
+ The OID of the system catalog the dependent object is in
+
+
+
+ objid
+ oid
+ any OID column
+ The OID of the specific dependent object
+
+
+
+ refclassid
+ oid
+ pg_class.oid
+ The OID of the system catalog the referenced object is in
+
+
+
+ refobjid
+ oid
+ any OID column
+ The OID of the specific referenced object
+
+
+
+
+
+
+
+
pg_statistic
***************
*** 4013,4020 ****
lockable object may
appear many times, if multiple transactions are holding or waiting
for locks on it. However, an object that currently has no locks on it
! will not appear at all. A lockable object is either a relation (e.g., a
! table) or a transaction ID.
--- 4088,4096 ----
lockable object may
appear many times, if multiple transactions are holding or waiting
for locks on it. However, an object that currently has no locks on it
! will not appear at all. A lockable object is either an arbitrary
! object in a system catalog, the most common case being a relation (e.g., a
! table), or a transaction ID.
***************
*** 4038,4048 ****
! relationoidpg_class.oid
! OID of the locked relation, or NULL if the lockable object
is a transaction ID
--- 4114,4133 ----
! classoidpg_class.oid
! The OID of the system catalog the locked object is in, or NULL if the
! lockable object is a transaction ID
!
!
!
! relation
! oid
! any OID column
!
! OID of the locked object, or NULL if the lockable object
is a transaction ID
Index: src/backend/catalog/Makefile
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/Makefile,v
retrieving revision 1.53
diff -c -r1.53 Makefile
*** src/backend/catalog/Makefile 21 Jul 2004 20:34:45 -0000 1.53
--- src/backend/catalog/Makefile 10 Dec 2004 14:21:47 -0000
***************
*** 12,18 ****
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
BKIFILES = postgres.bki postgres.description
--- 12,19 ----
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_shdepend.o \
! pg_type.o
BKIFILES = postgres.bki postgres.description
***************
*** 32,38 ****
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_shadow.h pg_group.h \
! pg_tablespace.h pg_depend.h indexing.h \
)
pg_includes := $(sort -I$(top_srcdir)/src/include -I$(top_builddir)/src/include)
--- 33,39 ----
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_shadow.h pg_group.h \
! pg_tablespace.h pg_depend.h pg_shdepend.h indexing.h \
)
pg_includes := $(sort -I$(top_srcdir)/src/include -I$(top_builddir)/src/include)
Index: src/backend/catalog/aclchk.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/aclchk.c,v
retrieving revision 1.108
diff -c -r1.108 aclchk.c
*** src/backend/catalog/aclchk.c 31 Dec 2004 21:59:38 -0000 1.108
--- src/backend/catalog/aclchk.c 10 Jan 2005 23:32:54 -0000
***************
*** 20,25 ****
--- 20,26 ----
#include "access/heapam.h"
#include "catalog/catalog.h"
#include "catalog/catname.h"
+ #include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_conversion.h"
***************
*** 268,273 ****
--- 269,278 ----
Datum values[Natts_pg_class];
char nulls[Natts_pg_class];
char replaces[Natts_pg_class];
+ List *oldgroups;
+ List *oldusers;
+ List *newgroups;
+ List *newusers;
/* open pg_class */
relation = heap_openr(RelationRelationName, RowExclusiveLock);
***************
*** 360,370 ****
--- 365,388 ----
/* 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.
+ */
+ aclmembers(old_acl, &oldusers, &oldgroups);
+
new_acl = merge_acl_with_grant(old_acl, stmt->is_grant,
stmt->grant_option, stmt->behavior,
stmt->grantees, this_privileges,
grantorId, ownerId);
+ aclmembers(new_acl, &newusers, &newgroups);
+
+ /* Update the shared dependency ACL info */
+ shdependUpdateAclInfo(RelOid_pg_class, relOid, ownerId, stmt->is_grant,
+ oldusers, newusers,
+ oldgroups, newgroups);
+
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, ' ', sizeof(nulls));
***************
*** 437,442 ****
--- 455,464 ----
Datum values[Natts_pg_database];
char nulls[Natts_pg_database];
char replaces[Natts_pg_database];
+ List *oldgroups;
+ List *oldusers;
+ List *newgroups;
+ List *newusers;
relation = heap_openr(DatabaseRelationName, RowExclusiveLock);
ScanKeyInit(&entry[0],
***************
*** 518,528 ****
--- 540,559 ----
/* get a detoasted copy of the ACL */
old_acl = DatumGetAclPCopy(aclDatum);
+ aclmembers(old_acl, &oldusers, &oldgroups);
+
new_acl = merge_acl_with_grant(old_acl, stmt->is_grant,
stmt->grant_option, stmt->behavior,
stmt->grantees, this_privileges,
grantorId, ownerId);
+ aclmembers(new_acl, &newusers, &newgroups);
+
+ /* Update the shared dependency ACL info */
+ shdependUpdateAclInfo(RelOid_pg_database, HeapTupleGetOid(tuple), ownerId, stmt->is_grant,
+ oldusers, newusers,
+ oldgroups, newgroups);
+
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, ' ', sizeof(nulls));
***************
*** 594,599 ****
--- 625,634 ----
Datum values[Natts_pg_proc];
char nulls[Natts_pg_proc];
char replaces[Natts_pg_proc];
+ List *oldgroups;
+ List *oldusers;
+ List *newgroups;
+ List *newusers;
oid = LookupFuncNameTypeNames(func->funcname, func->funcargs, false);
***************
*** 672,682 ****
--- 707,726 ----
/* get a detoasted copy of the ACL */
old_acl = DatumGetAclPCopy(aclDatum);
+ aclmembers(old_acl, &oldusers, &oldgroups);
+
new_acl = merge_acl_with_grant(old_acl, stmt->is_grant,
stmt->grant_option, stmt->behavior,
stmt->grantees, this_privileges,
grantorId, ownerId);
+ aclmembers(new_acl, &newusers, &newgroups);
+
+ /* Update the shared dependency ACL info */
+ shdependUpdateAclInfo(RelOid_pg_proc, oid, ownerId, stmt->is_grant,
+ oldusers, newusers,
+ oldgroups, newgroups);
+
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, ' ', sizeof(nulls));
***************
*** 747,752 ****
--- 791,800 ----
Datum values[Natts_pg_language];
char nulls[Natts_pg_language];
char replaces[Natts_pg_language];
+ List *oldgroups;
+ List *oldusers;
+ List *newgroups;
+ List *newusers;
relation = heap_openr(LanguageRelationName, RowExclusiveLock);
tuple = SearchSysCache(LANGNAME,
***************
*** 835,845 ****
--- 883,903 ----
/* get a detoasted copy of the ACL */
old_acl = DatumGetAclPCopy(aclDatum);
+ aclmembers(old_acl, &oldusers, &oldgroups);
+
new_acl = merge_acl_with_grant(old_acl, stmt->is_grant,
stmt->grant_option, stmt->behavior,
stmt->grantees, this_privileges,
grantorId, ownerId);
+ aclmembers(new_acl, &newusers, &newgroups);
+
+ /* Update the shared dependency ACL info */
+ shdependUpdateAclInfo(get_system_catalog_relid(LanguageRelationName),
+ HeapTupleGetOid(tuple), ownerId, stmt->is_grant,
+ oldusers, newusers,
+ oldgroups, newgroups);
+
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, ' ', sizeof(nulls));
***************
*** 910,915 ****
--- 968,977 ----
Datum values[Natts_pg_namespace];
char nulls[Natts_pg_namespace];
char replaces[Natts_pg_namespace];
+ List *oldgroups;
+ List *oldusers;
+ List *newgroups;
+ List *newusers;
relation = heap_openr(NamespaceRelationName, RowExclusiveLock);
tuple = SearchSysCache(NAMESPACENAME,
***************
*** 989,999 ****
--- 1051,1071 ----
/* get a detoasted copy of the ACL */
old_acl = DatumGetAclPCopy(aclDatum);
+ aclmembers(old_acl, &oldusers, &oldgroups);
+
new_acl = merge_acl_with_grant(old_acl, stmt->is_grant,
stmt->grant_option, stmt->behavior,
stmt->grantees, this_privileges,
grantorId, ownerId);
+ aclmembers(new_acl, &newusers, &newgroups);
+
+ /* Update the shared dependency ACL info */
+ shdependUpdateAclInfo(get_system_catalog_relid(NamespaceRelationName),
+ HeapTupleGetOid(tuple), ownerId, stmt->is_grant,
+ oldusers, newusers,
+ oldgroups, newgroups);
+
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, ' ', sizeof(nulls));
***************
*** 1066,1071 ****
--- 1138,1147 ----
Datum values[Natts_pg_tablespace];
char nulls[Natts_pg_tablespace];
char replaces[Natts_pg_tablespace];
+ List *oldgroups;
+ List *oldusers;
+ List *newgroups;
+ List *newusers;
relation = heap_openr(TableSpaceRelationName, RowExclusiveLock);
ScanKeyInit(&entry[0],
***************
*** 1147,1157 ****
--- 1223,1242 ----
/* get a detoasted copy of the ACL */
old_acl = DatumGetAclPCopy(aclDatum);
+ aclmembers(old_acl, &oldusers, &oldgroups);
+
new_acl = merge_acl_with_grant(old_acl, stmt->is_grant,
stmt->grant_option, stmt->behavior,
stmt->grantees, this_privileges,
grantorId, ownerId);
+ aclmembers(new_acl, &newusers, &newgroups);
+
+ /* Update the shared dependency ACL info */
+ shdependUpdateAclInfo(RelOid_pg_tablespace, HeapTupleGetOid(tuple), ownerId, stmt->is_grant,
+ oldusers, newusers,
+ oldgroups, newgroups);
+
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, ' ', sizeof(nulls));
Index: src/backend/catalog/dependency.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/dependency.c,v
retrieving revision 1.41
diff -c -r1.41 dependency.c
*** src/backend/catalog/dependency.c 31 Dec 2004 21:59:38 -0000 1.41
--- src/backend/catalog/dependency.c 10 Jan 2005 23:32:55 -0000
***************
*** 32,40 ****
--- 32,42 ----
#include "catalog/pg_rewrite.h"
#include "catalog/pg_trigger.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"
***************
*** 496,501 ****
--- 498,504 ----
break;
}
+ /* delete the pg_depend tuple */
simple_heap_delete(depRel, &tup->t_self);
}
***************
*** 572,577 ****
--- 575,588 ----
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.
*/
***************
*** 1305,1313 ****
--- 1316,1327 ----
static void
init_object_classes(void)
{
+ object_classes[OCLASS_AM] = get_system_catalog_relid(AccessMethodRelationName);
object_classes[OCLASS_CLASS] = RelOid_pg_class;
object_classes[OCLASS_PROC] = RelOid_pg_proc;
object_classes[OCLASS_TYPE] = RelOid_pg_type;
+ object_classes[OCLASS_DATABASE] = RelOid_pg_database;
+ object_classes[OCLASS_SHADOW] = RelOid_pg_shadow;
object_classes[OCLASS_CAST] = get_system_catalog_relid(CastRelationName);
object_classes[OCLASS_CONSTRAINT] = get_system_catalog_relid(ConstraintRelationName);
object_classes[OCLASS_CONVERSION] = get_system_catalog_relid(ConversionRelationName);
***************
*** 1318,1323 ****
--- 1332,1338 ----
object_classes[OCLASS_REWRITE] = get_system_catalog_relid(RewriteRelationName);
object_classes[OCLASS_TRIGGER] = get_system_catalog_relid(TriggerRelationName);
object_classes[OCLASS_SCHEMA] = get_system_catalog_relid(NamespaceRelationName);
+ object_classes[OCLASS_TBLSPACE] = RelOid_pg_tablespace;
object_classes_initialized = true;
}
***************
*** 1344,1349 ****
--- 1359,1376 ----
case RelOid_pg_type:
Assert(object->objectSubId == 0);
return OCLASS_TYPE;
+
+ case RelOid_pg_database:
+ Assert(object->objectSubId == 0);
+ return OCLASS_DATABASE;
+
+ case RelOid_pg_tablespace:
+ Assert(object->objectSubId == 0);
+ return OCLASS_TBLSPACE;
+
+ case RelOid_pg_shadow:
+ Assert(object->objectSubId == 0);
+ return OCLASS_SHADOW;
}
/*
***************
*** 1352,1357 ****
--- 1379,1389 ----
if (!object_classes_initialized)
init_object_classes();
+ if (object->classId == object_classes[OCLASS_AM])
+ {
+ Assert(object->objectSubId == 0);
+ return OCLASS_AM;
+ }
if (object->classId == object_classes[OCLASS_CAST])
{
Assert(object->objectSubId == 0);
***************
*** 1439,1444 ****
--- 1471,1510 ----
format_type_be(object->objectId));
break;
+ case OCLASS_AM:
+ {
+ Relation amDesc;
+ ScanKeyData skey[1];
+ SysScanDesc rcscan;
+ HeapTuple tup;
+ Form_pg_am amForm;
+
+ amDesc = heap_openr(AccessMethodRelationName, AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ ObjectIdAttributeNumber,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+
+ rcscan = systable_beginscan(amDesc, AmOidIndex, true,
+ SnapshotNow, 1, skey);
+
+ tup = systable_getnext(rcscan);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for access method %u",
+ object->objectId);
+
+ amForm = (Form_pg_am) GETSTRUCT(tup);
+
+ appendStringInfo(&buffer, gettext("access method %s"),
+ amForm->amname.data);
+
+ systable_endscan(rcscan);
+ heap_close(amDesc, AccessShareLock);
+ break;
+ }
+
case OCLASS_CAST:
{
Relation castDesc;
***************
*** 1715,1720 ****
--- 1781,1817 ----
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, gettext("tablespace %s"), tblspace);
+ 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, gettext("database %s"), datname);
+ break;
+ }
+
+ case OCLASS_SHADOW:
+ {
+ appendStringInfo(&buffer, gettext("user %s"),
+ GetUserNameFromId((AclId)object->objectId));
+ break;
+ }
+
default:
appendStringInfo(&buffer, "unrecognized object %u %u %d",
object->classId,
Index: src/backend/catalog/heap.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/heap.c,v
retrieving revision 1.279
diff -c -r1.279 heap.c
*** src/backend/catalog/heap.c 10 Jan 2005 20:02:19 -0000 1.279
--- src/backend/catalog/heap.c 26 Jan 2005 23:41:02 -0000
***************
*** 332,338 ****
/* ----------------------------------------------------------------
* heap_create_with_catalog - Create a cataloged relation
*
! * this is done in 6 steps:
*
* 1) CheckAttributeNamesTypes() is used to make certain the tuple
* descriptor contains a valid set of attribute names and types
--- 332,338 ----
/* ----------------------------------------------------------------
* heap_create_with_catalog - Create a cataloged relation
*
! * this is done in 8 steps:
*
* 1) CheckAttributeNamesTypes() is used to make certain the tuple
* descriptor contains a valid set of attribute names and types
***************
*** 789,794 ****
--- 789,796 ----
* 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 dependency links to its owner and tablespace, as needed.
*/
if (!IsBootstrapProcessingMode())
{
***************
*** 798,807 ****
--- 800,826 ----
myself.classId = RelOid_pg_class;
myself.objectId = new_rel_oid;
myself.objectSubId = 0;
+
+ /* the relation depends on its namespace */
referenced.classId = get_system_catalog_relid(NamespaceRelationName);
referenced.objectId = relnamespace;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ /* the relation depends on its tablespace, if specified */
+ if (reltablespace != 0)
+ {
+ referenced.classId = get_system_catalog_relid(TableSpaceRelationName);
+ referenced.objectId = reltablespace;
+ referenced.objectSubId = 0;
+ recordSharedDependencyOn(&myself, &referenced);
+ }
+
+ /* the relation depends on its owner */
+ referenced.classId = get_system_catalog_relid(ShadowRelationName);
+ referenced.objectId = GetUserId();
+ referenced.objectSubId = 0;
+ recordSharedDependencyOn(&myself, &referenced);
}
/*
Index: src/backend/catalog/pg_conversion.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/pg_conversion.c,v
retrieving revision 1.20
diff -c -r1.20 pg_conversion.c
*** src/backend/catalog/pg_conversion.c 31 Dec 2004 21:59:38 -0000 1.20
--- src/backend/catalog/pg_conversion.c 10 Jan 2005 23:32:55 -0000
***************
*** 121,126 ****
--- 121,132 ----
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ /* record shared dependency on owner */
+ referenced.classId = get_system_catalog_relid(ShadowRelationName);
+ referenced.objectId = conowner;
+ referenced.objectSubId = 0;
+ recordSharedDependencyOn(&myself, &referenced);
+
heap_freetuple(tup);
heap_close(rel, RowExclusiveLock);
Index: src/backend/catalog/pg_operator.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/pg_operator.c,v
retrieving revision 1.87
diff -c -r1.87 pg_operator.c
*** src/backend/catalog/pg_operator.c 31 Dec 2004 21:59:38 -0000 1.87
--- src/backend/catalog/pg_operator.c 10 Jan 2005 23:32:55 -0000
***************
*** 891,896 ****
--- 891,897 ----
/* 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))
***************
*** 964,967 ****
--- 965,974 ----
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
+
+ /* Dependency on owner */
+ referenced.classId = get_system_catalog_relid(ShadowRelationName);
+ referenced.objectId = oper->oprowner;
+ referenced.objectSubId = 0;
+ recordSharedDependencyOn(&myself, &referenced);
}
Index: src/backend/catalog/pg_proc.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/pg_proc.c,v
retrieving revision 1.122
diff -c -r1.122 pg_proc.c
*** src/backend/catalog/pg_proc.c 31 Dec 2004 21:59:38 -0000 1.122
--- src/backend/catalog/pg_proc.c 10 Jan 2005 23:32:56 -0000
***************
*** 295,300 ****
--- 295,303 ----
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
+ /* dependency on owner */
+ recordDependencyOnCurrentUser(&myself);
+
heap_freetuple(tup);
heap_close(rel, RowExclusiveLock);
Index: src/backend/catalog/pg_type.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/pg_type.c,v
retrieving revision 1.97
diff -c -r1.97 pg_type.c
*** src/backend/catalog/pg_type.c 31 Dec 2004 21:59:38 -0000 1.97
--- src/backend/catalog/pg_type.c 10 Jan 2005 23:32:56 -0000
***************
*** 488,493 ****
--- 488,496 ----
/* Normal dependency on the default expression. */
if (defaultExpr)
recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL);
+
+ /* Shared dependency on owner. */
+ recordDependencyOnCurrentUser(&myself);
}
/*
Index: src/backend/catalog/system_views.sql
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/system_views.sql,v
retrieving revision 1.11
diff -c -r1.11 system_views.sql
*** src/backend/catalog/system_views.sql 1 Jan 2005 20:44:14 -0000 1.11
--- src/backend/catalog/system_views.sql 10 Jan 2005 23:32:56 -0000
***************
*** 258,264 ****
CREATE VIEW pg_locks AS
SELECT *
! FROM pg_lock_status() AS L(relation oid, database oid,
transaction xid, pid int4, mode text, granted boolean);
CREATE VIEW pg_settings AS
--- 258,264 ----
CREATE VIEW pg_locks AS
SELECT *
! FROM pg_lock_status() AS L(object oid, class oid, database oid,
transaction xid, pid int4, mode text, granted boolean);
CREATE VIEW pg_settings AS
Index: src/backend/commands/conversioncmds.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/conversioncmds.c,v
retrieving revision 1.16
diff -c -r1.16 conversioncmds.c
*** src/backend/commands/conversioncmds.c 31 Dec 2004 21:59:41 -0000 1.16
--- src/backend/commands/conversioncmds.c 10 Jan 2005 23:32:56 -0000
***************
*** 18,23 ****
--- 18,24 ----
#include "access/heapam.h"
#include "catalog/catalog.h"
#include "catalog/catname.h"
+ #include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_type.h"
***************
*** 221,226 ****
--- 222,231 ----
simple_heap_update(rel, &tup->t_self, tup);
CatalogUpdateIndexes(rel, tup);
+ /* Update shared dependency reference */
+ shdependChangeOwner(get_system_catalog_relid(ConversionRelationName),
+ conversionOid,
+ newOwnerSysId);
}
heap_close(rel, NoLock);
Index: src/backend/commands/dbcommands.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/dbcommands.c,v
retrieving revision 1.148
diff -c -r1.148 dbcommands.c
*** src/backend/commands/dbcommands.c 31 Dec 2004 21:59:41 -0000 1.148
--- src/backend/commands/dbcommands.c 10 Jan 2005 23:32:56 -0000
***************
*** 23,28 ****
--- 23,29 ----
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/catalog.h"
+ #include "catalog/dependency.h"
#include "catalog/pg_database.h"
#include "catalog/pg_shadow.h"
#include "catalog/pg_tablespace.h"
***************
*** 343,348 ****
--- 344,350 ----
/*
* Iterate through all tablespaces of the template database, and copy
* each one to the new database.
+ * XXX maybe it could be done better using pg_shdepend info.
*/
rel = heap_openr(TableSpaceRelationName, AccessShareLock);
scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
***************
*** 497,502 ****
--- 499,526 ----
/* Update indexes */
CatalogUpdateIndexes(pg_database_rel, tuple);
+ /* Create pg_shdepend entries */
+ copyTemplateDependencies(src_dboid, dboid);
+ /* Register tablespace and owner dependencies */
+ {
+ ObjectAddress myself,
+ referenced;
+
+ myself.classId = RelOid_pg_database;
+ myself.objectId = dboid;
+ myself.objectSubId = 0;
+
+ referenced.classId = RelOid_pg_shadow;
+ referenced.objectId = datdba;
+ referenced.objectSubId = 0;
+ recordSharedDependencyOn(&myself, &referenced);
+
+ referenced.classId = RelOid_pg_tablespace;
+ referenced.objectId = dst_deftablespace;
+ referenced.objectSubId = 0;
+ recordSharedDependencyOn(&myself, &referenced);
+ }
+
/*
* Force dirty buffers out to disk, so that newly-connecting backends
* will see the new database in pg_database right away. (They'll see
***************
*** 633,638 ****
--- 657,667 ----
remove_dbtablespaces(db_id);
/*
+ * Remove shared dependency references in the database.
+ */
+ dropDatabaseDependencies(db_id);
+
+ /*
* Force dirty buffers out to disk, so that newly-connecting backends
* will see the database tuple marked dead in pg_database right away.
* (They'll see an uncommitted deletion, but they don't care; see
***************
*** 917,922 ****
--- 946,958 ----
heap_freetuple(newtuple);
+ /*
+ * Update shared dependency references
+ */
+ shdependChangeOwner(RelOid_pg_database,
+ HeapTupleGetOid(tuple),
+ newOwnerSysId);
+
/* must release buffer pins before FlushRelationBuffers */
systable_endscan(scan);
Index: src/backend/commands/functioncmds.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/functioncmds.c,v
retrieving revision 1.53
diff -c -r1.53 functioncmds.c
*** src/backend/commands/functioncmds.c 31 Dec 2004 21:59:41 -0000 1.53
--- src/backend/commands/functioncmds.c 10 Jan 2005 23:32:57 -0000
***************
*** 798,803 ****
--- 798,808 ----
simple_heap_update(rel, &newtuple->t_self, newtuple);
CatalogUpdateIndexes(rel, newtuple);
+ /* update shared dependency reference */
+ shdependChangeOwner(get_system_catalog_relid(ProcedureRelationName),
+ procOid,
+ newOwnerSysId);
+
heap_freetuple(newtuple);
}
Index: src/backend/commands/opclasscmds.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/opclasscmds.c,v
retrieving revision 1.29
diff -c -r1.29 opclasscmds.c
*** src/backend/commands/opclasscmds.c 31 Dec 2004 21:59:41 -0000 1.29
--- src/backend/commands/opclasscmds.c 10 Jan 2005 23:32:57 -0000
***************
*** 392,397 ****
--- 392,400 ----
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
+ /* dependency on owner */
+ recordDependencyOnCurrentUser(&myself);
+
heap_close(rel, RowExclusiveLock);
}
***************
*** 964,969 ****
--- 967,977 ----
CatalogUpdateIndexes(rel, tup);
}
+ /* Update shared dependency reference */
+ shdependChangeOwner(get_system_catalog_relid(OperatorClassRelationName),
+ amOid,
+ newOwnerSysId);
+
heap_close(rel, NoLock);
heap_freetuple(tup);
}
Index: src/backend/commands/operatorcmds.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/operatorcmds.c,v
retrieving revision 1.20
diff -c -r1.20 operatorcmds.c
*** src/backend/commands/operatorcmds.c 31 Dec 2004 21:59:41 -0000 1.20
--- src/backend/commands/operatorcmds.c 10 Jan 2005 23:32:57 -0000
***************
*** 311,316 ****
--- 311,323 ----
simple_heap_update(rel, &tup->t_self, tup);
CatalogUpdateIndexes(rel, tup);
+
+ /*
+ * Update shared dependency references.
+ */
+ shdependChangeOwner(get_system_catalog_relid(OperatorRelationName),
+ operOid,
+ newOwnerSysId);
}
heap_close(rel, NoLock);
Index: src/backend/commands/schemacmds.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/schemacmds.c,v
retrieving revision 1.27
diff -c -r1.27 schemacmds.c
*** src/backend/commands/schemacmds.c 31 Dec 2004 21:59:41 -0000 1.27
--- src/backend/commands/schemacmds.c 10 Jan 2005 23:32:57 -0000
***************
*** 47,52 ****
--- 47,53 ----
AclId owner_userid;
AclId saved_userid;
AclResult aclresult;
+ ObjectAddress myself;
saved_userid = GetUserId();
***************
*** 147,152 ****
--- 148,160 ----
}
}
+ /* Record dependency on owner*/
+ myself.classId = get_system_catalog_relid(NamespaceRelationName);
+ myself.objectId = namespaceId;
+ myself.objectSubId = 0;
+
+ recordDependencyOnCurrentUser(&myself);
+
/* Reset search path to normal state */
PopSpecialNamespace(namespaceId);
***************
*** 345,350 ****
--- 353,365 ----
CatalogUpdateIndexes(rel, newtuple);
heap_freetuple(newtuple);
+
+ /*
+ * Update shared dependency references.
+ */
+ shdependChangeOwner(get_system_catalog_relid(NamespaceRelationName),
+ HeapTupleGetOid(tup),
+ newOwnerSysId);
}
ReleaseSysCache(tup);
Index: src/backend/commands/tablecmds.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/tablecmds.c,v
retrieving revision 1.143
diff -c -r1.143 tablecmds.c
*** src/backend/commands/tablecmds.c 24 Jan 2005 23:21:57 -0000 1.143
--- src/backend/commands/tablecmds.c 26 Jan 2005 23:41:03 -0000
***************
*** 5285,5290 ****
--- 5285,5295 ----
heap_freetuple(newtuple);
/*
+ * Update shared dependency reference.
+ */
+ shdependChangeOwner(RelOid_pg_class, relationOid, newOwnerSysId);
+
+ /*
* If we are operating on a table, also change the ownership of
* any indexes and sequences that belong to the table, as well as
* the table's toast table (if it has one)
***************
*** 5468,5473 ****
--- 5473,5481 ----
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_TABLESPACE, tablespacename);
+ /* Update shared dependency reference */
+ shdependChangeTablespace(RelOid_pg_class, tab->relid, tablespaceId);
+
/* Save info for Phase 3 to do the real work */
if (OidIsValid(tab->newTableSpace))
ereport(ERROR,
Index: src/backend/commands/tablespace.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/tablespace.c,v
retrieving revision 1.15
diff -c -r1.15 tablespace.c
*** src/backend/commands/tablespace.c 31 Dec 2004 21:59:41 -0000 1.15
--- src/backend/commands/tablespace.c 10 Jan 2005 23:32:57 -0000
***************
*** 51,56 ****
--- 51,57 ----
#include "access/heapam.h"
#include "catalog/catalog.h"
#include "catalog/catname.h"
+ #include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_tablespace.h"
***************
*** 340,345 ****
--- 341,360 ----
set_short_version(location);
/*
+ * Record dependency link from tablespace to owner.
+ * XXX maybe this should be done after the symlink is created?
+ */
+ {
+ ObjectAddress myself;
+
+ myself.classId = RelOid_pg_tablespace;
+ myself.objectId = tablespaceoid;
+ myself.objectSubId = 0;
+
+ recordDependencyOnCurrentUser(&myself);
+ }
+
+ /*
* All seems well, create the symlink
*/
linkloc = (char *) palloc(strlen(DataDir) + 11 + 10 + 1);
***************
*** 439,444 ****
--- 454,472 ----
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE,
tablespacename);
+ /* Lock the tablespace */
+ LockSharedObject(tablespaceoid, RelOid_pg_tablespace, AccessExclusiveLock);
+
+ /* Verify pg_shdepend entries mentioning this tablespace. */
+ if (checkSharedDependencies(RelOid_pg_tablespace, tablespaceoid) > 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_IN_USE),
+ errmsg("cannot drop tablespace \"%s\"", tablespacename),
+ errdetail("Some objects depend on this tablespace.")));
+
+ /* Remove shared references from this tablespace to its owner */
+ deleteSharedDependencyRecordsFor(RelOid_pg_tablespace, tablespaceoid);
+
/*
* Remove the pg_tablespace tuple (this will roll back if we fail
* below)
***************
*** 865,870 ****
--- 893,903 ----
simple_heap_update(rel, &newtuple->t_self, newtuple);
CatalogUpdateIndexes(rel, newtuple);
+ /* Update shared dependency reference. */
+ shdependChangeOwner(RelOid_pg_tablespace,
+ HeapTupleGetOid(tup),
+ newOwnerSysId);
+
heap_freetuple(newtuple);
}
Index: src/backend/commands/typecmds.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/typecmds.c,v
retrieving revision 1.66
diff -c -r1.66 typecmds.c
*** src/backend/commands/typecmds.c 24 Jan 2005 23:21:57 -0000 1.66
--- src/backend/commands/typecmds.c 26 Jan 2005 23:41:03 -0000
***************
*** 2114,2119 ****
--- 2114,2123 ----
simple_heap_update(rel, &tup->t_self, tup);
CatalogUpdateIndexes(rel, tup);
+
+ shdependChangeOwner(get_system_catalog_relid(TypeRelationName),
+ typeOid,
+ newOwnerSysId);
}
/* Clean up */
Index: src/backend/commands/user.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/user.c,v
retrieving revision 1.147
diff -c -r1.147 user.c
*** src/backend/commands/user.c 31 Dec 2004 21:59:42 -0000 1.147
--- src/backend/commands/user.c 10 Jan 2005 23:32:57 -0000
***************
*** 19,24 ****
--- 19,25 ----
#include "access/heapam.h"
#include "catalog/catname.h"
+ #include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/pg_database.h"
#include "catalog/pg_group.h"
***************
*** 1091,1097 ****
tmp_tuple;
Relation pg_rel;
TupleDesc pg_dsc;
- ScanKeyData scankey;
HeapScanDesc scan;
AclId usesysid;
--- 1092,1097 ----
***************
*** 1115,1156 ****
errmsg("session user cannot be dropped")));
/*
! * Check if user 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_openr(DatabaseRelationName, AccessShareLock);
! pg_dsc = RelationGetDescr(pg_rel);
!
! ScanKeyInit(&scankey,
! Anum_pg_database_datdba,
! BTEqualStrategyNumber, F_INT4EQ,
! Int32GetDatum(usesysid));
!
! 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);
ereport(ERROR,
(errcode(ERRCODE_OBJECT_IN_USE),
errmsg("user \"%s\" cannot be dropped", user),
! errdetail("The user 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
! * user as well, but those could be spread out over all sorts of
! * databases which we don't have access to (easily).
! */
/*
* Remove the user from the pg_shadow table
--- 1115,1131 ----
errmsg("session user cannot be dropped")));
/*
! * Lock the user, so nobody can add dependencies to her while we drop
! * her. We keep the lock until the end of transaction.
! */
! LockSharedObject(usesysid, RelOid_pg_shadow, AccessExclusiveLock);
! /* Verify pg_shdepend entries mentioning this user. */
! if (checkSharedDependencies(RelOid_pg_shadow, usesysid) > 0)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_IN_USE),
errmsg("user \"%s\" cannot be dropped", user),
! errdetail("Some objects depend on this user.")));
/*
* Remove the user from the pg_shadow table
Index: src/backend/storage/lmgr/README
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/storage/lmgr/README,v
retrieving revision 1.15
diff -c -r1.15 README
*** src/backend/storage/lmgr/README 27 Aug 2004 17:07:41 -0000 1.15
--- src/backend/storage/lmgr/README 22 Dec 2004 02:52:16 -0000
***************
*** 79,103 ****
any alignment-padding bytes the compiler might insert in the struct
be zeroed out, else the hash computation will be random.
! tag.relId -
! Uniquely identifies the relation that the lock corresponds to.
!
tag.dbId -
Uniquely identifies the database in which the relation lives. If
this is a shared system relation (e.g. pg_database) the dbId must
be set to 0.
! tag.objId -
! Uniquely identifies the block/page within the relation and the
! tuple within the block. If we are setting a table level lock
! both the blockId and tupleId (in an item pointer this is called
! the position) are set to invalid, if it is a page level lock the
! blockId is valid, while the tupleId is still invalid. Finally if
! this is a tuple level lock (we currently never do this) then both
! the blockId and tupleId are set to valid specifications. This is
! how we get the appearance of a multi-level lock table while using
! only a single table (see Gray's paper on 2 phase locking if
! you are puzzled about how multi-level lock tables work).
grantMask -
This bitmask indicates what types of locks are currently held on the
--- 79,114 ----
any alignment-padding bytes the compiler might insert in the struct
be zeroed out, else the hash computation will be random.
! tag.classId -
! Uniquely identifies the object class that the lock corresponds to.
! To lock a relation, RelOid_pg_class is used, and XactLockTableId
! to lock a transaction. Other objects can be locked using the Oid
! of the system catalog they belong to.
!
! tag.objId -
! Uniquely identifies the object within the class that the lock
! corresponds to.
!
tag.dbId -
Uniquely identifies the database in which the relation lives. If
this is a shared system relation (e.g. pg_database) the dbId must
be set to 0.
! tag.objsubId -
! In a transaction lock, contains the Xid of the locked transaction.
! In a relation lock, uniquely identifies the block/page within the
! relation. If we are setting a table level lock, the blkno is set
! to invalid.
!
! tag.offnum -
! If it is a page level lock, objsubId is set to a valid blkno
! specification, and offnum (which in an item pointer is called the
! position) is invalid. If this is a tuple level lock (we currently
! do this only in userlocks), both objsubId and offnum are set to
! valid specifications. This is how we get the appearance of a
! multi-level lock table while using only a single table (see Gray's
! paper on 2 phase locking if you are puzzled about how multi-level
! lock tables work).
grantMask -
This bitmask indicates what types of locks are currently held on the
Index: src/backend/storage/lmgr/deadlock.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/storage/lmgr/deadlock.c,v
retrieving revision 1.32
diff -c -r1.32 deadlock.c
*** src/backend/storage/lmgr/deadlock.c 31 Dec 2004 22:01:05 -0000 1.32
--- src/backend/storage/lmgr/deadlock.c 10 Jan 2005 23:33:02 -0000
***************
*** 860,883 ****
if (i > 0)
appendStringInfoChar(&buf, '\n');
! if (info->locktag.relId == XactLockTableId && info->locktag.dbId == 0)
{
/* Lock is for transaction ID */
appendStringInfo(&buf,
gettext("Process %d waits for %s on transaction %u; blocked by process %d."),
info->pid,
GetLockmodeName(info->lockmode),
! info->locktag.objId.xid,
nextpid);
}
! else
{
/* Lock is for a relation */
appendStringInfo(&buf,
gettext("Process %d waits for %s on relation %u of database %u; blocked by process %d."),
info->pid,
GetLockmodeName(info->lockmode),
! info->locktag.relId,
info->locktag.dbId,
nextpid);
}
--- 860,909 ----
if (i > 0)
appendStringInfoChar(&buf, '\n');
! if (info->locktag.objId == InvalidOid &&
! info->locktag.classId == XactLockTableId &&
! info->locktag.dbId == InvalidOid)
{
/* Lock is for transaction ID */
appendStringInfo(&buf,
gettext("Process %d waits for %s on transaction %u; blocked by process %d."),
info->pid,
GetLockmodeName(info->lockmode),
! info->locktag.objsubId.xid,
nextpid);
}
! else if (info->locktag.dbId != InvalidOid &&
! info->locktag.classId == RelOid_pg_class)
{
/* Lock is for a relation */
appendStringInfo(&buf,
gettext("Process %d waits for %s on relation %u of database %u; blocked by process %d."),
info->pid,
GetLockmodeName(info->lockmode),
! info->locktag.objId,
! info->locktag.dbId,
! nextpid);
! }
! else if (info->locktag.dbId == InvalidOid)
! {
! /* Lock is for a shared object */
! appendStringInfo(&buf,
! gettext("Process %d waits for %s on object %u of class %u; blocked by process %d."),
! info->pid,
! GetLockmodeName(info->lockmode),
! info->locktag.objId,
! info->locktag.classId,
! nextpid);
! }
! else
! {
! /* Lock is for an object of another class */
! appendStringInfo(&buf,
! gettext("Process %d waits for %s on object %u of class %u of database %u; blocked by process %d."),
! info->pid,
! GetLockmodeName(info->lockmode),
! info->locktag.objId,
! info->locktag.classId,
info->locktag.dbId,
nextpid);
}
Index: src/backend/storage/lmgr/lmgr.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/storage/lmgr/lmgr.c,v
retrieving revision 1.71
diff -c -r1.71 lmgr.c
*** src/backend/storage/lmgr/lmgr.c 31 Dec 2004 22:01:05 -0000 1.71
--- src/backend/storage/lmgr/lmgr.c 26 Jan 2005 23:48:48 -0000
***************
*** 134,142 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = relation->rd_lockInfo.lockRelId.relId;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objId.blkno = InvalidBlockNumber;
if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
lockmode, false))
--- 134,143 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = relation->rd_lockInfo.lockRelId.relId;
! tag.classId = RelOid_pg_class;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objsubId.blkno = InvalidBlockNumber;
if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
lockmode, false))
***************
*** 168,176 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = relation->rd_lockInfo.lockRelId.relId;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objId.blkno = InvalidBlockNumber;
if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
lockmode, true))
--- 169,178 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = relation->rd_lockInfo.lockRelId.relId;
! tag.classId = RelOid_pg_class;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objsubId.blkno = InvalidBlockNumber;
if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
lockmode, true))
***************
*** 198,206 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = relation->rd_lockInfo.lockRelId.relId;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objId.blkno = InvalidBlockNumber;
LockRelease(LockTableId, &tag, GetTopTransactionId(), lockmode);
}
--- 200,209 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = relation->rd_lockInfo.lockRelId.relId;
! tag.classId = RelOid_pg_class;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objsubId.blkno = InvalidBlockNumber;
LockRelease(LockTableId, &tag, GetTopTransactionId(), lockmode);
}
***************
*** 223,231 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = relid->relId;
tag.dbId = relid->dbId;
! tag.objId.blkno = InvalidBlockNumber;
if (!LockAcquire(LockTableId, &tag, InvalidTransactionId,
lockmode, false))
--- 226,235 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = relid->relId;
! tag.classId = RelOid_pg_class;
tag.dbId = relid->dbId;
! tag.objsubId.blkno = InvalidBlockNumber;
if (!LockAcquire(LockTableId, &tag, InvalidTransactionId,
lockmode, false))
***************
*** 241,249 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = relid->relId;
tag.dbId = relid->dbId;
! tag.objId.blkno = InvalidBlockNumber;
LockRelease(LockTableId, &tag, InvalidTransactionId, lockmode);
}
--- 245,254 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = relid->relId;
! tag.classId = RelOid_pg_class;
tag.dbId = relid->dbId;
! tag.objsubId.blkno = InvalidBlockNumber;
LockRelease(LockTableId, &tag, InvalidTransactionId, lockmode);
}
***************
*** 261,269 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = relation->rd_lockInfo.lockRelId.relId;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objId.blkno = blkno;
if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
lockmode, false))
--- 266,275 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = relation->rd_lockInfo.lockRelId.relId;
! tag.classId = RelOid_pg_class;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objsubId.blkno = blkno;
if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
lockmode, false))
***************
*** 282,290 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = relation->rd_lockInfo.lockRelId.relId;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objId.blkno = blkno;
return LockAcquire(LockTableId, &tag, GetTopTransactionId(),
lockmode, true);
--- 288,297 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = relation->rd_lockInfo.lockRelId.relId;
! tag.classId = RelOid_pg_class;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objsubId.blkno = blkno;
return LockAcquire(LockTableId, &tag, GetTopTransactionId(),
lockmode, true);
***************
*** 299,307 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = relation->rd_lockInfo.lockRelId.relId;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objId.blkno = blkno;
LockRelease(LockTableId, &tag, GetTopTransactionId(), lockmode);
}
--- 306,315 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = relation->rd_lockInfo.lockRelId.relId;
! tag.classId = RelOid_pg_class;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objsubId.blkno = blkno;
LockRelease(LockTableId, &tag, GetTopTransactionId(), lockmode);
}
***************
*** 319,327 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = XactLockTableId;
tag.dbId = InvalidOid; /* xids are globally unique */
! tag.objId.xid = xid;
if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
ExclusiveLock, false))
--- 327,336 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = InvalidOid;
! tag.classId = XactLockTableId;
tag.dbId = InvalidOid; /* xids are globally unique */
! tag.objsubId.xid = xid;
if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
ExclusiveLock, false))
***************
*** 342,350 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = XactLockTableId;
tag.dbId = InvalidOid; /* xids are globally unique */
! tag.objId.xid = xid;
LockRelease(LockTableId, &tag, GetTopTransactionId(), ExclusiveLock);
}
--- 351,360 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = InvalidOid;
! tag.classId = XactLockTableId;
tag.dbId = InvalidOid; /* xids are globally unique */
! tag.objsubId.xid = xid;
LockRelease(LockTableId, &tag, GetTopTransactionId(), ExclusiveLock);
}
***************
*** 373,381 ****
Assert(!TransactionIdEquals(xid, myxid));
MemSet(&tag, 0, sizeof(tag));
! tag.relId = XactLockTableId;
tag.dbId = InvalidOid;
! tag.objId.xid = xid;
if (!LockAcquire(LockTableId, &tag, myxid, ShareLock, false))
elog(ERROR, "LockAcquire failed");
--- 383,392 ----
Assert(!TransactionIdEquals(xid, myxid));
MemSet(&tag, 0, sizeof(tag));
! tag.objId = InvalidOid;
! tag.classId = XactLockTableId;
tag.dbId = InvalidOid;
! tag.objsubId.xid = xid;
if (!LockAcquire(LockTableId, &tag, myxid, ShareLock, false))
elog(ERROR, "LockAcquire failed");
***************
*** 393,395 ****
--- 404,457 ----
if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid))
TransactionIdAbort(xid);
}
+
+ /*
+ * LockSharedObject
+ *
+ * Lock an arbitrary shared (non database-specific) object, such as
+ * a user or tablespace.
+ */
+ void
+ LockSharedObject(Oid objId, Oid classId, LOCKMODE lockmode)
+ {
+ LOCKTAG tag;
+
+ MemSet(&tag, 0, sizeof(tag));
+ tag.objId = objId;
+ tag.classId = classId;
+ tag.dbId = InvalidOid;
+ tag.objsubId.blkno = InvalidBlockNumber;
+
+ /* Only two reasonable lock types */
+ Assert(lockmode == AccessShareLock || lockmode == AccessExclusiveLock);
+
+ if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ lockmode, false))
+ elog(ERROR, "LockSharedObject: LockAcquire failed");
+ }
+
+ /*
+ * UnlockSharedObject
+ */
+ void
+ UnlockSharedObject(Oid objId, Oid classId, LOCKMODE lockmode)
+ {
+ LOCKTAG tag;
+
+ /* NoLock is a no-op */
+ if (lockmode == NoLock)
+ return;
+
+ MemSet(&tag, 0, sizeof(tag));
+ tag.objId = objId;
+ tag.classId = classId;
+ tag.dbId = InvalidOid;
+ tag.objsubId.blkno = InvalidBlockNumber;
+
+ /* Only two reasonable lock types */
+ Assert(lockmode == AccessShareLock
+ || lockmode == AccessExclusiveLock);
+
+ LockRelease(LockTableId, &tag, GetTopTransactionId(), lockmode);
+ }
+
Index: src/backend/storage/lmgr/lock.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/storage/lmgr/lock.c,v
retrieving revision 1.145
diff -c -r1.145 lock.c
*** src/backend/storage/lmgr/lock.c 31 Dec 2004 22:01:05 -0000 1.145
--- src/backend/storage/lmgr/lock.c 10 Jan 2005 23:33:02 -0000
***************
*** 110,117 ****
return
(((LOCK_LOCKMETHOD(*lock) == DEFAULT_LOCKMETHOD && Trace_locks)
|| (LOCK_LOCKMETHOD(*lock) == USER_LOCKMETHOD && Trace_userlocks))
! && (lock->tag.relId >= (Oid) Trace_lock_oidmin))
! || (Trace_lock_table && (lock->tag.relId == Trace_lock_table));
}
--- 110,117 ----
return
(((LOCK_LOCKMETHOD(*lock) == DEFAULT_LOCKMETHOD && Trace_locks)
|| (LOCK_LOCKMETHOD(*lock) == USER_LOCKMETHOD && Trace_userlocks))
! && (lock->tag.objId >= (Oid) Trace_lock_oidmin))
! || (Trace_lock_table && (lock->tag.objId == Trace_lock_table));
}
***************
*** 120,131 ****
{
if (LOCK_DEBUG_ENABLED(lock))
elog(LOG,
! "%s: lock(%lx) tbl(%d) rel(%u) db(%u) obj(%u) grantMask(%x) "
"req(%d,%d,%d,%d,%d,%d,%d)=%d "
"grant(%d,%d,%d,%d,%d,%d,%d)=%d wait(%d) type(%s)",
where, MAKE_OFFSET(lock),
! lock->tag.lockmethodid, lock->tag.relId, lock->tag.dbId,
! lock->tag.objId.blkno, lock->grantMask,
lock->requested[1], lock->requested[2], lock->requested[3],
lock->requested[4], lock->requested[5], lock->requested[6],
lock->requested[7], lock->nRequested,
--- 120,131 ----
{
if (LOCK_DEBUG_ENABLED(lock))
elog(LOG,
! "%s: lock(%lx) tbl(%d) obj(%u) class(%u) db(%u) objsub(%u) grantMask(%x) "
"req(%d,%d,%d,%d,%d,%d,%d)=%d "
"grant(%d,%d,%d,%d,%d,%d,%d)=%d wait(%d) type(%s)",
where, MAKE_OFFSET(lock),
! lock->tag.lockmethodid, lock->tag.objId, lock->tag.classId, lock->tag.dbId,
! lock->tag.objsubId.blkno, lock->grantMask,
lock->requested[1], lock->requested[2], lock->requested[3],
lock->requested[4], lock->requested[5], lock->requested[6],
lock->requested[7], lock->nRequested,
***************
*** 142,149 ****
if (
(((PROCLOCK_LOCKMETHOD(*proclockP) == DEFAULT_LOCKMETHOD && Trace_locks)
|| (PROCLOCK_LOCKMETHOD(*proclockP) == USER_LOCKMETHOD && Trace_userlocks))
! && (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.relId >= (Oid) Trace_lock_oidmin))
! || (Trace_lock_table && (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.relId == Trace_lock_table))
)
elog(LOG,
"%s: proclock(%lx) lock(%lx) tbl(%d) proc(%lx) xid(%u) hold(%x)",
--- 142,149 ----
if (
(((PROCLOCK_LOCKMETHOD(*proclockP) == DEFAULT_LOCKMETHOD && Trace_locks)
|| (PROCLOCK_LOCKMETHOD(*proclockP) == USER_LOCKMETHOD && Trace_userlocks))
! && (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.objId >= (Oid) Trace_lock_oidmin))
! || (Trace_lock_table && (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.objId == Trace_lock_table))
)
elog(LOG,
"%s: proclock(%lx) lock(%lx) tbl(%d) proc(%lx) xid(%u) hold(%x)",
***************
*** 422,429 ****
*
* lockmethodid 1 2
* tag.dbId database oid database oid
! * tag.relId rel oid or 0 0
! * tag.objId block id lock id2
* or xact id
* tag.offnum 0 lock id1
* proclock.xid xid or 0 0
--- 422,430 ----
*
* lockmethodid 1 2
* tag.dbId database oid database oid
! * tag.classId class oid 0
! * tag.objId rel oid or 0 0
! * tag.objsubId block id lock id2
* or xact id
* tag.offnum 0 lock id1
* proclock.xid xid or 0 0
***************
*** 456,462 ****
#ifdef LOCK_DEBUG
if (lockmethodid == USER_LOCKMETHOD && Trace_userlocks)
elog(LOG, "LockAcquire: user lock [%u] %s",
! locktag->objId.blkno, lock_mode_names[lockmode]);
#endif
/* ???????? This must be changed when short term locks will be used */
--- 457,463 ----
#ifdef LOCK_DEBUG
if (lockmethodid == USER_LOCKMETHOD && Trace_userlocks)
elog(LOG, "LockAcquire: user lock [%u] %s",
! locktag->objsubId.blkno, lock_mode_names[lockmode]);
#endif
/* ???????? This must be changed when short term locks will be used */
***************
*** 665,671 ****
elog(LOG, "deadlock risk: raising lock level"
" from %s to %s on object %u/%u/%u",
lock_mode_names[i], lock_mode_names[lockmode],
! lock->tag.relId, lock->tag.dbId, lock->tag.objId.blkno);
break;
}
}
--- 666,672 ----
elog(LOG, "deadlock risk: raising lock level"
" from %s to %s on object %u/%u/%u",
lock_mode_names[i], lock_mode_names[lockmode],
! lock->tag.objId, lock->tag.dbId, lock->tag.objsubId.blkno);
break;
}
}
***************
*** 1150,1156 ****
#ifdef LOCK_DEBUG
if (lockmethodid == USER_LOCKMETHOD && Trace_userlocks)
! elog(LOG, "LockRelease: user lock tag [%u] %d", locktag->objId.blkno, lockmode);
#endif
/* ???????? This must be changed when short term locks will be used */
--- 1151,1157 ----
#ifdef LOCK_DEBUG
if (lockmethodid == USER_LOCKMETHOD && Trace_userlocks)
! elog(LOG, "LockRelease: user lock tag [%u] %d", locktag->objsubId.blkno, lockmode);
#endif
/* ???????? This must be changed when short term locks will be used */
Index: src/backend/utils/adt/acl.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/utils/adt/acl.c,v
retrieving revision 1.113
diff -c -r1.113 acl.c
*** src/backend/utils/adt/acl.c 31 Dec 2004 22:01:21 -0000 1.113
--- src/backend/utils/adt/acl.c 11 Jan 2005 00:11:01 -0000
***************
*** 308,313 ****
--- 308,361 ----
}
/*
+ * aclmembers
+ * Returns all the members of the Acl, in two lists,
+ * one for users and other for the groups.
+ */
+ void
+ aclmembers(const Acl *acl, List **users, List **groups)
+ {
+ int i;
+ AclItem *acldat;
+
+ *users = NIL;
+ *groups = NIL;
+
+ if (acl == NULL)
+ return;
+
+ acldat = ACL_DAT(acl);
+
+ /*
+ * Walk the whole ACL searching. We skip "public" items, since they don't
+ * refer to a particular user or group; for anything else, we first check
+ * that we haven't added it already to the corresponding list.
+ */
+ for (i = 0; i < ACL_NUM(acl); i++)
+ {
+ AclItem ai = acldat[i];
+
+ switch (ACLITEM_GET_IDTYPE(ai))
+ {
+ case ACL_IDTYPE_WORLD:
+ break;
+ case ACL_IDTYPE_UID:
+ if (!list_member_oid(*users, ai.ai_grantee))
+ *users = lappend_oid(*users, ai.ai_grantee);
+ break;
+ case ACL_IDTYPE_GID:
+ if (!list_member_oid(*groups, ai.ai_grantee))
+ *groups = lappend_oid(*groups, ai.ai_grantee);
+ break;
+ }
+
+ if (!list_member_oid(*users, ai.ai_grantor))
+ *users = lappend_oid(*users, ai.ai_grantor);
+ }
+ }
+
+
+ /*
* allocacl
* Allocates storage for a new Acl with 'n' entries.
*
Index: src/backend/utils/adt/lockfuncs.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/utils/adt/lockfuncs.c,v
retrieving revision 1.16
diff -c -r1.16 lockfuncs.c
*** src/backend/utils/adt/lockfuncs.c 1 Jan 2005 05:43:07 -0000 1.16
--- src/backend/utils/adt/lockfuncs.c 10 Jan 2005 23:47:39 -0000
***************
*** 53,70 ****
/* build tupdesc for result tuples */
/* this had better match pg_locks view in system_views.sql */
! tupdesc = CreateTemplateTupleDesc(6, false);
! TupleDescInitEntry(tupdesc, (AttrNumber) 1, "relation",
OIDOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database",
OIDOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 3, "transaction",
XIDOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 4, "pid",
INT4OID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 5, "mode",
TEXTOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 6, "granted",
BOOLOID, -1, 0);
funcctx->tuple_desc = BlessTupleDesc(tupdesc);
--- 53,72 ----
/* build tupdesc for result tuples */
/* this had better match pg_locks view in system_views.sql */
! tupdesc = CreateTemplateTupleDesc(7, false);
! TupleDescInitEntry(tupdesc, (AttrNumber) 1, "object",
OIDOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 2, "class",
OIDOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 3, "database",
! OIDOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 4, "transaction",
XIDOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 5, "pid",
INT4OID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 6, "mode",
TEXTOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 7, "granted",
BOOLOID, -1, 0);
funcctx->tuple_desc = BlessTupleDesc(tupdesc);
***************
*** 93,100 ****
PGPROC *proc;
bool granted;
LOCKMODE mode = 0;
! Datum values[6];
! char nulls[6];
HeapTuple tuple;
Datum result;
--- 95,102 ----
PGPROC *proc;
bool granted;
LOCKMODE mode = 0;
! Datum values[7];
! char nulls[7];
HeapTuple tuple;
Datum result;
***************
*** 155,180 ****
MemSet(values, 0, sizeof(values));
MemSet(nulls, ' ', sizeof(nulls));
! if (lock->tag.relId == XactLockTableId && lock->tag.dbId == 0)
{
/* Lock is for transaction ID */
nulls[0] = 'n';
nulls[1] = 'n';
! values[2] = TransactionIdGetDatum(lock->tag.objId.xid);
}
else
{
/* Lock is for a relation */
! values[0] = ObjectIdGetDatum(lock->tag.relId);
! values[1] = ObjectIdGetDatum(lock->tag.dbId);
! nulls[2] = 'n';
}
! values[3] = Int32GetDatum(proc->pid);
! values[4] = DirectFunctionCall1(textin,
CStringGetDatum(GetLockmodeName(mode)));
! values[5] = BoolGetDatum(granted);
tuple = heap_formtuple(funcctx->tuple_desc, values, nulls);
result = HeapTupleGetDatum(tuple);
--- 157,186 ----
MemSet(values, 0, sizeof(values));
MemSet(nulls, ' ', sizeof(nulls));
! if (lock->tag.objId == InvalidOid
! && lock->tag.classId == XactLockTableId
! && lock->tag.dbId == InvalidOid)
{
/* Lock is for transaction ID */
nulls[0] = 'n';
nulls[1] = 'n';
! nulls[2] = 'n';
! values[3] = TransactionIdGetDatum(lock->tag.objsubId.xid);
}
else
{
/* Lock is for a relation */
! values[0] = ObjectIdGetDatum(lock->tag.objId);
! values[1] = ObjectIdGetDatum(lock->tag.classId);
! values[2] = ObjectIdGetDatum(lock->tag.dbId);
! nulls[3] = 'n';
}
! values[4] = Int32GetDatum(proc->pid);
! values[5] = DirectFunctionCall1(textin,
CStringGetDatum(GetLockmodeName(mode)));
! values[6] = BoolGetDatum(granted);
tuple = heap_formtuple(funcctx->tuple_desc, values, nulls);
result = HeapTupleGetDatum(tuple);
Index: src/bin/initdb/initdb.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/bin/initdb/initdb.c,v
retrieving revision 1.73
diff -c -r1.73 initdb.c
*** src/bin/initdb/initdb.c 8 Jan 2005 22:51:12 -0000 1.73
--- src/bin/initdb/initdb.c 10 Jan 2005 23:33:06 -0000
***************
*** 174,179 ****
--- 174,180 ----
static void get_set_pwd(void);
static void unlimit_systables(void);
static void setup_depend(void);
+ static void setup_shared_depend(void);
static void setup_sysviews(void);
static void setup_description(void);
static void setup_conversion(void);
***************
*** 1562,1567 ****
--- 1563,1662 ----
check_ok();
}
+ static void
+ setup_shared_depend(void)
+ {
+ PG_CMD_DECL;
+ char **line;
+ static char *pg_shdepend_setup[] = {
+ /*
+ * Fill pg_shdepend with info about all existant objects.
+ * We need to take the ownership and tablespace into consideration.
+ *
+ * Note that we first clear the table to rid of dependencies recorded
+ * by normal operation, because it's incomplete.
+ */
+ "DELETE FROM pg_shdepend\n",
+
+ /* Entries for owners of database-local objects */
+ "INSERT INTO pg_shdepend SELECT"
+ " (SELECT oid FROM pg_database WHERE datname=current_database()),"
+ " 'pg_type'::regclass, oid, 'pg_shadow'::regclass, typowner"
+ " FROM pg_type t\n",
+ "INSERT INTO pg_shdepend SELECT"
+ " (SELECT oid FROM pg_database WHERE datname=current_database()),"
+ " 'pg_proc'::regclass, oid, 'pg_shadow'::regclass, proowner"
+ " FROM pg_proc t\n",
+ "INSERT INTO pg_shdepend SELECT"
+ " (SELECT oid FROM pg_database WHERE datname=current_database()),"
+ " 'pg_class'::regclass, oid, 'pg_shadow'::regclass, relowner"
+ " FROM pg_class t\n",
+ "INSERT INTO pg_shdepend SELECT"
+ " (SELECT oid FROM pg_database WHERE datname=current_database()),"
+ " 'pg_operator'::regclass, oid, 'pg_shadow'::regclass, oprowner"
+ " FROM pg_operator t\n",
+ "INSERT INTO pg_shdepend SELECT"
+ " (SELECT oid FROM pg_database WHERE datname=current_database()),"
+ " 'pg_opclass'::regclass, oid, 'pg_shadow'::regclass, opcowner"
+ " FROM pg_opclass t\n",
+ "INSERT INTO pg_shdepend SELECT"
+ " (SELECT oid FROM pg_database WHERE datname=current_database()),"
+ " 'pg_am'::regclass, oid, 'pg_shadow'::regclass, amowner"
+ " FROM pg_am t\n",
+ "INSERT INTO pg_shdepend SELECT"
+ " (SELECT oid FROM pg_database WHERE datname=current_database()),"
+ " 'pg_namespace'::regclass, oid, 'pg_shadow'::regclass, nspowner"
+ " FROM pg_namespace t\n",
+ "INSERT INTO pg_shdepend SELECT"
+ " (SELECT oid FROM pg_database WHERE datname=current_database()),"
+ " 'pg_conversion'::regclass, oid, 'pg_shadow'::regclass, conowner"
+ " FROM pg_conversion t\n",
+
+ /* Entries for tablespaces of database-local objects */
+ "INSERT INTO pg_shdepend SELECT"
+ " (SELECT oid FROM pg_database WHERE datname=current_database()),"
+ " 'pg_class'::regclass, oid, 'pg_tablespace'::regclass, reltablespace"
+ " FROM pg_class t"
+ " WHERE reltablespace <> 0\n",
+
+ /* Entries for owners of shared objects */
+ "INSERT INTO pg_shdepend SELECT"
+ " 0,"
+ " 'pg_tablespace'::regclass, oid, 'pg_shadow'::regclass, spcowner"
+ " FROM pg_tablespace t\n",
+ "INSERT INTO pg_shdepend SELECT"
+ " 0,"
+ " 'pg_database'::regclass, oid, 'pg_shadow'::regclass, datdba"
+ " FROM pg_database t\n",
+ /* Entries for tablespaces of shared objects */
+ "INSERT INTO pg_shdepend SELECT"
+ " 0,"
+ " 'pg_database'::regclass, oid, 'pg_tablespace'::regclass, dattablespace"
+ " FROM pg_database t"
+ " WHERE dattablespace <> 0\n",
+ NULL
+ };
+
+
+ fputs(_("initializing pg_shdepend ... "), stdout);
+ fflush(stdout);
+
+ snprintf(cmd, sizeof(cmd),
+ "\"%s\" %s template1 >%s",
+ backend_exec, backend_options,
+ DEVNULL);
+
+ PG_CMD_OPEN;
+
+ for (line = pg_shdepend_setup; *line != NULL; line++)
+ PG_CMD_PUTS(*line);
+
+ PG_CMD_CLOSE;
+
+ check_ok();
+ }
+
+
/*
* set up system views
*/
***************
*** 2598,2603 ****
--- 2693,2700 ----
setup_depend();
+ setup_shared_depend();
+
setup_sysviews();
setup_description();
Index: src/include/catalog/catname.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/catalog/catname.h,v
retrieving revision 1.34
diff -c -r1.34 catname.h
*** src/include/catalog/catname.h 31 Dec 2004 22:03:24 -0000 1.34
--- src/include/catalog/catname.h 10 Jan 2005 23:33:34 -0000
***************
*** 25,30 ****
--- 25,31 ----
#define ConversionRelationName "pg_conversion"
#define DatabaseRelationName "pg_database"
#define DependRelationName "pg_depend"
+ #define SharedDependRelationName "pg_shdepend"
#define DescriptionRelationName "pg_description"
#define GroupRelationName "pg_group"
#define IndexRelationName "pg_index"
Index: src/include/catalog/dependency.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/catalog/dependency.h,v
retrieving revision 1.14
diff -c -r1.14 dependency.h
*** src/include/catalog/dependency.h 31 Dec 2004 22:03:24 -0000 1.14
--- src/include/catalog/dependency.h 10 Jan 2005 23:33:34 -0000
***************
*** 81,90 ****
/*
! * This enum covers all system catalogs whose OIDs can appear in classId.
*/
typedef enum ObjectClass
{
OCLASS_CLASS, /* pg_class */
OCLASS_PROC, /* pg_proc */
OCLASS_TYPE, /* pg_type */
--- 81,92 ----
/*
! * This enum covers all system catalogs whose OIDs can appear in
! * pg_depend.classId or pg_shdepend.classId.
*/
typedef enum ObjectClass
{
+ OCLASS_AM, /* pg_am */
OCLASS_CLASS, /* pg_class */
OCLASS_PROC, /* pg_proc */
OCLASS_TYPE, /* pg_type */
***************
*** 98,103 ****
--- 100,109 ----
OCLASS_REWRITE, /* pg_rewrite */
OCLASS_TRIGGER, /* pg_trigger */
OCLASS_SCHEMA, /* pg_namespace */
+ /* shared system catalogs: */
+ OCLASS_TBLSPACE, /* pg_tablespace */
+ OCLASS_DATABASE, /* pg_database */
+ OCLASS_SHADOW, /* pg_shadow */
MAX_OCLASS /* MUST BE LAST */
} ObjectClass;
***************
*** 136,139 ****
--- 142,172 ----
extern long deleteDependencyRecordsFor(Oid classId, Oid objectId);
+ /* in pg_shdepend.c */
+
+ extern void recordSharedDependencyOn(const ObjectAddress *depender,
+ const ObjectAddress *referenced);
+
+ extern void recordDependencyOnCurrentUser(const ObjectAddress *depender);
+
+ extern void shdependChangeOwner(Oid classId, Oid objectId,
+ int newOwnerSysId);
+
+ extern void shdependChangeTablespace(Oid classId, Oid objectId,
+ Oid newTblspc);
+
+ extern void shdependUpdateAclInfo(Oid classId, Oid objectId, AclId ownerId, bool isGrant,
+ List *oldusers, List *newusers,
+ List *oldgroups, List *newgroups);
+
+ extern int checkSharedDependencies(Oid classId, Oid objectId);
+
+ extern void copyTemplateDependencies(Oid templateDbId, Oid newDbId);
+
+ extern void dropDatabaseDependencies(Oid databaseId);
+
+ extern void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId);
+
+ extern void deleteGlobalDependencyRecordsFor(Oid classId, Oid objectId);
+
#endif /* DEPENDENCY_H */
Index: src/include/catalog/indexing.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/catalog/indexing.h,v
retrieving revision 1.84
diff -c -r1.84 indexing.h
*** src/include/catalog/indexing.h 31 Dec 2004 22:03:24 -0000 1.84
--- src/include/catalog/indexing.h 10 Jan 2005 23:33:34 -0000
***************
*** 67,72 ****
--- 67,74 ----
#define ProcedureOidIndex "pg_proc_oid_index"
#define RewriteOidIndex "pg_rewrite_oid_index"
#define RewriteRelRulenameIndex "pg_rewrite_rel_rulename_index"
+ #define SharedDependDependerIndex "pg_shdepend_depender_index"
+ #define SharedDependReferenceIndex "pg_shdepend_reference_index"
#define ShadowNameIndex "pg_shadow_usename_index"
#define ShadowSysidIndex "pg_shadow_usesysid_index"
#define StatisticRelidAttnumIndex "pg_statistic_relid_att_index"
***************
*** 165,170 ****
--- 167,176 ----
/* This following index is not used for a cache and is not unique */
DECLARE_UNIQUE_INDEX(pg_rewrite_oid_index on pg_rewrite using btree(oid oid_ops));
DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index on pg_rewrite using btree(ev_class oid_ops, rulename name_ops));
+ /* This following index is not used for a cache and is not unique */
+ DECLARE_INDEX(pg_shdepend_depender_index on pg_shdepend using btree(dbid oid_ops, classid oid_ops, objid oid_ops));
+ /* This following index is not used for a cache and is not unique */
+ DECLARE_INDEX(pg_shdepend_reference_index on pg_shdepend using btree(refclassid oid_ops, refobjid oid_ops));
DECLARE_UNIQUE_INDEX(pg_shadow_usename_index on pg_shadow using btree(usename name_ops));
DECLARE_UNIQUE_INDEX(pg_shadow_usesysid_index on pg_shadow using btree(usesysid int4_ops));
DECLARE_UNIQUE_INDEX(pg_statistic_relid_att_index on pg_statistic using btree(starelid oid_ops, staattnum int2_ops));
Index: src/include/storage/lmgr.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/storage/lmgr.h,v
retrieving revision 1.45
diff -c -r1.45 lmgr.h
*** src/include/storage/lmgr.h 31 Dec 2004 22:03:42 -0000 1.45
--- src/include/storage/lmgr.h 10 Jan 2005 23:33:37 -0000
***************
*** 61,64 ****
--- 61,68 ----
extern void XactLockTableDelete(TransactionId xid);
extern void XactLockTableWait(TransactionId xid);
+ /* Lock an arbitrary shared object */
+ extern void LockSharedObject(Oid objId, Oid classId, LOCKMODE lockmode);
+ extern void UnlockSharedObject(Oid objId, Oid classId, LOCKMODE lockmode);
+
#endif /* LMGR_H */
Index: src/include/storage/lock.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/storage/lock.h,v
retrieving revision 1.84
diff -c -r1.84 lock.h
*** src/include/storage/lock.h 31 Dec 2004 22:03:42 -0000 1.84
--- src/include/storage/lock.h 10 Jan 2005 23:33:38 -0000
***************
*** 106,121 ****
*/
typedef struct LOCKTAG
{
! Oid relId;
Oid dbId;
union
{
BlockNumber blkno;
TransactionId xid;
! } objId;
/*
! * offnum should be part of objId union above, but doing that would
* increase sizeof(LOCKTAG) due to padding. Currently used by
* userlocks only.
*/
--- 106,122 ----
*/
typedef struct LOCKTAG
{
! Oid objId;
! Oid classId;
Oid dbId;
union
{
BlockNumber blkno;
TransactionId xid;
! } objsubId;
/*
! * offnum should be part of objsubId union above, but doing that would
* increase sizeof(LOCKTAG) due to padding. Currently used by
* userlocks only.
*/
Index: src/include/utils/acl.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/utils/acl.h,v
retrieving revision 1.76
diff -c -r1.76 acl.h
*** src/include/utils/acl.h 31 Dec 2004 22:03:45 -0000 1.76
--- src/include/utils/acl.h 10 Jan 2005 23:48:11 -0000
***************
*** 228,233 ****
--- 228,234 ----
extern AclMode aclmask(const Acl *acl, AclId userid, AclId ownerid,
AclMode mask, AclMaskHow how);
+ extern void aclmembers(const Acl *acl, List **users, List **groups);
/*
* SQL functions (from acl.c)
Index: src/test/regress/expected/rules.out
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/test/regress/expected/rules.out,v
retrieving revision 1.95
diff -c -r1.95 rules.out
*** src/test/regress/expected/rules.out 27 Oct 2004 18:09:41 -0000 1.95
--- src/test/regress/expected/rules.out 19 Dec 2004 21:35:12 -0000
***************
*** 1276,1282 ****
--------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
iexit | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath);
pg_indexes | SELECT n.nspname AS schemaname, c.relname AS tablename, i.relname AS indexname, t.spcname AS "tablespace", pg_get_indexdef(i.oid) AS indexdef FROM ((((pg_index x JOIN pg_class c ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = i.reltablespace))) WHERE ((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char"));
! pg_locks | SELECT l.relation, l."database", l."transaction", l.pid, l."mode", l.granted FROM pg_lock_status() l(relation oid, "database" oid, "transaction" xid, pid integer, "mode" text, granted boolean);
pg_rules | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name);
pg_settings | SELECT a.name, a.setting, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val FROM pg_show_all_settings() a(name text, setting text, category text, short_desc text, extra_desc text, context text, vartype text, source text, min_val text, max_val text);
pg_stat_activity | SELECT d.oid AS datid, d.datname, pg_stat_get_backend_pid(s.backendid) AS procpid, pg_stat_get_backend_userid(s.backendid) AS usesysid, u.usename, pg_stat_get_backend_activity(s.backendid) AS current_query, pg_stat_get_backend_activity_start(s.backendid) AS query_start FROM pg_database d, (SELECT pg_stat_get_backend_idset() AS backendid) s, pg_shadow u WHERE ((pg_stat_get_backend_dbid(s.backendid) = d.oid) AND (pg_stat_get_backend_userid(s.backendid) = u.usesysid));
--- 1276,1282 ----
--------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
iexit | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath);
pg_indexes | SELECT n.nspname AS schemaname, c.relname AS tablename, i.relname AS indexname, t.spcname AS "tablespace", pg_get_indexdef(i.oid) AS indexdef FROM ((((pg_index x JOIN pg_class c ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = i.reltablespace))) WHERE ((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char"));
! pg_locks | SELECT l."object", l."class", l."database", l."transaction", l.pid, l."mode", l.granted FROM pg_lock_status() l("object" oid, "class" oid, "database" oid, "transaction" xid, pid integer, "mode" text, granted boolean);
pg_rules | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name);
pg_settings | SELECT a.name, a.setting, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val FROM pg_show_all_settings() a(name text, setting text, category text, short_desc text, extra_desc text, context text, vartype text, source text, min_val text, max_val text);
pg_stat_activity | SELECT d.oid AS datid, d.datname, pg_stat_get_backend_pid(s.backendid) AS procpid, pg_stat_get_backend_userid(s.backendid) AS usesysid, u.usename, pg_stat_get_backend_activity(s.backendid) AS current_query, pg_stat_get_backend_activity_start(s.backendid) AS query_start FROM pg_database d, (SELECT pg_stat_get_backend_idset() AS backendid) s, pg_shadow u WHERE ((pg_stat_get_backend_dbid(s.backendid) = d.oid) AND (pg_stat_get_backend_userid(s.backendid) = u.usesysid));
Index: src/test/regress/expected/sanity_check.out
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/test/regress/expected/sanity_check.out,v
retrieving revision 1.24
diff -c -r1.24 sanity_check.out
*** src/test/regress/expected/sanity_check.out 18 Jun 2004 06:14:27 -0000 1.24
--- src/test/regress/expected/sanity_check.out 10 Dec 2004 18:48:36 -0000
***************
*** 55,60 ****
--- 55,61 ----
pg_proc | t
pg_rewrite | t
pg_shadow | t
+ pg_shdepend | t
pg_statistic | t
pg_tablespace | t
pg_trigger | t
***************
*** 63,69 ****
shighway | t
tenk1 | t
tenk2 | t
! (53 rows)
--
-- another sanity check: every system catalog that has OIDs should have
--- 64,70 ----
shighway | t
tenk1 | t
tenk2 | t
! (54 rows)
--
-- another sanity check: every system catalog that has OIDs should have