yyscan_t scanner;
Datum prosrcdatum;
char *proc_source;
+ char *proc_signature;
HeapTuple typeTup;
Form_pg_type typeStruct;
PLpgSQL_variable *var;
plpgsql_check_syntax = forValidator;
plpgsql_curr_compile = function;
+ /* format_procedure leaks memory, so run it in temp context */
+ proc_signature = format_procedure(fcinfo->flinfo->fn_oid);
+
/*
* All the permanent output of compilation (e.g. parse tree) is kept in a
* per-function memory context, so it can be reclaimed easily.
ALLOCSET_DEFAULT_SIZES);
plpgsql_compile_tmp_cxt = MemoryContextSwitchTo(func_cxt);
- function->fn_signature = format_procedure(fcinfo->flinfo->fn_oid);
+ function->fn_signature = pstrdup(proc_signature);
MemoryContextSetIdentifier(func_cxt, function->fn_signature);
function->fn_oid = fcinfo->flinfo->fn_oid;
function->fn_input_collation = fcinfo->fncollation;
{
Oid classOid;
Oid typOid;
+ TypeName *typName;
+ MemoryContext oldCxt;
+
+ /* Avoid memory leaks in long-term function context */
+ oldCxt = MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
/*
* Look up the relation. Note that because relation rowtypes have the
errmsg("relation \"%s\" does not have a composite type",
ident)));
+ typName = makeTypeName(ident);
+
+ MemoryContextSwitchTo(oldCxt);
+
/* Build and return the row type struct */
- return plpgsql_build_datatype(typOid, -1, InvalidOid,
- makeTypeName(ident));
+ return plpgsql_build_datatype(typOid, -1, InvalidOid, typName);
}
/* ----------
Oid classOid;
Oid typOid;
RangeVar *relvar;
+ TypeName *typName;
MemoryContext oldCxt;
/*
errmsg("relation \"%s\" does not have a composite type",
relvar->relname)));
+ typName = makeTypeNameFromNameList(idents);
+
MemoryContextSwitchTo(oldCxt);
/* Build and return the row type struct */
- return plpgsql_build_datatype(typOid, -1, InvalidOid,
- makeTypeNameFromNameList(idents));
+ return plpgsql_build_datatype(typOid, -1, InvalidOid, typName);
}
/*
* origtypname is the parsed form of what the user wrote as the type name.
* It can be NULL if the type could not be a composite type, or if it was
* identified by OID to begin with (e.g., it's a function argument type).
+ * origtypname is in short-lived storage and must be copied if we choose
+ * to incorporate it into the function's parse tree.
*/
PLpgSQL_type *
plpgsql_build_datatype(Oid typeOid, int32 typmod,
errmsg("type %s is not composite",
format_type_be(typ->typoid))));
- typ->origtypname = origtypname;
+ typ->origtypname = copyObject(origtypname);
typ->tcache = typentry;
typ->tupdesc_id = typentry->tupDesc_identifier;
}
int32 typmod;
sql_error_callback_arg cbarg;
ErrorContextCallback syntax_errcontext;
+ MemoryContext oldCxt;
cbarg.location = location;
cbarg.yyscanner = yyscanner;
syntax_errcontext.previous = error_context_stack;
error_context_stack = &syntax_errcontext;
- /* Let the main parser try to parse it under standard SQL rules */
+ /*
+ * Let the main parser try to parse it under standard SQL rules. The
+ * parser leaks memory, so run it in temp context.
+ */
+ oldCxt = MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
typeName = typeStringToTypeName(string, NULL);
typenameTypeIdAndMod(NULL, typeName, &type_id, &typmod);
+ MemoryContextSwitchTo(oldCxt);
/* Restore former ereport callback */
error_context_stack = syntax_errcontext.previous;