@@ -183,6 +183,8 @@ create or replace package body ut_compound_data_helper is
183183 l_act_col_filter := get_columns_row_filter(a_exclude_xpath,a_include_xpath,'ucd','act_item_data');
184184 l_exp_col_filter := get_columns_row_filter(a_exclude_xpath,a_include_xpath,'ucd','exp_item_data');
185185
186+ --TODO: Generate a dynamic SQL based on input e.g. no need for PK during unordered and consolidate get_rows_diff
187+
186188 execute immediate q'[with exp as (
187189 select exp_item_data, exp_data_id, item_no rn,rownum col_no,
188190 nvl2(exp_item_data,ut3.ut_compound_data_helper.get_pk_value(i.join_by,exp_item_data),null) pk_value,
@@ -317,12 +319,12 @@ create or replace package body ut_compound_data_helper is
317319 function get_rows_diff(
318320 a_expected_dataset_guid raw, a_actual_dataset_guid raw, a_diff_id raw,
319321 a_max_rows integer, a_exclude_xpath varchar2, a_include_xpath varchar2,
320- a_join_by_xpath varchar2,a_unorderdered boolean
322+ a_join_by_xpath varchar2,a_unordered boolean
321323 ) return tt_row_diffs is
322324 l_result tt_row_diffs := tt_row_diffs();
323325 begin
324326 case
325- when a_unorderdered then
327+ when a_unordered then
326328 l_result := get_rows_diff_by_sql(a_expected_dataset_guid, a_actual_dataset_guid, a_diff_id,
327329 a_max_rows, a_exclude_xpath, a_include_xpath ,a_join_by_xpath);
328330 else
@@ -559,8 +561,9 @@ create or replace package body ut_compound_data_helper is
559561 return l_sql_stmt;
560562 end;
561563
562- function gen_compare_sql(a_column_info xmltype, a_exclude_xpath varchar2,
563- a_include_xpath varchar2, a_join_by_xpath varchar2, a_inclusion_type boolean, a_is_negated boolean ) return clob is
564+ function gen_compare_sql(a_column_info xmltype, a_exclude_xpath varchar2, a_include_xpath varchar2,
565+ a_join_by_xpath varchar2, a_inclusion_type boolean, a_is_negated boolean,
566+ a_unordered boolean) return clob is
564567 l_compare_sql clob;
565568 l_temp_string varchar2(32767);
566569
@@ -613,6 +616,7 @@ create or replace package body ut_compound_data_helper is
613616 dbms_lob.createtemporary(l_compare_sql, true);
614617
615618 --TODO: Resolve issues with collection and nested tables, can we extract by internal column name if defined e.g. xml of colval.id.getclobval()
619+ --TODO: Comment better all pieces
616620 --Check include and exclude columns and create an actual column list that have to be compared.
617621 if a_include_xpath is null and a_exclude_xpath is null then
618622 l_act_col_tab := get_columns_info(a_column_info);
@@ -638,12 +642,19 @@ create or replace package body ut_compound_data_helper is
638642 ut_utils.append_to_clob(l_compare_sql, l_temp_string);
639643 ut_utils.append_to_clob(l_compare_sql, l_select_stmt);
640644
641- l_temp_string := q'[,x.item_no,x.data_id from (select item_data,item_no,data_id from ]' || l_ut_owner || q'[.ut_compound_data_tmp where data_id = :self_guid) x,]'
645+ l_temp_string := ',x.data_id ,'
646+ || case when not a_unordered then 'position ' else 'rownum ' end
647+ ||'item_no from '|| l_ut_owner || '.ut_compound_data_tmp x, '
642648 ||q'[xmltable('/ROWSET/ROW' passing x.item_data columns ]';
643- ut_utils.append_to_clob(l_compare_sql, l_temp_string);
649+ ut_utils.append_to_clob(l_compare_sql, l_temp_string);
650+
651+ if not a_unordered then
652+ ut_utils.append_to_clob(l_compare_sql,'POSITION for ordinality, ');
653+ end if;
654+
644655 ut_utils.append_to_clob(l_compare_sql,l_xmltable_stmt);
645656
646- l_temp_string := q'[ ,item_data xmltype PATH '*' ) ucd ) ucd ) ,]';
657+ l_temp_string := q'[ ,item_data xmltype PATH '*' ) ucd where data_id = :self_guid ) ucd ) ,]';
647658 ut_utils.append_to_clob(l_compare_sql,l_temp_string);
648659
649660 l_temp_string :='act as ( select ucd.* , ';
@@ -654,35 +665,50 @@ create or replace package body ut_compound_data_helper is
654665 ut_utils.append_to_clob(l_compare_sql,l_temp_string);
655666 ut_utils.append_to_clob(l_compare_sql, l_select_stmt);
656667
657- l_temp_string := q'[, x.item_no,x.data_id from (select item_data,item_no,data_id from ]' || l_ut_owner || q'[.ut_compound_data_tmp where data_id = :other_guid) x,]'
668+ l_temp_string := ',x.data_id, '
669+ || case when not a_unordered then 'position ' else 'rownum ' end
670+ ||'item_no from ' || l_ut_owner || '.ut_compound_data_tmp x,'
658671 ||q'[xmltable('/ROWSET/ROW' passing x.item_data columns ]' ;
659672 ut_utils.append_to_clob(l_compare_sql,l_temp_string);
660- ut_utils.append_to_clob(l_compare_sql,l_xmltable_stmt||q'[ ,item_data xmltype PATH '*') ucd ) ucd ) ]');
661-
662- if a_join_by_xpath is null then
663- -- If no key defined do the join on all columns
664- l_temp_string := ' select a.item_data as act_item_data, a.data_id act_data_id,'
665- ||'e.item_data as exp_item_data, e.data_id exp_data_id, rownum item_no, nvl(e.dup_no,a.dup_no) dup_no '
673+
674+ if not a_unordered then
675+ ut_utils.append_to_clob(l_compare_sql,'POSITION for ordinality, ');
676+ end if;
677+
678+ ut_utils.append_to_clob(l_compare_sql,l_xmltable_stmt||q'[ ,item_data xmltype PATH '*') ucd where data_id = :other_guid ) ucd ) ]');
679+
680+ l_temp_string := ' select a.item_data as act_item_data, a.data_id act_data_id,'
681+ ||'e.item_data as exp_item_data, e.data_id exp_data_id, '||
682+ case when a_unordered then 'rownum item_no' else 'nvl(e.item_no,a.item_no) item_no' end ||', nvl(e.dup_no,a.dup_no) dup_no '
666683 ||'from act a '||get_join_type(a_inclusion_type,a_is_negated)||' exp e on ( ';
667- ut_utils.append_to_clob(l_compare_sql,l_temp_string);
668- ut_utils.append_to_clob(l_compare_sql,generate_equal_sql(l_act_col_tab)||q'[ and e.dup_no = a.dup_no ) where ]');
669- else
670- -- If key defined do the join or these and where on diffrences
671- l_temp_string := q'[ select a.item_data act_item_data, a.data_id act_data_id, ]'
672- ||' e.item_data exp_item_data, e.data_id exp_data_id, rownum item_no,nvl(e.dup_no,a.dup_no) dup_no from act a '||get_join_type(a_inclusion_type,a_is_negated)||' exp e on ( e.dup_no = a.dup_no and ';
673- ut_utils.append_to_clob(l_compare_sql,l_temp_string);
674-
675- ut_utils.append_to_clob(l_compare_sql,generate_join_by_on_stmt (l_pk_xpath_tabs,a_column_info,a_join_by_xpath)||' ) where');
676-
684+ ut_utils.append_to_clob(l_compare_sql,l_temp_string);
685+
686+ if a_unordered then
687+ ut_utils.append_to_clob(l_compare_sql,' e.dup_no = a.dup_no and ');
688+ end if;
689+
690+ if a_join_by_xpath is null and a_unordered then
691+ -- If no key defined do the join on all columns
692+ ut_utils.append_to_clob(l_compare_sql,generate_equal_sql(l_act_col_tab));
693+ elsif a_join_by_xpath is not null and a_unordered then
694+ -- If key defined do the join or these and where on diffrences
695+ ut_utils.append_to_clob(l_compare_sql,generate_join_by_on_stmt (l_pk_xpath_tabs,a_column_info,a_join_by_xpath));
696+ elsif not a_unordered then
697+ ut_utils.append_to_clob(l_compare_sql, 'a.item_no = e.item_no ' );
698+ end if;
677699
678- if not a_is_negated then
700+ ut_utils.append_to_clob(l_compare_sql,' ) where ');
701+
702+ if (a_join_by_xpath is not null) and (a_unordered) and (a_inclusion_type) and (not a_is_negated) then
679703 l_where_stmt := generate_not_equal_sql(l_act_col_tab, l_pk_xpath_tabs);
680704 if l_where_stmt is not null then
681705 ut_utils.append_to_clob(l_compare_sql,' ( '||l_where_stmt||' ) or ');
682706 end if;
683- end if;
684- end if;
685-
707+ elsif not a_unordered then
708+ l_where_stmt := generate_not_equal_sql(l_act_col_tab, l_pk_xpath_tabs);
709+ ut_utils.append_to_clob(l_compare_sql,' ( '||l_where_stmt||' ) or ');
710+ end if;
711+
686712 --If its inlcusion we expect a actual set to fully match and have no extra elements over expected
687713 if a_inclusion_type and not(a_is_negated) then
688714 l_temp_string := ' ( a.data_id is null ) ';
0 commit comments