powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / И снова вопрос по mon$call_stack (построение стека вызовов)
13 сообщений из 13, страница 1 из 1
И снова вопрос по mon$call_stack (построение стека вызовов)
    #38716671
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hi all

В продолжение стародавней темы от июня 2010.
dimitrТаблоидЕсть задача при любом обновлении этой таблицы записать в лог стек вызовов, т.е. из каких хранимок была дана команда, приведшая в результате к обновлению этой таблицычерез мониторинг эта задача не решается. аминь.
2 dimitr : ну сделай же что-нибудь в 3.0, ы ?

Ну невозможно же без слёз смотреть на вот это вот:

DDL:
p_01 ==> p_02 ==> p_03 ==> p_04; все p_NN - ХП; dbg_get_stack - вспомогалка для получения call-стека
Код: plaintext
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.
set term ^;
create or alter procedure p_01 as begin end^
create or alter procedure p_02 as begin end^
create or alter procedure p_03 as begin end^
create or alter procedure p_04 as begin end^

create or alter procedure dbg_get_stack
returns (
     call_level int
    ,statement_id int
    ,call_id int
    ,object_name type of column mon$call_stack.mon$object_name
    ,object_type type of column mon$call_stack.mon$object_type
    ,source_line type of column mon$call_stack.mon$source_line
    ,source_column type of column mon$call_stack.mon$source_column
)
as
begin
    for
        with recursive
        r as (
            select 1 call_level,
                 c.mon$statement_id,
                 c.mon$call_id,
                 c.mon$object_name,
                 c.mon$object_type,
                 c.mon$source_line,
                 c.mon$source_column
            from mon$call_stack c
            where c.mon$caller_id is null

            UNION ALL

            select h.call_level+1,
                   c.mon$statement_id,
                   c.mon$call_id,
                   c.mon$object_name,
                   c.mon$object_type,
                   c.mon$source_line,
                   c.mon$source_column
            from mon$call_stack c
              join r h
                on c.mon$caller_id = h.mon$call_id
        )
     select
        r.call_level
       ,r.mon$statement_id
       ,r.mon$call_id
       ,r.mon$object_name
       ,r.mon$object_type
       ,r.mon$source_line
       ,r.mon$source_column
    from r
    into
       call_level
       ,statement_id
       ,call_id
       ,object_name
       ,object_type
       ,source_line
       ,source_column
   do
       suspend;
end
^
set term ;^
commit;

recreate table dbg_stack(
     whoami varchar(31)
    ,call_level int
    ,statement_id int
    ,call_id int
    ,object_name char(31)
    ,object_type smallint
    ,source_line int
    ,source_column int
);
commit;
---------------------------------
set term ^;
create or alter procedure p_04 as
    declare n int;
begin
                -- dummy row 1
                -- dummy row 2
                -- dummy row 3
                -- dummy row 4
                select count(*) from rdb$types into n;
                insert into dbg_stack
                select  'p_04',p.*
                from dbg_get_stack p;
end
^
create or alter procedure p_03 as
    declare n int;
begin
            -- dummy row 1
            -- dummy row 2
            -- dummy row 3
            select count(*) from rdb$types into n;
            insert into dbg_stack
            select  'p_03',p.*
            from dbg_get_stack p;
            execute procedure p_04;
end
^
create or alter procedure p_02 as
    declare n int;
begin
        -- dummy row 1
        -- dummy row 2
        select count(*) from rdb$types into n;
        insert into dbg_stack
        select  'p_02',p.*
        from dbg_get_stack p;
        execute procedure p_03;
end
^
create or alter procedure p_01 as
    declare n int;
begin
    -- dummy row 1
    delete from dbg_stack;
    select count(*) from rdb$types into n;
    insert into dbg_stack
    select  'p_01',p.*
    from dbg_get_stack p;
    execute procedure p_02;
end
^
set term ;^
commit;
Test:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
SQL> execute procedure p_01;
SQL> set width whoami 6;
SQL> set width object_name 13;
SQL> select * from dbg_stack;

