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

<channel>
	<title>Taming Serpents and Pachyderms</title>
	<atom:link href="http://pyrseas.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://pyrseas.wordpress.com</link>
	<description>Musings on Python, PostgreSQL and other species</description>
	<lastBuildDate>Tue, 07 Feb 2012 13:20:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='pyrseas.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Taming Serpents and Pachyderms</title>
		<link>http://pyrseas.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://pyrseas.wordpress.com/osd.xml" title="Taming Serpents and Pachyderms" />
	<atom:link rel='hub' href='http://pyrseas.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Automated Database Augmentation</title>
		<link>http://pyrseas.wordpress.com/2012/02/05/automated-database-augmentation/</link>
		<comments>http://pyrseas.wordpress.com/2012/02/05/automated-database-augmentation/#comments</comments>
		<pubDate>Mon, 06 Feb 2012 04:59:42 +0000</pubDate>
		<dc:creator>jma</dc:creator>
				<category><![CDATA[Database tools]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[andromeda]]></category>
		<category><![CDATA[database augmentation]]></category>
		<category><![CDATA[database automation]]></category>
		<category><![CDATA[database tools]]></category>
		<category><![CDATA[pagila]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[triangulum]]></category>

		<guid isPermaLink="false">http://pyrseas.wordpress.com/?p=1476</guid>
		<description><![CDATA[Suppose you have a PostgreSQL database like the Pagila sample with 14 tables, each with a last_update timestamp column to record the date and time each row was modified, and it is now a requirement to capture which user effected &#8230; <a href="http://pyrseas.wordpress.com/2012/02/05/automated-database-augmentation/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1476&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Suppose you have a PostgreSQL database like the <a href="http://cvs.pgfoundry.org/cgi-bin/cvsweb.cgi/dbsamples/pagila/pagila-schema.sql?rev=1.8&amp;content-type=text/x-cvsweb-markup">Pagila sample</a> with 14 tables, each with a <tt>last_update</tt> timestamp column to record the date and time each row was modified, and it is now a requirement to capture which user effected each change. Or perhaps you have several tables without such audit trail columns and need to add them quickly. Or maybe you have decided to denormalize your design by adding a calculated column, e.g., extended price = unit price times quantity ordered, or a derived column, e.g., carrying the customer name in the invoice table.</p>
<p><a href="http://classroom209.blogspot.com/2011/01/vocab-for-fire-stormf.html"><img class="alignright" title="Drudgery" src="http://4.bp.blogspot.com/_knNIUa4PX-s/TSSSaT20CJI/AAAAAAAABLc/gem_AOMgrz0/s1600/Drudgery.jpg" alt="" width="288" height="230" /></a>If you have some experience as a DBA, the word &#8220;<a href="http://en.wiktionary.org/wiki/drudgery">drudgery</a>&#8221; may have come to mind at the prospect of implementing the above features. It&#8217;s possible that, after a while, you&#8217;ve developed an approach for dealing with some of them but still wish there&#8217;d be <em>some way</em> to automate these thankless tasks.</p>
<p>You may have looked at the Andromeda project&#8217;s &#8220;<a href="http://www.andromeda-project.org/automations.html">automations</a>&#8221; which provide some of these capabilities. However, in order to take advantage of the automations, you&#8217;ll first have to manually describe your database in a YAML format (and you&#8217;ll have to install Apache and PHP). Or you could have tried to use the follow-on project, <a href="http://code.google.com/p/triangulum-db/wiki/UsingTriangulum">Triangulum</a>, but essentially you&#8217;d still have to create a YAML schema (no need for Apache, but you still need PHP).</p>
<p>Some relief is forthcoming. As a result of discussions resulting from my <a title="Business Logic in the Database" href="http://pyrseas.wordpress.com/2012/01/02/business-logic-in-the-database/">Business Logic in the Database</a> post, I have been collaborating with Roger Hunwicks on a potential solution to these common DBA needs. The new Pyrseas tool is tentatively named <tt>dbextend</tt><sup>1</sup> and its initial documentation is available in the <a href="https://github.com/jmafc/Pyrseas/blob/extender/docs/dbextend.rst">Pyrseas extender branch</a>. This is how I envision <tt>dbextend</tt> being used.</p>
<p>Consider the opening example. The DBA would create a simple YAML file such as the (abbreviated) one below, listing the tables and the needed features:</p>
<pre>schema public:
  table actor:
    audit_columns: default
  table category:
    audit_columns: default
...
  table store:
    audit_columns: default</pre>
<p>The DBA would then use this file, say <tt>audext.yaml</tt>, as input to dbextend, e.g.,</p>
<pre>dbextend pagiladb audext.yaml</pre>
<p>dbextend reads the PostgreSQL catalogs (using code shared with <a href="http://pyrseas.readthedocs.org/en/latest/dbtoyaml.html">dbtoyaml</a> and <a href="http://pyrseas.readthedocs.org/en/latest/yamltodb.html">yamltodb</a>), building its internal representation. It also reads the YAML extensions file and builds a parallel (albeit much smaller) structure. Thirdly, it reads extension configuration information, e.g., a definition of what columns need to be added for &#8220;<tt>audit_columns: default</tt>&#8220;, for example, modified_timestamp and modified_by_user, what trigger(s) to add, and what function(s) to be created.</p>
<p>The output of dbextend is a YAML schema file, just like the one output by dbtoyaml, which can be piped directly to yamltodb to generate SQL to implement the desired features.</p>
<p>In case you&#8217;re wondering, dbextend —like other Pyrseas tools— will require Python, psycopg2 and pyyaml.</p>
<p>What features would <em>you</em> like to see automated? What are <em>your</em> suggested best practices for automating these common needs?</p>
<hr />
<p>Picture credit: Thanks to Mr. O&#8217;Brien, a fourth-grade teacher in Minnesota.</p>
<p><sup>1</sup> We&#8217;re still receptive to some other suitable name.</p>
<br />Filed under: <a href='http://pyrseas.wordpress.com/category/database-tools/'>Database tools</a>, <a href='http://pyrseas.wordpress.com/category/postgresql-2/'>PostgreSQL</a>, <a href='http://pyrseas.wordpress.com/category/python/'>Python</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pyrseas.wordpress.com/1476/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pyrseas.wordpress.com/1476/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pyrseas.wordpress.com/1476/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pyrseas.wordpress.com/1476/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pyrseas.wordpress.com/1476/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pyrseas.wordpress.com/1476/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pyrseas.wordpress.com/1476/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pyrseas.wordpress.com/1476/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pyrseas.wordpress.com/1476/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pyrseas.wordpress.com/1476/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pyrseas.wordpress.com/1476/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pyrseas.wordpress.com/1476/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pyrseas.wordpress.com/1476/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pyrseas.wordpress.com/1476/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1476&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pyrseas.wordpress.com/2012/02/05/automated-database-augmentation/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0d235d4094b8dbf2cd9932667d828795?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jmafc</media:title>
		</media:content>

		<media:content url="http://4.bp.blogspot.com/_knNIUa4PX-s/TSSSaT20CJI/AAAAAAAABLc/gem_AOMgrz0/s1600/Drudgery.jpg" medium="image">
			<media:title type="html">Drudgery</media:title>
		</media:content>
	</item>
		<item>
		<title>The Phantom of the Database – Part 4</title>
		<link>http://pyrseas.wordpress.com/2012/01/13/the-phantom-of-the-database-part-4/</link>
		<comments>http://pyrseas.wordpress.com/2012/01/13/the-phantom-of-the-database-part-4/#comments</comments>
		<pubDate>Fri, 13 Jan 2012 16:21:28 +0000</pubDate>
		<dc:creator>jma</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[User interfaces]]></category>
		<category><![CDATA[concurrency control]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[user interfaces]]></category>

		<guid isPermaLink="false">http://pyrseas.wordpress.com/?p=1463</guid>
		<description><![CDATA[At the end of November, I finished the third episode with mild suspense: I suggested that the problem of optimistic &#8220;locking&#8221; could perhaps be solved in PostgreSQL with something other than extra qualifications, row version numbers or timestamps. Let&#8217;s start &#8230; <a href="http://pyrseas.wordpress.com/2012/01/13/the-phantom-of-the-database-part-4/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1463&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>At the end of November, I finished the <a title="The Phantom of the Database – Part 3" href="http://pyrseas.wordpress.com/2011/11/28/the-phantom-of-the-database-part-3/">third episode</a> with mild suspense: I suggested that the problem of optimistic &#8220;locking&#8221; could perhaps be solved in PostgreSQL with something other than extra qualifications, row version numbers or timestamps.</p>
<p>Let&#8217;s start this episode with action!</p>
<pre>moviesdb=&gt; INSERT INTO film VALUES (47478, 'Seven  Samurai', 1956);
INSERT 0 1
moviesdb=&gt; SELECT xmin, xmax, ctid, title, release_year FROM film;
  xmin  | xmax | ctid  |     title      | release_year
--------+------+-------+----------------+--------------
 853969 |    0 | (0,1) | Seven  Samurai |         1956
(1 row)

moviesdb=&gt; UPDATE film SET title = 'Seven Samurai' WHERE id = 47478;
UPDATE 1
moviesdb=&gt; SELECT xmin, xmax, ctid, title, release_year FROM film;
  xmin  | xmax | ctid  |     title     | release_year
--------+------+-------+---------------+--------------
 853970 |    0 | (0,2) | Seven Samurai |         1956
(1 row)

moviesdb=&gt; UPDATE film SET title = 'Sichinin Samurai' WHERE id = 47478;
UPDATE 1
moviesdb=&gt; SELECT xmin, xmax, ctid, title, release_year FROM film;
  xmin  | xmax | ctid  |      title       | release_year
--------+------+-------+------------------+--------------
 853971 |    0 | (0,3) | Sichinin Samurai |         1956
(1 row)

moviesdb=&gt; UPDATE film SET release_year = 1954 WHERE id = 47478;
UPDATE 1
moviesdb=&gt; SELECT xmin, xmax, ctid, title, release_year FROM film;
  xmin  | xmax | ctid  |      title       | release_year
--------+------+-------+------------------+--------------
 853972 |    0 | (0,4) | Sichinin Samurai |         1954
(1 row)

moviesdb=&gt; VACUUM FULL film;
VACUUM
moviesdb=&gt; SELECT xmin, xmax, ctid, title, release_year FROM film;
  xmin  | xmax | ctid  |      title       | release_year
--------+------+-------+------------------+--------------
 853972 |    0 | (0,1) | Sichinin Samurai |         1954
(1 row)

moviesdb=&gt; BEGIN; DELETE FROM film WHERE id = 47478; ROLLBACK;
BEGIN
DELETE 1
ROLLBACK
moviesdb=&gt; SELECT xmin, xmax, ctid, title, release_year FROM film;
  xmin  |  xmax  | ctid  |      title       | release_year
--------+--------+-------+------------------+--------------
 853972 | 853974 | (0,1) | Sichinin Samurai |         1954
(1 row)

moviesdb=&gt; BEGIN; UPDATE film SET release_year = 1956 WHERE id = 47478;
BEGIN
UPDATE 1
moviesdb=&gt; SELECT xmin, xmax, ctid, title, release_year FROM film;
  xmin  | xmax | ctid  |      title       | release_year
--------+------+-------+------------------+--------------
 853975 |    0 | (0,2) | Sichinin Samurai |         1956
(1 row)

moviesdb=&gt; ROLLBACK;
ROLLBACK
moviesdb=&gt; SELECT xmin, xmax, ctid, title, release_year FROM film;
  xmin  |  xmax  | ctid  |      title       | release_year
--------+--------+-------+------------------+--------------
 853972 | 853975 | (0,1) | Sichinin Samurai |         1954
(1 row)</pre>
<p>What element in the queries above could be used as a surrogate &#8220;row version identifier?&#8221;  If you examine the changes carefully, you&#8217;ll notice that the <a href="http://www.postgresql.org/docs/current/static/ddl-system-columns.html">xmin system column</a> provides that capability. The ctid, a row locator, on the other hand, does not survive the VACUUM operation, and xmax is only used when a row is deleted (or updated, causing it to move).</p>
<p>So my suggestion, in terms of web user interfaces, is that fetching a row for a possible update should include the xmin value, e.g., in the get() method of the <a href="https://github.com/jmafc/database-ui-tutorial/blob/master/werkzeug/bl/film.py">Film class</a>, use the following:</p>
<pre>    def get(self, db):
        try:
            row = db.fetchone(
                "SELECT xmin, title, release_year FROM film WHERE id = %s",
                (self.id,))</pre>
<p>The xmin value can then be sent as a hidden field to the web client, and used in the update() method to implement optimistic concurrency control.</p>
<p><strong>Update:</strong> The DB UI Tutorial tag <a href="https://github.com/jmafc/database-ui-tutorial/tree/v0.4.3">v0.4.3</a> now has an implementation of this concept for the command line client.</p>
<br />Filed under: <a href='http://pyrseas.wordpress.com/category/postgresql-2/'>PostgreSQL</a>, <a href='http://pyrseas.wordpress.com/category/python/'>Python</a>, <a href='http://pyrseas.wordpress.com/category/user-interfaces/'>User interfaces</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pyrseas.wordpress.com/1463/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pyrseas.wordpress.com/1463/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pyrseas.wordpress.com/1463/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pyrseas.wordpress.com/1463/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pyrseas.wordpress.com/1463/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pyrseas.wordpress.com/1463/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pyrseas.wordpress.com/1463/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pyrseas.wordpress.com/1463/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pyrseas.wordpress.com/1463/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pyrseas.wordpress.com/1463/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pyrseas.wordpress.com/1463/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pyrseas.wordpress.com/1463/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pyrseas.wordpress.com/1463/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pyrseas.wordpress.com/1463/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1463&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pyrseas.wordpress.com/2012/01/13/the-phantom-of-the-database-part-4/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0d235d4094b8dbf2cd9932667d828795?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jmafc</media:title>
		</media:content>
	</item>
		<item>
		<title>Python Web Frameworks – Application Object</title>
		<link>http://pyrseas.wordpress.com/2012/01/10/python-web-frameworks-application-object/</link>
		<comments>http://pyrseas.wordpress.com/2012/01/10/python-web-frameworks-application-object/#comments</comments>
		<pubDate>Tue, 10 Jan 2012 05:33:29 +0000</pubDate>
		<dc:creator>jma</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[User interfaces]]></category>
		<category><![CDATA[bottle]]></category>
		<category><![CDATA[cherrypy]]></category>
		<category><![CDATA[diva]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[flask]]></category>
		<category><![CDATA[pesto]]></category>
		<category><![CDATA[pyramid]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[twisted]]></category>
		<category><![CDATA[user interfaces]]></category>
		<category><![CDATA[web.py]]></category>
		<category><![CDATA[web2py]]></category>
		<category><![CDATA[webob]]></category>
		<category><![CDATA[werkzeug]]></category>

		<guid isPermaLink="false">http://pyrseas.wordpress.com/?p=1424</guid>
		<description><![CDATA[In response to my previous post, someone asked &#8220;&#8230; what&#8217;s the point? How one way is better than the other?&#8221; My response was that I&#8217;m &#8220;not trying to judge these frameworks from the perspective of a developer (at least not &#8230; <a href="http://pyrseas.wordpress.com/2012/01/10/python-web-frameworks-application-object/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1424&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>In response to my <a title="Python Web Frameworks – Development Server" href="http://pyrseas.wordpress.com/2011/12/29/python-web-frameworks-development-server/">previous post</a>, someone <a href="http://news.ycombinator.com/item?id=3430379">asked</a><span style="color:#000000;"> &#8220;&#8230; what&#8217;s the point? How one way is better than the other?&#8221; </span>My response was that I&#8217;m &#8220;<span style="color:#000000;">not trying to judge these frameworks from the perspective of a developer (at least not completely), but rather from the POV of &#8216;if I were <em>writing</em> a framework, which features are essential, which nice to have, which I can disregard&#8217;&#8221; (emphasis added). Of course, I have my own biases as a developer as to what I consider &#8220;nice&#8221; or essential.<br />
</span></p>
<p><span style="color:#000000;"> With that clarification out of the way, let&#8217;s look at the next feature: the WSGI callable generally known as the <a href="http://www.python.org/dev/peps/pep-0333/#the-application-framework-side">application object</a>.</span></p>
<p><strong>Django</strong> doesn&#8217;t want developers to be concerned with this artifact. A Django application is the collection of model, views (controllers in standard MVC terminology) and templates (views) that gets run by the server. For those interested, the Django WSGI callable is an instance of WSGIHandler (in django.core.handlers.wsgi).</p>
<p>As best as I can tell,<strong> Twisted Web</strong> <a href="http://twistedmatrix.com/documents/current/web/howto/using-twistedweb.html#auto19">expects the developer to write the application object</a>. It will get called from the WSGIResponse run() method in twisted.web.wsgi. As its documentation says, Twisted Web is &#8220;a framework for doing things with the web&#8221; but is &#8220;not a &#8216;web framework&#8217; in the same sense&#8221; as Django, so it doesn&#8217;t fit well in this comparison.</p>
<p><strong>Pyramid</strong>&#8216;s <a href="http://docs.pylonsproject.org/projects/pyramid/en/1.2-branch/glossary.html#term-router">Router</a> class (in pyramid.router) is what implements the WSGI callable. The Router instance gets created from the <a href="http://docs.pylonsproject.org/projects/pyramid/en/1.2-branch/api/config.html#pyramid.config.Configurator">Configurator</a> class&#8217;s <a href="http://docs.pylonsproject.org/projects/pyramid/en/1.2-branch/narr/firstapp.html">make_wsgi_app</a>() method. Select Router attributes and methods:</p>
<ul>
<li>logger</li>
<li>root_factory</li>
<li>routes_mapper</li>
<li>request_factory</li>
<li>registry (from args)</li>
<li>handle_request()</li>
</ul>
<p>In <strong>CherryPy</strong>, the <a href="http://docs.cherrypy.org/stable/refman/_cptree.html#cherrypy._cptree.Application">Application</a> class is the application object, although it&#8217;s not generallly used directly. Instead a user root object is mounted on a <a href="http://docs.cherrypy.org/stable/refman/_cptree.html#cherrypy._cptree.Tree">Tree</a> which is a registry of these applications. Major attributes and methods:</p>
<ul>
<li>root (from args): root object (application handler)</li>
<li>namespaces, config: for configuration</li>
<li>wsgiapp(): a CPWSGIApp instance, to handle apps in a pipeline</li>
</ul>
<p>Being a support library,<strong> Werkzeug</strong> doesn&#8217;t include an application object, but it has a sample in its <a href="http://werkzeug.pocoo.org/docs/tutorial/#step-2-the-base-structure">Shortly example</a>. Major attributes and methods:</p>
<ul>
<li>dispatch_request(): dispatcher</li>
<li>jinja_env: template enviroment</li>
<li>url_map: Map() taking list of Rule()&#8217;s</li>
<li>error_404(): error handler</li>
<li>render_template(): template renderer</li>
</ul>
<p>Like Django, <strong>Web2py</strong> isn&#8217;t interested in having developers worry about the application object. Its WSGI callable is the standalone wsgibase() function, in gluon.main.</p>
<p>The <strong>web.py</strong> <a href="http://webpy.org/docs/0.3/api#web.application">application</a> class (yes, not capitalized) implements its WSGI callable. Major attributes and methods:</p>
<ul>
<li>autoreload (from args)</li>
<li>init_mapping (from args)</li>
<li>request()</li>
<li>handle(): matches path to mapping</li>
<li>run(): runs the developer server</li>
<li>notfound(), internalerror(): error handlers</li>
</ul>
<p><strong>Flask</strong>&#8216;s <a href="http://flask.pocoo.org/docs/api/#application-object">Flask</a> class is its application object, derived from flask.helpers._PackageBoundObject. Selected attributes and methods (in addition to those in Werkzeug&#8217;s example above):</p>
<ul>
<li>static_url_path, static_folder (from args)</li>
<li>instance_path (from args or auto-determined)</li>
<li>view_functions</li>
<li>before/after_xxx_funcs (dicts)</li>
<li>logger</li>
<li>run()</li>
<li>route(): decorator for URL rules</li>
<li>error_handler_spec (a dict)</li>
<li>errorhandler(): decorator for error handler functions<br />
<strong></strong></li>
</ul>
<p>Like Werkzeug,<strong> WebOb</strong> doesn’t include an application object, but it has a sample in its <a href="http://docs.webob.org/en/latest/wiki-example.html#creating-an-application">wiki example</a>, most of it very specific to the example.</p>
<p><strong>Bottle</strong>&#8216;s <a href="http://bottlepy.org/docs/dev/api.html#the-bottle-class">Bottle</a> class is its WSGI callable. Major attributes and methods:</p>
<ul>
<li>routes (list) and router (class Router instance)</li>
<li>config (class ConfigDict instance)</li>
<li>mount(): to mount an app at a given point</li>
<li>match(): to search for matching routes</li>
<li>route(): decorator to bind a function to a URL</li>
</ul>
<p><strong>Pesto</strong>&#8216;s <a href="http://www.ollycope.com/software/pesto/dispatch.html#pesto.dispatch.DispatcherApp">DispatcherApp</a> class is its application object. Major attributes and methods:</p>
<ul>
<li>prefix (from args): a &#8220;mount&#8221; point</li>
<li>matchpattern(), match(): matches URLs (match is decorator)</li>
<li>urlfor(): handler/dispatcher to URL converter</li>
<li>gettarget(): returns a four-part tuple from the URI</li>
<li>status404_application(): error handler</li>
</ul>
<p><strong>Diva</strong>&#8216;s <a href="http://code.cmlenz.net/diva/wiki/ApplicationObject">Application</a> class is the object of interest. Select attributes and methods:</p>
<ul>
<li>config (from kwargs), configure()</li>
<li>routing_cfg and routing</li>
<li>locale_dir (from args)</li>
<li>template_dirs (from args)</li>
<li>templates(): template loader</li>
<li>prepare() and cleanup(): before and after methods</li>
</ul>
<p><strong>Summary</strong>: For developers who care about writing application code, Django and Web2py and to some extent Pyramid and CherryPy hide the existence of the WSGI callable, while other frameworks require that the programmer instantiate it or invoke it. If I were to write a framework, I&#8217;d want to make it easy on the developer as the former projects do, but wouldn&#8217;t keep it completely out of sight.</p>
<br />Filed under: <a href='http://pyrseas.wordpress.com/category/python/'>Python</a>, <a href='http://pyrseas.wordpress.com/category/user-interfaces/'>User interfaces</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pyrseas.wordpress.com/1424/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pyrseas.wordpress.com/1424/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pyrseas.wordpress.com/1424/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pyrseas.wordpress.com/1424/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pyrseas.wordpress.com/1424/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pyrseas.wordpress.com/1424/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pyrseas.wordpress.com/1424/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pyrseas.wordpress.com/1424/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pyrseas.wordpress.com/1424/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pyrseas.wordpress.com/1424/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pyrseas.wordpress.com/1424/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pyrseas.wordpress.com/1424/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pyrseas.wordpress.com/1424/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pyrseas.wordpress.com/1424/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1424&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pyrseas.wordpress.com/2012/01/10/python-web-frameworks-application-object/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0d235d4094b8dbf2cd9932667d828795?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jmafc</media:title>
		</media:content>
	</item>
		<item>
		<title>Business Logic in the Database</title>
		<link>http://pyrseas.wordpress.com/2012/01/02/business-logic-in-the-database/</link>
		<comments>http://pyrseas.wordpress.com/2012/01/02/business-logic-in-the-database/#comments</comments>
		<pubDate>Mon, 02 Jan 2012 20:17:36 +0000</pubDate>
		<dc:creator>jma</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[business logic]]></category>
		<category><![CDATA[constraints]]></category>
		<category><![CDATA[postgresql]]></category>

		<guid isPermaLink="false">http://pyrseas.wordpress.com/?p=1401</guid>
		<description><![CDATA[Chris Travers recently responded to Tony Marston&#8217;s critique of an earlier post where Chris advocated &#8220;intelligent databases&#8221;1. Chris&#8217; response is well reasoned, particularly his point that once a database is accessed by more than a single application or via third-party &#8230; <a href="http://pyrseas.wordpress.com/2012/01/02/business-logic-in-the-database/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1401&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Chris Travers <a href="http://ledgersmbdev.blogspot.com/2012/01/reply-to-tony-marstons-advocacy-of.html">recently responded</a> to Tony Marston&#8217;s <a href="http://www.tonymarston.co.uk/php-mysql/the-case-against-intelligent-databases.html">critique</a> of an <a href="http://ledgersmbdev.blogspot.com/2011/11/case-for-intelligent-databases.html">earlier post</a> where Chris advocated &#8220;intelligent databases&#8221;<sup>1</sup>. Chris&#8217; response is well reasoned, particularly his point that once a database is accessed by more than a single application or via third-party tools, it&#8217;s almost a given that one should attempt to push &#8220;intelligence&#8221; and business logic into the database if possible.</p>
<p>However, there is a paragraph in Tony&#8217;s post that merits further scrutiny:</p>
<blockquote><p>The database has always been a dumb data store, with all the business logic held separately within the application. This is an old idea which is now reinforced by the single responsibility principle. It is the application code which is responsible for the application logic while the database is responsible for the storing and retrieval of data. Modern databases also have the ability to enforce data integrity, manage concurrency control, backup, recovery and replication while also controlling data access and maintaining database security.</p></blockquote>
<p>If a database (actually, a shortening of DBMS—a combination of the data and the software that manages it) has always been dumb, then presumably one would never specify UNIQUE indexes. It is a business requirement that invoice or employee numbers be unique, so if all the business logic should reside in the application, then the DBA should only create a regular index and the application —all the applications and tools!— should enforce uniqueness.</p>
<p>Tony&#8217;s mention of &#8220;data integrity&#8221; is somewhat ambiguous because different people have varied understandings of what that covers. As C. J. Date points out, &#8220;integrity &#8230; is the part [of the relational model] that has changed [or <em>evolved</em>] the most over the years.&#8221;<sup>2</sup> Perhaps Tony believes that primary keys, and unique and referential constraints should be enforced by the DBMS, but apparently an integrity constraint such as &#8220;No supplier with status less than 20 supplies any part in a quantity greater than 500&#8243;<sup>3</sup> should instead only be code in an application (make that all applications that access that database).</p>
<p>As for me, as I pointed out <a title="Where to CHECK your premises" href="http://pyrseas.wordpress.com/2011/08/01/where-to-check-your-premises/">earlier</a>, &#8220;constraints should be implemented, preferably declaratively, in the database schema&#8221; while &#8220;type constraints &#8230; should <em>also</em> be implemented in the user interface&#8221; (emphasis added). Ideally, the user interface should derive its code directly from the schema.</p>
<p><strong>Update:</strong> Many thanks to everyone who participated in the discussion. I think we&#8217;ve covered just about every angle pro or con incorporating business logic in the database, so I&#8217;ve closed comments now.</p>
<p><strong>Update 2:</strong> Chris has an <a href="http://ledgersmbdev.blogspot.com/2012/01/thoughts-on-what-to-put-in-database.html">update post</a> that may be of interest.</p>
<hr />
<p><sup>1</sup> Interestingly, the first time I heard the term &#8220;intelligent database&#8221; it was from <a href="http://kellblog.com/">Dave Kellogg</a> giving a marketing presentation for <a href="http://en.wikipedia.org/wiki/Ingres_%28database%29">Ingres</a> 6.3, which had incorporated some of the features in the <a href="http://www.eecs.berkeley.edu/Pubs/TechRpts/1986/ERL-86-85.pdf">UC Berkeley POSTGRES project</a>.<br />
<sup>2</sup> Date, C. J. <a href="http://www.amazon.com/gp/product/0321197844?ie=UTF8&amp;tag=freedomcircle"><em>An Introduction to Database Systems, 8th Edition</em></a>. 2004, p. 253.<br />
<sup>3</sup> Ibid., p. 254.</p>
<br />Filed under: <a href='http://pyrseas.wordpress.com/category/postgresql-2/'>PostgreSQL</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pyrseas.wordpress.com/1401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pyrseas.wordpress.com/1401/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pyrseas.wordpress.com/1401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pyrseas.wordpress.com/1401/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pyrseas.wordpress.com/1401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pyrseas.wordpress.com/1401/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pyrseas.wordpress.com/1401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pyrseas.wordpress.com/1401/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pyrseas.wordpress.com/1401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pyrseas.wordpress.com/1401/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pyrseas.wordpress.com/1401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pyrseas.wordpress.com/1401/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pyrseas.wordpress.com/1401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pyrseas.wordpress.com/1401/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1401&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pyrseas.wordpress.com/2012/01/02/business-logic-in-the-database/feed/</wfw:commentRss>
		<slash:comments>55</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0d235d4094b8dbf2cd9932667d828795?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jmafc</media:title>
		</media:content>
	</item>
		<item>
		<title>Python Web Frameworks &#8211; Development Server</title>
		<link>http://pyrseas.wordpress.com/2011/12/29/python-web-frameworks-development-server/</link>
		<comments>http://pyrseas.wordpress.com/2011/12/29/python-web-frameworks-development-server/#comments</comments>
		<pubDate>Thu, 29 Dec 2011 20:13:03 +0000</pubDate>
		<dc:creator>jma</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[User interfaces]]></category>
		<category><![CDATA[bottle]]></category>
		<category><![CDATA[cherrypy]]></category>
		<category><![CDATA[diva]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[flask]]></category>
		<category><![CDATA[pesto]]></category>
		<category><![CDATA[pyramid]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[twisted]]></category>
		<category><![CDATA[user interfaces]]></category>
		<category><![CDATA[web.py]]></category>
		<category><![CDATA[web2py]]></category>
		<category><![CDATA[webob]]></category>
		<category><![CDATA[werkzeug]]></category>

		<guid isPermaLink="false">http://pyrseas.wordpress.com/?p=1344</guid>
		<description><![CDATA[One of the most frequent tasks of a web developer is running the app while it&#8217;s being written. So we&#8217;ll begin our examination of Python web frameworks by looking at the development servers provided and how does one run the &#8230; <a href="http://pyrseas.wordpress.com/2011/12/29/python-web-frameworks-development-server/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1344&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>One of the most frequent tasks of a web developer is running the app while it&#8217;s being written. So we&#8217;ll begin our <a title="Python Web Frameworks – Candidates" href="http://pyrseas.wordpress.com/2011/12/26/python-web-frameworks-candidates/">examination</a> of Python web frameworks by looking at the development servers provided and how does one run the app.</p>
<p><strong>Django</strong> developers are used to invoking</p>
<pre>python manage.py runserver</pre>
<p>The <a href="https://docs.djangoproject.com/en/1.3/ref/django-admin/#runserver-port-or-address-port">runserver</a> option runs Django&#8217;s development server which is invoked via the run() function in django.core.servers.basehttp. This in turn runs a WSGIServer which is derived from Python&#8217;s wsgiref&#8217;s <a href="http://docs.python.org/library/wsgiref.html#module-wsgiref.simple_server">simple_server</a>.</p>
<p><strong>Twisted Web</strong> has its own server based on its core <a href="http://twistedmatrix.com/documents/current/core/howto/reactor-basics.html">reactor object</a>. Here&#8217;s a simple usage example:</p>
<pre>from twisted.web import server, resource
from twisted.internet import reactor

class HelloResource(resource.Resource):
    ...

reactor.listenTCP(8080, server.Site(HelloResource()))
reactor.run()</pre>
<p><strong>Pyramid</strong> <a href="http://docs.pylonsproject.org/projects/pyramid/en/1.2-branch/narr/firstapp.html">uses</a> Paste&#8217;s <a href="http://pythonpaste.org/modules/httpserver.html#module-paste.httpserver">paste.httpserver</a> which in turn is based on Python&#8217;s <a href="http://docs.python.org/library/basehttpserver.html">BaseHTTPServer</a>. Sample usage:</p>
<pre>from paste.httpserver import serve
from pyramid.config import Configurator

def hello_world(request):
   ... 

if __name__ == '__main__':
   config = Configurator()
   ...
   app = config.make_wsgi_app()
   serve(app, host='0.0.0.0')</pre>
<p>In <strong>CherryPy</strong>, the normal server is cherrypy.engine which is invoked as:</p>
<pre>cherrypy.engine.start()
cherrypy.engine.block()</pre>
<p>cherrypy.engine is actually an instance of <a href="http://docs.cherrypy.org/stable/refman/process/wspbus.html#cherrypy.process.wspbus.Bus">cherrypy.process.wspbus.Bus</a>. A simpler alternative to the engine calls is to use:</p>
<pre>cherrypy.quickstart(app())</pre>
<p>Under the covers, CherryPy also defines a global <tt>server</tt> variable that is an instance of <a href="http://docs.cherrypy.org/stable/refman/_cpserver.html#cherrypy._cpserver.Server">Server</a> which implements the HTTP server, with help from cherrypy._cpwsgi_server.CPWSGIServer.</p>
<p><strong>Werkzeug</strong> has a <a href="http://werkzeug.pocoo.org/docs/serving/">built-in server</a>, used as follows:</p>
<pre>from werkzeug.serving import run_simple
from myproject import make_app

app = make_app(...)
run_simple('localhost', 8080, app, use_reloader=True)</pre>
<p><a href="http://werkzeug.pocoo.org/docs/serving/#werkzeug.serving.run_simple">run_simple()</a> invokes its own (werkzeug.serving) make_server which creates one of three types of XxxWSGIServer&#8217;s, which are derived from Python&#8217;s BaseHTTPServer.HTTPServer.</p>
<p>When <strong>Web2py</strong> is invoked, a GUI dialog is shown. The dialog is implemented in gluon.widget and its web2pyDialog.start method creates a main.HttpServer. gluon.main&#8217;s HttpServer class uses the <a href="https://launchpad.net/rocket">Rocket server</a> whose code is in gluon.rocket.</p>
<p>In <strong>web.py</strong>, to run an application you instantiate a <a href="http://webpy.org/docs/0.3/api#web.application">web.application</a> and invoke its run() method, e.g.:</p>
<pre>app = web.application(urls, globals())
app.run()</pre>
<p>This eventually runs a BaseHTTPServer.HTTPServer from the Python standard library.</p>
<p><strong>Flask</strong>&#8216;s WSGI application class (Flask) has a <a href="http://flask.pocoo.org/docs/api/#flask.Flask.run">run()</a> method:</p>
<pre>run(host='127.0.0.1', port=5000, debug=None, **options)</pre>
<p>This invokes the Werkzeug serving.run_simple function (see above).</p>
<p><strong>WebOb</strong> doesn&#8217;t offer any server per se, but <a href="http://docs.webob.org/en/latest/do-it-yourself.html#serving-your-application">suggests</a> using Paste&#8217;s httpserver.serve or wsgiref.simple_server.</p>
<p><strong>Bottle</strong> has a <a href="http://bottlepy.org/docs/dev/api.html#bottle.run">standalone run() function</a>:</p>
<pre>run(app=None, server='wsgiref', host='127.0.0.1', port=8080,
    interval=1, reloader=False, quiet=False, plugins=None, **kargs)</pre>
<p>This runs one of several web servers supported, by default, wsgiref, which uses the wsgiref.simple_server.</p>
<p><strong>Pesto</strong> suggests using the Python wsgiref directly, e.g.:</p>
<pre>import pesto
dispatcher = pesto.dispatcher_app()
...
httpd = make_server('', 8080, dispatcher)
httpd.serve_forever()</pre>
<p><strong>Diva</strong> <a href="http://code.cmlenz.net/diva/wiki/DevelopmentServer#DevelopmentServer">uses</a> Python&#8217;s WSGIServer from the standard library to implement its main() and serve() standalone functions. The former can be used as follows:</p>
<pre>from diva.core import Application
from diva.server import main

class MyApp(Application): pass

main(MyApp())</pre>
<p><strong>Summary</strong>: With the exception of Twisted and CherryPy, all frameworks base their development servers on the standard library&#8217;s wsgiref or BaseHTTPServer, Paste or Rocket (which claims to be CherryPy-compatible). Lesson for prospective framework creators: Don&#8217;t write your own server. However, you may want to enhance your server with auto-reloading, threading, debugging. etc.</p>
<p>There are two approaches to running the app or server. Django and Web2py don&#8217;t want the developer to bother with writing app.run() or similar, the other frameworks expect the programmer to plug the various pieces together.</p>
<p>Best wishes for 2012 to all readers!</p>
<br />Filed under: <a href='http://pyrseas.wordpress.com/category/python/'>Python</a>, <a href='http://pyrseas.wordpress.com/category/user-interfaces/'>User interfaces</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pyrseas.wordpress.com/1344/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pyrseas.wordpress.com/1344/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pyrseas.wordpress.com/1344/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pyrseas.wordpress.com/1344/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pyrseas.wordpress.com/1344/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pyrseas.wordpress.com/1344/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pyrseas.wordpress.com/1344/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pyrseas.wordpress.com/1344/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pyrseas.wordpress.com/1344/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pyrseas.wordpress.com/1344/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pyrseas.wordpress.com/1344/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pyrseas.wordpress.com/1344/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pyrseas.wordpress.com/1344/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pyrseas.wordpress.com/1344/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1344&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pyrseas.wordpress.com/2011/12/29/python-web-frameworks-development-server/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0d235d4094b8dbf2cd9932667d828795?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jmafc</media:title>
		</media:content>
	</item>
		<item>
		<title>Python Web Frameworks &#8211; Candidates</title>
		<link>http://pyrseas.wordpress.com/2011/12/26/python-web-frameworks-candidates/</link>
		<comments>http://pyrseas.wordpress.com/2011/12/26/python-web-frameworks-candidates/#comments</comments>
		<pubDate>Mon, 26 Dec 2011 05:05:00 +0000</pubDate>
		<dc:creator>jma</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[User interfaces]]></category>
		<category><![CDATA[bottle]]></category>
		<category><![CDATA[cherrypy]]></category>
		<category><![CDATA[diva]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[flask]]></category>
		<category><![CDATA[pesto]]></category>
		<category><![CDATA[pyramid]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[twisted]]></category>
		<category><![CDATA[user interfaces]]></category>
		<category><![CDATA[web.py]]></category>
		<category><![CDATA[web2py]]></category>
		<category><![CDATA[webob]]></category>
		<category><![CDATA[werkzeug]]></category>

		<guid isPermaLink="false">http://pyrseas.wordpress.com/?p=1308</guid>
		<description><![CDATA[I&#8217;ve been researching web frameworks, partly with a view to writing my own, and thought I&#8217;d share my findings. This first post will present the candidates briefly and subsequent posts will delve into particular features. The candidates are presented based on &#8230; <a href="http://pyrseas.wordpress.com/2011/12/26/python-web-frameworks-candidates/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1308&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been researching web frameworks, partly with a view to writing my own, and thought I&#8217;d share my findings. This first post will present the candidates briefly and subsequent posts will delve into particular features.</p>
<p>The candidates are presented based on the number of users as found on <a href="http://www.ohloh.net/p">Ohloh</a>, as a rough measure of popularity.  Each includes the number of downloads for the latest release on <a href="http://pypi.python.org/pypi">PyPI</a> (sometimes misleading if a package had a recent release) and the salient parts of its advertised description (<em>caveat emptor</em>!)<em>.</em> All of them are open source and written in Python, but some of them are WSGI libraries rather than full frameworks.</p>
<p><a href="https://www.djangoproject.com/">Django</a> (843 users, 126,426 downloads): A &#8220;high-level &#8230; Web framework that encourages rapid development and clean, pragmatic design.&#8221;</p>
<p><a href="http://twistedmatrix.com/trac/wiki/TwistedWeb">Twisted Web</a> (136 users, 14,413 downloads [both for Twisted]):  An &#8220;HTPP server that can be used as a library or run &#8230; stand-alone &#8230;, an HTML templating engine [and] an HTTP client library.&#8221;</p>
<p><a href="http://www.pylonsproject.org/projects/pyramid/about">Pyramid</a> (aka Pylons on Ohloh, 125 users, 606 + 640 downloads): A &#8220;very general &#8230; web framework [designed] to make it easier for a developer to create an arbitrary web application.&#8221;</p>
<p><a href="http://www.cherrypy.org/">CherryPy</a> (75 users, PyPI download info not available): A &#8221;minimalist &#8230; pythonic, object-oriented web framework.&#8221;</p>
<p><a href="http://werkzeug.pocoo.org/">Werkzeug</a> (31 users, 4225 downloads): A &#8220;WSGI utility library, &#8230; [it] is Simple &#8230; And Powerful.&#8221;</p>
<p><a href="http://www.web2py.com/">Web2py</a> (21 users, 1157 downloads): A &#8220;full-stack framework for rapid development of fast, scalable, secure and portable database-driven web-based applications.&#8221;</p>
<p><a href="http://webpy.org/">Web.py</a> (18 users, 11,708 downloads): A &#8220;web framework &#8230; that is as simple as it is powerful&#8221; (hmmm &#8230; see Werkzeug above).</p>
<p><a href="http://flask.pocoo.org/">Flask</a> (16 users, 42,657 downloads): A &#8220;microframework &#8230; based on Werkzeug, Jinja 2 and good intentions.&#8221;</p>
<p><a href="http://www.webob.org/">WebOb</a> (16 users, 29,664 downloads): A &#8220;library that provides wrappers around the WSGI request environment, and an object to help create WSGI responses.&#8221;</p>
<p><a href="http://bottlepy.org/docs/dev/">Bottle</a> (4 users, 163 downloads): A &#8220;fast, simple and lightweight WSGI micro web-framework.&#8221;</p>
<p><a href="http://www.ollycope.com/software/pesto/">Pesto</a> (no users, 421 downloads): Not a framework, but a library for &#8220;writing WSGI web applications.&#8221;</p>
<p><a href="http://code.cmlenz.net/diva/">Diva</a> (not on Ohloh or PyPI): This is Christopher Lenz&#8217;s  framework experimentation sandbox: &#8220;a lightweight web framework &#8230; built on top of WSGI and integrated with &#8230; Genshi.&#8221; My first, unpublished attempt at writing a framework was based on Diva.</p>
<p>Left Out: I had to draw the line somewhere. Compared to Richard Jones&#8217; <a href="http://www.slideshare.net/r1chardj0n3s/web-microframework-battle">micro-framework battle</a>, I included three of what he called &#8220;mega frameworks&#8221; and excluded three of his micro frameworks. For the record, here are the ones I left out: <a href="http://aspen.io/">Aspen</a>, <a href="http://bobo.digicool.com/">Bobo</a>, <a href="http://www.cubicweb.org/">CubicWeb</a>, <a href="http://grok.zope.org/">Grok</a>, <a href="https://github.com/toastdriven/itty">Itty</a>, <a href="https://bitbucket.org/AdmiralNemo/milla">Milla</a>, <a href="http://www.nagare.org/">Nagare</a>, <a href="https://launchpad.net/nevow">Nevow</a>, <a href="http://adeel.github.com/pump/">Pump</a>, <a href="http://code.google.com/p/pyjamas/">Pyjamas</a>, <a href="http://www.pylonsproject.org/projects/pylons-framework/about">Pylons</a>, <a href="http://pythonpaste.org/">Python Paste</a>, <a href="http://www.quixote.ca/">Quixote</a>, <a href="http://spyce.sourceforge.net/">Spyce</a>, <a href="http://www.tornadoweb.org/">Tornado</a>, <a href="http://www.turbogears.org/">TurboGears</a>, <a href="http://www.webwareforpython.org/">Webware</a>, <a href="http://zope2.zope.org/">Zope 2</a> and <s>Zope 3</s><a href="http://bluebream.zope.org/">Bluebream</a>. But that&#8217;s not all: see the <a href="http://wiki.python.org/moin/WebFrameworks">Python.org wiki</a>, <a href="http://www.wsgi.org/en/latest/frameworks.html">WSGI.org</a> and <a href="http://en.wikipedia.org/wiki/Category:Python_web_application_frameworks">Wikipedia</a>.</p>
<p>Unlike Richard, I will not attempt to develop an application with each framework. Instead, I&#8217;ll analyze specific features along the lines of Christopher&#8217;s <a href="http://code.cmlenz.net/diva#Documentation">Diva documentation</a>.</p>
<br />Filed under: <a href='http://pyrseas.wordpress.com/category/python/'>Python</a>, <a href='http://pyrseas.wordpress.com/category/user-interfaces/'>User interfaces</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pyrseas.wordpress.com/1308/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pyrseas.wordpress.com/1308/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pyrseas.wordpress.com/1308/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pyrseas.wordpress.com/1308/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pyrseas.wordpress.com/1308/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pyrseas.wordpress.com/1308/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pyrseas.wordpress.com/1308/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pyrseas.wordpress.com/1308/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pyrseas.wordpress.com/1308/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pyrseas.wordpress.com/1308/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pyrseas.wordpress.com/1308/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pyrseas.wordpress.com/1308/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pyrseas.wordpress.com/1308/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pyrseas.wordpress.com/1308/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1308&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pyrseas.wordpress.com/2011/12/26/python-web-frameworks-candidates/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0d235d4094b8dbf2cd9932667d828795?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jmafc</media:title>
		</media:content>
	</item>
		<item>
		<title>Design Notes on Database Application Development</title>
		<link>http://pyrseas.wordpress.com/2011/12/19/design-notes-on-database-application-development/</link>
		<comments>http://pyrseas.wordpress.com/2011/12/19/design-notes-on-database-application-development/#comments</comments>
		<pubDate>Mon, 19 Dec 2011 05:01:02 +0000</pubDate>
		<dc:creator>jma</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[User interfaces]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[user interfaces]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[web2py]]></category>
		<category><![CDATA[rant]]></category>
		<category><![CDATA[nosql]]></category>

		<guid isPermaLink="false">http://pyrseas.wordpress.com/?p=1281</guid>
		<description><![CDATA[I recently took a brief look at web2py since its Database Abstraction Layer (DAL) sounded interesting. After following the tutorials in the Overview chapter, I ended up not delving into DAL.  Instead, I revisited Ruby on Rails which I had &#8230; <a href="http://pyrseas.wordpress.com/2011/12/19/design-notes-on-database-application-development/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1281&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I recently took a brief look at <a href="http://www.web2py.com/book">web2py</a> since its Database Abstraction Layer (DAL) sounded interesting. After following the tutorials in the Overview chapter, I ended up not delving into DAL.  Instead, I revisited <a href="http://rubyonrails.org/">Ruby on Rails</a> which I had last looked circa 2005 when its support for PostgreSQL was rather weak. Although that has improved, the basic approach of Rails hasn&#8217;t and is very similar to web2py&#8217;s as well as Django.</p>
<p>The essence of these full stack frameworks is that the developer —or should I say programmer— knows how to design classes and that that design can be transformed into a relational database design mechanically and flawlessly. Maybe I&#8217;m biased because my first involvements in software engineering were in the areas of IT system design, but the latter premise seems like a very weak foundation for developing robust systems.</p>
<p>Maybe this also explains, in part, why NoSQL solutions have cropped up and found a following. It&#8217;s much easier —albeit not reliable or sound— to design a system when you &#8220;liberate&#8221; yourself from the &#8220;straitjacket&#8221; constraints of a database design (aka <a href="http://en.wikipedia.org/wiki/Database_schema">schema</a>). However, in my experience, most systems beyond the blog/wiki/toy database examples used in tutorials benefit from specialized data analysis and modeling that result in a formal database design.</p>
<p>If the database precedes the application development, it appears the Rails/Django/web2py approach is <a href="http://image.truckinweb.com/f/18252423+w750+st0/0904trweb_03_z+2008_turkey_rod_run_truck_show+backasswards_truck.jpg">back asswards</a>. If the database is available during development, doesn&#8217;t it make more sense to re-use the database design effort in creating the application rather than try to repeat it with Python or Ruby classes?</p>
<p>The Pyrseas project, in its quest to rescue <a href="http://www.andromeda-project.org/">Andromeda</a>, plans to implement a utility to help in database application development (tentatively named <a href="http://pyrseas.readthedocs.org/en/latest/overview.html"><em>dbappgen</em></a> but that may change). The utility will start off by connecting to a database and will allow the developer to create the application based on the tables and other objects present in it, not the other way around. If database changes are needed, they can be made there first, not by imposing some application-induced &#8220;migration&#8221; (as web2py does).</p>
<p>Since Pyrseas&#8217; <a href="http://pyrseas.readthedocs.org/en/latest/overview.html">dbtoyaml</a> utility already outputs a YAML/JSON description of a database, it may even be possible to conduct an application development exercise, at least in part, without connecting to the database. For example, if the developer invokes <tt>dbappgen moviesdb</tt>, the utility could first check whether a file named <tt>moviesdb.yaml</tt> (or with similar extensions) exists in the current directory and if so, read it and recreate in memory the PostgreSQL catalogs, thus allowing &#8220;offline&#8221; development.</p>
<p>In other news, due to the <a href="http://lucumr.pocoo.org/2011/12/7/thoughts-on-python3/">recent discussions</a> regarding Python 3, my <a title="Dueling Frameworks, revisited" href="http://pyrseas.wordpress.com/2011/10/17/dueling-frameworks-revisited/">hopes that Werkzeug will be ported soon</a> have been dashed. It appears it&#8217;s either use WebOb or write my own framework (which ironically is <a href="http://lucumr.pocoo.org/2010/6/14/opening-the-flask/">what Armin recommended</a>).</p>
<br />Filed under: <a href='http://pyrseas.wordpress.com/category/postgresql-2/'>PostgreSQL</a>, <a href='http://pyrseas.wordpress.com/category/python/'>Python</a>, <a href='http://pyrseas.wordpress.com/category/user-interfaces/'>User interfaces</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pyrseas.wordpress.com/1281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pyrseas.wordpress.com/1281/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pyrseas.wordpress.com/1281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pyrseas.wordpress.com/1281/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pyrseas.wordpress.com/1281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pyrseas.wordpress.com/1281/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pyrseas.wordpress.com/1281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pyrseas.wordpress.com/1281/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pyrseas.wordpress.com/1281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pyrseas.wordpress.com/1281/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pyrseas.wordpress.com/1281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pyrseas.wordpress.com/1281/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pyrseas.wordpress.com/1281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pyrseas.wordpress.com/1281/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1281&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pyrseas.wordpress.com/2011/12/19/design-notes-on-database-application-development/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0d235d4094b8dbf2cd9932667d828795?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jmafc</media:title>
		</media:content>
	</item>
		<item>
		<title>The Phantom of the Database &#8211; Part 3</title>
		<link>http://pyrseas.wordpress.com/2011/11/28/the-phantom-of-the-database-part-3/</link>
		<comments>http://pyrseas.wordpress.com/2011/11/28/the-phantom-of-the-database-part-3/#comments</comments>
		<pubDate>Mon, 28 Nov 2011 05:09:52 +0000</pubDate>
		<dc:creator>jma</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[User interfaces]]></category>
		<category><![CDATA[concurrency control]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[user interfaces]]></category>

		<guid isPermaLink="false">http://pyrseas.wordpress.com/?p=1240</guid>
		<description><![CDATA[In the previous episode: Alice and Bob were trying to simultaneously update the title of the following row of the film table:   id   &#124;     title      &#124; release_year -------+----------------+--------------  47478 &#124; Seven  Samurai &#124;         1956 User Transaction Correctness In the &#8230; <a href="http://pyrseas.wordpress.com/2011/11/28/the-phantom-of-the-database-part-3/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1240&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>In the <a title="The Phantom of the Database – Part 2" href="http://pyrseas.wordpress.com/2011/11/21/the-phantom-of-the-database-part-2/">previous episode</a>: Alice and Bob were trying to simultaneously update the title of the following row of the film table:</p>
<pre>  id   |     title      | release_year
-------+----------------+--------------
 47478 | Seven  Samurai |         1956</pre>
<h3>User Transaction Correctness</h3>
<p>In the <a title="The Phantom of the Database – Part 1" href="http://pyrseas.wordpress.com/2011/11/07/the-phantom-of-the-database-part-1/">first episode</a>, Carol also wanted to concurrently change the release_year to 1954. Let us now consider her update in conjunction with one of the others.</p>
<p>If Bob modifies the title and Carol changes the year —provided our SQL statements only include the updated fields— there will be no problem. In other words, the changes can be merged, just as when Alice updates one section of a Wikipedia page and Bob changes another section of the same page (Note to self: have to talk to them about this <a href="http://en.wikipedia.org/wiki/Help:Edit_conflict">moonlighting</a>).</p>
<p>So the problem with Alice&#8217;s and Bob&#8217;s updates to the title (one to remove the extra space, the other to change it to Japanese) is that they <em>cannot</em> be merged. How can we implement a correct user transaction without incurring the penalty of locking the row in question?</p>
<h3>Optimistic Concurrency Control</h3>
<p>Richard Stephan was on the right track when he asked in a comment to the previous post: Should the application be using a pessimistic or an optimistic locking technique?</p>
<p><a href="http://en.wikipedia.org/wiki/Optimistic_concurrency_control">Optimistic concurrency control</a> (aka optimistic &#8220;locking&#8221;) is a transaction design approach that avoids the overhead of locking. As stated in the Wikipedia article, the &#8220;stateless nature of HTTP makes locking infeasible for web user interfaces,&#8221; so it&#8217;s almost a given that we should use OCC for our interface.</p>
<p>OCC involves validating that the record we updated was the correct one. A simple way to do this is to add a qualification to the original UPDATE that does the validation for us. For example, the DB-API cursor execute call could be coded as follows:</p>
<pre>cursor.execute("UPDATE film SET title = %s "
               "WHERE id = %s AND title = %s",
               (newrec.title, oldrec.id, oldrec.title))</pre>
<p>Above, <tt>newrec</tt> refers to the new record instance and <tt>oldrec</tt> to the old one. So both Alice and Bob would send UPDATEs with &#8220;AND title = &#8216;Seven  Samurai&#8217;&#8221;. Naturally, since they&#8217;re both modifying the title, only one of the statements can succeed.</p>
<p>The downside of having to add the extra qualification —in the general case— is that the user could&#8217;ve changed several fields so each UPDATE would have to be customized accordingly. This will have a negative impact, among other things, on the query planner. In addition, the web interface would have to deal with two values for each field.</p>
<p>Alternatives to the extra qualification are to add either a version number for each row or a sufficiently granular timestamp that also acts as a versioning scheme. However, since we&#8217;re using PostgreSQL, perhaps we can use something else &#8230;</p>
<p>Stay tuned.</p>
<br />Filed under: <a href='http://pyrseas.wordpress.com/category/postgresql-2/'>PostgreSQL</a>, <a href='http://pyrseas.wordpress.com/category/python/'>Python</a>, <a href='http://pyrseas.wordpress.com/category/user-interfaces/'>User interfaces</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pyrseas.wordpress.com/1240/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pyrseas.wordpress.com/1240/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pyrseas.wordpress.com/1240/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pyrseas.wordpress.com/1240/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pyrseas.wordpress.com/1240/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pyrseas.wordpress.com/1240/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pyrseas.wordpress.com/1240/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pyrseas.wordpress.com/1240/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pyrseas.wordpress.com/1240/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pyrseas.wordpress.com/1240/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pyrseas.wordpress.com/1240/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pyrseas.wordpress.com/1240/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pyrseas.wordpress.com/1240/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pyrseas.wordpress.com/1240/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1240&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pyrseas.wordpress.com/2011/11/28/the-phantom-of-the-database-part-3/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0d235d4094b8dbf2cd9932667d828795?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jmafc</media:title>
		</media:content>
	</item>
		<item>
		<title>The Phantom of the Database &#8211; Part 2</title>
		<link>http://pyrseas.wordpress.com/2011/11/21/the-phantom-of-the-database-part-2/</link>
		<comments>http://pyrseas.wordpress.com/2011/11/21/the-phantom-of-the-database-part-2/#comments</comments>
		<pubDate>Mon, 21 Nov 2011 05:09:14 +0000</pubDate>
		<dc:creator>jma</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[User interfaces]]></category>
		<category><![CDATA[concurrency control]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[user interfaces]]></category>

		<guid isPermaLink="false">http://pyrseas.wordpress.com/?p=1197</guid>
		<description><![CDATA[In the previous episode: Alice, Bob and Carol were trying to simultaneously update the following row of the film table:   id   &#124;     title      &#124; release_year -------+----------------+--------------  47478 &#124; Seven  Samurai &#124;         1956 Alice wanted to remove the extra space &#8230; <a href="http://pyrseas.wordpress.com/2011/11/21/the-phantom-of-the-database-part-2/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1197&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>In the <a title="The Phantom of the Database – Part 1" href="http://pyrseas.wordpress.com/2011/11/07/the-phantom-of-the-database-part-1/">previous episode</a>: Alice, Bob and Carol were trying to simultaneously update the following row of the film table:</p>
<pre>  id   |     title      | release_year
-------+----------------+--------------
 47478 | Seven  Samurai |         1956</pre>
<p>Alice wanted to remove the extra space in the title, Bob was trying to change the title to the phonetic Japanese version and Carol was correcting the release year to 1954. To simplify the analysis we&#8217;ll now limit ourselves to Alice&#8217;s and Bob&#8217;s updates.</p>
<h3>The Lost Update Problem</h3>
<p>If Alice&#8217;s statement executes first, Bob&#8217;s change will overwrite her update. Similarly, if Bob&#8217;s statement takes precedence, his change will be overwritten. Appropriately, this is conventionally known as the <a href="http://en.wikipedia.org/wiki/Write%E2%80%93write_conflict"><em>lost update</em></a> problem. The updates are known as <em>blind writes</em> or <em>dirty writes</em>. How can our Python user interface prevent this problem?</p>
<p>The traditional solution to the lost update problem is to use <a href="http://en.wikipedia.org/wiki/Two-phase_locking">two-phase locking</a>. You can use PostgreSQL&#8217;s <a href="http://www.postgresql.org/docs/current/static/app-psql.html">psql</a> application to verify how this works (I used the PROMPT1 variable to show which user is issuing the statements).</p>
<p>Alice&#8217;s session starts as follows:</p>
<pre>alice@moviesdb=&gt; begin;
BEGIN
alice@moviesdb=&gt; select title from film where id = 47478;
     title      
----------------
 Seven  Samurai
(1 row)</pre>
<p>Bob&#8217;s session is identical but then he issues the UPDATE statement:</p>
<pre>bob@moviesdb=&gt; begin;
BEGIN
bob@moviesdb=&gt; select title from film where id = 47478;
     title      
----------------
 Seven  Samurai
(1 row)

bob@moviesdb=&gt; update film set title = 'Sichinin no Samurai' where id = 47478;
UPDATE 1</pre>
<p>When Alice tries her UPDATE, her session hangs:</p>
<pre>alice@moviesdb=&gt; update film set title = 'Seven Samurai' where id = 47478;</pre>
<p>You can examine the situation from another psql session (I cheated and excluded that session&#8217;s data). I won&#8217;t try to explain (or understand) all this but you can see that Alice&#8217;s session is waiting due to an ungranted lock.</p>
<pre>moviesdb=# select procpid, waiting, current_query from pg_stat_activity;
 procpid | waiting |                       current_query
---------+---------+-----------------------------------------------------------
   25747 | t       | update film set title = 'Seven Samurai' where id = 47478;
   25900 | f       | &lt;IDLE&gt; in transaction
(2 rows)

moviesdb=# select pid, relation::regclass, locktype, page, tuple, mode, granted
moviesdb-# from pg_locks order by pid, relation, locktype;
  pid  | relation  |   locktype    | page | tuple |       mode       | granted
-------+-----------+---------------+------+-------+------------------+---------
 25747 | film      | relation      |      |       | AccessShareLock  | t
 25747 | film      | relation      |      |       | RowExclusiveLock | t
 25747 | film      | tuple         |    0 |    37 | ExclusiveLock    | t
 25747 | film_pkey | relation      |      |       | AccessShareLock  | t
 25747 | film_pkey | relation      |      |       | RowExclusiveLock | t
 25747 |           | transactionid |      |       | ShareLock        | f
 25747 |           | transactionid |      |       | ExclusiveLock    | t
 25747 |           | virtualxid    |      |       | ExclusiveLock    | t
 25900 | film      | relation      |      |       | RowExclusiveLock | t
 25900 | film      | relation      |      |       | AccessShareLock  | t
 25900 | film_pkey | relation      |      |       | RowExclusiveLock | t
 25900 | film_pkey | relation      |      |       | AccessShareLock  | t
 25900 |           | transactionid |      |       | ExclusiveLock    | t
 25900 |           | virtualxid    |      |       | ExclusiveLock    | t
(14 rows)</pre>
<p>Bob&#8217;s COMMIT releases his locks &#8230;</p>
<pre>bob@moviesdb=&gt; commit;
COMMIT</pre>
<p>and Alice&#8217;s UPDATE now goes through:</p>
<pre>UPDATE 1
alice@moviesdb=&gt; commit;
COMMIT
alice@moviesdb=&gt; select title from film where id = 47478;
     title     
---------------
 Seven Samurai
(1 row)</pre>
<p>Hey, what happened? Alice&#8217;s UPDATE overwrote Bob&#8217;s! Wasn&#8217;t that supposed to be prevented?</p>
<p>Here is the rub: if it is important for the application to update the row as was presented to the user, then we need to add another qualification to the UPDATE, i.e., we need something like &#8220;<tt>and title = 'Seven  Samurai'</tt>&#8220;. We&#8217;ll discuss this in a future installment.</p>
<br />Filed under: <a href='http://pyrseas.wordpress.com/category/postgresql-2/'>PostgreSQL</a>, <a href='http://pyrseas.wordpress.com/category/python/'>Python</a>, <a href='http://pyrseas.wordpress.com/category/user-interfaces/'>User interfaces</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pyrseas.wordpress.com/1197/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pyrseas.wordpress.com/1197/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pyrseas.wordpress.com/1197/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pyrseas.wordpress.com/1197/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pyrseas.wordpress.com/1197/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pyrseas.wordpress.com/1197/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pyrseas.wordpress.com/1197/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pyrseas.wordpress.com/1197/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pyrseas.wordpress.com/1197/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pyrseas.wordpress.com/1197/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pyrseas.wordpress.com/1197/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pyrseas.wordpress.com/1197/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pyrseas.wordpress.com/1197/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pyrseas.wordpress.com/1197/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1197&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pyrseas.wordpress.com/2011/11/21/the-phantom-of-the-database-part-2/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0d235d4094b8dbf2cd9932667d828795?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jmafc</media:title>
		</media:content>
	</item>
		<item>
		<title>PGBR 2011 recap</title>
		<link>http://pyrseas.wordpress.com/2011/11/14/pgbr-2011-recap/</link>
		<comments>http://pyrseas.wordpress.com/2011/11/14/pgbr-2011-recap/#comments</comments>
		<pubDate>Mon, 14 Nov 2011 05:04:10 +0000</pubDate>
		<dc:creator>jma</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[test driven development]]></category>

		<guid isPermaLink="false">http://pyrseas.wordpress.com/?p=1200</guid>
		<description><![CDATA[This is a summary of what I saw and heard at PGBR 2011. The night before the conference I had the opportunity to greet Alvaro Herrera, Bruce Momjian, Dave Page and Greg Smith. The conference opened on Thursday 3rd November &#8230; <a href="http://pyrseas.wordpress.com/2011/11/14/pgbr-2011-recap/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1200&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/tellesr/6322484113/sizes/l/in/pool-1655373@N21/"><img class="alignright" title="PGBR 2011" src="http://farm7.static.flickr.com/6035/6322484113_79fba7eb8a_m.jpg" alt="PGBR 2011 group photo" width="240" height="144" /></a>This is a summary of what I saw and heard at <a title="PostgreSQL Conference Brasil 2011" href="http://pyrseas.wordpress.com/2011/10/31/postgresql-conference-brasil-2011/">PGBR 2011</a>.</p>
<p>The night before the conference I had the opportunity to greet <a href="http://pgbr.postgresql.org.br/2011/palestrantes.php?id=35">Alvaro Herrera</a>, <a href="http://pgbr.postgresql.org.br/2011/palestrantes.php?id=38">Bruce Momjian</a>, <a href="http://pgbr.postgresql.org.br/2011/palestrantes.php?id=37">Dave Page</a> and <a href="http://pgbr.postgresql.org.br/2011/palestrantes.php?id=34">Greg Smith</a>.</p>
<p>The conference opened on Thursday 3rd November with introductory remarks by <a href="http://pgbr.postgresql.org.br/2011/palestrantes.php?id=25">Fábio Telles</a>, <a href="http://pgbr.postgresql.org.br/2011/palestrantes.php?id=31">Flavio Gurgel</a>, Bruce and <a href="http://pgbr.postgresql.org.br/2011/palestrantes.php?id=32">Euler Taveira</a>. I then attended Dave&#8217;s talk which covered the new foreign data wrapper functionality in PG 9.1.  The presentation was given with &#8220;simultaneous&#8221; translation into Portuguese, which meant I listened to almost every point twice. Next I went to <a href="http://pgbr.postgresql.org.br/2011/palestrantes.php?id=19">Rogerio Bassete</a>&#8216;s talk which dealt with the PostgreSQL windowing functions. Rogerio gave a multitude of examples, but unfortunately the time was relatively short.</p>
<p>At lunch, I talked with Rogerio, <a href="http://pgbr.postgresql.org.br/2011/palestrantes.php?id=18">Fabrízio de Royes Mello</a> and <a href="http://pgbr.postgresql.org.br/2011/palestrantes.php?id=4">Dickson Guedes</a>. It was personally satisfying to find out that Fabrizio had downloaded and tried <a href="http://pyrseas.readthedocs.org/en/latest/index.html">Pyrseas</a>, and was possibly going to &#8220;adopt&#8221; some of it. Dickson also mentioned that some years ago he had tried to implement something similar, so he was glad when he found out about Pyrseas.</p>
<p>The first slot after lunch was taken by the round table on the Brazilan market for PostgreSQL-based services. The participants included Euler (representing <a href="http://www.timbira.com.br/">Timbira</a>), Rodolfo Gobbi (for <a href="http://www.4linux.com.br/">4Linux</a>&#8211;I hope I have the name right), <a href="http://pgbr.postgresql.org.br/2011/palestrantes.php?id=2">Charly Batista</a> (for XPort), Nabucodonosor Coutinho (for <a href="http://www.mondriantecnologia.com/">Mondrian Tecnologia</a>) and Luis Dosso (for <a href="http://www.dextra.com.br/">Dextra</a>), with <a href="http://pgbr.postgresql.org.br/2011/palestrantes.php?id=3">Fernando Ike</a> acting as moderator. The overall take was that the Brazilian PostgreSQL market is mature yet still challenging, supporting variously sized provider companies serving a variety of public and private organizations. After a snack break, where I chatted with Coutinho, I attended Greg&#8217;s benchmarking talk (without translation).</p>
<p>The first day was topped off by the <a href="http://www.flickr.com/photos/tellesr/6322484113/in/pool-1655373@N21/">group photo</a> followed by &#8220;happy hour&#8221; which consisted mostly of Brazilian &#8220;<a href="http://pt.wikipedia.org/wiki/Chope">chopes</a>&#8221; (allegedly 200 litres of it).</p>
<p>On Friday I had breakfast with <a href="http://pgbr.postgresql.org.br/2011/palestrantes.php?id=16">Jaime Casanova</a> and mentioned I had earlier been responsible for another product named &#8220;repmgr&#8221; (for another DBMS). I later attended Greg&#8217;s performance pitfalls talk, translated by Flavio, and Dickson&#8217;s presentation covering the PG 9.1 EXTENSION capabilities and PGXN. At lunch I spoke with Charly.</p>
<p>Probably the most interesting session was <a href="http://pgbr.postgresql.org.br/2011/palestrantes.php?id=24">Diogo Biazus</a>&#8216; PL/pgSQL programming dojo. Diogo sported a <a href="http://en.wikipedia.org/wiki/Mohawk_hairstyle">mohawk</a> although the Brazilians called him a &#8220;mohicano,&#8221; but it wasn&#8217;t his hairstyle that was interesting: it was the concept of &#8220;dojo&#8221; as in &#8220;learn by doing.&#8221; Rather than giving a tutorial on PL/pgSQL, Diogo presented a programming challenge (the hard of hearing granny) and then assisted the attendees in developing a solution in PL/pgSQL using <a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a> and <a href="http://en.wikipedia.org/wiki/Pair_programming">pair programming</a>. Participants took five minute turns being the &#8220;pilot&#8221; and &#8220;co-pilot&#8221; of the pair. A most interesting experience!</p>
<p>For the last formal talk, I heard Flavio&#8217;s talk about myths and realities of Postgres DBA projects. To close, the Brazilian PG group presented their first ever awards to community members, followed by quite informal lightning talks, closing remarks and another group picture.</p>
<p>Overall, a very useful and enjoyable event. Thanks to all the organizers, speakers and others with whom I spoke! Thanks also to those who invited me back (no promises, but we&#8217;ll see).</p>
<br />Filed under: <a href='http://pyrseas.wordpress.com/category/postgresql-2/'>PostgreSQL</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/pyrseas.wordpress.com/1200/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/pyrseas.wordpress.com/1200/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/pyrseas.wordpress.com/1200/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/pyrseas.wordpress.com/1200/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/pyrseas.wordpress.com/1200/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/pyrseas.wordpress.com/1200/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/pyrseas.wordpress.com/1200/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/pyrseas.wordpress.com/1200/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/pyrseas.wordpress.com/1200/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/pyrseas.wordpress.com/1200/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/pyrseas.wordpress.com/1200/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/pyrseas.wordpress.com/1200/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/pyrseas.wordpress.com/1200/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/pyrseas.wordpress.com/1200/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=pyrseas.wordpress.com&amp;blog=19437126&amp;post=1200&amp;subd=pyrseas&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://pyrseas.wordpress.com/2011/11/14/pgbr-2011-recap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0d235d4094b8dbf2cd9932667d828795?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jmafc</media:title>
		</media:content>

		<media:content url="http://farm7.static.flickr.com/6035/6322484113_79fba7eb8a_m.jpg" medium="image">
			<media:title type="html">PGBR 2011</media:title>
		</media:content>
	</item>
	</channel>
</rss>
