Skip to content

Commit a3ed622

Browse files
committed
Since plpgsql keeps its compiled function parsetrees until backend exit,
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.
1 parent f10596c commit a3ed622

File tree

1 file changed

+29
-7
lines changed

1 file changed

+29
-7
lines changed

src/pl/plpgsql/src/pl_comp.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* procedural language
44
*
55
* IDENTIFICATION
6-
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.28 2001/03/22 06:16:21 momjian Exp $
6+
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.29 2001/04/06 02:06:48 tgl Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -85,6 +85,28 @@ int plpgsql_DumpExecTree = 0;
8585
PLpgSQL_function *plpgsql_curr_compile;
8686

8787

88+
/*
89+
* This routine is a crock, and so is everyplace that calls it. The problem
90+
* is that the compiled form of a plpgsql function is allocated permanently
91+
* (mostly via malloc()) and never released until backend exit. Subsidiary
92+
* data structures such as fmgr info records therefore must live forever
93+
* as well. A better implementation would store all this stuff in a per-
94+
* function memory context that could be reclaimed at need. In the meantime,
95+
* fmgr_info must be called in TopMemoryContext so that whatever it might
96+
* allocate, and whatever the eventual function might allocate using fn_mcxt,
97+
* will live forever too.
98+
*/
99+
static void
100+
perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
101+
{
102+
MemoryContext oldcontext;
103+
104+
oldcontext = MemoryContextSwitchTo(TopMemoryContext);
105+
fmgr_info(functionId, finfo);
106+
MemoryContextSwitchTo(oldcontext);
107+
}
108+
109+
88110
/* ----------
89111
* plpgsql_compile Given a pg_proc's oid, make
90112
* an execution tree for it.
@@ -184,7 +206,7 @@ plpgsql_compile(Oid fn_oid, int functype)
184206
function->fn_retbyval = typeStruct->typbyval;
185207
function->fn_rettyplen = typeStruct->typlen;
186208
function->fn_rettypelem = typeStruct->typelem;
187-
fmgr_info(typeStruct->typinput, &(function->fn_retinput));
209+
perm_fmgr_info(typeStruct->typinput, &(function->fn_retinput));
188210
}
189211
ReleaseSysCache(typeTup);
190212

@@ -257,7 +279,7 @@ plpgsql_compile(Oid fn_oid, int functype)
257279
var->datatype->typname = DatumGetCString(DirectFunctionCall1(nameout,
258280
NameGetDatum(&(typeStruct->typname))));
259281
var->datatype->typoid = procStruct->proargtypes[i];
260-
fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
282+
perm_fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
261283
var->datatype->typelem = typeStruct->typelem;
262284
var->datatype->typbyval = typeStruct->typbyval;
263285
var->datatype->atttypmod = -1;
@@ -607,7 +629,7 @@ plpgsql_parse_word(char *word)
607629
typ->typname = DatumGetCString(DirectFunctionCall1(nameout,
608630
NameGetDatum(&(typeStruct->typname))));
609631
typ->typoid = typeTup->t_data->t_oid;
610-
fmgr_info(typeStruct->typinput, &(typ->typinput));
632+
perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
611633
typ->typelem = typeStruct->typelem;
612634
typ->typbyval = typeStruct->typbyval;
613635
typ->atttypmod = -1;
@@ -923,7 +945,7 @@ plpgsql_parse_wordtype(char *word)
923945
typ->typname = DatumGetCString(DirectFunctionCall1(nameout,
924946
NameGetDatum(&(typeStruct->typname))));
925947
typ->typoid = typeTup->t_data->t_oid;
926-
fmgr_info(typeStruct->typinput, &(typ->typinput));
948+
perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
927949
typ->typelem = typeStruct->typelem;
928950
typ->typbyval = typeStruct->typbyval;
929951
typ->atttypmod = -1;
@@ -1066,7 +1088,7 @@ plpgsql_parse_dblwordtype(char *string)
10661088
typ->typname = DatumGetCString(DirectFunctionCall1(nameout,
10671089
NameGetDatum(&(typeStruct->typname))));
10681090
typ->typoid = typetup->t_data->t_oid;
1069-
fmgr_info(typeStruct->typinput, &(typ->typinput));
1091+
perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
10701092
typ->typelem = typeStruct->typelem;
10711093
typ->typbyval = typeStruct->typbyval;
10721094
typ->atttypmod = attrStruct->atttypmod;
@@ -1200,7 +1222,7 @@ plpgsql_parse_wordrowtype(char *string)
12001222
var->datatype = malloc(sizeof(PLpgSQL_type));
12011223
var->datatype->typname = strdup(NameStr(typeStruct->typname));
12021224
var->datatype->typoid = typetup->t_data->t_oid;
1203-
fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
1225+
perm_fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
12041226
var->datatype->typelem = typeStruct->typelem;
12051227
var->datatype->typbyval = typeStruct->typbyval;
12061228
var->datatype->atttypmod = attrStruct->atttypmod;

0 commit comments

Comments
 (0)