<?xml version="1.0" encoding="utf-8" ?>

<rss version="2.0" 
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:admin="http://webns.net/mvcb/"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
   xmlns:wfw="http://wellformedweb.org/CommentAPI/"
   xmlns:content="http://purl.org/rss/1.0/modules/content/"
   >
<channel>
    <title>Postgres OnLine Journal - plpgsql</title>
    <link>http://www.postgresonline.com/journal/</link>
    <description>an In depth look at the PostgreSQL open source database</description>
    <dc:language>en</dc:language>
    <generator>Serendipity 1.4.1 - http://www.s9y.org/</generator>
    <pubDate>Sun, 04 Sep 2011 04:55:17 GMT</pubDate>

    <image>
        <url>http://www.postgresonline.com/journal/templates/default/img/s9y_banner_small.png</url>
        <title>RSS: Postgres OnLine Journal - plpgsql - an In depth look at the PostgreSQL open source database</title>
        <link>http://www.postgresonline.com/journal/</link>
        <width>100</width>
        <height>21</height>
    </image>

<item>
    <title>SQL Server to PostgreSQL: Converting table structure</title>
    <link>http://www.postgresonline.com/journal/archives/219-SQL-Server-to-PostgreSQL-Converting-table-structure.html</link>
            <category>basics</category>
            <category>beginner</category>
            <category>oracle</category>
            <category>plpgsql</category>
            <category>sql server</category>
    
    <comments>http://www.postgresonline.com/journal/archives/219-SQL-Server-to-PostgreSQL-Converting-table-structure.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=219</wfw:comment>

    <slash:comments>1</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=219</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;We&#039;ve been working on converting some of our SQL Server apps to PostgreSQL.   In this
article we&#039;ll describe some things to watch out for and provide a function we wrote to automate some of
the conversion.&lt;/p&gt;

&lt;p&gt;Although both databases are fairly ANSI-SQL compliant, there are still differences 
with their CREATE TABLE statements, data types, and how they handle other things that makes porting applications not so trivial. &lt;/p&gt;
&lt;/p&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/219-SQL-Server-to-PostgreSQL-Converting-table-structure.html#extended&quot;&gt;Continue reading &quot;SQL Server to PostgreSQL: Converting table structure&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Sun, 04 Sep 2011 00:33:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/219-guid.html</guid>
    <category>migration</category>
<category>oracle</category>
<category>regular expressions</category>
<category>sql server</category>

</item>
<item>
    <title>Using PgAdmin PLPgSQL Debugger</title>
    <link>http://www.postgresonline.com/journal/archives/214-Using-PgAdmin-PLPgSQL-Debugger.html</link>
            <category>8.3</category>
            <category>8.4</category>
            <category>9.0</category>
            <category>9.1</category>
            <category>basics</category>
            <category>gis</category>
            <category>intermediate</category>
            <category>pgadmin</category>
            <category>plpgsql</category>
    
    <comments>http://www.postgresonline.com/journal/archives/214-Using-PgAdmin-PLPgSQL-Debugger.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=214</wfw:comment>

    <slash:comments>9</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=214</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;I&#039;m one of those old-fashioned folks that debugs with print lines and raise notices.  They&#039;re nice.
They always work, you can put clock time stops in there and don&#039;t require any fancy configuration.  
At a certain point you do have to pull out a real debugger to see what is going on.  This often
happens when your one-liners are no longer good enough and now you have to write 20 liners of plpgsql code.&lt;/p&gt;

&lt;p&gt;Such is the case with geocoding and the &lt;a href=&quot;http://www.postgis.org/documentation/manual-svn/Extras.html#Tiger_Geocoder&quot; target=&quot;_blank&quot;&gt;PostGIS tiger geocoder&lt;/a&gt; specifically.  Lots of interest has revived
on that with people submitting bug reports and we&#039;ve got paying clients in need of a fairly easy and speedy drop-in geocoder
that can be molded to handle such things as road way locations, badly mis-spelled real estate data, or just simply
to get rid of their dependency on Google, Yahoo, MapQuest, ESRI and other online or pricey geocoding tools.
So I thought I&#039;d take this opportunity to supplement our old-fashioned debugging with plpgsqldebugger goodness.
In this article, we&#039;ll show you how to configure the plpgsql debugger integrated in PgAdmin and run with it.&lt;/p&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/214-Using-PgAdmin-PLPgSQL-Debugger.html#extended&quot;&gt;Continue reading &quot;Using PgAdmin PLPgSQL Debugger&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Mon, 27 Jun 2011 01:49:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/214-guid.html</guid>
    <category>debugging</category>
<category>pgadmin</category>

</item>
<item>
    <title>Variadic Functions in PostgreSQL</title>
    <link>http://www.postgresonline.com/journal/archives/211-Variadic-Functions-in-PostgreSQL.html</link>
            <category>8.4</category>
            <category>gis</category>
            <category>intermediate</category>
            <category>mysql</category>
            <category>pl programming</category>
            <category>plpgsql</category>
            <category>postgis</category>
            <category>postgresql versions</category>
            <category>sql functions</category>
    
    <comments>http://www.postgresonline.com/journal/archives/211-Variadic-Functions-in-PostgreSQL.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=211</wfw:comment>

    <slash:comments>1</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=211</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;PostgreSQL 8.4 introduced the ability to create user-defined &lt;a href=&quot;http://en.wikipedia.org/wiki/Variadic_function&quot; target=&quot;_blank&quot;&gt;variadic functions&lt;/a&gt;. These are basically 
functions that take as input an undefined number of arguments where the argument that is an undefined number are all of the same type and are the last input arguments. Depesz went over it two years ago in &lt;a href=&quot;http://www.depesz.com/index.php/2008/07/31/waiting-for-84-variadic-functions/&quot; target=&quot;_blank&quot;&gt;Waiting for 8.4 variadic functions&lt;/a&gt;,
so we are a bit late to the party. In a nutshell -- variadic functions are syntactic sugar for functions that would otherwise take arrays. In this article we&#039;ll provide some more demonstrations of them to supplement Depesz article.&lt;/p&gt;

&lt;p&gt;I was reminded that I had never explored this feature, when recently documenting one of the
new PostGIS 2.0 Raster functions - &lt;a href=&quot;http://www.postgis.org/documentation/manual-svn/RT_ST_Reclass.html&quot; target=&quot;_blank&quot;&gt;ST_Reclass&lt;/a&gt; which employs this feature. 
I think ST_Reclass is a superb function and one of my favorite raster functions thus far that I hope to put to good use soon.  Our new PostGIS family member,Bborie Park, is running thru our
PostGIS Raster milestones much faster than I had dreamed. He&#039;s already implemented a good chunk of stuff we discussed in &lt;a href=&quot;http://www.postgis.us/chapter_13&quot; target=&quot;_blank&quot;&gt;Chapter 13 - PostGIS Raster&lt;/a&gt; and had stated you probably won&#039;t see in PostGIS 2.0.  He&#039;s
going a bit faster than I can catalog them, so the documentation is already embarrassingly behind the fantastic functionality that is already present in PostGIS 2.0.&lt;/p&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/211-Variadic-Functions-in-PostgreSQL.html#extended&quot;&gt;Continue reading &quot;Variadic Functions in PostgreSQL&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Fri, 03 Jun 2011 22:02:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/211-guid.html</guid>
    <category>mysql</category>
