VPD policy fails with ORA-28113: policy predicate has error











up vote
0
down vote

favorite












I have a table called payroll created by 'MANAGER' which contains the following:



EMP_ID               DEPT                      TOTAL      TAXES
-------------------- -------------------- ---------- ----------
E1 accounting 2400 100
E2 sales 2500 75
E3 research 3000 110
E4 operations 4200 120
E5 sales 4800 130
E6 sales 2500 75
E7 accounting 5200 140
E8 accounting 2700 105


I also have table called employees, created also by 'MANAGER', containing:



ENAME                USER_ID              DEPT               
-------------------- -------------------- --------------------
SAMI E4 operations
ALI E7 accounting
MIRIAM E5 sales


I also have beside 'MANAGER' two users 'ALI' and 'SAMI' and I want to limit their access to 'payroll' table based on their departments, so I gave them the select privilege on both tables 'EMPLOYEES' and 'payroll' and I wrote the following policy function:



create or replace function sec_fun (p_schema varchar2, p_obj varchar2)
return varchar2
as
v_dept MANAGER.employees.dept%type;
v_user varchar2(100);
v_id MANAGER.employees.user_id%type;
begin
v_user:= SYS_CONTEXT('userenv', 'SESSION_USER');;
select dept,user_id into v_dept, v_id from MANAGER.EMPLOYEES where ename=v_user;
if (v_dept!= 'accounting') then
return 'EMP_ID=' ||v_id;
else
return 'DEPT !=' || v_dept;
end if;
exception
when NO_DATA_FOUND then
return null;
end;
/


then I wrote:



begin
dbms_rls.add_policy(
'MANAGER',
'payroll',
'p1',
'MANAGER',
'sec_fun',
'select');
end;
/


now when I connect as 'ALI' then write



SELECT * FROM MANAGER.PAYROLL;


I get the following error which I looked and edited my policy function many times after reading the various solutions through the internet:



Error at Command Line:1 Column:23
Error report:
SQL Error: ORA-28113: policy predicate has error
*Cause: Policy function generates invalid predicate.
*Action: Review the trace file for detailed error information.


any help is so much appreciated. thank you in advance










share|improve this question
























  • You may want to reconsider your approach here. Your function will return a different predicate for each and every employee / department because you're hardcoding the values dynamically. A better approach may be to include the query on MANAGER.EMPLOYEES and the predicate on sys_context directly in the generated predicate; this way you end up with a static predicate which may have some performance benefit. Note: this may cause an alternative performance detriment depending on the plan generated for the resulting query; so YMMV.
    – Jeffrey Kemp
    Nov 20 at 2:42















up vote
0
down vote

favorite












I have a table called payroll created by 'MANAGER' which contains the following:



EMP_ID               DEPT                      TOTAL      TAXES
-------------------- -------------------- ---------- ----------
E1 accounting 2400 100
E2 sales 2500 75
E3 research 3000 110
E4 operations 4200 120
E5 sales 4800 130
E6 sales 2500 75
E7 accounting 5200 140
E8 accounting 2700 105


I also have table called employees, created also by 'MANAGER', containing:



ENAME                USER_ID              DEPT               
-------------------- -------------------- --------------------
SAMI E4 operations
ALI E7 accounting
MIRIAM E5 sales


I also have beside 'MANAGER' two users 'ALI' and 'SAMI' and I want to limit their access to 'payroll' table based on their departments, so I gave them the select privilege on both tables 'EMPLOYEES' and 'payroll' and I wrote the following policy function:



create or replace function sec_fun (p_schema varchar2, p_obj varchar2)
return varchar2
as
v_dept MANAGER.employees.dept%type;
v_user varchar2(100);
v_id MANAGER.employees.user_id%type;
begin
v_user:= SYS_CONTEXT('userenv', 'SESSION_USER');;
select dept,user_id into v_dept, v_id from MANAGER.EMPLOYEES where ename=v_user;
if (v_dept!= 'accounting') then
return 'EMP_ID=' ||v_id;
else
return 'DEPT !=' || v_dept;
end if;
exception
when NO_DATA_FOUND then
return null;
end;
/


then I wrote:



begin
dbms_rls.add_policy(
'MANAGER',
'payroll',
'p1',
'MANAGER',
'sec_fun',
'select');
end;
/


now when I connect as 'ALI' then write



SELECT * FROM MANAGER.PAYROLL;


I get the following error which I looked and edited my policy function many times after reading the various solutions through the internet:



Error at Command Line:1 Column:23
Error report:
SQL Error: ORA-28113: policy predicate has error
*Cause: Policy function generates invalid predicate.
*Action: Review the trace file for detailed error information.


any help is so much appreciated. thank you in advance










share|improve this question
























  • You may want to reconsider your approach here. Your function will return a different predicate for each and every employee / department because you're hardcoding the values dynamically. A better approach may be to include the query on MANAGER.EMPLOYEES and the predicate on sys_context directly in the generated predicate; this way you end up with a static predicate which may have some performance benefit. Note: this may cause an alternative performance detriment depending on the plan generated for the resulting query; so YMMV.
    – Jeffrey Kemp
    Nov 20 at 2:42













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I have a table called payroll created by 'MANAGER' which contains the following:



EMP_ID               DEPT                      TOTAL      TAXES
-------------------- -------------------- ---------- ----------
E1 accounting 2400 100
E2 sales 2500 75
E3 research 3000 110
E4 operations 4200 120
E5 sales 4800 130
E6 sales 2500 75
E7 accounting 5200 140
E8 accounting 2700 105


I also have table called employees, created also by 'MANAGER', containing:



ENAME                USER_ID              DEPT               
-------------------- -------------------- --------------------
SAMI E4 operations
ALI E7 accounting
MIRIAM E5 sales


I also have beside 'MANAGER' two users 'ALI' and 'SAMI' and I want to limit their access to 'payroll' table based on their departments, so I gave them the select privilege on both tables 'EMPLOYEES' and 'payroll' and I wrote the following policy function:



create or replace function sec_fun (p_schema varchar2, p_obj varchar2)
return varchar2
as
v_dept MANAGER.employees.dept%type;
v_user varchar2(100);
v_id MANAGER.employees.user_id%type;
begin
v_user:= SYS_CONTEXT('userenv', 'SESSION_USER');;
select dept,user_id into v_dept, v_id from MANAGER.EMPLOYEES where ename=v_user;
if (v_dept!= 'accounting') then
return 'EMP_ID=' ||v_id;
else
return 'DEPT !=' || v_dept;
end if;
exception
when NO_DATA_FOUND then
return null;
end;
/


then I wrote:



begin
dbms_rls.add_policy(
'MANAGER',
'payroll',
'p1',
'MANAGER',
'sec_fun',
'select');
end;
/


now when I connect as 'ALI' then write



SELECT * FROM MANAGER.PAYROLL;


I get the following error which I looked and edited my policy function many times after reading the various solutions through the internet:



Error at Command Line:1 Column:23
Error report:
SQL Error: ORA-28113: policy predicate has error
*Cause: Policy function generates invalid predicate.
*Action: Review the trace file for detailed error information.


any help is so much appreciated. thank you in advance










share|improve this question















I have a table called payroll created by 'MANAGER' which contains the following:



EMP_ID               DEPT                      TOTAL      TAXES
-------------------- -------------------- ---------- ----------
E1 accounting 2400 100
E2 sales 2500 75
E3 research 3000 110
E4 operations 4200 120
E5 sales 4800 130
E6 sales 2500 75
E7 accounting 5200 140
E8 accounting 2700 105


I also have table called employees, created also by 'MANAGER', containing:



ENAME                USER_ID              DEPT               
-------------------- -------------------- --------------------
SAMI E4 operations
ALI E7 accounting
MIRIAM E5 sales


I also have beside 'MANAGER' two users 'ALI' and 'SAMI' and I want to limit their access to 'payroll' table based on their departments, so I gave them the select privilege on both tables 'EMPLOYEES' and 'payroll' and I wrote the following policy function:



