@@ -139,6 +139,7 @@ create or replace type body ut_compound_data_value as
139139 l_actual ut_compound_data_value;
140140 l_diff_id ut_compound_data_helper.t_hash;
141141 l_row_diffs ut_compound_data_helper.tt_row_diffs;
142+
142143 begin
143144 if not a_other is of (ut_compound_data_value) then
144145 raise value_error;
@@ -173,7 +174,11 @@ create or replace type body ut_compound_data_value as
173174 ut_utils.append_to_clob( l_result, l_message );
174175 for i in 1 .. l_row_diffs.count loop
175176 l_results.extend;
176- l_results(l_results.last) := ' Row No. '||l_row_diffs(i).rn||' - '||rpad(l_row_diffs(i).diff_type,10)||l_row_diffs(i).diffed_row;
177+ if a_join_by_xpath is not null and l_row_diffs(i).pk_value is not null then
178+ l_results(l_results.last) := ' '||rpad(l_row_diffs(i).diff_type,10)||l_row_diffs(i).diffed_row||' for key: '||l_row_diffs(i).pk_value;
179+ else
180+ l_results(l_results.last) := ' Row No. '||l_row_diffs(i).rn||' - '||rpad(l_row_diffs(i).diff_type,10)||l_row_diffs(i).diffed_row;
181+ end if;
177182 end loop;
178183 ut_utils.append_to_clob(l_result,l_results);
179184 end if;
@@ -245,16 +250,28 @@ create or replace type body ut_compound_data_value as
245250 l_row_diffs ut_compound_data_helper.tt_row_diffs;
246251 c_max_rows constant integer := 20;
247252
248- type t_fetch_pk_hash_rec is record
253+ type t_pk_val_rec is record
249254 (
250- data_id raw(32),
251- item_hash raw(128),
252- item_data xmltype
255+ data_id raw(32),
256+ item_hash raw(128),
257+ pk_hash raw(128),
258+ pk_value varchar2(4000)
253259 );
254- type t_fetch_pk_hash_tab is table of t_fetch_pk_hash_rec;
255260
256- l_fetch_tab t_fetch_pk_hash_tab;
257- l_pk_hash_cursor sys_refcursor;
261+ type t_pk_val_tab is table of t_pk_val_rec;
262+ l_pk_val_tab t_pk_val_tab;
263+
264+ function get_column_xpath(a_join_by_xpath varchar2) return varchar2 is
265+ l_column varchar2(32767);
266+ begin
267+ if a_join_by_xpath is not null then
268+ l_column := l_ut_owner ||'.ut_compound_data_helper.get_hash(extract(t.item_data,:join_by_xpath).GetClobVal()) pk_hash ';
269+ else
270+ l_column := ':join_by_xpath pk_hash ';
271+ end if;
272+ return l_column;
273+ end;
274+
258275 begin
259276 if not a_other is of (ut_compound_data_value) then
260277 raise value_error;
@@ -268,60 +285,78 @@ create or replace type body ut_compound_data_value as
268285 /**
269286 * Due to incompatibility issues in XML between 11 and 12.2 and 12.1 versions we will prepopulate pk_hash upfront to
270287 * avoid optimizer incorrectly rewrite and causing NULL error or ORA-600
271- **/
288+ **/
289+ -- Pre generate hash minus to leave only onese that are diffrent, for example duplicates or diffrent hash
290+ /*if a_join_by_xpath is not null then
291+ execute immediate q'[select
292+ data_id,item_hash,pk_hash,
293+ listagg(extractvalue(tcd.column_value, '/*'), '; ') within GROUP(ORDER BY item_hash) pk_value
294+ from
295+ (select
296+ ucd.column_value row_data,
297+ ]'|| l_ut_owner ||q'[.ut_compound_data_helper.get_hash(extract(ucd.column_value,:join_xpath).GetClobVal()) pk_hash ,
298+ t.item_hash,
299+ t.data_id
300+ from ]' || l_ut_owner || q'[.ut_compound_data_tmp t ,
301+ table(xmlsequence(extract(t.item_data,'/*'))) ucd
302+ where data_id = :self_guid or data_id = :other_guid ),
303+ table(xmlsequence(extract(row_data ,:join_xpath))) tcd
304+ group by pk_hash,item_hash,data_id]'
305+ bulk collect into l_pk_val_tab using a_join_by_xpath,self.data_id, l_other.data_id,a_join_by_xpath;
272306
273- if a_join_by_xpath is not null then
274-
275- open l_pk_hash_cursor for q'[select t.data_id,t.item_hash,t.item_data
276- from ]'|| l_ut_owner ||q'[.ut_compound_data_tmp t
277- ,xmltable('*'
278- passing t.item_data
279- columns
280- xml_pk_hash clob path ']'|| a_join_by_xpath ||q'['
281- ) ucd
282- where data_id = :self_guid or data_id = :other_guid ]'
283- using self.data_id, l_other.data_id;
284- fetch l_pk_hash_cursor bulk collect into l_fetch_tab;
285- for pks in 1..l_fetch_tab.COUNT
286- loop
287- execute immediate 'update '|| l_ut_owner ||'.ut_compound_data_tmp
288- set pk_hash = '|| l_ut_owner ||'.ut_compound_data_helper.get_hash(extract(:item_data,:join_by_xpath).GetClobVal())
289- where item_hash = :item_hash'
290- using l_fetch_tab(pks).item_data,a_join_by_xpath , l_fetch_tab(pks).item_hash;
291- end loop;
292-
293- close l_pk_hash_cursor;
307+ forall pk_vals in 1..l_pk_val_tab.COUNT
308+ update ut_compound_data_tmp
309+ set pk_hash = l_pk_val_tab(pk_vals).pk_hash
310+ ,pk_value = l_pk_val_tab(pk_vals).pk_value
311+ where data_id = l_pk_val_tab(pk_vals).data_id
312+ and item_hash = l_pk_val_tab(pk_vals).item_hash;
294313 end if;
295-
296-
297- -- Pre generate hash minus to leave only onese that are diffrent, for example duplicates or diffrent hash
298- execute immediate 'insert into ' || l_ut_owner || '.ut_compound_data_diff_tmp ( diff_id,item_hash,pk_hash,duplicate_no )
314+ */
315+
316+ execute immediate 'insert into ' || l_ut_owner || '.ut_compound_data_diff_tmp ( diff_id,item_hash,pk_hash,duplicate_no)
317+ with calc_pk as
318+ ( select data_id,item_hash, '||get_column_xpath(a_join_by_xpath)||'
319+ from ' || l_ut_owner || '.ut_compound_data_tmp t
320+ )
299321 select distinct :diff_id,tmp.item_hash,tmp.pk_hash,tmp.duplicate_no
300322 from(
301323 (
302324 select t.item_hash,row_number() over (partition by t.item_hash,t.data_id order by 1,2) duplicate_no,
303- pk_hash
304- from ' || l_ut_owner || '.ut_compound_data_tmp t
305- where data_id = :self_guid
325+ pc.pk_hash
326+ from ' || l_ut_owner || '.ut_compound_data_tmp t,
327+ calc_pk pc
328+ where t.data_id = :self_guid
329+ and pc.data_id = t.data_id
330+ and pc.item_hash = t.item_hash
306331 minus
307332 select t.item_hash,row_number() over (partition by t.item_hash,t.data_id order by 1,2) duplicate_no,
308- pk_hash
309- from ' || l_ut_owner || '.ut_compound_data_tmp t
310- where data_id = :other_guid
333+ pc.pk_hash
334+ from ' || l_ut_owner || '.ut_compound_data_tmp t,
335+ calc_pk pc
336+ where t.data_id = :other_guid
337+ and pc.data_id = t.data_id
338+ and pc.item_hash = t.item_hash
311339 )
312340 union all
313341 (
314342 select t.item_hash,row_number() over (partition by t.item_hash,t.data_id order by 1,2) duplicate_no,
315- pk_hash
316- from ' || l_ut_owner || '.ut_compound_data_tmp t
317- where data_id = :other_guid
343+ pc.pk_hash
344+ from ' || l_ut_owner || '.ut_compound_data_tmp t,
345+ calc_pk pc
346+ where t.data_id = :other_guid
347+ and pc.data_id = t.data_id
348+ and pc.item_hash = t.item_hash
318349 minus
319350 select t.item_hash,row_number() over (partition by t.item_hash,t.data_id order by 1,2) duplicate_no,
320- pk_hash
321- from ' || l_ut_owner || '.ut_compound_data_tmp t
322- where data_id = :self_guid
351+ pc.pk_hash
352+ from ' || l_ut_owner || '.ut_compound_data_tmp t,
353+ calc_pk pc
354+ where t.data_id = :self_guid
355+ and pc.data_id = t.data_id
356+ and pc.item_hash = t.item_hash
323357 ))tmp'
324- using l_diff_id,
358+ using a_join_by_xpath,
359+ l_diff_id,
325360 self.data_id, l_other.data_id,
326361 l_other.data_id,self.data_id;
327362 --result is OK only if both are same
0 commit comments