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

Skip to content

Commit 06e92c6

Browse files
committed
Added ability to Diff columns (name and datatype differences).
1 parent daef404 commit 06e92c6

8 files changed

Lines changed: 108 additions & 34 deletions

File tree

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 ) return varchar2 is
28+
member function diff( a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2 ) 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 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 ) return varchar2,
27+
member function diff( a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2 ) return varchar2,
2828
not instantiable member function compare_implementation( a_other ut_data_value ) return integer
2929
) not final not instantiable
3030
/

source/expectations/data_values/ut_data_value_refcursor.tpb

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ create or replace type body ut_data_value_refcursor as
135135
return true;
136136
end;
137137

138-
overriding member function diff( a_other ut_data_value ) return varchar2 is
138+
overriding member function diff( a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2 ) return varchar2 is
139139
c_max_rows constant integer := 50;
140140
c_pad_depth constant integer := 5;
141141
l_results ut_utils.t_clob_tab;
@@ -145,26 +145,66 @@ create or replace type body ut_data_value_refcursor as
145145
l_diff_row_count integer;
146146
l_other ut_data_value_refcursor;
147147
l_diff_id raw(16);
148+
l_sql varchar2(32767);
148149
begin
149150
if not a_other is of (ut_data_value_refcursor) then
150151
raise value_error;
151152
end if;
152153
l_other := treat(a_other as ut_data_value_refcursor);
153-
l_diff_id := dbms_crypto.hash(self.data_set_guid||l_other.data_set_guid,2);
154+
154155
dbms_lob.createtemporary(l_result,true);
156+
157+
if not self.is_null and not l_other.is_null then
158+
l_sql :=
159+
'with ' ||
160+
' self_cols as (' ||
161+
' select r.column_value.getstringval() col, rownum rn ' ||
162+
' from ( select '||ut_refcursor_helper.get_columns_filter(a_exclude_xpath, a_include_xpath)||
163+
' from ( select :columns_info as item_data from dual ) ucd' ||
164+
' ) s, ' ||
165+
' table( xmlsequence(extract(s.item_data,''/ROW/*'')) ) r' ||
166+
' ),'||
167+
' other_cols as (' ||
168+
' select r.column_value.getstringval() col, rownum rn ' ||
169+
' from ( select '||ut_refcursor_helper.get_columns_filter(a_exclude_xpath, a_include_xpath)||
170+
' from (select :columns_info as item_data from dual ) ucd' ||
171+
' ) s, ' ||
172+
' table( xmlsequence(extract(s.item_data,''/ROW/*'')) ) r' ||
173+
' ) ' ||
174+
q'[select case when e.rn is null then '+' else '-' end
175+
||'Col No. '||rpad( nvl(a.rn,e.rn), :c_pad_depth)
176+
||' '||nvl(e.col, a.col)]' ||
177+
' from self_cols e' ||
178+
' full outer join other_cols a ' ||
179+
' on a.rn = e.rn and a.col = e.col' ||
180+
' where a.rn is null or e.rn is null' ||
181+
' order by NVL(a.rn,e.rn), a.rn';
182+
execute immediate l_sql bulk collect into l_results
183+
using a_exclude_xpath, a_include_xpath, self.columns_info,
184+
a_exclude_xpath, a_include_xpath, l_other.columns_info, c_pad_depth;
185+
186+
if l_results.count > 0 then
187+
ut_utils.append_to_clob(l_result,chr(10) || 'Columns:' || chr(10));
188+
ut_utils.append_to_clob(l_result,l_results);
189+
end if;
190+
end if;
191+
192+
l_diff_id := dbms_crypto.hash(self.data_set_guid||l_other.data_set_guid,2);
155193
-- First tell how many rows are different
156194
execute immediate 'select count(*) from ' || l_ut_owner || '.ut_data_set_diff_tmp where diff_id = :diff_id' into l_diff_row_count using l_diff_id;
157195

158-
--return rows which were previously marked as different
159-
execute immediate q'[select 'row_no: '||rpad( ucd.item_no, :c_pad_depth )||' '||xmlserialize( content ucd.item_data no indent)
160-
from ]' || l_ut_owner || '.ut_data_set_tmp ucd
161-
where ucd.data_set_guid = :self_guid
162-
and ucd.item_no in (select item_no from ' || l_ut_owner || '.ut_data_set_diff_tmp ucdc where diff_id = :diff_id)
163-
and rownum <= :max_rows'
196+
if l_diff_row_count > 0 then
197+
--return rows which were previously marked as different
198+
execute immediate
199+
q'[select 'Row No. '||rpad( ucd.item_no, :c_pad_depth )||' '||xmlserialize( content ucd.item_data no indent)
200+
from ]' || l_ut_owner || '.ut_data_set_tmp ucd
201+
where ucd.data_set_guid = :self_guid
202+
and ucd.item_no in (select item_no from ' || l_ut_owner || '.ut_data_set_diff_tmp ucdc where diff_id = :diff_id)
203+
and rownum <= :max_rows'
164204
bulk collect into l_results using c_pad_depth, self.data_set_guid, l_diff_id, c_max_rows;
165-
166-
ut_utils.append_to_clob(l_result,'[ count = ' || to_char(l_diff_row_count) ||' ]' || chr(10));
167-
ut_utils.append_to_clob(l_result,l_results);
205+
ut_utils.append_to_clob(l_result,chr(10) || 'Rows: [ diff count = ' || to_char(l_diff_row_count) ||' ]' || chr(10));
206+
ut_utils.append_to_clob(l_result,l_results);
207+
end if;
168208

