aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2001-01-22 00:50:07 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2001-01-22 00:50:07 +0000
commitc9fe12831632efc437354cb0482fd6cb5f246a4a (patch)
treeb9b19b88a07ebfd51915b60bc492bfe68c6cd732 /src/backend/executor
parent59a3a401497cd72c550fdfcaa782162d91335bba (diff)
downloadpostgresql-c9fe12831632efc437354cb0482fd6cb5f246a4a.tar.gz
postgresql-c9fe12831632efc437354cb0482fd6cb5f246a4a.zip
Clean up per-tuple memory leaks in trigger firing and plpgsql
expression evaluation.
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execMain.c62
-rw-r--r--src/backend/executor/execUtils.c38
-rw-r--r--src/backend/executor/nodeIndexscan.c11
3 files changed, 57 insertions, 54 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 1c826292c59..a4dbaae3026 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -27,7 +27,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.134 2001/01/01 21:22:54 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.135 2001/01/22 00:50:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -941,11 +941,13 @@ ExecutePlan(EState *estate,
/*
* Loop until we've processed the proper number of tuples from the
- * plan..
+ * plan.
*/
for (;;)
{
+ /* Reset the per-output-tuple exprcontext */
+ ResetPerTupleExprContext(estate);
/*
* Execute the plan and obtain a tuple
@@ -1213,20 +1215,25 @@ ExecAppend(TupleTableSlot *slot,
/* BEFORE ROW INSERT Triggers */
if (resultRelationDesc->trigdesc &&
- resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
+ resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
{
HeapTuple newtuple;
- newtuple = ExecBRInsertTriggers(resultRelationDesc, tuple);
+ newtuple = ExecBRInsertTriggers(estate, resultRelationDesc, tuple);
if (newtuple == NULL) /* "do nothing" */
return;
if (newtuple != tuple) /* modified by Trigger(s) */
{
- Assert(slot->ttc_shouldFree);
- heap_freetuple(tuple);
- slot->val = tuple = newtuple;
+ /*
+ * Insert modified tuple into tuple table slot, replacing the
+ * original. We assume that it was allocated in per-tuple
+ * memory context, and therefore will go away by itself.
+ * The tuple table slot should not try to clear it.
+ */
+ ExecStoreTuple(newtuple, slot, InvalidBuffer, false);
+ tuple = newtuple;
}
}
@@ -1257,8 +1264,9 @@ ExecAppend(TupleTableSlot *slot,
ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
/* AFTER ROW INSERT Triggers */
- if (resultRelationDesc->trigdesc)
- ExecARInsertTriggers(resultRelationDesc, tuple);
+ if (resultRelationDesc->trigdesc &&
+ resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0)
+ ExecARInsertTriggers(estate, resultRelationDesc, tuple);
}
/* ----------------------------------------------------------------
@@ -1286,7 +1294,7 @@ ExecDelete(TupleTableSlot *slot,
/* BEFORE ROW DELETE Triggers */
if (resultRelationDesc->trigdesc &&
- resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_DELETE] > 0)
+ resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_DELETE] > 0)
{
bool dodelete;
@@ -1343,9 +1351,9 @@ ldelete:;
*/
/* AFTER ROW DELETE Triggers */
- if (resultRelationDesc->trigdesc)
+ if (resultRelationDesc->trigdesc &&
+ resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
ExecARDeleteTriggers(estate, tupleid);
-
}
/* ----------------------------------------------------------------
@@ -1393,7 +1401,7 @@ ExecReplace(TupleTableSlot *slot,
/* BEFORE ROW UPDATE Triggers */
if (resultRelationDesc->trigdesc &&
- resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE] > 0)
+ resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE] > 0)
{
HeapTuple newtuple;
@@ -1404,9 +1412,14 @@ ExecReplace(TupleTableSlot *slot,
if (newtuple != tuple) /* modified by Trigger(s) */
{
- Assert(slot->ttc_shouldFree);
- heap_freetuple(tuple);
- slot->val = tuple = newtuple;
+ /*
+ * Insert modified tuple into tuple table slot, replacing the
+ * original. We assume that it was allocated in per-tuple
+ * memory context, and therefore will go away by itself.
+ * The tuple table slot should not try to clear it.
+ */
+ ExecStoreTuple(newtuple, slot, InvalidBuffer, false);
+ tuple = newtuple;
}
}
@@ -1478,7 +1491,8 @@ lreplace:;
ExecInsertIndexTuples(slot, &(tuple->t_self), estate, true);
/* AFTER ROW UPDATE Triggers */
- if (resultRelationDesc->trigdesc)
+ if (resultRelationDesc->trigdesc &&
+ resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)
ExecARUpdateTriggers(estate, tupleid, tuple);
}
@@ -1514,19 +1528,9 @@ ExecRelCheck(ResultRelInfo *resultRelInfo,
/*
* We will use the EState's per-tuple context for evaluating constraint
- * expressions. Create it if it's not already there; if it is, reset it
- * to free previously-used storage.
+ * expressions (creating it if it's not already there).
*/
- econtext = estate->es_per_tuple_exprcontext;
- if (econtext == NULL)
- {
- oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
- estate->es_per_tuple_exprcontext = econtext =
- MakeExprContext(NULL, estate->es_query_cxt);
- MemoryContextSwitchTo(oldContext);
- }
- else
- ResetExprContext(econtext);
+ econtext = GetPerTupleExprContext(estate);
/* Arrange for econtext's scan tuple to be the tuple under test */
econtext->ecxt_scantuple = slot;
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 5d4d7f145b3..a4c7143aa77 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.70 2000/12/27 23:59:11 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.71 2001/01/22 00:50:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -230,6 +230,26 @@ FreeExprContext(ExprContext *econtext)
pfree(econtext);
}
+/*
+ * Build a per-output-tuple ExprContext for an EState.
+ *
+ * This is normally invoked via GetPerTupleExprContext() macro.
+ */
+ExprContext *
+MakePerTupleExprContext(EState *estate)
+{
+ if (estate->es_per_tuple_exprcontext == NULL)
+ {
+ MemoryContext oldContext;
+
+ oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
+ estate->es_per_tuple_exprcontext =
+ MakeExprContext(NULL, estate->es_query_cxt);
+ MemoryContextSwitchTo(oldContext);
+ }
+ return estate->es_per_tuple_exprcontext;
+}
+
/* ----------------------------------------------------------------
* Result slot tuple type and ProjectionInfo support
* ----------------------------------------------------------------
@@ -836,21 +856,9 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
/*
* We will use the EState's per-tuple context for evaluating predicates
- * and functional-index functions. Create it if it's not already there;
- * if it is, reset it to free previously-used storage.
+ * and functional-index functions (creating it if it's not already there).
*/
- econtext = estate->es_per_tuple_exprcontext;
- if (econtext == NULL)
- {
- MemoryContext oldContext;
-
- oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
- estate->es_per_tuple_exprcontext = econtext =
- MakeExprContext(NULL, estate->es_query_cxt);
- MemoryContextSwitchTo(oldContext);
- }
- else
- ResetExprContext(econtext);
+ econtext = GetPerTupleExprContext(estate);
/* Arrange for econtext's scan tuple to be the tuple under test */
econtext->ecxt_scantuple = slot;
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index a8b29514b88..7c389975a71 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -8,14 +8,12 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.54 2000/08/24 03:29:03 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.55 2001/01/22 00:50:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* INTERFACE ROUTINES
- * ExecInsertIndexTuples inserts tuples into indices on result relation
- *
* ExecIndexScan scans a relation using indices
* ExecIndexNext using index to retrieve next tuple
* ExecInitIndexScan creates and initializes state info.
@@ -23,16 +21,9 @@
* ExecEndIndexScan releases all storage.
* ExecIndexMarkPos marks scan position.
* ExecIndexRestrPos restores scan position.
- *
- * NOTES
- * the code supporting ExecInsertIndexTuples should be
- * collected and merged with the genam stuff.
- *
*/
#include "postgres.h"
-
-
#include "access/genam.h"
#include "access/heapam.h"
#include "executor/execdebug.h"