Skip to content

Commit 5c5b012

Browse files
committed
update utl_call_stack to use varible length parsing
1 parent 58a8052 commit 5c5b012

File tree

2 files changed

+55
-29
lines changed

2 files changed

+55
-29
lines changed

src/Util/UTL_CALL_STACK.pkb

Lines changed: 50 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,47 +10,63 @@ caller_type varchar2(50));
1010
TYPE callstack IS TABLE OF stackline;
1111
*/
1212

13-
function getCallStack return callstack
13+
function getCallStack(pskip number default 0) return callstack
1414
IS
15+
--orcle docs say format_call stack only returns 2000.. but might as well be safe
1516
call_stack VARCHAR2(4096) DEFAULT dbms_utility.format_call_stack;
1617
n NUMBER;
1718
found_stack BOOLEAN DEFAULT FALSE;
1819
line VARCHAR2(255);
1920
cnt NUMBER := 0;
20-
21+
idx NUMBER := 0;
22+
2123
retval callstack := callstack();
2224
BEGIN
23-
--dbms_output.put_line(call_stack);
25+
-- dbms_output.put_line('in getCallstack');
26+
-- dbms_output.put_line('###################################################');
27+
-- dbms_output.put_line(call_stack);
28+
-- dbms_output.put_line('###################################################');
2429
--
2530
LOOP
31+
2632
n := instr( call_stack, chr(10) );
27-
EXIT
28-
WHEN ( n IS NULL OR n = 0 );
33+
EXIT WHEN ( n IS NULL OR n = 0 );
2934
--
3035
line := SUBSTR( call_stack, 1, n-1 );
3136
call_stack := SUBSTR( call_stack, n +1 );
3237
--
3338
IF ( NOT found_stack ) THEN
3439
IF ( line LIKE '%handle%number%name%' ) THEN
40+
-- dbms_output.put_line('found stack');
41+
-- dbms_output.put_line(' 1 2 3 4');
42+
-- dbms_output.put_line('1234567890123456789012345678901234567890');
3543
found_stack := TRUE;
3644
END IF;
3745
ELSE
3846
cnt := cnt + 1;
3947
-- cnt = 1 is ME
4048
-- cnt = 2 is MY Caller
4149
-- cnt = 3 is Their Caller
42-
IF ( cnt >2 ) THEN --start with 1 to ignore this fake getCallStack call.
43-
44-
retval.extend;
45-
46-
47-
--dbms_output.put_line(' 1 2 3');
48-
--dbms_output.put_line('123456789012345678901234567890');
49-
--dbms_output.put_line(line);
50+
IF ( cnt > 1+pskip ) THEN --start with 1 to ignore this fake getCallStack call.
51+
52+
retval.EXTEND;
53+
54+
BEGIN
55+
5056
--format '0x70165ba0 104 package body S06DP3.LOGMANAGER'
51-
retval(retval.last).handle := SUBSTR( line, 1, 13 );
52-
retval(retval.last).line := to_number(SUBSTR( line, 13, 8 ));
53-
line := SUBSTR( line, 23 ); --set to rest of line .. change from 21 to 23
57+
idx := instr(line,' ');
58+
-- dbms_output.put_line('handle:'||SUBSTR( line, 1, idx-1 )||'#');
59+
retval(retval.LAST).handle := SUBSTR( line, 1, idx-1 );
60+
61+
line := trim(substr(line,idx+1));
62+
idx := instr(line,' ');
63+
64+
-- dbms_output.put_line('lineno:'||trim(SUBSTR( line, 1,idx-1 ))||'#');
65+
retval(retval.LAST).line := TO_NUMBER(trim(SUBSTR( line, 1, idx-1 )));
66+
67+
line := trim(substr(line,idx+1)); --set to rest of line
68+
-- dbms_output.put_line('prog:'|| line||'#');
69+
5470
IF ( line LIKE 'pr%' ) THEN
5571
n := LENGTH( 'procedure ' );
5672
elsif ( line LIKE 'fun%' ) THEN
@@ -64,6 +80,7 @@ BEGIN
6480
ELSE
6581
n := NULL;
6682
END IF;
83+
6784
IF ( n IS NOT NULL ) THEN
6885
retval(retval.last).caller_type := ltrim(rtrim(upper(SUBSTR( line, 1, n-1 ))));
6986
ELSE
@@ -75,6 +92,14 @@ BEGIN
7592
--owner := ltrim(rtrim(SUBSTR( line, 1, n-1 )));
7693
--name := LTRIM(RTRIM(SUBSTR( LINE, N +1 )));
7794

