@@ -36,32 +36,39 @@ create or replace package body ut_coverage is
3636 end;
3737
3838 function get_cov_sources_sql(a_coverage_options ut_coverage_options) return varchar2 is
39- l_result varchar2(32767);
40- l_full_name varchar2(100);
41- l_view_name varchar2(200) := ut_metadata.get_source_view_name();
39+ l_result varchar2(32767);
40+ l_full_name varchar2(32767);
41+ l_mappings varchar2(32767);
42+ l_filters varchar2(32767);
43+ l_mappings_cardinality integer := 0;
4244 begin
43- if a_coverage_options.file_mappings is not null and a_coverage_options.file_mappings.count > 0 then
44- l_full_name := 'f.file_name';
45- else
46- l_full_name := 'lower(s.owner||''.''||s.name)';
47- end if;
48- l_result := '
49- select full_name, owner, name, line, to_be_skipped, text
50- from (
51- select '||l_full_name||q'[ as full_name,
45+ l_result := q'[
46+ with sources as (
47+ select /*+ cardinality(f {mappings_cardinality}) */
48+ {l_full_name} as full_name, s.owner, s.name, s.line, s.text
49+ from {sources_view} s {file_mappings}
50+ where s.type in ('PACKAGE BODY', 'TYPE BODY', 'PROCEDURE', 'FUNCTION')
51+ {filters}
52+ ),
53+ trigger_sources as (
54+ select /*+ cardinality(f {mappings_cardinality}) */
55+ {l_full_name} as full_name,
5256 s.owner,
5357 s.name,
54- s.line -
55- coalesce(
56- case when type!='TRIGGER' then 0 end,
57- (select min(t.line) - 1
58- from ]'||l_view_name||q'[ t
58+ s.line
59+ - (select min(t.line) - 1
60+ from {sources_view} t
5961 where t.owner = s.owner and t.type = s.type and t.name = s.name
60- and regexp_like( t.text, '[A-Za-z0-9$#_]*(begin|declare|compound).*','i'))
61- ) as line,
62- s.text, ]';
63- l_result := l_result ||
64- q'[case
62+ and regexp_like( t.text, '[A-Za-z0-9$#_]*(begin|declare|compound).*', 'i' )
63+ ) as line,
64+ s.text
65+ from {sources_view} s {file_mappings}
66+ where s.type = 'TRIGGER'
67+ {filters}
68+ ),
69+ coverage_sources as (
70+ select full_name, owner, name, line, text,
71+ case
6572 when
6673 -- to avoid execution of regexp_like on every line
6774 -- first do a rough check for existence of search pattern keyword
@@ -76,31 +83,107 @@ create or replace package body ut_coverage is
7683 '^([\t ]*(((not)?\s*(overriding|final|instantiable)[\t ]*)*(static|constructor|member)?[\t ]*(procedure|function)|package([\t ]+body)|begin|end([\t ]+\S+)*[ \t]*;))', 'i'
7784 )
7885 then 'Y'
79- end as to_be_skipped ]';
86+ end as to_be_skipped
87+ from (
88+ select * from sources
89+ union all
90+ select * from trigger_sources
91+ ) s
92+ )
93+ select full_name, owner, name, line, to_be_skipped, text
94+ from coverage_sources s
95+ --Exclude calls to utPLSQL framework, Unit Test packages and objects from a_exclude_list parameter of coverage reporter
96+ where (s.owner, s.name) not in ( select el.owner, el.name from table(:l_skipped_objects) el )
97+ and line > 0
98+ ]';
8099
81- l_result := l_result ||' from '||l_view_name||q'[ s]';
82-
83100 if a_coverage_options.file_mappings is not empty then
84- l_result := l_result || '
101+ l_mappings_cardinality := ut_utils.scale_cardinality(cardinality(a_coverage_options.file_mappings));
102+ l_full_name := 'f.file_name';
103+ l_mappings := '
85104 join table(:file_mappings) f
86105 on s.name = f.object_name
87106 and s.type = f.object_type
88- and s.owner = f.object_owner
89- where 1 = 1';
90- elsif a_coverage_options.include_objects is not empty then
91- l_result := l_result || '
92- where (s.owner, s.name) in (select il.owner, il.name from table(:include_objects) il)';
107+ and s.owner = f.object_owner';
93108 else
94- l_result := l_result || '
95- where s.owner in (select upper(t.column_value) from table(:l_schema_names) t)';
109+ l_full_name := q'[lower(s.owner||'.'||s.name)]';
110+ l_filters := case
111+ when a_coverage_options.include_objects is not empty then '
112+ and (s.owner, s.name) in (select il.owner, il.name from table(:include_objects) il)'
113+ else '
114+ and s.owner in (select upper(t.column_value) from table(:l_schema_names) t)'
115+ end;
96116 end if;
97- l_result := l_result || q'[
98- and s.type not in ('PACKAGE', 'TYPE', 'JAVA SOURCE')
99- --Exclude calls to utPLSQL framework, Unit Test packages and objects from a_exclude_list parameter of coverage reporter
100- and (s.owner, s.name) not in (select el.owner, el.name from table(:l_skipped_objects) el)
101- )
102- where line > 0]';
117+
118+ l_result := replace(l_result, '{sources_view}', ut_metadata.get_source_view_name());
119+ l_result := replace(l_result, '{l_full_name}', l_full_name);
120+ l_result := replace(l_result, '{file_mappings}', l_mappings);
121+ l_result := replace(l_result, '{filters}', l_filters);
122+ l_result := replace(l_result, '{mappings_cardinality}', l_mappings_cardinality);
123+
103124 return l_result;
125+
126+ -- if a_coverage_options.file_mappings is not null and a_coverage_options.file_mappings.count > 0 then
127+ -- l_full_name := 'f.file_name';
128+ -- else
129+ -- l_full_name := 'lower(s.owner||''.''||s.name)';
130+ -- end if;
131+ -- l_result := '
132+ -- select full_name, owner, name, line, to_be_skipped, text
133+ -- from (
134+ -- select '||l_full_name||q'[ as full_name,
135+ -- s.owner,
136+ -- s.name,
137+ -- s.line -
138+ -- coalesce(
139+ -- case when type!='TRIGGER' then 0 end,
140+ -- (select min(t.line) - 1
141+ -- from ]'||ut_metadata.get_source_view_name()||q'[ t
142+ -- where t.owner = s.owner and t.type = s.type and t.name = s.name
143+ -- and regexp_like( t.text, '[A-Za-z0-9$#_]*(begin|declare|compound).*','i'))
144+ -- ) as line,
145+ -- s.text, ]';
146+ -- l_result := l_result ||
147+ -- q'[case
148+ -- when
149+ -- -- to avoid execution of regexp_like on every line
150+ -- -- first do a rough check for existence of search pattern keyword
151+ -- (lower(s.text) like '%procedure%'
152+ -- or lower(s.text) like '%function%'
153+ -- or lower(s.text) like '%begin%'
154+ -- or lower(s.text) like '%end%'
155+ -- or lower(s.text) like '%package%'
156+ -- ) and
157+ -- regexp_like(
158+ -- s.text,
159+ -- '^([\t ]*(((not)?\s*(overriding|final|instantiable)[\t ]*)*(static|constructor|member)?[\t ]*(procedure|function)|package([\t ]+body)|begin|end([\t ]+\S+)*[ \t]*;))', 'i'
160+ -- )
161+ -- then 'Y'
162+ -- end as to_be_skipped ]';
163+ --
164+ -- l_result := l_result ||' from '||ut_metadata.get_source_view_name()||q'[ s]';
165+ --
166+ -- if a_coverage_options.file_mappings is not empty then
167+ -- l_result := l_result || '
168+ -- join table(:file_mappings) f
169+ -- on s.name = f.object_name
170+ -- and s.type = f.object_type
171+ -- and s.owner = f.object_owner
172+ -- where 1 = 1';
173+ -- elsif a_coverage_options.include_objects is not empty then
174+ -- l_result := l_result || '
175+ -- where (s.owner, s.name) in (select il.owner, il.name from table(:include_objects) il)';
176+ -- else
177+ -- l_result := l_result || '
178+ -- where s.owner in (select upper(t.column_value) from table(:l_schema_names) t)';
179+ -- end if;
180+ -- l_result := l_result || q'[
181+ -- and s.type not in ('PACKAGE', 'TYPE', 'JAVA SOURCE')
182+ -- --Exclude calls to utPLSQL framework, Unit Test packages and objects from a_exclude_list parameter of coverage reporter
183+ -- and (s.owner, s.name) not in (select el.owner, el.name from table(:l_skipped_objects) el)
184+ -- )
185+ -- where line > 0]';
186+ -- return l_result;
104187 end;
105188
106189 function get_cov_sources_cursor(a_coverage_options in ut_coverage_options,a_sql in varchar2) return sys_refcursor is
@@ -120,11 +203,11 @@ create or replace package body ut_coverage is
120203 raise_application_error(-20542, 'Possible SQL injection detected. a_sql parameter does not match valid pattern "' || l_valid_pattern || '".');
121204 end if;
122205 if a_coverage_options.file_mappings is not empty then
123- open l_cursor for l_sql using a_coverage_options.file_mappings, l_skip_objects;
206+ open l_cursor for l_sql using a_coverage_options.file_mappings, a_coverage_options.file_mappings, l_skip_objects;
124207 elsif a_coverage_options.include_objects is not empty then
125- open l_cursor for l_sql using a_coverage_options.include_objects, l_skip_objects;
208+ open l_cursor for l_sql using a_coverage_options.include_objects, a_coverage_options.include_objects, l_skip_objects;
126209 else
127- open l_cursor for l_sql using a_coverage_options.schema_names, l_skip_objects;
210+ open l_cursor for l_sql using a_coverage_options.schema_names, a_coverage_options.schema_names, l_skip_objects;
128211 end if;
129212 return l_cursor;
130213 end;
0 commit comments