Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7bb5533

Browse files
committed
Fixing issue with null object and counts
1 parent 061895a commit 7bb5533

14 files changed

Lines changed: 334 additions & 88 deletions

source/core/ut_metadata.pkb

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,25 @@ create or replace package body ut_metadata as
3030
l_object_number number;
3131
begin
3232
l_name := form_name(a_owner, a_object, a_procedure_name);
33+
do_resolve(l_name,l_context,a_owner,a_object, a_procedure_name);
34+
end do_resolve;
3335

34-
dbms_utility.name_resolve(name => l_name
35-
,context => l_context
36+
procedure do_resolve(a_fully_qualified_name in varchar2,a_context in integer,a_owner out nocopy varchar2, a_object out nocopy varchar2,
37+
a_procedure_name out nocopy varchar2) is
38+
l_dblink varchar2(200);
39+
l_part1_type number;
40+
l_object_number number;
41+
begin
42+
dbms_utility.name_resolve(name => a_fully_qualified_name
43+
,context => a_context
3644
,schema => a_owner
3745
,part1 => a_object
3846
,part2 => a_procedure_name
3947
,dblink => l_dblink
4048
,part1_type => l_part1_type
4149
,object_number => l_object_number);
42-
43-
end do_resolve;
44-
50+
end;
51+
4552
function form_name(a_owner_name varchar2, a_object varchar2, a_subprogram varchar2 default null) return varchar2 is
4653
l_name varchar2(200);
4754
begin
@@ -264,5 +271,18 @@ create or replace package body ut_metadata as
264271
return l_anytype;
265272
end;
266273

274+
function get_collection_element(a_anydata in anydata) return varchar2
275+
is
276+
l_anytype anytype;
277+
l_nested_type t_anytype_members_rec;
278+
l_type_code integer;
279+
begin
280+
l_type_code := a_anydata.gettype(l_anytype);
281+
if is_collection(l_type_code) then
282+
l_nested_type := get_anytype_members_info(ut_metadata.get_attr_elem_info(l_anytype).attr_elt_type);
283+
end if;
284+
return l_nested_type.schema_name || '.' ||l_nested_type.type_name;
285+
end;
286+
267287
end;
268288
/

source/core/ut_metadata.pks

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ create or replace package ut_metadata authid current_user as
7070
*/
7171
procedure do_resolve(a_owner in out nocopy varchar2, a_object in out nocopy varchar2, a_procedure_name in out nocopy varchar2);
7272

73+
/**
74+
* Resolves single string [owner.]object[.procedure] using dbms_utility.name_resolve and returns parts [owner] [object] [procedure]
75+
*/
76+
procedure do_resolve(a_fully_qualified_name in varchar2,a_context in integer,a_owner out nocopy varchar2,
77+
a_object out nocopy varchar2, a_procedure_name out nocopy varchar2);
78+
7379
/**
7480
* Return the text of the source line for a given object (body). It excludes package spec and type spec
7581
*/
@@ -140,6 +146,11 @@ create or replace package ut_metadata authid current_user as
140146
* Returns ANYTYPE descriptor of an object type
141147
*/
142148
function get_user_defined_type(a_owner varchar2, a_type_name varchar2) return anytype;
143-
149+
150+
/**
151+
* Return fully qualified name of the object from collection, if not collection returns null
152+
*/
153+
function get_collection_element(a_anydata in anydata) return varchar2;
154+
144155
end ut_metadata;
145156
/

source/expectations/data_values/ut_compound_data_helper.pkb

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,7 @@ create or replace package body ut_compound_data_helper is
391391
end if;
392392

393393
l_compare_sql := replace(l_compare_sql,'{:where_condition:}',l_where_stmt);
394+
394395
return l_compare_sql;
395396
end;
396397

@@ -407,7 +408,8 @@ create or replace package body ut_compound_data_helper is
407408
function get_rows_diff_by_sql(
408409
a_act_cursor_info ut_cursor_column_tab, a_exp_cursor_info ut_cursor_column_tab,
409410
a_expected_dataset_guid raw, a_actual_dataset_guid raw, a_diff_id raw,
410-
a_join_by_list ut_varchar2_list, a_unordered boolean, a_enforce_column_order boolean := false
411+
a_join_by_list ut_varchar2_list, a_unordered boolean, a_enforce_column_order boolean := false,
412+
a_extract_path varchar2
411413
) return tt_row_diffs is
412414
l_act_extract_xpath varchar2(32767):= ut_utils.to_xpath(get_column_extract_path(a_act_cursor_info));
413415
l_exp_extract_xpath varchar2(32767):= ut_utils.to_xpath(get_column_extract_path(a_exp_cursor_info));
@@ -429,7 +431,7 @@ create or replace package body ut_compound_data_helper is
429431
where diff_id = :diff_id
430432
and ucd.exp_data_id = :self_guid
431433
) i,
432-
table( xmlsequence( extract(i.exp_item_data,'/*') ) ) s
434+
table( xmlsequence( extract(i.exp_item_data,:extract_path) ) ) s
433435
),
434436
act as (
435437
select
@@ -444,7 +446,7 @@ create or replace package body ut_compound_data_helper is
444446
where diff_id = :diff_id
445447
and ucd.act_data_id = :other_guid
446448
) i,
447-
table( xmlsequence( extract(i.act_item_data,'/*') ) ) s
449+
table( xmlsequence( extract(i.act_item_data,:extract_path) ) ) s
448450
)
449451
select rn, diff_type, diffed_row, pk_value pk_value
450452
from (
@@ -520,16 +522,15 @@ create or replace package body ut_compound_data_helper is
520522
case when final_order = 1 then to_char(rnk) else col_name end
521523
]'
522524
end;
523-
524525
execute immediate l_sql
525526
bulk collect into l_results
526-
using l_exp_extract_xpath, l_join_xpath, a_diff_id, a_expected_dataset_guid,
527-
l_act_extract_xpath, l_join_xpath, a_diff_id, a_actual_dataset_guid,
528-
l_join_xpath, l_join_xpath, a_diff_id;
529-
527+
using l_exp_extract_xpath, l_join_xpath, a_diff_id, a_expected_dataset_guid,a_extract_path,
528+
l_act_extract_xpath, l_join_xpath, a_diff_id, a_actual_dataset_guid,a_extract_path,
529+
l_join_xpath, l_join_xpath, a_diff_id;
530530
return l_results;
531531
end;
532532

