|
| ||||||||||||
| ||||||||||||
|
2006 г.
Контекст сеанса в Oracle
Преподаватель технологий Oracle, www.ccas.ru/prz/ Сама садик я садила, АннотацияВ каждом сеансе работы с СУБД можно использовать так называемые контексты, формально представляющие собой именованный набор пар «параметр/значение». Контексты сеансов обладают рядом интересных свойств, существенно повышающих «внутренние» возможности Oracle по созданию приложений. В статье рассматриваются возможности проектирования локальных и глобальных контекстов сеанса и некоторые их свойства.Как построить контекст сеанса своими рукамиДля самостоятельного создания контекста служит специальная команда CREATE CONTEXT. Выдать ее (то есть создать контекст) может сеанс, имеющий полномочие CREATE ANY CONTEXT. Слово ANY в названии полномочия (привилегии) свидетельствует о том, что контекст - внесхемный объект в БД Oracle, такой, например, как роль, и отличный, например, от таблицы.Для каждого контекста требуется указать специальную «доверительную» программную единицу: процедуру, функцию или пакет. Именно из тела этой программной единицы Oracle разрешит обращаться к процедуре DBMS_SESSION.SET_CONTEXT. Принято такое неочевидное решение во имя безопасности, так как доступ к хранимым программным единицам регулируется уже готовым механизмом привилегий. Пример создания контекстаПоложим, доверительной программной единицей должна быть процедура SET_MYCONTEXT_VALUE: CONNECT / as sysdba CREATE OR REPLACE CONTEXT mycontext USING set_mycontext_value; Обратите внимание, что процедура не обязана существовать в момент создания контекста. Но в конце концов ее-таки потребуется создать: CREATE OR REPLACE PROCEDURE set_mycontext_value ( par IN VARCHAR2 , val IN VARCHAR2 ) AS BEGIN DBMS_SESSION.SET_CONTEXT ( 'mycontext', par, val ); END; / GRANT EXECUTE ON set_mycontext_value TO scott; Проверка:
SQL> CONNECT scott/tiger
Connected.
SQL> SELECT SYS_CONTEXT ( 'mycontext', 'sesame' ) FROM dual;
SYS_CONTEXT('MYCONTEXT','SESAME')
------------------------------------------------------------
Выше серым фоном выделена пустая строка. С помощью контекста MYCONTEXT и доступной ему процедуры пользователь SCOTT завел значение, которое сможет читать и переустанавливать в собственном сеансе вплоть до завершения. Другой сеанс пользователя SCOTT создаст и будет использовать с помощью этого же контекста свои значения, то есть значения контекста являются собственностью сеанса. Значения атрибутов контекста живут не долее пределов сеанса и защищены от доступа из других сеансов. В течение сеанса значения переменных пакета могут пропасть («сброс» пакета, хотя пользователи и нечасто прибегают к нему), и значения атрибутов контекста тоже (с помощью пакета DBMS_SESSION). Этим атрибуты схожи с переменными пакета. Но есть и отличия:
Вот еще пример использования нашего контекста:
SQL> EXECUTE set_mycontext_value -
> ( 'start work', TO_CHAR ( SYSDATE, 'hh24:mi:ss' ) )
PL/SQL procedure successfully completed.
SQL> REMARK выполняем работу, после чего смотрим когда начинали ...
SQL> SELECT SYS_CONTEXT ( 'mycontext', 'start work' ) FROM dual;
SYS_CONTEXT('MYCONTEXT','STARTWORK')
--------------------------------------------------------------------
13:58:06
Вариация в технологии: использование доверительного пакетаЕсли запросить структуру справочной таблицы доступных контекстов, то видно, что поле для доверительной программной единицы названо PACKAGE:SQL> SELECT * FROM all_context; NAMESPACE SCHEMA PACKAGE ---------------------- ---------------------- ---------------------- MYCONTEXT SYS SET_CONTEXT_VALUE Это не случайно: на практике часто более технологично установку контекста выполнять с помощью доверительного пакета, а не самостоятельной процедуры или функции. Ведь в состав пакета можно включить и прочие программные элементы, моделирующие логику предметной области. Пример:
CONNECT / as sysdba
CREATE OR REPLACE CONTEXT mycontext USING mycontext_pckg;
CREATE OR REPLACE PACKAGE mycontext_pckg IS
PROCEDURE set_value ( par VARCHAR2, val VARCHAR2 );
FUNCTION get_value ( par VARCHAR2 ) RETURN VARCHAR2;
END;
/
CREATE OR REPLACE PACKAGE BODY mycontext_pckg IS
PROCEDURE set_value ( par VARCHAR2, val VARCHAR2 )
IS
BEGIN
DBMS_SESSION.SET_CONTEXT ( 'mycontext', par, val );
END;
FUNCTION get_value ( par VARCHAR2 ) RETURN VARCHAR2
IS
BEGIN
RETURN SYS_CONTEXT ( 'mycontext', par );
END;
END;
/
GRANT EXECUTE ON mycontext_pckg TO scott;
Проверка:
SQL> CONNECT scott/tiger
Connected.
SQL> SELECT sys.mycontext_pckg.get_value ( 'sesame' ) FROM dual;
SYS.MYCONTEXT_PCKG.GET_VALUE('SESAME')
---------------------------------------------------------------------
Пакет можно спроектировать и иначе, закрыв, например, для пользователя имя атрибута или даже контекста. Можно запрограммировать все, что требует логика предметной области. Начальные значения атрибутов контекстаВыше было показано, как атрибуты контекстов выставляются в процессе сеанса связи с СУБД. Однако по подобию с CLIENTCONTEXT создаваемый контекст тоже можно обеспечить начальными значениями требуемых атрибутов из программы, открывающий сеанс. Это можно сделать
Возможность таких начальных присвоений обеспечивается соответствующими указаниями при создании контекста: CREATE CONTEXT ... INITIALIZED EXTERNALLY и CREATE CONTEXT ... INITIALIZED EXTERNALLY Начальные значения атрибутов контекста для сеансов - очень сильное средство, позволяющее наложить на относительно примитивный механизм внутренних пользователей БД инфраструктуру внешних пользователей, часто более проработанную и универсальную. Например, сервер приложений может поддерживать очень много пользователей web-страниц, обладающих собственными свойствами. Моделировать их отдельными локальными для Oracle пользователями может оказаться крайне неэффективно, и в этом случае возможность предварительного установления атрибутов перед обращением к БД будет давать единственный ключ к построению решения. Глобальный контекст сеанса («контекст приложения»)«Обычный» контекст сеанса имеет своею областью действия отдельный сеанс. Иногда этого разработчику приложения вполне достаточно, а иногда хочется большего. Можно ли, например, запретить сеансу самостоятельно выставлять значение атрибута и предоставить ему только чтение, а значение задавать из другого сеанса? Такую возможность обеспечивает глобальный контекст сеанса, называемый еще иногда контекстом приложения. Пример его использования показан ниже:
CONNECT / AS SYSDBA
CREATE OR REPLACE CONTEXT globalcontext
USING globalcontext_pckg
ACCESSED GLOBALLY
/
CREATE OR REPLACE PACKAGE globalcontext_pckg AS
PROCEDURE set_value (
par VARCHAR2
, val VARCHAR2
, usr VARCHAR2
, usrid VARCHAR2
);
END;
/
CREATE OR REPLACE PACKAGE BODY globalcontext_pckg AS
PROCEDURE set_value (
par VARCHAR2
, val VARCHAR2
, usr VARCHAR2
, usrid VARCHAR2
)
AS
BEGIN
DBMS_SESSION.SET_CONTEXT (
'globalcontext'
, par
, val
, usr
, usrid
);
END;
END;
/
EXECUTE globalcontext_pckg.set_value -
( 'sesame' , '123', 'SCOTT', 'XYZ32A6' )
Проверка:
SQL> CONNECT scott/tiger
Connected.
SQL> SELECT SYS_CONTEXT ( 'globalcontext', 'sesame' ) FROM dual;
SYS_CONTEXT('GLOBALCONTEXT','SESAME')
--------------------------------------------------------------------
Тут есть сразу несколько интересных новшеств.
Таким образом, мало войти в СУБД под «правильным» пользователем; для того, чтобы получить в сеансе значение желаемого атрибута (глобального контекста), нужно будет еще сообщить условную строку. Излишне напоминать, что очевидным кандидатом на такую строку является cookie сеанса общения с web. И только благодаря этому, а также механизму избирательного доступа к частям таблицы в Oracle («виртуальные частные базы данных», VPD/FGAC) и возможности сервера приложений автоматически выдавать SET_IDENTIFIER при обращении к БД, многочисленные пользователи web, формально подключаемые к СУБД под одними и теми же именами пользователей Oracle, смогут увидеть в базе каждый собственные данные.
|
|
CITForum © 1997–2025