<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Abdul Yadi's Blog</title>
	
	<link>http://abdulyadi.wordpress.com</link>
	<description>once upon a time in Batam</description>
	<lastBuildDate>Mon, 21 May 2012 13:00:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain="abdulyadi.wordpress.com" port="80" path="/?rsscloud=notify" registerProcedure="" protocol="http-post" />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Abdul Yadi's Blog</title>
		<link>http://abdulyadi.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://abdulyadi.wordpress.com/osd.xml" title="Abdul Yadi's Blog" />
	
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/AbdulyadisBlog" /><feedburner:info uri="abdulyadisblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://abdulyadi.wordpress.com/?pushpress=hub" /><feedburner:browserFriendly></feedburner:browserFriendly><item>
		<title>Consume SOAP Web Service from PostgreSQL User Defined Function in C</title>
		<link>http://abdulyadi.wordpress.com/2012/03/03/consume-soap-web-service-from-postgresql-user-defined-function-in-c/</link>
		<comments>http://abdulyadi.wordpress.com/2012/03/03/consume-soap-web-service-from-postgresql-user-defined-function-in-c/#comments</comments>
		<pubDate>Sat, 03 Mar 2012 19:14:17 +0000</pubDate>
		<dc:creator>abdulyadi</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://abdulyadi.wordpress.com/?p=174</guid>
		<description><![CDATA[In memoriam, Pipit F.Y.H (Oct 30, 1968 &#8211; Jan 15, 2012), we have passed precious moments, once in my lifetime. I have took a look directory of public SOAP web services at http://www.service-repository.com. Then an idea came across my mind to utilize gSOAP toolkit to develop some C code for a User Defined Function in [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=174&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<div>In memoriam, <b>Pipit F.Y.H</b> (Oct 30, 1968 &#8211; Jan 15, 2012), <i>we have passed precious moments, once in my lifetime</i>.</div>
<p><img width="130px" src="http://abdulyadi.files.wordpress.com/2012/03/pipit1.jpg?w=600" alt="f.y.h" /></p>
<div style="margin-top:5mm;">I have took a look directory of public SOAP web services at <a href="http://www.service-repository.com">http://www.service-repository.com</a>. Then an idea came across my mind to utilize <a href="http://www.cs.fsu.edu/~engelen/soap.html">gSOAP</a> toolkit to develop some C code for a User Defined Function in PostgreSQL, so I can consume service provided by <a href="http://www.service-repository.com/service/overview/1376273594">http://www.currencyserver.de/webservice/currencyserverwebservice.asmx?WSDL</a> to get currency rate through SQL command, such as <b><span style="font-family:courier;">SELECT provider, source, dest, rate FROM cy(&#8216;USD&#8217;, &#8216;IDR&#8217;)</span></b>.</div>
<div style="margin-top:5mm;">
<ul>
<li style="margin-top:2mm;">I download <a href="http://www.cs.fsu.edu/~engelen/soap.html">gSOAP</a> on my Ubuntu Laptop. Build and install it into <b><span style="font-family:courier;">/opt/gsoap</span></b> directory.</li>
<li style="margin-top:2mm;">Use gSOAP <b><span style="font-family:courier;">wsdl2h</span></b> to obtain the gSOAP header file <b><span style="font-family:courier;">cy.h</span></b> specification of the web service&#8217;s WSDL document:
<div style="background-color:#f0f0f0;font-family:courier;font-size:10pt;margin-right:50px;">/opt/gsoap/bin/wsdl2h -c -o cy.h http://www.currencyserver.de/webservice/currencyserverwebservice.asmx?WSDL</div>
</li>
<li style="margin-top:2mm;">Generate a bunch of source, header, xml and nsmap files based on <b><span style="font-family:courier;">cy.h</span></b> header file:
<div style="background-color:#f0f0f0;font-family:courier;font-size:10pt;margin-right:50px;">/opt/gsoap/bin/soapcpp2 -1 -c -C -pcy cy.h</div>
</li>
<li style="margin-top:2mm;">Copy <b><span style="font-family:courier;">stdsoap2.c</span></b> from gSOAP source code distribution into current work directory.</li>
<li style="margin-top:2mm;">Create C source code <b><span style="font-family:courier;">cy.c</span></b> for PostgreSQL User Defined Functions with Version 1 Calling Conventions:
<div style="background-color:#f0f0f0;font-family:courier;font-size:10pt;margin-right:50px;">
#include &lt;postgres.h&gt;<br />
#include &lt;fmgr.h&gt;<br />
#ifdef PG_MODULE_MAGIC<br />
PG_MODULE_MAGIC;<br />
#endif</p>
<p>#include &lt;utils/builtins.h&gt;<br />
#include &lt;funcapi.h&gt;<br />
#include &#8220;cyH.h&#8221;<br />
#include &#8220;CurrencyServerWebServiceSoap.nsmap&#8221;</p>
<p>PG_FUNCTION_INFO_V1(cy);<br />
Datum cy(PG_FUNCTION_ARGS);</p>
<p>void errExit(struct soap* soap);<br />
void cleanExit(struct soap* soap);<br />
struct cyData{ struct soap* soap; char** provList; };</p>
<p>Datum cy(PG_FUNCTION_ARGS) {</p>
<div style="margin-left:25px;">
	struct FuncCallContext* funcctx;<br />
	TupleDesc tupdesc;</p>
<p>	if (SRF_IS_FIRSTCALL()) {</p>
<div style="margin-left:50px;">
		MemoryContext oldcontext;<br />
		funcctx = SRF_FIRSTCALL_INIT();<br />
        	oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);<br />
		if(get_call_result_type(fcinfo, NULL, &amp;tupdesc) != TYPEFUNC_COMPOSITE) {</p>
<div style="margin-left:75px;">
			ereport(ERROR,</p>
<div style="margin-left:100px;">
				(	errcode(ERRCODE_FEATURE_NOT_SUPPORTED),<br />
					errmsg(&#8220;function returning record called in context &#8220;<br />
		                            &#8220;that cannot accept type record&#8221;)<br />
				)
</div>
<p>			);
</p></div>
<p>		}<br />
		funcctx-&gt;tuple_desc=BlessTupleDesc(tupdesc);<br />
		if(PG_NARGS()!=2)</p>
<div style="margin-left:75px;">
			elog(ERROR, &#8220;argument count must be %d&#8221;, 2);
</div>
<p>		struct cyData* pData=(struct cyData*)palloc(sizeof(struct cyData));<br />
		pData-&gt;soap=soap_new();<br />
		struct _ns1__getProviderList reqProvList;<br />
		struct _ns1__getProviderListResponse respProvList;<br />
		soap_default__ns1__getProviderList(pData-&gt;soap, &amp;reqProvList);<br />
		soap_default__ns1__getProviderListResponse(pData-&gt;soap, &amp;respProvList);<br />
		if(soap_call___ns2__getProviderList(pData-&gt;soap, NULL, NULL, &amp;reqProvList, &amp;respProvList)){</p>
<div style="margin-left:75px;">
			errExit(pData-&gt;soap);
</div>
<p>		}<br />
		char* delim=&#8221;, &#8220;;<br />
		char* ch=strtok(respProvList.getProviderListResult,delim);<br />
		int count=0;<br />
		while(ch){</p>
<div style="margin-left:75px;">
			pData-&gt;provList= count==0 ? (char**)palloc(++count*sizeof(char*))<br />
				: (char**)repalloc(pData-&gt;provList, ++count*sizeof(char*));<br />
			pData-&gt;provList[count-1]=pstrdup(ch);<br />
			ch=strtok(NULL,delim);
</div>
<p>		}<br />
		funcctx-&gt;max_calls=count;<br />
		funcctx-&gt;user_fctx=(void*)pData;</p>
<p>        	MemoryContextSwitchTo(oldcontext);
</div>
<p>	}</p>
<p>	funcctx = SRF_PERCALL_SETUP();</p>
<p>	if (funcctx-&gt;call_cntr max_calls) {</p>
<div style="margin-left:50px;">
		Datum result;<br />
		HeapTuple tuple;<br />
		bool isnull[]={false,false,false,false};</p>
<p>		struct cyData* pData=(struct cyData*)funcctx-&gt;user_fctx;</p>
<p>		struct _ns1__getCurrencyValue req;<br />
		struct _ns1__getCurrencyValueResponse resp;<br />
		soap_default__ns1__getCurrencyValue(pData-&gt;soap, &amp;req);</p>
<p>		req.provider=pData-&gt;provList[funcctx-&gt;call_cntr];<br />
		req.srcCurrency=TextDatumGetCString(PG_GETARG_DATUM(0));<br />
		req.dstCurrency=TextDatumGetCString(PG_GETARG_DATUM(1));<br />
		if(soap_call___ns2__getCurrencyValue(pData-&gt;soap, NULL, NULL, &amp;req, &amp;resp)){</p>
<div style="margin-left:75px;">
			errExit(pData-&gt;soap);
</div>
<p>		}<br />
		Datum values[]={</p>
<div style="margin-left:75px;">
			DirectFunctionCall1(textin, CStringGetDatum(pData-&gt;provList[funcctx-&gt;call_cntr])),<br />
			PG_GETARG_DATUM(0),<br />
			PG_GETARG_DATUM(1),<br />
			DirectFunctionCall1(float8_numeric, Float8GetDatum(resp.getCurrencyValueResult))
</div>
<p>		};</p>
<p>		tuple=heap_form_tuple(funcctx-&gt;tuple_desc, values, isnull);<br />
		result = HeapTupleGetDatum(tuple);</p>
<p>		SRF_RETURN_NEXT(funcctx, result);
</p></div>
<p>	} else {</p>
<div style="margin-left:50px;">
		struct cyData* pData=(struct cyData*)funcctx-&gt;user_fctx;<br />
		cleanExit(pData-&gt;soap);<br />
		SRF_RETURN_DONE(funcctx);
</div>
<p>	}
</div>
<p>}</p>
<p>void errExit(struct soap* soap) {</p>
<div style="margin-left:50px;">
	char buf[201]=&#8221;";<br />
	soap_sprint_fault(soap, buf, 200);<br />
	cleanExit(soap);<br />
	elog(ERROR, &#8220;%s&#8221;, buf);
</div>
<p>}</p>
<p>void cleanExit(struct soap* soap) {</p>
<div style="margin-left:50px;">
	soap_end(soap);<br />
	soap_free(soap);
</div>
<p>}
</div>
</li>
<li style="margin-top:2mm;">Create SQL skeleton for User Defined Functions <b><span style="font-family:courier;">cy.sql.in</span></b>:
<div style="background-color:#f0f0f0;font-family:courier;font-size:10pt;margin-right:50px;">
CREATE OR REPLACE FUNCTION cy(OUT provider text, INOUT source text, INOUT dest text, OUT rate numeric)<br />
RETURNS SETOF record<br />
AS &#8216;MODULE_PATHNAME&#8217;, &#8216;cy&#8217;  LANGUAGE C IMMUTABLE STRICT;<br />
GRANT EXECUTE ON FUNCTION cy(text, text) TO public;
</div>
</li>
<li style="margin-top:2mm;">Create <b><span style="font-family:courier;">Makefile</span></b> to comply with PostgreSQL build infrastructure for extensions (called PGXS):
<div style="background-color:#f0f0f0;font-family:courier;font-size:10pt;margin-right:50px;">
MODULE_big = cy<br />
OBJS = stdsoap2.o cyC.o cyClient.o cy.o<br />
DATA_built = cy.sql<br />
PG_CONFIG = /opt/pgsql/bin/pg_config<br />
PG_CPPFLAGS = -I/opt/gsoap/include<br />
PGXS := $(shell $(PG_CONFIG) &#8211;pgxs)<br />
include $(PGXS)
</div>
<p>Plase take note that my PostgreSQL resides in <b><span style="font-family:courier;">/opt/pgsql</span></b>.
</li>
<li style="margin-top:2mm;">Build and install everything:
<div style="background-color:#505050;color:white;font-family:monospace;font-size:10pt;margin-right:50px;">
abdul@mylaptop:~/wsdl/cy$ make<br />
abdul@mylaptop:~/wsdl/cy$ sudo make install<br />
abdul@mylaptop:~/wsdl/cy$ /opt/pgsql/bin/psql -U admin -h localhost -p 5432 -d test -f cy.sql
</div>
</li>
<li style="margin-top:2mm;">Login to database server:
<div style="background-color:#505050;color:white;font-family:monospace;font-size:10pt;margin-right:50px;">
abdul@mylaptop:~/wsdl/cy$ /opt/pgsql/bin/psql -U slony -h localhost -p 5432 test<br />
Password for user slony: <br />
psql (9.0.4)<br />
Type &#8220;help&#8221; for help.</p>
<p>test=#
</p></div>
</li>
<li style="margin-top:2mm;">Check my currency rate&#8230;
<div style="background-color:#505050;color:white;font-family:monospace;font-size:10pt;margin-right:50px;">
test=# SELECT * FROM cy(&#8216;USD&#8217;,'IDR&#8217;);<br />
 provider | source | dest |    rate    <br />
&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;<br />
 3        | USD    | IDR  | 9094.34819<br />
 4        | USD    | IDR  |     9087.5<br />
 AVERAGE  | USD    | IDR  | 9090.92409<br />
(3 rows)</p>
<p>test=# SELECT * FROM cy(&#8216;EUR&#8217;,'IDR&#8217;);<br />
 provider | source | dest |       rate   <br /> <br />
&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
 3        | EUR    | IDR  | 12020.0213983611<br />
 4        | EUR    | IDR  | 11993.8496462887<br />
 AVERAGE  | EUR    | IDR  | 12006.9261827403<br />
(3 rows)</p>
<p>test=# SELECT * FROM cy(&#8216;SGD&#8217;,'IDR&#8217;);<br />
 provider | source | dest |       rate      <br /> <br />
&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
 3        | SGD    | IDR  | 7272.91848469339<br />
 4        | SGD    | IDR  | 7257.45911065679<br />
 AVERAGE  | SGD    | IDR  | 7265.18348117957<br />
(3 rows)</p>
<p>test=#
</p></div>
<div style="margin-top:2mm;font-size:14pt;font-weight:bold;">Hi, it comes from the Public Web Service thousands miles away from my house, not from my database.</div>
</li>
</ul>
</div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/abdulyadi.wordpress.com/174/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/abdulyadi.wordpress.com/174/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/abdulyadi.wordpress.com/174/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/abdulyadi.wordpress.com/174/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/abdulyadi.wordpress.com/174/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/abdulyadi.wordpress.com/174/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/abdulyadi.wordpress.com/174/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/abdulyadi.wordpress.com/174/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/abdulyadi.wordpress.com/174/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/abdulyadi.wordpress.com/174/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/abdulyadi.wordpress.com/174/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/abdulyadi.wordpress.com/174/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/abdulyadi.wordpress.com/174/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/abdulyadi.wordpress.com/174/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=174&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://abdulyadi.wordpress.com/2012/03/03/consume-soap-web-service-from-postgresql-user-defined-function-in-c/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">abdulyadi</media:title>
		</media:content>

		<media:content url="http://abdulyadi.files.wordpress.com/2012/03/pipit1.jpg" medium="image">
			<media:title type="html">f.y.h</media:title>
		</media:content>
	</item>
		<item>
		<title>Detect Inactive Slony Node</title>
		<link>http://abdulyadi.wordpress.com/2011/07/18/detect-inactive-slony-node/</link>
		<comments>http://abdulyadi.wordpress.com/2011/07/18/detect-inactive-slony-node/#comments</comments>
		<pubDate>Mon, 18 Jul 2011 07:01:53 +0000</pubDate>
		<dc:creator>abdulyadi</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://abdulyadi.wordpress.com/?p=162</guid>
		<description><![CDATA[One concern in implementing Slony as PostgreSQL Replication System is that table sl_event easily growing to a huge number of record. So, I keep monitor its size on weekly basis. Its size ever reaches more than a million record. After doing some troubleshoot, I have found that it is caused by some inactive replication node [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=162&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>One concern in implementing Slony as PostgreSQL Replication System is that table <strong>sl_event</strong> easily growing to a huge number of record. So, I keep monitor its size on weekly basis. Its size ever reaches more than a million record.</p>
<p>After doing some troubleshoot, I have found that it is caused by some inactive replication node which does not confirm the changes message conveyed by the event. By re-activating slony daemon on the nodes, the problem goes away.</p>
<p>How to find out which nodes inactive? This is my query (assuimng the slony cluster name is <strong>clstr</strong>):</p>
<div style="font-family:courier;background-color:#efefef;">
SELECT t.con_received, t.ts FROM (<br />
    SELECT con_received, MAX(con_timestamp) ts<br />
    FROM    <strong>_clstr.</strong>sl_confirm GROUP BY con_received<br />
) t ORDER BY t.ts;
</div>
<p>
Following is example of the query outcome:<br />
 con_received |             ts<br />
&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
           24 | 2011-07-11 08:49:18.004292<br />
           26 | 2011-07-18 05:59:33.483955<br />
           30 | 2011-07-18 10:31:55.235895<br />
           31 | 2011-07-18 12:26:35.889352<br />
           22 | 2011-07-18 12:27:02.932156<br />
           21 | 2011-07-18 12:27:21.21836<br />
           15 | 2011-07-18 12:27:23.298656<br />
           18 | 2011-07-18 12:27:23.701799<br />
           17 | 2011-07-18 12:27:27.052192<br />
           28 | 2011-07-18 13:43:19.826342<br />
           11 | 2011-07-18 13:58:25.891667<br />
            1 | 2011-07-18 13:58:37.566528<br />
           29 | 2011-07-18 13:58:47.321221<br />
           16 | 2011-07-18 14:01:08.206147<br />
           13 | 2011-07-18 14:01:10.92797<br />
           19 | 2011-07-18 14:02:02.476146<br />
           14 | 2011-07-18 14:02:02.51104<br />
           20 | 2011-07-18 14:02:05.63391<br />
           27 | 2011-07-18 14:14:55.750242<br />
<br />
It tells us that node 24 has been inactive for 7 days relative to other nodes.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/abdulyadi.wordpress.com/162/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/abdulyadi.wordpress.com/162/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/abdulyadi.wordpress.com/162/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/abdulyadi.wordpress.com/162/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/abdulyadi.wordpress.com/162/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/abdulyadi.wordpress.com/162/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/abdulyadi.wordpress.com/162/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/abdulyadi.wordpress.com/162/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/abdulyadi.wordpress.com/162/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/abdulyadi.wordpress.com/162/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/abdulyadi.wordpress.com/162/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/abdulyadi.wordpress.com/162/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/abdulyadi.wordpress.com/162/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/abdulyadi.wordpress.com/162/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=162&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://abdulyadi.wordpress.com/2011/07/18/detect-inactive-slony-node/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">abdulyadi</media:title>
		</media:content>
	</item>
		<item>
		<title>Transfer Binary from Photo File to Database Table</title>
		<link>http://abdulyadi.wordpress.com/2010/12/25/transfer-binary-from-photo-file-to-database-table/</link>
		<comments>http://abdulyadi.wordpress.com/2010/12/25/transfer-binary-from-photo-file-to-database-table/#comments</comments>
		<pubDate>Sat, 25 Dec 2010 11:11:02 +0000</pubDate>
		<dc:creator>abdulyadi</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://abdulyadi.wordpress.com/?p=144</guid>
		<description><![CDATA[In many web application, personal photo is saved as [*.jpg] file in a folder in server&#8217;s disk. The relation with personal ID in database is established by set the filename accordingly in format: nnnnn.jpg, e.g: 00001.jpg, 00002.jpg and so on. Once upon a time, I was in charge to move content of photo file into [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=144&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<div>In many web application, personal photo is saved as [*.jpg] file in a folder in server&#8217;s disk. The relation with personal ID in database is established by set the filename accordingly in format: <b>nnnnn.jpg</b>, e.g: <b>00001.jpg</b>, <b>00002.jpg</b> and so on.</div>
<div style="margin-top:5px;">Once upon a time, I was in charge to move content of photo file into database&#8217;s field, integrated with personal identity table. All works in Linux environment and PostgreSQL 9.0.</div>
<div style="margin-top:5px;">I want to share the story&#8230;.</div>
<div style="margin-top:5px;">Original setting: photo file is saved in folder: <b>/home/webuser/photo/</b> and person table resides in <b>persondb</b> database with DDL as follows:</p>
<div style="font-family:courier;font-size:9pt;background-color:#f0f0f0;">
<div>CREATE TABLE person</div>
<div>(</div>
<div style="margin-left:2em;">id serial NOT NULL,</div>
<div style="margin-left:2em;">fullname text NOT NULL,</div>
<div style="margin-left:2em;">addres text NOT NULL,</div>
<div style="margin-left:2em;">CONSTRAINT &#8220;person: id must be unique&#8221; PRIMARY KEY (id)</div>
<div>) WITH (OIDS=FALSE);</div>
</p></div>
<p>	The table has been populated with hundreds of person records.
</p></div>
<div style="margin-top:10px;"><b>Part 1: Alter Table</b></div>
<div>Add a field to store photo bytearray:</p>
<div style="font-family:courier;font-size:9pt;background-color:#f0f0f0;">ALTER TABLE person ADD COLUMN photo bytea;</div>
</div>
<div style="margin-top:10px;"><b>Part 2: Create C Source Code</b></div>
<div>Create <b>person.c</b>:</p>
<div style="font-family:courier;font-size:9pt;background-color:#f0f0f0;">
<div>#include &lt;postgres.h&gt;</div>
<div>#include &lt;fmgr.h&gt;</div>
<div>#ifdef PG_MODULE_MAGIC</div>
<div style="margin-left:2em;">PG_MODULE_MAGIC;</div>
<div>#endif</div>
<div>#include &lt;lib/stringinfo.h&gt;</div>
<div>#include &lt;executor/spi.h&gt;</div>
<div>#include &lt;catalog/pg_type.h&gt;</div>
<div>#include &lt;utils/builtins.h&gt;</div>
<div>#include &lt;utils/bytea.h&gt;</div>
<div>#include &lt;catalog/pg_type.h&gt;</div>
<p></p>
<div>PG_FUNCTION_INFO_V1(person_photo);</div>
<div>Datum person_photo(PG_FUNCTION_ARGS);</div>
<p></p>
<div>Datum</div>
<div>person_photo(PG_FUNCTION_ARGS)</div>
<div>{</div>
<div style="margin-left:2em;">int32 personId;</div>
<div style="margin-left:2em;">StringInfoData photoFile;</div>
<div style="margin-left:2em;">StringInfoData photoBytea;</div>
<div style="margin-left:2em;">const char* PHOTO_PATH=&#8221;/home/webuser/photo/&#8221;;</div>
<div style="margin-left:2em;">const char* PHOTO_EXT=&#8221;jpg&#8221;;</div>
<div style="margin-left:2em;">FILE* f;</div>
<div style="margin-left:2em;">const size_t BUFFER_SIZE=5*1024;</div>
<div style="margin-left:2em;">char buf[BUFFER_SIZE];</div>
<div style="margin-left:2em;">size_t byteReadCount;</div>
<div style="margin-left:2em;">const int32 SQL_PARAM_COUNT=2;</div>
<div style="margin-left:2em;">Oid argTypes[SQL_PARAM_COUNT];</div>
<div style="margin-left:2em;">Datum vals[SQL_PARAM_COUNT];</div>
<p>
		////get function argument:BEGIN</p>
<div style="margin-left:2em;">if(PG_ARGISNULL(0)) {</div>
<div style="margin-left:4em;">elog(ERROR,&#8221;person id can not be NULL&#8221;);</div>
<div style="margin-left:2em;">i}</div>
<div style="margin-left:2em;">personId=PG_GETARG_INT32(0);</div>
<p>		////get function argument:END</p>
<p>		////read photo file:BEGIN			</p>
<div style="margin-left:2em;">photoBytea.data=0;</div>
<div style="margin-left:2em;">photoBytea.len=0;</div>
<div style="margin-left:2em;">initStringInfo(&amp;photoFile);</div>
<div style="margin-left:2em;">appendStringInfo(&amp;photoFile, &#8220;%s%05d.%s&#8221;, PHOTO_PATH, personId, PHOTO_EXT);</div>
<div style="margin-left:2em;">f=fopen(photoFile.data, &#8220;rb&#8221;);//open photo file</div>
<div style="margin-left:2em;">pfree(photoFile.data);</div>
<div style="margin-left:2em;">if(f){</div>
<div style="margin-left:4em;">initStringInfo(&amp;photoBytea);</div>
<div style="margin-left:4em;">while(!feof(f)){//keep reading until end of file</div>
<div style="margin-left:6em;">byteReadCount=fread(buf, 1, BUFFER_SIZE, f);</div>
<div style="margin-left:6em;">appendBinaryStringInfo(&amp;photoBytea, buf, byteReadCount);</div>
<div style="margin-left:4em;">}</div>
<div style="margin-left:4em;">fclose(f);</div>
<div style="margin-left:2em;">} else {</div>
<div style="margin-left:4em;">elog(NOTICE, &#8220;person with id %d does not have photo&#8221;, personId);</div>
<div style="margin-left:2em;">}</div>
<p>		////read photo file:END</p>
<p>		////save to database:BEGIN</p>
<div style="margin-left:2em;">if(photoBytea.len){</div>
<div style="margin-left:4em;">SPI_connect();</div>
<p></p>
<div style="margin-left:4em;">argTypes[0]=INT4OID;</div>
<div style="margin-left:4em;">argTypes[1]=BYTEAOID;</div>
<div style="margin-left:4em;">vals[0]=Int32GetDatum(personId);</div>
<div style="margin-left:4em;">vals[1]=DirectFunctionCall1(bytearecv, PointerGetDatum(&amp;photoBytea));</div>
<p></p>
<div style="margin-left:4em;">SPI_execute_with_args(&#8220;UPDATE person SET photo=$2 WHERE id=$1&#8243;, </div>
<div style="margin-left:6em;">SQL_PARAM_COUNT, argTypes, vals, NULL, FALSE, 1);</div>
<p></p>
<div style="margin-left:4em;">SPI_finish();</div>
<div style="margin-left:2em;">}</div>
<div style="margin-left:2em;">if(photoBytea.data){</div>
<div style="margin-left:4em;">pfree(photoBytea.data);</div>
<div style="margin-left:2em;">}</div>
<p>		////save to database:END</p>
<div style="margin-left:2em;">PG_RETURN_VOID();</div>
<div>}</div>
</p></div>
</div>
<div style="margin-top:10px;"><b>Part 3: Create SQL to Install Our Custom Library</b></div>
<div>Create <b>person.sql.in</b> in the same folder as <b>person.c</b>:</p>
<div style="font-family:courier;font-size:9pt;background-color:#f0f0f0;">
<div>CREATE OR REPLACE FUNCTION person_photo(person_id integer)</div>
<div>RETURNS VOID</div>
<div>AS &#8216;MODULE_PATHNAME&#8217; LANGUAGE C VOLATILE;</div>
</p></div>
</div>
<div style="margin-top:10px;"><b>Part 4: Create Makefile</b></div>
<div>Create <b>Makefile</b> in the same folder as <b>person.c</b>:</p>
<div style="font-family:courier;font-size:9pt;background-color:#f0f0f0;">
<div>MODULE_big = person</div>
<div>OBJS = person.o</div>
<div>DATA_built = person.sql</div>
<p></p>
<div>PG_CPPFLAGS := $(shell pg_config &#8211;includedir-server)</div>
<p></p>
<div>PGXS := $(shell pg_config &#8211;pgxs)</div>
<div>include $(PGXS)</div>
</p></div>
</div>
<div style="margin-top:10px;"><b>Part 5: Compile and Install</b></div>
<div>In the same folder as <b>Makefile</b>, run command <b>make</b> then <b>make install</b>. Make sure we have sufficient privilege to create file in PostgreSQL contrib and library folder. If everything goes fine then we will have two files:</p>
<ol>
<li>SQL file <b>person.sql</b> in PostgreSQL contrib directory.</li>
<li>Library file <b>person.so</b> in PostgreSQL library directory.</li>
</ol>
</div>
<div style="margin-top:10px;"><b>Part 6: Install Stored Procedure</b></div>
<div>Assuming we are in the same folder as <b>person.sql</b> and want to install stored procedure in <b>persondb</b> database (where table <b>person</b> exists) at host <b>server1</b>:</p>
<div style="font-family:courier;font-size:9pt;background-color:#f0f0f0;">
<div>psql -U postgres -h server1 -f person.sql -d persondb</div>
</p></div>
</div>
<div style="margin-top:10px;"><b>Part 7: Move Photo From File to Table</b></div>
<div>All preparation has been set. It is time to login to PostgreSQL server and run the stored procedure (make sure folder <b>/home/webuser/photo/</b> is accessible by postgres user):</p>
<div style="font-family:courier;font-size:9pt;background-color:#f0f0f0;">
<div>psql -U postgres -h server1 persondb</div>
<div>Password for user postgres:<b>[your password]</b></div>
<div>postgres=#<b>SELECT person_photo(id) FROM person;</b></div>
</p></div>
<p>	Wait a moment, let PostgreSQL read photo files and store the binaries into field <b>photo</b>.
</div>
<div style="margin-top:10px;">My story ends&#8230;.</div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/abdulyadi.wordpress.com/144/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/abdulyadi.wordpress.com/144/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/abdulyadi.wordpress.com/144/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/abdulyadi.wordpress.com/144/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/abdulyadi.wordpress.com/144/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/abdulyadi.wordpress.com/144/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/abdulyadi.wordpress.com/144/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/abdulyadi.wordpress.com/144/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/abdulyadi.wordpress.com/144/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/abdulyadi.wordpress.com/144/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/abdulyadi.wordpress.com/144/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/abdulyadi.wordpress.com/144/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/abdulyadi.wordpress.com/144/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/abdulyadi.wordpress.com/144/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=144&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://abdulyadi.wordpress.com/2010/12/25/transfer-binary-from-photo-file-to-database-table/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">abdulyadi</media:title>
		</media:content>
	</item>
		<item>
		<title>PgPool II 3.0: bug fixes for md5 authentication</title>
		<link>http://abdulyadi.wordpress.com/2010/09/25/pgpool-ii-3-0-bug-fixes/</link>
		<comments>http://abdulyadi.wordpress.com/2010/09/25/pgpool-ii-3-0-bug-fixes/#comments</comments>
		<pubDate>Sat, 25 Sep 2010 07:39:12 +0000</pubDate>
		<dc:creator>abdulyadi</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://abdulyadi.wordpress.com/?p=119</guid>
		<description><![CDATA[I have problem with PgPool II 3.0. I have downloaded the source code from http://pgfoundry.org/projects/pgpool. Extract and compile it successfully. Configure it just to have connection pooling enabled (other features: Replication, LoadBalance, Parallel Query are disabled). But, I can not connect to PostgreSQL 9.0 via PgPool port at 9999 with authentication mode set to md5 [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=119&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<div style="font-size:8.5pt;">
<div>I have problem with PgPool II 3.0. I have downloaded the source code from <a href="http://pgfoundry.org/projects/pgpool">http://pgfoundry.org/projects/pgpool</a>. Extract and compile it successfully. Configure it just to have connection pooling enabled (other features: Replication, LoadBalance, Parallel Query are disabled). But, I can not connect to PostgreSQL 9.0 via PgPool port at 9999 with authentication mode set to md5 in pg_hba.conf (pool_hba.conf is disabled).</div>
<p><div>After take some time to trace the source code, I have found bug in file <span style="font-family:courier;">pool_auth.c</span>. Inside function:</p>
<div style="font-family:courier;">static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor)</div>
<div>variable <span style="font-family:courier;">int size</span> is declared but it never have the length of password.</div>
<p><div>4 steps to fix the problem:</div>
<ol>
<li>Modify forward declaration of function <span style="font-family:courier;">int read_password_packet(&#8230;)</span>, add <span style="font-family:courier;">int *pwdSize</span> as the fourth argument:
<div style="font-family:courier;background-color:#f0f0f0;">
<div>//static int read_password_packet(POOL_CONNECTION *frontend, int protoMajor, 	char *password);</div>
<div style="color:red;">static int read_password_packet(POOL_CONNECTION *frontend, int protoMajor, 	char *password, <b>int *pwdSize</b>);</div>
</p></div>
<li>Modify function body of function <span style="font-family:courier;">int read_password_packet(&#8230;)</span>. Watch that *pwdSize has the password length at the end of the function body:
<div style="font-family:courier;background-color:#f0f0f0;">
<div>/*</div>
<div>* Read password packet from frontend</div>
<div>*/</div>
<div>//static int read_password_packet(POOL_CONNECTION *frontend, int protoMajor, 	char *password)</div>
<div style="color:red;">static int read_password_packet(POOL_CONNECTION *frontend, int protoMajor, 	char *password, <b>int *pwdSize</b>)</div>
<div>{</div>
<div>&nbsp;&nbsp;int size;</div>
<div>&nbsp;&nbsp;/* Read password packet */</div>
<div>&nbsp;&nbsp;if (protoMajor == PROTO_MAJOR_V2)</div>
<div>&nbsp;&nbsp;{</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;if (pool_read(frontend, &amp;size, sizeof(size)))</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;{</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pool_error(&#8220;read_password_packet: failed to read password packet size&#8221;);</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return -1;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;}</div>
<div>&nbsp;&nbsp;}</div>
<div>&nbsp;&nbsp;else</div>
<div>&nbsp;&nbsp;{</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;char k;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;if (pool_read(frontend, &amp;k, sizeof(k)))</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;{</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pool_debug(&#8220;read_password_packet_password: failed to read password packet \&#8221;p\&#8221;");</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return -1;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;}</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;if (k != &#8216;p&#8217;)</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;{</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pool_error(&#8220;read_password_packet_password: password packet does not start with \&#8221;p\&#8221;");</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return -1;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;}</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;if (pool_read(frontend, &amp;size, sizeof(size)))</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;{</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pool_error(&#8220;read_password_packet_password: failed to read password packet size&#8221;);</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return -1;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;}</div>
<div>&nbsp;&nbsp;}</div>
<div>&nbsp;&nbsp;if (pool_read(frontend, password, ntohl(size) &#8211; 4))</div>
<div>&nbsp;&nbsp;{</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pool_error(&#8220;read_password_packet: failed to read password (size: %d)&#8221;, ntohl(size) &#8211; 4);</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return -1;</div>
<div>&nbsp;&nbsp;}</div>
<div>&nbsp;&nbsp;<span style="font-weight:bold;color:red;">*pwdSize=size;</span> //now *pwdSize has password length</div>
<div>&nbsp;&nbsp;return 0;</div>
<div>}</div>
</p></div>
<li>Inside function
<div style="font-family:courier;">static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor)</div>
<div>add <span style="font-family:courier;">&amp;size</span> as fourth argument to every <span style="font-family:courier;">read_password_packet</span> function call, for example:</p>
<div style="font-family:courier;">read_password_packet(frontend, protoMajor, password, <span style="font-weight:bold;color:red;">&amp;size</span>)</div>
<li>Recompile and reinstall pgpool project.
</ol>
<p>Done. Now. I can login to PostgreSQL 9.0 smoothly through PgPool port: 9999.
</p></div>
</div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/abdulyadi.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/abdulyadi.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/abdulyadi.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/abdulyadi.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/abdulyadi.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/abdulyadi.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/abdulyadi.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/abdulyadi.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/abdulyadi.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/abdulyadi.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/abdulyadi.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/abdulyadi.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/abdulyadi.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/abdulyadi.wordpress.com/119/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=119&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://abdulyadi.wordpress.com/2010/09/25/pgpool-ii-3-0-bug-fixes/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">abdulyadi</media:title>
		</media:content>
	</item>
		<item>
		<title>dbi-link: fix error on insert/update/delete into/from remote mysql table</title>
		<link>http://abdulyadi.wordpress.com/2010/07/28/dbi-link-fix-error-on-insertupdatedelete-intofrom-remote-mysql-table/</link>
		<comments>http://abdulyadi.wordpress.com/2010/07/28/dbi-link-fix-error-on-insertupdatedelete-intofrom-remote-mysql-table/#comments</comments>
		<pubDate>Wed, 28 Jul 2010 02:33:58 +0000</pubDate>
		<dc:creator>abdulyadi</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://abdulyadi.wordpress.com/?p=112</guid>
		<description><![CDATA[I have installed dbi-link version 2.0.0 into my PostgreSQL 8.4 environment. The purpose is to query or modify remote mysql table from within postgresql user-defined-function. And whenever I try to insert/update/delete record into/from remote mysql table, I consistently get error message: ERROR: error from Perl function &#8220;shadow_trigger_func&#8221;: Can&#8217;t call method &#8220;quote&#8221; on an undefined value [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=112&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<div style="font-family:arial;font-size:10pt;">I have installed dbi-link version 2.0.0 into my PostgreSQL 8.4 environment. The purpose is to query or modify remote mysql table from within postgresql user-defined-function. And whenever I try to insert/update/delete record into/from remote mysql table, I consistently get error message:
</div>
<div style="background-color:#f0f0f0;font-family:courier;font-size:10pt;margin-top:.5em;">
ERROR: error from Perl function &#8220;shadow_trigger_func&#8221;: Can&#8217;t call method &#8220;quote&#8221; on an undefined value at line 61
</div>
<div style="font-family:arial;font-size:10pt;margin-top:.5em;">
So i go to the mentioned function and found out sub functions: <span style="font-family:courier;font-size:11pt;font-weight:bold;">make_pairs</span>, <span style="font-family:courier;font-weight:bold;">do_insert</span>, <span style="font-family:courier;font-weight:bold;">do_update</span> and <span style="font-family:courier;font-weight:bold;">do_delete</span> try to access variables: <span style="font-family:courier;font-weight:bold;">$data_source_id</span> and <span style="font-family:courier;font-weight:bold;">$table</span> which are declared locally in main function.
</div>
<div style="font-family:arial;font-size:10pt;margin-top:.5em;">
Knowing that problem, I have modified parameter passing as follows:
</div>
<p><div style="font-family:arial;font-size:10pt;margin-top:.5em;">
Within <b>main</b> function:
</div>
<div style="background-color:#f0f0f0;font-family:courier;font-size:10pt;margin-top:.5em;">
&#8230;<br />
if ($iud-&gt;{ $_TD-&gt;{new}{iud_action} }) {<br />
&nbsp;&nbsp;&nbsp;$iud-&gt;{ $_TD-&gt;{new}{iud_action} }-&gt;({<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;payload =&gt; $_TD-&gt;{new},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b><span style="color:red;">tbl =&gt; $table,</span></b><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b><span style="color:red;">source_id =&gt; $data_source_id</span></b><br />
&nbsp;&nbsp;&nbsp;});<br />
}<br />
else {<br />
&nbsp;&nbsp;&nbsp;die &#8220;Trigger event was $_TD-&gt;{new}{iud_action}&lt;, but should have been one of I, U or D!&quot;<br />
}<br />
&#8230;
</div>
<div style="font-family:arial;font-size:10pt;margin-top:.5em;">
And inside sub functions: modify <b>$table</b> and <b>$data_source_id</b> into <b>$params-&gt;{tbl}</b> and <b>$params-&gt;{source_id}</b>, respectively.
</div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/abdulyadi.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/abdulyadi.wordpress.com/112/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/abdulyadi.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/abdulyadi.wordpress.com/112/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/abdulyadi.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/abdulyadi.wordpress.com/112/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/abdulyadi.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/abdulyadi.wordpress.com/112/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/abdulyadi.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/abdulyadi.wordpress.com/112/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/abdulyadi.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/abdulyadi.wordpress.com/112/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/abdulyadi.wordpress.com/112/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/abdulyadi.wordpress.com/112/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=112&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://abdulyadi.wordpress.com/2010/07/28/dbi-link-fix-error-on-insertupdatedelete-intofrom-remote-mysql-table/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">abdulyadi</media:title>
		</media:content>
	</item>
		<item>
		<title>Integrated Networks for Educational Research</title>
		<link>http://abdulyadi.wordpress.com/2010/05/24/integrated-networks-for-eduactional-research/</link>
		<comments>http://abdulyadi.wordpress.com/2010/05/24/integrated-networks-for-eduactional-research/#comments</comments>
		<pubDate>Mon, 24 May 2010 15:13:31 +0000</pubDate>
		<dc:creator>abdulyadi</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://abdulyadi.wordpress.com/?p=106</guid>
		<description><![CDATA[Linux Community at Batam, Indonesia has launched a web application dedicated for educational research by Indonesian teachers. We call it INFER: Integrated Networks For Educational Research (http://infer.gelora-batam.org). It is a Rich Internet Application developed using Ext-GWT, deployed on Tomcat5 and backed by PostgreSQL 8.4 (for its CTE feature). Statistic Probability Density function is calculated within [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=106&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Linux Community at Batam, Indonesia has launched a web application dedicated for educational research by Indonesian teachers. We call it INFER: Integrated Networks For Educational Research (http://infer.gelora-batam.org). It is a Rich Internet Application developed using Ext-GWT, deployed on Tomcat5 and backed by <strong>PostgreSQL 8.4</strong> (for its CTE feature). Statistic Probability Density function is calculated within stored procedure written in C, to wrap library provided by GSL (GNU Scientific Library).</p>
<p>At this moment, the service provides analytical tools for: Correlation and One way Analyses Of Variance (ANOVA) study, as well as Exams Item Validation tool (as online alternative for ITEMAN.EXE by Assessments Systems Corporation).</p>
<p>The project will be continually enhanced by Batam Linux Community for more analytical tools.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/abdulyadi.wordpress.com/106/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/abdulyadi.wordpress.com/106/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/abdulyadi.wordpress.com/106/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/abdulyadi.wordpress.com/106/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/abdulyadi.wordpress.com/106/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/abdulyadi.wordpress.com/106/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/abdulyadi.wordpress.com/106/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/abdulyadi.wordpress.com/106/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/abdulyadi.wordpress.com/106/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/abdulyadi.wordpress.com/106/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/abdulyadi.wordpress.com/106/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/abdulyadi.wordpress.com/106/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/abdulyadi.wordpress.com/106/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/abdulyadi.wordpress.com/106/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=106&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://abdulyadi.wordpress.com/2010/05/24/integrated-networks-for-eduactional-research/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">abdulyadi</media:title>
		</media:content>
	</item>
		<item>
		<title>PLSQL for Curve Smoothing  </title>
		<link>http://abdulyadi.wordpress.com/2009/05/16/plsql-for-curve-smoothing/</link>
		<comments>http://abdulyadi.wordpress.com/2009/05/16/plsql-for-curve-smoothing/#comments</comments>
		<pubDate>Sat, 16 May 2009 03:39:19 +0000</pubDate>
		<dc:creator>abdulyadi</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://abdulyadi.wordpress.com/?p=62</guid>
		<description><![CDATA[In an engineering project, I have been assigned to a task constructing smooth curve for given sets of sample points. This is accomplished by implementing Cubic Splines and Thomas algorithm to solve linear algebraic equation. So, I write PLSQL stored procedure as follows: CREATE OR REPLACE FUNCTION spline( IN x_arr numeric[], IN y_arr numeric[], IN [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=62&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>In an engineering project, I have been assigned to a task constructing smooth curve for given sets of sample points. This is accomplished by implementing Cubic Splines and Thomas algorithm to solve linear algebraic equation. So, I write PLSQL stored procedure as follows:</p>
<div style="font-family:courier;font-size:8pt;background-color:#E0E0E0;">
CREATE OR REPLACE FUNCTION spline(<br />
	IN x_arr numeric[], IN y_arr numeric[], IN resolution numeric,<br />
	OUT xs numeric, OUT ys numeric)<br />
  RETURNS SETOF record AS<br />
$BODY$<br />
DECLARE<br />
&nbsp;&nbsp;x numeric[];<br />
&nbsp;&nbsp;y numeric[];<br />
&nbsp;&nbsp;e numeric[] DEFAULT &#8216;{}&#8217;::numeric[];<br />
&nbsp;&nbsp;f numeric[] DEFAULT &#8216;{}&#8217;::numeric[];<br />
&nbsp;&nbsp;g numeric[] DEFAULT &#8216;{}&#8217;::numeric[];<br />
&nbsp;&nbsp;r numeric[] DEFAULT &#8216;{}&#8217;::numeric[];<br />
&nbsp;&nbsp;f2 numeric[] DEFAULT &#8216;{}&#8217;::numeric[];<br />
&nbsp;&nbsp;count integer;<br />
&nbsp;&nbsp;i integer;<br />
&nbsp;&nbsp;j integer;<br />
&nbsp;&nbsp;idx integer;<br />
&nbsp;&nbsp;tmp numeric;<br />
BEGIN<br />
&nbsp;&nbsp;x:=x_arr;<br />
&nbsp;&nbsp;y:=y_arr;<br />
&nbsp;&nbsp;count:=ARRAY_UPPER(x,1);<br />
&nbsp;&nbsp;IF count&lt;3 THEN<br />
&nbsp;&nbsp;&nbsp;&nbsp;RAISE EXCEPTION &#8216;sample size must be &gt;=3&#8242;;<br />
&nbsp;&nbsp;END IF;<br />
&nbsp;&nbsp;IF ARRAY_UPPER(y,1)&lt;&gt;count THEN<br />
&nbsp;&nbsp;&nbsp;&nbsp;RAISE EXCEPTION &#8216;x and y array size must be identical&#8217;;<br />
&nbsp;&nbsp;END IF;</p>
<p>&#8212;&#8212;&#8211;sort x, ascendingly:<br />
&nbsp;&nbsp;FOR i IN 1..count-1 LOOP<br />
&nbsp;&nbsp;&nbsp;&nbsp;idx:=i+1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;FOR j IN i+2..count LOOP<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IF x[j]&lt;x[idx] THEN<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;idx:=j;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;END IF;<br />
&nbsp;&nbsp;&nbsp;&nbsp;END LOOP;<br />
&nbsp;&nbsp;&nbsp;&nbsp;IF x[idx]=x[i] THEN<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RAISE EXCEPTION &#8216;x values must be unique&#8217;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;ELSIF x[idx]&lt;x[i] THEN &#8211;swap<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmp=x[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x[i]=x[idx];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x[idx]=tmp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmp=y[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y[i]=y[idx];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y[idx]=tmp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;END IF;<br />
&nbsp;&nbsp;END LOOP;</p>
<p>&#8212;&#8212;&#8211;prepare variables for Thomas algorithm<br />
&nbsp;&nbsp;FOR i IN 1..count LOOP<br />
&nbsp;&nbsp;&nbsp;&nbsp;IF i=1 OR i=count THEN<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e:= e || 0.0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f:= f || 0.0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g:= g || 0.0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r:= r || 0.0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f2:=f2 || 0.0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CONTINUE;<br />
&nbsp;&nbsp;&nbsp;&nbsp;END IF;<br />
&nbsp;&nbsp;&nbsp;&nbsp;e:= e || x[i] &#8211; x[i-1];<br />
&nbsp;&nbsp;&nbsp;&nbsp;f:= f || 2*(x[i+1]-x[i-1]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;g:= g || x[i+1] &#8211; x[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;r:= r || ( (6/(x[i+1]-x[i])) * (y[i+1]-y[i]) )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ ( (6/(x[i]-x[i-1])) * (y[i-1]-y[i]) );<br />
&nbsp;&nbsp;&nbsp;&nbsp;f2:=f2 || 0.0;<br />
&nbsp;&nbsp;END LOOP;</p>
<p>&#8212;&#8212;&#8211;decomposition<br />
&nbsp;&nbsp;FOR i IN 2..count LOOP<br />
&nbsp;&nbsp;&nbsp;&nbsp;IF f[i-1]&lt;&gt;0 THEN<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e[i]:=e[i]/f[i-1];<br />
&nbsp;&nbsp;&nbsp;&nbsp;END IF;<br />
&nbsp;&nbsp;&nbsp;&nbsp;f[i]:=f[i]-(e[i]*g[i-1]);<br />
&nbsp;&nbsp;END LOOP;</p>
<p>&#8212;&#8212;&#8211;forward substitution<br />
&nbsp;&nbsp;FOR i IN 2..count LOOP<br />
&nbsp;&nbsp;&nbsp;&nbsp;r[i]:=r[i]-(e[i]*r[i-1]);<br />
&nbsp;&nbsp;END LOOP;</p>
<p>&#8212;&#8212;&#8211;backward substitution<br />
&nbsp;&nbsp;FOR i IN REVERSE count-1..1 LOOP<br />
&nbsp;&nbsp;&nbsp;&nbsp;IF f[i]&lt;&gt;0 THEN<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f2[i]:=(r[i] &#8211; (g[i]*f2[i+1])) / f[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;END IF;<br />
&nbsp;&nbsp;END LOOP;</p>
<p>&#8212;&#8212;&#8211;do interpolation<br />
&nbsp;&nbsp;FOR i IN 2..count LOOP<br />
&nbsp;&nbsp;&nbsp;&nbsp;xs:=x[i-1]-resolution;<br />
&nbsp;&nbsp;&nbsp;&nbsp;LOOP<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xs:=xs+resolution;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EXIT WHEN i=count AND xs&gt;x[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EXIT WHEN i=x[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ys:= ( (f2[i-1] * (x[i]-xs)^3)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ (f2[i] * (xs-x[i-1])^3)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;) / (6*(x[i]-x[i-1]));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ys:= ys +  (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(y[i-1]/(x[i]-x[i-1])) -<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(f2[i-1]*(x[i]-x[i-1])/6)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;) * (x[i]-xs);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ys:= ys + (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(y[i]/(x[i]-x[i-1])) -<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(f2[i]*(x[i]-x[i-1])/6)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;) * (xs-x[i-1]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RETURN NEXT;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EXIT WHEN xs&gt;=x[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;END LOOP;<br />
&nbsp;&nbsp;END LOOP;</p>
<p>&nbsp;&nbsp;RETURN;<br />
END;<br />
$BODY$<br />
  LANGUAGE &#8216;plpgsql&#8217; IMMUTABLE STRICT;
</p></div>
<p>The stored procedure takes 3 input arguments and 2 outs. <b>x_arr</b> and <b> y_arr</b> are sample points&#8217; <b>x</b> and <b>y</b>. With <b>resolution</b>, you can determine the resolution of smoothed curve&#8217;s <b>x</b>.</p>
<p>Output arguments: <b>xs</b> and <b>ys</b> contain the set of <b>x</b> and <b>y</b> of smoothed curve, respectively.</p>
<p>Let us use the function. At first, we have sample points:</p>
<table width="60%" border="0">
<tr>
<th width="10%" align="center">#</th>
<th width="45%" align="center">x</th>
<th width="45%" align="center">y</th>
</tr>
<tr>
<td align="center">1</td>
<td align="center">3.3</td>
<td align="center">1.2</td>
</tr>
<tr>
<td align="center">2</td>
<td align="center">4.2</td>
<td align="center">-1.1</td>
</tr>
<tr>
<td align="center">3</td>
<td align="center">6.8</td>
<td align="center">1.5</td>
</tr>
<tr>
<td align="center">4</td>
<td align="center">8.2</td>
<td align="center">1.2</td>
</tr>
<tr>
<td align="center">5</td>
<td align="center">10.2</td>
<td align="center">2.5</td>
</tr>
</table>
<p>Call the function, supply x and y array as displayed on above table, set resolution to <b>0.1</b>:</p>
<div style="font-family:courier;font-size:8pt;background-color:#E0E0E0;">
SELECT * FROM spline(<br />
&nbsp;&nbsp;&#8217;{3.3,4.2,6.8,8.2,10.2}&#8217;::numeric[],<br />
&nbsp;&nbsp; &#8216;{1.2,-1.1,1.5,1.2,2.5}&#8217;::numeric[],<br />
&nbsp;&nbsp;0.1);
</div>
<p>We will have set of records containing <b>xs</b> and <b>ys</b>.:</p>
<div style="font-family:courier;font-size:8pt;background-color:#E0E0E0;">
xs&nbsp;&nbsp;ys<br />
3.3&nbsp;&nbsp;1.199999999999999970<br />
3.4&nbsp;&nbsp;0.8860175045157231811<br />
3.5&nbsp;&nbsp;0.5764170295261004851<br />
3.6&nbsp;&nbsp;0.2755805955257859750<br />
3.7&nbsp;&nbsp;-0.0121097769905662565<br />
3.8&nbsp;&nbsp;-0.28227206752830211620<br />
&#8230; and so on
</div>
<p>Let us put them in graph:<br />
<img src="http://abdulyadi.files.wordpress.com/2009/05/curve.jpg?w=600" alt="curve" title="curve"   class="aligncenter size-full wp-image-92" /></p>
<p>The blue-y1 and red-y2 are sample and interpolation points as returned by the <b>spline</b> function, respectively.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/abdulyadi.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/abdulyadi.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/abdulyadi.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/abdulyadi.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/abdulyadi.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/abdulyadi.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/abdulyadi.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/abdulyadi.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/abdulyadi.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/abdulyadi.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/abdulyadi.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/abdulyadi.wordpress.com/62/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/abdulyadi.wordpress.com/62/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/abdulyadi.wordpress.com/62/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=62&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://abdulyadi.wordpress.com/2009/05/16/plsql-for-curve-smoothing/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">abdulyadi</media:title>
		</media:content>

		<media:content url="http://abdulyadi.files.wordpress.com/2009/05/curve.jpg" medium="image">
			<media:title type="html">curve</media:title>
		</media:content>
	</item>
		<item>
		<title>Tree-structured data and Nested Hash</title>
		<link>http://abdulyadi.wordpress.com/2009/02/06/tree-structured-data-and-nested-hash/</link>
		<comments>http://abdulyadi.wordpress.com/2009/02/06/tree-structured-data-and-nested-hash/#comments</comments>
		<pubDate>Fri, 06 Feb 2009 09:12:34 +0000</pubDate>
		<dc:creator>abdulyadi</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://abdulyadi.wordpress.com/?p=50</guid>
		<description><![CDATA[I have just accomplished a task to transfer tree-formed data structure from client application environment into PostgreSQL PLSQL body function. The tree at client side is structured as shown below: &#160;&#160;&#124;&#8211;Manager1 &#160;&#160;&#124;&#160;&#160;&#160;&#160;&#124; &#160;&#160;&#124;&#160;&#160;&#160;&#160;&#124;&#8211;Senior1 &#160;&#160;&#124;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#124;&#8211;Junior1 &#160;&#160;&#124;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#124;&#8211;Junior2 &#160;&#160;&#124;&#160;&#160;&#160;&#160;&#124; &#160;&#160;&#124;&#160;&#160;&#160;&#160;&#124;&#8211;Senior2 &#160;&#160;&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#8211;Junior3 &#160;&#160;&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#8211;Junior4 &#160;&#160;&#124;&#160;&#160; &#160;&#160;&#124;&#8211;Manager2 &#160;&#160;&#160;&#160;&#160;&#160;&#124; &#160;&#160;&#160;&#160;&#160;&#160;&#124;&#8211;Senior3 &#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#124;&#8211;Junior5 &#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#124;&#8211;Junior6 &#160;&#160;&#160;&#160;&#160;&#160;&#124; &#160;&#160;&#160;&#160;&#160;&#160;&#124;&#8211;Senior4 &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#8211;Junior7 &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#8211;Junior8 Instead of send the item pieces [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=50&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I have just accomplished a task to transfer tree-formed data structure from client application environment into PostgreSQL PLSQL body function. The tree at client side is structured as shown below:</p>
<div style="background-color:#E0E0E0;">
<p>&nbsp;&nbsp;|&#8211;Manager1<br />
&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|<br />
&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|&#8211;Senior1<br />
&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|&#8211;Junior1<br />
&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|&#8211;Junior2<br />
&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|<br />
&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|&#8211;Senior2<br />
&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&#8211;Junior3<br />
&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&#8211;Junior4<br />
&nbsp;&nbsp;|&nbsp;&nbsp;<br />
&nbsp;&nbsp;|&#8211;Manager2<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&#8211;Senior3<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|&#8211;Junior5<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|&#8211;Junior6<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&#8211;Senior4<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&#8211;Junior7<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&#8211;Junior8
</p></div>
<p>Instead of send the item pieces one by one, I want to send all the items at once.</p>
<h3>PLSQL Function (convert array of ltree into nested hash)</h3>
<p>I decide to package the tree items in the array of LTREE field type provided in PostgreSQL contrib module by Teodor Sigaev and Oleg Bartunov. Later in the function body, I convert the LTREE array into HSTORE (again thanks to Teodor Sigaev and Oleg Bartunov). HSTORE maps key to value. Both are string types. But in my case, the hash contains key which point to another hash, creating nested hash.</p>
<p>Following is the stored procedure in PLSQL created on Postgresql 8.3.1:</p>
<div style="background-color:#E0E0E0;font-family:courier;font-size:8pt;">
CREATE OR REPLACE FUNCTION organization(IN trees ltree[]) RETURNS void AS<br />
$BODY$<br />
DECLARE<br />
&#8212;&#8212;&#8211;ltree[] will be converted to nested hash:<br />
&#8212;&#8212;&#8212;&#8212;-hash_mgr=&gt;hash_snr=&gt;array(Juniors)<br />
&nbsp;&nbsp;&nbsp;&nbsp;i integer;<br />
&nbsp;&nbsp;&nbsp;&nbsp;count integer;<br />
&nbsp;&nbsp;&nbsp;&nbsp;hash_mgr hstore;<br />
&nbsp;&nbsp;&nbsp;&nbsp;hash_snr hstore;<br />
&nbsp;&nbsp;&nbsp;&nbsp;tree ltree;<br />
&nbsp;&nbsp;&nbsp;&nbsp;arr text[];<br />
&nbsp;&nbsp;&nbsp;&nbsp;mgr text;<br />
&nbsp;&nbsp;&nbsp;&nbsp;snr text;<br />
&nbsp;&nbsp;&nbsp;&nbsp;jnr text;<br />
&nbsp;&nbsp;&nbsp;&nbsp;k1 text; v1 text;<br />
&nbsp;&nbsp;&nbsp;&nbsp;k2 text; v2 text;<br />
BEGIN<br />
&nbsp;&nbsp;&nbsp;&nbsp;count:=ARRAY_UPPER(trees,1);<br />
&#8212;&#8212;&#8211;convert array of trees into nested hash:<br />
&nbsp;&nbsp;&nbsp;&nbsp;FOR i IN 1..count LOOP<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tree:=trees[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mgr:=SUBLTREE(tree,0,1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;snr:=SUBLTREE(tree,1,2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jnr:=SUBLTREE(tree,2,3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hash_snr:=(hash_mgr-&gt;mgr)::hstore;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arr:=(hash_snr-&gt;snr)::text[];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arr:=COALESCE(arr,&#8217;{}&#8217;::text[]) || jnr;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hash_snr:=COALESCE( hash_snr||(snr=&gt;arr::text),snr=&gt;arr::text);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hash_mgr:=COALESCE( hash_mgr||(mgr=&gt;hash_snr::text),mgr=&gt;hash_snr::text);<br />
&nbsp;&nbsp;&nbsp;&nbsp;END LOOP;<br />
&#8212;&#8212;&#8211;now we hava nested hash<br />
&#8212;&#8212;&#8211;usage 1: get Junior1 and Junior2:<br />
&nbsp;&nbsp;&nbsp;&nbsp;arr:=((hash_mgr-&gt;&#8217;Manager1&#8242;)::hstore)-&gt;&#8217;Senior1&#8242;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;RAISE NOTICE &#8216;% %&#8217;,arr[1],arr[2];<br />
&#8212;&#8212;&#8211;navigate all items<br />
&nbsp;&nbsp;&nbsp;&nbsp;FOR k1, v1 IN SELECT key, value FROM EACH(hash_mgr) LOOP<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RAISE NOTICE &#8216;manager: %&#8217;,k1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FOR k2, v2 IN SELECT key, value FROM EACH(v1::hstore) LOOP<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RAISE NOTICE &#8216;    senior: %&#8217;,k2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RAISE NOTICE &#8216;      junior: %&#8217;,(v2::text[])[1];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RAISE NOTICE &#8216;      junior: %&#8217;,(v2::text[])[2];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;END LOOP;<br />
&nbsp;&nbsp;&nbsp;&nbsp;END LOOP;<br />
&nbsp;&nbsp;&nbsp;&nbsp;RETURN;<br />
END;$BODY$<br />
LANGUAGE &#8216;plpgsql&#8217; STABLE;
</div>
<p>Let&#8217;s start from lowest level. Hash <b>hash_snr</b> maps &#8220;senior&#8221; to array of juniors.<br />
Go up one level, hash <b>hash_mgr</b> maps &#8220;manager&#8221; to hash <b>hash_snr</b>.</p>
<p>To use the function, client application should invoke it as follows:</p>
<div style="background-color:#E0E0E0;font-family:courier;font-size:8pt;">
SELECT organization(&#8216;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;Manager1.Senior1.Junior1,<br />
&nbsp;&nbsp;&nbsp;&nbsp;Manager1.Senior1.Junior2,<br />
&nbsp;&nbsp;&nbsp;&nbsp;Manager1.Senior2.Junior3,<br />
&nbsp;&nbsp;&nbsp;&nbsp;Manager1.Senior2.Junior4,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Manager2.Senior3.Junior5,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Manager2.Senior3.Junior6,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Manager2.Senior4.Junior7,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Manager2.Senior4.Junior8<br />
&nbsp;&nbsp;&nbsp;&nbsp;}&#8217;);
</div>
<p>Take note RAISE NOTICE at the lower portion of function body. It will give us messages as follows:</p>
<div style="background-color:#E0E0E0;font-family:courier;font-size:8pt;">
NOTICE:&nbsp;&nbsp;&nbsp;&nbsp;Junior1 Junior2<br />
NOTICE:&nbsp;&nbsp;&nbsp;&nbsp;manager: Manager1<br />
NOTICE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;senior: Senior1<br />
NOTICE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;junior: Junior1<br />
NOTICE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;junior: Junior2<br />
NOTICE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;senior: Senior2<br />
NOTICE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;junior: Junior3<br />
NOTICE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;junior: Junior4<br />
NOTICE:&nbsp;&nbsp;&nbsp;&nbsp;manager: Manager2<br />
NOTICE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;senior: Senior3<br />
NOTICE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;junior: Junior5<br />
NOTICE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;junior: Junior6<br />
NOTICE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;senior: Senior4<br />
NOTICE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;junior: Junior7<br />
NOTICE:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;junior: Junior8
</div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/abdulyadi.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/abdulyadi.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/abdulyadi.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/abdulyadi.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/abdulyadi.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/abdulyadi.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/abdulyadi.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/abdulyadi.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/abdulyadi.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/abdulyadi.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/abdulyadi.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/abdulyadi.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/abdulyadi.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/abdulyadi.wordpress.com/50/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=50&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://abdulyadi.wordpress.com/2009/02/06/tree-structured-data-and-nested-hash/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">abdulyadi</media:title>
		</media:content>
	</item>
		<item>
		<title>Prevent Concurrent Update in Read-Committed Transaction</title>
		<link>http://abdulyadi.wordpress.com/2008/12/04/prevent-concurrent-update-in-read-committed-transaction/</link>
		<comments>http://abdulyadi.wordpress.com/2008/12/04/prevent-concurrent-update-in-read-committed-transaction/#comments</comments>
		<pubDate>Thu, 04 Dec 2008 23:54:10 +0000</pubDate>
		<dc:creator>abdulyadi</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://abdulyadi.wordpress.com/?p=23</guid>
		<description><![CDATA[To prevent concurrent update on table records, I simply just encapsulate upates inside Serializable Transaction. But, quoted from Annotated postgresql.conf and Global User Configuration (GUC) Guide (http://www.varlena.com/GeneralBits/Tidbits/annotated_conf_e.html): Under a heavy multi-user load, setting “serializable” can impose a significant penalty as numerous transactions are forced to wait for the serialized transaction to complete. I want to [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=23&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>To prevent concurrent update on table records, I simply just encapsulate upates inside Serializable Transaction. But, quoted from Annotated postgresql.conf and Global User Configuration (GUC) Guide (http://www.varlena.com/GeneralBits/Tidbits/annotated_conf_e.html):</p>
<blockquote><p>Under a heavy multi-user load, setting “serializable” can impose a significant penalty as numerous transactions are forced to wait for the serialized transaction to complete.</p></blockquote>
<p>I want to share with you my simple way to implement the feature in PostgreSQL default transaction isolation level: READ COMMITTED.</p>
<p>First, define the table:</p>
<div style="font-family:courier;font-size:12px;">CREATE TABLE inventory(<br />
&nbsp;&nbsp;id serial NOT NULL,<br />
&nbsp;&nbsp;item text NOT NULL,<br />
&nbsp;&nbsp;qty integer NOT NULL,<br />
&nbsp;&nbsp;ver integer NOT NULL DEFAULT 1,<br />
&nbsp;&nbsp;CONSTRAINT inventory_pkey PRIMARY KEY (id)<br />
)<br />
WITH (OIDS=FALSE);</div>
<p>The last field <strong>ver</strong> is the focal point of the concurrent update protection.</p>
<p>Let&#8217;s create trigger function in PLSQL to be activated BEFORE INSERT and BEFORE UPDATE.</p>
<div style="font-family:courier;font-size:12px;">CREATE OR REPLACE FUNCTION trig_inventory()<br />
RETURNS trigger AS<br />
$BODY$<br />
BEGIN<br />
&nbsp;&nbsp;IF (TG_WHEN = &#8216;BEFORE&#8217; AND TG_OP = &#8216;INSERT&#8217;) THEN<br />
&nbsp;&nbsp;&nbsp;&nbsp;NEW.ver = 1; &#8211;force ver initiated with 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;RETURN NEW;<br />
&nbsp;&nbsp;ELSIF (TG_WHEN = &#8216;BEFORE&#8217; AND TG_OP = &#8216;UPDATE&#8217;) THEN<br />
&nbsp;&nbsp;&nbsp;&nbsp;IF OLD.ver &gt; NEW.ver THEN &#8211;somebody has updated this record<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RAISE EXCEPTION &#8216;Concurrent Update Protection!&#8217;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;END IF;<br />
&nbsp;&nbsp;&nbsp;&nbsp;NEW.ver = OLD.ver + 1; &#8211;increment UPDATE<br />
&nbsp;&nbsp;&nbsp;&nbsp;RETURN NEW;<br />
&nbsp;&nbsp;END IF;<br />
END;<br />
$BODY$<br />
LANGUAGE &#8216;plpgsql&#8217; VOLATILE;</div>
<p>Assign the trigger function to <strong>inventory</strong> table:</p>
<div style="font-family:courier;font-size:12px;">CREATE TRIGGER inventory_before_insert BEFORE INSERT<br />
&nbsp;&nbsp;ON inventory FOR EACH ROW EXECUTE PROCEDURE public.trig_inventory();<br />
CREATE TRIGGER inventory_before_update BEFORE UPDATE<br />
&nbsp;&nbsp;ON inventory FOR EACH ROW EXECUTE PROCEDURE public.trig_inventory();</div>
<p>Now, let us try the feature (use <strong>psql</strong>):<br />
First, insert record:</p>
<div style="font-family:courier;font-size:12px;">citra=# INSERT INTO inventory (item,qty) VALUES (&#8216;ITEM_1&#8242;,50) RETURNING *;<br />
id |  item  | qty | ver<br />
&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8211;+&#8212;&#8211;<br />
2 | ITEM_1 |  50 |   1<br />
(1 row)INSERT 0 1</div>
<p>Please note that field <strong>ver</strong> has been initialized to <strong>1</strong>;<br />
Now, update the record to check <strong>ver</strong> incremented:</p>
<div style="font-family:courier;font-size:12px;">citra=# BEGIN;<br />
BEGIN<br />
citra=# UPDATE inventory SET qty=qty+100 WHERE id=2 RETURNING *;<br />
id |  item  | qty | ver<br />
&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8211;+&#8212;&#8211;<br />
2 | ITEM_1 | 150 |   2<br />
(1 row)UPDATE 1<br />
citra=# COMMIT;</div>
<p>Finally, let&#8217;s simulate concurrent update protection. Besides current <strong>psql</strong> session, please open another session.<br />
For simplicity, I assume that users on both session has queried the record and identify the <strong>ver</strong> equals <strong>2</strong>. Please ensure that the <strong>ver</strong> field is included in update command.</p>
<div style="font-family:courier;font-size:12px;">
<table border="0">
<tbody>
<tr>
<td><b>session #1</b></td>
<td>&nbsp;</td>
<td><b>session #2</b></td>
</tr>
<tr>
<td>citra=# BEGIN;</td>
<td>&nbsp;</td>
<td>citra=# BEGIN;</td>
</tr>
<tr>
<td>citra=# UPDATE inventory SET qty=qty+100,ver=2 WHERE id=2 RETURNING *;</td>
<td>&nbsp;</td>
<td>citra=# UPDATE inventory SET qty=qty+100,ver=2 WHERE id=2 RETURNING *;</td>
</tr>
<tr>
<td>citra=# COMMIT;</td>
<td>&nbsp;</td>
<td>citra=# COMMIT;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>ERROR:  Concurrent Update Protection!</td>
</tr>
</tbody>
</table>
</div>
<p>The second session get the error message. The user must re-query the record to get the latest <strong>ver</strong> and use it in next update command.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/abdulyadi.wordpress.com/23/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/abdulyadi.wordpress.com/23/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/abdulyadi.wordpress.com/23/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/abdulyadi.wordpress.com/23/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/abdulyadi.wordpress.com/23/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/abdulyadi.wordpress.com/23/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/abdulyadi.wordpress.com/23/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/abdulyadi.wordpress.com/23/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/abdulyadi.wordpress.com/23/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/abdulyadi.wordpress.com/23/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/abdulyadi.wordpress.com/23/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/abdulyadi.wordpress.com/23/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/abdulyadi.wordpress.com/23/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/abdulyadi.wordpress.com/23/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=23&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://abdulyadi.wordpress.com/2008/12/04/prevent-concurrent-update-in-read-committed-transaction/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">abdulyadi</media:title>
		</media:content>
	</item>
		<item>
		<title>Cross-tab Report</title>
		<link>http://abdulyadi.wordpress.com/2008/11/27/cross-tab-report/</link>
		<comments>http://abdulyadi.wordpress.com/2008/11/27/cross-tab-report/#comments</comments>
		<pubDate>Thu, 27 Nov 2008 18:45:20 +0000</pubDate>
		<dc:creator>abdulyadi</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://abdulyadi.wordpress.com/?p=12</guid>
		<description><![CDATA[Another case with aggregate function. A sales table is defined and contains raw records of sales activity as follows: CREATE TABLE sales ( &#160;&#160;id serial NOT NULL, &#160;&#160;item text NOT NULL, &#160;&#160;sales_unit text NOT NULL, &#160;&#160;amount numeric NOT NULL, &#160;&#160;CONSTRAINT sales_pkey PRIMARY KEY (id) ) WITH (OIDS=FALSE); id item    sales_unit amount 1  ITEM_1  UNIT_1     1000.5 [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=12&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Another case with aggregate function. A sales table is defined and contains raw records of sales activity as follows:</p>
<p><span style="font-family:courier;">CREATE TABLE sales<br />
(<br />
&nbsp;&nbsp;id serial NOT NULL,<br />
&nbsp;&nbsp;item text NOT NULL,<br />
&nbsp;&nbsp;sales_unit text NOT NULL,<br />
&nbsp;&nbsp;amount numeric NOT NULL,<br />
&nbsp;&nbsp;CONSTRAINT sales_pkey PRIMARY KEY (id)<br />
)<br />
WITH (OIDS=FALSE);</span></p>
<pre>id item    sales_unit amount
1  ITEM_1  UNIT_1     1000.5
2  ITEM_1  UNIT_2     1100
3  ITEM_1  UNIT_3     1150.25
4  ITEM_1  UNIT_1     100.75
5  ITEM_2  UNIT_2     275
6  ITEM_2  UNIT_3     750.5
7  ITEM_2  UNIT_2     300.5</pre>
<p>Total sales amount for each sales unit for each item will be presented in cross-tab format:</p>
<pre>item    UNIT_1   UNIT_2   UNIT_3
ITEM_1  1101.25  1100     1150.25
ITEM_2  0        575.5    750.5</pre>
<p>To create aggregate function, let us prepare the State Transition Function:</p>
<div style="font-family:courier;">CREATE OR REPLACE FUNCTION sales_amount(<br />
&nbsp;&nbsp;amounts numeric[],<br />
&nbsp;&nbsp;unit text,<br />
&nbsp;&nbsp;amount numeric,<br />
&nbsp;&nbsp;units text,<br />
&nbsp;&nbsp;unitcount integer)<br />
RETURNS numeric[] AS<br />
$BODY$<br />
DECLARE<br />
&nbsp;&nbsp;out_amounts numeric[];<br />
&nbsp;&nbsp;unit_pattern text;<br />
&nbsp;&nbsp;sub_unit text[];<br />
&nbsp;&nbsp;idx integer;<br />
BEGIN<br />
&nbsp;&nbsp;out_amounts:=amounts;<br />
&nbsp;&nbsp;&#8212;&#8212;&#8211;units in format: [unit_name]:[array_index],[unit_name]:[array_index],&#8230;<br />
&nbsp;&nbsp;unit_pattern:= unit || &#8216;:[0-9]{1,}&#8217;;<br />
&nbsp;&nbsp;sub_unit:=regexp_matches(units,unit_pattern);<br />
&nbsp;&nbsp;IF sub_unit IS NULL THEN<br />
&nbsp;&nbsp;&nbsp;&nbsp;RETURN out_amounts;<br />
&nbsp;&nbsp;END IF;<br />
&nbsp;&nbsp;&#8212;&#8212;&#8211;get array_index for dept<br />
&nbsp;&nbsp;idx:=split_part(array_to_string(sub_unit,&#8221;),&#8217;:',2)::integer;<br />
&nbsp;&nbsp;IF array_upper(out_amounts,1) IS NULL THEN<br />
&nbsp;&nbsp;&#8212;&#8212;&#8211;initiate amount array with 0<br />
&nbsp;&nbsp;&nbsp;&nbsp;out_amounts:=string_to_array(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&#8217;0&#8242; || repeat( &#8216;,0&#8242;, unitcount-1 ) ,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&#8217;,&#8217; )::numeric[];<br />
&nbsp;&nbsp;END IF;<br />
&nbsp;&nbsp;out_amounts[idx]:=out_amounts[idx]+amount;<br />
&nbsp;&nbsp;RETURN out_amounts;<br />
END;$BODY$<br />
LANGUAGE &#8216;plpgsql&#8217; IMMUTABLE STRICT;</div>
<p>Here is the aggregate function:</p>
<div style="font-family:courier;">CREATE AGGREGATE sales_agg(text, numeric, text, integer) (<br />
&nbsp;&nbsp;SFUNC=sales_amount,<br />
&nbsp;&nbsp;STYPE=numeric[],<br />
&nbsp;&nbsp;INITCOND=&#8217;{}&#8217;<br />
);</div>
<p>Now, let us create user defined function:</p>
<div style="font-family:courier;">CREATE OR REPLACE FUNCTION create_sales_report(<br />
&nbsp;&nbsp;refcursor, &#8211;cursor name<br />
&nbsp;&nbsp;units text[] &#8211;array of your expected units to appear on corss-tab report<br />
)<br />
RETURNS void AS<br />
$BODY$<br />
DECLARE<br />
&nbsp;&nbsp;unit_count integer;<br />
&nbsp;&nbsp;units_series text;<br />
&nbsp;&nbsp;i integer;<br />
&nbsp;&nbsp;sql text;<br />
BEGIN<br />
&nbsp;&nbsp;unit_count:=array_upper(units,1);<br />
&nbsp;&nbsp;&#8212;&#8212;&#8211;convert units into [dept_name]:[array_index],[dept_name]:[array_index],&#8230;<br />
&nbsp;&nbsp;&#8212;&#8212;&#8211;to avoid repetitive loops inside aggregate function<br />
&nbsp;&nbsp;units_series:=&#8221;;<br />
&nbsp;&nbsp;FOR i in 1..unit_count LOOP<br />
&nbsp;&nbsp;&nbsp;&nbsp;IF i&gt;1 THEN<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;units_series:= units_series || &#8216;,&#8217;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;END IF;<br />
&nbsp;&nbsp;units_series:= units_series || units[i] || &#8216;:&#8217; || i;<br />
&nbsp;&nbsp;END LOOP;<br />
&nbsp;&nbsp;&#8212;&#8212;&#8211;compose sql statement<br />
&nbsp;&nbsp;sql:=    &#8216;SELECT t.item&#8217;;<br />
&nbsp;&nbsp;i:=1;<br />
&nbsp;&nbsp;WHILE units[i] IS NOT NULL LOOP<br />
&nbsp;&nbsp;&nbsp;&nbsp;sql:= sql || &#8216;,t.amounts[' || i || '] AS &#8216; || quote_ident(units[i]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;i:=i+1;<br />
&nbsp;&nbsp;END LOOP;<br />
&nbsp;&nbsp;sql:=sql || &#8216; FROM (SELECT item,&#8217;<br />
&nbsp;&nbsp;&nbsp;&nbsp;|| &#8216;sales_agg(sales_unit,amount,&#8217;<br />
&nbsp;&nbsp;&nbsp;&nbsp;|| quote_literal(units_series) || &#8216;,&#8217;<br />
&nbsp;&nbsp;&nbsp;&nbsp;|| unit_count || &#8216;) AS amounts &#8216;<br />
&nbsp;&nbsp;|| &#8216;FROM sales GROUP BY item&#8217;<br />
&nbsp;&nbsp;|| &#8216;) t ORDER BY t.item&#8217;;<br />
&nbsp;&nbsp;&#8212;&#8212;&#8211;open cursor<br />
&nbsp;&nbsp;OPEN $1 FOR EXECUTE sql;<br />
RETURN;<br />
END;$BODY$<br />
LANGUAGE &#8216;plpgsql&#8217; IMMUTABLE STRICT;</div>
<p>Following is how the function is called in psql console:</p>
<div style="font-family:courier;">citra=# begin;<br />
BEGIN<br />
citra=# select create_sales_report(&#8216;report&#8217;,'{UNIT_1,UNIT_2,UNIT_3}&#8217;);<br />
create_sales_report<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>(1 row)</p>
<p>citra=# FETCH ALL IN report;<br />
item  | UNIT_1  | UNIT_2 | UNIT_3<br />
&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;<br />
ITEM_1 | 1101.25 |   1100 | 1150.25<br />
ITEM_2 |       0 |  575.5 |   750.5<br />
(2 rows)</p>
<p>citra=# COMMIT;</p></div>
<p>The query can be expanded to have more sales units:</p>
<div style="font-family:courier;">#select create_sales_report(&#8216;report&#8217;,'{UNIT_1,UNIT_2,UNIT_3,&#8230;,&#8230;}&#8217;);</div>
<p>Or, to display all available sales units in the sales table, just use <b>array_agg</b> (see my previous post):</p>
<div style="font-family:courier;">#select create_sales_report(&#8216;report&#8217;,<br />
&nbsp;&nbsp;(SELECT array_agg(t.sales_unit) FROM (SELECT DISTINCT ON (sales_unit) sales_unit FROM sales) t)<br />
);</div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/abdulyadi.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/abdulyadi.wordpress.com/12/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/abdulyadi.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/abdulyadi.wordpress.com/12/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/abdulyadi.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/abdulyadi.wordpress.com/12/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/abdulyadi.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/abdulyadi.wordpress.com/12/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/abdulyadi.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/abdulyadi.wordpress.com/12/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/abdulyadi.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/abdulyadi.wordpress.com/12/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/abdulyadi.wordpress.com/12/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/abdulyadi.wordpress.com/12/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=abdulyadi.wordpress.com&#038;blog=5629914&#038;post=12&#038;subd=abdulyadi&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://abdulyadi.wordpress.com/2008/11/27/cross-tab-report/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">abdulyadi</media:title>
		</media:content>
	</item>
	</channel>
</rss>

