<?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>Radino's blog &#187; SQL</title>
	<atom:link href="http://radino.eu/tag/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://radino.eu</link>
	<description>Focusing on interesting SQL and PL/SQL problems</description>
	<lastBuildDate>Mon, 12 Jan 2009 09:43:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Bitwise OR Aggregate Function</title>
		<link>http://radino.eu/2008/05/31/bitwise-or-aggregate-function/</link>
		<comments>http://radino.eu/2008/05/31/bitwise-or-aggregate-function/#comments</comments>
		<pubDate>Sat, 31 May 2008 15:46:34 +0000</pubDate>
		<dc:creator>Radoslav Golian</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://radino.eu/?p=4</guid>
		<description><![CDATA[A few months ago I was working on an application which used bits to store some flags in one number. In this approach the bit value in the number indicates whether a flag is on (1) or off (0). In my case a flag was tied with a column of a front-end table. If the [...]]]></description>
			<content:encoded><![CDATA[<p>A few months ago I was working on an application which used bits to store some flags in one number. In this approach the bit value in the number indicates whether a flag is on (1) or off (0). In my case a flag was tied with a column of a front-end table. If the flag was off then the column didn&#8217;t appear on the front-end.</p>
<p>Example:</p>
<pre>flag     : flag<sub>3</sub> flag<sub>2</sub> flag<sub>1</sub> flag<sub>0</sub>
state    :   off   on   off    on
bit value:     0    1     0     1</pre>
<p>0101<sub>2</sub> (<a title="Binary numeral system" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/edit.php');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/edit.php');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/edit.php');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/edit.php');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4');pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Binary_numeral_system?referer=http://radino.eu/wp-admin/edit.php');" href="http://en.wikipedia.org/wiki/Binary_numeral_system" target="_blank">binary</a>) = 5<sub>10</sub> (decadic), so the number 5 will be stored in the database.</p>
<p>In this case, the columns tied with the flags flag<sub>0</sub> and flag<sub>2</sub> will appear on the front-end and the columns tied with the flags flag<sub>1</sub> and flag<sub>3</sub> won&#8217;t. We can use the <a title="BITAND function" onclick="pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/edit.php');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/edit.php');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/edit.php');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/edit.php');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4&amp;message=4');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm_sthref1112?referer=http://radino.eu/wp-admin/edit.php');" href="http://download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions013.htm#sthref1112">BITAND</a>  function to find out whether the flag is set or not. The flag flag<sub>i</sub> in the number X is set iff BITAND(X, 2<sup>i</sup>) = 1.</p>
<p>I had to merge some tables vertically, in that application. The appearance of a column in the merged table depended on the result of the bitwise OR operations. If the result of the operation table<sub>1</sub>_flag<sub>i</sub> OR table<sub>2</sub>_flag<sub>i</sub> &#8230; OR table<sub>n</sub>_flag<sub>i</sub> was equal to 1, then the column column<sub>i</sub> appeared in the merged table. I had to find all columns visible in the merged table.</p>
<p>There is no BITOR function in the Oracle database for the integer types. But it can be easily implemented: BITOR(N<sub>1</sub>, N<sub>2</sub>) = N<sub>1</sub> + N<sub>2</sub> &#8211; BITAND(N<sub>1</sub>, N<sub>2</sub>). This is common approach to compute the bitwise OR.</p>
<p>The idea is simple: In exactly one (arbitrary) number, we have to unset those bits, which are set in both numbers and then simply use the addition operation.</p>
<p>Example:</p>
<pre>   1001    1000    1001
OR 0101  + 0101  + 0100
   ----    ----    ----
   1101    1101    1101</pre>
<p>We unset the last bit in exactly one number, because it is the only one common bit for both numbers:</p>
<p>BITAND(1001, 0101) = 1</p>
<p>The next step to be done is implementation of bitwise OR aggregate function using <a title="Using User-Defined Aggregate Functions" onclick="pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B28359_01/appdev.111/b28425/aggr_functions.htm?referer=');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B28359_01/appdev.111/b28425/aggr_functions.htm?referer=http://radino.eu/wp-admin/edit.php');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B28359_01/appdev.111/b28425/aggr_functions.htm?referer=http://radino.eu/wp-admin/edit.php');pageTracker._trackPageview('/outgoing/download.oracle.com/docs/cd/B28359_01/appdev.111/b28425/aggr_functions.htm?referer=http://radino.eu/wp-admin/post.php?action=edit&amp;post=4');" href="http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28425/aggr_functions.htm" target="_blank">user-defined aggregates interface</a>:</p>
<pre>
<pre class="brush: sql">
CREATE OR REPLACE TYPE bitor_impl AS OBJECT
(
  bitor NUMBER,

  STATIC FUNCTION ODCIAggregateInitialize(ctx IN OUT bitor_impl) RETURN NUMBER,

  MEMBER FUNCTION ODCIAggregateIterate(SELF  IN OUT bitor_impl,
                                       VALUE IN NUMBER) RETURN NUMBER,

  MEMBER FUNCTION ODCIAggregateMerge(SELF IN OUT bitor_impl,
                                     ctx2 IN bitor_impl) RETURN NUMBER,

  MEMBER FUNCTION ODCIAggregateTerminate(SELF        IN OUT bitor_impl,
                                         returnvalue OUT NUMBER,
                                         flags       IN NUMBER) RETURN NUMBER
)
/

CREATE OR REPLACE TYPE BODY bitor_impl IS
  STATIC FUNCTION ODCIAggregateInitialize(ctx IN OUT bitor_impl) RETURN NUMBER IS
  BEGIN
    ctx := bitor_impl(0);
    RETURN ODCIConst.Success;
  END ODCIAggregateInitialize;

  MEMBER FUNCTION ODCIAggregateIterate(SELF  IN OUT bitor_impl,
                                       VALUE IN NUMBER) RETURN NUMBER IS
  BEGIN
    SELF.bitor := SELF.bitor + VALUE - bitand(SELF.bitor, VALUE);
    RETURN ODCIConst.Success;
  END ODCIAggregateIterate;

  MEMBER FUNCTION ODCIAggregateMerge(SELF IN OUT bitor_impl,
                                     ctx2 IN bitor_impl) RETURN NUMBER IS
  BEGIN
    SELF.bitor := SELF.bitor + ctx2.bitor - bitand(SELF.bitor, ctx2.bitor);
    RETURN ODCIConst.Success;
  END ODCIAggregateMerge;

  MEMBER FUNCTION ODCIAggregateTerminate(SELF        IN OUT bitor_impl,
                                         returnvalue OUT NUMBER,
                                         flags       IN NUMBER) RETURN NUMBER IS
  BEGIN
    returnvalue := SELF.bitor;
    RETURN ODCIConst.Success;
  END ODCIAggregateTerminate;
END;
/
</pre>
</pre>
<p>The last step is definition of the bitwise OR aggregate function. This definition is tied with the object bitor_impl, that implements the aggregate function. I implemented the ODCIAggregateMerge method in this object, therefore I can allow parallel execution by using clause PARALLEL_ENABLE.</p>
<pre>
<pre class="brush: sql">CREATE OR REPLACE FUNCTION bitoragg(x IN NUMBER) RETURN NUMBER
PARALLEL_ENABLE
AGGREGATE USING bitor_impl;
/
</pre>
</pre>
<p>The aggregate function in action:</p>
<pre>
<pre class="brush: sql">SQL&gt; DROP TABLE bitor_test;
Table dropped
SQL&gt; CREATE TABLE bitor_test(table_name varchar2(31), flags number);
Table created
SQL&gt; INSERT INTO bitor_test VALUES (&#039;table1&#039;, 5);  -- 0101
1 row inserted
SQL&gt; INSERT INTO bitor_test VALUES (&#039;table2&#039;, 1);  -- 0001
1 row inserted
SQL&gt; INSERT INTO bitor_test VALUES (&#039;table3&#039;, 9);  -- 1001
1 row inserted
SQL&gt; INSERT INTO bitor_test VALUES (&#039;table4&#039;, 12); -- 1100
1 row inserted
SQL&gt; COMMIT;
Commit complete
SQL&gt; SELECT bitoragg(flags) FROM bitor_test;
BITORAGG(FLAGS)
---------------
13
SQL&gt;
</pre>
</pre>
<p>Simple calculation shows us the correctness of this result:</p>
<p>5<sub>10</sub> OR 1<sub>10</sub> OR 9<sub>10</sub> OR 12<sub>10</sub> = 0101<sub>2</sub> OR 0001<sub>2</sub> OR 1001<sub>2</sub> OR 1100<sub>2</sub> = 1101<sub>2</sub> = 13<sub>10</sub></p>
]]></content:encoded>
			<wfw:commentRss>http://radino.eu/2008/05/31/bitwise-or-aggregate-function/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
