<?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/"
	>

<channel>
	<title>Enkitec Blog</title>
	<atom:link href="http://blog.enkitec.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.enkitec.com</link>
	<description>The official blog of Enkitec</description>
	<lastBuildDate>Sat, 29 Oct 2011 03:08:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.4</generator>
		<item>
		<title>My crsstat script: Improved Formatting of crs_stat on 10g and 11g</title>
		<link>http://blog.enkitec.com/2011/10/my-crsstat-script-improved-formatting-of-crs_stat-on-10g-and-11g/</link>
		<comments>http://blog.enkitec.com/2011/10/my-crsstat-script-improved-formatting-of-crs_stat-on-10g-and-11g/#comments</comments>
		<pubDate>Sat, 29 Oct 2011 03:08:53 +0000</pubDate>
		<dc:creator>Paul Elbow</dc:creator>
				<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://blog.enkitec.com/?p=525</guid>
		<description><![CDATA[My crsstat shows a tabular format of CRS or HAS resources (i.e. Cluster 10gR2-11gR2 or ASM/Single instance scenario 11gR2). It has been a work in progress for a while. When I first started working with 10gR2 RAC, I quickly discovered that I didn&#8217;t quite like the formatting of the default crs_stat -t output, so I [...]]]></description>
			<content:encoded><![CDATA[<p>My crsstat shows a tabular format of CRS or HAS resources (i.e. Cluster 10gR2-11gR2 or ASM/Single instance scenario 11gR2).  It has been a work in progress for a while.  When I first started working with 10gR2 RAC, I quickly discovered that I didn&#8217;t quite like the formatting of the default crs_stat -t output, so I wrote my first version of the crsstat script, which consisted of a korn shell script and an awk script (which gave pretty close to the same output as the current version).  I enhanced it at some point to show a different color, if the state didn&#8217;t match the target state.  Then 11gR2 came out and I really didn&#8217;t like the output, so I sat down and wrote the awk script to format the 11gR2 output and added a variable at the top to choose which awk script.  One of my colleagues saw it and liked the output, so I shared it; however, he asked if I could simplify the installation, as at that time you had to set the location of the script, whether it was 10g or 11g, and the location of the CRS_HOME.  Finally, I sat down and decided to make it as universal and easy to use, as I could by adding the awk scripts as variables within the ksh script and adding a section to attempt to determine the CRS or HAS home automatically.  It seems to work fairly well and several of my colleagues have been using it, so I thought I would share it more universally.  Hope everyone finds it useful!<br />
<span id="more-525"></span></p>
<h1>How it Works</h1>
<p>It should work with 10gR2-11gR2 without changes.  The first time is run, it will attempt to identify the Grid Infrastructure / CRS home and the version that is being used (CRS/HAS must be up for it to gather)- it takes that information and writes the info to a crsstat.env located in the same location as the script.  It only gathers the information the first time, so if you upgrade the Oracle software you will want to remove the crsstat.env and allow the script to re-gather the information.</p>
<p>The output of the script assumes a term width of 132 and attempts to highlight possible issues, by showing in RED those resources with a target of ONLINE and a state of OFFLINE.  You can also pass in “search criteria” as the first and only parameter.</p>
<p>Also of note, per Oracle support document 1086563.1, the “State Details” output in 11gR2 could show incorrect information, such as, “Instance Shutdown” even though it is up and running correctly.</p>
<p>Under the covers, the script is utilizing the “crs_stat -t” in 10gR2/11gR1 and “crsctl status resource -t” and then awks their output to create the tabular format.  It has been used on AIX and Linux (SuSE, Red Hat, Oracle).</p>
<h1>How to Install</h1>
<h2>Pre-requisite to Installation:</h2>
<p>1. CRS/HAS must be running<br />
2. The location of the crsstat script must be writable by the user that will run the installation (either root or your oracle user)</p>
<h2>Installation Location:</h2>
<p>Generally, it is practical to put the crsstat script in the /usr/local/bin directory, so everyone will have access (in most users path).  Make sure the crsstat.env file can be created in the /usr/local/bin directory the first time the script is run.  If it is preferred to put it an alternate location, choose a location that is accessible by your Unix users that should be able to list the CRS or HAS resources (i.e. in their PATH).</p>
<h2>Installation Process:</h2>
<p>1) Copy the installation script from this link <a href="http://blog.enkitec.com/wp-content/uploads/2011/10/crsstat.zip">http://blog.enkitec.com/wp-content/uploads/2011/10/crsstat.zip</a><br />
2) Do a &#8220;cp crsstat.zip /usr/local/bin/&#8221;<br />
3) As root run the crsstat and a &#8220;crsstat.env&#8221; file is created:</p>
<pre style="padding-left: 60px;"># cd /usr/local/bin
# unzip crsstat.zip
# chmod 755 crsstat
# ./crsstat
</pre>
<p><em style="padding-left: 65px;">Output like example below&#8230;</em></p>
<pre style="padding-left: 60px;"># chmod 644 crsstat.env</pre>
<p>4) Verify that the crsstat.env file has two entries like the following:<br />
GRID_HOME=/u01/app/oracle/product/11.2.0/grid<br />
GRID_VER=11.2</p>
<h1>Example Usage</h1>
<p>Basic Usage (note that the dbfs filesystem is offline when it should be online, thus it is highlight in red):</p>
<pre style="padding-left: 30px; background-color: #000000;"><span style="color: #ffffff; background-color: #000000;">$ crsstat

Resource Name                            Resource Type  Target       State        Node            State Details
---------------------------------------- -------------- ------------ ------------ --------------- --------------
ora.DATA.dg                              diskgroup      ONLINE       ONLINE       tstdb01
ora.DATA.dg                              diskgroup      ONLINE       ONLINE       tstdb02
ora.LISTENER.lsnr                        Listener       ONLINE       ONLINE       tstdb01
ora.LISTENER.lsnr                        Listener       ONLINE       ONLINE       tstdb02
ora.LISTENER_SCAN1.lsnr                  SCAN Listener  ONLINE       ONLINE       tstdb02
ora.LISTENER_SCAN2.lsnr                  SCAN Listener  ONLINE       ONLINE       tstdb01
ora.LISTENER_SCAN3.lsnr                  SCAN Listener  ONLINE       ONLINE       tstdb01
ora.RECO.dg                              diskgroup      ONLINE       ONLINE       tstdb01
ora.RECO.dg                              diskgroup      ONLINE       ONLINE       tstdb02
ora.SYSTEM.dg                            diskgroup      ONLINE       ONLINE       tstdb01
ora.SYSTEM.dg                            diskgroup      ONLINE       ONLINE       tstdb02
ora.asm                                  ASM            ONLINE       ONLINE       tstdb01
ora.asm                                  ASM            ONLINE       ONLINE       tstdb02
ora.cvu                                  cvu            ONLINE       ONLINE       tstdb01
ora.dbfs.db                              database       ONLINE       ONLINE       tstdb01         Open
ora.dbfs.db                              database       ONLINE       ONLINE       tstdb02         Open
<span style="color: #ff0000;">ora.dbfs.filesystem                                     ONLINE       OFFLINE</span>
<span style="color: #ff0000;">ora.dbfs.filesystem                                     ONLINE       OFFLINE</span>
ora.demo.db                              database       ONLINE       ONLINE       tstdb01         Open
ora.demo.db                              database       ONLINE       ONLINE       tstdb02         Open
ora.demo.workshop.svc                    service        ONLINE       ONLINE       tstdb01
ora.demo.workshop.svc                    service        ONLINE       ONLINE       tstdb02
ora.tstdb01.vip                          Cluster VIP    ONLINE       ONLINE       tstdb01
ora.tstdb02.vip                          Cluster VIP    ONLINE       ONLINE       tstdb02
ora.net1.network                         Network (VIP)  ONLINE       ONLINE       tstdb01
ora.net1.network                         Network (VIP)  ONLINE       ONLINE       tstdb02
ora.ons                                  Ora Notif Svc  ONLINE       ONLINE       tstdb01
ora.ons                                  Ora Notif Svc  ONLINE       ONLINE       tstdb02
ora.registry.acfs                        registry       ONLINE       ONLINE       tstdb01
ora.registry.acfs                        registry       ONLINE       ONLINE       tstdb02
ora.scan1.vip                            SCAN VIP       ONLINE       ONLINE       tstdb02
ora.scan2.vip                            SCAN VIP       ONLINE       ONLINE       tstdb01
ora.scan3.vip                            SCAN VIP       ONLINE       ONLINE       tstdb01
ora.test.db                              database       OFFLINE      OFFLINE
ora.test.db                              database       OFFLINE      OFFLINE
</span></pre>
<p>A couple of examples using the search key:</p>
<pre style="padding-left: 30px; background-color: #000000;"><span style="color: #ffffff; background-color: #000000;">$ crsstat service

Resource Name                            Resource Type  Target       State        Node            State Details
---------------------------------------- -------------- ------------ ------------ --------------- --------------
ora.demo.workshop.svc                    service        ONLINE       ONLINE       tstdb01
ora.demo.workshop.svc                    service        ONLINE       ONLINE       tstdb02

$ crsstat demo

Resource Name                            Resource Type  Target       State        Node            State Details
---------------------------------------- -------------- ------------ ------------ --------------- --------------
ora.demo.db                              database       ONLINE       ONLINE       enkdb01         Open
ora.demo.db                              database       ONLINE       ONLINE       enkdb02         Open
ora.demo.workshop.svc                    service        ONLINE       ONLINE       enkdb01
ora.demo.workshop.svc                    service        ONLINE       ONLINE       enkdb02
</span></pre>
<p>Another example, as sometimes when there are many databases it is useful to pipe the output to grep:</p>
<pre style="padding-left: 30px; background-color: #000000;"><span style="color: #ffffff; background-color: #000000;">$ crsstat database | grep -i offline

