Since plpgsql keeps its compiled function parsetrees until backend exit,
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 6 Apr 2001 02:06:48 +0000 (02:06 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 6 Apr 2001 02:06:48 +0000 (02:06 +0000)
it needs to ensure that data structures attached to fmgr info records in
the trees will stick around that long, too.  Current code was crashing
on cases like datatypes with old-style I/O functions.

src/pl/plpgsql/src/pl_comp.c

index 213bedb28d13580cb1a60eb3288be409985115f4..22bb9e03a8f6312fc34f99dcb05d2b3a4538a787 100644 (file)
@@ -3,7 +3,7 @@
  *           procedural language
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.28 2001/03/22 06:16:21 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.29 2001/04/06 02:06:48 tgl Exp $
  *
  *   This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -85,6 +85,28 @@ int          plpgsql_DumpExecTree = 0;
 PLpgSQL_function *plpgsql_curr_compile;
 
 
+/*
+ * This routine is a crock, and so is everyplace that calls it.  The problem
+ * is that the compiled form of a plpgsql function is allocated permanently
+ * (mostly via malloc()) and never released until backend exit.  Subsidiary
+ * data structures such as fmgr info records therefore must live forever
+ * as well.  A better implementation would store all this stuff in a per-
+ * function memory context that could be reclaimed at need.  In the meantime,
+ * fmgr_info must be called in TopMemoryContext so that whatever it might
+ * allocate, and whatever the eventual function might allocate using fn_mcxt,
+ * will live forever too.
+ */
+static void
+perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
+{
+   MemoryContext   oldcontext;
+
+   oldcontext = MemoryContextSwitchTo(TopMemoryContext);
+   fmgr_info(functionId, finfo);
+   MemoryContextSwitchTo(oldcontext);
+}
+
+
 /* ----------
  * plpgsql_compile     Given a pg_proc's oid, make
  *                     an execution tree for it.
@@ -184,7 +206,7 @@ plpgsql_compile(Oid fn_oid, int functype)
                function->fn_retbyval = typeStruct->typbyval;
                function->fn_rettyplen = typeStruct->typlen;
                function->fn_rettypelem = typeStruct->typelem;
-               fmgr_info(typeStruct->typinput, &(function->fn_retinput));
+               perm_fmgr_info(typeStruct->typinput, &(function->fn_retinput));
            }
            ReleaseSysCache(typeTup);
 
@@ -257,7 +279,7 @@ plpgsql_compile(Oid fn_oid, int functype)
                    var->datatype->typname = DatumGetCString(DirectFunctionCall1(nameout,
                                  NameGetDatum(&(typeStruct->typname))));
                    var->datatype->typoid = procStruct->proargtypes[i];
-                   fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
+                   perm_fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
                    var->datatype->typelem = typeStruct->typelem;
                    var->datatype->typbyval = typeStruct->typbyval;
                    var->datatype->atttypmod = -1;
@@ -607,7 +629,7 @@ plpgsql_parse_word(char *word)
        typ->typname = DatumGetCString(DirectFunctionCall1(nameout,
                                  NameGetDatum(&(typeStruct->typname))));
        typ->typoid = typeTup->t_data->t_oid;
-       fmgr_info(typeStruct->typinput, &(typ->typinput));
+       perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
        typ->typelem = typeStruct->typelem;
        typ->typbyval = typeStruct->typbyval;
        typ->atttypmod = -1;
@@ -923,7 +945,7 @@ plpgsql_parse_wordtype(char *word)
        typ->typname = DatumGetCString(DirectFunctionCall1(nameout,
                                  NameGetDatum(&(typeStruct->typname))));
        typ->typoid = typeTup->t_data->t_oid;
-       fmgr_info(typeStruct->typinput, &(typ->typinput));
+       perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
        typ->typelem = typeStruct->typelem;
        typ->typbyval = typeStruct->typbyval;
        typ->atttypmod = -1;
@@ -1066,7 +1088,7 @@ plpgsql_parse_dblwordtype(char *string)
    typ->typname = DatumGetCString(DirectFunctionCall1(nameout,
                                  NameGetDatum(&(typeStruct->typname))));
    typ->typoid = typetup->t_data->t_oid;
-   fmgr_info(typeStruct->typinput, &(typ->typinput));
+   perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
    typ->typelem = typeStruct->typelem;
    typ->typbyval = typeStruct->typbyval;
    typ->atttypmod = attrStruct->atttypmod;
@@ -1200,7 +1222,7 @@ plpgsql_parse_wordrowtype(char *string)
        var->datatype = malloc(sizeof(PLpgSQL_type));
        var->datatype->typname = strdup(NameStr(typeStruct->typname));
        var->datatype->typoid = typetup->t_data->t_oid;
-       fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
+       perm_fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
        var->datatype->typelem = typeStruct->typelem;
        var->datatype->typbyval = typeStruct->typbyval;
        var->datatype->atttypmod = attrStruct->atttypmod;