From edfbd0744a3e238ff297e907da5cf39e8433a068 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 8 Jan 2006 20:04:41 +0000 Subject: [PATCH] Avoid leaking memory while reading toasted entries from pg_rewrite, and nail a couple more system indexes into cache. This doesn't make any difference in normal system operation, but when forcing constant cache resets it's difficult to get through the rules regression test without these changes. --- src/backend/utils/cache/relcache.c | 60 +++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 216f1c8529..9d4e402ae2 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.234 2006/01/05 10:07:46 petere Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.235 2006/01/08 20:04:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -565,10 +565,9 @@ RelationBuildRuleLock(Relation relation) { Form_pg_rewrite rewrite_form = (Form_pg_rewrite) GETSTRUCT(rewrite_tuple); bool isnull; - Datum ruleaction; - Datum rule_evqual; - char *ruleaction_str; - char *rule_evqual_str; + Datum rule_datum; + text *rule_text; + char *rule_str; RewriteRule *rule; rule = (RewriteRule *) MemoryContextAlloc(rulescxt, @@ -580,31 +579,41 @@ RelationBuildRuleLock(Relation relation) rule->attrno = rewrite_form->ev_attr; rule->isInstead = rewrite_form->is_instead; - /* Must use heap_getattr to fetch ev_qual and ev_action */ - - ruleaction = heap_getattr(rewrite_tuple, + /* + * Must use heap_getattr to fetch ev_action and ev_qual. Also, + * the rule strings are often large enough to be toasted. To avoid + * leaking memory in the caller's context, do the detoasting here + * so we can free the detoasted version. + */ + rule_datum = heap_getattr(rewrite_tuple, Anum_pg_rewrite_ev_action, rewrite_tupdesc, &isnull); Assert(!isnull); - ruleaction_str = DatumGetCString(DirectFunctionCall1(textout, - ruleaction)); + rule_text = DatumGetTextP(rule_datum); + rule_str = DatumGetCString(DirectFunctionCall1(textout, + PointerGetDatum(rule_text))); oldcxt = MemoryContextSwitchTo(rulescxt); - rule->actions = (List *) stringToNode(ruleaction_str); + rule->actions = (List *) stringToNode(rule_str); MemoryContextSwitchTo(oldcxt); - pfree(ruleaction_str); + pfree(rule_str); + if ((Pointer) rule_text != DatumGetPointer(rule_datum)) + pfree(rule_text); - rule_evqual = heap_getattr(rewrite_tuple, - Anum_pg_rewrite_ev_qual, - rewrite_tupdesc, - &isnull); + rule_datum = heap_getattr(rewrite_tuple, + Anum_pg_rewrite_ev_qual, + rewrite_tupdesc, + &isnull); Assert(!isnull); - rule_evqual_str = DatumGetCString(DirectFunctionCall1(textout, - rule_evqual)); + rule_text = DatumGetTextP(rule_datum); + rule_str = DatumGetCString(DirectFunctionCall1(textout, + PointerGetDatum(rule_text))); oldcxt = MemoryContextSwitchTo(rulescxt); - rule->qual = (Node *) stringToNode(rule_evqual_str); + rule->qual = (Node *) stringToNode(rule_str); MemoryContextSwitchTo(oldcxt); - pfree(rule_evqual_str); + pfree(rule_str); + if ((Pointer) rule_text != DatumGetPointer(rule_datum)) + pfree(rule_text); if (numlocks >= maxlocks) { @@ -2207,6 +2216,13 @@ RelationCacheInitializePhase2(void) * true. (NOTE: perhaps it would be possible to reload them by * temporarily setting criticalRelcachesBuilt to false again. For now, * though, we just nail 'em in.) + * + * RewriteRelRulenameIndexId and TriggerRelidNameIndexId are not critical + * in the same way as the others, because the critical catalogs don't + * (currently) have any rules or triggers, and so these indexes can be + * rebuilt without inducing recursion. However they are used during + * relcache load when a rel does have rules or triggers, so we choose to + * nail them for performance reasons. */ if (!criticalRelcachesBuilt) { @@ -2225,8 +2241,10 @@ RelationCacheInitializePhase2(void) LOAD_CRIT_INDEX(AccessMethodStrategyIndexId); LOAD_CRIT_INDEX(AccessMethodProcedureIndexId); LOAD_CRIT_INDEX(OperatorOidIndexId); + LOAD_CRIT_INDEX(RewriteRelRulenameIndexId); + LOAD_CRIT_INDEX(TriggerRelidNameIndexId); -#define NUM_CRITICAL_INDEXES 6 /* fix if you change list above */ +#define NUM_CRITICAL_INDEXES 8 /* fix if you change list above */ criticalRelcachesBuilt = true; } -- 2.11.0