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

<channel>
	<title>Christopher Beck's Blog</title>
	<atom:link href="http://christopherbeck.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://christopherbeck.wordpress.com</link>
	<description>Yet another tech blog on Oracle, ApEx and PL/SQL development ( and other rants, just to keep it interesting ).</description>
	<lastBuildDate>Tue, 01 Dec 2009 18:26:46 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='christopherbeck.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://www.gravatar.com/blavatar/5e891385f17dde3e3c08488a62914360?s=96&#038;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>Christopher Beck's Blog</title>
		<link>http://christopherbeck.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://christopherbeck.wordpress.com/osd.xml" title="Christopher Beck&#8217;s Blog" />
		<item>
		<title>Email BLOB Attachments From The Database</title>
		<link>http://christopherbeck.wordpress.com/2009/12/01/email-blob-attachments-from-the-database/</link>
		<comments>http://christopherbeck.wordpress.com/2009/12/01/email-blob-attachments-from-the-database/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 18:26:46 +0000</pubDate>
		<dc:creator>Christopher Beck</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[BLOB]]></category>
		<category><![CDATA[email attachment]]></category>
		<category><![CDATA[SMTP]]></category>

		<guid isPermaLink="false">http://christopherbeck.wordpress.com/?p=175</guid>
		<description><![CDATA[Recently I was developing an oracle database application and had the requirement to send out an email with an attachment.  Initially it sounded pretty easy.  I&#8217;ll just use the APEX_MAIL package and its all handled for me.  But then I remembered, this was not an APEX application I was developing.   [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=175&subd=christopherbeck&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Recently I was developing an oracle database application and had the requirement to send out an email with an attachment.  Initially it sounded pretty easy.  I&#8217;ll just use the <strong>APEX_MAIL</strong> package and its all handled for me.  But then I remembered, this was not an APEX application I was developing.    So then I thought, no problem, I&#8217;ll just use the <strong>UTL_MAIL</strong> package.  There is an API to add attachments.   But wait, you can only add <strong>VARCHAR </strong>and <strong>RAW </strong>attachments and there is a max length of 32K on them.  Not very useful if you want to send a multi-megabyte document as an attachment ( ie. a blob).  So I had to drop down to an even lower API, <strong>UTL_SMTP</strong> and handle it all myself.  Oh, and the attachment needed to be zipped as well (to save space in the tubes of our interwebs).  I found the exercise interesting and thought I would share it with you.</p>
<p>For this example we have a table</p>
<pre class="brush: jscript;">
create table assets(
  id number primary key,
  name varchar2(100),
  content blob
  mime_type varchar2(100) );
</pre>
<p>And the code</p>
<pre class="brush: jscript;">
procedure mail_asset(
  p_asset_id number,
  p_from varchar2,
  p_to varchar2,
  p_subject varchar2,
  p_message varchar2 ) is
--
  l_asset assets%rowtype;
  l_blob blob := to_blob('1');
  l_conn utl_smtp.connection;
  l_raw raw(57);
  l_len integer := 0;
  l_idx integer := 1;
  l_buff_size integer := 57;
  l_boundary varchar2(32) := sys_guid();
  l_attachment_name long;
begin

  -- Connect
  l_conn := utl_smtp.open_connection( 'mail.oracle.com' );
  utl_smtp.helo( l_conn, 'oracle.com' );
  utl_smtp.mail( l_conn, p_from );
  utl_smtp.rcpt( l_conn, p_to );
  utl_smtp.open_data(l_conn);

  -- Header
  utl_smtp.write_data( l_conn, 'From: ' || p_from || utl_tcp.crlf );
  utl_smtp.write_data( l_conn, 'To: ' || p_to || utl_tcp.crlf );
  utl_smtp.write_data( l_conn, 'Subject: ' || p_subject ||
                               utl_tcp.crlf );
  utl_smtp.write_data( l_conn, 'MIME-Version: 1.0' || utl_tcp.crlf );
  utl_smtp.write_data( l_conn, 'Content-Type: multipart/mixed; ' ||
                               utl_tcp.crlf );
  utl_smtp.write_data( l_conn, ' boundary= &quot;' || l_boundary || '&quot;' ||
                               utl_tcp.crlf );
  utl_smtp.write_data( l_conn, utl_tcp.crlf );

  -- Body
  utl_smtp.write_data( l_conn, '--' || l_boundary || utl_tcp.crlf );
  utl_smtp.write_data( l_conn, 'Content-Type: text/plain;' ||
                               utl_tcp.crlf );
  utl_smtp.write_data( l_conn, ' charset=US-ASCII' || utl_tcp.crlf );
  utl_smtp.write_data( l_conn, utl_tcp.crlf );
  utl_smtp.write_data( l_conn, l_message || utl_tcp.crlf );
  utl_smtp.write_data( l_conn, utl_tcp.crlf );

  -- Fetch the asset info
  for c in ( select *
               from assets
              where asset_id = p_asset_id ) loop

    -- Compress if a content and not already zipped.
    if ( c.mime_type != 'application/zip' then
      utl_compress.lz_compress( src =&gt; c.content,
                                dst =&gt; l_blob );
      l_attachment_name := c.name || '.gz';
    else
      l_blob := c.content;
      l_attachment_name := c.name;
    end if;

    -- Attachment
    utl_smtp.write_data( l_conn, '--' || l_boundary || utl_tcp.crlf );
    utl_smtp.write_data( l_conn, 'Content-Type: application/octet-stream'
                                 || utl_tcp.crlf );
    utl_smtp.write_data( l_conn, 'Content-Disposition: attachment; ' ||
                                 utl_tcp.crlf );
    utl_smtp.write_data( l_conn, ' filename=&quot;' || l_attachment_name || '&quot;'
                                 || utl_tcp.crlf );
    utl_smtp.write_data( l_conn, 'Content-Transfer-Encoding: base64' ||
                                 utl_tcp.crlf );
    utl_smtp.write_data( l_conn, utl_tcp.crlf );

    -- Loop through the blob
    -- chuck it up into 57-byte pieces
    -- and base64 encode it and write it into the mail buffer
    l_len := dbms_lob.getlength(l_blob);
    while l_idx &lt; l_len loop
      dbms_lob.read( l_blob, l_buff_size, l_idx, l_raw );
      utl_smtp.write_raw_data( l_conn, utl_encode.base64_encode(l_raw) );
      utl_smtp.write_data( l_conn, utl_tcp.crlf );
      l_idx := l_idx + l_buff_size;
    end loop;
    utl_smtp.write_data( l_conn, utl_tcp.crlf );

  end loop;

  -- Close Email
  utl_smtp.write_data( l_conn, '--' || l_boundary || '--' ||
                                         utl_tcp.crlf );
  utl_smtp.write_data( l_conn, utl_tcp.crlf || '.' || utl_tcp.crlf );
  utl_smtp.close_data( l_conn );
  utl_smtp.quit( l_conn );

exception
  -- smtp errors, close connection and reraise
  when utl_smtp.transient_error or
       utl_smtp.permanent_error then
    utl_smtp.quit( l_conn );
    raise;

end mail_asset;
</pre>
<p>Just a few things about the code.</p>
<p><strong>Line 15</strong> &#8211; I use sys_guid() to generate a random 32 character string which I use as the boundary marker in the email message.  You can use any character string you like.</p>
<p><strong>Lines 20 and 21</strong> &#8211; You will need to change to your smtp server.</p>
<p><strong>Line 34</strong> &#8211; You will notice that there is a space in front of boundary.  That is on purpose. The reason for that is that <strong>Content-Type</strong> (Line 32) and the <strong>boundary</strong> could be on the same line like this:</p>
<p><strong>Content-Type: multipart/mixed; boundary=&#8221;xxxxxxxxxxxx&#8221;</strong></p>
<p>But for formatting sake, I broke it up into two lines, so it needs to be sent to the smtp server like</p>
<p><strong>Content-Type: multipart/mixed;<br />
&nbsp;boundary=&#8221;xxxxxxxxxxxx&#8221;</strong><br />
^ (single leading space)</p>
<p>with a leading space on boundary.  I also did it on lines 42 and 68.</p>
<p><strong>Line 79</strong> &#8211; No you can not do larger reads.  Each line of the encoded attachment needs to be 57 bytes.</p>
<p>In my example, I will only get at most 1 attachment because I pass in the asset_id and that is defined as the primary key.   But if the query at line 48 was changed to possibly return more than a single row, the code would still work and we would have an email with multiple attachments.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/christopherbeck.wordpress.com/175/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/christopherbeck.wordpress.com/175/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/christopherbeck.wordpress.com/175/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/christopherbeck.wordpress.com/175/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/christopherbeck.wordpress.com/175/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/christopherbeck.wordpress.com/175/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/christopherbeck.wordpress.com/175/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/christopherbeck.wordpress.com/175/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/christopherbeck.wordpress.com/175/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/christopherbeck.wordpress.com/175/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=175&subd=christopherbeck&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://christopherbeck.wordpress.com/2009/12/01/email-blob-attachments-from-the-database/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1f43c7305915db8a38b359be077b2cc8?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">beckdood</media:title>
		</media:content>
	</item>
		<item>
		<title>Enhanced APEX Shuttle Item</title>
		<link>http://christopherbeck.wordpress.com/2009/04/28/enhanced-shuttle-item/</link>
		<comments>http://christopherbeck.wordpress.com/2009/04/28/enhanced-shuttle-item/#comments</comments>
		<pubDate>Tue, 28 Apr 2009 01:07:55 +0000</pubDate>
		<dc:creator>Christopher Beck</dc:creator>
				<category><![CDATA[APEX]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[shuttle]]></category>

		<guid isPermaLink="false">http://christopherbeck.wordpress.com/?p=158</guid>
		<description><![CDATA[Recently I have been really, really busy building some internal applications for my company. All of them using Oracle and APEX of course. To satisfy some of application&#8217;s requirements, and just for usability sake, I had to tweek the default behavior of the APEX shuttle item.  The reason was the initial LOV that populated [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=158&subd=christopherbeck&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Recently I have been really, really busy building some internal applications for my company. All of them using Oracle and APEX of course. To satisfy some of application&#8217;s requirements, and just for usability sake, I had to tweek the default behavior of the APEX shuttle item.  The reason was the initial LOV that populated the shuttle contained over 500 values.  About 490+ too many as far as I was concerned.  The users felt the same way.  They complained that it was too hard to find what they were looking for, even though the list was in alphabetical order and I agreed.  So, I decided to add the functionality to allow the user to constrain the values in left-hand side of the shuttle.  Similar to the Popup LOVs with a filter option, but I wanted to use AJAX to accomplish it to avoid a page submit.  After a bunch of playing around and optimization, here is what I came up with:</p>
<p><a href="http://apex.oracle.com/pls/otn/f?p=19903:10">http://apex.oracle.com/pls/otn/f?p=19903:10</a><br />
<strong>Username/Password:  demo/demo</strong></p>
<p>I was surprised that it was not that hard to accomplish and there are very few moving parts.  All you need is a javascript function to make the AJAX call, an On Demand process to fetch only those values that meet the filter&#8217;s constraint and a way to trigger it.</p>
<p><strong>How It Works.</strong></p>
<p>As the user types in the textbox the shuttle automagically filters itself.  I use an onKeyUp event on the textbox P10_SEARCH_BY to trigger the AJAX call.</p>
<p><strong><code>onKeyUp="populateShuttle( this,'P10_SHUTTLE');"</code></strong></p>
<p>So everytime a KeyUp event happens in that textbox, a call to the populateShuttle function happens.  That function is responsible for making the AJAX call to the On-Demand Process, which fetches the appropriate values, and then parsing the results and repopulating the left hand side of the shuttle.</p>
<pre class="brush: jscript;">
function populateShuttle(filter,shuttleName)
{
  var right = $x(shuttleName+&quot;_RIGHT&quot;);

  for ( var i=0;i&lt;right.length; i++ )
    right.options[i].selected = true;

  var req = new htmldb_Get( null, 19903,
                          'APPLICATION_PROCESS=populateShuttle', 0 );

  req.addParam( 'x01', $v(right) );
  req.addParam( 'x02', $v(filter) );

  var resp = eval(req.get());

  var left = $x(shuttleName+&quot;_LEFT&quot;);
  left.length=0;

  if (resp)
    for ( var i=0; i&lt;resp.length; i++ )
      left.options[i] = new Option(resp[i].data, resp[i].id);	

  req = null;
}
</pre>
<p>Although APEX treats the shuttle as a single element, it is in fact made up of many HTML elements, 10 images and 2 multiselect list boxes.  With a little poking around the HTML of a generated APEX page with a shuttle item on it, I was able to determine that the actual DOM names of the multiselect list boxes of a shuttle were <strong>[SHUTTLE_NAME]_LEFT</strong> and <strong>[SHUTTLE_NAME]_RIGHT</strong>.   How convenient.  Accessing the actual elements was then trivial.  I just used the APEX supplied function <strong>$x()</strong> function to get the elements.</p>
<p>The first thing I do is get the right textbox and loop over its values, selecting each one.  This is so when I fetch its value, I get all the elements in the list.  I need this information so when I fetch the values for the left hand side of the shuttle, based on the user&#8217;s filter, I do NOT bring back any values that have already been moved to the right hand side of the shuttle.  In my example say you had already selected KING and moved him to the right.  Then you type a &#8216;K&#8217; in the filter_by textbox, you will only get back CLARK and BLAKE even though KING also meets the constraint of containing a &#8216;K&#8217;.<br />
Next, I get the value of the right hand side of the shuttle and the value of the filter_by textbox, using the <strong>$v()</strong> function and send the values to the On Demand process via the APEX global variables <strong>g_x01</strong> and <strong>g_x02</strong>.</p>
<p>The On Demand process is just a simple PL/SQL block that is a query loop.</p>
<pre class="brush: jscript;">
declare
  l_selected long  := wwv_flow.g_x01;
  l_search long := wwv_flow.g_x02;
begin
  htp.prn('[');
  for c in (
    select ename, empno, rownum r
      from emp
     where regexp_like( ename, nvl(l_search,ename), 'i' )
       and nvl(instr(':'||l_selected||':',':'||empno||':'),0)=0 )
  loop
    htp.prn( case when c.r&amp;gt;1 then',' else null end ||
             '{ id: ' || c.empno ||
             ', data: &quot;' || c.ename || '&quot;}' );
  end loop;
  htp.prn(']');
end;
</pre>
<p>It fetches all the values that match the filter</p>
<p><code> where regexp_like( ename, nvl(l_search,ename), 'i' )</code></p>
<p>but not those already be selected by the user.</p>
<p><code> and nvl(instr(':'||l_selected||':',':'||empno||':'),0)=0)</code></p>
<p>Now it&#8217;s just a simple process of looping over the rows, packaging them up and sending them back.  I have become a big fan of <strong>JSON </strong>( JavaScript Object Notation <a href="http://www.json.org">http://www.json.org/</a> ) ,  so that how I am packaging up the payload to pass back.  Basically, I&#8217;m making the results into a javascript array of objects.  Each object has an id and data element.  The payload look something like this</p>
<p><code>[{id: 7839, data: "KING"}{id: 7698, data: "BLAKE"} ... ]</code></p>
<p>This makes it super simple easy to work with once it gets back to the calling javascript function.  All you need to do is apply an eval() on it and its transformed into a true javascript array of objects that can be easily looped over and referenced.</p>
<p>In one line of code, I call the On Demand process, getting back the JSON packed result and <strong>eval()</strong> it.</p>
<p><code>var resp = eval(req.get());</code></p>
<p>Now the variable resp is an Array of objects with two elements in each object, id and data.  Looping over the values and populating the left hand side of the shuttle is trivial now.</p>
<pre>
<code>  if (resp)
    for ( var i=0; i&lt;resp.length; i++ )
      left.options[i] = new Option(resp[i].data, resp[i].id);</code>
</pre>
<p>And there you have it.  I hope I have shown that with some minor tweeks, you can extend the functionality of the base APEX items to be much more functional and user friendly.  As always, comments ( good and bad ) are always welcome.<span id="more-158"></span></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/christopherbeck.wordpress.com/158/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/christopherbeck.wordpress.com/158/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/christopherbeck.wordpress.com/158/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/christopherbeck.wordpress.com/158/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/christopherbeck.wordpress.com/158/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/christopherbeck.wordpress.com/158/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/christopherbeck.wordpress.com/158/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/christopherbeck.wordpress.com/158/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/christopherbeck.wordpress.com/158/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/christopherbeck.wordpress.com/158/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=158&subd=christopherbeck&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://christopherbeck.wordpress.com/2009/04/28/enhanced-shuttle-item/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1f43c7305915db8a38b359be077b2cc8?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">beckdood</media:title>
		</media:content>
	</item>
		<item>
		<title>Pipelined Functions</title>
		<link>http://christopherbeck.wordpress.com/2008/12/05/pipelined-functions/</link>
		<comments>http://christopherbeck.wordpress.com/2008/12/05/pipelined-functions/#comments</comments>
		<pubDate>Fri, 05 Dec 2008 17:25:11 +0000</pubDate>
		<dc:creator>Christopher Beck</dc:creator>
				<category><![CDATA[APEX]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[Pipeline Function]]></category>

		<guid isPermaLink="false">http://christopherbeck.wordpress.com/?p=146</guid>
		<description><![CDATA[Well, it&#8217;s been a quite while since I posted (I know, I’m slacking) so I thought I&#8217;d just quickly blog about what I just helped someone with yesterday.  It required me to use a pipelined function.  Not everyone has seen of them so I thought it may be interesting.
Pipelined functions allow you to [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=146&subd=christopherbeck&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Well, it&#8217;s been a quite while since I posted (I know, I’m slacking) so I thought I&#8217;d just quickly blog about what I just helped someone with yesterday.  It required me to use a pipelined function.  Not everyone has seen of them so I thought it may be interesting.</p>
<p>Pipelined functions allow you to basically select from a function rather than a database table.</p>
<p>A colleague of mine had to build an APEX report of opportunities.  The report was to be constrained by a multiselect listbox of product ids.  Show all opportunities that have ANY of the selected product ids.  So far it sound pretty easy.  The tricky part was how the product ids were stored in the opportunity table.</p>
<pre class="brush: jscript;">
create table opportunity(
  name varchar2(100),
  product_ids varchar2(255)
);
</pre>
<p>The PRODUCT_IDS column was populated with a colon delimited list of all the products that were used in that opportunity.  Now before you yell that that is probably not the best way to store that data and that a master-detail table relationship is probably the better way to go, I 100% agree.  But unfortunately, when you inherit an application, you many times must make do with what the original developer put in place (and that is the case here).</p>
<p>We all know when you submit a multiselect listbox in APEX, it comes in as a colon delimited list of all the values that were selected.  What we need to do is tokenize that selectlist string and compare each value against the table.</p>
<p>I came up with two possible solutions:</p>
<p>1. Build the query by hand.</p>
<p>Using apex_util.string_to_table() on the input, loop over all the values and manually build the report query by hand.<span>  </span></p>
<pre class="brush: jscript;">
declare
  l_ids apex_application_global.vc_arr2;
  l_query varchar2(32767) := null;
begin
  l_ids := apex_util.string_to_table( :p9_product_ids );
  for i in 1 .. l_ids.count loop
    l_query := l_query || &lt;insert query here&gt;;
    if i &lt;&gt; l_ids.count then
      l_query := l_query || ' union all ';
    end if';
  end loop;
  return l_query;
end;
</pre>
<p>This would have worked just fine (besides having to run the query N times and union all them together).</p>
<p>But I like to use nifty, (and more optimized) options and so I implemented my other solution:</p>
<p>2. Use a pipelined function.</p>
<p>To use this, we need to create a type and a function that returns that type.</p>
<pre class="brush: jscript;">
create or replace type myTableType as
table of varchar2(255)
/
</pre>
<pre class="brush: jscript;">
create or replace
function to_myTableType( p_string varchar2 )
return myTableType PIPELINED is
  l_arr apex_application_global.vc_arr2;
begin
  l_arr := apex_util.string_to_table( p_string );
  for i in 1 .. l_arr.count loop
    PIPE ROW( ':' || l_arr(i) || ':' );
  end loop;
  return;
end;
/
</pre>
<p>Notice that the function is declared as PIPELINED in its declaration.  Also notice the PIPE ROW() syntax in the loop.  That is where the function returns multiple values as rows in a query.  Its using the string_to_table() function to tokenize the string and then looping over the tokens, pipes the results out as rows.  And finally, this function contains a return clause without returning anything.  It had already returned multiple values in the PIPE ROW() line.</p>
<p>Now that we have this we can write a single, simple query in APEX that looks like this:</p>
<pre class="brush: jscript;">
select o.name, o.product_ids
  from opportunity o,
        table( to_myTableType( :p1_product_ids )) p
 where instr( ':' || o.product_ids || ':', p.COLUMN_VALUE ) &gt; 0;
</pre>
<p>Check out a working version here:  <a href="http://apex.oracle.com/pls/otn/f?p=19903:9">http://apex.oracle.com/pls/otn/f?p=19903:9</a></p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/christopherbeck.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/christopherbeck.wordpress.com/146/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/christopherbeck.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/christopherbeck.wordpress.com/146/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/christopherbeck.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/christopherbeck.wordpress.com/146/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/christopherbeck.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/christopherbeck.wordpress.com/146/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/christopherbeck.wordpress.com/146/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/christopherbeck.wordpress.com/146/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=146&subd=christopherbeck&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://christopherbeck.wordpress.com/2008/12/05/pipelined-functions/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1f43c7305915db8a38b359be077b2cc8?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">beckdood</media:title>
		</media:content>
	</item>
		<item>
		<title>WebLogic Server and APEX</title>
		<link>http://christopherbeck.wordpress.com/2008/09/15/weblogic-server-and-apex/</link>
		<comments>http://christopherbeck.wordpress.com/2008/09/15/weblogic-server-and-apex/#comments</comments>
		<pubDate>Mon, 15 Sep 2008 20:10:07 +0000</pubDate>
		<dc:creator>Christopher Beck</dc:creator>
				<category><![CDATA[APEX]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[WebLogic]]></category>

		<guid isPermaLink="false">http://christopherbeck.wordpress.com/?p=125</guid>
		<description><![CDATA[A good friend and colleague of mine at Oracle, Mark Greynolds, shared with me his work with WebLogic and APEX and getting them to work together.  I thought it was something that everyone would be interested in and asked him if he would be willing to document the steps and allow me to post [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=125&subd=christopherbeck&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>A good friend and colleague of mine at Oracle, <strong>Mark Greynolds</strong>, shared with me his work with <a href="http://www.oracle.com/appserver/weblogic/weblogic-suite.html" target="_blank">WebLogic</a> and APEX and getting them to work together.  I thought it was something that everyone would be interested in and asked him if he would be willing to document the steps and allow me to post them here on my blog.  He was and so here it is.</p>
<h2>WebLogic Server and APEX</h2>
<p>When a WebLogic Server (WLS) is the primary Web server, accessing APEX pages though the WLS requires a proxy. The configuration of APEX generally follows one of two configurations &#8211; Apache with mod_plsql or the Embedded PL/SQL gateway. When WebLogic (without Apache) is the main HTTP server, getting APEX to surface on the same port as WebLogic requires some form of proxy.</p>
<h2>Overall Approach</h2>
<p>This solution creates a very simple Web Application that invokes a Java Proxy Servlet when a user tries to access APEX pages. Wrapping this Web Application around the Java Proxy Servlet lets the WLS serve APEX without any port conflicts. The WLS Proxy Servlet is a fully documented out of the box tool.  To create and deploy the Web Application simply build the files outlined in this document, deploy the application and then access APEX.</p>
<h2>Exploded deployment</h2>
<p>For convenience, this solution takes advantage of the exploded deployment feature of the WSL. In addition to the ability to deploy jar, war and ear files, the WLS can deploy Web Applications as an exploded directory that contains the same contents of the archive file. An exploded archive directory contains the same files and directories as a jar archive. However, the files and directories reside directly in the file system instead of as a single archive file (JAR). This example uses the exploded deployment style to create the Web Application for this example.</p>
<h2>Default WebLogic application</h2>
<p>The default Web Application is what the server sends to browser clients who do not specify a recognized URI (or specify only &#8220;/&#8221; as the URI). Each server has only one default Web Application and for this solution to work, this application must be set as the default. If there is already a default, this servlet could be added to the existing application by using an exploded deployment of the default with modification to the web.xml to register the APEX proxy.</p>
<h2>Pre-requisites</h2>
<p><strong>1.</strong> An Oracle database successfully serving APEX pages. The APEX instance may be on the same or different machine and served from either Apache or the Embedded PL/SQL gateway. In this example, APEX uses the Embedded PL/SQL Gateway of a database running on the same machine as the WebLogic server and natively appears at the <strong>http://localhost:8080/</strong>apex URL.</p>
<p><strong>2.</strong> An Oracle WebLogic Server 10.3 running a Node Manger, the Administration Console and a Managed server. This example uses a domain created specifically for this exercise named APEXDemo. The WLS Administration console uses port 7001 and the Managed Server uses port 80.</p>
<p><strong>3.</strong> There is no other “default” WebLogic application for the Managed Server.</p>
<h2>Create the APEX Proxy Servlet</h2>
<p><strong>1.</strong> Create the following directory structure somewhere on disk. This example assumes the C:\ drive is used. Note: the <strong>apexproxy.war</strong> directory name mimics the normal J2EE naming convention for Web Application archive (WAR).</p>
<p><a href="http://christopherbeck.files.wordpress.com/2008/09/dir.png"><img class="aligncenter size-full wp-image-126" title="dir" src="http://christopherbeck.files.wordpress.com/2008/09/dir.png?w=145&#038;h=52" alt="" width="145" height="52" /></a></p>
<p><strong>2.</strong> In the <strong>apexproxy.war</strong> directory, create the <strong>index.html</strong> file. The WLS Managed Server renders this page when the server cannot map the browser’s URL to a valid destination. For this example, APEX becomes the default page due to a simple redirect to the full APEX path.</p>
<pre class="brush: xml;">

&lt;html&gt;
  &lt;head&gt;
    &lt;meta http-equiv=&quot;refresh&quot; content=&quot;0;url=apex&quot;&gt;
  &lt;/head&gt;
  &lt;body&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p><strong>3.</strong> In the <strong>WEB-INF</strong> directory, create the web.xml file that defines this simple Web Application.</p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;web-app&gt;
  &lt;display-name&gt;APEX Proxy&lt;/display-name&gt;
  &lt;servlet&gt;
    &lt;servlet-name&gt;ProxyServlet&lt;/servlet-name&gt;
    &lt;servlet-class&gt;
        weblogic.servlet.proxy.HttpProxyServlet
    &lt;/servlet-class&gt;
    &lt;init-param&gt;
&lt;param-name&gt;redirectURL&lt;/param-name&gt;
&lt;param-value&gt;http://localhost:8080&lt;/param-value&gt;
    &lt;/init-param&gt;
  &lt;/servlet&gt;
  &lt;servlet-mapping&gt;
     &lt;servlet-name&gt;ProxyServlet&lt;/servlet-name&gt;
     &lt;url-pattern&gt;/apex/*&lt;/url-pattern&gt;
  &lt;/servlet-mapping&gt;
  &lt;servlet-mapping&gt;
  &lt;servlet-name&gt;ProxyServlet&lt;/servlet-name&gt;
    &lt;url-pattern&gt;/i/*&lt;/url-pattern&gt;
  &lt;/servlet-mapping&gt;
  &lt;welcome-file-list&gt;
      &lt;welcome-file&gt;index.html&lt;/welcome-file&gt;
  &lt;/welcome-file-list&gt;
&lt;/web-app&gt;
</pre>
<p>The <strong>&lt;servlet-class&gt;</strong> tag identifies the proxy servlet class and provides the<br />
redirection URL to use when the container invokes the servlet. The two<br />
<strong>&lt;servlet-mapping&gt;</strong> tags explicitly identify the two URL patterns used by APEX.<br />
The WLS documentation suggests using a single mapping of “/” but this causes every<br />
unmatched request to forward to the Oracle XML DB default splash page and ignores the<br />
<strong>index.html</strong> file.<br />
<strong>4.</strong> In the <strong>WEB-INF</strong> directory, also create the following <strong>weblogic.xml</strong> file. At deployment, WLS scans this file for the information on how to configure the deployment.</p>
<pre class="brush: xml;">
&lt;?xml version='1.0' encoding='UTF-8'?&gt;
&lt;weblogic-web-app
 xmlns=&quot;http://www.bea.com/ns/weblogic/weblogic-web-app&quot;
 xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
 xsi:schemaLocation=&quot;http://www.bea.com/ns/weblogic/weblogic-web-app

http://www.bea.com/ns/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd&quot;&gt;

  &lt;session-descriptor&gt;&lt;/session-descriptor&gt;
  &lt;jsp-descriptor&gt;&lt;/jsp-descriptor&gt;
  &lt;container-descriptor&gt;&lt;/container-descriptor&gt;
  &lt;context-root&gt;/&lt;/context-root&gt;
  &lt;servlet-descriptor&gt;
    &lt;servlet-name&gt;ProxyServlet&lt;/servlet-name&gt;
  &lt;/servlet-descriptor&gt;
&lt;/weblogic-web-app&gt;
</pre>
<p>The <strong>&lt;context-root&gt;</strong> tag is the key for making this example function. This tag<br />
makes this the default application for the Managed Server.</p>
<h2>Deploy the Proxy Servlet</h2>
<p><strong>5.</strong> Begin the deployment by accessing the WLS Administration Console using the http://localhost:7001/console URL. For this example, the Administration Console’s Username and Password are <strong>weblogic</strong> and <strong>weblogic.</strong></p>
<p><a href="http://christopherbeck.files.wordpress.com/2008/09/login.png"><img class="aligncenter size-full wp-image-132" title="login" src="http://christopherbeck.files.wordpress.com/2008/09/login.png?w=480&#038;h=327" alt="" width="480" height="327" /></a></p>
<p><strong>6.</strong> On the left side navigation panel, click the <strong>Deployments</strong> link.</p>
<p><a href="http://christopherbeck.files.wordpress.com/2008/09/step-6.png"><img class="aligncenter size-full wp-image-133" title="step-6" src="http://christopherbeck.files.wordpress.com/2008/09/step-6.png?w=259&#038;h=314" alt="" width="259" height="314" /></a></p>
<p><strong>7.</strong> Click the <strong>Install</strong> button.</p>
<p><a href="http://christopherbeck.files.wordpress.com/2008/09/step-7.png"><img class="aligncenter size-full wp-image-134" title="step-7" src="http://christopherbeck.files.wordpress.com/2008/09/step-7.png?w=480&#038;h=131" alt="" width="480" height="131" /></a></p>
<p><strong>8.</strong> Use the <strong>Path:</strong> field to locate the <strong>C:\APEXProxy</strong> directory. NOTE: this page can<br />
navigate directories on the drive by entering C:\ and clicking the <strong>Next</strong> button. The server<br />
returns an error and shows the directories in a navigable list.</p>
<p><a href="http://christopherbeck.files.wordpress.com/2008/09/step-8.png"><img class="aligncenter size-full wp-image-135" title="step-8" src="http://christopherbeck.files.wordpress.com/2008/09/step-8.png?w=480&#038;h=350" alt="" width="480" height="350" /></a></p>
<p>Click the radio button next to the <strong>apexproxy.war</strong> directory name and then click the<br />
<strong>Next</strong> button. NOTE: do not type in the complete path to the war directory – clicking the<br />
radio button for the WAR automatically completes the Path specification.</p>
<p>9. Click the <strong>Next</strong> button to accept installing the deployment as an application.</p>
<p><a href="http://christopherbeck.files.wordpress.com/2008/09/step-9.png"><img class="aligncenter size-full wp-image-136" title="step-9" src="http://christopherbeck.files.wordpress.com/2008/09/step-9.png?w=480&#038;h=336" alt="" width="480" height="336" /></a></p>
<p>10. Select the desired server and click the <strong>Next</strong> button.</p>
<p><a href="http://christopherbeck.files.wordpress.com/2008/09/step-10.png"><img class="aligncenter size-full wp-image-137" title="step-10" src="http://christopherbeck.files.wordpress.com/2008/09/step-10.png?w=480&#038;h=342" alt="" width="480" height="342" /></a></p>
<p>11. Click the <strong>Finish</strong> button to accept default values for all the remaining deployment values<br />
and finish the deployment.</p>
<p>12. The Administration Console displays the configuration page for the newly deployed<br />
application with the following messages.</p>
<p><a href="http://christopherbeck.files.wordpress.com/2008/09/step-12-1.png"><img class="aligncenter size-full wp-image-139" title="step-12-1" src="http://christopherbeck.files.wordpress.com/2008/09/step-12-1.png?w=377&#038;h=81" alt="" width="377" height="81" /></a></p>
<p>Lower down the page, the server display the status of the new application.</p>
<p><a href="http://christopherbeck.files.wordpress.com/2008/09/step-12-2.png"><img class="aligncenter size-full wp-image-140" title="step-12-2" src="http://christopherbeck.files.wordpress.com/2008/09/step-12-2.png?w=480&#038;h=156" alt="" width="480" height="156" /></a></p>
<p>13. Enter the Managed Server URL in to a browser to see the APEX login page.</p>
<p>http://localhost</p>
<p>The browser receives a redirect from the index.html page and displays the APEX login<br />
screen.</p>
<p><a href="http://christopherbeck.files.wordpress.com/2008/09/step-13.png"><img class="aligncenter size-full wp-image-141" title="step-13" src="http://christopherbeck.files.wordpress.com/2008/09/step-13.png?w=480&#038;h=391" alt="" width="480" height="391" /></a></p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/christopherbeck.wordpress.com/125/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/christopherbeck.wordpress.com/125/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/christopherbeck.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/christopherbeck.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/christopherbeck.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/christopherbeck.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/christopherbeck.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/christopherbeck.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/christopherbeck.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/christopherbeck.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/christopherbeck.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/christopherbeck.wordpress.com/125/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=125&subd=christopherbeck&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://christopherbeck.wordpress.com/2008/09/15/weblogic-server-and-apex/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1f43c7305915db8a38b359be077b2cc8?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">beckdood</media:title>
		</media:content>

		<media:content url="http://christopherbeck.files.wordpress.com/2008/09/dir.png" medium="image">
			<media:title type="html">dir</media:title>
		</media:content>

		<media:content url="http://christopherbeck.files.wordpress.com/2008/09/login.png" medium="image">
			<media:title type="html">login</media:title>
		</media:content>

		<media:content url="http://christopherbeck.files.wordpress.com/2008/09/step-6.png" medium="image">
			<media:title type="html">step-6</media:title>
		</media:content>

		<media:content url="http://christopherbeck.files.wordpress.com/2008/09/step-7.png" medium="image">
			<media:title type="html">step-7</media:title>
		</media:content>

		<media:content url="http://christopherbeck.files.wordpress.com/2008/09/step-8.png" medium="image">
			<media:title type="html">step-8</media:title>
		</media:content>

		<media:content url="http://christopherbeck.files.wordpress.com/2008/09/step-9.png" medium="image">
			<media:title type="html">step-9</media:title>
		</media:content>

		<media:content url="http://christopherbeck.files.wordpress.com/2008/09/step-10.png" medium="image">
			<media:title type="html">step-10</media:title>
		</media:content>

		<media:content url="http://christopherbeck.files.wordpress.com/2008/09/step-12-1.png" medium="image">
			<media:title type="html">step-12-1</media:title>
		</media:content>

		<media:content url="http://christopherbeck.files.wordpress.com/2008/09/step-12-2.png" medium="image">
			<media:title type="html">step-12-2</media:title>
		</media:content>

		<media:content url="http://christopherbeck.files.wordpress.com/2008/09/step-13.png" medium="image">
			<media:title type="html">step-13</media:title>
		</media:content>
	</item>
		<item>
		<title>Report Hierarchical Data With APEX</title>
		<link>http://christopherbeck.wordpress.com/2008/09/05/report-hierarchical-data-with-apex/</link>
		<comments>http://christopherbeck.wordpress.com/2008/09/05/report-hierarchical-data-with-apex/#comments</comments>
		<pubDate>Fri, 05 Sep 2008 15:35:54 +0000</pubDate>
		<dc:creator>Christopher Beck</dc:creator>
				<category><![CDATA[APEX]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[CONNECT BY]]></category>
		<category><![CDATA[hierarchy]]></category>
		<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://christopherbeck.wordpress.com/?p=113</guid>
		<description><![CDATA[Anyone familiar with Oracle and hearing the word hierarchical immediately thinks of the sql CONNECT BY clause.  And I would bet that when they think about displaying this data, they would use some sort of tree widget.  APEX has a built-in tree widget and for many applications, it works fine.  
The drawback to the built-in tree [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=113&subd=christopherbeck&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Anyone familiar with Oracle and hearing the word hierarchical immediately thinks of the sql <a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/queries003.htm" target="_blank">CONNECT BY</a> clause.  And I would bet that when they think about displaying this data, they would use some sort of tree widget.  APEX has a built-in tree widget and for many applications, it works fine.  </p>
<p>The drawback to the <a href="http://download.oracle.com/docs/cd/E10513_01/doc/appdev.310/e10499/nav.htm#insertedID4" target="_blank">built-in tree widget</a> is that it brings back the entire dataset on the initial page render.  Good and Bad.  Saves round trips to the server, but could take a lot of initial time depending on the size of the data.  Showing/hiding branches of the tree with many elements also can make the application feel sluggish.  </p>
<p>On my current project, I needed to build an interface against just such a dataset.  So I needed an alternative to the built-in tree.  I looked at either writing my own tree using javascript and AJAX or using an already developed one.  Neither one appealed to me.  They both added development complexity and maintaining them weighed on my final decision.</p>
<p>What I chose to do was build a breadcrumb-like report displaying the path traversed and a second report displaying the elements at the current level.  All default APEX functionality.  Simple clean interface.  Easily developed and easily maintained.  <a href="http://apex.oracle.com/pls/otn/f?p=19903:5" target="_blank">You can check it out here</a>.</p>
<p>Let me quickly walk you through how it was built:</p>
<p><strong>1.</strong> Create a report on the base table constrained by the hidden item.  The query should look something like:</p>
<pre class="brush: sql;">
select *
  from emp
 where nvl(mgr,-1) = :p5_empno
</pre>
<p>I then linked the <strong>ENAME</strong> column back to the same page passing the <strong>EMPNO</strong> value into <strong> <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> 5_EMPNO</strong>.<br />
 <br />
<strong> 2.</strong> Create a hidden Item to hold the manager&#8217;s id.  I put it in the step 1&#8217;s report region and called it <strong>P5_EMPNO</strong> and set its default value to<strong> -1</strong>.</p>
<p><strong>3.</strong> Create a PATH report to manage the traversing the data.  This is where the magic happens.  I make use of the <a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/functions168.htm#SQLRF06116" target="_blank">SYS_CONNECT_BY_PATH()</a> function in conjunction with the <strong>START WITH&#8230;CONNECT BY </strong>clause.  The query I used was:</p>
<pre class="brush: sql;">
select '&lt;a href=&quot;f?p=' || :app_id || ':5:' ||
         :app_session || 
         '::::p5_empno:-1&quot;&gt;Top&lt;/a&gt; &gt;&gt;&gt; ' || 
         substr(
           sys_connect_by_path( 
             '&lt;a href=&quot;f?p=' || :app_id || ':5:' ||
             :app_session || '::::p5_empno:' || empno ||
             '&quot;&gt;' || ename || '&lt;/a&gt;', ' : ' ), 4 ) path 
  from emp 
 where empno = :p5_empno 
 start with mgr is null 
connect by prior empno = mgr
</pre>
<p>Some other tweeks to this region.  No Pagination.  Report Template of Value Attribute Pairs.  Layout above the first report region.  No region template.</p>
<p><strong>4.</strong> ???</p>
<p><strong>5. Profit!</strong></p>
<p>Now you can use the main report to drill into the children of the row you selected, all the while maintaining the context of where you are in the hierarchy with the path.</p>
<p>It&#8217;s a quick simple technique, and 100% APEX.  No additional javascript libraries or custom coding to accomplish a clean and simple interface.  And it will be easily maintained, either by you, or by the developer that comes after you.</p>
<p>Let me know what you think.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/christopherbeck.wordpress.com/113/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/christopherbeck.wordpress.com/113/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/christopherbeck.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/christopherbeck.wordpress.com/113/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/christopherbeck.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/christopherbeck.wordpress.com/113/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/christopherbeck.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/christopherbeck.wordpress.com/113/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/christopherbeck.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/christopherbeck.wordpress.com/113/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/christopherbeck.wordpress.com/113/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/christopherbeck.wordpress.com/113/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=113&subd=christopherbeck&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://christopherbeck.wordpress.com/2008/09/05/report-hierarchical-data-with-apex/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1f43c7305915db8a38b359be077b2cc8?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">beckdood</media:title>
		</media:content>
	</item>
		<item>
		<title>Google Chrome &#8211; The Newest Thing In Browsers</title>
		<link>http://christopherbeck.wordpress.com/2008/09/02/google-chrome-the-newest-thing-in-browsers/</link>
		<comments>http://christopherbeck.wordpress.com/2008/09/02/google-chrome-the-newest-thing-in-browsers/#comments</comments>
		<pubDate>Tue, 02 Sep 2008 18:59:58 +0000</pubDate>
		<dc:creator>Christopher Beck</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[Google]]></category>

		<guid isPermaLink="false">http://christopherbeck.wordpress.com/?p=105</guid>
		<description><![CDATA[
Google entered the browser world today with their own, built from the ground up, open sourced browser called Chrome.  You can download it here.  It&#8217;s currently in Beta ( but what of Google&#8217;s is not a beta ) and only available on XP and Vista ( but the Mac and Linux versions are in the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=105&subd=christopherbeck&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><span style="color:#0000ee;text-decoration:underline;"><br />
</span><img class="alignleft" src="http://www.google.com/chrome/intl/en/images/logo_sm.jpg" alt="" width="150" height="55" />Google entered the browser world today with their own, built from the ground up, open sourced browser called Chrome.  You can download it <a href="http://www.google.com/chrome" target="_blank">here</a>.  It&#8217;s currently in Beta ( but what of Google&#8217;s is not a beta ) and only available on XP and Vista ( but the Mac and Linux versions are in the works ).  I have not had time to do anything more than install it and post this using chrome.   Google released a <a href="http://www.google.com/googlebooks/chrome/" target="_blank">comicbook of sorts to describe all the new features and functions</a>.  It all sounds impressive.  I really like the idea that each tab is its own process and not a thread in a monster browser process.  </p>
<p style="text-align:center;"><a href="http://christopherbeck.files.wordpress.com/2008/09/taskmanager.png"><img class="alignnone size-large wp-image-110" src="http://christopherbeck.files.wordpress.com/2008/09/taskmanager.png?w=480&#038;h=282" alt="" width="480" height="282" /></a></p>
<p>Should help with the ever growing memory hogs like Firefox and IE.  Anyway, check it out and let me know what you find out.  Next stop for me is to put it through its paces with APEX.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/christopherbeck.wordpress.com/105/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/christopherbeck.wordpress.com/105/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/christopherbeck.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/christopherbeck.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/christopherbeck.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/christopherbeck.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/christopherbeck.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/christopherbeck.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/christopherbeck.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/christopherbeck.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/christopherbeck.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/christopherbeck.wordpress.com/105/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=105&subd=christopherbeck&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://christopherbeck.wordpress.com/2008/09/02/google-chrome-the-newest-thing-in-browsers/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1f43c7305915db8a38b359be077b2cc8?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">beckdood</media:title>
		</media:content>

		<media:content url="http://www.google.com/chrome/intl/en/images/logo_sm.jpg" medium="image" />

		<media:content url="http://christopherbeck.files.wordpress.com/2008/09/taskmanager.png?w=480" medium="image" />
	</item>
		<item>
		<title>APEX 3.1.2 Is Available</title>
		<link>http://christopherbeck.wordpress.com/2008/08/29/apex-312-is-available/</link>
		<comments>http://christopherbeck.wordpress.com/2008/08/29/apex-312-is-available/#comments</comments>
		<pubDate>Fri, 29 Aug 2008 18:08:35 +0000</pubDate>
		<dc:creator>Christopher Beck</dc:creator>
				<category><![CDATA[APEX]]></category>
		<category><![CDATA[3.1.2]]></category>
		<category><![CDATA[patch]]></category>
		<category><![CDATA[upgrade]]></category>

		<guid isPermaLink="false">http://christopherbeck.wordpress.com/?p=91</guid>
		<description><![CDATA[In case you were not aware, Oracle has released a new version of Application Express.  From the APEX site on OTN:
Aug 28 
Application Express 3.1.2 is now available.  The full installation is available here, the patchset is available on MetaLink &#8211; patch number 7313609.  Please read the Patch Set Notes for details [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=91&subd=christopherbeck&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>In case you were not aware, Oracle has released a new version of Application Express.  From the <a href="http://www.oracle.com/technology/products/database/application_express/index.html" target="_blank">APEX site on OTN</a>:</p>
<p style="padding-left:30px;"><strong>Aug 28 </strong></p>
<p class="navheader" style="padding-left:30px;"><strong>Application Express 3.1.2 is now available.  The full <a href="http://www.oracle.com/technology/products/database/application_express/download.html" target="_blank">installation</a> is available here, the patchset is available on <a href="http://metalink.oracle.com" target="_blank">MetaLink</a> &#8211; patch number 7313609.  Please read the <a href="http://www.oracle.com/technology/products/database/application_express/html/3.1.2_patchnote.html" target="_blank">Patch Set Notes</a> for details on the bugs fixed in this release.</strong></p>
<p>I just finished upgrading my local apex instance.  I chose to apply the patch instead of a full install and it worked fantastic.  Took less than 5 minutes to patch on my dell 620 laptop  running Ubuntu 7.10.  4 minutes to apply the patch and another minute to load the new images.</p>
<p style="text-align:center;"><a href="http://christopherbeck.files.wordpress.com/2008/08/elapsed_time.png"><img class="size-full wp-image-99 aligncenter" src="http://christopherbeck.files.wordpress.com/2008/08/elapsed_time.png?w=514&#038;h=260" alt="" width="514" height="260" /></a></p>
<p style="text-align:center;"><a href="http://christopherbeck.files.wordpress.com/2008/08/apex_3121.png"><img class="size-full wp-image-94 aligncenter" src="http://christopherbeck.files.wordpress.com/2008/08/apex_3121.png?w=503&#038;h=283" alt="" width="503" height="283" /></a></p>
<p>I read the install notes and there are more than <a href="http://www.oracle.com/technology/products/database/application_express/html/3.1.2_patchnote.html#CHDCBDAF" target="_blank">80 bug</a> fixes and enhancements.</p>
<p>Has anyone else installed it yet?  What do you all think?  I&#8217;ll blog my impressions once I kick the tires for a bit.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/christopherbeck.wordpress.com/91/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/christopherbeck.wordpress.com/91/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/christopherbeck.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/christopherbeck.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/christopherbeck.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/christopherbeck.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/christopherbeck.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/christopherbeck.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/christopherbeck.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/christopherbeck.wordpress.com/91/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/christopherbeck.wordpress.com/91/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/christopherbeck.wordpress.com/91/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=91&subd=christopherbeck&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://christopherbeck.wordpress.com/2008/08/29/apex-312-is-available/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1f43c7305915db8a38b359be077b2cc8?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">beckdood</media:title>
		</media:content>

		<media:content url="http://christopherbeck.files.wordpress.com/2008/08/elapsed_time.png" medium="image" />

		<media:content url="http://christopherbeck.files.wordpress.com/2008/08/apex_3121.png" medium="image" />
	</item>
		<item>
		<title>Regular Expression Searching With APEX</title>
		<link>http://christopherbeck.wordpress.com/2008/08/26/regular-expression-searching-with-apex/</link>
		<comments>http://christopherbeck.wordpress.com/2008/08/26/regular-expression-searching-with-apex/#comments</comments>
		<pubDate>Tue, 26 Aug 2008 15:15:39 +0000</pubDate>
		<dc:creator>Christopher Beck</dc:creator>
				<category><![CDATA[APEX]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[regexp_like]]></category>
		<category><![CDATA[regular expressions]]></category>

		<guid isPermaLink="false">http://christopherbeck.wordpress.com/?p=78</guid>
		<description><![CDATA[Ever since Oracle introduced regular expression functions in the database, I have been a big fan of them.  They really make certain tasks much easier and give you added functionality.  One place I always used them is in my APEX apps where I supply the user with a search box to constrain the results of [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=78&subd=christopherbeck&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Ever since Oracle introduced regular expression functions in the database, I have been a big fan of them.  They really make certain tasks much easier and give you added functionality.  One place I always used them is in my APEX apps where I supply the user with a search box to constrain the results of a query.</p>
<p>The old way I would have written the query constraint:</p>
<p><strong>where upper(COL1) like &#8216;%&#8217; || upper( <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> 1_SEARCH_TEXT ) || &#8216;%&#8217;</strong></p>
<p>Now using <strong>REGEXP_LIKE()</strong> you can achieve the same functionality while simplifying the constraint.  And you get the added bonus of advance searching for the power user.</p>
<p><strong>where regexp_like( COL1, nvl(:P1_REGEXP,COL1), &#8216;ix&#8217; ) </strong></p>
<p>The first thing you will probably notice is that there is no conditional operator in that expression.   None is needed.  The regexp_like function is a boolean function and is used as such.</p>
<p>So now, any basic search will work just as before.  But now, you can issue regular expression searches as well.  If you want all the entries that start with S, search for <strong>^s</strong></p>
<p>End with R, use <strong>r$</strong></p>
<p>Start with S and end with H, use <strong>^s.*h$</strong></p>
<p>Start with S or end with R, use <strong>^s|r$</strong></p>
<p>All 4 letter names, use <strong>^&#8230;.$</strong></p>
<p>Contains B, C, D or K, use <strong>[b-d,k]</strong><strong><br />
</strong></p>
<p>How about all names with double letters, use <strong>(.)\1</strong></p>
<p>There are many more things you can do.  If you want to read up about regular expressions in oracle, docs can be found <a href="http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28424/adfns_regexp.htm" target="_blank">here</a>.</p>
<p>Using regexp_like() opens up the advanced searching for all the regular expression junkies without compromising the simple searching and it add NO complexity to your applications.</p>
<p>I have staged a simple demo on apex.oracle.com, <a href="http://apex.oracle.com/pls/otn/f?p=19903:6" target="_blank">here</a></p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/christopherbeck.wordpress.com/78/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/christopherbeck.wordpress.com/78/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/christopherbeck.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/christopherbeck.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/christopherbeck.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/christopherbeck.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/christopherbeck.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/christopherbeck.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/christopherbeck.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/christopherbeck.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/christopherbeck.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/christopherbeck.wordpress.com/78/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=78&subd=christopherbeck&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://christopherbeck.wordpress.com/2008/08/26/regular-expression-searching-with-apex/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1f43c7305915db8a38b359be077b2cc8?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">beckdood</media:title>
		</media:content>
	</item>
		<item>
		<title>More Google Geocoding</title>
		<link>http://christopherbeck.wordpress.com/2008/08/11/more-google-geocoding/</link>
		<comments>http://christopherbeck.wordpress.com/2008/08/11/more-google-geocoding/#comments</comments>
		<pubDate>Mon, 11 Aug 2008 22:28:33 +0000</pubDate>
		<dc:creator>Christopher Beck</dc:creator>
				<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[Geocode]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Spatial]]></category>

		<guid isPermaLink="false">http://christopherbeck.wordpress.com/?p=55</guid>
		<description><![CDATA[Ok, for those who liked the prior post on Google geocoding via HTTP, you will enjoy this as well.  It builds on what was done in that example but retrieves even more information from google.
Before we used an output type of CSV and that only gave us back the LATITUDE and LONGITUDE.  But there is [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=55&subd=christopherbeck&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Ok, for those who liked the prior post on Google geocoding via HTTP, you will enjoy this as well.  It builds on what was done in that example but retrieves even more information from google.</p>
<p>Before we used an output type of CSV and that only gave us back the LATITUDE and LONGITUDE.  But there is more information that we can derive from the geocoding service if we use a different output type.  If we request the result in XML, then we are given the complete address as well as the longitude and latitude.  But we have to do a little extra work to parse out the results.</p>
<p>I have written a PL/SQL object type to do just that.  Why an object type and not a Package?  Personal preference.  In this case, it just seemed to feel right to make it an object.  With some simple code factoring, it could easily be converted into a package.  But since most PL/SQL developers don&#8217;t code object types, thought it might be interesting.</p>
<p>Let&#8217;s take a look at the object&#8217;s specification.</p>
<pre class="brush: jscript;">

create or replace
type google_geocode_type as object (

  -- Attributes
  response xmlType,
  search varchar2(32767),

  -- Constructor Methods
  constructor function google_geocode_type(
    p_search varchar2 default null ) return self as result,

  -- Execute Geocode
  member procedure execute(
    p_search varchar2 default null ),

  -- Getter Routines
  member function get_result_count return number,

  member function get_geometry(
    p_sequence number default 1 ) return sdo_geometry,

  member function get_latitude(
    p_sequence number default 1 ) return number,

  member function get_longitude(
    p_sequence number default 1 ) return number,

  member function get_address(
    p_sequence number default 1 ) return varchar2,

  member function get_street(
    p_sequence number default 1 ) return varchar2,

  member function get_city(
    p_sequence number default 1 ) return varchar2,

  member function get_state(
    p_sequence number default 1 ) return varchar2,

  member function get_zipcode(
    p_sequence number default 1 ) return varchar2,

  member function get_county(
    p_sequence number default 1 ) return varchar2,

  member function get_country(
    p_sequence number default 1 ) return varchar2

);
</pre>
<p>The object&#8217;s body is a bit long and I will not post all of it here but will make it all available for <a href="http://download.arch3r.com/blog/google_geocode_type.sql.gz" target="_blank">download</a>.  But I will post a few of the member functions and talk about what they are doing.</p>
<pre class="brush: jscript;">

constructor function google_geocode_type(
  p_search varchar2 default null ) return self as result is
begin
  self.search := p_search;
  return;
end;
</pre>
<p>For those who are not familiar with PL/SQL object types, a constructor function is the method called when you create a new instance of the object (just like java).  Every object has a default constructor, but you can define your own so to manage the object&#8217;s creation as well as defaulting certain object attributes.  For me, I did not want the use to have to supply a value for the attribute RESPONSE so I defined my own.</p>
<p>The EXECUTE() method is very similar to the the prior example.  I made a minor change to handle the case where we get back more than 32K of data.</p>
<pre class="brush: jscript;">
member procedure execute( p_search varchar2 default null ) is
  l_http_req  utl_http.req;
  l_http_resp utl_http.resp;
  l_response long;
  l_clob clob;
begin
  if p_search is not null then
    self.search := p_search;
  end if;
  l_http_req := utl_http.begin_request(
                  url =&gt; 'http://maps.google.com/maps/geo' ||
                  '?q=' || utl_url.escape( self.search ) ||  -- address to geocode
                  '&amp;output=xml' ||  -- XML return type
                  '&amp;key=abcdef' );  -- site key
  l_http_resp := utl_http.get_response( l_http_req );
  begin
    loop
      utl_http.read_text( l_http_resp, l_response );
      l_clob := l_clob || l_response;
    end loop;
  exception
    when utl_http.end_of_body then
     null;
   end;
  utl_http.end_response( l_http_resp );
  self.response := sys.xmlType.createXML( l_clob );
end execute;
</pre>
<p>Now depending on how specific the address you supply, you may get more than one answer.  I sent in a value of &#8220;1600 Pennsylvania Ave&#8221; and it returned 10 results.  If I made that search more specific, say &#8220;1600 Pennsylvania Ave, DC&#8221;, then I get just a single result.  But since we don&#8217;t know how many results we will get, we need to parse out all the results.  So the first thing we need to know is how many results came back.</p>
<pre class="brush: jscript;">
member function get_result_count return number is
  l_count number;
begin
  select count(*)
    into l_count
    from table( XMLSequence( extract(
                 self.response,
                 '//Placemark',
                 'xmlns=&quot;http://earth.google.com/kml/2.0&quot;' ) ) );
  return l_count;
end get_result_count;
</pre>
<p>This method calculates how many results are in the XML returned by finding each &lt;Placemark&gt; section,  and then counting them using the XMLSequence and Table functions in SQL.</p>
<p>Now we know how many results, we can begin to ask for the individual values.</p>
<pre class="brush: jscript;">
member function get_zipcode(
  p_sequence number default 1 ) return varchar2 is
begin
  return self.response.extract(
           '//Placemark[@id=&quot;p' || p_sequence || '&quot;]',
           'xmlns=&quot;http://earth.google.com/kml/2.0&quot;' ).extract(
             '//PostalCodeNumber/text()',
             'xmlns=&quot;urn:oasis:names:tc:ciq:xsdschema:xAL:2.0&quot;' ).getStringVal();
end get_zipcode;
</pre>
<p>Here in the GET_ZIPCODE() method, we use the EXTRACT() method on the XMLType variable RESPONSE and XPATH searching to retrieve the proper zipcode.  I had to do and extract() of an extract() because the relavant peices of data were in different namespaces in the XML.  (My XPATH searching ability is not that strong so there may be an easier way?  If you know of one, let me know.)</p>
<p>All the other get methods are similiar to this example.</p>
<p>Now let&#8217;s see how we would use this.</p>
<pre style="padding-left:60px;"><strong>  1  declare
  2    g google_geocode_type := new google_geocode_type();
  3  begin
  4    g.execute( '1910 Oracle way, reston' );
  5      dbms_output.put_line( 'lat/lon: ' ||
  6                            g.get_latitude()||'/'||
  7                            g.get_longitude() );
  8      dbms_output.put_line( 'Address: ' || g.get_address() );
  9      dbms_output.put_line( 'County: ' || g.get_county() );
 10* end;
SQL&gt; /
lat/lon: -77.351976/38.954872
Address: 1910 Oracle Way, Reston, VA 20190, USA
County: Fairfax County

PL/SQL procedure successfully completed.
</strong></pre>
<p>Given just the street and the city, google was able to determine the full address and the latitude and longitude.</p>
<p>Now let&#8217;s see what happens when we supply even less information</p>
<pre style="padding-left:60px;"><strong>  1  declare
  2    g google_geocode_type := new google_geocode_type();
  3  begin
  4    g.execute( '1600 Pennsylvania Ave' );
  5    for i in 1 .. g.get_result_count() loop
  6      dbms_output.put_line( 'lat/lon: ' ||
  7                            g.get_latitude(i)||'/'||
  8                            g.get_longitude(i) );
  9      dbms_output.put_line( 'Address: ' || g.get_address(i) );
 10    end loop;
 11* end;
SQL&gt; /
lat/lon: -90.229033/38.617594
Address: 1600 Pennsylvania Ave, St Louis, MO 63104, USA
lat/lon: -76.880242/42.031789
Address: 1600 Pennsylvania Ave, Pine City, NY 14871, USA
lat/lon: -82.984848/42.36331
Address: 1600 Pennsylvania St, Detroit, MI 48214, USA
lat/lon: -76.634388/39.30307
Address: 1600 Pennsylvania Ave, Baltimore, MD 21217, USA
lat/lon: -96.77534/32.759033
Address: 1600 Pennsylvania Ave, Dallas, TX 75215, USA
lat/lon: -81.620803/38.360844
Address: 1600 Pennsylvania Ave, Charleston, WV 25302, USA
lat/lon: -80.27183/40.687529
Address: 1600 Pennsylvania Ave, Monaca, PA 15061, USA
lat/lon: -79.8573/40.362383
Address: 1600 Pennsylvania Ave, West Mifflin, PA 15122, USA
lat/lon: -117.32709/34.084866
Address: 1600 Pennsylvania Ave, Colton, CA 92324, USA
lat/lon: -75.185584/40.121061
Address: 1600 Pennsylvania Ave, Oreland, PA 19075, USA

PL/SQL procedure successfully completed.</strong></pre>
<p>There sure are a lot of 1600 Pennsylvania Ave&#8217;s.  But if you notice, the most famous one is not even in the list?  Why?  I have NO idea???  But if we make our search a bit more specific&#8230;</p>
<pre style="padding-left:60px;"><strong>  1  declare
  2    g google_geocode_type := new google_geocode_type();
  3  begin
  4    g.execute( '1600 Pennsylvania Ave, dc' );
  5    for i in 1 .. g.get_result_count() loop
  6      dbms_output.put_line( 'lat/lon: ' ||
  7                            g.get_latitude(i)||'/'||
  8                            g.get_longitude(i) );
  9      dbms_output.put_line( 'Address: ' || g.get_address(i) );
 10    end loop;
 11* end;
SQL&gt; /
lat/lon: -77.036698/38.897102
Address: 1600 Pennsylvania Ave NW, Washington, DC 20006, USA

PL/SQL procedure successfully completed.</strong></pre>
<p>&#8230; we find that famous one that will be getting a new family moving in this January.</p>
<p>I hope this was interesting and helpful.  Again, if you want to get the code and try it out yourself, its <a href="http://download.arch3r.com/blog/google_geocode_type.sql.gz" target="_blank">right here</a>.  And as always, if you have any questions, just ask.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/christopherbeck.wordpress.com/55/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/christopherbeck.wordpress.com/55/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/christopherbeck.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/christopherbeck.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/christopherbeck.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/christopherbeck.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/christopherbeck.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/christopherbeck.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/christopherbeck.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/christopherbeck.wordpress.com/55/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/christopherbeck.wordpress.com/55/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/christopherbeck.wordpress.com/55/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=55&subd=christopherbeck&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://christopherbeck.wordpress.com/2008/08/11/more-google-geocoding/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1f43c7305915db8a38b359be077b2cc8?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">beckdood</media:title>
		</media:content>
	</item>
		<item>
		<title>Quick Geocoding Using Google</title>
		<link>http://christopherbeck.wordpress.com/2008/08/05/quick-geocoding-using-google/</link>
		<comments>http://christopherbeck.wordpress.com/2008/08/05/quick-geocoding-using-google/#comments</comments>
		<pubDate>Tue, 05 Aug 2008 19:20:49 +0000</pubDate>
		<dc:creator>Christopher Beck</dc:creator>
				<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[Geocode]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Spatial]]></category>

		<guid isPermaLink="false">http://christopherbeck.wordpress.com/?p=41</guid>
		<description><![CDATA[Location based services are all the rage these days.  Everyone is including it into their applications and there are many ways to accomplish this.  Oracle supports geocoding in the database but you need to own the geocoding dataset.  To get that dataset, you would probably need to purchase it from some provider like NAVTEQ.
But there [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=41&subd=christopherbeck&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Location based services are all the rage these days.  Everyone is including it into their applications and there are many ways to accomplish this.  Oracle supports geocoding in the database but you need to own the geocoding dataset.  To get that dataset, you would probably need to purchase it from some provider like <a href="http://www.navteq.com/" target="_blank">NAVTEQ</a>.</p>
<p>But there are services out there, like <a href="http://maps.google.com" target="_blank">Google</a>, that allows us common folk to use its data, but you have to know how to ask for it.  Google offers a ton of Javascript APIs for <a href="http://code.google.com/apis/maps/documentation/reference.html" target="_blank">mapping </a>and <a href="http://code.google.com/apis/maps/documentation/reference.html#GClientGeocoder" target="_blank">geocoding</a>, but that does nothing for us working in the database with PL/SQL.  I routinely want to geocode the addresses in a table on insert and update via a trigger.  Javascript is not going to help you here.</p>
<p>Luckily, Google supports geocoding via HTTP and I have written a simple function to access it.  ( Oracle also supports a geocoding solution via HTTP and has a hosted site to support it.  I will blog about it in the future. )</p>
<pre class="brush: jscript;">
create or replace
function google_geocode( p_address varchar2 ) return sdo_geometry is
 l_http_req  utl_http.req;
 l_http_resp utl_http.resp;
 l_response long;
 l_latlon long;
begin

 l_http_req := utl_http.begin_request(
   url =&gt; 'http://maps.google.com/maps/geo' ||
          '?q=' || utl_url.escape( p_address ) ||  -- address to geocode
          '&amp;output=csv' ||                         -- simplest return type
          '&amp;key=abcdef' );                         -- Google API site key

 l_http_resp := utl_http.get_response( l_http_req );
 utl_http.read_text( l_http_resp, l_response );
 utl_http.end_response( l_http_resp );
 l_latlon := substr( l_response, instr( l_response, ',', 1, 2 ) + 1 );

 return sdo_geometry(
          2001, 8307,
          sdo_point_type( to_number( substr( l_latlon, instr( l_latlon, ',' )+1 )),
                          to_number( substr( l_latlon, 1, instr( l_latlon, ',' )-1 )),
                          null ),
          null, null );
end google_geocode;
</pre>
<p>That&#8217;s it.  It&#8217;s not that complicated.  You just need to send via HTTP the address and you will get back a comma separated string which we parse out the latitude and longitude and stuff into a sdo_geometry type.</p>
<p>I&#8217;ll quickly dissect the code.</p>
<p><strong>Line 9</strong> &#8211; Initializing the HTTP call.  The URL includes 3 parameters ( q, output and key )</p>
<ul>
<li> <strong>q</strong> is the address string to be geocoded.</li>
<li> <strong>output</strong> is the format that we want the out returned in.  I chose <strong>csv</strong>.  It&#8217;s the simplest for this example.</li>
<li> <strong>key</strong> is the your Google API key.  ( Read more about getting a <a href="http://code.google.com/apis/maps/signup.html" target="_blank">Google API key</a> ).</li>
</ul>
<p><strong>Lines 15-17</strong> &#8211; Sending the request and fetching the result via HTTP.  The result that the comes back is in the form of:</p>
<ul>
<li><strong>HTTP_return_code,accuracy,latitude,longitude</strong></li>
</ul>
<p><strong>Line 18</strong> &#8211; Substring the latitude and longitude.</p>
<p><strong>Line 20</strong> &#8211; Creating and returning the <strong>SDO_GEOMETRY</strong></p>
<p>Now you can call this from your pl/sql code in the database, or code in your ApEx app ( since that too is stored and run in the database ) and geocode any address.  Just like this:</p>
<pre>SQL&gt; select google_geocode( '1910 Oracle Way, Reston' ) g
  2    from dual;
G(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDINATES)
--------------------------------------------------------------------------------
SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE(-77.351976, 38.954872, NULL), NULL, NULL)</pre>
<p>I tried to set up a quick demo of this on apex.oracle.com <a href="http://apex.oracle.com/pls/otn/f?p=19903:4" target="_blank">here</a>, but I need to get the access to run UTL_HTTP via setting up an ACL.  I am trying to see if I can get the admins to allow that for me.</p>
<p>If you want to read more about the options Google offers for geocoding via HTTP, you can read about it <a href="http://code.google.com/apis/maps/documentation/services.html#Geocoding_Direct" target="_blank">here</a>.</p>
<p>As always, if you have any questions, just ask.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/christopherbeck.wordpress.com/41/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/christopherbeck.wordpress.com/41/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/christopherbeck.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/christopherbeck.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/christopherbeck.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/christopherbeck.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/christopherbeck.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/christopherbeck.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/christopherbeck.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/christopherbeck.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/christopherbeck.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/christopherbeck.wordpress.com/41/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=christopherbeck.wordpress.com&blog=4298178&post=41&subd=christopherbeck&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://christopherbeck.wordpress.com/2008/08/05/quick-geocoding-using-google/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/1f43c7305915db8a38b359be077b2cc8?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">beckdood</media:title>
		</media:content>
	</item>
	</channel>
</rss>