create or replace function sec_fun (p_schema varchar2, p_obj varchar2)
return varchar2
as
v_dept MANAGER.employees.dept%type;
v_user varchar2(100);
v_id MANAGER.employees.user_id%type;
begin
v_user:= SYS_CONTEXT('userenv', 'SESSION_USER');;
select dept,user_id into v_dept, v_id from MANAGER.EMPLOYEES where ename=v_user;
if (v_dept!= 'accounting') then
return 'EMP_ID=' ||v_id;
else
return 'DEPT !=' || v_dept;
end if;
exception
when NO_DATA_FOUND then
return null;
end;
/


then I wrote:



begin
dbms_rls.add_policy(
'MANAGER',
'payroll',
'p1',
'MANAGER',
'sec_fun',
'select');
end;
/


now when I connect as 'ALI' then write



SELECT * FROM MANAGER.PAYROLL;


I get the following error which I looked and edited my policy function many times after reading the various solutions through the internet:



Error at Command Line:1 Column:23
Error report:
SQL Error: ORA-28113: policy predicate has error
*Cause: Policy function generates invalid predicate.
*Action: Review the trace file for detailed error information.


any help is so much appreciated. thank you in advance







oracle plsql






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 19 at 23:52









William Robertson

7,97422133




7,97422133










asked Nov 19 at 20:06









Miriam Arbaji

144




144












  • You may want to reconsider your approach here. Your function will return a different predicate for each and every employee / department because you're hardcoding the values dynamically. A better approach may be to include the query on MANAGER.EMPLOYEES and the predicate on sys_context directly in the generated predicate; this way you end up with a static predicate which may have some performance benefit. Note: this may cause an alternative performance detriment depending on the plan generated for the resulting query; so YMMV.
    – Jeffrey Kemp
    Nov 20 at 2:42


















  • You may want to reconsider your approach here. Your function will return a different predicate for each and every employee / department because you're hardcoding the values dynamically. A better approach may be to include the query on MANAGER.EMPLOYEES and the predicate on sys_context directly in the generated predicate; this way you end up with a static predicate which may have some performance benefit. Note: this may cause an alternative performance detriment depending on the plan generated for the resulting query; so YMMV.
    – Jeffrey Kemp
    Nov 20 at 2:42
















You may want to reconsider your approach here. Your function will return a different predicate for each and every employee / department because you're hardcoding the values dynamically. A better approach may be to include the query on MANAGER.EMPLOYEES and the predicate on sys_context directly in the generated predicate; this way you end up with a static predicate which may have some performance benefit. Note: this may cause an alternative performance detriment depending on the plan generated for the resulting query; so YMMV.
– Jeffrey Kemp
Nov 20 at 2:42




You may want to reconsider your approach here. Your function will return a different predicate for each and every employee / department because you're hardcoding the values dynamically. A better approach may be to include the query on MANAGER.EMPLOYEES and the predicate on sys_context directly in the generated predicate; this way you end up with a static predicate which may have some performance benefit. Note: this may cause an alternative performance detriment depending on the plan generated for the resulting query; so YMMV.
– Jeffrey Kemp
Nov 20 at 2:42












1 Answer
1






active

oldest

votes

















up vote
0
down vote



accepted










There are a few things that come up with FGAC that can trigger this situation.



First, if the predicate-generating function is itself invalid, the policy will always throw this exception. In the example provided here, the assignment of v_user (line 8) has double semicolons ;; which should cause compilation to fail.



When you run the create statement for sec_fun, you should get a message like the following:



Warning: Function created with compilation errors.
Elapsed: 00:00:00.483


Since the predicate-generator has a syntax error, the policy applied to PAYROLL will always fail with the ORA-28113.



One thing to note is that the ORA-28113 includes a helpful recommendation:

"Review the trace file for detailed error information."

When a policy fails, the database writes a trace file detailing the underlying cause.



Anyway, after dropping the double semicolons, this should at least compile. But there are other problems looming ahead that will also trigger this.



The next problem up is that the return statements as written are not valid predicates either because they don't create valid string literals.



For example, "EMP_ID = E1" is not usable because it includes a literal that is not enclosed in quotations. The same applies for the "DEPT != accounting" predicate.



In the reworked version below, these have been quoted.



Additionally, FGAC usually prefers a valid predicate be provided from all execution branches.

