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

Skip to content

Commit 2b9d4f3

Browse files
committed
Capture cursor info and filter it out
1 parent c997616 commit 2b9d4f3

8 files changed

Lines changed: 177 additions & 17 deletions

source/expectations/data_values/ut_compound_data_helper.pkb

Lines changed: 128 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ create or replace package body ut_compound_data_helper is
1818

1919
g_user_defined_type pls_integer := dbms_sql.user_defined_type;
2020
g_diff_count integer;
21+
g_filter_tab ut_varchar2_list;
2122

2223
function get_column_info_xml(a_column_details ut_key_anyval_pair) return xmltype is
2324
l_result varchar2(4000);
@@ -620,7 +621,7 @@ create or replace package body ut_compound_data_helper is
620621

621622
begin
622623
dbms_lob.createtemporary(l_compare_sql, true);
623-
624+
624625
--TODO: Resolve issues with collection and nested tables, can we extract by internal column name if defined e.g. xml of colval.id.getclobval()
625626
--TODO: Comment better all pieces
626627
l_column_filter := get_columns_row_filter(a_exclude_xpath, a_include_xpath);
@@ -717,7 +718,7 @@ create or replace package body ut_compound_data_helper is
717718
l_temp_string := ' (a.data_id is null or e.data_id is null) ';
718719
end if;
719720
ut_utils.append_to_clob(l_compare_sql,l_temp_string);
720-
721+
721722
return l_compare_sql;
722723
end;
723724

@@ -748,5 +749,129 @@ create or replace package body ut_compound_data_helper is
748749
return g_diff_count;
749750
end;
750751

