Index: doc/src/sgml/catalogs.sgml =================================================================== RCS file: /home/alvherre/cvs/pgsql/doc/src/sgml/catalogs.sgml,v retrieving revision 2.94 diff -c -r2.94 catalogs.sgml *** doc/src/sgml/catalogs.sgml 13 Dec 2004 18:05:07 -0000 2.94 --- doc/src/sgml/catalogs.sgml 13 Dec 2004 20:15:32 -0000 *************** *** 174,179 **** --- 174,183 ---- + pg_shdepend + cross-database dependencies between objects + + pg_statistic planner statistics *************** *** 3095,3100 **** --- 3099,3174 ---- + + <structname>pg_shdepend</structname> + + + pg_shdepend + + + + The shared catalog pg_shdepend records the + dependency relationships between database objects and global objects, + such as users and tablespaces. This information allows DROP + USER and DROP TABLESPACE to ensure that + those objects are unreferenced before attempting to delete them. + + + + <structname>pg_depend</> 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 + + + + +
+
+ + <structname>pg_statistic</structname> 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/catalog.c =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/catalog.c,v retrieving revision 1.56 diff -c -r1.56 catalog.c *** src/backend/catalog/catalog.c 29 Aug 2004 04:12:26 -0000 1.56 --- src/backend/catalog/catalog.c 10 Dec 2004 20:48:52 -0000 *************** *** 9,15 **** * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/catalog/catalog.c,v 1.56 2004/08/29 04:12:26 momjian Exp $ * *------------------------------------------------------------------------- */ --- 9,15 ---- * * * IDENTIFICATION ! * $PostgreSQL: pgsql-server/src/backend/catalog/catalog.c,v 1.55 2004/08/04 21:33:47 tgl Exp $ * *------------------------------------------------------------------------- */ Index: src/backend/catalog/dependency.c =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/dependency.c,v retrieving revision 1.40 diff -c -r1.40 dependency.c *** src/backend/catalog/dependency.c 12 Oct 2004 21:54:36 -0000 1.40 --- src/backend/catalog/dependency.c 10 Dec 2004 14:32:52 -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.277 diff -c -r1.277 heap.c *** src/backend/catalog/heap.c 1 Dec 2004 19:00:39 -0000 1.277 --- src/backend/catalog/heap.c 10 Dec 2004 14:33:13 -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.19 diff -c -r1.19 pg_conversion.c *** src/backend/catalog/pg_conversion.c 29 Aug 2004 04:12:28 -0000 1.19 --- src/backend/catalog/pg_conversion.c 30 Oct 2004 15:18:49 -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.86 diff -c -r1.86 pg_operator.c *** src/backend/catalog/pg_operator.c 29 Aug 2004 04:12:29 -0000 1.86 --- src/backend/catalog/pg_operator.c 30 Oct 2004 15:19:29 -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.121 diff -c -r1.121 pg_proc.c *** src/backend/catalog/pg_proc.c 18 Oct 2004 01:45:38 -0000 1.121 --- src/backend/catalog/pg_proc.c 30 Oct 2004 04:01:36 -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.96 diff -c -r1.96 pg_type.c *** src/backend/catalog/pg_type.c 29 Aug 2004 05:06:41 -0000 1.96 --- src/backend/catalog/pg_type.c 8 Dec 2004 05:44:26 -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/commands/conversioncmds.c =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/conversioncmds.c,v retrieving revision 1.15 diff -c -r1.15 conversioncmds.c *** src/backend/commands/conversioncmds.c 29 Aug 2004 05:06:41 -0000 1.15 --- src/backend/commands/conversioncmds.c 30 Oct 2004 15:21:47 -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.147 diff -c -r1.147 dbcommands.c *** src/backend/commands/dbcommands.c 18 Nov 2004 01:14:26 -0000 1.147 --- src/backend/commands/dbcommands.c 10 Dec 2004 03:58:29 -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.52 diff -c -r1.52 functioncmds.c *** src/backend/commands/functioncmds.c 29 Aug 2004 05:06:41 -0000 1.52 --- src/backend/commands/functioncmds.c 30 Oct 2004 14:32:21 -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.28 diff -c -r1.28 opclasscmds.c *** src/backend/commands/opclasscmds.c 29 Aug 2004 05:06:41 -0000 1.28 --- src/backend/commands/opclasscmds.c 30 Oct 2004 15:22:27 -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.19 diff -c -r1.19 operatorcmds.c *** src/backend/commands/operatorcmds.c 29 Aug 2004 05:06:41 -0000 1.19 --- src/backend/commands/operatorcmds.c 30 Oct 2004 14:33:34 -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.26 diff -c -r1.26 schemacmds.c *** src/backend/commands/schemacmds.c 5 Nov 2004 19:15:57 -0000 1.26 --- src/backend/commands/schemacmds.c 6 Nov 2004 18:08:35 -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.140 diff -c -r1.140 tablecmds.c *** src/backend/commands/tablecmds.c 16 Nov 2004 23:34:22 -0000 1.140 --- src/backend/commands/tablecmds.c 2 Dec 2004 22:17:19 -0000 *************** *** 5256,5261 **** --- 5256,5266 ---- 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) *************** *** 5439,5444 **** --- 5444,5452 ---- 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.14 diff -c -r1.14 tablespace.c *** src/backend/commands/tablespace.c 5 Nov 2004 19:15:57 -0000 1.14 --- src/backend/commands/tablespace.c 9 Dec 2004 05:23:38 -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); + /* 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 dependency references to this tablespace */ + deleteGlobalDependencyRecordsFor(RelOid_pg_tablespace, tablespaceoid); + + /* 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.64 diff -c -r1.64 typecmds.c *** src/backend/commands/typecmds.c 7 Oct 2004 15:21:52 -0000 1.64 --- src/backend/commands/typecmds.c 30 Oct 2004 03:24:21 -0000 *************** *** 2111,2116 **** --- 2111,2120 ---- 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.146 diff -c -r1.146 user.c *** src/backend/commands/user.c 27 Sep 2004 04:01:23 -0000 1.146 --- src/backend/commands/user.c 8 Dec 2004 04:23:56 -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 ---- *************** *** 1114,1156 **** (errcode(ERRCODE_OBJECT_IN_USE), 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 --- 1114,1128 ---- (errcode(ERRCODE_OBJECT_IN_USE), errmsg("session user cannot be dropped"))); ! /* 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 shared dependency references to this user */ ! deleteGlobalDependencyRecordsFor(RelOid_pg_shadow, usesysid); /* * Remove the user from the pg_shadow table Index: src/bin/initdb/initdb.c =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/bin/initdb/initdb.c,v retrieving revision 1.70 diff -c -r1.70 initdb.c *** src/bin/initdb/initdb.c 29 Nov 2004 03:05:03 -0000 1.70 --- src/bin/initdb/initdb.c 9 Dec 2004 07:53:10 -0000 *************** *** 173,178 **** --- 173,179 ---- 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); *************** *** 1559,1564 **** --- 1560,1659 ---- 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 */ *************** *** 2595,2600 **** --- 2690,2697 ---- setup_depend(); + setup_shared_depend(); + setup_sysviews(); setup_description(); Index: src/bin/psql/po/es.po =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/bin/psql/po/es.po,v retrieving revision 1.5 diff -c -r1.5 es.po *** src/bin/psql/po/es.po 11 Dec 2004 19:03:47 -0000 1.5 --- src/bin/psql/po/es.po 13 Dec 2004 20:17:40 -0000 *************** *** 809,815 **** #, c-format msgid " \\dp [PATTERN] list table, view, and sequence access privileges\n" msgstr "" ! "\\dp [PATRÓN] listar privilegios de acceso a tablas, vistas y secuencias\n" #: help.c:228 #, c-format --- 809,815 ---- #, c-format msgid " \\dp [PATTERN] list table, view, and sequence access privileges\n" msgstr "" ! " \\dp [PATRÓN] listar privilegios de acceso a tablas, vistas y secuencias\n" #: help.c:228 #, c-format *************** *** 835,841 **** msgstr "" " \\z [PATRÓN] listar privilegios de acceso a tablas, vistas y " "secuencias\n" ! " (lo mismo que \\dp)\n" #: help.c:234 #, c-format --- 835,841 ---- msgstr "" " \\z [PATRÓN] listar privilegios de acceso a tablas, vistas y " "secuencias\n" ! " (lo mismo que \\dp)\n" #: help.c:234 #, c-format Index: src/include/catalog/catname.h =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/include/catalog/catname.h,v retrieving revision 1.33 diff -c -r1.33 catname.h *** src/include/catalog/catname.h 29 Aug 2004 04:13:04 -0000 1.33 --- src/include/catalog/catname.h 29 Oct 2004 19:48:50 -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.13 diff -c -r1.13 dependency.h *** src/include/catalog/dependency.h 29 Aug 2004 04:13:04 -0000 1.13 --- src/include/catalog/dependency.h 10 Dec 2004 03:58:25 -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,168 ---- 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 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.83 diff -c -r1.83 indexing.h *** src/include/catalog/indexing.h 29 Aug 2004 04:13:05 -0000 1.83 --- src/include/catalog/indexing.h 29 Oct 2004 19:49:05 -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/catalog/pg_tablespace.h =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/include/catalog/pg_tablespace.h,v retrieving revision 1.4 diff -c -r1.4 pg_tablespace.h *** src/include/catalog/pg_tablespace.h 29 Aug 2004 05:06:55 -0000 1.4 --- src/include/catalog/pg_tablespace.h 10 Dec 2004 20:46:27 -0000 *************** *** 8,14 **** * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * ! * $PostgreSQL: pgsql/src/include/catalog/pg_tablespace.h,v 1.4 2004/08/29 05:06:55 momjian Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki --- 8,14 ---- * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * ! * $PostgreSQL: pgsql-server/src/include/catalog/pg_tablespace.h,v 1.3 2004/08/29 04:13:05 momjian Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki 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