Commit a8e0b660 authored by Tom Lane's avatar Tom Lane

Fix up plpgsql's "simple expression" evaluation mechanism so that it behaves

safely in the presence of subtransactions.  To ensure that any ExprContext
shutdown callbacks are called at the right times, we have to have a separate
EState for each level of subtransaction.  Per "TupleDesc reference leak" bug
report from Stefan Kaltenbrunner.

Although I'm convinced the code is wrong as far back as 8.0, it doesn't seem
that there are any ways for the problem to really manifest before 8.2: AFAICS,
8.0 and 8.1 only use the ExprContextCallback mechanism to handle set-returning
functions, which cannot usefully be executed in a "simple expression" anyway.
Hence, no backpatch before 8.2 --- the risk of unforeseen breakage seems
to outweigh the chance of fixing something.
parent 76c7d2af
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.34 2007/01/05 22:20:02 momjian Exp $ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.35 2007/01/28 16:15:49 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -46,6 +46,7 @@ _PG_init(void) ...@@ -46,6 +46,7 @@ _PG_init(void)
plpgsql_HashTableInit(); plpgsql_HashTableInit();
RegisterXactCallback(plpgsql_xact_cb, NULL); RegisterXactCallback(plpgsql_xact_cb, NULL);
RegisterSubXactCallback(plpgsql_subxact_cb, NULL);
/* Set up a rendezvous point with optional instrumentation plugin */ /* Set up a rendezvous point with optional instrumentation plugin */
plugin_ptr = (PLpgSQL_plugin **) find_rendezvous_variable("PLpgSQL_plugin"); plugin_ptr = (PLpgSQL_plugin **) find_rendezvous_variable("PLpgSQL_plugin");
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.82 2007/01/05 22:20:02 momjian Exp $ * $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.83 2007/01/28 16:15:49 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -180,11 +180,13 @@ typedef struct PLpgSQL_expr ...@@ -180,11 +180,13 @@ typedef struct PLpgSQL_expr
Oid expr_simple_type; Oid expr_simple_type;
/* /*
* if expr is simple AND in use in current xact, expr_simple_state is * if expr is simple AND prepared in current eval_estate,
* valid. Test validity by seeing if expr_simple_xid matches current XID. * expr_simple_state is valid. Test validity by seeing if expr_simple_id
* matches eval_estate_simple_id.
*/ */
ExprState *expr_simple_state; ExprState *expr_simple_state;
TransactionId expr_simple_xid; long int expr_simple_id;
/* params to pass to expr */ /* params to pass to expr */
int nparams; int nparams;
int params[1]; /* VARIABLE SIZE ARRAY ... must be last */ int params[1]; /* VARIABLE SIZE ARRAY ... must be last */
...@@ -612,7 +614,9 @@ typedef struct ...@@ -612,7 +614,9 @@ typedef struct
SPITupleTable *eval_tuptable; SPITupleTable *eval_tuptable;
uint32 eval_processed; uint32 eval_processed;
Oid eval_lastoid; Oid eval_lastoid;
ExprContext *eval_econtext; ExprContext *eval_econtext; /* for executing simple expressions */
EState *eval_estate; /* EState containing eval_econtext */
long int eval_estate_simple_id; /* ID for eval_estate */
/* status information for error context reporting */ /* status information for error context reporting */
PLpgSQL_function *err_func; /* current func */ PLpgSQL_function *err_func; /* current func */
...@@ -738,6 +742,8 @@ extern Datum plpgsql_exec_function(PLpgSQL_function *func, ...@@ -738,6 +742,8 @@ extern Datum plpgsql_exec_function(PLpgSQL_function *func,
extern HeapTuple plpgsql_exec_trigger(PLpgSQL_function *func, extern HeapTuple plpgsql_exec_trigger(PLpgSQL_function *func,
TriggerData *trigdata); TriggerData *trigdata);
extern void plpgsql_xact_cb(XactEvent event, void *arg); extern void plpgsql_xact_cb(XactEvent event, void *arg);
extern void plpgsql_subxact_cb(SubXactEvent event, SubTransactionId mySubid,
SubTransactionId parentSubid, void *arg);
/* ---------- /* ----------
* Functions for the dynamic string handling in pl_funcs.c * Functions for the dynamic string handling in pl_funcs.c
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment