Skip to content

Commit 738df43

Browse files
author
Neil Conway
committed
Fix bug in CONTINUE statement for PL/pgSQL: when we continue a loop,
we need to be careful to reset rc to PLPGSQL_RC_OK, depending on how the loop's logic is structured. If we continue a loop but it then exits without executing the loop's body again, we want to return PLPGSQL_RC_OK to our caller. Enhance the regression tests to catch this problem. Per report from Michael Fuhr.
1 parent 05db8b5 commit 738df43

File tree

3 files changed

+92
-23
lines changed

3 files changed

+92
-23
lines changed

src/pl/plpgsql/src/pl_exec.c

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* procedural language
44
*
55
* IDENTIFICATION
6-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.147 2005/06/22 01:35:02 neilc Exp $
6+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.148 2005/06/22 07:28:47 neilc Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -1216,11 +1216,9 @@ exec_stmt_if(PLpgSQL_execstate *estate, PLpgSQL_stmt_if *stmt)
12161216
static int
12171217
exec_stmt_loop(PLpgSQL_execstate *estate, PLpgSQL_stmt_loop *stmt)
12181218
{
1219-
int rc;
1220-
12211219
for (;;)
12221220
{
1223-
rc = exec_stmts(estate, stmt->body);
1221+
int rc = exec_stmts(estate, stmt->body);
12241222

12251223
switch (rc)
12261224
{
@@ -1271,12 +1269,12 @@ exec_stmt_loop(PLpgSQL_execstate *estate, PLpgSQL_stmt_loop *stmt)
12711269
static int
12721270
exec_stmt_while(PLpgSQL_execstate *estate, PLpgSQL_stmt_while *stmt)
12731271
{
1274-
bool value;
1275-
bool isnull;
1276-
int rc;
1277-
12781272
for (;;)
12791273
{
1274+
int rc;
1275+
bool value;
1276+
bool isnull;
1277+
12801278
value = exec_eval_boolean(estate, stmt->cond, &isnull);
12811279
exec_eval_cleanup(estate);
12821280

@@ -1425,21 +1423,22 @@ exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
14251423
else if (rc == PLPGSQL_RC_CONTINUE)
14261424
{
14271425
if (estate->exitlabel == NULL)
1428-
/* anonymous continue, so continue the current loop */
1429-
;
1426+
/* anonymous continue, so re-run the current loop */
1427+
rc = PLPGSQL_RC_OK;
14301428
else if (stmt->label != NULL &&
14311429
strcmp(stmt->label, estate->exitlabel) == 0)
14321430
{
1433-
/* labelled continue, matches the current stmt's label */
1431+
/* label matches named continue, so re-run loop */
14341432
estate->exitlabel = NULL;
1433+
rc = PLPGSQL_RC_OK;
14351434
}
14361435
else
14371436
{
14381437
/*
1439-
* otherwise, this is a labelled continue that does
1440-
* not match the current statement's label, if any:
1441-
* return RC_CONTINUE so that the CONTINUE will
1442-
* propagate up the stack.
1438+
* otherwise, this is a named continue that does not
1439+
* match the current statement's label, if any: return
1440+
* RC_CONTINUE so that the CONTINUE will propagate up
1441+
* the stack.
14431442
*/
14441443
break;
14451444
}
@@ -1555,18 +1554,22 @@ exec_stmt_fors(PLpgSQL_execstate *estate, PLpgSQL_stmt_fors *stmt)
15551554
else if (rc == PLPGSQL_RC_CONTINUE)
15561555
{
15571556
if (estate->exitlabel == NULL)
1558-
/* unlabelled continue, continue the current loop */
1557+
{
1558+
/* anonymous continue, so re-run the current loop */
1559+
rc = PLPGSQL_RC_OK;
15591560
continue;
1561+
}
15601562
else if (stmt->label != NULL &&
15611563
strcmp(stmt->label, estate->exitlabel) == 0)
15621564
{
1563-
/* labelled continue, matches the current stmt's label */
1565+
/* label matches named continue, so re-run loop */
1566+
rc = PLPGSQL_RC_OK;
15641567
estate->exitlabel = NULL;
15651568
continue;
15661569
}
15671570

15681571
/*
1569-
* otherwise, we processed a labelled continue
1572+
* otherwise, we processed a named continue
15701573
* that does not match the current statement's
15711574
* label, if any: return RC_CONTINUE so that the
15721575
* CONTINUE will propagate up the stack.
@@ -2462,14 +2465,12 @@ static int
24622465
exec_stmt_dynfors(PLpgSQL_execstate *estate, PLpgSQL_stmt_dynfors *stmt)
24632466
{
24642467
Datum query;
2465-
bool isnull = false;
2468+
bool isnull;
24662469
Oid restype;
24672470
char *querystr;
24682471
PLpgSQL_rec *rec = NULL;
24692472
PLpgSQL_row *row = NULL;
24702473
SPITupleTable *tuptab;
2471-
int rc = PLPGSQL_RC_OK;
2472-
int i;
24732474
int n;
24742475
void *plan;
24752476
Portal portal;
@@ -2536,8 +2537,12 @@ exec_stmt_dynfors(PLpgSQL_execstate *estate, PLpgSQL_stmt_dynfors *stmt)
25362537
*/
25372538
while (n > 0)
25382539
{
2540+
int i;
2541+
25392542
for (i = 0; i < n; i++)
25402543
{
2544+
int rc;
2545+
25412546
/*
25422547
* Assign the tuple to the target
25432548
*/

src/test/regress/expected/plpgsql.out

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2547,7 +2547,33 @@ begin
25472547
for _r in execute 'select * from conttesttbl' loop
25482548
continue when _r.v <= 20;
25492549
raise notice '%', _r.v;
2550-
end loop;
2550+
end loop;
2551+
2552+
raise notice '---7---';
2553+
for _i in 1..3 loop
2554+
raise notice '%', _i;
2555+
continue when _i = 3;
2556+
end loop;
2557+
2558+
raise notice '---8---';
2559+
_i := 1;
2560+
while _i <= 3 loop
2561+
raise notice '%', _i;
2562+
_i := _i + 1;
2563+
continue when _i = 3;
2564+
end loop;
2565+
2566+
raise notice '---9---';
2567+
for _r in select * from conttesttbl order by v limit 1 loop
2568+
raise notice '%', _r.v;
2569+
continue;
2570+
end loop;
2571+
2572+
raise notice '---10---';
2573+
for _r in execute 'select * from conttesttbl order by v limit 1' loop
2574+
raise notice '%', _r.v;
2575+
continue;
2576+
end loop;
25512577
end; $$ language plpgsql;
25522578
select continue_test1();
25532579
NOTICE: ---1---
@@ -2591,6 +2617,18 @@ NOTICE: 40
25912617
NOTICE: ---6---
25922618
NOTICE: 30
25932619
NOTICE: 40
2620+
NOTICE: ---7---
2621+
NOTICE: 1
2622+
NOTICE: 2
2623+
NOTICE: 3
2624+
NOTICE: ---8---
2625+
NOTICE: 1
2626+
NOTICE: 2
2627+
NOTICE: 3
2628+
NOTICE: ---9---
2629+
NOTICE: 10
2630+
NOTICE: ---10---
2631+
NOTICE: 10
25942632
continue_test1
25952633
----------------
25962634

src/test/regress/sql/plpgsql.sql

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2169,7 +2169,33 @@ begin
21692169
for _r in execute 'select * from conttesttbl' loop
21702170
continue when _r.v <= 20;
21712171
raise notice '%', _r.v;
2172-
end loop;
2172+
end loop;
2173+
2174+
raise notice '---7---';
2175+
for _i in 1..3 loop
2176+
raise notice '%', _i;
2177+
continue when _i = 3;
2178+
end loop;
2179+
2180+
raise notice '---8---';
2181+
_i := 1;
2182+
while _i <= 3 loop
2183+
raise notice '%', _i;
2184+
_i := _i + 1;
2185+
continue when _i = 3;
2186+
end loop;
2187+
2188+
raise notice '---9---';
2189+
for _r in select * from conttesttbl order by v limit 1 loop
2190+
raise notice '%', _r.v;
2191+
continue;
2192+
end loop;
2193+
2194+
raise notice '---10---';
2195+
for _r in execute 'select * from conttesttbl order by v limit 1' loop
2196+
raise notice '%', _r.v;
2197+
continue;
2198+
end loop;
21732199
end; $$ language plpgsql;
21742200

21752201
select continue_test1();

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