powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Стек вызова в Oracle 10g
9 сообщений из 9, страница 1 из 1
Стек вызова в Oracle 10g
    #40029481
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Подскажите, можно ли достать в 10g стек вызова?
Хочу протоколировать вызов процедур и функций в своем package, но не хочу каждый раз вручную указывать имя текущей процедуры или функции.
FORMAT_CALL_STACK подходит плохо, во-первых стек он выводит просто текстом, во-вторых в стеке есть только номер строки, но нет имени процедуры/функции.
UTL_CALL_STACK выглядит более интересно, но это только с 12 версии.
Мне полноценный стек не нужен, достаточно знать квалифицированное имя, откуда была вызвана текущая функция, и "глубину" вызова.
Вот тут вроде бы бэкпорт UTL_CALL_STACK для 9 и 10 версии, но требует для работы p_stack.
p_stack есть рядом , но он у меня не компилируется.
...
Рейтинг: 0 / 0
Стек вызова в Oracle 10g
    #40029493
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
p_stack загрузить удалось. Во-первых нужно было добавить типы, во-вторых нужно было загружать его в системную схему (чтобы был доступ к ALL_SOURCE).
Но теперь он работает только на один уровень. При попытке получить весь стек вызова я получаю ошибку:
Код: plaintext
1.
2.
3.
4.
5.
6.
ORA-06502: PL/SQL: : буфер символьных строк слишком маленький ошибка числа или значения
ORA-06512: на  "SYS.P_STACK", line 213
ORA-06512: на  "SYS.P_STACK", line 559
ORA-06512: на  "TEST.CC_GO", line 10
ORA-06512: на  "TEST.CC_GO", line 24
ORA-06512: на  line 8
В строке 213 написано:
Код: plsql
1.
c := substr( s, pos, 1 );


А c, в свою очередь, объявлена как char.
s объявлен как varchar2, и если внутри попадаются юникодные символы, то такая ошибка и возникает.
Кириллицу в коде я не использую, только в комментариях и строковых константах.

Если в объявлении c я меняю char на nchar, то возникает другая ошибка:
Код: plaintext
1.
2.
3.
4.
5.
6.
ORA-00942: таблица или представление пользователя не существует
ORA-06512: на  "SYS.P_STACK", line 152
ORA-06512: на  "SYS.P_STACK", line 559
ORA-06512: на  "TEST.CC_GO", line 10
ORA-06512: на  "TEST.CC_GO", line 24
ORA-06512: на  line 8
На строке 152 запрос:
Код: plsql
1.
2.
3.
4.
5.
          select SQL_FULLTEXT, PARSING_SCHEMA_NAME
          into tSqlFullText, tOwner
          from V$SQL
          where CHILD_ADDRESS = tHandle
            or CHILD_ADDRESS = hextoraw( substr( tHandle, 9 ) );



Не подскажите, как починить?
Менять все char на nchar, varchar2 на nvarchar2 и clob на nclob?
...
Рейтинг: 0 / 0
Стек вызова в Oracle 10g
    #40029512
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
V$SQL это синоним к SYS.V_$SQL.
Доступ к этому представлению есть у роли SELECT_CATALOG_ROLE.
Добавляю пользователю эту роль — но просмотреть V$SQL не могу (ошибка ORA-00942), хотя само представление вижу.
Как правильно сделать? Добавить права на select непосредственно пользователю?
Или можно это сделать через роли7
...
Рейтинг: 0 / 0
Стек вызова в Oracle 10g
    #40029520
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообщем удалось запустить.
Пакет P_STACK установил в пользовательскую схему, а не системную.
В строке 213 для переменной c тип сменил с char на nchar.
На системное представление V_$SQL дал права непосредственно пользователю.

Использую так:
Код: plsql
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.
CREATE PACKAGE ...

PROCEDURE TRC(msg VARCHAR2, tag VARCHAR2 := NULL) IS
  str VARCHAR2(2000);
  src VARCHAR2(200);
  cs VARCHAR2(4000);
  lvl PLS_INTEGER;
  len PLS_INTEGER := 50;
BEGIN
  cs := P_STACK.getCallStack();
  lvl := P_STACK.getDynamicDepth(cs) - 3;
  cs := P_STACK.getCallStackLine(cs, 3);
  src := P_STACK.getConcatenatedSubprograms(cs) || ':' || to_char(P_STACK.getUnitLine(cs), 'FM0000');
  str := substr('                                        ', 1, 1+lvl) || src;
  IF (length(str) > len) THEN str := substr(str, 1, len); END IF;
  IF (length(str) < len) THEN str := rpad(str, len); END IF;
  str := '[' || to_char(systimestamp, 'YYYY-MM-DD HH24:MI:SS.FF3') || str || '] ';
  IF (tag IS NOT NULL) THEN str := str || tag || ' '; END IF;
  IF (msg IS NOT NULL) THEN str := str || msg; END IF;
  DBMS_OUTPUT.PUT_LINE(str);
