<?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>Ramblings from the bit bucket &#187; Example</title>
	<atom:link href="http://blogs.planetingres.org/notnull/tag/example/feed/" rel="self" type="application/rss+xml" />
	<link>http://blogs.planetingres.org/notnull</link>
	<description>Just another blogs.planetingres.org weblog</description>
	<lastBuildDate>Tue, 01 Feb 2011 09:13:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Useful or useless? Follow on post &#8230;</title>
		<link>http://blogs.planetingres.org/notnull/2010/02/23/useful-or-useless-follow-on-post/</link>
		<comments>http://blogs.planetingres.org/notnull/2010/02/23/useful-or-useless-follow-on-post/#comments</comments>
		<pubDate>Tue, 23 Feb 2010 08:48:36 +0000</pubDate>
		<dc:creator>notnull</dc:creator>
				<category><![CDATA[database]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[Example]]></category>
		<category><![CDATA[ima]]></category>
		<category><![CDATA[ingres]]></category>
		<guid isPermaLink="false">http://blogs.planetingres.org/notnull/?p=131</guid>
		<description><![CDATA[Way back in May last year I experimented with some IMA tables that showed data types and operators defined in the DBMS.  Further poking around and a table for a list of the function instances is available, drop ima_dbms_fis; \p\g register table ima_dbms_fis ( server varchar(64) not null not default is 'SERVER', id integer4 not [...]]]></description>
			<content:encoded><![CDATA[<p>Way back in May last year I experimented with some IMA tables that<a title="Useful or useless? You decide" href="http://blogs.planetingres.org/notnull/2009/05/01/useful-or-useless-you-decide/"> showed data types and operators</a> defined in the DBMS.  Further poking around and a table for a list of the function instances is available,</p>
<pre>drop ima_dbms_fis;
\p\g
register table ima_dbms_fis (
        server varchar(64) not null not default is
                'SERVER',
        id integer4 not null not default is
                'exp.adf.adg.fi_id',
        complement integer4 not null not default is
                'exp.adf.adg.fi_cmplmnt',
        type varchar(20) not null not default is
                'exp.adf.adg.fi_type',
        flags integer4 not null not default is
                'exp.adf.adg.fi_flags',
        opid integer4 not null not default is
                'exp.adf.adg.fi_opid',
        args integer4 not null not default is
                'exp.adf.adg.fi_numargs',
        dtresult integer4 not null not default is
                'exp.adf.adg.fi_dtresult',
        dtarg1 integer4 not null not default is
                'exp.adf.adg.fi_dtarg1',
        dtarg2 integer4 not null not default is
                'exp.adf.adg.fi_dtarg2',
        dtarg3 integer4 not null not default is
                'exp.adf.adg.fi_dtarg3',
        dtarg4 integer4 not null not default is
                'exp.adf.adg.fi_dtarg4'
)
as import from 'tables'
with dbms = IMA,
structure = sortkeyed,
key = (server);
\p\g
grant all on ima_dbms_fis to ingres;
\p\g
grant select on ima_dbms_fis to public;
\p\g</pre>
<p>Adding this table to ima_dbms_types and ima_dbms_operators adds the ability to retrieve the list of functions and their signatures.  The query makes use of an internal function <em>iitypename</em> which translates the numeric type code into a name.</p>
<pre>select
    a.name,
    case when a.type='COMPARISON' then
        trim(iitypename(b.dtresult)) + ' = ( ' +
        trim(iitypename(b.dtarg1)) + ' ' +
        a.name + ' ' +
        trim(iitypename(b.dtarg2)) + ' )'
        when a.type='OPERATOR' then
        trim(iitypename(b.dtresult)) + ' = ( ' +
        trim(iitypename(b.dtarg1)) + ' ' +
        a.name + ' ' +
        trim(iitypename(b.dtarg2)) + ' )'
    else
        trim(iitypename(b.dtresult)) + ' = ' +
        a.name + '( ' +
            case when b.dtarg1 != '' then trim(iitypename(b.dtarg1)) else '' end +
            case when b.dtarg2 != '' then ', ' + trim(iitypename(b.dtarg2)) else '' end +
            case when b.dtarg3 != '' then ', ' + trim(iitypename(b.dtarg3)) else '' end +
            case when b.dtarg4 != '' then ', ' + trim(iitypename(b.dtarg4)) else '' end
        + ' )'
    end as signature
from
    ima_dbms_operators a,
    ima_dbms_fis b
where
    a.opid = b.opid
group by a.name, 2
order by a.name</pre>
<p>Some sample output from this query:</p>
<pre>|name                          |signature                       |
|soundex                       |char = soundex( text )          |
|soundex                       |char = soundex( varchar )       |
|sqrt                          |float = sqrt( float )           |
|squeeze                       |nvarchar = squeeze( nchar )     |
|squeeze                       |nvarchar = squeeze( nvarchar )  |
|squeeze                       |text = squeeze( c )             |</pre>
<p>So in answer to my own question; yes, it is useful.  I&#8217;ll be trying this on an <a title="IngresGeospatial" href="http://community.ingres.com/wiki/IngresGeospatial">IngresGeospatial</a> build when I get my hands on one.<br />
<h3>Related posts</h3>
<ul class="related_post">
<li><a href="http://blogs.planetingres.org/notnull/2010/05/16/debugging-the-hibernate-project-with-eclipse/" title="Debugging the Hibernate project with Eclipse">Debugging the Hibernate project with Eclipse</a></li>
<li><a href="http://blogs.planetingres.org/notnull/2010/04/01/hibernate-3-5-0-final-released/" title="Hibernate 3.5.0-Final released">Hibernate 3.5.0-Final released</a></li>
<li><a href="http://blogs.planetingres.org/notnull/2008/03/28/google-summer-of-code-gsoc-2008/" title="Google Summer of Code (GSoC) 2008">Google Summer of Code (GSoC) 2008</a></li>
<li><a href="http://blogs.planetingres.org/notnull/2006/06/08/ima-guru-pronounced-im-a-guru-i-definitely-am-not/" title="IMA Guru (Pronounced, I&#8217;m A Guru) &#8211; I definitely am not">IMA Guru (Pronounced, I&#8217;m A Guru) &#8211; I definitely am not</a></li>
<li><a href="http://blogs.planetingres.org/notnull/2011/02/01/data-access-message-protocol-wireshark-dissector/" title="Data Access Message Protocol &#8211; Wireshark dissector">Data Access Message Protocol &#8211; Wireshark dissector</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blogs.planetingres.org/notnull/2010/02/23/useful-or-useless-follow-on-post/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Enhanced Row producing procedures</title>
		<link>http://blogs.planetingres.org/notnull/2008/11/14/enhanced-row-producing-procedures/</link>
		<comments>http://blogs.planetingres.org/notnull/2008/11/14/enhanced-row-producing-procedures/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 21:47:47 +0000</pubDate>
		<dc:creator>notnull</dc:creator>
				<category><![CDATA[database]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[Example]]></category>
		<category><![CDATA[ingres]]></category>
		<category><![CDATA[feature enhancement]]></category>
		<category><![CDATA[row producing procedure]]></category>
		<category><![CDATA[table procedure]]></category>
		<guid isPermaLink="false">http://blogs.planetingres.org/notnull/?p=48</guid>
		<description><![CDATA[I was recently asked about the ability to run a row producing procedure from anything other than ESQLC, which reminded me of a couple of feature requests that I have recently made http://community.ingres.com/wiki/Table_Procedure_Enhancements, named result columns for a row producing procedure and the ability to use a row producing procedure in a view definition.  In [...]]]></description>
			<content:encoded><![CDATA[<p>I was recently asked about the ability to run a row producing procedure from anything other than ESQLC, which reminded me of a couple of feature requests that I have recently made <a href="http://community.ingres.com/wiki/Table_Procedure_Enhancements">http://community.ingres.com/wiki/Table_Procedure_Enhancements</a>, named result columns for a row producing procedure and the ability to use a row producing procedure in a view definition.  In addition to these main features the ability to invoke a procedure with positional parameters was added.</p>
<p>I&#8217;m currently using 9.3.0 (int.w32/135) and decided to try out these features.<br />
The CREATE PROCEDURE syntax for return a row has been extended to include column names, my clumsy attempt at a partial description of the syntax follows:</p>
<p><code>&lt;database procedure&gt; ::= CREATE PROCEDURE &lt;procedure name&gt; &lt;procedure parameter list&gt;<br />
RESULT ROW &lt;result row description&gt;<br />
&lt;procedure name&gt; ::= &lt;identifier&gt;</code></p>
<p><code>&lt;procedure parameter list&gt; ::= &lt;None&gt; |<br />
&lt;left paren&gt; &lt;SQL parameter declaration list&gt; &lt;right paren&gt;</code></p>
<p><code>&lt;result row description&gt; ::= &lt;result row column list&gt; |<br />
&lt;result set identifier&gt; &lt;table procedure column list&gt;</code></p>
<p><code>&lt;result set identifier&gt; ::= &lt;identifier&gt;</code></p>
<p><code>&lt;result row column list&gt; ::= &lt;left paren&gt; &lt;row column list element&gt;<br />
[ { &lt;comma&gt; &lt;row column list element&gt; }... ] &lt;right paren&gt;</code></p>
<p><code>&lt;row column list element&gt; ::= &lt;data type&gt; [ &lt;column constraint&gt; ][ &lt;default&gt; ]</code></p>
<p><code>&lt;table procedure column list&gt; ::= &lt;left paren&gt; &lt;table procedure column list element&gt;<br />
[ { &lt;comma&gt; &lt;table procedure column list element&gt; }... ] &lt;right paren&gt;<br />
</code><br />
<code>&lt;table procedure column list element&gt; ::= &lt;column name&gt; &lt;data type&gt; [ &lt;column constraint&gt; ][ &lt;default&gt; ]</code></p>
<p>The procedure can now be exceuted directly from an EXECUTE PROCEDURE statement (requiring esqlc) or as the table procedure in the FROM clause of a SELECT statement.  The latter releasing row producing procedures from the shackles of embedded SQL.</p>
<p>Time for a few simple contrived examples to demonstrate the syntax and use.</p>
<p>A simple table with some data.<br />
<code>create table t1 (c1 integer not null, c2 char(1) not null);</code></p>
<p><code>insert into t1 (c1, c2) values (1, 'A');<br />
insert into t1 (c1, c2) values (2, 'B');<br />
insert into t1 (c1, c2) values (2, 'B');<br />
insert into t1 (c1, c2) values (3, 'C');<br />
insert into t1 (c1, c2) values (3, 'C');<br />
insert into t1 (c1, c2) values (3, 'C');<br />
insert into t1 (c1, c2) values (4, 'D');<br />
insert into t1 (c1, c2) values (4, 'D');<br />
insert into t1 (c1, c2) values (4, 'D');<br />
insert into t1 (c1, c2) values (4, 'D');</code></p>
<p>A monadic procdure that returns a row from the table t1 restricted by value.</p>
<pre>create procedure  p1 (a1 integer not null)
    result row resrow (r1 integer, r2 char(1))
as
declare
    ival integer not null;
    cval char(1) not null;
begin
    for select c1, c2 into :ival, :cval
        from t1
        where c1 = :a1
        do
            return row ( :ival, :cval );
    endfor;
end
</pre>
<p>A dyadic procedure that returns a row from table t1 restricted by values.</p>
<pre>create procedure  p2 (a1 integer not null, a2 char(1) not null)
    result row resrow (r1 integer, r2 char(1))
as
declare
    ival integer not null;
    cval char(1) not null;
begin
    for select c1, c2 into :ival, :cval
        from t1
        where c1 = :a1 and c2 = :a2
        do
            return row ( :ival, :cval );
    endfor;
end</pre>
<p>The original syntax to execute the procedure must be executed from esqlc.</p>
<pre># include &lt;stdio.h&gt;
void
main()
{
exec sql begin declare section;
    int     aval;
    int     ival;
    char    array[2];
    char    *cval = array;
    exec sql end declare section;
    aval = 2;
    exec sql connect test;
    exec sql execute procedure p1(a1 = :aval) result row (:ival, :cval);
    exec sql begin;
        printf("r1 = %d, r2 = %s\n", ival, cval);
    exec sql end;
    exec sql disconnect;
}</pre>
<p>With the feature to execute the procedure in the FROM clause of a SELECT statement you can execute the procedure using<br />
<code>SELECT r1, r2 FROM p1(a1=2);</code></p>
<p>Parameters can be named, positional or a mixture.  Positional parameters must always appear first in the parameter list in a mixture of named and positional parameters.</p>
<p>An example of positional parameters<br />
<code>SELECT r1, r2 FROM p1(2);<br />
SELECT r1, r2 FROM p2(1, 'A');</code></p>
<p>An example of named parameters<br />
<code>SELECT r1, r2 FROM p1(a1=2);<br />
SELECT r1, r2 from p2(a2='A', a1=1);</code></p>
<p>An example of mixed parameters<br />
<code>SELECT r1, r2 FROM p2(1, a2='A');</code></p>
<p>The SELECT query statement that executes the procedure can be used in a VIEW definition and used as usual.</p>
<p><code>CREATE VIEW v1 AS SELECT r1, r2 FROM p1(2);</code></p>
<p>Some simple example queries.</p>
<pre>
-- Aggregate query
SELECT COUNT(p1.r1) AS count, SUM(p1.r1) AS sum FROM p1(4);
+-------------+----------------------+
|count        |sum                   |
+-------------+----------------------+
|            4|                    16|
+-------------+----------------------+
(1 row)
continue
Executing . . .
-- Query using the view defined from table procedure
SELECT t1.*, v1.* FROM t1, v1 WHERE v1.r2='B';
+-------------+----------+-------------+------+
|c1           |c2        |r1           |r2    |
+-------------+----------+-------------+------+
|            1|A         |            2|B     |
|            1|A         |            2|B     |
|            2|B         |            2|B     |
|            2|B         |            2|B     |
|            3|C         |            2|B     |
|            3|C         |            2|B     |
|            2|B         |            2|B     |
|            2|B         |            2|B     |
|            3|C         |            2|B     |
|            3|C         |            2|B     |
|            4|D         |            2|B     |
|            4|D         |            2|B     |
|            3|C         |            2|B     |
|            3|C         |            2|B     |
|            4|D         |            2|B     |
|            4|D         |            2|B     |
|            4|D         |            2|B     |
|            4|D         |            2|B     |
|            4|D         |            2|B     |
|            4|D         |            2|B     |
+-------------+----------+-------------+------+
(20 rows)
continue
Executing . . .
-- Query using both table and view
SELECT t1.*, v1.* FROM (t1 LEFT JOIN v1 ON t1.c1 = v1.r1 AND v1.r2='B');
+-------------+----------+-------------+------+
|c1           |c2        |r1           |r2    |
+-------------+----------+-------------+------+
|            1|A         |             |      |
|            2|B         |            2|B     |
|            2|B         |            2|B     |
|            3|C         |             |      |
|            2|B         |            2|B     |
|            2|B         |            2|B     |
|            3|C         |             |      |
|            4|D         |             |      |
|            3|C         |             |      |
|            4|D         |             |      |
|            4|D         |             |      |
|            4|D         |             |      |
+-------------+----------+-------------+------+
(12 rows)
continue
Executing . . .
-- Query using both table and table procedure
SELECT t1.*, p1.* FROM t1, p1(t1.c1) p1 WHERE p1.r2='B';
+-------------+----------+-------------+------+
|c1           |c2        |r1           |r2    |
+-------------+----------+-------------+------+
|            2|B         |            2|B     |
|            2|B         |            2|B     |
|            2|B         |            2|B     |
|            2|B         |            2|B     |
+-------------+----------+-------------+------+
(4 rows)</pre>
<h3>Related posts</h3>
<ul class="related_post">
<li><a href="http://blogs.planetingres.org/notnull/2010/02/23/useful-or-useless-follow-on-post/" title="Useful or useless? Follow on post &#8230;">Useful or useless? Follow on post &#8230;</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blogs.planetingres.org/notnull/2008/11/14/enhanced-row-producing-procedures/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

