Skip to content

Commit

Permalink
fix pldbgapi2 to correctly process empty exception hander - issue #156
Browse files Browse the repository at this point in the history
  • Loading branch information
okbob committed Oct 4, 2023
1 parent 7362365 commit b483c10
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 0 deletions.
41 changes: 41 additions & 0 deletions expected/plpgsql_check_active.out
Original file line number Diff line number Diff line change
Expand Up @@ -8981,3 +8981,44 @@ select * from plpgsql_check_function('fx1');
(9 rows)

drop function fx1;
-- tracer test
set plpgsql_check.enable_tracer to on;
select plpgsql_check_tracer(true);
NOTICE: tracer is active
NOTICE: tracer verbosity is verbose
plpgsql_check_tracer
----------------------
t
(1 row)

create role plpgsql_check_test_role;
DO $$
begin
begin
-- should to fail
create role plpgsql_check_test_role;
exception
when duplicate_object then
-- Role already exists
-- the exception handler is empty (#156)
end;
end;
$$;
NOTICE: #0 ->> start of block inline_code_block (oid=0)
NOTICE: #0.1 2 --> start of statement block
NOTICE: #0.2 3 --> start of statement block
NOTICE: #0.3 5 --> start of SQL statement (query='create role plpgsql_check_test ..')
NOTICE: #0.1 <-- end of SQL statement (elapsed time=0.010 ms) aborted
NOTICE: #0.2 <-- end of statement block (elapsed time=0.010 ms)
NOTICE: #0.3 <-- end of statement block (elapsed time=0.010 ms)
NOTICE: #0 <<- end of block (elapsed time=0.010 ms)
drop role plpgsql_check_test_role;
set plpgsql_check.enable_tracer to off;
select plpgsql_check_tracer(false);
NOTICE: tracer is not active
NOTICE: tracer verbosity is verbose
plpgsql_check_tracer
----------------------
f
(1 row)

41 changes: 41 additions & 0 deletions expected/plpgsql_check_active_1.out
Original file line number Diff line number Diff line change
Expand Up @@ -8984,3 +8984,44 @@ select * from plpgsql_check_function('fx1');
(9 rows)

drop function fx1;
-- tracer test
set plpgsql_check.enable_tracer to on;
select plpgsql_check_tracer(true);
NOTICE: tracer is active
NOTICE: tracer verbosity is verbose
plpgsql_check_tracer
----------------------
t
(1 row)

create role plpgsql_check_test_role;
DO $$
begin
begin
-- should to fail
create role plpgsql_check_test_role;
exception
when duplicate_object then
-- Role already exists
-- the exception handler is empty (#156)
end;
end;
$$;
NOTICE: #0 ->> start of block inline_code_block (oid=0)
NOTICE: #0.1 2 --> start of statement block
NOTICE: #0.2 3 --> start of statement block
NOTICE: #0.3 5 --> start of SQL statement (query='create role plpgsql_check_test ..')
NOTICE: #0.1 <-- end of SQL statement (elapsed time=0.010 ms) aborted
NOTICE: #0.2 <-- end of statement block (elapsed time=0.010 ms)
NOTICE: #0.3 <-- end of statement block (elapsed time=0.010 ms)
NOTICE: #0 <<- end of block (elapsed time=0.010 ms)
drop role plpgsql_check_test_role;
set plpgsql_check.enable_tracer to off;
select plpgsql_check_tracer(false);
NOTICE: tracer is not active
NOTICE: tracer verbosity is verbose
plpgsql_check_tracer
----------------------
f
(1 row)

24 changes: 24 additions & 0 deletions sql/plpgsql_check_active.sql
Original file line number Diff line number Diff line change
Expand Up @@ -5254,3 +5254,27 @@ $$ language plpgsql immutable;
select * from plpgsql_check_function('fx1');

drop function fx1;

-- tracer test
set plpgsql_check.enable_tracer to on;
select plpgsql_check_tracer(true);

create role plpgsql_check_test_role;

DO $$
begin
begin
-- should to fail
create role plpgsql_check_test_role;
exception
when duplicate_object then
-- Role already exists
-- the exception handler is empty (#156)
end;
end;
$$;

drop role plpgsql_check_test_role;

set plpgsql_check.enable_tracer to off;
select plpgsql_check_tracer(false);
23 changes: 23 additions & 0 deletions src/pldbgapi2.c
Original file line number Diff line number Diff line change
Expand Up @@ -1190,6 +1190,29 @@ pldbgapi2_stmt_end(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)

current_fmgr_plpgsql_cache = fcache_plpgsql;

/*
* The exception handler can be empty (see issue #156). In this case
* the statement on stack can be different, then current statemnt, and
* we should to fix stack.
*/
if (stmt->cmd_type == PLPGSQL_STMT_BLOCK)
{
while (fcache_plpgsql->current_stmtid_stack_size > 0 &&
fcache_plpgsql->stmtid_stack[fcache_plpgsql->current_stmtid_stack_size] != stmt->stmtid)
{
int stmtid = fcache_plpgsql->stmtid_stack[fcache_plpgsql->current_stmtid_stack_size];

for (i = 0; i < nplpgsql_plugins2; i++)
{
if (plpgsql_plugins2[i]->stmt_end2_aborted)
(plpgsql_plugins2[i]->stmt_end2_aborted)(estate->func->fn_oid, stmtid,
&fcache_plpgsql->plugin2_info[i]);
}

fcache_plpgsql->current_stmtid_stack_size -= 1;
}
}

if (fcache_plpgsql->stmtid_stack[fcache_plpgsql->current_stmtid_stack_size] != stmt->stmtid)
elog(ERROR, "pldbgapi2 statement call stack is broken");

Expand Down

0 comments on commit b483c10

Please sign in to comment.