-
Notifications
You must be signed in to change notification settings - Fork 188
Expand file tree
/
Copy pathut_executable.tpb
More file actions
183 lines (156 loc) · 7.14 KB
/
ut_executable.tpb
File metadata and controls
183 lines (156 loc) · 7.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
create or replace type body ut_executable is
/*
utPLSQL - Version 3
Copyright 2016 - 2021 utPLSQL Project
Licensed under the Apache License, Version 2.0 (the "License"):
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
constructor function ut_executable(
self in out nocopy ut_executable, a_owner varchar2, a_package varchar2,
a_procedure_name varchar2, a_executable_type varchar2
) return self as result is
begin
self.self_type := $$plsql_unit;
self.executable_type := a_executable_type;
self.owner_name := a_owner;
self.object_name := a_package;
self.procedure_name := a_procedure_name;
return;
end;
member function form_name(a_skip_current_user_schema boolean := false) return varchar2 is
l_owner_name varchar2(250) := owner_name;
begin
if a_skip_current_user_schema and sys_context('userenv', 'current_schema') = owner_name then
l_owner_name := null;
end if;
return ut_metadata.form_name(l_owner_name, object_name, procedure_name);
end;
member procedure do_execute(self in out nocopy ut_executable, a_item in out nocopy ut_suite_item) is
l_completed_without_errors boolean;
begin
l_completed_without_errors := self.do_execute(a_item);
end do_execute;
member function do_execute(self in out nocopy ut_executable, a_item in out nocopy ut_suite_item) return boolean is
l_statement varchar2(4000);
l_status number;
l_cursor_number number;
l_completed_without_errors boolean := true;
l_failed_with_invalid_pck boolean := true;
l_start_transaction_id varchar2(250);
l_end_transaction_id varchar2(250);
function is_defined return boolean is
l_result boolean := false;
l_message_part varchar2(4000) := 'Call params for ' || self.executable_type || ' are not valid: ';
begin
if self.object_name is null then
self.error_stack := l_message_part || 'package is not defined';
elsif self.procedure_name is null then
self.error_stack := l_message_part || 'procedure is not defined';
else
l_result := true;
end if;
return l_result;
end is_defined;
function is_invalid return boolean is
l_result boolean := true;
l_message_part varchar2(4000) := 'Call params for ' || self.executable_type || ' are not valid: ';
begin
if not ut_metadata.package_valid(self.owner_name, self.object_name) then
self.error_stack := l_message_part || 'package '||upper(self.owner_name||'.'||self.object_name)||' does not exist or is invalid.';
elsif not ut_metadata.procedure_exists(self.owner_name, self.object_name, self.procedure_name) then
self.error_stack := l_message_part || 'procedure '||upper(self.owner_name || '.' || self.object_name || '.' ||self.procedure_name)||' does not exist.';
else
l_result := false;
end if;
return l_result;
end is_invalid;
procedure save_dbms_output is
l_status number;
l_line varchar2(32767);
begin
dbms_output.get_line(line => l_line, status => l_status);
if l_status != 1 then
dbms_lob.createtemporary(self.serveroutput, true, dur => dbms_lob.session);
end if;
while l_status != 1 loop
if l_line is not null then
ut_utils.append_to_clob(self.serveroutput, l_line||chr(10));
end if;
dbms_output.get_line(line => l_line, status => l_status);
end loop;
end save_dbms_output;
begin
l_start_transaction_id := dbms_transaction.local_transaction_id(true);
--listener - before call to executable
ut_event_manager.trigger_event('before_'||self.executable_type, self);
l_completed_without_errors := is_defined();
if l_completed_without_errors then
l_statement :=
'declare' || chr(10) ||
' l_error_stack varchar2(32767);' || chr(10) ||
' l_error_backtrace varchar2(32767);' || chr(10) ||
'begin' || chr(10) ||
' begin' || chr(10) ||
' ' || self.form_name( a_skip_current_user_schema => true ) || ';' || chr(10) ||
' exception' || chr(10) ||
' when others then ' || chr(10) ||
' l_error_stack := dbms_utility.format_error_stack;' || chr(10) ||
' l_error_backtrace := dbms_utility.format_error_backtrace;' || chr(10) ||
' --raise on ORA-04068, ORA-04061: existing state of packages has been discarded to avoid unrecoverable session exception' || chr(10) ||
' end;' || chr(10) ||
' :a_error_stack := l_error_stack;' || chr(10) ||
' :a_error_backtrace := l_error_backtrace;' || chr(10) ||
'end;';
ut_utils.debug_log('ut_executable.do_execute l_statement: ' || l_statement);
l_cursor_number := dbms_sql.open_cursor;
/**
* The code will allow to execute once we check if packages are defined
* If it fail with 6550 (usually invalid package) it will check if because of invalid state or missing
* if for any other reason we will propagate it up as we didnt expected.
**/
begin
dbms_sql.parse(l_cursor_number, statement => l_statement, language_flag => dbms_sql.native);
dbms_sql.bind_variable(l_cursor_number, 'a_error_stack', to_char(null), 32767);
dbms_sql.bind_variable(l_cursor_number, 'a_error_backtrace', to_char(null), 32767);
l_status := dbms_sql.execute(l_cursor_number);
dbms_sql.variable_value(l_cursor_number, 'a_error_stack', self.error_stack);
dbms_sql.variable_value(l_cursor_number, 'a_error_backtrace', self.error_backtrace);
dbms_sql.close_cursor(l_cursor_number);
exception
when ut_utils.ex_invalid_package then
l_failed_with_invalid_pck := is_invalid();
dbms_sql.close_cursor(l_cursor_number);
if not l_failed_with_invalid_pck then
raise;
end if;
when others then
dbms_sql.close_cursor(l_cursor_number);
raise;
end;
save_dbms_output;
l_completed_without_errors := (self.error_stack||self.error_backtrace) is null;
if self.error_stack like '%ORA-04068%' or self.error_stack like '%ORA-04061%' then
ut_expectation_processor.set_invalidation_exception();
end if;
end if;
--listener - after call to executable
ut_event_manager.trigger_event('after_'||self.executable_type, self);
l_end_transaction_id := dbms_transaction.local_transaction_id();
if l_start_transaction_id != l_end_transaction_id or l_end_transaction_id is null then
a_item.add_transaction_invalidator(self.form_name());
end if;
return l_completed_without_errors;
end do_execute;
member function get_error_stack_trace return varchar2 is
begin
return rtrim(self.error_stack||self.error_backtrace, chr(10));
end;
end;
/