WHOAMI   CALL_LEVEL STATEMENT_ID      CALL_ID OBJECT_NAME   OBJECT_TYPE  SOURCE_LINE SOURCE_COLUMN
====== ============ ============ ============ ============= =========== ============ =============
p_01              1       810820       810821 P_01                    5            7             5
p_01              2       810820       810822 DBG_GET_STACK           5           13             5
p_02              1       810820       810821 P_01                    5            7             5
p_02              2       810820       810822 DBG_GET_STACK           5           13             5
p_03              1       810820       810821 P_01                    5            7             5
p_03              2       810820       810822 DBG_GET_STACK           5           13             5
p_04              1       810820       810821 P_01                    5            7             5
p_04              2       810820       810822 DBG_GET_STACK           5           13             5

Ну как можно отладить что-то, когда на заборе написаны такие "дрова" ? (я про P_03 и P_04, которые якобы были вызваны непосредственно из P_01) ?!
...
Рейтинг: 0 / 0
И снова вопрос по mon$call_stack (построение стека вызовов)
    #38716674
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоид,

в dbg_get_stack не вижу автономной транзакции
...
Рейтинг: 0 / 0
И снова вопрос по mon$call_stack (построение стека вызовов)
    #38716687
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitrв dbg_get_stack не вижу автономной транзакцииДобавил (хотя не понимаю, почему это нужно делать. Особливо если учесть, что мониторинг работает в til = snapshot...)
И всё равно - не взлетает каменный цветок.

Вот обновленнный DDL:
ХП dbg_get_stack результат теперь НЕ возвращает, а просто пишет в таблицу dbg_stack в автономной трн
Код: plaintext
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.
set term ^;
create or alter procedure dbg_get_stack as begin end^
create or alter procedure p_01 as begin end^
create or alter procedure p_02 as begin end^
create or alter procedure p_03 as begin end^
create or alter procedure p_04 as begin end^
set term ;^
recreate table dbg_stack(
     whoami varchar(31)
    ,call_level int
    ,statement_id int
    ,call_id int
    ,object_name char(31)
    ,object_type smallint
    ,source_line int
    ,source_column int
);
commit;

set term ^;
create or alter procedure dbg_get_stack(a_whoami varchar(31))
as
begin
    in autonomous transaction do
    begin
        for
            with recursive
            r as (
                select 1 call_level,
                     c.mon$statement_id,
                     c.mon$call_id,
                     c.mon$object_name,
                     c.mon$object_type,
                     c.mon$source_line,
                     c.mon$source_column
                from mon$call_stack c
                where c.mon$caller_id is null
    
                UNION ALL
    
                select h.call_level+1,
                       c.mon$statement_id,
                       c.mon$call_id,
                       c.mon$object_name,
                       c.mon$object_type,
                       c.mon$source_line,
                       c.mon$source_column
                from mon$call_stack c
                  join r h
                    on c.mon$caller_id = h.mon$call_id
            )
         select
            r.call_level
           ,r.mon$statement_id
           ,r.mon$call_id
           ,r.mon$object_name
           ,r.mon$object_type
           ,r.mon$source_line
           ,r.mon$source_column
        from r
        as cursor cr do
        begin
            insert into dbg_stack
            values(
                :a_whoami
               ,cr.call_level
               ,cr.mon$statement_id
               ,cr.mon$call_id
               ,cr.mon$object_name
               ,cr.mon$object_type
               ,cr.mon$source_line
               ,cr.mon$source_column
            );
        end
   end

end
^
set term ;^
commit;

---------------------------------
set term ^;
create or alter procedure p_04 as
    declare n int;
begin
                -- dummy row 1
                -- dummy row 2
                -- dummy row 3
                -- dummy row 4
                execute procedure dbg_get_stack( 'p_04' );
end
^
create or alter procedure p_03 as
    declare n int;
begin
            -- dummy row 1
            -- dummy row 2
            -- dummy row 3
            execute procedure p_04;
end
^
create or alter procedure p_02 as
    declare n int;
begin
        -- dummy row 1
        -- dummy row 2
        execute procedure p_03;
end
^
create or alter procedure p_01 as
    declare n int;
begin
    -- dummy row 1
    delete from dbg_stack;
    execute procedure p_02;
end
^
set term ;^
commit;
Test :
Код: plaintext
1.
execute procedure p_01;
select * from dbg_stack;

