Just some things to help with debugging PL/SQL code.
These grants must be made to the user creating the package.
It would be useful to know what the current level is in the call stack when debugging.
For Oracle 12c+, that can be obtained via UTL_CALL_STACK.DYNAMIC_DEPTH.
For older versions, it is more difficult.
What this code does is walk through the call stack and look for address lines.
The call depth is 0 based.
When you build the call_depth package, dbms_db_version.version is used to determine which code to compile.
This has been tested on 11.1 and 19.8 versions of the oracle database.
This script is called prior to creating the package. Adjust the values in this script as necessary.
Shortcut to create the call_depth
and dbg
packages.
A short demo of getting stack depth in oracle, before and after 11g.
All coded in a PL/SQL anonymous block
SQL# @demo-01
root stack depth: 0
### P1 ###
----- PL/SQL Call Stack -----
object line object
handle number name
0xb8920dc8 129 anonymous block
0xb8920dc8 147 anonymous block
current stack depth: 1
### P2 ###
----- PL/SQL Call Stack -----
object line object
handle number name
0xb8920dc8 112 anonymous block
0xb8920dc8 136 anonymous block
0xb8920dc8 147 anonymous block
current stack depth: 2
### P3 ###
----- PL/SQL Call Stack -----
object line object
handle number name
0xb8920dc8 95 anonymous block
0xb8920dc8 119 anonymous block
0xb8920dc8 136 anonymous block
0xb8920dc8 147 anonymous block
current stack depth: 3
PL/SQL procedure successfully completed.
Similar to demo-01.sql, but calls the call_depth
package.
SQL# @demo-02
root stack depth: 1
### P1 ###
----- PL/SQL Call Stack -----
object line object
handle number name
0x71f23990 24 anonymous block
0x71f23990 32 anonymous block
current stack depth: 2
### P2 ###
----- PL/SQL Call Stack -----
object line object
handle number name
0x71f23990 15 anonymous block
0x71f23990 26 anonymous block
0x71f23990 32 anonymous block
current stack depth: 3
### P3 ###
----- PL/SQL Call Stack -----
object line object
handle number name
0x71f23990 7 anonymous block
0x71f23990 17 anonymous block
0x71f23990 26 anonymous block
0x71f23990 32 anonymous block
current stack depth: 4
PL/SQL procedure successfully completed.
A more comprehensive demo of call_depth
SQL# @call-depth-test-01.sql
main depth : 1
who am i: __anonymous_block
who called: NA
p1 depth : 2
who am i: __anonymous_block.P1
who called: __anonymous_block
p2 depth : 3
who am i: __anonymous_block.P2
who called: __anonymous_block.P1
p3 depth : 4
who am i: __anonymous_block.P3
who called: __anonymous_block.P2
PL/SQL procedure successfully completed.
Create the package:
SQL# @call-depth
Package created.
No errors.
Package body created.
No errors.
Returns calling depth from the stack.
The value returned is adjusted so that values match:
- between 11g and 12c+
- whether called from anonymous block or stored procedures
declare
i_call_depth integer;
begin
i_call_depth := call_depth.get_depth;
dbms_output.put_line('depth: ' || to_char(i_call_depth));
end;
/
depth: 1
PL/SQL procedure successfully completed.
This will not work when called directly from sqlplus:
SQL# select call_depth.get_depth from dual;
select call_depth.get_depth from dual
*
ERROR at line 1:
ORA-64610: bad depth indicator
ORA-06512: at "SYS.UTL_CALL_STACK", line 19
ORA-06512: at "JKSTILL.CALL_DEPTH", line 218
Returns the name of the current procedure or function.
Note, this must be called immediately following a call to call_depth.get_depth.
declare
who_am_i varchar2(120);
begin
who_am_i := call_depth.who_am_i;
dbms_output.put_line('who_am_i: ' || who_am_i);
end;
SQL# /
who_am_i: __anonymous_block
Returns the name of the calling procedure or function.
Note, this must be called immediately following a call to call_depth.get_depth.
declare
who_called_me varchar2(120);
begin
who_called_me := call_depth.who_called_me;
dbms_output.put_line('who_called_me: ' || who_called_me);
end;
/
who_called_me: NA
As this was the body of an anonymous block, there was not caller; hence the NA.
This is a demo of using the call_depth package:
SQL# @demo-02
line: 0x818f3bd8 61 anonymous block
root stack depth: 0
### P1 ###
----- PL/SQL Call Stack -----
object line object
handle number name
0x818f3bd8 48 anonymous block
0x818f3bd8 66 anonymous block
line: 0x818f3bd8 50 anonymous block
line: 0x818f3bd8 66 anonymous block
current stack depth: 1
### P2 ###
----- PL/SQL Call Stack -----
object line object
handle number name
0x818f3bd8 31 anonymous block
0x818f3bd8 55 anonymous block
0x818f3bd8 66 anonymous block
line: 0x818f3bd8 33 anonymous block
line: 0x818f3bd8 55 anonymous block
line: 0x818f3bd8 66 anonymous block
current stack depth: 2
### P3 ###
----- PL/SQL Call Stack -----
object line object
handle number name
0x818f3bd8 14 anonymous block
0x818f3bd8 38 anonymous block
0x818f3bd8 55 anonymous block
0x818f3bd8 66 anonymous block
line: 0x818f3bd8 17 anonymous block
line: 0x818f3bd8 38 anonymous block
line: 0x818f3bd8 55 anonymous block
line: 0x818f3bd8 66 anonymous block
current stack depth: 3
PL/SQL procedure successfully completed.
The depth of the stack is different when called via anonymous block than when called strictly within stored code.
The value of depth of the current call is adjust to provide a consistent value, whether called from an anonymous block, or a stored procedure.
See these test scripts:
- call-stack-test-01.sql
- uses an anonymous block
- call-stack-test-02.sql
- uses a test package
The DBG package is a fairly simple package for debugging output and minimal logging.
The call depth is used to indent the text sent to dbg.debug_print.
Logging messages are created with dbg.logentry.
The default table name for the log table is PLSQL_LOG. This can be changed in the package body if you like. No indexes are created on the table - create whatever indexes you need.
The first invocation of dbg.logentry will create the log table if it doesn't already exist, along with a sequence PLSQL_LOG_SEQ.
Following are some tests of the package.
This script is called prior to creating the package. Adjust the values in this script as necessary.
This is the file used to create the package DBG.
SQL# @debug-pkg.sql
this line appears only when the develop flag is true
this line appears only when the debug flag is true
PL/SQL procedure successfully completed.
Package created.
No errors.
Package body created.
No errors.
Enable debugging output. It is disabled by default.
Disable debugging output. It is disabled by default.
Print the text if debugging is enabled.
dbg.debug_print('This is a test of the debug package');
Returns a boolean indicating the current debug status.
The same as dbms_output.print, but a bit easier to type.
The same as dbms_output.print_line, but a bit easier to type.
Get the character used to compose the header line used in dbg.debug_print;
Set the character used to compose the header line used in dbg.debug_print.
This will have effect only if called prior to the first call to dbg.debug_print.
Get the character used to compose the footer line used in dbg.debug_print;
Set the character used to compose the footer line used in dbg.debug_print.
This will have effect only if called prior to the first call to dbg.debug_print.
Get the length used for the header and footer lines.
Get the length used for the header and footer lines.
This will have effect only if called prior to the first call to dbg.debug_print.
Get the character used for padding the debug output text.
Set the character used for padding the debug output text.
Get the value for the current indent size.
Set the value for the indent size.
Initialize the log table and sequence.
This will be done automatically with the first logentry as well.
Add an entry to the log table.
See dbg-pkg-test-02.sql
for an example usage.
Just a simple test of the function that checks for the existence of the log table
SQL# @dbg-pkg-test-01.sql
this line appears only when the develop flag is true
this line appears only when the debug flag is true
PL/SQL procedure successfully completed.
table exists
PL/SQL procedure successfully completed.
This test enables debugging output, and prints a line of debug output.
Next it creates a log entry, and then selects the most recent log entry from the PLSQL_LOG table.
QL# @dbg-pkg-test-02.sql
this line appears only when the develop flag is true
this line appears only when the debug flag is true
PL/SQL procedure successfully completed.
============================================================
This is a test of the debug package
------------------------------------------------------------
PL/SQL procedure successfully completed.
ID LOG_TIMESTAMP CLIENT_INFO MODULE_INFO
---------- --------------------------------------------------------------------------- ---------------------------------------------------------------- ----------------------------------------------------------------
ACTION_INFO TAGS MSG
---------------------------------------------------------------- ---------------------------------------------------------------- --------------------------------------------------------------------------------
282 24-DEC-20 04.34.45.409620 PM Test Client Info Test Client Info: Module
Test Client Info: Action 1 free form search text This is a message for testing the DBG package
1 row selected.
This script demonstrate the use of call stack depth in debug output.
QL# @dbg-pkg-test-03.sql
============================================================
This is main
------------------------------------------------------------
Depth: 0
============================================================
This is p1
------------------------------------------------------------
Depth: 1
============================================================
This is p2
------------------------------------------------------------
Depth: 2
============================================================
This is p3
------------------------------------------------------------
Depth: 3
PL/SQL procedure successfully completed.