Skip to content

Commit dbf2538

Browse files
committed
Fixed failing test and test for Wrapped package.
To test wrapped package we need to have an annotation-like text in it. This way the exception handler `when ex_package_is_wrapped` gets tested after adding source filters
1 parent 4ec9eb5 commit dbf2538

9 files changed

Lines changed: 126 additions & 306 deletions

File tree

examples/developer_examples/RunExampleTestAnnotationsParsingTimeHugePackage.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ set echo off
88
declare
99
l_suites ut_suite_items;
1010
begin
11-
l_suites := ut_suite_manager.configure_execution_by_path(USER||'.TST_PKG_HUGE');
11+
l_suites := ut_suite_manager.configure_execution_by_path(ut_varchar2_list(USER||'.TST_PKG_HUGE'));
1212
end;
1313
/
1414

old_tests/RunAll.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,8 @@ begin
326326
'source/api/ut_runner.pks',
327327
'source/core/coverage',
328328
'source/core/types',
329+
'source/core/annotations/ut_annotation_manager.pkb',
330+
'source/core/annotations/ut_annotation_manager.pks',
329331
'source/core/annotations/ut_annotation_parser.pkb',
330332
'source/core/annotations/ut_annotation_parser.pks',
331333
'source/core/annotations/ut_annotation_cache_manager.pkb',

source/core/annotations/ut_annotation_parser.pkb

Lines changed: 24 additions & 189 deletions
Original file line numberDiff line numberDiff line change
@@ -194,113 +194,6 @@ create or replace package body ut_annotation_parser as
194194
return l_comments;
195195
end extract_and_replace_comments;
196196

197-
function parse_object_annotations(a_source_lines in out nocopy dbms_preprocessor.source_lines_t) return ut_annotations is
198-
l_processed_lines dbms_preprocessor.source_lines_t;
199-
l_source clob;
200-
l_annotations ut_annotations := ut_annotations();
201-
ex_package_is_wrapped exception;
202-
pragma exception_init(ex_package_is_wrapped, -24241);
203-
204-
begin
205-
if a_source_lines.count > 0 then
206-
--convert to post-processed source clob
207-
begin
208-
--get post-processed source
209-
l_processed_lines := sys.dbms_preprocessor.get_post_processed_source(a_source_lines);
210-
--convert to clob
211-
for i in 1..l_processed_lines.count loop
212-
ut_utils.append_to_clob(l_source, replace(l_processed_lines(i), chr(13)||chr(10), chr(10)));
213-
end loop;
214-
--parse annotations
215-
l_annotations := parse_object_annotations(l_source);
216-
dbms_lob.freetemporary(l_source);
217-
exception
218-
when ex_package_is_wrapped then
219-
null;
220-
end;
221-
end if;
222-
a_source_lines.delete;
223-
return l_annotations;
224-
end;
225-
226-
function get_annotated_objects_cursor(a_object_owner varchar2, a_object_type varchar2, a_object_name varchar2) return sys_refcursor is
227-
l_result sys_refcursor;
228-
l_ut_owner varchar2(250) := ut_utils.ut_owner;
229-
l_objects_view varchar2(200) := ut_metadata.get_dba_view('dba_objects');
230-
l_cursor_text long;
231-
begin
232-
l_cursor_text :=
233-
q'[select ]'||l_ut_owner||q'[.ut_annotation_cached_object(
234-
object_owner => o.owner,
235-
object_name => o.object_name,
236-
object_type => o.object_type,
237-
needs_refresh => case when o.last_ddl_time < i.parse_time then 'N' else 'Y' end,
238-
cache_id => i.cache_id
239-
)
240-
from ]'||l_objects_view||q'[ o
241-
left join ut3.ut_annotation_cache_info i
242-
on o.owner = i.object_owner and o.object_name = i.object_name and o.object_type = i.object_type
243-
where o.owner = :a_object_owner
244-
and o.object_type = :a_object_type
245-
and o.status = 'VALID'
246-
and :a_object_name ]'|| case when a_object_name is not null then '= o.object_name' else 'is null' end;
247-
open l_result for l_cursor_text using a_object_owner, a_object_type, a_object_name;
248-
return l_result;
249-
end;
250-
251-
function get_sources_for_annotations(a_object_owner varchar2, a_object_type varchar2, a_object_name varchar2) return sys_refcursor is
252-
l_result sys_refcursor;
253-
l_sources_view varchar2(200) := ut_metadata.get_dba_view('dba_source');
254-
begin
255-
open l_result for
256-
q'[select s.name, s.text
257-
from ]'||l_sources_view||q'[ s
258-
where s.type = :a_object_type
259-
and s.owner = :a_object_owner
260-
and s.name
261-
in (select x.name
262-
from ]'||l_sources_view||q'[ x
263-
where x.type = :a_object_type
264-
and x.owner = :a_object_owner
265-
and x.text like '%--%\%%' escape '\'
266-
and :a_object_name ]'|| case when a_object_name is not null then '= x.name' else 'is null' end || q'[
267-
)
268-
order by name, line]'
269-
using a_object_type, a_object_owner, a_object_type, a_object_owner, a_object_name;
270-
271-
return l_result;
272-
end;
273-
274-
function get_sources_for_annotations(a_object_owner varchar2, a_object_type varchar2, a_objects_to_refresh ut_annotation_cached_objects) return sys_refcursor is
275-
l_result sys_refcursor;
276-
l_sources_view varchar2(200) := ut_metadata.get_dba_view('dba_source');
277-
l_card natural;
278-
begin
279-
l_card := ut_utils.scale_cardinality(cardinality(a_objects_to_refresh));
280-
open l_result for
281-
q'[select /*+ cardinality( r ]'||l_card||q'[ )*/
282-
s.name, s.text
283-
from table(:a_objects_to_refresh) r
284-
join ]'||l_sources_view||q'[ s
285-
on s.name = r.object_name
286-
where s.type = :a_object_type
287-
and s.owner = :a_object_owner
288-
and s.name
289-
in (select /*+ cardinality( x ]'||l_card||q'[ )*/
290-
x.name
291-
from table(:a_objects_to_refresh) t
292-
join ]'||l_sources_view||q'[ x
293-
on x.name = t.object_name
294-
where x.type = :a_object_type
295-
and x.owner = :a_object_owner
296-
and x.text like '%--%\%%' escape '\'
297-
)
298-
order by name, line]'
299-
using a_objects_to_refresh, a_object_type, a_object_owner, a_objects_to_refresh, a_object_type, a_object_owner;
300-
301-
return l_result;
302-
end;
303-
304197
------------------------------------------------------------
305198
--public definitions
306199
------------------------------------------------------------
@@ -339,91 +232,33 @@ create or replace package body ut_annotation_parser as
339232
return l_result;
340233
end parse_object_annotations;
341234

