Программирование >>  Oracle 

1 ... 348 349 350 [ 351 ] 352 353 354 ... 469


Тщательный контроль доступа 1473

с запросом и как это происходит при использовании различных сред: PL/SQL, Pro*C, OCI, JDBC, ODBC и т.д.

Предположим, имеется следующая функция, возвращающая условие:

SQL> create or replace function rls examp

2 (p schema in varchar2, p object in varchar2)

3 return varchar2

4 as

5 begin

6 if (sys context(myctx, x) is not null)

7 then

8 return x > 0;

9 else

10 return l=0 ;

11 end if;

12 end;

13 /

Function created.

Она реализует такой алгоритм: если в контексте установлен атрибут x, возвращается условие x > 0; если же в контексте атрибут x не установлен, возвращается условие 1 = 0.

создать таблицу T, поместить в нее данные и добавить правила и контекст следующим образом:

SQL> create table t (x int);

Table created.

SQL> insert into t values (1234); 1 row created.

SQL> begin

2 dbms rls.add policy

3 (object schema => user,

4 object name => T,

5 policy name => T POLICY,

6 function schema => user,

7 policy function => rls examp,

8 statement types => select);

9 end;

10 /

PL/SQL procedure successfully completed.

SQL> create or replace procedure set ctx(p val in varchar2)

2 as

3 begin

4 dbms session.set context(myctx, x, p val);

5 end;

Procedure created.

SQL> create or replace context myctx using set ctx; Context created.



1474

Глава 21

Предполагается, что в случае установки контекста мы должны получить одну строку. Если же контекст не установлен, мы ни одной строки получить не должны. Если проверить это в среде SQL*Plus с помощью простых SQL-операторов, именно так и окажется:

SQL> exec set ctx(null);

PL/SQL procedure successfully completed.

SQL> select * from t; no rows selected SQL> exec set ctx(1);

PL/SQL procedure successfully completed.

SQL> select * from t;

1234

Итак, казалось бы, все в порядке. Динамически формируемое условие применяется так, как предполагалось. Фактически же, если использовать язык PL/SQL (или Pro*C, или правильно написанное приложение, использующее интерфейсы OCI/JDBC/ODBC, да и многие другие среды), оказывается, что это не так. Создадим, например, небольшую PL/SQL-процедуру:

SQL> create or replace procedure dump t

10 11 12 13 14 15

-> *

18 19 20 21

in number default NULL)

(some input

begin

dbms output.put line С** Результат выполнения оператора SELEGT

for x in (select * from t) loop

dbms output.put line(x.x); end loop;

FROM T);

if (some input then

is not null)

FROM T);

dbms output.put line

Результат выполнения другого оператора

for x in (select * from t) loop

dbms output.put line(x.x); end loop;

SELEGT

end if;

end;

Procedure created.

Эта процедура выполняет оператор SELECT * FROM T один раз, если входные данные не переданы, и два раза, если переданы какие-либо входные данные. Выполним эту



Тщательный контроль доступа 1475

процедуру и посмотрим результаты. Выполнение процедуры начнем, установив в контексте значение Null (поэтому будет применяться условие 1-0, другими словами, не будет возвращена ни одна строка):

;L> set serveroutput on

exec set ctx(NULL)

PL/SQL procedure successfully completed.

SQL> exec dump t

*** Результат выполнения оператора SELECT * FROM T PL/SQL procedure successfully completed.

Как и ожидалось, данные не получены. Теперь установим значение в контексте так, чтобы возвращалось условие x > 0. Затем вызовем процедуру DUMP T так, чтобы она выполняла оба запроса. В версиях Oracle 8.1.5 и 8.1.6 при этом произойдет следующее:

SQL> exec set ctx(l)

PL/SQL procedure successfully completed. SQL> exec dump t(0)

*** Результат выполнения оператора SELECT * FROM Т

*** Результат выполнения другого оператора SELECT * FROM T

1234

PL/SQL procedure successfully completed.

Перв1й запрос, первоначально выполненный при значении Null в контексте, по-прежнему не возвращает данн1х. Его курсор б1л сохранен в кэше и повторно не анализировался.

При выполнении процедуры со значением Null атрибута x в контексте, получаем предполагаемые результаты (потому что это было первое выполнение данной процедуры в сеансе). Устанавливаем атрибуту x непустое значение и получаем неоднозначные резтатт Первый оператор SELECT * FROM T в процедуре по-прежнему не возвращает ни одной строки - он, видимо, продолжает использовать условие 1=0. Второй запрос (который первый раз мы не выполняли) возвращает, как и предполагалось, пра-вильн1е результаты. Он использует условие x > 0, как и было задумано.

Почему первый оператор SELECT в этой процедуре не использует условие, которое мы предполагали? Это связано с оптимизацией, называемой кэшированием курсора. Язык PL/SQL и многие другие среды выполнения не закрывают курсор, когда этого требует разработчик. Представленный пример можно легко воспроизвести в Pro*C, если оставить опции прекомпилятора release cursor стандартное значение NO. Если тот же код обработать с опцией release cursor=YES, программа Pro*C будет работать аналогично запросам в среде SQL*Plus. Условие, используемое пакетом DBMS RLS, связывается с запросом на стадии анализа. Первый запрос SELECT * FROM T анализируется при первом выполнении хранимой процедуры, когда фактически возвращалось условие 1=0. PL/SQL-машина автоматически кэширует проанализированный курсор. При втором выполнении хранимой процедуры PL/SQL-машина повторно использует проанализированный курсор первого запроса SELECT * FROM T. Этот проанализированный курсор



1 ... 348 349 350 [ 351 ] 352 353 354 ... 469

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика