2016-10-18

Опасные GLOBAL CONTEXT

Постигла такая же ошибка, что описана тут
Значение глобального контекста доступны/недоступны в зависимости от установок client identifier при коннекте.
Случаи выходят такие
DBMS_SESSION.SET_IDENTIFIER НЕ УСТАНОВЛЕН
- SET_CONTEXT.CLIENT_ID не установлен – работает
- SET_CONTEXT.CLIENT_ID установлен – работает
DBMS_SESSION.SET_IDENTIFIER УСТАНОВЛЕН

- SET_CONTEXT.CLIENT_ID не установлен – NULL НЕ РАБОТАЕТ
- SET_CONTEXT.CLIENT_ID установлен, но другой != DBMS_SESSION.SET_IDENTIFIER– NULL НЕ РАБОТАЕТ
- SET_CONTEXT.CLIENT_ID установлен = DBMS_SESSION.SET_IDENTIFIER - РАБОТАЕТ
Как видно работать будет в 2 случаях:
1. DBMS_SESSION.SET_IDENTIFIER не установлен, т.е. попробовать очищать его в logon триггере.
2. копировать глобальный контекст для каждого DBMS_SESSION.SET_IDENTIFIER, т.е. после подключения выполнять SET_CONTEXT с CLIENT_ID = DBMS_SESSION.SET_IDENTIFIER – получается не глобальный контекст, а локальный.
Т.е. в любом случае для глобальных контекстов потребуются дополнительные дейстивия: или ОЧИСТКА DBMS_SESSION.CLEAR_IDENTIFIER или КОПИРОВАНИЕ КОНТЕКСТА
Тесты, взятые из вышеуказанной статьи
CLEAR SCREEN 

DROP CONTEXT TEST_CONTEXT;

CREATE OR REPLACE PACKAGE my_ctx_pkg
AS
PROCEDURE set_context( p_namespace VARCHAR2,
p_attribute VARCHAR2,
p_value     VARCHAR2,
p_client_id VARCHAR2 DEFAULT NULL);
END;
/
CREATE OR REPLACE PACKAGE BODY my_ctx_pkg
AS
PROCEDURE set_context( p_namespace VARCHAR2,
p_attribute VARCHAR2,
p_value     VARCHAR2,
p_client_id VARCHAR2 DEFAULT NULL)
AS
BEGIN
DBMS_SESSION.SET_CONTEXT(p_namespace, p_attribute, p_value, client_id => p_client_id);
END set_context;
END;
/
CREATE CONTEXT TEST_CONTEXT USING my_ctx_pkg ACCESSED GLOBALLY;

PROMPT НЕ устанавливаем client identifier при коннекте
exec DBMS_SESSION.CLEAR_IDENTIFIER();

PROMPT В контексте НЕ устанавливаем -- значение ВИДИМ
exec my_ctx_pkg.set_context('TEST_CONTEXT','ATTR', 'VAL', p_client_id => NULL);
SELECT SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER') CLIENT_IDENTIFIER,
SYS_CONTEXT('TEST_CONTEXT','ATTR') ATTR_VAL
FROM dual;

PROMPT В контексте УСТАНАВЛИВАЕМ -- значение ВИДИМ
exec my_ctx_pkg.set_context('TEST_CONTEXT','ATTR', 'VAL', p_client_id => 'set_in_context');
SELECT SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER') CLIENT_IDENTIFIER,
SYS_CONTEXT('TEST_CONTEXT','ATTR') ATTR_VAL
FROM dual;


PROMPT УСТАНАВЛИВАЕМ client identifier при коннекте
BEGIN
  dbms_session.set_identifier(client_id => 'session connect_id');
END;
/

PROMPT В контексте НЕ устанавливаем -- значение НЕ ВИДИМ
exec my_ctx_pkg.set_context('TEST_CONTEXT','ATTR', 'VAL', p_client_id => NULL);
SELECT SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER') CLIENT_IDENTIFIER,
SYS_CONTEXT('TEST_CONTEXT','ATTR') ATTR_VAL
FROM dual;

PROMPT В контексте устанавливаем ДРУГОЕ -- значение НЕ ВИДИМ
exec my_ctx_pkg.set_context('TEST_CONTEXT','ATTR', 'VAL', p_client_id => 'set_in_context');
SELECT SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER') CLIENT_IDENTIFIER,
SYS_CONTEXT('TEST_CONTEXT','ATTR') ATTR_VAL
FROM dual;

PROMPT В контексте устанавливаем ТОЖЕ -- значение ВИДИМ
exec my_ctx_pkg.set_context('TEST_CONTEXT','ATTR', 'VAL', p_client_id => 'session connect_id');
SELECT SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER') CLIENT_IDENTIFIER,
SYS_CONTEXT('TEST_CONTEXT','ATTR') ATTR_VAL
FROM dual;