aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
authorNeil Conway <neilc@samurai.com>2008-02-29 02:49:47 +0000
committerNeil Conway <neilc@samurai.com>2008-02-29 02:49:47 +0000
commit5694053570da490c0fa3a8f9245bce3c652215c5 (patch)
treeecc6f999e0df2d24fff3f7debe2df4bcf1c53b4b /src/backend/executor
parentc05c8fe5d7e260aabcb54ced95dbb0cb79a4283f (diff)
downloadpostgresql-5694053570da490c0fa3a8f9245bce3c652215c5.tar.gz
postgresql-5694053570da490c0fa3a8f9245bce3c652215c5.zip
Fix several memory leaks when rescanning SRFs. Arrange for an SRF's
"multi_call_ctx" to be a distinct sub-context of the EState's per-query context, and delete the multi_call_ctx as soon as the SRF finishes execution. This avoids leaking SRF memory until the end of the current query, which is particularly egregious when the SRF is scanned multiple times. This change also fixes a leak of the fields of the AttInMetadata struct in shutdown_MultiFuncCall(). Also fix a leak of the SRF result TupleDesc when rescanning a FunctionScan node. The TupleDesc is allocated in the per-query context for every call to ExecMakeTableFunctionResult(), so we should free it after calling that function. Since the SRF might choose to return a non-expendable TupleDesc, we only free the TupleDesc if it is not being reference-counted. Backpatch to 8.3 and 8.2 stable branches.
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/nodeFunctionscan.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index 3ab193cb14a..3164b9923f7 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.40.2.1 2006/12/26 19:26:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.40.2.2 2008/02/29 02:49:47 neilc Exp $
*
*-------------------------------------------------------------------------
*/
@@ -78,7 +78,17 @@ FunctionNext(FunctionScanState *node)
* do it always.
*/
if (funcTupdesc)
+ {
tupledesc_match(node->tupdesc, funcTupdesc);
+
+ /*
+ * If it is a dynamically-allocated TupleDesc, free it: it is
+ * typically allocated in the EState's per-query context, so we
+ * must avoid leaking it on rescan.
+ */
+ if (funcTupdesc->tdrefcount == -1)
+ FreeTupleDesc(funcTupdesc);
+ }
}
/*