|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.165 2001/05/14 20:30:19 momjian Exp $ |
| 11 | + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.166 2001/05/30 12:57:36 momjian Exp $ |
12 | 12 | *
|
13 | 13 | *
|
14 | 14 | * INTERFACE ROUTINES
|
|
48 | 48 | #include "miscadmin.h"
|
49 | 49 | #include "optimizer/clauses.h"
|
50 | 50 | #include "optimizer/planmain.h"
|
| 51 | +#include "optimizer/prep.h" |
51 | 52 | #include "optimizer/var.h"
|
52 | 53 | #include "nodes/makefuncs.h"
|
53 | 54 | #include "parser/parse_clause.h"
|
@@ -1975,6 +1976,150 @@ RemoveRelCheck(Relation rel)
|
1975 | 1976 |
|
1976 | 1977 | heap_endscan(rcscan);
|
1977 | 1978 | heap_close(rcrel, RowExclusiveLock);
|
| 1979 | + |
| 1980 | +} |
| 1981 | + |
| 1982 | +/* |
| 1983 | + * Removes all CHECK constraints on a relation that match the given name. |
| 1984 | + * It is the responsibility of the calling function to acquire a lock on |
| 1985 | + * the relation. |
| 1986 | + * Returns: The number of CHECK constraints removed. |
| 1987 | + */ |
| 1988 | +int |
| 1989 | +RemoveCheckConstraint(Relation rel, const char *constrName, bool inh) |
| 1990 | +{ |
| 1991 | + Oid relid; |
| 1992 | + Relation rcrel; |
| 1993 | + Relation relrel; |
| 1994 | + Relation inhrel; |
| 1995 | + Relation relidescs[Num_pg_class_indices]; |
| 1996 | + TupleDesc tupleDesc; |
| 1997 | + TupleConstr *oldconstr; |
| 1998 | + int numoldchecks; |
| 1999 | + int numchecks; |
| 2000 | + HeapScanDesc rcscan; |
| 2001 | + ScanKeyData key[2]; |
| 2002 | + HeapTuple rctup; |
| 2003 | + HeapTuple reltup; |
| 2004 | + Form_pg_class relStruct; |
| 2005 | + int rel_deleted = 0; |
| 2006 | + int all_deleted = 0; |
| 2007 | + |
| 2008 | + /* Find id of the relation */ |
| 2009 | + relid = RelationGetRelid(rel); |
| 2010 | + |
| 2011 | + /* Process child tables and remove constraints of the |
| 2012 | + same name. */ |
| 2013 | + if (inh) |
| 2014 | + { |
| 2015 | + List *child, |
| 2016 | + *children; |
| 2017 | + |
| 2018 | + /* This routine is actually in the planner */ |
| 2019 | + children = find_all_inheritors(relid); |
| 2020 | + |
| 2021 | + /* |
| 2022 | + * find_all_inheritors does the recursive search of the |
| 2023 | + * inheritance hierarchy, so all we have to do is process all |
| 2024 | + * of the relids in the list that it returns. |
| 2025 | + */ |
| 2026 | + foreach(child, children) |
| 2027 | + { |
| 2028 | + Oid childrelid = lfirsti(child); |
| 2029 | + |
| 2030 | + if (childrelid == relid) |
| 2031 | + continue; |
| 2032 | + inhrel = heap_open(childrelid, AccessExclusiveLock); |
| 2033 | + all_deleted += RemoveCheckConstraint(inhrel, constrName, false); |
| 2034 | + heap_close(inhrel, NoLock); |
| 2035 | + } |
| 2036 | + } |
| 2037 | + |
| 2038 | + /* Grab an exclusive lock on the pg_relcheck relation */ |
| 2039 | + rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock); |
| 2040 | + |
| 2041 | + /* |
| 2042 | + * Create two scan keys. We need to match on the oid of the table |
| 2043 | + * the CHECK is in and also we need to match the name of the CHECK |
| 2044 | + * constraint. |
| 2045 | + */ |
| 2046 | + ScanKeyEntryInitialize(&key[0], 0, Anum_pg_relcheck_rcrelid, |
| 2047 | + F_OIDEQ, RelationGetRelid(rel)); |
| 2048 | + |
| 2049 | + ScanKeyEntryInitialize(&key[1], 0, Anum_pg_relcheck_rcname, |
| 2050 | + F_NAMEEQ, PointerGetDatum(constrName)); |
| 2051 | + |
| 2052 | + /* Begin scanning the heap */ |
| 2053 | + rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 2, key); |
| 2054 | + |
| 2055 | + /* |
| 2056 | + * Scan over the result set, removing any matching entries. Note |
| 2057 | + * that this has the side-effect of removing ALL CHECK constraints |
| 2058 | + * that share the specified constraint name. |
| 2059 | + */ |
| 2060 | + while (HeapTupleIsValid(rctup = heap_getnext(rcscan, 0))) { |
| 2061 | + simple_heap_delete(rcrel, &rctup->t_self); |
| 2062 | + ++rel_deleted; |
| 2063 | + ++all_deleted; |
| 2064 | + } |
| 2065 | + |
| 2066 | + /* Clean up after the scan */ |
| 2067 | + heap_endscan(rcscan); |
| 2068 | + |
| 2069 | + /* |
| 2070 | + * Update the count of constraints in the relation's pg_class tuple. |
| 2071 | + * We do this even if there was no change, in order to ensure that an |
| 2072 | + * SI update message is sent out for the pg_class tuple, which will |
| 2073 | + * force other backends to rebuild their relcache entries for the rel. |
| 2074 | + * (Of course, for a newly created rel there is no need for an SI |
| 2075 | + * message, but for ALTER TABLE ADD ATTRIBUTE this'd be important.) |
| 2076 | + */ |
| 2077 | + |
| 2078 | + /* |
| 2079 | + * Get number of existing constraints. |
| 2080 | + */ |
| 2081 | + |
| 2082 | + tupleDesc = RelationGetDescr(rel); |
| 2083 | + oldconstr = tupleDesc->constr; |
| 2084 | + if (oldconstr) |
| 2085 | + numoldchecks = oldconstr->num_check; |
| 2086 | + else |
| 2087 | + numoldchecks = 0; |
| 2088 | + |
| 2089 | + /* Calculate the new number of checks in the table, fail if negative */ |
| 2090 | + numchecks = numoldchecks - rel_deleted; |
| 2091 | + |
| 2092 | + if (numchecks < 0) |
| 2093 | + elog(ERROR, "check count became negative"); |
| 2094 | + |
| 2095 | + relrel = heap_openr(RelationRelationName, RowExclusiveLock); |
| 2096 | + reltup = SearchSysCacheCopy(RELOID, |
| 2097 | + ObjectIdGetDatum(RelationGetRelid(rel)), 0, 0, 0); |
| 2098 | + |
| 2099 | + if (!HeapTupleIsValid(reltup)) |
| 2100 | + elog(ERROR, "cache lookup of relation %u failed", |
| 2101 | + RelationGetRelid(rel)); |
| 2102 | + relStruct = (Form_pg_class) GETSTRUCT(reltup); |
| 2103 | + |
| 2104 | + relStruct->relchecks = numchecks; |
| 2105 | + |
| 2106 | + simple_heap_update(relrel, &reltup->t_self, reltup); |
| 2107 | + |
| 2108 | + /* Keep catalog indices current */ |
| 2109 | + CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, |
| 2110 | + relidescs); |
| 2111 | + CatalogIndexInsert(relidescs, Num_pg_class_indices, relrel, reltup); |
| 2112 | + CatalogCloseIndices(Num_pg_class_indices, relidescs); |
| 2113 | + |
| 2114 | + /* Clean up after the scan */ |
| 2115 | + heap_freetuple(reltup); |
| 2116 | + heap_close(relrel, RowExclusiveLock); |
| 2117 | + |
| 2118 | + /* Close the heap relation */ |
| 2119 | + heap_close(rcrel, RowExclusiveLock); |
| 2120 | + |
| 2121 | + /* Return the number of tuples deleted */ |
| 2122 | + return all_deleted; |
1978 | 2123 | }
|
1979 | 2124 |
|
1980 | 2125 | static void
|
|
0 commit comments