Recently I bumped into a problem while dealing with "instead of" triggers in the Oracle database.
You may read more about instead of triggers in the official documentation:
https://docs.oracle.com/en/database/oracle/oracle-database/19/lnpls/plsql-triggers.html#GUID-9F06D45C-7C60-434E-A597-114A0C445671
https://docs.oracle.com/en/database/oracle/oracle-database/19/lnpls/plsql-triggers.html#GUID-9F06D45C-7C60-434E-A597-114A0C445671
The scenario is the following.
In my main schema (let's call it SC1) I created a view named DEMO_STATES_V based on the table DEMO_STATES located in another schema (let's call it SC2).
CREATE OR REPLACE VIEW my_demo_states AS SELECT st, state_name FROM sc2.demo_states;
The user SC1 has SELECT privilege granted on the table SC2.DEMO_STATES.
I created an "instead of" trigger on the view DEMO_STATES_V to handle DML operations.
Currently there is only a dbms output but it is enough to present the problem.
CREATE OR REPLACE TRIGGER my_demo_states_trg INSTEAD OF INSERT OR UPDATE OR DELETE ON my_demo_states FOR EACH ROW BEGIN dbms_output.put_line('The trigger executes!'); END; /
I tried to insert the record into the view and I'm expecting to get the dbms output written.
INSERT INTO my_demo_states (st, state_name) VALUES ('SI', 'Slovenia');
But...
Instead of the trigger execution and dbms output produced I got an error!
ORA-01031: insufficient privileges
Seems that the database checked insert privileges BEFORE executing the trigger!
And while user SC1 does not have the insert privilege granted... an error occurred.
Honestly, I haven't expected that. I mean, if I have the "instead of" trigger created, why would database check any DML privileges on the underlying table? The "instead of" trigger is going to handle eventual DML operations... and grants should be checked for the PL/SQL code in the trigger body.
Another but... there is an override. 💪
If You modify the SELECT statement for the view object and implement UNION ALL from DUAL with "1=2" condition... so that actually no record is added to the original result set from the first part of the select statement... then everything works! For example:
CREATE OR REPLACE VIEW my_demo_states AS SELECT st, state_name FROM dome_ms1.demo_states UNION ALL SELECT null, null FROM dual WHERE 1=2;
No privileges are checked and the trigger executes flawlessly!
No comments:
Post a Comment