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

Skip to content

Commit a0f39e0

Browse files
authored
Merge pull request #896 from utPLSQL/fix/cursor_error_handling
Fix/cursor error handling
2 parents 977c579 + f5331ac commit a0f39e0

9 files changed

Lines changed: 173 additions & 17 deletions

source/core/ut_expectation_processor.pkb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ create or replace package body ut_expectation_processor as
8888
begin
8989
add_expectation_result(ut_expectation_result(ut_utils.gc_failure, null, a_message));
9090
end;
91-
91+
9292
function get_session_parameters return tt_nls_params is
9393
l_session_params tt_nls_params;
9494
begin

source/core/ut_expectation_processor.pks

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ create or replace package ut_expectation_processor authid current_user as
3535
procedure add_expectation_result(a_expectation_result ut_expectation_result);
3636

3737
procedure report_failure(a_message in varchar2);
38-
38+
3939
procedure set_xml_nls_params;
4040

4141
procedure reset_nls_params;

source/core/ut_utils.pkb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,5 +737,20 @@ create or replace package body ut_utils is
737737
return l_results;
738738
end;
739739

740+
function remove_error_from_stack(a_error_stack varchar2, a_ora_code number) return varchar2 is
741+
l_caller_stack_line varchar2(4000);
742+
l_ora_search_pattern varchar2(500) := '^ORA'||a_ora_code||': (.*)$';
743+
begin
744+
l_caller_stack_line := regexp_replace(srcstr => a_error_stack
745+
,pattern => l_ora_search_pattern
746+
,replacestr => null
747+
,position => 1
748+
,occurrence => 1
749+
,modifier => 'm');
750+
return l_caller_stack_line;
751+
end;
752+
753+
754+
740755
end ut_utils;
741756
/

source/core/ut_utils.pks

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@ create or replace package ut_utils authid definer is
109109
gc_value_too_large constant pls_integer := -20217;
110110
pragma exception_init (ex_value_too_large, -20217);
111111

112+
ex_xml_processing exception;
113+
gc_xml_processing constant pls_integer := -19202;
114+
pragma exception_init (ex_xml_processing, -19202);
115+
116+
ex_failed_open_cur exception;
117+
gc_failed_open_cur constant pls_integer := -20218;
118+
pragma exception_init (ex_failed_open_cur, -20218);
119+
112120
gc_max_storage_varchar2_len constant integer := 4000;
113121
gc_max_output_string_length constant integer := 4000;
114122
gc_more_data_string constant varchar2(5) := '[...]';
@@ -368,6 +376,11 @@ create or replace package ut_utils authid definer is
368376
* Returns list of sub-type reporters for given list of super-type reporters
369377
*/
370378
function get_child_reporters(a_for_reporters ut_reporters_info := null) return ut_reporters_info;
371-
379+
380+
/**
381+
* Remove given ORA error from stack
382+
*/
383+
function remove_error_from_stack(a_error_stack varchar2, a_ora_code number) return varchar2;
384+
372385
end ut_utils;
373386
/

source/expectations/data_values/ut_compound_data_helper.pkb

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ create or replace package body ut_compound_data_helper is
1818

1919
g_diff_count integer;
2020
type t_type_name_map is table of varchar2(128) index by binary_integer;
21+
type t_types_no_length is table of varchar2(128) index by varchar2(128);
2122
g_type_name_map t_type_name_map;
2223
g_anytype_name_map t_type_name_map;
24+
g_type_no_length_map t_types_no_length;
2325

2426
g_compare_sql_template varchar2(4000) :=
2527
q'[
@@ -231,8 +233,7 @@ create or replace package body ut_compound_data_helper is
231233
elsif a_data_info.is_sql_diffable = 1 and a_data_info.column_type in ('DATE','TIMESTAMP','TIMESTAMP WITH TIME ZONE',
232234
'TIMESTAMP WITH LOCAL TIME ZONE') then
233235
l_col_type := 'VARCHAR2(50)';
234-
elsif a_data_info.is_sql_diffable = 1 and a_data_info.column_type in ('INTERVAL DAY TO SECOND',
235-
'INTERVAL YEAR TO MONTH', 'BINARY_FLOAT', 'BINARY_DOUBLE') then
236+
elsif a_data_info.is_sql_diffable = 1 and type_no_length(a_data_info.column_type) then
236237
l_col_type := a_data_info.column_type;
237238
else
238239
l_col_type := a_data_info.column_type
@@ -570,6 +571,8 @@ create or replace package body ut_compound_data_helper is
570571
--clob/blob/xmltype/object/nestedcursor/nestedtable
571572
if a_type_name IN (g_type_name_map(dbms_sql.blob_type),
572573
g_type_name_map(dbms_sql.clob_type),
574+
g_type_name_map(dbms_sql.long_type),
575+
g_type_name_map(dbms_sql.long_raw_type),
573576
g_type_name_map(dbms_sql.bfile_type),
574577
g_anytype_name_map(dbms_types.typecode_namedcollection))
575578
then
@@ -596,6 +599,24 @@ create or replace package body ut_compound_data_helper is
596599
open l_diff_cursor for a_diff_cursor_text using a_self_id, a_other_id;
597600
return l_diff_cursor;
598601
end;
602+
603+
function create_err_cursor_msg(a_error_stack varchar2) return varchar2 is
604+
begin
605+
return 'SQL exception thrown when fetching data from cursor:'||
606+
ut_utils.remove_error_from_stack(sqlerrm,ut_utils.gc_xml_processing)||chr(10)||
607+
ut_expectation_processor.who_called_expectation(a_error_stack)||
608+
'Check the query and data for errors.';
609+
end;
610+
611+
function type_no_length ( a_type_name varchar2) return boolean is
612+
begin
613+
return case
614+
when g_type_no_length_map.exists(a_type_name) then
615+
true
616+
else
617+
false
618+
end;
619+
end;
599620

