-- Dictionary Long Application -- --------------------------- -- MIT License -- Copyright (c) 2007 Adrian Billington, www.oracle-developer.net -- Permission is hereby granted, free of charge, to any person obtaining a copy -- of this software and associated documentation files (the "Software"), to deal -- in the Software without restriction, including without limitation the rights -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -- copies of the Software, and to permit persons to whom the Software is -- furnished to do so, subject to the following conditions: -- -- The above copyright notice and this permission notice shall be included in all -- copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -- SOFTWARE. set pause on prompt prompt prompt ************************************************************************** prompt ************************************************************************** prompt prompt Dictionary Long Application Installer (for 10.2+ databases) prompt =========================================================== prompt prompt This will install the Dictionary Long Application (dynamic version). prompt prompt To continue press Enter. To quit press Ctrl-C. prompt prompt (c) oracle-developer.net prompt prompt ************************************************************************** prompt ************************************************************************** prompt prompt pause prompt Installing application context... CREATE CONTEXT dla_ctx USING dla_pkg; prompt Installing types... CREATE TYPE dla_filter_ot AS OBJECT ( name VARCHAR2(30) , value VARCHAR2(4000) ); / CREATE TYPE dla_filter_ntt AS TABLE OF dla_filter_ot; / prompt Installing dla_ot type specification... CREATE TYPE dla_ot AS OBJECT ( /* || --------------------------------------------------------------------------------- || || Name: dla_ot || || Description: Implementation type for dynamic Dictionary Long Application || || License: MIT License || Copyright (c) 2007 Adrian Billington, www.oracle-developer.net || See https://github.com/oracle-developer/dla/blob/master/LICENSE || || --------------------------------------------------------------------------------- */ atype ANYTYPE --<-- transient record type , STATIC FUNCTION ODCITableDescribe( rtype OUT ANYTYPE, stmt IN VARCHAR2 ) RETURN NUMBER , STATIC FUNCTION ODCITablePrepare( sctx OUT dla_ot, tf_info IN sys.ODCITabFuncInfo, stmt IN VARCHAR2 ) RETURN NUMBER , STATIC FUNCTION ODCITableStart( sctx IN OUT dla_ot, stmt IN VARCHAR2 ) RETURN NUMBER , MEMBER FUNCTION ODCITableFetch( SELF IN OUT dla_ot, nrows IN NUMBER, rws OUT anydataset ) RETURN NUMBER , MEMBER FUNCTION ODCITableClose( SELF IN dla_ot ) RETURN NUMBER ); / prompt Installing dla_pkg package specification... CREATE PACKAGE dla_pkg AS /* || --------------------------------------------------------------------------------- || || Name: dla_pkg || || Description: Package wrapper to DBA views with LONG columns. This package || contains a single interface to a pipelined function implemented by || an object type (DLA_OT) using ANYDATASET. || || Version: This version is for Oracle 10.2.0.x and upwards. || || Semantically and syntactically, this application should run on || 10.1.x databases, but there is an ORA-0600 error which appears || to be a bug in the way ANYDATASET fetches CLOBs. For this reason, || it is recommended that the static version of the Dictionary Long || Application is used for versions less than 10.2.0.1. || || Included: Using this dynamic interface approach, it is possible to return any || dictionary view that contains a LONG. With this version of the || dictionary package, no additional setup is required to include new || views (unlike the 9i/10gR1 version). This also means that the || USER/ALL equivalents can be queried without any additional work. || || Notes: 1. The pipelined function returns a record structure that matches || the column structure of the underlying DBA_% view (or query || from that view). The only exception to this is of course the || LONG column, which is returned from each DBA_% view as a CLOB. || || 2. The interface function is further encapsulated by a set of || views for the commonly-used DBA_% views. Views are named || V_[dba_view name], e.g. V_DBA_VIEWS. To query other DBA_% views || either the interface function can be used directly or V_% || views can be setup easily using the existing examples as || templates. || || 3. A small number of filters can be set before running a query || against the pipelined function (or wrapper view) to limit the || amount of data returned. See SET_FILTER and usage notes for || details. For more specific filters, either the SET APIs can be || extended or the underlying query against the DBA_% view can || be modified to include additional predicates. || || 4. The ANYDATASET interface has been available as a Data Cartridge || since Oracle 9i. However, the ODCI methods needed to enable dynamic || describe of a SQL statement were not available until 10g (that is, || we could only interface to a known query structure). 10g enables || us to combine DBMS_SQL with ANYDATASET/ANYTYPE methods to build || a self-describing return structure for the first time. || || 5. This utility is designed for views with LONGs only. It is not a || general-purpose dynamic query engine. As such, some of the type || flexibility required of such an engine is not available. As of || 10.2.0.x, only a small number of types are used in DBA_% views || and this utility caters for them. It also adds the code required || to handle some additional types found in DBMS_TYPES, but these || will be unused until at least 11g. || || || Usage: a) Query direct from interface (entire view) || -------------------------------------------- || e.g. Query DBA_VIEWS where view text contains table SOME_TABLE. || || SELECT owner, view_name, text || FROM TABLE( || dla_pkg.query_view( || 'SELECT * FROM dba_views') || ) || WHERE UPPER(text) LIKE '%SOME_TABLE%'; || || b) Query direct from interface (specific sql against view) || ---------------------------------------------------------- || e.g. Query DBA_VIEWS where view text contains table SOME_TABLE. || || SELECT * || FROM TABLE( || dla_pkg.query_view( || 'SELECT owner, view_name, text FROM dba_views') || ) || WHERE UPPER(text) LIKE '%SOME_TABLE%'; || || c) Query direct from wrapper views || ---------------------------------- || e.g. Query V_DBA_VIEWS where view text contains table SOME_TABLE. || || SELECT owner, view_name, text || FROM v_dba_views || WHERE UPPER(text) LIKE '%SOME_TABLE%'; || || d) Use the filter APIs to restrict the function return || ------------------------------------------------------ || e.g. Add filters to restrict V_DBA_VIEWS to SCOTT.SOME_VIEW || || BEGIN || dla_pkg.set_filter(p_name => 'OWNER', || p_value => 'SCOTT'); || dla_pkg.set_filter(p_name => 'VIEW_NAME', || p_value => 'SOME_VIEW'); || END; || / || || SELECT owner, view_name, text || FROM v_dba_views; --<-- returns 1 row only for SCOTT.SOME_VIEW || || e) Clear the filters || ------------------------------------------------------ || e.g. Clear all current filters || || BEGIN || dla_pkg.clear_filter; || END; || / || || e.g. Clear a specific filter || || BEGIN || dla_pkg.clear_filter( p_name => 'OWNER', || p_value => 'SCOTT' ); || END; || / || || f) Show the current filters || ------------------------------------------------------ || e.g. Using API (can alternatively use SESSION_CONTEXT) || || SELECT * || FROM TABLE(dla_pkg.show_filters); || || g) Include pseudo-columns/functions || ------------------------------------------------------ || e.g. ROWID, ROWNUM, LEVEL, SYSDATE, USER. These *must* || be aliased. || || SELECT * || FROM TABLE( || dla_pkg.query_view( || 'SELECT ROWNUM AS rn, owner, view_name, text || FROM dba_views') || ); || || License: MIT License || Copyright (c) 2007 Adrian Billington, www.oracle-developer.net || See https://github.com/oracle-developer/dla/blob/master/LICENSE || || --------------------------------------------------------------------------------- */ /* || SET_FILTER sets a small range of filters to limit the amount of data returned || from a query. For example, to restrict the DBA_TRIGGERS function (or || V_DBA_TRIGGERS wrapper view) to SCOTT, set the OWNER filter to 'SCOTT' before || executing the query. || || Valid filters are: || || * OWNER || * TABLE_NAME || * VIEW_NAME || * COLUMN_NAME || * CONSTRAINT_NAME || * TRIGGER_NAME || * PARTITION_NAME || * SUBPARTITION_NAME || || Invalid filters will raise ORA-20000. || || Additional filters can easily be added to the package body as required. */ PROCEDURE set_filter( p_name IN VARCHAR2, p_value IN VARCHAR2 ); /* || CLEAR_FILTER removes a filter so that it doesn't restrict any subsequent || queries. Valid filters are: || || * ALL || * OWNER || * TABLE_NAME || * VIEW_NAME || * COLUMN_NAME || * CONSTRAINT_NAME || * TRIGGER_NAME || * PARTITION_NAME || * SUBPARTITION_NAME */ PROCEDURE clear_filter( p_name IN VARCHAR2 DEFAULT 'ALL' ); /* || Table function to show current filters. Alternatively, || query the SESSION_CONTEXT built-in view. */ FUNCTION show_filters RETURN dla_filter_ntt; /* || Pipelined function interface. */ FUNCTION query_view( p_stmt IN VARCHAR2 ) RETURN ANYDATASET PIPELINED USING dla_ot; /* || Record types for use across multiple DLA_OT methods. */ TYPE rt_dynamic_sql IS RECORD ( cursor INTEGER , column_cnt PLS_INTEGER , description DBMS_SQL.DESC_TAB2 , execute INTEGER ); TYPE rt_anytype_metadata IS RECORD ( precision PLS_INTEGER , scale PLS_INTEGER , length PLS_INTEGER , csid PLS_INTEGER , csfrm PLS_INTEGER , schema VARCHAR2(30) , type ANYTYPE , name VARCHAR2(30) , version VARCHAR2(30) , attr_cnt PLS_INTEGER , attr_type ANYTYPE , attr_name VARCHAR2(128) , typecode PLS_INTEGER ); /* || State variable for use across multiple DLA_OT methods. */ r_sql rt_dynamic_sql; END dla_pkg; / prompt Installing dla_ot type body... CREATE TYPE BODY dla_ot AS /* || --------------------------------------------------------------------------------- || || Name: dla_ot || || Description: Implementation type for dynamic Dictionary Long Application || || License: MIT License || Copyright (c) 2007 Adrian Billington, www.oracle-developer.net || See https://github.com/oracle-developer/dla/blob/master/LICENSE || || --------------------------------------------------------------------------------- */ ------------------------------------------------------------------------------------ STATIC FUNCTION ODCITableDescribe( rtype OUT ANYTYPE, stmt IN VARCHAR2 ) RETURN NUMBER IS r_sql dla_pkg.rt_dynamic_sql; v_rtype ANYTYPE; BEGIN /* || Parse the SQL and describe its format and structure. */ r_sql.cursor := DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE( r_sql.cursor, stmt, DBMS_SQL.NATIVE ); DBMS_SQL.DESCRIBE_COLUMNS2( r_sql.cursor, r_sql.column_cnt, r_sql.description ); DBMS_SQL.CLOSE_CURSOR( r_sql.cursor ); /* || Create the ANYTYPE record structure from this SQL structure. || Replace LONG columns with CLOB... */ ANYTYPE.BeginCreate( DBMS_TYPES.TYPECODE_OBJECT, v_rtype ); FOR i IN 1 .. r_sql.column_cnt LOOP v_rtype.AddAttr( r_sql.description(i).col_name, CASE --<>-- WHEN r_sql.description(i).col_type IN (1,96,11,208) THEN DBMS_TYPES.TYPECODE_VARCHAR2 --<>-- WHEN r_sql.description(i).col_type = 2 THEN DBMS_TYPES.TYPECODE_NUMBER --<LONG defined as CLOB>-- WHEN r_sql.description(i).col_type IN (8,112) THEN DBMS_TYPES.TYPECODE_CLOB --<>-- WHEN r_sql.description(i).col_type = 12 THEN DBMS_TYPES.TYPECODE_DATE --<>-- WHEN r_sql.description(i).col_type = 23 THEN DBMS_TYPES.TYPECODE_RAW --<>-- WHEN r_sql.description(i).col_type = 180 THEN DBMS_TYPES.TYPECODE_TIMESTAMP --<>-- WHEN r_sql.description(i).col_type = 181 THEN DBMS_TYPES.TYPECODE_TIMESTAMP_TZ --<>-- WHEN r_sql.description(i).col_type = 182 THEN DBMS_TYPES.TYPECODE_INTERVAL_YM --<>-- WHEN r_sql.description(i).col_type = 183 THEN DBMS_TYPES.TYPECODE_INTERVAL_DS --<>-- WHEN r_sql.description(i).col_type = 231 THEN DBMS_TYPES.TYPECODE_TIMESTAMP_LTZ --<>-- END, r_sql.description(i).col_precision, r_sql.description(i).col_scale, CASE r_sql.description(i).col_type WHEN 11 THEN 32 ELSE r_sql.description(i).col_max_len END, r_sql.description(i).col_charsetid, r_sql.description(i).col_charsetform ); END LOOP; v_rtype.EndCreate; /* || Now we can use this transient record structure to create a table type || of the same. This will create a set of types on the database for use || by the pipelined function... */ ANYTYPE.BeginCreate( DBMS_TYPES.TYPECODE_TABLE, rtype ); rtype.SetInfo( NULL, NULL, NULL, NULL, NULL, v_rtype, DBMS_TYPES.TYPECODE_OBJECT, 0 ); rtype.EndCreate(); RETURN ODCIConst.Success; END; ------------------------------------------------------------------------------------ STATIC FUNCTION ODCITablePrepare( sctx OUT dla_ot, tf_info IN sys.ODCITabFuncInfo, stmt IN VARCHAR2 ) RETURN NUMBER IS r_meta dla_pkg.rt_anytype_metadata; BEGIN /* || We prepare the dataset that our pipelined function will return by || describing the ANYTYPE that contains the transient record structure... */ r_meta.typecode := tf_info.rettype.GetAttrElemInfo( 1, r_meta.precision, r_meta.scale, r_meta.length, r_meta.csid, r_meta.csfrm, r_meta.type, r_meta.name ); /* || Using this, we initialise the scan context for use in this and || subsequent executions of the same dynamic SQL cursor... */ sctx := dla_ot(r_meta.type); RETURN ODCIConst.Success; END; ------------------------------------------------------------------------------------ STATIC FUNCTION ODCITableStart( sctx IN OUT dla_ot, stmt IN VARCHAR2 ) RETURN NUMBER IS r_meta dla_pkg.rt_anytype_metadata; BEGIN /* || We now describe the cursor again and use this and the described || ANYTYPE structure to define and execute the SQL statement... */ dla_pkg.r_sql.cursor := DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE( dla_pkg.r_sql.cursor, stmt, DBMS_SQL.NATIVE ); DBMS_SQL.DESCRIBE_COLUMNS2( dla_pkg.r_sql.cursor, dla_pkg.r_sql.column_cnt, dla_pkg.r_sql.description ); FOR i IN 1 .. dla_pkg.r_sql.column_cnt LOOP /* || Get the ANYTYPE attribute at this position... */ r_meta.typecode := sctx.atype.GetAttrElemInfo( i, r_meta.precision, r_meta.scale, r_meta.length, r_meta.csid, r_meta.csfrm, r_meta.type, r_meta.name ); CASE r_meta.typecode --<>-- WHEN DBMS_TYPES.TYPECODE_VARCHAR2 THEN DBMS_SQL.DEFINE_COLUMN( dla_pkg.r_sql.cursor, i, '', 32767 ); --<>-- WHEN DBMS_TYPES.TYPECODE_NUMBER THEN DBMS_SQL.DEFINE_COLUMN( dla_pkg.r_sql.cursor, i, CAST(NULL AS NUMBER) ); --<>-- WHEN DBMS_TYPES.TYPECODE_DATE THEN DBMS_SQL.DEFINE_COLUMN( dla_pkg.r_sql.cursor, i, CAST(NULL AS DATE) ); --<>-- WHEN DBMS_TYPES.TYPECODE_RAW THEN DBMS_SQL.DEFINE_COLUMN_RAW( dla_pkg.r_sql.cursor, i, CAST(NULL AS RAW), r_meta.length ); --<>-- WHEN DBMS_TYPES.TYPECODE_TIMESTAMP THEN DBMS_SQL.DEFINE_COLUMN( dla_pkg.r_sql.cursor, i, CAST(NULL AS TIMESTAMP) ); --<>-- WHEN DBMS_TYPES.TYPECODE_TIMESTAMP_TZ THEN DBMS_SQL.DEFINE_COLUMN( dla_pkg.r_sql.cursor, i, CAST(NULL AS TIMESTAMP WITH TIME ZONE) ); --<>-- WHEN DBMS_TYPES.TYPECODE_TIMESTAMP_LTZ THEN DBMS_SQL.DEFINE_COLUMN( dla_pkg.r_sql.cursor, i, CAST(NULL AS TIMESTAMP WITH LOCAL TIME ZONE) ); --<>-- WHEN DBMS_TYPES.TYPECODE_INTERVAL_YM THEN DBMS_SQL.DEFINE_COLUMN( dla_pkg.r_sql.cursor, i, CAST(NULL AS INTERVAL YEAR TO MONTH) ); --<>-- WHEN DBMS_TYPES.TYPECODE_INTERVAL_DS THEN DBMS_SQL.DEFINE_COLUMN( dla_pkg.r_sql.cursor, i, CAST(NULL AS INTERVAL DAY TO SECOND) ); --<>-- WHEN DBMS_TYPES.TYPECODE_CLOB THEN --<>-- CASE dla_pkg.r_sql.description(i).col_type WHEN 8 THEN DBMS_SQL.DEFINE_COLUMN_LONG( dla_pkg.r_sql.cursor, i ); ELSE DBMS_SQL.DEFINE_COLUMN( dla_pkg.r_sql.cursor, i, CAST(NULL AS CLOB) ); END CASE; --<>-- END CASE; END LOOP; /* || The cursor is prepared according to the structure of the type we wish || to fetch it into. We can now execute it and we are done for this method... */ dla_pkg.r_sql.execute := DBMS_SQL.EXECUTE( dla_pkg.r_sql.cursor ); RETURN ODCIConst.Success; END; ------------------------------------------------------------------------------------ MEMBER FUNCTION ODCITableFetch( SELF IN OUT dla_ot, nrows IN NUMBER, rws OUT ANYDATASET ) RETURN NUMBER IS TYPE rt_fetch_attributes IS RECORD ( v2_column VARCHAR2(32767) , num_column NUMBER , date_column DATE , clob_column CLOB , raw_column RAW(32767) , raw_error NUMBER , raw_length INTEGER , ids_column INTERVAL DAY TO SECOND , iym_column INTERVAL YEAR TO MONTH , ts_column TIMESTAMP , tstz_column TIMESTAMP WITH TIME ZONE , tsltz_column TIMESTAMP WITH LOCAL TIME ZONE , cvl_offset INTEGER := 0 , cvl_length INTEGER ); r_fetch rt_fetch_attributes; r_meta dla_pkg.rt_anytype_metadata; BEGIN IF DBMS_SQL.FETCH_ROWS( dla_pkg.r_sql.cursor ) > 0 THEN /* || First we describe our current ANYTYPE instance (SELF.A) to determine || the number and types of the attributes... */ r_meta.typecode := SELF.atype.GetInfo( r_meta.precision, r_meta.scale, r_meta.length, r_meta.csid, r_meta.csfrm, r_meta.schema, r_meta.name, r_meta.version, r_meta.attr_cnt ); /* || We can now begin to piece together our returning dataset. We create an || instance of ANYDATASET and then fetch the attributes off the DBMS_SQL || cursor using the metadata from the ANYTYPE. LONGs are converted to CLOBs... */ ANYDATASET.BeginCreate( DBMS_TYPES.TYPECODE_OBJECT, SELF.atype, rws ); rws.AddInstance(); rws.PieceWise(); FOR i IN 1 .. dla_pkg.r_sql.column_cnt LOOP r_meta.typecode := SELF.atype.GetAttrElemInfo( i, r_meta.precision, r_meta.scale, r_meta.length, r_meta.csid, r_meta.csfrm, r_meta.attr_type, r_meta.attr_name ); CASE r_meta.typecode --<>-- WHEN DBMS_TYPES.TYPECODE_VARCHAR2 THEN DBMS_SQL.COLUMN_VALUE( dla_pkg.r_sql.cursor, i, r_fetch.v2_column ); rws.SetVarchar2( r_fetch.v2_column ); --<>-- WHEN DBMS_TYPES.TYPECODE_NUMBER THEN DBMS_SQL.COLUMN_VALUE( dla_pkg.r_sql.cursor, i, r_fetch.num_column ); rws.SetNumber( r_fetch.num_column ); --<>-- WHEN DBMS_TYPES.TYPECODE_DATE THEN DBMS_SQL.COLUMN_VALUE( dla_pkg.r_sql.cursor, i, r_fetch.date_column ); rws.SetDate( r_fetch.date_column ); --<>-- WHEN DBMS_TYPES.TYPECODE_RAW THEN DBMS_SQL.COLUMN_VALUE_RAW( dla_pkg.r_sql.cursor, i, r_fetch.raw_column, r_fetch.raw_error, r_fetch.raw_length ); rws.SetRaw( r_fetch.raw_column ); --<>-- WHEN DBMS_TYPES.TYPECODE_INTERVAL_DS THEN DBMS_SQL.COLUMN_VALUE( dla_pkg.r_sql.cursor, i, r_fetch.ids_column ); rws.SetIntervalDS( r_fetch.ids_column ); --<>-- WHEN DBMS_TYPES.TYPECODE_INTERVAL_YM THEN DBMS_SQL.COLUMN_VALUE( dla_pkg.r_sql.cursor, i, r_fetch.iym_column ); rws.SetIntervalYM( r_fetch.iym_column ); --<>-- WHEN DBMS_TYPES.TYPECODE_TIMESTAMP THEN DBMS_SQL.COLUMN_VALUE( dla_pkg.r_sql.cursor, i, r_fetch.ts_column ); rws.SetTimestamp( r_fetch.ts_column ); --<>-- WHEN DBMS_TYPES.TYPECODE_TIMESTAMP_TZ THEN DBMS_SQL.COLUMN_VALUE( dla_pkg.r_sql.cursor, i, r_fetch.tstz_column ); rws.SetTimestampTZ( r_fetch.tstz_column ); --<>-- WHEN DBMS_TYPES.TYPECODE_TIMESTAMP_LTZ THEN DBMS_SQL.COLUMN_VALUE( dla_pkg.r_sql.cursor, i, r_fetch.tsltz_column ); rws.SetTimestamplTZ( r_fetch.tsltz_column ); --<>-- WHEN DBMS_TYPES.TYPECODE_CLOB THEN --<>-- CASE dla_pkg.r_sql.description(i).col_type WHEN 8 THEN LOOP DBMS_SQL.COLUMN_VALUE_LONG( dla_pkg.r_sql.cursor, i, 32767, r_fetch.cvl_offset, r_fetch.v2_column, r_fetch.cvl_length ); r_fetch.clob_column := r_fetch.clob_column || r_fetch.v2_column; r_fetch.cvl_offset := r_fetch.cvl_offset + 32767; EXIT WHEN r_fetch.cvl_length < 32767; END LOOP; ELSE DBMS_SQL.COLUMN_VALUE( dla_pkg.r_sql.cursor, i, r_fetch.clob_column ); END CASE; rws.SetClob( r_fetch.clob_column ); --<>-- END CASE; END LOOP; /* || Our ANYDATASET instance is complete. We end our create session... */ rws.EndCreate(); END IF; RETURN ODCIConst.Success; END; ------------------------------------------------------------------------------------ MEMBER FUNCTION ODCITableClose( SELF IN dla_ot ) RETURN NUMBER IS BEGIN DBMS_SQL.CLOSE_CURSOR( dla_pkg.r_sql.cursor ); dla_pkg.r_sql := NULL; RETURN ODCIConst.Success; END; END; / prompt Installing dla_pkg package body... CREATE PACKAGE BODY dla_pkg AS /* || --------------------------------------------------------------------------------- || || Name: dla_pkg || || Description: See package specification for details. || || License: MIT License || Copyright (c) 2007 Adrian Billington, www.oracle-developer.net || See https://github.com/oracle-developer/dla/blob/master/LICENSE || || --------------------------------------------------------------------------------- */ ----------------------------------------------------------------------------------- FUNCTION filter_is_valid( p_name IN VARCHAR2 ) RETURN BOOLEAN IS BEGIN RETURN (UPPER(p_name) IN ('OWNER', 'TABLE_NAME', 'VIEW_NAME', 'COLUMN_NAME','CONSTRAINT_NAME','TRIGGER_NAME', 'PARTITION_NAME','SUBPARTITION_NAME')); END filter_is_valid; ----------------------------------------------------------------------------------- PROCEDURE invalid_filter( p_name IN VARCHAR2 ) IS BEGIN RAISE_APPLICATION_ERROR( -20000, p_name || ' not a valid filter' ); END invalid_filter; ----------------------------------------------------------------------------------- PROCEDURE set_filter( p_name IN VARCHAR2, p_value IN VARCHAR2 ) IS BEGIN IF filter_is_valid(p_name) THEN DBMS_SESSION.SET_CONTEXT( 'dla_ctx', p_name, p_value ); ELSE invalid_filter(p_name); END IF; END set_filter; ----------------------------------------------------------------------------------- PROCEDURE clear_filter( p_name IN VARCHAR2 DEFAULT 'ALL' ) IS BEGIN IF UPPER(p_name) = 'ALL' THEN DBMS_SESSION.CLEAR_ALL_CONTEXT( 'dla_ctx' ); ELSIF filter_is_valid(p_name) THEN DBMS_SESSION.CLEAR_CONTEXT( 'dla_ctx', NULL, p_name ); ELSE invalid_filter(p_name); END IF; END clear_filter; ----------------------------------------------------------------------------------- FUNCTION show_filters RETURN dla_filter_ntt IS nt_filters dla_filter_ntt; BEGIN /* || Use SESSION_CONTEXT view rather than DBMS_SESSION.LIST_CONTEXT || in case other contexts are heavily used... */ SELECT dla_filter_ot(attribute, value) BULK COLLECT INTO nt_filters FROM session_context WHERE UPPER(namespace) = 'DLA_CTX'; RETURN nt_filters; END show_filters; ----------------------------------------------------------------------------------- END dla_pkg; / prompt Installing views... CREATE VIEW v_dba_constraints AS SELECT * FROM TABLE( dla_pkg.query_view( q'[select * from dba_constraints where ( owner = sys_context('dla_ctx','owner') or sys_context('dla_ctx','owner') is null ) and ( table_name = sys_context('dla_ctx','table_name') or sys_context('dla_ctx','table_name') is null ) and ( constraint_name = sys_context('dla_ctx','constraint_name') or sys_context('dla_ctx','constraint_name') is null )]' )); CREATE VIEW v_dba_tab_columns AS SELECT * FROM TABLE( dla_pkg.query_view( q'[select * from dba_tab_columns where ( owner = sys_context('dla_ctx','owner') or sys_context('dla_ctx','owner') is null ) and ( table_name = sys_context('dla_ctx','table_name') or sys_context('dla_ctx','table_name') is null ) and ( column_name = sys_context('dla_ctx','column_name') or sys_context('dla_ctx','column_name') is null )]' )); CREATE VIEW v_dba_tab_partitions AS SELECT * FROM TABLE( dla_pkg.query_view( q'[select * from dba_tab_partitions where ( table_owner = sys_context('dla_ctx','owner') or sys_context('dla_ctx','owner') is null ) and ( table_name = sys_context('dla_ctx','table_name') or sys_context('dla_ctx','table_name') is null ) and ( partition_name = sys_context('dla_ctx','partition_name') or sys_context('dla_ctx','partition_name') is null )]' )); CREATE VIEW v_dba_tab_subpartitions AS SELECT * FROM TABLE( dla_pkg.query_view( q'[select * from dba_tab_subpartitions where ( table_owner = sys_context('dla_ctx','owner') or sys_context('dla_ctx','owner') is null ) and ( table_name = sys_context('dla_ctx','table_name') or sys_context('dla_ctx','table_name') is null ) and ( partition_name = sys_context('dla_ctx','partition_name') or sys_context('dla_ctx','partition_name') is null ) and ( subpartition_name = sys_context('dla_ctx','subpartition_name') or sys_context('dla_ctx','subpartition_name') is null )]' )); CREATE VIEW v_dba_triggers AS SELECT * FROM TABLE( dla_pkg.query_view( q'[select * from dba_triggers where ( owner = sys_context('dla_ctx','owner') or sys_context('dla_ctx','owner') is null ) and ( table_name = sys_context('dla_ctx','table_name') or sys_context('dla_ctx','table_name') is null ) and ( trigger_name = sys_context('dla_ctx','trigger_name') or sys_context('dla_ctx','trigger_name') is null )]' )); CREATE VIEW v_dba_views AS SELECT * FROM TABLE( dla_pkg.query_view( q'[select * from dba_views where ( owner = sys_context('dla_ctx','owner') or sys_context('dla_ctx','owner') is null ) and ( view_name = sys_context('dla_ctx','view_name') or sys_context('dla_ctx','view_name') is null )]' )); prompt Installing synonyms and privileges... create or replace public synonym dla_pkg for dla_pkg; grant execute on dla_pkg to public; create or replace public synonym v_dba_constraints for v_dba_constraints; grant select on v_dba_constraints to public; create or replace public synonym v_dba_tab_columns for v_dba_tab_columns; grant select on v_dba_tab_columns to public; create or replace public synonym v_dba_tab_partitions for v_dba_tab_partitions; grant select on v_dba_tab_partitions to public; create or replace public synonym v_dba_tab_subpartitions for v_dba_tab_subpartitions; grant select on v_dba_tab_subpartitions to public; create or replace public synonym v_dba_triggers for v_dba_triggers; grant select on v_dba_triggers to public; create or replace public synonym v_dba_views for v_dba_views; grant select on v_dba_views to public; prompt prompt prompt ************************************************************************** prompt Installation complete. prompt **************************************************************************