1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-14 08:21:07 +03:00

Use a private memory context to store rule information in each relcache

entry that has rules.  This allows us to release the rule parsetrees
on relcache flush without needing a working freeObject() routine.
Formerly, the rule trees were leaked permanently at relcache flush.
Also, clean up handling of rule creation and deletion --- there was
not sufficient locking of the relation being modified, and there was
no reliable notification of other backends that a relcache reload
was needed.  Also, clean up relcache.c code so that scans of system
tables needed to load a relcache entry are done in the caller's
memory context, not in CacheMemoryContext.  This prevents any
un-pfreed memory from those scans from becoming a permanent memory
leak.
This commit is contained in:
Tom Lane
2000-06-30 07:04:23 +00:00
parent c9ec78a6b8
commit b41f4ab8c4
10 changed files with 346 additions and 517 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.37 2000/05/28 17:56:02 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.38 2000/06/30 07:04:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -52,30 +52,20 @@ RewriteGetRuleEventRel(char *rulename)
return NameStr(((Form_pg_class) GETSTRUCT(htup))->relname);
}
/* ----------------------------------------------------------------
*
/*
* RemoveRewriteRule
*
* Delete a rule given its rulename.
*
* There are three steps.
* 1) Find the corresponding tuple in 'pg_rewrite' relation.
* Find the rule Id (i.e. the Oid of the tuple) and finally delete
* the tuple.
* 3) Delete the locks from the 'pg_class' relation.
*
*
* ----------------------------------------------------------------
*/
void
RemoveRewriteRule(char *ruleName)
{
Relation RewriteRelation = NULL;
HeapTuple tuple = NULL;
Oid ruleId = (Oid) 0;
Oid eventRelationOid = (Oid) NULL;
Datum eventRelationOidDatum = (Datum) NULL;
bool isNull = false;
Relation RewriteRelation;
Relation event_relation;
HeapTuple tuple;
Oid ruleId;
Oid eventRelationOid;
bool hasMoreRules;
/*
* Open the pg_rewrite relation.
@ -83,7 +73,7 @@ RemoveRewriteRule(char *ruleName)
RewriteRelation = heap_openr(RewriteRelationName, RowExclusiveLock);
/*
* Scan the RuleRelation ('pg_rewrite') until we find a tuple
* Find the tuple for the target rule.
*/
tuple = SearchSysCacheTupleCopy(RULENAME,
PointerGetDatum(ruleName),
@ -99,44 +89,49 @@ RemoveRewriteRule(char *ruleName)
}
/*
* Store the OID of the rule (i.e. the tuple's OID) and the event
* Save the OID of the rule (i.e. the tuple's OID) and the event
* relation's OID
*/
ruleId = tuple->t_data->t_oid;
eventRelationOidDatum = heap_getattr(tuple,
Anum_pg_rewrite_ev_class,
RelationGetDescr(RewriteRelation),
&isNull);
if (isNull)
{
/* XXX strange!!! */
heap_freetuple(tuple);
elog(ERROR, "RemoveRewriteRule: internal error; null event target relation!");
}
eventRelationOid = DatumGetObjectId(eventRelationOidDatum);
eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
/*
* Now delete the relation level locks from the updated relation.
* (Make sure we do this before we remove the rule from pg_rewrite.
* Otherwise, heap_openr on eventRelationOid which reads pg_rwrite for
* the rules will fail.)
* 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.
*/
prs2_deleteFromRelation(eventRelationOid, ruleId);
event_relation = heap_open(eventRelationOid, AccessExclusiveLock);
hasMoreRules = event_relation->rd_rules != NULL &&
event_relation->rd_rules->numLocks > 1;
/*
* Delete any comments associated with this rule
*
*/
DeleteComments(ruleId);
/*
* Now delete the tuple...
* Now delete the pg_rewrite tuple for the rule
*/
heap_delete(RewriteRelation, &tuple->t_self, NULL);
heap_freetuple(tuple);
heap_close(RewriteRelation, RowExclusiveLock);
/*
* Set pg_class 'relhasrules' field correctly for event relation.
*
* Important side effect: an SI notice is broadcast to force all
* backends (including me!) to update relcache entries with the
* new rule set. Therefore, must do this even if relhasrules is
* still true!
*/
setRelhasrulesInRelation(eventRelationOid, hasMoreRules);
/* Close rel, but keep lock till commit... */
heap_close(event_relation, NoLock);
}
/*