Sometimes it might be interesting to understand, what's the SQL statement which is currently executed.
In an Oracle instance, for any other session it's quite simple by accessing some v$ views. But from "within" the statement, it's not straight forward. Nevertheless it's possible, by a creative combination of some features.
Here is the example.
First let's create a proper user:
CREATE USER know IDENTIFIED BY "thyself"; GRANT connect, resource TO know; GRANT UNLIMITED TABLESPACE TO know; GRANT CREATE VIEW TO know; GRANT imp_full_database TO know;
That's slightly more than really needed - so if you evern require this funcitonality, please be careful with required permissions!
In this example, we do not even need a table.
But a Package to keep some variables:
CREATE OR REPLACE PACKAGE other_color_injector AS -- package OCI text_keeper VARCHAR2(4000 CHAR) := '--'; current_color VARCHAR2(100 CHAR) := 'white'; FUNCTION rls_hook ( p_schema IN VARCHAR2, p_object IN VARCHAR2 ) RETURN VARCHAR2; END other_color_injector; / CREATE OR REPLACE PACKAGE BODY other_color_injector AS FUNCTION rls_hook ( p_schema IN VARCHAR2, p_object IN VARCHAR2 ) RETURN VARCHAR2 AS PRAGMA autonomous_transaction; chk_color VARCHAR2(100 CHAR); BEGIN text_keeper := sys_context('userenv', 'CURRENT_SQL'); -- first word in /* comment chk_color := regexp_substr(regexp_substr(text_keeper, '/\*.*\*'), '[[:alpha:]]+'); dbms_output.put_line(' SQL Text:' || text_keeper || '---'); IF chk_color IS NOT NULL THEN current_color := chk_color; END IF; RETURN NULL; END; END other_color_injector; /
And a function which gives us some feedback about the SQL in which it's called:
CREATE OR REPLACE TYPE rain_tab IS TABLE OF VARCHAR2(100 CHAR); create or replace FUNCTION rain_bow -- RETURN t_tf_tab return rain_tab PIPELINED AS BEGIN PIPE ROW ( other_color_injector.current_color ); RETURN; END; / create or replace view cloud as select column_value as color from rain_bow();
The view is somehow important for the next step whihc puts all the pieces together:
BEGIN dbms_rls.add_policy(object_schema => 'KNOW', object_name => 'CLOUD', policy_name => 'RAIN', function_schema => 'KNOW', policy_function => 'OTHER_COLOR_INJECTOR.RLS_HOOK', statement_types => 'select', update_check => false); END; /
With this objects in place, a beautiful, but maybe confusing result can be created:
Enter user-name: know/thyself@pdb1 Connected to: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.3.0.0.0 SQL> select * from cloud; COLOR ------------------------------------------- white SQL> select /* red */ * from cloud; COLOR ------------------------------------------- red SQL> select * from cloud; COLOR ------------------------------------------- red SQL> select /* green */ * from cloud; COLOR ------------------------------------------- green SQL> select * from cloud; COLOR ------------------------------------------- green SQL>
The important part is this line in OTHER_COLOR_INJECTOR.RLS_HOOK:
text_keeper := sys_context('userenv', 'CURRENT_SQL');
SYS_CONTEXT has access to CURRENT_SQL (and some other useful parameters) - but only in fine grained audot / RLS events. So all the other objects are required to make this information available in my view rain_bow.
I also created a small twitter quiz where I asked for methods to identify the current SQL and create values based on the SQL.
Rene Jeruschkat suggested a solution based on latest v$sqlstats:
exploiting the excessive privileges you granted know and keeping track of the color in v$sqlstats. pic.twitter.com/2tCu8eQyoH— Rene jeruschkat (@rene_jeruschkat) April 4, 2020
Mathias Rogel suggested to get the latest cursor from v$open_cursor which belongs to the current session:
— Matthias Rogel 🏃🚴🏊♂️🏋️ (@MatthiasRogel) April 5, 2020
Both are great solutions and show: there is quite often more than one way to solve a problem!
If you are curious about the greek letters in the title: Γνῶθι σεαυτόν they can be translated to know thyself - something which is often hard - not only for SQL statements.
Keine Kommentare:
Kommentar veröffentlichen