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

Skip to content

Commit 6cb5fe7

Browse files
committed
Further deprecation of Xpath
1 parent e4043b5 commit 6cb5fe7

11 files changed

Lines changed: 141 additions & 145 deletions

source/expectations/data_values/ut_compound_data_helper.pkb

Lines changed: 63 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -85,81 +85,45 @@ create or replace package body ut_compound_data_helper is
8585
end if;
8686
return l_filter;
8787
end;
88-
89-
function get_columns_diff(
90-
a_expected xmltype, a_actual xmltype, a_exclude_xpath varchar2, a_include_xpath varchar2
91-
) return tt_column_diffs is
88+
89+
function get_columns_diff(a_expected ut_cursor_column_tab, a_actual ut_cursor_column_tab)
90+
return tt_column_diffs is
9291
l_column_filter varchar2(32767);
9392
l_sql varchar2(32767);
9493
l_results tt_column_diffs;
9594
begin
96-
l_column_filter := get_columns_row_filter(a_exclude_xpath, a_include_xpath);
97-
--CARDINALITY hints added to address issue: https://github.com/utPLSQL/utPLSQL/issues/752
98-
l_sql := q'[
99-
with
100-
expected_cols as ( select :a_expected as item_data from dual ),
101-
actual_cols as ( select :a_actual as item_data from dual ),
102-
expected_cols_info as (
103-
select e.*,
104-
replace(expected_type,'VARCHAR2','CHAR') expected_type_compare
105-
from (
106-
select /*+ CARDINALITY(xt 100) */
107-
rownum expected_pos,
108-
xt.name expected_name,
109-
xt.type expected_type
110-
from (select ]'||l_column_filter||q'[ from expected_cols ucd) x,
111-
xmltable(
112-
'/ROW/*'
113-
passing x.item_data
114-
columns
115-
name varchar2(4000) PATH '@xml_valid_name',
116-
type varchar2(4000) PATH '/'
117-
) xt
118-
) e
119-
),
120-
actual_cols_info as (
121-
select a.*,
122-
replace(actual_type,'VARCHAR2','CHAR') actual_type_compare
123-
from (select /*+ CARDINALITY(xt 100) */
124-
rownum actual_pos,
125-
xt.name actual_name,
126-
xt.type actual_type
127-
from (select ]'||l_column_filter||q'[ from actual_cols ucd) x,
128-
xmltable('/ROW/*'
129-
passing x.item_data
130-
columns
131-
name varchar2(4000) path '@xml_valid_name',
132-
type varchar2(4000) path '/'
133-
) xt
134-
) a
135-
),
136-
joined_cols as (
137-
select e.*, a.*,
138-
row_number() over(partition by case when actual_pos + expected_pos is not null then 1 end order by actual_pos) a_pos_nn,
139-
row_number() over(partition by case when actual_pos + expected_pos is not null then 1 end order by expected_pos) e_pos_nn
140-
from expected_cols_info e
141-
full outer join actual_cols_info a on e.expected_name = a.actual_name
142-
)
95+
with
96+
expected_cols as
97+
(select access_path exp_column_name,column_position exp_col_pos,
98+
replace(column_type,'VARCHAR2','CHAR') exp_col_type_compare, column_type exp_col_type
99+
from table(a_expected)),
100+
actual_cols as
101+
(select access_path act_column_name,column_position act_col_pos,
102+
replace(column_type,'VARCHAR2','CHAR') act_col_type_compare, column_type act_col_type
103+
from table(a_actual)),
104+
joined_cols as
105+
(select e.*,a.*,
106+
row_number() over(partition by case when a.act_col_pos + e.exp_col_pos is not null then 1 end order by a.act_col_pos) a_pos_nn,
107+
row_number() over(partition by case when a.act_col_pos + e.exp_col_pos is not null then 1 end order by e.exp_col_pos) e_pos_nn
108+
from expected_cols e
109+
full outer join actual_cols a on e.exp_column_name = a.act_column_name)
143110
select case
144-
when expected_pos is null and actual_pos is not null then '+'
145-
when expected_pos is not null and actual_pos is null then '-'
146-
when expected_type_compare != actual_type_compare then 't'
111+
when exp_col_pos is null and act_col_pos is not null then '+'
112+
when exp_col_pos is not null and act_col_pos is null then '-'
113+
when exp_col_type_compare != act_col_type_compare then 't'
147114
else 'p'
148115
end as diff_type,
149-
expected_name, expected_type, expected_pos,
150-
actual_name, actual_type, actual_pos
116+
exp_column_name, exp_col_type, exp_col_pos,
117+
act_column_name, act_col_type, act_col_pos
118+
bulk collect into l_results
151119
from joined_cols
152120
--column is unexpected (extra) or missing
153-
where actual_pos is null or expected_pos is null
121+
where act_col_pos is null or exp_col_pos is null
154122
--column type is not matching (except CHAR/VARCHAR2)
155-
or actual_type_compare != expected_type_compare
123+
or act_col_type_compare != exp_col_type_compare
156124
--column position is not matching (both when excluded extra/missing columns as well as when they are included)
157-
or (a_pos_nn != e_pos_nn and expected_pos != actual_pos)
158-
order by expected_pos, actual_pos]';
159-
execute immediate l_sql
160-
bulk collect into l_results
161-
using a_expected, a_actual, a_exclude_xpath, a_include_xpath, a_exclude_xpath, a_include_xpath;
162-
125+
or (a_pos_nn != e_pos_nn and exp_col_pos != act_col_pos)
126+
order by exp_col_pos, act_col_pos;
163127
return l_results;
164128
end;
165129

