Как дать доступ к атрибутам объектного типа только методам это типа?
В этом вопросе шла речь о доступе к переменным сессии определённых в пакете.
В приведённой там документации на ACCESSIBLE BY Clause, сказанно, что она доступна также для пользовательских типов TYPE. Но примеров нет.
Пробую так дать доступ к атрибутам типа только методам этого типа:
create or replace type privT
accessible by (type privT, function getval, procedure setval) is object (
value varchar2 (8),
member procedure setval (self in out privT, v varchar2),
member function getval return varchar2
) instantiable final
/
Type PRIVT compiled
create or replace type body privT is
member procedure setval (self in out privT, v varchar2) is begin
self.value := v;
end;
member function getval return varchar2 is begin
return self.value;
end;
end;
/
Type Body PRIVT compiled
Всё компилируется, но не могу создать даже неинициализированную переменную этого типа:
declare
p privT;
begin null;
end;
/
Error report -
ORA-06550: line 2, column 7:
PLS-00904: insufficient privilege to access object PRIVT
Какое тут может быть решение?
Ответы (1 шт):
Авторизованный доступ может получить, цитата из документации:
unit_kind accessor [schema.]unit_name
Each accessor specifies another PL/SQL entity that may access the entity which includes the ACCESSIBLE BY clause.
Нельзя дать доступ самому себе, это должен быть другой объект БД. Причём, доступ можно дать только всему объекту: пакету, типу данных, а не их методам, функциям или процедурам.
Можно инкапсулировать объектный тип данных в другой, и переместить все методы туда:
create or replace type privT accessible by (type publT) is object (value varchar2 (8))
/
create or replace type publT force as object (
priv privT,
constructor function publT (v varchar2) return self as result,
member function get return varchar2,
member function setnew (self in out publT, v varchar2) return publT)
/
create or replace type body publT as
constructor function publT (v varchar2) return self as result is begin
self.priv := privT (v);
return;
end;
member function get return varchar2 is begin
return priv.value;
end;
member function setnew (self in out publT, v varchar2) return publT is begin
priv.value := v;
return self;
end;
end;
/
Теперь доступ только возможен через инкапсулирующий тип данных:
var rc refcursor
declare
--v privT; --insufficient privilege
v1 publT := publT ('val1');
v2 publT;
begin null;
--v1.priv.value := 'val2'; --insufficient privilege
v2 := v1.setnew ('val2');
open :rc for select v1.get () value, v2 v2 from dual;
end;
/
V1 V2(PRIV(VALUE))
-------- --------------------------------
val2 PUBLT(PRIVT('val2'))