Result:
WHOAMICALL_LEVELSTATEMENT_IDCALL_IDOBJECT_NAMEOBJECT_TYPESOURCE_LINESOURCE_COLUMNp_041812513812465P_01565p_042812513812466P_02569p_043812513812467P_035713p_044812513812468P_045817p_045812513812469DBG_GET_STACK569p_044812513812468P_045817p_045812513812469DBG_GET_STACK569p_043812513812467P_035713p_044812513812468P_045817p_045812513812469DBG_GET_STACK569p_044812513812468P_045817p_045812513812469DBG_GET_STACK569p_042812513812466P_02569p_043812513812467P_035713p_044812513812468P_045817p_045812513812469DBG_GET_STACK569p_044812513812468P_045817p_045812513812469DBG_GET_STACK569p_043812513812467P_035713p_044812513812468P_045817p_045812513812469DBG_GET_STACK569p_044812513812468P_045817p_045812513812469DBG_GET_STACK569p_041812513812465P_01565p_042812513812466P_02569p_043812513812467P_035713p_044812513812468P_045817p_045812513812469DBG_GET_STACK569p_044812513812468P_045817p_045812513812469DBG_GET_STACK569p_043812513812467P_035713p_044812513812468P_045817p_045812513812469DBG_GET_STACK569p_044812513812468P_045817p_045812513812469DBG_GET_STACK569p_042812513812466P_02569p_043812513812467P_035713p_044812513812468P_045817p_045812513812469DBG_GET_STACK569p_044812513812468P_045817p_045812513812469DBG_GET_STACK569p_043812513812467P_035713p_044812513812468P_045817p_045812513812469DBG_GET_STACK569p_044812513812468P_045817p_045812513812469DBG_GET_STACK569
"Глазами вижу", что в итоговой выборке должно быть только первые 5 строк из того, что на самом деле вылезло. Но чем это ограничить, доп. критерий какой-то есть ?
...
Рейтинг: 0 / 0
И снова вопрос по mon$call_stack (построение стека вызовов)
    #38716712
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тут весьма интересный эффект получается.

Когда в автономной тр-ции создаётся снапшот мониторинга, то стек вызовов текущего стейтмента в него попадает дважды - с основной и с автономной тр-цией (на самом деле там чуть сложнее, не хочу расписывать).
Поэтому у тебя дублируются данные.

PS Патч будет передан dimitr'у на рассмотрение.
...
Рейтинг: 0 / 0
И снова вопрос по mon$call_stack (построение стека вызовов)
    #38716721
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Фигово всё, джентльмены... :(

Чтобы получить в PSQL стек вызовов, надо стартовать автономку.
Старт автономки при работе с TIL =SNAPSHOT - дело весьма затратное, ибо копируется вся TIP. Если (OIT-OST)/2 больше 64 Кб, то будет вызов mmap'a, т.е. обращение за памятью к OS вместо юзания внутренних буферов ФБ. Эта операция, насколько я теперь знаю, является "сериализуемой", т.е. выстраивает всех, кто хочет поиметь такую память, в очередь.

Но даже если забить на это, стек всё равно будет содержать путь не до той точки, где вспыхло исключение (и именно так он показывается клиентом ), а до when-секции. То есть, самая интересная точка в нём - "не оттуда".

Надо бы встроенную переменную, об чём я просил в трекере , но тот вопрос висит в unresolved и, чую, долго еще будет так висеть.

Пойду-ка в дежурную аптеку. Там, говорят, завезли накануне...
...
Рейтинг: 0 / 0
И снова вопрос по mon$call_stack (построение стека вызовов)
    #38719709
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvladТут весьма интересный эффект получается.После внедрёжа вот этого: http://svn.code.sf.net/p/firebird/code/firebird/trunk/ChangeLog 2014-08-12 10:21 hvlad
M src/jrd/Monitoring.cpp
Avoid info duplication when statements in call stack attached to different transactions (for example: monitoring snapshot is created in autonomous transaction)
- стало лучше. Но эффекты тоже стали еще более "интересными".

Дано:
1) master & detail таблицы, связаны по FK с on delete cascade; их имена: dbg_main & dbg_detl;
2) на detail-таблицу наверчен триггер before delete or update, который вызывает несколько процедур:
Код: sql
1.
2.
3.
4.
5.
create or alter trigger dbg_detl_bud for dbg_detl active before update or delete
as
begin
  execute procedure p_01; -- а из неё вызываются ХП: P_02 ==> P_03 ==> P_04 ==> DBG_GET_STACK 
end


3) в master-таблицу вводится одна запись, в detail - две подчинённые к ней.
4) процедуры P_01...P_04, DBG_GET_STACK, и вообще весь DDL :
Код: plaintext
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.
set term ^;
create or alter procedure dbg_get_stack as begin end^
create or alter procedure p_01 as begin end^
create or alter procedure p_02 as begin end^
create or alter procedure p_03 as begin end^
create or alter procedure p_04 as begin end^
create or alter procedure p_00 as begin end^
set term ;^
commit;
------------------------------------------------------------------------
recreate table dbg_detl(id int primary key, pid int);
recreate table dbg_main(id int primary key);
commit;
alter table dbg_detl add constraint dbg_detl_fk foreign key (pid)
references dbg_main(id)
on delete cascade;
commit;
------------------------------------------------------------------------

recreate table dbg_stack(
     whoami varchar(31)
    ,call_level int
    ,statement_id int
    ,call_id int
    ,object_name char(31)
    ,object_type smallint
    ,source_line int
    ,source_column int
    ,trn_id int default current_transaction
);
commit;

set term ^;
create or alter procedure dbg_get_stack(
    a_whoami varchar(31)
)
as
    declare call_level int;
    declare mon$statement_id type of column mon$call_stack.mon$statement_id;
    declare mon$call_id type of column mon$call_stack.mon$call_id;
    declare mon$object_name type of column mon$call_stack.mon$object_name;
    declare mon$object_type type of column mon$call_stack.mon$object_type;
    declare mon$source_line type of column mon$call_stack.mon$source_line;
    declare mon$source_column type of column mon$call_stack.mon$source_column;
    declare v_stt varchar(4096);  -- use dyn SQL for watching in trace! 
begin
    v_stt = 'with recursive'
            || ' r as ('
            || '    select 1 call_level,'
            || '         c.mon$statement_id,'
            || '         c.mon$call_id,'
            || '         c.mon$object_name,'
            || '         c.mon$object_type,'
            || '         c.mon$source_line,'
            || '         c.mon$source_column'
            || '    from mon$call_stack c'
            || '    where c.mon$caller_id is null'
            || '    UNION ALL'
            || '    select h.call_level+1,'
            || '           c.mon$statement_id,'
            || '           c.mon$call_id,'
            || '           c.mon$object_name,'
            || '           c.mon$object_type,'
            || '           c.mon$source_line,'
            || '           c.mon$source_column'
            || '    from mon$call_stack c'
            || '      join r h'
            || '        on c.mon$caller_id = h.mon$call_id'
            || ')'
            || ' select'
            || '    r.call_level'
            || '   ,r.mon$statement_id'
            || '   ,r.mon$call_id'
            || '   ,r.mon$object_name'
            || '   ,r.mon$object_type'
            || '   ,r.mon$source_line'
            || '   ,r.mon$source_column'
            || ' from r'
    ;
    for
        execute statement (v_stt)
         with autonomous transaction  -- ::: NB ::: 
        into
            :call_level
            ,:mon$statement_id
            ,:mon$call_id
            ,:mon$object_name
            ,:mon$object_type
            ,:mon$source_line
            ,:mon$source_column
        do begin
            insert into dbg_stack(
                whoami
                ,call_level
                ,statement_id
                ,call_id
                ,object_name
                ,object_type
                ,source_line
                ,source_column
                --,trn_id
            )
            values(
                :a_whoami
                ,:call_level
                ,:mon$statement_id
                ,:mon$call_id
                ,:mon$object_name
                ,:mon$object_type
                ,:mon$source_line
                ,:mon$source_column
                --,current_transaction
            );
        end
end
^
set term ;^
commit;

---------------------------------
set term ^;
create or alter procedure p_04 as
    declare n int;
begin
                -- dummy row 1
                -- dummy row 2
                -- dummy row 3
                -- dummy row 4
                execute procedure dbg_get_stack( 'p_04' );
end
^
create or alter procedure p_03 as
    declare n int;
begin
            -- dummy row 1
            -- dummy row 2
            -- dummy row 3
            execute procedure p_04;
end
^
create or alter procedure p_02 as
    declare n int;
begin
        -- dummy row 1
        -- dummy row 2
        execute procedure p_03;
end
^
create or alter procedure p_01 as
    declare n int;
begin
    -- dummy row 1
    execute procedure p_02;
end
^

---------------------
create or alter trigger dbg_detl_bud for dbg_detl active before update or delete
as
begin
  execute procedure p_01;
end
^