@@ -690,6 +654,7 @@ create or replace package body ut_compound_data_helper is
690654
end if;
691655
ut_utils.append_to_clob(l_compare_sql,l_temp_string);
692656

657+
dbms_output.put_line(l_compare_sql);
693658
return l_compare_sql;
694659
end;
695660

@@ -735,12 +700,8 @@ create or replace package body ut_compound_data_helper is
735700
select lev,column_name,parent_name from hier),
736701
t1(column_name, parent_name) AS (
737702
select column_name,parent_name from table(:a_cursor_info) where parent_name is null
738-
union all
739-
select t2.column_name,t2.parent_name from table(:a_cursor_info) t2, t1 where t2.parent_name = t1.column_name)
740-
select ut_cursor_column(i.column_name,i.column_schema,i.column_type_name, i.column_prec,i.column_scale,i.column_len, i.parent_name,
741-
i.hierarchy_level,i.column_position, i.column_type)
742-
from t1 join table(:a_cursor_info) i on ( nvl(t1.parent_name,1) = nvl(i.parent_name,1) and t1.column_name = i.column_name)
743-
]';
703+
union all
704+
select t2.column_name,t2.parent_name from table(:a_cursor_info) t2, t1 where t2.parent_name = t1.column_name)]';
744705
begin
745706
return l_sql;
746707
end;
@@ -750,10 +711,13 @@ create or replace package body ut_compound_data_helper is
750711
l_sql varchar2(32767) := get_cursor_vs_list_sql;
751712
l_result ut_cursor_column_tab := ut_cursor_column_tab();
752713
begin
714+
l_sql := l_sql || q'[select ut_cursor_column(i.column_name,i.column_schema,i.column_type_name, i.column_prec,i.column_scale,i.column_len, i.parent_name,
715+
i.hierarchy_level,i.column_position, i.column_type)
716+
from t1 join table(:a_cursor_info) i on ( nvl(t1.parent_name,1) = nvl(i.parent_name,1) and t1.column_name = i.column_name)]';
753717
if a_include then
754718
l_sql := l_sql || ' join constructed c on ( nvl(t1.parent_name,1) = nvl(c.parent_name,1) and t1.column_name = c.column_name)';
755719
else
756-
l_sql := l_sql ||'left outer join constructed c on ( nvl(t1.parent_name,1) = nvl(c.parent_name,1) and t1.column_name = c.column_name)
720+
l_sql := l_sql ||' left outer join constructed c on ( nvl(t1.parent_name,1) = nvl(c.parent_name,1) and t1.column_name = c.column_name)
757721
where c.column_name is null';
758722
end if;
759723

@@ -764,18 +728,35 @@ create or replace package body ut_compound_data_helper is
764728
end;
765729

