@@ -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;
0 commit comments