<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	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/"
		>
<channel>
	<title>Comments on: On the false sense of security with PL/SQL based implementation of business rules &#8211; and what to do about it</title>
	<atom:link href="http://technology.amis.nl/2006/10/22/on-the-false-sense-of-security-with-plsql-based-implementation-of-business-rules-and-what-to-do-about-it/feed/" rel="self" type="application/rss+xml" />
	<link>http://technology.amis.nl/2006/10/22/on-the-false-sense-of-security-with-plsql-based-implementation-of-business-rules-and-what-to-do-about-it/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=on-the-false-sense-of-security-with-plsql-based-implementation-of-business-rules-and-what-to-do-about-it</link>
	<description></description>
	<lastBuildDate>Fri, 12 Apr 2013 10:04:09 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
	<item>
		<title>By: Dan D</title>
		<link>http://technology.amis.nl/2006/10/22/on-the-false-sense-of-security-with-plsql-based-implementation-of-business-rules-and-what-to-do-about-it/#comment-3940</link>
		<dc:creator>Dan D</dc:creator>
		<pubDate>Fri, 12 Feb 2010 04:37:00 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1375#comment-3940</guid>
		<description><![CDATA[Concerning the materialized view, if the view is used solely to implement check constraint you can apply the HAVING count(*) &gt;= 4.Â  On large data sets you practically don&#039;t consume any disk (still pay the penalty for refresh on underlying table changes but still better than triggers.]]></description>
		<content:encoded><![CDATA[<p>Concerning the materialized view, if the view is used solely to implement check constraint you can apply the HAVING count(*) &gt;= 4.Â  On large data sets you practically don&#8217;t consume any disk (still pay the penalty for refresh on underlying table changes but still better than triggers.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Brian Camire</title>
		<link>http://technology.amis.nl/2006/10/22/on-the-false-sense-of-security-with-plsql-based-implementation-of-business-rules-and-what-to-do-about-it/#comment-3939</link>
		<dc:creator>Brian Camire</dc:creator>
		<pubDate>Tue, 24 Oct 2006 15:42:12 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1375#comment-3939</guid>
		<description><![CDATA[Toon:

This thread on the OTN forums...

http://forums.oracle.com/forums/thread.jspa?messageID=1455919&amp;#1455919

...discusses a way to identify serializable transactions using the FLAG column in V$TRANSACTION.  You may already be aware of this method and have chosen not to use it because it is not fully documented.  Still, I thought it might interest you in case you were not aware of it.

Hope this helps,



Brian]]></description>
		<content:encoded><![CDATA[<p>Toon:</p>
<p>This thread on the OTN forums&#8230;</p>
<p><a href="http://forums.oracle.com/forums/thread.jspa?messageID=1455919&#038;#1455919" rel="nofollow">http://forums.oracle.com/forums/thread.jspa?messageID=1455919&#038;#1455919</a></p>
<p>&#8230;discusses a way to identify serializable transactions using the FLAG column in V$TRANSACTION.  You may already be aware of this method and have chosen not to use it because it is not fully documented.  Still, I thought it might interest you in case you were not aware of it.</p>
<p>Hope this helps,</p>
<p>Brian</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Toon Koppelaars</title>
		<link>http://technology.amis.nl/2006/10/22/on-the-false-sense-of-security-with-plsql-based-implementation-of-business-rules-and-what-to-do-about-it/#comment-3938</link>
		<dc:creator>Toon Koppelaars</dc:creator>
		<pubDate>Mon, 23 Oct 2006 21:50:18 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1375#comment-3938</guid>
		<description><![CDATA[Lucas,

With regards to your offline question of how this business rule would implement in RuleGen, here it is.

You need to tell RuleGen &#039;when&#039; the rule needs to be checked. This particular rule needs to be checked when CLERKS are inserted or, in case of updates, the number of employees being promoted to CLERK exceeds the number being demoted (within a same department).

You specify this through queries on the &#039;transition effect&#039; of the currently executed DML. RuleGen supplies views that hold the transition effect.

For inserts you register this query:
select distinct deptno
from v_insert_tx_effect
where new_job=&#039;CLERK&#039;
/

For updates you register this query:
select deptno
from (
select deptno,sum(case new_job
                  when &#039;CLERK&#039; then 1
                  else 0) promoted
             ,sum(case old_job
                  when &#039;CLERK&#039; then 1
                  else 0) demoted
from v_update_tx_effect
where updated_job=&#039;true&#039;
and (old_job=&#039;CLERK&#039; or new_job=&#039;CLERK&#039;)
group by deptno)
where promoted-demoted&gt;0
/

There is no need to register a query for deletes: they can never violate this rule.

Next you tell RuleGen, &#039;how&#039; the rule should be checked, in case one of the queries above actually returns rows. This also is done through supplying RuleGen with a query. This query can use the selected values of the queries above (available through local variable with name p_.

Here is the &#039;how&#039; for this rule.

select &#039;At most three CLERKs allowed (found &#039;&#124;&#124;
       to_char(num_clerks)&#124;&#124;&#039;) in department &#039;&#124;&#124;p_deptno&#124;&#124;&#039;.&#039;
as msg
from (select count(*) as num_clerks
      from emp
      where job=&#039;CLERK&#039; and deptno=p_deptno)
where num_clerks &gt; 3
/

The semantics is that this query selects the actual error-message that should be reported back in case of a violation. If no row gets selected then the rule is considered OK.

And finally you need to tell RuleGen how code-execution for checking this rule is to be serialized, this is done via dbms-lock in a similar manner as your code above. In this case you register a call to a service procedure of RuleGen that acquires the necessary application lock for this rule: sp_rg_lock_rule(&#039;X&#039;,&#039;BREMP001&#039;,p_deptno);

That&#039;s it in a nutshell: for this rule you register the three queries mentioned plus the serialization code, then execute a service procedure to generate the triggers (or modify existing generated triggers) and you are done. The rule is maintained.

(there are a few more details to it, but the essence is the stuff above).

Regards,
Toon

PS: The issue with serializable isolation level is a known issue in the framework. I&#039;m still trying to find a way to at least *detect* that the current transaction (or session) runs in serializable isolation mode. And if detected generate a generic error-message that rules cannot be maintained in this mode. But I haven&#039;t found a way to do this, nor another way of getting the rule-validation robust in this mode (in an acceptable scalable manner, that is).]]></description>
		<content:encoded><![CDATA[<p>Lucas,</p>
<p>With regards to your offline question of how this business rule would implement in RuleGen, here it is.</p>
<p>You need to tell RuleGen &#8216;when&#8217; the rule needs to be checked. This particular rule needs to be checked when CLERKS are inserted or, in case of updates, the number of employees being promoted to CLERK exceeds the number being demoted (within a same department).</p>
<p>You specify this through queries on the &#8216;transition effect&#8217; of the currently executed DML. RuleGen supplies views that hold the transition effect.</p>
<p>For inserts you register this query:<br />
select distinct deptno<br />
from v_insert_tx_effect<br />
where new_job=&#8217;CLERK&#8217;<br />
/</p>
<p>For updates you register this query:<br />
select deptno<br />
from (<br />
select deptno,sum(case new_job<br />
                  when &#8216;CLERK&#8217; then 1<br />
                  else 0) promoted<br />
             ,sum(case old_job<br />
                  when &#8216;CLERK&#8217; then 1<br />
                  else 0) demoted<br />
from v_update_tx_effect<br />
where updated_job=&#8217;true&#8217;<br />
and (old_job=&#8217;CLERK&#8217; or new_job=&#8217;CLERK&#8217;)<br />
group by deptno)<br />
where promoted-demoted&gt;0<br />
/</p>
<p>There is no need to register a query for deletes: they can never violate this rule.</p>
<p>Next you tell RuleGen, &#8216;how&#8217; the rule should be checked, in case one of the queries above actually returns rows. This also is done through supplying RuleGen with a query. This query can use the selected values of the queries above (available through local variable with name p_.</p>
<p>Here is the &#8216;how&#8217; for this rule.</p>
<p>select &#8216;At most three CLERKs allowed (found &#8216;||<br />
       to_char(num_clerks)||&#8217;) in department &#8216;||p_deptno||&#8217;.&#8217;<br />
as msg<br />
from (select count(*) as num_clerks<br />
      from emp<br />
      where job=&#8217;CLERK&#8217; and deptno=p_deptno)<br />
where num_clerks &gt; 3<br />
/</p>
<p>The semantics is that this query selects the actual error-message that should be reported back in case of a violation. If no row gets selected then the rule is considered OK.</p>
<p>And finally you need to tell RuleGen how code-execution for checking this rule is to be serialized, this is done via dbms-lock in a similar manner as your code above. In this case you register a call to a service procedure of RuleGen that acquires the necessary application lock for this rule: sp_rg_lock_rule(&#8216;X&#8217;,'BREMP001&#8242;,p_deptno);</p>
<p>That&#8217;s it in a nutshell: for this rule you register the three queries mentioned plus the serialization code, then execute a service procedure to generate the triggers (or modify existing generated triggers) and you are done. The rule is maintained.</p>
<p>(there are a few more details to it, but the essence is the stuff above).</p>
<p>Regards,<br />
Toon</p>
<p>PS: The issue with serializable isolation level is a known issue in the framework. I&#8217;m still trying to find a way to at least *detect* that the current transaction (or session) runs in serializable isolation mode. And if detected generate a generic error-message that rules cannot be maintained in this mode. But I haven&#8217;t found a way to do this, nor another way of getting the rule-validation robust in this mode (in an acceptable scalable manner, that is).</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: John Flack</title>
		<link>http://technology.amis.nl/2006/10/22/on-the-false-sense-of-security-with-plsql-based-implementation-of-business-rules-and-what-to-do-about-it/#comment-3937</link>
		<dc:creator>John Flack</dc:creator>
		<pubDate>Mon, 23 Oct 2006 16:17:30 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1375#comment-3937</guid>
		<description><![CDATA[Terrific stuff, Lucas - thanks.  I was aware of a lot of the information, but not the use of DBMS_LOCK.  Besides, this puts it all in one place, well thought out and well organized.]]></description>
		<content:encoded><![CDATA[<p>Terrific stuff, Lucas &#8211; thanks.  I was aware of a lot of the information, but not the use of DBMS_LOCK.  Besides, this puts it all in one place, well thought out and well organized.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Lucas Jellema</title>
		<link>http://technology.amis.nl/2006/10/22/on-the-false-sense-of-security-with-plsql-based-implementation-of-business-rules-and-what-to-do-about-it/#comment-3936</link>
		<dc:creator>Lucas Jellema</dc:creator>
		<pubDate>Mon, 23 Oct 2006 12:40:34 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1375#comment-3936</guid>
		<description><![CDATA[Brian,

Thanks for your comment. You are making a good point, though in my experience it is rare for applications to use serializable isolation level and do data manipulation. But you are right: in those (perhaps not so frequently occurring) situations you have to be aware that the approach I present is not secure. So either you do not serialize or you do not do DML. If you want to do both, you may have to use the FOR UPDATE OF approach.

best regards,

Lucas

Note: For more observations on Isolation Levels, you may want to check out &lt;a href=&quot;http://www.oracle.com/technology/oramag/oracle/05-nov/o65asktom.html&quot; rel=&quot;nofollow&quot;&gt;http://www.oracle.com/technology/oramag/oracle/05-nov/o65asktom.html&lt;/a&gt;.]]></description>
		<content:encoded><![CDATA[<p>Brian,</p>
<p>Thanks for your comment. You are making a good point, though in my experience it is rare for applications to use serializable isolation level and do data manipulation. But you are right: in those (perhaps not so frequently occurring) situations you have to be aware that the approach I present is not secure. So either you do not serialize or you do not do DML. If you want to do both, you may have to use the FOR UPDATE OF approach.</p>
<p>best regards,</p>
<p>Lucas</p>
<p>Note: For more observations on Isolation Levels, you may want to check out <a href="http://www.oracle.com/technology/oramag/oracle/05-nov/o65asktom.html" rel="nofollow">http://www.oracle.com/technology/oramag/oracle/05-nov/o65asktom.html</a>.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Brian Camire</title>
		<link>http://technology.amis.nl/2006/10/22/on-the-false-sense-of-security-with-plsql-based-implementation-of-business-rules-and-what-to-do-about-it/#comment-3935</link>
		<dc:creator>Brian Camire</dc:creator>
		<pubDate>Mon, 23 Oct 2006 00:28:10 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1375#comment-3935</guid>
		<description><![CDATA[Using DBMS_LOCK is not completely robust when using serializable isolation level because (unlike SELECT...FOR UPDATE) Oracle &quot;forgets&quot; about the lock once the transaction that acquired it commits (or is rolled back).

For example consider the following sequence of events under two concurrent sessions, A and B.

1.  Session A starts a new transaction *with serializable isolation level*.

2.  Session B starts a new transaction and makes a &quot;valid&quot; change to EMP that fires the trigger and acquires the lock.

3.  Session B commits, and Oracle releases the lock.

4.  Session A makes a change to EMP that fires the trigger.  Since A uses serializable isolation level, it can&#039;t &quot;see&quot; the changes made by B.  Since B&#039;s lock has been released, it cannot prevent A from making a change that, when combined with the change made by B, violates the business rule.

There is a more concrete example of this (relating to preventing overlapping ranges) at http://asktom.oracle.com/pls/ask/f?p=4950:61:18110426428579554560::::P61_ID:474121407101#20229209009012.

Using release_on_commit =&gt; FALSE in DBMS_LOCK.REQUEST() will not solve the problem, because the lock could still be &quot;prematurely&quot; released -- for example, if the session that started transaction B is closed before transaction A changes EMP.

So, SELECT...FOR UPDATE is too restrictive (since it prevents all concurrent changes, even if they don&#039;t violate the business rule), and DBMS_LOCK is not completely robust.]]></description>
		<content:encoded><![CDATA[<p>Using DBMS_LOCK is not completely robust when using serializable isolation level because (unlike SELECT&#8230;FOR UPDATE) Oracle &#8220;forgets&#8221; about the lock once the transaction that acquired it commits (or is rolled back).</p>
<p>For example consider the following sequence of events under two concurrent sessions, A and B.</p>
<p>1.  Session A starts a new transaction *with serializable isolation level*.</p>
<p>2.  Session B starts a new transaction and makes a &#8220;valid&#8221; change to EMP that fires the trigger and acquires the lock.</p>
<p>3.  Session B commits, and Oracle releases the lock.</p>
<p>4.  Session A makes a change to EMP that fires the trigger.  Since A uses serializable isolation level, it can&#8217;t &#8220;see&#8221; the changes made by B.  Since B&#8217;s lock has been released, it cannot prevent A from making a change that, when combined with the change made by B, violates the business rule.</p>
<p>There is a more concrete example of this (relating to preventing overlapping ranges) at <a href="http://asktom.oracle.com/pls/ask/f?p=4950:61:18110426428579554560" rel="nofollow">http://asktom.oracle.com/pls/ask/f?p=4950:61:18110426428579554560</a>::::P61_ID:474121407101#20229209009012.</p>
<p>Using release_on_commit =&gt; FALSE in DBMS_LOCK.REQUEST() will not solve the problem, because the lock could still be &#8220;prematurely&#8221; released &#8212; for example, if the session that started transaction B is closed before transaction A changes EMP.</p>
<p>So, SELECT&#8230;FOR UPDATE is too restrictive (since it prevents all concurrent changes, even if they don&#8217;t violate the business rule), and DBMS_LOCK is not completely robust.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Lucas Jellema</title>
		<link>http://technology.amis.nl/2006/10/22/on-the-false-sense-of-security-with-plsql-based-implementation-of-business-rules-and-what-to-do-about-it/#comment-3934</link>
		<dc:creator>Lucas Jellema</dc:creator>
		<pubDate>Sun, 22 Oct 2006 18:35:41 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1375#comment-3934</guid>
		<description><![CDATA[Toon,

You were absolutely right - now you are not anymore. I was still writing the article when I already posted part of it (afraid to lose content while editing) in the assumption that on a Sunday afternoon no one would read the article in the 20 minutes between the partial publication and the final post. However, I underestimated you - of course.

I have just completed the whole article. I think you will find the fundamental flaw described now - it is not robust! As well as a solution.

I would love to have your feedback on the complete article too by the way.

best reagrds,

Lucas]]></description>
		<content:encoded><![CDATA[<p>Toon,</p>
<p>You were absolutely right &#8211; now you are not anymore. I was still writing the article when I already posted part of it (afraid to lose content while editing) in the assumption that on a Sunday afternoon no one would read the article in the 20 minutes between the partial publication and the final post. However, I underestimated you &#8211; of course.</p>
<p>I have just completed the whole article. I think you will find the fundamental flaw described now &#8211; it is not robust! As well as a solution.</p>
<p>I would love to have your feedback on the complete article too by the way.</p>
<p>best reagrds,</p>
<p>Lucas</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Toon Koppelaars</title>
		<link>http://technology.amis.nl/2006/10/22/on-the-false-sense-of-security-with-plsql-based-implementation-of-business-rules-and-what-to-do-about-it/#comment-3933</link>
		<dc:creator>Toon Koppelaars</dc:creator>
		<pubDate>Sun, 22 Oct 2006 18:35:16 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1375#comment-3933</guid>
		<description><![CDATA[Oops.  Sems I read your post while not all was posted yet. I see you now have the thoughts on concurrency.

Again great post!]]></description>
		<content:encoded><![CDATA[<p>Oops.  Sems I read your post while not all was posted yet. I see you now have the thoughts on concurrency.</p>
<p>Again great post!</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Toon Koppelaars</title>
		<link>http://technology.amis.nl/2006/10/22/on-the-false-sense-of-security-with-plsql-based-implementation-of-business-rules-and-what-to-do-about-it/#comment-3932</link>
		<dc:creator>Toon Koppelaars</dc:creator>
		<pubDate>Sun, 22 Oct 2006 18:31:15 +0000</pubDate>
		<guid isPermaLink="false">http://technology.amis.nl/blog/?p=1375#comment-3932</guid>
		<description><![CDATA[Lucas,

Good thoughts on integrity constraint implementation: you fail to mention though what it is that is &#039;fundamentally flawed&#039;. Unless you mean that checks are executed too many times. Your solution to that issue will not work when the rule typically involves three or more tables: rules do not have a single &#039;case&#039; (as was the department key in your example) any more.

Also I would expect that you were going to mention that one has to think about locking &#039;something&#039; in order for the triggers firing simultaneously to still enforce the rule correctly.

Toon]]></description>
		<content:encoded><![CDATA[<p>Lucas,</p>
<p>Good thoughts on integrity constraint implementation: you fail to mention though what it is that is &#8216;fundamentally flawed&#8217;. Unless you mean that checks are executed too many times. Your solution to that issue will not work when the rule typically involves three or more tables: rules do not have a single &#8216;case&#8217; (as was the department key in your example) any more.</p>
<p>Also I would expect that you were going to mention that one has to think about locking &#8216;something&#8217; in order for the triggers firing simultaneously to still enforce the rule correctly.</p>
<p>Toon</p>
]]></content:encoded>
	</item>
</channel>
</rss>