766730
function compare_cursor_to_columns(a_cursor_info ut_cursor_column_tab, a_current_list ut_varchar2_list)
767-
return ut_cursor_column_tab is
731+
return ut_varchar2_list is
768732
l_sql varchar2(32767) := get_cursor_vs_list_sql;
769-
l_result ut_cursor_column_tab := ut_cursor_column_tab();
733+
l_result ut_varchar2_list := ut_varchar2_list();
770734
begin
735+
l_sql := l_sql || q'[select c.parent_name || case when c.parent_name is null then null else '/' end ||c.column_name
736+
from t1 join table(:a_cursor_info) i on ( nvl(t1.parent_name,1) = nvl(i.parent_name,1) and t1.column_name = i.column_name)]';
771737
l_sql := l_sql ||'right outer join constructed c on ( nvl(t1.parent_name,1) = nvl(c.parent_name,1) and t1.column_name = c.column_name)
772738
where t1.column_name is null';
773739

774740
execute immediate l_sql bulk collect into l_result
775741
using a_current_list,a_cursor_info,a_cursor_info,a_cursor_info;
776742
return l_result;
777743
end;
778-
744+
745+
function get_missing_pk(a_expected ut_cursor_column_tab, a_actual ut_cursor_column_tab, a_current_list ut_varchar2_list)
746+
return tt_missing_pk is
747+
l_actual ut_varchar2_list := coalesce(compare_cursor_to_columns(a_actual,a_current_list),ut_varchar2_list());
748+
l_expected ut_varchar2_list := coalesce(compare_cursor_to_columns(a_expected,a_current_list),ut_varchar2_list());
749+
l_missing_pk tt_missing_pk;
750+
begin
751+
select name,type
752+
bulk collect into l_missing_pk
753+
from
754+
(select act.column_value name, 'e' type from table(l_expected) act
755+
union all
756+
select exp.column_value name, 'a' type from table(l_actual) exp)
757+
order by type desc,name;
758+
return l_missing_pk;
759+
end;
779760

780761
function inc_exc_columns_from_cursor (a_cursor_info ut_cursor_column_tab, a_exclude_xpath ut_varchar2_list, a_include_xpath ut_varchar2_list)
781762
return ut_cursor_column_tab is
@@ -819,5 +800,13 @@ create or replace package body ut_compound_data_helper is
819800
return l_result;
820801
end;
821802

803+
function contains_collection (a_cursor_info ut_cursor_column_tab) return number is
804+
l_collection_elements number;
805+
begin
806+
select count(1) into l_collection_elements from
807+
table(a_cursor_info) c where c.is_collection = 1;
808+
return l_collection_elements;
809+
end;
810+
822811
end;
823812
/

source/expectations/data_values/ut_compound_data_helper.pks

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,8 @@ create or replace package ut_compound_data_helper authid definer is
6565
a_table_alias varchar2 := 'ucd', a_column_alias varchar2 := 'item_data'
6666
) return varchar2;
6767

68-
function get_columns_diff(
69-
a_expected xmltype, a_actual xmltype, a_exclude_xpath varchar2, a_include_xpath varchar2
70-
) return tt_column_diffs;
68+
function get_columns_diff(a_expected ut_cursor_column_tab, a_actual ut_cursor_column_tab)
69+
return tt_column_diffs;
7170

7271
function get_pk_value (a_join_by_xpath varchar2,a_item_data xmltype) return clob;
7372

@@ -107,10 +106,15 @@ create or replace package ut_compound_data_helper authid definer is
107106
return ut_cursor_column_tab;
108107

109108
function compare_cursor_to_columns(a_cursor_info ut_cursor_column_tab, a_current_list ut_varchar2_list)
110-
return ut_cursor_column_tab;
109+
return ut_varchar2_list;
110+
111+
function get_missing_pk(a_expected ut_cursor_column_tab, a_actual ut_cursor_column_tab, a_current_list ut_varchar2_list)
112+
return tt_missing_pk;
111113

112114
function inc_exc_columns_from_cursor (a_cursor_info ut_cursor_column_tab, a_exclude_xpath ut_varchar2_list, a_include_xpath ut_varchar2_list)
113115
return ut_cursor_column_tab;
114116

117+
function contains_collection (a_cursor_info ut_cursor_column_tab) return number;
118+
115119
end;
116120
/

source/expectations/data_values/ut_compound_data_value.tpb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ create or replace type body ut_compound_data_value as
7979
return l_result_string;
8080
end;
8181

