<?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>PL/Scope Archives - Philipp Salvisberg&#039;s Blog</title>
	<atom:link href="https://www.salvis.com/blog/tag/plscope/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.salvis.com/blog/tag/plscope/</link>
	<description>Database-centric development</description>
	<lastBuildDate>Wed, 08 Nov 2023 19:38:06 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://www.salvis.com/blog/wp-content/uploads/2014/04/favicon.png</url>
	<title>PL/Scope Archives - Philipp Salvisberg&#039;s Blog</title>
	<link>https://www.salvis.com/blog/tag/plscope/</link>
	<width>32</width>
	<height>32</height>
</image> 
<atom:link rel="hub" href="https://pubsubhubbub.appspot.com"/>
<atom:link rel="hub" href="https://pubsubhubbub.superfeedr.com"/>
<atom:link rel="hub" href="https://websubhub.com/hub"/>
<atom:link rel="self" href="https://www.salvis.com/blog/tag/plscope/feed/"/>
	<item>
		<title>plscope-utils for SQL Developer 1.0 &#8211; What&#8217;s New?</title>
		<link>https://www.salvis.com/blog/2022/07/17/plscope-utils-for-sql-developer-1-0-whats-new/</link>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Sun, 17 Jul 2022 12:21:08 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Code Analysis]]></category>
		<category><![CDATA[PL/Scope]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Developer]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=11536</guid>

					<description><![CDATA[<p>Introduction PL/Scope is an SDK for source code analysis. It is available since Oracle Database 11g Release 1 and has been significantly improved in 12c Release 2. plscope-utils for SQL Developer is a SQL Developer extension that simplifies the compilation with PL/Scope, visualizes PL/Scope information under a PL/Scope node in the Connections<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2022/07/17/plscope-utils-for-sql-developer-1-0-whats-new/">plscope-utils for SQL Developer 1.0 &#8211; What&#8217;s New?</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Introduction</h2>



<p>PL/Scope is an SDK for source code analysis. It is available since Oracle Database 11g Release 1 and has been significantly improved in 12c Release 2.</p>



<p>plscope-utils for SQL Developer is a SQL Developer extension that simplifies the compilation with PL/Scope, visualizes PL/Scope information under a <code>PL/Scope</code> node in the Connections window and provides various source code analysis reports.</p>



<p>Follow <a href="https://github.com/PhilippSalvisberg/plscope-utils/tree/main/sqldev#user-content-installation">these instructions</a> for a fresh install or an update to the latest version of plscope-utils for SQL Developer.</p>



<h2 class="wp-block-heading">Updated Tree Structure</h2>



<p>The level for grouping primary and secondary object types was removed. This makes the the tree simpler. All object types can now be filtered. This is especially helpful for schemas with many objects. And there is an additional node for <code>Sequences</code>.</p>



<figure class="wp-block-image is-resized"><a href="https://www.salvis.com/blog/wp-content/uploads/2022/07/plscope_node.png"><img fetchpriority="high" decoding="async" width="536" height="688" src="https://www.salvis.com/blog/wp-content/uploads/2022/07/plscope_node.png" alt="PL/Scope node in SQL Developer's Connection window (plscope-utils)" class="wp-image-11540" style="width:268px" srcset="https://www.salvis.com/blog/wp-content/uploads/2022/07/plscope_node.png 536w, https://www.salvis.com/blog/wp-content/uploads/2022/07/plscope_node-234x300.png 234w, https://www.salvis.com/blog/wp-content/uploads/2022/07/plscope_node-114x146.png 114w, https://www.salvis.com/blog/wp-content/uploads/2022/07/plscope_node-39x50.png 39w, https://www.salvis.com/blog/wp-content/uploads/2022/07/plscope_node-58x75.png 58w, https://www.salvis.com/blog/wp-content/uploads/2022/07/plscope_node-1x1.png 1w" sizes="(max-width:767px) 480px, 536px" /></a></figure>



<h2 class="wp-block-heading">No more ORA-01436: CONNECT BY loop in user data</h2>



<p>Many queries are based on recursive structures. In some data constellations, an ORA-1436 error caused no result to be returned. The reasons for this were manifold. Due to wrongly fixed hierarchies or due to dependency loops in the Oracle data dictionary. However, incomplete hierarchies are now fixed without causing a loop and all hierarchical queries use the <a href="https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/SELECT.html#GUID-CFA006CA-6FF1-4972-821E-6996142A51C6__GUID-6EE9767D-C75F-4AD4-A949-F19F62434C51">cycle_clause</a> which detects loops, avoids such runtime errors and ensures a reasonable result even with loops in the underlying data.</p>



<h2 class="wp-block-heading">Concise Representation of Identifiers</h2>



<p>Romain Vassallo contributed a <a href="https://github.com/PhilippSalvisberg/plscope-utils/pull/38">pull request</a> for the <code>plscope_identifiers</code> view. He added a column <code>name_usage</code> to combine <code>name</code>, <code>type</code>, <code>usage</code> and <code>sql_id</code> in a single column with a left indent of two characters per level.</p>



<p>The <code>Identifiers</code> tab includes now a column <code>Name (Type, Usage)</code> with this nifty logic.</p>



<figure class="wp-block-image"><a href="https://www.salvis.com/blog/wp-content/uploads/2022/07/identifiers_editor_plscope_utils-1.png"><img decoding="async" width="3456" height="2154" src="https://www.salvis.com/blog/wp-content/uploads/2022/07/identifiers_editor_plscope_utils-1.png" alt="PL/Scope identifiers tab in SQL Developer (plscope-utils)" class="wp-image-11546" srcset="https://www.salvis.com/blog/wp-content/uploads/2022/07/identifiers_editor_plscope_utils-1.png 3456w, https://www.salvis.com/blog/wp-content/uploads/2022/07/identifiers_editor_plscope_utils-1-300x187.png 300w, https://www.salvis.com/blog/wp-content/uploads/2022/07/identifiers_editor_plscope_utils-1-1024x638.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2022/07/identifiers_editor_plscope_utils-1-768x479.png 768w, https://www.salvis.com/blog/wp-content/uploads/2022/07/identifiers_editor_plscope_utils-1-1536x957.png 1536w, https://www.salvis.com/blog/wp-content/uploads/2022/07/identifiers_editor_plscope_utils-1-2048x1276.png 2048w, https://www.salvis.com/blog/wp-content/uploads/2022/07/identifiers_editor_plscope_utils-1-234x146.png 234w, https://www.salvis.com/blog/wp-content/uploads/2022/07/identifiers_editor_plscope_utils-1-50x31.png 50w, https://www.salvis.com/blog/wp-content/uploads/2022/07/identifiers_editor_plscope_utils-1-120x75.png 120w, https://www.salvis.com/blog/wp-content/uploads/2022/07/identifiers_editor_plscope_utils-1-1x1.png 1w" sizes="(max-width:767px) 480px, (max-width:3456px) 100vw, 3456px" /></a></figure>



<h2 class="wp-block-heading">That&#8217;s all?</h2>



<p>Yes, regarding plscope-utils for SQL Developer. However, there are optional <a href="https://github.com/PhilippSalvisberg/plscope-utils/blob/main/database/README.md">PL/SQL packages and views</a> for static code analysis based on PL/Scope. Optional means, the SQL Developer extension does not need them. But if you have to analyze code in your Oracle database they can be a good starting point for your work.</p>



<h2 class="wp-block-heading">Related Information</h2>



<p>If you are interested in PL/Scope, the following links may be of interest:</p>



<ul class="wp-block-list">
<li><a href="https://github.com/PhilippSalvisberg/plscope-utils/releases">plscope-utils releases</a></li>



<li><a href="https://github.com/PhilippSalvisberg/plscope-utils">plscope-utils on Github (Core Database Objects and SQL Developer Extension)</a></li>



<li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/19/adfns/plscope.html#GUID-24109CB5-7BB9-48B2-AD7A-39458AA13C0C">Oracle Database Development Guide 19c &#8211; Using PL/Scope</a></li>



<li><a href="https://www.salvis.com/blog/2017/10/15/entity-relationship-model-for-plscope/">Entity Relationship Model for PL/Scope</a></li>



<li><a href="https://www.salvis.com/blog/2017/10/14/limitations-of-plscope-and-how-to-deal-with-them/">Limitations of PL/Scope and How to Deal with Them</a></li>
</ul>
<p>The post <a href="https://www.salvis.com/blog/2022/07/17/plscope-utils-for-sql-developer-1-0-whats-new/">plscope-utils for SQL Developer 1.0 &#8211; What&#8217;s New?</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Is Your Application SmartDB?</title>
		<link>https://www.salvis.com/blog/2018/07/18/is-your-application-smartdb/</link>
					<comments>https://www.salvis.com/blog/2018/07/18/is-your-application-smartdb/#comments</comments>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Wed, 18 Jul 2018 17:52:54 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[PinkDB]]></category>
		<category><![CDATA[PL/Scope]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[SmartDB]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Injection]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=8527</guid>

					<description><![CDATA[<p>I recently had a few discussions regarding the Smart Database Paradigm (SmartDB) with long-standing customers, new customers, partners, competitors and colleagues. Some people think that using APEX and PL/SQL in their database application is SmartDB. But it is not that simple.&#160;Bryn Llewelyn defined the term &#8220;Smart Database Paradigm&#8221; (SmartDB) in his talk&#160;Guarding<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2018/07/18/is-your-application-smartdb/">Is Your Application SmartDB?</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>I recently had a few discussions regarding the Smart Database Paradigm (SmartDB) with long-standing customers, new customers, partners, competitors and colleagues. Some people think that using APEX and PL/SQL in their database application is SmartDB. But it is not that simple.&nbsp;Bryn Llewelyn defined the term &#8220;Smart Database Paradigm&#8221; (SmartDB) in his talk&nbsp;<a href="https://community.oracle.com/servlet/JiveServlet/previewBody/1018915-102-1-164853/Guarding_Your_Data_Behind_a_Hard_Shell_Plsql_API.pdf">Guarding your data behind a hard shell PL/SQL API</a>. Based on his definition a SmartDB application must have the following five properties:</p>



<ol class="wp-block-list">
<li><a href="#property_1">The connect user does not own database objects</a></li>



<li><a href="#property_2">The connect user can execute PL/SQL API units only</a></li>



<li><a href="#property_3">PL/SQL API units handle transactions</a></li>



<li><a href="#property_4">SQL statements are written by human hand</a></li>



<li><a href="#property_5">SQL statements exploit the full power of set-based SQL</a></li>
</ol>



<p>These five properties are not a set of recommendations. They are the bare minimum. Either your application has these properties or not. It&#8217;s binary. There is (almost) no room for interpretation. Here&#8217;s an excerpt of a longer Twitter thread, making my and especially Bryn Llewelyn&#8217;s view a bit clearer.</p>


<div class="jq-tabs tabs_wrapper tabs_horizontal"><ul><li><a href="#tab-69d58e4352595-1">My tweet</a></li><li><a href="#tab-69d58e4352595-2">Bryn's answer 1/3</a></li><li><a href="#tab-69d58e4352595-3">Bryn's answer 2/3</a></li><li><a href="#tab-69d58e4352595-4">Bryn's answer 3/3</a></li></ul><div id="tab-69d58e4352595-1" ></p>
<p><a href="https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_1.png"><img decoding="async" class="alignnone wp-image-8555" src="https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_1.png" alt="" width="452" height="350" srcset="https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_1.png 602w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_1-300x232.png 300w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_1-189x146.png 189w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_1-50x39.png 50w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_1-97x75.png 97w" sizes="(max-width:767px) 452px, 452px" /></a></p>
<p></div><div id="tab-69d58e4352595-2" ></p>
<p><a href="https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_2.png"><img loading="lazy" decoding="async" class="alignnone wp-image-8556" src="https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_2.png" alt="" width="449" height="448" srcset="https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_2.png 599w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_2-150x150.png 150w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_2-300x300.png 300w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_2-146x146.png 146w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_2-50x50.png 50w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_2-75x75.png 75w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_2-85x85.png 85w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_2-80x80.png 80w" sizes="auto, (max-width:767px) 449px, 449px" /></a></p>
<p></div><div id="tab-69d58e4352595-3" ></p>
<p><a href="https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_3.png"><img loading="lazy" decoding="async" class="alignnone wp-image-8557" src="https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_3.png" alt="" width="452" height="188" srcset="https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_3.png 602w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_3-300x125.png 300w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_3-260x108.png 260w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_3-50x21.png 50w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_3-150x63.png 150w" sizes="auto, (max-width:767px) 452px, 452px" /></a></p>
<p></div><div id="tab-69d58e4352595-4" ></p>
<p><a href="https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_4.png"><img loading="lazy" decoding="async" class="alignnone wp-image-8558" src="https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_4.png" alt="" width="448" height="618" srcset="https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_4.png 597w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_4-217x300.png 217w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_4-106x146.png 106w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_4-36x50.png 36w, https://www.salvis.com/blog/wp-content/uploads/2018/07/smartdb_twitter_4-54x75.png 54w" sizes="auto, (max-width:767px) 448px, 448px" /></a></p>
<p></div></div>



<p>In this blog post I show how to check the compliance with the first three SmartDB properties by querying the Oracle data dictionary. The remaining two SmartDB properties have to be evaluated manually using reviews. The goal is to show that some of these properties are easily not followed (for good reasons) and that makes your database-centric application something else than SmartDB (but not necessarily a <a href="https://en.wikipedia.org/wiki/Curate%27s_egg">curate&#8217;s egg</a>).</p>



<p>In <a href="https://www.salvis.com/blog/2017/12/17/how-to-prove-that-your-smartdb-app-is-secured-against-sql-injection-attacks/">How to Prove That Your SmartDB App Is Secure</a>&nbsp;I&#8217;ve crafted a good, a bad and an ugly demo application. I installed these applications using <a href="https://gist.github.com/PhilippSalvisberg/052b1321b0207bd71f1f1b44eb03a8fc#file-install_demo_apps-sql">this script</a>&nbsp;in my Oracle Database 18c instance.</p>



<p>The anonymous PL/SQL block and the SQL queries in this blog post require DBA privileges. The required minimum database version is mentioned in the title of the code block, e.g. (&gt;=9.2), (&gt;=12.1) or (&gt;=12.2).</p>



<p>Now let&#8217;s look at the five SmartDB properties.</p>



<h2 class="wp-block-heading"><a name="property_1"></a>1. The connect user does not own database objects</h2>



<p>The connect user is used by application components outside of the database to interact with the database. It is configured for example in the connection pool of the middle-tier application.</p>



<p>The connect user must access only the APIs of the underlying database applications and therefore does not need own database objects.</p>



<p>Checking the compliance of this property is simple.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Check SmartDB property 1: query (>=9.2)</span><span role="button" tabindex="0" data-code="SELECT username
  FROM dba_users
 WHERE username NOT IN (
         SELECT owner
           FROM dba_objects
       )
 ORDER BY username;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_users</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> username </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span></span>
<span class="line"><span style="color: #D4D4D4">           </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_objects</span></span>
<span class="line"><span style="color: #D4D4D4">       )</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">ORDER BY</span><span style="color: #D4D4D4"> username;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Check SmartDB property 1: result (complying connect users)</span><span role="button" tabindex="0" data-code="USERNAME                
------------------------
ANONYMOUS
APEX_INSTANCE_ADMIN_USER
APEX_PUBLIC_USER
APEX_REST_PUBLIC_USER
DIP
GGSYS
GSMCATUSER
GSMUSER
MDDATA
ORDS_PUBLIC_USER
SYS$UMF
SYSBACKUP
SYSDG
SYSKM
SYSRAC
THE_BAD_USER
THE_GOOD_USER
THE_UGLY_USER
XS$NULL

19 rows selected." style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">USERNAME                </span></span>
<span class="line"><span style="color: #D4D4D4">------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">ANONYMOUS</span></span>
<span class="line"><span style="color: #D4D4D4">APEX_INSTANCE_ADMIN_USER</span></span>
<span class="line"><span style="color: #D4D4D4">APEX_PUBLIC_USER</span></span>
<span class="line"><span style="color: #D4D4D4">APEX_REST_PUBLIC_USER</span></span>
<span class="line"><span style="color: #D4D4D4">DIP</span></span>
<span class="line"><span style="color: #D4D4D4">GGSYS</span></span>
<span class="line"><span style="color: #D4D4D4">GSMCATUSER</span></span>
<span class="line"><span style="color: #D4D4D4">GSMUSER</span></span>
<span class="line"><span style="color: #D4D4D4">MDDATA</span></span>
<span class="line"><span style="color: #D4D4D4">ORDS_PUBLIC_USER</span></span>
<span class="line"><span style="color: #D4D4D4">SYS$UMF</span></span>
<span class="line"><span style="color: #D4D4D4">SYSBACKUP</span></span>
<span class="line"><span style="color: #D4D4D4">SYSDG</span></span>
<span class="line"><span style="color: #D4D4D4">SYSKM</span></span>
<span class="line"><span style="color: #D4D4D4">SYSRAC</span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_USER</span></span>
<span class="line"><span style="color: #D4D4D4">THE_GOOD_USER</span></span>
<span class="line"><span style="color: #D4D4D4">THE_UGLY_USER</span></span>
<span class="line"><span style="color: #D4D4D4">XS$NULL</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">19 rows selected.</span></span></code></pre></div>



<p>If you are using a connect user that is not listed as a result, then your application is not SmartDB.</p>



<p>The result contains also users that do not have the <code>CREATE SESSION</code> privilege and therefore cannot be used as connect users. The queries to check SmartDB properties 2 and 3 will address this issue.</p>



<h2 class="wp-block-heading"><a name="property_2"></a>2. The connect user can execute PL/SQL API units only</h2>



<p>Database views and tables are guarded behind a hard shell PL/SQL API. Only the following database objects may be part of the API:</p>



<ul class="wp-block-list">
<li>Packages</li>



<li>Types</li>



<li>Functions</li>



<li>Procedures</li>
</ul>



<p>So we just have to check if the connect user has access to objects with the predicate <code>object_type NOT IN ('PACKAGE', 'TYPE', 'FUNCTION', 'PROCEDURE')</code>, right? Yes, but the result would not be helpful. Why? Because every user with just the <code>CREATE SESSION</code> privilege has access to some thousand tables and views via the <code>PUBLIC</code> role. For example <code>DUAL</code>, <code>ALL_VIEWS</code> or&nbsp;<code>NLS_SESSION_PARAMETERS</code>. Strictly speaking, it is not possible to create an Oracle user that can execute PL/SQL units only. Some might argue that this alone makes SmartDB applications a fantasy. However, I&#8217;m not in that camp. I think we just have to&nbsp;focus on our own objects and exclude all Oracle-maintained users along with some common utility users from the analysis.</p>



<p>Furthermore,&nbsp;the connect user should only have the <code>CONNECT</code> role (no more and no less). This way we ensure/know that no access is granted to internal objects via <code>ANY</code> privileges.</p>



<p>For this check, we can reuse the query for rule 1 from my previous blog post <a href="https://www.salvis.com/blog/2017/12/17/how-to-prove-that-your-smartdb-app-is-secured-against-sql-injection-attacks/">How to Prove That Your SmartDB App Is Secure</a>.</p>


<div class="accordion"><div class="mfn-acc accordion_wrapper  toggle"><br />
<div class="question"><div class="title"><i class="icon-plus acc-icon-plus" aria-hidden="true"></i><i class="icon-minus acc-icon-minus" aria-hidden="true"></i>Query to check SmartDB property 2</div><div class="answer"></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(3 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Check SmartDB property 2: query (>=12.1)</span><span role="button" tabindex="0" data-code="WITH
   -- roles as recursive structure
   role_base AS (
      -- roles without parent (=roots)
      SELECT r.role, NULL AS parent_role
        FROM dba_roles r
       WHERE r.role NOT IN (
                SELECT p.granted_role
                  FROM role_role_privs p
             )
      UNION ALL
      -- roles with parent (=children)
      SELECT granted_role AS role, role AS parent_role
        FROM role_role_privs
   ),
   -- roles tree, calculate role_path for every hierarchy level
   role_tree AS (
      SELECT role,
             parent_role,
             sys_connect_by_path(ROLE, '/') AS role_path
        FROM role_base
      CONNECT BY PRIOR role = parent_role
   ),
   -- roles graph, child added to all ancestors including self
   -- allows simple join to parent_role to find all descendants
   role_graph AS (
      SELECT DISTINCT
             role,
             regexp_substr(role_path, '(/)(\w+)', 1, 1, 'i', 2) AS parent_role
        FROM role_tree
   ),
   -- application users in scope of the analysis
   -- other users are treated as if they were not installed
   app_user AS (
      SELECT username
        FROM dba_users
       WHERE oracle_maintained = 'N' -- SYS, SYSTEM, SYSAUX, ...
         AND username NOT IN ('FTLDB', 'PLSCOPE', 'UT3')
   ),
   -- user system privileges
   sys_priv AS (
      -- system privileges granted directly to users
      SELECT u.username, p.privilege
        FROM dba_sys_privs p
        JOIN app_user u ON u.username = p.grantee
      UNION
      -- system privileges granted directly to PUBLIC
      SELECT u.username, p.privilege
        FROM dba_sys_privs p
       CROSS JOIN app_user u
       WHERE p.grantee = 'PUBLIC'
         AND p.privilege NOT IN (
                SELECT r.role
                  FROM dba_roles r
             )
      UNION
      -- system privileges granted to users via roles
      SELECT u.username, p.privilege
        FROM dba_role_privs r
        JOIN app_user u ON u.username = r.grantee
        JOIN role_graph g ON g.parent_role = r.granted_role
        JOIN dba_sys_privs p ON p.grantee = g.role
      UNION
      -- system privileges granted to PUBLIC via roles
      SELECT u.username, p.privilege
        FROM dba_role_privs r
        JOIN role_graph g ON g.parent_role = r.granted_role
        JOIN dba_sys_privs p ON p.grantee = g.role
        CROSS JOIN app_user u
       WHERE r.grantee = 'PUBLIC'
   ),
   -- user object privileges
   obj_priv AS (
      -- objects granted directly to users
      SELECT u.username, p.owner, p.type AS object_type, p.table_name AS object_name
        FROM dba_tab_privs p
        JOIN app_user u ON u.username = p.grantee
       WHERE p.owner IN (
                SELECT u2.username
                  FROM app_user u2
             )
      UNION
      -- objects granted to users via roles
      SELECT u.username, p.owner, p.type AS object_type, p.table_name AS object_name
        FROM dba_role_privs r
        JOIN app_user u ON u.username = r.grantee
        JOIN role_graph g ON g.parent_role = r.granted_role
        JOIN dba_tab_privs p ON p.grantee = g.role
       WHERE p.owner IN (
                SELECT u2.username
                  FROM app_user u2
             )
      -- objects granted to PUBLIC
      UNION
      SELECT u.username, p.owner, p.type AS object_type, p.table_name AS object_name
        FROM dba_tab_privs p
       CROSS JOIN app_user u
       WHERE p.owner IN (
                SELECT u2.username
                  FROM app_user u2
             )
         AND p.grantee = 'PUBLIC'
   ),
   -- issues if user is configured in the connection pool of a middle tier
   issues AS (
      -- privileges not part of CONNECT role
      SELECT username,
             'SYS' AS owner,
             'PRIVILEGE' AS object_type,
             privilege AS object_name,
             'Privilege is not part of the CONNECT role' AS issue
        FROM sys_priv
       WHERE privilege NOT IN ('CREATE SESSION', 'SET CONTAINER')
      -- access to non PL/SQL units
      UNION ALL
      SELECT username,
             owner,
             object_type,
             object_name,
             'Access to non-PL/SQL unit'
        FROM obj_priv
       WHERE object_type NOT IN ('PACKAGE', 'TYPE', 'FUNCTION', 'PROCEDURE')
      -- own objects
      UNION ALL
      SELECT u.username,
             o.owner,
             o.object_type,
             o.object_name,
             'Connect user must not own any object'
        FROM app_user u
        JOIN dba_objects o ON o.owner = u.username
      -- missing CREATE SESSION privilege
      UNION ALL
      SELECT u.username,
             'SYS',
             'PRIVILEGE',
             'CREATE SESSION',
             'Privilege is missing, but required'
        FROM app_user u
       WHERE u.username NOT IN (
                SELECT username
                  FROM sys_priv
                 WHERE privilege = 'CREATE SESSION' 
             )
   ),
   -- aggregate issues per user
   issue_aggr AS (
      SELECT u.username, COUNT(i.username) issue_count
        FROM app_user u
        LEFT JOIN issues i ON i.username = u.username
       GROUP BY u.username
   ),
   -- user summary (calculate is_smartdb_property_2_met)
   summary AS (
      SELECT username,
             CASE
                WHEN issue_count = 0 THEN
                   'YES'
                ELSE
                   'NO'
             END AS is_smartdb_property_2_met,
             issue_count
        FROM issue_aggr
       ORDER BY is_smartdb_property_2_met DESC, username
   )
-- main
SELECT * 
  FROM summary
 WHERE issue_count = 0;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">WITH</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- roles as recursive structure</span></span>
<span class="line"><span style="color: #D4D4D4">   role_base </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- roles without parent (=roots)</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> r.role, </span><span style="color: #569CD6">NULL</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> parent_role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_roles r</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> r.role </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> p.granted_role</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> role_role_privs p</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION ALL</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- roles with parent (=children)</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> granted_role </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">role</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> parent_role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> role_role_privs</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- roles tree, calculate role_path for every hierarchy level</span></span>
<span class="line"><span style="color: #D4D4D4">   role_tree </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             parent_role,</span></span>
<span class="line"><span style="color: #D4D4D4">             sys_connect_by_path(</span><span style="color: #569CD6">ROLE</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;/&#39;</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> role_path</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> role_base</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">CONNECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">BY</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PRIOR</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span><span style="color: #D4D4D4"> = parent_role</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- roles graph, child added to all ancestors including self</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- allows simple join to parent_role to find all descendants</span></span>
<span class="line"><span style="color: #D4D4D4">   role_graph </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT DISTINCT</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">role</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             regexp_substr(role_path, </span><span style="color: #CE9178">&#39;(/)(\w+)&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;i&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> parent_role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> role_tree</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- application users in scope of the analysis</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- other users are treated as if they were not installed</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   app_user </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_users</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> oracle_maintained = </span><span style="color: #CE9178">&#39;N&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #6A9955">-- SYS, SYSTEM, SYSAUX, ...</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> username </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;FTLDB&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PLSCOPE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;UT3&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- user system privileges</span></span>
<span class="line"><span style="color: #D4D4D4">   sys_priv </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- system privileges granted directly to users</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.privilege</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_sys_privs p</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = p.grantee</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- system privileges granted directly to PUBLIC</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.privilege</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_sys_privs p</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">CROSS JOIN</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> p.grantee = </span><span style="color: #CE9178">&#39;PUBLIC&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> p.privilege </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> r.role</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_roles r</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- system privileges granted to users via roles</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.privilege</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_role_privs r</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = r.grantee</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> role_graph g </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> g.parent_role = r.granted_role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> dba_sys_privs p </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> p.grantee = g.role</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- system privileges granted to PUBLIC via roles</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.privilege</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_role_privs r</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> role_graph g </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> g.parent_role = r.granted_role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> dba_sys_privs p </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> p.grantee = g.role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">CROSS JOIN</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> r.grantee = </span><span style="color: #CE9178">&#39;PUBLIC&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- user object privileges</span></span>
<span class="line"><span style="color: #D4D4D4">   obj_priv </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- objects granted directly to users</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.owner, p.type </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_type, p.table_name </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_name</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_tab_privs p</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = p.grantee</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> p.owner </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u2.username</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u2</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- objects granted to users via roles</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.owner, p.type </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_type, p.table_name </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_name</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_role_privs r</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = r.grantee</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> role_graph g </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> g.parent_role = r.granted_role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> dba_tab_privs p </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> p.grantee = g.role</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> p.owner </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u2.username</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u2</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- objects granted to PUBLIC</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.owner, p.type </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_type, p.table_name </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_name</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_tab_privs p</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">CROSS JOIN</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> p.owner </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u2.username</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u2</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> p.grantee = </span><span style="color: #CE9178">&#39;PUBLIC&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- issues if user is configured in the connection pool of a middle tier</span></span>
<span class="line"><span style="color: #D4D4D4">   issues </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- privileges not part of CONNECT role</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;SYS&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;PRIVILEGE&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_type,</span></span>
<span class="line"><span style="color: #D4D4D4">             privilege </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_name,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;Privilege is not part of the CONNECT role&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> issue</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> sys_priv</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> privilege </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;CREATE SESSION&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;SET CONTAINER&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- access to non PL/SQL units</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION ALL</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">             object_type,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">             object_name,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;Access to non-PL/SQL unit&#39;</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> obj_priv</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> object_type </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;PACKAGE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TYPE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;FUNCTION&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PROCEDURE&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- own objects</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION ALL</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username,</span></span>
<span class="line"><span style="color: #D4D4D4">             o.owner,</span></span>
<span class="line"><span style="color: #D4D4D4">             o.object_type,</span></span>
<span class="line"><span style="color: #D4D4D4">             o.object_name,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;Connect user must not own any object&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> dba_objects o </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> o.owner = u.username</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- missing CREATE SESSION privilege</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION ALL</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;SYS&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;PRIVILEGE&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;CREATE SESSION&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;Privilege is missing, but required&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> u.username </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> sys_priv</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> privilege = </span><span style="color: #CE9178">&#39;CREATE SESSION&#39;</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- aggregate issues per user</span></span>
<span class="line"><span style="color: #D4D4D4">   issue_aggr </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, </span><span style="color: #DCDCAA">COUNT</span><span style="color: #D4D4D4">(i.username) issue_count</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">LEFT JOIN</span><span style="color: #D4D4D4"> issues i </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> i.username = u.username</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">GROUP BY</span><span style="color: #D4D4D4"> u.username</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- user summary (calculate is_smartdb_property_2_met)</span></span>
<span class="line"><span style="color: #D4D4D4">   summary </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">CASE</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">WHEN</span><span style="color: #D4D4D4"> issue_count = </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #CE9178">&#39;YES&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">ELSE</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #CE9178">&#39;NO&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> is_smartdb_property_2_met,</span></span>
<span class="line"><span style="color: #D4D4D4">             issue_count</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> issue_aggr</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">ORDER BY</span><span style="color: #D4D4D4"> is_smartdb_property_2_met </span><span style="color: #569CD6">DESC</span><span style="color: #D4D4D4">, username</span></span>
<span class="line"><span style="color: #D4D4D4">   )</span></span>
<span class="line"><span style="color: #6A9955">-- main</span></span>
<span class="line"><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> * </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> summary</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> issue_count = </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">;</span></span></code></pre></div>


<p></div></div>
<br />
</div></div>




<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Check SmartDB property 2: result (complying connect users)</span><span role="button" tabindex="0" data-code="USERNAME                 IS_SMARTDB_PROPERTY_2_MET ISSUE_COUNT
------------------------ ------------------------- -----------
APEX_REST_PUBLIC_USER    YES                                 0
THE_BAD_USER             YES                                 0
THE_GOOD_USER            YES                                 0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">USERNAME                 IS_SMARTDB_PROPERTY_2_MET ISSUE_COUNT</span></span>
<span class="line"><span style="color: #D4D4D4">------------------------ ------------------------- -----------</span></span>
<span class="line"><span style="color: #D4D4D4">APEX_REST_PUBLIC_USER    YES                                 0</span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_USER             YES                                 0</span></span>
<span class="line"><span style="color: #D4D4D4">THE_GOOD_USER            YES                                 0</span></span></code></pre></div>



<p>If you are using a connect user that is not listed as a result, then your application is not SmartDB.</p>



<p>In this case, the <code>APEX_REST_PUBLIC_USER</code> is a false positive. The named subquery&nbsp; <code>app_user</code> excludes the&nbsp;<code>APEX_180100</code> user which grants various views and sequences to <code>PUBLIC</code>. Hence APEX 18.1 is not a SmartDB application.</p>



<h2 class="wp-block-heading"><a name="property_3"></a>3. PL/SQL API units handle transactions</h2>



<p>A SmartDB application holds the complete business logic in the database. A PL/SQL API call handles a transaction completely. The API must not contain units for partial transaction work. Such units may exist, but must not be part of the PL/SQL API exposed to the connect user.</p>



<p>For write operations a&nbsp;<code>COMMIT</code> is called on success and a <code>ROLLBACK</code> is called on failure at the end of the operation.</p>



<p>For read operations, the PL/SQL API is responsible for the read consistency.</p>



<p>Distributed transactions are supported via&nbsp;database links only. Other data sources cannot participate in the same database transaction. If this is a mandatory requirement, then SmartDB is the wrong approach. However, Oracle AQ can be a good alternative to propagate data consistently in upstream or downstream transactions.</p>



<p>To check if an application has this SmartDB property, we have to do something like this:</p>



<ul class="wp-block-list">
<li>Find all PL/SQL API units (as we&#8217;ve done for the <a href="#property_2">SmartDB property 2</a>).</li>



<li>Produce a call tree for PL/SQL API units. On the object level, this could be achieved by querying <code>DBA_DEPENDENCIES</code>. For a more accurate result on the sub-object level, PL/Scope could be used by querying&nbsp;<code>DBA_IDENTIFIERS</code>&nbsp;.</li>



<li>Find <code>INSERT</code>, <code>UPDATE</code>,&nbsp; <code>DELETE</code>, <code>MERGE</code>, <code>COMMIT</code> and&nbsp;<code>ROLLBACK</code> statements in PL/SQL units. Static statements can be found via PL/Scope in the <code>DBA_STATEMENTS</code> view. But executions in dynamic statements are a challenge, since the DML may be stored outside of the PL/SQL unit (e.g. in tables). It&#8217;s virtually impossible to get a complete result using static code analysis.</li>



<li>Bring these results together and check if DML statements are followed by a transaction control statement. This is another challenge. Without a parser (and some semantic analysis) it is not possible to find out if a statement is really executed (e.g. PL/Scope does not provide information about control structures).</li>
</ul>



<p>For this blog post, we use a naïve static code analysis approach. We analyze the object level and consider static SQL statements only. Furthermore, we assume that DML statements (INSERT, UPDATE,&nbsp; DELETE, MERGE) and transaction control statements (COMMIT,&nbsp;ROLLBACK) found in the call hierarchy are all executed and the transaction control statement is at the very end.</p>



<p>As long as the transaction control statements are not executed as dynamic SQL the result should be good enough. This means if the query produces no result for an application, then this is for sure not a SmartDB application, but if a result is produced, then this does not guarantee that the application is really following the rules and issuing a <code>COMMIT</code>&nbsp;or a <code>ROLLBACK</code>&nbsp;at the end of a write transaction.</p>


<div class="accordion"><div class="mfn-acc accordion_wrapper  toggle"><br />
<div class="question"><div class="title"><i class="icon-plus acc-icon-plus" aria-hidden="true"></i><i class="icon-minus acc-icon-minus" aria-hidden="true"></i>Compile all application users with PL/Scope</div><div class="answer"></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Prepare check SmartDB property 3: compile with PL/Scope (>=12.2)</span><span role="button" tabindex="0" data-code="SET SERVEROUTPUT ON SIZE UNLIMITED
DECLARE
   PROCEDURE exec_sql (in_sql_stmt IN VARCHAR2) IS
   BEGIN
      dbms_output.put_line('executing: ' || in_sql_stmt);
      EXECUTE IMMEDIATE in_sql_stmt;
   END exec_sql;
   --
   PROCEDURE enable_plscope IS
   BEGIN
      exec_sql(q'&#091;ALTER SESSION SET plscope_settings='IDENTIFIERS:ALL, STATEMENTS:ALL'&#093;');
   END enable_plscope;
   --
   PROCEDURE compile_private_synonyms(in_user IN VARCHAR2) IS
   BEGIN
      &lt;&lt;synonyms&gt;&gt;
      FOR r IN (
         SELECT synonym_name
           FROM dba_synonyms
          WHERE owner = in_user
      ) LOOP
         exec_sql('ALTER SYNONYM &quot;' || in_user || '&quot;.&quot;' || r.synonym_name || '&quot; COMPILE');
      END LOOP synonyms;
   END compile_private_synonyms;
   --
   PROCEDURE compile_public_synonyms(in_user IN VARCHAR2) IS
   BEGIN
      FOR r IN (
         SELECT synonym_name
           FROM dba_synonyms
          WHERE owner = 'PUBLIC'
            AND table_owner = in_user
      ) LOOP
         exec_sql('ALTER PUBLIC SYNONYM &quot;' || r.synonym_name || '&quot; COMPILE');
      END LOOP public_synonyms;
   END compile_public_synonyms;
   --
   PROCEDURE compile_types(in_user IN VARCHAR2) IS
      e_has_table_deps EXCEPTION;
      e_is_not_udt     EXCEPTION;
      e_compile_error  EXCEPTION;
      PRAGMA exception_init(e_has_table_deps, -2311);
      PRAGMA exception_init(e_is_not_udt, -22307);
      PRAGMA exception_init(e_compile_error, -24344);
   BEGIN
      &lt;&lt;types&gt;&gt;
      FOR r IN (
         SELECT o.object_type, o.object_name, count(d.name) AS priority 
           FROM dba_objects o
           LEFT JOIN dba_dependencies d
             ON d.owner = o.owner
                AND d.type = o.object_type
                AND d.name = o.object_name
          WHERE o.owner = in_user
            AND o.object_type in ('TYPE', 'TYPE BODY')
          GROUP BY o.object_type, o.object_name
          ORDER BY priority
      ) LOOP
         &lt;&lt;compile_type&gt;&gt;
         BEGIN
             IF r.object_type = 'TYPE' THEN
                exec_sql('ALTER TYPE &quot;' || in_user || '&quot;.&quot;' || r.object_name || '&quot; COMPILE');
             ELSE
                exec_sql('ALTER TYPE &quot;' || in_user || '&quot;.&quot;' || r.object_name || '&quot; COMPILE BODY');
             END IF;
         EXCEPTION
            WHEN e_has_table_deps OR e_is_not_udt OR e_compile_error THEN
               NULL;
         END compile_type;
      END LOOP types;
   END compile_types;
   --
   PROCEDURE compile_schema(in_user IN VARCHAR2) IS
   BEGIN
      -- synonyms and types are not covered by dbms_utility.compile_schema
      compile_private_synonyms(in_user);
      compile_public_synonyms(in_user);
      compile_types(in_user);
      dbms_utility.compile_schema(
         schema         =&gt; in_user,
         compile_all    =&gt; TRUE,
         reuse_settings =&gt; FALSE
      );
   END compile_schema;
BEGIN
   enable_plscope;
   &lt;&lt;app_user&gt;&gt;
   FOR r IN (
      SELECT username
        FROM dba_users
       WHERE oracle_maintained = 'N' 
         AND username NOT IN ('FTLDB', 'PLSCOPE', 'UT3')      
   ) LOOP
      compile_schema(r.username);
   END LOOP app_user;
END;
/" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">SET</span><span style="color: #D4D4D4"> SERVEROUTPUT </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> SIZE UNLIMITED</span></span>
<span class="line"><span style="color: #569CD6">DECLARE</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">exec_sql</span><span style="color: #D4D4D4"> (in_sql_stmt </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">dbms_output.</span><span style="color: #4EC9B0">put_line</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&#39;executing: &#39;</span><span style="color: #D4D4D4"> || in_sql_stmt);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">EXECUTE IMMEDIATE</span><span style="color: #D4D4D4"> in_sql_stmt;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> exec_sql;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">--</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">enable_plscope</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">      exec_sql(q</span><span style="color: #CE9178">&#39;[ALTER SESSION SET plscope_settings=&#39;</span><span style="color: #D4D4D4">IDENTIFIERS:</span><span style="color: #569CD6">ALL</span><span style="color: #D4D4D4">, STATEMENTS:</span><span style="color: #569CD6">ALL</span><span style="color: #CE9178">&#39;]&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> enable_plscope;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">--</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">compile_private_synonyms</span><span style="color: #D4D4D4">(in_user </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;&lt;synonyms&gt;&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">FOR</span><span style="color: #D4D4D4"> r </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> synonym_name</span></span>
<span class="line"><span style="color: #D4D4D4">           </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_synonyms</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> owner = in_user</span></span>
<span class="line"><span style="color: #D4D4D4">      ) </span><span style="color: #C586C0">LOOP</span></span>
<span class="line"><span style="color: #D4D4D4">         exec_sql(</span><span style="color: #CE9178">&#39;ALTER SYNONYM &quot;&#39;</span><span style="color: #D4D4D4"> || in_user || </span><span style="color: #CE9178">&#39;&quot;.&quot;&#39;</span><span style="color: #D4D4D4"> || r.synonym_name || </span><span style="color: #CE9178">&#39;&quot; COMPILE&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">END LOOP</span><span style="color: #D4D4D4"> synonyms;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> compile_private_synonyms;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">--</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">compile_public_synonyms</span><span style="color: #D4D4D4">(in_user </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">FOR</span><span style="color: #D4D4D4"> r </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> synonym_name</span></span>
<span class="line"><span style="color: #D4D4D4">           </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_synonyms</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> owner = </span><span style="color: #CE9178">&#39;PUBLIC&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> table_owner = in_user</span></span>
<span class="line"><span style="color: #D4D4D4">      ) </span><span style="color: #C586C0">LOOP</span></span>
<span class="line"><span style="color: #D4D4D4">         exec_sql(</span><span style="color: #CE9178">&#39;ALTER PUBLIC SYNONYM &quot;&#39;</span><span style="color: #D4D4D4"> || r.synonym_name || </span><span style="color: #CE9178">&#39;&quot; COMPILE&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">END LOOP</span><span style="color: #D4D4D4"> public_synonyms;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> compile_public_synonyms;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">--</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">compile_types</span><span style="color: #D4D4D4">(in_user </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">      e_has_table_deps </span><span style="color: #569CD6">EXCEPTION</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">      e_is_not_udt     </span><span style="color: #569CD6">EXCEPTION</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">      e_compile_error  </span><span style="color: #569CD6">EXCEPTION</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">PRAGMA exception_init</span><span style="color: #D4D4D4">(e_has_table_deps, -</span><span style="color: #B5CEA8">2311</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">PRAGMA exception_init</span><span style="color: #D4D4D4">(e_is_not_udt, -</span><span style="color: #B5CEA8">22307</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">PRAGMA exception_init</span><span style="color: #D4D4D4">(e_compile_error, -</span><span style="color: #B5CEA8">24344</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;&lt;types&gt;&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">FOR</span><span style="color: #D4D4D4"> r </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> o.object_type, o.object_name, </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">(d.</span><span style="color: #569CD6">name</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> priority </span></span>
<span class="line"><span style="color: #D4D4D4">           </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_objects o</span></span>
<span class="line"><span style="color: #D4D4D4">           </span><span style="color: #569CD6">LEFT JOIN</span><span style="color: #D4D4D4"> dba_dependencies d</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> d.owner = o.owner</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> d.</span><span style="color: #569CD6">type</span><span style="color: #D4D4D4"> = o.object_type</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> d.</span><span style="color: #569CD6">name</span><span style="color: #D4D4D4"> = o.object_name</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> o.owner = in_user</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> o.object_type </span><span style="color: #569CD6">in</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;TYPE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TYPE BODY&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">GROUP BY</span><span style="color: #D4D4D4"> o.object_type, o.object_name</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">ORDER BY</span><span style="color: #D4D4D4"> priority</span></span>
<span class="line"><span style="color: #D4D4D4">      ) </span><span style="color: #C586C0">LOOP</span></span>
<span class="line"><span style="color: #D4D4D4">         &lt;&lt;compile_type&gt;&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #C586C0">IF</span><span style="color: #D4D4D4"> r.object_type = </span><span style="color: #CE9178">&#39;TYPE&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">                exec_sql(</span><span style="color: #CE9178">&#39;ALTER TYPE &quot;&#39;</span><span style="color: #D4D4D4"> || in_user || </span><span style="color: #CE9178">&#39;&quot;.&quot;&#39;</span><span style="color: #D4D4D4"> || r.object_name || </span><span style="color: #CE9178">&#39;&quot; COMPILE&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #C586C0">ELSE</span></span>
<span class="line"><span style="color: #D4D4D4">                exec_sql(</span><span style="color: #CE9178">&#39;ALTER TYPE &quot;&#39;</span><span style="color: #D4D4D4"> || in_user || </span><span style="color: #CE9178">&#39;&quot;.&quot;&#39;</span><span style="color: #D4D4D4"> || r.object_name || </span><span style="color: #CE9178">&#39;&quot; COMPILE BODY&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #C586C0">END IF</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">EXCEPTION</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #569CD6">WHEN</span><span style="color: #D4D4D4"> e_has_table_deps </span><span style="color: #569CD6">OR</span><span style="color: #D4D4D4"> e_is_not_udt </span><span style="color: #569CD6">OR</span><span style="color: #D4D4D4"> e_compile_error </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #569CD6">NULL</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> compile_type;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">END LOOP</span><span style="color: #D4D4D4"> types;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> compile_types;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">--</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">compile_schema</span><span style="color: #D4D4D4">(in_user </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- synonyms and types are not covered by dbms_utility.compile_schema</span></span>
<span class="line"><span style="color: #D4D4D4">      compile_private_synonyms(in_user);</span></span>
<span class="line"><span style="color: #D4D4D4">      compile_public_synonyms(in_user);</span></span>
<span class="line"><span style="color: #D4D4D4">      compile_types(in_user);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">dbms_utility.</span><span style="color: #4EC9B0">compile_schema</span><span style="color: #D4D4D4">(</span></span>
<span class="line"><span style="color: #D4D4D4">         schema         =&gt; in_user,</span></span>
<span class="line"><span style="color: #D4D4D4">         compile_all    =&gt; </span><span style="color: #569CD6">TRUE</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">         reuse_settings =&gt; </span><span style="color: #569CD6">FALSE</span></span>
<span class="line"><span style="color: #D4D4D4">      );</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> compile_schema;</span></span>
<span class="line"><span style="color: #569CD6">BEGIN</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   enable_plscope;</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   &lt;&lt;app_user&gt;&gt;</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   </span><span style="color: #C586C0">FOR</span><span style="color: #D4D4D4"> r </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_users</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> oracle_maintained = </span><span style="color: #CE9178">&#39;N&#39;</span><span style="color: #D4D4D4"> </span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> username </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;FTLDB&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PLSCOPE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;UT3&#39;</span><span style="color: #D4D4D4">)      </span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   ) </span><span style="color: #C586C0">LOOP</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      compile_schema(r.username);</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   </span><span style="color: #C586C0">END LOOP</span><span style="color: #D4D4D4"> app_user;</span></span>
<span class="line"><span style="color: #569CD6">END</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">/</span></span></code></pre></div>


<p></div></div>
<br />
<div class="question"><div class="title"><i class="icon-plus acc-icon-plus" aria-hidden="true"></i><i class="icon-minus acc-icon-minus" aria-hidden="true"></i>Query to check SmartDB property 3</div><div class="answer"></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(3 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Check SmartDB property 3: query (>=12.2)</span><span role="button" tabindex="0" data-code="WITH 
   -- calculate object dependencies recursively
   -- using PL/SQL to handle cycles (expected on object level)
   -- SQL variant using NOCYCLE did not work (runs forever)
   FUNCTION get_dep (
      in_xml IN XMLTYPE
   ) RETURN XMLTYPE IS
      l_deps     sys.ora_mining_varchar2_nt;
      l_result   XMLTYPE := XMLTYPE('&lt;xml/&gt;');
      l_element  XMLTYPE;
      --
      PROCEDURE add_child(
         io_deps  IN OUT sys.ora_mining_varchar2_nt,
         in_owner           IN VARCHAR2,
         in_type            IN VARCHAR2,
         in_name            IN VARCHAR2,
         in_has_dml         IN INTEGER,
         in_has_transaction IN INTEGER
      ) IS
      BEGIN
         io_deps.extend;
         io_deps(io_deps.count) := in_owner || '.' || in_type || '.' || in_name 
            || '.' || in_has_dml || '.' || in_has_transaction;         
      END add_child;
      --
      FUNCTION exists_child(
         in_deps            IN sys.ora_mining_varchar2_nt,
         in_owner           IN VARCHAR2,
         in_type            IN VARCHAR2,
         in_name            IN VARCHAR2,
         in_has_dml         IN INTEGER,
         in_has_transaction IN INTEGER
      ) RETURN BOOLEAN is
         l_found INTEGER;
      BEGIN
         SELECT COUNT(*)
           INTO l_found
           FROM table(in_deps)
          WHERE column_value = in_owner || '.' || in_type || '.' || in_name 
                   || '.' || in_has_dml || '.' || in_has_transaction
            AND rownum = 1;
         RETURN l_found &gt; 0;
      END exists_child;
      --
      PROCEDURE add_children(
         io_deps  IN OUT sys.ora_mining_varchar2_nt,
         in_xml   IN     XMLTYPE,
         in_owner IN     VARCHAR2,
         in_type  IN     VARCHAR2,
         in_name  IN     VARCHAR2
      ) IS
      BEGIN
         FOR r IN (
            SELECT owner, type, name, has_dml, has_transaction
              FROM XMLTABLE(
                      'xml/row/value/dependency&#091;../../key/owner=$owner and ../../key/type=$type and ../../key/name=$name&#093;'
                      PASSING in_xml, in_owner AS &quot;owner&quot;, in_type AS &quot;type&quot;, in_name AS &quot;name&quot;
                      COLUMNS owner           VARCHAR2(128) PATH 'referenced_owner',
                              type            VARCHAR2(128) PATH 'referenced_type',
                              name            VARCHAR2(128) PATH 'referenced_name',
                              has_dml         INTEGER       PATH 'referenced_has_dml',
                              has_transaction INTEGER       PATH 'referenced_has_transaction'
                   )
         ) LOOP
            IF NOT exists_child(io_deps, r.owner, r.type, r.name, r.has_dml, r.has_transaction) THEN
               add_child(io_deps, r.owner, r.type, r.name, r.has_dml, r.has_transaction);
               add_children(io_deps, in_xml, r.owner, r.type, r.name);
            END IF;
         END LOOP;
      END add_children;
      ---
      FUNCTION get_fragment(
         in_deps  IN sys.ora_mining_varchar2_nt,
         in_owner IN VARCHAR2,
         in_type  IN VARCHAR2,
         in_name  IN VARCHAR2
      ) RETURN XMLTYPE IS
         l_xml XMLTYPE;
      BEGIN
         SELECT XMLELEMENT(&quot;xml&quot;,
                   XMLAGG(
                      XMLELEMENT(&quot;row&quot;,
                         XMLELEMENT(&quot;owner&quot;, in_owner),
                         XMLELEMENT(&quot;type&quot;, in_type),
                         XMLELEMENT(&quot;name&quot;, in_name),
                         XMLELEMENT(&quot;referenced_owner&quot;, regexp_substr(column_value, '&#091;^\.&#093;+', 1, 1)),
                         XMLELEMENT(&quot;referenced_type&quot;, regexp_substr(column_value, '&#091;^\.&#093;+', 1, 2)),
                         XMLELEMENT(&quot;referenced_name&quot;, regexp_substr(column_value, '&#091;^\.&#093;+', 1, 3)),
                         XMLELEMENT(&quot;referenced_has_dml&quot;, regexp_substr(column_value, '&#091;^\.&#093;+', 1, 4)),
                         XMLELEMENT(&quot;referenced_has_transaction&quot;, regexp_substr(column_value, '&#091;^\.&#093;+', 1, 5))
                      )
                   )
                )   
           INTO l_xml
           FROM table(in_deps);
          RETURN l_xml;
      END get_fragment;
      ---
      PROCEDURE add_to_result(
         io_result    IN OUT XMLTYPE,
         in_fragment  IN     XMLTYPE
      ) IS
      BEGIN
         SELECT xmlquery('
                   copy $i := $p1 modify
                   (
                      for $j in $i/xml 
                      return insert node $p2 into $j
                   )
                   return $i'
                   PASSING io_result AS &quot;p1&quot;, in_fragment.extract('/xml/row') AS &quot;p2&quot;
                   RETURNING CONTENT
                )
           INTO io_result
           FROM dual;  
      END add_to_result;
   BEGIN
      FOR r IN (
         SELECT owner, type, name
           FROM XMLTABLE (
                   '/xml/row/key'
                   PASSING in_xml
                   COLUMNS owner VARCHAR2(128) PATH 'owner',
                           type  VARCHAR2(128) PATH 'type',
                           name  VARCHAR2(128) PATH 'name'                           
                )
      ) 
      LOOP
         l_deps := sys.ora_mining_varchar2_nt();
         add_children(l_deps, in_xml, r.owner, r.type, r.name);
         add_to_result(l_result, get_fragment(l_deps, r.owner, r.type, r.name));
      END LOOP;
      RETURN l_result;
   END get_dep;
   -- application users in scope of the analysis
   -- other users are treated as if they were not installed
   app_user AS (
      SELECT username
        FROM dba_users
       WHERE oracle_maintained = 'N' -- SYS, SYSTEM, SYSAUX, ...
         AND username NOT IN ('FTLDB', 'PLSCOPE', 'UT3')
   ),
   -- materialize relevant PL/Scope identifiers to avoid very bad execution plans
   identifiers AS (
      SELECT --+ materialize
             owner,
             object_type, 
             object_name
        FROM dba_identifiers i
       WHERE usage_context_id = 0
         AND object_type IN ('PACKAGE BODY', 'TYPE BODY', 'FUNCTION', 'PROCEDURE', 'TRIGGER')
   ),
   -- PL/SQL objects without PL/Scope metadata
   missing_plscope_obj AS (
      SELECT o.owner, o.object_type, o.object_name
        FROM dba_objects o
        JOIN app_user u ON u.username = o.owner
        LEFT JOIN identifiers i
          ON i.owner = o.owner
             AND i.object_type = o.object_type
             AND i.object_name = o.object_name
       WHERE o.object_type IN ('PACKAGE BODY', 'TYPE BODY', 'FUNCTION', 'PROCEDURE', 'TRIGGER')
         AND i.object_name IS NULL
   ),   
   -- PL/SQL bodies extended by has_dml and has_transaction colums using PL/Scope 
   plscope_obj AS (
      SELECT s.owner, s.object_type, s.object_name,
             MAX (
                CASE
                   WHEN s.type IN ('INSERT', 'UPDATE', 'DELETE', 'MERGE') THEN
                      1
                   ELSE
                      0
                END
             ) AS has_dml,
             MAX (
                CASE
                   WHEN s.type IN ('COMMIT', 'ROLLBACK') THEN
                      1
                   ELSE
                      0
                END
             ) AS has_transaction
        FROM dba_statements s
        JOIN app_user u ON u.username = s.owner
       WHERE s.object_type IN ('PACKAGE BODY', 'TYPE BODY', 'FUNCTION', 'PROCEDURE', 'TRIGGER')
       GROUP BY s.owner, s.object_type, s.object_name
   ),
   -- dba_dependencies reduced to a PL/SQL bodies
   dep_base AS (
      SELECT owner,
             type, 
             name, 
             referenced_owner,
             CASE referenced_type
                WHEN 'PACKAGE' THEN 'PACKAGE BODY'
                WHEN 'TYPE' THEN 'TYPE BODY'
                ELSE referenced_type
             END AS referenced_type,
             referenced_name
        FROM dba_dependencies d
       WHERE referenced_type IN ('PACKAGE', 'PACKAGE BODY', 'TYPE', 'TYPE BODY', 'FUNCTION', 'PROCEDURE', 'SYNONYM')
         and (owner = 'PUBLIC' OR owner IN (SELECT username FROM app_user))
         and (referenced_owner = 'PUBLIC' OR referenced_owner IN (SELECT username FROM app_user))
   ), 
   -- extend dependencies by columns has_dml and has_transaction
   dep AS (
      select d.owner,
             d.type,
             d.name, 
             d.referenced_owner, 
             d.referenced_type, 
             d.referenced_name, 
             nvl(p.has_dml, 0) AS referenced_has_dml,
             nvl(p.has_transaction, 0) AS referenced_has_transaction
        FROM dep_base d
        LEFT JOIN plscope_obj p
          ON p.owner = d.referenced_owner
             AND p.object_type = d.referenced_type
             AND p.object_name = d.referenced_name
   ),
   -- XML because JSON values are still restricted to 4000/32767 bytes
   -- see Bug 27199654 : ORA-40459 WHEN GENERATING JSON DATA
   xml_dep AS (
      SELECT XMLELEMENT(&quot;xml&quot;,
                XMLAGG(
                   XMLELEMENT(&quot;row&quot;,
                      XMLELEMENT(&quot;key&quot;,
                         XMLELEMENT(&quot;owner&quot;, d.owner),
                         XMLELEMENT(&quot;type&quot;, d.type),
                         XMLELEMENT(&quot;name&quot;, d.name)
                      ),
                      XMLELEMENT(&quot;value&quot;,
                         XMLAGG(
                            XMLELEMENT(&quot;dependency&quot;,
                               XMLELEMENT(&quot;referenced_owner&quot;, d.referenced_owner),
                               XMLELEMENT(&quot;referenced_type&quot;, d.referenced_type),
                               XMLELEMENT(&quot;referenced_name&quot;, d.referenced_name),
                               XMLELEMENT(&quot;referenced_has_dml&quot;, d.referenced_has_dml),
                               XMLELEMENT(&quot;referenced_has_transaction&quot;, d.referenced_has_transaction)
                            )
                         )
                      )
                   )
                )
             ) AS xmldoc
        FROM dep d
        JOIN dba_objects o
          ON d.owner = o.owner
         AND d.type = o.object_type
         AND d.name = o.object_name
       WHERE o.owner IN (SELECT username FROM app_user)
         AND o.object_type IN ('PACKAGE BODY', 'TYPE BODY', 'FUNCTION', 'PROCEDURE')
         AND (d.owner, replace(d.type, ' BODY'), d.name) IN (
                SELECT owner, type, table_name 
                 FROM dba_tab_privs
             )
       GROUP BY d.owner, d.type, d.name               
   ),
   -- get the object dependencies via PL/SQL function
   -- passing data as XML because the PL/SQL function dont't have access to named subqueries
   dep_hier AS (
      SELECT owner, type, name, referenced_owner, referenced_type, referenced_name, 
             referenced_has_dml, referenced_has_transaction
        FROM XMLTABLE(
               '/xml/row'
               PASSING get_dep((SELECT xmldoc from xml_dep))
                   COLUMNS owner                      VARCHAR2(128) PATH 'owner',
                           type                       VARCHAR2(128) PATH 'type',
                           name                       VARCHAR2(128) PATH 'name',
                           referenced_owner           VARCHAR2(128) PATH 'referenced_owner',
                           referenced_type            VARCHAR2(128) PATH 'referenced_type',
                           referenced_name            VARCHAR2(128) PATH 'referenced_name',
                           referenced_has_dml         INTEGER       PATH 'referenced_has_dml',
                           referenced_has_transaction INTEGER       PATH 'referenced_has_transaction'
             )
   ),
   -- aggregate columns has_dml and has_transaction per root PL/SQL body
   app_plsql AS (
      SELECT owner, type AS object_type, name AS object_name,
             MAX(referenced_has_dml) AS has_dml,
             MAX(referenced_has_transaction) AS has_transaction
        FROM dep_hier
       GROUP by owner, type, name
   ),
   -- roles as recursive structure
   role_base AS (
      -- roles without parent (=roots)
      SELECT r.role, NULL AS parent_role
        FROM dba_roles r
       WHERE r.role NOT IN (
                SELECT p.granted_role
                  FROM role_role_privs p
             )
      UNION ALL
      -- roles with parent (=children)
      SELECT granted_role AS role, role AS parent_role
        FROM role_role_privs
   ),
   -- roles tree, calculate role_path for every hierarchy level
   role_tree AS (
      SELECT role,
             parent_role,
             sys_connect_by_path(ROLE, '/') AS role_path
        FROM role_base
      CONNECT BY PRIOR role = parent_role
   ),
   -- roles graph, child added to all ancestors including self
   -- allows simple join to parent_role to find all descendants
   role_graph AS (
      SELECT DISTINCT
             role,
             regexp_substr(role_path, '(/)(\w+)', 1, 1, 'i', 2) AS parent_role
        FROM role_tree
   ),
   -- user system privileges
   sys_priv AS (
      -- system privileges granted directly to users
      SELECT u.username, p.privilege
        FROM dba_sys_privs p
        JOIN app_user u ON u.username = p.grantee
      UNION
      -- system privileges granted directly to PUBLIC
      SELECT u.username, p.privilege
        FROM dba_sys_privs p
       CROSS JOIN app_user u
       WHERE p.grantee = 'PUBLIC'
         AND p.privilege NOT IN (
                SELECT r.role
                  FROM dba_roles r
             )
      UNION
      -- system privileges granted to users via roles
      SELECT u.username, p.privilege
        FROM dba_role_privs r
        JOIN app_user u ON u.username = r.grantee
        JOIN role_graph g ON g.parent_role = r.granted_role
        JOIN dba_sys_privs p ON p.grantee = g.role
      UNION
      -- system privileges granted to PUBLIC via roles
      SELECT u.username, p.privilege
        FROM dba_role_privs r
        JOIN role_graph g ON g.parent_role = r.granted_role
        JOIN dba_sys_privs p ON p.grantee = g.role
        CROSS JOIN app_user u
       WHERE r.grantee = 'PUBLIC'
   ),
   -- user object privileges
   obj_priv AS (
      -- objects granted directly to users
      SELECT u.username, p.owner, p.type AS object_type, p.table_name AS object_name
        FROM dba_tab_privs p
        JOIN app_user u ON u.username = p.grantee
       WHERE p.owner IN (
                SELECT u2.username
                  FROM app_user u2
             )
      UNION
      -- objects granted to users via roles
      SELECT u.username, p.owner, p.type AS object_type, p.table_name AS object_name
        FROM dba_role_privs r
        JOIN app_user u ON u.username = r.grantee
        JOIN role_graph g ON g.parent_role = r.granted_role
        JOIN dba_tab_privs p ON p.grantee = g.role
       WHERE p.owner IN (
                SELECT u2.username
                  FROM app_user u2
             )
      -- objects granted to PUBLIC
      UNION
      SELECT u.username, p.owner, p.type AS object_type, p.table_name AS object_name
        FROM dba_tab_privs p
       CROSS JOIN app_user u
       WHERE p.owner IN (
                SELECT u2.username
                  FROM app_user u2
             )
         AND p.grantee = 'PUBLIC'
   ),
   -- issues if user is configured in the connection pool of a middle tier
   issues AS (
     -- privileges not part of CONNECT role
      SELECT username,
             'SYS' AS owner,
             'PRIVILEGE' AS object_type,
             privilege AS object_name,
             'Privilege is not part of the CONNECT role' AS issue
        FROM sys_priv
       WHERE privilege NOT IN ('CREATE SESSION', 'SET CONTAINER')
      -- access to non PL/SQL units
      UNION ALL
      SELECT username,
             owner,
             object_type,
             object_name,
             'Access to non-PL/SQL unit'
        FROM obj_priv
       WHERE object_type NOT IN ('PACKAGE', 'TYPE', 'FUNCTION', 'PROCEDURE')
       -- own objects
      UNION ALL
      SELECT u.username,
             o.owner,
             o.object_type,
             o.object_name,
             'Connect user must not own any object'
        FROM app_user u
        JOIN dba_objects o ON o.owner = u.username
      -- missing CREATE SESSION privilege
      UNION ALL
      SELECT u.username,
             'SYS',
             'PRIVILEGE',
             'CREATE SESSION',
             'Privilege is missing, but required'
        FROM app_user u
       WHERE u.username NOT IN (
                SELECT username
                  FROM sys_priv
                 WHERE privilege = 'CREATE SESSION' 
             )
      -- missing PL/Scope metadata leads to wrong results
      UNION ALL 
      SELECT p.username,
             p.owner, 
             p.object_type, 
             p.object_name, 
             'PL/Scope metadata is missing, required for analysis'
        FROM obj_priv p
        JOIN missing_plscope_obj s
          ON s.owner = p.owner
             AND replace(s.object_type, ' BODY') = p.object_type
             AND s.object_name = p.object_name
      -- access to PL/SQL units updating database state without COMMIT/ROLLBACK
      UNION ALL 
      SELECT p.username,
             p.owner,
             p.object_type,
             p.object_name,
             'INSERT/UPDATE/DELETE/MERGE without COMMIT/ROLLBACK'
        FROM obj_priv p
        JOIN app_plsql a
          ON a.owner = p.owner
             AND replace(a.object_type, ' BODY') = p.object_type
             AND a.object_name = p.object_name
       WHERE p.object_type IN ('PACKAGE', 'TYPE', 'FUNCTION', 'PROCEDURE') 
         AND a.has_dml = 1 AND a.has_transaction = 0
   ),
   -- aggregate issues per user
   issue_aggr AS (
      SELECT u.username, COUNT(i.username) issue_count
        FROM app_user u
        LEFT JOIN issues i ON i.username = u.username
       GROUP BY u.username
   ),
   -- user summary (calculate is_smartdb_property_3_met)
   summary AS (
      SELECT username,
             CASE
                WHEN issue_count = 0 THEN
                   'YES'
                ELSE
                   'NO'
             END AS is_smartdb_property_3_met,
             issue_count
        FROM issue_aggr
       ORDER BY is_smartdb_property_3_met DESC, username
   )
-- main
SELECT * 
  FROM summary
 WHERE issue_count = 0;
/" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">WITH</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- calculate object dependencies recursively</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- using PL/SQL to handle cycles (expected on object level)</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- SQL variant using NOCYCLE did not work (runs forever)</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">FUNCTION</span><span style="color: #D4D4D4"> get_dep (</span></span>
<span class="line"><span style="color: #D4D4D4">      in_xml </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> XMLTYPE</span></span>
<span class="line"><span style="color: #D4D4D4">   ) </span><span style="color: #569CD6">RETURN</span><span style="color: #D4D4D4"> XMLTYPE </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">      l_deps     sys.ora_mining_varchar2_nt;</span></span>
<span class="line"><span style="color: #D4D4D4">      l_result   XMLTYPE := XMLTYPE(</span><span style="color: #CE9178">&#39;&lt;xml/&gt;&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      l_element  XMLTYPE;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">--</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4"> add_child(</span></span>
<span class="line"><span style="color: #D4D4D4">         io_deps  </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">OUT</span><span style="color: #D4D4D4"> sys.ora_mining_varchar2_nt,</span></span>
<span class="line"><span style="color: #D4D4D4">         in_owner           </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">         in_type            </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">         in_name            </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">         in_has_dml         </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">INTEGER</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">         in_has_transaction </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">INTEGER</span></span>
<span class="line"><span style="color: #D4D4D4">      ) </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">         io_deps.extend;</span></span>
<span class="line"><span style="color: #D4D4D4">         io_deps(io_deps.count) := in_owner || </span><span style="color: #CE9178">&#39;.&#39;</span><span style="color: #D4D4D4"> || in_type || </span><span style="color: #CE9178">&#39;.&#39;</span><span style="color: #D4D4D4"> || in_name </span></span>
<span class="line"><span style="color: #D4D4D4">            || </span><span style="color: #CE9178">&#39;.&#39;</span><span style="color: #D4D4D4"> || in_has_dml || </span><span style="color: #CE9178">&#39;.&#39;</span><span style="color: #D4D4D4"> || in_has_transaction;         </span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> add_child;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">--</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">FUNCTION</span><span style="color: #D4D4D4"> exists_child(</span></span>
<span class="line"><span style="color: #D4D4D4">         in_deps            </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> sys.ora_mining_varchar2_nt,</span></span>
<span class="line"><span style="color: #D4D4D4">         in_owner           </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">         in_type            </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">         in_name            </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">         in_has_dml         </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">INTEGER</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">         in_has_transaction </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">INTEGER</span></span>
<span class="line"><span style="color: #D4D4D4">      ) </span><span style="color: #569CD6">RETURN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">BOOLEAN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">is</span></span>
<span class="line"><span style="color: #D4D4D4">         l_found </span><span style="color: #569CD6">INTEGER</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">COUNT</span><span style="color: #D4D4D4">(*)</span></span>
<span class="line"><span style="color: #D4D4D4">           </span><span style="color: #569CD6">INTO</span><span style="color: #D4D4D4"> l_found</span></span>
<span class="line"><span style="color: #D4D4D4">           </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">table</span><span style="color: #D4D4D4">(in_deps)</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> column_value = in_owner || </span><span style="color: #CE9178">&#39;.&#39;</span><span style="color: #D4D4D4"> || in_type || </span><span style="color: #CE9178">&#39;.&#39;</span><span style="color: #D4D4D4"> || in_name </span></span>
<span class="line"><span style="color: #D4D4D4">                   || </span><span style="color: #CE9178">&#39;.&#39;</span><span style="color: #D4D4D4"> || in_has_dml || </span><span style="color: #CE9178">&#39;.&#39;</span><span style="color: #D4D4D4"> || in_has_transaction</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> rownum = </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">RETURN</span><span style="color: #D4D4D4"> l_found &gt; </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> exists_child;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">--</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4"> add_children(</span></span>
<span class="line"><span style="color: #D4D4D4">         io_deps  </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">OUT</span><span style="color: #D4D4D4"> sys.ora_mining_varchar2_nt,</span></span>
<span class="line"><span style="color: #D4D4D4">         in_xml   </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4">     XMLTYPE,</span></span>
<span class="line"><span style="color: #D4D4D4">         in_owner </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4">     </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">         in_type  </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4">     </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">         in_name  </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4">     </span><span style="color: #569CD6">VARCHAR2</span></span>
<span class="line"><span style="color: #D4D4D4">      ) </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">FOR</span><span style="color: #D4D4D4"> r </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">type</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">name</span><span style="color: #D4D4D4">, has_dml, has_transaction</span></span>
<span class="line"><span style="color: #D4D4D4">              </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> XMLTABLE(</span></span>
<span class="line"><span style="color: #D4D4D4">                      </span><span style="color: #CE9178">&#39;xml/row/value/dependency[../../key/owner=$owner and ../../key/type=$type and ../../key/name=$name]&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">                      PASSING in_xml, in_owner </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;owner&quot;</span><span style="color: #D4D4D4">, in_type </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;type&quot;</span><span style="color: #D4D4D4">, in_name </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;name&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">                      COLUMNS </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">           </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">128</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">PATH</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;referenced_owner&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                              </span><span style="color: #569CD6">type</span><span style="color: #D4D4D4">            </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">128</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">PATH</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;referenced_type&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                              </span><span style="color: #569CD6">name</span><span style="color: #D4D4D4">            </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">128</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">PATH</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;referenced_name&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                              has_dml         </span><span style="color: #569CD6">INTEGER</span><span style="color: #D4D4D4">       </span><span style="color: #569CD6">PATH</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;referenced_has_dml&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                              has_transaction </span><span style="color: #569CD6">INTEGER</span><span style="color: #D4D4D4">       </span><span style="color: #569CD6">PATH</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;referenced_has_transaction&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">                   )</span></span>
<span class="line"><span style="color: #D4D4D4">         ) </span><span style="color: #569CD6">LOOP</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #569CD6">IF</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> exists_child(io_deps, r.owner, r.type, r.name, r.has_dml, r.has_transaction) </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">               add_child(io_deps, r.owner, r.type, r.name, r.has_dml, r.has_transaction);</span></span>
<span class="line"><span style="color: #D4D4D4">               add_children(io_deps, in_xml, r.owner, r.type, r.name);</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IF</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">LOOP</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> add_children;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">---</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">FUNCTION</span><span style="color: #D4D4D4"> get_fragment(</span></span>
<span class="line"><span style="color: #D4D4D4">         in_deps  </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> sys.ora_mining_varchar2_nt,</span></span>
<span class="line"><span style="color: #D4D4D4">         in_owner </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">         in_type  </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">         in_name  </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VARCHAR2</span></span>
<span class="line"><span style="color: #D4D4D4">      ) </span><span style="color: #569CD6">RETURN</span><span style="color: #D4D4D4"> XMLTYPE </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">         l_xml XMLTYPE;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> XMLELEMENT(</span><span style="color: #CE9178">&quot;xml&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                   XMLAGG(</span></span>
<span class="line"><span style="color: #D4D4D4">                      XMLELEMENT(</span><span style="color: #CE9178">&quot;row&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                         XMLELEMENT(</span><span style="color: #CE9178">&quot;owner&quot;</span><span style="color: #D4D4D4">, in_owner),</span></span>
<span class="line"><span style="color: #D4D4D4">                         XMLELEMENT(</span><span style="color: #CE9178">&quot;type&quot;</span><span style="color: #D4D4D4">, in_type),</span></span>
<span class="line"><span style="color: #D4D4D4">                         XMLELEMENT(</span><span style="color: #CE9178">&quot;name&quot;</span><span style="color: #D4D4D4">, in_name),</span></span>
<span class="line"><span style="color: #D4D4D4">                         XMLELEMENT(</span><span style="color: #CE9178">&quot;referenced_owner&quot;</span><span style="color: #D4D4D4">, regexp_substr(column_value, </span><span style="color: #CE9178">&#39;[^\.]+&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">)),</span></span>
<span class="line"><span style="color: #D4D4D4">                         XMLELEMENT(</span><span style="color: #CE9178">&quot;referenced_type&quot;</span><span style="color: #D4D4D4">, regexp_substr(column_value, </span><span style="color: #CE9178">&#39;[^\.]+&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">)),</span></span>
<span class="line"><span style="color: #D4D4D4">                         XMLELEMENT(</span><span style="color: #CE9178">&quot;referenced_name&quot;</span><span style="color: #D4D4D4">, regexp_substr(column_value, </span><span style="color: #CE9178">&#39;[^\.]+&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">)),</span></span>
<span class="line"><span style="color: #D4D4D4">                         XMLELEMENT(</span><span style="color: #CE9178">&quot;referenced_has_dml&quot;</span><span style="color: #D4D4D4">, regexp_substr(column_value, </span><span style="color: #CE9178">&#39;[^\.]+&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">4</span><span style="color: #D4D4D4">)),</span></span>
<span class="line"><span style="color: #D4D4D4">                         XMLELEMENT(</span><span style="color: #CE9178">&quot;referenced_has_transaction&quot;</span><span style="color: #D4D4D4">, regexp_substr(column_value, </span><span style="color: #CE9178">&#39;[^\.]+&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">5</span><span style="color: #D4D4D4">))</span></span>
<span class="line"><span style="color: #D4D4D4">                      )</span></span>
<span class="line"><span style="color: #D4D4D4">                   )</span></span>
<span class="line"><span style="color: #D4D4D4">                )   </span></span>
<span class="line"><span style="color: #D4D4D4">           </span><span style="color: #569CD6">INTO</span><span style="color: #D4D4D4"> l_xml</span></span>
<span class="line"><span style="color: #D4D4D4">           </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">table</span><span style="color: #D4D4D4">(in_deps);</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">RETURN</span><span style="color: #D4D4D4"> l_xml;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> get_fragment;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">---</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4"> add_to_result(</span></span>
<span class="line"><span style="color: #D4D4D4">         io_result    </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">OUT</span><span style="color: #D4D4D4"> XMLTYPE,</span></span>
<span class="line"><span style="color: #D4D4D4">         in_fragment  </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4">     XMLTYPE</span></span>
<span class="line"><span style="color: #D4D4D4">      ) </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> xmlquery(</span><span style="color: #CE9178">&#39;</span></span>
<span class="line"><span style="color: #CE9178">                   copy $i := $p1 modify</span></span>
<span class="line"><span style="color: #CE9178">                   (</span></span>
<span class="line"><span style="color: #CE9178">                      for $j in $i/xml </span></span>
<span class="line"><span style="color: #CE9178">                      return insert node $p2 into $j</span></span>
<span class="line"><span style="color: #CE9178">                   )</span></span>
<span class="line"><span style="color: #CE9178">                   return $i&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">                   PASSING io_result </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;p1&quot;</span><span style="color: #D4D4D4">, in_fragment.extract(</span><span style="color: #CE9178">&#39;/xml/row&#39;</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;p2&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">                   RETURNING CONTENT</span></span>
<span class="line"><span style="color: #D4D4D4">                )</span></span>
<span class="line"><span style="color: #D4D4D4">           </span><span style="color: #569CD6">INTO</span><span style="color: #D4D4D4"> io_result</span></span>
<span class="line"><span style="color: #D4D4D4">           </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dual;  </span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> add_to_result;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">FOR</span><span style="color: #D4D4D4"> r </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">type</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">name</span></span>
<span class="line"><span style="color: #D4D4D4">           </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> XMLTABLE (</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #CE9178">&#39;/xml/row/key&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">                   PASSING in_xml</span></span>
<span class="line"><span style="color: #D4D4D4">                   COLUMNS </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">128</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">PATH</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;owner&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                           </span><span style="color: #569CD6">type</span><span style="color: #D4D4D4">  </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">128</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">PATH</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;type&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                           </span><span style="color: #569CD6">name</span><span style="color: #D4D4D4">  </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">128</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">PATH</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;name&#39;</span><span style="color: #D4D4D4">                           </span></span>
<span class="line"><span style="color: #D4D4D4">                )</span></span>
<span class="line"><span style="color: #D4D4D4">      ) </span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">LOOP</span></span>
<span class="line"><span style="color: #D4D4D4">         l_deps := sys.ora_mining_varchar2_nt();</span></span>
<span class="line"><span style="color: #D4D4D4">         add_children(l_deps, in_xml, r.owner, r.type, r.name);</span></span>
<span class="line"><span style="color: #D4D4D4">         add_to_result(l_result, get_fragment(l_deps, r.owner, r.type, r.name));</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">LOOP</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">RETURN</span><span style="color: #D4D4D4"> l_result;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> get_dep;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- application users in scope of the analysis</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- other users are treated as if they were not installed</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   app_user </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_users</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> oracle_maintained = </span><span style="color: #CE9178">&#39;N&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #6A9955">-- SYS, SYSTEM, SYSAUX, ...</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> username </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;FTLDB&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PLSCOPE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;UT3&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- materialize relevant PL/Scope identifiers to avoid very bad execution plans</span></span>
<span class="line"><span style="color: #D4D4D4">   identifiers </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #6A9955">--+ materialize</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             object_type, </span></span>
<span class="line"><span style="color: #D4D4D4">             object_name</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_identifiers i</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> usage_context_id = </span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> object_type </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;PACKAGE BODY&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TYPE BODY&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;FUNCTION&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PROCEDURE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TRIGGER&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- PL/SQL objects without PL/Scope metadata</span></span>
<span class="line"><span style="color: #D4D4D4">   missing_plscope_obj </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> o.owner, o.object_type, o.object_name</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_objects o</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = o.owner</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">LEFT JOIN</span><span style="color: #D4D4D4"> identifiers i</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> i.owner = o.owner</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> i.object_type = o.object_type</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> i.object_name = o.object_name</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> o.object_type </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;PACKAGE BODY&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TYPE BODY&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;FUNCTION&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PROCEDURE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TRIGGER&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> i.object_name </span><span style="color: #569CD6">IS</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">NULL</span></span>
<span class="line"><span style="color: #D4D4D4">   ),   </span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- PL/SQL bodies extended by has_dml and has_transaction colums using PL/Scope </span></span>
<span class="line"><span style="color: #D4D4D4">   plscope_obj </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> s.owner, s.object_type, s.object_name,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #DCDCAA">MAX</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">CASE</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #569CD6">WHEN</span><span style="color: #D4D4D4"> s.type </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;INSERT&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;UPDATE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;DELETE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;MERGE&#39;</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">                      </span><span style="color: #B5CEA8">1</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #569CD6">ELSE</span></span>
<span class="line"><span style="color: #D4D4D4">                      </span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">END</span></span>
<span class="line"><span style="color: #D4D4D4">             ) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> has_dml,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #DCDCAA">MAX</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">CASE</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #569CD6">WHEN</span><span style="color: #D4D4D4"> s.type </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;COMMIT&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;ROLLBACK&#39;</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">                      </span><span style="color: #B5CEA8">1</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #569CD6">ELSE</span></span>
<span class="line"><span style="color: #D4D4D4">                      </span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">END</span></span>
<span class="line"><span style="color: #D4D4D4">             ) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> has_transaction</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_statements s</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = s.owner</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> s.object_type </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;PACKAGE BODY&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TYPE BODY&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;FUNCTION&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PROCEDURE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TRIGGER&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">GROUP BY</span><span style="color: #D4D4D4"> s.owner, s.object_type, s.object_name</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- dba_dependencies reduced to a PL/SQL bodies</span></span>
<span class="line"><span style="color: #D4D4D4">   dep_base </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">type</span><span style="color: #D4D4D4">, </span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">name</span><span style="color: #D4D4D4">, </span></span>
<span class="line"><span style="color: #D4D4D4">             referenced_owner,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">CASE</span><span style="color: #D4D4D4"> referenced_type</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">WHEN</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;PACKAGE&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">THEN</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;PACKAGE BODY&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">WHEN</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;TYPE&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">THEN</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;TYPE BODY&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">ELSE</span><span style="color: #D4D4D4"> referenced_type</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> referenced_type,</span></span>
<span class="line"><span style="color: #D4D4D4">             referenced_name</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_dependencies d</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> referenced_type </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;PACKAGE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PACKAGE BODY&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TYPE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TYPE BODY&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;FUNCTION&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PROCEDURE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;SYNONYM&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> (</span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4"> = </span><span style="color: #CE9178">&#39;PUBLIC&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">OR</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user))</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> (referenced_owner = </span><span style="color: #CE9178">&#39;PUBLIC&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">OR</span><span style="color: #D4D4D4"> referenced_owner </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user))</span></span>
<span class="line"><span style="color: #D4D4D4">   ), </span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- extend dependencies by columns has_dml and has_transaction</span></span>
<span class="line"><span style="color: #D4D4D4">   dep </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> d.owner,</span></span>
<span class="line"><span style="color: #D4D4D4">             d.type,</span></span>
<span class="line"><span style="color: #D4D4D4">             d.name, </span></span>
<span class="line"><span style="color: #D4D4D4">             d.referenced_owner, </span></span>
<span class="line"><span style="color: #D4D4D4">             d.referenced_type, </span></span>
<span class="line"><span style="color: #D4D4D4">             d.referenced_name, </span></span>
<span class="line"><span style="color: #D4D4D4">             nvl(p.has_dml, </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> referenced_has_dml,</span></span>
<span class="line"><span style="color: #D4D4D4">             nvl(p.has_transaction, </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> referenced_has_transaction</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dep_base d</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">LEFT JOIN</span><span style="color: #D4D4D4"> plscope_obj p</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> p.owner = d.referenced_owner</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> p.object_type = d.referenced_type</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> p.object_name = d.referenced_name</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- XML because JSON values are still restricted to 4000/32767 bytes</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- see Bug 27199654 : ORA-40459 WHEN GENERATING JSON DATA</span></span>
<span class="line"><span style="color: #D4D4D4">   xml_dep </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> XMLELEMENT(</span><span style="color: #CE9178">&quot;xml&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                XMLAGG(</span></span>
<span class="line"><span style="color: #D4D4D4">                   XMLELEMENT(</span><span style="color: #CE9178">&quot;row&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                      XMLELEMENT(</span><span style="color: #CE9178">&quot;key&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                         XMLELEMENT(</span><span style="color: #CE9178">&quot;owner&quot;</span><span style="color: #D4D4D4">, d.owner),</span></span>
<span class="line"><span style="color: #D4D4D4">                         XMLELEMENT(</span><span style="color: #CE9178">&quot;type&quot;</span><span style="color: #D4D4D4">, d.type),</span></span>
<span class="line"><span style="color: #D4D4D4">                         XMLELEMENT(</span><span style="color: #CE9178">&quot;name&quot;</span><span style="color: #D4D4D4">, d.name)</span></span>
<span class="line"><span style="color: #D4D4D4">                      ),</span></span>
<span class="line"><span style="color: #D4D4D4">                      XMLELEMENT(</span><span style="color: #CE9178">&quot;value&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                         XMLAGG(</span></span>
<span class="line"><span style="color: #D4D4D4">                            XMLELEMENT(</span><span style="color: #CE9178">&quot;dependency&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                               XMLELEMENT(</span><span style="color: #CE9178">&quot;referenced_owner&quot;</span><span style="color: #D4D4D4">, d.referenced_owner),</span></span>
<span class="line"><span style="color: #D4D4D4">                               XMLELEMENT(</span><span style="color: #CE9178">&quot;referenced_type&quot;</span><span style="color: #D4D4D4">, d.referenced_type),</span></span>
<span class="line"><span style="color: #D4D4D4">                               XMLELEMENT(</span><span style="color: #CE9178">&quot;referenced_name&quot;</span><span style="color: #D4D4D4">, d.referenced_name),</span></span>
<span class="line"><span style="color: #D4D4D4">                               XMLELEMENT(</span><span style="color: #CE9178">&quot;referenced_has_dml&quot;</span><span style="color: #D4D4D4">, d.referenced_has_dml),</span></span>
<span class="line"><span style="color: #D4D4D4">                               XMLELEMENT(</span><span style="color: #CE9178">&quot;referenced_has_transaction&quot;</span><span style="color: #D4D4D4">, d.referenced_has_transaction)</span></span>
<span class="line"><span style="color: #D4D4D4">                            )</span></span>
<span class="line"><span style="color: #D4D4D4">                         )</span></span>
<span class="line"><span style="color: #D4D4D4">                      )</span></span>
<span class="line"><span style="color: #D4D4D4">                   )</span></span>
<span class="line"><span style="color: #D4D4D4">                )</span></span>
<span class="line"><span style="color: #D4D4D4">             ) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> xmldoc</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dep d</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> dba_objects o</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> d.owner = o.owner</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> d.type = o.object_type</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> d.name = o.object_name</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> o.owner </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user)</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> o.object_type </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;PACKAGE BODY&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TYPE BODY&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;FUNCTION&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PROCEDURE&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> (d.owner, </span><span style="color: #DCDCAA">replace</span><span style="color: #D4D4D4">(d.type, </span><span style="color: #CE9178">&#39; BODY&#39;</span><span style="color: #D4D4D4">), d.name) </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">type</span><span style="color: #D4D4D4">, table_name </span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_tab_privs</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">GROUP BY</span><span style="color: #D4D4D4"> d.owner, d.type, d.name               </span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- get the object dependencies via PL/SQL function</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- passing data as XML because the PL/SQL function dont&#39;t have access to named subqueries</span></span>
<span class="line"><span style="color: #D4D4D4">   dep_hier </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">type</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">name</span><span style="color: #D4D4D4">, referenced_owner, referenced_type, referenced_name, </span></span>
<span class="line"><span style="color: #D4D4D4">             referenced_has_dml, referenced_has_transaction</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> XMLTABLE(</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #CE9178">&#39;/xml/row&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">               PASSING get_dep((</span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> xmldoc </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> xml_dep))</span></span>
<span class="line"><span style="color: #D4D4D4">                   COLUMNS </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">                      </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">128</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">PATH</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;owner&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                           </span><span style="color: #569CD6">type</span><span style="color: #D4D4D4">                       </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">128</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">PATH</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;type&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                           </span><span style="color: #569CD6">name</span><span style="color: #D4D4D4">                       </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">128</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">PATH</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;name&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                           referenced_owner           </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">128</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">PATH</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;referenced_owner&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                           referenced_type            </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">128</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">PATH</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;referenced_type&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                           referenced_name            </span><span style="color: #569CD6">VARCHAR2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">128</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">PATH</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;referenced_name&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                           referenced_has_dml         </span><span style="color: #569CD6">INTEGER</span><span style="color: #D4D4D4">       </span><span style="color: #569CD6">PATH</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;referenced_has_dml&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                           referenced_has_transaction </span><span style="color: #569CD6">INTEGER</span><span style="color: #D4D4D4">       </span><span style="color: #569CD6">PATH</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;referenced_has_transaction&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- aggregate columns has_dml and has_transaction per root PL/SQL body</span></span>
<span class="line"><span style="color: #D4D4D4">   app_plsql </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">type</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_type, </span><span style="color: #569CD6">name</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_name,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #DCDCAA">MAX</span><span style="color: #D4D4D4">(referenced_has_dml) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> has_dml,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #DCDCAA">MAX</span><span style="color: #D4D4D4">(referenced_has_transaction) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> has_transaction</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dep_hier</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">GROUP by</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">type</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">name</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- roles as recursive structure</span></span>
<span class="line"><span style="color: #D4D4D4">   role_base </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- roles without parent (=roots)</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> r.role, </span><span style="color: #569CD6">NULL</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> parent_role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_roles r</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> r.role </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> p.granted_role</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> role_role_privs p</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION ALL</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- roles with parent (=children)</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> granted_role </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">role</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> parent_role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> role_role_privs</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- roles tree, calculate role_path for every hierarchy level</span></span>
<span class="line"><span style="color: #D4D4D4">   role_tree </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             parent_role,</span></span>
<span class="line"><span style="color: #D4D4D4">             sys_connect_by_path(</span><span style="color: #569CD6">ROLE</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;/&#39;</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> role_path</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> role_base</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">CONNECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">BY</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PRIOR</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span><span style="color: #D4D4D4"> = parent_role</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- roles graph, child added to all ancestors including self</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- allows simple join to parent_role to find all descendants</span></span>
<span class="line"><span style="color: #D4D4D4">   role_graph </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT DISTINCT</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">role</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             regexp_substr(role_path, </span><span style="color: #CE9178">&#39;(/)(\w+)&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;i&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> parent_role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> role_tree</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- user system privileges</span></span>
<span class="line"><span style="color: #D4D4D4">   sys_priv </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- system privileges granted directly to users</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.privilege</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_sys_privs p</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = p.grantee</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- system privileges granted directly to PUBLIC</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.privilege</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_sys_privs p</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">CROSS JOIN</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> p.grantee = </span><span style="color: #CE9178">&#39;PUBLIC&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> p.privilege </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> r.role</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_roles r</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- system privileges granted to users via roles</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.privilege</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_role_privs r</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = r.grantee</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> role_graph g </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> g.parent_role = r.granted_role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> dba_sys_privs p </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> p.grantee = g.role</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- system privileges granted to PUBLIC via roles</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.privilege</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_role_privs r</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> role_graph g </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> g.parent_role = r.granted_role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> dba_sys_privs p </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> p.grantee = g.role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">CROSS JOIN</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> r.grantee = </span><span style="color: #CE9178">&#39;PUBLIC&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- user object privileges</span></span>
<span class="line"><span style="color: #D4D4D4">   obj_priv </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- objects granted directly to users</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.owner, p.type </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_type, p.table_name </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_name</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_tab_privs p</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = p.grantee</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> p.owner </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u2.username</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u2</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- objects granted to users via roles</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.owner, p.type </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_type, p.table_name </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_name</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_role_privs r</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = r.grantee</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> role_graph g </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> g.parent_role = r.granted_role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> dba_tab_privs p </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> p.grantee = g.role</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> p.owner </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u2.username</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u2</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- objects granted to PUBLIC</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.owner, p.type </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_type, p.table_name </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_name</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_tab_privs p</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">CROSS JOIN</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> p.owner </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u2.username</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u2</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> p.grantee = </span><span style="color: #CE9178">&#39;PUBLIC&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- issues if user is configured in the connection pool of a middle tier</span></span>
<span class="line"><span style="color: #D4D4D4">   issues </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">     </span><span style="color: #6A9955">-- privileges not part of CONNECT role</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;SYS&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;PRIVILEGE&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_type,</span></span>
<span class="line"><span style="color: #D4D4D4">             privilege </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_name,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;Privilege is not part of the CONNECT role&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> issue</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> sys_priv</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> privilege </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;CREATE SESSION&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;SET CONTAINER&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- access to non PL/SQL units</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION ALL</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             object_type,</span></span>
<span class="line"><span style="color: #D4D4D4">             object_name,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;Access to non-PL/SQL unit&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> obj_priv</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> object_type </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;PACKAGE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TYPE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;FUNCTION&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PROCEDURE&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #6A9955">-- own objects</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION ALL</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username,</span></span>
<span class="line"><span style="color: #D4D4D4">             o.owner,</span></span>
<span class="line"><span style="color: #D4D4D4">             o.object_type,</span></span>
<span class="line"><span style="color: #D4D4D4">             o.object_name,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;Connect user must not own any object&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> dba_objects o </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> o.owner = u.username</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- missing CREATE SESSION privilege</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION ALL</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;SYS&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;PRIVILEGE&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;CREATE SESSION&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;Privilege is missing, but required&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> u.username </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> sys_priv</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> privilege = </span><span style="color: #CE9178">&#39;CREATE SESSION&#39;</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- missing PL/Scope metadata leads to wrong results</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION ALL</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> p.username,</span></span>
<span class="line"><span style="color: #D4D4D4">             p.owner, </span></span>
<span class="line"><span style="color: #D4D4D4">             p.object_type, </span></span>
<span class="line"><span style="color: #D4D4D4">             p.object_name, </span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;PL/Scope metadata is missing, required for analysis&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> obj_priv p</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> missing_plscope_obj s</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> s.owner = p.owner</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">replace</span><span style="color: #D4D4D4">(s.object_type, </span><span style="color: #CE9178">&#39; BODY&#39;</span><span style="color: #D4D4D4">) = p.object_type</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> s.object_name = p.object_name</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- access to PL/SQL units updating database state without COMMIT/ROLLBACK</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION ALL</span><span style="color: #D4D4D4"> </span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> p.username,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">             p.owner,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">             p.object_type,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">             p.object_name,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;INSERT/UPDATE/DELETE/MERGE without COMMIT/ROLLBACK&#39;</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> obj_priv p</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_plsql a</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> a.owner = p.owner</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">replace</span><span style="color: #D4D4D4">(a.object_type, </span><span style="color: #CE9178">&#39; BODY&#39;</span><span style="color: #D4D4D4">) = p.object_type</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> a.object_name = p.object_name</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> p.object_type </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;PACKAGE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TYPE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;FUNCTION&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PROCEDURE&#39;</span><span style="color: #D4D4D4">) </span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> a.has_dml = </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> a.has_transaction = </span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- aggregate issues per user</span></span>
<span class="line"><span style="color: #D4D4D4">   issue_aggr </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, </span><span style="color: #DCDCAA">COUNT</span><span style="color: #D4D4D4">(i.username) issue_count</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">LEFT JOIN</span><span style="color: #D4D4D4"> issues i </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> i.username = u.username</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">GROUP BY</span><span style="color: #D4D4D4"> u.username</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- user summary (calculate is_smartdb_property_3_met)</span></span>
<span class="line"><span style="color: #D4D4D4">   summary </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">CASE</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">WHEN</span><span style="color: #D4D4D4"> issue_count = </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #CE9178">&#39;YES&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">ELSE</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #CE9178">&#39;NO&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> is_smartdb_property_3_met,</span></span>
<span class="line"><span style="color: #D4D4D4">             issue_count</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> issue_aggr</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">ORDER BY</span><span style="color: #D4D4D4"> is_smartdb_property_3_met </span><span style="color: #569CD6">DESC</span><span style="color: #D4D4D4">, username</span></span>
<span class="line"><span style="color: #D4D4D4">   )</span></span>
<span class="line"><span style="color: #6A9955">-- main</span></span>
<span class="line"><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> * </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> summary</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> issue_count = </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">/</span></span></code></pre></div>


<p></div></div>
<br />
</div></div>




<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Check SmartDB property 3: result (complying connect users)</span><span role="button" tabindex="0" data-code="USERNAME                 IS_SMARTDB_PROPERTY_3_MET ISSUE_COUNT
------------------------ ------------------------- -----------
APEX_REST_PUBLIC_USER    YES                                 0
THE_BAD_USER             YES                                 0
THE_GOOD_USER            YES                                 0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">USERNAME                 IS_SMARTDB_PROPERTY_3_MET ISSUE_COUNT</span></span>
<span class="line"><span style="color: #D4D4D4">------------------------ ------------------------- -----------</span></span>
<span class="line"><span style="color: #D4D4D4">APEX_REST_PUBLIC_USER    YES                                 0</span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_USER             YES                                 0</span></span>
<span class="line"><span style="color: #D4D4D4">THE_GOOD_USER            YES                                 0</span></span></code></pre></div>



<p>If you are using a connect user that is not listed as a result, then your application is not SmartDB.</p>



<p>The query checks also the SmartDB properties 1 and 2. However, the query produces only a result if the PL/SQL bodies in application users are compiled with PL/Scope (see script above). Change the main part of the query to <code>SELECT * from issues</code> if you want to know why a connect user is not shown in the result.</p>



<p>BTW: the check results for the SmartDB properties 2 and 3 are identical because&nbsp;<code>THE_BAD_USER</code> and <code>THE_GOOD_USER</code> do not have access to write operations.</p>



<h2 class="wp-block-heading"><a name="property_4"></a>4. SQL statements are written by human hand</h2>



<p>If you generate&nbsp;<code>SELECT</code>, <code>INSERT</code>, <code>UPDATE</code>,&nbsp; <code>DELETE</code> or&nbsp;<code>MERGE</code> statements, then your application is not SmartDB.</p>



<p>I see the following reasons to generate code (including SQL statements):</p>



<ul class="wp-block-list">
<li>Don&#8217;t repeat yourself (<a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY principle</a>). Striving for DRYness leads to better data models, better designs and better code. In some cases, code generators are required to achieve the goal.</li>



<li>Reduce the overall complexity by using a domain-specific language (DSL). Enforce rules and conventions in the DSL and the code templates. This leads to a smaller code base and improves productivity.</li>
</ul>



<p>A generator creates code at design/build time or at runtime. Both approaches have pros and cons. Code generators producing code at runtime are easier to deploy but may produce more runtime errors, are harder to debug and come with a performance penalty. Code generators producing code at design/build time are more extensive and more costly to deploy, are much easier to debug, have better runtime performance and produce errors at install time rather than runtime.</p>



<p>Even if generated code should look like written by human hand, it should never become a part of your code base. Generated code is derived from something else. This &#8220;something else&#8221; (generator, code templates, generator input) is part of your code base. Do not amend generated code and keep your code base as small as possible. It&#8217;s okay to keep the generated code also in the version control system, but you should separate it from the &#8220;real code base&#8221;. It should be absolutely clear that the generated code is completely replaced by a subsequent generator run.</p>



<p>Code generators offer a high value when used correctly.&nbsp;Therefore, the general ban on the use of generators is simply ignorant.</p>



<h2 class="wp-block-heading"><a name="property_5"></a>5. SQL statements exploit the full power of set-based SQL</h2>



<p>If you use row-by-row processing when set-based SQL is feasible and noticeably faster, then your application is not SmartDB.</p>



<p>This is the most important SmartDB property. Set-based SQL is the key to good performance. It means that you are using the database as a processing engine and not as a data store only.</p>



<p>You should make it a habit to minimize the total number of executed SQL statements to get a job done. Less loops, more set-based SQL. In the end, it is simpler. You tell the database what you want and the optimizer figures out how to do it efficiently.</p>



<h2 class="wp-block-heading">Conclusion</h2>



<p>If you use set-based SQL in your application and manually craft your SQL statements, then you can check with a single SQL statement, if your application is really SmartDB. Don&#8217;t be disappointed, if it is not. Besides some demo applications, I haven&#8217;t seen a SmartDB application and I do not expect to see one soon.</p>



<p>The SmartDB idea is based on sound analysis and some good advice (see Toon Koppelaar&#8217;s excellent&nbsp;video and slide deck). But the resulting SmartDB definition overshoots the mark. It focuses too much on PL/SQL and ignores the capabilities of database-aware tools. These tools support SQL (or MDX) as the primary interface to the database (especially for queries). Using another path to the database is usually possible, but less efficient from a development cost and time-to-market perspective.</p>



<p>It looks like there is currently no&nbsp;way to refine the SmartDB definition making this approach broadly usable. The recommended alternative is to come up with your own definition. My <a href="https://www.salvis.com/blog/2018/07/18/the-pink-database-paradigm-pinkdb/">next post</a> is dealing with that topic. However, I&#8217;d still like to see a SmartDB 2.0 definition that tolerates views as part of the API, generated code and transaction control statements by the API caller.</p>
<p>The post <a href="https://www.salvis.com/blog/2018/07/18/is-your-application-smartdb/">Is Your Application SmartDB?</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.salvis.com/blog/2018/07/18/is-your-application-smartdb/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>How to Prove That Your SmartDB App Is Secure</title>
		<link>https://www.salvis.com/blog/2017/12/17/how-to-prove-that-your-smartdb-app-is-secured-against-sql-injection-attacks/</link>
					<comments>https://www.salvis.com/blog/2017/12/17/how-to-prove-that-your-smartdb-app-is-secured-against-sql-injection-attacks/#comments</comments>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Sat, 16 Dec 2017 23:46:08 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Code Analysis]]></category>
		<category><![CDATA[PinkDB]]></category>
		<category><![CDATA[PL/Scope]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[SmartDB]]></category>
		<category><![CDATA[SQL Injection]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=8010</guid>

					<description><![CDATA[<p>If you are guarding your data behind a hard shell PL/SQL API&#160;as Bryn Llewellyn, Toon Koppelaars and others recommend, then it should be quite easy to prove, that your PL/SQL application is secured against SQL injection attacks. The basic idea is 1) that you do not expose data via tables nor views<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2017/12/17/how-to-prove-that-your-smartdb-app-is-secured-against-sql-injection-attacks/">How to Prove That Your SmartDB App Is Secure</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>If you are <a href="https://community.oracle.com/servlet/JiveServlet/downloadBody/1018915-102-1-164853/Guarding_Your_Data_Behind_a_Hard_Shell_Plsql_API.pdf">guarding your data behind a hard shell PL/SQL API</a>&nbsp;as Bryn Llewellyn, Toon Koppelaars and others recommend, then it should be quite easy to prove, that your PL/SQL application is secured against <a href="https://en.wikipedia.org/wiki/SQL_injection">SQL injection</a> attacks. The basic idea is 1) that you do not expose data via tables nor views to Oracle users used in the middle-tier, by end-users and in the GUI; and 2) that you use only static SQL within PL/SQL packages. By following these two rules, you ensure that only SQL statements with bind variables are used in your application, making the injection of unwanted SQL fragments impossible. In this blog post, I show how to check if an application is complying with these two rules.</p>



<h2 class="wp-block-heading">Demo Applications</h2>



<p>I&#8217;ve prepared three tiny demo applications to visualise what guarding data behind a hard shell PL/SQL API means and how static and dynamic SQL can be used within Oracle Database 12c Release 2 (12.2). You may install these applications using <a href="https://gist.github.com/PhilippSalvisberg/052b1321b0207bd71f1f1b44eb03a8fc#file-install_demo_apps-sql">this script</a>.<br /></p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<h3 class="wp-block-heading has-text-align-center">The Good</h3>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://www.salvis.com/blog/wp-content/uploads/2017/12/the_good.png"><img loading="lazy" decoding="async" width="236" height="124" src="https://www.salvis.com/blog/wp-content/uploads/2017/12/the_good.png" alt="" class="wp-image-8043" srcset="https://www.salvis.com/blog/wp-content/uploads/2017/12/the_good.png 236w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_good-50x26.png 50w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_good-143x75.png 143w" sizes="auto, (max-width:767px) 236px, 236px" /></a></figure>
</div>


<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>


<div class="wp-block-image">
<figure class="aligncenter size-medium"><a href="https://www.salvis.com/blog/wp-content/uploads/2017/12/the_good_layers.png"><img loading="lazy" decoding="async" width="300" height="300" src="https://www.salvis.com/blog/wp-content/uploads/2017/12/the_good_layers-300x300.png" alt="" class="wp-image-8047" style="object-fit:cover" srcset="https://www.salvis.com/blog/wp-content/uploads/2017/12/the_good_layers-300x300.png 300w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_good_layers-150x150.png 150w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_good_layers-146x146.png 146w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_good_layers-50x50.png 50w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_good_layers-75x75.png 75w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_good_layers-85x85.png 85w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_good_layers-80x80.png 80w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_good_layers.png 618w" sizes="auto, (max-width:767px) 300px, 300px" /></a></figure>
</div>


<p>The table T is stored in the schema THE_GOOD_DATA and grants SELECT, INSERT, UPDATE and DELETE privileges to the schema&nbsp; THE_GOOD_API. This schema owns the PL/SQL package PKG, which implements the data access to table T via static SQL to eliminate the risk of SQL injection. The EXECUTE right on PKG is granted to THE_GOOD_USER. This user has the CONNECT role only and can be safely configured in the connection pool of the middle-tier application.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .75rem);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">The Good Data Access</span><span role="button" tabindex="0" data-code="CREATE OR REPLACE PACKAGE BODY 
   the_good_api.pkg 
AS
   FUNCTION f2 (
      p_c2 IN VARCHAR2
   ) RETURN CLOB IS
      l_result CLOB;
      l_c2 the_good_data.t.c2%TYPE;
   BEGIN
      l_c2 := p_c2;
      SELECT JSON_ARRAYAGG (
                JSON_OBJECT (
                   'c1' value c1,
                   'c2' value c2
                ) 
                RETURNING CLOB
             )
        INTO l_result
        FROM the_good_data.t
       WHERE lower(c2) LIKE '%' 
             || lower(l_c2) || '%';
      RETURN l_result;
   END f2;
END pkg;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">CREATE OR REPLACE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PACKAGE</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">BODY</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">   the_good_api.pkg </span></span>
<span class="line"><span style="color: #569CD6">AS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">FUNCTION</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">f2</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      p_c2 </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VARCHAR2</span></span>
<span class="line"><span style="color: #D4D4D4">   ) </span><span style="color: #C586C0">RETURN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">CLOB</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">l_result</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">CLOB</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">l_c2</span><span style="color: #D4D4D4"> the_good_data.t.c2%</span><span style="color: #569CD6">TYPE</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">l_c2</span><span style="color: #D4D4D4"> := p_c2;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> JSON_ARRAYAGG (</span></span>
<span class="line"><span style="color: #D4D4D4">                JSON_OBJECT (</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #CE9178">&#39;c1&#39;</span><span style="color: #D4D4D4"> value c1,</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #CE9178">&#39;c2&#39;</span><span style="color: #D4D4D4"> value c2</span></span>
<span class="line"><span style="color: #D4D4D4">                ) </span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">RETURNING</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">CLOB</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">INTO</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">l_result</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> the_good_data.t</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">lower</span><span style="color: #D4D4D4">(c2) </span><span style="color: #569CD6">LIKE</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;%&#39;</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">             || </span><span style="color: #DCDCAA">lower</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">l_c2</span><span style="color: #D4D4D4">) || </span><span style="color: #CE9178">&#39;%&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">RETURN</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">l_result</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> f2;</span></span>
<span class="line"><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> pkg;</span></span></code></pre></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<h3 class="wp-block-heading has-text-align-center">The Bad</h3>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://www.salvis.com/blog/wp-content/uploads/2017/12/the_bad.png"><img loading="lazy" decoding="async" width="236" height="124" src="https://www.salvis.com/blog/wp-content/uploads/2017/12/the_bad.png" alt="" class="wp-image-8044" srcset="https://www.salvis.com/blog/wp-content/uploads/2017/12/the_bad.png 236w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_bad-50x26.png 50w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_bad-143x75.png 143w" sizes="auto, (max-width:767px) 236px, 236px" /></a></figure>
</div>


<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>


<div class="wp-block-image">
<figure class="aligncenter size-medium"><a href="https://www.salvis.com/blog/wp-content/uploads/2017/12/the_bad_layers.png"><img loading="lazy" decoding="async" width="300" height="300" src="https://www.salvis.com/blog/wp-content/uploads/2017/12/the_bad_layers-300x300.png" alt="" class="wp-image-8048" style="object-fit:cover" srcset="https://www.salvis.com/blog/wp-content/uploads/2017/12/the_bad_layers-300x300.png 300w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_bad_layers-150x150.png 150w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_bad_layers-146x146.png 146w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_bad_layers-50x50.png 50w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_bad_layers-75x75.png 75w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_bad_layers-85x85.png 85w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_bad_layers-80x80.png 80w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_bad_layers.png 618w" sizes="auto, (max-width:767px) 300px, 300px" /></a></figure>
</div>


<p>This application looks very similar to &#8220;The Good&#8221;. One difference is, that the access to table T is implemented through dynamic SQL. There is also a private PL/SQL package named PKG2 which does a series of bad things with dynamic SQL. The implementation of all dynamic SQL is safe, there is no SQL injection possible. However, it is difficult to come to this conclusion by static code analysis and since the use of dynamic SQL is not necessary, this application is considered bad.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .75rem);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">The Bad Data Access</span><span role="button" tabindex="0" data-code="CREATE OR REPLACE PACKAGE BODY 
   the_bad_api.pkg 
AS
   FUNCTION f2 (
      p_c2 IN VARCHAR2
   ) RETURN CLOB IS
      co_sql_template CONSTANT CLOB
         := q'[
   SELECT JSON_ARRAYAGG (
             JSON_OBJECT (
                'c1' value c1, 
                'c2' value c2
             ) 
             RETURNING CLOB
          )
     FROM the_bad_data.t
    WHERE lower(c2) LIKE '%' 
          || lower(:c2_bind) || '%'
         ]';     
      l_result CLOB;
      l_c2 the_bad_data.t.c2%TYPE;
   BEGIN
      l_c2 := p_c2;
      EXECUTE IMMEDIATE 
              co_sql_template 
         INTO l_result USING l_c2;
      RETURN l_result;
   END f2;
END pkg;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">CREATE OR REPLACE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PACKAGE</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">BODY</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">   the_bad_api.pkg </span></span>
<span class="line"><span style="color: #569CD6">AS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">FUNCTION</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">f2</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      p_c2 </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VARCHAR2</span></span>
<span class="line"><span style="color: #D4D4D4">   ) </span><span style="color: #C586C0">RETURN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">CLOB</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">      co_sql_template </span><span style="color: #569CD6">CONSTANT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">CLOB</span></span>
<span class="line"><span style="color: #D4D4D4">         := q</span><span style="color: #CE9178">&#39;[</span></span>
<span class="line"><span style="color: #CE9178">   SELECT JSON_ARRAYAGG (</span></span>
<span class="line"><span style="color: #CE9178">             JSON_OBJECT (</span></span>
<span class="line"><span style="color: #CE9178">                &#39;</span><span style="color: #D4D4D4">c1</span><span style="color: #CE9178">&#39; value c1, </span></span>
<span class="line"><span style="color: #CE9178">                &#39;</span><span style="color: #D4D4D4">c2</span><span style="color: #CE9178">&#39; value c2</span></span>
<span class="line"><span style="color: #CE9178">             ) </span></span>
<span class="line"><span style="color: #CE9178">             RETURNING CLOB</span></span>
<span class="line"><span style="color: #CE9178">          )</span></span>
<span class="line"><span style="color: #CE9178">     FROM the_bad_data.t</span></span>
<span class="line"><span style="color: #CE9178">    WHERE lower(c2) LIKE &#39;</span><span style="color: #D4D4D4">%</span><span style="color: #CE9178">&#39; </span></span>
<span class="line"><span style="color: #CE9178">          || lower(:c2_bind) || &#39;</span><span style="color: #D4D4D4">%</span><span style="color: #CE9178">&#39;</span></span>
<span class="line"><span style="color: #CE9178">         ]&#39;</span><span style="color: #D4D4D4">;     </span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">l_result</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">CLOB</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">l_c2</span><span style="color: #D4D4D4"> the_bad_data.t.c2%</span><span style="color: #569CD6">TYPE</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">l_c2</span><span style="color: #D4D4D4"> := p_c2;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">EXECUTE IMMEDIATE</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">              co_sql_template </span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">INTO</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">l_result</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">USING</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">l_c2</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">RETURN</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">l_result</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> f2;</span></span>
<span class="line"><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> pkg;</span></span></code></pre></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<h3 class="wp-block-heading has-text-align-center">The Ugly</h3>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://www.salvis.com/blog/wp-content/uploads/2017/12/the_ugly.png"><img loading="lazy" decoding="async" width="236" height="124" src="https://www.salvis.com/blog/wp-content/uploads/2017/12/the_ugly.png" alt="" class="wp-image-8045" srcset="https://www.salvis.com/blog/wp-content/uploads/2017/12/the_ugly.png 236w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_ugly-50x26.png 50w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_ugly-143x75.png 143w" sizes="auto, (max-width:767px) 236px, 236px" /></a></figure>
</div>


<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>


<div class="wp-block-image">
<figure class="aligncenter size-medium"><a href="https://www.salvis.com/blog/wp-content/uploads/2017/12/the_ugly_layers-1.png"><img loading="lazy" decoding="async" width="300" height="300" src="https://www.salvis.com/blog/wp-content/uploads/2017/12/the_ugly_layers-1-300x300.png" alt="" class="wp-image-8057" style="object-fit:cover" srcset="https://www.salvis.com/blog/wp-content/uploads/2017/12/the_ugly_layers-1-300x300.png 300w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_ugly_layers-1-150x150.png 150w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_ugly_layers-1-146x146.png 146w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_ugly_layers-1-50x50.png 50w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_ugly_layers-1-75x75.png 75w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_ugly_layers-1-85x85.png 85w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_ugly_layers-1-80x80.png 80w, https://www.salvis.com/blog/wp-content/uploads/2017/12/the_ugly_layers-1.png 618w" sizes="auto, (max-width:767px) 300px, 300px" /></a></figure>
</div>


<p>The table T is stored in the schema THE_UGLY_DATA and grants SELECT, INSERT, UPDATE and DELETE privileges to THE_UGLY_USER. This user has the CONNECT role only. This is good and prohibits schema extensions. But without a PL/SQL API layer, there is no way to prevent SQL injection in the database. This is now becoming a responsibility of the middle-tier application along with other duties such as data consistency and efficient data processing.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .75rem);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">The Ugly Data Access</span><span role="button" tabindex="0" data-code="/* not available
 *
 * Query is crafted in 
 * the middle tier application
 */" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">/* not available</span></span>
<span class="line"><span style="color: #6A9955"> *</span></span>
<span class="line"><span style="color: #6A9955"> * Query is crafted in </span></span>
<span class="line"><span style="color: #6A9955"> * the middle tier application</span></span>
<span class="line"><span style="color: #6A9955"> */</span></span></code></pre></div>
</div>
</div>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Example result of a PKG.F2(&#8216;SQL&#8217;) call</span><span role="button" tabindex="0" data-code="[
   {
      &quot;c1&quot;: 2,
      &quot;c2&quot;: &quot;I like SQL.&quot;
   },
   {
      &quot;c1&quot;: 3,
      &quot;c2&quot;: &quot;And JSON is part of SQL and PL/SQL.&quot;
   }
]" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">[</span></span>
<span class="line"><span style="color: #D4D4D4">   {</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">&quot;c1&quot;</span><span style="color: #D4D4D4">: </span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">&quot;c2&quot;</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;I like SQL.&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">   },</span></span>
<span class="line"><span style="color: #D4D4D4">   {</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">&quot;c1&quot;</span><span style="color: #D4D4D4">: </span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">&quot;c2&quot;</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;And JSON is part of SQL and PL/SQL.&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">   }</span></span>
<span class="line"><span style="color: #D4D4D4">]</span></span></code></pre></div>



<h2 class="wp-block-heading">Rule 1) Do not expose data via tables nor views</h2>



<p>The idea behind a hard shell PL/SQL is to expose data through PL/SQL units only. Direct access to tables or views is unwanted. The Oracle users configured in the connection pool of the middle tier, need the CONNECT role and EXECUTE rights on the PL/SQL API only. These rights may be granted directly or indirectly via various levels of Oracle roles.</p>



<p>The following query shows if an Oracle database user is ready&nbsp;to be used in the middle-tier application. Oracle users maintained by Oracle itself, such as SYS, SYSTEM, SYSAUX, etc. are excluded along with some other users which grant objects to PUBLIC (see lines 35 to 38). To execute this query you need the SELECT_CATALOG_ROLE.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(3 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Users ready to be used in the middle tier</span><span role="button" tabindex="0" data-code="WITH
   -- roles as recursive structure
   role_base AS (
      -- roles without parent (=roots)
      SELECT r.role, NULL AS parent_role
        FROM dba_roles r
       WHERE r.role NOT IN (
                SELECT p.granted_role
                  FROM role_role_privs p
             )
      UNION ALL
      -- roles with parent (=children)
      SELECT granted_role AS role, role AS parent_role
        FROM role_role_privs
   ),
   -- roles tree, calculate role_path for every hierarchy level
   role_tree AS (
      SELECT role,
             parent_role,
             sys_connect_by_path(ROLE, '/') AS role_path
        FROM role_base
      CONNECT BY PRIOR role = parent_role
   ),
   -- roles graph, child added to all ancestors including self
   -- allows simple join to parent_role to find all descendants
   role_graph AS (
      SELECT DISTINCT
             role,
             regexp_substr(role_path, '(/)(\w+)', 1, 1, 'i', 2) AS parent_role
        FROM role_tree
   ),
   -- application users in scope of the analysis
   -- other users are treated as if they were not istalled
   app_user AS (
      SELECT username
        FROM dba_users
       WHERE oracle_maintained = 'N' -- SYS, SYSTEM, SYSAUX, ...
         AND username NOT IN ('FTLDB', 'PLSCOPE')
   ),
   -- user system privileges
   sys_priv AS (
      -- system privileges granted directly to users
      SELECT u.username, p.privilege
        FROM dba_sys_privs p
        JOIN app_user u ON u.username = p.grantee
      UNION
      -- system privileges granted directly to PUBLIC
      SELECT u.username, p.privilege
        FROM dba_sys_privs p
       CROSS JOIN app_user u
       WHERE p.grantee = 'PUBLIC'
         AND p.privilege NOT IN (
                SELECT r.role
                  FROM dba_roles r
             )
      UNION
      -- system privileges granted to users via roles
      SELECT u.username, p.privilege
        FROM dba_role_privs r
        JOIN app_user u ON u.username = r.grantee
        JOIN role_graph g ON g.parent_role = r.granted_role
        JOIN dba_sys_privs p ON p.grantee = g.role
      UNION
      -- system privileges granted to PUBLIC via roles
      SELECT u.username, p.privilege
        FROM dba_role_privs r
        JOIN role_graph g ON g.parent_role = r.granted_role
        JOIN dba_sys_privs p ON p.grantee = g.role
        CROSS JOIN app_user u
       WHERE r.grantee = 'PUBLIC'
   ),
   -- user object privileges
   obj_priv AS (
      -- objects granted directly to users
      SELECT u.username, p.owner, p.type AS object_type, p.table_name AS object_name
        FROM dba_tab_privs p
        JOIN app_user u ON u.username = p.grantee
       WHERE p.owner IN (
                SELECT u2.username
                  FROM app_user u2
             )
      UNION
      -- objects granted to users via roles
      SELECT u.username, p.owner, p.type AS object_type, p.table_name AS object_name
        FROM dba_role_privs r
        JOIN app_user u ON u.username = r.grantee
        JOIN role_graph g ON g.parent_role = r.granted_role
        JOIN dba_tab_privs p ON p.grantee = g.role
       WHERE p.owner IN (
                SELECT u2.username
                  FROM app_user u2
             )
      -- objects granted to PUBLIC
      UNION
      SELECT u.username, p.owner, p.type AS object_type, p.table_name AS object_name
        FROM dba_tab_privs p
       CROSS JOIN app_user u
       WHERE p.owner IN (
                SELECT u2.username
                  FROM app_user u2
             )
         AND p.grantee = 'PUBLIC'
   ),
   -- issues if user is configured in the connection pool of a middle tier
   issues AS (
      -- privileges not part of CONNECT role
      SELECT username,
             'SYS' AS owner,
             'PRIVILEGE' AS object_type,
             privilege AS object_name,
             'Privilege is not part of the CONNECT role' AS issue
        FROM sys_priv
       WHERE privilege NOT IN ('CREATE SESSION', 'SET CONTAINER')
      UNION ALL
      -- access to non PL/SQL units
      SELECT username,
             owner,
             object_type,
             object_name,
             'Access to non-PL/SQL unit'
        FROM obj_priv
       WHERE object_type NOT IN ('PACKAGE', 'TYPE', 'FUNCTION', 'PROCEDURE')
      -- own objects
      UNION ALL
      SELECT u.username,
             o.owner,
             o.object_type,
             o.object_name,
             'Connect user must not own any object'
        FROM app_user u
        JOIN dba_objects o ON o.owner = u.username
      -- missing CREATE SESSION privilege
      UNION ALL
      SELECT u.username,
             'SYS',
             'PRIVILEGE',
             'CREATE SESSION',
             'Privilege is missing, but required'
        FROM app_user u
       WHERE u.username NOT IN (
                SELECT username
                  FROM sys_priv
                 WHERE privilege = 'CREATE SESSION' 
             )
   ),
   -- aggregate issues per user
   issue_aggr AS (
      SELECT u.username, COUNT(i.username) issue_count
        FROM app_user u
        LEFT JOIN issues i ON i.username = u.username
       GROUP BY u.username
   ),
   -- user summary (calculate is_connect_user_ready)
   summary AS (
      SELECT username,
             CASE
                WHEN issue_count = 0 THEN
                   'YES'
                ELSE
                   'NO'
             END AS is_connect_user_ready,
             issue_count
        FROM issue_aggr
       ORDER BY is_connect_user_ready DESC, username
   )
-- main
SELECT * 
  FROM summary
 WHERE username LIKE 'THE%';
 
USERNAME      IS_CONNECT_USER_READY ISSUE_COUNT
------------- --------------------- -----------
THE_BAD_USER  YES                             0
THE_GOOD_USER YES                             0
THE_BAD_API   NO                              9
THE_BAD_DATA  NO                              3
THE_GOOD_API  NO                              4
THE_GOOD_DATA NO                              3
THE_UGLY_DATA NO                             10
THE_UGLY_USER NO                              1
 
8 rows selected." style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">WITH</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- roles as recursive structure</span></span>
<span class="line"><span style="color: #D4D4D4">   role_base </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- roles without parent (=roots)</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> r.role, </span><span style="color: #569CD6">NULL</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> parent_role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_roles r</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> r.role </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> p.granted_role</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> role_role_privs p</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION ALL</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- roles with parent (=children)</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> granted_role </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">role</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> parent_role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> role_role_privs</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- roles tree, calculate role_path for every hierarchy level</span></span>
<span class="line"><span style="color: #D4D4D4">   role_tree </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             parent_role,</span></span>
<span class="line"><span style="color: #D4D4D4">             sys_connect_by_path(</span><span style="color: #569CD6">ROLE</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;/&#39;</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> role_path</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> role_base</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">CONNECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">BY</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PRIOR</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span><span style="color: #D4D4D4"> = parent_role</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- roles graph, child added to all ancestors including self</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- allows simple join to parent_role to find all descendants</span></span>
<span class="line"><span style="color: #D4D4D4">   role_graph </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT DISTINCT</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">role</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             regexp_substr(role_path, </span><span style="color: #CE9178">&#39;(/)(\w+)&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;i&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> parent_role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> role_tree</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- application users in scope of the analysis</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- other users are treated as if they were not istalled</span></span>
<span class="line"><span style="color: #D4D4D4">   app_user </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_users</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> oracle_maintained = </span><span style="color: #CE9178">&#39;N&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #6A9955">-- SYS, SYSTEM, SYSAUX, ...</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> username </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;FTLDB&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PLSCOPE&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- user system privileges</span></span>
<span class="line"><span style="color: #D4D4D4">   sys_priv </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- system privileges granted directly to users</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.privilege</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_sys_privs p</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = p.grantee</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- system privileges granted directly to PUBLIC</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.privilege</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_sys_privs p</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">CROSS JOIN</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> p.grantee = </span><span style="color: #CE9178">&#39;PUBLIC&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> p.privilege </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> r.role</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_roles r</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- system privileges granted to users via roles</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.privilege</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_role_privs r</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = r.grantee</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> role_graph g </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> g.parent_role = r.granted_role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> dba_sys_privs p </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> p.grantee = g.role</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- system privileges granted to PUBLIC via roles</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.privilege</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_role_privs r</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> role_graph g </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> g.parent_role = r.granted_role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> dba_sys_privs p </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> p.grantee = g.role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">CROSS JOIN</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> r.grantee = </span><span style="color: #CE9178">&#39;PUBLIC&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- user object privileges</span></span>
<span class="line"><span style="color: #D4D4D4">   obj_priv </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- objects granted directly to users</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.owner, p.type </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_type, p.table_name </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_name</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_tab_privs p</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = p.grantee</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> p.owner </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u2.username</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u2</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- objects granted to users via roles</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.owner, p.type </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_type, p.table_name </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_name</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_role_privs r</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = r.grantee</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> role_graph g </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> g.parent_role = r.granted_role</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> dba_tab_privs p </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> p.grantee = g.role</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> p.owner </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u2.username</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u2</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- objects granted to PUBLIC</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, p.owner, p.type </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_type, p.table_name </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_name</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_tab_privs p</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">CROSS JOIN</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> p.owner </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u2.username</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u2</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> p.grantee = </span><span style="color: #CE9178">&#39;PUBLIC&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- issues if user is configured in the connection pool of a middle tier</span></span>
<span class="line"><span style="color: #D4D4D4">   issues </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- privileges not part of CONNECT role</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;SYS&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;PRIVILEGE&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_type,</span></span>
<span class="line"><span style="color: #D4D4D4">             privilege </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_name,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;Privilege is not part of the CONNECT role&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> issue</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> sys_priv</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> privilege </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;CREATE SESSION&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;SET CONTAINER&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION ALL</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- access to non PL/SQL units</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             object_type,</span></span>
<span class="line"><span style="color: #D4D4D4">             object_name,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;Access to non-PL/SQL unit&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> obj_priv</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> object_type </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;PACKAGE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TYPE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;FUNCTION&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PROCEDURE&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- own objects</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION ALL</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username,</span></span>
<span class="line"><span style="color: #D4D4D4">             o.owner,</span></span>
<span class="line"><span style="color: #D4D4D4">             o.object_type,</span></span>
<span class="line"><span style="color: #D4D4D4">             o.object_name,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;Connect user must not own any object&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> dba_objects o </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> o.owner = u.username</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">-- missing CREATE SESSION privilege</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION ALL</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;SYS&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;PRIVILEGE&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;CREATE SESSION&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;Privilege is missing, but required&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> u.username </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> sys_priv</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> privilege = </span><span style="color: #CE9178">&#39;CREATE SESSION&#39;</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- aggregate issues per user</span></span>
<span class="line"><span style="color: #D4D4D4">   issue_aggr </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username, </span><span style="color: #DCDCAA">COUNT</span><span style="color: #D4D4D4">(i.username) issue_count</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">LEFT JOIN</span><span style="color: #D4D4D4"> issues i </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> i.username = u.username</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">GROUP BY</span><span style="color: #D4D4D4"> u.username</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">-- user summary (calculate is_connect_user_ready)</span></span>
<span class="line"><span style="color: #D4D4D4">   summary </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">CASE</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">WHEN</span><span style="color: #D4D4D4"> issue_count = </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #CE9178">&#39;YES&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">ELSE</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #CE9178">&#39;NO&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> is_connect_user_ready,</span></span>
<span class="line"><span style="color: #D4D4D4">             issue_count</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> issue_aggr</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">ORDER BY</span><span style="color: #D4D4D4"> is_connect_user_ready </span><span style="color: #569CD6">DESC</span><span style="color: #D4D4D4">, username</span></span>
<span class="line"><span style="color: #D4D4D4">   )</span></span>
<span class="line"><span style="color: #6A9955">-- main</span></span>
<span class="line"><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> * </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> summary</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> username </span><span style="color: #569CD6">LIKE</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;THE%&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">USERNAME      IS_CONNECT_USER_READY ISSUE_COUNT</span></span>
<span class="line"><span style="color: #6A9955">------------- --------------------- -----------</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">THE_BAD_USER  YES                             </span><span style="color: #B5CEA8">0</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">THE_GOOD_USER YES                             </span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   </span><span style="color: #569CD6">NO</span><span style="color: #D4D4D4">                              </span><span style="color: #B5CEA8">9</span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_DATA  </span><span style="color: #569CD6">NO</span><span style="color: #D4D4D4">                              </span><span style="color: #B5CEA8">3</span></span>
<span class="line"><span style="color: #D4D4D4">THE_GOOD_API  </span><span style="color: #569CD6">NO</span><span style="color: #D4D4D4">                              </span><span style="color: #B5CEA8">4</span></span>
<span class="line"><span style="color: #D4D4D4">THE_GOOD_DATA </span><span style="color: #569CD6">NO</span><span style="color: #D4D4D4">                              </span><span style="color: #B5CEA8">3</span></span>
<span class="line"><span style="color: #D4D4D4">THE_UGLY_DATA </span><span style="color: #569CD6">NO</span><span style="color: #D4D4D4">                             </span><span style="color: #B5CEA8">10</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">THE_UGLY_USER </span><span style="color: #569CD6">NO</span><span style="color: #D4D4D4">                              </span><span style="color: #B5CEA8">1</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #B5CEA8">8</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">rows</span><span style="color: #D4D4D4"> selected.</span></span></code></pre></div>



<p>Just THE_GOOD_USER and THE_BAD_USER are ready to be used in the middle tier. To see the issues of all other users you may simply change the main part of the query as follows:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-start:166;--cbp-line-number-width:calc(3 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">All rule 1 issues</span><span role="button" tabindex="0" data-code="-- main
SELECT * 
  FROM issues
 WHERE username LIKE 'THE%'
 ORDER BY username, owner, object_type, object_name;

USERNAME      OWNER         OBJECT_TYPE  OBJECT_NAME          ISSUE                                    
------------- ------------- ------------ -------------------- -----------------------------------------
THE_BAD_API   SYS           PRIVILEGE    CREATE DATABASE LINK Privilege is not part of the CONNECT role
THE_BAD_API   SYS           PRIVILEGE    CREATE PROCEDURE     Privilege is not part of the CONNECT role
THE_BAD_API   THE_BAD_API   JAVA CLASS   C                    Connect user must not own any object     
THE_BAD_API   THE_BAD_API   JAVA SOURCE  C                    Connect user must not own any object     
THE_BAD_API   THE_BAD_API   PACKAGE      PKG                  Connect user must not own any object     
THE_BAD_API   THE_BAD_API   PACKAGE      PKG2                 Connect user must not own any object     
THE_BAD_API   THE_BAD_API   PACKAGE BODY PKG                  Connect user must not own any object     
THE_BAD_API   THE_BAD_API   PACKAGE BODY PKG2                 Connect user must not own any object     
THE_BAD_API   THE_BAD_DATA  TABLE        T                    Access to non-PL/SQL unit                
THE_BAD_DATA  SYS           PRIVILEGE    CREATE TABLE         Privilege is not part of the CONNECT role
THE_BAD_DATA  THE_BAD_DATA  INDEX        SYS_C0012875         Connect user must not own any object     
THE_BAD_DATA  THE_BAD_DATA  TABLE        T                    Connect user must not own any object     
THE_GOOD_API  SYS           PRIVILEGE    CREATE PROCEDURE     Privilege is not part of the CONNECT role
THE_GOOD_API  THE_GOOD_API  PACKAGE      PKG                  Connect user must not own any object     
THE_GOOD_API  THE_GOOD_API  PACKAGE BODY PKG                  Connect user must not own any object     
THE_GOOD_API  THE_GOOD_DATA TABLE        T                    Access to non-PL/SQL unit                
THE_GOOD_DATA SYS           PRIVILEGE    CREATE TABLE         Privilege is not part of the CONNECT role
THE_GOOD_DATA THE_GOOD_DATA INDEX        SYS_C0012873         Connect user must not own any object     
THE_GOOD_DATA THE_GOOD_DATA TABLE        T                    Connect user must not own any object     
THE_UGLY_DATA SYS           PRIVILEGE    CREATE CLUSTER       Privilege is not part of the CONNECT role
THE_UGLY_DATA SYS           PRIVILEGE    CREATE INDEXTYPE     Privilege is not part of the CONNECT role
THE_UGLY_DATA SYS           PRIVILEGE    CREATE OPERATOR      Privilege is not part of the CONNECT role
THE_UGLY_DATA SYS           PRIVILEGE    CREATE PROCEDURE     Privilege is not part of the CONNECT role
THE_UGLY_DATA SYS           PRIVILEGE    CREATE SEQUENCE      Privilege is not part of the CONNECT role
THE_UGLY_DATA SYS           PRIVILEGE    CREATE TABLE         Privilege is not part of the CONNECT role
THE_UGLY_DATA SYS           PRIVILEGE    CREATE TRIGGER       Privilege is not part of the CONNECT role
THE_UGLY_DATA SYS           PRIVILEGE    CREATE TYPE          Privilege is not part of the CONNECT role
THE_UGLY_DATA THE_UGLY_DATA INDEX        SYS_C0012877         Connect user must not own any object     
THE_UGLY_DATA THE_UGLY_DATA TABLE        T                    Connect user must not own any object     
THE_UGLY_USER THE_UGLY_DATA TABLE        T                    Access to non-PL/SQL unit                

30 rows selected." style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">-- main</span></span>
<span class="line"><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> * </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> issues</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> username </span><span style="color: #569CD6">LIKE</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;THE%&#39;</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">ORDER BY</span><span style="color: #D4D4D4"> username, </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">, object_type, object_name;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">USERNAME      </span><span style="color: #569CD6">OWNER</span><span style="color: #D4D4D4">         OBJECT_TYPE  OBJECT_NAME          ISSUE                                    </span></span>
<span class="line"><span style="color: #6A9955">------------- ------------- ------------ -------------------- -----------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   SYS           PRIVILEGE    </span><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">DATABASE</span><span style="color: #D4D4D4"> LINK Privilege </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> part of the </span><span style="color: #569CD6">CONNECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   SYS           PRIVILEGE    </span><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4">     Privilege </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> part of the </span><span style="color: #569CD6">CONNECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   THE_BAD_API   JAVA CLASS   C                    </span><span style="color: #569CD6">Connect</span><span style="color: #D4D4D4"> user must </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> own any </span><span style="color: #569CD6">object</span><span style="color: #D4D4D4">     </span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   THE_BAD_API   JAVA SOURCE  C                    </span><span style="color: #569CD6">Connect</span><span style="color: #D4D4D4"> user must </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> own any </span><span style="color: #569CD6">object</span><span style="color: #D4D4D4">     </span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   THE_BAD_API   PACKAGE      PKG                  </span><span style="color: #569CD6">Connect</span><span style="color: #D4D4D4"> user must </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> own any </span><span style="color: #569CD6">object</span><span style="color: #D4D4D4">     </span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   THE_BAD_API   PACKAGE      PKG2                 </span><span style="color: #569CD6">Connect</span><span style="color: #D4D4D4"> user must </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> own any </span><span style="color: #569CD6">object</span><span style="color: #D4D4D4">     </span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   THE_BAD_API   PACKAGE BODY PKG                  </span><span style="color: #569CD6">Connect</span><span style="color: #D4D4D4"> user must </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> own any </span><span style="color: #569CD6">object</span><span style="color: #D4D4D4">     </span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   THE_BAD_API   PACKAGE BODY PKG2                 </span><span style="color: #569CD6">Connect</span><span style="color: #D4D4D4"> user must </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> own any </span><span style="color: #569CD6">object</span><span style="color: #D4D4D4">     </span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   THE_BAD_DATA  </span><span style="color: #569CD6">TABLE</span><span style="color: #D4D4D4">        T                    Access </span><span style="color: #569CD6">to</span><span style="color: #D4D4D4"> non-PL/</span><span style="color: #569CD6">SQL</span><span style="color: #D4D4D4"> unit                </span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_DATA  SYS           PRIVILEGE    </span><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">TABLE</span><span style="color: #D4D4D4">         Privilege </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> part of the </span><span style="color: #569CD6">CONNECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_DATA  THE_BAD_DATA  </span><span style="color: #569CD6">INDEX</span><span style="color: #D4D4D4">        SYS_C0012875         </span><span style="color: #569CD6">Connect</span><span style="color: #D4D4D4"> user must </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> own any </span><span style="color: #569CD6">object</span><span style="color: #D4D4D4">     </span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_DATA  THE_BAD_DATA  </span><span style="color: #569CD6">TABLE</span><span style="color: #D4D4D4">        T                    </span><span style="color: #569CD6">Connect</span><span style="color: #D4D4D4"> user must </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> own any </span><span style="color: #569CD6">object</span><span style="color: #D4D4D4">     </span></span>
<span class="line"><span style="color: #D4D4D4">THE_GOOD_API  SYS           PRIVILEGE    </span><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4">     Privilege </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> part of the </span><span style="color: #569CD6">CONNECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span></span>
<span class="line"><span style="color: #D4D4D4">THE_GOOD_API  THE_GOOD_API  PACKAGE      PKG                  </span><span style="color: #569CD6">Connect</span><span style="color: #D4D4D4"> user must </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> own any </span><span style="color: #569CD6">object</span><span style="color: #D4D4D4">     </span></span>
<span class="line"><span style="color: #D4D4D4">THE_GOOD_API  THE_GOOD_API  PACKAGE BODY PKG                  </span><span style="color: #569CD6">Connect</span><span style="color: #D4D4D4"> user must </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> own any </span><span style="color: #569CD6">object</span><span style="color: #D4D4D4">     </span></span>
<span class="line"><span style="color: #D4D4D4">THE_GOOD_API  THE_GOOD_DATA </span><span style="color: #569CD6">TABLE</span><span style="color: #D4D4D4">        T                    Access </span><span style="color: #569CD6">to</span><span style="color: #D4D4D4"> non-PL/</span><span style="color: #569CD6">SQL</span><span style="color: #D4D4D4"> unit                </span></span>
<span class="line"><span style="color: #D4D4D4">THE_GOOD_DATA SYS           PRIVILEGE    </span><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">TABLE</span><span style="color: #D4D4D4">         Privilege </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> part of the </span><span style="color: #569CD6">CONNECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span></span>
<span class="line"><span style="color: #D4D4D4">THE_GOOD_DATA THE_GOOD_DATA </span><span style="color: #569CD6">INDEX</span><span style="color: #D4D4D4">        SYS_C0012873         </span><span style="color: #569CD6">Connect</span><span style="color: #D4D4D4"> user must </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> own any </span><span style="color: #569CD6">object</span><span style="color: #D4D4D4">     </span></span>
<span class="line"><span style="color: #D4D4D4">THE_GOOD_DATA THE_GOOD_DATA </span><span style="color: #569CD6">TABLE</span><span style="color: #D4D4D4">        T                    </span><span style="color: #569CD6">Connect</span><span style="color: #D4D4D4"> user must </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> own any </span><span style="color: #569CD6">object</span><span style="color: #D4D4D4">     </span></span>
<span class="line"><span style="color: #D4D4D4">THE_UGLY_DATA SYS           PRIVILEGE    </span><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> CLUSTER       Privilege </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> part of the </span><span style="color: #569CD6">CONNECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span></span>
<span class="line"><span style="color: #D4D4D4">THE_UGLY_DATA SYS           PRIVILEGE    </span><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> INDEXTYPE     Privilege </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> part of the </span><span style="color: #569CD6">CONNECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span></span>
<span class="line"><span style="color: #D4D4D4">THE_UGLY_DATA SYS           PRIVILEGE    </span><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> OPERATOR      Privilege </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> part of the </span><span style="color: #569CD6">CONNECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span></span>
<span class="line"><span style="color: #D4D4D4">THE_UGLY_DATA SYS           PRIVILEGE    </span><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4">     Privilege </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> part of the </span><span style="color: #569CD6">CONNECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span></span>
<span class="line"><span style="color: #D4D4D4">THE_UGLY_DATA SYS           PRIVILEGE    </span><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">SEQUENCE</span><span style="color: #D4D4D4">      Privilege </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> part of the </span><span style="color: #569CD6">CONNECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span></span>
<span class="line"><span style="color: #D4D4D4">THE_UGLY_DATA SYS           PRIVILEGE    </span><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">TABLE</span><span style="color: #D4D4D4">         Privilege </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> part of the </span><span style="color: #569CD6">CONNECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span></span>
<span class="line"><span style="color: #D4D4D4">THE_UGLY_DATA SYS           PRIVILEGE    </span><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> TRIGGER       Privilege </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> part of the </span><span style="color: #569CD6">CONNECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span></span>
<span class="line"><span style="color: #D4D4D4">THE_UGLY_DATA SYS           PRIVILEGE    </span><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">TYPE</span><span style="color: #D4D4D4">          Privilege </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> part of the </span><span style="color: #569CD6">CONNECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">role</span></span>
<span class="line"><span style="color: #D4D4D4">THE_UGLY_DATA THE_UGLY_DATA </span><span style="color: #569CD6">INDEX</span><span style="color: #D4D4D4">        SYS_C0012877         </span><span style="color: #569CD6">Connect</span><span style="color: #D4D4D4"> user must </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> own any </span><span style="color: #569CD6">object</span><span style="color: #D4D4D4">     </span></span>
<span class="line"><span style="color: #D4D4D4">THE_UGLY_DATA THE_UGLY_DATA </span><span style="color: #569CD6">TABLE</span><span style="color: #D4D4D4">        T                    </span><span style="color: #569CD6">Connect</span><span style="color: #D4D4D4"> user must </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> own any </span><span style="color: #569CD6">object</span><span style="color: #D4D4D4">     </span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">THE_UGLY_USER THE_UGLY_DATA </span><span style="color: #569CD6">TABLE</span><span style="color: #D4D4D4">        T                    Access </span><span style="color: #569CD6">to</span><span style="color: #D4D4D4"> non-PL/</span><span style="color: #569CD6">SQL</span><span style="color: #D4D4D4"> unit                </span></span>
<span class="line"></span>
<span class="line"><span style="color: #B5CEA8">30</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">rows</span><span style="color: #D4D4D4"> selected.</span></span></code></pre></div>



<p>THE_UGLY_USER has access to table T owned by THE_UGLY_DATA. This violates rule 1.</p>



<p>However, it is important to note, that we have excluded all Oracle maintained users from the analysis. So let&#8217;s have a look at all the tables and views granted to PUBLIC by the Oracle-maintained users.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Privileges on tables and views granted to PUBLIC</span><span role="button" tabindex="0" data-code="WITH
   public_privs AS (
      SELECT p.owner, 
             p.type       AS object_type, 
             p.privilege, 
             count(*)     AS priv_count
        FROM dba_tab_privs p
       WHERE p.grantee = 'PUBLIC'
         AND p.type IN ('VIEW', 'TABLE')
         AND p.owner IN (
                SELECT u2.username 
                  FROM dba_users u2 
                 WHERE u2.oracle_maintained = 'Y'
             )
       GROUP BY p.owner, p.type, p.privilege  
   ),
   public_privs_pivot AS (
      SELECT owner,
             object_type,
             insert_priv,
             update_priv,
             delete_priv,
             select_priv, -- allows SELECT ... FOR UPDATE ...
             read_priv,   -- does not allow SELECT ... FOR UPDATE ...
             flashback_priv,
             nvl(insert_priv,0) + nvl(update_priv,0) + nvl(delete_priv,0) 
             + nvl(select_priv,0) + nvl(read_priv,0) 
             + nvl(flashback_priv,0) AS total_priv
        FROM public_privs
       PIVOT (
                sum(priv_count) FOR privilege IN (
                   'INSERT'    AS insert_priv, 
                   'UPDATE'    AS update_priv, 
                   'DELETE'    AS delete_priv, 
                   'SELECT'    AS select_priv, 
                   'READ'      AS read_priv, 
                   'FLASHBACK' AS flashback_priv
                )
             )
       ORDER BY owner
   ),
   public_privs_report AS (
      SELECT owner,
             object_type,
             sum(insert_priv)    AS &quot;INSERT&quot;,
             sum(update_priv)    AS &quot;UPDATE&quot;,
             sum(delete_priv)    AS &quot;DELETE&quot;,
             sum(select_priv)    AS &quot;SELECT&quot;,
             sum(read_priv)      AS &quot;READ&quot;,
             sum(flashback_priv) AS &quot;FLASHBACK&quot;,
             sum(total_priv)     AS &quot;TOTAL&quot;
        FROM public_privs_pivot
       GROUP BY ROLLUP(owner, object_type)
      HAVING (GROUPING(owner), GROUPING(object_type)) IN ((0,0), (1,1))
       ORDER BY owner, object_type
   )
-- main
SELECT * FROM public_privs_report;

OWNER             OBJECT_TYPE     INSERT     UPDATE     DELETE     SELECT       READ  FLASHBACK      TOTAL
----------------- ----------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
APEX_050100       VIEW                 1          1          4          5        192                   203
CTXSYS            TABLE                                                 1          4                     5
CTXSYS            VIEW                11          5          8         12         51                    87
GSMADMIN_INTERNAL VIEW                                                             3                     3
LBACSYS           VIEW                                                            18                    18
MDSYS             TABLE               21         14         19         21         36                   111
MDSYS             VIEW                27         26         26         26         68                   173
OLAPSYS           VIEW                                                            18                    18
ORDDATA           VIEW                                       1                     5                     6
ORDSYS            VIEW                                                             5                     5
ORDS_METADATA     VIEW                                                 20                               20
SYS               TABLE               21         10         16         30         12                    89
SYS               VIEW                                                  1       1717          2       1720
SYSTEM            TABLE                3          3          3          4                               13
SYSTEM            VIEW                                                  1                                1
WMSYS             VIEW                                                            40                    40
XDB               TABLE                8          6          8          8         14                    44
XDB               VIEW                 2          2          2          2          3                    11
                                      94         67         87        131       2186          2       2567

19 rows selected." style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">WITH</span></span>
<span class="line"><span style="color: #D4D4D4">   public_privs </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> p.owner, </span></span>
<span class="line"><span style="color: #D4D4D4">             p.type       </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> object_type, </span></span>
<span class="line"><span style="color: #D4D4D4">             p.privilege, </span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">(*)     </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> priv_count</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_tab_privs p</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> p.grantee = </span><span style="color: #CE9178">&#39;PUBLIC&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> p.type </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;VIEW&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TABLE&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> p.owner </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u2.username </span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_users u2 </span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> u2.oracle_maintained = </span><span style="color: #CE9178">&#39;Y&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">GROUP BY</span><span style="color: #D4D4D4"> p.owner, p.type, p.privilege  </span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   public_privs_pivot </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             object_type,</span></span>
<span class="line"><span style="color: #D4D4D4">             insert_priv,</span></span>
<span class="line"><span style="color: #D4D4D4">             update_priv,</span></span>
<span class="line"><span style="color: #D4D4D4">             delete_priv,</span></span>
<span class="line"><span style="color: #D4D4D4">             select_priv, </span><span style="color: #6A9955">-- allows SELECT ... FOR UPDATE ...</span></span>
<span class="line"><span style="color: #D4D4D4">             read_priv,   </span><span style="color: #6A9955">-- does not allow SELECT ... FOR UPDATE ...</span></span>
<span class="line"><span style="color: #D4D4D4">             flashback_priv,</span></span>
<span class="line"><span style="color: #D4D4D4">             nvl(insert_priv,</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">) + nvl(update_priv,</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">) + nvl(delete_priv,</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">) </span></span>
<span class="line"><span style="color: #D4D4D4">             + nvl(select_priv,</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">) + nvl(read_priv,</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">) </span></span>
<span class="line"><span style="color: #D4D4D4">             + nvl(flashback_priv,</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> total_priv</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> public_privs</span></span>
<span class="line"><span style="color: #D4D4D4">       PIVOT (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #DCDCAA">sum</span><span style="color: #D4D4D4">(priv_count) </span><span style="color: #569CD6">FOR</span><span style="color: #D4D4D4"> privilege </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #CE9178">&#39;INSERT&#39;</span><span style="color: #D4D4D4">    </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> insert_priv, </span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #CE9178">&#39;UPDATE&#39;</span><span style="color: #D4D4D4">    </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> update_priv, </span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #CE9178">&#39;DELETE&#39;</span><span style="color: #D4D4D4">    </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> delete_priv, </span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #CE9178">&#39;SELECT&#39;</span><span style="color: #D4D4D4">    </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> select_priv, </span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #CE9178">&#39;READ&#39;</span><span style="color: #D4D4D4">      </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> read_priv, </span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #CE9178">&#39;FLASHBACK&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> flashback_priv</span></span>
<span class="line"><span style="color: #D4D4D4">                )</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">ORDER BY</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   public_privs_report </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             object_type,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #DCDCAA">sum</span><span style="color: #D4D4D4">(insert_priv)    </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;INSERT&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #DCDCAA">sum</span><span style="color: #D4D4D4">(update_priv)    </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;UPDATE&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #DCDCAA">sum</span><span style="color: #D4D4D4">(delete_priv)    </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;DELETE&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #DCDCAA">sum</span><span style="color: #D4D4D4">(select_priv)    </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;SELECT&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #DCDCAA">sum</span><span style="color: #D4D4D4">(read_priv)      </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;READ&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #DCDCAA">sum</span><span style="color: #D4D4D4">(flashback_priv) </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;FLASHBACK&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #DCDCAA">sum</span><span style="color: #D4D4D4">(total_priv)     </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;TOTAL&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> public_privs_pivot</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">GROUP BY</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">ROLLUP</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">, object_type)</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">HAVING</span><span style="color: #D4D4D4"> (</span><span style="color: #DCDCAA">GROUPING</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">), </span><span style="color: #DCDCAA">GROUPING</span><span style="color: #D4D4D4">(object_type)) </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> ((</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">,</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">), (</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">,</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">))</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">ORDER BY</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">, object_type</span></span>
<span class="line"><span style="color: #D4D4D4">   )</span></span>
<span class="line"><span style="color: #6A9955">-- main</span></span>
<span class="line"><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> * </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> public_privs_report;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">OWNER</span><span style="color: #D4D4D4">             OBJECT_TYPE     </span><span style="color: #569CD6">INSERT</span><span style="color: #D4D4D4">     </span><span style="color: #569CD6">UPDATE</span><span style="color: #D4D4D4">     </span><span style="color: #569CD6">DELETE</span><span style="color: #D4D4D4">     </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4">       </span><span style="color: #569CD6">READ</span><span style="color: #D4D4D4">  FLASHBACK      TOTAL</span></span>
<span class="line"><span style="color: #6A9955">----------------- ----------- ---------- ---------- ---------- ---------- ---------- ---------- ----------</span></span>
<span class="line"><span style="color: #D4D4D4">APEX_050100       VIEW                 </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">4</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">5</span><span style="color: #D4D4D4">        </span><span style="color: #B5CEA8">192</span><span style="color: #D4D4D4">                   </span><span style="color: #B5CEA8">203</span></span>
<span class="line"><span style="color: #D4D4D4">CTXSYS            </span><span style="color: #569CD6">TABLE</span><span style="color: #D4D4D4">                                                 </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">4</span><span style="color: #D4D4D4">                     </span><span style="color: #B5CEA8">5</span></span>
<span class="line"><span style="color: #D4D4D4">CTXSYS            VIEW                </span><span style="color: #B5CEA8">11</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">5</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">8</span><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">12</span><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">51</span><span style="color: #D4D4D4">                    </span><span style="color: #B5CEA8">87</span></span>
<span class="line"><span style="color: #D4D4D4">GSMADMIN_INTERNAL VIEW                                                             </span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">                     </span><span style="color: #B5CEA8">3</span></span>
<span class="line"><span style="color: #D4D4D4">LBACSYS           VIEW                                                            </span><span style="color: #B5CEA8">18</span><span style="color: #D4D4D4">                    </span><span style="color: #B5CEA8">18</span></span>
<span class="line"><span style="color: #D4D4D4">MDSYS             </span><span style="color: #569CD6">TABLE</span><span style="color: #D4D4D4">               </span><span style="color: #B5CEA8">21</span><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">14</span><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">19</span><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">21</span><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">36</span><span style="color: #D4D4D4">                   </span><span style="color: #B5CEA8">111</span></span>
<span class="line"><span style="color: #D4D4D4">MDSYS             VIEW                </span><span style="color: #B5CEA8">27</span><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">26</span><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">26</span><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">26</span><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">68</span><span style="color: #D4D4D4">                   </span><span style="color: #B5CEA8">173</span></span>
<span class="line"><span style="color: #D4D4D4">OLAPSYS           VIEW                                                            </span><span style="color: #B5CEA8">18</span><span style="color: #D4D4D4">                    </span><span style="color: #B5CEA8">18</span></span>
<span class="line"><span style="color: #D4D4D4">ORDDATA           VIEW                                       </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">                     </span><span style="color: #B5CEA8">5</span><span style="color: #D4D4D4">                     </span><span style="color: #B5CEA8">6</span></span>
<span class="line"><span style="color: #D4D4D4">ORDSYS            VIEW                                                             </span><span style="color: #B5CEA8">5</span><span style="color: #D4D4D4">                     </span><span style="color: #B5CEA8">5</span></span>
<span class="line"><span style="color: #D4D4D4">ORDS_METADATA     VIEW                                                 </span><span style="color: #B5CEA8">20</span><span style="color: #D4D4D4">                               </span><span style="color: #B5CEA8">20</span></span>
<span class="line"><span style="color: #D4D4D4">SYS               </span><span style="color: #569CD6">TABLE</span><span style="color: #D4D4D4">               </span><span style="color: #B5CEA8">21</span><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">16</span><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">30</span><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">12</span><span style="color: #D4D4D4">                    </span><span style="color: #B5CEA8">89</span></span>
<span class="line"><span style="color: #D4D4D4">SYS               VIEW                                                  </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">       </span><span style="color: #B5CEA8">1717</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">       </span><span style="color: #B5CEA8">1720</span></span>
<span class="line"><span style="color: #569CD6">SYSTEM</span><span style="color: #D4D4D4">            </span><span style="color: #569CD6">TABLE</span><span style="color: #D4D4D4">                </span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">4</span><span style="color: #D4D4D4">                               </span><span style="color: #B5CEA8">13</span></span>
<span class="line"><span style="color: #569CD6">SYSTEM</span><span style="color: #D4D4D4">            VIEW                                                  </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">                                </span><span style="color: #B5CEA8">1</span></span>
<span class="line"><span style="color: #D4D4D4">WMSYS             VIEW                                                            </span><span style="color: #B5CEA8">40</span><span style="color: #D4D4D4">                    </span><span style="color: #B5CEA8">40</span></span>
<span class="line"><span style="color: #D4D4D4">XDB               </span><span style="color: #569CD6">TABLE</span><span style="color: #D4D4D4">                </span><span style="color: #B5CEA8">8</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">6</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">8</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">8</span><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">14</span><span style="color: #D4D4D4">                    </span><span style="color: #B5CEA8">44</span></span>
<span class="line"><span style="color: #D4D4D4">XDB               VIEW                 </span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">                    </span><span style="color: #B5CEA8">11</span></span>
<span class="line"><span style="color: #D4D4D4">                                      </span><span style="color: #B5CEA8">94</span><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">67</span><span style="color: #D4D4D4">         </span><span style="color: #B5CEA8">87</span><span style="color: #D4D4D4">        </span><span style="color: #B5CEA8">131</span><span style="color: #D4D4D4">       </span><span style="color: #B5CEA8">2186</span><span style="color: #D4D4D4">          </span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">       </span><span style="color: #B5CEA8">2567</span></span>
<span class="line"></span>
<span class="line"><span style="color: #B5CEA8">19</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">rows</span><span style="color: #D4D4D4"> selected.</span></span></code></pre></div>



<p>Even THE_GOOD_USER has access to 2317 views and tables. To reduce this number we have to uninstall some components, but that&#8217;s just a drop in the ocean. There is currently no way to create an Oracle user without access to views and tables. Hence we just have to focus on our application and our data.</p>



<h2 class="wp-block-heading">Rule 2) Use only static SQL within PL/SQL</h2>



<p>If you use just static SQL in your PL/SQL units, then no SQL injection is possible. The absence of dynamic SQL proves that your application is secured against SQL injection attacks. Of course, there are good reasons for dynamic SQL. However, proving that a dynamic SQL is not injectable is difficult. Checking for the absence of dynamic SQL is the simpler approach, even if it is not as easy as I initially thought.</p>



<p>In&nbsp;<a href="http://www.oracle.com/technetwork/database/features/plsql/overview/how-to-write-injection-proof-plsql-1-129572.pdf">How to write SQL injection proof PL/SQL</a>&nbsp;the following ways are mentioned to implement dynamic SQL:</p>



<ul class="wp-block-list">
<li>native dynamic SQL (EXECUTE IMMEDIATE)</li>



<li>DBMS_SQL.EXECUTE</li>



<li>DBMS_SQL.PARSE</li>



<li>DBMS_UTILITY.EXEC_DDL_STATEMENT</li>



<li>DBMS_DDL.CREATE_WRAPPED</li>



<li>DBMS_HS_PASSTHROUGH.EXECUTE_IMMEDIATE</li>



<li>DBMS_HS_PASSTHROUGH.PARSE</li>



<li>OWA_UTIL.BIND_VARIABLES</li>



<li>OWA_UTIL.LISTPRINT</li>



<li>OWA_UTIL.TABLEPRINT</li>
</ul>



<p>But there are more ways to execute dynamic SQL, such as:</p>



<ul class="wp-block-list">
<li>Open-For Statement</li>



<li>Java Stored Procedure</li>



<li>DBMS_SYS_SQL.EXECUTE</li>



<li>DBMS_SYS_SQL.PARSE</li>



<li>DBMS_SYS_SQL.PARSE_AS_USER</li>
</ul>



<p>It&#8217;s difficult to get a complete list because the Oracle-supplied subprograms are wrapped and often the SQL statement is hidden behind a C API. That leaves us with two options</p>



<ol class="wp-block-list">
<li>Use a list of Oracle-supplied packages and/or subprograms to identify dynamic SQL, even if the list might be incomplete</li>



<li>Suspect that any Oracle-supplied subprogram may contain dynamic SQL, except some trusted packages such as &#8220;DBMS_STANDARD&#8221; and &#8220;STANDARD&#8221;</li>
</ol>



<p>Both options are not very appealing. But I&#8217;m in favour of option 1. At a certain point, I have to focus on my application code and assume/trust, that the Oracle-supplied packages are doing their part to reduce the risk of SQL injection.</p>



<p>The following object types may contain PL/SQL and have to be checked for dynamic SQL:</p>



<ul class="wp-block-list">
<li>FUNCTION</li>



<li>PROCEDURE</li>



<li>PACKAGE BODY</li>



<li>TYPE BODY</li>



<li>TRIGGER</li>
</ul>



<p>What if we call services outside of the database via REST calls or AQ messages? I think we may ignore these cases. They are not part of this application any more and even if the services call this database, they have to go through the hard shell, and these are PL/SQL units already covered.</p>



<p>We need PL/Scope metadata for some checks. The following anonymous PL/SQL block produces these data. Be aware that the application code and some SYS objects are compiled. Invalid, dependent objects will be recompiled at the end. Nonetheless, you should not run this code in your production environment.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(3 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Compile missing PL/Scope metadata</span><span role="button" tabindex="0" data-code="DECLARE
   PROCEDURE enable_plscope IS
   BEGIN
      EXECUTE IMMEDIATE q'[ALTER SESSION SET plscope_settings='IDENTIFIERS:ALL, STATEMENTS:ALL']';
   END enable_plscope;
   --
   PROCEDURE compile_defs_without_plscope IS
   BEGIN
      &lt;&lt;compile_definition&gt;&gt;
      FOR r IN (
         WITH
            -- application users in scope of the analysis
            -- other users are treated as if they were not istalled
            app_user AS (
               SELECT username
                 FROM dba_users
                WHERE oracle_maintained = 'N'
            ),
            -- objects for which PL/Scope metadata is required
            obj AS (
                SELECT o.owner, o.object_type, o.object_name
                  FROM dba_objects o
                 WHERE object_name IN ('DBMS_UTILITY', 'OWA_UTIL')
                   AND object_type IN ('PACKAGE', 'SYNONYM')
               UNION ALL
               SELECT o.owner, o.object_type, o.object_name
                 FROM dba_objects o
                 JOIN app_user u ON u.username = o.owner
                WHERE object_type IN ('PACKAGE BODY', 'TYPE BODY', 'FUNCTION', 
                         'PROCEDURE', 'TRIGGER')
            ),
            -- objects without PL/Scope metadata
            missing_plscope_obj AS (
               SELECT o.owner, o.object_type, o.object_name
                 FROM obj o
                 LEFT JOIN dba_identifiers i 
                   ON i.owner = o.owner 
                      AND i.object_type = o.object_type
                      AND i.object_name = o.object_name
                      AND i.usage_context_id = 0
                WHERE i.usage_context_id IS NULL
            ),
            -- all objects to recompile and (re)gather PL/Scope metadata
            compile_scope AS (
               SELECT o.owner, o.object_type, o.object_name
                 FROM obj o
                WHERE EXISTS (
                         SELECT 1
                           FROM missing_plscope_obj o2 
                          WHERE o2.owner = 'SYS' 
                      )
               UNION ALL
               SELECT owner, object_type, object_name
                 FROM missing_plscope_obj
                WHERE NOT EXISTS (
                         SELECT 1
                           FROM missing_plscope_obj o2 
                          WHERE o2.owner = 'SYS' 
                      )
            ),
            -- compile statement required to produce PL/Scope metadata
            compile_stmt AS (
               SELECT 'ALTER ' || replace(object_type, ' BODY') 
                      || ' &quot;' || owner || '&quot;.&quot;' || object_name || '&quot; COMPILE' 
                      || CASE
                            WHEN object_type LIKE '%BODY' THEN
                               ' BODY'
                         END AS stmt
                 FROM compile_scope
            )
         -- main
         SELECT stmt
           FROM compile_stmt
      ) LOOP
         EXECUTE IMMEDIATE r.stmt;
      END LOOP compile_definition;
   END compile_defs_without_plscope;
   --
   PROCEDURE recompile_invalids IS
   BEGIN
      &lt;&lt;schemas_with_invalids&gt;&gt;
      FOR r IN (
         SELECT DISTINCT owner
           FROM dba_objects
          WHERE status != 'VALID'
          ORDER BY CASE owner
                      WHEN 'SYS' THEN
                         1
                      WHEN 'SYSTEM' THEN
                         2
                      ELSE
                         3
                   END,
                owner
      ) LOOP
         utl_recomp.recomp_serial(r.owner);
      END LOOP schemas_with_invalids;
   END recompile_invalids;
BEGIN
   enable_plscope;
   compile_defs_without_plscope;
   recompile_invalids;
END;
/" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">DECLARE</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4"> enable_plscope </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">EXECUTE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IMMEDIATE</span><span style="color: #D4D4D4"> q</span><span style="color: #CE9178">&#39;[ALTER SESSION SET plscope_settings=&#39;</span><span style="color: #D4D4D4">IDENTIFIERS:ALL, STATEMENTS:ALL</span><span style="color: #CE9178">&#39;]&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> enable_plscope;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">--</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4"> compile_defs_without_plscope </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;&lt;compile_definition&gt;&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">FOR</span><span style="color: #D4D4D4"> r </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">WITH</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #6A9955">-- application users in scope of the analysis</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #6A9955">-- other users are treated as if they were not istalled</span></span>
<span class="line"><span style="color: #D4D4D4">            app_user </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_users</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> oracle_maintained = </span><span style="color: #CE9178">&#39;N&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">            ),</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #6A9955">-- objects for which PL/Scope metadata is required</span></span>
<span class="line"><span style="color: #D4D4D4">            obj </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> o.owner, o.object_type, o.object_name</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_objects o</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> object_name </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;DBMS_UTILITY&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;OWA_UTIL&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                   </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> object_type </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;PACKAGE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;SYNONYM&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #569CD6">UNION ALL</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> o.owner, o.object_type, o.object_name</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_objects o</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = o.owner</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> object_type </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;PACKAGE BODY&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TYPE BODY&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;FUNCTION&#39;</span><span style="color: #D4D4D4">, </span></span>
<span class="line"><span style="color: #D4D4D4">                         </span><span style="color: #CE9178">&#39;PROCEDURE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TRIGGER&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">            ),</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #6A9955">-- objects without PL/Scope metadata</span></span>
<span class="line"><span style="color: #D4D4D4">            missing_plscope_obj </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> o.owner, o.object_type, o.object_name</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> obj o</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">LEFT JOIN</span><span style="color: #D4D4D4"> dba_identifiers i </span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> i.owner = o.owner </span></span>
<span class="line"><span style="color: #D4D4D4">                      </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> i.object_type = o.object_type</span></span>
<span class="line"><span style="color: #D4D4D4">                      </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> i.object_name = o.object_name</span></span>
<span class="line"><span style="color: #D4D4D4">                      </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> i.usage_context_id = </span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> i.usage_context_id </span><span style="color: #569CD6">IS</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">NULL</span></span>
<span class="line"><span style="color: #D4D4D4">            ),</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #6A9955">-- all objects to recompile and (re)gather PL/Scope metadata</span></span>
<span class="line"><span style="color: #D4D4D4">            compile_scope </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> o.owner, o.object_type, o.object_name</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> obj o</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">EXISTS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                         </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">1</span></span>
<span class="line"><span style="color: #D4D4D4">                           </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> missing_plscope_obj o2 </span></span>
<span class="line"><span style="color: #D4D4D4">                          </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> o2.owner = </span><span style="color: #CE9178">&#39;SYS&#39;</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">                      )</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #569CD6">UNION ALL</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">, object_type, object_name</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> missing_plscope_obj</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">NOT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">EXISTS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                         </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">1</span></span>
<span class="line"><span style="color: #D4D4D4">                           </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> missing_plscope_obj o2 </span></span>
<span class="line"><span style="color: #D4D4D4">                          </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> o2.owner = </span><span style="color: #CE9178">&#39;SYS&#39;</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">                      )</span></span>
<span class="line"><span style="color: #D4D4D4">            ),</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #6A9955">-- compile statement required to produce PL/Scope metadata</span></span>
<span class="line"><span style="color: #D4D4D4">            compile_stmt </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;ALTER &#39;</span><span style="color: #D4D4D4"> || </span><span style="color: #DCDCAA">replace</span><span style="color: #D4D4D4">(object_type, </span><span style="color: #CE9178">&#39; BODY&#39;</span><span style="color: #D4D4D4">) </span></span>
<span class="line"><span style="color: #D4D4D4">                      || </span><span style="color: #CE9178">&#39; &quot;&#39;</span><span style="color: #D4D4D4"> || </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4"> || </span><span style="color: #CE9178">&#39;&quot;.&quot;&#39;</span><span style="color: #D4D4D4"> || object_name || </span><span style="color: #CE9178">&#39;&quot; COMPILE&#39;</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">                      || </span><span style="color: #569CD6">CASE</span></span>
<span class="line"><span style="color: #D4D4D4">                            </span><span style="color: #569CD6">WHEN</span><span style="color: #D4D4D4"> object_type </span><span style="color: #569CD6">LIKE</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;%BODY&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">                               </span><span style="color: #CE9178">&#39; BODY&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">                         </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> stmt</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> compile_scope</span></span>
<span class="line"><span style="color: #D4D4D4">            )</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #6A9955">-- main</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> stmt</span></span>
<span class="line"><span style="color: #D4D4D4">           </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> compile_stmt</span></span>
<span class="line"><span style="color: #D4D4D4">      ) </span><span style="color: #569CD6">LOOP</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">EXECUTE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IMMEDIATE</span><span style="color: #D4D4D4"> r.stmt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">LOOP</span><span style="color: #D4D4D4"> compile_definition;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> compile_defs_without_plscope;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">--</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4"> recompile_invalids </span><span style="color: #569CD6">IS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;&lt;schemas_with_invalids&gt;&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">FOR</span><span style="color: #D4D4D4"> r </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">SELECT DISTINCT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span></span>
<span class="line"><span style="color: #D4D4D4">           </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_objects</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">status</span><span style="color: #D4D4D4"> != </span><span style="color: #CE9178">&#39;VALID&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">ORDER BY</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">CASE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span></span>
<span class="line"><span style="color: #D4D4D4">                      </span><span style="color: #569CD6">WHEN</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;SYS&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">                         </span><span style="color: #B5CEA8">1</span></span>
<span class="line"><span style="color: #D4D4D4">                      </span><span style="color: #569CD6">WHEN</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;SYSTEM&#39;</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">                         </span><span style="color: #B5CEA8">2</span></span>
<span class="line"><span style="color: #D4D4D4">                      </span><span style="color: #569CD6">ELSE</span></span>
<span class="line"><span style="color: #D4D4D4">                         </span><span style="color: #B5CEA8">3</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">owner</span></span>
<span class="line"><span style="color: #D4D4D4">      ) </span><span style="color: #569CD6">LOOP</span></span>
<span class="line"><span style="color: #D4D4D4">         utl_recomp.recomp_serial(r.owner);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">LOOP</span><span style="color: #D4D4D4"> schemas_with_invalids;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> recompile_invalids;</span></span>
<span class="line"><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">   enable_plscope;</span></span>
<span class="line"><span style="color: #D4D4D4">   compile_defs_without_plscope;</span></span>
<span class="line"><span style="color: #D4D4D4">   recompile_invalids;</span></span>
<span class="line"><span style="color: #569CD6">END</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">/</span></span></code></pre></div>



<p>Here&#8217;s the query to check application users.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(3 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Users secured against SQL injection attacks</span><span role="button" tabindex="0" data-code="WITH
   app_user AS (
      SELECT username
        FROM dba_users
       WHERE oracle_maintained = 'N'
   ),
   obj AS (
      SELECT o.owner, o.object_type, o.object_name
        FROM dba_objects o
        JOIN app_user u ON u.username = o.owner
       WHERE object_type IN ('PACKAGE BODY', 'TYPE BODY', 'FUNCTION', 'PROCEDURE', 'TRIGGER')
   ),
   missing_plscope_obj AS (
      SELECT o.owner, o.object_type, o.object_name
        FROM obj o
        LEFT JOIN dba_identifiers i
          ON i.owner = o.owner
             AND i.object_type = o.object_type
             AND i.object_name = o.object_name
             AND i.usage_context_id = 0
       WHERE i.usage_context_id IS NULL
   ),
   stmt AS (
      SELECT s.owner, s.object_type, s.object_name, s.type, s.line, s.col
        FROM dba_statements s
        JOIN app_user u ON u.username = s.owner
       WHERE s.type IN ('EXECUTE IMMEDIATE', 'OPEN')
   ),
   dep AS (
      SELECT d.owner, d.name as object_name, d.type as object_type, d.referenced_name
        FROM dba_dependencies d
        JOIN app_user u ON u.username = d.owner
       WHERE d.referenced_name IN (
                'DBMS_SQL', 'DBMS_DDL', 'DBMS_HS_PASSTHROUGH', 'DBMS_SYS_SQL'
             )
   ),
   issues AS (
      SELECT owner, 
             object_type, 
             object_name, 
             type AS potential_sqli_risk
        FROM stmt
       WHERE type = 'EXECUTE IMMEDIATE'
      UNION
      SELECT stmt.owner, 
             stmt.object_type, 
             stmt.object_name, 
             'OPEN-FOR WITH DYNAMIC SQL'
        FROM stmt
        JOIN dba_source src
          ON src.owner = stmt.owner
             AND src.type = stmt.object_type
             AND src.name = stmt.object_name
             AND src.line = stmt.line
       WHERE stmt.type = 'OPEN'
         AND regexp_substr(substr(src.text, stmt.col), '^open\s+', 1, 1, 'i') IS NULL
         AND regexp_substr(substr(src.text, stmt.col), '^(&quot;?\w+&quot;?|q?'')', 1, 1, 'i') IS NOT NULL
      UNION
      SELECT owner, 
             object_type, 
             object_name, 
             referenced_name
        FROM dep
      UNION
      SELECT i.owner, 
             i.object_type, 
             i.object_name, 
             r.object_name || '.' || r.name 
        FROM dba_identifiers i
        JOIN app_user u ON u.username = i.owner
        JOIN dba_identifiers r
          ON r.signature = i.signature
             AND r.usage = 'DECLARATION'
       WHERE i.usage = 'CALL'
         AND r.owner = 'SYS'
         AND r.object_type = 'PACKAGE'
         AND (r.object_name, r.name) IN (
                ('DBMS_UTILITY', 'EXEC_DDL_STATEMENT'),
                ('OWA_UTIL', 'BIND_VARIABLES'),
                ('OWA_UTIL', 'LISTPRINT'),
                ('OWA_UTIL', 'TABLEPRINT')
             )
      UNION
      SELECT o.owner, 
             o.object_type, 
             o.object_name, 
             'SQL FROM JAVA SUSPECTED'
        FROM dba_objects o
        JOIN app_user u ON u.username = o.owner
       WHERE o.object_type = 'JAVA CLASS'
      UNION
      SELECT owner, 
             object_type, 
             object_name, 
             'PL/SCOPE METADATA MISSING'
        FROM missing_plscope_obj
   ),
   issue_aggr AS (
      SELECT u.username AS owner, COUNT(i.owner) issue_count
        FROM app_user u
        LEFT JOIN issues i ON i.owner = u.username
       GROUP BY u.username
   ),
   summary AS (
      SELECT owner,
             CASE
                WHEN issue_count = 0 THEN
                   'YES'
                ELSE
                   'NO'
             END AS is_user_sql_injection_free,
             issue_count
        FROM issue_aggr
       ORDER BY is_user_sql_injection_free DESC, owner
   )
-- main
SELECT * 
  FROM summary
 WHERE owner LIKE 'THE%';
 
OWNER         IS_USER_SQL_INJECTION_FREE ISSUE_COUNT
------------- -------------------------- -----------
THE_BAD_DATA  YES                                  0
THE_BAD_USER  YES                                  0
THE_GOOD_API  YES                                  0
THE_GOOD_DATA YES                                  0
THE_GOOD_USER YES                                  0
THE_UGLY_DATA YES                                  0
THE_UGLY_USER YES                                  0
THE_BAD_API   NO                                   9
 
8 rows selected." style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">WITH</span></span>
<span class="line"><span style="color: #D4D4D4">   app_user </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> username</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_users</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> oracle_maintained = </span><span style="color: #CE9178">&#39;N&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   obj </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> o.owner, o.object_type, o.object_name</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_objects o</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = o.owner</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> object_type </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;PACKAGE BODY&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TYPE BODY&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;FUNCTION&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PROCEDURE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TRIGGER&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   missing_plscope_obj </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> o.owner, o.object_type, o.object_name</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> obj o</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">LEFT JOIN</span><span style="color: #D4D4D4"> dba_identifiers i</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> i.owner = o.owner</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> i.object_type = o.object_type</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> i.object_name = o.object_name</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> i.usage_context_id = </span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> i.usage_context_id </span><span style="color: #569CD6">IS</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">NULL</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   stmt </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> s.owner, s.object_type, s.object_name, s.type, s.line, s.col</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_statements s</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = s.owner</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> s.type </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;EXECUTE IMMEDIATE&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;OPEN&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   dep </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> d.owner, d.name </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> object_name, d.type </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> object_type, d.referenced_name</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_dependencies d</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = d.owner</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> d.referenced_name </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #CE9178">&#39;DBMS_SQL&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;DBMS_DDL&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;DBMS_HS_PASSTHROUGH&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;DBMS_SYS_SQL&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   issues </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">, </span></span>
<span class="line"><span style="color: #D4D4D4">             object_type, </span></span>
<span class="line"><span style="color: #D4D4D4">             object_name, </span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">type</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> potential_sqli_risk</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> stmt</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">type</span><span style="color: #D4D4D4"> = </span><span style="color: #CE9178">&#39;EXECUTE IMMEDIATE&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> stmt.owner, </span></span>
<span class="line"><span style="color: #D4D4D4">             stmt.object_type, </span></span>
<span class="line"><span style="color: #D4D4D4">             stmt.object_name, </span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;OPEN-FOR WITH DYNAMIC SQL&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> stmt</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> dba_source src</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> src.owner = stmt.owner</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> src.type = stmt.object_type</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> src.name = stmt.object_name</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> src.line = stmt.line</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> stmt.type = </span><span style="color: #CE9178">&#39;OPEN&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> regexp_substr(substr(src.text, stmt.col), </span><span style="color: #CE9178">&#39;^open\s+&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;i&#39;</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">IS</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">NULL</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> regexp_substr(substr(src.text, stmt.col), </span><span style="color: #CE9178">&#39;^(&quot;?\w+&quot;?|q?&#39;&#39;)&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;i&#39;</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">IS NOT NULL</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">, </span></span>
<span class="line"><span style="color: #D4D4D4">             object_type, </span></span>
<span class="line"><span style="color: #D4D4D4">             object_name, </span></span>
<span class="line"><span style="color: #D4D4D4">             referenced_name</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dep</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> i.owner, </span></span>
<span class="line"><span style="color: #D4D4D4">             i.object_type, </span></span>
<span class="line"><span style="color: #D4D4D4">             i.object_name, </span></span>
<span class="line"><span style="color: #D4D4D4">             r.object_name || </span><span style="color: #CE9178">&#39;.&#39;</span><span style="color: #D4D4D4"> || r.name </span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_identifiers i</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = i.owner</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> dba_identifiers r</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> r.signature = i.signature</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> r.usage = </span><span style="color: #CE9178">&#39;DECLARATION&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> i.usage = </span><span style="color: #CE9178">&#39;CALL&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> r.owner = </span><span style="color: #CE9178">&#39;SYS&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> r.object_type = </span><span style="color: #CE9178">&#39;PACKAGE&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">AND</span><span style="color: #D4D4D4"> (r.object_name, r.name) </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                (</span><span style="color: #CE9178">&#39;DBMS_UTILITY&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;EXEC_DDL_STATEMENT&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">                (</span><span style="color: #CE9178">&#39;OWA_UTIL&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;BIND_VARIABLES&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">                (</span><span style="color: #CE9178">&#39;OWA_UTIL&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;LISTPRINT&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">                (</span><span style="color: #CE9178">&#39;OWA_UTIL&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TABLEPRINT&#39;</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> o.owner, </span></span>
<span class="line"><span style="color: #D4D4D4">             o.object_type, </span></span>
<span class="line"><span style="color: #D4D4D4">             o.object_name, </span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;SQL FROM JAVA SUSPECTED&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> dba_objects o</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> app_user u </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> u.username = o.owner</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> o.object_type = </span><span style="color: #CE9178">&#39;JAVA CLASS&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">, </span></span>
<span class="line"><span style="color: #D4D4D4">             object_type, </span></span>
<span class="line"><span style="color: #D4D4D4">             object_name, </span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #CE9178">&#39;PL/SCOPE METADATA MISSING&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> missing_plscope_obj</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   issue_aggr </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> u.username </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">, </span><span style="color: #DCDCAA">COUNT</span><span style="color: #D4D4D4">(i.owner) issue_count</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> app_user u</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">LEFT JOIN</span><span style="color: #D4D4D4"> issues i </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> i.owner = u.username</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">GROUP BY</span><span style="color: #D4D4D4"> u.username</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   summary </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">CASE</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">WHEN</span><span style="color: #D4D4D4"> issue_count = </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #CE9178">&#39;YES&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">ELSE</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #CE9178">&#39;NO&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span><span style="color: #D4D4D4"> is_user_sql_injection_free,</span></span>
<span class="line"><span style="color: #D4D4D4">             issue_count</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> issue_aggr</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">ORDER BY</span><span style="color: #D4D4D4"> is_user_sql_injection_free </span><span style="color: #569CD6">DESC</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">owner</span></span>
<span class="line"><span style="color: #D4D4D4">   )</span></span>
<span class="line"><span style="color: #6A9955">-- main</span></span>
<span class="line"><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> * </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> summary</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">LIKE</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;THE%&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #569CD6">OWNER</span><span style="color: #D4D4D4">         IS_USER_SQL_INJECTION_FREE ISSUE_COUNT</span></span>
<span class="line"><span style="color: #6A9955">------------- -------------------------- -----------</span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_DATA  YES                                  </span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_USER  YES                                  </span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">THE_GOOD_API  YES                                  </span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">THE_GOOD_DATA YES                                  </span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">THE_GOOD_USER YES                                  </span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">THE_UGLY_DATA YES                                  </span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">THE_UGLY_USER YES                                  </span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   </span><span style="color: #569CD6">NO</span><span style="color: #D4D4D4">                                   </span><span style="color: #B5CEA8">9</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #B5CEA8">8</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">rows</span><span style="color: #D4D4D4"> selected.</span></span></code></pre></div>



<p>To see the issues of THE_BAD_API you may simply change the main part of the query as follows:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-start:116;--cbp-line-number-width:calc(3 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">All rule 2 issues</span><span role="button" tabindex="0" data-code="-- main
SELECT * 
  FROM issues
 WHERE owner LIKE 'THE%';
 
OWNER         OBJECT_TYPE   OBJECT_NAME POTENTIAL_SQLI_RISK                     
------------- ------------- ----------- ----------------------------------------
THE_BAD_API   JAVA CLASS    C           SQL FROM JAVA SUSPECTED                 
THE_BAD_API   PACKAGE BODY  PKG         EXECUTE IMMEDIATE                       
THE_BAD_API   PACKAGE BODY  PKG2        DBMS_DDL                                
THE_BAD_API   PACKAGE BODY  PKG2        DBMS_SQL                                
THE_BAD_API   PACKAGE BODY  PKG2        DBMS_SYS_SQL                            
THE_BAD_API   PACKAGE BODY  PKG2        DBMS_UTILITY.EXEC_DDL_STATEMENT         
THE_BAD_API   PACKAGE BODY  PKG2        EXECUTE IMMEDIATE                       
THE_BAD_API   PACKAGE BODY  PKG2        OPEN-FOR WITH DYNAMIC SQL               
THE_BAD_API   PACKAGE BODY  PKG2        OWA_UTIL.LISTPRINT                      
 
9 rows selected." style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">-- main</span></span>
<span class="line"><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> * </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> issues</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">WHERE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">owner</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">LIKE</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;THE%&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #569CD6">OWNER</span><span style="color: #D4D4D4">         OBJECT_TYPE   OBJECT_NAME POTENTIAL_SQLI_RISK                     </span></span>
<span class="line"><span style="color: #6A9955">------------- ------------- ----------- ----------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   JAVA CLASS    C           </span><span style="color: #569CD6">SQL</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> JAVA SUSPECTED                 </span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   PACKAGE BODY  PKG         </span><span style="color: #569CD6">EXECUTE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IMMEDIATE</span><span style="color: #D4D4D4">                       </span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   PACKAGE BODY  PKG2        DBMS_DDL                                </span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   PACKAGE BODY  PKG2        DBMS_SQL                                </span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   PACKAGE BODY  PKG2        DBMS_SYS_SQL                            </span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   PACKAGE BODY  PKG2        DBMS_UTILITY.EXEC_DDL_STATEMENT         </span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   PACKAGE BODY  PKG2        </span><span style="color: #569CD6">EXECUTE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">IMMEDIATE</span><span style="color: #D4D4D4">                       </span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   PACKAGE BODY  PKG2        </span><span style="color: #569CD6">OPEN</span><span style="color: #D4D4D4">-</span><span style="color: #569CD6">FOR</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">WITH</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">DYNAMIC</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">SQL</span><span style="color: #D4D4D4">               </span></span>
<span class="line"><span style="color: #D4D4D4">THE_BAD_API   PACKAGE BODY  PKG2        OWA_UTIL.LISTPRINT                      </span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #B5CEA8">9</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">rows</span><span style="color: #D4D4D4"> selected.</span></span></code></pre></div>



<p>To suspect that every JAVA CLASS uses SQL is not a very&nbsp;differentiated analysis result. Further Java-specific code analysis is necessary. However, the other results are reasonable.</p>



<h2 class="wp-block-heading">Conclusion</h2>



<p>In this blog post, I showed&nbsp;how to prove, that a PL/SQL application does not use dynamic SQL and therefore is secured against SQL injection attacks.</p>



<p>The use of dynamic SQL is automatically reduced in PL/SQL because it is easier and more efficient for a developer to deal with compile errors than runtime errors. But there are cases when static SQL is not possible or not efficient enough. In those cases, proper input validation is a necessity to mitigate the SQL injection risk (see also &#8220;Ensuring the safety of a SQL literal&#8221; in&nbsp;<a href="http://www.oracle.com/technetwork/database/features/plsql/overview/how-to-write-injection-proof-plsql-1-129572.pdf">How to write SQL injection proof PL/SQL</a>).</p>



<p>Views are often part of the API in applications I&#8217;m involved in. I like the power and the flexibility of these views. In fact, I&#8217;m very grateful that the Oracle database provides a view API for its data dictionary, which simplified the analysis for this blog post. But views come with a SQL injection risk.&nbsp;Moreover, the risk and responsibility are delegated to a certain extent to the developers using the database API. Hence, in the future, I will think twice before making views part of the API, but I will for sure not rule them out per se.</p>
<p>The post <a href="https://www.salvis.com/blog/2017/12/17/how-to-prove-that-your-smartdb-app-is-secured-against-sql-injection-attacks/">How to Prove That Your SmartDB App Is Secure</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.salvis.com/blog/2017/12/17/how-to-prove-that-your-smartdb-app-is-secured-against-sql-injection-attacks/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
	</channel>
</rss>
