Commit edfbd074 authored by Tom Lane's avatar Tom Lane

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.
parent 44b928e8
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -565,10 +565,9 @@ RelationBuildRuleLock(Relation relation)
{ {
Form_pg_rewrite rewrite_form = (Form_pg_rewrite) GETSTRUCT(rewrite_tuple); Form_pg_rewrite rewrite_form = (Form_pg_rewrite) GETSTRUCT(rewrite_tuple);
bool isnull; bool isnull;
Datum ruleaction; Datum rule_datum;
Datum rule_evqual; text *rule_text;
char *ruleaction_str; char *rule_str;
char *rule_evqual_str;
RewriteRule *rule; RewriteRule *rule;
rule = (RewriteRule *) MemoryContextAlloc(rulescxt, rule = (RewriteRule *) MemoryContextAlloc(rulescxt,
...@@ -580,31 +579,41 @@ RelationBuildRuleLock(Relation relation) ...@@ -580,31 +579,41 @@ RelationBuildRuleLock(Relation relation)
rule->attrno = rewrite_form->ev_attr; rule->attrno = rewrite_form->ev_attr;
rule->isInstead = rewrite_form->is_instead; rule->isInstead = rewrite_form->is_instead;
/* Must use heap_getattr to fetch ev_qual and ev_action */ /*
* Must use heap_getattr to fetch ev_action and ev_qual. Also,
ruleaction = heap_getattr(rewrite_tuple, * 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, Anum_pg_rewrite_ev_action,
rewrite_tupdesc, rewrite_tupdesc,
&isnull); &isnull);
Assert(!isnull); Assert(!isnull);
ruleaction_str = DatumGetCString(DirectFunctionCall1(textout, rule_text = DatumGetTextP(rule_datum);
ruleaction)); rule_str = DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(rule_text)));
oldcxt = MemoryContextSwitchTo(rulescxt); oldcxt = MemoryContextSwitchTo(rulescxt);
rule->actions = (List *) stringToNode(ruleaction_str); rule->actions = (List *) stringToNode(rule_str);
MemoryContextSwitchTo(oldcxt); MemoryContextSwitchTo(oldcxt);
pfree(ruleaction_str); pfree(rule_str);
if ((Pointer) rule_text != DatumGetPointer(rule_datum))
pfree(rule_text);
rule_evqual = heap_getattr(rewrite_tuple, rule_datum = heap_getattr(rewrite_tuple,
Anum_pg_rewrite_ev_qual, Anum_pg_rewrite_ev_qual,
rewrite_tupdesc, rewrite_tupdesc,
&isnull); &isnull);
Assert(!isnull); Assert(!isnull);
rule_evqual_str = DatumGetCString(DirectFunctionCall1(textout, rule_text = DatumGetTextP(rule_datum);
rule_evqual)); rule_str = DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(rule_text)));
oldcxt = MemoryContextSwitchTo(rulescxt); oldcxt = MemoryContextSwitchTo(rulescxt);
rule->qual = (Node *) stringToNode(rule_evqual_str); rule->qual = (Node *) stringToNode(rule_str);
MemoryContextSwitchTo(oldcxt); MemoryContextSwitchTo(oldcxt);
pfree(rule_evqual_str); pfree(rule_str);
if ((Pointer) rule_text != DatumGetPointer(rule_datum))
pfree(rule_text);
if (numlocks >= maxlocks) if (numlocks >= maxlocks)
{ {
...@@ -2207,6 +2216,13 @@ RelationCacheInitializePhase2(void) ...@@ -2207,6 +2216,13 @@ RelationCacheInitializePhase2(void)
* true. (NOTE: perhaps it would be possible to reload them by * true. (NOTE: perhaps it would be possible to reload them by
* temporarily setting criticalRelcachesBuilt to false again. For now, * temporarily setting criticalRelcachesBuilt to false again. For now,
* though, we just nail 'em in.) * 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) if (!criticalRelcachesBuilt)
{ {
...@@ -2225,8 +2241,10 @@ RelationCacheInitializePhase2(void) ...@@ -2225,8 +2241,10 @@ RelationCacheInitializePhase2(void)
LOAD_CRIT_INDEX(AccessMethodStrategyIndexId); LOAD_CRIT_INDEX(AccessMethodStrategyIndexId);
LOAD_CRIT_INDEX(AccessMethodProcedureIndexId); LOAD_CRIT_INDEX(AccessMethodProcedureIndexId);
LOAD_CRIT_INDEX(OperatorOidIndexId); 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; criticalRelcachesBuilt = true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment