Есть несколько вещей, которые приходят с FGAC
, которые могут вызвать эту ситуацию.
Во-первых, если функция генерации предиката сама по себе недействительна, политика всегда выдает это исключение. В приведенном здесь примере присваивание v_user
(строка 8) имеет двойные точки с запятой ;;
, что должно привести к сбою компиляции.
Когда вы запускаете оператор create для sec_fun
, вы должны получить следующее сообщение:
Warning: Function created with compilation errors.
Elapsed: 00:00:00.483
Поскольку генератор предикатов имеет синтаксическую ошибку, политика, примененная к PAYROLL
, будет всегда завершаться с ошибкой ORA-28113
.
Следует отметить, что ORA-28113
содержит полезную рекомендацию:
"Review the trace file for detailed error information.
"
При сбое политики база данных записывает файл трассировки с подробным описанием основной причины.
В любом случае, после удаления двойных точек с запятой, это должно по крайней мере компилироваться. Но впереди есть другие проблемы, которые также вызовут это.
Следующая проблема заключается в том, что операторы return в том виде, в котором они написаны, также не являются допустимыми предикатами, поскольку они не создают действительных string literals
.
Например, "EMP_ID = E1
" нельзя использовать, потому что он включает в себя литерал, который не заключен в кавычки. То же самое относится и к предикату "DEPT != accounting
".
В переработанной версии ниже, они были процитированы.
Кроме того, FGAC
обычно предпочитает, чтобы действительный предикат предоставлялся из всех ветвей выполнения.
Возможно, возвращается NULL
, когда NO_DATA_FOUND
может работать в вашей ситуации, но может быть предпочтительнее вернуть действительный предикат (который фильтрует все данные). Вы можете предпочесть исключение для работника, которого не существует; в этом случае NULL
может быть приемлемым. Это просто рекомендация / мысль.
Еще одна вещь, на которую следует обратить внимание: использование SYS_CONTEXT
может иметь некоторые сложности и быть более многословным, чем требуется. Если не происходит какое-либо перенаправление / вложение / проксирование, которое сделает текущего пользователя неверным, можно просто использовать вместо этого функцию USER
и избежать некоторых осложнений sys_context
.
Вот альтернативная версия, которая должна компилировать, а не выдавать ошибки и фильтровать по описанным вами направлениям:
CREATE OR REPLACE FUNCTION SEC_FUN(P_SCHEMA VARCHAR2 , P_OBJ VARCHAR2) RETURN VARCHAR2
AS
V_DEPT EMPLOYEES.DEPT%TYPE;
V_ID EMPLOYEES.USER_ID%TYPE;
BEGIN
SELECT EMPLOYEES.DEPT, EMPLOYEES.USER_ID INTO V_DEPT, V_ID FROM MANAGER.EMPLOYEES WHERE EMPLOYEES.ENAME = USER;
IF (V_DEPT != 'accounting')
THEN
RETURN 'EMP_ID = ' || CHR(39)||V_ID||CHR(39);
ELSE
RETURN 'DEPT != ' || CHR(39)||V_DEPT||CHR(39);
END IF;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
RETURN '1 = 0';
END;
/