751-
end;
752+
function populate_filter_columns (a_column_string in varchar2, a_column_info ut_column_info_tab) return ut_column_info_rec is
753+
l_result ut_column_info_rec;
754+
l_column_from_string varchar2(32767);
755+
l_rest_of_path varchar2(32767);
756+
begin
757+
--check if string has a path
758+
l_column_from_string := regexp_substr(a_column_string,'^([^\/]*)?\/?(.*)',1,1,null,1);
759+
for col in 1..a_column_info.count loop
760+
if l_column_from_string = a_column_info(col).column_name then
761+
if a_column_string like '%/%' then
762+
l_rest_of_path := regexp_substr(a_column_string,'^([^\/]*)?\/(.*)',1,1,null,2);
763+
l_result := treat(a_column_info(col) as ut_column_info_rec);
764+
l_result.nested_details := ut_column_info_tab();
765+
l_result.nested_details.extend;
766+
l_result.nested_details(l_result.nested_details.last) := populate_filter_columns (l_rest_of_path,treat(a_column_info(col) as ut_column_info_rec).nested_details);
767+
else
768+
l_result := treat(a_column_info(col) as ut_column_info_rec);
769+
end if;
770+
end if;
771+
end loop;
772+
return l_result;
773+
end;
774+
775+
function get_child(a_parent in varchar2 default null) return ut_varchar2_list is
776+
l_out_tab ut_varchar2_list := ut_varchar2_list();
777+
cursor c_child(cp_parent in varchar2) is
778+
with sorted as
779+
(select r_num,
780+
regexp_substr(t.column_value, '[^/]+', 1, commas.column_value) as colval,
781+
commas.column_value lev
782+
from (select row_number() over(order by 1) r_num,
783+
column_value
784+
from ((table(g_filter_tab)))) t,
785+
table(cast(multiset
786+
(select level
787+
from dual
788+
connect by level <=
789+
length(regexp_replace(t.column_value,
790+
'[^/]+')) + 1) as
791+
sys.odcinumberlist)) commas
792+
order by r_num,
793+
lev),
794+
hier as
795+
(select r_num,
796+
lev,
797+
colval,
798+
lag(colval, 1) over(partition by r_num order by lev) parent
799+
from sorted)
800+
select distinct colval
801+
from hier
802+
where nvl(parent, 1) = nvl(cp_parent, 1);
803+
804+
begin
805+
open c_child(a_parent);
806+
fetch c_child bulk collect
807+
into l_out_tab;
808+
close c_child;
809+
return l_out_tab;
810+
end;
811+
812+
function exc_inc_cursors_columns(a_column_info_tab ut_column_info_tab,a_current_list ut_varchar2_list)
813+
return ut_column_info_tab is
814+
l_result ut_column_info_tab := ut_column_info_tab();
815+
l_record ut_column_info_rec;
816+
l_index integer := 1;
817+
begin
818+
--TODO : Optimize search using while or exists operator ?
819+
for lst in 1..a_current_list.count loop
820+
for i in 1..a_column_info_tab.count loop
821+
if a_current_list(lst) = a_column_info_tab(i).column_name then
822+
l_result.extend;
823+
if a_column_info_tab(i) is of (ut_column_info_rec) then
824+
l_record := treat(a_column_info_tab(i) as ut_column_info_rec);
825+
l_record.nested_details := exc_inc_cursors_columns(treat(a_column_info_tab(i) as ut_column_info_rec).nested_details,get_child(a_column_info_tab(i).column_name));
826+
end if;
827+
l_result(l_result.last) := l_record;
828+
end if;
829+
end loop;
830+
end loop;
831+
return l_result;
832+
end;
833+
834+
function inc_exc_columns_from_cursor (a_cursor_info ut_column_info_tab, a_exclude_xpath ut_varchar2_list, a_include_xpath ut_varchar2_list)
835+
return ut_column_info_tab is
836+
l_filtered_set ut_varchar2_list := ut_varchar2_list();
837+
l_result ut_column_info_tab := ut_column_info_tab();
838+
begin
839+
g_filter_tab := ut_varchar2_list();
840+
841+
-- if include and exclude is not null its columns from include minus exclude
842+
-- If inlcude is not null and exclude is null cursor will have only include
843+
-- If exclude is not null and include is null cursor will have all except exclude
844+
845+
if a_include_xpath.count > 0 and a_exclude_xpath.count > 0 then
846+
select col_names bulk collect into l_filtered_set
847+
from(
848+
select regexp_replace(column_value,'^((/ROW/)|^(//)|^(/\*/))?(.*)','\5') col_names
849+
from table(a_include_xpath)
850+
minus
851+
select regexp_replace(column_value,'^((/ROW/)|^(//)|^(/\*/))?(.*)','\5') col_names
852+
from table(a_exclude_xpath)
853+
);
854+
elsif a_include_xpath.count > 0 and a_exclude_xpath.count = 0 then
855+
select regexp_replace(column_value,'^((/ROW/)|^(//)|^(/\*/))?(.*)','\5') col_names
856+
bulk collect into l_filtered_set
857+
from table(a_include_xpath);
858+
elsif a_include_xpath.count = 0 and a_exclude_xpath.count > 0 then
859+
select regexp_replace(column_value,'^((/ROW/)|^(//)|^(/\*/))?(.*)','\5') col_names
860+
bulk collect into l_filtered_set
861+
from table(a_exclude_xpath);
862+
elsif a_cursor_info is not null then
863+
l_result:= a_cursor_info;
864+
else
865+
l_result := ut_column_info_tab();
866+
end if;
867+
868+
g_filter_tab := l_filtered_set;
869+
if g_filter_tab.count <> 0 then
870+
l_result := exc_inc_cursors_columns(a_cursor_info,get_child());
871+
end if;
872+
873+
return l_result;
874+
end;
875+
876+
end;
752877
/

source/expectations/data_values/ut_compound_data_helper.pks

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,5 +102,8 @@ create or replace package ut_compound_data_helper authid definer is
102102

103103
function get_rows_diff_count return integer;
104104

105+
function inc_exc_columns_from_cursor (a_cursor_info ut_column_info_tab, a_exclude_xpath ut_varchar2_list, a_include_xpath ut_varchar2_list)
106+
return ut_column_info_tab;
107+
105108
end;
106109
/

source/expectations/data_values/ut_compound_data_tmp.sql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ create global temporary table ut_compound_data_tmp(
1919
pk_hash raw(128),
2020
duplicate_no integer,
2121
constraint ut_cmp_data_tmp_hash_pk unique (data_id, item_no, duplicate_no)
22-
) on commit preserve rows xmltype column item_data store as binary xml;
22+
) on commit preserve rows;
23+
--xmltype column item_data store as binary xml;

source/expectations/data_values/ut_curr_usr_compound_helper.pkb

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,7 @@ create or replace package body ut_curr_usr_compound_helper is
3434
return ut_utils.boolean_to_int(is_sql_compare_allowed(a_type_name));
3535
end;
3636