END;

FUNCTION BMSYSUSER RETURN NUMBER IS
  v_res NUMBER;
BEGIN
  TRC('Запуск', '#');
  BEGIN
    select STAFF_ID into v_res from BM_STAFF where IS_ROLE is null and LOGIN = 'auto';
  EXCEPTION WHEN NO_DATA_FOUND THEN
    TRC('Результат не найден', '!');
    RETURN NULL;
  END;
  TRC('Результат: '||v_res);
  RETURN v_res;
END;
...
Рейтинг: 0 / 0
Стек вызова в Oracle 10g
    #40029621
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Такой вопрос.
Я бегло посмотрел P_STACK, там внутри просто кошмар, ручной парсинг исходников, чуть ли не посимвольный перебор.
Работает это не очень быстро, поэтому я функцию сделал такой:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
PROCEDURE TRC(msg VARCHAR2, tag VARCHAR2 := NULL) IS
  str VARCHAR2(2000);
  src VARCHAR2(200);
  cs VARCHAR2(4000);
  lvl PLS_INTEGER;
  len PLS_INTEGER := 50;
BEGIN
  IF (trc_stack=1) THEN
    cs := P_STACK.getCallStack();
    lvl := P_STACK.getDynamicDepth(cs) - 3;
    cs := P_STACK.getCallStackLine(cs, 3);
    src := P_STACK.getConcatenatedSubprograms(cs) || ':' || to_char(P_STACK.getUnitLine(cs), 'FM0000');
    str := substr('                                        ', 1, 1+lvl) || src;
    IF (length(str) > len) THEN str := substr(str, 1, len); END IF;
    IF (length(str) < len) THEN str := rpad(str, len); END IF;
  END IF;
  str := '[' || to_char(systimestamp, 'YYYY-MM-DD HH24:MI:SS.FF3') || str || '] ';
  IF (tag IS NOT NULL) THEN str := str || tag || ' '; END IF;
  IF (msg IS NOT NULL) THEN str := str || msg; END IF;
  DBMS_OUTPUT.PUT_LINE(str);
END;


trc_stack это переменная, статично заданная прямо в коде пакета (я вручную задаю 0 или 1 и компилирую пакет).
А может ли это быть сессионная переменная, чтобы не перекомпилировать пакет?
...
Рейтинг: 0 / 0
Стек вызова в Oracle 10g
    #40029640
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.

А может ли это быть сессионная переменная, чтобы не перекомпилировать пакет?


1) сделайте переменную пакетной
2) контекст
https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_5002.htm

.....
stax
...
Рейтинг: 0 / 0
Стек вызова в Oracle 10g
    #40029673
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1 это в спецификации пакета? Она сейчас там и прописана:
Код: plsql
1.
2.
PROCEDURE TRC(msg VARCHAR2, tag VARCHAR2 := NULL);
trc_stack NUMBER := 1;


Сейчас я просто задаю ей значение (0 или 1) и перекомпилирую пакет.

Пакет называется CC_GO, из внешнего кода мне нужно написать CC_GO.trc_stack := 0 ?
Это будет действовать только в пределах выполняемого блока кода?
Или в пределах сессии?
Насколько я понял, пакетные переменные действуют в рамках сессии -- изменение trc_stack действует и в новой процедуре.
...
Рейтинг: 0 / 0
Стек вызова в Oracle 10g
    #40029678
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.,

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
SQL> create or replace package stax_tas is
  2  trc_stack NUMBER := 1;
  3  end;
  4  /

Package created.

SQL> exec dbms_output.put_line(stax_tas.trc_stack);
1

PL/SQL procedure successfully completed.

SQL> exec stax_tas.trc_stack:=12345;

PL/SQL procedure successfully completed.

SQL> exec dbms_output.put_line(stax_tas.trc_stack);
12345

PL/SQL procedure successfully completed.

SQL> drop package stax_tas;

Package dropped.



зы
есть нюанс
умные кажись могут пакетные переменные сбрасывать

.....
stax
...
Рейтинг: 0 / 0
Стек вызова в Oracle 10g
    #40029686
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще такой вопрос.
В пакете определен тип, например:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
TYPE recResultOut IS RECORD
(
  result            NUMBER,
  code              VARCHAR2(80),
  rc                INT,
  reason            VARCHAR2(1000)
);


Есть ли возможность простыми способами (не осуществляя парсинг исходных кодов) определить состав этого типа, чтобы вывести наименования и значения членов типа?
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Стек вызова в Oracle 10g
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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