<?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:blogger="http://schemas.google.com/blogger/2008" 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;CkMMRnY_eyp7ImA9WhBbF04.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369</id><updated>2013-05-16T21:54:47.843+03:00</updated><category term="Unix" /><category term="Python" /><category term="SQL" /><category term="EXPLAIN" /><category term="English" /><category term="Waldschlösschenbrücke" /><category term="Flymake" /><category term="FOSDEM" /><category term="gzip" /><category term="ccache" /><category term="UserVoice" /><category term="psql" /><category term="PL/Proxy" /><category term="GNOME" /><category term="C++" /><category term="Computing" /><category term="Shell" /><category term="GCC" /><category term="Git" /><category term="Chrome" /><category term="PL/Python" /><category term="Wahl" /><category term="Mono" /><category term="Cloud" /><category term="Homebrew" /><category term="StackOverflow" /><category term="KDE" /><category term="I18n" /><category term="XSLT" /><category term="SSH" /><category term="MySQL" /><category term="Beamer" /><category term="E71" /><category term="PGXN" /><category term="Debian" /><category term="LXDE" /><category term="Nokia" /><category term="Autoconf" /><category term="Deutsch" /><category term="Dresden" /><category term="Perl" /><category term="Pex" /><category term="Bazaar" /><category term="OSX" /><category term="APT" /><category term="tar" /><category term="Haskell" /><category term="Jenkins" /><category term="PostgreSQL" /><category term="Clang" /><category term="Linux" /><category term="SSD" /><category term="GPS" /><category term="Emacs" /><category term="Bash" /><category term="Psycopg" /><category term="LaTeX" /><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>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>129</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;DkQMQno-fyp7ImA9WhBUFEs.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-1841255571162669339</id><published>2013-05-02T06:13:00.000+03:00</published><updated>2013-05-02T06:13:03.457+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-05-02T06:13:03.457+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GCC" /><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="C++" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>Moving to C++</title><content type="html">&lt;p&gt;&lt;a href="http://gcc.gnu.org/gcc-4.8/"&gt;GCC 4.8&lt;/a&gt; was recently released.  This is
the first GCC release that is written in C++ instead of C.  Which got
me thinking ...&lt;/p&gt;

&lt;p&gt;Would this make sense for PostgreSQL?&lt;/p&gt;

&lt;p&gt;I think it's worth a closer look.&lt;/p&gt;

&lt;p&gt;Much of GCC's job isn't actually that much different from PostgreSQL.
It parses language input, optimizes it, and produces some output.  It
doesn't have a storage layer, it just produces code that someone else
runs.  Also note that Clang and LLVM are written in C++.  I think it
would be fair to say that these folks are pretty well informed about
selecting a programming language for their job.&lt;/p&gt;

&lt;p&gt;It has become apparent to me that C is approaching a dead end.
Microsoft isn't updating their compiler to C99, advising people to
move to C++ instead.  So as long as PostgreSQL (or any other project,
for that matter) wants to support that compiler, they will be stuck on
C89 forever.  That's a long time.  We have been carefully introducing
the odd post-C89 feature, guarded by configure checks and #ifdefs,
but that will either come to an end, or the range of compilers that
actually get the full benefit of the code will become narrower and
narrower.&lt;/p&gt;

&lt;p&gt;C++ on the other hand is still a vibrant language.  New standards come
out and get adopted by compiler writers.  You know how some
people require Java 7 or Python 2.7 or Ruby 1.9 for their code?  You wish you
could have that sort of problem for your C code!  With C++ you
reasonably might.&lt;/p&gt;

&lt;p&gt;I'm also sensing that at this point there are more C++ programmers
than C programmers in the world.  So using C++ might help grow the
project better.  (Under the same theory that supporting Windows
natively would attract hordes of Windows programmers to the project,
which probably did not happen.)&lt;/p&gt;

&lt;p&gt;Moving to C++ wouldn't mean that you'd have to rewrite all your code
as classes or that you'd have to enter template hell.  You could
initially consider a C++ compiler a pickier C compiler, and introduce
new language features one by one, as you had done before.&lt;/p&gt;

&lt;p&gt;Most things that C++ is picky about are things that a C programmer
might appreciate anyway.  For example, it refuses implicit conversions
between void pointers and other pointers, or intermixing different
enums.  Actually, if you review various design discussions about the
behavior of SQL-level types, functions, and type casts in PostgreSQL,
PostgreSQL users and developers generally lean on the side of a strict
type system.  C++ appears to be much more in line with that thinking.&lt;/p&gt;

&lt;p&gt;There are also a number of obvious areas where having the richer
language and the richer standard library of C++ would simplify coding,
reduce repetition, and avoid bugs: memory and string handling;
container types such as lists and hash tables; fewer macros necessary;
the node management in the backend screams class hierarchy; things
like xlog numbers could be types with operators; careful use of
function overloading could simplify some complicated internal APIs.
There are more.  Everyone probably has their own pet peeve here.&lt;/p&gt;

&lt;p&gt;I was looking for evidence of this C++ conversion in the GCC source
code, and it's not straightforward to find.  As a random example,
consider
&lt;a href="http://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/gimple.c;h=64f7b1a19f2ada391b12510c9724c5c292f52090;hb=master"&gt;&lt;code&gt;gimple.c&lt;/code&gt;&lt;/a&gt;.
It looks like a normal C source file at first glance.  It is named
&lt;code&gt;.c&lt;/code&gt; after all.  But it actually uses C++ features (exercise for the
reader to find them), and the build process compiles it using a C++
compiler.&lt;/p&gt;

&lt;p&gt;LWN has an &lt;a href="https://lwn.net/Articles/542457/"&gt;article&lt;/a&gt; about how GCC moved to C++.&lt;/p&gt;

&lt;p&gt;Thoughts?&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=oRf1MVlVcoE:6MTngNXLSQ0: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=oRf1MVlVcoE:6MTngNXLSQ0: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=oRf1MVlVcoE:6MTngNXLSQ0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=oRf1MVlVcoE:6MTngNXLSQ0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=oRf1MVlVcoE:6MTngNXLSQ0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=oRf1MVlVcoE:6MTngNXLSQ0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=oRf1MVlVcoE:6MTngNXLSQ0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=oRf1MVlVcoE:6MTngNXLSQ0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=oRf1MVlVcoE:6MTngNXLSQ0:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=oRf1MVlVcoE:6MTngNXLSQ0:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=oRf1MVlVcoE:6MTngNXLSQ0: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/oRf1MVlVcoE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/1841255571162669339/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2013/05/moving-to-c.html#comment-form" title="21 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/1841255571162669339?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/1841255571162669339?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/oRf1MVlVcoE/moving-to-c.html" title="Moving to C++" /><author><name>Peter Eisentraut</name><uri>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>21</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2013/05/moving-to-c.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQCRn8-eip7ImA9WhBXGUg.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-8893991954537392380</id><published>2013-04-03T04:59:00.000+03:00</published><updated>2013-04-03T04:59:27.152+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-03T04:59:27.152+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="OSX" /><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="Homebrew" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>Installing multiple PostgreSQL versions on Homebrew</title><content type="html">&lt;p&gt;I was going to post this yesterday, but some might have thought that it was a
joke.  April 1st is always an annoying day to communicate real information.&lt;/p&gt;

&lt;p&gt;If you have been fond of the way Debian and Ubuntu manage multiple
PostgreSQL versions in parallel, you can now have the same on OS X
with Homebrew:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;brew tap petere/postgresql
brew install postgresql-9.2
# etc.
brew install --HEAD postgresql-common
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;postgresql-common&lt;/code&gt; is the same code as in Debian, only mangled a little.&lt;/p&gt;

&lt;p&gt;Now you have all the client programs symlinked through &lt;code&gt;pg_wrapper&lt;/code&gt;, and
you can use the server management tools such as:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;pg_createcluster 9.2 main
pg_ctlcluster 9.2 main start
pg_lsclusters
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let me know if you find this useful.&lt;/p&gt;

Links:
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/petere/homebrew-postgresql"&gt;&lt;code&gt;homebrew-postgresql&lt;/code&gt;&lt;/a&gt;
&lt;li&gt;&lt;a href="https://github.com/petere/postgresql-common/tree/homebrew"&gt;&lt;code&gt;postgresql-common&lt;/code&gt; &lt;code&gt;homebrew&lt;/code&gt; branch&lt;/a&gt;
&lt;/ul&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=RdKSC06z_4w:oqqblN4ji8Y: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=RdKSC06z_4w:oqqblN4ji8Y: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=RdKSC06z_4w:oqqblN4ji8Y:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=RdKSC06z_4w:oqqblN4ji8Y:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=RdKSC06z_4w:oqqblN4ji8Y:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=RdKSC06z_4w:oqqblN4ji8Y:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=RdKSC06z_4w:oqqblN4ji8Y:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=RdKSC06z_4w:oqqblN4ji8Y:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=RdKSC06z_4w:oqqblN4ji8Y:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=RdKSC06z_4w:oqqblN4ji8Y:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=RdKSC06z_4w:oqqblN4ji8Y: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/RdKSC06z_4w" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/8893991954537392380/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2013/04/installing-multiple-postgresql-versions.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/8893991954537392380?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/8893991954537392380?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/RdKSC06z_4w/installing-multiple-postgresql-versions.html" title="Installing multiple PostgreSQL versions on Homebrew" /><author><name>Peter Eisentraut</name><uri>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2013/04/installing-multiple-postgresql-versions.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08EQHs_eSp7ImA9WhBSEUs.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-4389332635953133787</id><published>2013-02-18T06:30:00.000+02:00</published><updated>2013-02-18T06:30:01.541+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-18T06:30:01.541+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><category scheme="http://www.blogger.com/atom/ns#" term="Haskell" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>Lists and Tuples</title><content type="html">I had initially found the divide between lists and tuples in Python confusing.  I came from a database background, so I have a certain expectation of what a tuple might be.  If you read up on what the difference is in Python, you will find that a) tuples are immutable, and b) singleton tuples use a funny syntax.  So just use lists, because it's easier to read and you can't go wrong that way.  Oh, and they are both sequences, another overloaded term.
&lt;p&gt;
(Yes, there are some details omitted here, such as that since a tuple is immutable, it is hashable and can be used as a dictionary key.  But I think that is used fairly seldomly.)
&lt;p&gt;
Then I came across Haskell and it dawned on me:  Was this just a poorly mangled feature from Haskell?  I don't know the history, but it looks a bit like it.  You see, Haskell also has list and tuples.  Lists are delimited by square brackets, and tuples are delimited by parentheses:
&lt;pre&gt;let alist = [1, 2, 3]
let atuple = (1, 2, 3)&lt;/pre&gt;
(Technically, in Python, tuples are not delimited by parentheses, but they often appear that way.)  But the difference is that Haskell does not use parentheses for any other purpose, such as delimiting function arguments.  It uses spaces for that.  (So it looks more like a shell script at times.)
&lt;pre&gt;Python: len([1, 2, 3])
Haskell: length [1, 2, 3]&lt;/pre&gt;
But in Haskell, tuples are not mutable lists and lists are not mutable tuples.  Tuples and lists are quite different but complementary things.  A list can only contain elements of the same type.  So you can have lists
&lt;pre&gt;[1, 2, 3, 4, 5]
["a", "b", "c", "d"]&lt;/pre&gt;
but not
&lt;pre&gt;[1, 2, "a"]&lt;/pre&gt;
A tuple, on the other hand, can contain values of different types
&lt;pre&gt;(1, 2, "a")
(3, 4, "b")&lt;/pre&gt;
A particular type combination in a tuple creates a new type on the fly, which becomes interesting when you embed tuples in a list.  So you can have a list
&lt;pre&gt;[(1, 2, "a"), (3, 4, "b")]&lt;/pre&gt;
but not
&lt;pre&gt;[(1, 2, "a"), (3, 4, 5)]&lt;/pre&gt;
Because Haskell is statically typed, it can verify this at compile time.
&lt;p&gt;
If you think in terms of relational databases, the term tuple in particular makes a lot of sense in this way.  A result set from a database query would be a list of tuples.
&lt;p&gt;
The arrival of the &lt;tt&gt;namedtuple&lt;/tt&gt; also supports the notion that tuples should be thought of as combining several pieces of data of different natures, but of course this is not enforced in either tuples or named tuples.
&lt;p&gt;
Now, none of this is relevant to Python.  Because of duck typing, a database query result set might as well be a list of lists or a tuple of tuples or something different altogether that emulates sequences.  But I found it useful to understand where this syntax and terminology might have come from.
&lt;p&gt;
Looking at the newer classes &lt;tt&gt;set&lt;/tt&gt; and &lt;tt&gt;frozenset&lt;/tt&gt;, it might also help to sometimes think of a tuple as a &lt;q&gt;frozenlist&lt;/q&gt; instead, because this is closer to the role it plays in Python.
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=WszWN2WL948:EUEsTYdxCr8: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=WszWN2WL948:EUEsTYdxCr8: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=WszWN2WL948:EUEsTYdxCr8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=WszWN2WL948:EUEsTYdxCr8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=WszWN2WL948:EUEsTYdxCr8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=WszWN2WL948:EUEsTYdxCr8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=WszWN2WL948:EUEsTYdxCr8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=WszWN2WL948:EUEsTYdxCr8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=WszWN2WL948:EUEsTYdxCr8:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=WszWN2WL948:EUEsTYdxCr8:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=WszWN2WL948:EUEsTYdxCr8: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/WszWN2WL948" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/4389332635953133787/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2013/02/lists-and-tuples.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/4389332635953133787?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/4389332635953133787?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/WszWN2WL948/lists-and-tuples.html" title="Lists and Tuples" /><author><name>Peter Eisentraut</name><uri>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>5</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2013/02/lists-and-tuples.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE4NRHg5fSp7ImA9WhBTGEQ.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-4606114762955482811</id><published>2013-02-15T04:56:00.000+02:00</published><updated>2013-02-15T04:56:35.625+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-15T04:56:35.625+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Jenkins" /><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>pgindent Jenkins job</title><content type="html">I have set up a Jenkins &lt;a href="http://pgci.eisentraut.org/jenkins/job/postgresql_master_pgindent/"&gt;job&lt;/a&gt; that runs pgindent.  Besides checking that the procedure of running pgindent works, it also provides a &lt;q&gt;preview&lt;/q&gt; of what pgindent would do with the current source (&lt;code&gt;&lt;a href="http://pgci.eisentraut.org/jenkins/job/postgresql_master_pgindent/lastSuccessfulBuild/artifact/pgindent.diff"&gt;pgindent.diff&lt;/a&gt;&lt;/code&gt;), which can be educational or terribly confusing.
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=O2qdN6-rTRg:R1qKUQ2dgOo: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=O2qdN6-rTRg:R1qKUQ2dgOo: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=O2qdN6-rTRg:R1qKUQ2dgOo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=O2qdN6-rTRg:R1qKUQ2dgOo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=O2qdN6-rTRg:R1qKUQ2dgOo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=O2qdN6-rTRg:R1qKUQ2dgOo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=O2qdN6-rTRg:R1qKUQ2dgOo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=O2qdN6-rTRg:R1qKUQ2dgOo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=O2qdN6-rTRg:R1qKUQ2dgOo:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=O2qdN6-rTRg:R1qKUQ2dgOo:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=O2qdN6-rTRg:R1qKUQ2dgOo: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/O2qdN6-rTRg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/4606114762955482811/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2013/02/pgindent-jenkins-job.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/4606114762955482811?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/4606114762955482811?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/O2qdN6-rTRg/pgindent-jenkins-job.html" title="pgindent Jenkins job" /><author><name>Peter Eisentraut</name><uri>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2013/02/pgindent-jenkins-job.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0ADRXY_eyp7ImA9WhNaF0o.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-923064140636321357</id><published>2013-02-02T06:36:00.000+02:00</published><updated>2013-02-02T06:36:14.843+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-02T06:36:14.843+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Pex" /><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>Introducing the Pex package manager for PostgreSQL</title><content type="html">I have written a new light-weight package manager for PostgreSQL, called &lt;quote&gt;pex&lt;/quote&gt;.  It's targeted at developers, allows easy customization, and supports multiple PostgreSQL installations.
&lt;p&gt;
Here is how it works:
&lt;p&gt;
Installation:
&lt;pre&gt;git clone git://github.com/petere/pex.git
cd pex
sudo make install&lt;/pre&gt;
&lt;p&gt;
Install some packages:
&lt;pre&gt;pex init
pex install plproxy
pex search hash
pex install pghashlib&lt;/pre&gt;
&lt;p&gt;
Multiple PostgreSQL installations:
&lt;pre&gt;pex -g /usr/local/pgsql2 install plproxy
pex -p 5433 install pghashlib&lt;/pre&gt;
&lt;p&gt;
Upgrade:
&lt;pre&gt;pex update
pex upgrade&lt;/pre&gt;
&lt;p&gt;
It works a bit like Homebrew, except that it doesn't use Ruby or a lot of metaphors. ;-)
&lt;p&gt;
Check it out at &lt;a href="https://github.com/petere/pex"&gt;https://github.com/petere/pex&lt;/a&gt;.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=Ro1r2tV_nEE:NSKG_ZqOsVU: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=Ro1r2tV_nEE:NSKG_ZqOsVU: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=Ro1r2tV_nEE:NSKG_ZqOsVU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=Ro1r2tV_nEE:NSKG_ZqOsVU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=Ro1r2tV_nEE:NSKG_ZqOsVU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=Ro1r2tV_nEE:NSKG_ZqOsVU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=Ro1r2tV_nEE:NSKG_ZqOsVU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=Ro1r2tV_nEE:NSKG_ZqOsVU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=Ro1r2tV_nEE:NSKG_ZqOsVU:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=Ro1r2tV_nEE:NSKG_ZqOsVU:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=Ro1r2tV_nEE:NSKG_ZqOsVU: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/Ro1r2tV_nEE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/923064140636321357/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2013/02/introducing-pex-package-manager-for.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/923064140636321357?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/923064140636321357?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/Ro1r2tV_nEE/introducing-pex-package-manager-for.html" title="Introducing the Pex package manager for PostgreSQL" /><author><name>Peter Eisentraut</name><uri>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2013/02/introducing-pex-package-manager-for.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08CQnk-eyp7ImA9WhNUEEo.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-7020262525327562952</id><published>2013-01-01T22:24:00.000+02:00</published><updated>2013-01-01T22:24:23.753+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-01T22:24:23.753+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Jenkins" /><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 and Jenkins</title><content type="html">A lot of places use &lt;a href="http://jenkins-ci.org/"&gt;Jenkins&lt;/a&gt; nowadays, including where I now work and have previously worked.  I enjoy working with Jenkins, and so I always wanted try out how this would work with &lt;a href="http://www.postgresql.org/"&gt;PostgreSQL&lt;/a&gt;.  Obviously, there would be some overlap with the &lt;a href="http://buildfarm.postgresql.org/"&gt;build farm&lt;/a&gt;, but that's OK.  The point of the build farm, after all, is to build things in many different ways to find potential problems, and this would just support that overall effort.
&lt;p&gt;
So I have set this up now: &lt;a href="http://pgci.eisentraut.org/jenkins/"&gt;http://pgci.eisentraut.org/jenkins/&lt;/a&gt;
&lt;p&gt;
It's already been very helpful during the last couple of weeks that I've run this.  The main point behind the effort is to automate things. These are things I do just about every day and won't have to anymore:
&lt;ul&gt;
&lt;li&gt;build PostgreSQL
&lt;li&gt;check for compiler warnings
&lt;li&gt;run various test suites
&lt;li&gt;do this for all supported branches
&lt;/ul&gt;
These are things I do every couple of weeks and have now automated:
&lt;ul&gt;
&lt;li&gt;check distribution building (&lt;code&gt;make distcheck&lt;/code&gt;)
&lt;li&gt;test build of additional documentation formats
&lt;li&gt;&lt;code&gt;cpluspluscheck&lt;/code&gt;
&lt;li&gt;check external web links in the documentation (The &lt;a href="http://pgci.eisentraut.org/jenkins/job/postgresql_master_linklint/"&gt;job&lt;/a&gt; for that currently appears to be reporting false positives.  Use with caution.)
&lt;li&gt;test &lt;a href="http://pgci.eisentraut.org/jenkins/job/postgresql_master_coverage/Coverage/"&gt;coverage&lt;/a&gt; reporting
&lt;/ul&gt;
Moreover, I have set up to build some extensions and external modules, which weren't regularly tested.  (The build farm is making some efforts in this area, though.)
&lt;p&gt;
Actually, many of the checks I had set up immediately found problems: newly introduced compiler warnings, secondary documentation format builds broken, cpluspluscheck failing, broken links in the HTML documentation, various extensions no longer build with Postg reSQL 9.3devel.
&lt;p&gt;
But there is more cool stuff:
&lt;ul&gt;
&lt;li&gt;There are various RSS feeds for all builds or failed buids.
&lt;li&gt;You can interact with the system on mobile devices.  I use JenkinsMobi for iOS.
&lt;li&gt;You can get up to date &lt;a href="http://pgci.eisentraut.org/jenkins/job/postgresql_master_world/Documentation/"&gt;documentation&lt;/a&gt; builds on a more predictable schedule.
&lt;/ul&gt;
&lt;p&gt;
The one thing (just about) it doesn't do is test operating system and CPU architecture portability.  Jenkins comes from a Java background, where this isn't much of an issue, and so there isn't good built-in support for that sort of thing.  But anyway, we have the build farm for that.
&lt;p&gt;
You can get the code at &lt;a href="http://bitbucket.org/petere/pgci"&gt;http://bitbucket.org/petere/pgci&lt;/a&gt;.  The entire setup is automated with Puppet.  You can fork it and set up your own (or send me your changes), or you can run it locally using &lt;a href="http://www.vagrantup.com/"&gt;Vagrant&lt;/a&gt; (which is what I do to test changes).
&lt;p&gt;
If you have any ideas, let me know (file an issue on Bitbucket).  I have plans for a number of enhancements already, foremost pg_upgrade testing.  Also, let me know if there are additional extensions you want tested.  I have just put in a few I use myself at the moment, but other can easily be added.
&lt;p&gt;
Happy New Year!&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=yKLxb5njR6I:1lWRtlxue1k: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=yKLxb5njR6I:1lWRtlxue1k: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=yKLxb5njR6I:1lWRtlxue1k:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=yKLxb5njR6I:1lWRtlxue1k:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=yKLxb5njR6I:1lWRtlxue1k:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=yKLxb5njR6I:1lWRtlxue1k:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=yKLxb5njR6I:1lWRtlxue1k:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=yKLxb5njR6I:1lWRtlxue1k:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=yKLxb5njR6I:1lWRtlxue1k:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=yKLxb5njR6I:1lWRtlxue1k:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=yKLxb5njR6I:1lWRtlxue1k: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/yKLxb5njR6I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/7020262525327562952/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2013/01/postgresql-and-jenkins.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/7020262525327562952?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/7020262525327562952?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/yKLxb5njR6I/postgresql-and-jenkins.html" title="PostgreSQL and Jenkins" /><author><name>Peter Eisentraut</name><uri>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2013/01/postgresql-and-jenkins.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUARn4_eCp7ImA9WhJaEU4.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-8144820783903807045</id><published>2012-10-02T03:20:00.000+03:00</published><updated>2012-10-02T03:20:47.040+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-02T03:20:47.040+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="psql" /><category scheme="http://www.blogger.com/atom/ns#" term="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>psqlrc files</title><content type="html">In PostgreSQL 9.2, you can use major-version-specific &lt;code&gt;.psqlrc&lt;/code&gt; files, such as &lt;code&gt;.psqlrc-9.2&lt;/code&gt;.  PostgreSQL 9.2 also added the "include relative" command &lt;code&gt;\ir&lt;/code&gt; to psql.  Combining these two, you can set up psql initialization to take advantage of any new features you want without breaking the use of old psql releases.
&lt;p&gt;
For example, I'd like to set up psql to automatically use &lt;code&gt;\x auto&lt;/code&gt;.  But if I just put that into &lt;code&gt;.psqlrc&lt;/code&gt;, older psql releases will complain about an unknown command.  (I usually have multiple PostgreSQL versions installed, and I share dotfiles across hosts.)  On the other hand, I don't want to have to duplicate the entire &lt;code&gt;.psqlrc&lt;/code&gt; file to add one command, which is where &lt;code&gt;\ir&lt;/code&gt; comes in.
&lt;p&gt;
Here is what I use, for example:
&lt;dl&gt;
&lt;dt&gt;&lt;code&gt;.psqlrc-9.2&lt;/code&gt;
&lt;dd&gt;&lt;pre&gt;\ir .psqlrc
\set QUIET yes
\set COMP_KEYWORD_CASE preserve-lower
\x auto
\unset QUIET&lt;/pre&gt;

