Para solucionar este problema, la versión 12c de la base de datos Oracle incorpora la cláusula BEQUEATH que permite definir una vista para que si esta incluye funciones, los permisos de ejecución de las mismas se acomoden con los permisos del usuario que invoca la vista.
Para facilitar el uso de esta nueva cláusula, Oracle 12c incluye dos nuevas funciones que permiten identificar al usuario que invoca una vista (o sentencia SQL), determinando por tanto si son utilizados los permisos del usuario que la invoca o si se utilizan los del propietario de la vista:
- Función ORA_INVOKING_USERID: devuelve el ID del usuario que está invocando la sentencia o vista actual. En el caso de que dicho usuario haya sido definido a través de la funcionalidad “Real Application Security” disponible en las bases de datos Oracle, la función devolverá un ID que es común para todas las sesiones abiertas por usuarios de este tipo pero que es diferente del ID de cualquier usuario de la base de datos.
- Función ORA_INVOKING_USER: devuelve el nombre del usuario que está invocando la sentencia o vista actual. En el caso de que dicho usuario haya sido definido a través de la funcionalidad “Real Application Security” disponible en las bases de datos Oracle, la función devolverá el valor XS$NULL.
Las funciones antes mencionadas solo pueden invocarse desde una sentencia SQL, es decir, no están disponibles desde PL/SQL nativo.
Veamos a continuación con un ejemplo como funciona la cláusula BEQUEATH y las funciones antes mencionadas. A continuación en el esquema INV crearemos la tabla articulos_inventario y la función cuenta_articulos que llama a las funciones ORA_INVOKING.
CREATE TABLE inv.articulos_inventario ( articulo_id INTEGER, almacen_id INTEGER, articulo VARCHAR2 (100) ) / BEGIN INSERT INTO inv.articulos_inventario VALUES (1, 10, 'UVW'); INSERT INTO inv.articulos_inventario VALUES (2, 10, 'XYZ'); INSERT INTO inv.articulos_inventario VALUES (3, 20, '987'); COMMIT; END; / CREATE OR REPLACE FUNCTION inv.cuenta_articulos (p_almacen_id IN INTEGER) RETURN PLS_INTEGER AUTHID CURRENT_USER IS l_cont PLS_INTEGER; l_usuario VARCHAR2 (100); l_usuario_id VARCHAR2 (100); BEGIN SELECT COUNT (*) INTO l_cont FROM articulos_inventario WHERE almacen_id = p_almacen_id; /* Invocando las funciones ORA_INVOKING */ SELECT ora_invoking_user INTO l_usuario FROM DUAL; SELECT ora_invoking_userid INTO l_usuario_id FROM DUAL; DBMS_OUTPUT.put_line (l_usuario); DBMS_OUTPUT.put_line (l_usuario_id); RETURN l_cont; END; /
Ahora creamos la vista cuenta_articulos_v definiendo con la cláusula BEQUEATH que se ejecute utilizando los permisos del usuario que la invoca (CURRENT_USER), asegurando que el usuario APPS puede llamar a la vista.
CREATE OR REPLACE VIEW cuenta_articulos_v BEQUEATH CURRENT_USER AS SELECT almacen_id , cuenta_articulos (almacen_id) art_en_almacen FROM articulos_inventario / GRANT SELECT ON cuenta_articulos_v TO apps /
A continuación, en el esquema APPS creamos una segunda tabla articulos_inventario pero insertando datos diferentes.
CREATE TABLE apps.articulos_inventario ( articulo_id INTEGER, almacen_id INTEGER, articulo VARCHAR2 (100) ) / BEGIN INSERT INTO apps.articulos_inventario VALUES (1, 20, 'APPS.UVW'); INSERT INTO apps.articulos_inventario VALUES (2, 20, 'APPS.XYZ'); INSERT INTO apps.articulos_inventario VALUES (3, 30, 'APPS.987'); COMMIT; END; /
Y finalmente ejecutamos bajo el usuario APPS un SELECT sobre la vista que hemos definido anteriormente y vemos la salida correspondiente.
SQL> SET SERVEROUTPUT ON SQL> SELECT * FROM INV.articulos_inventario 2 / ALMACEN_ID ART_EN_ALMACEN ---------- -------------- 10 0 10 0 20 2 APPS 212 APPS 212 APPS 212
Como podéis comprobar los datos que devuelve la vista proceden de la tabla del esquema INV (hay dos registros para el almacén ID 10), pero los valores devueltos por la función cuenta_articulos reflejan los datos almacenados en la tabla del esquema APPS. Asimismo, las funciones ORA_INVOKING devuelven la información relacionada con el usuario APPS.
Debemos advertir que la cláusula BEQUEATH CURRENT_USER no transforma la vista en un objeto propio del usuario que la invoca. El nombre de la vista requiere que se utilice el nombre del esquema propietario de la misma y los permisos de ejecución sobre la misma se comprueban sobre dicho esquema.
El principal beneficio de esta funcionalidad es que posibilita que funciones como USERENV o SYS_CONTEXT devuelvan valores consistentes con las funciones PL/SQL que sean referenciadas en una vista.
Artículos relacionados: Vistas materializadas.
0 comentarios:
Publicar un comentario