@@ -184,9 +184,7 @@ create or replace package body ut_compound_data_helper is
184184 l_act_col_filter := get_columns_row_filter(a_exclude_xpath,a_include_xpath,'ucd','act_item_data');
185185 l_exp_col_filter := get_columns_row_filter(a_exclude_xpath,a_include_xpath,'ucd','exp_item_data');
186186
187- --TODO: Generate SQL based on input as unorder join should aggregate
188-
189- l_sql := q'[with exp as (
187+ l_sql := q'[with exp as (
190188 select exp_item_data, exp_data_id, item_no rn,rownum col_no,
191189 nvl2(exp_item_data,ut3.ut_compound_data_helper.get_pk_value(i.join_by,exp_item_data),null) pk_value,
192190 s.column_value col, s.column_value.getRootElement() col_name, s.column_value.getclobval() col_val
@@ -366,6 +364,11 @@ create or replace package body ut_compound_data_helper is
366364 return dbms_crypto.hash(a_data, a_hash_type);
367365 end;
368366
367+ function get_fixed_size_hash(a_string varchar2, a_base integer :=0,a_size integer :=30) return number is
368+ begin
369+ return dbms_utility.get_hash_value(a_string,a_base,a_size);
370+ end;
371+
369372 function columns_hash(
370373 a_data_value_cursor ut_data_value_refcursor, a_exclude_xpath varchar2, a_include_xpath varchar2,
371374 a_hash_type binary_integer := dbms_crypto.hash_sh1
@@ -435,10 +438,10 @@ create or replace package body ut_compound_data_helper is
435438 l_index := l_pk_tab.first;
436439 if l_pk_tab.count > 0 then
437440 loop
438- if a_data_info.column_name = l_pk_tab(l_index) then
441+ if a_data_info.access_path = l_pk_tab(l_index) then
439442 l_exists := true;
440443 end if;
441- exit when l_index = l_pk_tab.count or (a_data_info.column_name = l_pk_tab(l_index));
444+ exit when l_index = l_pk_tab.count or (a_data_info.access_path = l_pk_tab(l_index));
442445 l_index := a_pk_table.next(l_index);
443446 end loop;
444447 end if;
@@ -459,12 +462,12 @@ create or replace package body ut_compound_data_helper is
459462 if l_pk_tab.count <> 0 then
460463 l_index:= l_pk_tab.first;
461464 loop
462- if a_data_info.column_name = a_pk_table (l_index) then
463- l_sql_stmt := l_sql_stmt || case when a_join_by_stmt is null then null else ' and ' end;
465+ if a_data_info.access_path = l_pk_tab (l_index) then
466+ l_sql_stmt := case when a_join_by_stmt is null then null else ' and ' end;
464467 l_sql_stmt := l_sql_stmt ||' a.'||a_col_name||q'[ = ]'||' e.'||a_col_name;
465468 end if;
466- exit when (a_data_info.column_name = a_pk_table (l_index)) or l_index = a_pk_table .count;
467- l_index := a_pk_table .next(l_index);
469+ exit when (a_data_info.access_path = l_pk_tab (l_index)) or l_index = l_pk_tab .count;
470+ l_index := l_pk_tab .next(l_index);
468471 end loop;
469472 ut_utils.append_to_clob(a_join_by_stmt,l_sql_stmt);
470473 end if;
@@ -477,10 +480,26 @@ create or replace package body ut_compound_data_helper is
477480 ut_utils.append_to_clob(a_equal_stmt,l_sql_stmt);
478481 end;
479482
480- procedure generate_partition_stmt(a_partition_stmt in out nocopy clob,a_col_name in varchar2) is
483+ procedure generate_partition_stmt(a_data_info ut_cursor_column, a_partition_stmt in out nocopy clob,a_pk_table in ut_varchar2_list ,a_col_name in varchar2) is
481484 l_alias varchar2(10) := 'ucd.';
485+ l_pk_tab ut_varchar2_list := coalesce(a_pk_table,ut_varchar2_list());
486+ l_index integer;
487+ l_sql_stmt varchar2(32767);
482488 begin
483- ut_utils.append_to_clob(a_partition_stmt,case when a_partition_stmt is null then null else ',' end||l_alias||a_col_name);
489+ if l_pk_tab.count <> 0 then
490+ l_index:= l_pk_tab.first;
491+ loop
492+ if a_data_info.access_path = l_pk_tab(l_index) then
493+ l_sql_stmt := case when a_partition_stmt is null then null else ',' end;
494+ l_sql_stmt := l_sql_stmt ||l_alias||a_col_name;
495+ end if;
496+ exit when (a_data_info.access_path = l_pk_tab(l_index)) or l_index = l_pk_tab.count;
497+ l_index := l_pk_tab.next(l_index);
498+ end loop;
499+ else
500+ l_sql_stmt := case when a_partition_stmt is null then null else ',' end ||l_alias||a_col_name;
501+ end if;
502+ ut_utils.append_to_clob(a_partition_stmt,l_sql_stmt);
484503 end;
485504
486505 procedure generate_select_stmt(a_data_info ut_cursor_column,a_sql_stmt in out nocopy clob, a_col_name varchar2) is
@@ -506,7 +525,7 @@ create or replace package body ut_compound_data_helper is
506525 elsif a_data_info.is_sql_diffable = 1 and a_data_info.column_type = 'DATE' then
507526 l_col_type := 'TIMESTAMP';
508527 else
509- l_col_type := a_data_info.column_type||'('||a_data_info.column_len||')';
528+ l_col_type := a_data_info.column_type||case when a_data_info.column_len is not null then '('||a_data_info.column_len||')' else null end ;
510529 end if;
511530 l_sql_stmt := ' '||a_col_name||' '||l_col_type||q'[ PATH ']'||a_data_info.access_path||q'[',]';
512531 ut_utils.append_to_clob(a_sql_stmt, l_sql_stmt);
@@ -517,30 +536,32 @@ create or replace package body ut_compound_data_helper is
517536 a_not_equal_stmt out nocopy clob) is
518537 l_cursor_info ut_cursor_column_tab := a_data_info.cursor_details.cursor_info;
519538 l_partition_tmp clob;
520- l_col_name varchar2(30 );
539+ l_col_name varchar2(100 );
521540 begin
522541 if l_cursor_info is not null then
523- --Parition by piece
542+ --Parition by piece
543+ --TODO : Collection is intersting exmaple that we probably has to extract full xml and hash it.
524544 ut_utils.append_to_clob(a_partition_stmt,', row_number() over (partition by ');
525- --TODO : Handle nested objects...
526545 for i in 1..l_cursor_info.count loop
546+ if l_cursor_info(i).is_user_defined = 0 then
527547 l_col_name := case when l_cursor_info(i).parent_name is null then
528548 l_cursor_info(i).xml_valid_name
529549 else
530- utl_raw.cast_to_varchar2( l_cursor_info(i).nested_name)
550+ l_cursor_info(i).nested_name
531551 end;
532552 --Get XMLTABLE column list
533553 generate_xmltab_stmt(l_cursor_info(i),a_xml_stmt,l_col_name);
534554 --Get Select statment list of columns
535555 generate_select_stmt(l_cursor_info(i),a_select_stmt,l_col_name);
536556 --Get columns by which we partition
537- generate_partition_stmt(l_partition_tmp,l_col_name);
557+ generate_partition_stmt(l_cursor_info(i), l_partition_tmp,a_pk_table ,l_col_name);
538558 --Get equal statement
539559 generate_equal_sql(a_equal_stmt,l_col_name);
540560 --Generate join by stmt
541561 generate_join_by_stmt(l_cursor_info(i),a_pk_table,a_join_by_stmt,l_col_name);
542562 --Generate not equal stmt
543563 generate_not_equal_stmt(l_cursor_info(i),a_pk_table,a_not_equal_stmt,l_col_name);
564+ end if;
544565 end loop;
545566 --Finish parition by
546567 ut_utils.append_to_clob(a_partition_stmt,l_partition_tmp||' order by '||l_partition_tmp||' ) dup_no ');
@@ -550,9 +571,8 @@ create or replace package body ut_compound_data_helper is
550571 end if;
551572 end;
552573
553- function gen_compare_sql(a_column_info xmltype, a_exclude_xpath varchar2, a_include_xpath varchar2,
554- a_join_by_xpath varchar2, a_inclusion_type boolean, a_is_negated boolean,
555- a_unordered boolean, a_other ut_data_value_refcursor :=null, a_join_by_list ut_varchar2_list:=null ) return clob is
574+ function gen_compare_sql(a_column_info xmltype,a_inclusion_type boolean, a_is_negated boolean,a_unordered boolean,
575+ a_other ut_data_value_refcursor :=null, a_join_by_list ut_varchar2_list:=ut_varchar2_list() ) return clob is
556576 l_compare_sql clob;
557577 l_temp_string varchar2(32767);
558578
@@ -638,10 +658,10 @@ create or replace package body ut_compound_data_helper is
638658 ut_utils.append_to_clob(l_compare_sql,' e.dup_no = a.dup_no and ');
639659 end if;
640660
641- if a_join_by_xpath is null and a_unordered then
661+ if (a_join_by_list.count = 0) and a_unordered then
642662 -- If no key defined do the join on all columns
643663 ut_utils.append_to_clob(l_compare_sql,l_equal_stmt);
644- elsif a_join_by_xpath is not null and a_unordered then
664+ elsif (a_join_by_list.count > 0) and a_unordered then
645665 -- If key defined do the join or these and where on diffrences
646666 ut_utils.append_to_clob(l_compare_sql,l_join_on_stmt);
647667 elsif not a_unordered then
@@ -650,7 +670,7 @@ create or replace package body ut_compound_data_helper is
650670
651671 ut_utils.append_to_clob(l_compare_sql,' ) where ');
652672
653- if (a_join_by_xpath is not null ) and (a_unordered) and (not a_is_negated) then
673+ if (a_join_by_list.count > 0 ) and (a_unordered) and (not a_is_negated) then
654674 if l_not_equal_stmt is not null then
655675 ut_utils.append_to_clob(l_compare_sql,' ( '||l_not_equal_stmt||' ) or ');
656676 end if;
@@ -663,6 +683,8 @@ create or replace package body ut_compound_data_helper is
663683 --If its inlcusion we expect a actual set to fully match and have no extra elements over expected
664684 if a_inclusion_type and not(a_is_negated) then
665685 l_temp_string := ' ( a.data_id is null ) ';
686+ elsif a_inclusion_type and a_is_negated then
687+ l_temp_string := ' 1 = 1 ';
666688 else
667689 l_temp_string := ' (a.data_id is null or e.data_id is null) ';
668690 end if;
@@ -699,9 +721,8 @@ create or replace package body ut_compound_data_helper is
699721 return g_diff_count;
700722 end;
701723
702- function filter_out_cols(a_cursor_info ut_cursor_column_tab, a_current_list ut_varchar2_list,a_include boolean)
703- return ut_cursor_column_tab is
704- l_sql varchar2(32767) :=
724+ function get_cursor_vs_list_sql return varchar2 is
725+ l_sql varchar2(32767) :=
705726 q'[with
706727 sorted as
707728 (select r_num,regexp_substr(t.column_value, '[^/]+', 1, commas.column_value) as colval,commas.column_value lev
@@ -721,10 +742,15 @@ create or replace package body ut_compound_data_helper is
721742 i.hierarchy_level,i.column_position, i.column_type)
722743 from t1 join table(:a_cursor_info) i on ( nvl(t1.parent_name,1) = nvl(i.parent_name,1) and t1.column_name = i.column_name)
723744 ]';
745+ begin
746+ return l_sql;
747+ end;
724748
749+ function filter_out_cols(a_cursor_info ut_cursor_column_tab, a_current_list ut_varchar2_list,a_include boolean := true)
750+ return ut_cursor_column_tab is
751+ l_sql varchar2(32767) := get_cursor_vs_list_sql;
725752 l_result ut_cursor_column_tab := ut_cursor_column_tab();
726753 begin
727- --TODO : Get this query tidy up
728754 if a_include then
729755 l_sql := l_sql || ' join constructed c on ( nvl(t1.parent_name,1) = nvl(c.parent_name,1) and t1.column_name = c.column_name)';
730756 else
@@ -738,6 +764,20 @@ create or replace package body ut_compound_data_helper is
738764 return l_result;
739765 end;
740766
767+ function compare_cursor_to_columns(a_cursor_info ut_cursor_column_tab, a_current_list ut_varchar2_list)
768+ return ut_cursor_column_tab is
769+ l_sql varchar2(32767) := get_cursor_vs_list_sql;
770+ l_result ut_cursor_column_tab := ut_cursor_column_tab();
771+ begin
772+ l_sql := l_sql ||'right outer join constructed c on ( nvl(t1.parent_name,1) = nvl(c.parent_name,1) and t1.column_name = c.column_name)
773+ where t1.column_name is null';
774+
775+ execute immediate l_sql bulk collect into l_result
776+ using a_current_list,a_cursor_info,a_cursor_info,a_cursor_info;
777+ return l_result;
778+ end;
779+
780+
741781 function inc_exc_columns_from_cursor (a_cursor_info ut_cursor_column_tab, a_exclude_xpath ut_varchar2_list, a_include_xpath ut_varchar2_list)
742782 return ut_cursor_column_tab is
743783 l_filtered_set ut_varchar2_list := ut_varchar2_list();
0 commit comments