&lt;dt&gt;&lt;code&gt;.psqlrc-9.3&lt;/code&gt;
&lt;dd&gt;&lt;pre&gt;\ir .psqlrc-9.2&lt;/pre&gt;
&lt;/dl&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=QiNcmQCr1Z4:m_3dHDVq8NM: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=QiNcmQCr1Z4:m_3dHDVq8NM: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=QiNcmQCr1Z4:m_3dHDVq8NM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=QiNcmQCr1Z4:m_3dHDVq8NM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=QiNcmQCr1Z4:m_3dHDVq8NM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=QiNcmQCr1Z4:m_3dHDVq8NM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=QiNcmQCr1Z4:m_3dHDVq8NM:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=QiNcmQCr1Z4:m_3dHDVq8NM:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=QiNcmQCr1Z4:m_3dHDVq8NM:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=QiNcmQCr1Z4:m_3dHDVq8NM:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=QiNcmQCr1Z4:m_3dHDVq8NM: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/QiNcmQCr1Z4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/8144820783903807045/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2012/10/psqlrc-files.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/8144820783903807045?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/8144820783903807045?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/QiNcmQCr1Z4/psqlrc-files.html" title="psqlrc files" /><author><name>Peter Eisentraut</name><uri>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2012/10/psqlrc-files.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0EDSXs_fSp7ImA9WhJUE0s.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-8931986875201370256</id><published>2012-09-11T15:14:00.000+03:00</published><updated>2012-09-11T15:14:38.545+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-09-11T15:14:38.545+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PGXN" /><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>pgxnclient supports tarballs and HTTP</title><content type="html">Need to install a PostgreSQL server add-on module?  The &lt;tt&gt;devel&lt;/tt&gt; branch of &lt;a href="https://github.com/dvarrazzo/pgxnclient"&gt;pgxnclient&lt;/a&gt; now supports this type of thing:
&lt;pre&gt;pgxnclient install http://pgfoundry.org/frs/download.php/3274/plproxy-2.4.tar.gz&lt;/pre&gt;
This downloads, unpacks, builds, and installs.  And the module doesn't need to be on PGXN.  And of course you don't have to use HTTP; a file system location will work as well.

