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

Skip to content

Commit 41ae0ff

Browse files
committed
Added methods for join_by
Adding compare for join by
1 parent b9ca972 commit 41ae0ff

14 files changed

Lines changed: 271 additions & 64 deletions

source/expectations/data_values/ut_compound_data_diff_tmp.sql

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,11 @@ create global temporary table ut_compound_data_diff_tmp(
1414
*/
1515
diff_id raw(128),
1616
item_no integer,
17-
constraint ut_compound_data_diff_tmp_pk primary key(diff_id,item_no)
17+
item_hash raw(128),
18+
duplicate_no integer,
19+
--constraint ut_compound_data_diff_tmp_uk1 unique (diff_id, item_no, item_hash, duplicate_no),
20+
constraint ut_compound_data_diff_tmp_chk check(
21+
item_no is not null and item_hash is null and duplicate_no is null
22+
or item_no is null and item_hash is not null and duplicate_no is not null
23+
)
1824
) on commit preserve rows;

source/expectations/data_values/ut_compound_data_helper.pkb

Lines changed: 108 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,79 @@ create or replace package body ut_compound_data_helper is
160160
return l_results;
161161
end;
162162

163+
function get_rows_diff(
164+
a_expected_dataset_guid raw, a_actual_dataset_guid raw, a_diff_id raw,
165+
a_max_rows integer, a_exclude_xpath varchar2, a_include_xpath varchar2,
166+
a_join_by_xpath varchar2
167+
) return tt_row_diffs is
168+
l_column_filter varchar2(32767);
169+
l_results tt_row_diffs;
170+
l_sql varchar2(32767); -- REMOVE LATER also for unorder
171+
begin
172+
l_column_filter := get_columns_filter(a_exclude_xpath,a_include_xpath);
173+
174+
/**
175+
* Since its unordered search we cannot select max rows from diffs as we miss some comparision records
176+
* We will restrict output on higher level of select
177+
*/
178+
179+
l_sql := q'[
180+
with
181+
diff_info as (select item_hash from ut_compound_data_diff_tmp ucdc where diff_id = :diff_guid)
182+
select rn,diff_type,diffed_row
183+
from (select dense_rank() over (order by pk_hash) as rn, diff_type,data_item diffed_row
184+
from (select nvl(exp.pk_hash, act.pk_hash) pk_hash,
185+
xmlserialize(content exp.row_data no indent) exp_item,
186+
xmlserialize(content act.row_data no indent) act_item
187+
from
188+
(select ucd.*, row_number() over(partition by pk_hash order by row_hash) duplicate_no
189+
from
190+
(select ucd.column_value row_data,
191+
dbms_crypto.hash( value(ucd).getclobval(),3) row_hash,
192+
dbms_crypto.hash( extract(value(ucd),']'|| a_join_by_xpath ||q'[').getClobVal(),3/*HASH_SH1*/) pk_hash
193+
from
194+
(select ]'||l_column_filter||q'[, ucd.item_no, ucd.item_data item_data_no_filter
195+
from ut_compound_data_tmp ucd
196+
where ucd.data_id = :self_guid
197+
and ucd.item_hash in (select i.item_hash from diff_info i)
198+
) r,
199+
table( xmlsequence( extract(r.item_data,'/*') ) ) ucd
200+
) ucd
201+
) exp
202+
join (
203+
select ucd.*, row_number() over(partition by pk_hash order by row_hash) duplicate_no
204+
from
205+
(select ucd.column_value row_data,
206+
dbms_crypto.hash( value(ucd).getclobval(),3/*HASH_SH1*/) row_hash,
207+
dbms_crypto.hash( extract(value(ucd),']'|| a_join_by_xpath ||q'[').getClobVal(),3/*HASH_SH1*/) pk_hash
208+
from
209+
(select ]'||l_column_filter||q'[, ucd.item_no, ucd.item_data item_data_no_filter
210+
from ut_compound_data_tmp ucd
211+
where ucd.data_id = :other_guid
212+
and ucd.item_hash in (select i.item_hash from diff_info i)
213+
) r,
214+
table( xmlsequence( extract(r.item_data,'/*') ) ) ucd
215+
) ucd
216+
) act
217+
on exp.pk_hash = act.pk_hash and exp.duplicate_no = act.duplicate_no
218+
where exp.row_hash != act.row_hash
219+
or exp.row_hash is null
220+
or act.row_hash is null
221+
)
222+
unpivot ( data_item for diff_type in (exp_item as 'Expected:', act_item as 'Actual:') )
223+
)
224+
where rownum < :max_rows
225+
order by 1, 2]';
226+
227+
execute immediate l_sql
228+
bulk collect into l_results
229+
using a_diff_id,
230+
a_exclude_xpath, a_include_xpath, a_expected_dataset_guid,
231+
a_exclude_xpath, a_include_xpath, a_actual_dataset_guid,
232+
a_max_rows;
233+
return l_results;
234+
end;
235+
163236
function get_rows_diff(
164237
a_expected_dataset_guid raw, a_actual_dataset_guid raw, a_diff_id raw,
165238
a_max_rows integer, a_exclude_xpath varchar2, a_include_xpath varchar2
@@ -237,21 +310,36 @@ create or replace package body ut_compound_data_helper is
237310
l_results tt_row_diffs;
238311
begin
239312
l_column_filter := get_columns_filter(a_exclude_xpath,a_include_xpath);
240-
execute immediate q'[
241-
select
242-
coalesce(exp.duplicate_no, act.duplicate_no) duplicate_no,
243-
case when exp.row_hash is null then 'Actual:' else 'Expected:' end diffed_type,
244-
case when exp.row_hash is null then
245-
xmlserialize(content act.row_data no indent)
246-
else
247-
xmlserialize(content exp.row_data no indent)
248-
end diffed_row
249-
from (select ucd.*, row_number() over(partition by row_hash order by row_hash) duplicate_no
313+
314+
/**
315+
* Since its unordered search we cannot select max rows from diffs as we miss some comparision records
316+
* We will restrict output on higher level of select
317+
*/
318+
execute immediate q'[with
319+
diff_info as (select item_hash from ut_compound_data_diff_tmp ucdc where diff_id = :diff_guid)
320+
select duplicate_no,
321+
diffed_type,
322+
diffed_row
323+
from
324+
(select
325+
coalesce(exp.duplicate_no,act.duplicate_no) duplicate_no,
326+
case
327+
when act.row_hash is null then
328+
'miss row'
329+
else 'extra row'
330+
end diffed_type,
331+
case when exp.row_hash is null then
332+
xmlserialize(content act.row_data no indent)
333+
when act.row_hash is null then
334+
xmlserialize(content exp.row_data no indent)
335+
end diffed_row
336+
from (select ucd.*, row_number() over(partition by row_hash order by row_hash) duplicate_no
250337
from (select ucd.column_value row_data,
251338
dbms_crypto.hash( value(ucd).getclobval(),3) row_hash
252-
from (select ]'||l_column_filter||q'[, ucd.item_no, ucd.item_data item_data_no_filter
339+
from (select ]'||l_column_filter||q'[, ucd.item_no, ucd.item_data item_data_no_filter
253340
from ut_compound_data_tmp ucd
254341
where ucd.data_id = :self_guid
342+
and ucd.item_hash in (select i.item_hash from diff_info i)
255343
) r,
256344
table( xmlsequence( extract(r.item_data,'/*') ) ) ucd
257345
) ucd
@@ -260,21 +348,23 @@ create or replace package body ut_compound_data_helper is
260348
(select ucd.*, row_number() over(partition by row_hash order by row_hash) duplicate_no
261349
from (select ucd.column_value row_data,
262350
dbms_crypto.hash( value(ucd).getclobval(),3/*HASH_SH1*/) row_hash
263-
from (select ]'||l_column_filter||q'[, ucd.item_no, ucd.item_data item_data_no_filter
351+
from (select ]'||l_column_filter||q'[, ucd.item_no, ucd.item_data item_data_no_filter
264352
from ut_compound_data_tmp ucd
265353
where ucd.data_id = :other_guid
354+
and ucd.item_hash in (select i.item_hash from diff_info i)
266355
) r,
267356
table( xmlsequence( extract(r.item_data,'/*') ) ) ucd
268357
) ucd
269358
) act
270-
on exp.row_hash = act.row_hash
271-
and exp.duplicate_no = act.duplicate_no
272-
where exp.row_hash is null or act.row_hash is null]'
359+
on exp.row_hash = act.row_hash
360+
and exp.duplicate_no = act.duplicate_no
361+
where exp.row_hash is null or act.row_hash is null ) where rownum < :max_rows ]'
273362
bulk collect into l_results
274-
using a_exclude_xpath, a_include_xpath, a_expected_dataset_guid,
275-
a_exclude_xpath, a_include_xpath, a_actual_dataset_guid;
363+
using a_diff_id,
364+
a_exclude_xpath, a_include_xpath, a_expected_dataset_guid,
365+
a_exclude_xpath, a_include_xpath, a_actual_dataset_guid,
366+
a_max_rows;
276367

277-
--execute immediate 'create table test as select * from ut_compound_data_tmp';
278368
return l_results;
279369

280370
end;

source/expectations/data_values/ut_compound_data_helper.pks

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ create or replace package ut_compound_data_helper authid definer is
5252
a_max_rows integer, a_exclude_xpath varchar2, a_include_xpath varchar2
5353
) return tt_row_diffs;
5454

55+
function get_rows_diff(
56+
a_expected_dataset_guid raw, a_actual_dataset_guid raw, a_diff_id raw,
57+
a_max_rows integer, a_exclude_xpath varchar2, a_include_xpath varchar2,
58+
a_join_by_xpath varchar2
59+
) return tt_row_diffs;
60+
5561
function get_rows_diff_unordered(
5662
a_expected_dataset_guid raw, a_actual_dataset_guid raw, a_diff_id raw,
5763
a_max_rows integer, a_exclude_xpath varchar2, a_include_xpath varchar2

source/expectations/data_values/ut_compound_data_tmp.sql

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,8 @@ create global temporary table ut_compound_data_tmp(
1515
data_id raw(32),
1616
item_no integer,
1717
item_data xmltype,
18-
constraint ut_compound_data_tmp_pk primary key(data_id, item_no)
18+
item_hash raw(128),
19+
duplicate_no integer
20+
--constraint ut_cmp_data_tmp_item_ak unique (data_id, item_no),
21+
--constraint ut_cmp_data_tmp_hash_pk unique (data_id, item_hash , duplicate_no)
1922
) on commit preserve rows;

source/expectations/data_values/ut_compound_data_value.tpb

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,17 @@ create or replace type body ut_compound_data_value as
7171
return l_result_string;
7272
end;
7373

74-
overriding member function diff( a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2, a_unordered boolean := false ) return varchar2 is
74+
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
7575
l_result clob;
7676
l_result_string varchar2(32767);
7777
begin
78-
l_result := get_data_diff(a_other, a_exclude_xpath, a_include_xpath, a_unordered);
78+
if a_join_by_xpath is not null then
79+
l_result := get_data_diff(a_other, a_exclude_xpath, a_include_xpath, a_join_by_xpath);
80+
elsif a_unordered then
81+
l_result := get_data_diff(a_other, a_exclude_xpath, a_include_xpath, a_unordered);
82+
else
83+
l_result := get_data_diff(a_other, a_exclude_xpath, a_include_xpath, a_join_by_xpath);
84+
end if;
7985
l_result_string := ut_utils.to_string(l_result,null);
8086
dbms_lob.freetemporary(l_result);
8187
return l_result_string;
@@ -102,8 +108,8 @@ create or replace type body ut_compound_data_value as
102108
--diff rows and row elements
103109
l_diff_id := ut_compound_data_helper.get_hash(self.data_id||l_actual.data_id);
104110
-- First tell how many rows are different
105-
execute immediate 'select unordered_cnt from ' || l_ut_owner || '.ut_compound_data_diff_tmp where diff_id = :diff_id' into l_diff_row_count using l_diff_id;
106-
111+
execute immediate 'select count(*) from ' || l_ut_owner || '.ut_compound_data_diff_tmp where diff_id = :diff_id' into l_diff_row_count using l_diff_id;
112+
107113
if l_diff_row_count > 0 then
108114
l_row_diffs := ut_compound_data_helper.get_rows_diff_unordered(
109115
self.data_id, l_actual.data_id, l_diff_id, c_max_rows, a_exclude_xpath, a_include_xpath
@@ -118,14 +124,14 @@ create or replace type body ut_compound_data_value as
118124
for i in 1 .. l_row_diffs.count loop
119125
l_results.extend;
120126
l_results(l_results.last) :=
121-
' Row Appeared '||l_row_diffs(i).rn||' - '||rpad(l_row_diffs(i).diff_type,10)||l_row_diffs(i).diffed_row;
127+
rpad(l_row_diffs(i).diff_type,10)||l_row_diffs(i).diffed_row;
122128
end loop;
123129
ut_utils.append_to_clob(l_result,l_results);
124130
end if;
125131
return l_result;
126132
end;
127133

128-
member function get_data_diff( a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2 ) return clob is
134+
member function get_data_diff( a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2, a_join_by_xpath varchar2) return clob is
129135
c_max_rows constant integer := 20;
130136
l_result clob;
131137
l_results ut_utils.t_clob_tab := ut_utils.t_clob_tab();
@@ -149,9 +155,15 @@ create or replace type body ut_compound_data_value as
149155
execute immediate 'select count(*) from ' || l_ut_owner || '.ut_compound_data_diff_tmp where diff_id = :diff_id' into l_diff_row_count using l_diff_id;
150156

151157
if l_diff_row_count > 0 then
152-
l_row_diffs := ut_compound_data_helper.get_rows_diff(
158+
if a_join_by_xpath is not null then
159+
l_row_diffs := ut_compound_data_helper.get_rows_diff(
160+
self.data_id, l_actual.data_id, l_diff_id, c_max_rows, a_exclude_xpath, a_include_xpath, a_join_by_xpath
161+
);
162+
else
163+
l_row_diffs := ut_compound_data_helper.get_rows_diff(
153164
self.data_id, l_actual.data_id, l_diff_id, c_max_rows, a_exclude_xpath, a_include_xpath
154-
);
165+
);
166+
end if;
155167
l_message := chr(10)
156168
||'Rows: [ ' || l_diff_row_count ||' differences'
157169
|| case when l_diff_row_count > c_max_rows and l_row_diffs.count > 0 then ', showing first '||c_max_rows end
@@ -224,7 +236,7 @@ create or replace type body ut_compound_data_value as
224236
return l_result;
225237
end;
226238

227-
member function compare_implementation(a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2, a_unordered boolean ) return integer is
239+
member function compare_implementation(a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2, a_join_by_xpath varchar2, a_unordered boolean ) return integer is
228240
l_other ut_compound_data_value;
229241
l_ut_owner varchar2(250) := ut_utils.ut_owner;
230242
l_column_filter varchar2(32767);
@@ -241,16 +253,36 @@ member function compare_implementation(a_other ut_data_value, a_exclude_xpath va
241253

242254
l_diff_id := ut_compound_data_helper.get_hash(self.data_id||l_other.data_id);
243255
l_column_filter := ut_compound_data_helper.get_columns_filter(a_exclude_xpath, a_include_xpath);
244-
245-
-- Find differences
246-
l_row_diffs := ut_compound_data_helper.get_rows_diff_unordered(
247-
self.data_id, l_other.data_id, l_diff_id, c_max_rows, a_exclude_xpath, a_include_xpath
248-
);
249-
250-
execute immediate 'insert into ' || l_ut_owner || '.ut_compound_data_diff_tmp ( diff_id, unordered_cnt )
251-
values (:diff_id, nvl(:unordered_cnt,0))' using l_diff_id, l_row_diffs.count;
256+
257+
-- Pre generate hash minus to leave only onese that are diffrent, for example duplicates or diffrent hash
258+
execute immediate 'insert into ' || l_ut_owner || '.ut_compound_data_diff_tmp ( diff_id,item_hash,duplicate_no )
259+
select :diff_id,x.item_hash,tmp.duplicate_no
260+
from(
261+
(
262+
select item_hash,row_number() over (partition by item_hash,data_id order by 1) duplicate_no
263+
from ut_compound_data_tmp
264+
where data_id = :self_guid
265+
minus
266+
select item_hash,row_number() over (partition by item_hash,data_id order by 1)
267+
from ut_compound_data_tmp
268+
where data_id = :other_guid
269+
)
270+
union all
271+
(
272+
select item_hash,row_number() over (partition by item_hash,data_id order by 1)
273+
from ut_compound_data_tmp
274+
where data_id = :other_guid
275+
minus
276+
select item_hash,row_number() over (partition by item_hash,data_id order by 1)
277+
from ut_compound_data_tmp
278+
where data_id = :self_guid
279+
))tmp
280+
,ut_compound_data_tmp x
281+
where tmp.item_hash = x.item_hash'
282+
using l_diff_id, self.data_id, l_other.data_id
283+
,l_other.data_id,self.data_id;
252284
--result is OK only if both are same
253-
if l_row_diffs.count = 0 and self.elements_count = l_other.elements_count then
285+
if sql%rowcount = 0 and self.elements_count = l_other.elements_count then
254286
l_result := 0;
255287
else
256288
l_result := 1;

source/expectations/data_values/ut_compound_data_value.tps

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ create or replace type ut_compound_data_value force under ut_data_value(
4242
overriding member function to_string return varchar2,
4343
overriding member function is_multi_line return boolean,
4444
overriding member function compare_implementation(a_other ut_data_value) return integer,
45-
overriding member function diff( a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2, a_unordered boolean := false ) return varchar2,
45+
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,
4646
member function get_data_diff( a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2, a_unordered boolean ) return clob,
47-
member function get_data_diff( a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2 ) return clob,
47+
member function get_data_diff( a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2, a_join_by_xpath varchar2 ) return clob,
4848
member function compare_implementation(a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2) return integer,
49-
member function compare_implementation(a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2, a_unordered boolean ) return integer
49+
member function compare_implementation(a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2, a_join_by_xpath varchar2, a_unordered boolean ) return integer
5050
) not final not instantiable
5151
/

source/expectations/data_values/ut_data_value.tpb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ create or replace type body ut_data_value as
2525
return false;
2626
end;
2727

28-
member function diff( a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2, a_unordered boolean :=false ) return varchar2 is
28+
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
2929
begin
3030
return null;
3131
end;

source/expectations/data_values/ut_data_value.tps

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ create or replace type ut_data_value force authid current_user as object (
2424
final member function to_string_report(a_add_new_line_for_multi_line boolean := false, a_with_object_info boolean := true) return varchar2,
2525
order member function compare( a_other ut_data_value ) return integer,
2626
member function is_diffable return boolean,
27-
member function diff( a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2, a_unordered boolean := false ) return varchar2,
27+
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,
2828
not instantiable member function compare_implementation( a_other ut_data_value ) return integer
2929
) not final not instantiable
3030
/

0 commit comments

Comments
 (0)