@@ -137,104 +137,74 @@ create or replace type body ut_data_value_refcursor as
137137
138138 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 := 20;
140- c_pad_depth constant integer := 5;
141140 l_results ut_utils.t_clob_tab;
142141 l_result clob;
143142 l_result_string varchar2(32767);
144143 l_ut_owner varchar2(250) := ut_utils.ut_owner;
145144 l_diff_row_count integer;
146- l_other ut_data_value_refcursor;
145+ l_actual ut_data_value_refcursor;
147146 l_diff_id raw(16);
148- l_column_filter varchar2(32767);
149- l_sql varchar2(32767);
147+ l_column_diffs ut_refcursor_helper.tt_column_diffs;
148+ l_row_diffs ut_refcursor_helper.tt_row_diffs;
149+ l_exclude_list ut_varchar2_list := ut_varchar2_list();
150+ l_exclude_xpath varchar2(32767);
150151 begin
151152 if not a_other is of (ut_data_value_refcursor) then
152153 raise value_error;
153154 end if;
154- l_other := treat(a_other as ut_data_value_refcursor);
155+ l_actual := treat(a_other as ut_data_value_refcursor);
155156
156157 dbms_lob.createtemporary(l_result,true);
157158
158- l_column_filter := ut_refcursor_helper.get_columns_filter(a_exclude_xpath, a_include_xpath);
159- if not self.is_null and not l_other.is_null then
160- l_sql :=
161- 'with ' ||
162- ' self_cols as (' ||
163- ' select r.column_value.getstringval() col, rownum rn ' ||
164- ' from ( select '||l_column_filter||
165- ' from ( select :columns_info as item_data from dual ) ucd' ||
166- ' ) s, ' ||
167- ' table( xmlsequence(extract(s.item_data,''/ROW/*'')) ) r' ||
168- ' ),'||
169- ' other_cols as (' ||
170- ' select r.column_value.getstringval() col, rownum rn ' ||
171- ' from ( select '||l_column_filter||
172- ' from (select :columns_info as item_data from dual ) ucd' ||
173- ' ) s, ' ||
174- ' table( xmlsequence(extract(s.item_data,''/ROW/*'')) ) r' ||
175- ' ) ' ||
176- q'[select case when e.rn is null then '+' else '-' end
177- ||'Col No. '||rpad( nvl(a.rn,e.rn), :c_pad_depth)
178- ||' '||nvl(e.col, a.col)]' ||
179- ' from self_cols e' ||
180- ' full outer join other_cols a ' ||
181- ' on a.rn = e.rn and a.col = e.col' ||
182- ' where a.rn is null or e.rn is null' ||
183- ' order by NVL(a.rn,e.rn), a.rn';
184- execute immediate l_sql bulk collect into l_results
185- using a_exclude_xpath, a_include_xpath, self.columns_info,
186- a_exclude_xpath, a_include_xpath, l_other.columns_info, c_pad_depth;
159+ if not self.is_null and not l_actual.is_null then
160+
161+ l_column_diffs := ut_refcursor_helper.get_columns_diff(self.columns_info, l_actual.columns_info, a_exclude_xpath, a_include_xpath);
162+
163+ select case diff_type
164+ when '-' then ' Column <'||expected_name||'> [data-type: '||expected_type||'] is missing. Expected column position: '||expected_pos||'.'
165+ when '+' then ' Column <'||actual_name||'> [position: '||actual_pos||', data-type: '||actual_type||'] is not expected in results.'
166+ when 't' then ' Column <'||actual_name||'> data-type is invalid. Expected: '||expected_type||', actual: '||actual_type||'.'
167+ when 'p' then ' Column <'||actual_name||'> is misplaced. Expected position: '||expected_pos||', actual position: '||actual_pos||'.'
168+ end diff_msg
169+ bulk collect into l_results
170+ from table(l_column_diffs)
171+ order by expected_pos, actual_pos;
187172
188173 if l_results.count > 0 then
189174 ut_utils.append_to_clob(l_result,chr(10) || 'Columns:' || chr(10));
190175 ut_utils.append_to_clob(l_result,l_results);
191176 end if;
177+
178+ select coalesce(expected_name,actual_name)
179+ bulk collect into l_exclude_list
180+ from table(l_column_diffs)
181+ where diff_type in ('-','+');
182+ end if;
183+ l_exclude_xpath := ut_utils.to_xpath(l_exclude_list);
184+ if a_exclude_xpath is not null then
185+ l_exclude_xpath := l_exclude_xpath || a_exclude_xpath;
192186 end if;
193187
194- l_diff_id := dbms_crypto.hash(self.data_set_guid||l_other .data_set_guid,2);
188+ l_diff_id := dbms_crypto.hash(self.data_set_guid||l_actual .data_set_guid,2);
195189 -- First tell how many rows are different
196190 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;
197191
198192 if l_diff_row_count > 0 then
199- --return rows which were previously marked as different
200- l_sql :=
201- q'[with diff_info as (select item_no from ]' || l_ut_owner || q'[.ut_data_set_diff_tmp ucdc where diff_id = :diff_guid and rownum <= :max_rows)
202- select ind||'Row No. '||rpad( rn, :c_pad_depth)||xmlserialize(content data_item no indent) diff
203- from (select nvl(exp.rn, act.rn) rn,
204- xmlagg(exp.col order by exp.col_no) exp_item,
205- xmlagg(act.col order by act.col_no) act_item
206- from (select r.item_no as rn, rownum col_no, s.column_value col,
207- extract(s.column_value,'/*/text()|/*/*').getclobval() col_val
208- from (select ]'||l_column_filter||q'[, ucd.item_no
209- from ]' || l_ut_owner || q'[.ut_data_set_tmp ucd
210- where ucd.data_set_guid = :self_guid
211- and ucd.item_no in (select i.item_no from diff_info i)
212- ) r,
213- table( xmlsequence( extract(r.item_data,'ROW/*') ) ) s
214- ) exp
215- full outer join (
216- select item_no as rn, rownum col_no, s.column_value col,
217- extract(s.column_value,'/*/text()|/*/*').getclobval() col_val
218- from (select ]'||l_column_filter||q'[, ucd.item_no
219- from ]' || l_ut_owner || q'[.ut_data_set_tmp ucd
220- where ucd.data_set_guid = :other_guid
221- and ucd.item_no in (select i.item_no from diff_info i)
222- ) r,
223- table( xmlsequence( extract(r.item_data,'ROW/*') ) ) s
224- ) act
225- on (exp.rn = act.rn and exp.col_no = act.col_no)
226- where (exp.rn is null and act.rn is not null or exp.rn is not null and act.rn is null)
227- or nvl(dbms_lob.compare(exp.col_val, act.col_val),1) != 0 and (exp.col_val is not null or act.col_val is not null)
228- group by nvl(exp.rn, act.rn)
229- )
230- unpivot (data_item for ind in (exp_item as '-', act_item as '+'))
231- order by rn, ind]';
232- execute immediate l_sql
193+ l_row_diffs := ut_refcursor_helper.get_rows_diff(
194+ self.data_set_guid, l_actual.data_set_guid, l_diff_id,
195+ c_max_rows, l_exclude_xpath, a_include_xpath
196+ );
197+
198+ select ' Row No. '||rn||' - '||rpad(diff_type,10)||diffed_row diff
233199 bulk collect into l_results
234- using l_diff_id, c_max_rows, c_pad_depth,
235- a_exclude_xpath, a_include_xpath, self.data_set_guid,
236- a_exclude_xpath, a_include_xpath, l_other.data_set_guid;
237- ut_utils.append_to_clob(l_result,chr(10) || 'Rows: [ diff count = ' || to_char(l_diff_row_count) ||' ]' || chr(10));
200+ from table(l_row_diffs)
201+ order by rn, diff_type;
202+
203+ if l_results.count = 0 then
204+ ut_utils.append_to_clob(l_result,chr(10) || 'Rows:'||chr(10)||' All rows are different as the columns are not matching.');
205+ else
206+ ut_utils.append_to_clob(l_result,chr(10) || 'Rows: [ diff count = ' || to_char(l_diff_row_count) ||' ]' || chr(10));
207+ end if;
238208 ut_utils.append_to_clob(l_result,l_results);
239209 end if;
240210
0 commit comments