? config.log ? config.cache ? config.status ? dropcons.diff ? GNUmakefile ? log ? unique.diff ? src/GNUmakefile ? src/Makefile.global ? src/backend/commands/command.c.diff ? src/backend/port/Makefile ? src/include/config.h ? src/include/stamp-h Index: src/backend/catalog/heap.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/catalog/heap.c,v retrieving revision 1.166 diff -c -r1.166 heap.c *** src/backend/catalog/heap.c 2001/05/30 12:57:36 1.166 --- src/backend/catalog/heap.c 2001/05/31 10:57:07 *************** *** 45,50 **** --- 45,51 ---- #include "catalog/pg_type.h" #include "commands/comment.h" #include "commands/trigger.h" + #include "commands/defrem.h" /* For RemoveUniqueConstraint */ #include "miscadmin.h" #include "optimizer/clauses.h" #include "optimizer/planmain.h" *************** *** 65,70 **** --- 66,72 ---- #include "utils/relcache.h" #include "utils/syscache.h" #include "utils/temprel.h" + #include "utils/acl.h" /* For RemoveUniqueConstraint */ static void AddNewRelationTuple(Relation pg_class_desc, *************** *** 2117,2122 **** --- 2119,2198 ---- /* Close the heap relation */ heap_close(rcrel, RowExclusiveLock); + + /* Return the number of tuples deleted */ + return all_deleted; + } + + /* + * Removes all UNIQUE constraints on a relation that match the given name. + * It is the responsibility of the calling function to acquire a lock on + * the relation. + * Returns: The number of UNIQUE constraints removed. + */ + int + RemoveUniqueConstraint(Relation rel, const char *constrName, bool inh) + { + Oid relid; + Relation inhrel; + int all_deleted = 0; + + /* Find id of the relation */ + relid = RelationGetRelid(rel); + + /* Process child tables and remove constraints of the + same name. This is currently disabled as it's + impossible to have duplicated index names anyway */ + inh = false; /* Disable inheritance */ + if (inh) + { + + List *child, + *children; + + /* This routine is actually in the planner */ + children = find_all_inheritors(relid); + + /* + * find_all_inheritors does the recursive search of the + * inheritance hierarchy, so all we have to do is process all + * of the relids in the list that it returns. + */ + foreach(child, children) + { + Oid childrelid = lfirsti(child); + + if (childrelid == relid) + continue; + + /* @@ What locking to use here? @@ */ + inhrel = heap_open(childrelid, AccessExclusiveLock); + all_deleted += RemoveUniqueConstraint(inhrel, constrName, false); + heap_close(inhrel, NoLock); + } + } + + /* Delete index */ + if (IsIndex(constrName, rel, true, false)) { + + /* Check that we own the index */ + if (!pg_ownercheck(GetUserId(), constrName, RELNAME)) + elog(ERROR, "ALTER TABLE / DROP CONSTRAINT: You do not own '%s'", + constrName); + + /* Check that it's not a system relation */ + if (!allowSystemTableMods && IsSystemRelationName(constrName)) + elog(ERROR, "ALTER TABLE / DROP CONSTRAINT: '%s' is a system relation", + constrName); + + /* Otherwise, we go ahead and drop the index */ + /* @@ It's unfortunate that this cast is required @@ */ + RemoveIndex((char *)constrName); + + elog(NOTICE, "ALTER TABLE / DROP CONSTRAINT will remove implicit index '%s' for table '%s'", + constrName, RelationGetRelationName(rel)); + ++all_deleted; + } /* Return the number of tuples deleted */ return all_deleted; Index: src/backend/commands/command.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/commands/command.c,v retrieving revision 1.131 diff -c -r1.131 command.c *** src/backend/commands/command.c 2001/05/30 13:00:03 1.131 --- src/backend/commands/command.c 2001/05/31 10:57:12 *************** *** 1666,1671 **** --- 1667,1679 ---- */ deleted += RemoveCheckConstraint(rel, constrName, inh); + + /* + * Second, we remove all UNIQUE constraints with the given name + */ + + CommandCounterIncrement(); + deleted += RemoveUniqueConstraint(rel, constrName, inh); /* * Now we remove NULL, PRIMARY KEY and FOREIGN KEY constraints. Index: src/backend/commands/indexcmds.c =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/commands/indexcmds.c,v retrieving revision 1.48 diff -c -r1.48 indexcmds.c *** src/backend/commands/indexcmds.c 2001/05/30 20:52:32 1.48 --- src/backend/commands/indexcmds.c 2001/05/31 10:57:14 *************** *** 41,46 **** --- 41,47 ---- #include "utils/builtins.h" #include "utils/fmgroids.h" #include "utils/syscache.h" + #include "utils/relcache.h" /* For IsIndex */ #define IsFuncIndex(ATTR_LIST) (((IndexElem*)lfirst(ATTR_LIST))->args != NIL) *************** *** 591,596 **** --- 592,677 ---- ReleaseSysCache(tuple); return result; + } + + /* + * IsIndex + * Determines whether or not a named index on a particular + * relation, of a specified type, exists. + * + * Params: + * name: The name of the index to look for + * rel: The relation the index is on + * unique: Restrict search to unique indices + * primary: Restrict search to primary indicies (If you specify primary, + * you will also almost always want to specify unique.) + * + * Returns: + * True if an index with the given name and type exists on the + * specified table, false otherwise. + */ + bool + IsIndex(const char *name, Relation rel, bool unique, bool primary) + { + Relation pg_index; + Relation index_rel; + Oid index_oid; + HeapScanDesc pg_index_scan; + HeapTuple pg_index_tup; + ScanKeyData key[4]; + bool found; + + /* Get the relation representing the index */ + index_rel = RelationNameGetRelation(name); + + /* Does the name exist at all? */ + if (!RelationIsValid(index_rel)) return false; + + /* Is the named relation an index? */ + if (index_rel->rd_rel->relkind != RELKIND_INDEX) return false; + + /* Open the system catalog index relation */ + pg_index = heap_openr(IndexRelationName, AccessShareLock); + + /* Grab the oid of the index. The relation should be valid, as we've checked above. */ + index_oid = RelationGetRelid(index_rel); + + /* + * Create three scan keys. We need to match on the oid of + * the index, if it's unique and if it's primary. + */ + ScanKeyEntryInitialize(&key[0], 0, Anum_pg_index_indexrelid, + F_OIDEQ, ObjectIdGetDatum(index_oid)); + + ScanKeyEntryInitialize(&key[1], 0, Anum_pg_index_indrelid, + F_OIDEQ, RelationGetRelid(rel)); + + ScanKeyEntryInitialize(&key[2], 0, Anum_pg_index_indisunique, + F_BOOLEQ, BoolGetDatum(unique)); + + ScanKeyEntryInitialize(&key[3], 0, Anum_pg_index_indisprimary, + F_BOOLEQ, BoolGetDatum(primary)); + + /* Begin scanning the heap */ + pg_index_scan = heap_beginscan(pg_index, 0, SnapshotNow, 4, key); + + /* Scan over the index table. If we find anything - report success. */ + found = false; + while (HeapTupleIsValid(pg_index_tup = heap_getnext(pg_index_scan, false))) { + found = true; + break; + } + + /* Clean up after */ + heap_endscan(pg_index_scan); + /* Should I be releasing this? I don't think so because what if someone renames the index + * or something before I drop it? */ + heap_close(pg_index, AccessShareLock); + + /* @@ Do I need this? @@ */ + RelationClose(index_rel); + + return found; } /* Index: src/include/catalog/heap.h =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/include/catalog/heap.h,v retrieving revision 1.36 diff -c -r1.36 heap.h *** src/include/catalog/heap.h 2001/05/30 12:57:36 1.36 --- src/include/catalog/heap.h 2001/05/31 10:57:18 *************** *** 46,52 **** List *rawConstraints); extern int RemoveCheckConstraint(Relation rel, const char *constrName, bool inh); ! extern Form_pg_attribute SystemAttributeDefinition(AttrNumber attno); --- 46,52 ---- List *rawConstraints); extern int RemoveCheckConstraint(Relation rel, const char *constrName, bool inh); ! extern int RemoveUniqueConstraint(Relation rel, const char *constrName, bool inh); extern Form_pg_attribute SystemAttributeDefinition(AttrNumber attno); Index: src/include/commands/defrem.h =================================================================== RCS file: /home/projects/pgsql/cvsroot/pgsql/src/include/commands/defrem.h,v retrieving revision 1.22 diff -c -r1.22 defrem.h *** src/include/commands/defrem.h 2001/01/24 19:43:23 1.22 --- src/include/commands/defrem.h 2001/05/31 10:57:18 *************** *** 18,24 **** #include "tcop/dest.h" /* ! * prototypes in defind.c */ extern void DefineIndex(char *heapRelationName, char *indexRelationName, --- 18,24 ---- #include "tcop/dest.h" /* ! * prototypes in indexcmds.c */ extern void DefineIndex(char *heapRelationName, char *indexRelationName, *************** *** 32,37 **** --- 32,38 ---- extern void ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable); + extern bool IsIndex(const char *name, Relation rel, bool unique, bool primary); extern void RemoveIndex(char *name); extern void ReindexIndex(const char *indexRelationName, bool force); extern void ReindexTable(const char *relationName, bool force);