Рассмотрим следующий пример.
Предположим, что у нас в Oracle Database 11g есть функция определенная с правами вызывающего:
[oracle@rac1 ~]$ sqlplus rscott/rtiger
SQL*Plus: Release 11.2.0.4.0 Production on Sat Nov 10 13:09:00 2014
Copyright (c) 1982, 2013, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP
and Data Mining options
SQL> CREATE OR REPLACE FUNCTION getClosedAccounts(v_pBranchId IN NUMBER) RETURN VARCHAR2
AUTHID CURRENT_USER IS
v_xRes NUMBER(9);
BEGIN
SELECT
count(a.rowid)
INTO
v_xRes
FROM
accounts a
WHERE
a.branch_id = v_pBranchId and
a.Status = 'CLOSED';
RETURN v_xRes;
END;
/
Function created.
SQL>
Вызов этой функции под другим пользователем, как и положено, будет сделан с правами вызывающего:
SQL> grant execute on getClosedAccounts to hr;
Grant succeeded.
SQL> connect hr/hr
Connected.
SQL> select rscott.getClosedAccounts(123) from dual;
select rscott.getClosedAccounts(123) from dual
*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at "RSCOTT.GETCLOSEDACCOUNTS", line 5
SQL>
Все правильно: вызов произошел с правами вызывающего, а пользователь HR не имеет прав не чтение таблицы accounts.
А теперь попробуем вызвать эту же функцию под пользователем HR, но уже внутри представления:
SQL> conn rscott/rtiger
Connected.
SQL>CREATE OR REPLACE VIEW v$Branches_Closed_Accounts AS
SELECT
b.Id,
getClosedAccounts(b.Id) as Closed_Count
FROM
branches b;
View created.
SQL> GRANT SELECT ON v$Branches_Closed_Accounts TO hr;
Grant succeeded.
SQL> conn hr/hr
Connected.
SQL> SELECT * FROM rscott.v$Branches_Closed_Accounts;
ID CLOSED_COUNT
--- ---------------------------------------------------------------------
1 0
Функция внутри представления была вызвана без всякой ошибки!
До Oracle Database 12c вызов функции внутри представления всегда происходит с правами создателя, даже если функция была определена как с правами вызывающего.
В Oracle Database 12c, в определении представления, указывается фраза BEQUEATH, которая определяет, как будут вызывать PL/SQL-функции используемые в запросе: DEFINER или CURRENT_USER.
Переключимся на Oracle Database 12c и перепишем наше представление по другому, указав что наша функция должна быть вызвана с правами вызывающего:
[oracle@localhost]$ sqlplus rscott/rtiger
SQL*Plus: Release 12.1.0.2.0 Production on Sun Nov 16 20:57:49 2014
Copyright (c) 1982, 2014, Oracle. All rights reserved.
Last Successful login time: Sun Nov 16 2014 20:56:22 +03:00
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
SQL> CREATE OR REPLACE VIEW v$Branches_Closed_Accounts
BEQUEATH CURRENT_USER AS
SELECT
b.Id,
getClosedAccounts(b.Id) as Closed_Count
FROM
branches b;
View created.
SQL> conn hr/hr
Connected.
SQL> SELECT * FROM rscott.v$Branches_Closed_Accounts;
SELECT * FROM rscott.v$Branches_Closed_Accounts
*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at "RSCOTT.GETCLOSEDACCOUNTS", line 5
SQL>
Теперь функция в представлении вызывается с правами вызывающего!По умолчанию, в Oracle Database 12 представление будет создаваться с неявной фразой BEQUEATH DEFINER, то есть поведение будет как в предыдущих версиях - функции в представлениях будут вызываться с правами создателя.
Важно отметить, что если в определении функции был указан режим вызова с правами создателя, то фраза BEQUEATH CURRENT_USER в представлении игнорируется:
SQL> conn rscott/rtiger
Connected.
SQL> CREATE OR REPLACE FUNCTION getClosedAccounts(v_pBranchId IN NUMBER) RETURN VARCHAR2
AUTHID DEFINER IS
v_xRes NUMBER(9);
BEGIN
SELECT
count(a.rowid)
INTO
v_xRes
FROM
accounts a
WHERE
a.branch_id = v_pBranchId and
a.Status = 'CLOSED';
RETURN v_xRes;
END;
/
Function created.
SQL> conn hr/hr
Connected.
SQL> SELECT * FROM rscott.v$Branches_Closed_Accounts;
ID CLOSED_COUNT
--- ---------------------------------------------------------------------
1 0