I think this can be very useful, especially during development, when not everything is available in packaged form, or even for deployment, if you don't want to bother packaging everything and have been installing from source anyway.
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=wne5a9eHFGI:bUQIQCEXWcA: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=wne5a9eHFGI:bUQIQCEXWcA: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=wne5a9eHFGI:bUQIQCEXWcA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=wne5a9eHFGI:bUQIQCEXWcA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=wne5a9eHFGI:bUQIQCEXWcA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=wne5a9eHFGI:bUQIQCEXWcA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=wne5a9eHFGI:bUQIQCEXWcA:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=wne5a9eHFGI:bUQIQCEXWcA:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=wne5a9eHFGI:bUQIQCEXWcA:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=wne5a9eHFGI:bUQIQCEXWcA:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=wne5a9eHFGI:bUQIQCEXWcA: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/wne5a9eHFGI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/8931986875201370256/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2012/09/pgxnclient-supports-tarballs-and-http.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/8931986875201370256?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/8931986875201370256?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/wne5a9eHFGI/pgxnclient-supports-tarballs-and-http.html" title="pgxnclient supports tarballs and HTTP" /><author><name>Peter Eisentraut</name><uri>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2012/09/pgxnclient-supports-tarballs-and-http.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YFSXo4eCp7ImA9WhJXGUw.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-8080077202735415980</id><published>2012-08-14T06:31:00.000+03:00</published><updated>2012-08-14T06:31:58.430+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-08-14T06:31:58.430+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>Funny version numbers</title><content type="html">Often, I install a new Debian package using apt-get install, and as the progress output flies by, I wonder, Whoa!, should I really be using a piece of software with &lt;i&gt;that&lt;/i&gt; version number?
&lt;p&gt;
It says a lot, after all.  If I see
&lt;pre&gt;tool 2.4.1-2&lt;/pre&gt;
then I (subconsciously) think, yeah, the upstream maintainers are obviously sane, the tool has been around for a while, they have made several major and minor releases, and what I'm using has seen about one round of bug fixing, and a minimal amount of tweaking by the Debian maintainer.
&lt;p&gt;
On the other hand, when I see
&lt;pre&gt;tool 7.0.50~6.5~rc2+0.20120405-1&lt;/pre&gt;
I don't know what went on there.  The original release version 7.0.50 was somehow wrong and had to be renamed 6.5?  And then the 2nd release candidate of that?  And then even that wasn't good enough, and some dated snapshot had to be taken?
&lt;p&gt;
Now, of course, there are often reasons for things like this, but it doesn't look good, and I felt it was getting out of hand a little bit.
&lt;p&gt;
I tried to look into this some more and find a regular expression for a reasonably sane version number.  It's difficult.  This is how far I've gotten: &lt;a href="https://gist.github.com/3345974"&gt;https://gist.github.com/3345974&lt;/a&gt;.  But this still lists more than 1500 packages with funny version numbers.  Which could be
cause for slight concern.
&lt;p&gt;
Take a look at what this prints.  You can't make some of that stuff up.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=qgwDYm53E34:pD8U-hGi_6E: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=qgwDYm53E34:pD8U-hGi_6E: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=qgwDYm53E34:pD8U-hGi_6E:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=qgwDYm53E34:pD8U-hGi_6E:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=qgwDYm53E34:pD8U-hGi_6E:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=qgwDYm53E34:pD8U-hGi_6E:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=qgwDYm53E34:pD8U-hGi_6E:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=qgwDYm53E34:pD8U-hGi_6E:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=qgwDYm53E34:pD8U-hGi_6E:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=qgwDYm53E34:pD8U-hGi_6E:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=qgwDYm53E34:pD8U-hGi_6E: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/qgwDYm53E34" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/8080077202735415980/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2012/08/funny-version-numbers.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/8080077202735415980?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/8080077202735415980?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/qgwDYm53E34/funny-version-numbers.html" title="Funny version numbers" /><author><name>Peter Eisentraut</name><uri>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2012/08/funny-version-numbers.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0YEQH04fSp7ImA9WhJRFkk.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-3194257967377430759</id><published>2012-07-19T01:05:00.000+03:00</published><updated>2012-07-19T01:05:01.335+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-07-19T01:05:01.335+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" /><category scheme="http://www.blogger.com/atom/ns#" term="Bash" /><title>Tracing shell scripts with time stamps</title><content type="html">A random tip for shell script hackers.  You know that with &lt;code&gt;set -x&lt;/code&gt; you can turn on tracing, so that every command is printed before being executed.

In bash, you can also customize the output prefix by setting the &lt;code&gt;PS4&lt;/code&gt; variable.  The default is &lt;code&gt;PS4='+ '&lt;/code&gt;.

Here is an example.  I wanted to "profile" a deployment script, to see why it took so long.  Ordinarily, I might have sprinkled it with &lt;code&gt;date&lt;/code&gt; calls.  Instead, I merely added
&lt;pre&gt;set -x
PS4='+\t '&lt;/pre&gt;
near the top.  &lt;code&gt;\t&lt;/code&gt; stands for time stamp.  (The script was already using bash explicitly, as opposed to &lt;code&gt;/bin/sh&lt;/code&gt;.)  That way, every line is prefixed by a time stamp, and the logs could easily be analyzed to find a possible performance bottleneck.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=N4VXEOgmP14:99KspF2hLwU: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=N4VXEOgmP14:99KspF2hLwU: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=N4VXEOgmP14:99KspF2hLwU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=N4VXEOgmP14:99KspF2hLwU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=N4VXEOgmP14:99KspF2hLwU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=N4VXEOgmP14:99KspF2hLwU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=N4VXEOgmP14:99KspF2hLwU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=N4VXEOgmP14:99KspF2hLwU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=N4VXEOgmP14:99KspF2hLwU:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=N4VXEOgmP14:99KspF2hLwU:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=N4VXEOgmP14:99KspF2hLwU: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/N4VXEOgmP14" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/3194257967377430759/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2012/07/tracing-shell-scripts-with-time-stamps.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/3194257967377430759?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/3194257967377430759?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/N4VXEOgmP14/tracing-shell-scripts-with-time-stamps.html" title="Tracing shell scripts with time stamps" /><author><name>Peter Eisentraut</name><uri>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2012/07/tracing-shell-scripts-with-time-stamps.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0EEQn47fip7ImA9WhVUFUs.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-7226111304649061325</id><published>2012-05-21T05:00:00.000+03:00</published><updated>2012-05-21T05:00:03.006+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-21T05:00:03.006+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="tar" /><category scheme="http://www.blogger.com/atom/ns#" term="gzip" /><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>Base backup compression options</title><content type="html">&lt;p&gt;I've been looking at my PostgreSQL base backups.  They are run using
the traditional&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;tar -c -z -f basebackup.tar.gz $PGDATA/...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;way (many details omitted).  I haven't gotten heavily into using
&lt;code&gt;pg_basebackup&lt;/code&gt; yet, but the following could apply there just as well.&lt;/p&gt;

