diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2001-01-22 00:50:07 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2001-01-22 00:50:07 +0000 |
commit | c9fe12831632efc437354cb0482fd6cb5f246a4a (patch) | |
tree | b9b19b88a07ebfd51915b60bc492bfe68c6cd732 /src/backend/executor | |
parent | 59a3a401497cd72c550fdfcaa782162d91335bba (diff) | |
download | postgresql-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.c | 62 | ||||
-rw-r--r-- | src/backend/executor/execUtils.c | 38 | ||||
-rw-r--r-- | src/backend/executor/nodeIndexscan.c | 11 |
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" |