37-
function get_column_type(a_desc_rec dbms_sql.desc_rec3, a_desc_user_types boolean := false) return ut_key_anyval_pair is
38-
l_data ut_data_value;
39-
l_result ut_key_anyval_pair;
40-
l_data_type varchar2(500) := 'unknown datatype';
41-
42-
function is_collection (a_owner varchar2,a_type_name varchar2) return boolean is
37+
function is_collection (a_owner varchar2,a_type_name varchar2) return boolean is
4338
l_type_view varchar2(200) := ut_metadata.get_dba_view('dba_types');
4439
l_typecode varchar2(100);
4540
begin
@@ -48,7 +43,16 @@ create or replace package body ut_curr_usr_compound_helper is
4843
into l_typecode using a_owner,a_type_name;
4944

5045
return l_typecode = 'COLLECTION';
46+
exception
47+
when no_data_found then
48+
return false;
5149
end;
50+
51+
function get_column_type(a_desc_rec dbms_sql.desc_rec3, a_desc_user_types boolean := false) return ut_key_anyval_pair is
52+
l_data ut_data_value;
53+
l_result ut_key_anyval_pair;
54+
l_data_type varchar2(500) := 'unknown datatype';
55+
5256
--TODO: Review the types in and resolving
5357
begin
5458

@@ -241,6 +245,11 @@ create or replace package body ut_curr_usr_compound_helper is
241245
return l_result ;
242246
end;
243247

248+
function get_column_type(a_type_code in integer, a_dbms_sql_desc in boolean) return varchar2 is
249+
begin
250+
return case when not a_dbms_sql_desc then g_anytype_name_map(a_type_code) else g_type_name_map(a_type_code) end;
251+
end;
252+
244253
begin
245254
g_anytype_name_map(dbms_types.typecode_date) := 'DATE';
246255
g_anytype_name_map(dbms_types.typecode_number) := 'NUMBER';
@@ -262,7 +271,7 @@ create or replace package body ut_curr_usr_compound_helper is
262271
g_anytype_name_map(dbms_types.typecode_varray) := 'VARRRAY';
263272
g_anytype_name_map(dbms_types.typecode_table) := 'TABLE';
264273
g_anytype_name_map(dbms_types.typecode_namedcollection) := 'NAMEDCOLLECTION';
265-
274+
266275
g_anytype_collection_name(dbms_types.typecode_varray) := 'VARRRAY';
267276
g_anytype_collection_name(dbms_types.typecode_table) := 'TABLE';
268277
g_anytype_collection_name(dbms_types.typecode_namedcollection) := 'NAMEDCOLLECTION';

source/expectations/data_values/ut_curr_usr_compound_helper.pks

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ create or replace package ut_curr_usr_compound_helper authid current_user is
33
function is_sql_compare_allowed(a_type_name varchar2) return boolean;
44

55
function is_sql_compare_int(a_type_name varchar2) return integer;
6-
6+
7+
function is_collection (a_owner varchar2,a_type_name varchar2) return boolean;
8+
79
procedure get_columns_info(
810
a_cursor in out nocopy sys_refcursor,
911
a_columns_info out nocopy xmltype,
@@ -15,5 +17,7 @@ create or replace package ut_curr_usr_compound_helper authid current_user is
1517

1618
function extract_min_col_info(a_full_col_info xmltype) return xmltype;
1719

20+
function get_column_type(a_type_code in integer, a_dbms_sql_desc in boolean) return varchar2;
21+
1822
end;
1923
/

source/expectations/data_values/ut_data_value_refcursor.tpb

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ create or replace type body ut_data_value_refcursor as
4848
self.elements_count := 0;
4949
self.columns_info := ut_curr_usr_compound_helper.extract_min_col_info(self.col_info_desc);
5050

51+
self.cursor_col_info := ut_cursor_info(l_cursor);
52+
5153
-- We use DBMS_XMLGEN in order to:
5254
-- 1) be able to process data in bulks (set of rows)
5355
-- 2) be able to influence the ROWSET/ROW tags
@@ -99,7 +101,7 @@ create or replace type body ut_data_value_refcursor as
99101
dbms_xmlgen.closeContext(l_ctx);
100102
raise;
101103
end;
102-
104+
103105
overriding member function to_string return varchar2 is
104106
l_result clob;
105107
l_result_string varchar2(32767);
@@ -236,7 +238,7 @@ create or replace type body ut_data_value_refcursor as
236238
if not a_other is of (ut_data_value_refcursor) then
237239
raise value_error;
238240
end if;
239-
241+
240242
l_other := treat(a_other as ut_data_value_refcursor);
241243

