Skip to content

Commit 21dca2b

Browse files
committed
Resolve issue with nested table being join
Removing XPATH
1 parent b094911 commit 21dca2b

4 files changed

Lines changed: 151 additions & 24 deletions

File tree

source/expectations/data_values/ut_compound_data_helper.pkb

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,12 @@ create or replace package body ut_compound_data_helper is
429429
if a_data_info.access_path = l_pk_tab(l_index) then
430430
l_sql_stmt := case when a_join_by_stmt is null then null else ' and ' end;
431431
l_sql_stmt := l_sql_stmt ||' a.'||a_col_name||q'[ = ]'||' e.'||a_col_name;
432-
end if;
432+
elsif a_data_info.parent_name = l_pk_tab(l_index)then
433+
--When then table is nested and join is on whole table
434+
--TODO : Can this be done smarter ?
435+
l_sql_stmt := case when a_join_by_stmt is null then null else ' and ' end;
436+
l_sql_stmt := l_sql_stmt ||' a.'||a_col_name||q'[ = ]'||' e.'||a_col_name;
437+
end if;
433438
exit when (a_data_info.access_path = l_pk_tab(l_index)) or l_index = l_pk_tab.count;
434439
l_index := l_pk_tab.next(l_index);
435440
end loop;
@@ -457,7 +462,13 @@ create or replace package body ut_compound_data_helper is
457462
if a_data_info.access_path = l_pk_tab(l_index) then
458463
l_sql_stmt := case when a_partition_stmt is null then null else ',' end;
459464
l_sql_stmt := l_sql_stmt ||l_alias||a_col_name;
465+
elsif a_data_info.parent_name = l_pk_tab(l_index)then
466+
--When then table is nested and join is on whole table
467+
--TODO : Can this be done smarter ?
468+
l_sql_stmt := case when a_partition_stmt is null then null else ',' end;
469+
l_sql_stmt := l_sql_stmt ||l_alias||a_col_name;
460470
end if;
471+
461472
exit when (a_data_info.access_path = l_pk_tab(l_index)) or l_index = l_pk_tab.count;
462473
l_index := l_pk_tab.next(l_index);
463474
end loop;
@@ -515,7 +526,6 @@ create or replace package body ut_compound_data_helper is
515526
begin
516527
if l_cursor_info is not null then
517528
--Parition by piece
518-
--TODO : Collection is intersting exmaple that we probably has to extract full xml and hash it.
519529
ut_utils.append_to_clob(a_partition_stmt,', row_number() over (partition by ');
520530
for i in 1..l_cursor_info.count loop
521531
if l_cursor_info(i).has_nested_col = 0 then
@@ -665,7 +675,6 @@ create or replace package body ut_compound_data_helper is
665675
end if;
666676
ut_utils.append_to_clob(l_compare_sql,l_temp_string);
667677

668-
dbms_output.put_line(l_compare_sql);
669678
return l_compare_sql;
670679
end;
671680

@@ -821,5 +830,19 @@ create or replace package body ut_compound_data_helper is
821830
return l_collection_elements;
822831
end;
823832

833+
function remove_incomparable_cols( a_cursor_details ut_cursor_column_tab,a_incomparable_cols ut_varchar2_list) return ut_cursor_column_tab is
834+
l_result ut_cursor_column_tab;
835+
begin
836+
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,
837+
i.hierarchy_level,i.column_position, i.column_type, i.is_collection)
838+
bulk collect into l_result
839+
from table(a_cursor_details) i
840+
left outer join table(a_incomparable_cols) c
841+
on (i.access_path = c.column_value)
842+
where c.column_value is null;
843+
844+
return l_result;
845+
end;
846+
824847
end;
825848
/

source/expectations/data_values/ut_compound_data_helper.pks

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,5 +116,7 @@ create or replace package ut_compound_data_helper authid definer is
116116

117117
function contains_collection (a_cursor_info ut_cursor_column_tab) return number;
118118

119+
function remove_incomparable_cols( a_cursor_details ut_cursor_column_tab,a_incomparable_cols ut_varchar2_list) return ut_cursor_column_tab;
120+
119121
end;
120122
/

source/expectations/data_values/ut_data_value_refcursor.tpb

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