169209
l_result_string := ut_utils.to_string(l_result,null);
170210
dbms_lob.freetemporary(l_result);

source/expectations/data_values/ut_data_value_refcursor.tps

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ create or replace type ut_data_value_refcursor under ut_data_value(
4646
overriding member function is_diffable return boolean,
4747
overriding member function get_object_info return varchar2,
4848
overriding member function to_string return varchar2,
49-
overriding member function diff( a_other ut_data_value ) return varchar2,
49+
overriding member function diff( a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2 ) return varchar2,
5050
member function is_empty return boolean,
5151
overriding member function is_multi_line return boolean,
5252
member function compare_implementation(a_other ut_data_value, a_exclude_xpath varchar2, a_include_xpath varchar2) return integer,

source/expectations/matchers/ut_equal.tpb

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -190,18 +190,24 @@ create or replace type body ut_equal as
190190
return l_result;
191191
end;
192192

193-
overriding member function run_matcher(self in out nocopy ut_equal, a_actual ut_data_value) return boolean is
193+
member function get_include_xpath return varchar2 is
194+
begin
195+
return ut_utils.to_xpath( coalesce(include_list, ut_varchar2_list()) );
196+
end;
197+
198+
member function get_exclude_xpath return varchar2 is
199+
begin
200+
return ut_utils.to_xpath( coalesce(exclude_list, ut_varchar2_list()) );
201+
end;
202+
203+
overriding member function run_matcher(self in out nocopy ut_equal, a_actual ut_data_value) return boolean is
194204
l_result boolean;
195-
l_exclude_xpath varchar2(32767);
196-
l_include_xpath varchar2(32767);
197205
begin
198206
if self.expected.data_type = a_actual.data_type then
199-
l_exclude_xpath := ut_utils.to_xpath( coalesce(exclude_list, ut_varchar2_list()) );
200-
l_include_xpath := ut_utils.to_xpath( coalesce(include_list, ut_varchar2_list()) );
201207
if self.expected is of (ut_data_value_anydata) then
202-
l_result := 0 = treat(self.expected as ut_data_value_anydata).compare_implementation(a_actual, l_exclude_xpath, l_include_xpath);
208+
l_result := 0 = treat(self.expected as ut_data_value_anydata).compare_implementation(a_actual, get_exclude_xpath(), get_include_xpath());
203209
elsif self.expected is of (ut_data_value_refcursor) then
204-
l_result := 0 = treat(self.expected as ut_data_value_refcursor).compare_implementation(a_actual, l_exclude_xpath, l_include_xpath);
210+
l_result := 0 = treat(self.expected as ut_data_value_refcursor).compare_implementation(a_actual, get_exclude_xpath(), get_include_xpath());
205211
else
206212
l_result := equal_with_nulls((self.expected = a_actual), a_actual);
207213
end if;
@@ -217,7 +223,7 @@ overriding member function run_matcher(self in out nocopy ut_equal, a_actual ut_
217223
begin
218224
l_result := (self as ut_matcher).failure_message(a_actual) || ': '|| self.expected.to_string_report();
219225
if self.expected.data_type = a_actual.data_type and self.expected.is_diffable then
220-
l_result := l_result || chr(10) || 'diff: ' || expected.diff(a_actual);
226+
l_result := l_result || chr(10) || 'diff: ' || expected.diff(a_actual, get_exclude_xpath(), get_include_xpath());
221227
end if;
222228
return l_result;
223229
end;

source/expectations/matchers/ut_equal.tps

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ create or replace type ut_equal under ut_comparison_matcher(
4949
member function include(a_items ut_varchar2_list) return ut_equal,
5050
member function exclude(a_items varchar2) return ut_equal,
5151
member function exclude(a_items ut_varchar2_list) return ut_equal,
52+
member function get_include_xpath return varchar2,
53+
member function get_exclude_xpath return varchar2,
5254
overriding member function run_matcher(self in out nocopy ut_equal, a_actual ut_data_value) return boolean,
5355
overriding member function failure_message(a_actual ut_data_value) return varchar2,
5456
overriding member function failure_message_when_negated(a_actual ut_data_value) return varchar2

test/core/expectations/compound_data/test_expectations_cursor.pkb

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -580,8 +580,9 @@ was expected to equal: (refcursor [ count = 3 ])
580580
<ROW><RN>1</RN></ROW>%
581581
<ROW><RN>2</RN></ROW>%
582582
<ROW><RN>3</RN></ROW>%
583-
diff: [ count = 1 ]%
584-
row_no: 3 <ROW><RN>3</RN></ROW>%]';
583+
diff:%
584+
Rows: [ diff count = 1 ]%
585+
Row No. 3 <ROW><RN>3</RN></ROW>%]';
585586
l_actual_message := ut3.ut_expectation_processor.get_failed_expectations()(1).message;
586587
--Assert
587588
ut.expect(l_actual_message).to_be_like(l_expected_message);
@@ -601,7 +602,6 @@ row_no: 3 <ROW><RN>3</RN></ROW>%]';
601602
ut.expect(expectations.failed_expectations_data()).to_be_empty();
602603
end;
603604