<category>postgis</category>
<category>postgresql 8.4</category>
<category>raster</category>
<category>string concatenation</category>

</item>
<item>
    <title>Using RETURNS TABLE vs. OUT parameters</title>
    <link>http://www.postgresonline.com/journal/archives/201-Using-RETURNS-TABLE-vs.-OUT-parameters.html</link>
            <category>8.4</category>
            <category>9.0</category>
            <category>db2</category>
            <category>intermediate</category>
            <category>pl programming</category>
            <category>plpgsql</category>
            <category>postgresql versions</category>
            <category>sql functions</category>
            <category>sql server</category>
    
    <comments>http://www.postgresonline.com/journal/archives/201-Using-RETURNS-TABLE-vs.-OUT-parameters.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=201</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=201</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;In a prior article &lt;a href=&quot;http://www.postgresonline.com/journal/archives/129-Use-of-OUT-and-INOUT-Parameters.html&quot; target=&quot;_blank&quot;&gt;Use of Out and InOut Parameters&lt;/a&gt;
we demonstrated how to use OUT parameters and INOUT parameters to return a set of records from a PostgreSQL function.
There is another approach to doing this, and that is to use the ANSI Standard RETURNS TABLE construct.  
If you come from a SQL Server or IBM DB2 background, the RETURNS TABLE construct is probably most familiar, but still
how you use it and what is legal in it is a little different than it is in SQL Server or IBM DB2.  We&#039;ll save the
contrast compare as a topic for another article.  &lt;/p&gt;

&lt;p&gt;In terms of performance between using OUT vs. RETURNS TABLE, we haven&#039;t noticed much of a difference. The main thing that is 
nice about RETURNS TABLE is just that it&#039;s syntactically more pleasing in the sense that its clearer the structure of what you are returning.&lt;/p&gt;

&lt;p&gt;In these next examples, we&#039;ll demonstrate similar examples we showed in the aforementioned article except using the 
&lt;code&gt;RETURNS TABLE&lt;/code&gt;.  
Be warned that the &lt;code&gt;RETURNS TABLE&lt;/code&gt; construct is only available for PostgreSQL 8.4+, while the OUT approach
has existed since PostgreSQL 8.1. With that said, if you need your code to work on 8.3 or lower, you can&#039;t use RETURNS TABLE.
When in doubt about a feature and you are creating code that needs to support earlier versions of PostgreSQL
(as we have to in the PostGIS development group),
or you want to get stubborn users off old antiquated versions of PostgreSQL and need a bit of ammunition  
(as we have to (on PostGIS development including our own developers - and you know who you are :) ) )
check the
&lt;a href=&quot;http://www.postgresql.org/about/featurematrix&quot; target=&quot;_blank&quot;&gt;PostgreSQL feature matrix&lt;/a&gt;.  
It will save you a lot of grief.&lt;/p&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/201-Using-RETURNS-TABLE-vs.-OUT-parameters.html#extended&quot;&gt;Continue reading &quot;Using RETURNS TABLE vs. OUT parameters&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Fri, 08 Apr 2011 02:32:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/201-guid.html</guid>
    <category>ibm db2</category>
<category>postgresql 9.0</category>
<category>sql server</category>

</item>
<item>
    <title>Use of OUT and INOUT Parameters</title>
    <link>http://www.postgresonline.com/journal/archives/129-Use-of-OUT-and-INOUT-Parameters.html</link>
            <category>8.2</category>
            <category>8.3</category>
            <category>8.4</category>
            <category>intermediate</category>
            <category>pl programming</category>
            <category>plpgsql</category>
            <category>postgresql versions</category>
            <category>sql functions</category>
    
    <comments>http://www.postgresonline.com/journal/archives/129-Use-of-OUT-and-INOUT-Parameters.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=129</wfw:comment>

    <slash:comments>1</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=129</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;PostgreSQL has supported what are called Out (output) parameters &lt;a href=&quot;http://www.postgresql.org/docs/8.1/interactive/plpgsql-declarations.html&quot; target=&quot;_blank&quot;&gt;since version 8.1&lt;/a&gt;.
We were surprised it has been that long since we always thought of it as a feature from 8.2+ 
until it recently came up for discussion on &lt;a href=&quot;http://postgis.refractions.net/pipermail/postgis-users/2009-July/024104.html&quot; target=&quot;_blank&quot;&gt;PostGIS newsgroup&lt;/a&gt; and we decided to investigate how 
long it has been supported.
&lt;/p&gt;
&lt;p&gt;What are OUT parameters?  These are parameters you define as part of the function argument
list that get returned back as part of the result.  When you create functions, the arguments 
 are defaulted to IN parameters when not explicitly specified (which means they are passed in and not returned) which 
is why you sometimes see PgAdmin do something like &lt;em&gt;IN somevariable variabletype&lt;/em&gt; when you use 
the function wizard.
&lt;/p&gt;
&lt;p&gt;You can have INOUT parameters as well which are function inputs that both get passed in, can be modified
by the function and also get returned.&lt;/p&gt;

&lt;p&gt;As a side note -  In 8.4, PostgreSQL was enhanced to allow dynamic sql RETURN QUERY using &lt;a href=&quot;http://www.postgresql.org/docs/8.4/static/plpgsql-statements.html&quot; target=&quot;_blank&quot;&gt;RETURN QUERY EXECUTE&lt;/a&gt; syntax for plpgsql queries and also
allow set returning functions being called in the SELECT part for any pl language.  In prior versions,
this was only a feature of PL functions written in SQL.
8.3 introduced RETURN query which required a static sql statement, but did make things a bit easier.
&lt;/p&gt;

&lt;p&gt;One of the common use cases for using OUT parameters is to be able to return multiple outputs from a function without having
to declare a PostgreSQL type as output of the function.  In this article we shall cover all variants of this.  We&#039;ll just focus on sql and plpgsql for this
discussion, since we are not sure to what extent other pl languages (if at all) support IN OUT.&lt;/p&gt;
 &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/129-Use-of-OUT-and-INOUT-Parameters.html#extended&quot;&gt;Continue reading &quot;Use of OUT and INOUT Parameters&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Thu, 30 Jul 2009 14:34:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/129-guid.html</guid>
    
</item>
<item>
    <title>PostgreSQL 8.3 PLPGSQL Cheatsheet Overview</title>
    <link>http://www.postgresonline.com/journal/archives/87-PostgreSQL-8.3-PLPGSQL-Cheatsheet-Overview.html</link>
            <category>8.3</category>
            <category>plpgsql</category>
            <category>special feature</category>
    
    <comments>http://www.postgresonline.com/journal/archives/87-PostgreSQL-8.3-PLPGSQL-Cheatsheet-Overview.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=87</wfw:comment>

    <slash:comments>1</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=87</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;To finish off our PL/PGSQL tutorial series, we are providing a PL/PGSQL cheat sheet.&lt;/P&gt;

