<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>The Anti-Kyte</title>
	<atom:link href="http://mikesmithers.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://mikesmithers.wordpress.com</link>
	<description>Oracle - for when it was like that when you got there</description>
	<lastBuildDate>Thu, 23 May 2013 16:21:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='mikesmithers.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>The Anti-Kyte</title>
		<link>http://mikesmithers.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://mikesmithers.wordpress.com/osd.xml" title="The Anti-Kyte" />
	<atom:link rel='hub' href='http://mikesmithers.wordpress.com/?pushpress=hub'/>
		<item>
		<title>ORA-02030 and invisible objects. The database bites back !</title>
		<link>http://mikesmithers.wordpress.com/2013/05/02/ora-02030-and-invisible-objects-the-database-bites-back/</link>
		<comments>http://mikesmithers.wordpress.com/2013/05/02/ora-02030-and-invisible-objects-the-database-bites-back/#comments</comments>
		<pubDate>Thu, 02 May 2013 13:25:51 +0000</pubDate>
		<dc:creator>mikesmithers</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[grant select on v$ views]]></category>
		<category><![CDATA[ORA-02030]]></category>
		<category><![CDATA[synonyms]]></category>
		<category><![CDATA[v$fixed_table]]></category>
		<category><![CDATA[v$fixed_view_definition]]></category>
		<category><![CDATA[v$instance]]></category>
		<category><![CDATA[v_$instance]]></category>

		<guid isPermaLink="false">http://mikesmithers.wordpress.com/?p=2010</guid>
		<description><![CDATA[Being Luis Suarez&#8217;s agent must be an interesting job right now. Maybe the man was a bit peckish. Alternatively, maybe he&#8217;s resigned to the FA&#8217;s reluctance to introduce a mid-season break and was simply making his own arrangements for time off during the season. Either way, this particular agent may well be trying to sign [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=2010&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Being Luis Suarez&#8217;s agent must be an interesting job right now.<br />
Maybe the man was a bit peckish.<br />
Alternatively, maybe he&#8217;s resigned to the FA&#8217;s reluctance to introduce a mid-season break and was simply making his own arrangements for time off during the season.<br />
Either way, this particular agent may well be trying to sign Luis up for an ad campaign for a popular brand of toothpaste.</p>
<p>Oracle DBA&#8217;s may sometimes have some sympathy with Suarez, although they&#8217;re more likely to end up chewing the desk in frustration, rather than their fellow DBA&#8217;s (unless the Christmas Party has really gotten out of hand).<br />
Every so often, Oracle throws out an error that, on the face of it, makes absolutely no sense&#8230;<br />
<span id="more-2010"></span></p>
<h3>The user</h3>
<p>Let&#8217;s start by creating an ordinary, every-day user &#8211; not quite a dba :</p>
<pre class="brush: sql; title: ; notranslate">
GRANT connect, resource TO nqdba IDENTIFIED BY pwd;
</pre>
<p>At this point, as you&#8217;d expect, this user doesn&#8217;t have access to very much :</p>
<pre class="brush: sql; highlight: [7]; title: ; notranslate">
SQL&gt; desc dba_tables
ERROR:
ORA-04043: object &quot;SYS&quot;.&quot;DBA_TABLES&quot; does not exist

SQL&gt; desc v$instance
ERROR:
ORA-04043: object &quot;SYS&quot;.&quot;V_$INSTANCE&quot; does not exist
</pre>
<p>It&#8217;s probably worth noting that the public synonym is being referenced for V$INSTANCE.<br />
Although the describe is on V$INSTANCE, the error is about V_$INSTANCE. The relevance of this will become apparent shortly.</p>
<h3>Grant Select</h3>
<p>For now though, our hard-pressed DBA may decide to solve this problem for the user by doing the following :</p>
<pre class="brush: sql; title: ; notranslate">
GRANT SELECT ON dba_tables TO nqdba
/

Grant succeeded.

</pre>
<p>&#8230;and now for V$INSTANCE&#8230;</p>
<pre class="brush: sql; highlight: [4]; title: ; notranslate">
GRANT SELECT ON v$instance TO nqdba
                *
ERROR at line 1:
ORA-02030: can only select from fixed tables/views
</pre>
<p>That&#8217;s interesting, the grant on DBA_TABLES works no problem. However, V$INSTANCE is having none of it.<br />
Also, the error is on V$INSTANCE &#8211; i.e. the synonym, rather than V_$INSTANCE, the underlying object.<br />
I wonder if there&#8217;s an object other than the synonym with this name &#8230;</p>
<pre class="brush: sql; title: ; notranslate">
SQL&gt; SELECT owner, object_type
  2  FROM dba_objects
  3  WHERE object_name = 'V$INSTANCE' 
  4  /

OWNER			       OBJECT_TYPE
------------------------------ -------------------
PUBLIC			       SYNONYM

SQL&gt; 
</pre>
<p>So, there&#8217;s apparently nothing apart from the synonym.<br />
To eliminate the synonym as the cause of our problem, let&#8217;s try the following :</p>
<pre class="brush: sql; highlight: [6]; title: ; notranslate">
CREATE PUBLIC SYNONYM sparkly_white FOR v$instance
/
GRANT SELECT ON sparkly_white TO nqdba
/

Grant succeeded.

SQL&gt;
</pre>
<p>So, granting via a synonym that&#8217;s NOT V$INSTANCE works fine. Therefore, there must be an object owned by SYS that is also called V$INSTANCE. </p>
<h3>Them Dynamically Fixed thingys</h3>
<p>The error states that we can only select from &#8220;fixed tables/views&#8221;. The syntax here is interesting.<br />
V$ views are more properly referred to as Dynamic Performance Views. These views are based on what are known as fixed tables. These tables are essentially representations of C structs deep in the Oracle Kernel. </p>
<p>Let&#8217;s see what the V_$INSTANCE view is actually based on&#8230;</p>
<pre class="brush: sql; title: ; notranslate">
set long 5000
SELECT text
FROM dba_views
WHERE owner = 'SYS'
AND view_name = 'V_$INSTANCE';
</pre>
<p>&#8230;run this and we get&#8230;</p>
<pre class="brush: sql; highlight: [7]; title: ; notranslate">
select &quot;INSTANCE_NUMBER&quot;,&quot;INSTANCE_NAME&quot;,&quot;HOST_NAME&quot;,
   &quot;VERSION&quot;,&quot;STARTUP_TIME&quot;,&quot;STATUS&quot;,
    &quot;PARALLEL&quot;,&quot;THREAD#&quot;,&quot;ARCHIVER&quot;,
    &quot;LOG_SWITCH_WAIT&quot;,&quot;LOGINS&quot;,&quot;SHUTDOWN_PENDING&quot;,
    &quot;DATABASE_STATUS&quot;,&quot;INSTANCE_ROLE&quot;,&quot;ACTIVE_STATE&quot;,
    &quot;BLOCKED&quot;,&quot;EDITION&quot; 
from v$instance
</pre>
<p>which is extremely confusing. The view is apparently pointing back to the synonym ( which after all, is the only object that we can find with that name in DBA_OBJECTS).</p>
<p>At this point, we give up on the conventional data dictionary views and dive into the twighlight world of V$FIXED_VIEW_DEFINITION. We should find the true view statement here, with luck&#8230;</p>
<pre class="brush: sql; title: ; notranslate">
SELECT  view_definition
FROM v$fixed_view_definition
WHERE view_name = 'V$INSTANCE'
/
</pre>
<p>Finally, we can see that there is actually an object called v$instance apart from the synonym, although this query yields the scarcely-more-helfpul&#8230;</p>
<pre class="brush: sql; highlight: [7]; title: ; notranslate">
SELECT INSTANCE_NUMBER , INSTANCE_NAME , HOST_NAME , 
    VERSION , STARTUP_TIME , STATUS , 
    PARALLEL , THREAD# , ARCHIVER , 
    LOG_SWITCH_WAIT , LOGINS , SHUTDOWN_PENDING, 
    DATABASE_STATUS, INSTANCE_ROLE, ACTIVE_STATE, 
    BLOCKED, EDITION 
FROM GV$INSTANCE 
WHERE inst_id = USERENV('Instance')
</pre>
<p>If we now perform the same check to find out what GV$INSTANCE is pointing at, the results are a bit more revealing :</p>
<pre class="brush: sql; highlight: [15]; title: ; wrap-lines: false; notranslate">
select ks.inst_id,ksuxsins,ksuxssid,
    ksuxshst,ksuxsver,ksuxstim,
    decode(ksuxssts,0,'STARTED',1,'MOUNTED',2,'OPEN',3,'OPEN MIGRATE','UNKNOWN'),
    decode(ksuxsshr,0,'NO',1,'YES',2,NULL),ksuxsthr,
    decode(ksuxsarc,0,'STOPPED',1,'STARTED','FAILED'),
    decode(ksuxslsw,0,NULL,2,'ARCHIVE LOG',3,'CLEAR LOG',4,
    'CHECKPOINT', 5,'REDO GENERATION'),
    decode(ksuxsdba,0,'ALLOWED','RESTRICTED'),
    decode(ksuxsshp,0,'NO','YES'),
    decode(kvitval,0,'ACTIVE',2147483647,'SUSPENDED','INSTANCE RECOVERY'),
    decode(ksuxsrol,1,'PRIMARY_INSTANCE',2,'SECONDARY_INSTANCE','UNKNOWN'), 
    decode(qui_state,0,'NORMAL',1,'QUIESCING',2,'QUIESCED','UNKNOWN'), 
    decode(bitand(ksuxsdst, 1), 0, 'NO', 1, 'YES', 'NO'), 
    decode(ksuxsedition, 1, 'PO', 2, 'SE', 4, 'EE', 8,'XE', 'UNKNOWN') 
from x$ksuxsinst ks, x$kvit kv, x$quiesce qu 
where kvittag = 'kcbwst'
</pre>
<p>Finally, we can see that V$INSTANCE is ultimately referencing fixed tables.</p>
<h3>The solution</h3>
<p>The solution to this problem is simple enough&#8230;well, simple enough when you know it. Simply grant the privilege on the underlying view. So&#8230;</p>
<pre class="brush: sql; highlight: [1]; title: ; notranslate">
GRANT SELECT ON v_$instance TO nqba
/

Grant succeeded.
</pre>
<h3>V$FIXED_TABLE</h3>
<p>At this point you may be thinking that it would be really useful if there was a list of those dynamic/fixed view thingys available. Well, as you&#8217;re a proper DBA, you probably wouldn&#8217;t use the term thingys, but I know where you&#8217;re coming from&#8230;</p>
<pre class="brush: sql; title: ; notranslate">
SELECT name, type
FROM v$fixed_table
WHERE name = 'V$INSTANCE'
/
</pre>
<p>There you go. If you&#8217;re trying to grant select on any of the tables listed in V$FIXED_TABLE, you&#8217;ll more than likely hit this particular error. Additonally, if the table is listed here, it means that you should be able to still see it even if the database itself is not opened.</p>
<p>To demonstrate, connect to an idle instance. If you&#8217;re running XE, simply shutdown the database then issue the following command at the prompt :</p>
<pre class="brush: bash; title: ; notranslate">
sqlplus /nolog
</pre>
<p>This will enable the prompt but you won&#8217;t be connected to the database. To connect :</p>
<pre class="brush: bash; title: ; notranslate">
conn sys as sysdba
</pre>
<p>&#8230; and supply the password when prompted.<br />
You will now get the message :</p>
<pre class="brush: plain; title: ; notranslate">
Connected to an idle instance
</pre>
<p>NOTE &#8211; an alternative way to do this on linux would be to switch to the oracle owner  :</p>
<pre class="brush: bash; title: ; notranslate">
sudo su oracle
sqlplus / as sysdba
</pre>
<p>So, you&#8217;re connected to an idle instance. It hasn&#8217;t just been banned for 10 matches for being a bit bitey, it&#8217;s idle because it&#8217;s not been started.<br />
Now mount the database ( at this point it will still not be properly started &#8211; i.e. started and open) :</p>
<pre class="brush: plain; title: ; notranslate">
startup mount
</pre>
<p>Now we can see that the database is not currently mounted, after all, you can&#8217;t query anything&#8230;</p>
<pre class="brush: sql; highlight: [4]; title: ; notranslate">
SELECT * FROM dba_tables
              *
ERROR at line 1:
ORA-01219: database not open: queries allowed on fixed tables/views only


SQL&gt; 
</pre>
<p>&#8230;except for&#8230;</p>
<pre class="brush: sql; title: ; notranslate">
SQL&gt; SELECT instance_name, status
  2  FROM v$instance;

INSTANCE_NAME	 STATUS
---------------- ------------
XE		 MOUNTED

SQL&gt; 
</pre>
<p>Just as useful, you can still see V$FIXED_TABLE when the database is mounted ( or unmounted for that matter), so you can always check to see which tables you can query.</p>
<p>Incidentally, once you&#8217;ve finished playing, you can either shutdown the database again :</p>
<pre class="brush: plain; title: ; notranslate">
shutdown
</pre>
<p>&#8230;or open it&#8230;</p>
<pre class="brush: plain; title: ; notranslate">
ALTER DATABASE OPEN
/
</pre>
<p>Deb has expressed her utter bafflement as to why a footballer would bite a fellow player. Then again, that&#8217;s not too surprising&#8230;she is a vegitarian after all.</p>
<br />Filed under: <a href='http://mikesmithers.wordpress.com/category/oracle/'>Oracle</a>, <a href='http://mikesmithers.wordpress.com/category/sql/'>SQL</a> Tagged: <a href='http://mikesmithers.wordpress.com/tag/grant-select-on-v-views/'>grant select on v$ views</a>, <a href='http://mikesmithers.wordpress.com/tag/ora-02030/'>ORA-02030</a>, <a href='http://mikesmithers.wordpress.com/tag/synonyms/'>synonyms</a>, <a href='http://mikesmithers.wordpress.com/tag/vfixed_table/'>v$fixed_table</a>, <a href='http://mikesmithers.wordpress.com/tag/vfixed_view_definition/'>v$fixed_view_definition</a>, <a href='http://mikesmithers.wordpress.com/tag/vinstance/'>v$instance</a>, <a href='http://mikesmithers.wordpress.com/tag/v_instance/'>v_$instance</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=2010&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mikesmithers.wordpress.com/2013/05/02/ora-02030-and-invisible-objects-the-database-bites-back/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3cb0956016bbad280193fbbd8e649b9?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Mike S</media:title>
		</media:content>
	</item>
		<item>
		<title>Customising the Oracle XE Menu in XFCE &#8211; why it&#8217;s better to be vegetarian</title>
		<link>http://mikesmithers.wordpress.com/2013/04/13/customising-the-oracle-xe-menu-in-xfce-why-its-better-to-be-vegetarian/</link>
		<comments>http://mikesmithers.wordpress.com/2013/04/13/customising-the-oracle-xe-menu-in-xfce-why-its-better-to-be-vegetarian/#comments</comments>
		<pubDate>Sat, 13 Apr 2013 14:56:23 +0000</pubDate>
		<dc:creator>mikesmithers</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[bash for loop]]></category>
		<category><![CDATA[desktop files]]></category>
		<category><![CDATA[directory files]]></category>
		<category><![CDATA[oracle xe on xfce mint]]></category>
		<category><![CDATA[xfce]]></category>
		<category><![CDATA[xfce-applications.menu]]></category>

		<guid isPermaLink="false">http://mikesmithers.wordpress.com/?p=1981</guid>
		<description><![CDATA[Roberto Goldbrick. The name of the central character in a biting satire about a Premiership footballer ? Actually, it&#8217;s the name of the horse I drew out in the Office Grand National Sweep Stake. &#8220;Oh well&#8221;, said Deb as the winner crossed the line with Roberto nowhere to be seen, &#8220;by next week it&#8217;ll be [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=1981&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Roberto Goldbrick. The name of the central character in a biting satire about a Premiership footballer ? Actually, it&#8217;s the name of the horse I drew out in the Office Grand National Sweep Stake.</p>
<p>&#8220;Oh well&#8221;, said Deb as the winner crossed the line with Roberto nowhere to be seen, &#8220;by next week it&#8217;ll be a value frozen lasagne&#8221;.<br />
That&#8217;s the thing about vegetarians, they do like to assert their moral superiority at times. It can be quite difficult to find a suitable riposte. After all, you feel a bit of a twit accusing someone of vegicide.</p>
<p>In order to overcome my disappointment, I&#8217;ve taken refuge in Mint 14 XFCE running on my netbook.</p>
<p>Using the steps <a href="http://wp.me/pweWl-ja">here</a> and <a href="http://wp.me/pweWl-oa">here</a>  I&#8217;ve managed to install Oracle 11gXE without any problems&#8230;.apart from the fact that the Menu items now appear on the Others menu.<br />
Being a lightweight desktop, XFCE doesn&#8217;t provide a default GUI to enable menu editing, so I&#8217;ve had to do a bit of investigation&#8230;<br />
<span id="more-1981"></span></p>
<h3>XFCE Menu files</h3>
<p>In order to get my Oracle Menu, together with the correct entries, there are three types of file I need to deal with.</p>
<h4>desktop files</h4>
<p>Each menu item has it&#8217;s own .desktop file. These can be found in /usr/share/applications.<br />
To see all the files that were created as part of the XE installation:</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/share/applications
ls oracle*.desktop
</pre>
<p>You should see&#8230;</p>
<pre class="brush: plain; title: ; notranslate">
oraclexe-backup.desktop             oraclexe-registerforonlineforum.desktop
oraclexe-getstarted.desktop         oraclexe-restore.desktop
oraclexe-gettingstarted.desktop     oraclexe-runsql.desktop
oraclexe-gotoonlineforum.desktop    oraclexe-startdb.desktop
oraclexe-readdocumentation.desktop  oraclexe-stopdb.desktop
</pre>
<p>If we have a look at the contents of the oraclexe-startdb.desktop file :</p>
<pre class="brush: bash; title: ; notranslate">
[Desktop Entry]
Exec=/u01/app/oracle/product/11.2.0/xe/config/scripts/startdb.sh
Terminal=false
MultipleArgs=true
Type=Application
Categories=Applications;
Icon=oraclexe-startdatabase.png
MimeType=Application/database
Encoding=UTF-8
Name=Start Database
Name[pt_BR]=Iniciar Banco de Dados
Name[ja]=データベースの起動
Name[zh_CN]=启动数据库
</pre>
<p>Most of that is fairly straight forward. The file details the script that should be executed, whether a Terminal should be opened, the icon to display on the menu etc.<br />
The menu it needs to appear on? That&#8217;s a different story.</p>
<h4>Directory Files</h4>
<p>These files act as containers for the .desktop files within the Menu structure. They should all be in /usr/share/desktop-directories.<br />
The Oracle menu however, has been created in /usr/share/desktop-menu-files.<br />
Before we start moving it around, it&#8217;s probably worth having a look at it&#8217;s contents (the filename is oraclexe-11g.directory):</p>
<pre class="brush: bash; title: ; notranslate">
[Desktop Entry]
Icon=oraclexe-11g.png
Type=Directory
Encoding=UTF-8

Name=Oracle Database 11g Express Edition
Name[pt_BR]=Oracle Database 11g Express Edition
Name[ja]=Oracle Database 11g Express Edition
Name[zh_CN]=Oracle Database 11g Express Edition
</pre>
<p>On it&#8217;s own, it doesn&#8217;t really move the story on much, save for the fact that it is defined as being of type Directory.</p>
<p>Finally, however, we get to the heart of the menu system.</p>
<h4>The Menu file</h4>
<p>The file /usr/share/xfcemint/xfce-applications.menu is where all of the magic happens. This is an XML file which controls the contents of the Menu itself. Let&#8217;s take a look at the definition for the System menu :</p>
<pre class="brush: xml; title: ; wrap-lines: false; notranslate">
    &lt;Menu&gt;
        &lt;Name&gt;System&lt;/Name&gt;
        &lt;Directory&gt;xfce-system.directory&lt;/Directory&gt;
        &lt;Include&gt;
            &lt;Or&gt;
                &lt;Category&gt;Emulator&lt;/Category&gt;
                &lt;Category&gt;System&lt;/Category&gt;
            &lt;/Or&gt;
        &lt;/Include&gt;
        &lt;Exclude&gt;
            &lt;Or&gt;
                &lt;Filename&gt;Thunar.desktop&lt;/Filename&gt;
                &lt;Filename&gt;xfce4-session-logout.desktop&lt;/Filename&gt;
            &lt;/Or&gt;
        &lt;/Exclude&gt;
    &lt;/Menu&gt;
</pre>
<p>We can see that the entry references the appropriate .directory file.<br />
We can also see that the menu can include either categories of .desktop files or specifically named files.<br />
OK, so in this case, the named files are specifically excluded from the menu, but the principle should be sound.</p>
<h3>Getting the Oracle Menu</h3>
<p>There would appear to be two ways to do this. The first is to specify the files to include on the menu explicitly. The second is to edit the .desktop files to specify a category which we can then include in the Oracle menu by means of the  tags in the .desktop and .menu files.<br />
Either way, the first thing we need to do is to copy the oracle .directory file to the correct location :</p>
<pre class="brush: bash; title: ; notranslate">
sudo cp /usr/share/desktop-menu-files/oraclexe-11g.directory /usr/share/desktop-directories/.
</pre>
<h4>Option 1 &#8211; specify the files</h4>
<p>We now need to add an entry into the xfce-applications.menu. OK, strictly speaking, we now need to backup the xfce-applications.menu file, just in case our XML skills aren&#8217;t quite as good as we thought they were :</p>
<pre class="brush: bash; title: ; notranslate">
sudo cp /usr/share/xfcemint/xfce-applications.menu xfce-applications.bak
</pre>
<p>Now, let&#8217;s add in the Oracle menu :</p>
<pre class="brush: bash; title: ; wrap-lines: false; notranslate">
    &lt;Menu&gt;
        &lt;Name&gt;Oracle Database 11g Express Edition&lt;/Name&gt;
        &lt;Directory&gt;oraclexe-11g.directory&lt;/Directory&gt;
        &lt;Include&gt;
           &lt;Filename&gt;oraclexe-startdb.desktop&lt;/Filename&gt;
           &lt;Filename&gt;oraclexe-stopdb.desktop&lt;/Filename&gt;
           &lt;Filename&gt;oraclexe-runsql.desktop&lt;/Filename&gt;
           &lt;Filename&gt;oraclexe-backup.desktop&lt;/Filename&gt;
           &lt;Filename&gt;oraclexe-restore.desktop&lt;/Filename&gt;
           &lt;Filename&gt;oraclexe-gettingstarted.desktop&lt;/Filename&gt;
           &lt;Filename&gt;oraclexe-readdocumentation.desktop&lt;/Filename&gt;
           &lt;Filename&gt;oraclexe-registerforonlineforum.desktop&lt;/Filename&gt;
           &lt;Filename&gt;oraclexe-gotoonlineforum.desktop&lt;/Filename&gt;
           &lt;Filename&gt;oraclexe-getstarted.desktop&lt;/Filename&gt;
        &lt;/Include&gt;

    &lt;/Menu&gt;
</pre>
<p>NOTE &#8211; I added this above the entry for the Others menu, which seems to be a catch-all for anything that doesn&#8217;t fit in any of the menus previously defined in the file.</p>
<p>Save the change, now go back to the desktop and fire up the Menu&#8230;</p>
<p><a href="http://mikesmithers.files.wordpress.com/2013/04/ora_menu.png"><img src="http://mikesmithers.files.wordpress.com/2013/04/ora_menu.png?w=450&#038;h=263" alt="ora_menu" width="450" height="263" class="alignnone size-full wp-image-1984" /></a></p>
<h4>Option 2 &#8211; Use a category</h4>
<p>Well, that seemed to work quite well. However, if we wanted to add another item to the menu, we would need to go and edit xfce-applications.menu all over again.<br />
A more dynamic approach would be to use a Category. This would mean that any new .desktop files of the appropriate category would automatically be included.<br />
To do this, we&#8217;ll need to add the category to both our existing desktop files and to the menu definition in xfce-applications.menu.<br />
Let&#8217;s call the category XE.</p>
<p>First of all, we need to change the appropriate desktop files. Time for a small script&#8230;save_category.sh</p>
<pre class="brush: bash; title: ; wrap-lines: false; notranslate">
#!/bin/sh
#
# Script to add a category to all of the oracle .desktop files
#
for dtfile in $(ls /usr/share/applications/oraclexe-*.desktop)
do
	cp $dtfile $dtfile.bak
	sed -i 's/Categories=Applications;/Categories=Applications;XE/' $dtfile
done
exit 0

</pre>
<p>We need to run this using sudo as we don&#8217;t have permissions on these files&#8230;</p>
<pre class="brush: bash; title: ; notranslate">
sudo sh change_category.sh
</pre>
<p>If we have a look at the .desktop files now, we should see that the category tag has been changed and the category XE added :</p>
<pre class="brush: bash; highlight: [6]; title: ; wrap-lines: false; notranslate">
[Desktop Entry]
Exec=/u01/app/oracle/product/11.2.0/xe/config/scripts/startdb.sh
Terminal=false
MultipleArgs=true
Type=Application
Categories=Applications;XE
Icon=oraclexe-startdatabase.png
MimeType=Application/database
Encoding=UTF-8
Name=Start Database
Name[pt_BR]=Iniciar Banco de Dados
Name[ja]=データベースの起動
Name[zh_CN]=启动数据库
</pre>
<p>Now we need to go back to the menu and replace the hard-coded filenames with the new category :</p>
<pre class="brush: bash; highlight: [5]; title: ; notranslate">
   &lt;Menu&gt;
        &lt;Name&gt;Oracle Database 11g Express Edition&lt;/Name&gt;
        &lt;Directory&gt;oraclexe-11g.directory&lt;/Directory&gt;
        &lt;Include&gt;
           &lt;Category&gt;XE&lt;/Category&gt;
        &lt;/Include&gt;

    &lt;/Menu&gt;
</pre>
<p>Now, when we hit the big shiny menu button&#8230;you get exactly the same result.<br />
If you want to do more than just get your Oracle XE stuff onto the menu, there&#8217;s a really useful <a href="wiki.xfce.org/howto/customize-menu">howto on the XFCE wiki</a>.</p>
<p>As for me, domestic drudgery calls. Looks like I&#8217;m going to have to ruthlessly skin some defenceless potatoes.</p>
<br />Filed under: <a href='http://mikesmithers.wordpress.com/category/linux-2/'>Linux</a> Tagged: <a href='http://mikesmithers.wordpress.com/tag/bash-for-loop/'>bash for loop</a>, <a href='http://mikesmithers.wordpress.com/tag/desktop-files/'>desktop files</a>, <a href='http://mikesmithers.wordpress.com/tag/directory-files/'>directory files</a>, <a href='http://mikesmithers.wordpress.com/tag/oracle-xe-on-xfce-mint/'>oracle xe on xfce mint</a>, <a href='http://mikesmithers.wordpress.com/tag/xfce/'>xfce</a>, <a href='http://mikesmithers.wordpress.com/tag/xfce-applications-menu/'>xfce-applications.menu</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=1981&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mikesmithers.wordpress.com/2013/04/13/customising-the-oracle-xe-menu-in-xfce-why-its-better-to-be-vegetarian/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3cb0956016bbad280193fbbd8e649b9?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Mike S</media:title>
		</media:content>

		<media:content url="http://mikesmithers.files.wordpress.com/2013/04/ora_menu.png" medium="image">
			<media:title type="html">ora_menu</media:title>
		</media:content>
	</item>
		<item>
		<title>Facial Hair and Funky Job Titles – A Personal History of the Internet Age</title>
		<link>http://mikesmithers.wordpress.com/2013/04/06/facial-hair-and-funky-job-titles-a-personal-history-of-the-internet-age/</link>
		<comments>http://mikesmithers.wordpress.com/2013/04/06/facial-hair-and-funky-job-titles-a-personal-history-of-the-internet-age/#comments</comments>
		<pubDate>Sat, 06 Apr 2013 16:26:20 +0000</pubDate>
		<dc:creator>mikesmithers</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Bob Miner]]></category>
		<category><![CDATA[c programming language]]></category>
		<category><![CDATA[GNU Linux]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[http]]></category>

		<guid isPermaLink="false">http://mikesmithers.wordpress.com/?p=1968</guid>
		<description><![CDATA[I had a rare technical issue with my blog recently. My e-mailed cry for help was answered and my problem resolved. The helpful soul at WordPress who aided me in my time of need was Jackie, who rejoices in the title of Hapiness Engineer. I&#8217;d imagine that WordPress must have a novel and somewhat refreshing [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=1968&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>I had a rare technical issue with my blog recently. My e-mailed cry for help was answered and my problem resolved. The helpful soul at WordPress who aided me in my time of need was Jackie, who rejoices in the title of Hapiness Engineer.</p>
<p>I&#8217;d imagine that WordPress must have a novel and somewhat refreshing approach to Job titles.<br />
We could apply this to Deb, for example. As a Health Professional working with the under fives, she could be a Small Human Maintenance Consultant.</p>
<p>There are some similarities between Deb&#8217;s job and my own. Whilst I have on occasion dealt with people whose job titles include words like &#8216;Chief&#8217; and &#8216;Officer&#8217;, I also occasionally have to deal with the aftermath of toys being violently ejected from prams.</p>
<p>At the moment however, I find myself leading a team, all of whom are rather younger than me. This presents a number of challenges.</p>
<p>The realisation that I have children that are older than some of my colleagues is particularly acute when we discuss technological issues.<br />
In computing terms, I grew up before the Internet was the all-pervasive presence it is now.<br />
I learned to touch-type many years ago, in order to reduce the number of typos I made whilst writing code.<br />
This is beginning to feel somewhat quaint with the proliferation of declarative development environments and technologies.</p>
<p>I suppose the point of this post is to wander back through the technologies that influenced my career as a programmer and explain why they are so important in shaping the technological landscape we now operate in.<br />
<span id="more-1968"></span></p>
<h3>The C Programming Language</h3>
<p>Working at Bell Labs in the early 70s must&#8217;ve been something special. Whilst not chronologically first on my list, the C language takes it&#8217;s place in the pantheon.<br />
40 years on, <a href="https://en.wikipedia.org/wiki/Dennis_Ritchie">Dennis Ritchie</a>&#8216;s masterpiece, comprising a mere 32 keywords, has provided the basis for most of the mainstream languages that have followed ( C++, Java, C#, take your pick).<br />
Providing a viable alternative to Assembler meant that C was portable. Provided you could write a compiler for the hardware you wanted to use, you could run C programs on it.<br />
Not content with that, <a href="https://en.wikipedia.org/wiki/Brian_Kernighan">Kernaghan</a> and Ritchie then produced the seminal C Programming Language manual.<br />
Not only did this introduce the world to the much imitated “hello world” program, it served as a de-facto standards reference for the language into the 1990s.</p>
<p>C may no longer be what all the cool kids are using, but it&#8217;s influence is still all pervasive. To take a not entirely random example&#8230;</p>
<h3>Unix</h3>
<p>Whilst it slightly pre-dates C, <a href="https://en.wikipedia.org/wiki/Ken_Thompson">Ken Thompson</a>&#8216;s Unix got it&#8217;s big break when re-written in the language in the early 70s.<br />
This made it as portable as C itself, thus opening the way for a move away from mainframes and onto more affordable hardware.<br />
Today Unix, in all it&#8217;s variations, remains the dominant operating system in the datacentre.<br />
The multi-user, multi-tasking OS is on the back-end of a large chunk of the World Wide Web.<br />
For me, it was the first OS that I really got to grips with. The diversity of tools and flexibility of being able to write utility scripts quickly and simply is still a joy&#8230;especially to anyone who has been subjected to DOS (and later Windows) batch scripting.</p>
<p>At this point it&#8217;s worth stopping for a moment and considering that Ritchie, Thompson and Kernaghan were all colleagues at Bell Labs. As Dream Team&#8217;s go, this is the programming equivalent of having Pele, Cruyff and Maradona playing up front (but with less arguing over who takes the free-kicks).</p>
<p>A major reason for Unix&#8217;s current ubiquity is&#8230;.</p>
<h3>GNU/Linux</h3>
<p><a href="https://en.wikipedia.org/wiki/Linus_torvalds">Linus Torvalds </a>had developed a version of unix that would run on standard PC hardware, but had no tools written for it.<br />
<a href="https://en.wikipedia.org/wiki/Richard_stallman">Richard Stallman</a>&#8216;s GNU project had a set of tools in need of an Operating System to run on.<br />
Put the two together and&#8230;.<br />
Linux is now the OS of choice in a sizeable percentage of the world&#8217;s Server rooms.<br />
There&#8217;s also a better than even chance that Linux is at the heart of your smart-phone.<br />
In the same way that Unix opened up the choice of hardware for servers, Linux paved the way for running Enterprise class servers on much cheaper kit than had hitherto been available.</p>
<p>The other significant contribution that Linux has made to computing history is that is has served as the platform that really kick-started and then sustained the open source movement.<br />
The advent of the “gift economy” where code is developed and made available freely, has resulted in some of the best software available over the last 20 years.</p>
<p>Meanwhile, somewhere in Switzerland&#8230;.</p>
<h3>HTML and HTTP</h3>
<p>Perhaps the most profound example of building on pre-existing technology to create something truly life changing can be found in the work of <a href="https://en.wikipedia.org/wiki/Tim_Berners-Lee">Tim Berners-Lee</a>.<br />
Take SGML – the root of all Markup Languages and use it to create a means of linking between documents.<br />
To serve the HTML pages, write an extension to the File Transfer Protocol (FTP).<br />
Put them together and …. long before the Large Hadron Collider was commissioned CERN was itself the source of a Big Bang.</p>
<h3>The Relational Database</h3>
<p>You knew we&#8217;d get here eventually.<br />
When Oracle version 2.0 was released onto the market in 1979, it became what is commonly credited as the first commercially available relational database.<br />
<a href="https://en.wikipedia.org/wiki/Larry_Ellison">Larry Ellison</a> and friends were onto a winner.<br />
Fast forward through the introduction of PL/SQL ( in Forms 3.0 in 1988) and data driven web applications (powered by a selection of RDBMS&#8217;s) and Oracle is now busy trying to take over the world.<br />
In the meantime, it&#8217;s given me a platform on which to make a career. So, in this list at least ( i.e. my list), it certainly deserves it&#8217;s place.<br />
You can find a timeline of the <a href="http://oracle.com.edgesuite.net/timeline/oracle/">company&#8217;s history on their website</a>.</p>
<p>Incidentally, whilst reading up on the history of Oracle, I came across the name of <a href="http://en.wikipedia.org/wiki/Bob_Miner">Bob Miner</a> – Oracle&#8217;s lead engineer in it&#8217;s early days.<br />
Obviously a brilliant software engineer (he&#8217;s credited with writing most of Oracle 3), Miner was also renound for looking after the people he managed.<br />
In his Wikipedia entry, Larry Ellison is quoted as saying that Miner was “loyal to the people before the company”.</p>
<p>Wouldn&#8217;t you like to work for someone like that ?</p>
<p>The book case that Deb has ordered is just being delivered. Time for me to end my wander down memory lane and return to my role as Furniture Assembly Drone and Feng Shue Vision Implementer ( Deb has the vision and I just move the furniture around).</p>
<br />Filed under: <a href='http://mikesmithers.wordpress.com/category/uncategorized/'>Uncategorized</a> Tagged: <a href='http://mikesmithers.wordpress.com/tag/bob-miner/'>Bob Miner</a>, <a href='http://mikesmithers.wordpress.com/tag/c-programming-language/'>c programming language</a>, <a href='http://mikesmithers.wordpress.com/tag/gnu-linux/'>GNU Linux</a>, <a href='http://mikesmithers.wordpress.com/tag/html/'>html</a>, <a href='http://mikesmithers.wordpress.com/tag/http/'>http</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=1968&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mikesmithers.wordpress.com/2013/04/06/facial-hair-and-funky-job-titles-a-personal-history-of-the-internet-age/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3cb0956016bbad280193fbbd8e649b9?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Mike S</media:title>
		</media:content>
	</item>
		<item>
		<title>How long is a (piece of) String. Cricketing Greats and the length function</title>
		<link>http://mikesmithers.wordpress.com/2013/03/23/how-long-is-a-piece-of-string-cricketing-greats-and-the-length-function/</link>
		<comments>http://mikesmithers.wordpress.com/2013/03/23/how-long-is-a-piece-of-string-cricketing-greats-and-the-length-function/#comments</comments>
		<pubDate>Sat, 23 Mar 2013 20:03:10 +0000</pubDate>
		<dc:creator>mikesmithers</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[length]]></category>
		<category><![CDATA[NVL]]></category>

		<guid isPermaLink="false">http://mikesmithers.wordpress.com/?p=1944</guid>
		<description><![CDATA[My Dad gave me a book recently – the 100 Greatest Cricketers. As well as selecting what – in his opinion at least – were the 100 finest exponents of the game, the author also decided to rank them in order from 1 to 100. At this point, for those who don&#8217;t know, I should [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=1944&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>My Dad gave me a book recently – the 100 Greatest Cricketers. As well as selecting what – in his opinion at least – were the 100 finest exponents of the game, the author also decided to rank them in order from 1 to 100.<br />
At this point, for those who don&#8217;t know, I should perhaps explain that Cricket is one of those games given by the English to the rest of the world&#8230;.to prove what sporting losers the English could be.<br />
For any Australians reading, to whom this statement may ring hollow given their teams current travails, fret not. Historically, England&#8217;s brief ascendancy the battle for the Ashes tends to come to a juddering halt when least expected, usually in the form of a 4-0 thrashing ( think 1958-59, 1989).</p>
<p>Anyway, back to the book. Comparing players across different eras is hard enough – just how would you evaluate the relative merits of Sachin Tendulkar and Sir Jack Hobbs, for example ?<br />
But comparing the relative merits of a batsmen and bowler who were contemporaries in the same team is equally problematic. Who is the greater cricketer out of Dennis Lillee and Greg Chappell, or Malcolm Marshall and Viv Richards ?</p>
<p>All of this brings to mind the saying, “how long is a piece of string”.<br />
In SQL, at least, we do have an answer to this question&#8230;or do we ? <span id="more-1944"></span></p>
<h3>The LENGTH function</h3>
<p>Simple enough really, if you want to know the length of a string, you just need to do something like this (Fred Trueman would approve):</p>
<pre class="brush: sql; title: ; notranslate">
SELECT LENGTH('line') 
FROM dual;
</pre>
<p>All as expected. Obviously, if the string you pass in is NULL, then LENGTH will return 0&#8230;or will it ? </p>
<p>Time for a cricketing themed example&#8230;</p>
<pre class="brush: plain; title: ; notranslate">
CREATE TABLE greats( 
    first_name VARCHAR2(50), 
    last_name VARCHAR2(50), 
    sobriquet VARCHAR2(100)) 
/ 

INSERT INTO greats( first_name, last_name, sobriquet) 
VALUES( 'SACHIN', 'TENDULKAR', 'Little Master') 
/ 

INSERT INTO greats( first_name, last_name, sobriquet) 
VALUES( 'JACK', 'HOBBS', 'The Master') 
/ 

INSERT INTO greats( first_name, last_name, sobriquet) 
VALUES('RAHUL', 'DRAVID', 'The Wall') 
/ 
 
INSERT INTO greats( first_name, last_name, sobriquet) 
VALUES('VICTOR', 'TRUMPER', NULL) 
/ 

INSERT INTO greats( first_name, last_name, sobriquet)
VALUES('DONALD', 'BRADMAN', 'The Don')
/

INSERT INTO greats( first_name, last_name, sobriquet)
VALUES('FREDERICK', 'SPOFFORTH', 'The Demon')
/
COMMIT;
</pre>
<p>Not quite sure why Victor Trumper never got his own nickname. By all accounts he was a modest man, but a genius of a cricketer&#8230;.rather like a lot of the other players in our table. Anyway, this does at least give us the chance to observe what happens when we do this :</p>
<pre class="brush: sql; highlight: [9]; title: ; notranslate">
SQL&gt; SELECT last_name, LENGTH(sobriquet) 
  2  FROM greats; 

LAST_NAME		       LENGTH(SOBRIQUET) 
------------------------------ ------------------ 
TENDULKAR				       13 
HOBBS					       10 
DRAVID						8 
TRUMPER 
BRADMAN 					7 
SPOFFORTH					9 

6 rows selected. 

SQL&gt; 
</pre>
<p>Unlike the COUNT function, LENGTH is not always guaranteed to return an Integer. If the string passed in is NULL, then it will return NULL.<br />
To avoid being tripped up by this, you may well therefore consider the following to be prudent :</p>
<pre class="brush: sql; highlight: [2]; title: ; notranslate">
SELECT last_name, 
    NVL(LENGTH(sobriquet),0) 
FROM greats;
</pre>
<p>I had almost managed to get all the way through this without mentioning England&#8217;s latest demonstration of grace in defeat&#8230;.but Deb has just walked in and “reminded” me about the rugby last week. The Welsh  have never been bashful about winning.</p>
<br />Filed under: <a href='http://mikesmithers.wordpress.com/category/oracle/'>Oracle</a>, <a href='http://mikesmithers.wordpress.com/category/sql/'>SQL</a> Tagged: <a href='http://mikesmithers.wordpress.com/tag/length/'>length</a>, <a href='http://mikesmithers.wordpress.com/tag/nvl/'>NVL</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=1944&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mikesmithers.wordpress.com/2013/03/23/how-long-is-a-piece-of-string-cricketing-greats-and-the-length-function/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3cb0956016bbad280193fbbd8e649b9?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Mike S</media:title>
		</media:content>
	</item>
		<item>
		<title>Disabling the Oracle Diagnostic and Tuning Pack APIs – If you want something done, do it yourself</title>
		<link>http://mikesmithers.wordpress.com/2013/03/07/disabling-the-oracle-diagnostic-and-tuning-pack-apis-if-you-want-something-done-do-it-yourself/</link>
		<comments>http://mikesmithers.wordpress.com/2013/03/07/disabling-the-oracle-diagnostic-and-tuning-pack-apis-if-you-want-something-done-do-it-yourself/#comments</comments>
		<pubDate>Thu, 07 Mar 2013 22:14:28 +0000</pubDate>
		<dc:creator>mikesmithers</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[CONTROL_MANAGEMENT_PACK_ACCESS]]></category>
		<category><![CDATA[create or replace public synonym]]></category>
		<category><![CDATA[dbms_addm]]></category>
		<category><![CDATA[dbms_advisor]]></category>
		<category><![CDATA[DBMS_FEATURE_USAGE_INTERNAL.EXEC_DB_USAGE_SAMPLING]]></category>
		<category><![CDATA[DBMS_MANAGEMENT_PACKS]]></category>
		<category><![CDATA[dbms_sqltune]]></category>
		<category><![CDATA[dbms_workload_replay]]></category>
		<category><![CDATA[dbms_workload_repository]]></category>
		<category><![CDATA[Diagnostic and Tuning Pack]]></category>
		<category><![CDATA[diagnostic pack]]></category>
		<category><![CDATA[Disable Diagnostic and Tuning Packs]]></category>
		<category><![CDATA[public synonyms]]></category>
		<category><![CDATA[REGEXP_INSTR]]></category>
		<category><![CDATA[REGEXP_REPLACE]]></category>
		<category><![CDATA[SQLDeveloper Last AWR Report]]></category>
		<category><![CDATA[tuning pack]]></category>

		<guid isPermaLink="false">http://mikesmithers.wordpress.com/?p=1904</guid>
		<description><![CDATA[At last, we have reached the final episode of the Star Wars themed odyssey through the tangled web that is Oracle&#8217;s Diagnostic and Tuning Pack licensing. Just as well really, Deb has flatly refused to give over any more evenings to my “research” &#8211; i.e. re-watching all of the films. Even the appeal of Ewan [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=1904&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>At last, we have reached the final episode of the Star Wars themed odyssey through the tangled web that is Oracle&#8217;s Diagnostic and Tuning Pack licensing.<br />
Just as well really, Deb has flatly refused to give over any more evenings to my “research” &#8211; i.e. re-watching all of the films. Even the appeal of Ewan MacGregor&#8217;s Alec Guiness impression has now waned.<br />
Just to recap then, so far I&#8217;ve looked at :</p>
<ul>
<li><a href="http://wp.me/pweWl-rW">Oracle Licensing for the various Database Editions</a></li>
<li><a href="http://wp.me/pweWl-sZ">How Oracle audits features used on the database</a></li>
<li><a href="http://wp.me/pweWl-t9">The components that comprise the Diagnostic and Tuning Pack APIs</a></li>
<li><a href="//wp.me/pweWl-tX”">How SQLDeveloper can be quite expensive</a></li>
</ul>
<p>Now, finally we&#8217;re going to have a look at how we can minimize the chances of an errant select statement causing a whole heap of trouble.<br />
Yes, we&#8217;re going to have a go at disabling access to the Diagnostic and Tuning Pack APIs without (hopefully), breaking anything.<br />
<span id="more-1904"></span></p>
<h3>A brief word about DBMS_MANAGEMENT_PACKS</h3>
<p>There are ways of disabling AWR. Apart from this only being part of the tuning pack and therefore not the panacea we&#8217;re looking for, the original method for doing this did sum up the confusion surrounding licensing.<br />
Oracle&#8217;s advice was to run the following (NOTE &#8211; please don&#8217;t run until you&#8217;ve read on) : </p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate"> 
BEGIN 
	DBMS_WORKLOAD_REPOSITORY.MODIFY_SNAPSHOT_SETTINGS( interval =&gt; 0); 
END; 
</pre>
<p>Have you spotted the floor in this plan ? Yep, DBMS_WORKLOAD_REPOSITORY is part of the Tuning pack.<br />
So, if you&#8217;re not licensed for the Tuning Pack then you shouldn&#8217;t be using this package. Have a look at <a href="http://jonathanlewis.wordpress.com/2006/11/19/awr-dilemma/">Jonathan Lewis&#8217; take on this</a>. </p>
<p>In 11.1, the DBMS_MANAGEMENT_PACKS package came along.<br />
The only documentation I could find was on the ever-reliable <a href="http://psoug.org/reference/dbms_mgmt_packs.html">Morgan&#8217;s library</a>. </p>
<p>Apparently, you can now use this package to disable AWR&#8230;</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate"> 
BEGIN 
	DBMS_MANAGEMENT_PACKS.MODIFY_AWR_SETTINGS(interval =&gt; 0); 
END; 
/ 
</pre>
<p>Like I said, this isn&#8217;t exactly what we&#8217;re after here.<br />
Furthermore, I&#8217;d treat this with some caution. I would want to be sure that the MODIFY_AWR_SETTINGS procedure wasn&#8217;t simply calling DBMS_WORKLOAD_REPOSITORY – something it&#8217;s difficult to verify without testing as the package body itself is wrapped.</p>
<p>However, there are a couple of other package members that are of interest. </p>
<p>Of particular interest are the PURGE procedure and the REPORT function. </p>
<p>The comments for the PURGE procedure are : </p>
<pre class="brush: sql; highlight: [2,3,4]; title: ; notranslate"> 
--    PROCEDURE DBMS_MANAGEMENT_PACKS.purge 
--    PURPOSE: Remove/deactivate objects in the database that are inconsistent 
--             with the proposed setting of the 
--             &quot;control_management_pack_access&quot; parameter 
--    PARAMETERS: 
--         LICENSE_LEVEL 
--             Any valid value for init.ora parameter 
--             &quot;control_management_pack_access&quot;. NULL is also a valid value, 
--             and it is equivalent to using teh function with the current 
--             value of the init.ora parameter. 
PROCEDURE purge(license_level IN varchar2); 
</pre>
<p>And for the REPORT function : </p>
<pre class="brush: sql; highlight: [2,3]; title: ; notranslate"> 
--    FUNCTION DBMS_MANAGEMENT_PACKS.report 
--    PURPOSE: Get a text report of what changes will be done to the system 
--             if the &quot;purge&quot; procedure is called with a specific level. 
--    PARAMETERS: 
--         LICENSE_LEVEL 
--             Any valid value for init.ora parameter 
--             &quot;control_management_pack_access&quot;. NULL is also a valid value, 
--             and it is equivalent to using teh function with the current 
--             value of the init.ora parameter. 
--    RETURN: a clob containing a text explanation of the changes. 
FUNCTION report(license_level IN varchar2) RETURN clob; 
</pre>
<p>OK, so let&#8217;s connect as SYS and have a look at what we can get from the report function.<br />
First of all, let&#8217;s check the setting of the control_management_pack_access parameter : </p>
<pre class="brush: sql; title: ; notranslate"> 
SELECT value 
FROM v$parameter 
WHERE name = 'control_management_pack_access' 
/ 

VALUE 
------------------------------ 
NONE 
</pre>
<p>Now let&#8217;s see what we can get from the report. </p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate"> 
set long 999999 
SELECT DBMS_MANAGEMENT_PACKS.REPORT(NULL) 
FROM dual 
/	 

List of objects to be deleted by DBMS_MANAGEMENT_PACKS.PURGE                                                                                                                                                                                                    
Requested license level is none                                                                                                                                                                                                                                  
------------------------------------------------------------ 
 
 
 
</pre>
<p>So, it would appear that, despite what the comments say, this package won&#8217;t actually do<br />
anything. Hopefully, this is simply a placeholder and the functionality we need will be<br />
available in a future version of the RDBMS. In the meantime however, we need to find some<br />
other way of resolving matters.</p>
<h3>The thing about Public Synonyms</h3>
<p>I&#8217;ve learned a number of interesting techniques from <a href="http://blog.red-database-security.com/">Alexander Kornbrust</a> over the years.<br />
If you ever get the chance to see him present on Oracle Security, I would highly recommend it.</p>
<p>One Oracle cracking technique in particular involves the exploitation of Public Synonyms by re-pointing a synonym to an object other than that orginally intended.</p>
<p>Time for a quick example. </p>
<p>First of all, I&#8217;m going to create this table under my own schema.</p>
<pre class="brush: sql; highlight: [44,47]; title: ; wrap-lines: false; notranslate">

CREATE TABLE star_wars_films(
    title VARCHAR2(35),
    description VARCHAR2(100))
/

INSERT INTO star_wars_films( title, description)
VALUES( 
    'Episode 1 - The Phantom Menace',
    'Boy meets annoying CGI character and woman with a mad hairdresser.')
/

INSERT INTO star_wars_films( title, description)
VALUES( 
    'Episode 2 - Attack of the Clones',
    'Yoda gets out for a bit of exercise. Christopher Lee gives electrifying performance')
/

INSERT INTO star_wars_films( title, description)
VALUES( 
    'Episode 3 - Revenge of the Sith',
    q'[Influence of Padme's flamboyant taste induces Annakin to have a complete image makeover]')
/

INSERT INTO star_wars_films( title, description)
VALUES(
    'Episode 4 - A New Hope',
    'Alec Guiness does Alec Guiness impression. Death Star engineers learn importance of proper testing')
/

INSERT INTO star_wars_films( title, description)
VALUES( 
    'Episode 5 - The Empire Strikes Back',
    'Akward moment at family reunion. Han Solo catches a cold')
/

INSERT INTO star_wars_films( title, description)
VALUES( 
    'Episode 6 - Return of the Jedi',
    'WARNING - animated teddy bears present choking hazard. Unsuitable for Sith Lords')
/

COMMIT;

CREATE OR REPLACE PUBLIC SYNONYM star_wars_films FOR mike.star_wars_films
/

GRANT SELECT ON star_wars_films TO PUBLIC
/
</pre>
<p>Now, if I connect as another user ( hr, for example), I can do this :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
SELECT *
FROM star_wars_films
/
...
Episode 1 - The Phantom Menace      Boy meets annoying CGI character and woman with a mad hairdresser.                                 
Episode 2 - Attack of the Clones    Yoda gets out for a bit of exercise. Christopher Lee gives electrifying performance                
Episode 3 - Revenge of the Sith     Influence of Padme's flamboyant taste induces Annakin to have a complete image makeover            
Episode 4 - A New Hope              Alec Guiness does Alec Guiness impression. Death Star engineers learn importance of proper testing 
Episode 5 - The Empire Strikes Back Akward moment at family reunion. Han Solo catches a cold                                           
Episode 6 - Return of the Jedi      WARNING - animated teddy bears present choking hazard. Unsuitable for Sith Lords                   

</pre>
<p>In desparation, Darth Debbie has hacked into my database to put a stop to all this Star Wars nonsense&#8230;</p>
<pre class="brush: sql; highlight: [13]; title: ; wrap-lines: false; notranslate">
CREATE TABLE foot_down(message VARCHAR2(100)) 
/ 

INSERT INTO foot_down(message) 
VALUES('You are only allowed to watch Love Actually or Bridget Jones !') 
/ 

COMMIT; 

GRANT SELECT on foot_down TO PUBLIC 
/ 

CREATE OR REPLACE PUBLIC SYNONYM star_wars_films for deb.foot_down 
/
</pre>
<p>Now, when we run the same query as another user&#8230;</p>
<pre class="brush: sql; highlight: [5,6,7]; title: ; wrap-lines: false; notranslate">
SELECT *
FROM star_wars_films
/

MESSAGE 
--------------------------------------------------------------------------- 
You are only allowed to watch Love Actually or Bridget Jones ! 

</pre>
<p>How does this relate to the problem at hand ?<br />
Well, all of the objects that comprise the Diagnostic and Tuning Pack APIs have Public Synonyms.<br />
The tools and scripts that utilize these APIs rely on the synonyms being present. At least, I haven&#8217;t noticed too many references to SYS.object_name in the code that I&#8217;ve looked at.</p>
<p>Let&#8217;s see how we can apply this technique to minimize the possibility of inadvertant access to the APIs.</p>
<h3>Disclaimer and Other Notes</h3>
<p>At this point, I should make it clear that what follows has been tested to the extent I&#8217;ve set out here and no further.<br />
I&#8217;ve used Oracle 11gXE (11.2.0.2)  for my testing. I haven&#8217;t tested this on any other Oracle Database Editions or versions.<br />
If you&#8217;re interested in deploying this fix, I&#8217;d suggest that you conduct you&#8217;re own testing first.<br />
This would need to be done under an <a href="http://www.oracle.com/technetwork/licenses/standard-license-152015.html">OTN license</a> –  not on a database that you&#8217;re using for development of an application and certainly not on any production instance.<br />
I&#8217;d also suggest you&#8217;d run the database with the fix in place for at least a week and keep an eye on the alert.log for any issues that may arise.</p>
<p>Now that&#8217;s out of the way&#8230;</p>
<h3>The Disable Tuning Pack API Application</h3>
<p>The application consists of the following database components</p>
<ul>
<li>A schema to own the database objects</li>
<li>A table of the API members for each of the Diagnostic and Tuning packs</li>
<li>A table containing a warning message</li>
<li>A function that raises an error using the text of the message</li>
<li>Packages with the same signatures as those included in the APIs</li>
</ul>
<p>Once we&#8217;ve got that little lot together, we&#8217;ll then re-point all of the public synonyms to the relevant objects in our application.</p>
<h4>The DISABLE_PACK_DT schema</h4>
<p>The first step is to create the application owner schema :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
CREATE USER disable_pack_dt IDENTIFIED BY pwd 
/ 

ALTER USER disable_pack_dt DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP 
/ 

ALTER USER disable_pack_dt QUOTA UNLIMITED on USERS 
/
</pre>
<p>Additionally, this schema requires privileges on some of the packages that we&#8217;ll be replacing. To do this, connect as SYS and  :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
--
-- Must run as SYS as SYSDBA.
-- Grant execute on the underlying packages, not the synonyms !
--
GRANT EXECUTE ON sys.dbms_workload_replay TO disable_pack_dt
/
GRANT EXECUTE ON sys.dbms_advisor TO disable_pack_dt
/
GRANT SELECT ON sys.wri$_adv_parameters TO disable_pack_dt
/
</pre>
<h4>The API members table</h4>
<p>This table holds details of all of the database objects that comprise the Diagnostic and Tuning API. NOTE – it does not include the underlying tables of the views in question.<br />
YOu can find more details on how I derived the contents of the table <a href="//wp.me/pweWl-t9”">here</a>.</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
--
-- Run as a user with CREATE ANY TABLE privileges
--
CREATE TABLE disable_pack_dt.pack_members(
    object_name VARCHAR2(30),
    object_type VARCHAR2(20),
    pack_name VARCHAR2(10),
    full_member VARCHAR2(1),
    notes VARCHAR2(4000))
/

--
-- Script to populate the disable_pack_dt.pack_members table with
-- Diagnostic and Tuning Pack API Objects that are individually specified by
-- the license.
--

--
--  DBMS_WORKLOAD_REPOSITORY
--
INSERT INTO disable_pack_dt.pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'DBMS_WORKLOAD_REPOSITORY', 'PACKAGE', 'DIAGNOSTIC',
    'Y', NULL)
/

--
-- DBMS_ADDM
--
INSERT INTO disable_pack_dt.pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'DBMS_ADDM', 'PACKAGE', 'DIAGNOSTIC',
    'Y', NULL)
/

--
-- DBMS_ADVISOR - NOTE - this is a member of BOTH packs
--
INSERT INTO disable_pack_dt.pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'DBMS_ADVISOR', 'PACKAGE', 'BOTH',
    'N', 
    'DIAGNOSTIC PACK - Only if advisor_name =&gt; ADDM OR task_name LIKE ADDM%'
    ||' TUNING PACK - where advisor_name =&gt; SQL Tuning Advisor OR SQL Access Advisor')
/

--
-- DBMS_WORKLOAD_REPLAY
--
INSERT INTO disable_pack_dt.pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'DBMS_WORKLOAD_REPLAY', 'PACKAGE', 'DIAGNOSTIC',
    'N', 'COMPARE_PERIOD_REPORT function only')
/

--
-- V$ACTIVE_SESSION_HISTORY
-- NOTE - this is a synonym for V_$ACTIVE_SESSION_HISTORY
--
INSERT INTO disable_pack_dt.pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'V$ACTIVE_SESSION_HISTORY', 'SYNONYM', 'DIAGNOSTIC',
    'Y', 'Synonym for V_$ACTIVE_SESSION_HISTORY')
/

INSERT INTO disable_pack_dt.pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'V_$ACTIVE_SESSION_HISTORY', 'VIEW', 'DIAGNOSTIC',
    'Y', 'Synonym for this view is V_$ACTIVE_SESSION_HISTORY')
/

--
-- DBA_STREAMS_TP_PATH_BOTTLENECK
--
INSERT INTO disable_pack_dt.pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'DBA_STREAMS_TP_PATH_BOTTLENECK', 'VIEW', 'DIAGNOSTIC',
    'Y', NULL)
/

--
--  DBA_STREAMS_TP_COMPONENT_STAT
--
INSERT INTO disable_pack_dt.pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'DBA_STREAMS_TP_COMPONENT_STAT', 'VIEW', 'DIAGNOSTIC',
    'N', 'Only rows where STATISTIC_UNIT = PERCENT')
/

--
-- DBMS_SQLTUNE
--
INSERT INTO disable_pack_dt.pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'DBMS_SQLTUNE', 'PACKAGE', 'TUNING',
    'Y', NULL)
/

--
-- V$SQL_MONITOR - NOTE - this is a public synonym for V_$SQL_MONITOR !!!
-- Therefore, we'll specify the underlying view here as well
--
INSERT INTO disable_pack_dt.pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'V$SQL_MONITOR', 'SYNONYM', 'TUNING',
    'Y', 'Synonym for V_$SQL_MONITOR')
/

INSERT INTO disable_pack_dt.pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'V_$SQL_MONITOR', 'VIEW', 'TUNING',
    'Y', 'Synonym for this view is V$SQL_MONITOR')
/

--
-- V$SQL_PLAN_MONITOR - public synonym for V_SQL_PLAN_MONITOR.
-- Again, specify the underlying view here as well
--

INSERT INTO disable_pack_dt.pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'V_$SQL_PLAN_MONITOR', 'VIEW', 'TUNING',
    'Y', 'Synonym for this view is V$SQL_PLAN_MONITOR')
/

INSERT INTO disable_pack_dt.pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'V$SQL_PLAN_MONITOR', 'SYNONYM', 'TUNING',
    'Y', 'Synonym for V_$SQL_PLAN_MONITOR')
/

COMMIT;

--
-- Find all of the Diagnostic Pack views that are not specified by
-- name in the License and insert them into the PACK_MEMBERS table
--
INSERT INTO disable_pack_dt.pack_members( 
    object_name, object_type, pack_name,
    full_member, notes)
    SELECT object_name, object_type, 'DIAGNOSTIC',
        'Y', NULL
    FROM sys.dba_objects
    WHERE owner = 'SYS'
    AND object_type = 'VIEW'
    AND (
        object_name LIKE 'DBA_ADDM_%'
    OR ( 
        object_name LIKE 'DBA_HIST_%'
        AND object_name NOT IN (
            'DBA_HIST_SNAPSHOT', 'DBA_HIST_DATABASE_INSTANCE', 
            'DBA_HIST_SNAP_ERROR', 'DBA_HIST_SEG_STAT', 
            'DBA_HIST_SEG_STAT_OBJ', 'DBA_HIST_UNDOSTAT')
        )
    )
    UNION    
    SELECT object_name, object_type, 'DIAGNOSTIC',
        'N', 
        'Only where ADVISOR_NAME = ADDM or TASK_NAME LIKE ADDM% '
        ||'or TASK_ID relates back to TASK_NAME that is like ADDM%'
    FROM sys.dba_objects
    WHERE owner = 'SYS'
    AND object_type = 'VIEW'
    AND object_name LIKE 'DBA_ADVISOR_%'
/

COMMIT;
</pre>
<h4>The message table</h4>
<p>For the Views that comprise these APIs, we&#8217;re going to re-direct any queries to a table that simply contains a message.</p>
<p>Although not all of the Views are “full members” of the APIs, I have decided to treat them in the same way for the purposes of this application.<br />
For example, we could simply amend the DBA_STREAMS_TP_COMPONENT_STAT view to return only rows where the static_unit is not &#8216;PERCENT&#8217; :</p>
<pre class="brush: sql; highlight: [42]; title: ; wrap-lines: false; notranslate">
  CREATE OR REPLACE FORCE VIEW &quot;SYS&quot;.&quot;DBA_STREAMS_TP_COMPONENT_STAT&quot; (&quot;COMPONENT_ID&quot;, &quot;COMPONENT_NAME&quot;, &quot;COMPONENT_DB&quot;, &quot;COMPONENT_TYPE&quot;, &quot;SUB_COMPONENT_TYPE&quot;, &quot;SESSION_ID&quot;, &quot;SESSION_SERIAL#&quot;, &quot;STATISTIC_TIME&quot;, &quot;STATISTIC_NAME&quot;, &quot;STATISTIC_VALUE&quot;, &quot;STATISTIC_UNIT&quot;, &quot;ADVISOR_RUN_ID&quot;, &quot;ADVISOR_RUN_TIME&quot;) AS 
  SELECT C.COMPONENT_ID,
       nvl(C.COMPONENT_NAME, C.SPARE3) COMPONENT_NAME,
       C.COMPONENT_DB,
       decode(C.COMPONENT_TYPE,
              1, 'CAPTURE',
              2, 'PROPAGATION SENDER',
              3, 'PROPAGATION RECEIVER',
              4, 'APPLY',
              5, 'QUEUE',
              NULL),
       decode(S.SUB_COMPONENT_TYPE,
              -- Capture sub-components
              11, 'LOGMINER READER',
              12, 'LOGMINER PREPARER',
              13, 'LOGMINER BUILDER',
              14, 'CAPTURE SESSION',
              -- Apply sub-components
              41, 'PROPAGATION SENDER+RECEIVER',
              42, 'APPLY READER',
              43, 'APPLY COORDINATOR',
              44, 'APPLY SERVER',
              NULL),
       S.SESSION_ID,
       S.SESSION_SERIAL#,
       S.STATISTIC_TIME,
       S.STATISTIC_NAME,
       -- State is a varchar2 stored in spare3, everything else is a number
       decode(S.STATISTIC_NAME,
              'STATE', S.SPARE3,
              S.STATISTIC_VALUE),
       S.STATISTIC_UNIT,
       S.ADVISOR_RUN_ID,
       S.ADVISOR_RUN_TIME
FROM streams$_component C,
     streams$_component_stat_out S
WHERE C.COMPONENT_ID = S.COMPONENT_ID
  AND S.STATISTIC_NAME IS NOT NULL
  AND S.STATISTIC_NAME NOT IN (
       'SEND RATE TO APPLY',
       'BYTES SENT VIA SQL*NET TO DBLINK')
 AND NVL(s.statistic_unit, 'X') != 'PERCENT';
</pre>
<p>However, this would likely make things a bit confusing. After all, the result of the following query would probably leave you scratching your head if you didn&#8217;t know of the little addition to the predicate :</p>
<pre class="brush: sql; title: ; notranslate">
SELECT *
FROM dba_streams_tp_component_stat
WHERE s.statistic_unit = 'PERCENT';
</pre>
<p>We want any SQL adventurer on our database to know that this View is off limits and why.<br />
In any case, if the intrepid sole in question still wishes to make use of the view ( with the appropriate insurance of the additional predicate) then they can always by-pass the synonym by prefixing the schema owner ( i.e. SYS. DBA_STREAMS_TP_COMPONENT_STAT).<br />
Therefore, any atempt to access any of these views will be re-directed to this table :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
CREATE TABLE disable_pack_dt.disable_pack_message(
    urgent_please_read VARCHAR2(4000))
/

INSERT INTO disable_pack_dt.disable_pack_message( urgent_please_read)
VALUES(
    'Diagnostic and Tuning Packs are NOT LICENSED on this database.'||CHR(10)
    ||'Please do not access any of the pack API objects or underlying tables.'||CHR(10)
    ||'For a full list please see the table disable_pack_dt.pack_members')
/

COMMIT;

GRANT SELECT ON disable_pack_dt.disable_pack_message TO PUBLIC
/

</pre>
<h4>The Error Function</h4>
<p>This function simply raises an error using the text in the message table :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
CREATE OR REPLACE FUNCTION disable_pack_dt.get_err_msg_fn
    RETURN VARCHAR2 IS
-------------------------------------------------------------------------------
-- This function will never return a value. It will always raise an error
-- with the message text being the value in 
-- DISABLE_PACK_MESSAGE.URGENT_PLEASE_READ.
--
-------------------------------------------------------------------------------
    l_msg disable_pack_dt.disable_pack_message.urgent_please_read%TYPE;
BEGIN
    SELECT urgent_please_read
    INTO l_msg
    FROM disable_pack_dt.disable_pack_message;
    RAISE_APPLICATION_ERROR(-20999, l_msg);
END;
/
</pre>
<h4>Full member Packages</h4>
<p>Of the five packages that are members of the Diagnostic and Tuning pack, four are wholly part of on or other of the packs. Two others are only considered part of these packs under certain circumstances.</p>
<p>As the packages are likely to be invoked in a rather different context to the views – i.e. in a PL/SQL block rather than in a SELECT statement – we need to come up with something a bit different for them.</p>
<p>What we&#8217;re going to do is to create a wrapper for each of the packages. For the three packages whose use is totally prohibited, we want any call to them to result in displaying the same error message as for the views.</p>
<p>To do this, we need to create the wrapper packages in the DISABLE_PACK_DT schema and point the Public Synonyms to them.</p>
<p>For the packages that are only partial members of the API, we need only to block any prohibited calls whilst passing through anything else.</p>
<p>For each package member we want to block, we simply need to re-direct the call to the get_err_msg_fn function we&#8217;ve just created.</p>
<p>You can get the names of the three full member packages with this query :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
SQL&gt; SELECT object_name 
  2  FROM disable_pack_dt.pack_members 
  3  WHERE object_type = 'PACKAGE' 
  4  AND full_member = 'Y' 
  5  ORDER BY 1; 

OBJECT_NAME 
------------------------------ 
DBMS_ADDM 
DBMS_SQLTUNE 
DBMS_WORKLOAD_REPOSITORY 

SQL&gt; 
</pre>
<p>Before listing the sourcecode for the blocker packages, I should point out that I did save myself some typing here by getting the code out of the DBA_SOURCE view. As a result, the code doesn&#8217;t follow my normal coding conventions.</p>
<p>Here then, is the code for the header and body for each of the packages :</p>
<p><strong>BLOCK_DBMS_ADDM</strong></p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
CREATE OR REPLACE PACKAGE disable_pack_dt.BLOCK_DBMS_ADDM
authid current_user
IS

procedure analyze_db ( task_name             in out varchar2,
begin_snapshot        in number,
end_snapshot          in number,
db_id                 in number := NULL);



procedure analyze_inst ( task_name             in out varchar2,
begin_snapshot        in number,
end_snapshot          in number,
instance_number       in number := NULL,
db_id                 in number := NULL);


procedure analyze_partial ( task_name             in out varchar2,
instance_numbers      in varchar2,
begin_snapshot        in number,
end_snapshot          in number,
db_id                 in number := NULL);


procedure insert_finding_directive ( task_name           in varchar2,
dir_name            in varchar2,
finding_name        in varchar2,
min_active_sessions in number := 0,
min_perc_impact     in number := 0);


procedure insert_sql_directive ( task_name           in varchar2,
dir_name            in varchar2,
sql_id              in varchar2,
min_active_sessions in number := 0,
min_response_time   in number := 0);


procedure insert_segment_directive ( task_name           in varchar2,
dir_name            in varchar2,
owner_name          in varchar2,
object_name         in varchar2 := NULL,
sub_object_name     in varchar2 := NULL);


procedure insert_segment_directive ( task_name           in varchar2,
dir_name            in varchar2,
object_number       in number);


procedure insert_parameter_directive ( task_name           in varchar2,
dir_name            in varchar2,
parameter_name      in varchar2);

procedure delete_finding_directive ( task_name           in varchar2,
dir_name            in varchar2);

procedure delete_sql_directive ( task_name           in varchar2,
dir_name            in varchar2);

procedure delete_segment_directive ( task_name           in varchar2,
dir_name            in varchar2);

procedure delete_parameter_directive ( task_name           in varchar2,
dir_name            in varchar2);


procedure delete ( task_name             in varchar2);



function get_report ( task_name             in varchar2)
return clob;


function get_ash_query ( task_name in varchar2, finding_id in number)
return varchar2;

END BLOCK_DBMS_ADDM;
/ 
</pre>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
CREATE OR REPLACE PACKAGE BODY disable_pack_dt.BLOCK_DBMS_ADDM
IS

procedure analyze_db ( task_name             in out varchar2,
begin_snapshot        in number,
end_snapshot          in number,
db_id                 in number := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


procedure analyze_inst ( task_name             in out varchar2,
begin_snapshot        in number,
end_snapshot          in number,
instance_number       in number := NULL,
db_id                 in number := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


procedure analyze_partial ( task_name             in out varchar2,
instance_numbers      in varchar2,
begin_snapshot        in number,
end_snapshot          in number,
db_id                 in number := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


procedure insert_finding_directive ( task_name           in varchar2,
dir_name            in varchar2,
finding_name        in varchar2,
min_active_sessions in number := 0,
min_perc_impact     in number := 0) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



procedure insert_sql_directive ( task_name           in varchar2,
dir_name            in varchar2,
sql_id              in varchar2,
min_active_sessions in number := 0,
min_response_time   in number := 0) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



procedure insert_segment_directive ( task_name           in varchar2,
dir_name            in varchar2,
owner_name          in varchar2,
object_name         in varchar2 := NULL,
sub_object_name     in varchar2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



procedure insert_segment_directive ( task_name           in varchar2,
dir_name            in varchar2,
object_number       in number) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



procedure insert_parameter_directive ( task_name           in varchar2,
dir_name            in varchar2,
parameter_name      in varchar2) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


procedure delete_finding_directive ( task_name           in varchar2,
dir_name            in varchar2) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


procedure delete_sql_directive ( task_name           in varchar2,
dir_name            in varchar2) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


procedure delete_segment_directive ( task_name           in varchar2,
dir_name            in varchar2) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


procedure delete_parameter_directive ( task_name           in varchar2,
dir_name            in varchar2) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



procedure delete ( task_name             in varchar2) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 




function get_report ( task_name             in varchar2)
return clob IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



function get_ash_query ( task_name in varchar2, finding_id in number)
return varchar2 IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


END BLOCK_DBMS_ADDM;
/

</pre>
<p><strong>BLOCK_DBMS_SQLTUNE</strong></p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
CREATE OR REPLACE PACKAGE disable_pack_dt.BLOCK_DBMS_SQLTUNE AUTHID CURRENT_USER AS
ADV_SQLTUNE_NAME  CONSTANT VARCHAR2(18) := 'SQL Tuning Advisor';

SCOPE_LIMITED       CONSTANT VARCHAR2(7)  := 'LIMITED';
SCOPE_COMPREHENSIVE CONSTANT VARCHAR2(13) := 'COMPREHENSIVE';

TIME_LIMIT_DEFAULT  CONSTANT   NUMBER := 1800;

TYPE_TEXT           CONSTANT   VARCHAR2(4) := 'TEXT'       ;
TYPE_XML            CONSTANT   VARCHAR2(3) := 'XML'        ;
TYPE_HTML           CONSTANT   VARCHAR2(4) := 'HTML'       ;

LEVEL_TYPICAL       CONSTANT   VARCHAR2(7) := 'TYPICAL'    ;
LEVEL_BASIC         CONSTANT   VARCHAR2(5) := 'BASIC'      ;
LEVEL_ALL           CONSTANT   VARCHAR2(3) := 'ALL'        ;

SECTION_FINDINGS    CONSTANT   VARCHAR2(8) := 'FINDINGS'   ;
SECTION_PLANS       CONSTANT   VARCHAR2(5) := 'PLANS'      ;
SECTION_INFORMATION CONSTANT   VARCHAR2(11):= 'INFORMATION';
SECTION_ERRORS      CONSTANT   VARCHAR2(6) := 'ERRORS'     ;
SECTION_ALL         CONSTANT   VARCHAR2(3) := 'ALL'        ;
SECTION_SUMMARY     CONSTANT   VARCHAR2(7) := 'SUMMARY'    ;

DATE_FMT       constant varchar2(21)       :=  'mm/dd/yyyy hh24:mi:ss';

REC_TYPE_ALL          CONSTANT   VARCHAR2(3)  := 'ALL';
REC_TYPE_SQL_PROFILES CONSTANT   VARCHAR2(8)  := 'PROFILES';
REC_TYPE_STATS        CONSTANT   VARCHAR2(10) := 'STATISTICS';
REC_TYPE_INDEXES      CONSTANT   VARCHAR2(7)  := 'INDEXES';
REC_TYPE_PX           CONSTANT   VARCHAR2(18) := 'PARALLEL_EXECUTION';
REC_TYPE_ALTER_PLANS  CONSTANT   VARCHAR2(17) := 'ALTERNATIVE_PLANS';

MODE_REPLACE_OLD_STATS CONSTANT   NUMBER := 1;
MODE_ACCUMULATE_STATS  CONSTANT   NUMBER := 2;

SINGLE_EXECUTION       CONSTANT   POSITIVE := 1;
ALL_EXECUTIONS         CONSTANT   POSITIVE := 2;
LIMITED_COMMAND_TYPE   CONSTANT   BINARY_INTEGER  := 1;
ALL_COMMAND_TYPE       CONSTANT   BINARY_INTEGER  := 2;

REGULAR_PROFILE        CONSTANT   VARCHAR2(11) := 'SQL PROFILE';
PX_PROFILE             CONSTANT   VARCHAR2(10) := 'PX PROFILE';

STS_STGTAB_10_2_VERSION     CONSTANT NUMBER := 1;
STS_STGTAB_11_1_VERSION     CONSTANT NUMBER := 2;
STS_STGTAB_11_2_VERSION     CONSTANT NUMBER := 3;
STS_STGTAB_11_202_VERSION   CONSTANT NUMBER := 4;


NO_RECURSIVE_SQL            CONSTANT VARCHAR2(30) := 'N';
HAS_RECURSIVE_SQL           CONSTANT VARCHAR2(30) := 'Y';



FUNCTION create_tuning_task(
sql_text    IN CLOB,
bind_list   IN sql_binds := NULL,
user_name   IN VARCHAR2  := NULL,
scope       IN VARCHAR2  := SCOPE_COMPREHENSIVE,
time_limit  IN NUMBER    := TIME_LIMIT_DEFAULT,
task_name   IN VARCHAR2  := NULL,
description IN VARCHAR2  := NULL)
RETURN VARCHAR2;

FUNCTION create_tuning_task(
sql_id          IN VARCHAR2,
plan_hash_value IN NUMBER   := NULL,
scope           IN VARCHAR2 := SCOPE_COMPREHENSIVE,
time_limit      IN NUMBER   := TIME_LIMIT_DEFAULT,
task_name       IN VARCHAR2 := NULL,
description     IN VARCHAR2 := NULL)
RETURN VARCHAR2;

FUNCTION create_tuning_task(
begin_snap      IN NUMBER,
end_snap        IN NUMBER,
sql_id          IN VARCHAR2,
plan_hash_value IN NUMBER   := NULL,
scope           IN VARCHAR2 := SCOPE_COMPREHENSIVE,
time_limit      IN NUMBER   := TIME_LIMIT_DEFAULT,
task_name       IN VARCHAR2 := NULL,
description     IN VARCHAR2 := NULL)
RETURN VARCHAR2;

FUNCTION create_tuning_task(
sqlset_name       IN VARCHAR2,
basic_filter      IN VARCHAR2 :=  NULL,
object_filter     IN VARCHAR2 :=  NULL,
rank1             IN VARCHAR2 :=  NULL,
rank2             IN VARCHAR2 :=  NULL,
rank3             IN VARCHAR2 :=  NULL,
result_percentage IN NUMBER   :=  NULL,
result_limit      IN NUMBER   :=  NULL,
scope             IN VARCHAR2 :=  SCOPE_COMPREHENSIVE,
time_limit        IN NUMBER   :=  TIME_LIMIT_DEFAULT,
task_name         IN VARCHAR2 :=  NULL,
description       IN VARCHAR2 :=  NULL,
plan_filter       IN VARCHAR2 :=  'MAX_ELAPSED_TIME',
sqlset_owner      IN VARCHAR2 :=  NULL)
RETURN VARCHAR2;

FUNCTION create_tuning_task(
spa_task_name     IN VARCHAR2,
spa_task_owner    IN VARCHAR2 :=  NULL,
spa_compare_exec  IN VARCHAR2 :=  NULL,
basic_filter      IN
VARCHAR2 :=  NULL,
time_limit        IN NUMBER   :=  TIME_LIMIT_DEFAULT,
task_name         IN VARCHAR2 :=  NULL,
description       IN VARCHAR2 :=  NULL)
RETURN VARCHAR2;

PROCEDURE set_tuning_task_parameter(
task_name IN VARCHAR2,
parameter IN VARCHAR2,
value     IN VARCHAR2);

PROCEDURE set_tuning_task_parameter(
task_name IN VARCHAR2,
parameter IN VARCHAR2,
value     IN NUMBER);

PROCEDURE set_tuning_task_parameter(
parameter IN VARCHAR2,
value     IN VARCHAR2);

PROCEDURE set_tuning_task_parameter(
parameter IN VARCHAR2,
value     IN NUMBER);

FUNCTION execute_tuning_task(
task_name        IN VARCHAR2,
execution_name   IN VARCHAR2               := NULL,
execution_params IN dbms_advisor.argList   := NULL,
execution_desc   IN VARCHAR2               := NULL)
RETURN VARCHAR2;
PROCEDURE execute_tuning_task(
task_name        IN VARCHAR2,
execution_name   IN VARCHAR2               := NULL,
execution_params IN dbms_advisor.argList   := NULL,
execution_desc   IN VARCHAR2               := NULL);


procedure interrupt_tuning_task(task_name IN VARCHAR2);

PROCEDURE cancel_tuning_task(task_name IN VARCHAR2);

PROCEDURE reset_tuning_task(task_name IN VARCHAR2);

PROCEDURE drop_tuning_task(task_name IN VARCHAR2);

PROCEDURE resume_tuning_task(
task_name    IN VARCHAR2,
basic_filter IN VARCHAR2 := NULL);

FUNCTION report_tuning_task(
task_name      IN VARCHAR2,
type           IN VARCHAR2 := TYPE_TEXT,
level          IN VARCHAR2 := LEVEL_TYPICAL,
section        IN VARCHAR2 := SECTION_ALL,
object_id      IN NUMBER   := NULL,
result_limit   IN NUMBER   := NULL,
owner_name     IN VARCHAR2 := NULL,
execution_name IN VARCHAR2 := NULL)
RETURN clob;

FUNCTION script_tuning_task(
task_name      IN VARCHAR2,
rec_type       IN VARCHAR2 := REC_TYPE_ALL,
object_id      IN NUMBER   := NULL,
result_limit   IN NUMBER   := NULL,
owner_name     IN VARCHAR2 := NULL,
execution_name IN VARCHAR2 := NULL)
RETURN CLOB;


PROCEDURE create_sql_plan_baseline(
task_name            IN VARCHAR2,
object_id            IN NUMBER := NULL,
plan_hash_value      IN NUMBER,
owner_name           IN VARCHAR2 := NULL);

PROCEDURE implement_tuning_task(
task_name      IN VARCHAR2,
rec_type       IN VARCHAR2 := REC_TYPE_SQL_PROFILES,
owner_name     IN VARCHAR2 := NULL,
execution_name IN VARCHAR2 := NULL);


FUNCTION report_auto_tuning_task(
begin_exec     IN VARCHAR2  := NULL,
end_exec       IN VARCHAR2  := NULL,
type           IN VARCHAR2  := TYPE_TEXT,
level          IN VARCHAR2  := LEVEL_TYPICAL,
section        IN VARCHAR2  := SECTION_ALL,
object_id      IN NUMBER    := NULL,
result_limit   IN NUMBER    := NULL)
RETURN CLOB;



TYPE sqlset_cursor IS REF CURSOR;


PROCEDURE create_sqlset(
sqlset_name  IN VARCHAR2,
description  IN VARCHAR2 := NULL,
sqlset_owner IN VARCHAR2 := NULL);

FUNCTION create_sqlset(
sqlset_name   IN VARCHAR2 := NULL,
description   IN VARCHAR2 := NULL,
sqlset_owner  IN VARCHAR2 := NULL)
RETURN VARCHAR2;

PROCEDURE drop_sqlset(
sqlset_name   IN VARCHAR2,
sqlset_owner  IN VARCHAR2 := NULL);

PROCEDURE delete_sqlset(
sqlset_name  IN VARCHAR2,
basic_filter IN VARCHAR2 := NULL,
sqlset_owner IN VARCHAR2 := NULL);

PROCEDURE load_sqlset(
sqlset_name       IN VARCHAR2,
populate_cursor   IN sqlset_cursor,
load_option       IN VARCHAR2 := 'INSERT',
update_option     IN VARCHAR2 := 'REPLACE',
update_condition  IN VARCHAR2 :=  NULL,
update_attributes IN VARCHAR2 :=  NULL,
ignore_null       IN BOOLEAN  :=  TRUE,
commit_rows       IN POSITIVE :=  NULL,
sqlset_owner      IN VARCHAR2 :=  NULL);

PROCEDURE capture_cursor_cache_sqlset(
sqlset_name         IN VARCHAR2,
time_limit          IN POSITIVE := 1800,
repeat_interval     IN POSITIVE := 300,
capture_option      IN VARCHAR2 := 'MERGE',
capture_mode        IN NUMBER   := MODE_REPLACE_OLD_STATS,
basic_filter        IN VARCHAR2 := NULL,
sqlset_owner        IN VARCHAR2 := NULL,
recursive_sql       IN VARCHAR2 := HAS_RECURSIVE_SQL);

PROCEDURE update_sqlset(
sqlset_name     IN VARCHAR2,
sql_id          IN                    
VARCHAR2,
attribute_name  IN VARCHAR2,
attribute_value IN VARCHAR2 := NULL,
sqlset_owner    IN VARCHAR2 := NULL);

PROCEDURE update_sqlset(
sqlset_name     IN VARCHAR2,
sql_id          IN VARCHAR2,
plan_hash_value IN NUMBER,
attribute_name  IN VARCHAR2,
attribute_value IN VARCHAR2 := NULL,
sqlset_owner    IN VARCHAR2 := NULL);

PROCEDURE update_sqlset(
sqlset_name     IN VARCHAR2,
sql_id          IN VARCHAR2,
attribute_name  IN VARCHAR2,
attribute_value IN NUMBER   := NULL,
sqlset_owner    IN VARCHAR2 := NULL);

PROCEDURE update_sqlset(
sqlset_name     IN VARCHAR2,
sql_id          IN VARCHAR2,
plan_hash_value IN NUMBER,
attribute_name  IN VARCHAR2,
attribute_value IN NUMBER   := NULL,
sqlset_owner    IN VARCHAR2 := NULL);

FUNCTION add_sqlset_reference(
sqlset_name  IN VARCHAR2,
description  IN VARCHAR2 := NULL,
sqlset_owner IN VARCHAR2 := NULL)
RETURN NUMBER;

PROCEDURE remove_sqlset_reference(
sqlset_name  IN VARCHAR2,
reference_id IN NUMBER,
sqlset_owner IN VARCHAR2 := NULL);

FUNCTION select_sqlset(
sqlset_name       IN VARCHAR2,
basic_filter      IN VARCHAR2 := NULL,
object_filter     IN VARCHAR2 := NULL,
ranking_measure1  IN VARCHAR2 := NULL,
ranking_measure2  IN VARCHAR2 := NULL,
ranking_measure3  IN VARCHAR2 := NULL,
result_percentage IN NUMBER   := 1,
result_limit      IN NUMBER   := NULL,
attribute_list    IN VARCHAR2 := 'TYPICAL',
plan_filter       IN VARCHAR2 := NULL,
sqlset_owner      IN VARCHAR2 := NULL,
recursive_sql     IN VARCHAR2 := HAS_RECURSIVE_SQL)
RETURN sys.sqlset PIPELINED;

FUNCTION select_cursor_cache(
basic_filter      IN VARCHAR2 := NULL,
object_filter     IN VARCHAR2 := NULL,
ranking_measure1  IN VARCHAR2 := NULL,
ranking_measure2  IN VARCHAR2 := NULL,
ranking_measure3  IN VARCHAR2 := NULL,
result_percentage IN NUMBER   := 1,
result_limit      IN NUMBER   := NULL,
attribute_list    IN VARCHAR2 := 'TYPICAL',
recursive_sql     IN VARCHAR2 := HAS_RECURSIVE_SQL)
RETURN sys.sqlset PIPELINED;

FUNCTION select_workload_repository(
begin_snap        IN NUMBER,
end_snap          IN NUMBER,
basic_filter      IN VARCHAR2 := NULL,
object_filter     IN VARCHAR2 := NULL,
ranking_measure1  IN VARCHAR2 := NULL,
ranking_measure2  IN VARCHAR2 := NULL,
ranking_measure3  IN VARCHAR2 := NULL,
result_percentage IN NUMBER   := 1,
result_limit      IN NUMBER   := NULL,
attribute_list    IN VARCHAR2 := 'TYPICAL',
recursive_sql     IN VARCHAR2 := HAS_RECURSIVE_SQL)
RETURN sys.sqlset PIPELINED;

FUNCTION select_workload_repository(
baseline_name     IN VARCHAR2,
basic_filter      IN VARCHAR2 := NULL,
object_filter     IN VARCHAR2 := NULL,
ranking_measure1  IN VARCHAR2 := NULL,
ranking_measure2  IN VARCHAR2 := NULL,
ranking_measure3  IN VARCHAR2 := NULL,
result_percentage IN NUMBER   := 1,
result_limit      IN NUMBER   := NULL,
attribute_list    IN VARCHAR2 := 'TYPICAL',
recursive_sql     IN VARCHAR2 := HAS_RECURSIVE_SQL)
RETURN sys.sqlset PIPELINED;

FUNCTION select_sql_trace(
directory              IN VARCHAR2,
file_name              IN VARCHAR2 := NULL,
mapping_table_name     IN VARCHAR2 := NULL,
mapping_table_owner    IN VARCHAR2 := NULL,
select_mode            IN POSITIVE := SINGLE_EXECUTION,
options                IN BINARY_INTEGER := LIMITED_COMMAND_TYPE,
pattern_start          IN VARCHAR2 := NULL,
pattern_end            IN VARCHAR2 := NULL,
result_limit           IN POSITIVE := NULL)
RETURN sys.sqlset PIPELINED;

FUNCTION select_sqlpa_task(
task_name         IN VARCHAR2,
task_owner        IN VARCHAR2 := NULL,
execution_name    IN VARCHAR2 := NULL,
level_filter      IN VARCHAR2 := 'REGRESSED',
basic_filter      IN VARCHAR2 := NULL,
object_filter     IN VARCHAR2 := NULL,
attribute_list    IN VARCHAR2 := 'TYPICAL')
RETURN sys.sqlset PIPELINED;


PROCEDURE create_stgtab_sqlset(
table_name           IN VARCHAR2,
schema_name          IN VARCHAR2 := NULL,
tablespace_name      IN VARCHAR2 := NULL,
db_version           IN NUMBER   := NULL);

PROCEDURE pack_stgtab_sqlset(
sqlset_name          IN VARCHAR2,
sqlset_owner          
IN VARCHAR2 := NULL,
staging_table_name   IN VARCHAR2,
staging_schema_owner IN VARCHAR2 := NULL,
db_version           IN NUMBER   := NULL);

PROCEDURE unpack_stgtab_sqlset(
sqlset_name          IN VARCHAR2 := '%',
sqlset_owner         IN VARCHAR2 := NULL,
replace              IN BOOLEAN,
staging_table_name   IN VARCHAR2,
staging_schema_owner IN VARCHAR2 := NULL);

PROCEDURE remap_stgtab_sqlset(
old_sqlset_name        IN VARCHAR2,
old_sqlset_owner       IN VARCHAR2 := NULL,
new_sqlset_name        IN VARCHAR2 := NULL,
new_sqlset_owner       IN VARCHAR2 := NULL,
staging_table_name     IN VARCHAR2,
staging_schema_owner   IN VARCHAR2 := NULL);

FUNCTION transform_sqlset_cursor(
populate_cursor IN sqlset_cursor)
RETURN sys.sqlset PIPELINED;

FUNCTION accept_sql_profile(
task_name    IN VARCHAR2,
object_id    IN NUMBER   := NULL,
name         IN VARCHAR2 := NULL,
description  IN VARCHAR2 := NULL,
category     IN VARCHAR2 := NULL,
task_owner   IN VARCHAR2 := NULL,
replace      IN BOOLEAN  := FALSE,
force_match  IN BOOLEAN  := FALSE,
profile_type IN VARCHAR2 := REGULAR_PROFILE)
RETURN VARCHAR2;

PROCEDURE accept_sql_profile(
task_name    IN VARCHAR2,
object_id    IN NUMBER   := NULL,
name         IN VARCHAR2 := NULL,
description  IN VARCHAR2 := NULL,
category     IN VARCHAR2 := NULL,
task_owner   IN VARCHAR2 := NULL,
replace      IN BOOLEAN  := FALSE,
force_match  IN BOOLEAN  := FALSE,
profile_type IN VARCHAR2 := REGULAR_PROFILE);

PROCEDURE drop_sql_profile(
name          IN VARCHAR2,
ignore        IN BOOLEAN  := FALSE);

PROCEDURE alter_sql_profile(
name                 IN VARCHAR2,
attribute_name       IN VARCHAR2,
value                IN VARCHAR2);

PROCEDURE import_sql_profile(
sql_text      IN CLOB,
profile       IN sqlprof_attr,
name          IN VARCHAR2 := NULL,
description   IN VARCHAR2 := NULL,
category      IN VARCHAR2 := NULL,
validate      IN BOOLEAN  := TRUE,
replace       IN BOOLEAN  := FALSE,
force_match   IN BOOLEAN  := FALSE);

PROCEDURE import_sql_profile(
sql_text      IN CLOB,
profile_xml   IN CLOB,
name          IN VARCHAR2 := NULL,
description   IN VARCHAR2 := NULL,
category      IN VARCHAR2 := NULL,
validate      IN BOOLEAN  := TRUE,
replace       IN BOOLEAN  := FALSE,
force_match   IN BOOLEAN  := FALSE);

FUNCTION sqltext_to_signature(sql_text    IN CLOB,
force_match IN BOOLEAN  := FALSE)
RETURN NUMBER;

FUNCTION sqltext_to_signature(sql_text    IN CLOB,
force_match IN BINARY_INTEGER)
RETURN NUMBER;


PROCEDURE create_stgtab_sqlprof(
table_name            IN VARCHAR2,
schema_name           IN VARCHAR2 := NULL,
tablespace_name       IN VARCHAR2 := NULL);

PROCEDURE pack_stgtab_sqlprof(
profile_name          IN VARCHAR2 := '%',
profile_category      IN VARCHAR2 := 'DEFAULT',
staging_table_name    IN VARCHAR2,
staging_schema_owner  IN VARCHAR2 := NULL);

PROCEDURE unpack_stgtab_sqlprof(
profile_name          IN VARCHAR2 := '%',
profile_category      IN VARCHAR2 := '%',
replace               IN BOOLEAN,
staging_table_name    IN VARCHAR2,
staging_schema_owner  IN VARCHAR2 := NULL);

PROCEDURE remap_stgtab_sqlprof(
old_profile_name      IN VARCHAR2,
new_profile_name      IN VARCHAR2 := NULL,
new_profile_category  IN VARCHAR2 := NULL,
staging_table_name    IN VARCHAR2,
staging_schema_owner  IN VARCHAR2 := NULL);

FUNCTION report_sql_monitor(
sql_id                    in varchar2 default  NULL,
session_id                in number   default  NULL,
session_serial            in number   default  NULL,
sql_exec_start            in date     default  NULL,
sql_exec_id               in number   default  NULL,
inst_id                   in number   default  NULL,
start_time_filter         in date     default  NULL,
end_time_filter           in date     default  NULL,
instance_id_filter        in number   default  NULL,
parallel_filter           in varchar2 default  NULL,
plan_line_filter          in number   default  NULL,
event_detail              in varchar2 default  'yes',
bucket_max_count          in number        
default  128,
bucket_interval           in number   default  NULL,
base_path                 in varchar2 default  NULL,
last_refresh_time         in date     default  NULL,
report_level              in varchar2 default 'TYPICAL',
type                      in varchar2 default 'TEXT',
sql_plan_hash_value       in number   default  NULL)
RETURN clob;


FUNCTION report_sql_monitor_xml(
sql_id                    in varchar2 default  NULL,
session_id                in number   default  NULL,
session_serial            in number   default  NULL,
sql_exec_start            in date     default  NULL,
sql_exec_id               in number   default  NULL,
inst_id                   in number   default  NULL,
start_time_filter         in date     default  NULL,
end_time_filter           in date     default  NULL,
instance_id_filter        in number   default  NULL,
parallel_filter           in varchar2 default  NULL,
plan_line_filter          in number   default  NULL,
event_detail              in varchar2 default  'yes',
bucket_max_count          in number   default  128,
bucket_interval           in number   default  NULL,
base_path                 in varchar2 default  NULL,
last_refresh_time         in date     default  NULL,
report_level              in varchar2 default 'TYPICAL',
auto_refresh              in number   default  NULL,
sql_plan_hash_value       in number   default  NULL)
return xmltype;


FUNCTION report_sql_monitor_list(
sql_id                    in varchar2 default  NULL,
session_id                in number   default  NULL,
session_serial            in number   default  NULL,
inst_id                   in number   default  NULL,
active_since_date         in date     default  NULL,
active_since_sec          in number   default  NULL,
last_refresh_time         in date     default  NULL,
report_level              in varchar2 default  'TYPICAL',
auto_refresh              in number   default  NULL,
base_path                 in varchar2 default  NULL,
type                      in varchar2 default 'TEXT')
RETURN clob;


FUNCTION report_sql_monitor_list_xml(
sql_id                    in varchar2 default  NULL,
session_id                in number   default  NULL,
session_serial            in number   default  NULL,
inst_id                   in number   default  NULL,
active_since_date         in date     default  NULL,
active_since_sec          in number   default  NULL,
last_refresh_time         in date     default  NULL,
report_level              in varchar2 default  'TYPICAL',
auto_refresh              in number   default  NULL,
base_path                 in varchar2 default  NULL)
RETURN xmltype;


FUNCTION report_sql_detail(
sql_id                   in  varchar2   default NULL,
sql_plan_hash_value      in  number     default NULL,
start_time               in  date       default NULL,
duration                 in  number     default NULL,
inst_id                  in  number     default NULL,
dbid                     in  number     default NULL,
event_detail             in  varchar2   default 'yes',
bucket_max_count         in  number     default 128,
bucket_interval          in  number     default NULL,
top_n                    in  number     default 10,
report_level             in  varchar2   default 'typical',
type                     in  varchar2   default 'ACTIVE',
data_source              in  varchar2   default 'auto',
end_time                 in  date       default NULL,
duration_stats           in  number     default NULL)
RETURN clob;


FUNCTION report_sql_detail_xml(
sql_id                   in  varchar2   default NULL,
sql_plan_hash_value      in  number     default NULL,
start_time               in  date       default NULL,
duration                 in  number     default NULL,
inst_id                  in  number     default NULL,
dbid                     in  number     default NULL,
event_detail             in  varchar2   default 'yes',
bucket_max_count         in  number     default 128,
bucket_interval          in    
number     default NULL,
top_n                    in  number     default 10,
report_level             in  varchar2   default 'typical',
data_source              in  varchar2   default 'auto',
end_time                 in  date       default NULL,
duration_stats           in  number     default NULL)
return xmltype;


FUNCTION extract_bind(
bind_data   IN RAW,
bind_pos    IN PLS_INTEGER) RETURN SQL_BIND;

FUNCTION extract_binds(
bind_data IN RAW)
RETURN SQL_BIND_SET PIPELINED;

PROCEDURE set_auto_tuning_task_parameter(
parameter IN VARCHAR2,
value     IN VARCHAR2);

PROCEDURE set_auto_tuning_task_parameter(
parameter IN VARCHAR2,
value     IN NUMBER);

FUNCTION build_stash_xml(
session_id                in number   default  NULL,
session_serial            in number   default  NULL,
session_inst_id           in number   default  NULL,
px_mode                   in varchar2 default  'yes',
start_time                in date     default  NULL,
end_time                  in date     default  NULL,
missing_seconds           in number   default  NULL,
instance_low_filter       in number   default  0,
instance_high_filter      in number   default  10000,
bucket_max_count          in number   default  128,
bucket_interval           in number   default  NULL,
report_level              in varchar2 default 'TYPICAL',
cpu_cores                 in binary_integer  default  NULL,
is_hyper                  in varchar2        default  NULL)
RETURN xmltype;

PROCEDURE check_sqlset_privs(
sqlset_name   IN VARCHAR2,
sqlset_owner  IN VARCHAR2,
sqlset_create IN BOOLEAN := false,
read_only     IN BOOLEAN := false);

PROCEDURE check_sql_profile_priv(priv IN VARCHAR2);

PROCEDURE cap_sts_cbk(
sqlset_name    IN VARCHAR2,
iterations     IN POSITIVE,
cap_option     IN VARCHAR2,
cap_mode       IN NUMBER,
cbk_proc_name  IN VARCHAR2,
basic_filter   IN VARCHAR2 := NULL,
sqlset_owner   IN VARCHAR2 := NULL);

FUNCTION prepare_sqlset_statement(
sqlset_name        IN            VARCHAR2,
sqlset_owner       IN            VARCHAR2,
basic_filter       IN            VARCHAR2 := NULL,
stmt_filter        IN            BOOLEAN  := FALSE,
object_filter      IN            VARCHAR2 := NULL,
plan_filter        IN            VARCHAR2 := NULL,
rank1              IN            VARCHAR2 := NULL,
rank2              IN            VARCHAR2 := NULL,
rank3              IN            VARCHAR2 := NULL,
result_percentage  IN            NUMBER   := 1,
result_limit       IN            NUMBER   := NULL,
attribute_list     IN            VARCHAR2 := NULL,
attribute_selected IN OUT NOCOPY BINARY_INTEGER,
wrap_obj_ctor      IN            BOOLEAN := FALSE,
check_binds        IN            BOOLEAN := TRUE,
sts_id             OUT           NUMBER,
first_rows_hint    IN            BOOLEAN  :=  TRUE)
RETURN VARCHAR2;

FLAG_PREPAWR_WRAPCTOR  CONSTANT NUMBER := POWER(2, 0);
FLAG_PREPAWR_NOCKBINDS CONSTANT NUMBER := POWER(2, 1);
FLAG_PREPAWR_INCLBID   CONSTANT NUMBER := POWER(2, 2);

FUNCTION prepare_awr_statement(
begin_snap         IN             NUMBER,
end_snap           IN             NUMBER,
basic_filter       IN             VARCHAR2 := NULL,
stmt_filter        IN             BOOLEAN  := FALSE,
object_filter      IN             VARCHAR2 := NULL,
rank1              IN             VARCHAR2 := NULL,
rank2              IN             VARCHAR2 := NULL,
rank3              IN             VARCHAR2 := NULL,
result_percentage  IN             NUMBER   := 1,
result_limit       IN             NUMBER   := NULL,
attribute_list     IN             VARCHAR2 := NULL,
attribute_selected IN OUT NOCOPY  BINARY_INTEGER,
flags              IN             NUMBER   := 0)
RETURN VARCHAR2;

PROCEDURE sqlset_progress_stats(
sqlset_name        IN            VARCHAR2,
sqlset_owner       IN            VARCHAR2,
basic_filter       IN            VARCHAR2 := NULL,
plan_filter        IN            VARCHAR2 := NULL,
rank1              IN            VARCHAR2 := NULL,
rank2              IN            VARCHAR2 := NULL,
rank3           
IN            VARCHAR2 := NULL,
result_percentage  IN            NUMBER   := 1,
result_limit       IN            NUMBER   := NULL,
sql_count          OUT           NUMBER,
workload_time      OUT           NUMBER,
exec_type#         IN            PLS_INTEGER);

PROCEDURE examine_stgtab(
stgtab_owner       IN            VARCHAR2,
stgtab             IN            VARCHAR2,
sts_name           OUT           VARCHAR2,
sts_owner          OUT           VARCHAR2);

END BLOCK_DBMS_SQLTUNE;
/
</pre>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
CREATE OR REPLACE PACKAGE BODY disable_pack_dt.BLOCK_DBMS_SQLTUNE AS 

FUNCTION create_tuning_task(
sql_text    IN CLOB,
bind_list   IN sql_binds := NULL,
user_name   IN VARCHAR2  := NULL,
scope       IN VARCHAR2  := SCOPE_COMPREHENSIVE,
time_limit  IN NUMBER    := TIME_LIMIT_DEFAULT,
task_name   IN VARCHAR2  := NULL,
description IN VARCHAR2  := NULL)
RETURN VARCHAR2 IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION create_tuning_task(
sql_id          IN VARCHAR2,
plan_hash_value IN NUMBER   := NULL,
scope           IN VARCHAR2 := SCOPE_COMPREHENSIVE,
time_limit      IN NUMBER   := TIME_LIMIT_DEFAULT,
task_name       IN VARCHAR2 := NULL,
description     IN VARCHAR2 := NULL)
RETURN VARCHAR2 IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION create_tuning_task(
begin_snap      IN NUMBER,
end_snap        IN NUMBER,
sql_id          IN VARCHAR2,
plan_hash_value IN NUMBER   := NULL,
scope           IN VARCHAR2 := SCOPE_COMPREHENSIVE,
time_limit      IN NUMBER   := TIME_LIMIT_DEFAULT,
task_name       IN VARCHAR2 := NULL,
description     IN VARCHAR2 := NULL)
RETURN VARCHAR2 IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION create_tuning_task(
sqlset_name       IN VARCHAR2,
basic_filter      IN VARCHAR2 :=  NULL,
object_filter     IN VARCHAR2 :=  NULL,
rank1             IN VARCHAR2 :=  NULL,
rank2             IN VARCHAR2 :=  NULL,
rank3             IN VARCHAR2 :=  NULL,
result_percentage IN NUMBER   :=  NULL,
result_limit      IN NUMBER   :=  NULL,
scope             IN VARCHAR2 :=  SCOPE_COMPREHENSIVE,
time_limit        IN NUMBER   :=  TIME_LIMIT_DEFAULT,
task_name         IN VARCHAR2 :=  NULL,
description       IN VARCHAR2 :=  NULL,
plan_filter
IN VARCHAR2 :=  'MAX_ELAPSED_TIME',
sqlset_owner      IN VARCHAR2 :=  NULL)
RETURN VARCHAR2 IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION create_tuning_task(
spa_task_name     IN VARCHAR2,
spa_task_owner    IN VARCHAR2 :=  NULL,
spa_compare_exec  IN VARCHAR2 :=  NULL,
basic_filter      IN VARCHAR2 :=  NULL,
time_limit        IN NUMBER   :=  TIME_LIMIT_DEFAULT,
task_name         IN VARCHAR2 :=  NULL,
description       IN VARCHAR2 :=  NULL)
RETURN VARCHAR2 IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE set_tuning_task_parameter(
task_name IN VARCHAR2,
parameter IN VARCHAR2,
value     IN VARCHAR2) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE set_tuning_task_parameter(
task_name IN VARCHAR2,
parameter IN VARCHAR2,
value     IN NUMBER) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE set_tuning_task_parameter(
parameter IN VARCHAR2,
value     IN VARCHAR2) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE set_tuning_task_parameter(
parameter IN VARCHAR2,
value     IN NUMBER) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION execute_tuning_task(
task_name        IN VARCHAR2,
execution_name   IN VARCHAR2               := NULL,
execution_params IN dbms_advisor.argList   := NULL,
execution_desc   IN VARCHAR2               := NULL)
RETURN VARCHAR2 IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 

PROCEDURE execute_tuning_task(
task_name        IN VARCHAR2,
execution_name   IN VARCHAR2               := NULL,
execution_params IN dbms_advisor.argList   := NULL,
execution_desc   IN VARCHAR2               := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



procedure interrupt_tuning_task(task_name IN VARCHAR2) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE cancel_tuning_task(task_name IN VARCHAR2) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE reset_tuning_task(task_name IN VARCHAR2) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE drop_tuning_task(task_name IN VARCHAR2) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE resume_tuning_task(
task_name    IN VARCHAR2,
basic_filter IN VARCHAR2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION report_tuning_task(
task_name      IN VARCHAR2,
type           IN VARCHAR2 := TYPE_TEXT,
level          IN VARCHAR2 := LEVEL_TYPICAL,
section        IN VARCHAR2 := SECTION_ALL,
object_id      IN NUMBER   := NULL,
result_limit   IN NUMBER   := NULL,
owner_name     IN VARCHAR2 := NULL,
execution_name IN VARCHAR2 := NULL)
RETURN clob IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION script_tuning_task(
task_name      IN VARCHAR2,
rec_type       IN VARCHAR2 := REC_TYPE_ALL,
object_id      IN NUMBER   := NULL,
result_limit   IN NUMBER   := NULL,
owner_name     IN VARCHAR2 := NULL,
execution_name IN VARCHAR2 := NULL)
RETURN CLOB IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



PROCEDURE create_sql_plan_baseline(
task_name            IN VARCHAR2,
object_id            IN NUMBER := NULL,
plan_hash_value      IN NUMBER,
owner_name           IN VARCHAR2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE implement_tuning_task(
task_name      IN VARCHAR2,
rec_type       IN VARCHAR2 := REC_TYPE_SQL_PROFILES,
owner_name     IN VARCHAR2 := NULL,
execution_name IN VARCHAR2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg :=  
disable_pack_dt.get_err_msg_fn; 
END; 



FUNCTION report_auto_tuning_task(
begin_exec     IN VARCHAR2  := NULL,
end_exec       IN VARCHAR2  := NULL,
type           IN VARCHAR2  := TYPE_TEXT,
level          IN VARCHAR2  := LEVEL_TYPICAL,
section        IN VARCHAR2  := SECTION_ALL,
object_id      IN NUMBER    := NULL,
result_limit   IN NUMBER    := NULL)
RETURN CLOB IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 

PROCEDURE create_sqlset(
sqlset_name  IN VARCHAR2,
description  IN VARCHAR2 := NULL,
sqlset_owner IN VARCHAR2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION create_sqlset(
sqlset_name   IN VARCHAR2 := NULL,
description   IN VARCHAR2 := NULL,
sqlset_owner  IN VARCHAR2 := NULL)
RETURN VARCHAR2 IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE drop_sqlset(
sqlset_name   IN VARCHAR2,
sqlset_owner  IN VARCHAR2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE delete_sqlset(
sqlset_name  IN VARCHAR2,
basic_filter IN VARCHAR2 := NULL,
sqlset_owner IN VARCHAR2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE load_sqlset(
sqlset_name       IN VARCHAR2,
populate_cursor   IN sqlset_cursor,
load_option       IN VARCHAR2 := 'INSERT',
update_option     IN VARCHAR2 := 'REPLACE',
update_condition  IN VARCHAR2 :=  NULL,
update_attributes IN VARCHAR2 :=  NULL,
ignore_null       IN BOOLEAN  :=  TRUE,
commit_rows       IN POSITIVE :=  NULL,
sqlset_owner      IN VARCHAR2 :=  NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE capture_cursor_cache_sqlset(
sqlset_name         IN VARCHAR2,
time_limit          IN POSITIVE := 1800,
repeat_interval     IN POSITIVE := 300,
capture_option      IN VARCHAR2 := 'MERGE',
capture_mode        IN NUMBER   := MODE_REPLACE_OLD_STATS,
basic_filter        IN VARCHAR2 := NULL,
sqlset_owner        IN VARCHAR2 := NULL,
recursive_sql       IN VARCHAR2 := HAS_RECURSIVE_SQL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE update_sqlset(
sqlset_name     IN VARCHAR2,
sql_id          IN VARCHAR2,
attribute_name  IN VARCHAR2,
attribute_value IN VARCHAR2 := NULL,
sqlset_owner    IN VARCHAR2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE update_sqlset(
sqlset_name     IN VARCHAR2,
sql_id          IN VARCHAR2,
plan_hash_value IN NUMBER,
attribute_name  IN VARCHAR2,
attribute_value IN VARCHAR2 := NULL,
sqlset_owner    IN VARCHAR2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE update_sqlset(
sqlset_name     IN VARCHAR2,
sql_id          IN VARCHAR2,
attribute_name  IN VARCHAR2,
attribute_value IN NUMBER   := NULL,
sqlset_owner    IN VARCHAR2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE update_sqlset(
sqlset_name     IN VARCHAR2,
sql_id          IN VARCHAR2,
plan_hash_value IN NUMBER,
attribute_name  IN VARCHAR2,
attribute_value IN NUMBER   := NULL,
sqlset_owner    IN VARCHAR2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION add_sqlset_reference(
sqlset_name  IN VARCHAR2,
description  IN VARCHAR2 := NULL,
sqlset_owner IN VARCHAR2 := NULL)
RETURN NUMBER IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE remove_sqlset_reference(
sqlset_name  IN VARCHAR2,
reference_id IN NUMBER,
sqlset_owner IN VARCHAR2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION select_sqlset(
sqlset_name       IN VARCHAR2,
basic_filter      IN VARCHAR2 := NULL,
object_filter     IN VARCHAR2 :=    
NULL,
ranking_measure1  IN VARCHAR2 := NULL,
ranking_measure2  IN VARCHAR2 := NULL,
ranking_measure3  IN VARCHAR2 := NULL,
result_percentage IN NUMBER   := 1,
result_limit      IN NUMBER   := NULL,
attribute_list    IN VARCHAR2 := 'TYPICAL',
plan_filter       IN VARCHAR2 := NULL,
sqlset_owner      IN VARCHAR2 := NULL,
recursive_sql     IN VARCHAR2 := HAS_RECURSIVE_SQL)
RETURN sys.sqlset PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION select_cursor_cache(
basic_filter      IN VARCHAR2 := NULL,
object_filter     IN VARCHAR2 := NULL,
ranking_measure1  IN VARCHAR2 := NULL,
ranking_measure2  IN VARCHAR2 := NULL,
ranking_measure3  IN VARCHAR2 := NULL,
result_percentage IN NUMBER   := 1,
result_limit      IN NUMBER   := NULL,
attribute_list    IN VARCHAR2 := 'TYPICAL',
recursive_sql     IN VARCHAR2 := HAS_RECURSIVE_SQL)
RETURN sys.sqlset PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION select_workload_repository(
begin_snap        IN NUMBER,
end_snap          IN NUMBER,
basic_filter      IN VARCHAR2 := NULL,
object_filter     IN VARCHAR2 := NULL,
ranking_measure1  IN VARCHAR2 := NULL,
ranking_measure2  IN VARCHAR2 := NULL,
ranking_measure3  IN VARCHAR2 := NULL,
result_percentage IN NUMBER   := 1,
result_limit      IN NUMBER   := NULL,
attribute_list    IN VARCHAR2 := 'TYPICAL',
recursive_sql     IN VARCHAR2 := HAS_RECURSIVE_SQL)
RETURN sys.sqlset PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION select_workload_repository(
baseline_name     IN VARCHAR2,
basic_filter      IN VARCHAR2 := NULL,
object_filter     IN VARCHAR2 := NULL,
ranking_measure1  IN VARCHAR2 := NULL,
ranking_measure2  IN VARCHAR2 := NULL,
ranking_measure3  IN VARCHAR2 := NULL,
result_percentage IN NUMBER   := 1,
result_limit      IN NUMBER   := NULL,
attribute_list    IN VARCHAR2 := 'TYPICAL',
recursive_sql     IN VARCHAR2 := HAS_RECURSIVE_SQL)
RETURN sys.sqlset PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION select_sql_trace(
directory              IN VARCHAR2,
file_name              IN VARCHAR2 := NULL,
mapping_table_name     IN VARCHAR2 := NULL,
mapping_table_owner    IN VARCHAR2 := NULL,
select_mode            IN POSITIVE := SINGLE_EXECUTION,
options                IN BINARY_INTEGER := LIMITED_COMMAND_TYPE,
pattern_start          IN VARCHAR2 := NULL,
pattern_end            IN VARCHAR2 := NULL,
result_limit           IN POSITIVE := NULL)
RETURN sys.sqlset PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION select_sqlpa_task(
task_name         IN VARCHAR2,
task_owner        IN VARCHAR2 := NULL,
execution_name    IN VARCHAR2 := NULL,
level_filter      IN VARCHAR2 := 'REGRESSED',
basic_filter      IN VARCHAR2 := NULL,
object_filter     IN VARCHAR2 := NULL,
attribute_list    IN VARCHAR2 := 'TYPICAL')
RETURN sys.sqlset PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



PROCEDURE create_stgtab_sqlset(
table_name           IN VARCHAR2,
schema_name          IN VARCHAR2 := NULL,
tablespace_name      IN VARCHAR2 := NULL,
db_version           IN NUMBER   := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE pack_stgtab_sqlset(
sqlset_name          IN VARCHAR2,
sqlset_owner         IN VARCHAR2 := NULL,
staging_table_name   IN VARCHAR2,
staging_schema_owner IN VARCHAR2 := NULL,
db_version           IN NUMBER   := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE unpack_stgtab_sqlset(
sqlset_name          IN VARCHAR2 := '%',
sqlset_owner         IN VARCHAR2 := NULL,
replace              IN BOOLEAN,
staging_table_name   IN VARCHAR2,
staging_schema_owner IN VARCHAR2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg :=                     
disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE remap_stgtab_sqlset(
old_sqlset_name        IN VARCHAR2,
old_sqlset_owner       IN VARCHAR2 := NULL,
new_sqlset_name        IN VARCHAR2 := NULL,
new_sqlset_owner       IN VARCHAR2 := NULL,
staging_table_name     IN VARCHAR2,
staging_schema_owner   IN VARCHAR2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION transform_sqlset_cursor(
populate_cursor IN sqlset_cursor)
RETURN sys.sqlset PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION accept_sql_profile(
task_name    IN VARCHAR2,
object_id    IN NUMBER   := NULL,
name         IN VARCHAR2 := NULL,
description  IN VARCHAR2 := NULL,
category     IN VARCHAR2 := NULL,
task_owner   IN VARCHAR2 := NULL,
replace      IN BOOLEAN  := FALSE,
force_match  IN BOOLEAN  := FALSE,
profile_type IN VARCHAR2 := REGULAR_PROFILE)
RETURN VARCHAR2 IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE accept_sql_profile(
task_name    IN VARCHAR2,
object_id    IN NUMBER   := NULL,
name         IN VARCHAR2 := NULL,
description  IN VARCHAR2 := NULL,
category     IN VARCHAR2 := NULL,
task_owner   IN VARCHAR2 := NULL,
replace      IN BOOLEAN  := FALSE,
force_match  IN BOOLEAN  := FALSE,
profile_type IN VARCHAR2 := REGULAR_PROFILE) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE drop_sql_profile(
name          IN VARCHAR2,
ignore        IN BOOLEAN  := FALSE) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE alter_sql_profile(
name                 IN VARCHAR2,
attribute_name       IN VARCHAR2,
value                IN VARCHAR2) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE import_sql_profile(
sql_text      IN CLOB,
profile       IN sqlprof_attr,
name          IN VARCHAR2 := NULL,
description   IN VARCHAR2 := NULL,
category      IN VARCHAR2 := NULL,
validate      IN BOOLEAN  := TRUE,
replace       IN BOOLEAN  := FALSE,
force_match   IN BOOLEAN  := FALSE) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE import_sql_profile(
sql_text      IN CLOB,
profile_xml   IN CLOB,
name          IN VARCHAR2 := NULL,
description   IN VARCHAR2 := NULL,
category      IN VARCHAR2 := NULL,
validate      IN BOOLEAN  := TRUE,
replace       IN BOOLEAN  := FALSE,
force_match   IN BOOLEAN  := FALSE) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION sqltext_to_signature(sql_text    IN CLOB,
force_match IN BOOLEAN  := FALSE)
RETURN NUMBER IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION sqltext_to_signature(sql_text    IN CLOB,
force_match IN BINARY_INTEGER)
RETURN NUMBER IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



PROCEDURE create_stgtab_sqlprof(
table_name            IN VARCHAR2,
schema_name           IN VARCHAR2 := NULL,
tablespace_name       IN VARCHAR2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE pack_stgtab_sqlprof(
profile_name          IN VARCHAR2 := '%',
profile_category      IN VARCHAR2 := 'DEFAULT',
staging_table_name    IN VARCHAR2,
staging_schema_owner  IN VARCHAR2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE unpack_stgtab_sqlprof(
profile_name          IN VARCHAR2 := '%',
profile_category      IN VARCHAR2 := '%',
replace               IN BOOLEAN,
staging_table_name    IN VARCHAR2,
staging_schema_owner  IN VARCHAR2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE remap_stgtab_sqlprof(
old_profile_name      IN VARCHAR2,
new_profile_name      IN VARCHAR2 := NULL,
new_profile_category
IN VARCHAR2 := NULL,
staging_table_name    IN VARCHAR2,
staging_schema_owner  IN VARCHAR2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION report_sql_monitor(
sql_id                    in varchar2 default  NULL,
session_id                in number   default  NULL,
session_serial            in number   default  NULL,
sql_exec_start            in date     default  NULL,
sql_exec_id               in number   default  NULL,
inst_id                   in number   default  NULL,
start_time_filter         in date     default  NULL,
end_time_filter           in date     default  NULL,
instance_id_filter        in number   default  NULL,
parallel_filter           in varchar2 default  NULL,
plan_line_filter          in number   default  NULL,
event_detail              in varchar2 default  'yes',
bucket_max_count          in number   default  128,
bucket_interval           in number   default  NULL,
base_path                 in varchar2 default  NULL,
last_refresh_time         in date     default  NULL,
report_level              in varchar2 default 'TYPICAL',
type                      in varchar2 default 'TEXT',
sql_plan_hash_value       in number   default  NULL)
RETURN clob IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



FUNCTION report_sql_monitor_xml(
sql_id                    in varchar2 default  NULL,
session_id                in number   default  NULL,
session_serial            in number   default  NULL,
sql_exec_start            in date     default  NULL,
sql_exec_id               in number   default  NULL,
inst_id                   in number   default  NULL,
start_time_filter         in date     default  NULL,
end_time_filter           in date     default  NULL,
instance_id_filter        in number   default  NULL,
parallel_filter           in varchar2 default  NULL,
plan_line_filter          in number   default  NULL,
event_detail              in varchar2 default  'yes',
bucket_max_count          in number   default  128,
bucket_interval           in number   default  NULL,
base_path                 in varchar2 default  NULL,
last_refresh_time         in date     default  NULL,
report_level              in varchar2 default 'TYPICAL',
auto_refresh              in number   default  NULL,
sql_plan_hash_value       in number   default  NULL)
return xmltype IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



FUNCTION report_sql_monitor_list(
sql_id                    in varchar2 default  NULL,
session_id                in number   default  NULL,
session_serial            in number   default  NULL,
inst_id                   in number   default  NULL,
active_since_date         in date     default  NULL,
active_since_sec          in number   default  NULL,
last_refresh_time         in date     default  NULL,
report_level              in varchar2 default  'TYPICAL',
auto_refresh              in number   default  NULL,
base_path                 in varchar2 default  NULL,
type                      in varchar2 default 'TEXT')
RETURN clob IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



FUNCTION report_sql_monitor_list_xml(
sql_id                    in varchar2 default  NULL,
session_id                in number   default  NULL,
session_serial            in number   default  NULL,
inst_id                   in number   default  NULL,
active_since_date         in date     default  NULL,
active_since_sec          in number   default  NULL,
last_refresh_time         in date     default  NULL,
report_level              in varchar2 default  'TYPICAL',
auto_refresh              in number   default  NULL,
base_path                 in varchar2 default  NULL)
RETURN xmltype IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



FUNCTION report_sql_detail(
sql_id                   in  varchar2   default NULL,
sql_plan_hash_value      in  number   
default NULL,
start_time               in  date       default NULL,
duration                 in  number     default NULL,
inst_id                  in  number     default NULL,
dbid                     in  number     default NULL,
event_detail             in  varchar2   default 'yes',
bucket_max_count         in  number     default 128,
bucket_interval          in  number     default NULL,
top_n                    in  number     default 10,
report_level             in  varchar2   default 'typical',
type                     in  varchar2   default 'ACTIVE',
data_source              in  varchar2   default 'auto',
end_time                 in  date       default NULL,
duration_stats           in  number     default NULL)
RETURN clob IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



FUNCTION report_sql_detail_xml(
sql_id                   in  varchar2   default NULL,
sql_plan_hash_value      in  number     default NULL,
start_time               in  date       default NULL,
duration                 in  number     default NULL,
inst_id                  in  number     default NULL,
dbid                     in  number     default NULL,
event_detail             in  varchar2   default 'yes',
bucket_max_count         in  number     default 128,
bucket_interval          in  number     default NULL,
top_n                    in  number     default 10,
report_level             in  varchar2   default 'typical',
data_source              in  varchar2   default 'auto',
end_time                 in  date       default NULL,
duration_stats           in  number     default NULL)
return xmltype IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



FUNCTION extract_bind(
bind_data   IN RAW,
bind_pos    IN PLS_INTEGER) RETURN SQL_BIND IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION extract_binds(
bind_data IN RAW)
RETURN SQL_BIND_SET PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 




PROCEDURE set_auto_tuning_task_parameter(
parameter IN VARCHAR2,
value     IN VARCHAR2) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE set_auto_tuning_task_parameter(
parameter IN VARCHAR2,
value     IN NUMBER) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION build_stash_xml(
session_id                in number   default  NULL,
session_serial            in number   default  NULL,
session_inst_id           in number   default  NULL,
px_mode                   in varchar2 default  'yes',
start_time                in date     default  NULL,
end_time                  in date     default  NULL,
missing_seconds           in number   default  NULL,
instance_low_filter       in number   default  0,
instance_high_filter      in number   default  10000,
bucket_max_count          in number   default  128,
bucket_interval           in number   default  NULL,
report_level              in varchar2 default 'TYPICAL',
cpu_cores                 in binary_integer  default  NULL,
is_hyper                  in varchar2        default  NULL)
RETURN xmltype IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE check_sqlset_privs(
sqlset_name   IN VARCHAR2,
sqlset_owner  IN VARCHAR2,
sqlset_create IN BOOLEAN := false,
read_only     IN BOOLEAN := false) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE check_sql_profile_priv(priv IN VARCHAR2) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE cap_sts_cbk(
sqlset_name    IN VARCHAR2,
iterations     IN POSITIVE,
cap_option     IN VARCHAR2,
cap_mode       IN NUMBER,
cbk_proc_name  IN VARCHAR2,
basic_filter   IN VARCHAR2 := NULL,
sqlset_owner   IN VARCHAR2 := NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 

END; 


FUNCTION prepare_sqlset_statement(
sqlset_name        IN            VARCHAR2,
sqlset_owner       IN            VARCHAR2,
basic_filter       IN            VARCHAR2 := NULL,
stmt_filter        IN            BOOLEAN  := FALSE,
object_filter      IN            VARCHAR2 := NULL,
plan_filter        IN            VARCHAR2 := NULL,
rank1              IN            VARCHAR2 := NULL,
rank2              IN            VARCHAR2 := NULL,
rank3              IN            VARCHAR2 := NULL,
result_percentage  IN            NUMBER   := 1,
result_limit       IN            NUMBER   := NULL,
attribute_list     IN            VARCHAR2 := NULL,
attribute_selected IN OUT NOCOPY BINARY_INTEGER,
wrap_obj_ctor      IN            BOOLEAN := FALSE,
check_binds        IN            BOOLEAN := TRUE,
sts_id             OUT           NUMBER,
first_rows_hint    IN            BOOLEAN  :=  TRUE)
RETURN VARCHAR2 IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION prepare_awr_statement(
begin_snap         IN             NUMBER,
end_snap           IN             NUMBER,
basic_filter       IN             VARCHAR2 := NULL,
stmt_filter        IN             BOOLEAN  := FALSE,
object_filter      IN             VARCHAR2 := NULL,
rank1              IN             VARCHAR2 := NULL,
rank2              IN             VARCHAR2 := NULL,
rank3              IN             VARCHAR2 := NULL,
result_percentage  IN             NUMBER   := 1,
result_limit       IN             NUMBER   := NULL,
attribute_list     IN             VARCHAR2 := NULL,
attribute_selected IN OUT NOCOPY  BINARY_INTEGER,
flags              IN             NUMBER   := 0)
RETURN VARCHAR2 IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE sqlset_progress_stats(
sqlset_name        IN            VARCHAR2,
sqlset_owner       IN            VARCHAR2,
basic_filter       IN            VARCHAR2 := NULL,
plan_filter        IN            VARCHAR2 := NULL,
rank1              IN            VARCHAR2 := NULL,
rank2              IN            VARCHAR2 := NULL,
rank3              IN            VARCHAR2 := NULL,
result_percentage  IN            NUMBER   := 1,
result_limit       IN            NUMBER   := NULL,
sql_count          OUT           NUMBER,
workload_time      OUT           NUMBER,
exec_type#         IN            PLS_INTEGER) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE examine_stgtab(
stgtab_owner       IN            VARCHAR2,
stgtab             IN            VARCHAR2,
sts_name           OUT           VARCHAR2,
sts_owner          OUT           VARCHAR2) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


END BLOCK_DBMS_SQLTUNE;

/
</pre>
<p><strong>BLOCK_DBMS_WORKLOAD_REPOSITORY</strong></p>
<p>NOTE &#8211; for this to compile, we first need to create the AWRRPT_INSTANCE_LIST_TYPE database type in the DISABLE_PACK_DT schema</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
--
-- Create this type in the DISABLE_PACK_DT schema to allow compilation of
-- BLOCK_DBMS_WORKLOAD_REPOSITORY package.
--
CREATE TYPE disable_pack_dt.awrrpt_instance_list_type AS TABLE OF NUMBER
/
</pre>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
CREATE OR REPLACE PACKAGE disable_pack_dt.BLOCK_DBMS_WORKLOAD_REPOSITORY AS


MIN_INTERVAL    CONSTANT NUMBER := 10;                       /* 10 minutes */
MAX_INTERVAL    CONSTANT NUMBER := 52560000;                  /* 100 years */

MIN_RETENTION   CONSTANT NUMBER := 1440;                          /* 1 day */
MAX_RETENTION   CONSTANT NUMBER := 52560000;                  /* 100 years */




PROCEDURE create_snapshot(flush_level IN VARCHAR2 DEFAULT 'TYPICAL'
);

FUNCTION create_snapshot(flush_level IN VARCHAR2 DEFAULT 'TYPICAL'
)  RETURN NUMBER;


PROCEDURE drop_snapshot_range(low_snap_id      IN NUMBER,
high_snap_id     IN NUMBER,
dbid             IN NUMBER DEFAULT NULL
);



PROCEDURE modify_snapshot_settings(retention  IN NUMBER DEFAULT NULL,
interval   IN NUMBER DEFAULT NULL,
topnsql    IN NUMBER DEFAULT NULL,
dbid       IN NUMBER DEFAULT NULL
);


PROCEDURE modify_snapshot_settings(retention  IN NUMBER   DEFAULT NULL,
interval   IN NUMBER   DEFAULT NULL,
topnsql    IN VARCHAR2,
dbid       IN NUMBER   DEFAULT NULL
);



PROCEDURE add_colored_sql(sql_id         IN VARCHAR2,
dbid           IN NUMBER DEFAULT NULL
);



PROCEDURE remove_colored_sql(sql_id         IN VARCHAR2,
dbid           IN NUMBER DEFAULT NULL
);



PROCEDURE create_baseline(start_snap_id  IN NUMBER,
end_snap_id    IN NUMBER,
baseline_name  IN VARCHAR2,
dbid           IN NUMBER DEFAULT NULL,
expiration     IN NUMBER DEFAULT NULL
);

FUNCTION create_baseline(start_snap_id  IN NUMBER,
end_snap_id    IN NUMBER,
baseline_name  IN VARCHAR2,
dbid           IN NUMBER DEFAULT NULL,
expiration     IN NUMBER DEFAULT NULL
)  RETURN NUMBER;

PROCEDURE create_baseline(start_time     IN DATE,
end_time       IN DATE,
baseline_name  IN VARCHAR2,
dbid           IN NUMBER DEFAULT NULL,
expiration     IN NUMBER DEFAULT NULL
);

FUNCTION create_baseline(start_time     IN DATE,
end_time       IN DATE,
baseline_name  IN VARCHAR2,
dbid           IN NUMBER DEFAULT NULL,
expiration     IN NUMBER DEFAULT NULL
)  RETURN NUMBER;

FUNCTION select_baseline_details(l_baseline_id   IN NUMBER,
l_beg_snap      IN NUMBER DEFAULT NULL,
l_end_snap      IN NUMBER DEFAULT NULL,
l_dbid          IN NUMBER DEFAULT NULL)
RETURN awrbl_details_type_table PIPELINED;

FUNCTION select_baseline_metric(l_baseline_name  IN VARCHAR2,
l_dbid           IN NUMBER DEFAULT NULL,
l_instance_num   IN NUMBER DEFAULT NULL)
RETURN awrbl_metric_type_table PIPELINED;

PROCEDURE rename_baseline(old_baseline_name IN VARCHAR2,
new_baseline_name IN VARCHAR2,
dbid              IN NUMBER DEFAULT NULL
);

PROCEDURE modify_baseline_window_size(window_size IN NUMBER,
dbid        IN NUMBER DEFAULT NULL
);

PROCEDURE drop_baseline(baseline_name IN VARCHAR2,
cascade       IN BOOLEAN DEFAULT false,
dbid          IN NUMBER DEFAULT NULL
);


PROCEDURE create_baseline_template(start_time     IN DATE,
end_time       IN DATE,
baseline_name  IN VARCHAR2,
template_name  IN VARCHAR2,
expiration     IN NUMBER DEFAULT NULL,
dbid           IN NUMBER DEFAULT NULL
);

PROCEDURE create_baseline_template(day_of_week          IN VARCHAR2,
hour_in_day          IN NUMBER,
duration             IN NUMBER,
start_time           IN DATE,
end_time             IN DATE,
baseline_name_prefix IN VARCHAR2,
template_name        IN VARCHAR2,
expiration           IN NUMBER DEFAULT 35,
dbid                 IN NUMBER
DEFAULT NULL
);

PROCEDURE drop_baseline_template(template_name  IN VARCHAR2,
dbid           IN NUMBER DEFAULT NULL
);


FUNCTION awr_report_text(l_dbid     IN NUMBER,
l_inst_num IN NUMBER,
l_bid      IN NUMBER,
l_eid      IN NUMBER,
l_options  IN NUMBER DEFAULT 0)
RETURN awrrpt_text_type_table PIPELINED;

FUNCTION awr_report_html(l_dbid     IN NUMBER,
l_inst_num IN NUMBER,
l_bid      IN NUMBER,
l_eid      IN NUMBER,
l_options  IN NUMBER DEFAULT 0)
RETURN awrrpt_html_type_table PIPELINED;

FUNCTION awr_global_report_text(l_dbid     IN NUMBER,
l_inst_num IN AWRRPT_INSTANCE_LIST_TYPE,
l_bid      IN NUMBER,
l_eid      IN NUMBER,
l_options  IN NUMBER       
DEFAULT 0)
RETURN awrdrpt_text_type_table PIPELINED;
FUNCTION awr_global_report_text(l_dbid     IN NUMBER,
l_inst_num IN VARCHAR2,
l_bid      IN NUMBER,
l_eid      IN NUMBER,
l_options  IN NUMBER DEFAULT 0)
RETURN awrdrpt_text_type_table PIPELINED;

FUNCTION awr_global_report_html(l_dbid     IN NUMBER,
l_inst_num IN AWRRPT_INSTANCE_LIST_TYPE,
l_bid      IN NUMBER,
l_eid      IN NUMBER,
l_options  IN NUMBER DEFAULT 0)
RETURN awrrpt_html_type_table PIPELINED;
FUNCTION awr_global_report_html(l_dbid     IN NUMBER,
l_inst_num IN VARCHAR2,
l_bid      IN NUMBER,
l_eid      IN NUMBER,
l_options  IN NUMBER DEFAULT 0)
RETURN awrrpt_html_type_table PIPELINED;

FUNCTION awr_sql_report_text(l_dbid     IN NUMBER,
l_inst_num IN NUMBER,
l_bid      IN NUMBER,
l_eid      IN NUMBER,
l_sqlid    IN VARCHAR2,
l_options  IN NUMBER DEFAULT 0)
RETURN awrsqrpt_text_type_table PIPELINED;

FUNCTION awr_sql_report_html(l_dbid     IN NUMBER,
l_inst_num IN NUMBER,
l_bid      IN NUMBER,
l_eid      IN NUMBER,
l_sqlid    IN VARCHAR2,
l_options  IN NUMBER DEFAULT 0)
RETURN awrrpt_html_type_table PIPELINED;


FUNCTION awr_diff_report_text(dbid1     IN NUMBER,
inst_num1 IN NUMBER,
bid1      IN NUMBER,
eid1      IN NUMBER,
dbid2     IN NUMBER,
inst_num2 IN NUMBER,
bid2      IN NUMBER,
eid2      IN NUMBER)
RETURN awrdrpt_text_type_table PIPELINED;

FUNCTION awr_diff_report_html(dbid1     IN NUMBER,
inst_num1 IN NUMBER,
bid1      IN NUMBER,
eid1      IN NUMBER,
dbid2     IN NUMBER,
inst_num2 IN NUMBER,
bid2      IN NUMBER,
eid2      IN NUMBER)
RETURN awrrpt_html_type_table PIPELINED;

FUNCTION awr_global_diff_report_text(dbid1     IN NUMBER,
inst_num1 IN AWRRPT_INSTANCE_LIST_TYPE,
bid1      IN NUMBER,
eid1      IN NUMBER,
dbid2     IN NUMBER,
inst_num2 IN AWRRPT_INSTANCE_LIST_TYPE,
bid2      IN NUMBER,
eid2      IN NUMBER)
RETURN awrdrpt_text_type_table PIPELINED;
FUNCTION awr_global_diff_report_text(dbid1     IN NUMBER,
inst_num1 IN VARCHAR2,
bid1      IN NUMBER,
eid1      IN NUMBER,
dbid2     IN NUMBER,
inst_num2 IN VARCHAR2,
bid2      IN NUMBER,
eid2      IN NUMBER)
RETURN awrdrpt_text_type_table PIPELINED;

FUNCTION awr_global_diff_report_html(dbid1     IN NUMBER,
inst_num1 IN AWRRPT_INSTANCE_LIST_TYPE,
bid1      IN NUMBER,
eid1      IN NUMBER,
dbid2     IN NUMBER,
inst_num2 IN AWRRPT_INSTANCE_LIST_TYPE,
bid2      IN NUMBER,
eid2      IN NUMBER)
RETURN awrrpt_html_type_table PIPELINED;
FUNCTION awr_global_diff_report_html(dbid1     IN NUMBER,
inst_num1 IN VARCHAR2,
bid1      IN NUMBER,
eid1      IN NUMBER,
dbid2     IN NUMBER,
inst_num2 IN VARCHAR2,
bid2      IN NUMBER,
eid2      IN NUMBER)
RETURN awrrpt_html_type_table PIPELINED;


FUNCTION ash_report_text(l_dbid          IN NUMBER,
l_inst_num      IN NUMBER,
l_btime         IN DATE,
l_etime         IN DATE,
l_options       IN NUMBER    DEFAULT 0,
l_slot_width    IN NUMBER    DEFAULT 0,
l_sid           IN NUMBER    DEFAULT NULL,
l_sql_id        IN VARCHAR2  DEFAULT NULL,
l_wait_class    IN VARCHAR2  DEFAULT NULL,
l_service_hash  IN NUMBER    DEFAULT NULL,
l_module        IN VARCHAR2  DEFAULT NULL,
l_action        IN VARCHAR2  DEFAULT NULL,
l_client_id     IN VARCHAR2  DEFAULT NULL,
l_plsql_entry   IN VARCHAR2  DEFAULT NULL,
l_data_src      IN NUMBER    DEFAULT 0
)
RETURN awrrpt_text_type_table PIPELINED;

FUNCTION ash_report_html(l_dbid          IN NUMBER,
l_inst_num      IN NUMBER,
l_btime         IN DATE,
l_etime         IN DATE,
l_options       IN NUMBER    DEFAULT 0,
l_slot_width    IN NUMBER    DEFAULT 0,
l_sid           IN NUMBER    DEFAULT NULL,
l_sql_id        IN VARCHAR2  DEFAULT NULL,
l_wait_class    IN VARCHAR2  DEFAULT NULL,
l_service_hash  IN NUMBER    DEFAULT NULL,
l_module        IN VARCHAR2  DEFAULT NULL,
l_action        IN VARCHAR2  DEFAULT NULL,
l_client_id     IN VARCHAR2  DEFAULT NULL,
l_plsql_entry   IN VARCHAR2  DEFAULT NULL,
l_data_src      IN NUMBER    DEFAULT 0
)
RETURN awrrpt_html_type_table PIPELINED;
FUNCTION ash_global_report_text(l_dbid          IN NUMBER,
l_inst_num      IN       
VARCHAR2,
l_btime         IN DATE,
l_etime         IN DATE,
l_options       IN NUMBER    DEFAULT 0,
l_slot_width    IN NUMBER    DEFAULT 0,
l_sid           IN NUMBER    DEFAULT NULL,
l_sql_id        IN VARCHAR2  DEFAULT NULL,
l_wait_class    IN VARCHAR2  DEFAULT NULL,
l_service_hash  IN NUMBER    DEFAULT NULL,
l_module        IN VARCHAR2  DEFAULT NULL,
l_action        IN VARCHAR2  DEFAULT NULL,
l_client_id     IN VARCHAR2  DEFAULT NULL,
l_plsql_entry   IN VARCHAR2  DEFAULT NULL,
l_data_src      IN NUMBER    DEFAULT 0
)
RETURN awrdrpt_text_type_table PIPELINED;
FUNCTION ash_global_report_html(l_dbid          IN NUMBER,
l_inst_num      IN VARCHAR2,
l_btime         IN DATE,
l_etime         IN DATE,
l_options       IN NUMBER    DEFAULT 0,
l_slot_width    IN NUMBER    DEFAULT 0,
l_sid           IN NUMBER    DEFAULT NULL,
l_sql_id        IN VARCHAR2  DEFAULT NULL,
l_wait_class    IN VARCHAR2  DEFAULT NULL,
l_service_hash  IN NUMBER    DEFAULT NULL,
l_module        IN VARCHAR2  DEFAULT NULL,
l_action        IN VARCHAR2  DEFAULT NULL,
l_client_id     IN VARCHAR2  DEFAULT NULL,
l_plsql_entry   IN VARCHAR2  DEFAULT NULL,
l_data_src      IN NUMBER    DEFAULT 0
)
RETURN awrrpt_html_type_table PIPELINED;
PROCEDURE control_restricted_snapshot(allow IN BOOLEAN);

PROCEDURE awr_set_report_thresholds(top_n_events      IN NUMBER DEFAULT NULL,
top_n_files       IN NUMBER DEFAULT NULL,
top_n_segments    IN NUMBER DEFAULT NULL,
top_n_services    IN NUMBER DEFAULT NULL,
top_n_sql         IN NUMBER DEFAULT NULL,
top_n_sql_max     IN NUMBER DEFAULT NULL,
top_sql_pct       IN NUMBER DEFAULT NULL,
shmem_threshold   IN NUMBER DEFAULT NULL,
versions_threshold IN NUMBER DEFAULT NULL
);

PROCEDURE purge_sql_details(numrows IN NUMBER DEFAULT NULL,
dbid    IN NUMBER DEFAULT NULL);


PROCEDURE update_object_info(maxrows   IN  NUMBER  DEFAULT 0);

END BLOCK_DBMS_WORKLOAD_REPOSITORY;
/
</pre>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
CREATE OR REPLACE PACKAGE BODY disable_pack_dt.BLOCK_DBMS_WORKLOAD_REPOSITORY AS



MIN_INTERVAL    CONSTANT NUMBER := 10;                       /* 10 minutes */
MAX_INTERVAL    CONSTANT NUMBER := 52560000;                  /* 100 years */

MIN_RETENTION   CONSTANT NUMBER := 1440;                          /* 1 day */
MAX_RETENTION   CONSTANT NUMBER := 52560000;                  /* 100 years */




PROCEDURE create_snapshot(flush_level IN VARCHAR2 DEFAULT 'TYPICAL'
) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION create_snapshot(flush_level IN VARCHAR2 DEFAULT 'TYPICAL'
)  RETURN NUMBER IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



PROCEDURE drop_snapshot_range(low_snap_id      IN NUMBER,
high_snap_id     IN NUMBER,
dbid             IN NUMBER DEFAULT NULL
) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 




PROCEDURE modify_snapshot_settings(retention  IN NUMBER DEFAULT NULL,
interval   IN NUMBER DEFAULT NULL,
topnsql    IN NUMBER DEFAULT NULL,
dbid       IN NUMBER DEFAULT NULL
) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



PROCEDURE modify_snapshot_settings(retention  IN NUMBER   DEFAULT NULL,
interval   IN NUMBER   DEFAULT NULL,
topnsql    IN VARCHAR2,
dbid       IN NUMBER   DEFAULT NULL
) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 




PROCEDURE add_colored_sql(sql_id         IN VARCHAR2,
dbid           IN NUMBER DEFAULT NULL
) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 




PROCEDURE remove_colored_sql(sql_id         IN VARCHAR2,
dbid           IN NUMBER DEFAULT NULL
) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 




PROCEDURE create_baseline(start_snap_id  IN NUMBER,
end_snap_id    IN NUMBER,
baseline_name  IN VARCHAR2,
dbid           IN NUMBER DEFAULT NULL,
expiration     IN NUMBER DEFAULT NULL
) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION create_baseline(start_snap_id  IN NUMBER,
end_snap_id    IN NUMBER,
baseline_name  IN VARCHAR2,
dbid           IN NUMBER DEFAULT NULL,
expiration     IN NUMBER DEFAULT NULL
)  RETURN NUMBER IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE create_baseline(start_time     IN DATE,
end_time       IN DATE,
baseline_name  IN VARCHAR2,
dbid           IN NUMBER DEFAULT NULL,
expiration     IN NUMBER DEFAULT NULL
) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION create_baseline(start_time     IN DATE,
end_time       IN DATE,
baseline_name  IN VARCHAR2,
dbid           IN NUMBER DEFAULT NULL,
expiration     IN NUMBER DEFAULT NULL
)  RETURN NUMBER IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION select_baseline_details(l_baseline_id   IN NUMBER,
l_beg_snap      IN NUMBER DEFAULT NULL,
l_end_snap      IN NUMBER DEFAULT NULL,
l_dbid          IN NUMBER DEFAULT NULL)
RETURN awrbl_details_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION select_baseline_metric(l_baseline_name  IN VARCHAR2,
l_dbid           IN NUMBER DEFAULT NULL,
l_instance_num   IN NUMBER DEFAULT NULL)
RETURN awrbl_metric_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE rename_baseline(old_baseline_name IN VARCHAR2,
new_baseline_name IN VARCHAR2,
dbid              IN NUMBER DEFAULT NULL
) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE modify_baseline_window_size(window_size IN NUMBER,
dbid        IN NUMBER DEFAULT NULL
) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE                   
drop_baseline(baseline_name IN VARCHAR2,
cascade       IN BOOLEAN DEFAULT false,
dbid          IN NUMBER DEFAULT NULL
) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



PROCEDURE create_baseline_template(start_time     IN DATE,
end_time       IN DATE,
baseline_name  IN VARCHAR2,
template_name  IN VARCHAR2,
expiration     IN NUMBER DEFAULT NULL,
dbid           IN NUMBER DEFAULT NULL
) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE create_baseline_template(day_of_week          IN VARCHAR2,
hour_in_day          IN NUMBER,
duration             IN NUMBER,
start_time           IN DATE,
end_time             IN DATE,
baseline_name_prefix IN VARCHAR2,
template_name        IN VARCHAR2,
expiration           IN NUMBER DEFAULT 35,
dbid                 IN NUMBER
DEFAULT NULL
) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE drop_baseline_template(template_name  IN VARCHAR2,
dbid           IN NUMBER DEFAULT NULL
) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



FUNCTION awr_report_text(l_dbid     IN NUMBER,
l_inst_num IN NUMBER,
l_bid      IN NUMBER,
l_eid      IN NUMBER,
l_options  IN NUMBER DEFAULT 0)
RETURN awrrpt_text_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION awr_report_html(l_dbid     IN NUMBER,
l_inst_num IN NUMBER,
l_bid      IN NUMBER,
l_eid      IN NUMBER,
l_options  IN NUMBER DEFAULT 0)
RETURN awrrpt_html_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION awr_global_report_text(l_dbid     IN NUMBER,
l_inst_num IN AWRRPT_INSTANCE_LIST_TYPE,
l_bid      IN NUMBER,
l_eid      IN NUMBER,
l_options  IN NUMBER DEFAULT 0)
RETURN awrdrpt_text_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 

FUNCTION awr_global_report_text(l_dbid     IN NUMBER,
l_inst_num IN VARCHAR2,
l_bid      IN NUMBER,
l_eid      IN NUMBER,
l_options  IN NUMBER DEFAULT 0)
RETURN awrdrpt_text_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION awr_global_report_html(l_dbid     IN NUMBER,
l_inst_num IN AWRRPT_INSTANCE_LIST_TYPE,
l_bid      IN NUMBER,
l_eid      IN NUMBER,
l_options  IN NUMBER DEFAULT 0)
RETURN awrrpt_html_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 

FUNCTION awr_global_report_html(l_dbid     IN NUMBER,
l_inst_num IN VARCHAR2,
l_bid      IN NUMBER,
l_eid      IN NUMBER,
l_options  IN NUMBER DEFAULT 0)
RETURN awrrpt_html_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION awr_sql_report_text(l_dbid     IN NUMBER,
l_inst_num IN NUMBER,
l_bid      IN NUMBER,
l_eid      IN NUMBER,
l_sqlid    IN VARCHAR2,
l_options  IN NUMBER DEFAULT 0)
RETURN awrsqrpt_text_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION awr_sql_report_html(l_dbid     IN NUMBER,
l_inst_num IN NUMBER,
l_bid      IN NUMBER,
l_eid      IN NUMBER,
l_sqlid    IN VARCHAR2,
l_options  IN NUMBER DEFAULT 0)
RETURN awrrpt_html_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



FUNCTION awr_diff_report_text(dbid1     IN NUMBER,
inst_num1 IN NUMBER,
bid1      IN NUMBER,
eid1      IN NUMBER,
dbid2     IN NUMBER,
inst_num2 IN NUMBER,
bid2      IN NUMBER,
eid2      IN NUMBER)
RETURN awrdrpt_text_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION awr_diff_report_html(dbid1     IN NUMBER,
inst_num1 IN NUMBER,
bid1      IN NUMBER,
eid1      IN NUMBER,
dbid2     IN NUMBER,
inst_num2 IN NUMBER,
bid2      IN NUMBER,
eid2      IN NUMBER)
RETURN          
awrrpt_html_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION awr_global_diff_report_text(dbid1     IN NUMBER,
inst_num1 IN AWRRPT_INSTANCE_LIST_TYPE,
bid1      IN NUMBER,
eid1      IN NUMBER,
dbid2     IN NUMBER,
inst_num2 IN AWRRPT_INSTANCE_LIST_TYPE,
bid2      IN NUMBER,
eid2      IN NUMBER)
RETURN awrdrpt_text_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 

FUNCTION awr_global_diff_report_text(dbid1     IN NUMBER,
inst_num1 IN VARCHAR2,
bid1      IN NUMBER,
eid1      IN NUMBER,
dbid2     IN NUMBER,
inst_num2 IN VARCHAR2,
bid2      IN NUMBER,
eid2      IN NUMBER)
RETURN awrdrpt_text_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION awr_global_diff_report_html(dbid1     IN NUMBER,
inst_num1 IN AWRRPT_INSTANCE_LIST_TYPE,
bid1      IN NUMBER,
eid1      IN NUMBER,
dbid2     IN NUMBER,
inst_num2 IN AWRRPT_INSTANCE_LIST_TYPE,
bid2      IN NUMBER,
eid2      IN NUMBER)
RETURN awrrpt_html_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 

FUNCTION awr_global_diff_report_html(dbid1     IN NUMBER,
inst_num1 IN VARCHAR2,
bid1      IN NUMBER,
eid1      IN NUMBER,
dbid2     IN NUMBER,
inst_num2 IN VARCHAR2,
bid2      IN NUMBER,
eid2      IN NUMBER)
RETURN awrrpt_html_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



FUNCTION ash_report_text(l_dbid          IN NUMBER,
l_inst_num      IN NUMBER,
l_btime         IN DATE,
l_etime         IN DATE,
l_options       IN NUMBER    DEFAULT 0,
l_slot_width    IN NUMBER    DEFAULT 0,
l_sid           IN NUMBER    DEFAULT NULL,
l_sql_id        IN VARCHAR2  DEFAULT NULL,
l_wait_class    IN VARCHAR2  DEFAULT NULL,
l_service_hash  IN NUMBER    DEFAULT NULL,
l_module        IN VARCHAR2  DEFAULT NULL,
l_action        IN VARCHAR2  DEFAULT NULL,
l_client_id     IN VARCHAR2  DEFAULT NULL,
l_plsql_entry   IN VARCHAR2  DEFAULT NULL,
l_data_src      IN NUMBER    DEFAULT 0
)
RETURN awrrpt_text_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


FUNCTION ash_report_html(l_dbid          IN NUMBER,
l_inst_num      IN NUMBER,
l_btime         IN DATE,
l_etime         IN DATE,
l_options       IN NUMBER    DEFAULT 0,
l_slot_width    IN NUMBER    DEFAULT 0,
l_sid           IN NUMBER    DEFAULT NULL,
l_sql_id        IN VARCHAR2  DEFAULT NULL,
l_wait_class    IN VARCHAR2  DEFAULT NULL,
l_service_hash  IN NUMBER    DEFAULT NULL,
l_module        IN VARCHAR2  DEFAULT NULL,
l_action        IN VARCHAR2  DEFAULT NULL,
l_client_id     IN VARCHAR2  DEFAULT NULL,
l_plsql_entry   IN VARCHAR2  DEFAULT NULL,
l_data_src      IN NUMBER    DEFAULT 0
)
RETURN awrrpt_html_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 

FUNCTION ash_global_report_text(l_dbid          IN NUMBER,
l_inst_num      IN VARCHAR2,
l_btime         IN DATE,
l_etime         IN DATE,
l_options       IN NUMBER    DEFAULT 0,
l_slot_width    IN NUMBER    DEFAULT 0,
l_sid           IN NUMBER    DEFAULT NULL,
l_sql_id        IN VARCHAR2  DEFAULT NULL,
l_wait_class    IN VARCHAR2  DEFAULT NULL,
l_service_hash  IN NUMBER    DEFAULT NULL,
l_module        IN VARCHAR2  DEFAULT NULL,
l_action        IN VARCHAR2  DEFAULT NULL,
l_client_id     IN VARCHAR2  DEFAULT NULL,
l_plsql_entry   IN VARCHAR2  DEFAULT NULL,
l_data_src      IN NUMBER    DEFAULT 0
)
RETURN awrdrpt_text_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 

FUNCTION ash_global_report_html(l_dbid          IN NUMBER,
l_inst_num      IN VARCHAR2,
l_btime         IN DATE,
l_etime         IN DATE,
l_options       IN NUMBER    DEFAULT 0,
l_slot_width    IN NUMBER    DEFAULT 0,
l_sid           IN NUMBER    DEFAULT NULL,
l_sql_id        IN VARCHAR2        
DEFAULT NULL,
l_wait_class    IN VARCHAR2  DEFAULT NULL,
l_service_hash  IN NUMBER    DEFAULT NULL,
l_module        IN VARCHAR2  DEFAULT NULL,
l_action        IN VARCHAR2  DEFAULT NULL,
l_client_id     IN VARCHAR2  DEFAULT NULL,
l_plsql_entry   IN VARCHAR2  DEFAULT NULL,
l_data_src      IN NUMBER    DEFAULT 0
)
RETURN awrrpt_html_type_table PIPELINED IS 
l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 

PROCEDURE control_restricted_snapshot(allow IN BOOLEAN) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE awr_set_report_thresholds(top_n_events      IN NUMBER DEFAULT NULL,
top_n_files       IN NUMBER DEFAULT NULL,
top_n_segments    IN NUMBER DEFAULT NULL,
top_n_services    IN NUMBER DEFAULT NULL,
top_n_sql         IN NUMBER DEFAULT NULL,
top_n_sql_max     IN NUMBER DEFAULT NULL,
top_sql_pct       IN NUMBER DEFAULT NULL,
shmem_threshold   IN NUMBER DEFAULT NULL,
versions_threshold IN NUMBER DEFAULT NULL
) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


PROCEDURE purge_sql_details(numrows IN NUMBER DEFAULT NULL,
dbid    IN NUMBER DEFAULT NULL) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 



PROCEDURE update_object_info(maxrows   IN  NUMBER  DEFAULT 0) IS 
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 


END BLOCK_DBMS_WORKLOAD_REPOSITORY;

/
</pre>
<h4>Partial API member packages</h4>
<p>This leaves us with two packages to deal with, DBMS_ADVISOR and DBMS_WORKLOAD_REPLAY.</p>
<p>As we don&#8217;t necessarily want to block all access to these packages, we need to pass on any legitimate calls to their functions or procedures, whilst stopping anything that would require a license.</p>
<p>DBMS_WORKLOAD_REPLAY is by far the more straightforward case. Only a call to the COMPARE_PERIOD_REPORT function of this package will require a DIAGNOSTIC pack license.</p>
<p><strong>DBMS_WORKLOAD_REPLAY</strong></p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
CREATE OR REPLACE PACKAGE disable_pack_dt.BLOCK_DBMS_WORKLOAD_REPLAY AS

PROCEDURE PROCESS_CAPTURE( capture_dir        IN VARCHAR2,
parallel_level     IN NUMBER DEFAULT NULL);

FUNCTION PROCESS_CAPTURE_COMPLETION
RETURN NUMBER;

FUNCTION PROCESS_CAPTURE_REMAINING_TIME
RETURN NUMBER;

PROCEDURE INITIALIZE_REPLAY( replay_name     IN VARCHAR2,
replay_dir      IN VARCHAR2 );

PROCEDURE SET_ADVANCED_PARAMETER( pname  IN VARCHAR2,
pvalue IN VARCHAR2);
PROCEDURE SET_ADVANCED_PARAMETER( pname  IN VARCHAR2,
pvalue IN NUMBER);
PROCEDURE SET_ADVANCED_PARAMETER( pname  IN VARCHAR2,
pvalue IN BOOLEAN);

FUNCTION GET_ADVANCED_PARAMETER( pname IN VARCHAR2)
RETURN VARCHAR2;

PROCEDURE RESET_ADVANCED_PARAMETERS;

PROCEDURE SET_REPLAY_TIMEOUT(enabled       IN  BOOLEAN DEFAULT TRUE,
min_delay     IN  NUMBER  DEFAULT 10,
max_delay     IN  NUMBER  DEFAULT 120,
delay_factor  IN  NUMBER  DEFAULT 8);

PROCEDURE GET_REPLAY_TIMEOUT(enabled       OUT  BOOLEAN,
min_delay     OUT  NUMBER,
max_delay     OUT  NUMBER,
delay_factor  OUT  NUMBER);

PROCEDURE  PREPARE_REPLAY(synchronization         IN BOOLEAN,
connect_time_scale      IN NUMBER   DEFAULT 100,
think_time_scale        IN NUMBER   DEFAULT 100,
think_time_auto_correct IN BOOLEAN  DEFAULT TRUE,
scale_up_multiplier     IN NUMBER   DEFAULT 1,
capture_sts             IN BOOLEAN  DEFAULT FALSE,
sts_cap_interval        IN NUMBER   DEFAULT 300);

PROCEDURE  PREPARE_REPLAY(synchronization         IN VARCHAR2 DEFAULT 'SCN',
connect_time_scale      IN NUMBER   DEFAULT 100,
think_time_scale        IN NUMBER   DEFAULT 100,
think_time_auto_correct IN BOOLEAN  DEFAULT TRUE,
scale_up_multiplier     IN NUMBER   DEFAULT 1,
capture_sts             IN BOOLEAN  DEFAULT FALSE,
sts_cap_interval        IN NUMBER   DEFAULT 300);

PROCEDURE  START_REPLAY;

PROCEDURE  PAUSE_REPLAY;

PROCEDURE  RESUME_REPLAY;

FUNCTION IS_REPLAY_PAUSED
RETURN BOOLEAN;

PROCEDURE  CANCEL_REPLAY(reason    IN VARCHAR2 DEFAULT NULL);

FUNCTION GET_REPLAY_INFO(dir    IN VARCHAR2)
RETURN NUMBER;

PROCEDURE DELETE_REPLAY_INFO(replay_id    IN NUMBER);

PROCEDURE REMAP_CONNECTION(connection_id         IN  NUMBER,
replay_connection     IN  VARCHAR2);


TYPE_XML            CONSTANT   VARCHAR2(3) := 'XML'        ;
TYPE_HTML           CONSTANT   VARCHAR2(4) := 'HTML'       ;
TYPE_TEXT           CONSTANT   VARCHAR2(4) := 'TEXT'       ;

FUNCTION  REPORT( replay_id        IN NUMBER,
format           IN VARCHAR2 )
RETURN    CLOB;

PROCEDURE COMPARE_PERIOD_REPORT( replay_id1 IN NUMBER,
replay_id2 IN NUMBER,
format     IN VARCHAR2,
result     OUT CLOB );

FUNCTION COMPARE_SQLSET_REPORT( replay_id1    IN NUMBER,
replay_id2    IN NUMBER,
format        IN VARCHAR2,
r_level       IN VARCHAR2 := 'ALL',
r_sections    IN VARCHAR2 := 'ALL',
result        OUT CLOB )
RETURN VARCHAR2;


PROCEDURE EXPORT_AWR( replay_id             IN NUMBER );
PROCEDURE EXPORT_PERFORMANCE_DATA( replay_id IN NUMBER);

FUNCTION IMPORT_AWR( replay_id       IN NUMBER,
staging_schema  IN VARCHAR2,
force_cleanup   IN BOOLEAN DEFAULT FALSE )
RETURN NUMBER;
FUNCTION IMPORT_PERFORMANCE_DATA(
replay_id       IN NUMBER,
staging_schema  IN VARCHAR2,
force_cleanup   IN BOOLEAN DEFAULT FALSE )
RETURN NUMBER;

FUNCTION CALIBRATE (capture_dir          IN VARCHAR2,
process_per_cpu      IN BINARY_INTEGER DEFAULT 4,
threads_per_process  IN BINARY_INTEGER DEFAULT 50)
RETURN CLOB;

FUNCTION GET_CAPTURED_TABLES(capture_dir IN VARCHAR2)
RETURN CLOB;


FUNCTION GET_DIVERGING_STATEMENT(replay_id    IN NUMBER,
stream_id    IN NUMBER,
call_counter IN NUMBER)
RETURN CLOB;

PROCEDURE POPULATE_DIVERGENCE(replay_id    IN NUMBER,
stream_id    IN NUMBER  DEFAULT NULL,
call_counter IN NUMBER  DEFAULT NULL);

FUNCTION POPULATE_DIVERGENCE_STATUS(replay_id    IN NUMBER)
RETURN VARCHAR2;

FUNCTION DIVERGING_STATEMENT_STATUS(replay_id    IN NUMBER,
stream_id    IN NUMBER,
call_counter IN NUMBER)
RETURN VARCHAR2;

PROCEDURE ADD_FILTER( fname          IN VARCHAR2,
fattribute     IN VARCHAR2,
fvalue         IN VARCHAR2);
PROCEDURE ADD_FILTER( fname          IN VARCHAR2,
fattribute     IN VARCHAR2,
fvalue         IN NUMBER);

PROCEDURE DELETE_FILTER( fname       IN VARCHAR2);

PROCEDURE REUSE_REPLAY_FILTER_SET(replay_dir  IN VARCHAR2,
filter_set  IN VARCHAR2);


PROCEDURE CREATE_FILTER_SET(replay_dir     IN VARCHAR2,
filter_set     IN VARCHAR2,
default_action IN VARCHAR2 DEFAULT 'INCLUDE');

PROCEDURE USE_FILTER_SET(filter_set     IN VARCHAR2);

KECP_CLIENT_CONNECT_LOGIN      CONSTANT   NUMBER   := 1;
KECP_CLIENT_CONNECT_ADMIN      CONSTANT   NUMBER   := 2;
KECP_CLIENT_CONNECT_GOODBYE    CONSTANT   NUMBER   := 3;
KECP_CLIENT_CONNECT_THRDFAIL   CONSTANT   NUMBER   := 4;
KECP_CLIENT_CONNECT_CHKPPID    CONSTANT   NUMBER   := 5;
KECP_CLIENT_CONNECT_CLOCK_TICK CONSTANT   NUMBER   := 6;
KECP_CLIENT_CONNECT_CHK_VSN    CONSTANT   NUMBER   := 7;

KECP_CMD_END_OF_REPLAY         CONSTANT   NUMBER   := 1;
KECP_CMD_REPLAY_CANCELLED      CONSTANT   NUMBER   := 2;

FUNCTION CLIENT_CONNECT(who         IN NUMBER,
arg         IN NUMBER DEFAULT 0)
RETURN   NUMBER;

PROCEDURE CLIENT_VITALS(id          IN BINARY_INTEGER,
name        IN VARCHAR2,
value       IN NUMBER);

FUNCTION PROCESS_REPLAY_GRAPH
RETURN NUMBER;

FUNCTION SYNCPOINT_WAIT_TO_POST(wait_point IN NUMBER)
RETURN NUMBER;

TYPE uc_graph_record IS RECORD(time NUMBER, user_calls NUMBER, flags NUMBER);
TYPE uc_graph_table  IS TABLE OF uc_graph_record;

PROCEDURE export_uc_graph(replay_id NUMBER);
PROCEDURE import_uc_graph(replay_id NUMBER);
FUNCTION user_calls_graph(replay_id IN NUMBER)
RETURN uc_graph_table PIPELINED;
FUNCTION stop_sts_c(sts_name  IN VARCHAR2,
sts_owner IN VARCHAR2,
in_db_caprep OUT BOOLEAN)
RETURN BOOLEAN;



FUNCTION get_processing_path(capture_id IN NUMBER)
RETURN VARCHAR2;


FUNCTION get_replay_path(replay_id IN NUMBER)
RETURN VARCHAR2;

PROCEDURE initialize_replay_internal( replay_name    IN  VARCHAR2,
replay_dir     IN  VARCHAR2,
replay_type    IN  VARCHAR2);

PROCEDURE get_perf_data_export_status( replay_id      IN  NUMBER,
awr_data      OUT  VARCHAR2,
sts_data      OUT  VARCHAR2);

PROCEDURE set_attribute(capture_id IN NUMBER,
replay_id  IN NUMBER,
name       IN VARCHAR2, -- VARCHAR2(50)
value      IN VARCHAR2); -- VARCHAR2(200)

FUNCTION  get_attribute(capture_id IN NUMBER,
replay_id  IN NUMBER,
name       IN VARCHAR2)
RETURN VARCHAR2;

PROCEDURE delete_attribute(capture_id IN NUMBER,
replay_id  IN NUMBER,
name       IN VARCHAR2);

PROCEDURE persist_attributes(capture_id IN NUMBER);

PROCEDURE sync_attributes_from_file(capture_id IN NUMBER);

END BLOCK_DBMS_WORKLOAD_REPLAY;
/
</pre>
<pre class="brush: sql; highlight: [220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235]; title: ; wrap-lines: false; notranslate">
CREATE OR REPLACE PACKAGE BODY disable_pack_dt.BLOCK_DBMS_WORKLOAD_REPLAY AS
-------------------------------------------------------------------------------
-- Only the COMPARE_PERIOD_REPORT function is part of the DIAGNOSTIC pack.
-- For this pack, refer to the erroring function.
-- For everything else, just call the underlying procedure or function.
--
-------------------------------------------------------------------------------
PROCEDURE PROCESS_CAPTURE( 
    capture_dir IN VARCHAR2,
    parallel_level IN NUMBER DEFAULT NULL)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.PROCESS_CAPTURE(
        capture_dir =&gt; capture_dir,
        parallel_level =&gt; parallel_level);
END;

FUNCTION PROCESS_CAPTURE_COMPLETION
    RETURN NUMBER
IS
BEGIN 
    RETURN sys.DBMS_WORKLOAD_REPLAY.PROCESS_CAPTURE_COMPLETION;
END;

FUNCTION PROCESS_CAPTURE_REMAINING_TIME
    RETURN NUMBER
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.PROCESS_CAPTURE_REMAINING_TIME;
END;

PROCEDURE INITIALIZE_REPLAY( 
    replay_name IN VARCHAR2,
    replay_dir IN VARCHAR2 )
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.INITIALIZE_REPLAY(
        replay_name =&gt; replay_name,
        replay_dir =&gt; replay_dir);
END;

PROCEDURE SET_ADVANCED_PARAMETER( 
    pname  IN VARCHAR2,
    pvalue IN VARCHAR2)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.SET_ADVANCED_PARAMETER(
        pname =&gt; pname,
        pvalue =&gt; pvalue);
END;

PROCEDURE SET_ADVANCED_PARAMETER( 
    pname  IN VARCHAR2,
    pvalue IN NUMBER)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.SET_ADVANCED_PARAMETER(
        pname =&gt; pname,
        pvalue =&gt; pvalue);
END;

PROCEDURE SET_ADVANCED_PARAMETER( 
    pname IN VARCHAR2,
    pvalue IN BOOLEAN)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.SET_ADVANCED_PARAMETER(
        pname =&gt; pname,
        pvalue =&gt; pvalue);
END;


FUNCTION GET_ADVANCED_PARAMETER( pname IN VARCHAR2)
    RETURN VARCHAR2
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.GET_ADVANCED_PARAMETER( pname =&gt; pname);
END;

PROCEDURE RESET_ADVANCED_PARAMETERS IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.RESET_ADVANCED_PARAMETERS;
END;

PROCEDURE SET_REPLAY_TIMEOUT(
    enabled IN BOOLEAN DEFAULT TRUE,
    min_delay     IN  NUMBER  DEFAULT 10,
    max_delay     IN  NUMBER  DEFAULT 120,
    delay_factor  IN  NUMBER  DEFAULT 8)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.SET_REPLAY_TIMEOUT(
        enabled =&gt; enabled,
        min_delay =&gt; min_delay,
        max_delay =&gt; max_delay,
        delay_factor =&gt; delay_factor);
END;

PROCEDURE GET_REPLAY_TIMEOUT(
    enabled       OUT  BOOLEAN,
    min_delay     OUT  NUMBER,
    max_delay     OUT  NUMBER,
    delay_factor  OUT  NUMBER)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.GET_REPLAY_TIMEOUT(
        enabled =&gt; enabled,
        min_delay =&gt; min_delay,
        max_delay =&gt; max_delay,
        delay_factor =&gt; delay_factor);
END;


PROCEDURE  PREPARE_REPLAY(
    synchronization         IN BOOLEAN,
    connect_time_scale      IN NUMBER   DEFAULT 100,
    think_time_scale        IN NUMBER   DEFAULT 100,
    think_time_auto_correct IN BOOLEAN  DEFAULT TRUE,
    scale_up_multiplier     IN NUMBER   DEFAULT 1,
    capture_sts             IN BOOLEAN  DEFAULT FALSE,
    sts_cap_interval        IN NUMBER   DEFAULT 300)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.PREPARE_REPLAY(
        synchronization =&gt; synchronization,
        connect_time_scale =&gt; connect_time_scale,
        think_time_scale =&gt; think_time_scale,
        think_time_auto_correct =&gt; think_time_auto_correct,
        scale_up_multiplier =&gt; scale_up_multiplier,
        capture_sts =&gt; capture_sts,
        sts_cap_interval =&gt; sts_cap_interval);
END;

PROCEDURE  PREPARE_REPLAY(
    synchronization         IN VARCHAR2 DEFAULT 'SCN',
    connect_time_scale      IN NUMBER   DEFAULT 100,
    think_time_scale        IN NUMBER   DEFAULT 100,
    think_time_auto_correct IN BOOLEAN  DEFAULT TRUE,
    scale_up_multiplier     IN NUMBER   DEFAULT 1,
    capture_sts             IN BOOLEAN  DEFAULT FALSE,
    sts_cap_interval        IN NUMBER   DEFAULT 300)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.PREPARE_REPLAY(
        synchronization =&gt; synchronization,
        connect_time_scale =&gt; connect_time_scale,
        think_time_scale =&gt; think_time_scale,
        think_time_auto_correct =&gt; think_time_auto_correct,
        scale_up_multiplier =&gt; scale_up_multiplier,
        capture_sts =&gt; capture_sts,
        sts_cap_interval =&gt; sts_cap_interval);
END;

PROCEDURE  START_REPLAY IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.START_REPLAY;
END;

PROCEDURE  PAUSE_REPLAY IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.PAUSE_REPLAY;
END;

PROCEDURE  RESUME_REPLAY IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.RESUME_REPLAY;
END;

FUNCTION IS_REPLAY_PAUSED
    RETURN BOOLEAN
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.IS_REPLAY_PAUSED;
END;

PROCEDURE  CANCEL_REPLAY(
    reason    IN VARCHAR2 DEFAULT NULL)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.CANCEL_REPLAY( reason =&gt; reason);
END;


FUNCTION GET_REPLAY_INFO(dir    IN VARCHAR2)
    RETURN NUMBER
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.GET_REPLAY_INFO(dir =&gt; dir);
END;

PROCEDURE DELETE_REPLAY_INFO(
    replay_id    IN NUMBER)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.DELETE_REPLAY_INFO( replay_id =&gt; replay_id);
END;

PROCEDURE REMAP_CONNECTION(
    connection_id         IN  NUMBER,
    replay_connection     IN  VARCHAR2)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.REMAP_CONNECTION(
        connection_id =&gt; connection_id,
        replay_connection =&gt; replay_connection);
END;


FUNCTION  REPORT( 
    replay_id        IN NUMBER,
    format           IN VARCHAR2 )
    RETURN    CLOB
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.REPORT(
        replay_id =&gt; replay_id,
        format =&gt; format);
END;

PROCEDURE COMPARE_PERIOD_REPORT( 
    replay_id1 IN NUMBER,
    replay_id2 IN NUMBER,
    format     IN VARCHAR2,
    result     OUT CLOB )
-------------------------------------------------------------------------------
-- This procedure is the one that we need to block. Instead of passing the
-- call through to the underlying package, call the 
-- DISABLE_PACK_DT.GET_ERR_MSG_FN to force an error.
--
-------------------------------------------------------------------------------
IS
    l_msg VARCHAR2(4000);
BEGIN 
    l_msg := disable_pack_dt.get_err_msg_fn; 
END; 

FUNCTION COMPARE_SQLSET_REPORT( 
    replay_id1    IN NUMBER,
    replay_id2    IN NUMBER,
    format        IN VARCHAR2,
    r_level       IN VARCHAR2 := 'ALL',
    r_sections    IN VARCHAR2 := 'ALL',
    result        OUT CLOB )
    RETURN VARCHAR2
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.COMPARE_SQLSET_REPORT(
        replay_id1 =&gt; replay_id1,
        replay_id2 =&gt; replay_id2,
        format =&gt; format,
        r_level =&gt; r_level,
        r_sections =&gt; r_sections,
        result =&gt; result);
END;

PROCEDURE EXPORT_AWR( replay_id             IN NUMBER ) IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.EXPORT_AWR( replay_id =&gt; replay_id);
END;

PROCEDURE EXPORT_PERFORMANCE_DATA( replay_id IN NUMBER) IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.EXPORT_PERFORMANCE_DATA( replay_id =&gt; replay_id);
END;

FUNCTION IMPORT_AWR( 
    replay_id       IN NUMBER,
    staging_schema  IN VARCHAR2,
    force_cleanup   IN BOOLEAN DEFAULT FALSE )
    RETURN NUMBER
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.IMPORT_AWR(
        replay_id =&gt; replay_id,
        staging_schema =&gt; staging_schema,
        force_cleanup =&gt; force_cleanup);
END;


FUNCTION IMPORT_PERFORMANCE_DATA(
    replay_id       IN NUMBER,
    staging_schema  IN VARCHAR2,
    force_cleanup   IN BOOLEAN DEFAULT FALSE )
    RETURN NUMBER
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.IMPORT_PERFORMANCE_DATA(
        replay_id =&gt; replay_id,
        staging_schema =&gt; staging_schema,
        force_cleanup =&gt; force_cleanup);
END;

FUNCTION CALIBRATE (
    capture_dir          IN VARCHAR2,
    process_per_cpu      IN BINARY_INTEGER DEFAULT 4,
    threads_per_process  IN BINARY_INTEGER DEFAULT 50)
    RETURN CLOB 
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.CALIBRATE(
        capture_dir =&gt; capture_dir,
        process_per_cpu =&gt; process_per_cpu,
        threads_per_process =&gt; threads_per_process);
END;

FUNCTION GET_CAPTURED_TABLES(capture_dir IN VARCHAR2)
    RETURN CLOB
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.GET_CAPTURED_TABLES(
        capture_dir =&gt; capture_dir);
END;


FUNCTION GET_DIVERGING_STATEMENT(
    replay_id    IN NUMBER,
    stream_id    IN NUMBER,
    call_counter IN NUMBER)
    RETURN CLOB
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.GET_DIVERGING_STATEMENT(
        replay_id =&gt; replay_id,
        stream_id =&gt; stream_id,
        call_counter =&gt; call_counter);
END;

PROCEDURE POPULATE_DIVERGENCE(
    replay_id    IN NUMBER,
    stream_id    IN NUMBER  DEFAULT NULL,
    call_counter IN NUMBER  DEFAULT NULL)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.POPULATE_DIVERGENCE(
        replay_id =&gt; replay_id,
        stream_id =&gt; stream_id,
        call_counter =&gt; call_counter);
END;

FUNCTION POPULATE_DIVERGENCE_STATUS(replay_id    IN NUMBER)
    RETURN VARCHAR2
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.POPULATE_DIVERGENCE_STATUS( replay_id =&gt; replay_id);
END;

FUNCTION DIVERGING_STATEMENT_STATUS(
    replay_id    IN NUMBER,
    stream_id    IN NUMBER,
    call_counter IN NUMBER)
    RETURN VARCHAR2 
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.DIVERGING_STATEMENT_STATUS(
        replay_id =&gt; replay_id,
        stream_id =&gt; stream_id,
        call_counter =&gt; call_counter);
END;

PROCEDURE ADD_FILTER( 
    fname          IN VARCHAR2,
    fattribute     IN VARCHAR2,
    fvalue         IN VARCHAR2)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.ADD_FILTER(
        fname =&gt; fname,
        fattribute =&gt; fattribute,
        fvalue =&gt; fvalue);
END;

PROCEDURE ADD_FILTER( 
    fname          IN VARCHAR2,
    fattribute     IN VARCHAR2,
    fvalue         IN NUMBER)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.ADD_FILTER(
        fname =&gt; fname,
        fattribute =&gt; fattribute,
        fvalue =&gt; fvalue);
END;        

PROCEDURE DELETE_FILTER( fname IN VARCHAR2) IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.DELETE_FILTER( fname =&gt; fname);
END;

PROCEDURE REUSE_REPLAY_FILTER_SET(
    replay_dir  IN VARCHAR2,
    filter_set  IN VARCHAR2)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.REUSE_REPLAY_FILTER_SET(
        replay_dir =&gt; replay_dir,
        filter_set =&gt; filter_set);
END;

PROCEDURE CREATE_FILTER_SET(
    replay_dir     IN VARCHAR2,
    filter_set     IN VARCHAR2,
    default_action IN VARCHAR2 DEFAULT 'INCLUDE')
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.CREATE_FILTER_SET(
        replay_dir =&gt; replay_dir,
        filter_set =&gt; filter_set,
        default_action =&gt; default_action);
END;

PROCEDURE USE_FILTER_SET(filter_set     IN VARCHAR2) IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.USE_FILTER_SET( filter_set =&gt; filter_set);
END;

FUNCTION CLIENT_CONNECT(
    who         IN NUMBER,
    arg         IN NUMBER DEFAULT 0)
    RETURN   NUMBER
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.CLIENT_CONNECT(
        who =&gt; who,
        arg =&gt; arg);
END;

PROCEDURE CLIENT_VITALS(
    id          IN BINARY_INTEGER,
    name        IN VARCHAR2,
    value       IN NUMBER)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.CLIENT_VITALS(
        id =&gt; id,
        name =&gt; name,
        value =&gt; value);
END;

FUNCTION PROCESS_REPLAY_GRAPH
    RETURN NUMBER
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.PROCESS_REPLAY_GRAPH;
END;

FUNCTION SYNCPOINT_WAIT_TO_POST(wait_point IN NUMBER)
    RETURN NUMBER
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.SYNCPOINT_WAIT_TO_POST( wait_point =&gt; wait_point);
END;

PROCEDURE export_uc_graph(replay_id NUMBER)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.EXPORT_UC_GRAPH( replay_id =&gt; replay_id);
END;

PROCEDURE import_uc_graph(replay_id NUMBER)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.EXPORT_UC_GRAPH( replay_id =&gt; replay_id);
END;

FUNCTION user_calls_graph(replay_id IN NUMBER)
RETURN uc_graph_table PIPELINED
IS
    --
    -- This is a bit tricky - can't just pass through the call to a pipelined
    -- function as we'll get PLS-00653 - aggregate/table functions are not allowed
    -- in a PL/SQL scope. So...
    --
    CURSOR c_function IS
        SELECT time, user_calls, flags
        FROM TABLE( sys.DBMS_WORKLOAD_REPLAY.USER_CALLS_GRAPH( replay_id));
    l_row c_function%ROWTYPE;
BEGIN
    LOOP
        FETCH c_function INTO l_row.time, l_row.user_calls, l_row.flags;
        EXIT WHEN c_function%NOTFOUND;
        PIPE ROW( l_row);
    END LOOP;
    CLOSE c_function;
    RETURN;
END;

FUNCTION stop_sts_c(
    sts_name  IN VARCHAR2,
    sts_owner IN VARCHAR2,
    in_db_caprep OUT BOOLEAN)
    RETURN BOOLEAN
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.STOP_STS_C(
        sts_name =&gt; sts_name,
        sts_owner =&gt; sts_owner,
        in_db_caprep =&gt; in_db_caprep);
END;


FUNCTION get_processing_path(capture_id IN NUMBER)
    RETURN VARCHAR2
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.GET_PROCESSING_PATH( capture_id =&gt; capture_id);
END;


FUNCTION get_replay_path(replay_id IN NUMBER)
    RETURN VARCHAR2
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.GET_REPLAY_PATH( replay_id =&gt; replay_id);
END;

PROCEDURE initialize_replay_internal( 
    replay_name    IN  VARCHAR2,
    replay_dir     IN  VARCHAR2,
    replay_type    IN  VARCHAR2)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.INITIALIZE_REPLAY_INTERNAL(
        replay_name =&gt; replay_name,
        replay_dir =&gt; replay_dir,
        replay_type =&gt; replay_type);
END;

PROCEDURE get_perf_data_export_status( 
    replay_id      IN  NUMBER,
    awr_data      OUT  VARCHAR2,
    sts_data      OUT  VARCHAR2)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.GET_PERF_DATA_EXPORT_STATUS(
        replay_id =&gt; replay_id,
        awr_data =&gt; awr_data,
        sts_data =&gt; sts_data);
END;

PROCEDURE set_attribute(
    capture_id IN NUMBER,
    replay_id  IN NUMBER,
    name       IN VARCHAR2, -- VARCHAR2(50)
    value      IN VARCHAR2) -- VARCHAR2(200)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.SET_ATTRIBUTE(
        capture_id =&gt; capture_id,
        replay_id =&gt; replay_id,
        name =&gt; name,
        value =&gt; value);
END;

FUNCTION  get_attribute(
    capture_id IN NUMBER,
    replay_id  IN NUMBER,
    name       IN VARCHAR2)
    RETURN VARCHAR2
IS
BEGIN
    RETURN sys.DBMS_WORKLOAD_REPLAY.GET_ATTRIBUTE(
        capture_id =&gt; capture_id,
        replay_id =&gt; replay_id,
        name =&gt; name);
END;

PROCEDURE delete_attribute(
    capture_id IN NUMBER,
    replay_id  IN NUMBER,
    name       IN VARCHAR2)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.DELETE_ATTRIBUTE(
        capture_id =&gt; capture_id,
        replay_id =&gt; replay_id,
        name =&gt; name);
END;

PROCEDURE persist_attributes(capture_id IN NUMBER)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.PERSIST_ATTRIBUTES(capture_id =&gt; capture_id);
END;

PROCEDURE sync_attributes_from_file(capture_id IN NUMBER)
IS
BEGIN
    sys.DBMS_WORKLOAD_REPLAY.SYNC_ATTRIBUTES_FROM_FILE(
        capture_id =&gt; capture_id);
END;

END BLOCK_DBMS_WORKLOAD_REPLAY;
/
</pre>
<p>For the DBMS_ADVISOR package, things are bit more complicated.<br />
Remember, this is the only package ( as at 11g) that is a member of both the Diagnostic and the Tuning Pack.</p>
<p>For the use of this package to be deemed part of the Diagnostic Pack, a package member must be called with an advisor_name parameter value of ADDM or with a task_name parameter that starts ADDM.<br />
For the Tuning Pack, the advisor_name parameter must be set to either &#8216;SQL Tuning Advisor&#8217; or &#8216;SQL Access Advisor&#8217;.</p>
<p>We can perform all of these checks in a simple function like this :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
FUNCTION license_check_fn( i_name IN VARCHAR2, i_value IN VARCHAR2) 
    RETURN BOOLEAN 
IS 
    l_msg VARCHAR2(4000); 
BEGIN 
    IF UPPER(i_name) = 'ADVISOR_NAME' 
        AND UPPER(i_value) IN ( 
            'ADDM', 'SQL TUNING ADVISOR', 'SQL ACCESS ADVISOR') 
    THEN 
        -- 
        -- Cause the pack license error to be raised. 
        -- 
        l_msg := disable_pack_dt.get_err_msg_fn; 
    ELSIF UPPER(i_name) = 'TASK_NAME' 
        AND UPPER( i_value) LIKE 'ADDM%' 
    THEN 
        -- 
        -- cause the pack license error to be raised. 
        -- 
        l_msg := disable_pack_dt.get_err_msg_fn; 
    END IF; 
    -- 
    -- If we get here then we haven't raised an error so OK to continue. 
    -- 
    RETURN TRUE; 
END;
</pre>
<p>If we just include this as a private function in the body of the package, we should be ready to go.<br />
So, start with the pacakge header :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
CREATE OR REPLACE PACKAGE disable_pack_dt.BLOCK_DBMS_ADVISOR
authid current_user
IS


ADV_NAME_DEFAULT         constant varchar2(30) := 'Default Advisor';
ADV_NAME_ADDM            constant varchar2(30) := 'ADDM';
ADV_NAME_SQLACCESS       constant varchar2(30) := 'SQL Access Advisor';
ADV_NAME_UNDO            constant varchar2(30) := 'Undo Advisor';
ADV_NAME_SQLTUNE         constant varchar2(30) := 'SQL Tuning Advisor';
ADV_NAME_SEGMENT         constant varchar2(30) := 'Segment Advisor';
ADV_NAME_SQLWM           constant varchar2(30) := 'SQL Workload Manager';
ADV_NAME_TUNEMV          constant varchar2(30) := 'Tune MView';
ADV_NAME_SQLPA           constant varchar2(30) := 'SQL Performance Analyzer';
ADV_NAME_SQLREPAIR       constant varchar2(30) := 'SQL Repair Advisor';
ADV_NAME_COMPRESS        constant varchar2(30) := 'Compression Advisor';

ADV_ID_DEFAULT           constant number := 0;
ADV_ID_ADDM              constant number := 1;
ADV_ID_SQLACCESS         constant number := 2;
ADV_ID_UNDO              constant number := 3;
ADV_ID_SQLTUNE           constant number := 4;
ADV_ID_SEGMENT           constant number := 5;
ADV_ID_SQLWM             constant number := 6;
ADV_ID_TUNEMV            constant number := 7;
ADV_ID_SQLPA             constant number := 8;
ADV_ID_SQLREPAIR         constant number := 9;
ADV_ID_COMPRESS          constant number := 10;


ADVISOR_ALL           constant number       := -995;
ADVISOR_CURRENT       constant number       := -996;
ADVISOR_DEFAULT       constant number       := -997;
ADVISOR_UNLIMITED     constant number       := -998;
ADVISOR_UNUSED        constant number       := -999;


SQLACCESS_GENERAL       constant varchar2(20) := 'SQLACCESS_GENERAL';
SQLACCESS_OLTP          constant varchar2(20) := 'SQLACCESS_OLTP';
SQLACCESS_WAREHOUSE     constant varchar2(20) := 'SQLACCESS_WAREHOUSE';

SQLACCESS_ADVISOR       constant varchar2(30) := ADV_NAME_SQLACCESS;
TUNE_MVIEW_ADVISOR      constant varchar2(30) := ADV_NAME_TUNEMV;
SQLWORKLOAD_MANAGER     constant varchar2(30) := ADV_NAME_SQLWM;

TYPE argList IS TABLE OF sys.wri$_adv_parameters.value%TYPE;

TYPE varchar2adv IS TABLE OF VARCHAR2(256) INDEX BY BINARY_INTEGER;



procedure cancel_task (task_name       in varchar2);


procedure create_task (advisor_name          in varchar2,
task_id               out number,
task_name             in out varchar2,
task_desc             in varchar2 := null,
template              in varchar2 := null,
is_template           in varchar2 := 'FALSE',
how_created           in varchar2 := null);


procedure create_task (advisor_name          in varchar2,
task_name             in varchar2,
task_desc             in varchar2 := null,
template              in varchar2 := null,
is_template           in varchar2 := 'FALSE',
how_created           in varchar2 := null);


procedure create_task (parent_task_name      in varchar2,
rec_id                in number,
task_id               out number,
task_name             in out varchar2,
task_desc             in varchar2,
template              in varchar2);

procedure delete_task (task_name       in varchar2);

procedure execute_task(task_name IN VARCHAR2);

FUNCTION execute_task(
task_name        IN VARCHAR2,
execution_type   IN VARCHAR2 := NULL,
execution_name   IN VARCHAR2 := NULL,
execution_desc   IN VARCHAR2 := NULL,
execution_params IN argList  := NULL)
RETURN VARCHAR2;

procedure interrupt_task (task_name       in varchar2);


procedure mark_recommendation (task_name       in varchar2,
id              in number,
action          in varchar2);

procedure reset_task(task_name       in varchar2);

procedure resume_task(task_name       in varchar2);


procedure set_task_parameter (task_name      in varchar2,
parameter      in varchar2,
value          in varchar2);

procedure set_task_parameter (task_name      in varchar2,
parameter      in varchar2,
value          in number);


procedure set_default_task_parameter (advisor_name   in varchar2,
parameter      in varchar2,
value       
in varchar2);

procedure set_default_task_parameter (advisor_name   in varchar2,
parameter      in varchar2,
value          in number);


PROCEDURE create_object(task_name     IN VARCHAR2 ,
object_type   IN VARCHAR2 ,
attr1         IN VARCHAR2 := null,
attr2         IN VARCHAR2 := null,
attr3         IN VARCHAR2 := null,
attr4         IN clob := NULL,
object_id    OUT NUMBER);


PROCEDURE create_object(task_name     IN VARCHAR2 ,
object_type   IN VARCHAR2 ,
attr1         IN VARCHAR2 := null,
attr2         IN VARCHAR2 := null,
attr3         IN VARCHAR2 := null,
attr4         IN clob := NULL,
attr5         IN VARCHAR2 := null,
object_id    OUT NUMBER);


PROCEDURE update_object(task_name     IN VARCHAR2 ,
object_id     IN NUMBER ,
attr1         IN VARCHAR2 := null,
attr2         IN VARCHAR2 := null,
attr3         IN VARCHAR2 := null,
attr4         IN clob := NULL,
attr5         IN VARCHAR2 := null);



procedure create_file (buffer         in clob,
location       in varchar2,
filename       in varchar2);

function get_task_report (task_name      in varchar2,
type           in varchar2 := 'TEXT',
level          in varchar2 := 'TYPICAL',
section        in varchar2 := 'ALL',
owner_name     in varchar2 := NULL,
execution_name in varchar2 := NULL,
object_id      in number   := NULL)
return clob;

function get_task_script (task_name      in varchar2,
type           in varchar2 := 'IMPLEMENTATION',
rec_id         in number   := NULL,
act_id         in number   := NULL,
owner_name     in varchar2 := NULL,
execution_name in varchar2 := NULL,
object_id      in number   := NULL)
return clob;


procedure implement_task (task_name       in varchar2,
rec_id          in number := NULL,
exit_on_error   in boolean := NULL);


procedure quick_tune (advisor_name           in varchar2,
task_name              in varchar2,
attr1                  in clob := null,
attr2                  in varchar2 := null,
attr3                  in number := null,
template               in varchar2 := null,
implement              in boolean := FALSE,
description            in varchar2 := null);


procedure tune_mview (task_name      in out varchar2,
mv_create_stmt in     clob);



procedure update_rec_attributes (task_name            in varchar2,
rec_id               in number,
action_id            in number,
attribute_name       in varchar2,
value                in varchar2);


procedure get_rec_attributes (task_name            in varchar2,
rec_id               in number,
action_id            in number,
attribute_name       in varchar2,
value                out varchar2,
owner_name           in varchar2 := NULL);


procedure update_task_attributes (task_name       in varchar2,
new_name        in varchar2 := null,
description     in varchar2 := null,
read_only       in varchar2 := null,
is_template     in varchar2 := null,
how_created     in varchar2 := null);




function format_message_group(group_id IN number, msg_type IN number := 0)
return varchar2;



function format_message(msg_id IN varchar2)
return varchar2;


procedure check_privs;


procedure check_read_privs(owner_name IN VARCHAR2);


procedure setup_repository;


procedure add_sqlwkld_statement (workload_name        in varchar2,
module               in varchar2 := '',
action               in varchar2 := '',
cpu_time             in number := 0,
elapsed_time         in number := 0,
disk_reads           in number := 0,
buffer_gets          in number := 0,
rows_processed       in number := 0,
optimizer_cost       in number := 0,
executions           in number := 1,
priority             in number := 2,
last_execution_date  in date := SYSDATE,
stat_period          in number := 0,
username             in varchar2,
sql_text             in clob);


procedure add_sqlwkld_ref (task_name      in varchar2,
workload_name  in varchar2,
is_sts         in number := 0);


procedure add_sts_ref (task_name      in varchar2,
sts_owner      in varchar2,
workload_name  in varchar2);


procedure create_sqlwkld (workload_name    
in out varchar2,
description              in varchar2 := null,
template                 in varchar2 := null,
is_template              in varchar2 := 'FALSE');


procedure delete_sqlwkld (workload_name            in varchar2);


procedure delete_sqlwkld_ref (task_name       in varchar2,
workload_name   in varchar2,
is_sts          in number := 2);


procedure delete_sts_ref (task_name       in varchar2,
sts_owner       in varchar2,
workload_name   in varchar2);


procedure delete_sqlwkld_statement (workload_name     in varchar2,
sql_id            in number);

procedure delete_sqlwkld_statement (workload_name     in varchar2,
search            in varchar2,
deleted           out number);


procedure import_sqlwkld_sts (workload_name         in varchar2,
sts_owner             in varchar2,
sts_name              in varchar2,
import_mode           in varchar2 := 'NEW',
priority              in number := 2,
saved_rows            out number,
failed_rows           out number);

procedure import_sqlwkld_sts (workload_name         in varchar2,
sts_name              in varchar2,
import_mode           in varchar2 := 'NEW',
priority              in number := 2,
saved_rows            out number,
failed_rows           out number);


procedure import_sqlwkld_schema (workload_name         in varchar2,
import_mode           in varchar2 := 'NEW',
priority              in number := 2,
saved_rows            out number,
failed_rows           out number);



procedure import_sqlwkld_sqlcache (workload_name         in varchar2,
import_mode           in varchar2 := 'NEW',
priority              in number := 2,
saved_rows            out number,
failed_rows           out number);



procedure import_sqlwkld_sumadv (workload_name         in varchar2,
import_mode           in varchar2 := 'NEW',
priority              in number := 2,
sumadv_id             in number,
saved_rows            out number,
failed_rows           out number);


procedure import_sqlwkld_user (workload_name         in varchar2,
import_mode           in varchar2 := 'NEW',
owner_name            in varchar2,
table_name            in varchar2,
saved_rows            out number,
failed_rows           out number);


procedure copy_sqlwkld_to_sts (workload_name         in varchar2,
sts_name              in varchar2,
import_mode           in varchar2 := 'NEW');


procedure reset_sqlwkld (workload_name       in varchar2);


procedure set_sqlwkld_parameter (workload_name        in varchar2,
parameter            in varchar2,
value                in varchar2);

procedure set_sqlwkld_parameter (workload_name        in varchar2,
parameter            in varchar2,
value                in number);


procedure set_default_sqlwkld_parameter (parameter      in varchar2,
value          in varchar2);

procedure set_default_sqlwkld_parameter (parameter      in varchar2,
value          in number);


procedure update_sqlwkld_attributes (workload_name    in varchar2,
new_name         in varchar2 := null,
description      in varchar2 := null,
read_only        in varchar2 := null,
is_template      in varchar2 := null,
how_created      in varchar2 := null);


procedure update_sqlwkld_statement (workload_name     in varchar2,
sql_id            in number,
application       in varchar2 := null,
action            in varchar2 := null,
priority          in number := null,
username          in varchar2 := null);

procedure update_sqlwkld_statement (workload_name     in varchar2,
search            in varchar2,
updated           out number,
application       in varchar2 := null,
action            in varchar2 := null,
priority          in number := null,
username          in varchar2 := null);


procedure setup_user_environment (advisor_name    in varchar2);


procedure get_access_advisor_defaults (task_name      out varchar2,
task_id_num    out number,
workload_name  out varchar2,
work_id_num    out number);


procedure delete_directive (directive_id    in number,
instance_name   in varchar2,
task_name       in varchar2 :=   
NULL);


function evaluate_directive (directive_id      in number,
instance_name     in varchar2,
task_name         in varchar2 := NULL,
p1                in clob := NULL,
p2                in clob := NULL)
return clob;


procedure insert_directive (directive_id    in number,
instance_name   in varchar2,
task_name       in varchar2,
document        in clob);


procedure update_directive (directive_id    in number,
instance_name   in varchar2,
task_name       in varchar2,
document        in clob);


END BLOCK_DBMS_ADVISOR;
/
</pre>
<p>&#8230;and the body, including our function&#8230;</p>
<pre class="brush: sql; highlight: [12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44]; title: ; wrap-lines: false; notranslate">
CREATE OR REPLACE PACKAGE BODY disable_pack_dt.BLOCK_DBMS_ADVISOR
IS
-------------------------------------------------------------------------------
-- The Diagnostic and Tuning Pack licenses are required when either
-- 1) advisor_name =&gt; 'ADDM'
-- 2) advisor_name =&gt; 'SQL Tuning Advisor'
-- 3) advisor_name =&gt; 'SQL Access Advisor'
-- 4) task_name LIKE 'ADDM%'
--  
-------------------------------------------------------------------------------

FUNCTION license_check_fn( i_name IN VARCHAR2, i_value IN VARCHAR2)
    RETURN BOOLEAN
-------------------------------------------------------------------------------
-- Private function called by relevant package members to check that parameter
-- values do not require the Diagnostic or Tuning Pack license to be used.
-- i_name - name of the parameter ( should be 'ADVISOR_NAME' or 'TASK_NAME')
-- i_value - the value passed in for the parameter in question.
--
-------------------------------------------------------------------------------
IS 
    l_msg VARCHAR2(4000);
BEGIN
    IF UPPER(i_name) = 'ADVISOR_NAME' 
        AND UPPER(i_value) IN ( 
            'ADDM', 'SQL TUNING ADVISOR', 'SQL ACCESS ADVISOR')
    THEN
        --
        -- Cause the pack license error to be raised.
        --
        l_msg := disable_pack_dt.get_err_msg_fn;
    ELSIF UPPER(i_name) = 'TASK_NAME'
        AND UPPER( i_value) LIKE 'ADDM%'
    THEN
        --
        -- cause the pack license error to be raised.
        --
        l_msg := disable_pack_dt.get_err_msg_fn;
    END IF;
    --
    -- If we get here then we haven't raised an error so OK to continue.
    --
    RETURN TRUE;
END;
    
procedure cancel_task (task_name       in varchar2)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X')) THEN
        sys.DBMS_ADVISOR.CANCEL_TASK(task_name =&gt; task_name);
    END IF;
END;

procedure create_task (
    advisor_name          in varchar2,
    task_id               out number,
    task_name             in out varchar2,
    task_desc             in varchar2 := null,
    template              in varchar2 := null,
    is_template           in varchar2 := 'FALSE',
    how_created           in varchar2 := null)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'advisor_name', i_value =&gt; NVL( advisor_name, 'X'))
        AND license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL( task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.CREATE_TASK(
            advisor_name =&gt; advisor_name,
            task_id =&gt; task_id,
            task_name =&gt; task_name,
            task_desc =&gt; task_desc,
            template =&gt; template,
            is_template =&gt; is_template,
            how_created =&gt; how_created);
    END IF;
END;

procedure create_task (
    advisor_name          in varchar2,
    task_name             in varchar2,
    task_desc             in varchar2 := null,
    template              in varchar2 := null,
    is_template           in varchar2 := 'FALSE',
    how_created           in varchar2 := null)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'advisor_name', i_value =&gt; NVL( advisor_name, 'X'))
        AND license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL( task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.CREATE_TASK(    
            advisor_name =&gt; advisor_name,
            task_name =&gt; task_name,
            task_desc =&gt; task_desc,
            template =&gt; template,
            is_template =&gt; is_template,
            how_created =&gt; how_created);
    END IF;
END;

procedure create_task (
    parent_task_name      in varchar2,
    rec_id                in number,
    task_id               out number,
    task_name             in out varchar2,
    task_desc             in varchar2,
    template              in varchar2)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.CREATE_TASK(
            parent_task_name =&gt; parent_task_name,
            rec_id =&gt; rec_id,
            task_id =&gt; task_id,
            task_name =&gt; task_name,
            task_desc =&gt; task_desc,
            template =&gt; template);
    END IF;
END;

procedure delete_task (task_name       in varchar2)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL( task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.DELETE_TASK( task_name =&gt; task_name);
    END IF;
END;

procedure execute_task(task_name IN VARCHAR2)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL( task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.EXECUTE_TASK(task_name =&gt; task_name);
    END IF;
END;

FUNCTION execute_task(
    task_name        IN VARCHAR2,
    execution_type   IN VARCHAR2 := NULL,
    execution_name   IN VARCHAR2 := NULL,
    execution_desc   IN VARCHAR2 := NULL,
    execution_params IN argList  := NULL)
    RETURN VARCHAR2
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL( task_name, 'X'))
    THEN
        --
        -- NOTE - compiler doesn't like the execution_params value
        -- for some reason and insists on returning a 
        -- PLS-00306 error. As the parameter is set to NULL explicitly
        -- here (not even defaulted) then just pass NULL as the argument.
        --
        RETURN sys.DBMS_ADVISOR.EXECUTE_TASK(
            task_name =&gt; task_name,
            execution_type =&gt; execution_type,
            execution_name =&gt; execution_name,
            execution_desc =&gt; execution_desc,
            execution_params =&gt; NULL);
    END IF;
END;

procedure interrupt_task (task_name in varchar2)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL( task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.INTERRUPT_TASK( task_name =&gt; task_name);
    END IF;
END;

procedure mark_recommendation (
    task_name       in varchar2,
    id              in number,
    action          in varchar2)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL( task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.MARK_RECOMMENDATION(
            task_name =&gt; task_name,
            id =&gt; id,
            action =&gt; action);
    END IF;
END;

procedure reset_task(task_name       in varchar2)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.RESET_TASK( task_name =&gt; task_name);
    END IF;
END;

procedure resume_task(task_name       in varchar2)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.RESUME_TASK( task_name =&gt; task_name);
    END IF;
END;

procedure set_task_parameter (
    task_name      in varchar2,
    parameter      in varchar2,
    value          in varchar2)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.SET_TASK_PARAMETER(
            task_name =&gt; task_name,
            parameter =&gt; parameter,
            value =&gt; value);
    END IF;
END;
    
procedure set_task_parameter (
    task_name      in varchar2,
    parameter      in varchar2,
    value          in number)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.SET_TASK_PARAMETER(
            task_name =&gt; task_name,
            parameter =&gt; parameter,
            value =&gt; value);
    END IF;
END;

procedure set_default_task_parameter (
    advisor_name   in varchar2,
    parameter      in varchar2,
    value          in varchar2)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'advisor_name', i_value =&gt; NVL(advisor_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.SET_DEFAULT_TASK_PARAMETER(
            advisor_name =&gt; advisor_name,
            parameter =&gt; parameter,
            value =&gt; value);
    END IF;
END;

procedure set_default_task_parameter (
    advisor_name   in varchar2,
    parameter      in varchar2,
    value          in number)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'advisor_name', i_value =&gt; NVL(advisor_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.SET_DEFAULT_TASK_PARAMETER(
            advisor_name =&gt; advisor_name,
            parameter =&gt; parameter,
            value =&gt; value);
    END IF;
END;

PROCEDURE create_object(
    task_name     IN VARCHAR2 ,
    object_type   IN VARCHAR2 ,
    attr1         IN VARCHAR2 := null,
    attr2         IN VARCHAR2 := null,
    attr3         IN VARCHAR2 := null,
    attr4         IN clob := NULL,
    object_id    OUT NUMBER)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X'))
    THEN
        --
        -- For some reason, the DBMS_ADVISOR package has
        -- CREATE_OBJECT overloaded with one extra attr parameter.
        -- The problem is that, if you pass by reference, you'll get
        -- a PLS-00307 - &quot;Too many declarations of CREATE_OBJECT match this call&quot;
        -- To avoid this, pass by position.
        --
        sys.DBMS_ADVISOR.CREATE_OBJECT(
            task_name,
            object_type,
            attr1,
            attr2,
            attr3,
            attr4,
            object_id);
    END IF;
END;

PROCEDURE create_object(
    task_name     IN VARCHAR2 ,
    object_type   IN VARCHAR2 ,
    attr1         IN VARCHAR2 := null,
    attr2         IN VARCHAR2 := null,
    attr3         IN VARCHAR2 := null,
    attr4         IN clob := NULL,
    attr5         IN VARCHAR2 := null,
    object_id    OUT NUMBER)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.CREATE_OBJECT(
            task_name =&gt; task_name,
            object_type =&gt; object_type,
            attr1 =&gt; attr1,
            attr2 =&gt; attr2,
            attr3 =&gt; attr3,
            attr4 =&gt; attr4,
            attr5 =&gt; attr5,
            object_id =&gt; object_id);
    END IF;
END;

PROCEDURE update_object(
    task_name     IN VARCHAR2 ,
    object_id     IN NUMBER ,
    attr1         IN VARCHAR2 := null,
    attr2         IN VARCHAR2 := null,
    attr3         IN VARCHAR2 := null,
    attr4         IN clob := NULL,
    attr5         IN VARCHAR2 := null)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.UPDATE_OBJECT(
            task_name =&gt; task_name,
            object_id =&gt; object_id,
            attr1 =&gt; attr1,
            attr2 =&gt; attr2,
            attr3 =&gt; attr3,
            attr4 =&gt; attr4,
            attr5 =&gt; attr5);
    END IF;
END;

procedure create_file (
    buffer         in clob,
    location       in varchar2,
    filename       in varchar2)
IS
BEGIN
    sys.DBMS_ADVISOR.CREATE_FILE(
        buffer =&gt; buffer,
        location =&gt; location,
        filename =&gt; filename);
END;

function get_task_report (
    task_name      in varchar2,
    type           in varchar2 := 'TEXT',
    level          in varchar2 := 'TYPICAL',
    section        in varchar2 := 'ALL',
    owner_name     in varchar2 := NULL,
    execution_name in varchar2 := NULL,
    object_id      in number   := NULL)
    return clob
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X'))
    THEN
        RETURN sys.DBMS_ADVISOR.GET_TASK_REPORT(
            task_name =&gt; task_name,
            type =&gt; type,
            level =&gt; level,
            section =&gt; section,
            owner_name =&gt; owner_name,
            execution_name =&gt; execution_name,
            object_id =&gt; object_id);
    END IF;
END;

function get_task_script (
    task_name      in varchar2,
    type           in varchar2 := 'IMPLEMENTATION',
    rec_id         in number   := NULL,
    act_id         in number   := NULL,
    owner_name     in varchar2 := NULL,
    execution_name in varchar2 := NULL,
    object_id      in number   := NULL)
    return clob
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X'))
    THEN
        RETURN sys.DBMS_ADVISOR.GET_TASK_SCRIPT(
            task_name =&gt; task_name,
            type =&gt; type,
            rec_id =&gt; rec_id,
            act_id =&gt; act_id,
            owner_name =&gt; owner_name,
            execution_name =&gt; execution_name,
            object_id =&gt; object_id);
    END IF;
END;

procedure implement_task (
    task_name       in varchar2,
    rec_id          in number := NULL,
    exit_on_error   in boolean := NULL)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL( task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.IMPLEMENT_TASK(
            task_name =&gt; task_name,
            rec_id =&gt; rec_id,
            exit_on_error =&gt; exit_on_error);
    END IF;
END;

procedure quick_tune (
    advisor_name           in varchar2,
    task_name              in varchar2,
    attr1                  in clob := null,
    attr2                  in varchar2 := null,
    attr3                  in number := null,
    template               in varchar2 := null,
    implement              in boolean := FALSE,
    description            in varchar2 := null)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'advisor_name', i_value =&gt; NVL( advisor_name, 'X'))
        AND license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL( task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.QUICK_TUNE(
            advisor_name =&gt; advisor_name,
            task_name =&gt; task_name,
            attr1 =&gt; attr1,
            attr2 =&gt; attr2,
            attr3 =&gt; attr3,
            template =&gt; template,
            implement =&gt; implement,
            description =&gt; description);
    END IF;
END;
        
procedure tune_mview (
    task_name      in out varchar2,
    mv_create_stmt in     clob)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL( task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.TUNE_MVIEW(
            task_name =&gt; task_name,
            mv_create_stmt =&gt; mv_create_stmt);
    END IF;
END;


procedure update_rec_attributes (
    task_name            in varchar2,
    rec_id               in number,
    action_id            in number,
    attribute_name       in varchar2,
    value                in varchar2)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL( task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.UPDATE_REC_ATTRIBUTES(
            task_name =&gt; task_name,
            rec_id =&gt; rec_id,
            action_id =&gt; action_id,
            attribute_name =&gt; attribute_name,
            value =&gt; value);
    END IF;
END;

procedure get_rec_attributes (
    task_name            in varchar2,
    rec_id               in number,
    action_id            in number,
    attribute_name       in varchar2,
    value                out varchar2,
    owner_name           in varchar2 := NULL)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL( task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.GET_REC_ATTRIBUTES(
            task_name =&gt; task_name,
            rec_id =&gt; rec_id,
            action_id =&gt; action_id,
            attribute_name =&gt; attribute_name,
            value =&gt; value,
            owner_name =&gt; owner_name);
    END IF;
END;

procedure update_task_attributes (
    task_name       in varchar2,
    new_name        in varchar2 := null,
    description     in varchar2 := null,
    read_only       in varchar2 := null,
    is_template     in varchar2 := null,
    how_created     in varchar2 := null)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL( task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.UPDATE_TASK_ATTRIBUTES(
            task_name =&gt; task_name,
            new_name =&gt; new_name,
            description =&gt; description,
            read_only =&gt; read_only,
            is_template =&gt; is_template,
            how_created =&gt; how_created);
    END IF;
END;

function format_message_group(
    group_id IN number, 
    msg_type IN number := 0)
    return varchar2 
IS
BEGIN
    RETURN sys.DBMS_ADVISOR.FORMAT_MESSAGE_GROUP(
        group_id =&gt; group_id,
        msg_type =&gt; msg_type);
END;

function format_message(msg_id IN varchar2)
    return varchar2
IS
BEGIN
    RETURN sys.DBMS_ADVISOR.FORMAT_MESSAGE( msg_id =&gt; msg_id);
END;

procedure check_privs
IS
BEGIN
    sys.DBMS_ADVISOR.CHECK_PRIVS;
END;

procedure check_read_privs(owner_name IN VARCHAR2)
IS
BEGIN
    sys.DBMS_ADVISOR.CHECK_READ_PRIVS( owner_name =&gt; owner_name);
END;

procedure setup_repository
IS
BEGIN
    sys.DBMS_ADVISOR.SETUP_REPOSITORY;
END;

procedure add_sqlwkld_statement (
    workload_name        in varchar2,
    module               in varchar2 := '',
    action               in varchar2 := '',
    cpu_time             in number := 0,
    elapsed_time         in number := 0,
    disk_reads           in number := 0,
    buffer_gets          in number := 0,
    rows_processed       in number := 0,
    optimizer_cost       in number := 0,
    executions           in number := 1,
    priority             in number := 2,
    last_execution_date  in date := SYSDATE,
    stat_period          in number := 0,
    username             in varchar2,
    sql_text             in clob)
IS
BEGIN
    sys.DBMS_ADVISOR.ADD_SQLWKLD_STATEMENT(
        workload_name =&gt; workload_name,
        module =&gt; module,
        action =&gt; action,
        cpu_time =&gt; cpu_time,
        elapsed_time =&gt; elapsed_time,
        disk_reads =&gt; disk_reads,
        buffer_gets =&gt; buffer_gets,
        rows_processed =&gt; rows_processed,
        optimizer_cost =&gt; optimizer_cost,
        executions =&gt; executions,
        priority =&gt; priority,
        last_execution_date =&gt; last_execution_date,
        stat_period =&gt; stat_period,
        username =&gt; username,
        sql_text =&gt; sql_text);
END;

procedure add_sqlwkld_ref (
    task_name      in varchar2,
    workload_name  in varchar2,
    is_sts         in number := 0)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.ADD_SQLWKLD_REF(
            task_name =&gt; task_name,
            workload_name =&gt; workload_name,
            is_sts =&gt; is_sts);
    END IF;
END;

procedure add_sts_ref (
    task_name      in varchar2,
    sts_owner      in varchar2,
    workload_name  in varchar2)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.ADD_STS_REF(
            task_name =&gt; task_name,
            sts_owner =&gt; sts_owner,
            workload_name =&gt; workload_name);
    END IF;
END;

procedure create_sqlwkld (
    workload_name            in out varchar2,
    description              in varchar2 := null,
    template                 in varchar2 := null,
    is_template              in varchar2 := 'FALSE')
IS
BEGIN
    sys.DBMS_ADVISOR.CREATE_SQLWKLD(
        workload_name =&gt; workload_name,
        description =&gt; description,
        template =&gt; template,
        is_template =&gt; is_template);
END;

procedure delete_sqlwkld (workload_name            in varchar2)
IS
BEGIN
    sys.DBMS_ADVISOR.DELETE_SQLWKLD(
        workload_name =&gt; workload_name);
END;

procedure delete_sqlwkld_ref (
    task_name       in varchar2,
    workload_name   in varchar2,
    is_sts          in number := 2)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.DELETE_SQLWKLD_REF(
            task_name =&gt; task_name,
            workload_name =&gt; workload_name,
            is_sts =&gt; is_sts);
    END IF;
END;

procedure delete_sts_ref (
    task_name       in varchar2,
    sts_owner       in varchar2,
    workload_name   in varchar2)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.DELETE_STS_REF(
            task_name =&gt; task_name,
            sts_owner =&gt; sts_owner,
            workload_name =&gt; workload_name);
    END IF;
END;

procedure delete_sqlwkld_statement (
    workload_name     in varchar2,
    sql_id            in number)
IS
BEGIN
    sys.DBMS_ADVISOR.DELETE_SQLWKLD_STATEMENT(
        workload_name =&gt; workload_name,
        sql_id =&gt; sql_id);
END;

procedure delete_sqlwkld_statement (
    workload_name     in varchar2,
    search            in varchar2,
    deleted           out number)
IS
BEGIN
    sys.DBMS_ADVISOR.DELETE_SQLWKLD_STATEMENT(
        workload_name =&gt; workload_name,
        search =&gt; search,
        deleted =&gt; deleted);
END;

procedure import_sqlwkld_sts (
    workload_name         in varchar2,
    sts_owner             in varchar2,
    sts_name              in varchar2,
    import_mode           in varchar2 := 'NEW',
    priority              in number := 2,
    saved_rows            out number,
    failed_rows           out number)
IS
BEGIN
    sys.DBMS_ADVISOR.IMPORT_SQLWKLD_STS(
        workload_name =&gt; workload_name,
        sts_owner =&gt; sts_owner,
        sts_name =&gt; sts_name,
        import_mode =&gt; import_mode,
        priority =&gt; priority,
        saved_rows =&gt; saved_rows,
        failed_rows =&gt; failed_rows);
END;

procedure import_sqlwkld_sts (
    workload_name         in varchar2,
    sts_name              in varchar2,
    import_mode           in varchar2 := 'NEW',
    priority              in number := 2,
    saved_rows            out number,
    failed_rows           out number)
IS
BEGIN
    sys.DBMS_ADVISOR.IMPORT_SQLWKLD_STS(
        workload_name =&gt; workload_name,
        sts_name =&gt; sts_name,
        import_mode =&gt; import_mode,
        priority =&gt; priority,
        saved_rows =&gt; saved_rows,
        failed_rows =&gt; failed_rows);
END;

procedure import_sqlwkld_schema (
    workload_name         in varchar2,
    import_mode           in varchar2 := 'NEW',
    priority              in number := 2,
    saved_rows            out number,
    failed_rows           out number)
IS
BEGIN
    sys.DBMS_ADVISOR.IMPORT_SQLWKLD_SCHEMA(
        workload_name =&gt; workload_name,
        import_mode =&gt; import_mode,
        priority =&gt; priority,
        saved_rows =&gt; saved_rows,
        failed_rows =&gt; failed_rows);
END;

procedure import_sqlwkld_sqlcache (
    workload_name         in varchar2,
    import_mode           in varchar2 := 'NEW',
    priority              in number := 2,
    saved_rows            out number,
    failed_rows           out number)
IS
BEGIN
    sys.DBMS_ADVISOR.IMPORT_SQLWKLD_SQLCACHE(
        workload_name =&gt; workload_name,
        import_mode =&gt; import_mode,
        priority =&gt; priority,
        saved_rows =&gt; saved_rows,
        failed_rows =&gt; failed_rows);
END;

procedure import_sqlwkld_sumadv (
    workload_name         in varchar2,
    import_mode           in varchar2 := 'NEW',
    priority              in number := 2,
    sumadv_id             in number,
    saved_rows            out number,
    failed_rows           out number)
IS
BEGIN
    sys.DBMS_ADVISOR.IMPORT_SQLWKLD_SUMADV(
        workload_name =&gt; workload_name,
        import_mode =&gt; import_mode,
        priority =&gt; priority,
        sumadv_id =&gt; sumadv_id,
        saved_rows =&gt; saved_rows,
        failed_rows =&gt; failed_rows);
END;

procedure import_sqlwkld_user (
    workload_name         in varchar2,
    import_mode           in varchar2 := 'NEW',
    owner_name            in varchar2,
    table_name            in varchar2,
    saved_rows            out number,
    failed_rows           out number)
IS
BEGIN
    sys.DBMS_ADVISOR.IMPORT_SQLWKLD_USER(
        workload_name =&gt; workload_name,
        import_mode =&gt; import_mode,
        owner_name =&gt; owner_name,
        table_name =&gt; table_name,
        saved_rows =&gt; saved_rows,
        failed_rows =&gt; failed_rows);
END;

procedure copy_sqlwkld_to_sts (
    workload_name         in varchar2,
    sts_name              in varchar2,
    import_mode           in varchar2 := 'NEW')
IS
BEGIN
    sys.DBMS_ADVISOR.COPY_SQLWKLD_TO_STS(
        workload_name =&gt; workload_name,
        sts_name =&gt; sts_name,
        import_mode =&gt; import_mode);
END;

procedure reset_sqlwkld (workload_name       in varchar2)
IS
BEGIN
    sys.DBMS_ADVISOR.RESET_SQLWKLD( workload_name =&gt; workload_name);
END;

procedure set_sqlwkld_parameter (
    workload_name        in varchar2,
    parameter            in varchar2,
    value                in varchar2)
IS
BEGIN
    sys.DBMS_ADVISOR.SET_SQLWKLD_PARAMETER(
        workload_name =&gt; workload_name,
        parameter =&gt; parameter,
        value =&gt; value);
END;

procedure set_sqlwkld_parameter (
    workload_name        in varchar2,
    parameter            in varchar2,
    value                in number)
IS
BEGIN
    sys.DBMS_ADVISOR.SET_SQLWKLD_PARAMETER(
        workload_name =&gt; workload_name,
        parameter =&gt; parameter,
        value =&gt; value);
END;
procedure set_default_sqlwkld_parameter (
    parameter      in varchar2,
    value          in varchar2)
IS
BEGIN
    sys.DBMS_ADVISOR.SET_DEFAULT_SQLWKLD_PARAMETER(
        parameter =&gt; parameter,
        value =&gt; value);
END;

procedure set_default_sqlwkld_parameter (
    parameter      in varchar2,
    value          in number)
IS
BEGIN
    sys.DBMS_ADVISOR.SET_DEFAULT_SQLWKLD_PARAMETER(
        parameter =&gt; parameter,
        value =&gt; value);
END;

procedure update_sqlwkld_attributes (
    workload_name    in varchar2,
    new_name         in varchar2 := null,
    description      in varchar2 := null,
    read_only        in varchar2 := null,
    is_template      in varchar2 := null,
    how_created      in varchar2 := null)
IS
BEGIN
    sys.DBMS_ADVISOR.UPDATE_SQLWKLD_ATTRIBUTES(
        workload_name =&gt; workload_name,
        new_name =&gt; new_name,
        description =&gt; description,
        read_only =&gt; read_only,
        is_template =&gt; is_template,
        how_created =&gt; how_created);
END;

procedure update_sqlwkld_statement (
    workload_name     in varchar2,
    sql_id            in number,
    application       in varchar2 := null,
    action            in varchar2 := null,
    priority          in number := null,
    username          in varchar2 := null)
IS
BEGIN
    sys.DBMS_ADVISOR.UPDATE_SQLWKLD_STATEMENT(
        workload_name =&gt; workload_name,
        sql_id =&gt; sql_id,
        application =&gt; application,
        action =&gt; action,
        priority =&gt; priority,
        username =&gt; username);
END;

procedure update_sqlwkld_statement (
    workload_name     in varchar2,
    search            in varchar2,
    updated           out number,
    application       in varchar2 := null,
    action            in varchar2 := null,
    priority          in number := null,
    username          in varchar2 := null)
IS
BEGIN
    sys.DBMS_ADVISOR.UPDATE_SQLWKLD_STATEMENT(
        workload_name =&gt; workload_name,
        search =&gt; search,
        updated =&gt; updated,
        application =&gt; application,
        action =&gt; action,
        priority =&gt; priority,
        username =&gt; username);
END;
    
procedure setup_user_environment (advisor_name    in varchar2)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'advisor_name', i_value =&gt; NVL(advisor_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.SETUP_USER_ENVIRONMENT( advisor_name =&gt; advisor_name);
    END IF;
END;

procedure get_access_advisor_defaults (
    task_name      out varchar2,
    task_id_num    out number,
    workload_name  out varchar2,
    work_id_num    out number)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.GET_ACCESS_ADVISOR_DEFAULTS(
            task_name =&gt; task_name,
            task_id_num =&gt; task_id_num,
            workload_name =&gt; workload_name,
            work_id_num =&gt; work_id_num);
    END IF;
END;

procedure delete_directive (
    directive_id    in number,
    instance_name   in varchar2,
    task_name       in varchar2 :=   NULL)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.DELETE_DIRECTIVE(
            directive_id =&gt; directive_id,
            instance_name =&gt; instance_name,
            task_name =&gt; task_name);
    END IF;
END;

function evaluate_directive (
    directive_id      in number,
    instance_name     in varchar2,
    task_name         in varchar2 := NULL,
    p1                in clob := NULL,
    p2                in clob := NULL)
    return clob
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X'))
    THEN
        RETURN sys.DBMS_ADVISOR.EVALUATE_DIRECTIVE(
            directive_id =&gt; directive_id,
            instance_name =&gt; instance_name,
            task_name =&gt; task_name,
            p1 =&gt; p1,
            p2 =&gt; p2);
    END IF;
END;

procedure insert_directive (
    directive_id    in number,
    instance_name   in varchar2,
    task_name       in varchar2,
    document        in clob)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL( task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.INSERT_DIRECTIVE(
            directive_id =&gt; directive_id,
            instance_name =&gt; instance_name,
            task_name =&gt; task_name,
            document =&gt; document);
    END IF;
END;

procedure update_directive (
    directive_id    in number,
    instance_name   in varchar2,
    task_name       in varchar2,
    document        in clob)
IS
BEGIN
    IF license_check_fn( i_name =&gt; 'task_name', i_value =&gt; NVL(task_name, 'X'))
    THEN
        sys.DBMS_ADVISOR.UPDATE_DIRECTIVE(
            directive_id =&gt; directive_id,
            instance_name =&gt; instance_name,
            task_name =&gt; task_name,
            document =&gt; document);
    END IF;
END;

END BLOCK_DBMS_ADVISOR;
/
</pre>
<p>Finally, we want to grant access to these packages :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">

GRANT EXECUTE ON disable_pack_dt.block_dbms_addm TO PUBLIC
/

GRANT EXECUTE ON disable_pack_dt.block_dbms_advisor TO PUBLIC
/

GRANT EXECUTE ON disable_pack_dt.block_dbms_sqltune TO PUBLIC
/

GRANT EXECUTE ON disable_pack_dt.block_dbms_workload_replay TO PUBLIC
/

GRANT EXECUTE ON disable_pack_dt.block_dbms_workload_repository TO PUBLIC
/
</pre>
<p>Now we have all of our code, all we need to do is to make sure that it is accessed …</p>
<h3>Re-pointing the Public Synonyms</h3>
<p>We&#8217;re going to do this in two stages – Views first and then Packages.<br />
Before that, however, it&#8217;s probably worth generating the code required to rollback these changes should you need to :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
-------------------------------------------------------------------------------
-- Script to generate commands to rollback Public Synonym changes for the
-- DISABLE_PACK_DT application.
-- NOTE - we're not checking the veracity of the object names in DBA_SYNONYMS
-- here. We are simply creating a script that may be run in the event of a 
-- rollback to put things back exactly as they were before making the changes
-- for this application.
--
-------------------------------------------------------------------------------
set heading off
set feedback off
set lines 200
set pages 5000
spool rollback_syns_slave.sql
SELECT 'CREATE OR REPLACE PUBLIC SYNONYM '||syn.synonym_name||' FOR '||syn.table_owner||'.'||syn.table_name||';'
FROM dba_synonyms syn, disable_pack_dt.pack_members mem
WHERE syn.table_name = mem.object_name
AND syn.owner = 'PUBLIC'
/
spool off
</pre>
<p>Run this and you should now have a rollback script in rollback_syns_slave.sql, containing all the CREATE OR REPLACE PUBLIC SYNONYM statements required to re-set things to the way they were before we started.<br />
<strong>NOTE</strong> &#8211; althought there are 165 records in the PACK_MEMBERS table, three of these are synonyms. Therefore, we should only have 162 synonyms to change in total.</p>
<p>Now to change the View synonyms.<br />
To save some typing, we&#8217;re going to script this bit.</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
set serveroutput on size unlimited
set lines 130
spool change_view_synonyms.log
DECLARE
-------------------------------------------------------------------------------
-- change_view_synonyms.sql - script to re-point the public synonyms
-- for all the views that are part of the Diagnostic and Tuning Pack APIs
-- to the DISABLE_PACK_MESSAGE table.
--
-------------------------------------------------------------------------------
    l_cmd VARCHAR2(500);
BEGIN
    FOR r_mem IN (
        SELECT object_name
        FROM disable_pack_dt.pack_members
        WHERE object_type = 'VIEW')
    LOOP
        DBMS_OUTPUT.PUT_LINE('Replacing SYNONYM for '||r_mem.object_name);
        --
        -- As ever when concatenating values from a select statement into a 
        -- command, we need to make sure that the values in question are not
        -- in fact injection statements.
        -- In this case, the values should contain only $, _ and alphanumeric
        -- characters.
        --
        IF REGEXP_INSTR( 
            REGEXP_REPLACE( r_mem.object_name, '[$,_]'), 
            '[[:punct:]]|[[:space:]]') &gt; 0
        THEN
            RAISE_APPLICATION_ERROR(-20000, 'Object name '
                ||r_mem.object_name||' contains suspicious characters.');
        END IF;
        l_cmd := 'CREATE OR REPLACE PUBLIC SYNONYM '
            ||r_mem.object_name||' FOR disable_pack_dt.disable_pack_message';
        EXECUTE IMMEDIATE l_cmd;
    END LOOP;
END;
/
spool off
</pre>
<p>For the packages, we can just code the changes directly as there are only five of them :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
spool change_pack_synonyms.log

prompt
prompt Replacing synonym for DBMS_ADDM
prompt

CREATE OR REPLACE PUBLIC SYNONYM dbms_addm 
    FOR disable_pack_dt.block_dbms_addm
/

prompt
prompt Replacing synonym for DBMS_ADVISOR
prompt

CREATE OR REPLACE PUBLIC SYNONYM dbms_advisor 
    FOR disable_pack_dt.block_dbms_advisor
/

prompt
prompt Replacing synonym for DBMS_SQLTUNE
prompt

CREATE OR REPLACE PUBLIC SYNONYM dbms_sqltune 
    FOR disable_pack_dt.block_dbms_sqltune
/

prompt
prompt Replacing synonym for DBMS_WORKLOAD_REPLAY
prompt

CREATE OR REPLACE PUBLIC SYNONYM dbms_workload_replay
    FOR disable_pack_dt.block_dbms_workload_replay
/

prompt
prompt Replacing synonym for DBMS_ADVISOR
prompt

CREATE OR REPLACE PUBLIC SYNONYM dbms_workload_repository 
    FOR disable_pack_dt.block_dbms_workload_repository
/

spool off
</pre>
<h3>The tests</h3>
<p>For each test, we need to compare the usage statistics before and after the run. The first question is, how do we get Oracle to collect the usage statistics ?<br />
I&#8217;ve seen various things advising that you update the SYS.WRI$_DBU_USAGE_SAMPLE table. However, there is a more reliable alternative :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
BEGIN
	DBMS_FEATURE_USAGE_INTERNAL.EXEC_DB_USAGE_SAMPLING( curr_date =&gt; SYSDATE);
END;
/
</pre>
<p>Note &#8211; whilst executing this procedure does not update the WRI$_DBU_USAGE_SAMPLE table, it does update<br />
the SYS.WRI$_DBU_FEATURE_USAGE table with new stats on the features used.<br />
We can save the results of each feature usage audit before and after each test as follows :</p>
<pre class="brush: plain; title: ; notranslate">
CREATE TABLE before_test_1 AS
  SELECT *
  FROM sys.wri$_dbu_feature_usage
  WHERE detected_usages &gt; 0;
</pre>
<p>This means that we can check for any changes using the results from the before and after tables.<br />
If our tests work then, provided you don&#8217;t have any of the Tuning and Diagnostic features registered as being used before you start, you should get no rows returned when you run the query :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
SELECT name, TO_CHAR(last_usage_date, 'DD-MON-YYYY')
FROM after_test1
MINUS
SELECT name, TO_CHAR(last_usage_date, 'DD-MON-YYYY')
FROM before_test1;
</pre>
<p>So, to recap, before testing started I created a table called BEFORE_TEST1 containing all of the records in sys.wri$dbu_feature_usage where detected usages was greater than zero.</p>
<p>I then ran the test, then generated a usage statistics collection and then created an AFTER_TEST table.<br />
By comparing the most recently created table with it&#8217;s immediate predecessor, I was able to tell if the test had caused any additional features to have been used.</p>
<h4>Test 1 – Accessing a View</h4>
<p>Connect as the HR user and …</p>
<pre class="brush: plain; highlight: [4,5,6,7,8]; title: ; wrap-lines: false; notranslate">
SQL&gt; SELECT *      
  2  FROM dba_advisor_tasks; 

URGENT_PLEASE_READ 
-------------------------------------------------------------------------------- 
Diagnostic and Tuning Packs are NOT LICENSED on this database. 
Please do not access any of the pack API objects or underlying tables. 
For a full list please see the table disable_pack_dt.pack_members 
</pre>
<p>The check returned no rows.</p>
<h4>Test 2 – Specify view columns</h4>
<p>If column names are specified anywhere in the select statement, including the predicate, we should get an error&#8230;</p>
<pre class="brush: sql; highlight: [6,7,8,9]; title: ; wrap-lines: false; notranslate">
spool test2.log 
SELECT owner, task_name, description 
FROM dba_advisor_tasks 
/

SELECT owner, task_name, description 
                         * 
ERROR at line 1: 
ORA-00904: &quot;DESCRIPTION&quot;: invalid identifier 
</pre>
<p>Normally, when you get this error, you&#8217;ll check the table structure by means of a describe&#8230;</p>
<pre class="brush: sql; highlight: [4]; title: ; wrap-lines: false; notranslate">
SQL&gt; desc dba_advisor_tasks 
 Name					   Null?    Type 
 ----------------------------------------- -------- ---------------------------- 
 URGENT_PLEASE_READ				    VARCHAR2(4000) 

SQL&gt; 
</pre>
<p>Now, you&#8217;d expect the user to select this from the table and see the message :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
SQL&gt; SELECT urgent_please_read 
  2  FROM dba_advisor_tasks 
  3  / 

URGENT_PLEASE_READ 
-------------------------------------------------------------------------------- 
Diagnostic and Tuning Packs are NOT LICENSED on this database. 
Please do not access any of the pack API objects or underlying tables. 
For a full list please see the table disable_pack_dt.pack_members 


SQL&gt; 
</pre>
<p><strong>NOTE</strong> – if instead, the user decides to try prefixing the object owner in the from clause, they can get to the underlying view as they will by-pass the synonym.<br />
I&#8217;ve deliberately steered away from revoking access to these objects in order to balance the need to disable the packs with the risk of breaking something internally within Oracle.</p>
<p>Anyway, once again I got no rows returned from my usage check.</p>
<h4>Test 3 – SQLDeveloper Last AWR Report</h4>
<p>As mentioned previously, <a href="http://wp.me/pweWl-tX">SQLDeveloper has an AWR Report  available</a>.<br />
For this test, I am going to run the code for this report directly from SQL*Plus. As a follow-up, I&#8217;ll run it from inside SQLDeveloper.</p>
<p>First of all, running this from SQLPlus. This time, we need to use another user as HR does not have permissions on dba_hist_snapshot. For my testing, I used an account with DBA priviliges :</p>
<pre class="brush: sql; highlight: [13,14]; title: ; wrap-lines: false; notranslate">
declare 
    dbid number; 
    instance_id number; 
    start_id number; 
    end_id number; 
begin 
    dbms_output.enable(1000000); 
    select max(snap_id)-1,max(snap_id) into start_id,end_id from dba_hist_snapshot; 
    select dbid into dbid from v$database; 
    select instance_number into instance_id from v$instance; 

    dbms_output.put_line('&lt;PRE&gt;'); 
    for rc in ( select output from 
        table(dbms_workload_repository.awr_report_text(dbid,instance_id,start_id,end_id)) 
    ) loop 
        -- dbms_output.put_line('&lt;BR&gt;'); 
        dbms_output.put_line(rc.output); 
    end loop; 
    dbms_output.put_line('&lt;/PRE&gt;'); 
end; 
/
</pre>
<p>when we execute this, we get …</p>
<pre class="brush: plain; highlight: [4,5,6]; title: ; notranslate">
declare 
* 
ERROR at line 1: 
ORA-20999: Diagnostic and Tuning Packs are NOT LICENSED on this database. 
Please do not access any of the pack API objects or underlying tables. 
For a full list please see the table disable_pack_dt.pack_members 
ORA-06512: at &quot;DISABLE_PACK_DT.GET_ERR_MSG_FN&quot;, line 14 
ORA-06512: at &quot;DISABLE_PACK_DT.BLOCK_DBMS_WORKLOAD_REPOSITORY&quot;, line 238 
ORA-06512: at line 1 
ORA-06512: at line 13 


SQL&gt; 
</pre>
<p>As before, when checking the before and after usage stats, there&#8217;s no change.</p>
<h4>Test 4 – AWR Report from SQLDeveloper</h4>
<p>Unless something very unusual happens, we should get exactly the same result when we invoke this code from the SQL Developer Reports tab …</p>
<div id="attachment_1913" class="wp-caption alignnone" style="width: 460px"><a href="http://mikesmithers.files.wordpress.com/2013/03/sqldeveloper_rpt1.png"><img src="http://mikesmithers.files.wordpress.com/2013/03/sqldeveloper_rpt1.png?w=450&#038;h=301" alt="Fingers crossed...and press the button !" width="450" height="301" class="size-full wp-image-1913" /></a><p class="wp-caption-text">Fingers crossed&#8230;and press the button !</p></div>
<p>When we execute this report, we get&#8230;.</p>
<div id="attachment_1914" class="wp-caption alignnone" style="width: 460px"><a href="http://mikesmithers.files.wordpress.com/2013/03/sqldev_error.png"><img src="http://mikesmithers.files.wordpress.com/2013/03/sqldev_error.png?w=450&#038;h=220" alt="...and nothing happens. Apart from our error message popping up." width="450" height="220" class="size-full wp-image-1914" /></a><p class="wp-caption-text">&#8230;and nothing happens. Apart from our error message popping up.</p></div>
<p>Once again, a comparison of the before and after test tables should show that no usage has been recorded for AWR Report.</p>
<h3>Conclusion</h3>
<p>The Oracle supplied methods of disabling the Diagnostic and Tuning packs all have their limitations.<br />
Turning the relevant features off in Enterprise Manager will only stop their use from within Enterprise Manager.<br />
The same can be said of the  control_management_pack_access parameter.<br />
As we have seen, the License options in SQLDeveloper also has it&#8217;s limitations.</p>
<p>Whilst the synonyms approach, is not foolproof, it does offer significantly improved protection against accidentally using features for which you are not licensed.</p>
<p>Deb reckons that with the money this will save on licenses, I can afford to take her to the pictures.<br />
Funny, I didn&#8217;t think that Star Wars 7 was out yet.</p>
<br />Filed under: <a href='http://mikesmithers.wordpress.com/category/oracle/'>Oracle</a>, <a href='http://mikesmithers.wordpress.com/category/plsql/'>PL/SQL</a>, <a href='http://mikesmithers.wordpress.com/category/sql/'>SQL</a> Tagged: <a href='http://mikesmithers.wordpress.com/tag/control_management_pack_access/'>CONTROL_MANAGEMENT_PACK_ACCESS</a>, <a href='http://mikesmithers.wordpress.com/tag/create-or-replace-public-synonym/'>create or replace public synonym</a>, <a href='http://mikesmithers.wordpress.com/tag/dbms_addm/'>dbms_addm</a>, <a href='http://mikesmithers.wordpress.com/tag/dbms_advisor/'>dbms_advisor</a>, <a href='http://mikesmithers.wordpress.com/tag/dbms_feature_usage_internal-exec_db_usage_sampling/'>DBMS_FEATURE_USAGE_INTERNAL.EXEC_DB_USAGE_SAMPLING</a>, <a href='http://mikesmithers.wordpress.com/tag/dbms_management_packs/'>DBMS_MANAGEMENT_PACKS</a>, <a href='http://mikesmithers.wordpress.com/tag/dbms_sqltune/'>dbms_sqltune</a>, <a href='http://mikesmithers.wordpress.com/tag/dbms_workload_replay/'>dbms_workload_replay</a>, <a href='http://mikesmithers.wordpress.com/tag/dbms_workload_repository/'>dbms_workload_repository</a>, <a href='http://mikesmithers.wordpress.com/tag/diagnostic-and-tuning-pack/'>Diagnostic and Tuning Pack</a>, <a href='http://mikesmithers.wordpress.com/tag/diagnostic-pack/'>diagnostic pack</a>, <a href='http://mikesmithers.wordpress.com/tag/disable-diagnostic-and-tuning-packs/'>Disable Diagnostic and Tuning Packs</a>, <a href='http://mikesmithers.wordpress.com/tag/public-synonyms/'>public synonyms</a>, <a href='http://mikesmithers.wordpress.com/tag/regexp_instr/'>REGEXP_INSTR</a>, <a href='http://mikesmithers.wordpress.com/tag/regexp_replace/'>REGEXP_REPLACE</a>, <a href='http://mikesmithers.wordpress.com/tag/sqldeveloper-last-awr-report/'>SQLDeveloper Last AWR Report</a>, <a href='http://mikesmithers.wordpress.com/tag/tuning-pack/'>tuning pack</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=1904&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mikesmithers.wordpress.com/2013/03/07/disabling-the-oracle-diagnostic-and-tuning-pack-apis-if-you-want-something-done-do-it-yourself/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3cb0956016bbad280193fbbd8e649b9?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Mike S</media:title>
		</media:content>

		<media:content url="http://mikesmithers.files.wordpress.com/2013/03/sqldeveloper_rpt1.png" medium="image">
			<media:title type="html">Fingers crossed...and press the button !</media:title>
		</media:content>

		<media:content url="http://mikesmithers.files.wordpress.com/2013/03/sqldev_error.png" medium="image">
			<media:title type="html">...and nothing happens. Apart from our error message popping up.</media:title>
		</media:content>
	</item>
		<item>
		<title>SQLDeveloper and a very expensive query</title>
		<link>http://mikesmithers.wordpress.com/2013/02/09/sqldeveloper-and-a-very-expensive-query/</link>
		<comments>http://mikesmithers.wordpress.com/2013/02/09/sqldeveloper-and-a-very-expensive-query/#comments</comments>
		<pubDate>Sat, 09 Feb 2013 00:20:58 +0000</pubDate>
		<dc:creator>mikesmithers</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLDeveloper]]></category>
		<category><![CDATA[$WRI_DBU_FEATURE_USAGE_METADATA]]></category>
		<category><![CDATA[CONTROL_MANAGEMENT_PACK_ACCESS]]></category>
		<category><![CDATA[DBA_FEATURE_USAGE_STATISTICS]]></category>
		<category><![CDATA[Diagnostic and Tuning Pack]]></category>
		<category><![CDATA[Oracle Database Licensing]]></category>
		<category><![CDATA[SQLDeveloper Licensing settings]]></category>
		<category><![CDATA[v$parameter]]></category>

		<guid isPermaLink="false">http://mikesmithers.wordpress.com/?p=1857</guid>
		<description><![CDATA[The magic of the FA Cup. It&#8217;s one of those cliches that you are brought up to believe as an article of faith if you&#8217;re English. It is supposed to refer to the glorious unpredictability in a knockout cup competition where there is no seeding. In recent years, it&#8217;s become a lazy journalist&#8217;s phrase. An [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=1857&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>The magic of the FA Cup. It&#8217;s one of those cliches that you are brought up to believe as an article of faith if you&#8217;re English.<br />
It is supposed to refer to the glorious unpredictability in a knockout cup competition where there is no seeding.<br />
In recent years, it&#8217;s become a lazy journalist&#8217;s phrase. An attempt to sensationalise a result that, usually, isn&#8217;t that surprising.<br />
In this year&#8217;s fourth round, however, Non-league Luton Town went to Premier League Norwich and won, 1-0.<br />
The first time in 24 years that a top-flight club has been knocked out by one outside of the Football League has taken it&#8217;s toll.<br />
Simon, life-long Luton fan, now has some very achy face muscles as a result of walking around with a huge grin on his face for the last week.<br />
At this point, I could try to relate this sporting miracle back to the Star Wars theme that&#8217;s been running through this series of posts on Oracle Licensing, but it&#8217;s a bit difficult.<br />
Luton, plucky underdog rebels. Norwich City the Evil Empire&#8230;I just can&#8217;t really see it.<br />
<a href="http://www.deliaonline.com/">Delia Smith</a> as Palpatine with <a href="https://en.wikipedia.org/wiki/Chris_Hughton">Chris Hughton</a> as Darth Vader ? Somehow it just doesn&#8217;t seem to work.<br />
Anyway, back to the license stuff. So far, we&#8217;ve looked at :</p>
<ul>
<li><a href="http://wp.me/pweWl-rW">Oracle Licensing for the various Database Editions</a></li>
<li><a href="http://wp.me/pweWl-sZ">How Oracle audits features used on the database</a></li>
<li><a href="http://wp.me/pweWl-t9">The components that comprise the Diagnostic and Tuning Pack APIs</a></li>
</ul>
<p>This time, we&#8217;re going to turn our attention to SQLDeveloper and of the ways in which it attempts to allow users to avoid using the Diagnostic and Tuning Packs. <span id="more-1857"></span></p>
<h3>Disabling the Diagnostic and Tuning Packs – the documented approaches</h3>
<p>The Oracle licensing documentation itself makes mention of two ways of &#8220;disabling&#8221; these Packs.</p>
<p>Oracle Enterprise Manager has options available to turn off Diagnostic and Tuning Pack features. It appears that setting these will prevent Enterprise Manager itself from using them.</p>
<p>Then, there is the  CONTROL_MANAGEMENT_PACK_ACCESS initialization parameter, available from 11g. Setting this to NONE should avoid any standard Oracle jobs/processes from using the Diagnostic and Tuning Pack features in a way that will register in the feature usage checks. </p>
<p>SQLDeveloper offers something that is ostensibly similar to the OEM options.<br />
The SQLDeveloper IDE has come on in leaps and bounds in terms of the functionality offered.<br />
This additional functionality has also brought with it a mechanism to safeguard against inadvertant usage of the Diagnostic and Tuning Packs from within the tool. However, this is not entirely foolproof&#8230; </p>
<h3>SQLDeveloper Licensing Preferences</h3>
<p>To start with, lets take a look at SQLDeveloper&#8217;s Database Licensing screen. </p>
<p>Open SQLDeveloper and go to the <strong>Tools</strong> Menu and select <strong>Preferences</strong>.<br />
Under the <strong>Database</strong> node in the tree, select <strong>Licensing</strong>.<br />
For each Connection you have defined you&#8217;ll see three check boxes &#8230; </p>
<p><a href="http://mikesmithers.files.wordpress.com/2013/02/license1.jpg"><img src="http://mikesmithers.files.wordpress.com/2013/02/license1.jpg?w=450&#038;h=322" alt="license1" width="450" height="322" class="alignnone size-full wp-image-1859" /></a></p>
<p>According to the SQLDeveloper help, the default value of these settings ( i.e. filled boxes) means that<br />
it is unknown whether the relevant packs are licensed on the database.<br />
To make sure that SQLDeveloper knows that these are NOT licensed, change the checkboxes to be blank&#8230; </p>
<div id="attachment_1860" class="wp-caption alignnone" style="width: 460px"><a href="http://mikesmithers.files.wordpress.com/2013/02/license2.jpg"><img src="http://mikesmithers.files.wordpress.com/2013/02/license2.jpg?w=450&#038;h=321" alt="Look Mum, no packs !" width="450" height="321" class="size-full wp-image-1860" /></a><p class="wp-caption-text">Look Mum, no packs !</p></div>
<p>Now click <strong>OK</strong> to save. </p>
<p>Once again, to make sure that the new settings are effective, shutdown and re-start SQLDeveloper.<br />
Then go and review the settings.<br />
All looking good so far. </p>
<p>At this point, we just need to check a couple of things. First, we need to make sure that the<br />
database initialization parameter is set correctly : </p>
<pre class="brush: sql; title: ; notranslate"> 
SELECT value 
FROM v$parameter 
WHERE name = 'control_management_pack_access' 
/ 
</pre>
<p>The query should return &#8216;NONE&#8217;. </p>
<p>The second step is to make sure that we have no detected usages of AWR Report on the database : </p>
<pre class="brush: sql; highlight: [8]; title: ; notranslate"> 
SELECT currently_used, detected_usages, first_usage_date 
FROM dba_feature_usage_statistics 
WHERE name = 'AWR Report' 
/ 

CURRENTLY_USED DETECTED_USAGES FIRST_USAGE_DATE 
-------------- --------------- ---------------- 
FALSE                        0                  
</pre>
<p>To make sure that no usage has been detected since the last usage audit run, we can do a double-check using<br />
the code specified in $WRI_DBU_FEATURE_USAGE_METADATA for AWR Report. NOTE &#8211; unless you&#8217;re running as SYS, you&#8217;ll need to add the schema name to the tables in this query (as I have here) : </p>
<pre class="brush: sql; highlight: [2,4]; title: ; wrap-lines: false; notranslate"> 
with last_period as 
       (select * from sys.wrm$_wr_usage 
         where upper(feature_type) like 'REPORT' 
           and usage_time &gt;=  (select nvl(max(last_sample_date), sysdate-7) from sys.wri$_dbu_usage_sample) ) 
       select decode (count(*), 0, 0, 1), 
              count(*), 
              feature_list 
         from last_period, 
        (select substr(sys_connect_by_path(feature_count, ','),2) feature_list 
           from 
             (select feature_count, 
                     count(*) over () cnt, 
                     row_number () over (order by 1) seq 
                from 
                  (select feature_name || ':' || count(*) feature_count 
                     from last_period 
                 group by feature_name) 
             ) 
        where seq=cnt 
        start with seq=1 
   connect by prior seq+1=seq) 
     group by feature_list 
 / 
</pre>
<p>Provided this query returns no rows, then we&#8217;re good to go. </p>
<p>Now, SQLDeveloper has a number of useful reports bundled with it. These are available on the <strong>Reports</strong> tab.<br />
If this isn&#8217;t visible, then you can open it by going to the <strong>View</strong> menu and selecting <strong>Reports</strong>.<br />
Under the <strong>Data Dictionary Reports</strong>, there is a sub-folder containing <strong>ASH and AWR</strong> reports. </p>
<div id="attachment_1858" class="wp-caption alignnone" style="width: 460px"><a href="http://mikesmithers.files.wordpress.com/2013/02/awr_report.jpg"><img src="http://mikesmithers.files.wordpress.com/2013/02/awr_report.jpg?w=450&#038;h=386" alt="Hmmm, should I press the big red button ?" width="450" height="386" class="size-full wp-image-1858" /></a><p class="wp-caption-text">Hmmm, should I press the big red button ?</p></div>
<p>If you now run the <strong>Last AWR Report</strong>, the output is likely to be fairly light on detail. However, if you look at the sourcecode for this query, by hitting the<br />
Run Report in SQL Worksheet button, you can see that the sourcecode looks like this : </p>
<pre class="brush: sql; highlight: [8,14]; title: ; wrap-lines: false; notranslate"> 
declare 
dbid number; 
instance_id number; 
start_id number; 
end_id number; 
begin 
dbms_output.enable(1000000); 
select max(snap_id)-1,max(snap_id) into start_id,end_id from dba_hist_snapshot; 
select dbid into dbid from v$database; 
select instance_number into instance_id from v$instance; 

dbms_output.put_line('&lt;PRE&gt;'); 
for rc in ( select output from 
   table(dbms_workload_repository.awr_report_text(dbid,instance_id,start_id,end_id)) 
           ) loop 
  -- dbms_output.put_line('&lt;BR&gt;'); 
   dbms_output.put_line(rc.output); 
end loop; 
dbms_output.put_line('&lt;/PRE&gt;'); 
end; 
</pre>
<p>OK, so DBA_HIST_SNAPSHOT is one of those Diagnostic Pack views, but the SQLDeveloper settings and inititialization parameter should have protected<br />
us from any accidental usage of the Diagnostic Pack shouldn&#8217;t it ? </p>
<p>Let&#8217;s re-run the detection query to check&#8230; </p>
<pre class="brush: sql; highlight: [27]; title: ; wrap-lines: false; notranslate"> 
with last_period as 
       (select * from sys.wrm$_wr_usage 
         where upper(feature_type) like 'REPORT' 
           and usage_time &gt;=  (select nvl(max(last_sample_date), sysdate-7) from sys.wri$_dbu_usage_sample) ) 
       select decode (count(*), 0, 0, 1), 
              count(*), 
              feature_list 
         from last_period, 
        (select substr(sys_connect_by_path(feature_count, ','),2) feature_list 
           from 
             (select feature_count, 
                     count(*) over () cnt, 
                     row_number () over (order by 1) seq 
                from 
                  (select feature_name || ':' || count(*) feature_count 
                     from last_period 
                 group by feature_name) 
             ) 
        where seq=cnt 
        start with seq=1 
   connect by prior seq+1=seq) 
     group by feature_list 
 / 

DECODE(COUNT(*),0,0,1)   COUNT(*) FEATURE_LIST
---------------------- ---------- -------------- 
                     1          1 AWR Report:1
</pre>
<p>Oh. Despite our best efforts, it only takes one curious soul playing with SQLDeveloper reports and the DBA is going to have his or her work cut-out.<br />
If you want to calculate the cost of this query, you might want to consider an alternative to Explain Plan&#8230;. the <a href="https://shop.oracle.com/pls/ostore/f?p=dstore:home:0:::::&amp;tz=0:00">Oracle Store</a>.</p>
<h3>Counting the Cost</h3>
<p>Incidentally, if you want to do any conversion, the dollar exchange rate for stirling is currently around 1.6&#8230;.and you can get a season ticket for Luton for around £300.<br />
Let&#8217;s assume that the database on which you&#8217;ve encountered this problem is Standard Edition running on 4 quad-core CPUs.</p>
<p>Because it&#8217;s standard edition, you&#8217;re licensed per socket rather than per core.<br />
So, on current prices you&#8217;d have paid £46920 for your licenses ( £11730 per processor) and would expect an annual maintenance fee in the region of £10323.</p>
<p>The problem is, due to your usage of the Diagnostic Pack, you now become liable for </p>
<ul>
<li>Upgrading your licenses to Enterprise Edition</li>
<li>purchasing the license for the Diagnostic Pack</li>
</ul>
<p>Remember, the Diagnostic Pack is only available as an option on Enterprise Edition.<br />
OK, here goes&#8230;<br />
Enterprise Edition processor licenses are based on the number of cores rather than the number of physical CPUs. For most CPU types, the calculation works out to one core being the equivalent of 0.75 processors.</p>
<p>Our box has 16 cores ( 4 per CPU), so this will work out to 12 Processor Licenses.</p>
<p>An Enterprise Edition per Processor License is £31839.<br />
Twelve of those comes to £382068.<br />
To rub a bit of salt into the wound, the first year support cost is a shade over £7000 per processor ( £84000).</p>
<p>The Diagnostic Pack comes in at £3352.00 per processor with a first year support cost of £737.33. Both figures are per processor.</p>
<p>For the sake of simplicity ( and for any wild optimists reading this), we&#8217;ll assume that you can offset the purchase cost of your existing database licenses against the new Enterprise Edition licenses.<br />
Even then, the numbers are frighteningly big&#8230;</p>
<p>Enterprise Edition Database (12 @ £31839) £382068<br />
plus First Year Support ( 12@ £7004.64)  £84055.68<br />
Diagnostic Pack ( 12@ £3352) £40224.00<br />
plus First Year Support (12 @ £737.33) £8847.96<br />
Sub-Total £514795.64<br />
Less Standard Edition Licenses (4 @ 11730) &#8211; £46920<br />
Less Standard Edition Support ( 4 @ 2580.86) -£10323.</p>
<p>Total due to Oracle :  £457,552.64.</p>
<p>As you&#8217;re likely to have a similar spec Development server ( and possibly even a DR server) runnng clones of this database, you&#8217;ll need to double or even triple this figure. Yep it&#8217;s likely to be per server.</p>
<p>In Oracle terms then, we can probably conclude that&#8230;</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
SELECT output 
FROM TABLE(DBMS_WORKLOAD_REPOSITORY.AWR_REPORT_TEXT(dbid,instance_id,start_id,end_id)) 
/
</pre>
<p>&#8230;is a million dollar question.</p>
<h3>Coming Soon&#8230;A New Hope</h3>
<p>To be fair to SQLDevelepor, this particular problem is not directly of the tool&#8217;s own making ( although closing this particular loophole would be greatly appreciated).<br />
The Licensing of the Diagnostic and Tuning Packs has been a running sore since Oracle released the 10g database in 2003. Yes, 10 years later and we&#8217;re still looking for a solution.<br />
<a href="http://wp.me/pweWl-uI">In the next ( and final) post in this particular saga</a>, I&#8217;ll take matters into my own hands in an attempt to make things a little easier all round.<br />
I&#8217;ll even dispense with the Star Wars references alltogether (maybe).<br />
In the meantime, I&#8217;m off to the SQLDeveloper forum&#8230;&#8221;Help me <a href="http://www.thatjeffsmith.com/">Jeff Smith</a>, you&#8217;re my only hope&#8230; &#8220;</p>
<br />Filed under: <a href='http://mikesmithers.wordpress.com/category/oracle/'>Oracle</a>, <a href='http://mikesmithers.wordpress.com/category/sql/'>SQL</a>, <a href='http://mikesmithers.wordpress.com/category/sqldeveloper/'>SQLDeveloper</a> Tagged: <a href='http://mikesmithers.wordpress.com/tag/wri_dbu_feature_usage_metadata/'>$WRI_DBU_FEATURE_USAGE_METADATA</a>, <a href='http://mikesmithers.wordpress.com/tag/control_management_pack_access/'>CONTROL_MANAGEMENT_PACK_ACCESS</a>, <a href='http://mikesmithers.wordpress.com/tag/dba_feature_usage_statistics/'>DBA_FEATURE_USAGE_STATISTICS</a>, <a href='http://mikesmithers.wordpress.com/tag/diagnostic-and-tuning-pack/'>Diagnostic and Tuning Pack</a>, <a href='http://mikesmithers.wordpress.com/tag/oracle-database-licensing/'>Oracle Database Licensing</a>, <a href='http://mikesmithers.wordpress.com/tag/sqldeveloper-licensing-settings/'>SQLDeveloper Licensing settings</a>, <a href='http://mikesmithers.wordpress.com/tag/vparameter/'>v$parameter</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=1857&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mikesmithers.wordpress.com/2013/02/09/sqldeveloper-and-a-very-expensive-query/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3cb0956016bbad280193fbbd8e649b9?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Mike S</media:title>
		</media:content>

		<media:content url="http://mikesmithers.files.wordpress.com/2013/02/license1.jpg" medium="image">
			<media:title type="html">license1</media:title>
		</media:content>

		<media:content url="http://mikesmithers.files.wordpress.com/2013/02/license2.jpg" medium="image">
			<media:title type="html">Look Mum, no packs !</media:title>
		</media:content>

		<media:content url="http://mikesmithers.files.wordpress.com/2013/02/awr_report.jpg" medium="image">
			<media:title type="html">Hmmm, should I press the big red button ?</media:title>
		</media:content>
	</item>
		<item>
		<title>Oracle Database Diagnostic and Tuning Packs – exactly what are you not licensed for ?</title>
		<link>http://mikesmithers.wordpress.com/2013/01/26/oracle-database-diagnostic-and-tuning-packs-exactly-what-are-you-not-licensed-for/</link>
		<comments>http://mikesmithers.wordpress.com/2013/01/26/oracle-database-diagnostic-and-tuning-packs-exactly-what-are-you-not-licensed-for/#comments</comments>
		<pubDate>Sat, 26 Jan 2013 18:47:27 +0000</pubDate>
		<dc:creator>mikesmithers</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[CONTROL_MANAGEMENT_PACK_ACCESS]]></category>
		<category><![CDATA[dba_dependencies]]></category>
		<category><![CDATA[dba_objects]]></category>
		<category><![CDATA[Diagnostic and Tuning Pack API List]]></category>
		<category><![CDATA[Oracle Database Licensing]]></category>
		<category><![CDATA[Oracle Diagnostic Pack]]></category>
		<category><![CDATA[Oracle Tuning Pack]]></category>

		<guid isPermaLink="false">http://mikesmithers.wordpress.com/?p=1807</guid>
		<description><![CDATA[It&#8217;s that time of year. The expense of Christmas is becoming apparent and January payday has seemed to be forever in arriving. “&#8230;and I need a crown !”, said Deb. This caused me to pause for a moment. Was my better half getting delusions of granduer ? Further, delicate enquiries revealed that it was merely [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=1807&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>It&#8217;s that time of year. The expense of Christmas is becoming apparent and January payday has seemed to be forever in arriving.<br />
“&#8230;and I need a crown !”, said Deb.<br />
This caused me to pause for a moment. Was my better half getting delusions of granduer ?<br />
Further, delicate enquiries revealed that it was merely a dental crown to which she was referring.<br />
Not that it seems to make much difference financially. You could probably buy a fairly substantial piece of regal headgear for what the dentist was asking.</p>
<p>On the plus side, Queen Deb&#8217;s costume for the next instalment of the Licensing Epic doesn&#8217;t require such accoutriments&#8230;although a big pair of headphones and lots of hairspray may be in order. Yes, I&#8217;m still on my Star Wars themed odyssey through Oracle Database Licensing.</p>
<p>In the previous posts, I&#8217;ve already covered :</p>
<ul>
<li><a href="http://wp.me/pweWl-rW">Oracle Licensing for the various Database Editions</a></li>
<li><a href="http://wp.me/pweWl-sZ">How Oracle audits features used on the database</a></li>
</ul>
<p>Now, it&#8217;s time to get to grips with the licensing minefield that are the Diagnostic and Tuning Packs.<br />
Queue the orchestra&#8230;.</p>
<h2>Episode 2 – Attack of the Diagnostic and Tuning Packs</h2>
<p>Confusion is rife in the Data Centre. The Geeki have found that the incredibly useful AWR and ASH utilities are in fact secret members of The Diagnostic Pack.<br />
Fearing the presence of the Dark Side, they must now re-enter the realms of the mysterious Oracle Database License to </p>
<ul>
<li>Determine which features are part of these packs</li>
<li>Work out exactly what constitutes usage of these packs</li>
<li>find out which database objects that are part of these packs</li>
</ul>
<p>With this information, at least they will know which objects they must avoid if they are not to have to pay substanital additonal licenses&#8230;</p>
<h3>Disclaimer</h3>
<p>This code has been written and tested on Oracle Database 11gR2 Express Edition.<br />
The licensing information I&#8217;ve referenced is for Oracle Database 11gR2.<br />
I&#8217;m fairly sure it all works as expected. However, as you undoubtedly know, you shouldn&#8217;t take my word for it.<br />
Before you go playing around with this on any production environment, please make sure it does what I think it does.<br />
Of course, if you do find any issues, I&#8217;d be great if you could put a comment on here so that I can correct any issues&#8230;and also to give a pointer to anyone else looking at this post.<br />
Yes, I know the standard disclaimer about &#8220;similarity to events or persons living or dead&#8221; always goes at the end of the film, but I thought it best to put it at the start.<br />
Incidentally, have you ever wondered exactly what real-life events Star Wars could have a similarity to ?</p>
<p><span id="more-1807"></span></p>
<h3>Decyphering the Ancient Holocron – Diagnostic and Tuning Pack Licensing</h3>
<p>Whatever Database Edition you choose to install, the Diagnostic and Tuning Pack objects will end up sitting in your database.</p>
<p>Why look at these together, rather than separately ?<br />
Well, one reason is that, if you want to use any Tuning Pack features, you must also purchas the Diagnostic Pack.</p>
<p>The ancient archives contain no clue as to why this would be, but it is thought that these tools were originally intended to be universally available. However, at some point, someone decided that they should be available only as additional cost options to the Enterprise Edition.<br />
The assumption that the license documentation was written after the code would probably help in understanding what follows.</p>
<p>Let&#8217;s start by taking a look at the features included in each of these packs. This is worth doing as the  feature usage auditing does not specify explicitly which database features are part of which pack ( or even if a feature is an additional cost option). As for most of this post, this information can be found in the <a href="http://docs.oracle.com/cd/E11882_01/license.112/e10594/options.htm#CIHIHDDJ">Database Licensing Documentation</a>.</p>
<h4>Diagnostic Pack Features</h4>
<p>So, from the licensing documentation, we can see that the Diagnostic Pack includes :</p>
<ul>
<li>Automatic Workload Repository (AWR)</li>
<li>Automatic Database Diagnostic Monitor (ADDM) </li>
<li>Active Session History (ASH)</li>
<li>Performance Monitoring (database and host)</li>
</ul>
<p>There&#8217;s other stuff in there, but the point is that some of the descriptions are a bit vague to say the least.<br />
For example, “Performance Monitoring” &#8211; would that include BSTAT/ESTAT and tkprof ?<br />
Well, no, it doesn&#8217;t. However, further clarity is needed here. We&#8217;ll come onto that in a moment.<br />
First though, let&#8217;s take a look at&#8230;</p>
<h4>Tuning Pack Features</h4>
<p>The list for the Tuning Pack is a bit shorter but some ambiguity still remains :</p>
<ul>
<li>SQL Access Advisor</li>
<li>SQL Tuning Advisor</li>
<li>Automatic SQL Tuning</li>
<li>SQL Tuning Sets</li>
<li>SQL Monitoring</li>
<li>Reorganize objects</li>
</ul>
<p>Reorganize objects is another one of those ever-so-slightly fuzzy definitions.</p>
<h4>Enabling and Disabling the Packs</h4>
<p>Instructions are included for disabling access for both packs from Enterprise Manager.<br />
There is also mention of the<br />
CONTROL_MANAGEMENT_PACK_ACCESS init.ora parameter.<br />
However, what neither of these settings will do is to disable access to the command-line APIs.<br />
And here&#8217;s the rub. The documentation clearly states that  any and all methods of accessing Oracle Diagnostics/Tuning Pack functionality, even through command-line APIs, or direct access to the underlying data, requires a license.</p>
<p>What we need then, is a comprehensive list of these APIs to help us avoid accidentally using the packs and incurring the resultant licensing costs.</p>
<h3>Command Line APIs</h3>
<p>Using the information in the licensing documentation, we&#8217;re going to build a table listing all of the command-line APIs for each pack. At least then, we&#8217;ll have a reference for database objects that we shouldn&#8217;t be using without licensing these packs.</p>
<h4>The table</h4>
<p>The table we&#8217;ll create to hold this information will consist of the following columns :</p>
<ul>
<li>object_name</li>
<li>object_type</li>
<li>pack_name – the pack to which the object belongs or BOTH if it belongs to both of them</li>
<li>full_member – Y if it&#8217;s completely a member of the pack or N if it is only under certain circumstances</li>
<li>notes – details of the circumstances in which the object is considered a member of the pack</li>
</ul>
<pre class="brush: sql; title: ; notranslate">
CREATE TABLE pack_members( 
    object_name VARCHAR2(30), 
    object_type VARCHAR2(20), 
    pack_name VARCHAR2(10), 
    full_member VARCHAR2(1), 
    notes VARCHAR2(4000)) 
/
</pre>
<h4>Populating the table</h4>
<p>First, the simple bit. This script populates the table with details of all the objects explicitly listed in the license documentation :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
--
-- Script to populate the pack_members table with
-- Diagnostic and Tuning Pack API Objects that are individually specified by
-- the license.
--

--
--  DBMS_WORKLOAD_REPOSITORY
--
INSERT INTO pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'DBMS_WORKLOAD_REPOSITORY', 'PACKAGE', 'DIAGNOSTIC',
    'Y', NULL)
/

--
-- DBMS_ADDM
--
INSERT INTO pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'DBMS_ADDM', 'PACKAGE', 'DIAGNOSTIC',
    'Y', NULL)
/

--
-- DBMS_ADVISOR - NOTE - this is a member of BOTH packs
--
INSERT INTO pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'DBMS_ADVISOR', 'PACKAGE', 'BOTH',
    'N', 
    'DIAGNOSTIC PACK - Only if advisor_name =&gt; ADDM OR task_name LIKE ADDM%'
    ||' TUNING PACK - where advisor_name =&gt; SQL Tuning Advisor OR SQL Access Advisor')
/

--
-- DBMS_WORKLOAD_REPLAY
--
INSERT INTO pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'DBMS_WORKLOAD_REPLAY', 'PACKAGE', 'DIAGNOSTIC',
    'N', 'COMPARE_PERIOD_REPORT function only')
/

--
-- V$ACTIVE_SESSION_HISTORY
-- NOTE - this is a synonym for V_$ACTIVE_SESSION_HISTORY
--
INSERT INTO pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'V$ACTIVE_SESSION_HISTORY', 'SYNONYM', 'DIAGNOSTIC',
    'Y', 'Synonym for V_$ACTIVE_SESSION_HISTORY')
/

INSERT INTO pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'V_$ACTIVE_SESSION_HISTORY', 'VIEW', 'DIAGNOSTIC',
    'Y', 'Synonym for this view is V_$ACTIVE_SESSION_HISTORY')
/

--
-- DBA_STREAMS_TP_PATH_BOTTLENECK
--
INSERT INTO pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'DBA_STREAMS_TP_PATH_BOTTLENECK', 'VIEW', 'DIAGNOSTIC',
    'Y', NULL)
/

--
--  DBA_STREAMS_TP_COMPONENT_STAT
--
INSERT INTO pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'DBA_STREAMS_TP_COMPONENT_STAT', 'VIEW', 'DIAGNOSTIC',
    'N', 'Only rows where STATISTIC_UNIT = PERCENT')
/

--
-- DBMS_SQLTUNE
--
INSERT INTO pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'DBMS_SQLTUNE', 'PACKAGE', 'TUNING',
    'Y', NULL)
/

--
-- V$SQL_MONITOR - NOTE - this is a public synonym for V_$SQL_MONITOR !!!
-- Therefore, we'll specify the underlying view here as well
--
INSERT INTO pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'V$SQL_MONITOR', 'SYNONYM', 'TUNING',
    'Y', 'Synonym for V_$SQL_MONITOR')
/

INSERT INTO pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'V_$SQL_MONITOR', 'VIEW', 'TUNING',
    'Y', 'Synonym for this view is V$SQL_MONITOR')
/

--
-- V$SQL_PLAN_MONITOR - public synonym for V_SQL_PLAN_MONITOR.
-- Again, specify the underlying view here as well
--

INSERT INTO pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'V_$SQL_PLAN_MONITOR', 'VIEW', 'TUNING',
    'Y', 'Synonym for this view is V$SQL_PLAN_MONITOR')
/

INSERT INTO pack_members(
    object_name, object_type, pack_name, 
    full_member, notes)
VALUES(
    'V$SQL_PLAN_MONITOR', 'SYNONYM', 'TUNING',
    'Y', 'Synonym for V_$SQL_PLAN_MONITOR')
/

COMMIT;
</pre>
<p>Now things get slightly more involved. We&#8217;ve got to decipher the rules in the documentation to determine exactly which other objects are also part of the respective APIs&#8230;</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
--
-- Find all of the Diagnostic Pack views that are not specified by
-- name in the License and insert them into the PACK_MEMBERS table
--
INSERT INTO pack_members( 
    object_name, object_type, pack_name,
    full_member, notes)
    SELECT object_name, object_type, 'DIAGNOSTIC',
        'Y', NULL
    FROM sys.dba_objects
    WHERE owner = 'SYS'
    AND object_type = 'VIEW'
    AND (
        object_name LIKE 'DBA_ADDM_%'
    OR ( 
        object_name LIKE 'DBA_HIST_%'
        AND object_name NOT IN (
            'DBA_HIST_SNAPSHOT', 'DBA_HIST_DATABASE_INSTANCE', 
            'DBA_HIST_SNAP_ERROR', 'DBA_HIST_SEG_STAT', 
            'DBA_HIST_SEG_STAT_OBJ', 'DBA_HIST_UNDOSTAT')
        )
    )
    UNION    
    SELECT object_name, object_type, 'DIAGNOSTIC',
        'N', 
        'Only where ADVISOR_NAME = ADDM or TASK_NAME LIKE ADDM% '
        ||'or TASK_ID relates back to TASK_NAME that is like ADDM%'
    FROM sys.dba_objects
    WHERE owner = 'SYS'
    AND object_type = 'VIEW'
    AND object_name LIKE 'DBA_ADVISOR_%'
/
COMMIT;
</pre>
<p>After that, we should now have 165 records in the PACK_MEMBERS table. Of these, 159 are Diagnostic Pack, five are Tuning pack, and one – DBMS_ADVISOR – is part of both packs.</p>
<h3>List of Diagnostic and Tuning Pack APIs</h3>
<p>Now, finally, you can see all of the APIs for each pack in one place.<br />
For the Diagnostic Pack :</p>
<pre class="brush: sql; title: ; notranslate">
SELECT object_name, object_type
FROM pack_members
WHERE pack_name IN ('DIAGNOSTIC', 'BOTH')
ORDER BY 2,1
/
</pre>
<p>The output is :</p>
<pre class="brush: plain; title: ; wrap-lines: false; notranslate">

OBJECT_NAME                    OBJECT_TYPE                                      
------------------------------ ------------------------------                   
DBMS_ADDM                      PACKAGE                                          
DBMS_ADVISOR                   PACKAGE                                          
DBMS_WORKLOAD_REPLAY           PACKAGE                                          
DBMS_WORKLOAD_REPOSITORY       PACKAGE                                          
DBA_ADDM_FDG_BREAKDOWN         VIEW                                             
DBA_ADDM_FINDINGS              VIEW                                             
DBA_ADDM_INSTANCES             VIEW                                             
DBA_ADDM_SYSTEM_DIRECTIVES     VIEW                                             
DBA_ADDM_TASKS                 VIEW                                             
DBA_ADDM_TASK_DIRECTIVES       VIEW                                             
DBA_ADVISOR_ACTIONS            VIEW                                             
DBA_ADVISOR_COMMANDS           VIEW                                             
DBA_ADVISOR_DEFINITIONS        VIEW                                             
DBA_ADVISOR_DEF_PARAMETERS     VIEW                                             
DBA_ADVISOR_DIR_DEFINITIONS    VIEW                                             
DBA_ADVISOR_DIR_INSTANCES      VIEW                                             
DBA_ADVISOR_DIR_TASK_INST      VIEW                                             
DBA_ADVISOR_EXECUTIONS         VIEW                                             
DBA_ADVISOR_EXECUTION_TYPES    VIEW                                             
DBA_ADVISOR_EXEC_PARAMETERS    VIEW                                             
DBA_ADVISOR_FDG_BREAKDOWN      VIEW                                             
DBA_ADVISOR_FINDINGS           VIEW                                             
DBA_ADVISOR_FINDING_NAMES      VIEW                                             
DBA_ADVISOR_JOURNAL            VIEW                                             
DBA_ADVISOR_LOG                VIEW                                             
DBA_ADVISOR_OBJECTS            VIEW                                             
DBA_ADVISOR_OBJECT_TYPES       VIEW                                             
DBA_ADVISOR_PARAMETERS         VIEW                                             
DBA_ADVISOR_PARAMETERS_PROJ    VIEW                                             
DBA_ADVISOR_RATIONALE          VIEW                                             
DBA_ADVISOR_RECOMMENDATIONS    VIEW                                             
DBA_ADVISOR_SQLA_COLVOL        VIEW                                             
DBA_ADVISOR_SQLA_REC_SUM       VIEW                                             
DBA_ADVISOR_SQLA_TABLES        VIEW                                             
DBA_ADVISOR_SQLA_TABVOL        VIEW                                             
DBA_ADVISOR_SQLA_WK_MAP        VIEW                                             
DBA_ADVISOR_SQLA_WK_STMTS      VIEW                                             
DBA_ADVISOR_SQLA_WK_SUM        VIEW                                             
DBA_ADVISOR_SQLPLANS           VIEW                                             
DBA_ADVISOR_SQLSTATS           VIEW                                             
DBA_ADVISOR_SQLW_COLVOL        VIEW                                             
DBA_ADVISOR_SQLW_JOURNAL       VIEW                                             
DBA_ADVISOR_SQLW_PARAMETERS    VIEW                                             
DBA_ADVISOR_SQLW_STMTS         VIEW                                             
DBA_ADVISOR_SQLW_SUM           VIEW                                             
DBA_ADVISOR_SQLW_TABLES        VIEW                                             
DBA_ADVISOR_SQLW_TABVOL        VIEW                                             
DBA_ADVISOR_SQLW_TEMPLATES     VIEW                                             
DBA_ADVISOR_TASKS              VIEW                                             
DBA_ADVISOR_TEMPLATES          VIEW                                             
DBA_ADVISOR_USAGE              VIEW                                             
DBA_HIST_ACTIVE_SESS_HISTORY   VIEW                                             
DBA_HIST_ASH_SNAPSHOT          VIEW                                             
DBA_HIST_BASELINE              VIEW                                             
DBA_HIST_BASELINE_DETAILS      VIEW                                             
DBA_HIST_BASELINE_METADATA     VIEW                                             
DBA_HIST_BASELINE_TEMPLATE     VIEW                                             
DBA_HIST_BG_EVENT_SUMMARY      VIEW                                             
DBA_HIST_BUFFERED_QUEUES       VIEW                                             
DBA_HIST_BUFFERED_SUBSCRIBERS  VIEW                                             
DBA_HIST_BUFFER_POOL_STAT      VIEW                                             
DBA_HIST_CLUSTER_INTERCON      VIEW                                             
DBA_HIST_COLORED_SQL           VIEW                                             
DBA_HIST_COMP_IOSTAT           VIEW                                             
DBA_HIST_CR_BLOCK_SERVER       VIEW                                             
DBA_HIST_CURRENT_BLOCK_SERVER  VIEW                                             
DBA_HIST_DATAFILE              VIEW                                             
DBA_HIST_DB_CACHE_ADVICE       VIEW                                             
DBA_HIST_DISPATCHER            VIEW                                             
DBA_HIST_DLM_MISC              VIEW                                             
DBA_HIST_DYN_REMASTER_STATS    VIEW                                             
DBA_HIST_ENQUEUE_STAT          VIEW                                             
DBA_HIST_EVENT_HISTOGRAM       VIEW                                             
DBA_HIST_EVENT_NAME            VIEW                                             
DBA_HIST_FILEMETRIC_HISTORY    VIEW                                             
DBA_HIST_FILESTATXS            VIEW                                             
DBA_HIST_IC_CLIENT_STATS       VIEW                                             
DBA_HIST_IC_DEVICE_STATS       VIEW                                             
DBA_HIST_INSTANCE_RECOVERY     VIEW                                             
DBA_HIST_INST_CACHE_TRANSFER   VIEW                                             
DBA_HIST_INTERCONNECT_PINGS    VIEW                                             
DBA_HIST_IOSTAT_DETAIL         VIEW                                             
DBA_HIST_IOSTAT_FILETYPE       VIEW                                             
DBA_HIST_IOSTAT_FILETYPE_NAME  VIEW                                             
DBA_HIST_IOSTAT_FUNCTION       VIEW                                             
DBA_HIST_IOSTAT_FUNCTION_NAME  VIEW                                             
DBA_HIST_JAVA_POOL_ADVICE      VIEW                                             
DBA_HIST_LATCH                 VIEW                                             
DBA_HIST_LATCH_CHILDREN        VIEW                                             
DBA_HIST_LATCH_MISSES_SUMMARY  VIEW                                             
DBA_HIST_LATCH_NAME            VIEW                                             
DBA_HIST_LATCH_PARENT          VIEW                                             
DBA_HIST_LIBRARYCACHE          VIEW                                             
DBA_HIST_LOG                   VIEW                                             
DBA_HIST_MEMORY_RESIZE_OPS     VIEW                                             
DBA_HIST_MEMORY_TARGET_ADVICE  VIEW                                             
DBA_HIST_MEM_DYNAMIC_COMP      VIEW                                             
DBA_HIST_METRIC_NAME           VIEW                                             
DBA_HIST_MTTR_TARGET_ADVICE    VIEW                                             
DBA_HIST_MUTEX_SLEEP           VIEW                                             
DBA_HIST_MVPARAMETER           VIEW                                             
DBA_HIST_OPTIMIZER_ENV         VIEW                                             
DBA_HIST_OSSTAT                VIEW                                             
DBA_HIST_OSSTAT_NAME           VIEW                                             
DBA_HIST_PARAMETER             VIEW                                             
DBA_HIST_PARAMETER_NAME        VIEW                                             
DBA_HIST_PERSISTENT_QMN_CACHE  VIEW                                             
DBA_HIST_PERSISTENT_QUEUES     VIEW                                             
DBA_HIST_PERSISTENT_SUBS       VIEW                                             
DBA_HIST_PGASTAT               VIEW                                             
DBA_HIST_PGA_TARGET_ADVICE     VIEW                                             
DBA_HIST_PLAN_OPERATION_NAME   VIEW                                             
DBA_HIST_PLAN_OPTION_NAME      VIEW                                             
DBA_HIST_PROCESS_MEM_SUMMARY   VIEW                                             
DBA_HIST_RESOURCE_LIMIT        VIEW                                             
DBA_HIST_ROWCACHE_SUMMARY      VIEW                                             
DBA_HIST_RSRC_CONSUMER_GROUP   VIEW                                             
DBA_HIST_RSRC_PLAN             VIEW                                             
DBA_HIST_RULE_SET              VIEW                                             
DBA_HIST_SERVICE_NAME          VIEW                                             
DBA_HIST_SERVICE_STAT          VIEW                                             
DBA_HIST_SERVICE_WAIT_CLASS    VIEW                                             
DBA_HIST_SESSMETRIC_HISTORY    VIEW                                             
DBA_HIST_SESS_TIME_STATS       VIEW                                             
DBA_HIST_SGA                   VIEW                                             
DBA_HIST_SGASTAT               VIEW                                             
DBA_HIST_SGA_TARGET_ADVICE     VIEW                                             
DBA_HIST_SHARED_POOL_ADVICE    VIEW                                             
DBA_HIST_SHARED_SERVER_SUMMARY VIEW                                             
DBA_HIST_SQLBIND               VIEW                                             
DBA_HIST_SQLCOMMAND_NAME       VIEW                                             
DBA_HIST_SQLSTAT               VIEW                                             
DBA_HIST_SQLTEXT               VIEW                                             
DBA_HIST_SQL_BIND_METADATA     VIEW                                             
DBA_HIST_SQL_PLAN              VIEW                                             
DBA_HIST_SQL_SUMMARY           VIEW                                             
DBA_HIST_SQL_WORKAREA_HSTGRM   VIEW                                             
DBA_HIST_STAT_NAME             VIEW                                             
DBA_HIST_STREAMS_APPLY_SUM     VIEW                                             
DBA_HIST_STREAMS_CAPTURE       VIEW                                             
DBA_HIST_STREAMS_POOL_ADVICE   VIEW                                             
DBA_HIST_SYSMETRIC_HISTORY     VIEW                                             
DBA_HIST_SYSMETRIC_SUMMARY     VIEW                                             
DBA_HIST_SYSSTAT               VIEW                                             
DBA_HIST_SYSTEM_EVENT          VIEW                                             
DBA_HIST_SYS_TIME_MODEL        VIEW                                             
DBA_HIST_TABLESPACE            VIEW                                             
DBA_HIST_TABLESPACE_STAT       VIEW                                             
DBA_HIST_TBSPC_SPACE_USAGE     VIEW                                             
DBA_HIST_TEMPFILE              VIEW                                             
DBA_HIST_TEMPSTATXS            VIEW                                             
DBA_HIST_THREAD                VIEW                                             
DBA_HIST_TOPLEVELCALL_NAME     VIEW                                             
DBA_HIST_WAITCLASSMET_HISTORY  VIEW                                             
DBA_HIST_WAITSTAT              VIEW                                             
DBA_HIST_WR_CONTROL            VIEW                                             
DBA_STREAMS_TP_COMPONENT_STAT  VIEW                                             
DBA_STREAMS_TP_PATH_BOTTLENECK VIEW                                             
V$ACTIVE_SESSION_HISTORY       SYNONYM                                             
V_$ACTIVE_SESSION_HISTORY       VIEW
</pre>
<p>And now for the Tuning Pack :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
SELECT object_name, object_type
FROM pack_members
WHERE pack_name IN ('TUNING', 'BOTH')
ORDER BY 2,1
/
</pre>
<p>The output is :</p>
<pre class="brush: plain; title: ; wrap-lines: false; notranslate">

OBJECT_NAME                    OBJECT_TYPE                                      
------------------------------ ------------------------------                   
DBMS_ADVISOR                   PACKAGE                                          
DBMS_SQLTUNE                   PACKAGE                                          
V$SQL_PLAN_MONITOR             SYNONYM                                          
V$SQL_MONITOR                 SYNONYM                                          
V_$SQL_MONITOR                  VIEW                                             
V_$SQL_PLAN_MONITOR            VIEW                            
</pre>
<p>Ideally, there should be a way of disabling access to these objects and that&#8217;s a theme I&#8217;ll return to in a later post.<br />
For now though, if you want to find the underlying tables for any of these views, you can do this fairly easily (remember, these<br />
underlying tables will also trigger the license if accessed directly)&#8230;</p>
<pre class="brush: plain; title: ; notranslate">
SELECT dep.referenced_owner table_owner, dep.referenced_name table_name
FROM dba_dependencies dep, pack_members pm
WHERE dep.name = pm.object_name
AND dep.type = pm.object_type
AND dep.owner = 'SYS'
AND dep.referenced_type = 'TABLE'
AND pm.object_type = 'VIEW'
AND pm.object_name = 'DBA_ADVISOR_TASKS'
/

TABLE_OWNER                    TABLE_NAME                   
------------------------------ ------------------------------
SYS                            WRI$_ADV_TASKS                 
SYS                            WRI$_ADV_EXECUTIONS            

</pre>
<p>It&#8217;s not quite so good at getting a complete list of all the tables that fall into this category as some of the views actually reference tables that have nothing to do with these packs, such as COL$ and USER$. </p>
<h3>In the next Episode&#8230;</h3>
<p>Just when you thought it was all under control, <a href="http://wp.me/pweWl-tX">the next post</a> will attempt to address the question “Just what is the most expensive query I can run on Oracle ?”</p>
<p>No previews, but I can tell you that it&#8217;s related to the Diagnostic and Tuning Packs.<br />
In the meantime, I&#8217;ve got to start doing some expectation management ahead of Valentines Day.</p>
<br />Filed under: <a href='http://mikesmithers.wordpress.com/category/oracle/'>Oracle</a>, <a href='http://mikesmithers.wordpress.com/category/sql/'>SQL</a> Tagged: <a href='http://mikesmithers.wordpress.com/tag/control_management_pack_access/'>CONTROL_MANAGEMENT_PACK_ACCESS</a>, <a href='http://mikesmithers.wordpress.com/tag/dba_dependencies/'>dba_dependencies</a>, <a href='http://mikesmithers.wordpress.com/tag/dba_objects/'>dba_objects</a>, <a href='http://mikesmithers.wordpress.com/tag/diagnostic-and-tuning-pack-api-list/'>Diagnostic and Tuning Pack API List</a>, <a href='http://mikesmithers.wordpress.com/tag/oracle-database-licensing/'>Oracle Database Licensing</a>, <a href='http://mikesmithers.wordpress.com/tag/oracle-diagnostic-pack/'>Oracle Diagnostic Pack</a>, <a href='http://mikesmithers.wordpress.com/tag/oracle-tuning-pack/'>Oracle Tuning Pack</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=1807&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mikesmithers.wordpress.com/2013/01/26/oracle-database-diagnostic-and-tuning-packs-exactly-what-are-you-not-licensed-for/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3cb0956016bbad280193fbbd8e649b9?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Mike S</media:title>
		</media:content>
	</item>
		<item>
		<title>DBMS_FEATURE_USAGE_REPORT and The Phantom AFTER SELECT Trigger</title>
		<link>http://mikesmithers.wordpress.com/2013/01/23/dbms_feature_usage_report-and-the-phantom-after-select-trigger/</link>
		<comments>http://mikesmithers.wordpress.com/2013/01/23/dbms_feature_usage_report-and-the-phantom-after-select-trigger/#comments</comments>
		<pubDate>Wed, 23 Jan 2013 17:51:02 +0000</pubDate>
		<dc:creator>mikesmithers</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[AWR]]></category>
		<category><![CDATA[dba_dependencies]]></category>
		<category><![CDATA[DBA_FEATURE_USAGE_STATISTICS]]></category>
		<category><![CDATA[dba_views]]></category>
		<category><![CDATA[DBMS_FEATURE_USAGE_INTERNAL]]></category>
		<category><![CDATA[DBMS_FEATURE_USAGE_REPORT]]></category>
		<category><![CDATA[Oracle Feature Usage]]></category>
		<category><![CDATA[Oracle licensing]]></category>
		<category><![CDATA[wri$_dbu_feature_metadata]]></category>
		<category><![CDATA[wri$_dbu_feature_usage]]></category>
		<category><![CDATA[wri$_dbu_usage_sample]]></category>

		<guid isPermaLink="false">http://mikesmithers.wordpress.com/?p=1797</guid>
		<description><![CDATA[Splat ! Darth Debbie has just launched a surprise attack using her current favourite weapon. Never get into a snowball fight with that woman. Milton Keynes, like much of the UK at the moment, looks less like it&#8217;s leafy, quiet self and more like the Arctic Tundra at present. Being in a part of the [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=1797&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Splat !<br />
Darth Debbie has just launched a surprise attack using her current favourite weapon. Never get into a snowball fight with that woman.<br />
Milton Keynes, like much of the UK at the moment, looks less like it&#8217;s leafy, quiet self and more like the Arctic Tundra at present.<br />
Being in a part of the country where normally, you can tell the changing of the seasons by the changing temperature of the rain, a little bit of snow always causes chaos.<br />
On the plus side, the national weather forecasters – The Met Office – issue colour-coded weather warnings which, at times like this include the always hilarious Yellow Snow Warning.</p>
<p>Anyway, the reason for the Star Wars references in this post is that I was planning to cover the whole question of license monitoring with particular reference to the Diagnostic and Tuning packs. However, it was getting to be more of a novel than a blog post so I&#8217;ve decided to split it down into more manageable chunks&#8230;or Episodes.<br />
So, in the style of the Epic Space Opera, please imagine the following paragraph scrolling through space with John Williams and his Orchestra blaring out of your speakers&#8230;</p>
<h2 style="text-align:center;">Episode 1 – The Phantom AFTER SELECT Trigger</h2>
<p style="text-align:center;">It is a time of license audits.<br />
The sinister Oracle Corporation have besieged the peaceful Database with some arcane licensing restrictions.<br />
The Geeki, keepers of peace and tranquility in the Data Centre are on the case.<br />
Using their mystical powers, they begin to investigate DBMS_FEATURE_USAGE_REPORT to discover</p>
<ul>
<li>Where Oracle stores information on Database Features being used</li>
<li>How this information is collected</li>
<li>What unnatural force powers are at work to enable the recording of SELECT statements against some tables and views</li>
</ul>
<p style="text-align:center;">Queen Debbie ( she&#8217;s changed sides in this paragraph) is wondering just how geeky this is all going to get ….</p>
<p><span id="more-1797"></span></p>
<h3>Under the covers of DBMS_FEATURE_USAGE_REPORT</h3>
<p>As mentioned in my previous post ( or <a href="http://wp.me/pweWl-rW">Episode 0.9 if you prefer</a>), you can find out what features are currently in use on the database by means of the DBMS_FEATURE_USAGE_REPORT package :</p>
<pre class="brush: sql; title: ; notranslate">
SELECT output
FROM TABLE( DBMS_FEATURE_USAGE_REPORT.display_text)
/
</pre>
<p>An extract of the output from this query will look something like this :</p>
<pre class="brush: plain; title: ; wrap-lines: false; notranslate">
...
DB Feature Usage Summary                            DB/Release: XE/11.2.0.2.0
-&gt; This section displays the summary of Usage for Database Features.
-&gt; The Currently Used column is TRUE if usage was detected for
-&gt; the feature at the last sample time.

                                          Curr-
                                          ently Detected    Total Last Usage
Feature Name                              Used    Usages  Samples    Time
----------------------------------------- ----- -------- -------- --------------
Automatic Maintenance - Optimizer Statist TRUE         6        6 01/19/13 17:35
Automatic Maintenance - Space Advisor     TRUE         6        6 01/19/13 17:35
Automatic Memory Tuning                   TRUE         6        6 01/19/13 17:35
Automatic Segment Space Management (syste TRUE         6        6 01/19/13 17:35
Automatic Undo Management                 TRUE         6        6 01/19/13 17:35
Character Set                             TRUE         6        6 01/19/13 17:35
Deferred Segment Creation                 TRUE         6        6 01/19/13 17:35
Job Scheduler                             TRUE         6        6 01/19/13 17:35
LOB                                       TRUE         6        6 01/19/13 17:35
Locally Managed Tablespaces (system)      TRUE         6        6 01/19/13 17:35
Locally Managed Tablespaces (user)        TRUE         6        6 01/19/13 17:35
Object                                    TRUE         6        6 01/19/13 17:35
Partitioning (system)                     TRUE         6        6 01/19/13 17:35
Recovery Area                             TRUE         6        6 01/19/13 17:35
Resource Manager                          TRUE         6        6 01/19/13 17:35
SecureFiles (system)                      TRUE         6        6 01/19/13 17:35
SecureFiles (user)                        TRUE         6        6 01/19/13 17:35
Server Parameter File                     TRUE         6        6 01/19/13 17:35
Undo Advisor                              TRUE         1        6 01/19/13 17:35
Virtual Private Database (VPD)            TRUE         6        6 01/19/13 17:35
ADDM                                      FALSE        0        6
ASO native encryption and checksumming    FALSE        0        6
...
</pre>
<p>So, we have information on whether a feature has been used, how many times it&#8217;s been used and when usage was last detected.</p>
<p>Incidentally, there is also a display_html function in this package which will return the same information.</p>
<p>All interesting stuff. But what if we want to go a bit deeper ? We may want to see just the features that are currently used, or even ones that have ever been used.<br />
We can&#8217;t apply a predicate to this particular query, so where else can we get this information from ?</p>
<h3>DBA_FEATURE_USAGE_STATISTICS</h3>
<p>The DBA_FEATURE_USAGE_STATISTICS view is a bit more like it. As well as the name of the feature there is a (sometimes) helpful description. For example, if you&#8217;re wondering what “Automatic Maintenance – Optimizer Statistics Gathering” means&#8230;</p>
<pre class="brush: sql; title: ; notranslate">
SELECT description
FROM dba_feature_usage_statistics
WHERE name LIKE 'Automatic Maintenance - Optimizer%'
</pre>
<p>So, we can now get a listing of just the features in use from this view :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
SELECT NAME, detected_usages, first_usage_date, last_usage_date
FROM dba_feature_usage_statistics
WHERE currently_used = 'TRUE'
/

NAME                                                             DETECTED_USAGES FIRST_USAGE_DATE LAST_USAGE_DATE
---------------------------------------------------------------- --------------- ---------------- ---------------
Automatic Maintenance - Optimizer Statistics Gathering                         6 07-OCT-12        19-JAN-13
Automatic Maintenance - Space Advisor                                          6 07-OCT-12        19-JAN-13
Character Set                                                                  6 07-OCT-12        19-JAN-13
Locally Managed Tablespaces (system)                                           6 07-OCT-12        19-JAN-13
Locally Managed Tablespaces (user)                                             6 07-OCT-12        19-JAN-13
Partitioning (system)                                                          6 07-OCT-12        19-JAN-13
Recovery Area                                                                  6 07-OCT-12        19-JAN-13
Resource Manager                                                               6 07-OCT-12        19-JAN-13
Server Parameter File                                                          6 07-OCT-12        19-JAN-13
Virtual Private Database (VPD)                                                 6 07-OCT-12        19-JAN-13
LOB                                                                            6 07-OCT-12        19-JAN-13
Object                                                                         6 07-OCT-12        19-JAN-13
SecureFiles (user)                                                             6 07-OCT-12        19-JAN-13
SecureFiles (system)                                                           6 07-OCT-12        19-JAN-13
Job Scheduler                                                                  6 07-OCT-12        19-JAN-13
Automatic Memory Tuning                                                        6 07-OCT-12        19-JAN-13
Automatic Segment Space Management (system)                                    6 07-OCT-12        19-JAN-13
Automatic Undo Management                                                      6 07-OCT-12        19-JAN-13
Deferred Segment Creation                                                      6 07-OCT-12        19-JAN-13
Undo Advisor                                                                   1 19-JAN-13        19-JAN-13

 20 rows selected
</pre>
<p>Well that&#8217;s something of an improvement. But how and when is this information collected ?<br />
Another question that springs to mind, which is of more relevance to our current quest is – how does the database detect that a view that&#8217;s part of the Diagnostic or Tuning Pack API has been accessed via a SELECT statement ?</p>
<h3>Digging Deeper</h3>
<p>As DBA_FEATURE_USAGE_STATISTICS is a view, we can progress our investigation by examining it&#8217;s definition :</p>
<pre class="brush: sql; title: ; notranslate">
SELECT text
FROM dba_views
WHERE owner = 'SYS'
AND view_name = 'DBA_FEATURE_USAGE_STATISTICS'
/
</pre>
<p>The output is :</p>
<pre class="brush: sql; highlight: [9,10]; title: ; wrap-lines: false; notranslate">
select samp.dbid, fu.name, samp.version, detected_usages, total_samples,
  decode(to_char(last_usage_date, 'MM/DD/YYYY, HH:MI:SS'),
         NULL, 'FALSE',
         to_char(last_sample_date, 'MM/DD/YYYY, HH:MI:SS'), 'TRUE',
         'FALSE')
  currently_used, first_usage_date, last_usage_date, aux_count,
  feature_info, last_sample_date, last_sample_period,
  sample_interval, mt.description
 from wri$_dbu_usage_sample samp, wri$_dbu_feature_usage fu,
      wri$_dbu_feature_metadata mt
 where
  samp.dbid    = fu.dbid and
  samp.version = fu.version and
  fu.name      = mt.name and
  fu.name not like '_DBFUS_TEST%' and   /* filter out test features */
  bitand(mt.usg_det_method, 4) != 4     /* filter out disabled features */
</pre>
<p>The view then is built on three tables</p>
<ul>
<li>wri$_dbu_usage_sample</li>
<li>wri$_dbu_dbu_feature_usage</li>
<li>wri$_dbu_feature_metadata</li>
</ul>
<p>Incidentally, there is some advice knocking about that tables starting wri$ should not be queried as this will cause a license usage to be recorded. However, as the view itself is not part of any additional pack and querying the view does not cause this, we can safely say that this does not apply to these three tables.</p>
<p>Documentation on these tables seems to be a bit sparse so let&#8217;s see what we can find out&#8230;</p>
<h4>WRI$_DBU_USAGE_SAMPLE</h4>
<p>This table contains information about the last time the feature usage audit was run, as well as the interval between runs (i.e. number of seconds between the last run and the next run).<br />
The feature usage audit itself is initiated by the MMON background process.<br />
It looks as if this table will only ever hold a single row of data.</p>
<p>Incidentally, the last_sample_date_num looks to be the number of seconds between the last_sample_date and midnight on 1st January 1970 :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
SELECT TO_CHAR( last_sample_date, 'DD-MON-YYYY HH24:MI'),
  TO_CHAR(
  TO_DATE('01-JAN-1970 00:00', 'DD-MON-YYYY HH24:MI')
  +
  (last_sample_date_num /60/60/24),
    'DD-MON-YYYY HH24:MI')
FROM sys.wri$_dbu_usage_sample
/

SAMPLE_DATE          SAMPLE_DATE_NUM
-------------------- --------------------
19-JAN-2013 17:35    19-JAN-2013 17:35
</pre>
<p>NOTE – it is possible to run the feature usage audit manually using DBMS_FEATURE_USAGE_INTERNAL.EXEC_DB_USAGE_SAMPLING.<br />
You can also use this framework to monitor usage of any application features you may choose.<br />
There&#8217;s a great example of this on the <a href="//psoug.org/reference/dbms_feature_usage.html">PSOUG site</a>.</p>
<h4>WRI$_DBU_FEATURE_USAGE</h4>
<p>This table holds the result from each feature usage audit run.<br />
It contains details such as the first and last usage dates and the number of detected usages.<br />
it seems to provide the bulk of the information we can see in the view :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
SELECT name, first_usage_date, last_usage_date
FROM sys.wri$_dbu_feature_usage
WHERE detected_usages &gt; 0
/

NAME                                                         FIRST_USAGE_DAT LAST_USAGE_DATE
------------------------------------------------------------ --------------- ---------------
Automatic Maintenance - Optimizer Statistics Gathering       07-OCT-12       19-JAN-13
Automatic Maintenance - Space Advisor                        07-OCT-12       19-JAN-13
Character Set                                                07-OCT-12       19-JAN-13
Locally Managed Tablespaces (system)                         07-OCT-12       19-JAN-13
Locally Managed Tablespaces (user)                           07-OCT-12       19-JAN-13
Partitioning (system)                                        07-OCT-12       19-JAN-13
Recovery Area                                                07-OCT-12       19-JAN-13
Resource Manager                                             07-OCT-12       19-JAN-13
Server Parameter File                                        07-OCT-12       19-JAN-13
Virtual Private Database (VPD)                               07-OCT-12       19-JAN-13
LOB                                                          07-OCT-12       19-JAN-13
Object                                                       07-OCT-12       19-JAN-13
SecureFiles (user)                                           07-OCT-12       19-JAN-13
SecureFiles (system)                                         07-OCT-12       19-JAN-13
Job Scheduler                                                07-OCT-12       19-JAN-13
Automatic Memory Tuning                                      07-OCT-12       19-JAN-13
Automatic Segment Space Management (system)                  07-OCT-12       19-JAN-13
Automatic Undo Management                                    07-OCT-12       19-JAN-13
Deferred Segment Creation                                    07-OCT-12       19-JAN-13
Undo Advisor                                                 19-JAN-13       19-JAN-13

 20 rows selected

</pre>
<p>The last of these three tables is probably the most relevant in our quest for the elusive SELECT trigger&#8230;</p>
<h4>WRI$_DBU_FEATURE_METADATA</h4>
<p>This table contains the name of the feature as it appears in DBA_FEATURE_USAGE_STATISTICS. It also contains the code used to detect usage in the USG_DET_LOGIC column.</p>
<p>Remember, AWR is part of the Diagnostic Pack, usage of which includes direct access to the command-line APIs ( packages and views) i.e. a SELECT statement.</p>
<p>So, can we get somewhere by looking at the detection method for usage of the AWR Report feature ?</p>
<pre class="brush: sql; highlight: [2]; title: ; wrap-lines: false; notranslate">
with last_period as
       (select * from sys.wrm$_wr_usage
         where upper(feature_type) like 'REPORT'
           and usage_time &gt;=  (select nvl(max(last_sample_date), sysdate-7) from sys.wri$_dbu_usage_sample) )
       select decode (count(*), 0, 0, 1),
              count(*),
              feature_list
         from last_period,
        (select substr(sys_connect_by_path(feature_count, ','),2) feature_list
           from
             (select feature_count,
                     count(*) over () cnt,
                     row_number () over (order by 1) seq
                from
                  (select feature_name || ':' || count(*) feature_count
                     from last_period
                 group by feature_name)
             )
        where seq=cnt
        start with seq=1
   connect by prior seq+1=seq)
     group by feature_list;
</pre>
<p>So, the usage itself is recorded in the WRM$_WR_USAGE table.<br />
Attempting to track down our mythical SELECT trigger, we can check the dependencies for this table :</p>
<pre class="brush: sql; title: ; wrap-lines: false; notranslate">
SELECT owner, name, type
FROM dba_dependencies
WHERE referenced_owner = 'SYS'
AND referenced_name = 'WRM$_WR_USAGE'
/

OWNER      NAME                           TYPE
---------- ------------------------------ ---------------
SYS        DBMS_SWRF_REPORT_INTERNAL      PACKAGE BODY

</pre>
<p>Here we hit a dead-end as the DBMS_SWRF_REPORT_INTERNAL package is wrapped.</p>
<p>It&#8217;s a similar story with ADDM.</p>
<p>At this stage, it looks very much as if the selecting of a view or table is recorded by means of the MMON background process.</p>
<h3>In the next episode&#8230;</h3>
<p>So, our valiant search for the SELECT trigger has come to nothing.<br />
Additionally, nowhere in these tables does it explicitly state which features are additional cost options.<br />
All is not lost however. We have found some useful information on how Oracle&#8217;s internal feature auditing routines operate.<br />
<a href="http://wp.me/pweWl-t9">In the next post</a>, we&#8217;ll continue our journey into the Dark Side by trying to pin down exactly which objects are included in the Diagnostic and Tuning Packs.</p>
<p>In the meantime, watch out for the Yellow Snow.</p>
<br />Filed under: <a href='http://mikesmithers.wordpress.com/category/oracle/'>Oracle</a>, <a href='http://mikesmithers.wordpress.com/category/sql/'>SQL</a> Tagged: <a href='http://mikesmithers.wordpress.com/tag/awr/'>AWR</a>, <a href='http://mikesmithers.wordpress.com/tag/dba_dependencies/'>dba_dependencies</a>, <a href='http://mikesmithers.wordpress.com/tag/dba_feature_usage_statistics/'>DBA_FEATURE_USAGE_STATISTICS</a>, <a href='http://mikesmithers.wordpress.com/tag/dba_views/'>dba_views</a>, <a href='http://mikesmithers.wordpress.com/tag/dbms_feature_usage_internal/'>DBMS_FEATURE_USAGE_INTERNAL</a>, <a href='http://mikesmithers.wordpress.com/tag/dbms_feature_usage_report/'>DBMS_FEATURE_USAGE_REPORT</a>, <a href='http://mikesmithers.wordpress.com/tag/oracle-feature-usage/'>Oracle Feature Usage</a>, <a href='http://mikesmithers.wordpress.com/tag/oracle-licensing/'>Oracle licensing</a>, <a href='http://mikesmithers.wordpress.com/tag/wri_dbu_feature_metadata/'>wri$_dbu_feature_metadata</a>, <a href='http://mikesmithers.wordpress.com/tag/wri_dbu_feature_usage/'>wri$_dbu_feature_usage</a>, <a href='http://mikesmithers.wordpress.com/tag/wri_dbu_usage_sample/'>wri$_dbu_usage_sample</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=1797&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mikesmithers.wordpress.com/2013/01/23/dbms_feature_usage_report-and-the-phantom-after-select-trigger/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3cb0956016bbad280193fbbd8e649b9?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Mike S</media:title>
		</media:content>
	</item>
		<item>
		<title>Oracle Database Licensing for SMEs – Making a Contribution to Larry&#8217;s Yacht Fund</title>
		<link>http://mikesmithers.wordpress.com/2012/12/28/oracle-database-licensing-for-smes-making-a-contribution-to-larrys-yacht-fund/</link>
		<comments>http://mikesmithers.wordpress.com/2012/12/28/oracle-database-licensing-for-smes-making-a-contribution-to-larrys-yacht-fund/#comments</comments>
		<pubDate>Fri, 28 Dec 2012 14:50:31 +0000</pubDate>
		<dc:creator>mikesmithers</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[DBMS_FEATURE_USAGE_REPORT]]></category>
		<category><![CDATA[License Metric]]></category>
		<category><![CDATA[Named User Plus]]></category>
		<category><![CDATA[Oracle Database Licensing]]></category>
		<category><![CDATA[Oracle Technology Deployment Declaration Program]]></category>
		<category><![CDATA[Per Processor License]]></category>
		<category><![CDATA[Standard Edition]]></category>
		<category><![CDATA[Standard Edition One]]></category>
		<category><![CDATA[Standby Database]]></category>

		<guid isPermaLink="false">http://mikesmithers.wordpress.com/?p=1732</guid>
		<description><![CDATA[In the battle of the sexes, there is only one winner. I call her Deb. This should go some way to explaining the difference in approach between the two DBAs in the following story. For many years now, licensing of Oracle Database software has been an arcane and confusing business. Whilst this is often an [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=1732&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>In the battle of the sexes, there is only one winner. I call her Deb.<br />
This should go some way to explaining the difference in approach between the two DBAs in the following story.</p>
<p>For many years now, licensing of Oracle Database software has been an arcane and confusing business. Whilst this is often an area that falls to the humble DBA to admninister, most DBAs aren&#8217;t lawyers. Sometimes, keeping on top of the licensing requirements takes a back-seat to the day-to-day technical challenges.</p>
<p>What follows is a cautionary tale on the potential ramifications of finding out that you are under-licensed&#8230;around the same time that Oracle also discover this unfortunate fact.<br />
<span id="more-1732"></span></p>
<p>Before I go on, it&#8217;s time for the obligatory&#8230;</p>
<h3>Disclaimer</h3>
<p>The information about licensing here should NOT be taken as definitive. This is just stuff that I&#8217;ve found out and conclusions I&#8217;ve drawn. I&#8217;m not a lawyer. I&#8217;m also not clairvoyant. Oracle&#8217;s licensing is a moving target and it&#8217;s quite likely that it will move quite a bit in the near future as technology marches ever onward and things become clouded by&#8230;well&#8230;The Cloud.</p>
<h2>You want How Much ?!</h2>
<h3>An Innocent Question</h3>
<p>DBA Dan , was having a busy day as usual. He worked for a small company – less than 100 employees all told and was single-handedly managing multiple Oracle Databases on various servers.</p>
<p>The significance of the missive that arrived in his inbox that morning would not become apparent for some time.</p>
<p>The e-mail was from the Oracle Technology Deployment Declaration Program.<br />
It asked, politely, that Dan fill out the attached spreadsheet detailing what Oracle Products, including version numbers and editions were running on which servers.<br />
This information was required to be provided within 5 working days.</p>
<p>“Great”, thought Dan, “something else to add onto the pile of things to do”.<br />
In a quiet moment later that week, Dan duly filled in the spreadsheet.<br />
He reflected later, that he should really have re-checked the Company&#8217;s licenses before pressing the send button. At the time he&#8217;d just assumed that when the databases had been set up originally ( before his time at the company), the appropriate licenses would have been acquired. After all, that would have been handled by the DBA at the time, wouldn&#8217;t it ?</p>
<h3>Blood in the Water</h3>
<p>A couple of weeks later, another unsolicited e-mail dropped into Dan&#8217;s inbox. This was from a company called Fairly Unscrupulous Databases Ltd (FUD), an Oracle Partner.<br />
They advised that they had been instructed by Oracle to conduct an audit of the Company&#8217;s Oracle license usage. There was also some mention of a “system health-check”.<br />
In order to complete this, Dan was asked to run the attached software on all of the servers running Oracle Products.<br />
The attached software turned out to be Oracle&#8217;s Remote Diagnostic Agent – a suite of Perl scripts primarily used by Oracle Support for gathering information to help in call resolution.</p>
<p>Dan did as he was asked. He even ran it on the Company&#8217;s Disaster Recovery Servers although he was sure that Standby databases didn&#8217;t require a separate license. I mean, everyone knows that, right ?</p>
<p>Dan didn&#8217;t really pay that much attention to the output of the RDA. If he had, he would have noticed that this tool looks at a number of key areas on the server, as well as the database.<br />
These include :</p>
<ul>
<li>Oracle Configuration Manager</li>
<li>ORACLE_BASE</li>
<li>ORACLE_HOME</li>
<li>Certain Windows Registry Keys and Windows Services ( or unix equivalents)</li>
<li>Enterprise Manager</li>
<li>Server hardware (including CPUs)</li>
<li>The v$license view</li>
<li>Database Feature Usage Statistics</li>
</ul>
<p>The output dispatch back to FUD, Dan thought no more of it&#8230;until&#8230;</p>
<h3>The Health Check-which leg don&#8217;t you need ?</h3>
<p>The health check report that FUD sent back contained 50-odd pages of stuff that Dan already knew. Anodyne was the word that sprang to mind.<br />
Tucked away at the very end of this exercise in the blindingly obvious was the killer blow.<br />
In summary, FUD thought that the Company&#8217;s Oracle Databases were perfectly healthy. Unfortunately, Oracle&#8217;s bank balance was not quite as healthy as it could have been, so a contribution to swell the coffers would be appreciated.</p>
<p>In other words, the Company had been found to be in breach of it&#8217;s license and the shortfall, backdated of course, would need to be made good.</p>
<h3>Crunching the Numbers</h3>
<p>The next few days were quite crowded for Dan.<br />
First, he was given the unique opportunity to explain to a not-entirely-happy CEO just why Oracle had invoiced the Company for the thick end of one million pounds for the unpaid licenses – a sum greater than the company&#8217;s annual turnover and which would almost certainly mean insolvency.</p>
<p>He then learned that some frantic meetings between the CEO and those nice people from FUD had resulted in a compromise by which Oracle agreed to waive the license bill in exchange for the Company correctly licensing it&#8217;s databases, stopping the “use” of the Packs, and buying some rather expensive Oracle Software, the practical use for which was not immediately apparent.</p>
<p>In the end, the Company survived, Oracle and FUD presented an invoice that – only just – added up to six figures ( but still rather more than the £10K or so the company usually paid for Oracle licenses annually)&#8230;and Dan had a rather short conversation with the CEO. The gist of this was that Dan would be given the unlimited time to look into his prospects for alternative employment.<br />
Dan left with the distinct impression that any reference provided for him by the CEO would not add up to much more than four letters.</p>
<h3>Predator or Pragmatist</h3>
<p>Cynics might regard Oracle&#8217;s actions in this (fictional) scenario to be little more than using scare tactics to extort money from it&#8217;s hard-pressed smaller customers.<br />
A less judgemental view would be that Oracle is simply fulfilling it&#8217;s duty to it&#8217;s shareholders and claiming that to which it is legally entitled.<br />
Either way, the profound effect of these events on both our poor DBA and the Company itself, render this something of a moot point.</p>
<h2>The Wonderful World of License Documentation</h2>
<h3>Forewarned is forearmed</h3>
<p>Contrast the tale of woe that is the story of Desparate Dan, to that of Deb, <a href="http://wp.me/pweWl-ko">the working royal</a>.</p>
<p>Deb works as a DBA in a company remarkably similar to the one that Dan left in such a hurry.<br />
After starting at the Company, one of the first things she does is to find out what databases are running where and in what configuration.</p>
<p>On the MAIN_APP server, she has a single 11g Standard Edition One database which is used for the Company&#8217;s in-house application. The server has two physical CPUs.</p>
<p>On the TEST_APP server, she has Development, Test and UAT databases. These are also Standard Edition One. The server has two physical CPUs</p>
<p>On the SPIDERMAN server, she has a 10g Standard Edition database that back-ends the company&#8217;s public-facing web application. The server has one physical CPU</p>
<p>On DR_MAIN_APP in the Disaster Recovery Office, she has a standby database for the MAIN_APP database. The server has one physical CPU.</p>
<p>The Company currently holds a 100 Named User Plus license for Standard Edition One.</p>
<p>Having spent most of her career to date working on Enterprise Edition ( she is a Princess after all), she&#8217;s reasonably au fait with the ins and outs of Oracle Licensing. However, she also knows that assumption is usually the calling card of Mr Cock-Up ( a bloke, naturally).<br />
Therefore, she decides to do some research.</p>
<h3>License Metrics</h3>
<p>To begin with Deb looks at the definitions for the two main license metrics for Oracle databases – Named User Plus and Per Processor.</p>
<h4>Named User Plus</h4>
<p>Deb notices that, if you purchase one of Oracle&#8217;s database products using the Named User Plus license metric, the minimum order allowed by Oracle is 5 licenses.</p>
<p>She also knows that a default installation of Oracle creates at least 14 database schemas. Therefore, it can be deduced that working out the number of Named Users is not as simple as doing :</p>
<pre class="brush: sql; title: ; notranslate">
SELECT COUNT(*)
FROM dba_users;
</pre>
<p>According to the documentation found on <a href="http://oraclestore.oracle.com/OA_HTML/ibeCCtpSctDspRte.jsp?section=11365&amp;media=os_local_license_agreement&amp;minisite=10061&amp;respid=1298373&amp;grp=STORE&amp;language=US">this page on the Oracle Store site</a> …</p>
<blockquote><p>Named User Plus / Named User: is defined as an individual authorized by you to use the programs which are installed on a single server or multiple servers, regardless of whether the individual is actively using the programs at any given time.<br />
All of the remaining provisions of this definition apply only with respect to Named User Plus licenses, and not to Named User licenses.<br />
A non human operated device will be counted as a named user plus in addition to all individuals authorized to use the programs, if such devices can access the programs.<br />
If multiplexing hardware or software (e.g., a TP monitor or a web server product) is used, this number must be measured at the multiplexing front end.<br />
Automated batching of data from computer to computer is permitted.<br />
You are responsible for ensuring that the named user plus per processor minimums are maintained for the programs contained in the user minimum table in the licensing rules section; the minimums table provides for the minimum number of named users plus required and all actual users must be licensed.
</p></blockquote>
<p>The fact that the definition covers “programs which are installed on a single server or multiple servers&#8230;” is quite interesting.<br />
In Deb&#8217;s case, the test databases on TEST_APP are all copies of the database on MAIN_APP.<br />
Therefore, all of the databases on both of these servers have the same set of users.</p>
<p>So, if we have an individual user called Mike, who connects as user MIKE to all of the databases across the MAIN_APP and TEST_APP servers, this would constitute 1 named user.</p>
<p>Similarly, as Deb is the DBA, she is the only person who will connect as SYS and SYSTEM, as well as using her own account – DEB.<br />
DEB, SYS, and SYSTEM across all of the databases on the two servers will constitute one named user under the Named User Plus license definition.</p>
<p>This point is also relevant when we come to consider the Disaster Recovery site a little later on.</p>
<p>Of some concern however is the bit about multiplexing. Essentially, as the web database is publicly available and there is no way to control the number of users who may access the database, it looks like Deb is going to need to cover this database using Per Processor licenses.</p>
<h4>Per Processor – the Standard Edition Twist</h4>
<p>Having spent most of her career working with Enterprise Edition databases, Deb is familiar with the concept of the CPU core multiplier which is used to calculate the number of EE licenses required for a server. However, trawling through the oracle site,  <a href="http://www.oracle.com/us/corporate/pricing/databaselicensing-070584.pdf">she notices this</a>.</p>
<blockquote><p>When licensing Oracle programs with Standard Edition One or Standard Edition in the product name, a processor is counted equivalent to a socket; however, in the case of multi-chip modules, each chip in the multi-chip module is counted as one occupied socket.
</p></blockquote>
<p>So, Standard Edition and Standard Edition One per processor licenses are per physical CPU, not per core.</p>
<h3>Oracle Database Editions</h3>
<p>At present there are three licensable editions of the Oracle Database :</p>
<ul>
<li>Standard Edtion One</li>
<li>Standard Edition</li>
<li>Enterprise Edition</li>
</ul>
<p>You can find the various different features available for each in the Oracle documentation. The feature list for <a href="http://docs.oracle.com/cd/E11882_01/license.112/e10594/editions.htm">11gR2 can be found here</a>.</p>
<h4>Standard Edition and Standard Edition One</h4>
<p>For smaller sites, it&#8217;s worth noting that Standard Edtion One and Standard Edition are almost identical.<br />
The main differentiator between the two is that the cheaper Standard Edition One may run on a maximum of two physical CPUs where as Standard Edition may run on a maximum of four.<br />
Standard Edition does come with a couple of extras – Oracle RAC and Automated Workload Management.<br />
This is something that may well be worth considering when evaluating which license is required, irrespective of the License Metric required.</p>
<h3>Editions and Metrics – the main points</h3>
<p>Generally speaking then, the following applies for license metrics :</p>
<ul>
<li>If you have a known user community ( e.g. an internal company application) then Named User Plus licensing is an option you may want to consider.
</li>
<li>If you&#8217;re database is publicly accessible ( usually the backend for a website) then you&#8217;re probably limited to the Per Processor metric.</li>
<li>Standby databases must be licensed separately using the same metric as the main database&#8230;but may be covered by existing Named User Plus Licenses.</li>
<li>Unlike Enterprise Edition, the Per Processor license for both Standard Edition and Standard Edition One applies per physical CPU rather than per CPU core.</li>
</ul>
<p>The  main differences between Standard Edition One and Standard Edition are :</p>
<ul>
<li>Standard Edition One is cheaper</li>
<li>Standard Edition One is limited to a maximum of two physical CPUs.</li>
<li>Standard Edition may run on up to four physical CPUs.</li>
<li>Standard Edition comes with Oracle RAC and Automated Workload Management.</li>
</ul>
<h3>Standby Database Licensing – Myth and Reality</h3>
<p>There is a widely held belief that Standby Databases do not require a license. Howerver, looking at <a href="http://www.oracle.com/us/corporate/pricing/specialty-topics/index.html">Oracle&#8217;s Licensing Data Recovery Environments documentation</a>&#8230;</p>
<blockquote><p>Standby: One or more copies of the primary database are maintained on a separate server(s) at all times. The sites in a standby configuration may be dispersed geographically and are connected by Oracle Net Services. As the primary database is modified, log information generated by the changes are sent to the standby database(s) and subsequently applied to the standby database. If the primary database fails, a standby database can be activated to be the new primary database. In this environment, <strong>the primary and the standby databases must be fully licensed. Additionally, the same metric must be used when licensing the databases in a standby environment</strong>. If any Option or Management Pack (except RAC) is licensed on the primary server, then it must also be licensed on the Standby server. If RAC is on the primary server but not on the standby server, then licensing it is not required.
</p></blockquote>
<p>So, if the primary database is licensed per processor then the Standby needs it&#8217;s own per processor licenses. However if, as in Deb&#8217;s case, the Primary is licensed by Named User Plus the situation is a bit different.<br />
Obviously, the standby database is an exact copy of the primary.</p>
<p>Remember, the Named User Plus license covers a single user <em>across multiple servers</em>.<br />
Here the DR_MAIN_APP server, where the Standby database is located, is just another server.<br />
Therefore, no additional Named User Plus licenses are required to cover the Standby database.</p>
<h3>Database Features</h3>
<p>Oracle keeps track of what features are being used on the database.<br />
The quickest way to see this information is to issue the following query :</p>
<pre class="brush: sql; title: ; notranslate">
SELECT output
FROM TABLE( DBMS_FEATURE_USAGE_REPORT.DISPLAY_TEXT);
</pre>
<p>The output is not entirely helpful in terms of which features are standard for which database edition. However, it does give you the crux of the information that would be used in any license audit.</p>
<h3>A Happy Ending</h3>
<p>Having reported her findings to the CEO, Deb persuades the company to shell out for a single Standard Edition One processor license to cover the SPIDERMAN server.<br />
When Oracle come calling to check-up on licenses, she can fill in her spreadsheet, confident in the knowledge that the company is now fully covered in terms of Oracle licenses and there is unlikely to be any follow-up.<br />
The CEO, who had a nasty experience with Oracle licensing at a previous company, is happy that the cost of an additional license is more than offset by the potential cost of a full license audit.</p>
<h3>The Moral of the Story</h3>
<p>If you&#8217;re starting a new job as a DBA , especially if you are <em>the</em> DBA, licensing needs to be a priority, right up there with Disaster Recovery.<br />
Make sure you know what you&#8217;re licensed for and what database editions and features you&#8217;re running.<br />
Also make sure you know details like the number of CPUs on the database servers themselves.<br />
The sooner any license short-fall is identified, the sooner it can be addressed. In the long-term, the consequences of not doing so can be pretty severe.</p>
<br />Filed under: <a href='http://mikesmithers.wordpress.com/category/oracle/'>Oracle</a> Tagged: <a href='http://mikesmithers.wordpress.com/tag/dbms_feature_usage_report/'>DBMS_FEATURE_USAGE_REPORT</a>, <a href='http://mikesmithers.wordpress.com/tag/license-metric/'>License Metric</a>, <a href='http://mikesmithers.wordpress.com/tag/named-user-plus/'>Named User Plus</a>, <a href='http://mikesmithers.wordpress.com/tag/oracle-database-licensing/'>Oracle Database Licensing</a>, <a href='http://mikesmithers.wordpress.com/tag/oracle-technology-deployment-declaration-program/'>Oracle Technology Deployment Declaration Program</a>, <a href='http://mikesmithers.wordpress.com/tag/per-processor-license/'>Per Processor License</a>, <a href='http://mikesmithers.wordpress.com/tag/standard-edition/'>Standard Edition</a>, <a href='http://mikesmithers.wordpress.com/tag/standard-edition-one/'>Standard Edition One</a>, <a href='http://mikesmithers.wordpress.com/tag/standby-database/'>Standby Database</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=1732&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mikesmithers.wordpress.com/2012/12/28/oracle-database-licensing-for-smes-making-a-contribution-to-larrys-yacht-fund/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3cb0956016bbad280193fbbd8e649b9?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Mike S</media:title>
		</media:content>
	</item>
		<item>
		<title>Defaulting Null values in SQL*Loader</title>
		<link>http://mikesmithers.wordpress.com/2012/12/27/defaulting-null-values-in-sqlloader/</link>
		<comments>http://mikesmithers.wordpress.com/2012/12/27/defaulting-null-values-in-sqlloader/#comments</comments>
		<pubDate>Thu, 27 Dec 2012 13:20:18 +0000</pubDate>
		<dc:creator>mikesmithers</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[control file]]></category>
		<category><![CDATA[fields terminated by]]></category>
		<category><![CDATA[infile]]></category>
		<category><![CDATA[load data]]></category>
		<category><![CDATA[specify a value if null]]></category>
		<category><![CDATA[SQL*Loader]]></category>
		<category><![CDATA[sqlldr]]></category>
		<category><![CDATA[trailing nullcols]]></category>

		<guid isPermaLink="false">http://mikesmithers.wordpress.com/?p=1727</guid>
		<description><![CDATA[Having spent the last couple of months working with a South African ( hello Trevor) and being reminded, oh so gently, of that nation&#8217;s recent cricketing success, I was hoping to get the opportunity to return the favour via the medium of Rugby Union. The Springboks narrow defeat of England in the Autumn International did [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=1727&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>Having spent the last couple of months working with a South African ( hello Trevor) and being reminded, oh so gently, of that nation&#8217;s recent cricketing success, I was hoping to get the opportunity to return the favour via the medium of Rugby Union.</p>
<p>The Springboks narrow defeat of England in the Autumn International did little to derail this cunning plan. Unfortunately, my emergency backup nationality failed at a crucial moment as the hitherto invincible All Blacks were roundly thrashed by England a week later.<br />
People in glass-houses&#8230;</p>
<p>Anyway, what follows is a solution to a fairly specific problem we were confronted with recently.<br />
<span id="more-1727"></span></p>
<h3>The problem</h3>
<p>Imagine you have a flat file which is loaded by means of SQL*Loader into a database table.<br />
For operational reasons, it is not possible to alter the structure of the table.</p>
<p>The table may look something like this :</p>
<pre class="brush: sql; title: ; notranslate">
CREATE TABLE results(
    fixture_date DATE NOT NULL,
    home_team VARCHAR2(30) NOT NULL,
    away_team VARCHAR2(30) NOT NULL,
    home_points NUMBER NOT NULL,
    away_points NUMBER NOT NULL)
/
</pre>
<p>The file that you are required to load into the table is called fixtures.dat and looks like this …</p>
<pre class="brush: plain; title: ; notranslate">
18082012,AUSTRALIA,NEW ZEALAND,19,27
18082012,SOUTH AFRICA,ARGENTINA,27,6
25082012,NEW ZEALAND,AUSTRALIA,22,0
25082012,ARGENTINA,SOUTH AFRICA,16,16
08092012,AUSTRALIA,SOUTH AFRICA,26,19
08092012,NEW ZEALAND,ARGENTINA,21,5
15092012,AUSTRALIA,ARGENTINA,,
15092012,NEW ZEALAND,SOUTH AFRICA,,
29092012,SOUTH AFRICA,AUSTRALIA,,
29092012,ARGENTINA,NEW ZEALAND,,
06102012,SOUTH AFRICA,NEW ZEALAND,,
06102012,ARGENTINA,AUSTRALIA,,
</pre>
<p>The data is the fixture list for this year&#8217;s Rugby Championship. No, I&#8217;m not making any comment about any of the results.</p>
<p>Notice a problem ? Yes, the HOME_POINTS and AWAY_POINTS columns in the table are mandatory, but the file itself contains nulls for these values in some of the records.<br />
So the question is – how do we load this file directly into the table using only SQL*Loader ?</p>
<h3>The SQL*Loader Control File</h3>
<p>These days, you&#8217;ll often find SQL*Loader used for <a href="http://wp.me/pweWl-i1">External Tables</a>.<br />
In this instance, we&#8217;re going to be using this utility in it&#8217;s more traditional command-line mode.<br />
Fortunately, the command itself is fairly simple, because most of the messy stuff can be written separately in a control file. </p>
<p>The control file specifies </p>
<ul>
<li> the action ( LOAD DATA)</li>
<li>the file containing the data (INFILE)</li>
<li>the table to load into</li>
<li>The delimiter used in the file (FIELDS TERMINATED BY)</li>
<li>treat any missing values at the end of a line as null (TRAILING NULLCOLS)</li>
</ul>
<p>Finally, and most significantly from our point of view, it specifies how any data needs to be modified before loading.</p>
<p>The formatting of date data is fairly common place in control files.<br />
However, you can also manipulate individual data items in more sophisticated ways such as, for example, assigning a default value when a null exists&#8230;</p>
<p>In this case, the control file looks something like this :</p>
<pre class="brush: bash; highlight: [7,10,11]; title: ; notranslate">
LOAD DATA 
INFILE 'fixtures.dat'
INTO TABLE results
APPEND FIELDS TERMINATED BY ','
TRAILING NULLCOLS
( 
    fixture_date DATE &quot;DDMMYYYY&quot;,
    home_team,
    away_team,
    home_points &quot;NVL(:home_points,0)&quot;,
    away_points &quot;NVL(:away_points,0)&quot;)   
</pre>
<p>Time to put it to the test (<strong>NOTE</strong> – in this case, I&#8217;m connecting to a schema where the RESULTS table already exists) :</p>
<pre class="brush: bash; highlight: [1,8]; title: ; notranslate">
$ sqlldr userid=mike control=results.ctl
Password:

SQL*Loader: Release 11.2.0.2.0 - Production on Thu Dec 27 12:50:46 2012

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

Commit point reached - logical record count 12
 $ 
</pre>
<p>It looks as if all the rows have been loaded successully so we can now check the actual contents of the table &#8230;</p>
<pre class="brush: plain; highlight: [9,10]; title: ; wrap-lines: false; notranslate">
SQL&gt; SELECT fixture_date, home_team, away_team,  
  2     home_points, away_points
  3  FROM results
  4  WHERE fixture_date = TO_DATE('15092012', 'DDMMYYYY')
  5  /

FIXTURE_DATE HOME_TEAM		  AWAY_TEAM	       HOME_POINTS AWAY_POINTS
------------ -------------------- -------------------- ----------- -----------
15-SEP-12    AUSTRALIA		  ARGENTINA			 0	     0
15-SEP-12    NEW ZEALAND	  SOUTH AFRICA			 0	     0

SQL&gt; 
</pre>
<p>This is by no means the neatest way of manipulating data during upload into Oracle and there may well be performance penalties using this method. However, when you&#8217;re stuck for a better alternative, it&#8217;s worth remembering that SQL*Loader does have a fair amount of flexibility.</p>
<p>There, I&#8217;ve managed to get all the way through this post without a single reference to South Africa&#8217;s success or otherwise in this particular competition&#8230;but the results can be found <a href="http://www.scorespro.com/rugby-union/world/rugby-championship/2012/results/http://">here if you just have to know how it went for them</a>.</p>
<p>That&#8217;s the great thing about writing a blog, you always get the last word&#8230;unless a certain Welsh person decides to remind you just which team won the Six Nations this year!</p>
<br />Filed under: <a href='http://mikesmithers.wordpress.com/category/oracle/'>Oracle</a> Tagged: <a href='http://mikesmithers.wordpress.com/tag/control-file/'>control file</a>, <a href='http://mikesmithers.wordpress.com/tag/fields-terminated-by/'>fields terminated by</a>, <a href='http://mikesmithers.wordpress.com/tag/infile/'>infile</a>, <a href='http://mikesmithers.wordpress.com/tag/load-data/'>load data</a>, <a href='http://mikesmithers.wordpress.com/tag/specify-a-value-if-null/'>specify a value if null</a>, <a href='http://mikesmithers.wordpress.com/tag/sqlloader/'>SQL*Loader</a>, <a href='http://mikesmithers.wordpress.com/tag/sqlldr/'>sqlldr</a>, <a href='http://mikesmithers.wordpress.com/tag/trailing-nullcols/'>trailing nullcols</a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikesmithers.wordpress.com&#038;blog=7683929&#038;post=1727&#038;subd=mikesmithers&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://mikesmithers.wordpress.com/2012/12/27/defaulting-null-values-in-sqlloader/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://2.gravatar.com/avatar/e3cb0956016bbad280193fbbd8e649b9?s=96&#38;d=http%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Mike S</media:title>
		</media:content>
	</item>
	</channel>
</rss>
