Skip to content
Permalink
Browse files

support statements and branch coverage metrics

  • Loading branch information
okbob committed Feb 14, 2020
1 parent 317487d commit c6f9896ead0a0969db23c3062f1fe7ce5f38029b
@@ -2,7 +2,7 @@

MODULE_big = plpgsql_check
OBJS = $(patsubst %.c,%.o,$(wildcard src/*.c))
DATA = plpgsql_check--1.8.sql
DATA = plpgsql_check--1.9.sql
EXTENSION = plpgsql_check

ifndef MAJORVERSION
@@ -468,6 +468,13 @@ The profile per statements (not per line) can be displayed by function plpgsql_p
There are two functions for cleaning stored profiles: `plpgsql_profiler_reset_all()` and
`plpgsql_profiler_reset(regprocedure)`.

## Coverage metrics

plpgsql_check provides two functions:

* `plpgsql_coverage_statements(name)`
* `plpgsql_coverage_branches(name)`

## Note

There is another very good PLpgSQL profiler - https://bitbucket.org/openscg/plprofiler
@@ -7187,3 +7187,77 @@ select * from plpgsql_check_function_tb('fx_testr');

drop function fx_testr();
drop table testr;
-- coverage tests
set plpgsql_check.profiler to on;
create or replace function covtest(int)
returns int as $$
declare a int = $1;
begin
a := a + 1;
if a < 10 then
a := a + 1;
end if;
a := a + 1;
return a;
end;
$$ language plpgsql;
set plpgsql_check.profiler to on;
select covtest(10);
covtest
---------
12
(1 row)

select stmtid, exec_stmts, stmtname from plpgsql_profiler_function_statements_tb('covtest');
stmtid | exec_stmts | stmtname
--------+------------+-----------------
0 | 1 | statement block
1 | 1 | assignment
2 | 1 | IF
3 | 0 | assignment
4 | 1 | assignment
5 | 1 | RETURN
(6 rows)

select plpgsql_coverage_statements('covtest');
plpgsql_coverage_statements
-----------------------------
0.8333333333333334
(1 row)

select plpgsql_coverage_branches('covtest');
plpgsql_coverage_branches
---------------------------
0.5
(1 row)

select covtest(1);
covtest
---------
4
(1 row)

select stmtid, exec_stmts, stmtname from plpgsql_profiler_function_statements_tb('covtest');
stmtid | exec_stmts | stmtname
--------+------------+-----------------
0 | 2 | statement block
1 | 2 | assignment
2 | 2 | IF
3 | 1 | assignment
4 | 2 | assignment
5 | 2 | RETURN
(6 rows)

select plpgsql_coverage_statements('covtest');
plpgsql_coverage_statements
-----------------------------
1
(1 row)

select plpgsql_coverage_branches('covtest');
plpgsql_coverage_branches
---------------------------
1
(1 row)

set plpgsql_check.profiler to on;
@@ -182,3 +182,20 @@ LANGUAGE C STRICT;
CREATE FUNCTION plpgsql_profiler_reset(funcoid regprocedure)
RETURNS void AS 'MODULE_PATHNAME','plpgsql_profiler_reset'
LANGUAGE C STRICT;

CREATE OR REPLACE FUNCTION plpgsql_coverage_statements(funcoid regprocedure)
RETURNS double precision AS 'MODULE_PATHNAME', 'plpgsql_coverage_statements'
LANGUAGE C;

CREATE OR REPLACE FUNCTION plpgsql_coverage_statements(name text)
RETURNS double precision AS 'MODULE_PATHNAME', 'plpgsql_coverage_statements_name'
LANGUAGE C;

CREATE OR REPLACE FUNCTION plpgsql_coverage_branches(funcoid regprocedure)
RETURNS double precision AS 'MODULE_PATHNAME', 'plpgsql_coverage_branches'
LANGUAGE C;

CREATE OR REPLACE FUNCTION plpgsql_coverage_branches(name text)
RETURNS double precision AS 'MODULE_PATHNAME', 'plpgsql_coverage_branches_name'
LANGUAGE C;

@@ -1,6 +1,6 @@
# plpgsql_check extension
comment = 'extended check for plpgsql functions'
default_version = '1.8'
default_version = '1.9'
module_pathname = '$libdir/plpgsql_check'
relocatable = false
requires = 'plpgsql'
@@ -3987,3 +3987,36 @@ select * from plpgsql_check_function_tb('fx_testr');
drop function fx_testr();
drop table testr;

-- coverage tests
set plpgsql_check.profiler to on;

create or replace function covtest(int)
returns int as $$
declare a int = $1;
begin
a := a + 1;
if a < 10 then
a := a + 1;
end if;
a := a + 1;
return a;
end;
$$ language plpgsql;

set plpgsql_check.profiler to on;

select covtest(10);

select stmtid, exec_stmts, stmtname from plpgsql_profiler_function_statements_tb('covtest');

select plpgsql_coverage_statements('covtest');
select plpgsql_coverage_branches('covtest');

select covtest(1);

select stmtid, exec_stmts, stmtname from plpgsql_profiler_function_statements_tb('covtest');

select plpgsql_coverage_statements('covtest');
select plpgsql_coverage_branches('covtest');

set plpgsql_check.profiler to on;
@@ -108,6 +108,13 @@ typedef struct PLpgSQL_checkstate
bool has_mp; /* true, when multiple plan was used */
} PLpgSQL_checkstate;

typedef struct
{
int statements;
int branches;
int executed_statements;
int executed_branches;
} coverage_state;

/*
* function from assign.c
@@ -149,6 +156,8 @@ extern char * plpgsql_check_get_src(HeapTuple procTuple);
/*
* functions from tablefunc.c
*/
extern void plpgsql_check_info_init(plpgsql_check_info *cinfo, Oid fn_oid);


/*
* functions from profiler.c
@@ -259,7 +268,7 @@ extern void plpgsql_check_profiler_stmt_beg(PLpgSQL_execstate *estate, PLpgSQL_s
extern void plpgsql_check_profiler_stmt_end(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt);

extern void plpgsql_check_profiler_show_profile(plpgsql_check_result_info *ri, plpgsql_check_info *cinfo);
extern void plpgsql_check_profiler_show_profile_statements(plpgsql_check_result_info *ri, plpgsql_check_info *cinfo);
extern void plpgsql_check_profiler_show_profile_statements(plpgsql_check_result_info *ri, plpgsql_check_info *cinfo, coverage_state *cs);

extern bool plpgsql_check_profiler;

@@ -68,5 +68,9 @@ extern PGDLLEXPORT Datum plpgsql_profiler_function_tb(PG_FUNCTION_ARGS);
extern PGDLLEXPORT Datum plpgsql_profiler_function_statements_tb(PG_FUNCTION_ARGS);
extern PGDLLEXPORT Datum plpgsql_profiler_function_tb_name(PG_FUNCTION_ARGS);
extern PGDLLEXPORT Datum plpgsql_profiler_function_statements_tb_name(PG_FUNCTION_ARGS);
extern PGDLLEXPORT Datum plpgsql_coverage_statements(PG_FUNCTION_ARGS);
extern PGDLLEXPORT Datum plpgsql_coverage_branches(PG_FUNCTION_ARGS);
extern PGDLLEXPORT Datum plpgsql_coverage_statements_name(PG_FUNCTION_ARGS);
extern PGDLLEXPORT Datum plpgsql_coverage_branches_name(PG_FUNCTION_ARGS);

#endif

0 comments on commit c6f9896

Please sign in to comment.
You can’t perform that action at this time.