82+
-- TODO : Rework to exclude xpath
8283
member function get_data_diff(a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2,
8384
a_join_by_xpath varchar2, a_unordered boolean) return clob is
8485
c_max_rows integer := ut_utils.gc_diff_max_rows;
@@ -128,15 +129,16 @@ create or replace type body ut_compound_data_value as
128129
l_message := chr(10)
129130
||'Rows: [ ' || l_diff_row_count ||' differences'
130131
|| case when l_diff_row_count > c_max_rows and l_row_diffs.count > 0 then ', showing first '||c_max_rows end
131-
||' ]' || chr(10)
132-
|| case when l_row_diffs.count = 0
133-
then ' All rows are different as the columns are not matching.' end;
132+
||' ]'||chr(10)|| case when l_row_diffs.count = 0 then ' All rows are different as the columns are not matching.' else null end;
134133
ut_utils.append_to_clob( l_result, l_message );
135134
for i in 1 .. l_row_diffs.count loop
136135
l_results.extend;
137136
l_results(l_results.last) := get_diff_message(l_row_diffs(i),a_unordered);
138137
end loop;
139138
ut_utils.append_to_clob(l_result,l_results);
139+
else
140+
l_message:= chr(10)||'Rows: [ all different ]'||chr(10)||' All rows are different as the columns are not matching.';
141+
ut_utils.append_to_clob( l_result, l_message );
140142
end if;
141143
return l_result;
142144
end;

source/expectations/data_values/ut_curr_usr_compound_helper.pkb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ create or replace package body ut_curr_usr_compound_helper is
2020
--clob/blob/xmltype/object/nestedcursor/nestedtable
2121
if a_type_name IN (g_type_name_map(dbms_sql.blob_type),
2222
g_type_name_map(dbms_sql.clob_type),
23-
g_type_name_map(dbms_sql.bfile_type))
23+
g_type_name_map(dbms_sql.bfile_type),
24+
g_anytype_name_map(dbms_types.typecode_namedcollection))
2425
then
2526
return false;
2627
else

source/expectations/data_values/ut_cursor_column.tpb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ create or replace type body ut_cursor_column as
3434
self.has_nested_col := case when lower(self.column_type) = 'user_defined_type' and self.is_collection = 0 then 1 else 0 end;
3535
end;
3636

