Аннотация
В каждом сеансе работы с СУБД можно использовать так называемые контексты, формально представляющие собой именованный набор пар «параметр/значение». Контексты сеансов обладают рядом интересных свойств, существенно повышающих «внутренние» возможности Oracle по созданию приложений. В статье рассматриваются два предопределенных контекста Oracle: USERENV и CLIENTCONTEXT.
Введение
В каждом
сеансе работы с СУБД можно использовать так называемые
контексты. Каждый контекст - это именованный набор пар «параметр/значение». Oracle называет каждый конкретный подобный набор
пространством имен (namespace), а элементы пространства имен
атрибутами, способными принимать
значения.
Создаются контексты SQL-предложением CREATE CONTEXT. Из-за этого далее вместо «пространства имен» предпочтение отдается термину «контекст». Параметры контекста («атрибуты») устанавливаются процедурой DBMS_SESSION.SET_CONTEXT, а вот вычитываются в программу стандартной функцией SYS_CONTEXT. Пакет DBMS_SESSION содержит ряд других подпрограмм для работы с контекстами.
Здесь рассматривается лишь формальная сторона контекста сеанса, а способ его применения разработчик может определить сам или почерпнуть из описаний избирательного доступа к данным (FGAC или Label Security) и сервера приложений Oracle.
Готовый справочный контекст сеанса USERENV
Один контекст, с названием USERENV, создавать явным образом не требуется. Он доступен любому сеансу связи с СУБД Oracle в виде готового набора значений, разрешающего только прочтение, но не правку. Он позволяет узнать всевозможные сведения о сеансе, полезные для прикладного программирования. Ранее в Oracle существовала одноименная функция, но сейчас она поддерживается ради старых программ.
Пример информации, которую можно получить из контекста USERENV в программу:
COLUMN authent FORMAT A10
COLUMN curr_schema FORMAT A10
COLUMN curr_user FORMAT A10
COLUMN db_name FORMAT A10
COLUMN db_domain FORMAT A10
COLUMN host FORMAT A15
COLUMN ip_address FORMAT A15
COLUMN os_user FORMAT A15
SELECT
SYS_CONTEXT ( 'userenv', 'AUTHENTICATION_TYPE' ) authent
, SYS_CONTEXT ( 'userenv', 'CURRENT_SCHEMA' ) curr_schema
, SYS_CONTEXT ( 'userenv', 'CURRENT_USER' ) curr_user
, SYS_CONTEXT ( 'userenv', 'DB_NAME' ) db_name
, SYS_CONTEXT ( 'userenv', 'DB_DOMAIN' ) db_domain
, SYS_CONTEXT ( 'userenv', 'HOST' ) host
, SYS_CONTEXT ( 'userenv', 'IP_ADDRESS' ) ip_address
, SYS_CONTEXT ( 'userenv', 'OS_USER' ) os_user
FROM dual
;
Полный список атрибутов контекста USERENV можно узнать из документации (в справочнике по SQL, в разделе, посвященному функции SYS_CONTEXT).
Вот пример того, как сведения из этого контекста помогают различить разные условия употребления конкретной программы:
CONNECT scott/tiger
CREATE PROCEDURE whoowns
AS
BEGIN
DBMS_OUTPUT.PUT_LINE ( SYS_CONTEXT ( 'userenv', 'CURRENT_SCHEMA' ) );
DBMS_OUTPUT.PUT_LINE ( SYS_CONTEXT ( 'userenv', 'CURRENT_USER' ) );
DBMS_OUTPUT.PUT_LINE ( user );
END;
/
Проверка:
SQL> SET SERVEROUTPUT ON
SQL> EXECUTE whoowns
SCOTT
SCOTT
SCOTT
PL/SQL procedure successfully completed.
SQL> ALTER SESSION SET CURRENT_SCHEMA = system;
Session altered.
SQL> EXECUTE scott.whoowns
SCOTT
SCOTT
SCOTT
PL/SQL procedure successfully completed.
SQL> CONNECT / as sysdba
Connected.
SQL> SET SERVEROUTPUT ON
SQL> EXECUTE scott.whoowns
SCOTT
SCOTT
SYS
PL/SQL procedure successfully completed.
Перетранслируем процедуру для работы с правами запускающего:
CONNECT scott/tiger
CREATE OR REPLACE PROCEDURE whoowns
AUTHID CURRENT_USER
AS
BEGIN
DBMS_OUTPUT.PUT_LINE ( SYS_CONTEXT ( 'userenv', 'CURRENT_SCHEMA' ) );
DBMS_OUTPUT.PUT_LINE ( SYS_CONTEXT ( 'userenv', 'CURRENT_USER' ) );
DBMS_OUTPUT.PUT_LINE ( user );
END;
/
Снова проверка:
SQL> SET SERVEROUTPUT ON
SQL> EXECUTE whoowns
SCOTT
SCOTT
SCOTT
PL/SQL procedure successfully completed.
SQL> ALTER SESSION SET CURRENT_SCHEMA = system;
Session altered.
SQL> EXECUTE scott.whoowns
SYSTEM
SCOTT
SCOTT
PL/SQL procedure successfully completed.
SQL> CONNECT / as sysdba
Connected.
SQL> SET SERVEROUTPUT ON
SQL> EXECUTE scott.whoowns
SYS
SYS
SYS
PL/SQL procedure successfully completed.
SQL> ALTER SESSION SET CURRENT_SCHEMA = system;
Session altered.
SQL> EXECUTE scott.whoowns
SYSTEM
SYS
SYS
Примеры поясняют отличие атрибутов CURRENT_SCHEMA и CURRENT_USER контекста USERENV друг от друга и от системной переменной USER.
Готовый изменяемый контекст сеанса CLIENTCONTEXT
Еще один предопределенный контекст, с именем CLIENTCONTEXT, также не требует специального создания, однако в отличие от USERENV он позволяет сеансу создавать собственные атрибуты и задавать им значения. Особенность этого контекста в том, что он, в дополнение к обычному способу (изнутри сеанса), позволяет устанавливать значения атрибутам заранее, при открытии соединения с СУБД клиентской программой, и передавать их для обработки в сеанс. Делается это
- либо через библиотеку OCI с помощью специального вызова OCIAppCtxSet
- либо из программы на Java с помощью методов класса oracle.jdbc.internal.OracleConnection.
Тем самым контекст CLIENTCONTEXT способен при открытии сеанса передать информацию, дополнительную к традиционному имени пользователя и к ограниченному кругу сведений (адрес IP клиента, имя компьютера и пр.), доступному из контекста USERENV.
Значения переданных в сеанс атрибутов контекста CLIENTCONTEXT можно читать как обычно функцией SYS_CONTEXT, и изменять, но можно заводить и новые атрибуты:
SQL> CONNECT scott/tiger
Connected.
SQL> EXECUTE DBMS_SESSION.SET_CONTEXT ( 'CLIENTCONTEXT', 'a', 'b' )
PL/SQL procedure successfully completed.
SQL> SELECT SYS_CONTEXT ('CLIENTCONTEXT', 'a' ) FROM dual;
SYS_CONTEXT('CLIENTCONTEXT','A')
--------------------------------------------------------------------
b
Если бы атрибут A был установлен клиентской программой на C или на Java перед установлением соединения, значение B мы бы увидели сразу.
Второе отличительное свойство контекста CLIENTCONTEXT в том, что Oracle разрешает именно для него обращаться к DBMS_SESSION.SET_CONTEXT напрямую (см. выше). Это исключение: контексты, которые разработчик пожелает создавать сам, позволят обращаться к DBMS_SESSION.SET_CONTEXT только из текста своей доверительной программной единицы.