set term ;^
commit;

insert into dbg_main(id) values(1);
insert into dbg_detl(id, pid) values(1,1);
insert into dbg_detl(id, pid) values(2,1);
commit;


Далее делаем два варианта удаления из dbg_detl:
1) непосредственно удаляя из неё, т.е.: delete from dbg_detl;
2) опосредованно через delete from dbg_main, что вызовет каскадный триггер на удаление подчинённых строк в dbg_detl (и это удаление уже приведёт к срабатыванию вышепоказанного триггерка dbg_detl_bud).

Скрипт для варианта-1 :
Код: sql
1.
2.
3.
4.
5.
set width whoami 15; set width object_name 20; 
select current_transaction from rdb$database; 
delete from dbg_detl; 
select whoami,call_level,object_name,source_line,source_column,trn_id from dbg_stack; 
rollback;


Его результат:
всё хорошо, кроме номера транзакции в dbg_stack - см в конце поста "вопрос-2"
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
CURRENT_TRANSACTION
===================
              62761


WHOAMI            CALL_LEVEL OBJECT_NAME           SOURCE_LINE SOURCE_COLUMN       TRN_ID
=============== ============ ==================== ============ ============= ============
p_04                       1 DBG_DETL_BUD                    4             3        62761
p_04                       2 P_01                            5             5        62761
p_04                       3 P_02                            6             9        62761
p_04                       4 P_03                            7            13        62761
p_04                       5 P_04                            8            17        62761
p_04                       6 DBG_GET_STACK                  47             5        62761
p_04                       1 DBG_DETL_BUD                    4             3        62761
p_04                       2 P_01                            5             5        62761
p_04                       3 P_02                            6             9        62761
p_04                       4 P_03                            7            13        62761
p_04                       5 P_04                            8            17        62761
p_04                       6 DBG_GET_STACK                  47             5        62761

Скрипт для варианта-2 :
Код: sql
1.
2.
3.
4.
5.
6.
set width whoami 15; set width object_name 20; 
select current_transaction from rdb$database; 
delete from dbg_main; 
select whoami,call_level,object_name,source_line,source_column,trn_id from dbg_stack; 
rollback;
select * from dbg_stack;



Его результат:
Код: plaintext
1.
2.
3.
CURRENT_TRANSACTION
===================
              62764

(да, это - весь результат: никаких данных в dbg_stack нету!)

Фрагмент трейса для варианта-1 :
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
2014-08-13T17:38:04.1130 (30975:0x7fb5e238a9d0) EXECUTE_STATEMENT_FINISH
        oltp30 (ATT_319, SYSDBA:NONE, NONE, TCPv4:192.168.43.96)
        C:\MIX\firebird\fb25\bin\isql.exe:2916
                (TRA_62763, CONCURRENCY | WAIT | READ_WRITE)

Statement 927:
-------------------------------------------------------------------------------
with recursive r as (    select 1 call_level,         c.mon$statement_id,         c.mon$call_id,         c.mon$object_name,         c.mon$object_type,         c.mon$source_line,         c.mon$source_column    from mon$call_stack c    where c.mon$caller_id is null    UNION ALL    select h.call_level+1,           c.mon$statement_id,           c.mon$call_id,           c.mon$object_name,           c.mon$object_type,           c.mon$source_line,           c.mon$source_column    from mon$call_stack c      join r h        on c.mon$caller_id = h.mon$call_id) select    r.call_level   ,r.mon$statement_id   ,r.mon$call_id   ,r.mon$object_name   ,r.mon$object_type   ,r.mon$source_line   ,r.mon$source_column from r
 6 records fetched 
      0 ms, 1 fetch(es)

2014-08-13T17:38:04.1130 (30975:0x7fb5e238a9d0) EXECUTE_PROCEDURE_FINISH
        oltp30 (ATT_319, SYSDBA:NONE, NONE, TCPv4:192.168.43.96)
        C:\MIX\firebird\fb25\bin\isql.exe:2916
                (TRA_62761, CONCURRENCY | WAIT | READ_WRITE)

Procedure DBG_GET_STACK:
param0 = varchar(31), "p_04"

      0 ms, 18 fetch(es),  6 mark(s) 

Table                             Natural     Index    Update    Insert    Delete   Backout     Purge   Expunge
***************************************************************************************************************
DBG_STACK                                                              6 

