- Notifications
You must be signed in to change notification settings - Fork 849
/
Copy pathemulate-backtrace.sql
200 lines (177 loc) · 4.9 KB
/
emulate-backtrace.sql
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/*
UTL_CALL_STACK, introduced in Oracle Database 12c, offers fine-grained access to
the execution call stack, error stack, and backtrace information. Prior to
UTL_CALL_STACK, developers used functions in DBMS_UTILITY to obtain this infromation:
FORMAT_CALL_STACK, FORMAT_ERROR_STACK, FORMAT_ERROR_BACKTRACE.
The my_utl_call_stack offers functions of the same name to replace those functions.
*/
CREATE OR REPLACE PACKAGE my_utl_call_stack
AUTHID DEFINER
IS
FUNCTION format_call_stack RETURN VARCHAR2;
FUNCTION format_error_stack RETURN VARCHAR2;
FUNCTION format_error_backtrace RETURN VARCHAR2;
FUNCTION backtrace_to RETURN VARCHAR2;
END;
/
CREATE OR REPLACE PACKAGE BODY my_utl_call_stack
IS
FUNCTION format_call_stack
RETURN VARCHAR2
IS
l_return VARCHAR2 (32767)
:= '----- PL/SQL Call Stack -------'
|| CHR (10)
|| 'Line Object name'
|| CHR (10)
|| '-------- ----------------------';
BEGIN
/* 1 is always this function, so ignore it. */
FOR indx IN 2 .. utl_call_stack.dynamic_depth
LOOP
l_return :=
l_return
|| case when l_return is not null then CHR (10) end
|| LPAD (TO_CHAR (utl_call_stack.unit_line (indx)), 8)
|| ' '
|| utl_call_stack.owner (indx)
|| '.'
|| utl_call_stack.concatenate_subprogram (
utl_call_stack.subprogram (indx));
END LOOP;
RETURN l_return;
END;
FUNCTION format_error_stack
RETURN VARCHAR2
IS
l_return VARCHAR2 (32767);
BEGIN
FOR indx IN 1 .. utl_call_stack.error_depth
LOOP
l_return :=
l_return
|| case when l_return is not null then CHR (10) end
|| 'ORA-'
|| LPAD (TO_CHAR (utl_call_stack.error_number (indx)), 5, '0')
|| ': '
|| utl_call_stack.error_msg (indx);
END LOOP;
RETURN l_return;
END;
FUNCTION format_error_backtrace
RETURN VARCHAR2
IS
l_return VARCHAR2 (32767);
BEGIN
FOR indx IN 1 .. utl_call_stack.backtrace_depth
LOOP
l_return :=
l_return
|| case when l_return is not null then CHR (10) end
|| indx
|| ' -> '
|| utl_call_stack.backtrace_unit (indx)
|| ' - Line '
|| TO_CHAR (utl_call_stack.backtrace_line (indx));
END LOOP;
RETURN l_return;
EXCEPTION
WHEN OTHERS
THEN
IF SQLCODE = -64610
THEN
/* ORA-64610: bad depth indicator */
RETURN l_return;
ELSE
RAISE;
END IF;
END;
FUNCTION backtrace_to
RETURN VARCHAR2
IS
BEGIN
RETURN utl_call_stack.backtrace_unit (1)
|| ' on line '
|| utl_call_stack.backtrace_line (1);
END;
END;
/
SET SERVEROUTPUT ON
CREATE OR REPLACE PROCEDURE p1
IS
PROCEDURE nested_in_p1
IS
BEGIN
DBMS_OUTPUT.put_line ('Call Stack from DBMS_UTILITY');
DBMS_OUTPUT.put_line ('-');
DBMS_OUTPUT.put_line (DBMS_UTILITY.format_call_stack);
DBMS_OUTPUT.put_line ('-');
DBMS_OUTPUT.put_line ('Call Stack from UTL_CALL_STACK');
DBMS_OUTPUT.put_line ('-');
DBMS_OUTPUT.put_line (my_utl_call_stack.format_call_stack);
RAISE NO_DATA_FOUND;
END;
BEGIN
nested_in_p1;
END;
/
CREATE OR REPLACE PACKAGE pkg
AUTHID DEFINER
IS
PROCEDURE p;
END;
/
CREATE OR REPLACE PACKAGE BODY pkg
IS
PROCEDURE p
IS
BEGIN
p1;
END;
END;
/
CREATE OR REPLACE PROCEDURE p2
AUTHID DEFINER
IS
BEGIN
pkg.p;
END;
/
CREATE OR REPLACE PROCEDURE p3
AUTHID DEFINER
IS
BEGIN
p2;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('-');
DBMS_OUTPUT.put_line ('Error Stack from DBMS_UTILTY');
DBMS_OUTPUT.put_line ('-');
DBMS_OUTPUT.put_line (DBMS_UTILITY.format_error_stack);
DBMS_OUTPUT.put_line ('Error Stack from UTL_CALL_STACK');
DBMS_OUTPUT.put_line ('-');
DBMS_OUTPUT.put_line (my_utl_call_stack.format_error_stack);
DBMS_OUTPUT.put_line ('-');
DBMS_OUTPUT.put_line ('Backtrace from DBMS_UTILITY');
DBMS_OUTPUT.put_line ('-');
DBMS_OUTPUT.put_line (DBMS_UTILITY.format_error_backtrace);
DBMS_OUTPUT.put_line ('-');
DBMS_OUTPUT.put_line ('Backtrace from UTL_CALL_STACK');
DBMS_OUTPUT.put_line ('-');
DBMS_OUTPUT.put_line (my_utl_call_stack.format_error_backtrace);
DBMS_OUTPUT.put_line ('-');
DBMS_OUTPUT.put_line ('Backtrace to: ' || my_utl_call_stack.backtrace_to());
RAISE;
END;
/
BEGIN
p3;
/* Trapping the exception because if I do not, LiveSQL will not
show the contents of the DBMS_OUTPUT buffer.
*/
EXCEPTION WHEN OTHERS
THEN
NULL;
END;
/