533+
--TODO : removal
533534
function get_rows_diff(
534535
a_expected_dataset_guid raw, a_actual_dataset_guid raw, a_diff_id raw,
535536
a_max_rows integer, a_exclude_xpath varchar2, a_include_xpath varchar2

source/expectations/data_values/ut_compound_data_helper.pks

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ create or replace package ut_compound_data_helper authid definer is
6868
function get_rows_diff_by_sql(
6969
a_act_cursor_info ut_cursor_column_tab,a_exp_cursor_info ut_cursor_column_tab,
7070
a_expected_dataset_guid raw, a_actual_dataset_guid raw, a_diff_id raw,
71-
a_join_by_list ut_varchar2_list, a_unordered boolean, a_enforce_column_order boolean := false
71+
a_join_by_list ut_varchar2_list, a_unordered boolean, a_enforce_column_order boolean := false,
72+
a_extract_path varchar2
7273
) return tt_row_diffs;
7374

7475
subtype t_hash is raw(128);

source/expectations/data_values/ut_compound_data_value.tps

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,12 @@ create or replace type ut_compound_data_value force under ut_data_value(
3434
* Holds unique id for retrieving the data from ut_compound_data_tmp temp table
3535
*/
3636
data_id raw(16),
37-
37+
38+
/**
39+
* Holds name for the type of compound
40+
*/
41+
compound_type varchar2(50),
42+
3843
overriding member function get_object_info return varchar2,
3944
overriding member function is_null return boolean,
4045
overriding member function is_diffable return boolean,

source/expectations/data_values/ut_data_value_anydata.tpb

Lines changed: 95 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -15,69 +15,118 @@ create or replace type body ut_data_value_anydata as
1515
See the License for the specific language governing permissions and
1616
limitations under the License.
1717
*/
18-
member procedure init(self in out nocopy ut_data_value_anydata, a_value anydata) is
19-
l_query sys_refcursor;
20-
l_ctx number;
21-
l_ut_owner varchar2(250) := ut_utils.ut_owner;
22-
cursor_not_open exception;
23-
l_cursor_number number;
24-
l_anydata_type varchar2(100) := get_instance(a_value);
25-
l_element_count number;
18+
19+
member function is_null(a_value in anydata) return number is
20+
l_result integer := 0;
21+
l_anydata_sql varchar2(4000);
22+
begin
23+
if a_value is not null and self.compound_type = 'object' then
24+
l_anydata_sql := '
25+
declare
26+
l_data '||self.data_type||';
27+
l_value anydata := :a_value;
28+
l_status integer;
29+
begin
30+
l_status := l_value.get'||self.compound_type||'(l_data);
31+
:l_data_is_null := case when l_data is null then 1 else 0 end;
32+
end;';
33+
execute immediate l_anydata_sql using in a_value, out l_result;
34+
--TODO : Refactor
35+
elsif a_value is not null and self.compound_type = 'collection' then
36+
l_anydata_sql := '
37+
declare
38+
l_data '||self.data_type||';
39+
l_value anydata := :a_value;
40+
l_status integer;
41+
begin
42+
l_status := l_value.get'||self.compound_type||'(l_data);
43+
:l_data_is_null := case
44+
when l_data is null then 1
45+
when l_data is empty then 1
46+
else 0 end;
47+
end;';
48+
execute immediate l_anydata_sql using in a_value, out l_result;
49+
else
50+
l_result := 1;
51+
end if;
52+
return l_result;
53+
end;
54+
55+
overriding member function get_object_info return varchar2 is
56+
begin
57+
return self.data_type || case when self.compound_type = 'collection' then ' [ count = '||self.elements_count||' ]' else null end;
58+
end;
59+
60+
member procedure get_cursor_from_anydata(a_value in anydata, a_refcursor out sys_refcursor) is
61+
l_anydata_sql varchar2(4000);
62+
63+
function resolve_name(a_object_name in varchar2) return varchar2 is
64+
l_schema varchar(250);
65+
l_object varchar(250);
66+
l_procedure_name varchar(250);
67+
begin
68+
ut_metadata.do_resolve(a_object_name,7,l_schema,l_object, l_procedure_name);
69+
return l_object;
70+
end;
71+
72+
function get_object_name(a_value anydata) return varchar2 is
73+
begin
74+
return resolve_name(ut_metadata.get_collection_element(a_value));
75+
end;
2676

27-
--Used by dbms_utility...
28-
l_type_name varchar2(250);
29-
l_schema varchar(250);
30-
l_part1 varchar(250);
31-
l_part2 varchar(250);
32-
l_dblink varchar(250);
33-
l_part1_type number;
34-
l_objectid number;
77+
function get_object_name(a_datatype in varchar2) return varchar2 is
78+
begin
79+
return resolve_name(a_datatype);
80+
end;
3581

3682
begin
37-
self.data_type := case when a_value is not null then lower(a_value.gettypename()) else 'undefined' end;
38-
self.data_id := sys_guid();
39-
self.self_type := $$plsql_unit;
40-
self.cursor_details := ut_cursor_details();
41-
if a_value is not null then
42-
--TODO : Move that to helper ??
43-
dbms_utility.name_resolve(self.data_type,7, l_schema, l_part1, l_part2, l_dblink, l_part1_type, l_objectid);
44-
--TODO: Refactor into something nicer
45-
execute immediate '
83+
l_anydata_sql := '
4684
declare
4785
l_data '||self.data_type||';
4886
l_value anydata := :a_value;
4987
l_status integer;
5088
l_tmp_refcursor sys_refcursor;
5189
l_refcursor sys_refcursor;
5290
begin
53-
l_status := l_value.get'||l_anydata_type||'(l_data);
54-
:l_data_is_null := case when l_data is null then 1 else 0 end; '||
55-
case when l_anydata_type = 'collection' then
56-
' open l_tmp_refcursor for select * from table(l_data);'
91+
l_status := l_value.get'||self.compound_type||'(l_data); '||
92+
case when self.compound_type = 'collection' then
93+
' open l_tmp_refcursor for select value(x) as '||get_object_name(a_value)||' from table(l_data) x;'
5794
else
58-
' open l_tmp_refcursor for select l_data '||l_part1||' from dual;'
95+
' open l_tmp_refcursor for select l_data '||get_object_name(self.data_type)||' from dual;'
5996
end ||
60-
q'[ :l_refcursor := l_tmp_refcursor;
61-
if l_data is not null then
62-
:l_count := ]'|| case when l_anydata_type = 'collection' then 'l_data.count; ' else '0; ' end ||
63-
'end if;
64-
end;' using in a_value, out self.is_data_null, out l_query, out l_element_count;
65-
else
66-
self.is_data_null := 1;
97+
' :l_refcursor := l_tmp_refcursor;
98+
end;';
99+
execute immediate l_anydata_sql using in a_value, out a_refcursor;
100+
end;
101+
102+
member procedure init(self in out nocopy ut_data_value_anydata, a_value anydata) is
103+
l_refcursor sys_refcursor;
104+
l_ctx number;
105+
l_ut_owner varchar2(250) := ut_utils.ut_owner;
106+
cursor_not_open exception;
107+
l_cursor_number number;
108+
109+
begin
110+
self.data_type := case when a_value is not null then lower(a_value.gettypename()) else 'undefined' end;
111+
self.compound_type := get_instance(a_value);
112+
self.extract_path := '/*/*';
113+
self.data_id := sys_guid();
114+
self.self_type := $$plsql_unit;
115+
self.cursor_details := ut_cursor_details();
116+
self.is_data_null := is_null(a_value);
117+
self.elements_count := 0;
118+
if not self.is_null() then
119+
get_cursor_from_anydata(a_value,l_refcursor);
67120
end if;
121+
68122
ut_compound_data_helper.cleanup_diff;
69123
if not self.is_null() then
70-
self.elements_count := 0;
71-
if l_query%isopen then
72-
self.extract_cursor(l_query);
73-
--For collection we have to overwrite a number due to being calculated not correctly
74-
if l_anydata_type = 'collection' then
75-
self.elements_count := l_element_count;
76-
end if;
77-
l_cursor_number := dbms_sql.to_cursor_number(l_query);
124+
if l_refcursor%isopen then
125+
self.elements_count := self.extract_cursor(l_refcursor);
126+
l_cursor_number := dbms_sql.to_cursor_number(l_refcursor);
78127
self.cursor_details := ut_cursor_details(l_cursor_number);
79128
dbms_sql.close_cursor(l_cursor_number);
80-
elsif not l_query%isopen then
129+
elsif not l_refcursor%isopen then
81130
raise cursor_not_open;
82131
end if;
83132
end if;

source/expectations/data_values/ut_data_value_anydata.tps

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ create or replace type ut_data_value_anydata under ut_data_value_refcursor(
1515
See the License for the specific language governing permissions and
1616
limitations under the License.
1717
*/
18-
19-
18+
19+
member function is_null(a_value in anydata) return number,
20+
member procedure get_cursor_from_anydata(a_value in anydata, a_refcursor out sys_refcursor),
21+
overriding member function get_object_info return varchar2,
2022
member procedure init(self in out nocopy ut_data_value_anydata, a_value anydata),
2123
member function get_instance(a_data_value anydata) return varchar2,
2224
constructor function ut_data_value_anydata(self in out nocopy ut_data_value_anydata, a_value anydata) return self as result,
@@ -27,4 +29,4 @@ create or replace type ut_data_value_anydata under ut_data_value_refcursor(
2729
a_is_negated boolean := false
2830
) return integer
2931
)
30-
/
32+

0 commit comments

Comments
 (0)