37+
--TODO : Scenarios :
38+
--namedcollection xmltype getclobhash
39+
--collection xml type get clob hash
40+
-- user defined type
41+
3742
constructor function ut_cursor_column( self in out nocopy ut_cursor_column,
3843
a_col_name varchar2, a_col_schema_name varchar2,
3944
a_col_type_name varchar2, a_col_prec integer, a_col_scale integer,

source/expectations/data_values/ut_data_value_refcursor.tpb

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -116,14 +116,17 @@ create or replace type body ut_data_value_refcursor as
116116
return l_result_string;
117117
end;
118118

119-
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 is
119+
member function diff( a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2, a_join_by_xpath varchar2,
120+
a_unordered boolean := false, a_join_by_list ut_varchar2_list:=ut_varchar2_list() ) return varchar2 is
120121
l_result clob;
121122
l_results ut_utils.t_clob_tab := ut_utils.t_clob_tab();
122123
l_result_string varchar2(32767);
123124
l_actual ut_data_value_refcursor;
124125
l_column_diffs ut_compound_data_helper.tt_column_diffs := ut_compound_data_helper.tt_column_diffs();
125126
l_exclude_xpath varchar2(32767) := a_exclude_xpath;
127+
126128
l_missing_pk ut_compound_data_helper.tt_missing_pk := ut_compound_data_helper.tt_missing_pk();
129+
l_col_diffs ut_compound_data_helper.tt_column_diffs := ut_compound_data_helper.tt_column_diffs();
127130

128131
function get_col_diff_text(a_col ut_compound_data_helper.t_column_diffs) return varchar2 is
129132
begin
@@ -143,7 +146,6 @@ create or replace type body ut_data_value_refcursor as
143146
function get_missing_key_message(a_missing_keys ut_compound_data_helper.t_missing_pk) return varchar2 is
144147
l_message varchar2(200);
145148
begin
146-
147149
if a_missing_keys.diff_type = 'a' then
148150
l_message := ' Join key '||a_missing_keys.missingxpath||' does not exists in actual';
149151
elsif a_missing_keys.diff_type = 'e' then
@@ -184,7 +186,7 @@ create or replace type body ut_data_value_refcursor as
184186

185187
--diff columns
186188
if not self.is_null and not l_actual.is_null then
187-
l_column_diffs := ut_compound_data_helper.get_columns_diff(self.columns_info, l_actual.columns_info, a_exclude_xpath, a_include_xpath);
189+
l_column_diffs := ut_compound_data_helper.get_columns_diff(self.cursor_details.cursor_info,l_actual.cursor_details.cursor_info);
188190

189191
if l_column_diffs.count > 0 then
190192
ut_utils.append_to_clob(l_result,chr(10) || 'Columns:' || chr(10));
@@ -199,8 +201,8 @@ create or replace type body ut_data_value_refcursor as
199201
end if;
200202

201203
--check for missing pk
202-
if (a_join_by_xpath is not null) then
203-
l_missing_pk := ut_compound_data_helper.is_pk_exists(self.key_info, l_actual.key_info, a_exclude_xpath, a_include_xpath,a_join_by_xpath);
204+
if a_join_by_list.count > 0 then
205+
l_missing_pk := ut_compound_data_helper.get_missing_pk(self.cursor_details.cursor_info,l_actual.cursor_details.cursor_info,a_join_by_list);
204206
end if;
205207

206208
--diff rows and row elements if the pk is not missing
@@ -213,7 +215,8 @@ create or replace type body ut_data_value_refcursor as
213215
ut_utils.append_to_clob(l_result, get_missing_key_message(l_missing_pk(i))|| chr(10));
214216
end loop;
215217

216-
if ut_utils.int_to_boolean(self.contain_collection) or ut_utils.int_to_boolean(l_actual.contain_collection) then
218+
if ut_compound_data_helper.contains_collection(self.cursor_details.cursor_info) > 0
219+
or ut_compound_data_helper.contains_collection(l_actual.cursor_details.cursor_info) > 0 then
217220
ut_utils.append_to_clob(l_result,' Please make sure that your join clause is not refferring to collection element'|| chr(10));
218221
end if;
219222

@@ -228,36 +231,29 @@ create or replace type body ut_data_value_refcursor as
228231
a_is_negated boolean := false, a_join_by_list ut_varchar2_list:=ut_varchar2_list())
229232
return integer is
230233
l_result integer := 0;
231-
l_other ut_data_value_refcursor;
232-
233-
l_act_pk ut_cursor_column_tab;
234-
l_exp_pk ut_cursor_column_tab;
234+
l_actual ut_data_value_refcursor;
235+
236+
l_pk_missing_tab ut_compound_data_helper.tt_missing_pk;
235237

236-
function is_pk_missing (a_pk_missing_tab ut_compound_data_helper.tt_missing_pk) return integer is
237-
begin
238-
return case when a_pk_missing_tab.count > 0 then 1 else 0 end;
239-
end;
240238
begin
241239
if not a_other is of (ut_data_value_refcursor) then
242240
raise value_error;
243241
end if;
244242

245-
l_other := treat(a_other as ut_data_value_refcursor);
243+
l_actual := treat(a_other as ut_data_value_refcursor);
246244

247245
--if we join by key and key is missing fail and report error
248246
if a_join_by_list.count > 0 then
249-
l_act_pk := ut_compound_data_helper.compare_cursor_to_columns(self.cursor_details.cursor_info ,a_join_by_list);
250-
l_exp_pk := ut_compound_data_helper.compare_cursor_to_columns(l_other.cursor_details.cursor_info,a_join_by_list);
251-
l_result := case when (l_act_pk.count > 0) or (l_exp_pk.count > 0) then 1 else 0 end;
247+
l_pk_missing_tab := ut_compound_data_helper.get_missing_pk(self.cursor_details.cursor_info,l_actual.cursor_details.cursor_info,a_join_by_list);
248+
l_result := case when (l_pk_missing_tab.count > 0) then 1 else 0 end;
252249
end if;
253250

254-
255251
if l_result = 0 then
256-
if (self.cursor_details is not null and l_other.cursor_details is not null) and (self.cursor_details != l_other.cursor_details) then
252+
if (self.cursor_details is not null and l_actual.cursor_details is not null) and (self.cursor_details != l_actual.cursor_details) then
257253
l_result := 1;
258-
end if;
254+
end if;
259255
l_result := l_result + (self as ut_compound_data_value).compare_implementation(a_other,a_unordered, a_inclusion_compare,
260-
a_is_negated, a_join_by_list);
256+
a_is_negated, a_join_by_list);
261257
end if;
262258

263259
return l_result;

0 commit comments

Comments
 (0)