600621
begin
601622
g_anytype_name_map(dbms_types.typecode_date) := 'DATE';
@@ -642,6 +663,15 @@ begin
642663
g_type_name_map( dbms_sql.urowid_type ) := 'UROWID';
643664
g_type_name_map( dbms_sql.user_defined_type ) := 'USER_DEFINED_TYPE';
644665
g_type_name_map( dbms_sql.ref_type ) := 'REF_TYPE';
645-
666+
667+
668+
/**
669+
* List of types that have no length but can produce a max_len from desc_cursor function.
670+
*/
671+
g_type_no_length_map('ROWID') := 'ROWID';
672+
g_type_no_length_map('INTERVAL DAY TO SECOND') := 'INTERVAL DAY TO SECOND';
673+
g_type_no_length_map('INTERVAL YEAR TO MONTH') := 'INTERVAL YEAR TO MONTH';
674+
g_type_no_length_map('BINARY_DOUBLE') := 'BINARY_DOUBLE';
675+
g_type_no_length_map('BINARY_FLOAT') := 'BINARY_FLOAT';
646676
end;
647677
/

source/expectations/data_values/ut_compound_data_helper.pks

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,5 +92,12 @@ create or replace package ut_compound_data_helper authid definer is
9292

9393
function get_compare_cursor(a_diff_cursor_text in clob,a_self_id raw, a_other_id raw) return sys_refcursor;
9494

95+
function create_err_cursor_msg(a_error_stack varchar2) return varchar2;
96+
97+
/*
98+
* Function to return true or false if the type dont have an length
99+
*/
100+
function type_no_length ( a_type_name varchar2) return boolean;
101+
95102
end;
96103
/

source/expectations/data_values/ut_data_value_refcursor.tpb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ create or replace type body ut_data_value_refcursor as
9696
exception
9797
when cursor_not_open then
9898
raise_application_error(-20155, 'Cursor is not open');
99+
when ut_utils.ex_xml_processing then
100+
if l_cursor%isopen then
101+
close l_cursor;
102+
end if;
103+
raise_application_error(ut_utils.gc_failed_open_cur,
104+
ut_compound_data_helper.create_err_cursor_msg(dbms_utility.format_call_stack()));
99105
when others then
100106
if l_cursor%isopen then
101107
close l_cursor;
@@ -111,7 +117,9 @@ create or replace type body ut_data_value_refcursor as
111117
dbms_lob.createtemporary(l_result, true);
112118
ut_utils.append_to_clob(l_result, 'Data-types:'||chr(10));
113119

114-
ut_utils.append_to_clob( l_result, self.cursor_details.get_xml_children().getclobval() );
120+
if self.cursor_details.cursor_columns_info.count > 0 then
121+
ut_utils.append_to_clob( l_result, self.cursor_details.get_xml_children().getclobval() );
122+
end if;
115123
ut_utils.append_to_clob(l_result,chr(10)||(self as ut_compound_data_value).to_string());
116124
l_result_string := ut_utils.to_string(l_result,null);
117125
dbms_lob.freetemporary(l_result);

test/ut3_user/expectations/test_expectations_cursor.pkb

