diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/catalog/heap.c | 147 | ||||
-rw-r--r-- | src/backend/commands/command.c | 69 | ||||
-rw-r--r-- | src/include/catalog/heap.h | 5 |
3 files changed, 215 insertions, 6 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 41910472146..0675cd766a5 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.165 2001/05/14 20:30:19 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.166 2001/05/30 12:57:36 momjian Exp $ * * * INTERFACE ROUTINES @@ -48,6 +48,7 @@ #include "miscadmin.h" #include "optimizer/clauses.h" #include "optimizer/planmain.h" +#include "optimizer/prep.h" #include "optimizer/var.h" #include "nodes/makefuncs.h" #include "parser/parse_clause.h" @@ -1975,6 +1976,150 @@ RemoveRelCheck(Relation rel) heap_endscan(rcscan); heap_close(rcrel, RowExclusiveLock); + +} + +/* + * Removes all CHECK 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 CHECK constraints removed. + */ +int +RemoveCheckConstraint(Relation rel, const char *constrName, bool inh) +{ + Oid relid; + Relation rcrel; + Relation relrel; + Relation inhrel; + Relation relidescs[Num_pg_class_indices]; + TupleDesc tupleDesc; + TupleConstr *oldconstr; + int numoldchecks; + int numchecks; + HeapScanDesc rcscan; + ScanKeyData key[2]; + HeapTuple rctup; + HeapTuple reltup; + Form_pg_class relStruct; + int rel_deleted = 0; + int all_deleted = 0; + + /* Find id of the relation */ + relid = RelationGetRelid(rel); + + /* Process child tables and remove constraints of the + same name. */ + 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; + inhrel = heap_open(childrelid, AccessExclusiveLock); + all_deleted += RemoveCheckConstraint(inhrel, constrName, false); + heap_close(inhrel, NoLock); + } + } + + /* Grab an exclusive lock on the pg_relcheck relation */ + rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock); + + /* + * Create two scan keys. We need to match on the oid of the table + * the CHECK is in and also we need to match the name of the CHECK + * constraint. + */ + ScanKeyEntryInitialize(&key[0], 0, Anum_pg_relcheck_rcrelid, + F_OIDEQ, RelationGetRelid(rel)); + + ScanKeyEntryInitialize(&key[1], 0, Anum_pg_relcheck_rcname, + F_NAMEEQ, PointerGetDatum(constrName)); + + /* Begin scanning the heap */ + rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 2, key); + + /* + * Scan over the result set, removing any matching entries. Note + * that this has the side-effect of removing ALL CHECK constraints + * that share the specified constraint name. + */ + while (HeapTupleIsValid(rctup = heap_getnext(rcscan, 0))) { + simple_heap_delete(rcrel, &rctup->t_self); + ++rel_deleted; + ++all_deleted; + } + + /* Clean up after the scan */ + heap_endscan(rcscan); + + /* + * Update the count of constraints in the relation's pg_class tuple. + * We do this even if there was no change, in order to ensure that an + * SI update message is sent out for the pg_class tuple, which will + * force other backends to rebuild their relcache entries for the rel. + * (Of course, for a newly created rel there is no need for an SI + * message, but for ALTER TABLE ADD ATTRIBUTE this'd be important.) + */ + + /* + * Get number of existing constraints. + */ + + tupleDesc = RelationGetDescr(rel); + oldconstr = tupleDesc->constr; + if (oldconstr) + numoldchecks = oldconstr->num_check; + else + numoldchecks = 0; + + /* Calculate the new number of checks in the table, fail if negative */ + numchecks = numoldchecks - rel_deleted; + + if (numchecks < 0) + elog(ERROR, "check count became negative"); + + relrel = heap_openr(RelationRelationName, RowExclusiveLock); + reltup = SearchSysCacheCopy(RELOID, + ObjectIdGetDatum(RelationGetRelid(rel)), 0, 0, 0); + + if (!HeapTupleIsValid(reltup)) + elog(ERROR, "cache lookup of relation %u failed", + RelationGetRelid(rel)); + relStruct = (Form_pg_class) GETSTRUCT(reltup); + + relStruct->relchecks = numchecks; + + simple_heap_update(relrel, &reltup->t_self, reltup); + + /* Keep catalog indices current */ + CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, + relidescs); + CatalogIndexInsert(relidescs, Num_pg_class_indices, relrel, reltup); + CatalogCloseIndices(Num_pg_class_indices, relidescs); + + /* Clean up after the scan */ + heap_freetuple(reltup); + heap_close(relrel, RowExclusiveLock); + + /* Close the heap relation */ + heap_close(rcrel, RowExclusiveLock); + + /* Return the number of tuples deleted */ + return all_deleted; } static void diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c index 90cfba50be5..5f799199ed7 100644 --- a/src/backend/commands/command.c +++ b/src/backend/commands/command.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.129 2001/05/27 09:59:28 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.130 2001/05/30 12:57:36 momjian Exp $ * * NOTES * The PerformAddAttribute() code, like most of the relation @@ -51,9 +51,7 @@ #include "catalog/pg_shadow.h" #include "utils/relcache.h" -#ifdef _DROP_COLUMN_HACK__ #include "parser/parse.h" -#endif /* _DROP_COLUMN_HACK__ */ #include "access/genam.h" @@ -1324,6 +1322,11 @@ AlterTableAddConstraint(char *relationName, break; } + case CONSTR_PRIMARY: + { + + break; + } default: elog(ERROR, "ALTER TABLE / ADD CONSTRAINT is not implemented for that constraint type."); } @@ -1585,13 +1588,71 @@ AlterTableAddConstraint(char *relationName, /* * ALTER TABLE DROP CONSTRAINT + * Note: It is legal to remove a constraint with name "" as it is possible + * to add a constraint with name "". + * Christopher Kings-Lynne */ void AlterTableDropConstraint(const char *relationName, bool inh, const char *constrName, int behavior) { - elog(ERROR, "ALTER TABLE / DROP CONSTRAINT is not implemented"); + Relation rel; + int deleted; + +#ifndef NO_SECURITY + if (!pg_ownercheck(GetUserId(), relationName, RELNAME)) + elog(ERROR, "ALTER TABLE: permission denied"); +#endif + + /* We don't support CASCADE yet - in fact, RESTRICT + * doesn't work to the spec either! */ + if (behavior == CASCADE) + elog(ERROR, "ALTER TABLE / DROP CONSTRAINT does not support the CASCADE keyword"); + + /* + * Acquire an exclusive lock on the target relation for + * the duration of the operation. + */ + + rel = heap_openr(relationName, AccessExclusiveLock); + + /* Disallow DROP CONSTRAINT on views, indexes, sequences, etc */ + if (rel->rd_rel->relkind != RELKIND_RELATION) + elog(ERROR, "ALTER TABLE / DROP CONSTRAINT: %s is not a table", + relationName); + + /* + * Since all we have is the name of the constraint, we have to look through + * all catalogs that could possibly contain a constraint for this relation. + * We also keep a count of the number of constraints removed. + */ + + deleted = 0; + + /* + * First, we remove all CHECK constraints with the given name + */ + + deleted += RemoveCheckConstraint(rel, constrName, inh); + + /* + * Now we remove NULL, UNIQUE, PRIMARY KEY and FOREIGN KEY constraints. + * + * Unimplemented. + */ + + /* Close the target relation */ + heap_close(rel, NoLock); + + /* If zero constraints deleted, complain */ + if (deleted == 0) + elog(ERROR, "ALTER TABLE / DROP CONSTRAINT: %s does not exist", + constrName); + /* Otherwise if more than one constraint deleted, notify */ + else if (deleted > 1) + elog(NOTICE, "Multiple constraints dropped"); + } diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index 7ab04b05fb2..5488e794e96 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: heap.h,v 1.35 2001/05/07 00:43:24 tgl Exp $ + * $Id: heap.h,v 1.36 2001/05/30 12:57:36 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -45,6 +45,9 @@ extern void AddRelationRawConstraints(Relation rel, List *rawColDefaults, List *rawConstraints); +extern int RemoveCheckConstraint(Relation rel, const char *constrName, bool inh); + + extern Form_pg_attribute SystemAttributeDefinition(AttrNumber attno); #endif /* HEAP_H */ |