提交 a1dbe521 编写于 作者: T Tom Lane

Repair memory leak introduced by recent change to make SPI return a

tupdesc even with zero tuples returned: some plpgsql routines assumed
they didn't need to do SPI_freetuptable() after retrieving no tuples.
上级 191ef2b4
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* procedural language * procedural language
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.79 2003/02/16 02:30:39 tgl Exp $ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.80 2003/03/02 20:45:47 tgl Exp $
* *
* This software is copyrighted by Jan Wieck - Hamburg. * This software is copyrighted by Jan Wieck - Hamburg.
* *
...@@ -1388,11 +1388,12 @@ exec_stmt_fors(PLpgSQL_execstate * estate, PLpgSQL_stmt_fors * stmt) ...@@ -1388,11 +1388,12 @@ exec_stmt_fors(PLpgSQL_execstate * estate, PLpgSQL_stmt_fors * stmt)
if (rc != PLPGSQL_RC_OK) if (rc != PLPGSQL_RC_OK)
{ {
/* /*
* We're aborting the loop, so cleanup and set FOUND * We're aborting the loop, so cleanup and set FOUND.
* (This code should match the code after the loop.)
*/ */
exec_set_found(estate, found);
SPI_freetuptable(tuptab); SPI_freetuptable(tuptab);
SPI_cursor_close(portal); SPI_cursor_close(portal);
exec_set_found(estate, found);
if (rc == PLPGSQL_RC_EXIT) if (rc == PLPGSQL_RC_EXIT)
{ {
...@@ -1429,6 +1430,11 @@ exec_stmt_fors(PLpgSQL_execstate * estate, PLpgSQL_stmt_fors * stmt) ...@@ -1429,6 +1430,11 @@ exec_stmt_fors(PLpgSQL_execstate * estate, PLpgSQL_stmt_fors * stmt)
tuptab = SPI_tuptable; tuptab = SPI_tuptable;
} }
/*
* Release last group of tuples
*/
SPI_freetuptable(tuptab);
/* /*
* Close the implicit cursor * Close the implicit cursor
*/ */
...@@ -2381,7 +2387,7 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt) ...@@ -2381,7 +2387,7 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt)
if (n == 0) if (n == 0)
exec_move_row(estate, rec, row, NULL, tuptab->tupdesc); exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
else else
found = true; found = true; /* processed at least one tuple */
/* /*
* Now do the loop * Now do the loop
...@@ -2400,14 +2406,15 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt) ...@@ -2400,14 +2406,15 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt)
*/ */
rc = exec_stmts(estate, stmt->body); rc = exec_stmts(estate, stmt->body);
/*
* We're aborting the loop, so cleanup and set FOUND
*/
if (rc != PLPGSQL_RC_OK) if (rc != PLPGSQL_RC_OK)
{ {
exec_set_found(estate, found); /*
* We're aborting the loop, so cleanup and set FOUND.
* (This code should match the code after the loop.)
*/
SPI_freetuptable(tuptab); SPI_freetuptable(tuptab);
SPI_cursor_close(portal); SPI_cursor_close(portal);
exec_set_found(estate, found);
if (rc == PLPGSQL_RC_EXIT) if (rc == PLPGSQL_RC_EXIT)
{ {
...@@ -2445,7 +2452,12 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt) ...@@ -2445,7 +2452,12 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt)
} }
/* /*
* Close the cursor * Release last group of tuples
*/
SPI_freetuptable(tuptab);
/*
* Close the implicit cursor
*/ */
SPI_cursor_close(portal); SPI_cursor_close(portal);
...@@ -2753,25 +2765,16 @@ exec_stmt_fetch(PLpgSQL_execstate * estate, PLpgSQL_stmt_fetch * stmt) ...@@ -2753,25 +2765,16 @@ exec_stmt_fetch(PLpgSQL_execstate * estate, PLpgSQL_stmt_fetch * stmt)
elog(ERROR, "cursor \"%s\" is invalid", curname); elog(ERROR, "cursor \"%s\" is invalid", curname);
pfree(curname); pfree(curname);
/* ----------
* Initialize the global found variable to false
* ----------
*/
exec_set_found(estate, false);
/* ---------- /* ----------
* Determine if we fetch into a record or a row * Determine if we fetch into a record or a row
* ---------- * ----------
*/ */
if (stmt->rec != NULL) if (stmt->rec != NULL)
rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->recno]); rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->recno]);
else else if (stmt->row != NULL)
{
if (stmt->row != NULL)
row = (PLpgSQL_row *) (estate->datums[stmt->row->rowno]); row = (PLpgSQL_row *) (estate->datums[stmt->row->rowno]);
else else
elog(ERROR, "unsupported target in exec_stmt_select()"); elog(ERROR, "unsupported target in exec_stmt_fetch()");
}
/* ---------- /* ----------
* Fetch 1 tuple from the cursor * Fetch 1 tuple from the cursor
...@@ -2782,22 +2785,19 @@ exec_stmt_fetch(PLpgSQL_execstate * estate, PLpgSQL_stmt_fetch * stmt) ...@@ -2782,22 +2785,19 @@ exec_stmt_fetch(PLpgSQL_execstate * estate, PLpgSQL_stmt_fetch * stmt)
n = SPI_processed; n = SPI_processed;
/* ---------- /* ----------
* If the FETCH didn't return a row, set the target * Set the target and the global FOUND variable appropriately.
* to NULL and return with FOUND = false.
* ---------- * ----------
*/ */
if (n == 0) if (n == 0)
{ {
exec_move_row(estate, rec, row, NULL, tuptab->tupdesc); exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
return PLPGSQL_RC_OK; exec_set_found(estate, false);
} }
else
/* ---------- {
* Put the result into the target and set found to true
* ----------
*/
exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc); exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
exec_set_found(estate, true); exec_set_found(estate, true);
}
SPI_freetuptable(tuptab); SPI_freetuptable(tuptab);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册