Perhaps returning NULL when NO_DATA_FOUND could work in your situation, but it might be preferable to return a valid predicate (that filters all data). You might prefer to throw an exception for an employee that doesn't exist; in that case NULL might be acceptable. It is just a recommendation/thought.



One other thing to note is that using SYS_CONTEXT can have some complications and be more verbose than is required. Unless there is some indirection/nesting/proxying going on that would make the current user incorrect, one can just use the USER function instead, and avoid some sys_context complications.



Here's an alternative version that should compile, not throw errors, and filter along the lines you have described:



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;
/





share|improve this answer





















  • thank you so much..it worked
    – Miriam Arbaji
    Nov 19 at 22:17










  • another question please...without the CHR(39) it fails i mean: return 'dept!=' || V_DEPT; would fail...why??
    – Miriam Arbaji
    Nov 19 at 22:29












  • Thanks Miriam, Glad to hear this works ok. For your other question, I actually mentioned that in my answer, in the line beginning For example, "EMP_ID = E1" is not usable because... The CHR(39) are quotations, and are required since emp_ids are text instead of numbers.
    – alexgibbs
    Nov 19 at 23:03










  • okay now i get it thank you a lot
    – Miriam Arbaji
    Nov 19 at 23:36











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53381880%2fvpd-policy-fails-with-ora-28113-policy-predicate-has-error%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
0
down vote



accepted










There are a few things that come up with FGAC that can trigger this situation.



First, if the predicate-generating function is itself invalid, the policy will always throw this exception. In the example provided here, the assignment of v_user (line 8) has double semicolons ;; which should cause compilation to fail.



When you run the create statement for sec_fun, you should get a message like the following:



Warning: Function created with compilation errors.
Elapsed: 00:00:00.483


Since the predicate-generator has a syntax error, the policy applied to PAYROLL will always fail with the ORA-28113.



One thing to note is that the ORA-28113 includes a helpful recommendation:

"Review the trace file for detailed error information."

When a policy fails, the database writes a trace file detailing the underlying cause.



Anyway, after dropping the double semicolons, this should at least compile. But there are other problems looming ahead that will also trigger this.



The next problem up is that the return statements as written are not valid predicates either because they don't create valid string literals.



For example, "EMP_ID = E1" is not usable because it includes a literal that is not enclosed in quotations. The same applies for the "DEPT != accounting" predicate.



In the reworked version below, these have been quoted.



Additionally, FGAC usually prefers a valid predicate be provided from all execution branches.

Perhaps returning NULL when NO_DATA_FOUND could work in your situation, but it might be preferable to return a valid predicate (that filters all data). You might prefer to throw an exception for an employee that doesn't exist; in that case NULL might be acceptable. It is just a recommendation/thought.



One other thing to note is that using SYS_CONTEXT can have some complications and be more verbose than is required. Unless there is some indirection/nesting/proxying going on that would make the current user incorrect, one can just use the USER function instead, and avoid some sys_context complications.



Here's an alternative version that should compile, not throw errors, and filter along the lines you have described:



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;
/





share|improve this answer





















  • thank you so much..it worked
    – Miriam Arbaji
    Nov 19 at 22:17










  • another question please...without the CHR(39) it fails i mean: return 'dept!=' || V_DEPT; would fail...why??
    – Miriam Arbaji
    Nov 19 at 22:29












  • Thanks Miriam, Glad to hear this works ok. For your other question, I actually mentioned that in my answer, in the line beginning For example, "EMP_ID = E1" is not usable because... The CHR(39) are quotations, and are required since emp_ids are text instead of numbers.
    – alexgibbs
    Nov 19 at 23:03










  • okay now i get it thank you a lot
    – Miriam Arbaji
    Nov 19 at 23:36















up vote
0
down vote



accepted










There are a few things that come up with FGAC that can trigger this situation.



First, if the predicate-generating function is itself invalid, the policy will always throw this exception. In the example provided here, the assignment of v_user (line 8) has double semicolons ;; which should cause compilation to fail.



When you run the create statement for sec_fun, you should get a message like the following:



Warning: Function created with compilation errors.
Elapsed: 00:00:00.483


