23 июля 2008 г.

"Кем была вызвана процедура или функция?"

Мой коллега нашел метод позволяющий в процедуре узнать кем она была вызвана, например, в таком примере:

Есть 3 процедуры: процедура 1, процедура 2 и процедура 3
При этом процедура 3 вызывается как из процедуры 1, так и из процедуры 2
Может ли процедура 3 не используя входные параметры понять из какой процедуры она вызвана, из 1-й или 2-й?
Он нашел функцию пакета dbms_utility.format_call_stack, который оказывается возвращает полную цепочку процедур, функций или анонимного PL/SQL блока, которая вызвала эту процедуру:
----- PL/SQL Call Stack -----
object line object
handle number name
3902e1880 4 procedure MYSCHEMA.PROC3
3902e8470 3 procedure MYSCHEMA.PROC1
3902d3400 2 anonymous block
В этом примере, анонимный блок вызвал процедуру PROC1, а PROC1 вызвала процедуру PROC3.
Процедура 3, которая вызывается процедурой 1 или 2:
create or replace procedure proc3 is
call_stack varchar2(4096);
begin
call_stack := dbms_utility.format_call_stack;
dbms_output.put_line(call_stack);
end;
Процедуры 1 и 2, которые вызывают процедуру 3:
create procedure proc1 is
begin
proc3;
end;

create procedure proc2 is
begin
proc3;
end;
Вызов процедур 1 и 2:
SQL> exec proc1;

----- PL/SQL Call Stack -----
object line object
handle number name
3902e1880 4 procedure MYSCHEMA.PROC3
3902e8470 3 procedure MYSCHEMA.PROC1
390175a80 1 anonymous block

PL/SQL procedure successfully completed

SQL> exec proc2;

----- PL/SQL Call Stack -----
object line object
handle number name
3902e1880 4 procedure MYSCHEMA.PROC3
3902db938 3 procedure MYSCHEMA.PROC2
390180160 1 anonymous block

PL/SQL procedure successfully completed
Только, из стэка вызывающих процедур и функций нужно вытащить то, что нужно. В данном случае вторую строку стэка. У Тома Кайта есть процедура who_called_me, которая парсит этот стэк и возвращяет кем была вызвана процедура или функция.