604-
--%test(Reports column diff on cusror with different column data-type)
605605
procedure column_diff_on_data_type_diff is
606606
l_actual sys_refcursor;
607607
l_expected sys_refcursor;
@@ -626,23 +626,50 @@ was expected to equal: (refcursor [ count = 2 ])
626626
Data:
627627
<ROW><RN>1</RN><ANOTHER_RN>1</ANOTHER_RN></ROW>%
628628
<ROW><RN>2</RN><ANOTHER_RN>2</ANOTHER_RN></ROW>%
629-
<ROW><RN>3</RN><ANOTHER_RN>3</ANOTHER_RN></ROW>%
630-
diff:
631-
Columns:
632-
+<RN>VARCHAR2</RN>
633-
-<RN>NUMBER</RN>%]';
629+
diff:%
630+
Columns:%
631+
+Col No. 1 <RN>VARCHAR2</RN>%
632+
-Col No. 1 <RN>NUMBER</RN>%]';
634633
l_actual_message := ut3.ut_expectation_processor.get_failed_expectations()(1).message;
635634
--Assert
636635
ut.expect(l_actual_message).to_be_like(l_expected_message);
637636
end;
638637

639638
--%test(Reports column diff on cusror with different column name)
640639
procedure column_diff_on_col_name_diff is
640+
l_actual sys_refcursor;
641+
l_expected sys_refcursor;
642+
l_actual_message varchar2(32767);
643+
l_expected_message varchar2(32767);
641644
begin
642-
null;
645+
--Arrange
646+
open l_actual for select rownum rn, rownum bad_column_name from dual connect by level <=2;
647+
open l_expected for select rownum rn, rownum expected_column_name from dual connect by level <=2;
648+
--Act
649+
ut3.ut.expect(l_actual).to_equal(l_expected);
650+
651+
l_expected_message := q'[Actual: (refcursor [ count = 2 ])
652+
Data-types:
653+
<ROW><RN>NUMBER</RN><BAD_COLUMN_NAME>NUMBER</BAD_COLUMN_NAME></ROW>
654+
Data:
655+
<ROW><RN>1</RN><BAD_COLUMN_NAME>1</BAD_COLUMN_NAME></ROW>%
656+
<ROW><RN>2</RN><BAD_COLUMN_NAME>2</BAD_COLUMN_NAME></ROW>%
657+
was expected to equal: (refcursor [ count = 2 ])
658+
Data-types:
659+
<ROW><RN>NUMBER</RN><EXPECTED_COLUMN_NAME>NUMBER</EXPECTED_COLUMN_NAME></ROW>
660+
Data:
661+
<ROW><RN>1</RN><EXPECTED_COLUMN_NAME>1</EXPECTED_COLUMN_NAME></ROW>%
662+
<ROW><RN>2</RN><EXPECTED_COLUMN_NAME>2</EXPECTED_COLUMN_NAME></ROW>%
663+
diff:%
664+
Columns:%
665+
+Col No. 2 <BAD_COLUMN_NAME>NUMBER</BAD_COLUMN_NAME>%
666+
-Col No. 2 <EXPECTED_COLUMN_NAME>NUMBER</EXPECTED_COLUMN_NAME>%]';
667+
l_actual_message := ut3.ut_expectation_processor.get_failed_expectations()(1).message;
668+
--Assert
669+
ut.expect(l_actual_message).to_be_like(l_expected_message);
643670
end;
644671

645-
--%test(Reports only mismatched columns on column value mismatch)
672+
--%test(Reports only mismatched columns on column data mismatch)
646673
procedure data_diff_on_col_data_mismatch is
647674
begin
648675
null;

test/core/expectations/compound_data/test_expectations_cursor.pks

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,9 @@ create or replace package test_expectations_cursor is
132132
procedure column_diff_on_data_type_diff;
133133

134134
--%test(Reports column diff on cusror with different column name)
135-
--%disabled
136135
procedure column_diff_on_col_name_diff;
137136

138-
--%test(Reports only mismatched columns on column value mismatch)
137+
--%test(Reports only mismatched columns on column data mismatch)
139138
--%disabled
140139
procedure data_diff_on_col_data_mismatch;
141140

0 commit comments

Comments
 (0)