&lt;p&gt;I had found some of the base backups to be pretty slow, so I dug a
little deeper.  I was surprised to find that the job was completely
CPU bound.  The blocking factor was the &lt;code&gt;gzip&lt;/code&gt; process.  So it was
worth thinking about other compression options.  (The alternative is
of course no compression, but that would waste a lot of space.)&lt;/p&gt;

&lt;p&gt;There are two ways to approach this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use a faster compression method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parallelize the compression.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a faster compression method, there is &lt;code&gt;lzop&lt;/code&gt;, for example.  GNU
&lt;code&gt;tar&lt;/code&gt; has support for that, by using &lt;code&gt;--lzop&lt;/code&gt; instead of &lt;code&gt;-z&lt;/code&gt;.  It
gives a pretty good speed improvement, but the compression results are
of course worse.&lt;/p&gt;

&lt;p&gt;For parallelizing compression, there are parallel (multithreaded)
implementations of the well-known &lt;code&gt;gzip&lt;/code&gt; and &lt;code&gt;bzip2&lt;/code&gt; compression
methods, called &lt;code&gt;pigz&lt;/code&gt; and &lt;code&gt;pbzip2&lt;/code&gt;, respectively.  You can hook these
into GNU &lt;code&gt;tar&lt;/code&gt; by using the &lt;code&gt;-I&lt;/code&gt; option, something like &lt;code&gt;-I pigz&lt;/code&gt;.
Alternatively, put them into a pipe after &lt;code&gt;tar&lt;/code&gt;, so that you can pass
them some options.  Because otherwise they will bring your system to a
screeching halt!  If you've never seen a system at a constant 1600%
CPU for 10 minutes, try these.&lt;/p&gt;

&lt;p&gt;If you have a regular service window or natural slow time at night or
on weekends, these tools can be quite useful, because you might be
able to cut down the time for your base backup from, say 2 hours to 10
minutes.  But if you need to be always on, you will probably want to
qualify this a little, by reducing the number of CPUs used for this
job.  But it can still be pretty effective if you have many CPUs and
want to dedicate a couple to the compression task for a while.&lt;/p&gt;


&lt;p&gt;Personally, I have settled on &lt;code&gt;pigz&lt;/code&gt; as my standard weapon of choice
now.  It's much faster than &lt;code&gt;pbzip2&lt;/code&gt; and can easily beat
single-threaded &lt;code&gt;lzop&lt;/code&gt;.  Also, it produces standard &lt;code&gt;gzip&lt;/code&gt; output, of
course, so you don't need to install special tools everywhere, and you
can access the file with standard tools in a bind.&lt;/p&gt;

&lt;p&gt;Also, consider all of this in the context of restoring.  No matter how
you take the backup, wouldn't it be nice to be able to restore a
backup almost 8 or 16 or 32 times faster?&lt;/p&gt;

&lt;p&gt;I have intentionally not included any benchmark numbers here, because
it will obviously be pretty site-specific.  But it should be easy to
test for everyone, and the results should speak for themselves.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=N6S_H1NtMtE:jAG7-s_bKGs: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=N6S_H1NtMtE:jAG7-s_bKGs: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=N6S_H1NtMtE:jAG7-s_bKGs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=N6S_H1NtMtE:jAG7-s_bKGs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=N6S_H1NtMtE:jAG7-s_bKGs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=N6S_H1NtMtE:jAG7-s_bKGs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=N6S_H1NtMtE:jAG7-s_bKGs:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=N6S_H1NtMtE:jAG7-s_bKGs:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=N6S_H1NtMtE:jAG7-s_bKGs:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=N6S_H1NtMtE:jAG7-s_bKGs:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=N6S_H1NtMtE:jAG7-s_bKGs: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/N6S_H1NtMtE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/7226111304649061325/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2012/05/base-backup-compression-options.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/7226111304649061325?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/7226111304649061325?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/N6S_H1NtMtE/base-backup-compression-options.html" title="Base backup compression options" /><author><name>Peter Eisentraut</name><uri>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2012/05/base-backup-compression-options.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk8FQHw9eip7ImA9WhVUEUw.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-4672623148988461810</id><published>2012-05-15T23:46:00.000+03:00</published><updated>2012-05-15T23:46:51.262+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-15T23:46:51.262+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>My (anti-)take on database schema version management</title><content type="html">&lt;p&gt;There were a number of posts recently about managing schema versions
and schema deployment in PostgreSQL.  I have analyzed these with great
interest, but I have concluded that they are all more or less
significantly flawed.  (Of course, most of these solutions do in fact
work for someone, but they are not general enough to become canonical
go-to solutions for this problem class, in my opinion.)  I have
developed a list of elimination criteria by which I can evaluate
future developments in this area.  So here are some of the things that
I don't want in my schema version management system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Using schemas for distinguishing multiple versions (like
&lt;a href="http://feedproxy.google.com/~r/blogspot/EzOjx/~3/HrUj6PXPD-c/schema-based-versioning-and-deployment.html"&gt;this&lt;/a&gt;,
but that's actually more about API versioning).  That simply won't
work for deploying objects that are not in schemas, such as casts,
languages, extensions, and, well, schemas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using extensions (like
&lt;a href="http://philsorber.blogspot.com/2012/01/deploy-schemata-like-boss.html"&gt;this&lt;/a&gt;).
Well, this could work.  But extensions by themselves do nothing
about the core problem.  They are just an SQL wrapper interface
around upgrade scripts.  You still need to write the upgrade
scripts, order them, test them, package them.  The extension
mechanism might replace the, say, shell script that would
otherwise run the upgrade files in a suitable order.  Another
issue is that extensions require access to the server file system.
Changing this is being
&lt;a href="https://commitfest.postgresql.org/action/patch_view?id=746"&gt;discussed&lt;/a&gt;
as "inline extensions", but there is no consensus.  This is a
smaller problem, but it needs to be thought about.  Also, I do
need to support PostgreSQL 9.0 and earlier for little while more.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Requiring naming each change (patch names, like
&lt;a href="http://www.depesz.com/2010/08/22/versioning/"&gt;this&lt;/a&gt;).  Naming
things is hard.  Numbering things is easy.  And how many good
names are you going to still be able to come up with after 100 or
so changes?&lt;/p&gt;


&lt;p&gt;Take a lesson from file version control systems: versions are
numbers or, if it must be, hashes or the like (UUIDs have been
suggested).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using a version control tool for tracking upgrade paths (like
&lt;a href="http://justatheory.com/computers/databases/sqitch-draft.html"&gt;this&lt;/a&gt;).
Sqitch, unlike the initial draft of this concept, doesn't actually
require a version control tool for deployment, which wouldn't have
worked for me, because what we ship is a tarball or a deb/rpm-type
package.  But it still requires you to maintain some kind of
sanity in your version control history so that the tool can make
sense out of it.  That sounds fragile and inconvenient.  The other
choice appears to be writing the plan files manually without any
VCS involvement, but then this loses much of the apparent appeal
of this tool, and it's really no better than the "naming each
change" approach mentioned above.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Taking snapshots or the like of a production or staging or central
development system.  Production systems and staging systems should
be off limits for this sort of thing.  Central development systems
don't exist, because with distributed version control, every
developer has their own setups, branches, deployments, and world
views.&lt;/p&gt;

&lt;p&gt;You could set it up so that every developer gets their own
test database, sets up the schema there, takes a dump, and checks
that in.  There are going to be problems with that, including that
dumps produced by &lt;code&gt;pg_dump&lt;/code&gt; are ugly and optimized for restoring,
not for developing with, and they don't have a deterministic
output order.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Storing the database source code in a different place or in a
different manner than the rest of the source code.  This includes
using a version control system like mentioned above (meaning
storing part of the information in the version control meta
information rather than in the files that are checked into the
version control system in the normal way), using a separate
repository like Post Facto, or using something like the mentioned
staging server.&lt;/p&gt;

&lt;p&gt;The source is the source, and it must be possible to check out,
edit, build, test, and deploy everything in a uniform and
customary manner.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Allowing lattice-like dependencies between change sets (like most
examples cited above).  This sounds great on paper, especially if
you want to support distributed development in branches.  But then
you can have conflicts, for example where two upgrades add a
column to the same table.  Depending on the upgrade path, you end
up with different results.  As your change graph grows, you will
have an exploding number of possible upgrade paths that will need
to be tested.&lt;/p&gt;

&lt;p&gt;There needs to be an unambiguous, canonical state of the database
schema for a given source checkout.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Requiring running through all the upgrade scripts for a fresh
deployment (like
&lt;a href="http://www.depesz.com/2010/08/22/versioning/"&gt;this&lt;/a&gt;).  There are
two problems with this.  First, it's probably going to be very
slow.  Fresh deployments need to be reasonably fast, because they
will be needed for automated tests, including unit tests, where
you don't want to wait for minutes to set up the basic schema.
Second, it's inefficient.  Over time, you might drop columns, add
new columns, delete rows, migrate them to different tables, etc.
If you run through all those upgrade scripts, then a supposedly
fresh database will already contain a bunch of rubble, dropped
attributes, dead rows, and the like.&lt;/p&gt;

&lt;p&gt;Therefore, the current version needs to be deployable from a
script that will not end up replaying history.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using metalanguages or abstraction layers (like Pyrseas or
Liquibase or any of the metaformats included in various web
frameworks).  It'd probably a good idea to check some of these out
for simple applications.  But my concern is whether using an
abstraction layer would prevent me from using certain features.
For example, look at the
&lt;a href="http://pyrseas.wordpress.com/feature-matrix/"&gt;Pyrseas feature matrix&lt;/a&gt;.
It's pretty impressive.  But it doesn't support extensions, roles,
or grants.  So (going by that list), I can't use it.  (It's being
&lt;a href="http://pyrseas.wordpress.com/2012/04/10/pyrseas-postgresql-features-feedback-requested/"&gt;worked on&lt;/a&gt;.)
And in a previous version, when I looked at it for a previous
project, it didn't support foreign-data functionality, so I
couldn't use it then either.  And those are just the top-level
things the author thought of.  Actually, the Pyrseas author has
gone through some
&lt;a href="http://pyrseas.wordpress.com/2012/03/05/more-database-tools/"&gt;effort&lt;/a&gt;
to have almost complete coverage of PostgreSQL DDL features, so
give this tool a try.  But it won't be for everyone.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, I'm going to keep looking.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=oQEkUaIl864:yzBa1wJGLSg: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=oQEkUaIl864:yzBa1wJGLSg: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=oQEkUaIl864:yzBa1wJGLSg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=oQEkUaIl864:yzBa1wJGLSg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=oQEkUaIl864:yzBa1wJGLSg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=oQEkUaIl864:yzBa1wJGLSg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=oQEkUaIl864:yzBa1wJGLSg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=oQEkUaIl864:yzBa1wJGLSg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=oQEkUaIl864:yzBa1wJGLSg:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=oQEkUaIl864:yzBa1wJGLSg:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=oQEkUaIl864:yzBa1wJGLSg: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/oQEkUaIl864" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/4672623148988461810/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2012/05/my-anti-take-on-database-schema-version.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/4672623148988461810?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/4672623148988461810?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/oQEkUaIl864/my-anti-take-on-database-schema-version.html" title="My (anti-)take on database schema version management" /><author><name>Peter Eisentraut</name><uri>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>6</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2012/05/my-anti-take-on-database-schema-version.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEMBSX07fyp7ImA9WhVUEE8.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-8649223265877939272</id><published>2012-05-14T23:14:00.000+03:00</published><updated>2012-05-14T23:14:18.307+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-14T23:14:18.307+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="tar" /><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="Shell" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>Time to retrain the fingers</title><content type="html">&lt;p&gt;For years, no decades, I've typed &lt;code&gt;tar tzf something&lt;/code&gt;, &lt;code&gt;tar xzf
something&lt;/code&gt;.  Except when someone annoying sent an uncompressed tar
file and I had to then go and take out the &lt;code&gt;z&lt;/code&gt; in the middle.&lt;/p&gt;

&lt;p&gt;Then came &lt;code&gt;bzip2&lt;/code&gt;, and we learned &lt;code&gt;tar tjf&lt;/code&gt;, &lt;code&gt;tar xjf&lt;/code&gt;.  OK, I could
live with that.  One emerging problem was that the tab completion now
worked the wrong way around conceptually, because you had to pick and
type the right letter first in order to see the appropriate set of
files to unpack offered for completion.&lt;/p&gt;

&lt;p&gt;Then came &lt;code&gt;lzma&lt;/code&gt;, which was (quick, guess?), &lt;code&gt;tar tJf&lt;/code&gt;, &lt;code&gt;tar xJf&lt;/code&gt;.
And then there was &lt;code&gt;lzop&lt;/code&gt;, which was too boring to get its own letter,
so you had to type out &lt;code&gt;tar -x --lzop -f&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But &lt;code&gt;lzma&lt;/code&gt; was short-lived, because then came &lt;code&gt;xz&lt;/code&gt;, which was also
&lt;code&gt;J&lt;/code&gt;, because &lt;code&gt;lzma&lt;/code&gt; was now too boring as well to get its own letter.&lt;/p&gt;

&lt;p&gt;Oh, and there is also the old &lt;code&gt;compress&lt;/code&gt;, which is &lt;code&gt;Z&lt;/code&gt;, and &lt;code&gt;lzip&lt;/code&gt;,
which I'd never heard of.&lt;/p&gt;

&lt;p&gt;But stop that.  Now there is&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; -a, --auto-compress
            use archive suffix to determine the compression program
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This handles all the above compression programs, and no compression.  So from now on, I always use &lt;code&gt;tar taf&lt;/code&gt; and &lt;code&gt;tar xaf&lt;/code&gt;.  Awesome.&lt;/p&gt;

&lt;p&gt;The finger movements will be almost the same on QWERTY and AZERTY, and
easier than before on QWERTZ.&lt;/p&gt;

&lt;p&gt;Actually, this option is already four years old in GNU tar.  Funny I'd
never heard of it until recently.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=f_JKGtPrFWY:U9lw1eN8ii8: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=f_JKGtPrFWY:U9lw1eN8ii8: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=f_JKGtPrFWY:U9lw1eN8ii8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=f_JKGtPrFWY:U9lw1eN8ii8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=f_JKGtPrFWY:U9lw1eN8ii8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=f_JKGtPrFWY:U9lw1eN8ii8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=f_JKGtPrFWY:U9lw1eN8ii8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=f_JKGtPrFWY:U9lw1eN8ii8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=f_JKGtPrFWY:U9lw1eN8ii8:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=f_JKGtPrFWY:U9lw1eN8ii8:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=f_JKGtPrFWY:U9lw1eN8ii8: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/f_JKGtPrFWY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/8649223265877939272/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2012/05/time-to-retrain-fingers.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/8649223265877939272?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/8649223265877939272?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/f_JKGtPrFWY/time-to-retrain-fingers.html" title="Time to retrain the fingers" /><author><name>Peter Eisentraut</name><uri>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>6</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2012/05/time-to-retrain-fingers.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEEEQHo4eyp7ImA9WhVWFkU.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-1527693985151094416</id><published>2012-04-29T11:03:00.000+03:00</published><updated>2012-04-29T11:03:21.433+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-04-29T11:03:21.433+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SSH" /><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="Shell" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>Setting the time zone on remote SSH hosts</title><content type="html">&lt;p&gt;The tasks: I have one or more desktop/laptop machines with varying
local time zones (because the persons using them are actually in
different time zones, or because the one person using them travels).
I also have a number of servers configured in some random time zones.
(It could be the time zone where they are physically located, or the
time zone of the person who installed it, or UTC for neutrality.)&lt;/p&gt;

&lt;p&gt;Now what I would like to have happen is that if I log in using SSH
from a desktop to a server, I see time on that server in my local time
zone.  For things like &lt;code&gt;ls -l&lt;/code&gt;, for example.  Obviously, this
&lt;q&gt;illusion&lt;/q&gt; will never be perfect.  Nothing (except something very
complicated) will adjust the time stamps in the syslog output, for
example.  But the &lt;code&gt;ls -l&lt;/code&gt; case in particular seems to come up a lot,
to check how long ago was this file modified.&lt;/p&gt;

&lt;p&gt;This should be completely doable in principle, because you can set the
&lt;code&gt;TZ&lt;/code&gt; environment variable to any time zone you like, and it will be
used for things like &lt;code&gt;ls -l&lt;/code&gt;.  But how do you get the &lt;code&gt;TZ&lt;/code&gt; setting
from here to there?&lt;/p&gt;

&lt;p&gt;First, you have to make the remote SSH server accept the &lt;code&gt;TZ&lt;/code&gt;
environment variable.  At least on Debian, this is not done by
default.  So make a setting like this in &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Allow client to pass locale environment variables
AcceptEnv LANG LC_* TZ
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You also need to make the equivalent setting on the client side,
either in &lt;code&gt;/etc/ssh/ssh_config&lt;/code&gt; or in &lt;code&gt;~/.ssh/config&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;SendEnv LANG LC_* TZ
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which leaves the question, how do you get your local time zone into
the &lt;code&gt;TZ&lt;/code&gt; variable to pass to the remote server?  The actual time zone
configuration is the file &lt;code&gt;/etc/localtime&lt;/code&gt;, which belongs to glibc.
In current Debian, this is (normally) a &lt;em&gt;copy&lt;/em&gt; of some file under
&lt;code&gt;/usr/share/zoneinfo/&lt;/code&gt;.  In the distant past, it was a symlink, which
would have made things easier, but now it's a copy, so you don't know
where it came from.  But the name of the time zone is also written to
&lt;code&gt;/etc/timezone&lt;/code&gt;, so you can use that.&lt;/p&gt;

&lt;p&gt;The format of the &lt;code&gt;TZ&lt;/code&gt; environment variable can be found in the glibc
documentation.  If you skip past most of the text, you will see the
relevant parts:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The third format looks like this:&lt;/p&gt;
  
  &lt;p&gt;:CHARACTERS&lt;/p&gt;
  
  &lt;p&gt;Each operating system interprets this format differently; in the GNU
  C library, CHARACTERS is the name of a file which describes the time
  zone.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So what you could do is set&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;TZ=":$(cat /etc/timezone)"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Better yet, for hopping through multiple SSH hosts in particular, make
sure to preserve an already set TZ:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;TZ=${TZ:-":$(cat /etc/timezone)"}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And finally, how does one hook this into &lt;code&gt;ssh&lt;/code&gt;?  The best I could
think of is a shell alias:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;alias ssh='TZ=${TZ:-":$(cat /etc/timezone)"} ssh'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now this set up has a number of flaws, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Possibly only works between Linux (Debian?) hosts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Only works if available time zone names match.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Only works when calling &lt;code&gt;ssh&lt;/code&gt; from the shell.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But it practice it has turned out to be quite useful.&lt;/p&gt;

&lt;p&gt;Comments?  Improvements?  Better ideas?&lt;/p&gt;

&lt;p&gt;Related thoughts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;With this system in hand, I have resorted to setting the time zone
on most servers to UTC, since I will see my local time zone
automatically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Important for the complete server localization illusion: some ideas
on dealing with
&lt;a href="http://vincent.bernat.im/en/blog/2011-ssh-and-locales.html"&gt;locales on remote hosts&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=1kbmoucKqxY:zeALRjEfgfc: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=1kbmoucKqxY:zeALRjEfgfc: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=1kbmoucKqxY:zeALRjEfgfc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=1kbmoucKqxY:zeALRjEfgfc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=1kbmoucKqxY:zeALRjEfgfc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=1kbmoucKqxY:zeALRjEfgfc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=1kbmoucKqxY:zeALRjEfgfc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=1kbmoucKqxY:zeALRjEfgfc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=1kbmoucKqxY:zeALRjEfgfc:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=1kbmoucKqxY:zeALRjEfgfc:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=1kbmoucKqxY:zeALRjEfgfc: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/1kbmoucKqxY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/1527693985151094416/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2012/04/setting-time-zone-on-remote-ssh-hosts.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/1527693985151094416?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/1527693985151094416?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/1kbmoucKqxY/setting-time-zone-on-remote-ssh-hosts.html" title="Setting the time zone on remote SSH hosts" /><author><name>Peter Eisentraut</name><uri>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>6</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2012/04/setting-time-zone-on-remote-ssh-hosts.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEACSXo-eyp7ImA9WhVRE0g.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-7038970913114852612</id><published>2012-03-21T19:59:00.000+02:00</published><updated>2012-03-21T19:59:28.453+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-21T19:59:28.453+02:00</app:edited><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="Computing" /><category scheme="http://www.blogger.com/atom/ns#" term="English" /><title>PostgreSQL and compiler warnings</title><content type="html">&lt;p&gt;Recently, I did some work on backpatching a few commits from PostgreSQL master, and I noticed that with the current tools, the old branches create tons of compiler warnings.  In PostgreSQL 8.3, the oldest currently supported branch, a &lt;code&gt;make all&lt;/code&gt; with GCC 4.6.3 produces 231 warnings!  (Also note that there are only 751 &lt;tt&gt;.c&lt;/tt&gt; files, so that's a warning every three files.)  We do a lot of work cleaning up any and all compiler warnings, at least those issued by the latest GCC.  These kinds of noisy builds are quite troublesome to work with, because it is more difficult to check whether your changes introduced any new, more serious warnings.
&lt;p&gt;
Let's take a look at the current number of compiler warnings in different PostgreSQL branches with different compilers:

&lt;table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides"&gt;
&lt;colgroup&gt;&lt;col class="right" /&gt;&lt;col class="right" /&gt;&lt;col class="right" /&gt;&lt;col class="right" /&gt;&lt;col class="right" /&gt;&lt;col class="right" /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th scope="col" class="right"&gt;&lt;/th&gt;&lt;th scope="col" class="right"&gt;gcc 4.4&lt;/th&gt;&lt;th scope="col" class="right"&gt;gcc 4.5&lt;/th&gt;&lt;th scope="col" class="right"&gt;gcc 4.6&lt;/th&gt;&lt;th scope="col" class="right"&gt;gcc 4.7&lt;/th&gt;&lt;th scope="col" class="right"&gt;clang&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;th class="right"&gt;8.3&lt;/td&gt;&lt;td class="right"&gt;173&lt;/td&gt;&lt;td class="right"&gt;51&lt;/td&gt;&lt;td class="right"&gt;231&lt;/td&gt;&lt;td class="right"&gt;207&lt;/td&gt;&lt;td class="right"&gt;665&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th class="right"&gt;8.4&lt;/td&gt;&lt;td class="right"&gt;12&lt;/td&gt;&lt;td class="right"&gt;17&lt;/td&gt;&lt;td class="right"&gt;201&lt;/td&gt;&lt;td class="right"&gt;201&lt;/td&gt;&lt;td class="right"&gt;673&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th class="right"&gt;9.0&lt;/td&gt;&lt;td class="right"&gt;13&lt;/td&gt;&lt;td class="right"&gt;13&lt;/td&gt;&lt;td class="right"&gt;89&lt;/td&gt;&lt;td class="right"&gt;89&lt;/td&gt;&lt;td class="right"&gt;780&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th class="right"&gt;9.1&lt;/td&gt;&lt;td class="right"&gt;24&lt;/td&gt;&lt;td class="right"&gt;24&lt;/td&gt;&lt;td class="right"&gt;40&lt;/td&gt;&lt;td class="right"&gt;40&lt;/td&gt;&lt;td class="right"&gt;25&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th class="right"&gt;master&lt;/td&gt;&lt;td class="right"&gt;1&lt;/td&gt;&lt;td class="right"&gt;1&lt;/td&gt;&lt;td class="right"&gt;1&lt;/td&gt;&lt;td class="right"&gt;1&lt;/td&gt;&lt;td class="right"&gt;1&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
Obviously, GCC 4.6 introduced many new warnings.  If you use the compiler that was current around the time the branch was originally released, you'll be better off.  But even then, you should expect a few surprises.  (8.3 would probably require gcc 4.3, but I don't have that available anymore.)
&lt;p&gt;
Fortunately, it looks as though GCC 4.7, which is currently in release candidate state, will spare us of new warnings.  Also note that clang (version 3.0) is now as good as GCC, as far as noise is concerned.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=xPl698fHJ_A:k1N1TIZ0XwY: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=xPl698fHJ_A:k1N1TIZ0XwY: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=xPl698fHJ_A:k1N1TIZ0XwY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=xPl698fHJ_A:k1N1TIZ0XwY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=xPl698fHJ_A:k1N1TIZ0XwY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=xPl698fHJ_A:k1N1TIZ0XwY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=xPl698fHJ_A:k1N1TIZ0XwY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=xPl698fHJ_A:k1N1TIZ0XwY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=xPl698fHJ_A:k1N1TIZ0XwY:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=xPl698fHJ_A:k1N1TIZ0XwY:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=xPl698fHJ_A:k1N1TIZ0XwY: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/xPl698fHJ_A" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/7038970913114852612/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2012/03/postgresql-and-compiler-warnings.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/7038970913114852612?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/7038970913114852612?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/xPl698fHJ_A/postgresql-and-compiler-warnings.html" title="PostgreSQL and compiler warnings" /><author><name>Peter Eisentraut</name><uri>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2012/03/postgresql-and-compiler-warnings.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYGQXc4fSp7ImA9WhVSEEw.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-905949064609005724</id><published>2012-03-06T07:35:00.000+02:00</published><updated>2012-03-06T07:35:20.935+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-06T07:35:20.935+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Autoconf" /><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 make install times</title><content type="html">I have decided that &lt;tt&gt;make install&lt;/tt&gt; is too slow for me.  Compare: A run of &lt;tt&gt;make install&lt;/tt&gt; takes about 10 seconds (details below), but a run of &lt;tt&gt;make all&lt;/tt&gt; with the tree mostly up to date and using ccache for the rest usually takes about 1 or 2 seconds.  You can end up wasting a lot of time if you need to do many of these build and install cycles during development.  In particular, &lt;tt&gt;make check&lt;/tt&gt; includes a run of &lt;tt&gt;make install&lt;/tt&gt;, so all this time is added to the time it takes for tests to complete.
&lt;p&gt;
So let's optimize this.  The times below are all medians from 5 consecutive runs, writing over an existing installation, so they all had to do the same amount of work.
&lt;p&gt;
This is the baseline:
&lt;ul&gt;
&lt;li&gt;&lt;tt&gt;make install&lt;/tt&gt; &amp;mdash; 10.493 s
&lt;/ul&gt;
&lt;p&gt;
The first change is to use a faster shell.  This system is using bash as &lt;tt&gt;/bin/sh&lt;/tt&gt;.  Many Linux distributions now use dash instead, but for some reason I haven't changed this system during the upgrade.
&lt;ul&gt;
&lt;li&gt;&lt;tt&gt;make install SHELL=/bin/dash&lt;/tt&gt; &amp;mdash; 6.344 s
&lt;/ul&gt;
I guess I'll  be switching this system soon as well then!
&lt;p&gt;
The next thing is to avoid installing the translation files.  This exploded the number of files that need to be installed.  Instead of, say, one program file, you end up installing one program file and a dozen or so translation files.
&lt;ul&gt;
&lt;li&gt;&lt;tt&gt;make install SHELL=/bin/bash enable_nls=no&lt;/tt&gt; &amp;mdash; 6.890 s
&lt;li&gt;&lt;tt&gt;make install SHELL=/bin/dash enable_nls=no&lt;/tt&gt; &amp;mdash; 4.482 s
&lt;/ul&gt;
(In practice you would use &lt;tt&gt;configure --disable-nls&lt;/tt&gt;, which is the default.  The above is just a way to do this without reconfiguring.)  Now I have in the past preferred to build with NLS support to be able to catch errors in that area, but considering this improvement and the availability of the &lt;tt&gt;make maintainer-check&lt;/tt&gt; target, I might end up building without it more often.
&lt;p&gt;
Another tip I remembered from the past was to use the &lt;tt&gt;make -s&lt;/tt&gt; option to avoid screen output.  Depending on the operating system and whether you are logged in locally or remotely, this can be a big win.  On my system, this got lost in the noise a bit, but it appeared to make a small difference over many runs.
&lt;ul&gt;
&lt;li&gt;&lt;tt&gt;make install SHELL=/bin/bash -s&lt;/tt&gt; &amp;mdash; 10.511 s
&lt;li&gt;&lt;tt&gt;make install SHELL=/bin/dash -s&lt;/tt&gt; &amp;mdash; 6.146 s
&lt;/ul&gt;
Do add this to your arsenal anyway if you want to get maximum performance.
&lt;p&gt;
Next, let's replace the &lt;tt&gt;install-sh&lt;/tt&gt; script that does the actual file copying.  For obscure reasons, PostgreSQL always uses that shell script, instead of  the &lt;tt&gt;/usr/bin/install&lt;/tt&gt; program that an Autoconf-based build system would normally use.  But you can override the make variables and sustitute the program you want:
&lt;ul&gt;
&lt;li&gt;&lt;tt&gt;make install SHELL=/bin/bash INSTALL=install&lt;/tt&gt; &amp;mdash; 5.418 s
&lt;li&gt;&lt;tt&gt;make install SHELL=/bin/dash INSTALL=install&lt;/tt&gt; &amp;mdash; 3.995 s
&lt;/ul&gt;
Interestingly, the choice of shell still makes a noticeable difference, even though it's no longer used to execute &lt;tt&gt;install-sh&lt;/tt&gt;.
&lt;p&gt;
Finally, you can also use parallel make for the installation step:
&lt;ul&gt;
&lt;li&gt;&lt;tt&gt;make install SHELL=/bin/bash -j2&lt;/tt&gt; &amp;mdash; 6.538 s
&lt;li&gt;&lt;tt&gt;make install SHELL=/bin/dash -j2&lt;/tt&gt; &amp;mdash; 4.158 s
&lt;/ul&gt;
You can gather from these numbers that the installation process appears to be mostly CPU-bound.  This system has 4 cores, so let's add some more parallelization:
&lt;ul&gt;
&lt;li&gt;&lt;tt&gt;make install SHELL=/bin/dash -j3&lt;/tt&gt; &amp;mdash; 3.330 s
&lt;li&gt;&lt;tt&gt;make install SHELL=/bin/dash -j4&lt;/tt&gt; &amp;mdash; 2.944 s
&lt;li&gt;&lt;tt&gt;make install SHELL=/bin/dash -j5&lt;/tt&gt; &amp;mdash; 2.930 s
&lt;li&gt;&lt;tt&gt;make install SHELL=/bin/dash -j6&lt;/tt&gt; &amp;mdash; 2.952 s
&lt;/ul&gt;
That's probably enough.
&lt;p&gt;
Now let's put everything together:
&lt;ul&gt;
&lt;li&gt;&lt;tt&gt;make install SHELL=/bin/dash enable_nls=no INSTALL=install -s -j4&lt;/tt&gt; &amp;mdash; 1.708&amp;nbsp;s
&lt;/ul&gt;
Or even:
&lt;ul&gt;
&lt;li&gt;&lt;tt&gt;make install SHELL=/bin/dash enable_nls=no INSTALL=install -s -j3&lt;/tt&gt; &amp;mdash; 1.654&amp;nbsp;s
&lt;/ul&gt;
That's a very nice improvement from 10.493 s!
&lt;p&gt;
The problem is, it is not all that easy to pass these options to the &lt;tt&gt;make install&lt;/tt&gt; calls made in &lt;tt&gt;make check&lt;/tt&gt; runs.  If you can and want to change your system shell, and you configure without NLS support, then you will probably already be more than half way there.  Then again, I suspect most readers already have that setup anyway.  For the other options, to take down the installation time to almost instantaneous, you have to do ad hoc surgery in various places.  I'm looking into improving that.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=k5-8ePB6MSg:4KWXGGFZy7w: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=k5-8ePB6MSg:4KWXGGFZy7w: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=k5-8ePB6MSg:4KWXGGFZy7w:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=k5-8ePB6MSg:4KWXGGFZy7w:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=k5-8ePB6MSg:4KWXGGFZy7w:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=k5-8ePB6MSg:4KWXGGFZy7w:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=k5-8ePB6MSg:4KWXGGFZy7w:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=k5-8ePB6MSg:4KWXGGFZy7w:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=k5-8ePB6MSg:4KWXGGFZy7w:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/PeterEisentraut?i=k5-8ePB6MSg:4KWXGGFZy7w:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/PeterEisentraut?a=k5-8ePB6MSg:4KWXGGFZy7w: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/k5-8ePB6MSg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://petereisentraut.blogspot.com/feeds/905949064609005724/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://petereisentraut.blogspot.com/2012/03/postgresql-make-install-times.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/905949064609005724?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5541296000399974369/posts/default/905949064609005724?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/PeterEisentraut/~3/k5-8ePB6MSg/postgresql-make-install-times.html" title="PostgreSQL make install times" /><author><name>Peter Eisentraut</name><uri>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>5</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2012/03/postgresql-make-install-times.html</feedburner:origLink></entry><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="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="5 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>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>5</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="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>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.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="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="9 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>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>9</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="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>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.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="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>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.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="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>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.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="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>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.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;Ck8BRH0zfip7ImA9WhVXE0g.&quot;"><id>tag:blogger.com,1999:blog-5541296000399974369.post-8837541431411735039</id><published>2011-06-02T00:00:00.000+03:00</published><updated>2012-04-14T00:00:55.386+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-04-14T00:00:55.386+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; 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="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="7 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>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>7</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="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>https://plus.google.com/112189380626711223301</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh6.googleusercontent.com/-gbKmSwnbKr8/AAAAAAAAAAI/AAAAAAAAAAA/kaMouFl0lFk/s512-c/photo.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html</feedburner:origLink></entry></feed>
