Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5dc721f

Browse files
authored
Merge pull request #646 from lwasylow/feature/cursor_implicit
Fixed issue with implicit cursor
2 parents 5b63b1e + 3ff247a commit 5dc721f

6 files changed

Lines changed: 97 additions & 19 deletions

File tree

source/core/ut_utils.pkb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,5 +544,19 @@ procedure append_to_clob(a_src_clob in out nocopy clob, a_clob_table t_clob_tab,
544544
return l_filtered_list;
545545
end;
546546

547+
function xmlgen_escaped_string(a_string in varchar2) return varchar2 is
548+
l_result varchar2(4000);
549+
l_sql varchar2(32767) := q'!select q'[!'||a_string||q'!]' as "!'||a_string||'" from dual';
550+
begin
551+
if a_string is not null then
552+
select extract(dbms_xmlgen.getxmltype(l_sql),'/*/*/*').getRootElement()
553+
into l_result
554+
from dual;
555+
else
556+
l_result := a_string;
557+
end if;
558+
return l_result;
559+
end;
560+
547561
end ut_utils;
548562
/

source/core/ut_utils.pks

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,5 +302,8 @@ create or replace package ut_utils authid definer is
302302
/*It takes a collection of type ut_varchar2_list and it only returns the elements which meets the regular expression*/
303303
function filter_list(a_list IN ut_varchar2_list, a_regexp_filter in varchar2) return ut_varchar2_list;
304304

305+
-- Generates XMLGEN escaped string
306+
function xmlgen_escaped_string(a_string in varchar2) return varchar2;
307+
305308
end ut_utils;
306309
/

source/expectations/data_values/ut_compound_data_helper.pkb

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,12 @@ create or replace package body ut_compound_data_helper is
5555
a_cursor := dbms_sql.to_refcursor( l_cursor_number );
5656
l_columns_tab := get_columns_info( l_columns_desc, l_columns_count);
5757

58-
select XMLELEMENT("ROW", xmlagg(xmlelement(evalname key, value))) into l_result from table(l_columns_tab );
58+
select
59+
XMLELEMENT("ROW", xmlagg(xmlelement(evalname ut_utils.xmlgen_escaped_string(key),
60+
XMLATTRIBUTES(key AS "xml_valid_name"),
61+
value)))
62+
into l_result
63+
from table(l_columns_tab );
5964

6065
return l_result;
6166
end;
@@ -89,31 +94,41 @@ create or replace package body ut_compound_data_helper is
8994
l_sql varchar2(32767);
9095
l_results tt_column_diffs;
9196
begin
92-
l_column_filter := ut_compound_data_helper.get_columns_filter(a_exclude_xpath, a_include_xpath);
97+
l_column_filter := get_columns_filter(a_exclude_xpath, a_include_xpath);
9398
l_sql := q'[
9499
with
95100
expected_cols as ( select :a_expected as item_data from dual ),
96101
actual_cols as ( select :a_actual as item_data from dual ),
97-
expected_cols_info as (
102+
expected_cols_info as (
98103
select e.*,
99104
replace(expected_type,'VARCHAR2','CHAR') expected_type_compare
100105
from (
101-
select rownum expected_pos,
102-
r.column_value.getrootelement() expected_name,
103-
extractvalue(r.column_value,'/*') expected_type
104-
from ( select ]'||l_column_filter||q'[ from expected_cols ucd ) s,
105-
table( xmlsequence(extract(s.item_data,'/*/*')) ) r
106+
SELECT rownum expected_pos,
107+
xt.name expected_name,
108+
xt.type expected_type
109+
FROM (select ]'||l_column_filter||q'[ from expected_cols ucd) x,
110+
XMLTABLE('/ROW/*'
111+
PASSING x.item_data
112+
COLUMNS
113+
name VARCHAR2(4000) PATH '@xml_valid_name',
114+
type VARCHAR2(4000) PATH '/'
115+
) xt
106116
) e
107117
),
108118
actual_cols_info as (
109119
select a.*,
110120
replace(actual_type,'VARCHAR2','CHAR') actual_type_compare
111121
from (
112-
select rownum actual_pos,
113-
r.column_value.getrootelement() actual_name,
114-
extractvalue(r.column_value,'/*') actual_type
115-
from ( select ]'||l_column_filter||q'[ from actual_cols ucd ) s,
116-
table( xmlsequence(extract(s.item_data,'/*/*')) ) r
122+
SELECT rownum actual_pos,
123+
xt.name actual_name,
124+
xt.type actual_type
125+
FROM (select ]'||l_column_filter||q'[ from actual_cols ucd) x,
126+
XMLTABLE('/ROW/*'
127+
PASSING x.item_data
128+
COLUMNS
129+
name VARCHAR2(4000) PATH '@xml_valid_name',
130+
type VARCHAR2(4000) PATH '/'
131+
) xt
117132
) a
118133
),
119134
joined_cols as (
@@ -152,7 +167,7 @@ create or replace package body ut_compound_data_helper is
152167
l_column_filter varchar2(32767);
153168
l_results tt_row_diffs;
154169
begin
155-
l_column_filter := get_columns_filter(a_exclude_xpath, a_include_xpath);
170+
l_column_filter := get_columns_filter(a_exclude_xpath,a_include_xpath);
156171
execute immediate q'[
157172
with
158173
diff_info as (select item_no from ut_compound_data_diff_tmp ucdc where diff_id = :diff_guid and rownum <= :max_rows)
@@ -231,14 +246,14 @@ create or replace package body ut_compound_data_helper is
231246
a_hash_type binary_integer := dbms_crypto.hash_sh1
232247
) return t_hash is
233248
l_cols_hash t_hash;
234-
begin
235-
if not a_data_value_cursor.is_null then
249+
begin
250+
if not a_data_value_cursor.is_null then
236251
execute immediate
237252
q'[select dbms_crypto.hash(replace(x.item_data.getclobval(),'>CHAR<','>VARCHAR2<'),]'||a_hash_type||') ' ||
238253
' from ( select '||get_columns_filter(a_exclude_xpath, a_include_xpath)||
239254
' from (select :columns_info as item_data from dual ) ucd' ||
240255
' ) x'
241-
into l_cols_hash using a_exclude_xpath, a_include_xpath, a_data_value_cursor.columns_info;
256+
into l_cols_hash using a_exclude_xpath,a_include_xpath, a_data_value_cursor.columns_info;
242257
end if;
243258
return l_cols_hash;
244259
end;
@@ -263,5 +278,6 @@ begin
263278
g_type_name_map( dbms_sql.number_type ) := 'NUMBER';
264279
g_type_name_map( dbms_sql.rowid_type ) := 'ROWID';
265280
g_type_name_map( dbms_sql.urowid_type ) := 'UROWID';
281+
266282
end;
267283
/

source/expectations/data_values/ut_data_value_refcursor.tpb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ create or replace type body ut_data_value_refcursor as
140140
for i in 1 .. a_column_diffs.count loop
141141
if a_column_diffs(i).diff_type in ('-','+') then
142142
l_incomparable_cols.extend;
143-
l_incomparable_cols(l_incomparable_cols.last) := coalesce(a_column_diffs(i).expected_name,a_column_diffs(i).actual_name);
143+
l_incomparable_cols(l_incomparable_cols.last) := ut_utils.xmlgen_escaped_string(coalesce(a_column_diffs(i).expected_name,a_column_diffs(i).actual_name));
144144
end if;
145145
end loop;
146146
l_result := ut_utils.to_xpath(l_incomparable_cols);

test/core/expectations/compound_data/test_expectations_cursor.pkb

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,5 +963,46 @@ Rows: [ 4 differences ]
963963
ut.expect(ut3.ut_expectation_processor.get_warnings()(1)).to_be_like('The syntax: "%" is deprecated.%');
964964
end;
965965

966+
procedure column_diff_on_col_name_implicit is
967+
l_actual SYS_REFCURSOR;
968+
l_expected SYS_REFCURSOR;
969+
l_actual_message varchar2(32767);
970+
l_expected_message varchar2(32767);
971+
begin
972+
--Arrange
973+
open l_actual for select '1' , '2' from dual connect by level <=2;
974+
open l_expected for select rownum , rownum expected_column_name from dual connect by level <=2;
975+
--Act
976+
ut3.ut.expect(l_actual).to_equal(l_expected);
977+
978+
l_expected_message := q'[Actual: refcursor [ count = 2 ] was expected to equal: refcursor [ count = 2 ]%
979+
Diff:%
980+
Columns:%
981+
Column <ROWNUM> [data-type: NUMBER] is missing. Expected column position: 1.%
982+
Column <EXPECTED_COLUMN_NAME> [data-type: NUMBER] is missing. Expected column position: 2.%
983+
Column <'1'> [position: 1, data-type: CHAR] is not expected in results.%
984+
Column <'2'> [position: 2, data-type: CHAR] is not expected in results.%
985+
Rows: [ 2 differences ]%
986+
All rows are different as the columns are not matching.%]';
987+
l_actual_message := ut3.ut_expectation_processor.get_failed_expectations()(1).message;
988+
--Assert
989+
ut.expect(l_actual_message).to_be_like(l_expected_message);
990+
end;
991+
992+
procedure column_match_on_col_name_implicit is
993+
l_actual SYS_REFCURSOR;
994+
l_expected SYS_REFCURSOR;
995+
l_actual_message varchar2(32767);
996+
l_expected_message varchar2(32767);
997+
begin
998+
--Arrange
999+
open l_actual for select '1' , rownum from dual connect by level <=2;
1000+
open l_expected for select '1' , rownum from dual connect by level <=2;
1001+
--Act
1002+
ut3.ut.expect(l_actual).to_equal(l_expected);
1003+
--Assert
1004+
ut.expect(expectations.failed_expectations_data()).to_be_empty();
1005+
end;
1006+
9661007
end;
9671008
/

test/core/expectations/compound_data/test_expectations_cursor.pks

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,11 @@ create or replace package test_expectations_cursor is
187187
--%test(Adds a warning when using depreciated syntax to_( equal( a_expected sys_refcursor, a_exclude ut_varchar2_list )) )
188188
procedure deprec_equal_excl_list;
189189

190-
--%test(Reports column name differences if found)
190+
--%test(Reports column diff on cursor with column name implicit )
191+
procedure column_diff_on_col_name_implicit;
191192

193+
--%test(Reports column match on cursor with column name implicit )
194+
procedure column_match_on_col_name_implicit;
195+
192196
end;
193197
/

0 commit comments

Comments
 (0)