Từ rất lâu rồi, các “chuyên gia” oracle thường sử dụng package DBMS_UTILITY để lấy stack gọi hiện tại đang được thực thi. Ví dụ như sau:
SQL> create or replace
2 procedure old_style_call_stack is
3 begin
4 dbms_output.put_line(
5 dbms_utility.format_call_stack
6 );
7 end;
8 /
Procedure created.
SQL> create or replace package pkg
2 is
3 procedure main_proc;
4 end;
5 /
Package created.
SQL>
SQL> create or replace package body pkg
2 is
3 procedure proc_in_pkg is
4 procedure inline_proc2 is
5 procedure inline_proc3 is x int;
6 begin
7 old_style_call_stack;
8
9 end;
10 begin
11 inline_proc3;
12 end;
13 begin
14 inline_proc2;
15 end;
16
17 procedure main_proc is
18 procedure inline_proc1 is
19 begin
20 proc_in_pkg;
21 end;
22 begin
23 inline_proc1;
24 end;
25 end;
26 /
Package body created.
SQL>
SQL> set serverout on
SQL> begin
2 pkg.main_proc;
3 end;
4 /
----- PL/SQL Call Stack -----
object line object
handle number name
0x11e168060 3 procedure MCDONAC.OLD_STYLE_CALL_STACK
0x11e472ac0 7 package body MCDONAC.PKG
0x11e472ac0 11 package body MCDONAC.PKG
0x11e472ac0 14 package body MCDONAC.PKG
0x11e472ac0 20 package body MCDONAC.PKG
0x11e472ac0 23 package body MCDONAC.PKG
0x11e3efb20 2 anonymous block
PL/SQL procedure successfully completed.
Như chúng ta thấy FORMAT_CALL_STACK chỉ trả về một chuỗi đơn giản các row theo stack thực thi. Chúng ta có thể sửa đổi một chút như sau để thấy được chuỗi lệnh trông thực sự như thế nào:
SQL> create or replace
2 procedure old_style_call_stack is
3 begin
4 dbms_output.put_line(
5 replace(dbms_utility.format_call_stack,chr(10))
6 );
7 end;
8 /
Procedure created.
SQL> create or replace package pkg
2 is
3 procedure main_proc;
4 end;
5 /
Package created.
SQL>
SQL> create or replace package body pkg
2 is
3 procedure proc_in_pkg is
4 procedure inline_proc2 is
5 procedure inline_proc3 is x int;
6 begin
7 old_style_call_stack;
8
9 end;
10 begin
11 inline_proc3;
12 end;
13 begin
14 inline_proc2;
15 end;
16
17 procedure main_proc is
18 procedure inline_proc1 is
19 begin
20 proc_in_pkg;
21 end;
22 begin
23 inline_proc1;
24 end;
25 end;
26 /
Package body created.
SQL>
SQL> set serverout on
SQL> begin
2 pkg.main_proc;
3 end;
4 /
----- PL/SQL Call Stack ----- object line object handle number name 0x11e168060 3 procedure MCDONAC.OLD_STYLE_CALL_STACK0x11e472ac0
7 package body MCDONAC.PKG0x11e472ac0 11 package body MCDONAC.PKG0x11e472ac0 14 package body MCDONAC.PKG0x11e472ac0 20 package
body MCDONAC.PKG0x11e472ac0 23 package body MCDONAC.PKG0x11e3efb20 2 anonymous block
PL/SQL procedure successfully completed.
Package UTL_CALL_STACK đã cải thiện điều này bằng cách lưu trữ thông tin stack thực thi trong một cấu trúc mảng, và ở mỗi mức chúng ta có thể lấy được các thông tin theo yêu cầu:
SQL> create or replace
2 procedure better_call_stack is
3 begin
4 for i in reverse 1 .. utl_call_stack.dynamic_depth()
5 loop
6 dbms_output.put_line(
7 rpad(utl_call_stack.lexical_depth(i),9)
8 || rpad(to_char(utl_call_stack.unit_line(i),'99'),8)
9 || utl_call_stack.concatenate_subprogram(utl_call_stack.subprogram(i)));
10 end loop;
11 end;
12 /
Procedure created.
SQL>
SQL> create or replace package pkg
2 is
3 procedure main_proc;
4 end;
5 /
Package created.
SQL>
SQL> create or replace package body pkg
2 is
3 procedure proc_in_pkg is
4 procedure inline_proc2 is
5 procedure inline_proc3 is x int;
6 begin
7 --old_style_call_stack;
8 better_call_stack;
9 end;
10 begin
11 inline_proc3;
12 end;
13 begin
14 inline_proc2;
15 end;
16
17 procedure main_proc is
18 procedure inline_proc1 is
19 begin
20 proc_in_pkg;
21 end;
22 begin
23 inline_proc1;
24 end;
25 end;
26 /
Package body created.
SQL>
SQL> set serverout on
SQL> begin
2 pkg.main_proc;
3 end;
4 /
0 2 __anonymous_block
1 23 PKG.MAIN_PROC
2 20 PKG.MAIN_PROC.INLINE_PROC1
1 14 PKG.PROC_IN_PKG
2 11 PKG.PROC_IN_PKG.INLINE_PROC2
3 8 PKG.PROC_IN_PKG.INLINE_PROC2.INLINE_PROC3
0 5 BETTER_CALL_STACK
PL/SQL procedure successfully completed.
Nhưng hiệu quả lớn nhất của UTL_CALL_STACK không chỉ là việc làm rõ ràng hơn cấu trúc dữ liệu. Bạn hãy nhìn vào kết quả bên trên và bạn sẽ thấy một cải tiến quan trọng mà UTL_CALL_STACK cung cấp so với DBMS_UTILITY.
Đối với những package dùng DBMS_UTILITY, có một cách để có thể sử dụng package UTL_CALL_STACK cung cấp thêm các thông tin mong muốn như sau:
SQL> create or replace
2 procedure old_style_call_stack is
3 begin
4 dbms_output.put_line(dbms_utility.format_call_stack);
5 end;
6 /
Procedure created.
SQL> create or replace package pkg
2 is
3 procedure main_proc;
4 end;
5 /
Package created.
SQL>
SQL> create or replace package body pkg
2 is
3 procedure proc_in_pkg is
4 procedure inline_proc2 is
5 procedure inline_proc3 is x int;
6 begin
7 old_style_call_stack;
8
9 end;
10 begin
11 inline_proc3;
12 end;
13 begin
14 inline_proc2;
15 end;
16
17 procedure main_proc is
18 procedure inline_proc1 is
19 begin
20 proc_in_pkg;
21 end;
22 begin
23 inline_proc1;
24 end;
25 end;
26 /
Package body created.
SQL>
SQL> set serverout on
SQL> begin
2 pkg.main_proc;
3 end;
4 /
----- PL/SQL Call Stack -----
object line object
handle number name
00007FFE00CFA088 3 procedure MCDONAC.OLD_STYLE_CALL_STACK
00007FFE00ED34E8 7 package body MCDONAC.PKG.PROC_IN_PKG.INLINE_PROC2.INLINE_PROC3
00007FFE00ED34E8 11 package body MCDONAC.PKG.PROC_IN_PKG.INLINE_PROC2
00007FFE00ED34E8 14 package body MCDONAC.PKG.PROC_IN_PKG
00007FFE00ED34E8 20 package body MCDONAC.PKG.MAIN_PROC.INLINE_PROC1
00007FFE00ED34E8 23 package body MCDONAC.PKG.MAIN_PROC
00007FFE00D12C88 2 anonymous block
PL/SQL procedure successfully completed.
Leave a Review