Фрагмент трейса для варианта-2 :
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
2014-08-13T17:40:57.8280 (30975:0x7fb5e238dcc0) EXECUTE_STATEMENT_FINISH
        oltp30 (ATT_319, SYSDBA:NONE, NONE, TCPv4:192.168.43.96)
        C:\MIX\firebird\fb25\bin\isql.exe:2916
                (TRA_62766, CONCURRENCY | WAIT | READ_WRITE)

Statement 933:
-------------------------------------------------------------------------------
with recursive r as (    select 1 call_level,         c.mon$statement_id,         c.mon$call_id,         c.mon$object_name,         c.mon$object_type,         c.mon$source_line,         c.mon$source_column    from mon$call_stack c    where c.mon$caller_id is null    UNION ALL    select h.call_level+1,           c.mon$statement_id,           c.mon$call_id,           c.mon$object_name,           c.mon$object_type,           c.mon$source_line,           c.mon$source_column    from mon$call_stack c      join r h        on c.mon$caller_id = h.mon$call_id) select    r.call_level   ,r.mon$statement_id   ,r.mon$call_id   ,r.mon$object_name   ,r.mon$object_type   ,r.mon$source_line   ,r.mon$source_column from r
 0 records fetched 
      0 ms, 1 fetch(es)

2014-08-13T17:40:57.8280 (30975:0x7fb5e238dcc0) EXECUTE_PROCEDURE_FINISH
        oltp30 (ATT_319, SYSDBA:NONE, NONE, TCPv4:192.168.43.96)
        C:\MIX\firebird\fb25\bin\isql.exe:2916
                (TRA_62764, CONCURRENCY | WAIT | READ_WRITE)

Procedure DBG_GET_STACK:
param0 = varchar(31), "p_04"

      0 ms


ИТОГО получаем: при удалении, которое вызвано каскадным триггером (вариант-2), записи в mon$call_stack недоступны. По кр. мере, вот этот запрос ("якорь" рекурсии):
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
                select 1 call_level,
                     c.mon$statement_id,
                     c.mon$call_id,
                     c.mon$object_name,
                     c.mon$object_type,
                     c.mon$source_line,
                     c.mon$source_column
                from mon$call_stack c
                where c.mon$caller_id is null

- возвращает ноль строк и рекурсия, след-но, тоже ничего не вернёт.

ВОПРОС-1 : Как заполучить стек вызовов в таком случае, как вариант-2 ?


Кроме того, хотя и оффтоп, но скажу сюда и ВОПРОС-2 , чтоб не забылось.
Если я выполняю вот это вот (см ХП dbg_get_stack в вышеприведенном DDL):
Код: plaintext
1.
2.
3.
4.
5.
6.
    for
        execute statement (v_stt)
         with autonomous transaction 
        into . . .
   do begin
      insert into ...
   end
- то согласно доке: http://www.firebirdsql.org/refdocs/langrefupd25-psql-execstat.html#langrefupd25-psql-execstat-with-trans WITH AUTONOMOUS TRANSACTION causes a separate transaction to be started, with the same parameters as the current transaction- должна была стартовать НОВАЯ транзакция. Но по результатам варианта-1 видим, что этого не случилось. Это так и должно быть ?
...
Рейтинг: 0 / 0
И снова вопрос по mon$call_stack (построение стека вызовов)
    #38719732
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
про каскады старый баян, на днях постараюсь поправить
...
Рейтинг: 0 / 0
И снова вопрос по mon$call_stack (построение стека вызовов)
    #38719742
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitrпро каскады старый баян, на днях постараюсь поправитьа в 2.5 бакпорт сделаешь ?
...
Рейтинг: 0 / 0
И снова вопрос по mon$call_stack (построение стека вызовов)
    #38719773
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоиддолжна была стартовать НОВАЯ транзакция. Но по результатам варианта-1 видим, что этого не случилось. Это так и должно быть ?Отбой, разобрался. Надо было включать в строку стейтмента, который динамически выполняется, слово 'current_transaction'.
...
Рейтинг: 0 / 0
И снова вопрос по mon$call_stack (построение стека вызовов)
    #38719816
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitrпро каскады старый баянЕсли ты про CORE-2286 , то почему он 'Fixed' & 'Closed' ?
...
Рейтинг: 0 / 0
И снова вопрос по mon$call_stack (построение стека вызовов)
    #38719846
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоид,

