1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-18 02:02:55 +03:00

The previous fix in CVS HEAD and 8.4 for handling the case where a cursor

being used in a PL/pgSQL FOR loop is closed was inadequate, as Tom Lane
pointed out. The bug affects FOR statement variants too, because you can
close an implicitly created cursor too by guessing the "<unnamed portal X>"
name created for it.

To fix that, "pin" the portal to prevent it from being dropped while it's
being used in a PL/pgSQL FOR loop. Backpatch all the way to 7.4 which is
the oldest supported version.
This commit is contained in:
Heikki Linnakangas
2010-07-05 09:27:36 +00:00
parent 03795ffbc8
commit 9e3a7f50e4
3 changed files with 67 additions and 8 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.180.2.12 2010/02/12 19:38:00 tgl Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.180.2.13 2010/07/05 09:27:36 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1661,9 +1661,11 @@ exec_stmt_fors(PLpgSQL_execstate *estate, PLpgSQL_stmt_fors *stmt)
/*
* Open the implicit cursor for the statement and fetch the initial 10
* rows.
* rows. Pin the portal to make sure it doesn't get closed by the user
* statements we execute.
*/
exec_run_select(estate, stmt->query, 0, &portal);
PinPortal(portal);
SPI_cursor_fetch(portal, true, 10);
tuptab = SPI_tuptable;
@@ -1745,6 +1747,7 @@ exec_stmt_fors(PLpgSQL_execstate *estate, PLpgSQL_stmt_fors *stmt)
* code should match the code after the loop.)
*/
SPI_freetuptable(tuptab);
UnpinPortal(portal);
SPI_cursor_close(portal);
exec_set_found(estate, found);
@@ -1770,6 +1773,7 @@ exec_stmt_fors(PLpgSQL_execstate *estate, PLpgSQL_stmt_fors *stmt)
/*
* Close the implicit cursor
*/
UnpinPortal(portal);
SPI_cursor_close(portal);
/*
@@ -2777,6 +2781,12 @@ exec_stmt_dynfors(PLpgSQL_execstate *estate, PLpgSQL_stmt_dynfors *stmt)
pfree(querystr);
SPI_freeplan(plan);
/*
* Make sure the portal doesn't get closed by the user statements
* we execute.
*/
PinPortal(portal);
/*
* Fetch the initial 10 tuples
*/
@@ -2860,6 +2870,7 @@ exec_stmt_dynfors(PLpgSQL_execstate *estate, PLpgSQL_stmt_dynfors *stmt)
* code should match the code after the loop.)
*/
SPI_freetuptable(tuptab);
UnpinPortal(portal);
SPI_cursor_close(portal);
exec_set_found(estate, found);
@@ -2885,6 +2896,7 @@ exec_stmt_dynfors(PLpgSQL_execstate *estate, PLpgSQL_stmt_dynfors *stmt)
/*
* Close the implicit cursor
*/
UnpinPortal(portal);
SPI_cursor_close(portal);
/*