&lt;P&gt;Below is a Thumbnail view of the PostgreSQL 8.3 PL/PGSQL cheat sheet 
that covers both 8.3 new features and past core PL/PGSQL features.  This is by no means comprehensive, but are the features we use most often. 
&lt;/P&gt;
&lt;a href=&quot;/special_feature.php?sf_name=postgresql83_plpgsql_cheatsheet&amp;outputformat=html&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;/images/journal/postgresql83_plpgsql_cheatsheet_small.jpg&quot; border=&quot;1&quot;/&gt;&lt;/a&gt;
&lt;/P&gt;
&lt;P&gt;PDF Portrait version 8.5 x 11&quot; of this cheatsheet is available at &lt;a href=&quot;/special_feature.php?sf_name=postgresql83_plpgsql_cheatsheet&amp;outputformat=pdf&quot; target=&quot;_blank&quot;&gt;PostgreSQL 8.3 PL/PGSQL Cheatsheet 8.5 x 11&lt;/a&gt; and also available in
&lt;a href=&quot;/special_feature.php?sf_name=postgresql83_plpgsql_cheatsheet&amp;outputformat=a4pdf&quot; target=&quot;_blank&quot;&gt;PDF A4 format&lt;/a&gt; and &lt;a href=&quot;/special_feature.php?sf_name=postgresql83_plpgsql_cheatsheet&amp;outputformat=html&quot; target=_blank&gt;HTML&lt;/a&gt;.
&lt;/P&gt; 
    </content:encoded>

    <pubDate>Wed, 03 Dec 2008 21:13:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/87-guid.html</guid>
    
</item>
<item>
    <title>Quick Guide to writing PLPGSQL Functions: Part 3 - NOTICES, RECURSION, and more</title>
    <link>http://www.postgresonline.com/journal/archives/83-Quick-Guide-to-writing-PLPGSQL-Functions-Part-3-NOTICES,-RECURSION,-and-more.html</link>
            <category>intermediate</category>
            <category>pl programming</category>
            <category>plpgsql</category>
            <category>sql server</category>
    
    <comments>http://www.postgresonline.com/journal/archives/83-Quick-Guide-to-writing-PLPGSQL-Functions-Part-3-NOTICES,-RECURSION,-and-more.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=83</wfw:comment>

    <slash:comments>1</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=83</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;P&gt;In this third part of our PLPGSQL Quick Guide series, we shall delve into writing recursive functions.  Before we do that, we shall demonstrate a very important
but trivial feature in PostgreSQL and that is the RAISE NOTICE feature.  There are more elegant ways of debugging, but this is the simple brain dead way of doing so.
&lt;/P&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/83-Quick-Guide-to-writing-PLPGSQL-Functions-Part-3-NOTICES,-RECURSION,-and-more.html#extended&quot;&gt;Continue reading &quot;Quick Guide to writing PLPGSQL Functions: Part 3 - NOTICES, RECURSION, and more&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Sun, 30 Nov 2008 00:24:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/83-guid.html</guid>
    
</item>
<item>
    <title>Quick Guide to writing PLPGSQL Functions: Part 2 </title>
    <link>http://www.postgresonline.com/journal/archives/76-Quick-Guide-to-writing-PLPGSQL-Functions-Part-2.html</link>
            <category>beginner</category>
            <category>pl programming</category>
            <category>plpgsql</category>
    
    <comments>http://www.postgresonline.com/journal/archives/76-Quick-Guide-to-writing-PLPGSQL-Functions-Part-2.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=76</wfw:comment>

    <slash:comments>6</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=76</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;P&gt;In first part &lt;a href=&quot;http://www.postgresonline.com/journal/archives/58-Quick-Guide-to-writing-PLPGSQL-Functions-Part-1.html&quot;&gt;Guide to Writing PLPGSQL functions&lt;/a&gt;, we covered the plpgsql function anatomy and basic IF and FOR loops. In this second part of our PLPGSQL Quick Guide series, we shall delve more into control flow.  As we mentioned in the previous part, the following control flow constructs exist for PLPGSQL.
&lt;/P&gt;

&lt;UL&gt;
	&lt;LI&gt;FOR &lt;i&gt;somevariable&lt;/i&gt; IN (1 ...someendnumber) LOOP  .. END LOOP;&lt;/LI&gt;
	&lt;LI&gt;FOR &lt;i&gt;somevariable&lt;/i&gt; IN REVERSE someendnumber .. 1 BY &lt;i&gt;somestep&lt;/i&gt; LOOP  .. END LOOP;&lt;/LI&gt;
	&lt;LI&gt;FOR &lt;i&gt;somevariable&lt;/i&gt; IN EXECUTE(&lt;i&gt;somesqlquery&lt;/i&gt;) LOOP ..RETURN NEXT; .. END LOOP;&lt;/LI&gt;
	&lt;LI&gt;LOOP ..logic statements EXIT .. EXIT WHEN .. CONTINUE WHEN .. END LOOP;&lt;/LI&gt;
	&lt;LI&gt;WHILE ... LOOP  ... END LOOP; &lt;/LI&gt;
	&lt;LI&gt;EXCEPTION WHEN .... WHEN .. &lt;/LI&gt;
	&lt;LI&gt;Introduced in 8.3 RETURN QUERY which can be in any LOOP like structure or stand alone.  This is 
	covered in &lt;a href=&quot;http://www.postgresonline.com/journal/archives/33-New-Features-for-PostgreSQL-Stored-Functions.html&quot; target=&quot;_blank&quot;&gt;New Features of PostgreSQL Functions&lt;/a&gt;&lt;/LI&gt;
&lt;/UL&gt;

&lt;P&gt;In this section we shall demonstrate looping thru sets of records and writing a set returning function.  In the next section after,
we shall delve a little into recursive functions, doing table updates, and raising notices.&lt;/P&gt;
 &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/76-Quick-Guide-to-writing-PLPGSQL-Functions-Part-2.html#extended&quot;&gt;Continue reading &quot;Quick Guide to writing PLPGSQL Functions: Part 2 &quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Tue, 28 Oct 2008 18:09:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/76-guid.html</guid>
    <category>plpgsql</category>

</item>
<item>
    <title>Quick Guide to writing PLPGSQL Functions: Part 1</title>
    <link>http://www.postgresonline.com/journal/archives/58-Quick-Guide-to-writing-PLPGSQL-Functions-Part-1.html</link>
            <category>beginner</category>
            <category>pl programming</category>
            <category>plpgsql</category>
    
    <comments>http://www.postgresonline.com/journal/archives/58-Quick-Guide-to-writing-PLPGSQL-Functions-Part-1.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=58</wfw:comment>

    <slash:comments>7</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=58</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;P&gt;In this series we&#039;ll go over writing PLPGSQL stored functions.  We shall follow up in a later issue with a one page cheat sheet.