ora.test.db                              database       OFFLINE      OFFLINE
ora.test.db                              database       OFFLINE      OFFLINE
</span></pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.enkitec.com/2011/10/my-crsstat-script-improved-formatting-of-crs_stat-on-10g-and-11g/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Table Functions: 9i Feature Worth Revisiting (Part 2)</title>
		<link>http://blog.enkitec.com/2011/10/table-functions-9i-feature-worth-revisiting-part-2/</link>
		<comments>http://blog.enkitec.com/2011/10/table-functions-9i-feature-worth-revisiting-part-2/#comments</comments>
		<pubDate>Mon, 17 Oct 2011 22:14:25 +0000</pubDate>
		<dc:creator>Toby Marks</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[9i]]></category>
		<category><![CDATA[PIPE ROW]]></category>
		<category><![CDATA[PIPELINED]]></category>
		<category><![CDATA[TABLE]]></category>
		<category><![CDATA[Table Functions]]></category>

		<guid isPermaLink="false">http://blog.enkitec.com/?p=470</guid>
		<description><![CDATA[In part I of this series I showed a simple example of how table functions can be used to treat PL/SQL collection types as tables in a SQL query. We used a nested table collection type to which we manually added a few entries. In this example, I intend to show a more practical use [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://blog.enkitec.com/?p=407">part I of this series</a> I showed a simple example of how table functions can be used to treat PL/SQL collection types as tables in a SQL query. We used a nested table collection type to which we manually added a few entries. In this example, I intend to show a more practical use of table functions using all three PL/SQL collection types: associative arrays, nested tables, and VARRAYs.</p>
<p><span id="more-470"></span></p>
<p>Let&#8217;s revisit a use case I alluded to in my earlier blog entry: incorporating LDAP data into a query. Suppose your task is to code a custom authorization scheme for an enterprise application reporting system. You want row access to be determined by a user&#8217;s group memberships in the company&#8217;s Active Directory server. If a user is assigned to &#8220;the Company A group&#8221; in Active Directory, he gets to see Company A&#8217;s data. You can configure that kind of restriction at a database level using <a href="http://www.oracle.com/technetwork/database/security/index-088277.html">Oracle&#8217;s Virtual Private Database</a> feature. Configuring VPD is beyond the scope of this blog entry, but ultimately you will be associating a table to a portion of a SQL WHERE clause that gets appended to every query written against that table. You can find more documentation on VPD <a href="http://download.oracle.com/docs/cd/B28359_01/network.111/b28531/vpd.htm">on the OTN site</a>. In this case, let&#8217;s assume you know that another team has written a PL/SQL database package to query data from Active Directory, and you want to make use of that code. The only problem is that all the functions in that package return collections of various types, and you need to be able to access that information from the WHERE clause you are building with VPD. This is where table functions come in handy.</p>
<p>Let&#8217;s begin by setting up our example schema. We&#8217;ll be looking at client sales data. First, let&#8217;s set up our clients.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p470code13'); return false;">View Code</a> SQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p47013"><td class="code" id="p470code13"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> clients <span style="color: #66cc66;">&#40;</span>
  client_id NUMBER<span style="color: #66cc66;">,</span>
  client_name VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> clients <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">100</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Timco Industries'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> clients <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">200</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Moneybros'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> clients <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">300</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'The Monacle Corporation'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> clients <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">400</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Schmapple'</span><span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>

<p>We also need application users who will be logging in to view the report data. We&#8217;ll assume each application user is uniquely linked to a user in Active Directory via the external_id column.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p470code14'); return false;">View Code</a> SQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p47014"><td class="code" id="p470code14"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> users <span style="color: #66cc66;">&#40;</span>
  sequence_number NUMBER<span style="color: #66cc66;">,</span>
  user_name VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
  external_id VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
  first_name VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">30</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
  last_name VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">30</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> users <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'JACKA'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'jaugusti'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Jack'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Augustine'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> users <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'KENKI'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'kkidd'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Ken'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Kidd'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> users <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'BRIAH'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'bhill'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Brian'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Hill'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> users <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">4</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'KEOVO'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'kvongkas'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Keo'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Vongkaseum'</span><span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>

<p>Finally, we need a data table on which to report.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p470code15'); return false;">View Code</a> SQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p47015"><td class="code" id="p470code15"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> quarterly_sales_data <span style="color: #66cc66;">&#40;</span>
  sequence_number NUMBER<span style="color: #66cc66;">,</span>
  client_id NUMBER<span style="color: #66cc66;">,</span>
  sales_year NUMBER<span style="color: #66cc66;">,</span>
  sales_quarter NUMBER<span style="color: #66cc66;">,</span>
  sales_amount NUMBER<span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> quarterly_sales_data <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">100</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">2011</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">20000</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> quarterly_sales_data <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">100</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">2011</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">17500</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> quarterly_sales_data <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">100</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">2011</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">3</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">33000</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> quarterly_sales_data <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">4</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">200</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">2011</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">4500</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> quarterly_sales_data <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">5</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">200</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">2011</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">7000</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> quarterly_sales_data <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">6</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">200</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">2011</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">3</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">6300</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> quarterly_sales_data <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">7</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">300</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">2011</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">11100</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> quarterly_sales_data <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">8</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">300</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">2011</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">12800</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> quarterly_sales_data <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">9</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">300</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">2011</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">3</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">14000</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> quarterly_sales_data <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">400</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">2011</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">55600</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> quarterly_sales_data <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">11</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">400</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">2011</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">80000</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> quarterly_sales_data <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">12</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">400</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">2011</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">3</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">78500</span><span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>

<p>Our basic report query will look something like this:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p470code16'); return false;">View Code</a> SQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p47016"><td class="code" id="p470code16"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> client_name<span style="color: #66cc66;">,</span> sales_year<span style="color: #66cc66;">,</span> sales_quarter<span style="color: #66cc66;">,</span> sales_amount
  <span style="color: #993333; font-weight: bold;">FROM</span> quarterly_sales_data <span style="color: #993333; font-weight: bold;">NATURAL</span> <span style="color: #993333; font-weight: bold;">JOIN</span> clients;</pre></td></tr></table></div>

<p>Our Active Directory groups will be TIMCO_GRP, MONEYBROS_GRP, MONACLE_GRP, and SCHMAPPLE_GRP. If a user belongs to one or more of these groups, he has permission to view the respective client&#8217;s data.</p>
<p>Now we need a function that returns data from Active Directory. Just to keep it simple we will create a package that hardcodes the group memberships and returns them as collections of various types. We will then look at how table functions can be used to transform each one of those collections into an aggregate result set. (NOTE: querying LDAP directories from PL/SQL is not too difficult, and might serve as the basis for a future blog entry.)</p>
<p>Here&#8217;s our function. We&#8217;ve placed it in a package called LDAP_UTIL.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p470code17'); return false;">View Code</a> SQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p47017"><td class="code" id="p470code17"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">OR</span> <span style="color: #993333; font-weight: bold;">REPLACE</span> PACKAGE ldap_util <span style="color: #993333; font-weight: bold;">AS</span>
&nbsp;
  TYPE ldap_entry_typ <span style="color: #993333; font-weight: bold;">IS</span> RECORD <span style="color: #66cc66;">&#40;</span>
    cn VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">30</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
    description VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1000</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
    distinguished_name VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">200</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
    name VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">30</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
    samaccountname VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">30</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
  TYPE ldap_groups_nt <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">TABLE</span> OF ldap_entry_typ;
  TYPE ldap_groups_aa <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">TABLE</span> OF ldap_entry_typ <span style="color: #993333; font-weight: bold;">INDEX</span> <span style="color: #993333; font-weight: bold;">BY</span> PLS_INTEGER;
  TYPE ldap_groups_va <span style="color: #993333; font-weight: bold;">IS</span> VARRAY<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">100</span><span style="color: #66cc66;">&#41;</span> of ldap_entry_typ;
&nbsp;
  <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_user_groups_nt <span style="color: #66cc66;">&#40;</span>p_user VARCHAR2<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">RETURN</span> ldap_groups_nt;
  <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_user_groups_aa <span style="color: #66cc66;">&#40;</span>p_user VARCHAR2<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">RETURN</span> ldap_groups_aa;
  <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_user_groups_va <span style="color: #66cc66;">&#40;</span>p_user VARCHAR2<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">RETURN</span> ldap_groups_va;
&nbsp;
END ldap_util;
<span style="color: #66cc66;">/</span>
<span style="color: #993333; font-weight: bold;">SHOW</span> ERRORS
&nbsp;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">OR</span> <span style="color: #993333; font-weight: bold;">REPLACE</span> PACKAGE BODY ldap_util <span style="color: #993333; font-weight: bold;">AS</span>
&nbsp;
  <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_user_groups_nt <span style="color: #66cc66;">&#40;</span>p_user VARCHAR2<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">RETURN</span> ldap_groups_nt <span style="color: #993333; font-weight: bold;">IS</span>
    l_groups ldap_groups_nt :<span style="color: #66cc66;">=</span> ldap_groups_nt<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
  BEGIN
    CASE p_user
      WHEN <span style="color: #ff0000;">'jaugusti'</span> THEN
&nbsp;
        l_groups<span style="color: #66cc66;">.</span>extend;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TIMCO_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Timco Industries account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=TIMCO_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TIMCO_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TIMCO_GRP'</span>;
&nbsp;
      WHEN <span style="color: #ff0000;">'kkidd'</span> THEN
&nbsp;
        l_groups<span style="color: #66cc66;">.</span>extend;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONEYBROS_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Moneybros account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=MONEYBROS_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONEYBROS_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONEYBROS_GRP'</span>;
&nbsp;
      WHEN <span style="color: #ff0000;">'bhill'</span> THEN
&nbsp;
        l_groups<span style="color: #66cc66;">.</span>extend;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TIMCO_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Timco Industries account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=TIMCO_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TIMCO_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TIMCO_GRP'</span>;
&nbsp;
        l_groups<span style="color: #66cc66;">.</span>extend;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONACLE_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Monacle Corporation account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=MONACLE_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONACLE_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONACLE_GRP'</span>;
&nbsp;
      WHEN <span style="color: #ff0000;">'kvongkas'</span> THEN
&nbsp;
        l_groups<span style="color: #66cc66;">.</span>extend;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONEYBROS_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Moneybros account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=MONEYBROS_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONEYBROS_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONEYBROS_GRP'</span>;
&nbsp;
        l_groups<span style="color: #66cc66;">.</span>extend;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONACLE_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Monacle Corporation account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=MONACLE_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONACLE_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONACLE_GRP'</span>;
&nbsp;
        l_groups<span style="color: #66cc66;">.</span>extend;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'SCHMAPPLE_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Schmapple account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=SCHMAPPLE_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'SCHMAPPLE_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'SCHMAPPLE_GRP'</span>;
&nbsp;
    END CASE;
    <span style="color: #993333; font-weight: bold;">RETURN</span> l_groups;
  END get_user_groups_nt;
&nbsp;
  <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_user_groups_aa <span style="color: #66cc66;">&#40;</span>p_user VARCHAR2<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">RETURN</span> ldap_groups_aa <span style="color: #993333; font-weight: bold;">IS</span>
    l_groups ldap_groups_aa;
  BEGIN
    CASE p_user
      WHEN <span style="color: #ff0000;">'jaugusti'</span> THEN
&nbsp;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TIMCO_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Timco Industries account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=TIMCO_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TIMCO_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TIMCO_GRP'</span>;
&nbsp;
      WHEN <span style="color: #ff0000;">'kkidd'</span> THEN
&nbsp;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONEYBROS_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Moneybros account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=MONEYBROS_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONEYBROS_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONEYBROS_GRP'</span>;
&nbsp;
      WHEN <span style="color: #ff0000;">'bhill'</span> THEN
&nbsp;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TIMCO_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Timco Industries account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=TIMCO_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TIMCO_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TIMCO_GRP'</span>;
&nbsp;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONACLE_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Monacle Corporation account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=MONACLE_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONACLE_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONACLE_GRP'</span>;
&nbsp;
      WHEN <span style="color: #ff0000;">'kvongkas'</span> THEN
&nbsp;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONEYBROS_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Moneybros account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=MONEYBROS_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONEYBROS_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONEYBROS_GRP'</span>;
&nbsp;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONACLE_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Monacle Corporation account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=MONACLE_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONACLE_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONACLE_GRP'</span>;
&nbsp;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'SCHMAPPLE_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Schmapple account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=SCHMAPPLE_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'SCHMAPPLE_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'SCHMAPPLE_GRP'</span>;
&nbsp;
    END CASE;
    <span style="color: #993333; font-weight: bold;">RETURN</span> l_groups;
  END get_user_groups_aa;
&nbsp;
  <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_user_groups_va <span style="color: #66cc66;">&#40;</span>p_user VARCHAR2<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">RETURN</span> ldap_groups_va <span style="color: #993333; font-weight: bold;">IS</span>
    l_groups ldap_groups_va :<span style="color: #66cc66;">=</span> ldap_groups_va<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
  BEGIN
    CASE p_user
      WHEN <span style="color: #ff0000;">'jaugusti'</span> THEN
&nbsp;
        l_groups<span style="color: #66cc66;">.</span>extend;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TIMCO_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Timco Industries account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=TIMCO_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TIMCO_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TIMCO_GRP'</span>;
&nbsp;
      WHEN <span style="color: #ff0000;">'kkidd'</span> THEN
&nbsp;
        l_groups<span style="color: #66cc66;">.</span>extend;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONEYBROS_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Moneybros account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=MONEYBROS_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONEYBROS_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONEYBROS_GRP'</span>;
&nbsp;
      WHEN <span style="color: #ff0000;">'bhill'</span> THEN
&nbsp;
        l_groups<span style="color: #66cc66;">.</span>extend;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TIMCO_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Timco Industries account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=TIMCO_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TIMCO_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TIMCO_GRP'</span>;
&nbsp;
        l_groups<span style="color: #66cc66;">.</span>extend;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONACLE_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Monacle Corporation account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=MONACLE_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONACLE_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONACLE_GRP'</span>;
&nbsp;
      WHEN <span style="color: #ff0000;">'kvongkas'</span> THEN
&nbsp;
        l_groups<span style="color: #66cc66;">.</span>extend;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONEYBROS_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Moneybros account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=MONEYBROS_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONEYBROS_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONEYBROS_GRP'</span>;
&nbsp;
        l_groups<span style="color: #66cc66;">.</span>extend;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONACLE_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Monacle Corporation account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=MONACLE_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONACLE_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'MONACLE_GRP'</span>;
&nbsp;
        l_groups<span style="color: #66cc66;">.</span>extend;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>cn :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'SCHMAPPLE_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>description :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'Employees working on the Schmapple account.'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>distinguished_name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'CN=SCHMAPPLE_GRP,OU=Global Groups,DC=acme,DC=com'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>name :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'SCHMAPPLE_GRP'</span>;
        l_groups<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">.</span>samaccountname :<span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'SCHMAPPLE_GRP'</span>;
&nbsp;
    END CASE;
    <span style="color: #993333; font-weight: bold;">RETURN</span> l_groups;
  END get_user_groups_va;
&nbsp;
END ldap_util;
<span style="color: #66cc66;">/</span>
<span style="color: #993333; font-weight: bold;">SHOW</span> ERRORS</pre></td></tr></table></div>

<p>As you can see, LDAP_UTIL has three functions that return the three kinds of collections in PL/SQL: nested tables, associative arrays, and varrays.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p470code18'); return false;">View Code</a> SQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p47018"><td class="code" id="p470code18"><pre class="sql" style="font-family:monospace;">  <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_user_groups_nt <span style="color: #66cc66;">&#40;</span>p_user VARCHAR2<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">RETURN</span> ldap_groups_nt;
  <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_user_groups_aa <span style="color: #66cc66;">&#40;</span>p_user VARCHAR2<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">RETURN</span> ldap_groups_aa;
  <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_user_groups_va <span style="color: #66cc66;">&#40;</span>p_user VARCHAR2<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">RETURN</span> ldap_groups_va;</pre></td></tr></table></div>

<p>The collections consist of a group of records representing &#8220;group&#8221; data from Active Directory.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p470code19'); return false;">View Code</a> SQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p47019"><td class="code" id="p470code19"><pre class="sql" style="font-family:monospace;">  TYPE ldap_entry_typ <span style="color: #993333; font-weight: bold;">IS</span> RECORD <span style="color: #66cc66;">&#40;</span>
    cn VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">30</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
    description VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1000</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
    distinguished_name VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">200</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
    name VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">30</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
    samaccountname VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">30</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>

<p>The p_user parameter would be the user&#8217;s network id, corresponding to the sAMAccountName attribute in Active Directory; since we&#8217;re hardcoding group data this is not important to us at the moment. The point is you pass in a username and you get a collection of groups.</p>
<p>Using the same technique we demonstrated in part one, we now create a wrapper package of pipelined functions to transform the collection data into something we can query &#8211; an aggregate result set.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p470code20'); return false;">View Code</a> SQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p47020"><td class="code" id="p470code20"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">OR</span> <span style="color: #993333; font-weight: bold;">REPLACE</span> PACKAGE ldap_util_pipelined <span style="color: #993333; font-weight: bold;">AS</span>
&nbsp;
  <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_user_groups_nt <span style="color: #66cc66;">&#40;</span>p_user VARCHAR2<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">RETURN</span> ldap_util<span style="color: #66cc66;">.</span>ldap_groups_nt PIPELINED;
  <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_user_groups_aa <span style="color: #66cc66;">&#40;</span>p_user VARCHAR2<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">RETURN</span> ldap_util<span style="color: #66cc66;">.</span>ldap_groups_nt PIPELINED;
  <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_user_groups_va <span style="color: #66cc66;">&#40;</span>p_user VARCHAR2<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">RETURN</span> ldap_util<span style="color: #66cc66;">.</span>ldap_groups_va PIPELINED;
&nbsp;
END ldap_util_pipelined;
<span style="color: #66cc66;">/</span>
<span style="color: #993333; font-weight: bold;">SHOW</span> ERRORS
&nbsp;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">OR</span> <span style="color: #993333; font-weight: bold;">REPLACE</span> PACKAGE BODY ldap_util_pipelined <span style="color: #993333; font-weight: bold;">AS</span>
&nbsp;
  <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_user_groups_nt <span style="color: #66cc66;">&#40;</span>p_user VARCHAR2<span style="color: #66cc66;">&#41;</span> 
  <span style="color: #993333; font-weight: bold;">RETURN</span> ldap_util<span style="color: #66cc66;">.</span>ldap_groups_nt PIPELINED <span style="color: #993333; font-weight: bold;">IS</span>
    l_groups ldap_util<span style="color: #66cc66;">.</span>ldap_groups_nt;
  BEGIN
    l_groups :<span style="color: #66cc66;">=</span> ldap_util<span style="color: #66cc66;">.</span>get_user_groups_nt<span style="color: #66cc66;">&#40;</span>p_user<span style="color: #66cc66;">&#41;</span>;
    <span style="color: #993333; font-weight: bold;">FOR</span> i <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">..</span> l_groups<span style="color: #66cc66;">.</span>count LOOP
      PIPE ROW <span style="color: #66cc66;">&#40;</span>l_groups<span style="color: #66cc66;">&#40;</span>i<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
    END LOOP;
    <span style="color: #993333; font-weight: bold;">RETURN</span>;
  END get_user_groups_nt;
&nbsp;
  <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_user_groups_aa <span style="color: #66cc66;">&#40;</span>p_user VARCHAR2<span style="color: #66cc66;">&#41;</span> 
  <span style="color: #993333; font-weight: bold;">RETURN</span> ldap_util<span style="color: #66cc66;">.</span>ldap_groups_nt PIPELINED <span style="color: #993333; font-weight: bold;">IS</span>
    l_groups ldap_util<span style="color: #66cc66;">.</span>ldap_groups_aa;
  BEGIN
    l_groups :<span style="color: #66cc66;">=</span> ldap_util<span style="color: #66cc66;">.</span>get_user_groups_aa<span style="color: #66cc66;">&#40;</span>p_user<span style="color: #66cc66;">&#41;</span>;
    <span style="color: #993333; font-weight: bold;">FOR</span> i <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">..</span> l_groups<span style="color: #66cc66;">.</span>count LOOP
      PIPE ROW <span style="color: #66cc66;">&#40;</span>l_groups<span style="color: #66cc66;">&#40;</span>i<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
    END LOOP;
    <span style="color: #993333; font-weight: bold;">RETURN</span>;
  END get_user_groups_aa;
&nbsp;
  <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_user_groups_va <span style="color: #66cc66;">&#40;</span>p_user VARCHAR2<span style="color: #66cc66;">&#41;</span> 
  <span style="color: #993333; font-weight: bold;">RETURN</span> ldap_util<span style="color: #66cc66;">.</span>ldap_groups_va PIPELINED <span style="color: #993333; font-weight: bold;">IS</span>
    l_groups ldap_util<span style="color: #66cc66;">.</span>ldap_groups_va;
  BEGIN
    l_groups :<span style="color: #66cc66;">=</span> ldap_util<span style="color: #66cc66;">.</span>get_user_groups_va<span style="color: #66cc66;">&#40;</span>p_user<span style="color: #66cc66;">&#41;</span>;
    <span style="color: #993333; font-weight: bold;">FOR</span> i <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">..</span> l_groups<span style="color: #66cc66;">.</span>count LOOP
      PIPE ROW <span style="color: #66cc66;">&#40;</span>l_groups<span style="color: #66cc66;">&#40;</span>i<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
    END LOOP;
    <span style="color: #993333; font-weight: bold;">RETURN</span>;
  END get_user_groups_va;
&nbsp;
END ldap_util_pipelined;
<span style="color: #66cc66;">/</span>
<span style="color: #993333; font-weight: bold;">SHOW</span> ERRORS</pre></td></tr></table></div>

<p>Note the return types of the three functions in ldap_util_pipelined.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p470code21'); return false;">View Code</a> SQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p47021"><td class="code" id="p470code21"><pre class="sql" style="font-family:monospace;">  <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_user_groups_nt <span style="color: #66cc66;">&#40;</span>p_user VARCHAR2<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">RETURN</span> ldap_util<span style="color: #66cc66;">.</span>ldap_groups_nt PIPELINED;
  <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_user_groups_aa <span style="color: #66cc66;">&#40;</span>p_user VARCHAR2<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">RETURN</span> ldap_util<span style="color: #66cc66;">.</span>ldap_groups_nt PIPELINED;
  <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_user_groups_va <span style="color: #66cc66;">&#40;</span>p_user VARCHAR2<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">RETURN</span> ldap_util<span style="color: #66cc66;">.</span>ldap_groups_va PIPELINED;</pre></td></tr></table></div>

<p>The first two return a nested table collection, while the third returns a VARRAY. These two collections can be pipelined because they correspond to native SQL datatypes in Oracle; not so for associative arrays. In order to pipeline the associative array returned from ldap_util.get_user_groups_aa, we need to map that collection to one of the other types. Here, we map it to a nested table. The iterative logic is the same, though, as the other two functions.</p>
<p>Now we can verify that our approach worked by issuing some simple queries, supported by the SQL &#8220;TABLE&#8221; construct.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p470code22'); return false;">View Code</a> SQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p47022"><td class="code" id="p470code22"><pre class="sql" style="font-family:monospace;">SQL<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">select</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">from</span> <span style="color: #993333; font-weight: bold;">table</span><span style="color: #66cc66;">&#40;</span>ldap_util_pipelined<span style="color: #66cc66;">.</span>get_user_groups_nt<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'jaugusti'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
CN        DESCRIPTION                                        DISTINGUISHED_NAME                            NAME      SAMACCOUN
<span style="color: #808080; font-style: italic;">--------- -------------------------------------------------- --------------------------------------------- --------- ---------</span>
TIMCO_GRP Employees working <span style="color: #993333; font-weight: bold;">on</span> the Timco Industries account<span style="color: #66cc66;">.</span> CN<span style="color: #66cc66;">=</span>TIMCO_GRP<span style="color: #66cc66;">,</span>OU<span style="color: #66cc66;">=</span>Global Groups<span style="color: #66cc66;">,</span>DC<span style="color: #66cc66;">=</span>acme<span style="color: #66cc66;">,</span>DC<span style="color: #66cc66;">=</span>com  TIMCO_GRP TIMCO_GRP</pre></td></tr></table></div>

<p>As you can see, the individual attributes of the record structure form the columns of our new table, and we can reference those columns directly, if we wish.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p470code23'); return false;">View Code</a> SQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p47023"><td class="code" id="p470code23"><pre class="sql" style="font-family:monospace;">SQL<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">select</span> cn <span style="color: #993333; font-weight: bold;">from</span> <span style="color: #993333; font-weight: bold;">table</span><span style="color: #66cc66;">&#40;</span>ldap_util_pipelined<span style="color: #66cc66;">.</span>get_user_groups_nt<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'kvongkas'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
CN
<span style="color: #808080; font-style: italic;">---------------</span>
MONEYBROS_GRP
MONACLE_GRP
SCHMAPPLE_GRP</pre></td></tr></table></div>

<p>All that&#8217;s left for us at this point is to construct a WHERE clause condition to use with Oracle&#8217;s Virtual Private Database feature to limit data returned from queries against the table QUARTERLY_SALES_DATA. That condition could look something like this, assuming that our application connects to the database as the logged in user.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p470code24'); return false;">View Code</a> SQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p47024"><td class="code" id="p470code24"><pre class="sql" style="font-family:monospace;">client_id <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> CASE cn
                       WHEN <span style="color: #ff0000;">'TIMCO_GRP'</span> THEN <span style="color: #cc66cc;">100</span>
                       WHEN <span style="color: #ff0000;">'MONEYBROS_GRP'</span> THEN <span style="color: #cc66cc;">200</span>
                       WHEN <span style="color: #ff0000;">'MONACLE_GRP'</span> THEN <span style="color: #cc66cc;">300</span>
                       WHEN <span style="color: #ff0000;">'SCHMAPPLE_GRP'</span> THEN <span style="color: #cc66cc;">400</span>
                     END
                <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #993333; font-weight: bold;">TABLE</span><span style="color: #66cc66;">&#40;</span>ldap_util_pipelined<span style="color: #66cc66;">.</span>get_user_groups_nt<span style="color: #66cc66;">&#40;</span>USER<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></td></tr></table></div>

<p>Here the mapping between AD group name and client ID is hardcoded in the CASE expression. A more flexible way would be to create a mapping table. Also, this is probably not a case study in writing a well performing VPD clause, but the real point here is that using SQL table functions and PL/SQL pipelined functions, we can translate data retrieved from an API, LDAP directory, or web service into table-like structures that we can query, join, and otherwise manipulate just like real tables.</p>
<p><script src="http://connect.facebook.net/en_US/all.js#appId=245406032159496&#038;xfbml=1"></script><br />
<script type="text/javascript" src="//platform.twitter.com/widgets.js"></script><br />
<script type="text/javascript">  (function() {    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;    po.src = 'https://apis.google.com/js/plusone.js';    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);  })();</script><br />
<script src="http://platform.linkedin.com/in.js" type="text/javascript"></script></p>
<div id="fb-root"></div>
<p><fb:like href="" send="false" layout="button_count" width="100" show_faces="false" font="arial"></fb:like><a href="https://twitter.com/share" class="twitter-share-button" data-count="horizontal" data-via="toby_marks">Tweet</a><g:plusone size="medium"></g:plusone><script type="IN/Share" data-url="http://blog.enkitec.com/2011/10/table-functions-9i-feature-worth-revisiting-part-2/" data-counter="right"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.enkitec.com/2011/10/table-functions-9i-feature-worth-revisiting-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sizing up your environment for backups to tape</title>
		<link>http://blog.enkitec.com/2011/09/sizing-up-your-environment-for-backups-to-tape/</link>
		<comments>http://blog.enkitec.com/2011/09/sizing-up-your-environment-for-backups-to-tape/#comments</comments>
		<pubDate>Thu, 01 Sep 2011 16:11:52 +0000</pubDate>
		<dc:creator>Heath Boral</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Backups]]></category>
		<category><![CDATA[Exadata]]></category>
		<category><![CDATA[Sizing]]></category>
		<category><![CDATA[Tape]]></category>

		<guid isPermaLink="false">http://blog.enkitec.com/?p=444</guid>
		<description><![CDATA[So, you just spent many long hours putting together your latest and greatest creation. Hot off the presses, you have a true work of art. Now what? You are being audited on backups? You realize that there was no money for backup gear in the budget, but having this kind of risk over your head [...]]]></description>
			<content:encoded><![CDATA[<p>So, you just spent many long hours putting together your latest and greatest creation. Hot off the presses, you have a true work of art. Now what? You are being audited on backups? You realize that there was no money for backup gear in the budget, but having this kind of risk over your head can only be viewed as something to offload to an over-taxed shared services IT department at your org or a chance to play russian roullette with your data? No! It&#8217;s time to get an accurate assessment of what you need to backup and get your tape requirements sorted out so that you can present a case for your backups and any needed gear to get the job done. Don&#8217;t worry, you may not have to spend 2 trillion dollars on gear (unless you work for the government), especially if you already have a working environment to do your existing backups and just need to find/make capacity on the tape SAN. That being said, you still need to know what you&#8217;ll need to do or ask for and how can you do that if you just go to upper management and say, &#8221; I just got an Exadata and I need at least 48&#215;365 = 17520 TB of capacity in my tape backup gear to make sure we are covered for the year. Let&#8217;s not be greedy. Even the most novice executive will question the costs needed to satisfy that kind of requirement.</p>
<p>Making the assumption that you are using RMAN, you have already configured your backups to run a weekly full on each database to tape once per week, incrementals daily, and a reasonable amount of archivelogs being generated daily to the Fast Recovery Area, we can proceed to estimate your immediate needs.</p>
<p>If you are running Oracle and you are using RMAN, you can get the sizing numbers you need for your tape requirements somewhat easily if you are already taking backups to your Fast Recovery Area. There are a number of different views that can provide information about your backups, but I have found the most beneficial information can be gathered from the views used here. The helpful script that follows can be run to collect data on all the different types of backups you are currently running and the sizes (this script allows you to feed a list of SIDs):</p>
<p>#!/bin/bash</p>
<p>. /home/oracle/.bash_profile</p>
<p>ORAENV_ASK=NO</p>
<p>for DB in `echo &#8220;$DB_LIST&#8221;`; do<br />
export ORACLE_SID=$DB<br />
. oraenv $DB &gt;/dev/null</p>
<p>echo &#8220;Database: $DB&#8221;</p>
<p>sqlplus -s \/ as sysdba&lt;&lt;EOF<br />
set serveroutput on<br />
set linesize 150<br />
set pagesize 300</p>
<p>select ctime &#8220;Date&#8221;,</p>
<p>decode(backup_type, &#8216;L&#8217;, &#8216;Archive Log&#8217;, &#8216;D&#8217;, &#8216;Full&#8217;, &#8216;Incremental&#8217;) backup_type,bsize &#8220;Size GB&#8221; from (select trunc(bp.completion_time) ctime, backup_type, round(sum(bp.bytes/1024/1024/1024),2) bsize</p>
<p>from v\$backup_set bs,</p>
<p>v\$backup_piece bp where bs.set_stamp = bp.set_stamp and bs.set_count  = bp.set_count and bp.status = &#8216;A&#8217; group by trunc(bp.completion_time), backup_type) order by 1, 2;</p>
<p>exit;<br />
EOF<br />
done</p>
<p>You can then look at the history of your current backups and right-size your tape requirements.</p>
<p>You might also check how many archive logs you are generating in a week under full production load:</p>
<p>&nbsp;</p>
<p>col gbytes form 999,999.99</p>
<p>select sum(blocks*block_size)/1024/1024/1024 gbytes</p>
<p>from v$archived_log</p>
<p>where next_time &gt; sysdate-8;</p>
<p>&nbsp;</p>
<p>Some things to consider when you decide on your tape solution:</p>
<p>The type of tape drives</p>
<p>Encryption needs</p>
<p>The amount of compression</p>
<p>The number of tape drives</p>
<p>The type of backup software (OSB vs Netbackup vs Tivoli)</p>
<p>Your vaulting schedule (number of available media slots)</p>
<p>How fast can your channel send the data to the tape drives</p>
<p>Assuming you already have a tape SAN and you are not given enough money in your budget or enough lead time to get the gear in place before an audit, you might consider looking at what you have now in place and checking to see if you are doing too many backups, you have tuned your backups incorrectly, or if you have a number of backups that would benefit from VTL or dedup technologies in order to free space on your existing tape infrastructure.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.enkitec.com/2011/09/sizing-up-your-environment-for-backups-to-tape/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Get Oracle Instant Client Working on Mac OS X Lion</title>
		<link>http://blog.enkitec.com/2011/08/get-oracle-instant-client-working-on-mac-os-x-lion/</link>
		<comments>http://blog.enkitec.com/2011/08/get-oracle-instant-client-working-on-mac-os-x-lion/#comments</comments>
		<pubDate>Wed, 17 Aug 2011 14:46:21 +0000</pubDate>
		<dc:creator>Toby Marks</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[10.7]]></category>
		<category><![CDATA[hints]]></category>
		<category><![CDATA[Lion]]></category>
		<category><![CDATA[Oracle Instant Client]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[rlwrap]]></category>

		<guid isPermaLink="false">http://blog.enkitec.com/?p=420</guid>
		<description><![CDATA[CJ Travis has an excellent and thorough article on installing Oracle Instant Client on Mac OS X 10.7. The gist: you have to install the 32-bit version. As a bonus, he tells you how to download and install the handy rlwrap command line utility, which gives you the ability to navigate the statement history in [...]]]></description>
			<content:encoded><![CDATA[<p>CJ Travis has an <a href="http://www.cjtravis.com/?p=744">excellent and thorough article</a> on installing Oracle Instant Client on Mac OS X 10.7. The gist: you have to install the 32-bit version. As a bonus, he tells you how to download and install the handy <a href="http://blog.enkitec.com/2010/04/using-sqlplus-with-rlwrap-on-ms-windows/">rlwrap</a> command line utility, which gives you the ability to navigate the statement history in SQL*Plus in a very bash-like fashion, using the up and down keys.</p>
<p><span id="more-420"></span></p>
<p><script src="http://connect.facebook.net/en_US/all.js#appId=245406032159496&#038;xfbml=1"></script><br />
<script type="text/javascript" src="//platform.twitter.com/widgets.js"></script><br />
<script type="text/javascript">  (function() {    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;    po.src = 'https://apis.google.com/js/plusone.js';    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);  })();</script><br />
<script src="http://platform.linkedin.com/in.js" type="text/javascript"></script>
<div id="fb-root"></div>
<p><fb:like href="" send="false" layout="button_count" width="100" show_faces="false" font="arial"></fb:like><a href="https://twitter.com/share" class="twitter-share-button" data-count="horizontal" data-via="toby_marks">Tweet</a><g:plusone size="medium"></g:plusone><script type="IN/Share" data-url="http://blog.enkitec.com/2011/08/get-oracle-instant-client-working-on-mac-os-x-lion/" data-counter="right"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.enkitec.com/2011/08/get-oracle-instant-client-working-on-mac-os-x-lion/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Table Functions: 9i Feature Worth Revisiting (Part 1)</title>
		<link>http://blog.enkitec.com/2011/08/table-functions-9i-feature-worth-revisiting-part-1/</link>
		<comments>http://blog.enkitec.com/2011/08/table-functions-9i-feature-worth-revisiting-part-1/#comments</comments>
		<pubDate>Fri, 12 Aug 2011 17:48:49 +0000</pubDate>
		<dc:creator>Toby Marks</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[9i]]></category>
		<category><![CDATA[PIPE ROW]]></category>
		<category><![CDATA[PIPELINED]]></category>
		<category><![CDATA[TABLE]]></category>
		<category><![CDATA[Table Functions]]></category>

		<guid isPermaLink="false">http://blog.enkitec.com/?p=407</guid>
		<description><![CDATA[Yes, they&#8217;ve been around for a while, but if you haven&#8217;t made use of table functions lately you might want to reacquaint yourself with this old gem. Table functions allow you to query the contents of PL/SQL collection types using SQL&#8217;s TABLE operator. Here is a simple example. ?View Code SQLCREATE OR REPLACE PACKAGE example [...]]]></description>
			<content:encoded><![CDATA[<p>Yes, they&#8217;ve been around for a while, but if you haven&#8217;t made use of table functions lately you might want to reacquaint yourself with this old gem. Table functions allow you to query the contents of PL/SQL collection types using SQL&#8217;s TABLE operator. Here is a simple example.</p>
<p><span id="more-407"></span></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p407code28'); return false;">View Code</a> SQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p40728"><td class="code" id="p407code28"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">OR</span> <span style="color: #993333; font-weight: bold;">REPLACE</span> PACKAGE example <span style="color: #993333; font-weight: bold;">AS</span>
&nbsp;
     TYPE nested_table_typ <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">TABLE</span> OF VARCHAR2<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">100</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
     <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_nested_table_data <span style="color: #993333; font-weight: bold;">RETURN</span> nested_table_typ PIPELINED;
&nbsp;
END example;
<span style="color: #66cc66;">/</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">OR</span> <span style="color: #993333; font-weight: bold;">REPLACE</span> PACKAGE BODY example <span style="color: #993333; font-weight: bold;">AS</span>
&nbsp;
     <span style="color: #993333; font-weight: bold;">FUNCTION</span> get_nested_table_data <span style="color: #993333; font-weight: bold;">RETURN</span> nested_table_typ PIPELINED <span style="color: #993333; font-weight: bold;">IS</span>
     BEGIN
          PIPE ROW <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'one'</span><span style="color: #66cc66;">&#41;</span>;
          PIPE ROW <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'two'</span><span style="color: #66cc66;">&#41;</span>;
          PIPE ROW <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'three'</span><span style="color: #66cc66;">&#41;</span>;
          <span style="color: #993333; font-weight: bold;">RETURN</span>;
     END get_nested_table_data;
&nbsp;
END example;
<span style="color: #66cc66;">/</span></pre></td></tr></table></div>

<p>The package function example.get_nested_table_data returns a PL/SQL collection — in this case, a nested table. The PIPELINED directive instructs the function to return data to the calling query as rows are populated by the PIPE ROW command. That way, you don&#8217;t need to wait for the function to finish before you get results from your query.</p>
<p>The function can be invoked from the SELECT clause of a query in the usual way, and will return a valid result.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p407code29'); return false;">View Code</a> SQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p40729"><td class="code" id="p407code29"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> example<span style="color: #66cc66;">.</span>get_nested_table_data <span style="color: #993333; font-weight: bold;">FROM</span> dual;
&nbsp;
GET_NESTED_TABLE_DATA
<span style="color: #808080; font-style: italic;">-------------------------------</span>
SCHEMA<span style="color: #66cc66;">.</span>SYS_PLSQL_166672_9_1<span style="color: #66cc66;">&#40;</span>one<span style="color: #66cc66;">,</span>two<span style="color: #66cc66;">,</span>three<span style="color: #66cc66;">&#41;</span></pre></td></tr></table></div>

<p>This is possible because nested tables and VARRAYs are supported as native types in SQL. The other type of PL/SQL collection, associative arrays, are not. Therefore you cannot use an associative array as the return type of a pipelined table function. However, it&#8217;s pretty trivial to create a wrapper function that translates an associative array into a nested table. You wouldn&#8217;t necessarily take this approach in your own code, but it comes in handy when you&#8217;re transforming data coming from a third party package or function.</p>
<p>But what if you need the contents of the collection presented as a table, with one record per entry in the collection? This is where the TABLE operator comes in handy.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p407code30'); return false;">View Code</a> SQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p40730"><td class="code" id="p407code30"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> column_value <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #993333; font-weight: bold;">TABLE</span><span style="color: #66cc66;">&#40;</span>example<span style="color: #66cc66;">.</span>get_nested_table_data<span style="color: #66cc66;">&#41;</span>;
&nbsp;
COLUMN_VALUE
<span style="color: #808080; font-style: italic;">-------------------</span>
one
two
three</pre></td></tr></table></div>

<p>The TABLE operator casts a collection type as an aggregated result set, meaning it allows you to query it as if it were a table.</p>
<p>Why would you need to do this?</p>
<p>One reason might be because you want to query or join data retrieved from a web service, or from an LDAP server. Another reason might be to simplify a complex query with lots of unions, case statements, and subqueries by fetching, manipulating, and combining your data inside a PL/SQL function. You can leverage the ease and maintainability of building your collection in a procedural manner, while still having access to the collection data from SQL. There is some overhead associated with that approach, though, so you&#8217;ll want to be careful about applying it in performance-critical situations. Still, though, it&#8217;s worth considering when the complexity of SQL constructs gets out of hand.</p>
<p><script src="http://connect.facebook.net/en_US/all.js#appId=245406032159496&#038;xfbml=1"></script><br />
<script type="text/javascript" src="//platform.twitter.com/widgets.js"></script><br />
<script type="text/javascript">  (function() {    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;    po.src = 'https://apis.google.com/js/plusone.js';    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);  })();</script><br />
<script src="http://platform.linkedin.com/in.js" type="text/javascript"></script>
<div id="fb-root"></div>
<p><fb:like href="" send="false" layout="button_count" width="100" show_faces="false" font="arial"></fb:like><a href="https://twitter.com/share" class="twitter-share-button" data-count="horizontal" data-via="toby_marks">Tweet</a><g:plusone size="medium"></g:plusone><script type="IN/Share" data-url="http://blog.enkitec.com/?p=407" data-counter="right"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.enkitec.com/2011/08/table-functions-9i-feature-worth-revisiting-part-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Recyclebin</title>
		<link>http://blog.enkitec.com/2011/05/recyclebin/</link>
		<comments>http://blog.enkitec.com/2011/05/recyclebin/#comments</comments>
		<pubDate>Wed, 25 May 2011 10:48:23 +0000</pubDate>
		<dc:creator>Jon Adams</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.enkitec.com/?p=357</guid>
		<description><![CDATA[What is the recyclebin? The Oracle recyclebin has been around since version 10g release 1 as part of a feature called Flashback Drop and in my opinion, continues to be a little-known and little-understood feature. It has saved me from potential data loss on at least one occasion, though, so I think it deserves some [...]]]></description>
			<content:encoded><![CDATA[<p>What is the recyclebin?<br />
The Oracle recyclebin has been around since version 10g release 1 as part of a feature called Flashback Drop and in my opinion, continues to be a little-known and little-understood feature.  It has saved me from potential data loss on at least one occasion, though, so I think it deserves some consideration.<br />
The recyclebin is actually a data dictionary table containing information about dropped objects. Each named user account has their own recyclebin.  Unless a user has the SYSDBA privilege, the only objects that the user has access to in the recyclebin are those that the user owns. A user can view his objects in the recyclebin using the following statement:</p>
<p><span id="more-357"></span></p>
<p>SELECT * FROM RECYCLEBIN;</p>
<p>Dropped tables and any associated objects such as indexes, constraints, nested tables, are not removed when the table is dropped and still occupy space in the tablespace where they originated.  They continue to count against user space quotas, until specifically purged from the recyclebin either manually or by the database because of tablespace space constraints.</p>
<p>When you drop a tablespace including its contents, the objects in the tablespace are NOT placed in the recycle bin AND the database purges any entries in the recycle bin for objects located in that tablespace.</p>
<p>When you drop a user, any objects belonging to the user are not placed in the recycle bin and any objects in the recycle bin are purged that belong to that user.</p>
<p>When you drop a cluster, its member tables are not placed in the recycle bin and any former member tables in the recycle bin are purged that belong to that cluster.</p>
<p>When you drop a type, any dependent objects such as subtypes are not placed in the recycle bin and any former dependent objects in the recycle bin are purged.</p>
<p>Recyclebin Settings<br />
In 10g release 1, recyclebin was enabled by default and there was only an undocumented parameter to disable it.  This parameter was _recyclebin which defaulted to a value of TRUE.  The recyclebin initialization parameter was introduced in 10g release 2 and had a default setting of ‘on’.  It was a dynamic parameter and could be enabled or disabled with either an ‘alter session’ or an ‘alter system’ command.  Oracle 11g release 1 made no changes to the basic feature, except to add the ‘deferred’ option to the ‘alter session’ command to allow subsequent, but not the current, session to be affected.  Release 2 remained unchanged from release 1.<br />
To find out if the recyclebin is enabled, except for 10g release 1, you can execute ‘show parameter recyclebin’ from a SQL prompt as a user with sysdba privileges.<br />
Sample output:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p357code34'); return false;">View Code</a> NONE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p35734"><td class="code" id="p357code34"><pre class="none" style="font-family:monospace;">SQL&amp;gt; show parameter recyclebin
&nbsp;
NAME                                 TYPE                             VALUE
------------------------------------ -------------------------------- ------------------------------
recyclebin                           string                           on</pre></td></tr></table></div>

<p>I would recommend keeping the recyclebin enabled at all times, except during an upgrade, to add an extra layer of recovery options to the existing environment.</p>
<p>Using Recyclebin</p>
<p>Once recyclebin is enabled, you don’t have to give much thought to its use.  Every time a ‘drop table’ command is executed, the table and its associated objects (indexes, constraints, nested tables) are placed in the recyclebin and renamed with a system-generated naming standard.  Because objects age out of the recyclebin based on demands for space, it is always a good idea to back up a table with an export or a create table as select (CTAS) option before dropping it.  This is especially true for dropping very large tables which may not fit in the recyclebin.</p>
<p>In the event that you do not want a table to be preserved in the recyclebin, the addition of the ‘purge’ option at the end of the ‘drop table’ statement ensures that the recyclebin bin is bypassed and the table as well as the associated objects are dropped from the database.</p>
<p>Purging the recyclebin can be performed at both the user and system level.  As stated earlier, each named account in the database will automatically have a recyclebin  assigned to it.  A user can simply execute the ‘purge recyclebin’ command to purge their individual recyclebin.  Users with the sysdba privilege can purse the entire recyclebin with the ‘purge dba_recyclebin’ command.  Be careful, though, as this command also purges the users’ individual recyclebins as well.  Purging the entire reyclebin should be reserved for upgrade situations, or unless otherwise directed by Oracle Support.</p>
<p>You can also perform selective purges of the recyclebin.  For example ‘purge tablespace tmpdata’ only purges those objects in the recyclebin belonging to the tmpdata tablespace.  Also, ‘purge tablespace tmpdata user jon’ will purge only those objects in the recyclebin belonging to the tmpdata tablespace owned by the named user jon.  You can also purge individual tables from the recyclebin with the command ‘purge table<br />
’.  The table name in this command can be either the system-generated recyclebin name or the original name of the table.</p>
<p>To recover a table from the recyclebin, you need to know if it is available.  Use the following query to get this information:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p357code35'); return false;">View Code</a> NONE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p35735"><td class="code" id="p357code35"><pre class="none" style="font-family:monospace;">select owner, object_name, original_name, droptime
from dba_recyclebin
where owner = ‘CMN’;
&nbsp;
OWNER                          OBJECT_NAME                    ORIGINAL_NAME                    DROPTIME
------------------------------ ------------------------------ -------------------------------- -------------------
CMN                            BIN$o5lg4yWjH3ngRAAUT0rhuQ==$0 CMN_BASE_CONTACT                 2011-05-18:23:12:42
CMN                            BIN$o5lg4yWiH3ngRAAUT0rhuQ==$0 CMN_BASE_CONTACT_PK              2011-05-18:23:12:42
CMN                            BIN$o5icV6rtByXgRAAUT0rhuQ==$0 CMN_BASE_CONTACT                 2011-05-18:22:51:07
CMN                            BIN$o5icV6rfByXgRAAUT0rhuQ==$0 CMN_BASE_CONTACT                 2011-05-18:22:17:45
CMN                            BIN$o5lg4yWvH3ngRAAUT0rhuQ==$0 CMN_BASE_CONTACT                 2011-05-18:23:15:11
CMN                            BIN$o5icV6rgByXgRAAUT0rhuQ==$0 EXECUTE_TABLE                    2011-05-18:22:49:58
CMN                            BIN$o5mU5fo6KF/gRAAUT0rhuQ==$0 EXECUTE_TABLE                    2011-05-18:23:30:15
CMN                            BIN$o5icV6ruByXgRAAUT0rhuQ==$0 EXECUTE_TABLE                    2011-05-18:22:53:23
CMN                            BIN$o5mU5foqKF/gRAAUT0rhuQ==$0 CMN_BASE_CONTACT                 2011-05-18:23:27:15
CMN                            BIN$o5mU5fo5KF/gRAAUT0rhuQ==$0 CMN_BASE_CONTACT                 2011-05-18:23:30:08
CMN                            BIN$o5mU5fo4KF/gRAAUT0rhuQ==$0 CMN_BASE_CONTACT_PK              2011-05-18:23:30:08
CMN                            BIN$o5mU5fpGKF/gRAAUT0rhuQ==$0 CMN_BASE_CONTACT                 2011-05-18:23:32:02
CMN                            BIN$o5mU5fpHKF/gRAAUT0rhuQ==$0 EXECUTE_TABLE                    2011-05-18:23:32:02</pre></td></tr></table></div>

<p>NOTE – The owner clause in this query was only given to limit the size of the output.</p>
<p>From this output, you can see which tables are present in the recyclebin and when they were dropped.  As you can see, there can be several versions of the same table in the recyclebin.</p>
<p>This brings us to the purpose of the recyclebin – recovering an accidentally dropped table.  What you may or may not know is that the recyclebin tables can be queried like normal tables.  You can query the recyclebin copies of the table until you find the one that contains the data you are interested in…</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p357code36'); return false;">View Code</a> NONE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p35736"><td class="code" id="p357code36"><pre class="none" style="font-family:monospace;">select count(*)
from cmn.&quot;BIN$o5mU5fpGKF/gRAAUT0rhuQ==$0&quot;;
&nbsp;
  COUNT(*)
----------
        89</pre></td></tr></table></div>

<p>Note that it is important to use both the owner identifier (CMN) and double-quotation marks because of the special characters in the recyclebin table name.<br />
Once the table you want to recover has been identified, there are a few different methods by which you can recover the table or the individual data.  The ‘flashback table<br />
to before drop’ command will recover the latest copy of the table in the recyclebin.  You can also specify the ‘rename to ’ at the end of the command to recover the table to a different table name.  In the case where there are several copies of the table in the recyclebin and you are not interested in the latest copy, you can do a simple create table as select (CTAS) operation using the recyclebin table name, not the original name.  Remember to use double-quotation marks around the recyclebin table name due to the special characters.  You should also be able to recover select rows from the recyclebin table using the same method.</p>
<p>Summary<br />
In situations where the code we deploy is beyond our control, this feature may prove invaluable.  It is one of those features that you can set and forget, but are very thankful when it is available and you need it.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.enkitec.com/2011/05/recyclebin/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Make bash scripts crontab-compatible</title>
		<link>http://blog.enkitec.com/2011/05/make-bash-scripts-crontab-compatible/</link>
		<comments>http://blog.enkitec.com/2011/05/make-bash-scripts-crontab-compatible/#comments</comments>
		<pubDate>Fri, 06 May 2011 17:05:08 +0000</pubDate>
		<dc:creator>Toby Marks</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Bash]]></category>
		<category><![CDATA[cron]]></category>
		<category><![CDATA[crontab]]></category>
		<category><![CDATA[hints]]></category>
		<category><![CDATA[shell scripting]]></category>

		<guid isPermaLink="false">http://blog.enkitec.com/?p=315</guid>
		<description><![CDATA[When writing shell scripts in bash, consider whether your script can be automated in a batch scheduler like cron. If you reference any external resources in your script relative to the directory in which it resides, those references may break when running your script through cron. By default, crontab runs scripts in the user&#8217;s home [...]]]></description>
			<content:encoded><![CDATA[<p>When writing shell scripts in bash, consider whether your script can be automated in a batch scheduler like cron. If you reference any external resources in your script relative to the directory in which it resides, those references may break when running your script through cron.</p>
<p>By default, crontab runs scripts in the user&#8217;s home directory, as specified in <em>/etc/passwd</em>. For user &#8220;Tim&#8221; with home directory <em>/home/tim</em>, a sample crontab might look something like the following:</p>
<p><span id="more-315"></span></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p315code42'); return false;">View Code</a> BASH</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p31542"><td class="code" id="p315code42"><pre class="bash" style="font-family:monospace;"><span style="color: #000000;">0</span> <span style="color: #000000;">0</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> runme.sh</pre></td></tr></table></div>

<p>Every night at midnight, cron will try to run the file <em>/home/tim/runme.sh</em>. However, if <em>runme.sh</em> is actually in a sub-directory under <em>~tim</em>, you will need to tell cron how to reach the file. One option would be to qualify the path in crontab, like so:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p315code43'); return false;">View Code</a> BASH</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p31543"><td class="code" id="p315code43"><pre class="bash" style="font-family:monospace;"><span style="color: #000000;">0</span> <span style="color: #000000;">0</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> ~<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>runme.sh</pre></td></tr></table></div>

<p>Now cron can find the file. However, if the script makes references to other files inside of <em>/bin</em> in a path-relative way, those references will be broken.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p315code44'); return false;">View Code</a> BASH</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p31544"><td class="code" id="p315code44"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
<span style="color: #666666; font-style: italic;">#runme.sh</span>
.<span style="color: #000000; font-weight: bold;">/</span>runthis.sh      <span style="color: #666666; font-style: italic;"># can't find this file when running under cron</span>
.<span style="color: #000000; font-weight: bold;">/</span>runthat.sh      <span style="color: #666666; font-style: italic;"># can't find this file when running under cron</span></pre></td></tr></table></div>

<p>That&#8217;s because to cron <em>./</em> is not the directory in which the script is running, but rather whatever is defined as the base directory; in the default case, the user&#8217;s home directory.</p>
<p>It is possible to specify the base directory in the crontab file itself by defining the special variable <em>HOME</em>.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p315code45'); return false;">View Code</a> BASH</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p31545"><td class="code" id="p315code45"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">HOME</span>=<span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>tim<span style="color: #000000; font-weight: bold;">/</span>bin
<span style="color: #000000;">0</span> <span style="color: #000000;">0</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> <span style="color: #000000; font-weight: bold;">*</span> runme.sh</pre></td></tr></table></div>

<p>However, you may not always have control over how your crontab is configured. Perhaps a system administrator is in charge of all the schedules on your server. Or you may organize your scripts in several different directories.</p>
<p>An easy solution is to start your bash scripts with the following command:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p315code46'); return false;">View Code</a> BASH</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p31546"><td class="code" id="p315code46"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> $<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">dirname</span> <span style="color: #007800;">$0</span><span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></td></tr></table></div>

<p>The program <em>dirname</em> returns the directory portion of the fully qualified path name sent to it. The <em>$0</em> argument in this context is name of the running script. Basically, this code ensures that the current working directory is the same as the directory in which your script is running. That way all your path-relative references are correct whether running manually or through a scheduler.</p>
<p><script src="http://connect.facebook.net/en_US/all.js#appId=245406032159496&#038;xfbml=1"></script><br />
<script type="text/javascript" src="//platform.twitter.com/widgets.js"></script><br />
<script type="text/javascript">  (function() {    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;    po.src = 'https://apis.google.com/js/plusone.js';    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);  })();</script><br />
<script src="http://platform.linkedin.com/in.js" type="text/javascript"></script>
<div id="fb-root"></div>
<p><fb:like href="" send="false" layout="button_count" width="100" show_faces="false" font="arial"></fb:like><a href="https://twitter.com/share" class="twitter-share-button" data-count="horizontal" data-via="toby_marks">Tweet</a><g:plusone size="medium"></g:plusone><script type="IN/Share" data-url="http://blog.enkitec.com/?p=315" data-counter="right"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.enkitec.com/2011/05/make-bash-scripts-crontab-compatible/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Invalidating Toplink Session Cache To Avoid Stale Data</title>
		<link>http://blog.enkitec.com/2011/04/invalidating-toplink-session-cache-to-avoid-stale-data/</link>
		<comments>http://blog.enkitec.com/2011/04/invalidating-toplink-session-cache-to-avoid-stale-data/#comments</comments>
		<pubDate>Thu, 28 Apr 2011 13:38:50 +0000</pubDate>
		<dc:creator>Toby Marks</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[J2EE]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[Oracle Application Server]]></category>
		<category><![CDATA[stale data]]></category>
		<category><![CDATA[Toplink]]></category>
		<category><![CDATA[Weblogic]]></category>

		<guid isPermaLink="false">http://blog.enkitec.com/?p=295</guid>
		<description><![CDATA[Toplink is a Java framework that maps objects to database tables. It is the reference implementation for the Java Persistence Architecture, or JPA. Developers use Toplink to manage data persistence (storage), queries, and transactions in an Oracle database. By default, Toplink makes use of a special cache called a Session Cache, maintained on the server, [...]]]></description>
			<content:encoded><![CDATA[<p>Toplink is a Java framework that maps objects to database tables. It is the reference implementation for the Java Persistence Architecture, or JPA. Developers use Toplink to manage data persistence (storage), queries, and transactions in an Oracle database. By default, Toplink makes use of a special cache called a Session Cache, maintained on the server, which is meant to speed up performance. Queried data is stored in the Session Cache and used in subsequent queries to reduce or eliminate calls to the database.</p>
<p>One problem with this approach is how to deal with &#8220;stale data&#8221;. In other words, what happens when data is changing in the database? How does the developer ensure that the cached data is current?</p>
<p><span id="more-295"></span></p>
<p>I ran into this issue recently when consulting with one of our clients on a third-party J2EE application that used Toplink for its persistence layer. What we noticed was that at a certain point in the business process the application was clearly displaying stale data. The &#8220;status&#8221; column on a certain record was being changed in the database (as could be verified by a SQL query), but the application still displayed the prior status. Refreshing the screen and requerying the data had no effect. The problem was that the status was being changed through a custom stored procedure which performed direct updates on the screen&#8217;s underlying table. This approach was technically against the directives of the third-party application vendor, who insisted that all such changes to the database be made via calls to its own web services. That was for good reason. The web services they provided as an API for custom development were the same ones used by the screens to query data. They used the same Toplink Session Cache. Changes made through the web services, therefore, would have updated the cache, thereby avoiding the problem. As it was, the client had unintentionally created out-of-sync scenario between the cache and the database, and the status information displayed on the screen was invalid.</p>
<p>The most obvious solution would have been to modify the custom procedure to make use of the provided APIs. However, we didn&#8217;t have an API in this instance that provided exactly the required functionality. Having the software vendor modify or extend the API for our purposes would have been prohibitively expensive, in both time and money.</p>
<p>Another possibility we considered was to have the vendor make a smaller modification to bypass the Toplink cache for queries on that screen. It is possible to disable caching per table, through the global configuration file persistence.xml, or as a property of an individual query. However, the vendor was not predisposed to introduce what they viewed as a &#8220;hack&#8221; to accommodate our custom functionality.</p>
<p>Ultimately we decided to implement a tacked-on solution that would arrive at the same goal and eliminate the need for an additional iteration through the vendor&#8217;s dev/test cycle. We created a custom servlet, installed in the third-party application itself, that invalidated the Toplink Session Cache for a specified table or, as an additional method, for all tables. Invalidating the cache means that the next time a query is executed against that table, the  cache is bypassed and data is retrieved directly from the database. To make it easier for the non-Java in-house developers to use, we created a custom wrapper package to mask the call to the servlet. A call to this package was added to the client&#8217;s custom code just after the record in question was updated and commited.</p>
<p>The solution consisted of two Java classes, JAR&#8217;ed and deployed as a library in the third-party application&#8217;s WEB-INF/lib directory.</p>
<p>CacheInvalidator.java<br />
CacheInvalidatorServlet.java</p>
<p>The web application configuration file web.xml was also modified to add a reference to the new &#8220;cacheinvalidator&#8221; servlet.</p>
<p>The code was adapted from the following documentation, available on Oracle Tech Net:</p>
<p>Database Change Notification and TopLink Cache Invalidation<br />
<a href="http://www.oracle.com/technetwork/middleware/ias/index-097190.html">http://www.oracle.com/technetwork/middleware/ias/index-097190.html</a></p>
<p>Oracle TopLink Cache Invalidation<br />
<a href="http://www.oracle.com/technetwork/middleware/ias/index-100679.html">http://www.oracle.com/technetwork/middleware/ias/index-100679.html</a></p>
<p>The two methods of CacheInvalidator that do the actual work are shown here. The first takes tablename as an argument, so that the invalidation can be targeted. The second invalidates, or effectively wipes, the entire cache.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p295code50'); return false;">View Code</a> JAVA</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p29550"><td class="code" id="p295code50"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> invalidateClass<span style="color: #009900;">&#40;</span>Session session, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> tableName<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aexception+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Exception</span></a> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>tableName <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span> <span style="color: #339933;">||</span> tableName.<span style="color: #006633;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aexception+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Exception</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;tableName cannot be null&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">Class</span> baseClass <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">Class</span><span style="color: #009900;">&#41;</span>tableNameToClass.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>tableName<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>baseClass <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aexception+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Exception</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;table <span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span> <span style="color: #339933;">+</span> tableName <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\&quot;</span> not found in cache&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// invalidate in TopLink cache the object corresponding to the baseClass</span>
    session.<span style="color: #006633;">getIdentityMapAccessor</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">invalidateClass</span><span style="color: #009900;">&#40;</span>baseClass<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// invalidate all objects in the cache</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> invalidateAllClasses<span style="color: #009900;">&#40;</span>Session session<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// invalidate in TopLink cache the object corresponding to the baseClass</span>
    session.<span style="color: #006633;">getIdentityMapAccessor</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">invalidateAll</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>The CacheInvalidatorServlet takes a table name or the special keyword &#8220;ALL&#8221; as a parameter and calls the corresponding method in CacheInvalidator.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p295code51'); return false;">View Code</a> JAVA</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p29551"><td class="code" id="p295code51"><pre class="java" style="font-family:monospace;"><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> oName <span style="color: #339933;">=</span> request.<span style="color: #006633;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;objectName&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> responseString <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
    SessionManager manager <span style="color: #339933;">=</span> SessionManager.<span style="color: #006633;">getManager</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">//SESSIONNAME defined in sessions.xml</span>
    Server server <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>Server<span style="color: #009900;">&#41;</span>manager.<span style="color: #006633;">getSession</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;SESSIONNAME&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    Session session <span style="color: #339933;">=</span> server.<span style="color: #006633;">getActiveSession</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    CacheInvalidator invalidator <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> CacheInvalidator<span style="color: #009900;">&#40;</span>session<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>oName.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;ALL&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        invalidator.<span style="color: #006633;">invalidateAllClasses</span><span style="color: #009900;">&#40;</span>session<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        responseString <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;successfully invalidated toplink cache for all tables.&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
        invalidator.<span style="color: #006633;">invalidateClass</span><span style="color: #009900;">&#40;</span>session, oName<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        responseString <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;successfully invalidated toplink cache for table: &quot;</span><span style="color: #339933;">+</span>oName<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aexception+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Exception</span></a> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    responseString <span style="color: #339933;">=</span> e.<span style="color: #006633;">getMessage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Caling a servlet from PL/SQL is not particularly complicated, but in our case involved the lookup of server information stored in the database. The wrapper package allowed us to provide the developers with a simple, one-line invocation.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p295code52'); return false;">View Code</a> SQL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p29552"><td class="code" id="p295code52"><pre class="sql" style="font-family:monospace;">p_servlet_response :<span style="color: #66cc66;">=</span> utl_http<span style="color: #66cc66;">.</span>request<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'http://'</span><span style="color: #66cc66;">||</span>l_app_server_host<span style="color: #66cc66;">||</span><span style="color: #ff0000;">':'</span>
          <span style="color: #66cc66;">||</span>l_app_server_port<span style="color: #66cc66;">||</span><span style="color: #ff0000;">'/jedi/cacheinvalidatorservlet?objectName='</span>
          <span style="color: #66cc66;">||</span>p_obj_to_invalidate<span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>

<p>After making a call to our cacheinvalidator package subsequent to updating the status record, the stale data problem was eliminated in the application.</p>
<p><script src="http://connect.facebook.net/en_US/all.js#appId=245406032159496&#038;xfbml=1"></script><br />
<script type="text/javascript" src="//platform.twitter.com/widgets.js"></script><br />
<script type="text/javascript">  (function() {    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;    po.src = 'https://apis.google.com/js/plusone.js';    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);  })();</script><br />
<script src="http://platform.linkedin.com/in.js" type="text/javascript"></script>
<div id="fb-root"></div>
<p><fb:like href="" send="false" layout="button_count" width="100" show_faces="false" font="arial"></fb:like><a href="https://twitter.com/share" class="twitter-share-button" data-count="horizontal" data-via="toby_marks">Tweet</a><g:plusone size="medium"></g:plusone><script type="IN/Share" data-url="http://blog.enkitec.com/?p=295" data-counter="right"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.enkitec.com/2011/04/invalidating-toplink-session-cache-to-avoid-stale-data/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fixed Object Statistics Benefits in 11g</title>
		<link>http://blog.enkitec.com/2011/04/fixed-object-statistics-benefits-in-11g/</link>
		<comments>http://blog.enkitec.com/2011/04/fixed-object-statistics-benefits-in-11g/#comments</comments>
		<pubDate>Thu, 28 Apr 2011 13:38:33 +0000</pubDate>
		<dc:creator>Jon Adams</dc:creator>
				<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://blog.enkitec.com/?p=241</guid>
		<description><![CDATA[I wrote recently about fixed object statistics in 10g and used an example to illustrate their benefit to the optimizer in one particular situation. I recently found a similar situation in an 11g (release 2) database and wanted to see if I could get the same benefit from generating optimizer statistics on the fixed objects. [...]]]></description>
			<content:encoded><![CDATA[<p>I wrote recently about fixed object statistics in 10g and used an example to illustrate<br />
their benefit to the optimizer in one particular situation.  I recently found a similar situation in an 11g (release 2) database and wanted to see if I could get the same benefit from generating optimizer statistics on the fixed objects.  The automatic statistics gathering job in 11g does not collect the fixed object statistics by default, but the fact that a pre-configured optimizer job exists underscores the importance of optimizer statistics.</p>
<p>We will start with a typical query you would execute to find out who is accessing<br />
certain objects in the database:  select distinct owner<br />
from v$access;</p>
<p>Our test system: Oracle 11.2.0.1.0 64-bit on Sun SPARC Solaris version 10</p>
<p><span id="more-241"></span></p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p241code67'); return false;">View Code</a> NONE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p24167"><td class="code" id="p241code67"><pre class="none" style="font-family:monospace;">SQL&amp;gt; set timing on
SQL&amp;gt; select distinct owner
  2  from v$access;
&nbsp;
&nbsp;
from v$access
     *
ERROR at line 2:
ORA-01013: user requested cancel of current operation
&nbsp;
Elapsed: 00:08:13.62</pre></td></tr></table></div>

<p>Not exactly the performance we expect from this Oracle database version. What&#8217;s going on?</p>
<p>NOTE &#8211; SQL_ID = f9u1sd8tq9rcm (obtained from querying v$session during execution)</p>
<p>Let&#8217;s look at the explain plan for this query.  Since we want to get all the information<br />
possible, we use the following alter session command and a call to the dbms_xplan package.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p241code68'); return false;">View Code</a> NONE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p24168"><td class="code" id="p241code68"><pre class="none" style="font-family:monospace;">alter session set statistics_level=ALL;
&nbsp;
Session altered.
&nbsp;
--We execute the query again with the gather_plan_statistics hint to generate extended statistics.
&nbsp;
SQL&amp;gt; select /*+ gather_plan_statistics */ distinct owner from v$access;
We know the query probably won't finish, so we kill it with a  after a minute.</pre></td></tr></table></div>

<p>NOTE &#8211; SQL_ID = dmfdcmvwkgfqh (obtained from querying v$session during execution)<br />
The SQL_ID changed because of the hint.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p241code69'); return false;">View Code</a> NONE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p24169"><td class="code" id="p241code69"><pre class="none" style="font-family:monospace;">select * from table(dbms_xplan.display_cursor('&amp;amp;sql_id','&amp;amp;child_no','allstats'))
/
&nbsp;
Enter value for sql_id: dmfdcmvwkgfqh
Enter value for child_no: 0
old   1: select * from table(dbms_xplan.display_cursor('&amp;amp;sql_id','&amp;amp;child_no','allstats'))
new   1: select * from table(dbms_xplan.display_cursor('dmfdcmvwkgfqh','0','allstats'))
&nbsp;
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  dmfdcmvwkgfqh, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ distinct owner from v$access
&nbsp;
Plan hash value: 3850776806
&nbsp;
-------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                  | Name            | Starts | E-Rows | A-Rows |   A-Time   |  OMem |  1Mem |  O/1/M   |
-------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |                 |      1 |        |      0 |00:00:00.01 |       |       |          |
|   1 |  HASH UNIQUE               |                 |      1 |      1 |      0 |00:00:00.01 |   741K|   741K|          |
|   2 |   NESTED LOOPS             |                 |      1 |      1 |     32 |00:00:04.04 |       |       |          |
|   3 |    NESTED LOOPS            |                 |      1 |      1 |     32 |00:00:04.04 |       |       |          |
|   4 |     MERGE JOIN CARTESIAN   |                 |      1 |    100 |   2291K|00:00:11.60 |       |       |          |
|*  5 |      FIXED TABLE FULL      | X$KSUSE         |      1 |      1 |     47 |00:00:00.01 |       |       |          |
|   6 |      BUFFER SORT           |                 |     47 |    100 |   2291K|00:00:08.38 |  3454K|   810K|     1/0/0|
|   7 |       FIXED TABLE FULL     | X$KGLDP         |      1 |    100 |  48886 |00:00:00.33 |       |       |          |
|*  8 |     FIXED TABLE FIXED INDEX| X$KGLLK (ind:1) |   2291K|      1 |     32 |00:01:13.38 |       |       |          |
|*  9 |    FIXED TABLE FIXED INDEX | X$KGLOB (ind:1) |     32 |      1 |     32 |00:00:00.01 |       |       |          |
-------------------------------------------------------------------------------------------------------------------------
&nbsp;
Predicate Information (identified by operation id):
---------------------------------------------------
&nbsp;
   5 - filter(&quot;S&quot;.&quot;INST_ID&quot;=USERENV('INSTANCE'))
   8 - filter((&quot;L&quot;.&quot;KGLLKUSE&quot;=&quot;S&quot;.&quot;ADDR&quot; AND &quot;L&quot;.&quot;KGLLKHDL&quot;=&quot;D&quot;.&quot;KGLHDADR&quot; AND &quot;L&quot;.&quot;KGLNAHSH&quot;=&quot;D&quot;.&quot;KGLNAHSH&quot;))
   9 - filter((&quot;O&quot;.&quot;KGLNAHSH&quot;=&quot;D&quot;.&quot;KGLRFHSH&quot; AND &quot;O&quot;.&quot;KGLHDADR&quot;=&quot;D&quot;.&quot;KGLRFHDL&quot;))
&nbsp;
28 rows selected.</pre></td></tr></table></div>

<p>A &#8216;merge join cartesian&#8217; operation is at the heart of this query.  This operation was common in a 10g environment, and is not uncommon in 11g, apparently.  This operation mixed with bad cardinality estimates can really hang a query.<br />
The bad estimates I refer too can be seen in this plan as an enormous difference between what the optimizer estimates (E-Rows) the number of rows it will need to access compared to the actual (A-Rows) number of rows that will need to<br />
be accessed. A typical cause of this disparity is statistics that are severely out of date or non-existent.  We can check the number of fixed tables that have statistics with the following query (for a 10gR2 database, it should return about 790 rows):</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p241code70'); return false;">View Code</a> NONE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p24170"><td class="code" id="p241code70"><pre class="none" style="font-family:monospace;">SQL&amp;gt; select count(*) from sys.tab_stats$;
&nbsp;
  COUNT(*)
----------
         0</pre></td></tr></table></div>

<p>If no rows are returned (as was the case in this system), then no fixed object statistics are present.  This could be the cause of the problem querying the v$access view.  We can check this assumption further by trying to remove the optimizer from the equation altogether with the use of a query hint:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p241code71'); return false;">View Code</a> NONE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p24171"><td class="code" id="p241code71"><pre class="none" style="font-family:monospace;">SQL&amp;gt; select /*+ RULE */ distinct owner from v$access;
&nbsp;
OWNER
----------------------------------------------------------------
0
ATG_ADMIN
ATG_CATALOG1
DBSNMP
JRADAMS
PUBLIC
STOREORD
SYS
SYSTEM
TCSWEB
WEBJMS
&nbsp;
12 rows selected.
&nbsp;
Elapsed: 00:00:00.55</pre></td></tr></table></div>

<p>As you can see, the query returned in less than a second.  Let&#8217;s look at the explain plan (we won&#8217;t bother trying to look at all the stats since we bypassed the optimizer):</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p241code72'); return false;">View Code</a> NONE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p24172"><td class="code" id="p241code72"><pre class="none" style="font-family:monospace;">SQL&amp;gt; set autotrace traceonly explain
SQL&amp;gt; select /*+ RULE */ distinct owner from v$access;
Elapsed: 00:00:00.00
&nbsp;
Execution Plan
----------------------------------------------------------
Plan hash value: 868229819
&nbsp;
-------------------------------------------
| Id  | Operation               | Name    |
-------------------------------------------
|   0 | SELECT STATEMENT        |         |
|   1 |  SORT UNIQUE            |         |
|   2 |   MERGE JOIN            |         |
|   3 |    SORT JOIN            |         |
|   4 |     MERGE JOIN          |         |
|   5 |      SORT JOIN          |         |
|   6 |       MERGE JOIN        |         |
|   7 |        SORT JOIN        |         |
|   8 |         FIXED TABLE FULL| X$KGLLK |
|*  9 |        SORT JOIN        |         |
|  10 |         FIXED TABLE FULL| X$KGLDP |
|* 11 |      SORT JOIN          |         |
|  12 |       FIXED TABLE FULL  | X$KGLOB |
|* 13 |    SORT JOIN            |         |
|* 14 |     FIXED TABLE FULL    | X$KSUSE |
-------------------------------------------
&nbsp;
Predicate Information (identified by operation id):
---------------------------------------------------
&nbsp;
   9 - access(&quot;L&quot;.&quot;KGLLKHDL&quot;=&quot;D&quot;.&quot;KGLHDADR&quot; AND
              &quot;L&quot;.&quot;KGLNAHSH&quot;=&quot;D&quot;.&quot;KGLNAHSH&quot;)
       filter(&quot;L&quot;.&quot;KGLNAHSH&quot;=&quot;D&quot;.&quot;KGLNAHSH&quot; AND
              &quot;L&quot;.&quot;KGLLKHDL&quot;=&quot;D&quot;.&quot;KGLHDADR&quot;)
  11 - access(&quot;O&quot;.&quot;KGLNAHSH&quot;=&quot;D&quot;.&quot;KGLRFHSH&quot; AND
              &quot;O&quot;.&quot;KGLHDADR&quot;=&quot;D&quot;.&quot;KGLRFHDL&quot;)
       filter(&quot;O&quot;.&quot;KGLHDADR&quot;=&quot;D&quot;.&quot;KGLRFHDL&quot; AND
              &quot;O&quot;.&quot;KGLNAHSH&quot;=&quot;D&quot;.&quot;KGLRFHSH&quot;)
  13 - access(&quot;L&quot;.&quot;KGLLKUSE&quot;=&quot;S&quot;.&quot;ADDR&quot;)
       filter(&quot;L&quot;.&quot;KGLLKUSE&quot;=&quot;S&quot;.&quot;ADDR&quot;)
  14 - filter(&quot;S&quot;.&quot;INST_ID&quot;=USERENV('INSTANCE'))
&nbsp;
Note
-----
   - rule based optimizer used (consider using cbo)</pre></td></tr></table></div>

<p>Although there are several merge joins as well as several full table scans present,<br />
there is no sign of the &#8216;merge join cartesian&#8217; from the earlier optimizer explain plan.  This should be enough proof that the optimizer does not have the information it needs to produce the best results.</p>
<p>The RULE hint is a definite work around for this problem, but Oracle has been stating<br />
that the rule-based optimizer has been deprecated for years, so there is no guarantee how much longer this hint will be effective as a workaround.  We should try to solve this issue working with the optimizer, and not bypassing it, because improving the optimizer&#8217;s function will bring benefits to the entire system</p>
<p>Generating new fixed object statistics is a database-wide change though that needs to be approached with caution.  Even though there is some evidence that it would<br />
make a positive impact in this situation, it could have a negative impact on other<br />
processes that have higher importance, especially if this is an established production<br />
system where performance is at an expected level.</p>
<p>In the case where we cannot readily generate new fixed object statistics, there are<br />
optimizer-based workarounds in the form of these hints:</p>
<p>_optimizer_cartesian_enabled<br />
_optimizer_mjc_enabled</p>
<p>The _optimizer_cartesian_enabled parameter was introduced in 10gR2 as a means to stop the merge join cartesian operation.  This parameter is set to TRUE by default.  It can be set at the session or system level.  Let&#8217;s set it for this session, then try our test query again:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p241code73'); return false;">View Code</a> NONE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p24173"><td class="code" id="p241code73"><pre class="none" style="font-family:monospace;">SQL&amp;gt; set autotrace off;
&nbsp;
SQL&amp;gt; alter session set &quot;_optimizer_cartesian_enabled&quot;=FALSE;
&nbsp;
Session altered.
&nbsp;
SQL&amp;gt; col pd_name format a50
SQL&amp;gt; col pd_value format a50
SQL&amp;gt; select n.ksppinm pd_name, c.ksppstvl pd_value
from x$ksppi n, x$ksppcv c
where n.indx=c.indx
and (
   lower(n.ksppinm) like lower('_optimizer_cartesian_enabled')
   or lower(n.ksppdesc) like lower('_optimizer_cartesian_enabled')
)
/
&nbsp;
PD_NAME                                  PD_VALUE
---------------------------------------- --------------------
_optimizer_cartesian_enabled             FALSE
&nbsp;
SQL&amp;gt; set timing on
SQL&amp;gt; select distinct owner
  2  from v$access;
&nbsp;
OWNER
----------------------------------------------------------------
&nbsp;
PUBLIC
SYSTEM
SYS
WEBJMS
STOREORD
0
JRADAMS
ATG_ADMIN
ATG_CATALOG1
TCSWEB
DBSNMP
&nbsp;
12 rows selected.
&nbsp;
Elapsed: 00:00:03.57</pre></td></tr></table></div>

<p>Looks like it worked in this particular situation.  As for the other hint, _optimizer_mjc_enabled, which is TRUE by default also, there are references online that point to setting this parameter to FALSE as well in order to have the optimizer avoid cartesian merge joins as well.  MOS note 457058.1 outlines the use of this parameter.  We can try it here to test the theory:</p>
<p>We will set the _optimizer_cartesian_enabled parameter back to its default value first:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p241code74'); return false;">View Code</a> NONE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p24174"><td class="code" id="p241code74"><pre class="none" style="font-family:monospace;">SQL&amp;gt; alter session set &quot;_optimizer_cartesian_enabled&quot;=TRUE;
&nbsp;
Session altered.
&nbsp;
SQL&amp;gt; select n.ksppinm pd_name, c.ksppstvl pd_value
from x$ksppi n, x$ksppcv c
where n.indx=c.indx
and (
   lower(n.ksppinm) like lower('_optimizer_cartesian_enabled')
   or lower(n.ksppdesc) like lower('_optimizer_cartesian_enabled')
)
/ 
&nbsp;
PD_NAME                                  PD_VALUE
---------------------------------------- --------------------
_optimizer_cartesian_enabled             TRUE
&nbsp;
--Now we can set the _optimizer_mjc_enabled parameter:
&nbsp;
SQL&amp;gt; alter session set &quot;_optimizer_mjc_enabled&quot;=FALSE;
&nbsp;
Session altered.
&nbsp;
SQL&amp;gt; select n.ksppinm pd_name, c.ksppstvl pd_value
from x$ksppi n, x$ksppcv c
where n.indx=c.indx
and (
   lower(n.ksppinm) like lower('_optimizer_mjc_enabled')
   or lower(n.ksppdesc) like lower('_optimizer_mjc_enabled')
)
/  
&nbsp;
PD_NAME                                  PD_VALUE
---------------------------------------- --------------------
_optimizer_mjc_enabled                   FALSE
&nbsp;
--Now for the query:
&nbsp;
SQL&amp;gt; select distinct owner
from v$access;  
&nbsp;
&nbsp;
ERROR at line 1:
ORA-01013: user requested cancel of current operation
&nbsp;
Elapsed: 00:03:09.75</pre></td></tr></table></div>

<p>What does the explain plan look like?</p>
<p>Don&#8217;t forget to run the query again with the gather_plan_statistics hint</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p241code75'); return false;">View Code</a> NONE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p24175"><td class="code" id="p241code75"><pre class="none" style="font-family:monospace;">select /*+ gather_plan_statistics */ distinct owner from v$access;
&nbsp;
select * from table(dbms_xplan.display_cursor('&amp;amp;sql_id','&amp;amp;child_no','allstats'))
/
&nbsp;
Enter value for sql_id: dmfdcmvwkgfqh
Enter value for child_no: 0
old   1: select * from table(dbms_xplan.display_cursor('&amp;amp;sql_id','&amp;amp;child_no','allstats'))
new   1: select * from table(dbms_xplan.display_cursor('dmfdcmvwkgfqh','0','allstats'))
&nbsp;
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  dmfdcmvwkgfqh, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ distinct owner from v$access
&nbsp;
Plan hash value: 3850776806
&nbsp;
-------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                  | Name            | Starts | E-Rows | A-Rows |   A-Time   |  OMem |  1Mem |  O/1/M   |
-------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |                 |      1 |        |      0 |00:00:00.01 |       |       |          |
|   1 |  HASH UNIQUE               |                 |      1 |      1 |      0 |00:00:00.01 |   741K|   741K|          |
|   2 |   NESTED LOOPS             |                 |      1 |      1 |     32 |00:00:04.04 |       |       |          |
|   3 |    NESTED LOOPS            |                 |      1 |      1 |     32 |00:00:04.04 |       |       |          |
|   4 |     MERGE JOIN CARTESIAN   |                 |      1 |    100 |   2291K|00:00:11.60 |       |       |          |
|*  5 |      FIXED TABLE FULL      | X$KSUSE         |      1 |      1 |     47 |00:00:00.01 |       |       |          |
|   6 |      BUFFER SORT           |                 |     47 |    100 |   2291K|00:00:08.38 |  3454K|   810K|     1/0/0|
|   7 |       FIXED TABLE FULL     | X$KGLDP         |      1 |    100 |  48886 |00:00:00.33 |       |       |          |
|*  8 |     FIXED TABLE FIXED INDEX| X$KGLLK (ind:1) |   2291K|      1 |     32 |00:01:13.38 |       |       |          |
|*  9 |    FIXED TABLE FIXED INDEX | X$KGLOB (ind:1) |     32 |      1 |     32 |00:00:00.01 |       |       |          |
-------------------------------------------------------------------------------------------------------------------------
&nbsp;
Predicate Information (identified by operation id):
---------------------------------------------------
&nbsp;
   5 - filter(&quot;S&quot;.&quot;INST_ID&quot;=USERENV('INSTANCE'))
   8 - filter((&quot;L&quot;.&quot;KGLLKUSE&quot;=&quot;S&quot;.&quot;ADDR&quot; AND &quot;L&quot;.&quot;KGLLKHDL&quot;=&quot;D&quot;.&quot;KGLHDADR&quot; AND &quot;L&quot;.&quot;KGLNAHSH&quot;=&quot;D&quot;.&quot;KGLNAHSH&quot;))
   9 - filter((&quot;O&quot;.&quot;KGLNAHSH&quot;=&quot;D&quot;.&quot;KGLRFHSH&quot; AND &quot;O&quot;.&quot;KGLHDADR&quot;=&quot;D&quot;.&quot;KGLRFHDL&quot;))
&nbsp;
28 rows selected.</pre></td></tr></table></div>

<p>It looks like the _optimizer_mjc_enabled parameter is not as affective in stopping the merge join cartesian operations as the _optimizer_cartesian_enabled parameter.</p>
<p>I would suggest enabling hints like this at the session level first to verify behavior against certain operations, then only enabling them for those operations. In my opinion, disabling merge join cartesian operations altogether would introduce behavior into a system whose consequences should be thoroughly tested beforehand.  Don&#8217;t get caught up in the &#8216;silver bullet&#8217; mentality when you try to apply a fix for one process against the entire system thinking it is a cure for all your database woes.</p>
<p>So now that we have a work around, we don&#8217;t need to worry about this situation anymore, right?  I would think that most of us want to fix the underlying issue and not &#8216;patch it and go&#8217;.  I want to know what happens if we do generate the new fixed table statistics we want.  Fortunately, I was lucky enough to have a test system where I was able to recreate this problem.  Here is what happened when fixed table statistics were generated:</p>
<p>First, make sure the hints we were working with have been set back to their default values.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p241code76'); return false;">View Code</a> NONE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p24176"><td class="code" id="p241code76"><pre class="none" style="font-family:monospace;">SQL&amp;gt; alter session set &quot;_optimizer_cartesian_enabled&quot;=TRUE;
&nbsp;
Session altered.
&nbsp;
SQL&amp;gt; alter session set &quot;_optimizer_mjc_enabled&quot;=TRUE;
&nbsp;
Session altered.
&nbsp;
SQL&amp;gt; select n.ksppinm pd_name, c.ksppstvl pd_value
from x$ksppi n, x$ksppcv c
where n.indx=c.indx
and (
   lower(n.ksppinm) like lower('_optimizer%enabled')
   or lower(n.ksppdesc) like lower('_optimizer%enabled')
)
/
&nbsp;
PD_NAME                                  PD_VALUE
---------------------------------------- --------------------
_optimizer_mjc_enabled                   TRUE
_optimizer_cartesian_enabled             TRUE</pre></td></tr></table></div>

<p>Note &#8211; There were more records in the actual output, but I abreviated the output<br />
to avoid confusion.</p>
<p>Now generate new fixed table statistics:</p>
<p>********************************************************************************</p>
<p>NOTE &#8211; THERE IS A POSSIBILITY OF HITTING A BUG NATIVE TO 11.2.0.1 WHEN TRYING TO GENENERATE FIXED OBJECT STATISTICS.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p241code77'); return false;">View Code</a> NONE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p24177"><td class="code" id="p241code77"><pre class="none" style="font-family:monospace;">SQL&amp;gt; exec dbms_stats.gather_fixed_objects_stats;
BEGIN dbms_stats.gather_fixed_objects_stats; END;
&nbsp;
*
ERROR at line 1:
ORA-20011: Approximate NDV failed: ORA-00439: feature not enabled: Data Guard
Broker
ORA-06512: at “SYS.DBMS_STATS”, line 20508
ORA-06512: at “SYS.DBMS_STATS”, line 20951
ORA-06512: at “SYS.DBMS_STATS”, line 21498
ORA-06512: at line 1</pre></td></tr></table></div>

<p>MOS note 9471411.8 outlines bug 9471411, which is the cause of this error.<br />
This bug is fixed in 11.2.0.2, 11.2.0.1.3, and 12.1 (future release).</p>
<p>If by chance you encounter this bug, there will still be fixed objects that<br />
will have stats generated.  Retry the query after the bug is encountered.</p>
<p>********************************************************************************</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p241code78'); return false;">View Code</a> NONE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p24178"><td class="code" id="p241code78"><pre class="none" style="font-family:monospace;">SQL&amp;gt; exec dbms_stats.gather_fixed_objects_stats;
BEGIN dbms_stats.gather_fixed_objects_stats; END;
&nbsp;
PL/SQL procedure successfully completed.
&nbsp;
SQL&amp;gt; select count(*) from sys.tab_stats$;
&nbsp;
  COUNT(*)
----------
       798
&nbsp;
Elapsed: 00:00:00.01</pre></td></tr></table></div>

<p>Now let&#8217;s flush the old SQL out of the shared pool to ensure we get fresh explain plans:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p241code79'); return false;">View Code</a> NONE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p24179"><td class="code" id="p241code79"><pre class="none" style="font-family:monospace;">SQL&amp;gt; alter system flush shared_pool;
&nbsp;
System altered.
&nbsp;
Elapsed: 00:00:03.38
&nbsp;
SQL&amp;gt; select distinct owner
  2  from v$access;
&nbsp;
OWNER
----------------------------------------------------------------
SYSTEM
PUBLIC
SYS
TKCSOWNER
SUPRKRON
0
&nbsp;
6 rows selected.
&nbsp;
Elapsed: 00:00:00.28</pre></td></tr></table></div>

<p>This is what we should have been getting in terms of performance from the beginning.</p>
<p>What does the explain plan say?</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p241code80'); return false;">View Code</a> NONE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p24180"><td class="code" id="p241code80"><pre class="none" style="font-family:monospace;">select /*+ gather_plan_statistics */ distinct owner from v$access;
&nbsp;
select * from table(dbms_xplan.display_cursor('&amp;amp;sql_id','&amp;amp;child_no','allstats'))
/
&nbsp;
Enter value for sql_id: dmfdcmvwkgfqh
Enter value for child_no: 0
old   1: select * from table(dbms_xplan.display_cursor('&amp;amp;sql_id','&amp;amp;child_no','allstats'))
new   1: select * from table(dbms_xplan.display_cursor('dmfdcmvwkgfqh','0','allstats'))
&nbsp;
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  dmfdcmvwkgfqh, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ distinct owner from v$access
&nbsp;
Plan hash value: 174934893
&nbsp;
-------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                  | Name            | Starts | E-Rows | A-Rows |   A-Time   |  OMem |  1Mem |  O/1/M   |
-------------------------------------------------------------------------------------------------------------------------
|   1 |  HASH UNIQUE               |                 |      1 |     40 |      6 |00:00:00.44 |  1207K|  1207K|     1/0/0|
|   2 |   NESTED LOOPS             |                 |      1 |   2327 |    500 |00:00:00.39 |       |       |          |
|   3 |    NESTED LOOPS            |                 |      1 |   2327 |    500 |00:00:00.34 |       |       |          |
|   4 |     HASH JOIN              |                 |      1 |   2327 |   2400 |00:00:00.26 |  1236K|  1236K|     1/0/0|
|   5 |      FIXED TABLE FULL      | X$KSUSE         |      1 |   1105 |   1105 |00:00:00.01 |       |       |          |
|   6 |      FIXED TABLE FULL      | X$KGLLK         |      1 |   2327 |   2400 |00:00:00.02 |       |       |          |
|   7 |     FIXED TABLE FIXED INDEX| X$KGLDP (ind:1) |   2400 |      1 |    500 |00:00:00.08 |       |       |          |
|   8 |    FIXED TABLE FIXED INDEX | X$KGLOB (ind:1) |    500 |      1 |    500 |00:00:00.04 |       |       |          |
-------------------------------------------------------------------------------------------------------------------------
&nbsp;
19 rows selected.</pre></td></tr></table></div>

<p>No merge join cartesian operations and the number of estimated rows (E-Rows) is a lot closer to the number of actual rows (A-Rows) than the previous optimizer-based plan.</p>
<p>Summary</p>
<p>We have seen that fixed object statistics are important to the optimizer.  Fixed objects are used in all kinds of recursive statements that can affect user performance, so enabling the optimizer to access them effectively is a benefit that can outweigh most any possible risk of gathering them in a database where they do not exist at all.</p>
<p>When considering jobs to generate statistics, don&#8217;t forget the fixed tables in this plan.  As these objects change less frequently than most objects in a production system, once a month should be a sufficient starting point.  Of course, you wouls want to re-gather these statistics when the load caracteristics of your system change, after patches, after hardware upgrades or migrations.  Think about gathering statistics on your dictionary objects (dbms_stats.gather_dictionary_stats) as well when considering the fixed object stats. Once a month should be a sufficient starting point as well for these statistics.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.enkitec.com/2011/04/fixed-object-statistics-benefits-in-11g/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Silently removing an old ORACLE_HOME</title>
		<link>http://blog.enkitec.com/2011/04/silently-removing-an-old-oracle_home/</link>
		<comments>http://blog.enkitec.com/2011/04/silently-removing-an-old-oracle_home/#comments</comments>
		<pubDate>Thu, 28 Apr 2011 13:38:02 +0000</pubDate>
		<dc:creator>Jon Adams</dc:creator>
				<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://blog.enkitec.com/?p=236</guid>
		<description><![CDATA[During a database upgrade, the majority of the focus is on the pre-requisites for the upgrade, the upgrade itself, and post-upgrade tasks. Little focus is given to the downgrade process and none at all to the removal of the Oracle software used by the previous database version. I was at a new client site the [...]]]></description>
			<content:encoded><![CDATA[<p>During a database upgrade, the majority of the focus is on the pre-requisites for the upgrade, the upgrade itself, and post-upgrade tasks.  Little focus is given to the downgrade process and none at all to the removal of the Oracle software used by the previous database version. I was at a new client site the other day and they were running tight on space in one particular file system.  The file system contained the Oracle software for versions 8i and 10g.  The single database had been upgraded from the 8i to the 10g version some years ago, but the 8i software had never been removed.  It was my first time working with this environment, so I wanted to make sure I did not remove anything vital when removing the old Oracle software.</p>
<p>Was the tightening of space sudden or gradual?</p>
<p><span id="more-236"></span></p>
<p>The answer was that the space was being eaten up gradually.  At that point, I reviewed the ‘usual suspects’ when looking to clear space from an Oracle database server.  These include:</p>
<p>•	Overly-large alert.log or listener.log files<br />
•	Archived copies of the alert.log or listener.log files (seen it done).<br />
•	Excessive trace files or core dumps (this would also prompt me to look for errors in the alert.log).<br />
•	Excessive .aud files under $ORACLE_HOME/rdbms/audit.<br />
•	Executing ‘sudo du -ak | sort –nr &gt; ./out.log’ in a Unix environment at the top of the file system in question will generate a list of space hogs in a file call out.log in the current directory.  You may find some old exports to remove.  If removal is not an option, at least compress them.</p>
<p>Once the usual suspects were covered, space was still tight, so the removal of the old 8i Oracle software seemed a good way to free up some space.</p>
<p>I wanted to use the 10g Oracle Universal Installar (OUI) and the next problem I was facing was a lack of an X-window capability on the server and no one present to tell me if it was even configured.  From previous experience, setting up X-window capabilities is time-consuming and often frustrating; whether you are using Cygwin, VNCServer, or another piece of client software.<br />
Wouldn’t it be good to be able to run one command silently and have Oracle remove the old home without having to go through the graphical, interactive OUI?  The OUI has had a silent method of execution ever since OUI first appeared in version 8i.  It can also perform silent de-installs.  You just have to perform a few pre-checks before using this method.</p>
<p>Do you have a newer version of OUI to work with?</p>
<p>In this case I did as there was a newer 10g installation in the same file system.  If not, I could have used a version of OUI from the 10g distribution media, or downloaded a copy of the distribution media from Oracle Technet (http://www.oracle.com/technetwork/index.html). If I had to download a copy, I would probably download the latest version available for my platform.</p>
<p>What is the name and location of the Oracle home we want to remove?</p>
<p>The quickest way to determine this information is with the use of the opatch utility.  This utility is located under $ORACLE_HOME/OPatch.  You should use the highest version of the utility present on the system.  In my case, it was the one present under the 10g Oracle home.  If this utility is not present, the latest version can be downloaded from My Oracle Support (MOS), path number 6880880.  It is a compressed file that is designed to be decompressed directly into the ORACLE_HOME where you are going to install it.  It will replace the existing opatch utility if it exists.<br />
Execute ‘opatch lsinventory –all’ to get a listing similar to this one:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p236code82'); return false;">View Code</a> NONE</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p23682"><td class="code" id="p236code82"><pre class="none" style="font-family:monospace;">opatch lsinventory -all
Invoking OPatch 10.2.0.2.2
&nbsp;
Oracle interim Patch Installer version 10.2.0.2.2
Copyright (c) 2005, Oracle Corporation.  All rights reserved..
&nbsp;
Oracle Home       : /u01/app/oracle/product/10.2.0
Central Inventory : /u01/app/oracle/oraInventory
   from           : /var/opt/oracle/oraInst.loc
OPatch version    : 10.2.0.2.2
OUI version       : 10.2.0.1.0
OUI location      : /u01/app/oracle/product/10.2.0/oui
Log file location : /u01/app/oracle/product/10.2.0/cfgtoollogs/opatch/opatch2011-03-22_19-50-00PM.log
&nbsp;
Lsinventory Output file location : /u01/app/oracle/product/10.2.0/cfgtoollogs/opatch/lsinv/lsinventory2011-03-22_19-50-00PM.txt
&nbsp;
--------------------------------------------------------------------------------
List of Oracle Homes:
  Name          Location
   OraDb10g_home1         /u01/app/oracle/product/10.2.0.4ee/db_1
   agent10g         	/u01/app/oracle/product/agent10g
   Oracle10gR1         /u01/app/oracle/product/10.1.0se
   EKUASDV         /u01/app/oracle/product/10.2.0
   EKUASQA         /u01/app/oracle/product/10.2.0
&nbsp;
Installed Top-level Products (2):
&nbsp;
Oracle Database 10g                                                  10.2.0.1.0
Oracle Database 10g Products                                         10.2.0.1.0
There are 2 products installed in this Oracle Home.
&nbsp;
Interim patches (1) :
&nbsp;
Patch  4375798      : applied on Wed Sep 12 18:54:13 GMT 2007
   Created on 31 Oct 2005, 23:17:10 hrs US/Pacific
   Bugs fixed:
     4375798
--------------------------------------------------------------------------------
&nbsp;
OPatch succeeded.</pre></td></tr></table></div>

<p>As you can see, all the Oracle homes present on the system are listed, including the names and locations.  Please note that this listing was not from the actual system I was working on and the names have been changed to protect the parties involved.<br />
Is this ORACLE_HOME still being used?</p>
<p>After making sure that the entry for the old Oracle home is either gone or commented out of the oratab file, there are several commands you can use to find out if any active processes are using files out of the old ORACLE_HOME.  The simplest is ‘ps –ef | grep ’ where  is the location of the old ORACLE_HOME.  To be absolutely sure, you can use the ‘lsof | grep ’, but it would probably require an OS account with root privileges.  If the lsof command does not return any values, then it is probably safe to remove the old Oracle home.</p>
<p>Removing the ORACLE_HOME</p>
<p>After going through the previous considerations and finding out the name and location of the ORACLE_HOME I want to remove, I can use the OUI to remove it.  The OUI can be executed from the $ORACLE_HOME/oui/bin directory or from the distribution media.  The syntax I need is:</p>
<p>/runInstaller -deinstall -silent REMOVE_HOMES={&#8220;/app/oracle/OraHome_1&#8243;}</p>
<p>The REMOVE_HOMES argument requires the exact path of the ORACLE_HOME to be removed.  If the actual directory where the software is located is still present after running the OUI command above, you can safely remove it with OS commands.</p>
<p>Summary<br />
In all honesty, I had previously ignored the silent aspect of the OUI to perform installs (and de-installs).  I guess I was addicted to the attractive Java-type OUI interface with its active progress bar and animations.  The silent method of OUI does come in handy for performing multiple installations on several of the same platforms, such as when you deploy OEM agent software.  Bottom line is that it might be beneficial to take a quick look at other methods of execution of your most common tools.</p>
<p>Addendum<br />
The runInstaller -deinstall option is not available in 11.2.0.2, but was tested fine in 11.2.0.1.  The test consisted of using the 11.2.0.1 runInstaller to remove a previous installation of the 11.2.0.2 software where the 11.2.0.2 Oracle home had been registered in the central inventory, but the 11.2.0.2 binaries had been removed.  It was necessary to remove the home before proceeding with a new installation of the 11.2.0.2 software.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.enkitec.com/2011/04/silently-removing-an-old-oracle_home/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