Since the predicate-generator has a syntax error, the policy applied to PAYROLL will always fail with the ORA-28113.



One thing to note is that the ORA-28113 includes a helpful recommendation:

"Review the trace file for detailed error information."

When a policy fails, the database writes a trace file detailing the underlying cause.



Anyway, after dropping the double semicolons, this should at least compile. But there are other problems looming ahead that will also trigger this.



The next problem up is that the return statements as written are not valid predicates either because they don't create valid string literals.



For example, "EMP_ID = E1" is not usable because it includes a literal that is not enclosed in quotations. The same applies for the "DEPT != accounting" predicate.



In the reworked version below, these have been quoted.



Additionally, FGAC usually prefers a valid predicate be provided from all execution branches.

Perhaps returning NULL when NO_DATA_FOUND could work in your situation, but it might be preferable to return a valid predicate (that filters all data). You might prefer to throw an exception for an employee that doesn't exist; in that case NULL might be acceptable. It is just a recommendation/thought.



One other thing to note is that using SYS_CONTEXT can have some complications and be more verbose than is required. Unless there is some indirection/nesting/proxying going on that would make the current user incorrect, one can just use the USER function instead, and avoid some sys_context complications.



Here's an alternative version that should compile, not throw errors, and filter along the lines you have described:



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;
/





share|improve this answer





















  • thank you so much..it worked
    – Miriam Arbaji
    Nov 19 at 22:17










  • another question please...without the CHR(39) it fails i mean: return 'dept!=' || V_DEPT; would fail...why??
    – Miriam Arbaji
    Nov 19 at 22:29












  • Thanks Miriam, Glad to hear this works ok. For your other question, I actually mentioned that in my answer, in the line beginning For example, "EMP_ID = E1" is not usable because... The CHR(39) are quotations, and are required since emp_ids are text instead of numbers.
    – alexgibbs
    Nov 19 at 23:03










  • okay now i get it thank you a lot
    – Miriam Arbaji
    Nov 19 at 23:36













up vote
0
down vote



accepted







up vote
0
down vote



accepted






There are a few things that come up with FGAC that can trigger this situation.



First, if the predicate-generating function is itself invalid, the policy will always throw this exception. In the example provided here, the assignment of v_user (line 8) has double semicolons ;; which should cause compilation to fail.



When you run the create statement for sec_fun, you should get a message like the following:



Warning: Function created with compilation errors.
Elapsed: 00:00:00.483


Since the predicate-generator has a syntax error, the policy applied to PAYROLL will always fail with the ORA-28113.



One thing to note is that the ORA-28113 includes a helpful recommendation:

"Review the trace file for detailed error information."

When a policy fails, the database writes a trace file detailing the underlying cause.



Anyway, after dropping the double semicolons, this should at least compile. But there are other problems looming ahead that will also trigger this.



The next problem up is that the return statements as written are not valid predicates either because they don't create valid string literals.



For example, "EMP_ID = E1" is not usable because it includes a literal that is not enclosed in quotations. The same applies for the "DEPT != accounting" predicate.



In the reworked version below, these have been quoted.



Additionally, FGAC usually prefers a valid predicate be provided from all execution branches.

Perhaps returning NULL when NO_DATA_FOUND could work in your situation, but it might be preferable to return a valid predicate (that filters all data). You might prefer to throw an exception for an employee that doesn't exist; in that case NULL might be acceptable. It is just a recommendation/thought.



One other thing to note is that using SYS_CONTEXT can have some complications and be more verbose than is required. Unless there is some indirection/nesting/proxying going on that would make the current user incorrect, one can just use the USER function instead, and avoid some sys_context complications.



Here's an alternative version that should compile, not throw errors, and filter along the lines you have described:



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;
/





share|improve this answer












There are a few things that come up with FGAC that can trigger this situation.



First, if the predicate-generating function is itself invalid, the policy will always throw this exception. In the example provided here, the assignment of v_user (line 8) has double semicolons ;; which should cause compilation to fail.



When you run the create statement for sec_fun, you should get a message like the following:



Warning: Function created with compilation errors.
Elapsed: 00:00:00.483