342-
function get_annotated_objects(a_object_owner varchar2, a_object_type varchar2, a_object_name varchar2 := null) return ut_annotated_objects pipelined is
343-
l_info_rows ut_annotation_cached_objects;
344-
l_in_cache ut_annotation_cached_objects;
345-
l_to_parse ut_annotation_cached_objects := ut_annotation_cached_objects();
346-
l_cursor sys_refcursor;
347-
l_results ut_annotated_objects;
348-
l_result ut_annotated_object;
349-
c_object_fetch_limit constant integer := 10;
350-
c_lines_fetch_limit constant integer := 1000;
351-
l_lines dbms_preprocessor.source_lines_t;
352-
l_names dbms_preprocessor.source_lines_t;
353-
l_name varchar2(250) := '''';
354-
l_object_lines dbms_preprocessor.source_lines_t;
355-
begin
356-
--get information about cached objects
357-
l_cursor := get_annotated_objects_cursor(a_object_owner, a_object_type, a_object_name);
358-
fetch l_cursor bulk collect into l_info_rows;
359-
close l_cursor;
360-
361-
--get list of objects in cache
362-
select value(x) bulk collect into l_in_cache from table(l_info_rows) x where x.needs_refresh = 'N';
363-
364-
--if not all in cache, get list of objects to refresh
365-
if l_in_cache.count <= l_info_rows.count then
366-
select value(x) bulk collect into l_to_parse from table(l_info_rows) x where x.needs_refresh = 'Y';
367-
end if;
368-
369-
--pipe annotations from cache
370-
if l_in_cache.count > 0 then
371-
l_cursor := ut_annotation_cache_manager.get_annotations_for_objects(l_in_cache);
372-
loop
373-
fetch l_cursor bulk collect into l_results limit c_object_fetch_limit;
374-
for i in 1 .. l_results.count loop
375-
pipe row (l_results(i));
376-
end loop;
377-
exit when l_cursor%notfound;
378-
end loop;
379-
close l_cursor;
380-
end if;
381-
382-
--if some source needs parsing
383-
if l_to_parse.count > 0 then
384-
--do we need to parse all of sources
385-
if l_in_cache.count = 0 then
386-
l_cursor := get_sources_for_annotations(a_object_owner, a_object_type, a_object_name);
387-
else
388-
-- sources need to be filtered by objects to parse
389-
l_cursor := get_sources_for_annotations(a_object_owner, a_object_type, l_to_parse);
390-
end if;
391-
392-
--remove cached annotations data for objects that will be refreshed
393-
ut_annotation_cache_manager.cleanup_cache(l_to_parse);
394-
395-
loop
396-
fetch l_cursor bulk collect into l_names, l_lines limit c_lines_fetch_limit;
397-
398-
for i in 1 .. l_names.count loop
399-
400-
if l_names(i) != l_name then
401-
l_result := ut_annotated_object(a_object_owner, l_name, a_object_type, parse_object_annotations(l_object_lines));
402-
ut_annotation_cache_manager.update_cache(l_result);
403-
if l_result.annotations.count > 0 then
404-
pipe row (l_result);
405-
end if;
406-
end if;
407-
408-
l_name := l_names(i);
409-
l_object_lines(l_object_lines.count+1) := l_lines(i);
235+
function parse_object_annotations(a_source_lines dbms_preprocessor.source_lines_t) return ut_annotations is
236+
l_processed_lines dbms_preprocessor.source_lines_t;
237+
l_source clob;
238+
l_annotations ut_annotations := ut_annotations();
239+
ex_package_is_wrapped exception;
240+
pragma exception_init(ex_package_is_wrapped, -24241);
410241

242+
begin
243+
if a_source_lines.count > 0 then
244+
--convert to post-processed source clob
245+
begin
246+
--get post-processed source
247+
l_processed_lines := sys.dbms_preprocessor.get_post_processed_source(a_source_lines);
248+
--convert to clob
249+
for i in 1..l_processed_lines.count loop
250+
ut_utils.append_to_clob(l_source, replace(l_processed_lines(i), chr(13)||chr(10), chr(10)));
411251
end loop;
412-
exit when l_cursor%notfound;
413-
414-
end loop;
415-
416-
if l_name is not null then
417-
l_result := ut_annotated_object(a_object_owner, l_name, a_object_type, parse_object_annotations(l_object_lines));
418-
ut_annotation_cache_manager.update_cache(l_result);
419-
if l_result.annotations.count > 0 then
420-
pipe row (l_result);
421-
end if;
422-
end if;
423-
424-
close l_cursor;
252+
dbms_output.put_line(l_source);
253+
--parse annotations
254+
l_annotations := parse_object_annotations(l_source);
255+
dbms_lob.freetemporary(l_source);
256+
exception
257+
when ex_package_is_wrapped then
258+
null;
259+
end;
425260
end if;
426-
261+
return l_annotations;
427262
end;
428263

429264
end ut_annotation_parser;

source/core/annotations/ut_annotation_parser.pks

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,28 @@ create or replace package ut_annotation_parser authid current_user as
1717
*/
1818

1919
/**
20-
* Reads database source code, parses it and returns annotations
20+
* Parses the source passed as input parameter and returns annotations
2121
*/
2222

2323
/**
24-
* Parses source code and converts it to annotations
24+
* Runs the source lines through dbms_preprocessor to remove lines that were not compiled (conditional compilation)
25+
* Parses the processed source code and converts it to annotations
2526
*
26-
* @param a_source clob containing source code to be parsed
27+
* @param a_source_lines ordered lines of source code to be parsed
2728
* @return array containing annotations
2829
*/
29-
function parse_object_annotations(a_source clob) return ut_annotations;
30+
function parse_object_annotations(a_source_lines dbms_preprocessor.source_lines_t) return ut_annotations;
31+
3032

3133
/**
32-
* Parses an object or all objects of a specified type for database schema.
33-
* Pesults are returned in a form of a pipelined function.
34-
* @param a_object_owner schema name to be parsed
35-
* @param a_object_type type of object to be parsed
36-
* @param a_object_name name of object to be parsed - optional
37-
* @return array containing annotated objects along with annotations for each object (nested)
34+
*
35+
* @private
36+
* Parses source code and converts it to annotations
37+
*
38+
* @param a_source_lines ordered lines of source code to be parsed
39+
* @return array containing annotations
3840
*/
39-
function get_annotated_objects(a_object_owner varchar2, a_object_type varchar2, a_object_name varchar2 := null) return ut_annotated_objects pipelined;
41+
function parse_object_annotations(a_source clob) return ut_annotations;
4042

4143
end ut_annotation_parser;
4244
/

source/core/ut_suite_manager.pkb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ create or replace package body ut_suite_manager is
280280
execute immediate
281281
q'[select value(x)
282282
from table(
283-
]'||ut_utils.ut_owner||q'[.ut_annotation_parser.get_annotated_objects(:a_owner_name, 'PACKAGE')
283+
]'||ut_utils.ut_owner||q'[.ut_annotation_manager.get_annotated_objects(:a_owner_name, 'PACKAGE')
284284
)x ]'
285285
bulk collect into l_annotated_objects using a_owner_name;
286286
for i in 1 .. l_annotated_objects.count loop

source/install.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ alter session set plsql_warnings = 'ENABLE:ALL', 'DISABLE:(5004,5018,6000,6001,6
8888
@@install_component.sql 'core/annotations/ut_annotation_cache_manager.pkb'
8989
@@install_component.sql 'core/annotations/ut_annotation_parser.pks'
9090
@@install_component.sql 'core/annotations/ut_annotation_parser.pkb'
91+
@@install_component.sql 'core/annotations/ut_annotation_manager.pks'
92+
@@install_component.sql 'core/annotations/ut_annotation_manager.pkb'
9193

9294
--suite manager
9395
@@install_component.sql 'core/ut_suite_manager.pks'

source/uninstall.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ drop type ut_data_value force;
172172

173173
drop table ut_cursor_data;
174174

175+
drop package ut_annotation_manager;
176+
175177
drop package ut_annotation_parser;
176178

177179
drop package ut_annotation_cache_manager;

0 commit comments

Comments
 (0)