&lt;/P&gt;
&lt;h4&gt;The Anatomy of a PLPGSQL FUNCTION&lt;/h4&gt;
&lt;P&gt;All PLPGSQL functions follow a structure that looks something like the below. 
&lt;pre&gt;
&lt;code&gt;
&lt;span class=&quot;syntax0&quot;&gt;&lt;span class=&quot;syntax8&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;syntax8&quot;&gt;OR&lt;/span&gt; &lt;span class=&quot;syntax9&quot;&gt;REPLACE&lt;/span&gt; &lt;span class=&quot;syntax8&quot;&gt;FUNCTION&lt;/span&gt; &lt;span class=&quot;syntax6&quot;&gt;fnsomefunc&lt;/span&gt;&lt;span class=&quot;syntax18&quot;&gt;(&lt;/span&gt;numtimes &lt;span class=&quot;syntax8&quot;&gt;integer&lt;/span&gt;, msg &lt;span class=&quot;syntax8&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;syntax18&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;syntax8&quot;&gt;RETURNS&lt;/span&gt; &lt;span class=&quot;syntax8&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;syntax8&quot;&gt;AS&lt;/span&gt;
$$
&lt;span class=&quot;syntax8&quot;&gt;DECLARE&lt;/span&gt;
    strresult &lt;span class=&quot;syntax8&quot;&gt;text&lt;/span&gt;;
&lt;span class=&quot;syntax8&quot;&gt;BEGIN&lt;/span&gt;
    strresult :&lt;span class=&quot;syntax18&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax13&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax13&quot;&gt;&#039;&lt;/span&gt;;
    &lt;span class=&quot;syntax8&quot;&gt;IF&lt;/span&gt; numtimes &lt;span class=&quot;syntax18&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax5&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;syntax8&quot;&gt;THEN&lt;/span&gt;
        &lt;span class=&quot;syntax8&quot;&gt;FOR&lt;/span&gt; i &lt;span class=&quot;syntax8&quot;&gt;IN&lt;/span&gt; &lt;span class=&quot;syntax5&quot;&gt;1&lt;/span&gt; .. numtimes LOOP
            strresult :&lt;span class=&quot;syntax18&quot;&gt;=&lt;/span&gt; strresult &lt;span class=&quot;syntax18&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;syntax18&quot;&gt;|&lt;/span&gt; msg &lt;span class=&quot;syntax18&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;syntax18&quot;&gt;|&lt;/span&gt; E&lt;span class=&quot;syntax13&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax13&quot;&gt;\r\n&lt;/span&gt;&lt;span class=&quot;syntax13&quot;&gt;&#039;&lt;/span&gt;;
        &lt;span class=&quot;syntax8&quot;&gt;END&lt;/span&gt; LOOP;
    &lt;span class=&quot;syntax8&quot;&gt;END&lt;/span&gt; &lt;span class=&quot;syntax8&quot;&gt;IF&lt;/span&gt;;
    &lt;span class=&quot;syntax8&quot;&gt;RETURN&lt;/span&gt; strresult;
&lt;span class=&quot;syntax8&quot;&gt;END&lt;/span&gt;;
$$
LANGUAGE &lt;span class=&quot;syntax13&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax13&quot;&gt;plpgsql&lt;/span&gt;&lt;span class=&quot;syntax13&quot;&gt;&#039;&lt;/span&gt; IMMUTABLE
SECURITY DEFINER
  COST &lt;span class=&quot;syntax5&quot;&gt;10&lt;/span&gt;;

&lt;span class=&quot;syntax1&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt;To&lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt;the&lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt;we&lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt;do&lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt;returns&lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt;ten&lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt;there&#039;s&lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;syntax1&quot;&gt; &lt;/span&gt;
carriage &lt;span class=&quot;syntax8&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;syntax8&quot;&gt;as&lt;/span&gt; a single &lt;span class=&quot;syntax8&quot;&gt;text&lt;/span&gt; field.
&lt;span class=&quot;syntax8&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;syntax6&quot;&gt;fnsomefunc&lt;/span&gt;&lt;span class=&quot;syntax18&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax5&quot;&gt;10&lt;/span&gt;, &lt;span class=&quot;syntax13&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax13&quot;&gt;Hello&lt;/span&gt;&lt;span class=&quot;syntax13&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax13&quot;&gt;there&lt;/span&gt;&lt;span class=&quot;syntax13&quot;&gt;&#039;&lt;/span&gt;&lt;span class=&quot;syntax18&quot;&gt;)&lt;/span&gt;;
&lt;/span&gt;
&lt;/code&gt;
&lt;/pre&gt;
&lt;/P&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/58-Quick-Guide-to-writing-PLPGSQL-Functions-Part-1.html#extended&quot;&gt;Continue reading &quot;Quick Guide to writing PLPGSQL Functions: Part 1&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Sat, 11 Oct 2008 22:46:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/58-guid.html</guid>
    <category>plpgsql</category>

</item>
<item>
    <title>Choosing the right Database Procedural Language PL</title>
    <link>http://www.postgresonline.com/journal/archives/50-Choosing-the-right-Database-Procedural-Language-PL.html</link>
            <category>beginner</category>
            <category>mysql</category>
            <category>pl programming</category>
            <category>plperl</category>
            <category>plpgsql</category>
            <category>PLR</category>
            <category>sql functions</category>
            <category>sql server</category>
    
    <comments>http://www.postgresonline.com/journal/archives/50-Choosing-the-right-Database-Procedural-Language-PL.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=50</wfw:comment>

    <slash:comments>4</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=50</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;P&gt;One of the great selling points of PostgreSQL is its pluggable PL language architecture.  MySQL is known for its pluggable storage and 
PostgreSQL is known for its pluggable PL language architecture.  From &lt;a href=&quot;http://www.scribd.com/doc/2575733/The-future-of-MySQL-The-Project&quot; target=_blank&gt;Monty&#039;s notes on slide 12&lt;/a&gt; looks like MySQL 
may be working on a pluggable PL language architecture of their own.
The most common of these languages are the all-purpose languages SQL and C (these are built-in and not really PLs like the others, but we&#039;ll throw them in there),
&lt;a href=&quot;http://www.postgresql.com.cn/docs/8.3/static/plpgsql.html&quot; target=_blank&gt;PLPgSQL&lt;/a&gt; which is also built-in but not always enabled, &lt;a href=&quot;http://www.postgresql.org/docs/8.3/static/plperl.html&quot; target=_blank&gt;PL/Perl&lt;/a&gt;, &lt;a href=&quot;http://www.postgresql.org/docs/8.3/interactive/plpython.html&quot; target=_blank&gt;PL/Python&lt;/a&gt;, and the domain specific languages &lt;a href=&quot;http://joeconway.com/plr/doc/index.html&quot; target=_blank&gt;PL/R&lt;/a&gt;, &lt;A href=&quot;http://plsh.projects.postgresql.org/&quot; target=_blank&gt;PL/SH&lt;/A&gt; and gaining popularity Skype released &lt;a href=&quot;https://developer.skype.com/SkypeGarage/DbProjects/PlProxy&quot; target=_blank&gt;PL/Proxy&lt;/a&gt;.  
There are others in the family such as &lt;a href=&quot;http://www.postgresql.org/docs/8.3/interactive/pltcl.html&quot; target=_blank&gt;PL/Tcl&lt;/a&gt;, &lt;a href=&quot;https://projects.commandprompt.com/public/plphp&quot; target=_blank&gt;PL/PHP&lt;/a&gt;, &lt;a href=&quot;http://raa.ruby-lang.org/project/pl-ruby/&quot; target=_blank&gt;PL/Ruby&lt;/a&gt;, &lt;a href=&quot;http://plscheme.projects.postgresql.org/&quot; target=_blank&gt;PL/Scheme (a dialect of Lisp)&lt;/a&gt;, &lt;a href=&quot;http://wiki.tada.se/display/pljava/Home&quot; target=_blank&gt;PL/Java&lt;/a&gt;, &lt;a href=&quot;http://pllua.projects.postgresql.org/&quot; target=_blank&gt;PL/Lua&lt;/a&gt; and &lt;a href=&quot;http://pgfoundry.org/projects/pllolcode&quot; target=_blank&gt;PL/LOLCode (for kicks and as a reference implementation.  Think of LOLCode as PostgreSQL Pluggable PL equivalent of MySQL&#039;s BLACK HOLE storage engine.)&lt;/a&gt; .
&lt;/P&gt;

&lt;P&gt;The other interesting thing about the PostgreSQL PL language architecture is that it is a fairly thin wrapper around these languages.
This means the kind of code you write in those languages is pretty much what you would write if you were doing general programming
in those languages minus some spi calls. Since the handler is a just a thin wrapper around the environment, the language environment must be installed on the database server before you can use the PL language handler.  This means you can have these functions utilized in your SQL statements and you can write
in a language you feel comfortable with if you can get the darn PL compiled for your environment or someone has already kindly compiled it for your environment or that it is even compilable for your environment.  The pluggable PL architecture means you can 
write a PL Handler for your favorite language or invent your own language that you can run in the database.   In the end 
the barrier between code,data, and semantic constructs is more of a constraint imposed by compilers.  If you have any doubts about the above statement, you need only look at some javascript injection attacks
to bring the statement home. One of my fantasies is 
developing a language that morphs itself, that utilizes the database as its morphing engine and its OS and that breaks the illusion of data being data, code being code, and lacks rigid semantics.  
Of the languages we have worked with, &lt;a href=&quot;http://en.wikipedia.org/wiki/Smalltalk&quot; target=_blank&gt;SmallTalk&lt;/a&gt; comes closest to a language that satisfies these ideals and Lisp to a much lesser extent.  Lisp lacked the semantic elegance of SmallTalk among other things.
&lt;/P&gt;

&lt;P&gt;Most people are used to having their procedural language push their data around.  PL code living in PostgreSQL allows your data to push your procedural code around in a set-based way.  This is a simple but pretty powerful feature since data is in general more fluid than code. For interpretated/just-in time compiled languages it can live in the database, for compiled it has to call compiled functions. &lt;/P&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/50-Choosing-the-right-Database-Procedural-Language-PL.html#extended&quot;&gt;Continue reading &quot;Choosing the right Database Procedural Language PL&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Sat, 10 May 2008 06:58:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/50-guid.html</guid>
    
</item>
<item>
    <title>REST in PostgreSQL Part 1 - The DB components</title>
    <link>http://www.postgresonline.com/journal/archives/36-REST-in-PostgreSQL-Part-1-The-DB-components.html</link>
            <category>application development</category>
            <category>intermediate</category>
            <category>pagila</category>
            <category>plpgsql</category>
            <category>tsearch</category>
            <category>webservices</category>
    
    <comments>http://www.postgresonline.com/journal/archives/36-REST-in-PostgreSQL-Part-1-The-DB-components.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=36</wfw:comment>

    <slash:comments>2</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=36</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;P&gt;In this section we&#039;ll go over creating the views and stored functions that our REST Server service will rely on.&lt;/P&gt;
&lt;P&gt;Our REST service will be a thin wrapper around a pgsql function that accepts film queries and returns results in XML.&lt;/P&gt;

&lt;h4&gt;Loading the database&lt;/h4&gt;
&lt;P&gt;&lt;b&gt;Step 1:&lt;/b&gt; Download the Pagila 0.10.0 database from 
&lt;a href=&quot;http://pgfoundry.org/frs/?group_id=1000150&amp;release_id=570&quot; target=&quot;_blank&quot;&gt;http://pgfoundry.org/frs/?group_id=1000150&amp;release_id=570&lt;/a&gt;
and load the Pagila database using the following commands: &lt;br /&gt;&lt;br /&gt;
&lt;b&gt;Note:&lt;/b&gt;For windows users - psql is usually located at &lt;em&gt;&quot;C:\Program Files\PostgreSQL\8.3\bin\psql&quot;&lt;/em&gt;&lt;br /&gt;
&lt;PRE&gt;
&lt;CODE&gt;
psql -h localhost -p 5433 -U postgres -c &quot;CREATE DATABASE pagila ENCODING &#039;UTF8&#039;&quot;
psql -h localhost -p 5433 -U postgres -c &quot;CREATE ROLE pagila_app LOGIN PASSWORD &#039;pg@123&#039;&quot;
psql -h localhost -p 5433 -U postgres -d pagila -f &quot;pagila-schema.sql&quot;
psql -h localhost -p 5433 -U postgres -d pagila -f &quot;pagila-data.sql&quot;
&lt;/CODE&gt;
&lt;/PRE&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/36-REST-in-PostgreSQL-Part-1-The-DB-components.html#extended&quot;&gt;Continue reading &quot;REST in PostgreSQL Part 1 - The DB components&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Sun, 16 Mar 2008 18:33:00 -0400</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/36-guid.html</guid>
    
</item>
<item>
    <title>New Features for PostgreSQL Stored Functions</title>
    <link>http://www.postgresonline.com/journal/archives/33-New-Features-for-PostgreSQL-Stored-Functions.html</link>
            <category>intermediate</category>
            <category>pl programming</category>
            <category>plpgsql</category>
            <category>sql functions</category>
    
    <comments>http://www.postgresonline.com/journal/archives/33-New-Features-for-PostgreSQL-Stored-Functions.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=33</wfw:comment>

    <slash:comments>8</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=33</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;P&gt;PostgreSQL 8.3 introduced a couple of new features that improves the processing of functions and makes plpgsql
functions easier to write.  These are as follows: &lt;/P&gt;
&lt;OL&gt;
	&lt;LI&gt;The new ROWS and COST declarations for a function.  These can be used for any PostgreSQL function written in any language.  These declarations
		allow the function designer to dictate to the planner how many records to expect and provide a hint as to how expensive a function call is.  COST is measured in CPU cycles.  A higher COST number means more costly.
		For example a high cost function called in an AND where condition will not be called 
		if any of the less costly functions result in a false evaluation.  The number of ROWs as well as COST will give the planner a better idea of
		which strategy to use. &lt;/LI&gt;	
	&lt;LI&gt;RETURN QUERY functionality was introduced as well and only applies to plpgsql written functions.  
		This is both an easier as well as a more efficient way of returning query results in plpgsql functions.  
		Hubert Lubazeuwski provides an example of this in &lt;a href=&quot;http://www.depesz.com/index.php/2007/08/01/set-returning-functions-in-83/&quot; target=_blank&gt;set returning functions in 8.3&lt;/a&gt;.
		We shall provide yet another example of this.&lt;/LI&gt;
	&lt;LI&gt;Server configuration parameters can now be set on a per-function basis. This is useful say in cases where you know a function will need a lot of work_mem, but you don&#039;t want to 
		give all queries accessing the database that greater level of worker memory or you are doing something that index scan just works much better than sequential scan and you want to
		change the planners default behavior only for this function.&lt;/LI&gt;
	&lt;LI&gt;Scrollable Cursors in PL/pgSQL - this is documented in &lt;a href=&quot;http://www.postgresql.org/docs/8.3/interactive/plpgsql-cursors.html#PLPGSQL-CURSOR-DECLARATIONS&quot; target=_blank&gt;Declaring Cursor Variables&lt;/a&gt;&lt;/LI&gt;
	&lt;LI&gt;Plan Invalidation - Merlin Moncure covers this in &lt;a href=&quot;http://merlinmoncure.blogspot.com/2007/09/as-previously-stated-postgresql-8.html&quot; target=_blank&gt;PostgreSQL 8.3 Features: Plan Invalidation&lt;/a&gt; so we won&#039;t bother giving
	another example of this.  Basic point to take away from this is that in procedures where you have stale plans floating dependent on tables being dropped by a function, those plans will
			be automagically deleted so you don&#039;t have ghost plans breaking your function.&lt;/LI&gt;
&lt;/OL&gt; &lt;br /&gt;&lt;a href=&quot;http://www.postgresonline.com/journal/archives/33-New-Features-for-PostgreSQL-Stored-Functions.html#extended&quot;&gt;Continue reading &quot;New Features for PostgreSQL Stored Functions&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Tue, 26 Feb 2008 17:32:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/33-guid.html</guid>
    
</item>
<item>
    <title>Trojan SQL Function Hack - A PL Lemma in Disguise</title>
    <link>http://www.postgresonline.com/journal/archives/16-Trojan-SQL-Function-Hack-A-PL-Lemma-in-Disguise.html</link>
            <category>advanced</category>
            <category>pl programming</category>
            <category>plpgsql</category>
            <category>sql functions</category>
    
    <comments>http://www.postgresonline.com/journal/archives/16-Trojan-SQL-Function-Hack-A-PL-Lemma-in-Disguise.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=16</wfw:comment>

    <slash:comments>2</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=16</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;P&gt;Have you ever noticed that in PostgreSQL you can put set returning functions in the SELECT part 
of an sql statement if the function is written in language SQL or C.  Try the same trick for PL written functions
such as plpgsql, plperl, plr etc, and you get a slap on the wrist of the form 
&lt;b style=&#039;color:red&#039;&gt;ERROR:  set-valued function called in context that cannot accept a set&lt;/b&gt;.  For Plpgsql and other PL languages you must put the set returning function in the FROM clause. &lt;/P&gt;

&lt;P&gt;Below is a simple  example: 
&lt;PRE&gt;
&lt;CODE&gt;
--Build test data
CREATE TABLE test
(
  test_id serial NOT NULL,
  test_date date,
  CONSTRAINT pk_test PRIMARY KEY (test_id)
)
WITH (OIDS=FALSE);

INSERT INTO test(test_date)
	SELECT current_date + n
		FROM generate_series(1,1000) n;
		
--test function with sql
CREATE OR REPLACE FUNCTION fnsqltestprevn(id integer, lastn integer)
  RETURNS SETOF test AS
$$
	SELECT *
	FROM test 
	WHERE test_id &lt; $1 ORDER BY test_id
	LIMIT $2
$$
  LANGUAGE &#039;sql&#039; VOLATILE;
  
--Test example 1 works fine
SELECT (fnsqltestprevn(6,5)).*;

--Test example 2 works fine
SELECT *
	FROM fnsqltestprevn(6,5);
	
--Same test function written as plpgsql
CREATE OR REPLACE FUNCTION fnplpgsqltestprevn(id integer, prevn integer)
  RETURNS SETOF test AS
$$
DECLARE
    rectest test;
BEGIN
	FOR rectest 
		IN(SELECT * 
			FROM test 
			WHERE test_id &lt; id 
			ORDER BY test_id LIMIT prevn)  
								LOOP
		RETURN NEXT rectest;
	END LOOP;
END;
$$
LANGUAGE &#039;plpgsql&#039; VOLATILE;

--Test example 1 - gives error
-- ERROR:  set-valued function called in context that cannot accept a set
SELECT (fnplpgsqltestprevn(6,5)).*;

--Test example 2 works fine
SELECT *
	FROM fnplpgsqltestprevn(6,5);
&lt;/CODE&gt;
&lt;/PRE&gt;
So it appears that PostgreSQL is not quite as democratic as we would like.  
&lt;PRE&gt;
&lt;CODE&gt;
--But what if we did this?
CREATE OR REPLACE FUNCTION fnsqltrojtestprevn(id integer, prevn integer)
	RETURNS SETOF test AS
$$
	SELECT * FROM fnplpgsqltestprevn($1, $2);
$$
LANGUAGE &#039;sql&#039; VOLATILE;

--Test example 1 - works fine
SELECT (fnsqltrojtestprevn(6,5)).*;

--Test example 2 works fine
SELECT *
	FROM fnsqltrojtestprevn(6,5);
&lt;/CODE&gt;
&lt;/PRE&gt;
&lt;P&gt;
All interesting, but so what? you may ask.  It is bad practice to put
set returning functions in a SELECT clause.  Such things are commonly mistakes and should be avoided.&lt;/P&gt;
&lt;/P&gt;

&lt;h3&gt;Functional Row Expansion&lt;/h3&gt;
&lt;P&gt;It turns out that there are a whole class of problems in SQL where the simplest way to achieve the desired result is via
a technique we shall call &lt;b&gt;Functional Row Expansion&lt;/b&gt;.  By that, we mean that for each record in a given set, we want to
return another set of records that can not be expressed as a constant join expression.  Basically the join expression is different
for each record or the function we want to apply is too complicated to be expressed as a static join statement or join at all.
&lt;/P&gt;

&lt;P&gt;Taking the above example.  Lets say for each record in test, you want to return the 4 records preceding including the current one.  So basically you want to
explode each row into 5 or fewer rows.  Your general gut reaction would be do something as follows: &lt;/P&gt;

&lt;br /&gt;
these give error: ERROR:  function expression in FROM cannot refer to other relations of same query level
&lt;br /&gt;
&lt;PRE&gt;
	&lt;CODE&gt;
		SELECT test.test_id As ref_id, test.test_date as ref_date, targ.*
			FROM test , 
				(SELECT tinner.* 
					FROM test as tinner 
						WHERE tinner.test_id &lt;= test.test_id 
					ORDER BY tinner.test_id LIMIT 5) As targ;
					
		SELECT test.test_id As ref_id, test.test_date as ref_date, targ.*
			FROM test,fnsqltrojtestprevn(test.test_id, 5) As targ;
	&lt;/CODE&gt;
&lt;/PRE&gt;
&lt;br /&gt;&lt;br /&gt;
--But this does what you want
&lt;PRE&gt;
	&lt;CODE&gt;
SELECT test.test_id As ref_id, test.test_date as ref_date, 
	(fnsqltrojtestprevn(test.test_id, 5)).*
  FROM test
	&lt;/CODE&gt;
&lt;/PRE&gt;

&lt;P&gt;Keep in mind what makes the above tricky is that you want to return at most 4 of the preceding plus current.  If you want to return all the preceding plus current, then 
you can do a trivial self join as follows: &lt;/P&gt;
&lt;PRE&gt;
	&lt;CODE&gt;
SELECT test.test_id As ref_id, test.test_date as ref_date, targ.*
  FROM test INNER JOIN
	 test As targ ON targ.test_id &lt;= test.test_id
  ORDER BY test.test_id, targ.test_id
	&lt;/CODE&gt;
&lt;/PRE&gt;

&lt;P&gt;So as you can see - its sometimes tricky to tell when you need to use this technique and when you don&#039;t.&lt;/P&gt;
&lt;P&gt;For this trivial example, writing the function as an SQL only function works fine and is the best to use.  SQL functions unfortunately
lack the ability to define dynamic sql statements, among other deficiencies so resorting to using a pl language is often easier which means you lose this useful feature of sql functions.  
Stuffing a pl function in an SQL function just might do the trick.  We haven&#039;t tried this on other pl languages except plpgsql, but we suspect it should work the same.
&lt;/P&gt;

 
    </content:encoded>

    <pubDate>Mon, 31 Dec 2007 17:33:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/16-guid.html</guid>
    
</item>
<item>
    <title>Language Architecture in PostgreSQL</title>
    <link>http://www.postgresonline.com/journal/archives/6-Language-Architecture-in-PostgreSQL.html</link>
            <category>intermediate</category>
            <category>pl programming</category>
            <category>plpgsql</category>
            <category>PLR</category>
            <category>sql functions</category>
    
    <comments>http://www.postgresonline.com/journal/archives/6-Language-Architecture-in-PostgreSQL.html#comments</comments>
    <wfw:comment>http://www.postgresonline.com/journal/wfwcomment.php?cid=6</wfw:comment>

    <slash:comments>4</slash:comments>
    <wfw:commentRss>http://www.postgresonline.com/journal/rss.php?version=2.0&amp;type=comments&amp;cid=6</wfw:commentRss>
    

    <author>nospam@example.com (Leo Hsu and Regina Obe)</author>
    <content:encoded>
    &lt;p&gt;Perhaps one of the most unique and exciting things that makes PostgreSQL stand out from other database systems, are the numerous choices of languages one can use to create database functions, triggers and define new aggregate functions with.  Not only can you use various languages to write your database stored functions with, but often times the code you write lives right in the database.  You have no idea how cool this is until you see it in action.&lt;/p&gt;

&lt;p&gt;The other interesting thing about the PostgreSQL language architecture is the relative ease with which new languages can be incorporated in the system.&lt;/p&gt;

&lt;h4&gt;Native Languages of PostgreSQL&lt;/h4&gt;
&lt;p&gt;There are 3 languages that come packaged with PostgreSQL (2 non-PL ones are installed automatically and not even listed as languages (C and SQL) in the languages section of a db).  The defacto PL/PgSQL procedural language is available for install in all PostgreSQL distributions, but need not be installed in a db by default .  
&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;i&gt;C Extern&lt;/i&gt; which allows for binding C libraries as functions.  C Extern is similar to the way languages like MySQL bind C libraries for use in DB or the way SQL Server 2005+ binds .NET assemblies as functions in SQL Server.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;SQL&lt;/i&gt; - this is a non-procedural language.  It allows one to write parameterized db stored functions with plain SQL, but lacks procedural logic constructs such as IF, FOR, WHILE and so forth.  It is basically a macro substitution language.  Functions written in this way are basically in-lined in with the queries they are used (except in case of STABLE, IMMUTABLE defined in which case cached results are often used) in so they are more easily optimizable than functions written in other languages.  NOTE: that MySQL 5+ also has a Procedural language called SQL, but the MySQL SQL language is a procedural language more in line with PostgreSQL &lt;i&gt;pl/pgsql&lt;/i&gt; and closer in syntax to DB2&#039;s SQL PL.  I&#039;ll also note that DB2 has a concept of INLINE SQL PL which is kind of like PostgreSQL sql language, although a bit more powerful.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;PL/PgSQL&lt;/i&gt; - this is PostgreSQL defacto Procedural Language.  It is not always installed by default in a database but the language handler is always available for installation.  The equivalent but slightly different in syntax in other systems would be Transact SQL in SQL Server/Sybase, PL/SQL in Oracle, SQL in MySQL5+, and SQL PL in DB2.&lt;/li&gt; 
&lt;/ol&gt;

&lt;h4&gt;The PL languages&lt;/h4&gt;
&lt;p&gt;Aside from PL/pgSQL there are numerous other procedural languages that one can use to create database stored functions and triggers.  Some of these languages are fairly stable and even more are experimental.  Some are only supported on Unix/Linux, but many are supported on Unix/Linux/MacOS/windows.  In any case there are 3 key components needed before you can start using a new language: 

&lt;/p&gt;&lt;ol&gt;
    &lt;li&gt;The environment for the language - e.g. PHP, Perl, Python, Ruby, Java, R etc. interpreter and libraries installed on the PostgreSQL server box&lt;/li&gt;
    &lt;li&gt;The compiled call handler function - this is a C-compiled function that does the transfer between the PostgreSQL environment and the language environment.&lt;/li&gt;&lt;li&gt;The language registered in the database you wish to use it in.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;Registering a language in a Database&lt;/h3&gt;
&lt;p&gt;For &lt;i&gt;pl/pgsql&lt;/i&gt; items 1 and 2 are already done if you have a working PostgreSQL install.  In order to accomplish item 3, you may need to do the following from psql or PgAdmin III query window.

&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
 CREATE TRUSTED PROCEDURAL LANGUAGE &#039;plpgsql&#039;
  HANDLER plpgsql_call_handler
  VALIDATOR plpgsql_validator;
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;Alternatively you can run &lt;em&gt;createlang plpgsql somedb&lt;/em&gt; from commandline.   Note createlang is a command line program that is located in the &lt;b&gt;bin&lt;/b&gt; folder of your PostgreSQL install.&lt;/p&gt;

&lt;p&gt;To see a list of procedural languages that you already have call handlers registered for in PostgreSQL.  These are the languages you can register in your specific database - do a 
&lt;/p&gt;
&lt;code&gt;SELECT * FROM pg_catalog.pg_pltemplate&lt;/code&gt;

&lt;h4&gt;A Flavor of the Procedural Languages (PLs)&lt;/h4&gt;
&lt;p&gt;In this section, we&#039;ll show a brief sampling of what functions look like written in various PLs.  These are not to suggest they are the only ones that exist.  For these examples, I&#039;m going to use the $ quoting syntax introduced in PostgreSQL 8.0 which allows for not having to escape out single quotes.&lt;/p&gt;

&lt;h5&gt;SQL - the not PL language&lt;/h5&gt;
&lt;p&gt;For basic CRUD stuff,selects and simple functions, nothing hits the spot like just plain old SQL.  Since this is such a common choice and often the best choice - here are 3 examples.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;CREATE OR REPLACE FUNCTION cp_simpleupdate(thekey integer, thevalue varchar(50))
  RETURNS void AS
	$BODY$
		UPDATE testtable SET test_stuff = $2 WHERE test_id = $1
	$BODY$
  LANGUAGE &#039;sql&#039; VOLATILE;
&lt;/code&gt;

--Example use
SELECT cp_simpleupdate(1, &#039;set to this&#039;); 
&lt;/pre&gt;

&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
--Here is a simple example to simulate the MySQL 5.0 function
CREATE OR REPLACE FUNCTION from_unixtime(unixts integer)
  RETURNS timestamp without time zone AS
$BODY$SELECT CAST(&#039;epoch&#039; As timestamp) + ($1 * INTERVAL &#039;1 second&#039;) $BODY$
  LANGUAGE &#039;sql&#039; IMMUTABLE;
  
  --Example use
  SELECT from_unixtime(1134657687); 
  SELECT from_unixtime(tbl.fromsomefield) FROM tbl;
&lt;/code&gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;pre&gt;
&lt;code&gt;
CREATE OR REPLACE FUNCTION cp_test(subject varchar)
  RETURNS SETOF testtable AS
  $BODY$
	SELECT * FROM testtable where test_stuff LIKE $1;
	$BODY$
  LANGUAGE &#039;sql&#039; VOLATILE;
  --Example use
  SELECT * FROM cp_test(&#039;%stuff%&#039;);
&lt;/code&gt;
&lt;/pre&gt;

&lt;pre&gt;
&lt;code&gt;
  CREATE OR REPLACE FUNCTION cp_testusingoutparams(subject varchar, out test_id int, out test_stuff varchar)
  RETURNS SETOF record AS
$BODY$
	SELECT test_id, test_stuff FROM testtable where test_stuff LIKE $1;
$BODY$
  LANGUAGE &#039;sql&#039; VOLATILE;

--Example use - Note the subtle difference - the second syntax with out parameters is newer
-- It allows you to get around the messy issue of when you are returning a record type
--That a record type has no specific type.
SELECT * FROM cp_usingoutparams(&#039;%stuff%&#039;);
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;For details on using out parameters, check out Robert Treat&#039;s &lt;a href=&quot;http://people.planetpostgresql.org/xzilla/index.php?/archives/149-guid.html&quot; target=_blank&gt;out parameter sql &amp;amp; plpgsql examples&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;PLPGSQL - a real PL Language&lt;/h4&gt;
&lt;p&gt;For more complex logic and massaging of results before sending back.  You need something more powerful than standard SQL. 
Below are some examples using PLPGSQL.
&lt;/p&gt;


&lt;pre&gt;
&lt;code&gt;
CREATE OR REPLACE FUNCTION cp_harderupdate(thekey integer, thevalue varchar)
RETURNS void AS
$BODY$
BEGIN
	IF EXISTS(SELECT test_id FROM testtable WHERE test_id = thekey) THEN 
		UPDATE testtable SET test_stuff = thevalue WHERE test_id = thekey;
	ELSE
		INSERT INTO testtable(test_id, test_stuff) VALUES(thekey, thevalue);
	END IF;
     RETURN;
END;
$BODY$
LANGUAGE &#039;plpgsql&#039; VOLATILE;

--Example use
SELECT cp_harderupdate(1, &#039;this is more stuff&#039;);

&lt;/code&gt;
&lt;/pre&gt;

&lt;h4&gt;Using PL/Perl&lt;/h4&gt;
&lt;CODE&gt;
&lt;PRE&gt;
CREATE OR REPLACE FUNCTION get_neworders() RETURNS SETOF orders AS $$
    my $rv = spi_exec_query(&#039;select * from orders where processed IS NULL;&#039;);
    my $status = $rv-&gt;{status};
    my $nrows = $rv-&gt;{processed};
    foreach my $rn (0 .. $nrows - 1) {
        my $row = $rv-&gt;{rows}[$rn];
        return_next($row);
    }
    return undef;
$$ LANGUAGE plperl;
&lt;/PRE&gt;
&lt;/CODE&gt;

&lt;h4&gt;Using PL/R a language and environment for statistics&lt;/h4&gt;
&lt;P&gt;One of my favorite PL languages to program is PL/R.  The reason for this is that the R statistical environment is such a rich environment for doing statistical processing.  It now is also supported on windows as well as Mac and Linux.&lt;/p&gt;

&lt;P&gt;To learn more about R and installing PL/R.  Check out our Boston GIS article &lt;i&gt;&lt;a href=&quot;http://www.bostongis.com/PrinterFriendly.aspx?content_name=postgresql_plr_tut01&quot; target=_blank&gt;PLR Part 1: Up and Running with PL/R (PLR) in PostgreSQL: An almost Idiot&#039;s Guide&lt;/a&gt;&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Below is the classic median aggregate function in R.  It uses the native median function in the R environment to create a PostgreSQL aggregate median function&lt;/p&gt;
&lt;PRE&gt;
&lt;CODE&gt;
CREATE or REPLACE FUNCTION r_median(_float8) 
	returns float as $BODY$ median(arg1) $BODY$ language &#039;plr&#039;;

CREATE AGGREGATE median (
  sfunc = plr_array_accum,
  basetype = float8,
  stype = _float8,
  finalfunc = r_median
);

--Example use
SELECT median(age) As themedian_age, period_year 
        FROM crimestats GROUP BY period_year ORDER BY period_year;
&lt;/CODE&gt;
&lt;/PRE&gt;

&lt;P&gt;We will be covering PLR in greater detail in another article.&lt;/P&gt; 
    </content:encoded>

    <pubDate>Fri, 30 Nov 2007 00:00:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.postgresonline.com/journal/archives/6-guid.html</guid>
    
</item>

</channel>
</rss>