Skip to content

Commit a1dbe52

Browse files
committed
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.
1 parent 191ef2b commit a1dbe52

File tree

1 file changed

+31
-31
lines changed

1 file changed

+31
-31
lines changed

src/pl/plpgsql/src/pl_exec.c

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* procedural language
44
*
55
* IDENTIFICATION
6-
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.79 2003/02/16 02:30:39 tgl Exp $
6+
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.80 2003/03/02 20:45:47 tgl Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -1388,11 +1388,12 @@ exec_stmt_fors(PLpgSQL_execstate * estate, PLpgSQL_stmt_fors * stmt)
13881388
if (rc != PLPGSQL_RC_OK)
13891389
{
13901390
/*
1391-
* We're aborting the loop, so cleanup and set FOUND
1391+
* We're aborting the loop, so cleanup and set FOUND.
1392+
* (This code should match the code after the loop.)
13921393
*/
1393-
exec_set_found(estate, found);
13941394
SPI_freetuptable(tuptab);
13951395
SPI_cursor_close(portal);
1396+
exec_set_found(estate, found);
13961397

13971398
if (rc == PLPGSQL_RC_EXIT)
13981399
{
@@ -1429,6 +1430,11 @@ exec_stmt_fors(PLpgSQL_execstate * estate, PLpgSQL_stmt_fors * stmt)
14291430
tuptab = SPI_tuptable;
14301431
}
14311432

1433+
/*
1434+
* Release last group of tuples
1435+
*/
1436+
SPI_freetuptable(tuptab);
1437+
14321438
/*
14331439
* Close the implicit cursor
14341440
*/
@@ -2381,7 +2387,7 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt)
23812387
if (n == 0)
23822388
exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
23832389
else
2384-
found = true;
2390+
found = true; /* processed at least one tuple */
23852391

23862392
/*
23872393
* Now do the loop
@@ -2400,14 +2406,15 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt)
24002406
*/
24012407
rc = exec_stmts(estate, stmt->body);
24022408

2403-
/*
2404-
* We're aborting the loop, so cleanup and set FOUND
2405-
*/
24062409
if (rc != PLPGSQL_RC_OK)
24072410
{
2408-
exec_set_found(estate, found);
2411+
/*
2412+
* We're aborting the loop, so cleanup and set FOUND.
2413+
* (This code should match the code after the loop.)
2414+
*/
24092415
SPI_freetuptable(tuptab);
24102416
SPI_cursor_close(portal);
2417+
exec_set_found(estate, found);
24112418

24122419
if (rc == PLPGSQL_RC_EXIT)
24132420
{
@@ -2445,7 +2452,12 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt)
24452452
}
24462453

24472454
/*
2448-
* Close the cursor
2455+
* Release last group of tuples
2456+
*/
2457+
SPI_freetuptable(tuptab);
2458+
2459+
/*
2460+
* Close the implicit cursor
24492461
*/
24502462
SPI_cursor_close(portal);
24512463

@@ -2753,25 +2765,16 @@ exec_stmt_fetch(PLpgSQL_execstate * estate, PLpgSQL_stmt_fetch * stmt)
27532765
elog(ERROR, "cursor \"%s\" is invalid", curname);
27542766
pfree(curname);
27552767

2756-
/* ----------
2757-
* Initialize the global found variable to false
2758-
* ----------
2759-
*/
2760-
exec_set_found(estate, false);
2761-
27622768
/* ----------
27632769
* Determine if we fetch into a record or a row
27642770
* ----------
27652771
*/
27662772
if (stmt->rec != NULL)
27672773
rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->recno]);
2774+
else if (stmt->row != NULL)
2775+
row = (PLpgSQL_row *) (estate->datums[stmt->row->rowno]);
27682776
else
2769-
{
2770-
if (stmt->row != NULL)
2771-
row = (PLpgSQL_row *) (estate->datums[stmt->row->rowno]);
2772-
else
2773-
elog(ERROR, "unsupported target in exec_stmt_select()");
2774-
}
2777+
elog(ERROR, "unsupported target in exec_stmt_fetch()");
27752778

27762779
/* ----------
27772780
* Fetch 1 tuple from the cursor
@@ -2782,22 +2785,19 @@ exec_stmt_fetch(PLpgSQL_execstate * estate, PLpgSQL_stmt_fetch * stmt)
27822785
n = SPI_processed;
27832786

27842787
/* ----------
2785-
* If the FETCH didn't return a row, set the target
2786-
* to NULL and return with FOUND = false.
2788+
* Set the target and the global FOUND variable appropriately.
27872789
* ----------
27882790
*/
27892791
if (n == 0)
27902792
{
27912793
exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
2792-
return PLPGSQL_RC_OK;
2794+
exec_set_found(estate, false);
2795+
}
2796+
else
2797+
{
2798+
exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
2799+
exec_set_found(estate, true);
27932800
}
2794-
2795-
/* ----------
2796-
* Put the result into the target and set found to true
2797-
* ----------
2798-
*/
2799-
exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
2800-
exec_set_found(estate, true);
28012801

28022802
SPI_freetuptable(tuptab);
28032803

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy