<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DkUGRXw_fyp7ImA9WhRUEUU.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369</id><updated>2012-01-22T00:17:04.247+02:00</updated><category term="Unix" /><category term="Python" /><category term="StackOverflow" /><category term="KDE" /><category term="I18n" /><category term="XSLT" /><category term="MySQL" /><category term="E71" /><category term="SQL" /><category term="Beamer" /><category term="EXPLAIN" /><category term="Debian" /><category term="English" /><category term="Nokia" /><category term="LXDE" /><category term="Autoconf" /><category term="Waldschlösschenbrücke" /><category term="Flymake" /><category term="FOSDEM" /><category term="Deutsch" /><category term="Dresden" /><category term="Perl" /><category term="Bazaar" /><category term="ccache" /><category term="UserVoice" /><category term="psql" /><category term="PL/Proxy" /><category term="APT" /><category term="GNOME" /><category term="Computing" /><category term="Shell" /><category term="PostgreSQL" /><category term="Git" /><category term="Clang" /><category term="Chrome" /><category term="Linux" /><category term="SSD" /><category term="PL/Python" /><category term="GPS" /><category term="Wahl" /><category term="Mono" /><category term="Emacs" /><category term="Bash" /><category term="Psycopg" /><category term="LaTeX" /><category term="Cloud" /><category term="Xfce" /><title>Peter Eisentraut's Blog</title><subtitle type="html">on software development, open source, databases, and geek stuff</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://petereisentraut.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>113</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/PeterEisentraut" /><feedburner:info uri="petereisentraut" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="license" type="text/html" href="http://creativecommons.org/licenses/by/3.0/" /><logo>http://www.gravatar.com/avatar/91c59ba5a0ecc3520e135ce55b18d580.png</logo><entry gd:etag="W/&quot;CkAASH87eCp7ImA9WhRREEU.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-6524184260756294934</id><published>2011-11-22T21:48:00.001+02:00</published><updated>2011-11-23T22:39:09.100+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-23T22:39:09.100+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Git" /><category scheme="http://www.blogger.com/atom/ns#" term="Bazaar" /><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Debian" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>git whoami</title><content type="html">My favorite feature in &lt;tt&gt;bzr&lt;/tt&gt; (Bazaar) is the &lt;tt&gt;bzr whoami&lt;/tt&gt; command, which prints what your current identity (name and email) is, as far as the repository is concerned.  You can tell I haven't used &lt;tt&gt;bzr&lt;/tt&gt; much if that's as far as I have gotten.  But seriously, with so many Git repositories around, several project identities, &lt;a href="http://michael-prokop.at/blog/2009/05/30/directory-specific-shell-configuration-with-zsh/"&gt;directory-specific shell configuration&lt;/a&gt;, and so on, it's easy to get confused, and it's annoying to have to check and repair commits for correct user name and email all the time.  So here is &lt;a href="https://github.com/petere/git-whoami"&gt;&lt;tt&gt;git whoami&lt;/tt&gt;&lt;/a&gt;.  This has already saved me so many headaches.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-6524184260756294934?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=V0fCgvMU9go:nXiCrRjGmJI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=V0fCgvMU9go:nXiCrRjGmJI:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=V0fCgvMU9go:nXiCrRjGmJI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=V0fCgvMU9go:nXiCrRjGmJI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=V0fCgvMU9go:nXiCrRjGmJI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=V0fCgvMU9go:nXiCrRjGmJI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=V0fCgvMU9go:nXiCrRjGmJI:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=V0fCgvMU9go:nXiCrRjGmJI:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=V0fCgvMU9go:nXiCrRjGmJI:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=V0fCgvMU9go:nXiCrRjGmJI:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=V0fCgvMU9go:nXiCrRjGmJI:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/V0fCgvMU9go" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/6524184260756294934/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2011/11/git-whoami.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/6524184260756294934?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/6524184260756294934?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/V0fCgvMU9go/git-whoami.html" title="git whoami" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2011/11/git-whoami.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0INQn0zeip7ImA9WhRQEU0.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-6917075564869560428</id><published>2011-11-22T15:55:00.001+02:00</published><updated>2011-12-05T20:26:33.382+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-05T20:26:33.382+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PL/Python" /><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>plpydbapi: DB-API for PL/Python</title><content type="html">One thing that's weird about &lt;a href="http://www.postgresql.org/docs/current/static/plpython.html"&gt;PL/Python&lt;/a&gt; is that its &lt;a href="http://www.postgresql.org/docs/current/static/plpython-database.html"&gt;database access API&lt;/a&gt; is completely different from the standard Python &lt;a href="http://www.python.org/dev/peps/pep-0249/"&gt;DB-API&lt;/a&gt;. It is similar to &lt;a href="http://www.postgresql.org/docs/current/static/plperl-builtins.html#PLPERL-DATABASE"&gt;PL/Perl&lt;/a&gt; and &lt;a href="http://www.postgresql.org/docs/current/static/pltcl-dbaccess.html"&gt;PL/Tcl&lt;/a&gt;, and the C "&lt;a href="http://www.postgresql.org/docs/current/static/spi.html"&gt;SPI&lt;/a&gt;" API, from which they are all derived, but that's little help for a Python programmer.  (The reasons for this are lost in history.  Probably laziness.)  Moreover, the two APIs use the same function names for different purposes.
&lt;p&gt;
So I set out to develop a DB-API compatible layer on top of PL/Python: &lt;a href="https://github.com/petere/plpydbapi"&gt;plpydbapi&lt;/a&gt;
&lt;p&gt;
Example:
&lt;pre class="prettyprint"&gt;
CREATE FUNCTION test() RETURNS void
LANGUAGE plpythonu
AS $$
import plpydbapi

dbconn = plpydbapi.connect()
cursor = dbconn.cursor()
cursor.execute("SELECT ... FROM ...")
for row in cursor.fetchall():
    plpy.notice("got row %s" % row)
dbconn.close()
$$;
&lt;/pre&gt;
&lt;p&gt;
Granted, it's more verbose than the native PL/Python syntax, so you might not want to use it after all.  But it can be helpful if database calls are nested in some other modules, or you just don't want to learn another database access API.
&lt;p&gt;
This started out more as an experiment, but it turns out that with the many improvements in &lt;a href="http://www.postgresql.org/docs/9.1/static/release-9-1.html#AEN107340"&gt;PL/Python in PostgreSQL 9.1&lt;/a&gt;, it's possible to do this.  (Subtransaction control and exception handling were the big issues.)  The one gaping hole is that there is apparently no way to get metadata out of a query result.  Something to address in PostgreSQL 9.2, perhaps.
&lt;p&gt;
Thanks go to the &lt;a href="https://launchpad.net/dbapi-compliance"&gt;DB-API compliance test suite&lt;/a&gt;, which was extremely helpful in making this happen.  (Nonetheless, the test suite is quite incomplete in some regards, so treat the result with care anyway.)
&lt;p&gt;
Another thing that I found neat about this project is that I managed to get the unit tests based on Python's unittest module to run in the PL/Python environment inside the PostgreSQL server.  That's the power of unittest2.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-6917075564869560428?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=kay0Wq2Mdxg:QCYQu39-hC0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=kay0Wq2Mdxg:QCYQu39-hC0:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=kay0Wq2Mdxg:QCYQu39-hC0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=kay0Wq2Mdxg:QCYQu39-hC0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=kay0Wq2Mdxg:QCYQu39-hC0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=kay0Wq2Mdxg:QCYQu39-hC0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=kay0Wq2Mdxg:QCYQu39-hC0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=kay0Wq2Mdxg:QCYQu39-hC0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=kay0Wq2Mdxg:QCYQu39-hC0:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=kay0Wq2Mdxg:QCYQu39-hC0:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=kay0Wq2Mdxg:QCYQu39-hC0:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/kay0Wq2Mdxg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/6917075564869560428/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2011/11/plpydbapi-db-api-for-plpython.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/6917075564869560428?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/6917075564869560428?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/kay0Wq2Mdxg/plpydbapi-db-api-for-plpython.html" title="plpydbapi: DB-API for PL/Python" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2011/11/plpydbapi-db-api-for-plpython.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEAGRHYyfyp7ImA9WhRSEUw.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-8847407952008509734</id><published>2011-11-12T17:27:00.001+02:00</published><updated>2011-11-12T17:45:25.897+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-12T17:45:25.897+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GNOME" /><category scheme="http://www.blogger.com/atom/ns#" term="Debian" /><category scheme="http://www.blogger.com/atom/ns#" term="Xfce" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>Switching desktop environments</title><content type="html">So, like many people, I have received GNOME 3 in the latest upgrade on Debian testing, and switched away to Xfce very soon after.  What's amazing (to me) about this whole experience, however, is how easy it is to switch desktop environments in Debian.  Two years ago, I &lt;a href="http://petereisentraut.blogspot.com/2009/08/why-i-dumped-kde.html"&gt;fled KDE&lt;/a&gt; in very similar circumstances.  I have since used Openbox, LXDE, GNOME, Xfce, as well as a few more obscure window managers in short-lived experiments.  All of this was easy to do and worked flawlessly.  Most of my settings, my preferred programs, and startup applications were preserved, and if I didn't like it, I could switch back without a problem.  (Ironically, the upgrades from KDE 3 to KDE 4 and from GNOME 2 to GNOME 3 lost far more settings than changes to other environments.)  And of course you can mix and match applications from different environments, and these days this doesn't result in a visual crime.  I don't know whom to thank for this, probably a combination of upstream developers, freedesktop.org guys, and Debian maintainers.  Keep it up.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-8847407952008509734?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=E-M4zEW1Rtk:rPcRLV-WZY4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=E-M4zEW1Rtk:rPcRLV-WZY4:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=E-M4zEW1Rtk:rPcRLV-WZY4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=E-M4zEW1Rtk:rPcRLV-WZY4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=E-M4zEW1Rtk:rPcRLV-WZY4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=E-M4zEW1Rtk:rPcRLV-WZY4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=E-M4zEW1Rtk:rPcRLV-WZY4:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=E-M4zEW1Rtk:rPcRLV-WZY4:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=E-M4zEW1Rtk:rPcRLV-WZY4:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=E-M4zEW1Rtk:rPcRLV-WZY4:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=E-M4zEW1Rtk:rPcRLV-WZY4:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/E-M4zEW1Rtk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/8847407952008509734/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2011/11/switching-desktop-environments.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/8847407952008509734?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/8847407952008509734?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/E-M4zEW1Rtk/switching-desktop-environments.html" title="Switching desktop environments" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>6</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2011/11/switching-desktop-environments.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQGQXk_fyp7ImA9WhdVEUk.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-7066164265748139413</id><published>2011-09-16T06:38:00.000+03:00</published><updated>2011-09-16T06:38:40.747+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-16T06:38:40.747+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ccache" /><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Clang" /><category scheme="http://www.blogger.com/atom/ns#" term="Debian" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>ccache and clang, part 2</title><content type="html">There's more funny business when using &lt;tt&gt;ccache&lt;/tt&gt; in combination with &lt;tt&gt;clang&lt;/tt&gt;. &lt;a href="http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html"&gt;Last time&lt;/a&gt; I suggested that you use the invocation
&lt;pre&gt;./configure CC='ccache clang -Qunused-arguments -fcolor-diagnostics'&lt;/pre&gt;
to get rid of the "argument unused during compilation" warnings.
&lt;p&gt;
But you still might get loads of warnings that you wouldn't normally get without &lt;tt&gt;ccache&lt;/tt&gt;, such as this example (from the PostgreSQL source code):
&lt;pre&gt;
extension.c:382:35: warning: equality comparison with extraneous parentheses [-Wparentheses]
 if (( (((control-&gt;directory)[0]) == '/') ))
        ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
extension.c:382:35: note: use '=' to turn this equality comparison into an assignment
&lt;/pre&gt;
(This is the opposite of the warning that tells you to put two pairs of parentheses around an assignment used as a truth value.)
Or:
&lt;pre&gt;
path.c:727:7: warning: explicitly assigning a variable of type 'char *' to itself [-Wself-assign]
 path = (path);
 ~~~~ ^  ~~~~
&lt;/pre&gt;
The problem is, these come from macro expansions, so wouldn't normally see them, because (I guess) the compiler driver is smart enough not to warn about such things when they come from macro expansions.
&lt;p&gt;
The way &lt;tt&gt;ccache&lt;/tt&gt; works is approximately
&lt;ol&gt;
&lt;li&gt;preprocess the input file
&lt;li&gt;look for it in the cache
&lt;li&gt;if not found, compile the &lt;i&gt;preprocessed&lt;/i&gt; file
&lt;/ol&gt;
What would be better in this situation is
&lt;ol&gt;
&lt;li&gt;preprocess the input file
&lt;li&gt;look for it in the cache
&lt;li&gt;if not found, compile the &lt;i&gt;original&lt;/i&gt; file
&lt;/ol&gt;
And indeed you can turn on that second behavior by setting the obscure environment variable &lt;tt&gt;CCACHE_CPP2&lt;/tt&gt; (as in, run cpp twice):
&lt;pre&gt;export CCACHE_CPP2=yes&lt;/pre&gt;
Then all these extra warnings disappear.
&lt;p&gt;
(The &lt;tt&gt;ccache&lt;/tt&gt; man page is worth a read.  There are a few interesting settings to play with.)
&lt;p&gt;
I'm currently playing around with a shell script &lt;tt&gt;ccache-clang&lt;/tt&gt; that looks like this:
&lt;pre&gt;CCACHE_CPP2=yes exec ccache clang -Qunused-arguments `test -t 2 &amp;&amp; echo -fcolor-diagnostics` "$@"&lt;/pre&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-7066164265748139413?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=bHF8vZX2hY0:E7oQbcMpXDA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=bHF8vZX2hY0:E7oQbcMpXDA:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=bHF8vZX2hY0:E7oQbcMpXDA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=bHF8vZX2hY0:E7oQbcMpXDA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=bHF8vZX2hY0:E7oQbcMpXDA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=bHF8vZX2hY0:E7oQbcMpXDA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=bHF8vZX2hY0:E7oQbcMpXDA:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=bHF8vZX2hY0:E7oQbcMpXDA:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=bHF8vZX2hY0:E7oQbcMpXDA:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=bHF8vZX2hY0:E7oQbcMpXDA:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=bHF8vZX2hY0:E7oQbcMpXDA:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/bHF8vZX2hY0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/7066164265748139413/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2011/09/ccache-and-clang-part-2.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/7066164265748139413?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/7066164265748139413?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/bHF8vZX2hY0/ccache-and-clang-part-2.html" title="ccache and clang, part 2" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>6</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2011/09/ccache-and-clang-part-2.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0IMSHg4cSp7ImA9WhdWFkU.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-1648054734715715411</id><published>2011-09-10T23:13:00.000+03:00</published><updated>2011-09-10T23:13:09.639+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-10T23:13:09.639+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>Beta work</title><content type="html">PostgreSQL 9.1.0 was wrapped the yesterday (or the day before yesterday, depending on from where you see it). It is now in a special place, where it can rest and let the flavor soak in, before it's released into the wild next week.
&lt;p&gt;
Time to reflect.
&lt;p&gt;
One thing that is sometimes criticized about the PostgreSQL release process is that there is too much time between the start of beta (or the end of the last commit fest) and the final release, and that it's not clear what ordinary contributors can do during that time to speed things up. This is now worked around to some degree by starting the next development cycle during the beta period of the previous one. (Evaluating the success of that approach is another matter.) But because this matter had also bothered me, I have taken notes this time, first of all so I don't forget anything next time, but perhaps also to provide some inspiration for others.
&lt;p&gt;
So here is what I'd been up to during the 9.1 beta period:
&lt;dl&gt;
&lt;dt&gt;&lt;b&gt;Documentation work&lt;/b&gt;
&lt;dd&gt;
It is well understood that the documentation needs a general review during beta time. As features are patched in, chunks of documentation are added here and there, and at the end of it all you just need to stare at it for a bit and see whether the order and flow still make sense. I didn't do much of that this time, but I know others did. Other things to do are:
&lt;ul&gt;
&lt;li&gt;Various bits of SGML markup usually need to be cleaned up, e.g., alignment of verbatim environments, linking to formal objects.
&lt;li&gt;I always run the whole documentation through a spell checker, which always results in a bunch of corrections.
&lt;li&gt;The SQL features list in the documentation needs to be updated.
&lt;li&gt;The SQL key words list in the documentation needs to be updated.
&lt;li&gt;All generated man pages should be looked through manually for formatting artifacts.
&lt;li&gt;Non-ASCII characters in the SGML source need to be checked. They should be converted to entities, and ideally they should fit into the Latin 1 set.
&lt;/ul&gt;
Other people also spent significant time on preparing the release notes, which is a huge job. I didn't even get into that, except that the spell checking and automated cleanups apply to the release notes as well, since they are part of the documentation build.

&lt;dt&gt;&lt;b&gt;Source code cleanup&lt;/b&gt;
&lt;dd&gt;
We run pgindent during beta, but there are also a number of other things to do to clean up the source code. A lot of these I didn't plan. Mostly, one thing led to another.
&lt;ul&gt;
&lt;li&gt;Check for non-ASCII characters in source. These should either be in UTF-8 or replaced by an ASCII equivalent.
&lt;li&gt;Spell checking: You can't run the whole source through a spell checker, but there are also a few typical misspellings or variant spellings that are easy to clean up over the entire source tree, such as GIST -&gt; GiST or cancelled -&gt; canceled.
&lt;li&gt;Check the &lt;tt&gt;--help&lt;/tt&gt; and &lt;tt&gt;--version&lt;/tt&gt; output of all programs to see whether it follows conventions.
&lt;li&gt;In particular, check that the &lt;tt&gt;--help&lt;/tt&gt; output is aligned, not too wide, and that the options are ordered sensibly. (Very often a new option is just added at the end or at some random place in the middle.)
&lt;li&gt;Diff the &lt;tt&gt;--help&lt;/tt&gt; outputs between the previous and the current version to find out about all new command-line options and check whether they are sensibly named and properly documented.
&lt;li&gt;And the order in which options are presented in the &lt;tt&gt;--help&lt;/tt&gt; output and on the man pages should not be gratuitously different.
&lt;li&gt;Similarly, the backslash command help output in psql (&lt;tt&gt;\?&lt;/tt&gt;) should be checked that it looks ok.
&lt;li&gt;Go through the configuration file samples and check them for sanity, up-to-dateness, and proper formatting.
&lt;li&gt;Remove literal tabs from string constants. How did they ever get in there?
&lt;li&gt;Compile the code with a bunch of extra warning options.  GCC has a lot of those, try them all out.  A lot of them generate a lot of noise, but going through them about once a release does find the occasional trouble spot, or at least provides inspiration for future code cleanup projects.  As of 9.1, you can also throw Clang into the mix.
&lt;li&gt;Also, check building against cutting edge versions of library dependencies. Good candidates are Perl and Python, which introduce small breakage with each new release. If there is a new release candidate of those guys out while we prepare the PostgreSQL release, our users will be building against the final versions soon, so we need to be prepared.
&lt;/ul&gt;

&lt;dt&gt;&lt;b&gt;Translation work&lt;/b&gt;
&lt;dd&gt;
Besides the translation work itself and orchestrating the translator contributors, this is also the best chance to read through every single user-visible message that was introduced in the new version. So there are occasional spelling fixes, some messages are poorly worded or incomprehensible to a normal user, or sometimes the code can be restructured so that some error condition doesn't happen at all. A lot of this feeds back into source code cleanup items.

&lt;dt&gt;&lt;b&gt;Help the packagers&lt;/b&gt;
&lt;dd&gt;
We have a great bunch of packagers who prepare PostgreSQL for installation on various operating systems. Help them out. Make sure all new features are properly integrated, package descriptions are up-to-date, upgrades work.

&lt;/dl&gt;

And then of course you field submissions from testers and other contributors who will submit countless bug reports, failures on unusual platforms, documentation fixes.
&lt;p&gt;
So that can keep you busy for a month or three. The goal ought to be to automated most of this. But much of it can't be. So we really do need to spend the time to do these things, especially polishing the user-facing things.  We don't want the first program output or documentation page the user sees of the new release to be ugly or wrong.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-1648054734715715411?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=6t0yiaGZGpk:50tmEaTAmvA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=6t0yiaGZGpk:50tmEaTAmvA:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=6t0yiaGZGpk:50tmEaTAmvA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=6t0yiaGZGpk:50tmEaTAmvA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=6t0yiaGZGpk:50tmEaTAmvA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=6t0yiaGZGpk:50tmEaTAmvA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=6t0yiaGZGpk:50tmEaTAmvA:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=6t0yiaGZGpk:50tmEaTAmvA:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=6t0yiaGZGpk:50tmEaTAmvA:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=6t0yiaGZGpk:50tmEaTAmvA:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=6t0yiaGZGpk:50tmEaTAmvA:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/6t0yiaGZGpk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/1648054734715715411/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2011/09/beta-work.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/1648054734715715411?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/1648054734715715411?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/6t0yiaGZGpk/beta-work.html" title="Beta work" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2011/09/beta-work.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUGQ3Y9fCp7ImA9WhdSEU0.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-8959335935832180408</id><published>2011-07-19T23:10:00.000+03:00</published><updated>2011-07-19T23:10:22.864+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-19T23:10:22.864+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>Undefined symbol</title><content type="html">Here is a small DBA tale from a few months ago.  I wanted to upgrade a few servers to the latest minor release of PostgreSQL.  It was the upgrade from 8.4.4 to 8.4.5.  To minimize downtime, I had the following obvious idea: I'd install all the packages first, and once everything was in place and an opportune time for a service disruption had arrived, I'd just restart the services, and everything would be backup in less than a minute.  (If you just let the package manager do its thing, it's always a bit unpredictable when the services are stopped and restarted, which might result several minutes of downtime.)&lt;br /&gt;
&lt;br /&gt;
This operation had dramatic consequences.  As soon as I had the new packages installed, I got massive amounts of these errors:&lt;br /&gt;
&lt;br /&gt;
&lt;tt&gt;ERROR:  could not load library "/usr/lib/postgresql/8.4/lib/plpgsql.so": /usr/lib/postgresql/8.4/lib/plpgsql.so: undefined symbol: PinPortal&lt;/tt&gt;&lt;br /&gt;
&lt;br /&gt;
Since a lot of things use PL/pgSQL, this meant that the database system was pretty much dead at this point.&lt;br /&gt;
&lt;br /&gt;
What had happened?&lt;br /&gt;
&lt;br /&gt;
Well, version 8.4.5 introduced some new functions in the server that PL/pgSQL made use of.  As soon as you install the new &lt;tt&gt;plpgsql&lt;/tt&gt; module, the next session that starts will load the new libary, but unless you restarted the server, the running server process won't have that symbol.&lt;br /&gt;
&lt;br /&gt;
It was easy to fix this by restarting the server, but that's not how things were planned.&lt;br /&gt;
&lt;br /&gt;
Consequence: Unless shown otherwise and a lot of care is taken, you must upgrade the server and all loadable modules to exactly matching versions and at the same time, and you must restart the server at the same time.&lt;br /&gt;
&lt;br /&gt;
It might be useful as a preventive measure to compare symbol tables before upgrading.  It could also be tracked more carefully at the source level, by explicitly mentioning the addition of meant-to-be-called-externally functions to the server in the release notes.  (I suppose we don't usually remove functions, but who knows.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-8959335935832180408?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=NossJLL7ygc:CsQkeS6mS5M:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=NossJLL7ygc:CsQkeS6mS5M:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=NossJLL7ygc:CsQkeS6mS5M:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=NossJLL7ygc:CsQkeS6mS5M:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=NossJLL7ygc:CsQkeS6mS5M:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=NossJLL7ygc:CsQkeS6mS5M:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=NossJLL7ygc:CsQkeS6mS5M:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=NossJLL7ygc:CsQkeS6mS5M:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=NossJLL7ygc:CsQkeS6mS5M:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=NossJLL7ygc:CsQkeS6mS5M:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=NossJLL7ygc:CsQkeS6mS5M:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/NossJLL7ygc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/8959335935832180408/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2011/07/undefined-symbol.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/8959335935832180408?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/8959335935832180408?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/NossJLL7ygc/undefined-symbol.html" title="Undefined symbol" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2011/07/undefined-symbol.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEYGRX4_fip7ImA9WhZbGEg.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-4046553751794577836</id><published>2011-06-23T22:08:00.000+03:00</published><updated>2011-06-23T22:08:44.046+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-23T22:08:44.046+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Debian" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>Bootstrapping Debian packages</title><content type="html">I read something about &lt;tt&gt;dh_make&lt;/tt&gt; again a while ago, which made me wonder, besides &lt;tt&gt;dh_make&lt;/tt&gt;, how do people generally bootstrap new Debian packages.  I don't think I've ever actually used &lt;tt&gt;dh_make&lt;/tt&gt; for anything but experimenting.  For the longest time, copying over the packaging files from some similar package worked pretty well.&lt;br /&gt;
&lt;br /&gt;
Recently, however, I have applied a completely new strategy: I start with nothing, call &lt;code&gt;debuild&lt;/code&gt;, fix the error, retry, until it works.  This might sound pretty bizarre, but it works pretty well and enhances your understanding of how the packaging tools work.&lt;br /&gt;
&lt;br /&gt;
Here is about how it works:&lt;br /&gt;
&lt;br /&gt;
Start with nothing, call &lt;code&gt;debuild&lt;/code&gt;, it complains:&lt;br /&gt;
&lt;pre&gt;cannot find readable debian/changelog anywhere!&lt;/pre&gt;Call &lt;code&gt;dch --create&lt;/code&gt;, which says:&lt;br /&gt;
&lt;pre&gt;Cannot find debian directory!&lt;/pre&gt;OK, &lt;code&gt;mkdir debian&lt;/code&gt;, call &lt;code&gt;dch --create&lt;/code&gt; again, fill in the template.  Call &lt;code&gt;debuild&lt;/code&gt; again, now it says:&lt;br /&gt;
&lt;pre&gt;but there's no debian/rules there!&lt;/pre&gt;Create a &lt;code&gt;debian/rules&lt;/code&gt;, that's easy to do by heart nowadays, at least as a start:&lt;br /&gt;
&lt;pre&gt;#!/usr/bin/make -f

%:
        dh $@&lt;/pre&gt;Call &lt;code&gt;debuild&lt;/code&gt; again, now &lt;code&gt;dpkg-buildpackage&lt;/code&gt; actually starts, but stops with:&lt;br /&gt;
&lt;pre&gt;dpkg-source: error: cannot read mypackage/debian/control: No such file or directory&lt;/pre&gt;At this point I'm too lazy to figure out what is necessary to put into &lt;code&gt;debian/control&lt;/code&gt;, so let's just keep it simple and touch &lt;code&gt;debian/control&lt;/code&gt;.  At this point dpkg-source gets into a bit of trouble:&lt;br /&gt;
&lt;pre&gt;Use of uninitialized value $sourcepackage in sprintf at /usr/bin/dpkg-source line 290.&lt;/pre&gt;So let's put that in and also follow the subsequent advice to add &lt;code&gt;debian/source/format&lt;/code&gt; and the &lt;code&gt;Maintainer&lt;/code&gt; and &lt;code&gt;Standards-Version&lt;/code&gt; fields.  So far we have:&lt;br /&gt;
&lt;pre&gt;Source: mypackage
Maintainer: Peter Eisentraut &amp;lt;petere@debian.org&amp;gt;
Standards-Version: 3.9.2&lt;/pre&gt;The next hint of a message is:&lt;br /&gt;
&lt;pre&gt;dh: No packages to build.&lt;/pre&gt;This means we need a binary package stanza, so I'll just add&lt;br /&gt;
&lt;pre&gt;Package: mypackage
Architecture: any&lt;/pre&gt;Now &lt;code&gt;debhelper&lt;/code&gt; complains:&lt;br /&gt;
&lt;pre&gt;dh: Compatibility levels before 5 are deprecated.&lt;/pre&gt;Not sure why it didn't complain about that earlier.  Let's stick 8 in there.&lt;br /&gt;
&lt;br /&gt;
At this point I had to do actual work and mess around with &lt;code&gt;debian/rules&lt;/code&gt; a bit to get the package to actually build, but a few minutes later I had a functioning provisional package.&lt;br /&gt;
&lt;br /&gt;
The next step is to clean up the warnings from the various &lt;code&gt;dpkg-*&lt;/code&gt; workers:&lt;br /&gt;
&lt;pre&gt;dpkg-gencontrol: warning: missing information for output field Description
dpkg-gencontrol: warning: package mypackage: unused substitution variable ${shlibs:Depends}
dpkg-deb: warning: parsing file 'debian/mypackage/DEBIAN/control' near line 6 package 'mypackage': missing description
dpkg-genchanges: warning: missing Section for binary package mypackage; using '-'
dpkg-genchanges: warning: missing Priority for binary package mypackage; using '-'
dpkg-genchanges: warning: missing Section for source files
dpkg-genchanges: warning: missing Priority for source files&lt;/pre&gt;So we add &lt;code&gt;Description&lt;/code&gt;, &lt;code&gt;Depends&lt;/code&gt;, &lt;code&gt;Section&lt;/code&gt;, and &lt;code&gt;Priority&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
And finally we have a list of complaints from Lintian to address:&lt;br /&gt;
&lt;pre&gt;W: mypackage source: debhelper-but-no-misc-depends mypackage
E: mypackage source: package-uses-debhelper-but-lacks-build-depends
W: mypackage source: package-needs-versioned-debhelper-build-depends 8
W: mypackage source: debhelper-overrides-need-versioned-build-depends (&gt;= 7.0.50~)
E: mypackage source: temporary-debhelper-file debhelper.log
E: mypackage: no-copyright-file&lt;/pre&gt;The only things I added manually after that were &lt;code&gt;Vcs-*&lt;/code&gt;, &lt;code&gt;Homepage&lt;/code&gt;, and &lt;code&gt;Enhances&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
Now the only things left to do are running the thing through &lt;code&gt;cowbuilder&lt;/code&gt; a few times and putting in all the necessary build dependencies, and writing a nice changelog entry.&lt;br /&gt;
&lt;br /&gt;
Note, this method does not replace putting in some thought.  But it's an interesting way to get a relatively clean package.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-4046553751794577836?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=6hUEXmjf1cw:J0uFGBy9K0w:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=6hUEXmjf1cw:J0uFGBy9K0w:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=6hUEXmjf1cw:J0uFGBy9K0w:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=6hUEXmjf1cw:J0uFGBy9K0w:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=6hUEXmjf1cw:J0uFGBy9K0w:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=6hUEXmjf1cw:J0uFGBy9K0w:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=6hUEXmjf1cw:J0uFGBy9K0w:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=6hUEXmjf1cw:J0uFGBy9K0w:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=6hUEXmjf1cw:J0uFGBy9K0w:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=6hUEXmjf1cw:J0uFGBy9K0w:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=6hUEXmjf1cw:J0uFGBy9K0w:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/6hUEXmjf1cw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/4046553751794577836/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2011/06/bootstrapping-debian-packages.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/4046553751794577836?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/4046553751794577836?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/6hUEXmjf1cw/bootstrapping-debian-packages.html" title="Bootstrapping Debian packages" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>6</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2011/06/bootstrapping-debian-packages.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkYAQXsyfCp7ImA9WhZUEEk.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-8837541431411735039</id><published>2011-06-02T21:42:00.000+03:00</published><updated>2011-06-02T21:42:20.594+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-02T21:42:20.594+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Debian" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>Enabling core files for PostgreSQL on Debian</title><content type="html">The other day, I was a bit puzzled over a seemingly simple task: Enable core files to be generated from a PostgreSQL instance running on Debian.  That instance has unfortunately been segfaulting on occasion, but never left a core file.&lt;br /&gt;
&lt;br /&gt;
Now in principle it is clear that&lt;br /&gt;
&lt;pre&gt;ulimit -c unlimited&lt;/pre&gt;is the incantation to get this done.  But where do you put this?  You could hack it into the init script, but that seemed a bit ugly, and I wanted a sustainable solution.&lt;br /&gt;
&lt;br /&gt;
A useful thing in the meantime is to check the current settings.  That information is available in &lt;tt&gt;/proc/$PID/limits&lt;/tt&gt; with the PID of the postmaster process (or any child process, really), and it looked like this to begin with:&lt;br /&gt;
&lt;pre&gt;Limit                     Soft Limit           Hard Limit           Units     
Max cpu time              unlimited            unlimited            ms        
Max file size             unlimited            unlimited            bytes     
Max data size             unlimited            unlimited            bytes     
Max stack size            8388608              unlimited            bytes     
Max core file size        0                    unlimited            bytes     
...&lt;/pre&gt;Use &lt;tt&gt;sudo grep core /proc/$(sudo cat /var/run/postgresql/8.4-main.pid)/limits&lt;/tt&gt; if you want it automated.&lt;br /&gt;
&lt;br /&gt;
So it's good to know that we only need to set the soft limit.&lt;br /&gt;
&lt;br /&gt;
One way to configure this &lt;q&gt;properly&lt;/q&gt; would appear to be in &lt;tt&gt;/etc/security/limits.conf&lt;/tt&gt;.  There you can add a line like&lt;br /&gt;
&lt;pre&gt;*               soft    core            unlimited&lt;/pre&gt;to enable core dumps globally.  I'm not actually sure whether that would work if the service is started during the boot without PAM.  In any case, I didn't want to enable core files globally; who knows what that would lead to.&lt;br /&gt;
&lt;br /&gt;
One could replace the &lt;tt&gt;*&lt;/tt&gt; by a user name, such as &lt;tt&gt;postgres&lt;/tt&gt;, and then enable &lt;tt&gt;pam_limits.so&lt;/tt&gt; in &lt;tt&gt;/etc/pam.d/su&lt;/tt&gt;.  But the &lt;tt&gt;postgresql&lt;/tt&gt; init script in Debian is nested about four levels deep, so it wasn't clear whether it called &lt;tt&gt;su&lt;/tt&gt; at all.&lt;br /&gt;
&lt;br /&gt;
Now as it turns out, the init script ends up changing the user using this Perl code:&lt;br /&gt;
&lt;pre&gt;$) = $groups;
$( = $gid;
$&amp;gt; = $&amp;lt; = $uid;&lt;/pre&gt;(see &lt;tt&gt;change_ugid&lt;/tt&gt; in &lt;tt&gt;/usr/share/postgresql-common/PgCommon.pm&lt;/tt&gt;), so the whole PAM line of thought wasn't going to work anyway.  (Other packages such as &lt;tt&gt;pgbouncer&lt;/tt&gt; and &lt;tt&gt;slony1&lt;/tt&gt; do got through &lt;tt&gt;su&lt;/tt&gt;, so that would be a solution for those.)&lt;br /&gt;
&lt;br /&gt;
The way to solve this is the &lt;tt&gt;pg_ctl&lt;/tt&gt; &lt;tt&gt;-c&lt;/tt&gt; option, which sets the soft limit for core files to unlimited.  And the way to pass this option through the init script maze is the file &lt;tt&gt;/etc/postgresql/8.4/main/pg_ctl.conf&lt;/tt&gt;, which should contain a line like this:&lt;br /&gt;
&lt;pre&gt;pg_ctl_options = '-c'&lt;/pre&gt;Then restart &lt;tt&gt;postgresql&lt;/tt&gt;, and check &lt;tt&gt;/proc/$PID/limits&lt;/tt&gt; again:&lt;br /&gt;
&lt;pre&gt;Limit                     Soft Limit           Hard Limit           Units     
Max cpu time              unlimited            unlimited            ms        
Max file size             unlimited            unlimited            bytes     
Max data size             unlimited            unlimited            bytes     
Max stack size            8388608              unlimited            bytes     
Max core file size        unlimited            unlimited            bytes     &lt;/pre&gt;OK.&lt;br /&gt;
&lt;br /&gt;
Another thing that's recommendable in this context is to change the core file names to have a unique element, so that if multiple backends crash before you can take a look, they don't overwrite each other's core files.  The core(7) man page explains the configuration options;&lt;br /&gt;
I went with this sysctl setting:&lt;br /&gt;
&lt;pre&gt;kernel.core_pattern = core.%e.%p&lt;/pre&gt;which includes process name and PID.  The PID file still ends up in the data directory of the PostgreSQL instance, which could also be changed, but I didn't find it necessary.&lt;br /&gt;
&lt;br /&gt;
Stick the above line in &lt;tt&gt;/etc/sysctl.d/local.conf&lt;/tt&gt; and reload with&lt;br /&gt;
&lt;pre&gt;service procps force-reload&lt;/pre&gt;I actually use a setting like that on all machines now; it's just nicer.&lt;br /&gt;
&lt;br /&gt;
OK, and now I'll wait for the next core file.  Or not.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-8837541431411735039?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=m1os4_NeWXQ:tM9TSRF4sdA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=m1os4_NeWXQ:tM9TSRF4sdA:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=m1os4_NeWXQ:tM9TSRF4sdA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=m1os4_NeWXQ:tM9TSRF4sdA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=m1os4_NeWXQ:tM9TSRF4sdA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=m1os4_NeWXQ:tM9TSRF4sdA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=m1os4_NeWXQ:tM9TSRF4sdA:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=m1os4_NeWXQ:tM9TSRF4sdA:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=m1os4_NeWXQ:tM9TSRF4sdA:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=m1os4_NeWXQ:tM9TSRF4sdA:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=m1os4_NeWXQ:tM9TSRF4sdA:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/m1os4_NeWXQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/8837541431411735039/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2011/06/enabling-core-files-for-postgresql-on.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/8837541431411735039?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/8837541431411735039?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/m1os4_NeWXQ/enabling-core-files-for-postgresql-on.html" title="Enabling core files for PostgreSQL on Debian" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2011/06/enabling-core-files-for-postgresql-on.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQFRnY8cCp7ImA9WhZXFk8.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-6608931159355457870</id><published>2011-05-05T22:38:00.000+03:00</published><updated>2011-05-05T22:38:37.878+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-05T22:38:37.878+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ccache" /><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Clang" /><category scheme="http://www.blogger.com/atom/ns#" term="Debian" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>ccache and clang</title><content type="html">Just a note for the Internet:  When you use &lt;tt&gt;ccache&lt;/tt&gt; and &lt;tt&gt;clang&lt;/tt&gt; together, you will probably get a lot of warnings like these:&lt;br /&gt;
&lt;pre&gt;clang: warning: argument unused during compilation: '-c'
clang: warning: argument unused during compilation: '-I .'&lt;/pre&gt;These are harmless, but if you want to get rid of them, use the &lt;tt&gt;clang&lt;/tt&gt; option &lt;tt&gt;-Qunused-arguments&lt;/tt&gt;, which will hide them.  (The first one is already &lt;a href="http://git.samba.org/?p=ccache.git;a=commit;h=f0db645c75a2c063526685b791a4afd7b2884d1d"&gt;fixed&lt;/a&gt; in &lt;tt&gt;ccache&lt;/tt&gt;.)&lt;br /&gt;
&lt;br /&gt;
The reason for this is that &lt;tt&gt;ccache&lt;/tt&gt; splits the compilation into separate calls to the preprocessor and the compiler proper, and it tries to sort out which of the options that you called it with go with which call.  But since &lt;tt&gt;gcc&lt;/tt&gt; doesn't complain about passing &lt;tt&gt;-c&lt;/tt&gt; to the preprocessor or &lt;tt&gt;-I&lt;/tt&gt; to the compiler, &lt;tt&gt;ccache&lt;/tt&gt; doesn't bother about sorting this out (&lt;a href="https://bugzilla.samba.org/show_bug.cgi?id=8118"&gt;bug&lt;/a&gt;).  That's why you don't lose any information relative to using &lt;tt&gt;gcc&lt;/tt&gt; if you use the &lt;tt&gt;-Qunused-arguments&lt;/tt&gt; option.&lt;br /&gt;
&lt;br /&gt;
Also, if you like &lt;tt&gt;clang&lt;/tt&gt;'s colored diagnostics messages, you'll have to turn them on explicitly with &lt;tt&gt;-fcolor-diagnostics&lt;/tt&gt;, because when running through &lt;tt&gt;ccache&lt;/tt&gt;, &lt;tt&gt;clang&lt;/tt&gt; doesn't think it's printing to a terminal and turns off the color by default.&lt;br /&gt;
&lt;br /&gt;
So a complete invocation might look like this:&lt;br /&gt;
&lt;pre&gt;./configure CC='ccache clang -Qunused-arguments -fcolor-diagnostics'&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-6608931159355457870?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=gZ9wUQ9B9oo:rr13jU8Nnxk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=gZ9wUQ9B9oo:rr13jU8Nnxk:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=gZ9wUQ9B9oo:rr13jU8Nnxk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=gZ9wUQ9B9oo:rr13jU8Nnxk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=gZ9wUQ9B9oo:rr13jU8Nnxk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=gZ9wUQ9B9oo:rr13jU8Nnxk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=gZ9wUQ9B9oo:rr13jU8Nnxk:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=gZ9wUQ9B9oo:rr13jU8Nnxk:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=gZ9wUQ9B9oo:rr13jU8Nnxk:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=gZ9wUQ9B9oo:rr13jU8Nnxk:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=gZ9wUQ9B9oo:rr13jU8Nnxk:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/gZ9wUQ9B9oo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/6608931159355457870/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/6608931159355457870?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/6608931159355457870?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/gZ9wUQ9B9oo/ccache-and-clang.html" title="ccache and clang" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UNSXw8fyp7ImA9WhZQFU0.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-4234380204807586838</id><published>2011-04-23T00:54:00.000+03:00</published><updated>2011-04-23T00:54:58.277+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-23T00:54:58.277+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><category scheme="http://www.blogger.com/atom/ns#" term="Emacs" /><title>Emacs fill column for PostgreSQL</title><content type="html">Since it's pgindent season, here's a small related tip for Emacs users.&lt;br /&gt;
&lt;pre&gt;(setq fill-column 79)&lt;/pre&gt;This will set the maximum line length for filling commands such as &lt;kbd&gt;M-q&lt;/kbd&gt; to the same length that pgindent uses.  That is especially useful when you want to reformat block comments nicely.  The default is 70, which will cause perpetual conflicts between Emacs and pgindent.&lt;br /&gt;
&lt;br /&gt;
The &lt;a href="http://git.postgresql.org/gitweb?p=postgresql.git;a=commitdiff;h=415f5e12592d135919549a5eb21893fda0417ebf;hp=9e9b9ac7d1860fbb98eb4db17a94ff25524b6447"&gt;commit&lt;/a&gt; shows various other ways to include this in your Emacs configuration.  (I use the &lt;code&gt;c-add-style&lt;/code&gt; approach, personally.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-4234380204807586838?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=7GEcUwe8yMc:S3aVnPmVkzY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=7GEcUwe8yMc:S3aVnPmVkzY:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=7GEcUwe8yMc:S3aVnPmVkzY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=7GEcUwe8yMc:S3aVnPmVkzY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=7GEcUwe8yMc:S3aVnPmVkzY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=7GEcUwe8yMc:S3aVnPmVkzY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=7GEcUwe8yMc:S3aVnPmVkzY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=7GEcUwe8yMc:S3aVnPmVkzY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=7GEcUwe8yMc:S3aVnPmVkzY:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=7GEcUwe8yMc:S3aVnPmVkzY:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=7GEcUwe8yMc:S3aVnPmVkzY:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/7GEcUwe8yMc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/4234380204807586838/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2011/04/emacs-fill-column-for-postgresql.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/4234380204807586838?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/4234380204807586838?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/7GEcUwe8yMc/emacs-fill-column-for-postgresql.html" title="Emacs fill column for PostgreSQL" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2011/04/emacs-fill-column-for-postgresql.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08HRH45cSp7ImA9Wx9aF0U.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-1245452865346972754</id><published>2011-03-10T22:43:00.000+02:00</published><updated>2011-03-10T22:43:55.029+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-10T22:43:55.029+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Git" /><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Debian" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>My new Git pre-commit hook</title><content type="html">This appears to be kind of useful:&lt;br /&gt;
&lt;pre&gt;#!/bin/sh

output=$(find . -name '.#*' -print)
if [ -n "$output" ]; then
        echo "unsaved Emacs files:" 1&gt;&amp;2
        echo "$output" 1&gt;&amp;2
        exit 1
fi&lt;/pre&gt;Had that kind of problem a few times. :-)&lt;br /&gt;
&lt;br /&gt;
Now what would be really handy are system-wide Git hooks that apply to all repositories, like &lt;tt&gt;~/.gitignore&lt;/tt&gt; complements &lt;tt&gt;.git/info/exclude&lt;/tt&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-1245452865346972754?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=YGp1SQlYPOU:YKOScyn-9Pk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=YGp1SQlYPOU:YKOScyn-9Pk:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=YGp1SQlYPOU:YKOScyn-9Pk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=YGp1SQlYPOU:YKOScyn-9Pk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=YGp1SQlYPOU:YKOScyn-9Pk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=YGp1SQlYPOU:YKOScyn-9Pk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=YGp1SQlYPOU:YKOScyn-9Pk:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=YGp1SQlYPOU:YKOScyn-9Pk:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=YGp1SQlYPOU:YKOScyn-9Pk:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=YGp1SQlYPOU:YKOScyn-9Pk:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=YGp1SQlYPOU:YKOScyn-9Pk:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/YGp1SQlYPOU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/1245452865346972754/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2011/03/my-new-git-pre-commit-hook.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/1245452865346972754?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/1245452865346972754?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/YGp1SQlYPOU/my-new-git-pre-commit-hook.html" title="My new Git pre-commit hook" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>6</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2011/03/my-new-git-pre-commit-hook.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUEFSHs7eSp7ImA9Wx9UEE8.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-8699275971626322314</id><published>2011-02-06T23:26:00.000+02:00</published><updated>2011-02-06T23:26:59.501+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-06T23:26:59.501+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Debian" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>Squeeze + PostgreSQL = Broken</title><content type="html">The PostgreSQL package in Debian squeeze, just released, is linked with libedit instead of libreadline.  This has two interesting properties:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=611918"&gt;It crashes.&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=608442"&gt;You can only enter ASCII characters.&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;If either of these is a concern, think carefully before you upgrade.&lt;br /&gt;
&lt;br /&gt;
Is there a way to at least configure libedit to accept non-ASCII characters?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-8699275971626322314?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=B5wTfX-kM84:8CEbw2U4XWY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=B5wTfX-kM84:8CEbw2U4XWY:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=B5wTfX-kM84:8CEbw2U4XWY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=B5wTfX-kM84:8CEbw2U4XWY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=B5wTfX-kM84:8CEbw2U4XWY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=B5wTfX-kM84:8CEbw2U4XWY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=B5wTfX-kM84:8CEbw2U4XWY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=B5wTfX-kM84:8CEbw2U4XWY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=B5wTfX-kM84:8CEbw2U4XWY:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=B5wTfX-kM84:8CEbw2U4XWY:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=B5wTfX-kM84:8CEbw2U4XWY:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/B5wTfX-kM84" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/8699275971626322314/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2011/02/squeeze-postgresql-broken.html#comment-form" title="15 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/8699275971626322314?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/8699275971626322314?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/B5wTfX-kM84/squeeze-postgresql-broken.html" title="Squeeze + PostgreSQL = Broken" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>15</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2011/02/squeeze-postgresql-broken.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08CR384fSp7ImA9Wx9WEUQ.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-1345967081841991232</id><published>2011-01-16T17:31:00.000+02:00</published><updated>2011-01-16T17:31:06.135+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-16T17:31:06.135+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="FOSDEM" /><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Debian" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>Going</title><content type="html">&lt;a href="http://www.fosdem.org"&gt;&lt;img src="http://www.fosdem.org/promo/going-to" alt="I'm going to FOSDEM, the Free and Open Source Software Developers' European Meeting" /&gt;&lt;/a&gt;&lt;br /&gt;
me too&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-1345967081841991232?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=jcP85tc6mlY:yVmROvkG9rk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=jcP85tc6mlY:yVmROvkG9rk:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=jcP85tc6mlY:yVmROvkG9rk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=jcP85tc6mlY:yVmROvkG9rk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=jcP85tc6mlY:yVmROvkG9rk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=jcP85tc6mlY:yVmROvkG9rk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=jcP85tc6mlY:yVmROvkG9rk:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=jcP85tc6mlY:yVmROvkG9rk:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=jcP85tc6mlY:yVmROvkG9rk:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=jcP85tc6mlY:yVmROvkG9rk:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=jcP85tc6mlY:yVmROvkG9rk:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/jcP85tc6mlY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/1345967081841991232/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2011/01/going.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/1345967081841991232?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/1345967081841991232?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/jcP85tc6mlY/going.html" title="Going" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2011/01/going.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0ABRXczeSp7ImA9Wx9XGEs.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-7976688977303766021</id><published>2011-01-12T22:55:00.000+02:00</published><updated>2011-01-12T22:55:54.981+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-12T22:55:54.981+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="StackOverflow" /><category scheme="http://www.blogger.com/atom/ns#" term="SQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>Perception vs. Reality</title><content type="html">So this is interesting: In the &lt;a href="http://blog.stackoverflow.com/2011/01/survey-says/"&gt;Stack Overflow Annual User Survey&lt;/a&gt;, 62.2% of respondents claim they are "proficient" in SQL.  This tops all the languages listed.  This is perhaps not that surprising, but I had at the same time &amp;mdash; subjectively &amp;mdash; noticed an abundance of let's say clueless questions and suboptimal answers on SQL and RDBMS topics in the StackExchange network.  Quite clearly SQL is somewhat different from algorithmic programming languages in that there is a gap between being familiar with the language and really understanding its effects.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-7976688977303766021?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=Y_cMhrGvTXQ:-mZva0e2Bw0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=Y_cMhrGvTXQ:-mZva0e2Bw0:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=Y_cMhrGvTXQ:-mZva0e2Bw0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=Y_cMhrGvTXQ:-mZva0e2Bw0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=Y_cMhrGvTXQ:-mZva0e2Bw0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=Y_cMhrGvTXQ:-mZva0e2Bw0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=Y_cMhrGvTXQ:-mZva0e2Bw0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=Y_cMhrGvTXQ:-mZva0e2Bw0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=Y_cMhrGvTXQ:-mZva0e2Bw0:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=Y_cMhrGvTXQ:-mZva0e2Bw0:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=Y_cMhrGvTXQ:-mZva0e2Bw0:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/Y_cMhrGvTXQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/7976688977303766021/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2011/01/perception-vs-reality.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/7976688977303766021?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/7976688977303766021?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/Y_cMhrGvTXQ/perception-vs-reality.html" title="Perception vs. Reality" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2011/01/perception-vs-reality.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkAGQ3g9eyp7ImA9Wx9XFEk.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-6525427238892732407</id><published>2011-01-08T00:40:00.001+02:00</published><updated>2011-01-08T01:58:42.663+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-08T01:58:42.663+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Debian" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><category scheme="http://www.blogger.com/atom/ns#" term="Emacs" /><title>Git commit mode</title><content type="html">Hardly anything ruins a glorious day of coding like fat-fingering the commit message late at night as you doze off, and then pushing it out for the world to see. To prevent that, I have equipped my Emacs configuration with a few little tools now.&lt;br /&gt;
&lt;br /&gt;
First, I found the &lt;a href="https://github.com/rafl/git-commit-mode"&gt;git-commit-mode&lt;/a&gt;, a special mode for Git commit messages.  This helps you format the commit messages according to &lt;a href="http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html"&gt;convention&lt;/a&gt;, and will use ugly colors if, for example, you write lines that are too long or you do not keep the second line blank.  It also allows the use of things like &lt;kbd&gt;M-q&lt;/kbd&gt; without shredding the whole file template.&lt;br /&gt;
&lt;br /&gt;
Second, I integrated on-the-fly spell checking into the git-commit-mode.  It won't stop you from writing nonsense, but it will catch the silly mistakes.&lt;br /&gt;
&lt;br /&gt;
Here's a simple configuration snippet:&lt;br /&gt;
&lt;pre&gt;(require 'git-commit)
(add-hook 'git-commit-mode-hook 'turn-on-flyspell)
(add-hook 'git-commit-mode-hook (lambda () (toggle-save-place 0)))&lt;/pre&gt;The last line is handy if you have save-place on by default.  When you make a new commit, it would then normally place the cursor where a previously edited commit message was finished, because to the save-place functionality, it looks as though it's the same file.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-6525427238892732407?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=umqRMZKGAk8:izitupLVL6I:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=umqRMZKGAk8:izitupLVL6I:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=umqRMZKGAk8:izitupLVL6I:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=umqRMZKGAk8:izitupLVL6I:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=umqRMZKGAk8:izitupLVL6I:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=umqRMZKGAk8:izitupLVL6I:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=umqRMZKGAk8:izitupLVL6I:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=umqRMZKGAk8:izitupLVL6I:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=umqRMZKGAk8:izitupLVL6I:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=umqRMZKGAk8:izitupLVL6I:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=umqRMZKGAk8:izitupLVL6I:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/umqRMZKGAk8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/6525427238892732407/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2011/01/git-commit-mode.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/6525427238892732407?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/6525427238892732407?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/umqRMZKGAk8/git-commit-mode.html" title="Git commit mode" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2011/01/git-commit-mode.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQEQnw4fip7ImA9Wx9SE08.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-3366671105011064985</id><published>2010-12-02T22:05:00.000+02:00</published><updated>2010-12-02T22:05:03.236+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-02T22:05:03.236+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>Development time</title><content type="html">Let's say you want to contribute to PostgreSQL development and want to play by the rules (which are actually not rules, but guidelines or encouragements), such as:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;While a release is in beta, you work on finalizing the release, not on future projects.&lt;/li&gt;
&lt;li&gt;During a commitfest, you work on testing and integrating the proposals submitted for the commitfest, not on new features.&lt;/li&gt;
&lt;li&gt;Major features should not be submitted for the first time at the last commitfest.&lt;/li&gt;
&lt;/ol&gt;The final release of PostgreSQL 9.0.0 was on 2010-09-20. By that time you already missed the first commitfest (2010-07), and the second commitfest (2010-09) was already under way. The second commitfest was actually slightly delayed and ended on 2010-10-26, whereas the third and next-to-last-for-9.1 commitfest (2010-11) started punctually on 2010-11-15.&lt;br /&gt;
&lt;br /&gt;
That means if, while being a team player on all the community efforts, you wanted to develop a major new feature for PostgreSQL 9.1, you had a total of about 20 days to do it. (That is, if you didn't spend several days in early November at PgWest.) And that is within a one-year release cycle.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-3366671105011064985?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=HSuLwDWDy8I:cJIRc9QDH0E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=HSuLwDWDy8I:cJIRc9QDH0E:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=HSuLwDWDy8I:cJIRc9QDH0E:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=HSuLwDWDy8I:cJIRc9QDH0E:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=HSuLwDWDy8I:cJIRc9QDH0E:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=HSuLwDWDy8I:cJIRc9QDH0E:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=HSuLwDWDy8I:cJIRc9QDH0E:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=HSuLwDWDy8I:cJIRc9QDH0E:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=HSuLwDWDy8I:cJIRc9QDH0E:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=HSuLwDWDy8I:cJIRc9QDH0E:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=HSuLwDWDy8I:cJIRc9QDH0E:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/HSuLwDWDy8I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/3366671105011064985/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2010/12/development-time.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/3366671105011064985?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/3366671105011064985?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/HSuLwDWDy8I/development-time.html" title="Development time" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2010/12/development-time.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk8EQX84cCp7ImA9Wx5bGU0.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-7894594231724448254</id><published>2010-11-04T23:06:00.000+02:00</published><updated>2010-11-04T23:06:40.138+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-04T23:06:40.138+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Debian" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><category scheme="http://www.blogger.com/atom/ns#" term="Bash" /><title>pipefail</title><content type="html">It is widely considered good style to include&lt;br /&gt;
&lt;pre&gt;set -e&lt;/pre&gt;near the beginning of a shell script so that it aborts when there is an uncaught error.  The Debian policy also &lt;a href="http://www.debian.org/doc/debian-policy/ch-maintainerscripts.html#s6.1"&gt;recommends this&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this doesn't work in pipelines.  So if you have something like&lt;br /&gt;
&lt;pre&gt;some_command | sed '...'&lt;/pre&gt;a failure of &lt;code&gt;some_command&lt;/code&gt; won't be recognized.&lt;br /&gt;
&lt;br /&gt;
By default, the return status of a pipeline is the return status of the last command.  So that would be the &lt;code&gt;sed&lt;/code&gt; command above, which is usually not the failure candidate you're worried about.  Also, the definition of &lt;code&gt;set -e&lt;/code&gt; is to exit immediately if the return status of the last &lt;em&gt;pipeline&lt;/em&gt; is nonzero, so the exit status of &lt;code&gt;some_command&lt;/code&gt; isn't considered there.&lt;br /&gt;
&lt;br /&gt;
Fortunately, there is a straightforward solution, which might not be very well known.  Use&lt;br /&gt;
&lt;pre&gt;set -o pipefail&lt;/pre&gt;With &lt;code&gt;pipefail&lt;/code&gt;, the return status of a pipeline is "the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands exit successfully".  So if &lt;code&gt;some_command&lt;/code&gt; fails, the whole pipeline fails, and &lt;code&gt;set -e&lt;/code&gt; kicks in.  So you need to use &lt;code&gt;set -o pipefail&lt;/code&gt; and &lt;code&gt;set -e&lt;/code&gt; together to get this effect.&lt;br /&gt;
&lt;br /&gt;
This only works in bash, so if you're trying to write scripts that conform to POSIX or some other standard, you can't use it.  (There are usually other ways to discover failures in pipelines in other shells, but none are as simple as this one, it appears.)  But if you are writing bash anyway, you should definitely use it.  And if you're not using bash but use a lot of pipelines in your scripts, you should perhaps consider using bash.&lt;br /&gt;
&lt;br /&gt;
(Hmm, it looks like there could be a number of latent bugs in the existing Debian package maintainer scripts, because this issue appears to be widely ignored.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-7894594231724448254?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=CXfUSzH9MIA:deVhFlr3Oo8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=CXfUSzH9MIA:deVhFlr3Oo8:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=CXfUSzH9MIA:deVhFlr3Oo8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=CXfUSzH9MIA:deVhFlr3Oo8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=CXfUSzH9MIA:deVhFlr3Oo8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=CXfUSzH9MIA:deVhFlr3Oo8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=CXfUSzH9MIA:deVhFlr3Oo8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=CXfUSzH9MIA:deVhFlr3Oo8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=CXfUSzH9MIA:deVhFlr3Oo8:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=CXfUSzH9MIA:deVhFlr3Oo8:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=CXfUSzH9MIA:deVhFlr3Oo8:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/CXfUSzH9MIA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/7894594231724448254/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2010/11/pipefail.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/7894594231724448254?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/7894594231724448254?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/CXfUSzH9MIA/pipefail.html" title="pipefail" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2010/11/pipefail.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0ENQ3g_fCp7ImA9Wx5bFk4.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-5163705193991919023</id><published>2010-11-01T21:28:00.000+02:00</published><updated>2010-11-01T21:28:12.644+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-11-01T21:28:12.644+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Git" /><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Debian" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>Git User's Survey 2010 Results</title><content type="html">The results of the &lt;a href="https://git.wiki.kernel.org/index.php/GitSurvey2010"&gt;Git User's Survey 2010&lt;/a&gt; are up.&lt;br /&gt;
&lt;br /&gt;
Not many surprises, but I can see how this sort of survey is very useful for the developers of Git.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-5163705193991919023?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=UCMTJn7f3i0:6atKfjA3HAQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=UCMTJn7f3i0:6atKfjA3HAQ:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=UCMTJn7f3i0:6atKfjA3HAQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=UCMTJn7f3i0:6atKfjA3HAQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=UCMTJn7f3i0:6atKfjA3HAQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=UCMTJn7f3i0:6atKfjA3HAQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=UCMTJn7f3i0:6atKfjA3HAQ:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=UCMTJn7f3i0:6atKfjA3HAQ:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=UCMTJn7f3i0:6atKfjA3HAQ:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=UCMTJn7f3i0:6atKfjA3HAQ:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=UCMTJn7f3i0:6atKfjA3HAQ:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/UCMTJn7f3i0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/5163705193991919023/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2010/11/git-users-survey-2010-results.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/5163705193991919023?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/5163705193991919023?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/UCMTJn7f3i0/git-users-survey-2010-results.html" title="Git User's Survey 2010 Results" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2010/11/git-users-survey-2010-results.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak4CRXo6fSp7ImA9Wx5VEkQ.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-3132187132877331995</id><published>2010-10-05T20:16:00.000+03:00</published><updated>2010-10-05T20:16:04.415+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-05T20:16:04.415+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Git" /><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Debian" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>Git User's Survey 2010</title><content type="html">The &lt;a href="https://www.survs.com/survey/MUPYR8UJ4B"&gt;Git User's Survey 2010&lt;/a&gt; is up. Please devote a few minutes of your time to fill out the simple questionnaire; it'll help the Git community understand your needs, what you like about Git (and what you don't), and help improve it.&lt;br /&gt;
&lt;br /&gt;
The survey is open from 1 September to 15 October, 2010.&lt;br /&gt;
&lt;br /&gt;
Go to &lt;a href="https://git.wiki.kernel.org/index.php/GitSurvey2010"&gt;https://git.wiki.kernel.org/index.php/GitSurvey2010&lt;/a&gt; for more information.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-3132187132877331995?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=a0Vi-H7QqYs:nMjdDyY_ggc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=a0Vi-H7QqYs:nMjdDyY_ggc:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=a0Vi-H7QqYs:nMjdDyY_ggc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=a0Vi-H7QqYs:nMjdDyY_ggc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=a0Vi-H7QqYs:nMjdDyY_ggc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=a0Vi-H7QqYs:nMjdDyY_ggc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=a0Vi-H7QqYs:nMjdDyY_ggc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=a0Vi-H7QqYs:nMjdDyY_ggc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=a0Vi-H7QqYs:nMjdDyY_ggc:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=a0Vi-H7QqYs:nMjdDyY_ggc:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=a0Vi-H7QqYs:nMjdDyY_ggc:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/a0Vi-H7QqYs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/3132187132877331995/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2010/10/git-users-survey-2010.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/3132187132877331995?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/3132187132877331995?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/a0Vi-H7QqYs/git-users-survey-2010.html" title="Git User's Survey 2010" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2010/10/git-users-survey-2010.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEIBQnc-fip7ImA9Wx5TE0k.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-7254060052395031757</id><published>2010-07-28T22:49:00.000+03:00</published><updated>2010-07-28T22:49:13.956+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-28T22:49:13.956+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Flymake" /><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><category scheme="http://www.blogger.com/atom/ns#" term="Emacs" /><title>PostgreSQL and Flymake</title><content type="html">&lt;a href="http://flymake.sourceforge.net/"&gt;Flymake&lt;/a&gt; is an on-the-fly syntax checker for Emacs.  Here is how you can use it for editing the PostgreSQL source code.  Add this to your &lt;tt&gt;src/Makefile.custom&lt;/tt&gt;:&lt;br /&gt;
&lt;pre&gt;check-syntax:
        $(COMPILE.c) -fsyntax-only $(CHK_SOURCES)&lt;/pre&gt;Then you can activate the flymake minor mode either manually using &lt;kbd&gt;M-x flymake-mode&lt;/kbd&gt;, or by adding it to your Emacs customization for PostgreSQL.  I use:&lt;br /&gt;
&lt;pre&gt;(defun pgsql-c-mode ()
  "C mode adjusted for PostgreSQL project"
  (interactive)
  (c-mode)
  (flymake-mode)

  ; .. and the rest ...
)&lt;/pre&gt;Here is a screenshot:&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_dgdplFJMdoQ/TFCHQHxmUWI/AAAAAAAAADg/WMmVpBJYC9o/s1600/flymake-postgresql1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="321" src="http://1.bp.blogspot.com/_dgdplFJMdoQ/TFCHQHxmUWI/AAAAAAAAADg/WMmVpBJYC9o/s400/flymake-postgresql1.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;Notice the marked line with the syntax error and the tooltip/popup with the error message, which appears when the mouse hovers over the marked line.&lt;br /&gt;
&lt;br /&gt;
Note, however, that since activating flymake will essentially cause a compiler to be running continuously in the background, this is not what you want to use when hacking PostgreSQL on the road. ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-7254060052395031757?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=O5WYk6DrGcA:D_kLoKgPw1Y:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=O5WYk6DrGcA:D_kLoKgPw1Y:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=O5WYk6DrGcA:D_kLoKgPw1Y:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=O5WYk6DrGcA:D_kLoKgPw1Y:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=O5WYk6DrGcA:D_kLoKgPw1Y:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=O5WYk6DrGcA:D_kLoKgPw1Y:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=O5WYk6DrGcA:D_kLoKgPw1Y:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=O5WYk6DrGcA:D_kLoKgPw1Y:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=O5WYk6DrGcA:D_kLoKgPw1Y:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=O5WYk6DrGcA:D_kLoKgPw1Y:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=O5WYk6DrGcA:D_kLoKgPw1Y:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/O5WYk6DrGcA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/7254060052395031757/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2010/07/postgresql-and-flymake.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/7254060052395031757?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/7254060052395031757?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/O5WYk6DrGcA/postgresql-and-flymake.html" title="PostgreSQL and Flymake" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_dgdplFJMdoQ/TFCHQHxmUWI/AAAAAAAAADg/WMmVpBJYC9o/s72-c/flymake-postgresql1.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2010/07/postgresql-and-flymake.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4NSXk4fip7ImA9WxFbEU4.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-1881352655423398436</id><published>2010-07-03T07:23:00.000+03:00</published><updated>2010-07-03T07:23:18.736+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-03T07:23:18.736+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Debian" /><category scheme="http://www.blogger.com/atom/ns#" term="APT" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>Increasing the priority of Debian experimental</title><content type="html">Many people run Debian testing or unstable or some mix thereof.&amp;nbsp; This works pretty well for a development system or a general desktop system if you know a bit about what you're doing (note: nonetheless officially not recommended).&amp;nbsp; Sometimes you throw packages from &lt;a href="http://www.debian.org/doc/developers-reference/resources#experimental"&gt;experimental&lt;/a&gt; into the mix, if you want to get the latest stuff that isn't yet fully integrated into the rest of Debian.&lt;br /&gt;
&lt;br /&gt;
The default APT priority of the Debian experimental release &lt;a href="http://www.debian.org/doc/manuals/reference/ch02.en.html#_archive_level_release_files"&gt;is 1&lt;/a&gt;, which ensures that it is never automatically installed or upgraded. This is not always ideal, in my experience. Of course, you don't want a package from experimental to take precedence over a package from stable, testing, or unstable by default. But I think when you have in the past installed a package from experimental, you probably want to pull in upgrades to that package from experimental as well. Otherwise, you will end up with completely unmaintained packages on your system.&amp;nbsp; That is because in practice many packages in experimental are not actually experimental or broken or unmaintained, but just an advance branch of some software that is just for some reason not ready to go down the unstable-testing-stable road.&lt;br /&gt;
&lt;br /&gt;
To make this work better, I have set the priority of experimental to 101 in my &lt;tt&gt;/etc/apt/preferences&lt;/tt&gt;:&lt;pre&gt;Package: *
Pin: release experimental
Pin-Priority: 101&lt;/pre&gt;Now the following will happen: If you just &lt;tt&gt;apt-get install&lt;/tt&gt; a package, it will come from whatever "normal" release you have in your sources.list, say stable or testing. You can override that using &lt;tt&gt;-t experimental&lt;/tt&gt; as usual. If you install a package from experimental and later an upgrade is available in experimental, &lt;tt&gt;apt-get upgrade&lt;/tt&gt; will install that automatically. Also, if an upgrade in a "normal" release appears that has a higher version number, that version will be installed.&lt;br /&gt;
&lt;br /&gt;
Of course, caveats apply. Some software in experimental is &lt;i&gt;really&lt;/i&gt; experimental and should only be installed under close supervision. If a package is available only in experimental, this setup will install it when you ask for the package, even if you might not have actually wanted it if you had known that it was in experimental.  Figure it out yourself. :)&lt;br /&gt;
&lt;br /&gt;
Similar considerations apply to &lt;a href="http://www.backports.org/"&gt;backports&lt;/a&gt;. I use&lt;pre&gt;Package: *
Pin: release a=lenny-backports
Pin-Priority: 102&lt;/pre&gt;On the system I have in mind here, the standard distribution is stable, testing is 101, and backports is 102, taking precedence over testing. Because for some architecture-independent packages you don't need backports, so you can pull them directly from testing that way.&lt;br /&gt;
&lt;br /&gt;
In general, the APT priority business is relatively powerful and often a good alternative to, say, manually downloading packages from various distributions, installing them manually, forgetting where they came from, and never upgrading them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-1881352655423398436?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=-es6REb__XM:DOPM4Cn0TFo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=-es6REb__XM:DOPM4Cn0TFo:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=-es6REb__XM:DOPM4Cn0TFo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=-es6REb__XM:DOPM4Cn0TFo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=-es6REb__XM:DOPM4Cn0TFo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=-es6REb__XM:DOPM4Cn0TFo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=-es6REb__XM:DOPM4Cn0TFo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=-es6REb__XM:DOPM4Cn0TFo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=-es6REb__XM:DOPM4Cn0TFo:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=-es6REb__XM:DOPM4Cn0TFo:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=-es6REb__XM:DOPM4Cn0TFo:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/-es6REb__XM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/1881352655423398436/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2010/07/increasing-priority-of-debian.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/1881352655423398436?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/1881352655423398436?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/-es6REb__XM/increasing-priority-of-debian.html" title="Increasing the priority of Debian experimental" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2010/07/increasing-priority-of-debian.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEMQ346fip7ImA9WxFUGUg.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-6654931650562384186</id><published>2010-07-01T05:50:00.001+03:00</published><updated>2010-07-01T05:51:22.016+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-01T05:51:22.016+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>An Update On Views</title><content type="html">A long time ago, in a text book far away, someone described the following (relational) database design approach: Put all your data in tables, normalized and so on, as you'd expect.&amp;nbsp; An top of each table, create a view.&amp;nbsp; The database clients only access the views.&amp;nbsp; As the application evolves, tables might change, more views will be added, but the interface that the existing views present to the outside stays the same.&amp;nbsp; Sounds nice; everything stays backward compatible.&lt;br /&gt;
&lt;br /&gt;
In order for this to work, views need to be updatable.&amp;nbsp; Updatable views have been standardized in SQL as far back as 1992, and have been implemented (partially, possibly) in some of the popular/successful SQL implementations.&amp;nbsp; Curiously, however, this feature has evaded PostgreSQL altogether so far.&amp;nbsp; Conventional wisdom has held it that views can be made updatable by hand using the rewrite rules system, and a proper implementation of automatically updatable views would only need to create the rules automatically.&amp;nbsp; Debate and coding around this idea has been taking place for many years, mostly inspired by the heroic efforts of &lt;a href="http://psoos.blogspot.com/"&gt;Bernd Helmle&lt;/a&gt;.&amp;nbsp; But I think the conclusion of those in the know by now is that the rewrite rules system is inappropriate for this task (and in fact others have argued that the rewrite rules system is inappropriate for any task and should be ripped out; perhaps harsh but not far from the truth in my opinion).&amp;nbsp; So the updatable views effort is at square one (or zero) at the moment.&lt;br /&gt;
&lt;br /&gt;
In the meantime, updatable views have been conspicuously absent from any of the recent &lt;a href="http://rhaas.blogspot.com/2010/05/lots-and-lots-of-postgresql-feature.html"&gt;top-needed features list&lt;/a&gt; for PostgreSQL.&amp;nbsp; Which basically means no one really cares (anymore).&amp;nbsp; Why is that?&lt;br /&gt;
&lt;br /&gt;
My observation is that the typical use of views has changed quite a bit of the years (decades), and has decreased altogether.&amp;nbsp; The idea of using views as transparent interfaces on top of tables never really took off to begin with.&amp;nbsp; Using views to encapsulate complex queries is still reasonable, but not terribly common.&amp;nbsp; Part of the reason is that many queries are generated, either by ORMs or by custom code.&amp;nbsp; The other reason is that server-side functions provide a much more powerful abstraction mechanism.&amp;nbsp; They can't do everything, in particular inlining of queries doesn't alway work, but they can do a lot more with parameters and general procedural programming.&amp;nbsp; Views are also used for access control, either for columns or for rows.&amp;nbsp; Column security can now be had with explicit column privileges in PostgreSQL, and one could argue that using views for this was a workaround all along.&amp;nbsp; And using &lt;a href="http://archives.postgresql.org/message-id/4AE02DF0.40101@enterprisedb.com"&gt;views for row access control doesn't actually really work&lt;/a&gt;, as it turns out.&amp;nbsp; Proper row security might be an upcoming feature, but it will need to work differently.&amp;nbsp; And anyway, superfinely granular access control is rather rare in SQL databases overall, I guess.&amp;nbsp; And in all of these cases, the views don't need to be updatable.&lt;br /&gt;
&lt;br /&gt;
Views are occasionally used as a thin wrapper around a table-returning function, so the function can be access like a table.&amp;nbsp; But this only works when reading.&amp;nbsp; Another use, somewhat related actually, is defining views for monitoring the database system or the database application.&amp;nbsp; Because those views are often used interactively, it is&lt;br /&gt;
important that they are convenient to access, and so hugely complex queries combined with custom functions or possibly query generation are inappropriate.&lt;br /&gt;
&lt;br /&gt;
On the other hand, materialized views are all the rage now, appearing at the top of the requested PostgreSQL feature list, and having been fixtures in the feature lists of other SQL implementations for some time.&amp;nbsp; While traditional views are a tool for organizing code and interfaces, materialized views are purely a performance optimization tool (which, by the way, is the reason materialized views are not&lt;br /&gt;
specified in the SQL standard).&amp;nbsp; Depending on how you implement materialized views, they might even be usable implicitly, if the query matches the materialized query.&amp;nbsp; Then, materialized views wouldn't really be views at all anymore, they're just query caches.&lt;br /&gt;
&lt;br /&gt;
So, what do you think?&amp;nbsp; Are traditional views an obsolescent, marginal feature?&amp;nbsp; Is the matter of updatable views obsolete?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-6654931650562384186?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=tUZcr3DZXvs:jsj8CPc2R0Q:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=tUZcr3DZXvs:jsj8CPc2R0Q:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=tUZcr3DZXvs:jsj8CPc2R0Q:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=tUZcr3DZXvs:jsj8CPc2R0Q:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=tUZcr3DZXvs:jsj8CPc2R0Q:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=tUZcr3DZXvs:jsj8CPc2R0Q:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=tUZcr3DZXvs:jsj8CPc2R0Q:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=tUZcr3DZXvs:jsj8CPc2R0Q:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=tUZcr3DZXvs:jsj8CPc2R0Q:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=tUZcr3DZXvs:jsj8CPc2R0Q:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=tUZcr3DZXvs:jsj8CPc2R0Q:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/tUZcr3DZXvs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/6654931650562384186/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2010/07/update-on-views.html#comment-form" title="21 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/6654931650562384186?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/6654931650562384186?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/tUZcr3DZXvs/update-on-views.html" title="An Update On Views" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>21</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2010/07/update-on-views.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkUNRHc-fSp7ImA9WxFWEEo.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-6571909025494949734</id><published>2010-05-28T23:24:00.000+03:00</published><updated>2010-05-28T23:24:55.955+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-28T23:24:55.955+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="SQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>System-Versioned Tables</title><content type="html">After my &lt;a href="http://petereisentraut.blogspot.com/2010/04/news-from-sql-standard.html"&gt;report on the upcoming SQL:2011&lt;/a&gt;, some people had asked me about the system-versioned table feature that is going to be the arguably only major new feature there.  Here is how it works:&lt;pre&gt;CREATE TABLE tab (
    useful_data int,
    more_data varchar,
    start timestamp GENERATED ALWAYS AS SYSTEM VERSION START,
    end timestamp GENERATED ALWAYS AS SYSTEM VERSION END
) WITH SYSTEM VERSIONING;&lt;/pre&gt;(This hilariously verbose syntax arises because this is defined so that it fits into the more general generated columns feature, e.&amp;nbsp;g., &lt;code&gt;GENERATED ALWAYS AS IDENTITY&lt;/code&gt;, similar to PostgreSQL's serial type.)&lt;br /&gt;
&lt;pre&gt;INSERT INTO tab (useful_data, more_data) VALUES (...);&lt;/pre&gt;This sets the "start" column to the current transaction timestamp, and the "end" column to the highest possible timestamp value.&lt;br /&gt;
&lt;pre&gt;UPDATE tab SET useful_data = something WHERE more_data = whatever;&lt;/pre&gt;For each row that would normally be updated, set the "end" timestamp to the current transaction timestamp, and insert a new row with the "start" timestamp set to the current transaction timestamp.  &lt;code&gt;DELETE&lt;/code&gt; works analogously.&lt;br /&gt;
&lt;pre&gt;SELECT * FROM tab;&lt;/pre&gt;This only shows rows where &lt;code&gt;current_timestamp&lt;/code&gt; is between "start" and "end".  To show the non-current data, the following options are&lt;br /&gt;
possible:&lt;pre&gt;SELECT * FROM tab AS OF SYSTEM TIME timestamp;
SELECT * FROM tab VERSIONS BEFORE SYSTEM TIME timestamp;
SELECT * FROM tab VERSIONS AFTER SYSTEM TIME timestamp;
SELECT * FROM tab VERSIONS BETWEEN SYSTEM TIME timestamp AND timestamp;&lt;/pre&gt;There's also the option of&lt;pre&gt;CREATE TABLE tab ( ... ) WITH SYSTEM VERSIONING KEEP VERSIONS FOR interval;&lt;/pre&gt;to automatically delete old versions.&lt;br /&gt;
&lt;br /&gt;
That's more or less it.  It's pretty much xmin/xmax/vacuum on a higher level with timestamps instead of numbers.  And it's a revival of the old time travel feature.  Obviously, you can do most or all of this with triggers already.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-6571909025494949734?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=adhMZnHTXIM:ezdnh7l8p6M:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=adhMZnHTXIM:ezdnh7l8p6M:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=adhMZnHTXIM:ezdnh7l8p6M:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=adhMZnHTXIM:ezdnh7l8p6M:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=adhMZnHTXIM:ezdnh7l8p6M:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=adhMZnHTXIM:ezdnh7l8p6M:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=adhMZnHTXIM:ezdnh7l8p6M:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=adhMZnHTXIM:ezdnh7l8p6M:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=adhMZnHTXIM:ezdnh7l8p6M:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=adhMZnHTXIM:ezdnh7l8p6M:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=adhMZnHTXIM:ezdnh7l8p6M:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/adhMZnHTXIM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/6571909025494949734/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2010/05/system-versioned-tables.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/6571909025494949734?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/6571909025494949734?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/adhMZnHTXIM/system-versioned-tables.html" title="System-Versioned Tables" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>6</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2010/05/system-versioned-tables.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0EGRXc6fip7ImA9WxFXEkQ.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-4922075580998574655</id><published>2010-05-19T22:00:00.000+03:00</published><updated>2010-05-19T22:00:24.916+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-19T22:00:24.916+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>PostgreSQL Package Management</title><content type="html">Database development sucks, and I would like to fix it.  I don't mean database system software development; that's awesome. ;-)  I mean database development as in writing the tables, views, functions, and other code that make up your database.  We have come further in recent years in PostgreSQL land.  We have had the &lt;a href="http://pgfoundry.org/projects/edb-debugger/"&gt;PL/pgSQL debugger&lt;/a&gt;, there is &lt;a href="http://github.com/kputnam/piggly"&gt;Piggly&lt;/a&gt; for PL/pgSQL code coverage, we have &lt;a href="http://pgtap.org/"&gt;pgTAP&lt;/a&gt; for unit testing support, we have in &lt;a href="http://www.post-facto.org/"&gt;Post Facto&lt;/a&gt; a version control system running inside the database, although I'll try to explain below why I think that that is not the right solution.  My problem is that getting database code from the editor to the database server in a safe manner is pretty difficult.  This already starts with deploying simple database code to a single server for the first time (as shown in this &lt;a href="http://petereisentraut.blogspot.com/2010/03/running-sql-scripts-with-psql.html"&gt;entry&lt;/a&gt;), and gradually gets more complicated when you need to update existing installations, manage multiple servers, or even multiple versions of that code.&lt;br /&gt;
&lt;br /&gt;
My answer to that problem is an old friend: package management.  Package managers such as dpkg and rpm are pretty well-established solutions and have shown over the years that managing software deployments can be easy and occasionally even fun.&lt;br /&gt;
&lt;br /&gt;
Consider how the development and deployment of normal software proceeds:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;You edit some files in your text editor.&lt;br /&gt;
&lt;li&gt;You execute some kind of build step (could be compilation or more trivial).&lt;br /&gt;
&lt;li&gt;Maybe you run a test suite.&lt;br /&gt;
&lt;li&gt;You check your files into version control.&lt;br /&gt;
&lt;/ul&gt;And then you or someone else, perhaps a release manager or system administratior does something like this:
&lt;ul&gt;&lt;li&gt;Tag a release.&lt;br /&gt;
&lt;li&gt;Export the tag from version control.&lt;br /&gt;
&lt;li&gt;Build the software.&lt;br /&gt;
&lt;li&gt;Run tests.&lt;br /&gt;
&lt;li&gt;Build a package.&lt;br /&gt;
&lt;li&gt;Push package to repository.&lt;br /&gt;
&lt;li&gt;Install/upgrade package on deployment machines.&lt;br /&gt;
&lt;/ul&gt;There are of course sites that do this differently.  One could, for example, just copy the built files onto the target machines.  But if you do that, then you might as well be happy with the current state of SQL deployment.  Many sites are going for &lt;a href="http://omniti.com/seeds/online-application-deployment-reducing-risk"&gt;continuous deployment&lt;/a&gt; nowadays, in which case you might not need a way to track what version of the code is currently running, but you will still want a way to make deployments and upgrades in a safe manner.

My premise is that the development cycle of database software should work in pretty much the same way as for other software.  But we are only slowly getting the tools to support this work flow.

We have editors that allow editing SQL, of course.  We don't really need any new build tools; the existing ones appear to serve just fine.  We have testing support, getting better all the time.  At this point it was once thought that perhaps a database-based version control system such as Post Facto would address the remaining issues.  After considering that for a while I have figured out that it doesn't.  The main problems with that approach are:
&lt;ul&gt;&lt;li&gt;Abuses version control system as a deployment tool.  Some people deploy code by svn checkout, but most don't.&lt;br /&gt;
&lt;li&gt;Does not allow for a build step (in a straightforward manner).  The database is the source code.  You can't generate your database from some XML source, for example.&lt;br /&gt;
&lt;li&gt;I consider it preferable to put database code and related non-database code in the same version control system, so they can be developed, browsed, deployed, etc. together.&lt;br /&gt;
&lt;/ul&gt;A database-based version control system might actually be the thing for some people, just like other version control systems serve different needs.  (Except, note that mine is better than yours! ;-) )
&lt;p&gt;So I think what the world needs is a package manager for databases, that manages database objects just like a package manager for operating systems manages files.  And it should work in much the same ways, like this:
&lt;ul&gt;&lt;li&gt;Conceptually, there are two major modes of operation: building a package and installing a package (think &lt;tt&gt;rpmbuild&lt;/tt&gt; and &lt;tt&gt;rpm&lt;/tt&gt;, or &lt;tt&gt;dpkg-buildpackage&lt;/tt&gt; and &lt;tt&gt;dpkg&lt;/tt&gt;).&lt;br /&gt;
&lt;li&gt;Building a package is controlled by a special instruction file (think RPM spec file or &lt;tt&gt;debian/&lt;/tt&gt; directory).&lt;br /&gt;
&lt;li&gt;Building a package involves running that software's normal build routine and installing it into a temporary staging area.  In simple cases, this is running &lt;tt&gt;psql -f somefile.sql&lt;/tt&gt;, but it could be anything.  You could have an ORM tool generate the database.&lt;br /&gt;
&lt;li&gt;The package file is an archive file containing the contents of that staging area plus some metadata.&lt;br /&gt;
&lt;li&gt;Installing a package unpacks the archive file and places the contents into the designated destination, while sensibly dealing with existing installations.&lt;br /&gt;
&lt;/ul&gt;There are additional features of well-known package managers that could be of interest in a database environment: pre/post scripts for additional setup, relocations (perhaps for selecting installation schemas), integration with a repository manager (like yum or apt).
&lt;p&gt;So I have set out to write such a tool and have arrived at a small prototype.  Here is how it works:&lt;pre&gt;$ pgpkg build
 pgpgk/rules clean
make: Nothing to be done for `clean'.
 pgpgk/rules build
make: Nothing to be done for `build'.
 pgpgk/rules binary
psql -X -q -f install_foo.sql
pgpkg create
wrote ../foo_1.0.pgpkg&lt;/pre&gt;This build process is currently driven by a Debian-style rules and
control file.  An RPM-style spec file might also be possible.
&lt;pre&gt;$ pgpkg contents ../foo_1.0.pgpkg
{'Client-Encoding': 'UTF8', 'Version': 1.0, 'Format': '0.0', 'Package': 'foo'}
CREATE FUNCTION "public"."test1"(integer) RETURNS integer LANGUAGE "sql" VOLATILE AS $$select 1$$;
CREATE FUNCTION "public"."test2"(integer) RETURNS integer LANGUAGE "sql" VOLATILE AS $$select 2$$;
CREATE FUNCTION "public"."test3"(integer, integer) RETURNS integer LANGUAGE "sql" VOLATILE AS $$select 3$$;

$ pgpkg install -d 'dbname=bar' ../foo_1.0.pgpkg

$ pgpkg remove -d 'dbname=bar' foo&lt;/pre&gt;
There are more features planned, such as diffing packages, but I haven't gotten to those yet.  Also, don't get too excited yet, it only handles a very small subset of SQL objects.  Much more code needs to be added to handle everything, but that will mostly be a typing exercise (famous last words).
&lt;p&gt;Ah, but what about this &lt;a href="http://wiki.postgresql.org/wiki/ExtensionPackaging"&gt;extension packaging&lt;/a&gt; business that has been discussed for the last couple of years?  Well, I have been
staring at the various design documents for that same couple of years now, and it's not going anywhere and it's not really set out to solve my problem.  Partially by coincidence, partially by intent, as I'm posting this the guys are &lt;a href="http://wiki.postgresql.org/wiki/PgCon_2010_Developer_Meeting"&gt;sitting&lt;/a&gt; in Ottawa discussing extension packaging yet again, so at least take this as a challenge to get something going. :-)
&lt;p&gt;Note that I am calling this thing a "package", because that's what it is.  It's not (necessarily) an "extension" (although an extension could be packaged as a package), and it's not a "module" (that term is reserved by SQL; what Oracle calls a package is actually a module).
&lt;p&gt;Also note that this is implemented as an external program, not in the database server.  I think the operating system shell is a much more usable and versatile environment.  Think of all the things you might want to do: build many packages, compare packages, install
some/many/all packages, grep package contents, copy, download, or upload packages.  This makes most sense from the shell.  If you think about it, neither dpkg nor rpm require extensions in the kernel or the file system to do their work; the same applies here.  Another advantage is that the implementation can evolve faster and doesn't need to wait for say PostgreSQL 9.1 to be out.
&lt;p&gt;Anyway, for the moment, forget about extensions.  Think about the database application code that you need to move around.  Does the above approach make sense?  Could it be useful?  Ideas, suggestions?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-4922075580998574655?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=BlZCSUOAEJk:o-NiudTuqwQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=BlZCSUOAEJk:o-NiudTuqwQ:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=BlZCSUOAEJk:o-NiudTuqwQ:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=BlZCSUOAEJk:o-NiudTuqwQ:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=BlZCSUOAEJk:o-NiudTuqwQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=BlZCSUOAEJk:o-NiudTuqwQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=BlZCSUOAEJk:o-NiudTuqwQ:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=BlZCSUOAEJk:o-NiudTuqwQ:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=BlZCSUOAEJk:o-NiudTuqwQ:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=BlZCSUOAEJk:o-NiudTuqwQ:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=BlZCSUOAEJk:o-NiudTuqwQ:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/BlZCSUOAEJk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/4922075580998574655/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2010/05/postgresql-package-management.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/4922075580998574655?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/4922075580998574655?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/BlZCSUOAEJk/postgresql-package-management.html" title="PostgreSQL Package Management" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><thr:total>5</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2010/05/postgresql-package-management.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0MCQHw7fSp7ImA9WxFXEUs.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-6923279425943817314</id><published>2010-05-18T08:44:00.000+03:00</published><updated>2010-05-18T08:44:21.205+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-18T08:44:21.205+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="EXPLAIN" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>Visual Explain Reloaded</title><content type="html">One of the new features in PostgreSQL 9.0 is &lt;a href="http://www.postgresql.org/docs/9.0/static/sql-explain.html"&gt;EXPLAIN&lt;/a&gt; output in different markup formats (XML, JSON, YAML).  The idea is that this makes it easier for programs (as opposed to humans) to parse the output.&lt;br /&gt;
&lt;br /&gt;
Using one of the standard &lt;a href="http://www.postgresql.org/docs/9.0/static/using-explain.html"&gt;teaching examples&lt;/a&gt;, compare the outputs:&lt;br /&gt;
&lt;pre&gt;regression=&amp;gt; EXPLAIN SELECT * FROM tenk1 t1, tenk2 t2
WHERE t1.unique1 &amp;lt; 100 AND t1.unique2 = t2.unique2;
                                        QUERY PLAN
------------------------------------------------------------------------------------------
 Hash Join  (cost=227.95..700.46 rows=101 width=488)
   Hash Cond: (t2.unique2 = t1.unique2)
   -&amp;gt;  Seq Scan on tenk2 t2  (cost=0.00..434.00 rows=10000 width=244)
   -&amp;gt;  Hash  (cost=226.68..226.68 rows=101 width=244)
         -&amp;gt;  Bitmap Heap Scan on tenk1 t1  (cost=5.03..226.68 rows=101 width=244)
               Recheck Cond: (unique1 &amp;lt; 100)
               -&amp;gt;  Bitmap Index Scan on tenk1_unique1  (cost=0.00..5.01 rows=101 width=0)
                     Index Cond: (unique1 &amp;lt; 100)
(8 rows)
&lt;/pre&gt;&lt;pre&gt;regression=&amp;gt; EXPLAIN (FORMAT JSON) SELECT * FROM tenk1 t1, tenk2 t2
WHERE t1.unique1 &amp;lt; 100 AND t1.unique2 = t2.unique2;

                     QUERY PLAN
-----------------------------------------------------
 [                                                  +
   {                                                +
     "Plan": {                                      +
       "Node Type": "Hash Join",                    +
       "Join Type": "Inner",                        +
       "Startup Cost": 227.95,                      +
       "Total Cost": 700.46,                        +
       "Plan Rows": 101,                            +
       "Plan Width": 488,                           +
       "Hash Cond": "(t2.unique2 = t1.unique2)",    +
       "Plans": [                                   +
         {                                          +
           "Node Type": "Seq Scan",                 +
           "Parent Relationship": "Outer",          +
           "Relation Name": "tenk2",                +
           "Alias": "t2",                           +
           "Startup Cost": 0.00,                    +
           "Total Cost": 434.00,                    +
           "Plan Rows": 10000,                      +
           "Plan Width": 244                        +
         },                                         +
         {                                          +
           "Node Type": "Hash",                     +
           "Parent Relationship": "Inner",          +
           "Startup Cost": 226.68,                  +
           "Total Cost": 226.68,                    +
           "Plan Rows": 101,                        +
           "Plan Width": 244,                       +
           "Plans": [                               +
             {                                      +
               "Node Type": "Bitmap Heap Scan",     +
               "Parent Relationship": "Outer",      +
               "Relation Name": "tenk1",            +
               "Alias": "t1",                       +
               "Startup Cost": 5.03,                +
               "Total Cost": 226.68,                +
               "Plan Rows": 101,                    +
               "Plan Width": 244,                   +
               "Recheck Cond": "(unique1 &amp;lt; 100)",   +
               "Plans": [                           +
                 {                                  +
                   "Node Type": "Bitmap Index Scan",+
                   "Parent Relationship": "Outer",  +
                   "Index Name": "tenk1_unique1",   +
                   "Startup Cost": 0.00,            +
                   "Total Cost": 5.01,              +
                   "Plan Rows": 101,                +
                   "Plan Width": 0,                 +
                   "Index Cond": "(unique1 &amp;lt; 100)"  +
                 }                                  +
               ]                                    +
             }                                      +
           ]                                        +
         }                                          +
       ]                                            +
     }                                              +
   }                                                +
 ]
(1 row)
&lt;/pre&gt;For just reading the plan, the new formats are probably not better, although some might prefer them.  The real win comes when you can feed this to a program to create a visualization.  With the old format, parsing the output was complicated and error prone.  With the new formats, it is easy.  In fact, it was so easy that I couldn't resist writing a small visual explain program that renders plans through the graphviz library.  Here is how you can use it: &lt;br /&gt;
&lt;pre&gt;regression=&amp;gt; \a\t
regression=&amp;gt; EXPLAIN (FORMAT JSON) SELECT * FROM tenk1 t1, tenk2 t2
WHERE t1.unique1 &amp;lt; 100 AND t1.unique2 = t2.unique2 \g |veung
&lt;/pre&gt;Result:&lt;br /&gt;
&lt;a href="http://2.bp.blogspot.com/_dgdplFJMdoQ/S_In33KeqYI/AAAAAAAAADU/N_nYFZ0Uack/s1600/veung-dotty.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/S_In33KeqYI/AAAAAAAAADU/N_nYFZ0Uack/s320/veung-dotty.png" /&gt;&lt;/a&gt;&lt;br /&gt;
Simple and useful.  Get it from &lt;a href="http://github.com/petere/veung"&gt;GitHub&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5541296000399974369-6923279425943817314?l=petereisentraut.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=_XCyiX3F_P8:mHfvuFRuTP0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=_XCyiX3F_P8:mHfvuFRuTP0:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=_XCyiX3F_P8:mHfvuFRuTP0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=_XCyiX3F_P8:mHfvuFRuTP0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=_XCyiX3F_P8:mHfvuFRuTP0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=_XCyiX3F_P8:mHfvuFRuTP0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=_XCyiX3F_P8:mHfvuFRuTP0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=_XCyiX3F_P8:mHfvuFRuTP0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=_XCyiX3F_P8:mHfvuFRuTP0:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=_XCyiX3F_P8:mHfvuFRuTP0:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=_XCyiX3F_P8:mHfvuFRuTP0:I9og5sOYxJI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?d=I9og5sOYxJI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/PeterEisentraut/~4/_XCyiX3F_P8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/6923279425943817314/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2010/05/visual-explain-reloaded.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/6923279425943817314?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/6923279425943817314?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/_XCyiX3F_P8/visual-explain-reloaded.html" title="Visual Explain Reloaded" /><author><name>Peter Eisentraut</name><uri>http://www.blogger.com/profile/02849480732923051923</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://2.bp.blogspot.com/_dgdplFJMdoQ/SkrluKExkqI/AAAAAAAAAB0/6Iqczims95U/S220/dscf0472.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_dgdplFJMdoQ/S_In33KeqYI/AAAAAAAAADU/N_nYFZ0Uack/s72-c/veung-dotty.png" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2010/05/visual-explain-reloaded.html</feedburner:origLink></entry></feed>