Lines changed: 81 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -994,18 +994,16 @@ Rows: [ 4 differences ]
994994
procedure reports_on_exception_in_cursor
995995
as
996996
l_actual sys_refcursor;
997-
l_error_code integer := -19202; --Error occurred in XML processing
998997
begin
999998
--Act
1000999
open l_actual for select 1/0 as error_column from dual connect by level < 10;
1001-
begin
10021000
ut3.ut.expect(l_actual).to_be_empty();
1003-
--Assert
1004-
ut.fail('Expected '||l_error_code||' but nothing was raised');
1005-
exception
1006-
when others then
1007-
ut.expect(sqlcode).to_equal(l_error_code);
1008-
end;
1001+
1002+
ut.fail('Expected exception on cursor fetch');
1003+
exception
1004+
when others then
1005+
ut.expect(sqlerrm).to_be_like('%ORA-20218: SQL exception thrown when fetching data from cursor:%
1006+
%ORA-01476: divisor is equal to zero%Check the query and data for errors%');
10091007
end;
10101008

10111009
procedure exception_when_closed_cursor
@@ -2545,5 +2543,80 @@ Diff:%
25452543
ut.expect(l_actual_message).to_be_like(l_expected_message);
25462544
end;
25472545

2546+
procedure xml_error_actual is
2547+
l_actual sys_refcursor;
2548+
l_expected sys_refcursor;
2549+
l_exp_message varchar2(32000);
2550+
begin
2551+
l_exp_message :='ORA-20218: SQL exception thrown when fetching data from cursor:
2552+
ORA-01476: divisor is equal to zero
2553+
at "UT3$USER#.TEST_EXPECTATIONS_CURSOR%", line 2561 ut3.ut.expect(l_actual).to_equal(l_expected);%
2554+
Check the query and data for errors.';
2555+
2556+
open l_actual for
2557+
select 1 as test from dual;
2558+
open l_expected for
2559+
select 1/0 as test from dual;
2560+
2561+
ut3.ut.expect(l_actual).to_equal(l_expected);
2562+
--Line that error relates to in expected messag
2563+
2564+
ut.fail('Expected exception on cursor fetch');
2565+
exception
2566+
when others then
2567+
ut.expect(sqlerrm).to_be_like(l_exp_message);
2568+
end;
2569+
2570+
procedure xml_error_expected is
2571+
l_actual sys_refcursor;
2572+
l_expected sys_refcursor;
2573+
l_exp_message varchar2(32000);
2574+
begin
2575+
2576+
l_exp_message :='ORA-20218: SQL exception thrown when fetching data from cursor:
2577+
ORA-01476: divisor is equal to zero
2578+
at "UT3$USER#.TEST_EXPECTATIONS_CURSOR%", line 2586 ut3.ut.expect(l_actual).to_equal(l_expected);%
2579+
Check the query and data for errors.';
2580+
2581+
open l_expected for
2582+
select 1/0 as test from dual;
2583+
open l_actual for
2584+
select 1 as test from dual;
2585+
2586+
ut3.ut.expect(l_actual).to_equal(l_expected);
2587+
2588+
ut.fail('Expected exception on cursor fetch');
2589+
exception
2590+
when others then
2591+
ut.expect(sqlerrm).to_be_like(l_exp_message);
2592+
end;
2593+
2594+
procedure no_length_datatypes is
2595+
l_actual sys_refcursor;
2596+
l_expected sys_refcursor;
2597+
begin
2598+
ut3.ut.set_nls;
2599+
open l_expected for
2600+
select cast(3.14 as binary_double) as pi_double,
2601+
cast(3.14 as binary_float) as pi_float,
2602+
rowid as row_rowid,
2603+
numtodsinterval(1.12345678912, 'day') row_ds_interval,
2604+
numtoyminterval(1.1, 'year') row_ym_interval
2605+
from dual;
2606+
2607+
open l_actual for
2608+
select cast(3.14 as binary_double) as pi_double,
2609+
cast(3.14 as binary_float) as pi_float,
2610+
rowid as row_rowid,
2611+
numtodsinterval(1.12345678912, 'day') row_ds_interval,
2612+
numtoyminterval(1.1, 'year') row_ym_interval
2613+
from dual;
2614+
--Act
2615+
ut3.ut.expect( l_actual ).to_equal( l_expected );
2616+
--Assert
2617+
ut.expect(ut3_tester_helper.main_helper.get_failed_expectations_num).to_equal(0);
2618+
ut3.ut.reset_nls;
2619+
2620+
end;
25482621
end;
25492622
/

test/ut3_user/expectations/test_expectations_cursor.pks

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,11 +393,21 @@ create or replace package test_expectations_cursor is
393393

394394
--%test(Cursor to contain duplicates fail)
395395
procedure to_contain_duplicates_fail;
396-
396+
397397
--%test(Display a message with a uer defined type with only type name not structure on equal)
398398
procedure udt_messg_format_eq;
399399

400400
--%test(Display a message with a uer defined type with only type name not structure on empty)
401-
procedure udt_messg_format_empt;
401+
procedure udt_messg_format_empt;
402+
403+
--%test(Fail to process a cursor for actual)
404+
procedure xml_error_actual;
405+
406+
--%test(Fail to process a cursor for expected)
407+
procedure xml_error_expected;
408+
409+
--%test(Check that cursor correctly handles no length dataypes)
410+
procedure no_length_datatypes;
411+
402412
end;
403413
/

0 commit comments

Comments
 (0)