*
  *
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
        {
                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,
                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)
                {
         * 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)
        {
                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;
        }