нет, этот тикет совсем не причем
...
Рейтинг: 0 / 0
И снова вопрос по mon$call_stack (построение стека вызовов)
    #38720426
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitrпро каскады старый баян, на днях постараюсь поправитьА вот тут ещё одна внезапность: если ХП вызывать через ES, то внутри неё (или тех модулей, что она вызывает) обращение к mon$call_stack - бесполезное дело. Не видна часть стека, которая была ДО вызова через ES.
Это баян или нет ?
DDL:
::: NB ::: см вызов процедуры P_04 via ES в ХП P_03
Код: plaintext
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.
set term ^;
create or alter procedure p_01 as begin end^
create or alter procedure p_02 as begin end^
create or alter procedure p_03 as begin end^
create or alter procedure p_04 as begin end^

create or alter procedure dbg_get_stack
returns (
     call_level int
    ,statement_id int
    ,call_id int
    ,object_name type of column mon$call_stack.mon$object_name
    ,object_type type of column mon$call_stack.mon$object_type
    ,source_line type of column mon$call_stack.mon$source_line
    ,source_column type of column mon$call_stack.mon$source_column
)
as
begin
    for
        with recursive
        r as (
            select 1 call_level,
                 c.mon$statement_id,
                 c.mon$call_id,
                 c.mon$object_name,
                 c.mon$object_type,
                 c.mon$source_line,
                 c.mon$source_column
            from mon$call_stack c
            where c.mon$caller_id is null

            UNION ALL

            select h.call_level+1,
                   c.mon$statement_id,
                   c.mon$call_id,
                   c.mon$object_name,
                   c.mon$object_type,
                   c.mon$source_line,
                   c.mon$source_column
            from mon$call_stack c
              join r h
                on c.mon$caller_id = h.mon$call_id
        )
     select
        r.call_level
       ,r.mon$statement_id
       ,r.mon$call_id
       ,r.mon$object_name
       ,r.mon$object_type
       ,r.mon$source_line
       ,r.mon$source_column
    from r
    into
       call_level
       ,statement_id
       ,call_id
       ,object_name
       ,object_type
       ,source_line
       ,source_column
   do
       suspend;
end
^
set term ;^
commit;

recreate table dbg_stack(
     whoami varchar(31)
    ,call_level int
    ,statement_id int
    ,call_id int
    ,object_name char(31)
    ,object_type smallint
    ,source_line int
    ,source_column int
);
commit;
---------------------------------
set term ^;
create or alter procedure p_04 as
    declare n int;
begin
                -- dummy row 1
                -- dummy row 2
                -- dummy row 3
                -- dummy row 4
                insert into dbg_stack
                select  'p_04',p.*
                from dbg_get_stack p;
end
^
create or alter procedure p_03 as
    declare n int;
    declare s varchar(30);
begin
            -- dummy row 1
            -- dummy row 2
            -- dummy row 3
             --execute procedure p_04;  -- так было
             execute statement('execute procedure p_04');  -- так стало
end
^
create or alter procedure p_02 as
    declare n int;
begin
        -- dummy row 1
        -- dummy row 2
        execute procedure p_03;
end
^
create or alter procedure p_01 as
    declare n int;
begin
    -- dummy row 1
    delete from dbg_stack;
    execute procedure p_02;
end
^
set term ;^
commit;

test:
execute procedure p_01;
select * from dbg_stack;

result:
WHOAMICALL_LEVELSTATEMENT_IDCALL_IDOBJECT_NAMEOBJECT_TYPESOURCE_LINESOURCE_COLUMNp_041945918P_045817p_042945919DBG_GET_STACK5135

А вот если убрать ES и вернуть взад то, что было ранее, то будет всё Ок:WHOAMICALL_LEVELSTATEMENT_IDCALL_IDOBJECT_NAMEOBJECT_TYPESOURCE_LINESOURCE_COLUMNp_04110491050P_01565p_04210491051P_02569p_04310491052P_035813p_04410491053P_045817p_04510491054DBG_GET_STACK5135
PS. LI-T6.3.0.31288 Firebird 3.0 Alpha 2
...
Рейтинг: 0 / 0
И снова вопрос по mon$call_stack (построение стека вызовов)
    #38720684
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоид,

тоже баян
...
Рейтинг: 0 / 0
13 сообщений из 13, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / И снова вопрос по mon$call_stack (построение стека вызовов)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]