diff options
author | Neil Conway <neilc@samurai.com> | 2008-02-29 02:49:39 +0000 |
---|---|---|
committer | Neil Conway <neilc@samurai.com> | 2008-02-29 02:49:39 +0000 |
commit | ff428cdeda20b8b1cf465f8c6cd27da9b2abe9b7 (patch) | |
tree | f5e986961f4b9d7cab06b679c666e3da4b590bff /src/backend/executor/nodeFunctionscan.c | |
parent | b13635ce59ca44cc0bc1dcccd9bf7e086fa13ac7 (diff) | |
download | postgresql-ff428cdeda20b8b1cf465f8c6cd27da9b2abe9b7.tar.gz postgresql-ff428cdeda20b8b1cf465f8c6cd27da9b2abe9b7.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/nodeFunctionscan.c')
-rw-r--r-- | src/backend/executor/nodeFunctionscan.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c index 81b9c69e9a2..6bbb5b139b6 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.45 2008/01/01 19:45:49 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.46 2008/02/29 02:49:39 neilc Exp $ * *------------------------------------------------------------------------- */ @@ -77,7 +77,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); + } } /* |