Since the predicate-generator has a syntax error, the policy applied to PAYROLL will always fail with the ORA-28113.



One thing to note is that the ORA-28113 includes a helpful recommendation:

"Review the trace file for detailed error information."

When a policy fails, the database writes a trace file detailing the underlying cause.



Anyway, after dropping the double semicolons, this should at least compile. But there are other problems looming ahead that will also trigger this.



The next problem up is that the return statements as written are not valid predicates either because they don't create valid string literals.



For example, "EMP_ID = E1" is not usable because it includes a literal that is not enclosed in quotations. The same applies for the "DEPT != accounting" predicate.



In the reworked version below, these have been quoted.



Additionally, FGAC usually prefers a valid predicate be provided from all execution branches.

Perhaps returning NULL when NO_DATA_FOUND could work in your situation, but it might be preferable to return a valid predicate (that filters all data). You might prefer to throw an exception for an employee that doesn't exist; in that case NULL might be acceptable. It is just a recommendation/thought.



One other thing to note is that using SYS_CONTEXT can have some complications and be more verbose than is required. Unless there is some indirection/nesting/proxying going on that would make the current user incorrect, one can just use the USER function instead, and avoid some sys_context complications.



Here's an alternative version that should compile, not throw errors, and filter along the lines you have described:



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;
/






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 19 at 21:50









alexgibbs

1,5732913




1,5732913












  • thank you so much..it worked
    – Miriam Arbaji
    Nov 19 at 22:17










  • another question please...without the CHR(39) it fails i mean: return 'dept!=' || V_DEPT; would fail...why??
    – Miriam Arbaji
    Nov 19 at 22:29












  • Thanks Miriam, Glad to hear this works ok. For your other question, I actually mentioned that in my answer, in the line beginning For example, "EMP_ID = E1" is not usable because... The CHR(39) are quotations, and are required since emp_ids are text instead of numbers.
    – alexgibbs
    Nov 19 at 23:03










  • okay now i get it thank you a lot
    – Miriam Arbaji
    Nov 19 at 23:36


















  • thank you so much..it worked
    – Miriam Arbaji
    Nov 19 at 22:17










  • another question please...without the CHR(39) it fails i mean: return 'dept!=' || V_DEPT; would fail...why??
    – Miriam Arbaji
    Nov 19 at 22:29












  • Thanks Miriam, Glad to hear this works ok. For your other question, I actually mentioned that in my answer, in the line beginning For example, "EMP_ID = E1" is not usable because... The CHR(39) are quotations, and are required since emp_ids are text instead of numbers.
    – alexgibbs
    Nov 19 at 23:03










  • okay now i get it thank you a lot
    – Miriam Arbaji
    Nov 19 at 23:36
















thank you so much..it worked
– Miriam Arbaji
Nov 19 at 22:17




thank you so much..it worked
– Miriam Arbaji
Nov 19 at 22:17












another question please...without the CHR(39) it fails i mean: return 'dept!=' || V_DEPT; would fail...why??
– Miriam Arbaji
Nov 19 at 22:29






another question please...without the CHR(39) it fails i mean: return 'dept!=' || V_DEPT; would fail...why??
– Miriam Arbaji
Nov 19 at 22:29














Thanks Miriam, Glad to hear this works ok. For your other question, I actually mentioned that in my answer, in the line beginning For example, "EMP_ID = E1" is not usable because... The CHR(39) are quotations, and are required since emp_ids are text instead of numbers.
– alexgibbs
Nov 19 at 23:03




Thanks Miriam, Glad to hear this works ok. For your other question, I actually mentioned that in my answer, in the line beginning For example, "EMP_ID = E1" is not usable because... The CHR(39) are quotations, and are required since emp_ids are text instead of numbers.
– alexgibbs
Nov 19 at 23:03












okay now i get it thank you a lot
– Miriam Arbaji
Nov 19 at 23:36




okay now i get it thank you a lot
– Miriam Arbaji
Nov 19 at 23:36


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53381880%2fvpd-policy-fails-with-ora-28113-policy-predicate-has-error%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Wiesbaden

Marschland

Dieringhausen