95+
EXCEPTION
96+
WHEN OTHERS THEN
97+
--we cant deal with errors in this package..so just set values to something
98+
retval(retval.LAST).handle := NVL(retval(retval.LAST).handle,' ');
99+
retval(retval.LAST).line := nvl(retval(retval.LAST).line , -1);
100+
retval(retval.LAST).caller_type := nvl(retval(retval.LAST).caller_type , 'unknown');
101+
retval(retval.LAST).object_name := nvl(retval(retval.LAST).object_name , 'unknown');
102+
END;
78103
END IF;
79104
END IF;
80105
END LOOP;
@@ -85,7 +110,7 @@ END getCallStack;
85110
FUNCTION subprogram(dynamic_depth IN PLS_INTEGER) RETURN UNIT_QUALIFIED_NAME AS
86111
cs callstack;
87112
BEGIN
88-
cs := getcallstack;
113+
cs := getcallstack(1);
89114
--RETURN UNIT_QUALIFIED_NAME(
90115
--substr(cs(dynamic_depth).object_name,1, instr(cs(dynamic_depth).object_name,'.'))
91116
--,nvl( substr(cs(dynamic_depth).object_name,instr(cs(dynamic_depth).object_name,'.')), '__anonymous_block')
@@ -97,25 +122,26 @@ END getCallStack;
97122
RETURN VARCHAR2 AS
98123
retval varchar2(2000);
99124
BEGIN
125+
IF qualified_name.FIRST IS NOT NULL THEN
100126
for i in qualified_name.first .. qualified_name.last LOOP
101127
retval := retval||'.'||qualified_name(i);
102-
end loop;
128+
END loop;
129+
END IF;
103130
RETURN LTRIM(retval,'.');
104131
END concatenate_subprogram;
105132

106133
FUNCTION owner(dynamic_depth IN PLS_INTEGER) RETURN VARCHAR2 AS
107134
cs callstack;
108135
BEGIN
109-
cs := getcallstack;
136+
cs := getcallstack(1);
110137
--RETURN subprogram(dynamic_depth)(0);
111138
RETURN substr(cs(dynamic_depth).object_name,1,instr(cs(dynamic_depth).object_name,'.')-1);
112139
END owner;
113140

114141
FUNCTION unit_line(dynamic_depth IN PLS_INTEGER) RETURN PLS_INTEGER AS
115-
116142
cs callstack;
117143
BEGIN
118-
cs := getcallstack;
144+
cs := getcallstack(1);
119145
RETURN cs(dynamic_depth).line;
120146
END unit_line;
121147

@@ -124,12 +150,10 @@ END getCallStack;
124150
FUNCTION dynamic_depth RETURN PLS_INTEGER AS
125151
cs callstack;
126152
BEGIN
127-
cs := getcallstack;
153+
cs := getcallstack(1);
128154
RETURN cs.count;
129155
END dynamic_depth;
130-
131-
132-
156+
133157
-- --------------------------------
134158
-- --------------------------------------
135159

@@ -142,7 +166,7 @@ END getCallStack;
142166
FUNCTION lexical_depth(dynamic_depth IN PLS_INTEGER) RETURN PLS_INTEGER AS
143167
cs callstack;
144168
BEGIN
145-
cs := getcallstack;
169+
cs := getcallstack(1);
146170
return LENGTH(cs(dynamic_depth).object_name) - LENGTH(REPLACE(cs(dynamic_depth).object_name, '.'));
147171
--RETURN regexp_count(cs(dynamic_depth).object_name,'\.');
148172
--RETURN length(translate(cs(dynamic_depth).object_name,'.abcdefghijk', '.'));

src/Util/UTL_CALL_STACK.pks

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
create or replace PACKAGE utl_call_stack IS
1+
create or replace PACKAGE utl_call_stack
2+
AUTHID CURRENT_USER
3+
IS
24

35
TYPE stackline IS record (
46
handle VARCHAR2(30),
@@ -8,10 +10,10 @@ caller_type varchar2(50));
810

911
TYPE callstack IS TABLE OF stackline;
1012

11-
FUNCTION getCallStack RETURN callstack;
13+
FUNCTION getCallStack(pskip number default 0) RETURN callstack;
1214

1315
/**
14-
* this is a pre 12c implementauyion of utl_call_stack.
16+
* this is a pre 12c implementation of utl_call_stack.
1517
*
1618
* @headcom
1719
*/

0 commit comments

Comments
 (0)