Skip to content

Commit b186630

Browse files
committed
better detection of missing return in exception handlers
1 parent df9cd90 commit b186630

File tree

3 files changed

+106
-2
lines changed

3 files changed

+106
-2
lines changed

expected/plpgsql_check_active.out

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3875,3 +3875,58 @@ select * from plpgsql_check_function('dyn_sql_4()');
38753875
(2 rows)
38763876

38773877
drop function dyn_sql_4();
3878+
create or replace function test_bug(text)
3879+
returns regproc as $$
3880+
begin
3881+
return $1::regproc;
3882+
exception when undefined_function or invalid_name then
3883+
raise;
3884+
end;
3885+
$$ language plpgsql;
3886+
-- should not raise a exception
3887+
select * from plpgsql_check_function('test_bug');
3888+
plpgsql_check_function
3889+
------------------------
3890+
(0 rows)
3891+
3892+
create or replace function test_bug(text)
3893+
returns regproc as $$
3894+
begin
3895+
return $1::regproc;
3896+
exception when undefined_function or invalid_name then
3897+
raise notice '%', $1; -- bug
3898+
end;
3899+
$$ language plpgsql;
3900+
select test_bug('kuku'); -- should to fail
3901+
NOTICE: kuku
3902+
ERROR: control reached end of function without RETURN
3903+
CONTEXT: PL/pgSQL function test_bug(text)
3904+
select * from plpgsql_check_function('test_bug');
3905+
plpgsql_check_function
3906+
--------------------------------------------------------------------
3907+
warning extra:2F005:control reached end of function without RETURN
3908+
(1 row)
3909+
3910+
drop function test_bug(text);
3911+
create or replace function test_bug(text)
3912+
returns regproc as $$
3913+
begin
3914+
return $1::regproc;
3915+
exception when undefined_function or invalid_name then
3916+
raise notice '%', $1;
3917+
return NULL;
3918+
end;
3919+
$$ language plpgsql;
3920+
select test_bug('kuku'); -- should be ok
3921+
NOTICE: kuku
3922+
test_bug
3923+
----------
3924+
3925+
(1 row)
3926+
3927+
select * from plpgsql_check_function('test_bug');
3928+
plpgsql_check_function
3929+
------------------------
3930+
(0 rows)
3931+
3932+
drop function test_bug(text);

sql/plpgsql_check_active.sql

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2825,3 +2825,45 @@ select * from dyn_sql_4();
28252825
select * from plpgsql_check_function('dyn_sql_4()');
28262826

28272827
drop function dyn_sql_4();
2828+
2829+
create or replace function test_bug(text)
2830+
returns regproc as $$
2831+
begin
2832+
return $1::regproc;
2833+
exception when undefined_function or invalid_name then
2834+
raise;
2835+
end;
2836+
$$ language plpgsql;
2837+
2838+
-- should not raise a exception
2839+
select * from plpgsql_check_function('test_bug');
2840+
2841+
create or replace function test_bug(text)
2842+
returns regproc as $$
2843+
begin
2844+
return $1::regproc;
2845+
exception when undefined_function or invalid_name then
2846+
raise notice '%', $1; -- bug
2847+
end;
2848+
$$ language plpgsql;
2849+
2850+
select test_bug('kuku'); -- should to fail
2851+
2852+
select * from plpgsql_check_function('test_bug');
2853+
2854+
drop function test_bug(text);
2855+
2856+
create or replace function test_bug(text)
2857+
returns regproc as $$
2858+
begin
2859+
return $1::regproc;
2860+
exception when undefined_function or invalid_name then
2861+
raise notice '%', $1;
2862+
return NULL;
2863+
end;
2864+
$$ language plpgsql;
2865+
2866+
select test_bug('kuku'); -- should be ok
2867+
select * from plpgsql_check_function('test_bug');
2868+
2869+
drop function test_bug(text);

src/stmtwalk.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,8 @@ plpgsql_check_stmt(PLpgSQL_checkstate *cstate, PLpgSQL_stmt *stmt, int *closing,
349349
}
350350
else
351351
{
352+
closing_handlers = *closing;
353+
352354
foreach(l, stmt_block->exceptions->exc_list)
353355
{
354356
PLpgSQL_exception *exception = (PLpgSQL_exception *) lfirst(l);
@@ -362,8 +364,12 @@ plpgsql_check_stmt(PLpgSQL_checkstate *cstate, PLpgSQL_stmt *stmt, int *closing,
362364
-1);
363365
}
364366

365-
if (closing_handlers != *closing)
366-
*closing = PLPGSQL_CHECK_POSSIBLY_CLOSED;
367+
*closing = closing_handlers;
368+
369+
if (closing_handlers == PLPGSQL_CHECK_CLOSED_BY_EXCEPTIONS)
370+
*exceptions = exceptions_transformed;
371+
else
372+
*exceptions = NIL;
367373
}
368374

369375
/*
@@ -1151,6 +1157,7 @@ plpgsql_check_stmt(PLpgSQL_checkstate *cstate, PLpgSQL_stmt *stmt, int *closing,
11511157
stmt_dynexecute->params);
11521158
}
11531159
break;
1160+
11541161
case PLPGSQL_STMT_OPEN:
11551162
{
11561163
PLpgSQL_stmt_open *stmt_open = (PLpgSQL_stmt_open *) stmt;

0 commit comments

Comments
 (0)