diff options
| author | Tom Lane | 2002-07-12 18:43:19 +0000 |
|---|---|---|
| committer | Tom Lane | 2002-07-12 18:43:19 +0000 |
| commit | 7c6df91dda27accab3097390ef0d21d93028c7a1 (patch) | |
| tree | 5705b975e8de4edf82252e6df28e0bd57c83cb95 /src/backend/rewrite | |
| parent | 791a40f943e2a9353c5823fb4f2bd446ec623d38 (diff) | |
Second phase of committing Rod Taylor's pg_depend/pg_constraint patch.
pg_relcheck is gone; CHECK, UNIQUE, PRIMARY KEY, and FOREIGN KEY
constraints all have real live entries in pg_constraint. pg_depend
exists, and RESTRICT/CASCADE options work on most kinds of DROP;
however, pg_depend is not yet very well populated with dependencies.
(Most of the ones that are present at this point just replace formerly
hardwired associations, such as the implicit drop of a relation's pg_type
entry when the relation is dropped.) Need to add more logic to create
dependency entries, improve pg_dump to dump constraints in place of
indexes and triggers, and add some regression tests.
Diffstat (limited to 'src/backend/rewrite')
| -rw-r--r-- | src/backend/rewrite/rewriteDefine.c | 22 | ||||
| -rw-r--r-- | src/backend/rewrite/rewriteRemove.c | 148 | ||||
| -rw-r--r-- | src/backend/rewrite/rewriteSupport.c | 37 |
3 files changed, 109 insertions, 98 deletions
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index 43f8ffd6f1f..5922cb4ab5b 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.73 2002/06/20 20:29:33 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.74 2002/07/12 18:43:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,6 +16,7 @@ #include "access/heapam.h" #include "catalog/catname.h" +#include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/pg_rewrite.h" #include "commands/view.h" @@ -57,6 +58,8 @@ InsertRule(char *rulname, TupleDesc tupDesc; HeapTuple tup; Oid rewriteObjectId; + ObjectAddress myself, + referenced; if (IsDefinedRewriteRule(eventrel_oid, rulname)) elog(ERROR, "Attempt to insert rule \"%s\" failed: already exists", @@ -103,6 +106,23 @@ InsertRule(char *rulname, heap_freetuple(tup); + /* + * Install dependency on rule's relation to ensure it will go away + * on relation deletion. If the rule is ON SELECT, make the dependency + * implicit --- this prevents deleting a view's SELECT rule. Other + * kinds of rules can be AUTO. + */ + myself.classId = RelationGetRelid(pg_rewrite_desc); + myself.objectId = rewriteObjectId; + myself.objectSubId = 0; + + referenced.classId = RelOid_pg_class; + referenced.objectId = eventrel_oid; + referenced.objectSubId = 0; + + recordDependencyOn(&myself, &referenced, + (evtype == CMD_SELECT) ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO); + heap_close(pg_rewrite_desc, RowExclusiveLock); return rewriteObjectId; diff --git a/src/backend/rewrite/rewriteRemove.c b/src/backend/rewrite/rewriteRemove.c index 71fd4d5ac40..4ce9f3f2b90 100644 --- a/src/backend/rewrite/rewriteRemove.c +++ b/src/backend/rewrite/rewriteRemove.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.50 2002/06/20 20:29:34 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.51 2002/07/12 18:43:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,14 +17,15 @@ #include "access/genam.h" #include "access/heapam.h" #include "catalog/catname.h" +#include "catalog/dependency.h" #include "catalog/indexing.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/lsyscache.h" #include "utils/syscache.h" @@ -34,77 +35,102 @@ * Delete a rule given its name. */ void -RemoveRewriteRule(Oid owningRel, const char *ruleName) +RemoveRewriteRule(Oid owningRel, const char *ruleName, DropBehavior behavior) { - Relation RewriteRelation; - Relation event_relation; HeapTuple tuple; - Oid ruleId; Oid eventRelationOid; - bool hasMoreRules; AclResult aclresult; - - /* - * Open the pg_rewrite relation. - */ - RewriteRelation = heap_openr(RewriteRelationName, RowExclusiveLock); + ObjectAddress object; /* * Find the tuple for the target rule. */ - tuple = SearchSysCacheCopy(RULERELNAME, - ObjectIdGetDatum(owningRel), - PointerGetDatum(ruleName), - 0, 0); + tuple = SearchSysCache(RULERELNAME, + ObjectIdGetDatum(owningRel), + PointerGetDatum(ruleName), + 0, 0); /* - * complain if no rule with such name existed + * complain if no rule with such name exists */ if (!HeapTupleIsValid(tuple)) elog(ERROR, "Rule \"%s\" not found", ruleName); /* - * Save the OID of the rule (i.e. the tuple's OID) and the event - * relation's OID + * Verify user has appropriate permissions. */ - ruleId = tuple->t_data->t_oid; eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class; Assert(eventRelationOid == owningRel); + aclresult = pg_class_aclcheck(eventRelationOid, GetUserId(), ACL_RULE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, get_rel_name(eventRelationOid)); /* - * We had better grab AccessExclusiveLock so that we know no other - * rule additions/deletions are going on for this relation. Else we - * cannot set relhasrules correctly. Besides, we don't want to be - * changing the ruleset while queries are executing on the rel. + * Do the deletion */ - event_relation = heap_open(eventRelationOid, AccessExclusiveLock); + object.classId = get_system_catalog_relid(RewriteRelationName); + object.objectId = tuple->t_data->t_oid; + object.objectSubId = 0; + + ReleaseSysCache(tuple); + + performDeletion(&object, behavior); +} + + +/* + * Guts of rule deletion. + */ +void +RemoveRewriteRuleById(Oid ruleOid) +{ + Relation RewriteRelation; + ScanKeyData skey[1]; + SysScanDesc rcscan; + Relation event_relation; + HeapTuple tuple; + Oid eventRelationOid; + bool hasMoreRules; /* - * Verify user has appropriate permissions. + * Open the pg_rewrite relation. */ - aclresult = pg_class_aclcheck(eventRelationOid, GetUserId(), ACL_RULE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, RelationGetRelationName(event_relation)); + RewriteRelation = heap_openr(RewriteRelationName, RowExclusiveLock); + + /* + * Find the tuple for the target rule. + */ + ScanKeyEntryInitialize(&skey[0], 0x0, + ObjectIdAttributeNumber, F_OIDEQ, + ObjectIdGetDatum(ruleOid)); - /* do not allow the removal of a view's SELECT rule */ - if (event_relation->rd_rel->relkind == RELKIND_VIEW && - ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_type == '1') - elog(ERROR, "Cannot remove a view's SELECT rule"); + rcscan = systable_beginscan(RewriteRelation, RewriteOidIndex, true, + SnapshotNow, 1, skey); - hasMoreRules = event_relation->rd_rules != NULL && - event_relation->rd_rules->numLocks > 1; + tuple = systable_getnext(rcscan); + + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "RemoveRewriteRuleById: Rule %u does not exist", + ruleOid); /* - * Delete any comments associated with this rule + * We had better grab AccessExclusiveLock so that we know no other + * rule additions/deletions are going on for this relation. Else we + * cannot set relhasrules correctly. Besides, we don't want to be + * changing the ruleset while queries are executing on the rel. */ - DeleteComments(ruleId, RelationGetRelid(RewriteRelation)); + eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class; + event_relation = heap_open(eventRelationOid, AccessExclusiveLock); + + hasMoreRules = event_relation->rd_rules != NULL && + event_relation->rd_rules->numLocks > 1; /* * Now delete the pg_rewrite tuple for the rule */ simple_heap_delete(RewriteRelation, &tuple->t_self); - heap_freetuple(tuple); + systable_endscan(rcscan); heap_close(RewriteRelation, RowExclusiveLock); @@ -120,49 +146,3 @@ RemoveRewriteRule(Oid owningRel, const char *ruleName) /* Close rel, but keep lock till commit... */ heap_close(event_relation, NoLock); } - -/* - * RelationRemoveRules - - * removes all rules associated with the relation when the relation is - * being removed. - */ -void -RelationRemoveRules(Oid relid) -{ - Relation RewriteRelation; - SysScanDesc scanDesc; - ScanKeyData scanKeyData; - HeapTuple tuple; - - /* - * Open the pg_rewrite relation. - */ - RewriteRelation = heap_openr(RewriteRelationName, RowExclusiveLock); - - /* - * Scan pg_rewrite for all the tuples that have the same ev_class - * as relid (the relation to be removed). - */ - ScanKeyEntryInitialize(&scanKeyData, - 0, - Anum_pg_rewrite_ev_class, - F_OIDEQ, - ObjectIdGetDatum(relid)); - - scanDesc = systable_beginscan(RewriteRelation, - RewriteRelRulenameIndex, - true, SnapshotNow, - 1, &scanKeyData); - - while (HeapTupleIsValid(tuple = systable_getnext(scanDesc))) - { - /* Delete any comments associated with this rule */ - DeleteComments(tuple->t_data->t_oid, RelationGetRelid(RewriteRelation)); - - simple_heap_delete(RewriteRelation, &tuple->t_self); - } - - systable_endscan(scanDesc); - - heap_close(RewriteRelation, RowExclusiveLock); -} diff --git a/src/backend/rewrite/rewriteSupport.c b/src/backend/rewrite/rewriteSupport.c index ba590b8cc66..3f4c7f23871 100644 --- a/src/backend/rewrite/rewriteSupport.c +++ b/src/backend/rewrite/rewriteSupport.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.52 2002/06/20 20:29:34 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.53 2002/07/12 18:43:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -18,6 +18,7 @@ #include "catalog/catname.h" #include "catalog/indexing.h" #include "rewrite/rewriteSupport.h" +#include "utils/inval.h" #include "utils/syscache.h" @@ -44,9 +45,8 @@ IsDefinedRewriteRule(Oid owningRel, const char *ruleName) * NOTE: an important side-effect of this operation is that an SI invalidation * message is sent out to all backends --- including me --- causing relcache * entries to be flushed or updated with the new set of rules for the table. - * Therefore, we execute the update even if relhasrules has the right value - * already. Possible future improvement: skip the disk update and just send - * an SI message in that case. + * This must happen even if we find that no change is needed in the pg_class + * row. */ void SetRelationRuleStatus(Oid relationId, bool relHasRules, @@ -54,6 +54,7 @@ SetRelationRuleStatus(Oid relationId, bool relHasRules, { Relation relationRelation; HeapTuple tuple; + Form_pg_class classForm; Relation idescs[Num_pg_class_indices]; /* @@ -66,18 +67,28 @@ SetRelationRuleStatus(Oid relationId, bool relHasRules, 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "SetRelationRuleStatus: cache lookup failed for relation %u", relationId); + classForm = (Form_pg_class) GETSTRUCT(tuple); - /* Do the update */ - ((Form_pg_class) GETSTRUCT(tuple))->relhasrules = relHasRules; - if (relIsBecomingView) - ((Form_pg_class) GETSTRUCT(tuple))->relkind = RELKIND_VIEW; + if (classForm->relhasrules != relHasRules || + (relIsBecomingView && classForm->relkind != RELKIND_VIEW)) + { + /* Do the update */ + classForm->relhasrules = relHasRules; + if (relIsBecomingView) + classForm->relkind = RELKIND_VIEW; - simple_heap_update(relationRelation, &tuple->t_self, tuple); + simple_heap_update(relationRelation, &tuple->t_self, tuple); - /* Keep the catalog indices up to date */ - CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs); - CatalogIndexInsert(idescs, Num_pg_class_indices, relationRelation, tuple); - CatalogCloseIndices(Num_pg_class_indices, idescs); + /* Keep the catalog indices up to date */ + CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs); + CatalogIndexInsert(idescs, Num_pg_class_indices, relationRelation, tuple); + CatalogCloseIndices(Num_pg_class_indices, idescs); + } + else + { + /* no need to change tuple, but force relcache rebuild anyway */ + CacheInvalidateRelcache(relationId); + } heap_freetuple(tuple); heap_close(relationRelation, RowExclusiveLock); |