119+
member function get_data_diff(a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2,
120+
a_join_by_xpath varchar2, a_unordered boolean,a_join_by_list ut_varchar2_list:=ut_varchar2_list()) return clob is
121+
c_max_rows integer := ut_utils.gc_diff_max_rows;
122+
l_result clob;
123+
l_results ut_utils.t_clob_tab := ut_utils.t_clob_tab();
124+
l_message varchar2(32767);
125+
l_ut_owner varchar2(250) := ut_utils.ut_owner;
126+
l_diff_row_count integer;
127+
l_actual ut_compound_data_value;
128+
l_diff_id ut_compound_data_helper.t_hash;
129+
l_row_diffs ut_compound_data_helper.tt_row_diffs;
130+
l_compare_type varchar2(10);
131+
l_self ut_compound_data_value;
132+
133+
function get_diff_message (a_row_diff ut_compound_data_helper.t_row_diffs,a_is_unordered boolean) return varchar2 is
134+
begin
135+
136+
if a_is_unordered then
137+
if a_row_diff.pk_value is not null then
138+
return ' PK '||a_row_diff.pk_value||' - '||rpad(a_row_diff.diff_type,10)||a_row_diff.diffed_row;
139+
else
140+
return rpad(a_row_diff.diff_type,10)||a_row_diff.diffed_row;
141+
end if;
142+
else
143+
return ' Row No. '||a_row_diff.rn||' - '||rpad(a_row_diff.diff_type,10)||a_row_diff.diffed_row;
144+
end if;
145+
end;
146+
147+
begin
148+
if not a_other is of (ut_compound_data_value) then
149+
raise value_error;
150+
end if;
151+
152+
l_actual := treat(a_other as ut_compound_data_value);
153+
154+
dbms_lob.createtemporary(l_result,true);
155+
156+
l_diff_id := ut_compound_data_helper.get_hash(self.data_id||l_actual.data_id);
157+
158+
-- First tell how many rows are different
159+
l_diff_row_count := ut_compound_data_helper.get_rows_diff_count;
160+
--TODO : Change message when the types not matching
161+
if l_diff_row_count > 0 then
162+
l_row_diffs := ut_compound_data_helper.get_rows_diff(
163+
self.data_id, l_actual.data_id, l_diff_id, c_max_rows, a_exclude_xpath,
164+
a_include_xpath, a_join_by_xpath, a_other is of (ut_data_value_refcursor), a_unordered);
165+
l_message := chr(10)
166+
||'Rows: [ ' || l_diff_row_count ||' differences'
167+
|| case when l_diff_row_count > c_max_rows and l_row_diffs.count > 0 then ', showing first '||c_max_rows end
168+
||' ]'||chr(10)|| case when l_row_diffs.count = 0 then ' All rows are different as the columns are not matching.' else null end;
169+
ut_utils.append_to_clob( l_result, l_message );
170+
for i in 1 .. l_row_diffs.count loop
171+
l_results.extend;
172+
l_results(l_results.last) := get_diff_message(l_row_diffs(i),a_unordered);
173+
end loop;
174+
ut_utils.append_to_clob(l_result,l_results);
175+
else
176+
l_message:= chr(10)||'Rows: [ all different ]'||chr(10)||' All rows are different as the columns are not matching.';
177+
ut_utils.append_to_clob( l_result, l_message );
178+
end if;
179+
return l_result;
180+
end;
181+
119182
member function diff( a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2, a_join_by_xpath varchar2,
120183
a_unordered boolean := false, a_join_by_list ut_varchar2_list:=ut_varchar2_list() ) return varchar2 is
121184
l_result clob;
122185
l_results ut_utils.t_clob_tab := ut_utils.t_clob_tab();
123186
l_result_string varchar2(32767);
124187
l_actual ut_data_value_refcursor;
125188
l_column_diffs ut_compound_data_helper.tt_column_diffs := ut_compound_data_helper.tt_column_diffs();
126-
l_exclude_xpath varchar2(32767) := a_exclude_xpath;
127189

