? src/backend/catalog/pg_depend.c ? src/include/catalog/pg_depend.h Index: src/backend/catalog/Makefile =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/Makefile,v retrieving revision 1.39 diff -c -r1.39 Makefile *** src/backend/catalog/Makefile 2002/03/26 19:15:22 1.39 --- src/backend/catalog/Makefile 2002/03/31 18:33:50 *************** *** 12,18 **** OBJS = catalog.o heap.o index.o indexing.o namespace.o aclchk.o \ pg_aggregate.o pg_largeobject.o pg_namespace.o \ ! pg_operator.o pg_proc.o pg_type.o BKIFILES = postgres.bki postgres.description --- 12,18 ---- OBJS = catalog.o heap.o index.o indexing.o namespace.o aclchk.o \ pg_aggregate.o pg_largeobject.o pg_namespace.o \ ! pg_operator.o pg_proc.o pg_type.o pg_depend.o BKIFILES = postgres.bki postgres.description *************** *** 26,32 **** # indexing.h had better be last. POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\ ! pg_proc.h pg_type.h pg_attribute.h pg_class.h \ pg_attrdef.h pg_relcheck.h pg_inherits.h pg_index.h \ pg_operator.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \ pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \ --- 26,32 ---- # indexing.h had better be last. POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\ ! pg_proc.h pg_type.h pg_attribute.h pg_class.h pg_depend.h \ pg_attrdef.h pg_relcheck.h pg_inherits.h pg_index.h \ pg_operator.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \ pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \ Index: src/backend/catalog/heap.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/heap.c,v retrieving revision 1.193 diff -c -r1.193 heap.c *** src/backend/catalog/heap.c 2002/03/29 19:05:59 1.193 --- src/backend/catalog/heap.c 2002/03/31 18:35:04 *************** *** 37,42 **** --- 37,43 ---- #include "catalog/index.h" #include "catalog/indexing.h" #include "catalog/pg_attrdef.h" + #include "catalog/pg_depend.h" #include "catalog/pg_inherits.h" #include "catalog/pg_namespace.h" #include "catalog/pg_relcheck.h" *************** *** 50,55 **** --- 51,58 ---- #include "optimizer/planmain.h" #include "optimizer/prep.h" #include "optimizer/var.h" + #include "parser/parse.h" /* For keyword RESTRICT */ + #include "parser/parse_coerce.h" #include "parser/parse_expr.h" #include "parser/parse_relation.h" #include "parser/parse_target.h" *************** *** 71,78 **** char *temp_relname); static void DeleteAttributeTuples(Relation rel); static void DeleteRelationTuple(Relation rel); - static void DeleteTypeTuple(Relation rel); - static void RelationRemoveIndexes(Relation relation); static void RelationRemoveInheritance(Relation relation); static void AddNewRelationType(const char *typeName, Oid typeNamespace, --- 74,79 ---- *************** *** 261,266 **** --- 262,272 ---- nailme = true; relid = RelOid_pg_proc; } + else if (strcmp(DependRelationName, relname) == 0) + { + nailme = true; + relid = RelOid_pg_depend; + } else if (strcmp(RelationRelationName, relname) == 0) { nailme = true; *************** *** 433,438 **** --- 439,445 ---- bool hasindex; Relation idescs[Num_pg_attr_indices]; int natts = tupdesc->natts; + ObjectAddress myself, dependee; /* * open pg_attribute *************** *** 446,451 **** --- 453,463 ---- if (hasindex) CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs); + /* Prep Static dependency values */ + myself.classId = RelOid_pg_class; + myself.objectId = new_rel_oid; + dependee.classId = RelOid_pg_type; + /* * first we add the user attributes.. */ *************** *** 467,472 **** --- 479,492 ---- if (hasindex) CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup); + /* Register Dependencies */ + myself.objectSubId = (*dpp)->attnum; + + dependee.objectId = (*dpp)->atttypid; + dependee.objectSubId = 0; + + dependCreate(&myself, &dependee, false); + heap_freetuple(tup); dpp++; } *************** *** 489,494 **** --- 509,515 ---- attStruct = (Form_pg_attribute) GETSTRUCT(tup); attStruct->attrelid = new_rel_oid; + /* * Unneeded since they should be OK in the constant data * anyway *************** *** 503,508 **** --- 524,540 ---- heap_freetuple(tup); } + + /* Add Oid type dependency for Oid column*/ + if (relhasoids && (*dpp)->attnum == ObjectIdAttributeNumber) { + myself.objectSubId = (*dpp)->attnum; + + dependee.objectId = (*dpp)->atttypid; + dependee.objectSubId = 0; + + dependCreate(&myself, &dependee, false); + } + dpp++; } *************** *** 868,894 **** heap_close(catalogRelation, RowExclusiveLock); } - /* - * RelationRemoveIndexes - */ - static void - RelationRemoveIndexes(Relation relation) - { - List *indexoidlist, - *indexoidscan; - - indexoidlist = RelationGetIndexList(relation); - - foreach(indexoidscan, indexoidlist) - { - Oid indexoid = lfirsti(indexoidscan); - - index_drop(indexoid); - } - - freeList(indexoidlist); - } - /* -------------------------------- * DeleteRelationTuple * --- 900,905 ---- *************** *** 915,920 **** --- 926,932 ---- /* * delete the relation tuple from pg_class, and finish up. */ + simple_heap_delete(pg_class_desc, &tup->t_self); heap_freetuple(tup); *************** *** 1082,1194 **** heap_close(pg_attribute_desc, RowExclusiveLock); } - /* -------------------------------- - * DeleteTypeTuple - * - * If the user attempts to destroy a relation and there - * exists attributes in other relations of type - * "relation we are deleting", then we have to do something - * special. presently we disallow the destroy. - * -------------------------------- - */ - static void - DeleteTypeTuple(Relation rel) - { - Relation pg_type_desc; - HeapScanDesc pg_type_scan; - Relation pg_attribute_desc; - HeapScanDesc pg_attribute_scan; - ScanKeyData key; - ScanKeyData attkey; - HeapTuple tup; - HeapTuple atttup; - Oid typoid; - - /* - * open pg_type - */ - pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock); - - /* - * create a scan key to locate the type tuple corresponding to this - * relation. - */ - ScanKeyEntryInitialize(&key, 0, - Anum_pg_type_typrelid, - F_OIDEQ, - ObjectIdGetDatum(RelationGetRelid(rel))); - - pg_type_scan = heap_beginscan(pg_type_desc, - 0, - SnapshotNow, - 1, - &key); - - /* - * use heap_getnext() to fetch the pg_type tuple. If this tuple is - * not valid then something's wrong. - */ - tup = heap_getnext(pg_type_scan, 0); - - if (!HeapTupleIsValid(tup)) - { - heap_endscan(pg_type_scan); - heap_close(pg_type_desc, RowExclusiveLock); - elog(ERROR, "DeleteTypeTuple: type \"%s\" does not exist", - RelationGetRelationName(rel)); - } - - /* - * now scan pg_attribute. if any other relations have attributes of - * the type of the relation we are deleteing then we have to disallow - * the deletion. should talk to stonebraker about this. -cim 6/19/90 - */ - typoid = tup->t_data->t_oid; - - pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock); - - ScanKeyEntryInitialize(&attkey, - 0, - Anum_pg_attribute_atttypid, - F_OIDEQ, - ObjectIdGetDatum(typoid)); - - pg_attribute_scan = heap_beginscan(pg_attribute_desc, - 0, - SnapshotNow, - 1, - &attkey); - - /* - * try and get a pg_attribute tuple. if we succeed it means we can't - * delete the relation because something depends on the schema. - */ - atttup = heap_getnext(pg_attribute_scan, 0); - - if (HeapTupleIsValid(atttup)) - { - Oid relid = ((Form_pg_attribute) GETSTRUCT(atttup))->attrelid; - - heap_endscan(pg_attribute_scan); - heap_close(pg_attribute_desc, RowExclusiveLock); - heap_endscan(pg_type_scan); - heap_close(pg_type_desc, RowExclusiveLock); - - elog(ERROR, "DeleteTypeTuple: column of type %s exists in relation %u", - RelationGetRelationName(rel), relid); - } - heap_endscan(pg_attribute_scan); - heap_close(pg_attribute_desc, RowExclusiveLock); - - /* - * Ok, it's safe so we delete the relation tuple from pg_type and - * finish up. - */ - simple_heap_delete(pg_type_desc, &tup->t_self); - - heap_endscan(pg_type_scan); - heap_close(pg_type_desc, RowExclusiveLock); - } /* ---------------------------------------------------------------- * heap_drop_with_catalog - removes all record of named relation from catalogs --- 1094,1099 ---- *************** *** 1199,1207 **** * 4) remove pg_class tuple * 5) remove pg_attribute tuples and related descriptions * 6) remove pg_description tuples ! * 7) remove pg_type tuples ! * 8) RemoveConstraints () ! * 9) unlink relation * * old comments * Except for vital relations, removes relation from --- 1104,1111 ---- * 4) remove pg_class tuple * 5) remove pg_attribute tuples and related descriptions * 6) remove pg_description tuples ! * 7) RemoveConstraints () ! * 8) unlink relation * * old comments * Except for vital relations, removes relation from *************** *** 1228,1234 **** Oid toasttableOid; bool has_toasttable; bool istemp; ! int i; /* * Open and lock the relation. --- 1132,1140 ---- Oid toasttableOid; bool has_toasttable; bool istemp; ! int i, natts; ! ObjectAddress myself; ! HeapTuple tuple; /* * Open and lock the relation. *************** *** 1264,1270 **** if (rel->rd_rules != NULL) RelationRemoveRules(rid); ! /* triggers */ RelationRemoveTriggers(rel); /* --- 1170,1179 ---- if (rel->rd_rules != NULL) RelationRemoveRules(rid); ! /* triggers ! * ! * Should be updated to use pg_depend methods ! */ RelationRemoveTriggers(rel); /* *************** *** 1273,1283 **** RelationRemoveInheritance(rel); /* ! * remove indexes if necessary */ ! RelationRemoveIndexes(rel); /* * delete attribute tuples */ DeleteAttributeTuples(rel); --- 1182,1226 ---- RelationRemoveInheritance(rel); /* ! * Deal with dependencies ! * ! * Take care of any attributes first, then the main object ! * last when objectSubId = 0. Ignore system attributes. */ ! tuple = SearchSysCache(RELOID, rid, 0, 0, 0); ! if (!HeapTupleIsValid(tuple)) ! elog(ERROR, "Relation %s doesn't exist", RelationGetRelationName(rel)); ! ! natts = ((Form_pg_class) GETSTRUCT(tuple))->relnatts; ! ! /* Must free before calling dependDelete */ ! ReleaseSysCache(tuple); /* + * Drop in decending order so the table is handled after all + * of its columns. + * + * Oid first due to abilities like Primary Key on Oid. This is + * done whether it has oids or not. + */ + myself.classId = RelOid_pg_class; + myself.objectId = rid; + + /* + * Delete depends on Oid regardless of whether + * the relation has Oids or not. + */ + myself.objectSubId = ObjectIdAttributeNumber; + dependDelete(&myself, RESTRICT); + + for (i = natts; i >= 0; i--) + { + myself.objectSubId = i; + dependDelete(&myself, RESTRICT); + } + + + /* * delete attribute tuples */ DeleteAttributeTuples(rel); *************** *** 1289,1300 **** RemoveStatistics(rel); - RemoveConstraints(rel); - /* ! * delete type tuple */ ! DeleteTypeTuple(rel); /* * delete relation tuple --- 1232,1243 ---- RemoveStatistics(rel); /* ! * Remove constraints if necessary ! * ! * Should be updated to use pg_depend methods */ ! RemoveConstraints(rel); /* * delete relation tuple Index: src/backend/catalog/index.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/index.c,v retrieving revision 1.174 diff -c -r1.174 index.c *** src/backend/catalog/index.c 2002/03/26 19:15:28 1.174 --- src/backend/catalog/index.c 2002/03/31 18:35:09 *************** *** 32,37 **** --- 32,39 ---- #include "catalog/heap.h" #include "catalog/index.h" #include "catalog/indexing.h" + #include "catalog/pg_class.h" + #include "catalog/pg_depend.h" #include "catalog/pg_index.h" #include "catalog/pg_opclass.h" #include "catalog/pg_proc.h" *************** *** 41,46 **** --- 43,49 ---- #include "miscadmin.h" #include "optimizer/clauses.h" #include "optimizer/prep.h" + #include "parser/parse.h" /* For keyword RESTRICT */ #include "parser/parse_func.h" #include "storage/sinval.h" #include "storage/smgr.h" *************** *** 570,575 **** --- 573,581 ---- Oid indexoid; char *temp_relname = NULL; + ObjectAddress myself; + int i; + SetReindexProcessing(false); /* *************** *** 605,611 **** else indexTupDesc = ConstructTupleDescriptor(heapRelation, indexInfo->ii_NumKeyAttrs, ! indexInfo->ii_KeyAttrNumbers, classObjectId); if (istemp) --- 611,617 ---- else indexTupDesc = ConstructTupleDescriptor(heapRelation, indexInfo->ii_NumKeyAttrs, ! indexInfo->ii_KeyAttrNumbers, classObjectId); if (istemp) *************** *** 647,652 **** --- 653,687 ---- */ UpdateRelationRelation(indexRelation, temp_relname); + + myself.classId = RelOid_pg_class; + myself.objectId = indexoid; + myself.objectSubId = 0; + + /* Store dependencies on the attributes */ + for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++) + { + ObjectAddress dependee; + + dependee.classId = RelOid_pg_class; + dependee.objectId = heapRelationId; + dependee.objectSubId = indexInfo->ii_KeyAttrNumbers[i]; + + /* We always cascade index drops with attribute drops */ + dependCreate(&myself, &dependee, true); + } + + /* Store the dependency on the function (if appropriate) */ + if (OidIsValid(indexInfo->ii_FuncOid)) { + ObjectAddress dependee; + + dependee.classId = RelOid_pg_proc; + dependee.objectId = indexInfo->ii_FuncOid; + dependee.objectSubId = 0; + + dependCreate(&myself, &dependee, false); + } + /* * We create the disk file for this relation here */ *************** *** 726,731 **** --- 761,768 ---- HeapTuple tuple; int16 attnum; int i; + + ObjectAddress myself; Assert(OidIsValid(indexId)); *************** *** 835,840 **** --- 872,882 ---- heap_close(userHeapRelation, NoLock); RelationForgetRelation(indexId); + + myself.classId = RelOid_pg_class; + myself.objectId = indexId; + myself.objectSubId = 0; + dependDelete(&myself, RESTRICT); /* if it's a temp index, clear the temp mapping table entry */ remove_temp_rel_by_relid(indexId); Index: src/backend/catalog/namespace.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/namespace.c,v retrieving revision 1.3 diff -c -r1.3 namespace.c *** src/backend/catalog/namespace.c 2002/03/30 01:02:41 1.3 --- src/backend/catalog/namespace.c 2002/03/31 18:35:09 *************** *** 233,235 **** --- 233,261 ---- return rel; } + + /* + * namespaceIdGetNspname + * Fetch the namespace name by the namespace OID + */ + char * + namespaceIdGetNspname(Oid namespaceId) + { + char *schemaname; + HeapTuple tup; + + tup = SearchSysCache(NAMESPACEOID, + namespaceId, + 0, 0, 0); + + if (!HeapTupleIsValid(tup)) { + elog(ERROR, "namespaceIdGetName(): NamespaceId %d does not exist.", + namespaceId); + } + + schemaname = NameStr(((Form_pg_namespace) GETSTRUCT(tup))->nspname); + + ReleaseSysCache(tup); + + return(schemaname); + } Index: src/backend/catalog/pg_proc.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/pg_proc.c,v retrieving revision 1.67 diff -c -r1.67 pg_proc.c *** src/backend/catalog/pg_proc.c 2002/03/29 19:06:02 1.67 --- src/backend/catalog/pg_proc.c 2002/03/31 18:35:11 *************** *** 17,22 **** --- 17,23 ---- #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/indexing.h" + #include "catalog/pg_depend.h" #include "catalog/pg_language.h" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" Index: src/backend/catalog/pg_type.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/pg_type.c,v retrieving revision 1.70 diff -c -r1.70 pg_type.c *** src/backend/catalog/pg_type.c 2002/03/29 19:06:02 1.70 --- src/backend/catalog/pg_type.c 2002/03/31 18:35:13 *************** *** 17,22 **** --- 17,23 ---- #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/indexing.h" + #include "catalog/pg_depend.h" #include "catalog/pg_type.h" #include "miscadmin.h" #include "utils/builtins.h" *************** *** 167,172 **** --- 168,175 ---- NameData name; TupleDesc tupDesc; int i; + ObjectAddress myself; + ObjectAddress dependee; /* * validate size specifications: either positive (fixed-length) or -1 *************** *** 299,304 **** --- 302,363 ---- CatalogOpenIndices(Num_pg_type_indices, Name_pg_type_indices, idescs); CatalogIndexInsert(idescs, Num_pg_type_indices, pg_type_desc, tup); CatalogCloseIndices(Num_pg_type_indices, idescs); + } + + /* + * Create dependencies + */ + + /* Load our object address */ + myself.classId = RelOid_pg_type; + myself.objectId = typeObjectId; + myself.objectSubId = 0; + + /* Dependency on the input function */ + dependee.classId = RelOid_pg_proc; + dependee.objectId = DatumGetObjectId(values[Anum_pg_type_typinput - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + + /* Dependency on the output function */ + dependee.classId = RelOid_pg_proc; + dependee.objectId = DatumGetObjectId(values[Anum_pg_type_typoutput - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + + /* Dependency on the receive function */ + dependee.classId = RelOid_pg_proc; + dependee.objectId = DatumGetObjectId(values[Anum_pg_type_typreceive - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + + /* Dependency on the send function */ + dependee.classId = RelOid_pg_proc; + dependee.objectId = DatumGetObjectId(values[Anum_pg_type_typsend - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + + /* + * Dependency on the relation for complex types. Assume it's for + * a relation of somekind and drop it when the relation is removed. + */ + if (DatumGetObjectId(values[Anum_pg_type_typrelid - 1]) != InvalidOid) { + dependee.classId = RelOid_pg_class; + dependee.objectId = DatumGetObjectId(values[Anum_pg_type_typrelid - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, true); + } + + /* + * Dependency on the element Id for arrays. We can assume that it's for + * an array and that we should always cascade into this type when the base + * type is being removed. + */ + if (DatumGetObjectId(values[Anum_pg_type_typelem - 1]) != InvalidOid) { + dependee.classId = RelOid_pg_type; + dependee.objectId = DatumGetObjectId(values[Anum_pg_type_typelem - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, true); } /* Index: src/backend/commands/command.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/command.c,v retrieving revision 1.168 diff -c -r1.168 command.c *** src/backend/commands/command.c 2002/03/30 01:02:41 1.168 --- src/backend/commands/command.c 2002/03/31 18:35:33 *************** *** 28,33 **** --- 28,34 ---- #include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_attrdef.h" + #include "catalog/pg_depend.h" #include "catalog/pg_index.h" #include "catalog/pg_namespace.h" #include "catalog/pg_opclass.h" *************** *** 329,334 **** --- 330,337 ---- Form_pg_type tform; int attndims; + ObjectAddress myself, dependee; + /* * Grab an exclusive lock on the target table, which we will NOT * release until end of transaction. *************** *** 464,469 **** --- 467,484 ---- ReleaseSysCache(typeTuple); heap_insert(attrdesc, attributeTuple); + + /* Register Dependencies */ + myself.classId = RelOid_pg_class; + myself.objectId = attribute->attrelid; + myself.objectSubId = attribute->attnum; + + dependee.classId = RelOid_pg_type; + dependee.objectId = attribute->atttypid; + dependee.objectSubId = 0; + + dependCreate(&myself, &dependee, false); + /* Update indexes on pg_attribute */ if (RelationGetForm(attrdesc)->relhasindex) Index: src/backend/commands/proclang.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/proclang.c,v retrieving revision 1.29 diff -c -r1.29 proclang.c *** src/backend/commands/proclang.c 2002/02/18 23:11:11 1.29 --- src/backend/commands/proclang.c 2002/03/31 18:35:34 *************** *** 18,28 **** --- 18,30 ---- #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/indexing.h" + #include "catalog/pg_depend.h" #include "catalog/pg_language.h" #include "catalog/pg_proc.h" #include "commands/proclang.h" #include "fmgr.h" #include "miscadmin.h" + #include "parser/parse.h" /* For keyword RESTRICT */ #include "utils/builtins.h" #include "utils/syscache.h" *************** *** 49,65 **** void CreateProceduralLanguage(CreatePLangStmt *stmt) { ! char languageName[NAMEDATALEN]; ! HeapTuple procTup; ! Oid typev[FUNC_MAX_ARGS]; ! char nulls[Natts_pg_language]; ! Datum values[Natts_pg_language]; ! Relation rel; ! HeapTuple tup; ! TupleDesc tupDesc; ! int i; /* * Check permission --- 51,70 ---- void CreateProceduralLanguage(CreatePLangStmt *stmt) { ! char languageName[NAMEDATALEN]; ! HeapTuple procTup; ! Oid typev[FUNC_MAX_ARGS]; ! char nulls[Natts_pg_language]; ! Datum values[Natts_pg_language]; ! Relation rel; ! HeapTuple tup; ! TupleDesc tupDesc; ! ObjectAddress myself; ! ObjectAddress proc; ! ! int i; /* * Check permission *************** *** 96,101 **** --- 101,111 ---- elog(ERROR, "PL handler function %s() isn't of return type Opaque", stmt->plhandler); + /* Address of the PL handler function */ + proc.classId = RelOid_pg_proc; + proc.objectId = procTup->t_data->t_oid; + proc.objectSubId = 0; + /* * Insert the new language into pg_language */ *************** *** 132,137 **** --- 142,155 ---- CatalogCloseIndices(Num_pg_language_indices, idescs); } + /* Address of myself */ + myself.classId = RelationGetRelid(rel); + myself.objectId = tup->t_data->t_oid; + myself.objectSubId = 0; + + /* Create dependency on the language PL Handler function */ + dependCreate(&myself, &proc, false); + heap_close(rel, RowExclusiveLock); } *************** *** 171,176 **** --- 189,197 ---- if (!((Form_pg_language) GETSTRUCT(langTup))->lanispl) elog(ERROR, "Language %s isn't a created procedural language", languageName); + + /* Deal with Dependencies */ + dependDeleteTuple(langTup, rel, RESTRICT); simple_heap_delete(rel, &langTup->t_self); Index: src/backend/commands/remove.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/remove.c,v retrieving revision 1.72 diff -c -r1.72 remove.c *** src/backend/commands/remove.c 2002/03/29 19:06:06 1.72 --- src/backend/commands/remove.c 2002/03/31 18:35:34 *************** *** 16,21 **** --- 16,22 ---- #include "access/heapam.h" #include "catalog/catname.h" + #include "catalog/pg_depend.h" #include "catalog/pg_language.h" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" *************** *** 79,84 **** --- 80,88 ---- elog(ERROR, "RemoveOperator: operator '%s': permission denied", operatorName); + /* Deal with dependencies */ + dependDeleteTuple(tup, relation, RESTRICT); + /* Delete any comments associated with this operator */ DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation)); *************** *** 110,236 **** heap_close(relation, RowExclusiveLock); } - #ifdef NOTYET - /* - * this stuff is to support removing all reference to a type - * don't use it - pma 2/1/94 - */ - /* - * SingleOpOperatorRemove - * Removes all operators that have operands or a result of type 'typeOid'. - */ - static void - SingleOpOperatorRemove(Oid typeOid) - { - Relation rel; - ScanKeyData key[3]; - HeapScanDesc scan; - HeapTuple tup; - static attnums[3] = {7, 8, 9}; /* left, right, return */ - int i; - ScanKeyEntryInitialize(&key[0], - 0, 0, F_OIDEQ, (Datum) typeOid); - rel = heap_openr(OperatorRelationName, RowExclusiveLock); - for (i = 0; i < 3; ++i) - { - key[0].sk_attno = attnums[i]; - scan = heap_beginscan(rel, 0, SnapshotNow, 1, key); - while (HeapTupleIsValid(tup = heap_getnext(scan, 0))) - { - /* Delete any comments associated with this operator */ - DeleteComments(tup->t_data->t_oid, RelationGetRelid(rel)); - - simple_heap_delete(rel, &tup->t_self); - } - - heap_endscan(scan); - } - heap_close(rel, RowExclusiveLock); - } - /* - * AttributeAndRelationRemove - * Removes all entries in the attribute and relation relations - * that contain entries of type 'typeOid'. - * Currently nothing calls this code, it is untested. - */ - static void - AttributeAndRelationRemove(Oid typeOid) - { - struct oidlist - { - Oid reloid; - struct oidlist *next; - }; - struct oidlist *oidptr, - *optr; - Relation rel; - ScanKeyData key[1]; - HeapScanDesc scan; - HeapTuple tup; - - /* - * Get the oid's of the relations to be removed by scanning the entire - * attribute relation. We don't need to remove the attributes here, - * because amdestroy will remove all attributes of the relation. XXX - * should check for duplicate relations - */ - - ScanKeyEntryInitialize(&key[0], - 0, 3, F_OIDEQ, (Datum) typeOid); - - oidptr = (struct oidlist *) palloc(sizeof(*oidptr)); - oidptr->next = NULL; - optr = oidptr; - rel = heap_openr(AttributeRelationName, AccessShareLock); - scan = heap_beginscan(rel, 0, SnapshotNow, 1, key); - while (HeapTupleIsValid(tup = heap_getnext(scan, 0))) - { - optr->reloid = ((Form_pg_attribute) GETSTRUCT(tup))->attrelid; - optr->next = (struct oidlist *) palloc(sizeof(*oidptr)); - optr = optr->next; - } - optr->next = NULL; - heap_endscan(scan); - heap_close(rel, AccessShareLock); - - optr = oidptr; - - ScanKeyEntryInitialize(&key[0], 0, - ObjectIdAttributeNumber, - F_OIDEQ, (Datum) 0); - /* get RowExclusiveLock because heap_destroy will need it */ - rel = heap_openr(RelationRelationName, RowExclusiveLock); - while (PointerIsValid((char *) optr->next)) - { - Oid relOid = (optr++)->reloid; - - key[0].sk_argument = ObjectIdGetDatum(relOid); - scan = heap_beginscan(rel, 0, SnapshotNow, 1, key); - tup = heap_getnext(scan, 0); - if (HeapTupleIsValid(tup)) - heap_drop_with_catalog(relOid, allowSystemTableMods); - heap_endscan(scan); - } - heap_close(rel, RowExclusiveLock); - } - #endif /* NOTYET */ - - /* * TypeRemove * Removes a datatype. - * - * NOTE: since this tries to remove the associated array type too, it'll - * only work on scalar types. */ void RemoveType(List *names) { TypeName *typename; - Relation relation; - Oid typeoid; - HeapTuple tup; /* Make a TypeName so we can use standard type lookup machinery */ typename = makeNode(TypeName); --- 114,128 ---- *************** *** 238,247 **** --- 130,154 ---- typename->typmod = -1; typename->arrayBounds = NIL; + RemoveTypeByTypeName(typename); + } + + /* + * TypeRemove + * Removes a datatype. + */ + void + RemoveTypeByTypeName(TypeName *typename) + { + HeapTuple tup; + Oid typeoid; + Relation relation; + relation = heap_openr(TypeRelationName, RowExclusiveLock); /* Use LookupTypeName here so that shell types can be removed. */ typeoid = LookupTypeName(typename); + if (!OidIsValid(typeoid)) elog(ERROR, "Type \"%s\" does not exist", TypeNameToString(typename)); *************** *** 257,262 **** --- 164,172 ---- elog(ERROR, "RemoveType: type '%s': permission denied", TypeNameToString(typename)); + /* Deal with dependencies */ + dependDeleteTuple(tup, relation, RESTRICT); + /* Delete any comments associated with this type */ DeleteComments(typeoid, RelationGetRelid(relation)); *************** *** 265,291 **** ReleaseSysCache(tup); - /* Now, delete the "array of" that type */ - typename->arrayBounds = makeList1(makeInteger(1)); - - typeoid = LookupTypeName(typename); - if (!OidIsValid(typeoid)) - elog(ERROR, "Type \"%s\" does not exist", - TypeNameToString(typename)); - - tup = SearchSysCache(TYPEOID, - ObjectIdGetDatum(typeoid), - 0, 0, 0); - if (!HeapTupleIsValid(tup)) - elog(ERROR, "Type \"%s\" does not exist", - TypeNameToString(typename)); - - DeleteComments(typeoid, RelationGetRelid(relation)); - - simple_heap_delete(relation, &tup->t_self); - - ReleaseSysCache(tup); - heap_close(relation, RowExclusiveLock); } --- 175,180 ---- *************** *** 334,339 **** --- 223,231 ---- elog(ERROR, "%s is not a domain", TypeNameToString(typename)); + /* Deal with dependencies */ + dependDeleteTuple(tup, relation, behavior); + /* Delete any comments associated with this type */ DeleteComments(typeoid, RelationGetRelid(relation)); *************** *** 409,414 **** --- 301,309 ---- elog(WARNING, "Removing built-in function \"%s\"", functionName); } + /* Deal with dependencies */ + dependDeleteTuple(tup, relation, RESTRICT); + /* Delete any comments associated with this function */ DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation)); *************** *** 449,454 **** --- 344,352 ---- if (!HeapTupleIsValid(tup)) agg_error("RemoveAggregate", aggName, basetypeID); + + /* Deal with dependencies */ + dependDeleteTuple(tup, relation, RESTRICT); if (!pg_aggr_ownercheck(tup->t_data->t_oid, GetUserId())) { Index: src/backend/commands/trigger.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/trigger.c,v retrieving revision 1.109 diff -c -r1.109 trigger.c *** src/backend/commands/trigger.c 2002/03/29 22:10:33 1.109 --- src/backend/commands/trigger.c 2002/03/31 18:35:45 *************** *** 18,23 **** --- 18,24 ---- #include "catalog/catalog.h" #include "catalog/catname.h" #include "catalog/indexing.h" + #include "catalog/pg_depend.h" #include "catalog/namespace.h" #include "catalog/pg_language.h" #include "catalog/pg_proc.h" *************** *** 26,31 **** --- 27,33 ---- #include "commands/trigger.h" #include "executor/executor.h" #include "miscadmin.h" + #include "parser/parse.h" /* For keyword RESTRICT */ #include "utils/acl.h" #include "utils/builtins.h" #include "utils/fmgroids.h" *************** *** 72,77 **** --- 74,81 ---- char constrtrigname[NAMEDATALEN]; char *constrname = ""; Oid constrrelid = InvalidOid; + Oid insertOid, insertTupOid; + ObjectAddress myself, dependee; rel = heap_openrv(stmt->relation, AccessExclusiveLock); *************** *** 258,263 **** --- 262,269 ---- tuple = heap_formtuple(tgrel->rd_att, values, nulls); + insertOid = tgrel->rd_id; + /* * Insert tuple into pg_trigger. */ *************** *** 265,270 **** --- 271,280 ---- CatalogOpenIndices(Num_pg_trigger_indices, Name_pg_trigger_indices, idescs); CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple); CatalogCloseIndices(Num_pg_trigger_indices, idescs); + + /* Need the Inserted Tup Oid below for the address of 'myself' */ + insertTupOid = tuple->t_data->t_oid; + heap_freetuple(tuple); heap_close(tgrel, RowExclusiveLock); *************** *** 292,297 **** --- 302,336 ---- heap_freetuple(tuple); heap_close(pgrel, RowExclusiveLock); + + /* + * Insert dependencies + */ + myself.classId = insertOid; + myself.objectId = insertTupOid; + myself.objectSubId = 0; + + /* tgrelid */ + dependee.classId = RelOid_pg_class; + dependee.objectId = RelationGetRelid(rel); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, true); + + /* tgfoid */ + dependee.classId = RelOid_pg_proc; + dependee.objectId = funcoid; + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + + /* tgconstrrelid */ + if (constrrelid != InvalidOid) + { + dependee.classId = RelOid_pg_class; + dependee.objectId = constrrelid; + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, true); + } + /* * We used to try to update the rel's relcache entry here, but that's * fairly pointless since it will happen as a byproduct of the *************** *** 350,355 **** --- 389,397 ---- if (namestrcmp(&(pg_trigger->tgname), trigname) == 0) { + /* Deal with dependencies */ + dependDeleteTuple(tuple, tgrel, RESTRICT); + /* Delete any comments associated with this trigger */ DeleteComments(tuple->t_data->t_oid, RelationGetRelid(tgrel)); *************** *** 415,420 **** --- 457,465 ---- while (HeapTupleIsValid(tup = systable_getnext(tgscan))) { + /* Deal with dependencies */ + dependDeleteTuple(tup, tgrel, RESTRICT); + /* Delete any comments associated with this trigger */ DeleteComments(tup->t_data->t_oid, RelationGetRelid(tgrel)); Index: src/backend/rewrite/rewriteRemove.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v retrieving revision 1.47 diff -c -r1.47 rewriteRemove.c *** src/backend/rewrite/rewriteRemove.c 2002/03/29 19:06:13 1.47 --- src/backend/rewrite/rewriteRemove.c 2002/03/31 18:37:16 *************** *** 14,27 **** */ #include "postgres.h" - #include "utils/builtins.h" #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/pg_rewrite.h" #include "commands/comment.h" #include "miscadmin.h" #include "rewrite/rewriteRemove.h" #include "rewrite/rewriteSupport.h" #include "utils/acl.h" #include "utils/fmgroids.h" #include "utils/syscache.h" --- 14,30 ---- */ #include "postgres.h" #include "access/heapam.h" #include "catalog/catname.h" + #include "catalog/pg_depend.h" #include "catalog/pg_rewrite.h" #include "commands/comment.h" + #include "nodes/parsenodes.h" /* Required by parser/parse.h */ + #include "parser/parse.h" /* For keyword RESTRICT */ #include "miscadmin.h" #include "rewrite/rewriteRemove.h" #include "rewrite/rewriteSupport.h" + #include "utils/builtins.h" #include "utils/acl.h" #include "utils/fmgroids.h" #include "utils/syscache.h" *************** *** 101,106 **** --- 104,112 ---- hasMoreRules = event_relation->rd_rules != NULL && event_relation->rd_rules->numLocks > 1; + + /* Deal with dependencies */ + dependDeleteTuple(tuple, RewriteRelation, RESTRICT); /* * Delete any comments associated with this rule Index: src/bin/initdb/initdb.sh =================================================================== RCS file: /projects/cvsroot/pgsql/src/bin/initdb/initdb.sh,v retrieving revision 1.145 diff -c -r1.145 initdb.sh *** src/bin/initdb/initdb.sh 2002/03/02 21:39:34 1.145 --- src/bin/initdb/initdb.sh 2002/03/31 18:43:17 *************** *** 502,507 **** --- 502,703 ---- PGSQL_OPT="$PGSQL_OPT -O" + $ECHO_N "initializing pg_depend... "$ECHO_C + + "$PGPATH"/postgres $PGSQL_OPT template1 >/dev/null < 0 \ + EXCEPT \ + SELECT classid \ + , objid \ + , objsubid \ + , depclassid \ + , depobjid \ + , depobjsubid \ + , FALSE \ + FROM pg_depend; + + -- Toast tables depend on the relations + INSERT INTO pg_depend \ + SELECT \ + DISTINCT (SELECT oid FROM pg_class WHERE relname = 'pg_class') \ + , toast.oid \ + , 0 \ + , (SELECT oid FROM pg_class WHERE relname = 'pg_class') \ + , pg_class.oid \ + , 0 \ + , TRUE \ + FROM pg_class \ + JOIN pg_class as toast ON (pg_class.reltoastrelid = toast.oid) \ + EXCEPT \ + SELECT classid \ + , objid \ + , objsubid \ + , depclassid \ + , depobjid \ + , depobjsubid \ + , TRUE \ + FROM pg_depend; + + -- Indexes depend on the relation + INSERT INTO pg_depend \ + SELECT \ + DISTINCT (SELECT oid FROM pg_class WHERE relname = 'pg_class') \ + , idx.oid \ + , 0 \ + , (SELECT oid FROM pg_class WHERE relname = 'pg_class') \ + , pg_class.oid \ + , 0 \ + , TRUE \ + FROM pg_class \ + JOIN pg_class as idx ON (pg_class.reltoastidxid = idx.oid) \ + EXCEPT \ + SELECT classid \ + , objid \ + , objsubid \ + , depclassid \ + , depobjid \ + , depobjsubid \ + , TRUE \ + FROM pg_depend; + + -- Procedures depend on their control language + INSERT INTO pg_depend \ + SELECT \ + DISTINCT (SELECT oid FROM pg_class WHERE relname = 'pg_proc') \ + , pg_proc.oid \ + , 0 \ + , (SELECT oid FROM pg_class WHERE relname = 'pg_language') \ + , pg_language.oid \ + , 0 \ + , FALSE \ + FROM pg_proc \ + JOIN pg_language ON (prolang = pg_language.oid) \ + EXCEPT \ + SELECT classid \ + , objid \ + , objsubid \ + , depclassid \ + , depobjid \ + , depobjsubid \ + , FALSE \ + FROM pg_depend; + + -- Procedures depend on their control language (*= for oid and oidvector needed) + INSERT INTO pg_depend \ + SELECT \ + DISTINCT (SELECT oid FROM pg_class WHERE relname = 'pg_proc') \ + , pg_proc.oid \ + , 0 \ + , (SELECT oid FROM pg_class WHERE relname = 'pg_type') \ + , pg_type.oid \ + , 0 \ + , FALSE \ + FROM pg_proc \ + JOIN pg_type ON (pg_type.oid IN ( proargtypes[0] \ + , proargtypes[1] \ + , proargtypes[2] \ + , proargtypes[3] \ + , prorettype \ + )) \ + EXCEPT \ + SELECT classid \ + , objid \ + , objsubid \ + , depclassid \ + , depobjid \ + , depobjsubid \ + , FALSE \ + FROM pg_depend; + EOF + $ECHO_N "initializing pg_shadow... "$ECHO_C "$PGPATH"/postgres $PGSQL_OPT template1 >/dev/null <