@@ -19,6 +19,70 @@ create or replace package body ut_suite_manager is
1919 gc_suitpath_error_message constant varchar2(100) := 'Suitepath exceeds 1000 CHAR on: ';
2020 gc_tag_errmsg constant integer := 450;
2121
22+ gc_get_cache_suite_sql constant varchar2(32767) :=
23+ q'[with
24+ suite_items as (
25+ select /*+ cardinality(c 100) */ c.*
26+ from {:owner:}.ut_suite_cache c
27+ where 1 = 1 {:object_list:}
28+ and c.object_owner = '{:object_owner:}'
29+ and ( {:path:}
30+ and {:object_name:}
31+ and {:procedure_name:}
32+ )
33+ )
34+ ),
35+ {:tags:},
36+ suitepaths as (
37+ select distinct substr(path,1,instr(path,'.',-1)-1) as suitepath,
38+ path,
39+ object_owner
40+ from {:suite_item_name:}
41+ where self_type = 'UT_SUITE'
42+ ),
43+ gen as (
44+ select rownum as pos
45+ from xmltable('1 to 20')
46+ ),
47+ suitepath_part AS (
48+ select distinct
49+ substr(b.suitepath, 1, instr(b.suitepath || '.', '.', 1, g.pos) -1) as path,
50+ object_owner
51+ from suitepaths b
52+ join gen g
53+ on g.pos <= regexp_count(b.suitepath, '\w+')
54+ ),
55+ logical_suite_data as (
56+ select 'UT_LOGICAL_SUITE' as self_type, p.path, p.object_owner,
57+ upper( substr(p.path, instr( p.path, '.', -1 ) + 1 ) ) as object_name,
58+ cast(null as {:owner:}.ut_executables) as x,
59+ cast(null as {:owner:}.ut_integer_list) as y,
60+ cast(null as {:owner:}.ut_executable_test) as z
61+ from suitepath_part p
62+ where p.path
63+ not in (select s.path from suitepaths s)
64+ ),
65+ logical_suites as (
66+ select to_number(null) as id, s.self_type, s.path, s.object_owner, s.object_name,
67+ s.object_name as name, null as line_no, null as parse_time,
68+ null as description, null as rollback_type, 0 as disabled_flag,
69+ {:owner:}.ut_varchar2_rows() as warnings,
70+ s.x as before_all_list, s.x as after_all_list,
71+ s.x as before_each_list, s.x as before_test_list,
72+ s.x as after_each_list, s.x as after_test_list,
73+ s.y as expected_error_codes, null as test_tags,
74+ s.z as item
75+ from logical_suite_data s
76+ ),
77+ items as (
78+ select * from {:suite_item_name:}
79+ union all
80+ select * from logical_suites
81+ )
82+ select c.*
83+ from items c
84+ order by c.object_owner,{:random_seed:}]';
85+
2286 type t_path_item is record (
2387 object_name varchar2(250),
2488 procedure_name varchar2(250),
@@ -330,7 +394,7 @@ create or replace package body ut_suite_manager is
330394 end loop;
331395 close a_suite_data_cursor;
332396 end reconstruct_from_cache;
333-
397+
334398 function get_missing_objects(a_object_owner varchar2) return ut_varchar2_rows is
335399 l_rows sys_refcursor;
336400 l_ut_owner varchar2(250) := ut_utils.ut_owner;
@@ -356,66 +420,46 @@ create or replace package body ut_suite_manager is
356420 return l_result;
357421 end;
358422
359- function get_cached_suite_data(
360- a_object_owner varchar2,
361- a_path varchar2 := null,
362- a_object_name varchar2 := null,
363- a_procedure_name varchar2 := null,
364- a_skip_all_objects boolean := false,
365- a_random_seed positive,
366- a_tags ut_varchar2_rows := null
367- ) return t_cached_suites_cursor is
368- l_path varchar2( 4000 );
369- l_result sys_refcursor;
370- l_ut_owner varchar2(250) := ut_utils.ut_owner;
371- l_sql varchar2(32767);
372- l_suite_item_name varchar2(20);
373- l_tags ut_varchar2_rows := coalesce(a_tags,ut_varchar2_rows());
423+ function get_object_names_sql(a_skip_all_objects boolean ) return varchar2 is
374424 begin
375- if a_path is null and a_object_name is not null then
376- execute immediate 'select min(path)
377- from '||l_ut_owner||q'[.ut_suite_cache
378- where object_owner = :a_object_owner
379- and object_name = :a_object_name
380- and name = nvl(:a_procedure_name, name)]'
381- into l_path using upper(a_object_owner), upper(a_object_name), upper(a_procedure_name);
382- else
383- l_path := lower( a_path );
384- end if;
385- l_suite_item_name := case when l_tags.count > 0 then 'suite_items_tags' else 'suite_items' end;
386-
387- l_sql :=
388- q'[with
389- suite_items as (
390- select /*+ cardinality(c 100) */ c.*
391- from ]'||l_ut_owner||q'[.ut_suite_cache c
392- where 1 = 1 ]'||case when not a_skip_all_objects then q'[
425+ return case when not a_skip_all_objects then q'[
393426 and exists
394427 ( select 1
395428 from all_objects a
396429 where a.object_name = c.object_name
397- and a.owner = ']'||upper(a_object_owner)||q'[ '
430+ and a.owner = '{:object_owner:} '
398431 and a.owner = c.object_owner
399432 and a.object_type = 'PACKAGE'
400- )]' end ||q'[
401- and c.object_owner = ']'||upper(a_object_owner)||q'['
402- and ( ]' || case when l_path is not null then q'[
433+ )]' else null end;
434+ end;
435+
436+ function get_path_sql(a_path in varchar2) return varchar2 is
437+ begin
438+ return case when a_path is not null then q'[
403439 :l_path||'.' like c.path || '.%' /*all children and self*/
404440 or ( c.path||'.' like :l_path || '.%' --all parents
405441 ]'
406- else ' :l_path is null and ( :l_path is null ' end
407- || case when a_object_name is not null
408- then 'and c.object_name = :a_object_name '
409- else 'and :a_object_name is null' end ||'
410- '|| case when a_procedure_name is not null
411- then 'and c.name = :a_procedure_name'
412- else 'and :a_procedure_name is null' end ||q'[
413- )
414- )
415- ),]'
416- ||case when l_tags.count > 0 then
417- q'[
418- filter_tags as (
442+ else ' :l_path is null and ( :l_path is null ' end;
443+ end;
444+
445+ function get_object_name_sql(a_object_name in varchar2) return varchar2 is
446+ begin
447+ return case when a_object_name is not null
448+ then ' c.object_name = :a_object_name '
449+ else ' :a_object_name is null' end;
450+ end;
451+
452+ function get_procedure_name_sql(a_procedure_name in varchar2) return varchar2 is
453+ begin
454+ return case when a_procedure_name is not null
455+ then ' c.name = :a_procedure_name'
456+ else ' :a_procedure_name is null' end;
457+ end;
458+
459+ function get_tags_sql(a_tags_count in integer) return varchar2 is
460+ begin
461+ return case when a_tags_count > 0 then
462+ q'[filter_tags as (
419463 select c.*
420464 from suite_items c
421465 where c.tags multiset intersect :a_tag_list is not empty
@@ -426,60 +470,15 @@ create or replace package body ut_suite_manager is
426470 t.path||'.' like c.path || '.%' /*all children and self*/
427471 or c.path||'.' like t.path || '.%' --all parents
428472 )
429- ), ]'
473+ )]'
430474 else
431- q'[dummy as (select 'x' from dual where :a_tag_list is null ),]'
432- end||
433- q'[ suitepaths as (
434- select distinct substr(path,1,instr(path,'.',-1)-1) as suitepath,
435- path,
436- object_owner
437- from ]'||l_suite_item_name||q'[
438- where self_type = 'UT_SUITE'
439- ),
440- gen as (
441- select rownum as pos
442- from xmltable('1 to 20')
443- ),
444- suitepath_part AS (
445- select distinct
446- substr(b.suitepath, 1, instr(b.suitepath || '.', '.', 1, g.pos) -1) as path,
447- object_owner
448- from suitepaths b
449- join gen g
450- on g.pos <= regexp_count(b.suitepath, '\w+')
451- ),
452- logical_suite_data as (
453- select 'UT_LOGICAL_SUITE' as self_type, p.path, p.object_owner,
454- upper( substr(p.path, instr( p.path, '.', -1 ) + 1 ) ) as object_name,
455- cast(null as ]'||l_ut_owner||q'[.ut_executables) as x,
456- cast(null as ]'||l_ut_owner||q'[.ut_integer_list) as y,
457- cast(null as ]'||l_ut_owner||q'[.ut_executable_test) as z
458- from suitepath_part p
459- where p.path
460- not in (select s.path from suitepaths s)
461- ),
462- logical_suites as (
463- select to_number(null) as id, s.self_type, s.path, s.object_owner, s.object_name,
464- s.object_name as name, null as line_no, null as parse_time,
465- null as description, null as rollback_type, 0 as disabled_flag,
466- ]'||l_ut_owner||q'[.ut_varchar2_rows() as warnings,
467- s.x as before_all_list, s.x as after_all_list,
468- s.x as before_each_list, s.x as before_test_list,
469- s.x as after_each_list, s.x as after_test_list,
470- s.y as expected_error_codes, null as test_tags,
471- s.z as item
472- from logical_suite_data s
473- ),
474- items as (
475- select * from ]'||l_suite_item_name||q'[
476- union all
477- select * from logical_suites
478- )
479- select c.*
480- from items c
481- order by c.object_owner,]'||
482- case
475+ q'[dummy as (select 'x' from dual where :a_tag_list is null )]'
476+ end;
477+ end;
478+
479+ function get_random_seed_sql(a_random_seed positive) return varchar2 is
480+ begin
481+ return case
483482 when a_random_seed is null then q'[
484483 replace(
485484 case
@@ -492,10 +491,51 @@ create or replace package body ut_suite_manager is
492491 c.line_no,
493492 :a_random_seed]'
494493 else
495- l_ut_owner||' .ut_annotation_manager.hash_suite_path(
494+ ' {:owner:} .ut_annotation_manager.hash_suite_path(
496495 c.path, :a_random_seed
497496 ) desc nulls last'
498- end;
497+ end;
498+ end;
499+
500+ function get_cached_suite_data(
501+ a_object_owner varchar2,
502+ a_path varchar2 := null,
503+ a_object_name varchar2 := null,
504+ a_procedure_name varchar2 := null,
505+ a_skip_all_objects boolean := false,
506+ a_random_seed positive,
507+ a_tags ut_varchar2_rows := null
508+ ) return t_cached_suites_cursor is
509+ l_path varchar2( 4000 );
510+ l_result sys_refcursor;
511+ l_ut_owner varchar2(250) := ut_utils.ut_owner;
512+ l_sql varchar2(32767);
513+ l_suite_item_name varchar2(20);
514+ l_tags ut_varchar2_rows := coalesce(a_tags,ut_varchar2_rows());
515+ begin
516+ if a_path is null and a_object_name is not null then
517+ execute immediate 'select min(path)
518+ from '||l_ut_owner||q'[.ut_suite_cache
519+ where object_owner = :a_object_owner
520+ and object_name = :a_object_name
521+ and name = nvl(:a_procedure_name, name)]'
522+ into l_path using upper(a_object_owner), upper(a_object_name), upper(a_procedure_name);
523+ else
524+ l_path := lower( a_path );
525+ end if;
526+ l_suite_item_name := case when l_tags.count > 0 then 'suite_items_tags' else 'suite_items' end;
527+
528+ l_sql := gc_get_cache_suite_sql;
529+ l_sql := replace(l_sql,'{:suite_item_name:}',l_suite_item_name);
530+ l_sql := replace(l_sql,'{:object_list:}',get_object_names_sql(a_skip_all_objects));
531+ l_sql := replace(l_sql,'{:object_owner:}',upper(a_object_owner));
532+ l_sql := replace(l_sql,'{:path:}',get_path_sql(l_path));
533+ l_sql := replace(l_sql,'{:object_name:}',get_object_name_sql(a_object_name));
534+ l_sql := replace(l_sql,'{:procedure_name:}',get_procedure_name_sql(a_procedure_name));
535+ l_sql := replace(l_sql,'{:tags:}',get_tags_sql(l_tags.count));
536+ l_sql := replace(l_sql,'{:random_seed:}',get_random_seed_sql(a_random_seed));
537+ l_sql := replace(l_sql,'{:owner:}',l_ut_owner);
538+
499539 open l_result for l_sql using l_path, l_path, upper(a_object_name), upper(a_procedure_name), l_tags, a_random_seed;
500540 return l_result;
501541 end;
0 commit comments