190+
l_act_cols ut_cursor_column_tab;
191+
l_exp_cols ut_cursor_column_tab;
192+
128193
l_missing_pk ut_compound_data_helper.tt_missing_pk := ut_compound_data_helper.tt_missing_pk();
129194
l_col_diffs ut_compound_data_helper.tt_column_diffs := ut_compound_data_helper.tt_column_diffs();
130195

196+
c_max_rows integer := ut_utils.gc_diff_max_rows;
197+
l_diff_id ut_compound_data_helper.t_hash;
198+
l_diff_row_count integer;
199+
l_row_diffs ut_compound_data_helper.tt_row_diffs;
200+
l_message varchar2(32767);
201+
131202
function get_col_diff_text(a_col ut_compound_data_helper.t_column_diffs) return varchar2 is
132203
begin
133204
return
@@ -155,59 +226,90 @@ create or replace type body ut_data_value_refcursor as
155226
return l_message;
156227
end;
157228

158-
function add_incomparable_cols_to_xpath(
159-
a_column_diffs ut_compound_data_helper.tt_column_diffs, a_exclude_xpath varchar2
160-
) return varchar2 is
229+
function remove_incomparable_cols( a_cursor_details ut_cursor_column_tab,a_column_diffs ut_compound_data_helper.tt_column_diffs) return ut_cursor_column_tab is
161230
l_incomparable_cols ut_varchar2_list := ut_varchar2_list();
162-
l_result varchar2(32767);
231+
l_filter_out ut_cursor_column_tab;
163232
begin
164233
for i in 1 .. a_column_diffs.count loop
165234
if a_column_diffs(i).diff_type in ('-','+') then
166235
l_incomparable_cols.extend;
167-
l_incomparable_cols(l_incomparable_cols.last) := ut_utils.xmlgen_escaped_string(coalesce(a_column_diffs(i).expected_name,a_column_diffs(i).actual_name));
168-
end if;
236+
l_incomparable_cols(l_incomparable_cols.last) := coalesce(a_column_diffs(i).expected_name,a_column_diffs(i).actual_name);
237+
end if;
169238
end loop;
170-
l_result := ut_utils.to_xpath(l_incomparable_cols);
171-
if a_exclude_xpath is not null and l_result is not null then
172-
l_result := l_result ||'|'||a_exclude_xpath;
173-
else
174-
l_result := coalesce(a_exclude_xpath, l_result);
175-
end if;
176-
return l_result;
239+
240+
return ut_compound_data_helper.remove_incomparable_cols(a_cursor_details,l_incomparable_cols);
177241
end;
178242

243+
function get_diff_message (a_row_diff ut_compound_data_helper.t_row_diffs,a_is_unordered boolean) return varchar2 is
244+
begin
245+
246+
if a_is_unordered then
247+
if a_row_diff.pk_value is not null then
248+
return ' PK '||a_row_diff.pk_value||' - '||rpad(a_row_diff.diff_type,10)||a_row_diff.diffed_row;
249+
else
250+
return rpad(a_row_diff.diff_type,10)||a_row_diff.diffed_row;
251+
end if;
252+
else
253+
return ' Row No. '||a_row_diff.rn||' - '||rpad(a_row_diff.diff_type,10)||a_row_diff.diffed_row;
254+
end if;
255+
end;
256+
179257
begin
180258
if not a_other is of (ut_data_value_refcursor) then
181259
raise value_error;
182260
end if;
183261
l_actual := treat(a_other as ut_data_value_refcursor);
184262

185-
dbms_lob.createtemporary(l_result,true);
263+
l_act_cols := l_actual.cursor_details.cursor_info;
264+
l_exp_cols := self.cursor_details.cursor_info;
186265

266+
dbms_lob.createtemporary(l_result,true);
187267
--diff columns
188268
if not self.is_null and not l_actual.is_null then
189269
l_column_diffs := ut_compound_data_helper.get_columns_diff(self.cursor_details.cursor_info,l_actual.cursor_details.cursor_info);
190270

