diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 216f1c852926199162c57960bfd0d833aaf263a8..9d4e402ae20cfbf7129080f14e8df975b60f3e46 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;
 	}