242244
--if we join by key and key is missing fail and report error
@@ -265,6 +267,14 @@ create or replace type body ut_data_value_refcursor as
265267
return self.elements_count = 0;
266268
end;
267269

270+
member function filter_cursor (a_exclude_xpath ut_varchar2_list, a_include_xpath ut_varchar2_list) return ut_data_value_refcursor is
271+
l_result ut_data_value_refcursor := self;
272+
begin
273+
if l_result.cursor_col_info.cursor_info is not null then
274+
l_result.cursor_col_info.cursor_info := ut_compound_data_helper.inc_exc_columns_from_cursor(l_result.cursor_col_info.cursor_info,a_exclude_xpath,a_include_xpath);
275+
end if;
276+
return l_result;
277+
end;
268278

269279
end;
270280
/

source/expectations/data_values/ut_data_value_refcursor.tps

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,18 @@ create or replace type ut_data_value_refcursor under ut_compound_data_value(
4444
*/
4545
key_info xmltype,
4646

47+
/*
48+
*columns info
49+
*/
50+
cursor_col_info ut_cursor_info,
51+
4752
constructor function ut_data_value_refcursor(self in out nocopy ut_data_value_refcursor, a_value sys_refcursor) return self as result,
4853
member procedure init(self in out nocopy ut_data_value_refcursor, a_value sys_refcursor),
4954
overriding member function to_string return varchar2,
5055
overriding member function diff( a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2, a_join_by_xpath varchar2, a_unordered boolean := false ) return varchar2,
5156
overriding member function compare_implementation(a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2, a_join_by_xpath varchar2,
5257
a_unordered boolean, a_inclusion_compare boolean := false, a_is_negated boolean := false) return integer,
53-
overriding member function is_empty return boolean
58+
overriding member function is_empty return boolean,
59+
member function filter_cursor (a_exclude_xpath ut_varchar2_list, a_include_xpath ut_varchar2_list) return ut_data_value_refcursor
5460
)
5561
/

source/expectations/matchers/ut_equal.tpb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ create or replace type body ut_equal as
2525
self.exclude_list := ut_varchar2_list();
2626
self.join_columns := ut_varchar2_list();
2727
end;
28-
28+
2929
member function equal_with_nulls(a_assert_result boolean, a_actual ut_data_value) return boolean is
3030
begin
3131
ut_utils.debug_log('ut_equal.equal_with_nulls :' || ut_utils.to_test_result(a_assert_result) || ':');
@@ -228,12 +228,14 @@ create or replace type body ut_equal as
228228

229229
overriding member function run_matcher(self in out nocopy ut_equal, a_actual ut_data_value) return boolean is
230230
l_result boolean;
231+
l_actual ut_data_value;
231232
begin
232233
if self.expected.data_type = a_actual.data_type then
233234
if self.expected is of (ut_data_value_anydata) then
234235
l_result := 0 = treat(self.expected as ut_data_value_anydata).compare_implementation(a_actual, get_exclude_xpath(), get_include_xpath());
235236
elsif self.expected is of (ut_data_value_refcursor) then
236-
l_result := 0 = treat(self.expected as ut_data_value_refcursor).compare_implementation(a_actual, get_exclude_xpath(), get_include_xpath(), get_join_by_xpath(), get_unordered());
237+
l_actual := treat(a_actual as ut_data_value_refcursor).filter_cursor(exclude_list, include_list);
238+
l_result := 0 = treat(self.expected as ut_data_value_refcursor).filter_cursor(exclude_list, include_list).compare_implementation(a_actual, get_exclude_xpath(), get_include_xpath(), get_join_by_xpath(), get_unordered());
237239
else
238240
l_result := equal_with_nulls((self.expected = a_actual), a_actual);
239241
end if;

0 commit comments

Comments
 (0)