191271
if l_column_diffs.count > 0 then
192272
ut_utils.append_to_clob(l_result,chr(10) || 'Columns:' || chr(10));
193273
end if;
194-
195274
for i in 1 .. l_column_diffs.count loop
196275
l_results.extend;
197276
l_results(l_results.last) := get_col_diff_text(l_column_diffs(i));
198277
end loop;
199278
ut_utils.append_to_clob(l_result, l_results);
200-
l_exclude_xpath := add_incomparable_cols_to_xpath(l_column_diffs, a_exclude_xpath);
279+
l_act_cols := remove_incomparable_cols(l_actual.cursor_details.cursor_info,l_column_diffs);
280+
l_exp_cols := remove_incomparable_cols(self.cursor_details.cursor_info,l_column_diffs);
201281
end if;
202282

203283
--check for missing pk
204284
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);
285+
l_missing_pk := ut_compound_data_helper.get_missing_pk(l_exp_cols,l_act_cols,a_join_by_list);
206286
end if;
207287

208288
--diff rows and row elements if the pk is not missing
209289
if l_missing_pk.count = 0 then
210-
ut_utils.append_to_clob(l_result, self.get_data_diff(a_other, a_exclude_xpath, a_include_xpath, a_join_by_xpath, a_unordered));
290+
l_diff_id := ut_compound_data_helper.get_hash(self.data_id||l_actual.data_id);
291+
292+
-- First tell how many rows are different
293+
l_diff_row_count := ut_compound_data_helper.get_rows_diff_count;
294+
l_results := ut_utils.t_clob_tab();
295+
if l_diff_row_count > 0 then
296+
l_row_diffs := ut_compound_data_helper.get_rows_diff(
297+
self.data_id, l_actual.data_id, l_diff_id, c_max_rows, a_exclude_xpath,
298+
a_include_xpath, a_join_by_xpath, a_other is of (ut_data_value_refcursor), a_unordered);
299+
l_message := chr(10)
300+
||'Rows: [ ' || l_diff_row_count ||' differences'
301+
|| case when l_diff_row_count > c_max_rows and l_row_diffs.count > 0 then ', showing first '||c_max_rows end
302+
||' ]'||chr(10)|| case when l_row_diffs.count = 0 then ' All rows are different as the columns are not matching.' else null end;
303+
ut_utils.append_to_clob( l_result, l_message );
304+
for i in 1 .. l_row_diffs.count loop
305+
l_results.extend;
306+
l_results(l_results.last) := get_diff_message(l_row_diffs(i),a_unordered);
307+
end loop;
308+
ut_utils.append_to_clob(l_result,l_results);
309+
else
310+
l_message:= chr(10)||'Rows: [ all different ]'||chr(10)||' All rows are different as the columns are not matching.';
311+
ut_utils.append_to_clob( l_result, l_message );
312+
end if;
211313
else
212314
ut_utils.append_to_clob(l_result,chr(10) || 'Unable to join sets:' || chr(10));
213315
for i in 1 .. l_missing_pk.count loop
@@ -242,13 +344,11 @@ create or replace type body ut_data_value_refcursor as
242344

243345
l_actual := treat(a_other as ut_data_value_refcursor);
244346

245-
--if we join by key and key is missing fail and report error
246347
if a_join_by_list.count > 0 then
247348
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);
248349
l_result := case when (l_pk_missing_tab.count > 0) then 1 else 0 end;
249350
end if;
250351

251-
252352
if l_result = 0 then
253353
if (self.cursor_details is not null and l_actual.cursor_details is not null) and (self.cursor_details != l_actual.cursor_details) then
254354
l_result := 1;

source/expectations/data_values/ut_data_value_refcursor.tps

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ create or replace type ut_data_value_refcursor under ut_compound_data_value(
5252
constructor function ut_data_value_refcursor(self in out nocopy ut_data_value_refcursor, a_value sys_refcursor) return self as result,
5353
member procedure init(self in out nocopy ut_data_value_refcursor, a_value sys_refcursor),
5454
overriding member function to_string return varchar2,
55+
member function get_data_diff(a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2,
56+
a_join_by_xpath varchar2, a_unordered boolean,a_join_by_list ut_varchar2_list:=ut_varchar2_list()) return clob,
5557
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
5658
,a_join_by_list ut_varchar2_list:=ut_varchar2_list()) return varchar2,
5759
overriding member function compare_implementation(a_other ut_data_value, a_unordered boolean, a_inclusion_compare boolean := false,

0 commit comments

Comments
 (0)